[PATCH v3 2/6] winex11.drv: Support Xinerama display device handler.

Zhiyi Zhang zzhang at codeweavers.com
Tue May 14 04:48:25 CDT 2019


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/winex11.drv/xinerama.c | 150 ++++++++++++++++++++++++++++++++++++
 1 file changed, 150 insertions(+)

diff --git a/dlls/winex11.drv/xinerama.c b/dlls/winex11.drv/xinerama.c
index 739b139736..d4ccc0373e 100644
--- a/dlls/winex11.drv/xinerama.c
+++ b/dlls/winex11.drv/xinerama.c
@@ -30,6 +30,8 @@
 #include "wine/library.h"
 #include "x11drv.h"
 #include "wine/debug.h"
+#include "wine/heap.h"
+#include "wine/unicode.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(x11drv);
 
@@ -199,8 +201,146 @@ RECT get_primary_monitor_rect(void)
     return get_primary()->rcMonitor;
 }
 
+static BOOL xinerama_get_gpus( struct x11drv_gpu **new_gpus, int *count )
+{
+    static const WCHAR wine_gpuW[] = {'W','i','n','e',' ','G','P','U',0};
+    struct x11drv_gpu *gpus;
+
+    /* Xinerama has no support for GPU, faking one */
+    gpus = heap_calloc( 1, sizeof(*gpus) );
+    if (!gpus)
+        return FALSE;
+
+    strcpyW( gpus[0].name, wine_gpuW );
+
+    *new_gpus = gpus;
+    *count = 1;
+
+    return TRUE;
+}
+
+static void xinerama_free_gpus( struct x11drv_gpu *gpus )
+{
+    heap_free( gpus );
+}
+
+static BOOL xinerama_get_adapters( ULONG_PTR gpu_id, struct x11drv_adapter **new_adapters, int *count )
+{
+    struct x11drv_adapter *adapters = NULL;
+    INT index = 0;
+    INT i, j;
+    INT primary_index;
+    BOOL mirrored;
+
+    if (gpu_id)
+        return FALSE;
+
+    /* Being lazy, actual adapter count maybe less */
+    adapters = heap_calloc( nb_monitors, sizeof(*adapters) );
+    if (!adapters)
+        return FALSE;
+
+    primary_index = primary_monitor;
+    if (primary_index >= nb_monitors)
+        primary_index = 0;
+
+    for (i = 0; i < nb_monitors; i++)
+    {
+        mirrored = FALSE;
+        for (j = 0; j < i; j++)
+        {
+            if (EqualRect( &monitors[i].rcMonitor, &monitors[j].rcMonitor) && !IsRectEmpty( &monitors[j].rcMonitor ))
+            {
+                mirrored = TRUE;
+                break;
+            }
+        }
+
+        /* Mirrored monitors share the same adapter */
+        if (mirrored)
+            continue;
+
+        /* Use monitor index as id */
+        adapters[index].id = (ULONG_PTR)i;
+
+        if (i == primary_index)
+            adapters[index].state_flags |= DISPLAY_DEVICE_PRIMARY_DEVICE;
+
+        if (!IsRectEmpty( &monitors[i].rcMonitor ))
+            adapters[index].state_flags |= DISPLAY_DEVICE_ATTACHED_TO_DESKTOP;
+
+        index++;
+    }
+
+    /* Primary adapter has to be first */
+    if (primary_index)
+    {
+        struct x11drv_adapter tmp;
+        tmp = adapters[primary_index];
+        adapters[primary_index] = adapters[0];
+        adapters[0] = tmp;
+    }
+
+    *new_adapters = adapters;
+    *count = index;
+    return TRUE;
+}
+
+static void xinerama_free_adapters( struct x11drv_adapter *adapters )
+{
+    heap_free( adapters );
+}
+
+static BOOL xinerama_get_monitors( ULONG_PTR adapter_id, struct x11drv_monitor **new_monitors, int *count )
+{
+    static const WCHAR generic_nonpnp_monitorW[] = {
+        'G','e','n','e','r','i','c',' ',
+        'N','o','n','-','P','n','P',' ','M','o','n','i','t','o','r',0};
+    struct x11drv_monitor *monitor;
+    INT first = (INT)adapter_id;
+    INT monitor_count = 0;
+    INT index = 0;
+    INT i;
+
+    for (i = first; i < nb_monitors; i++)
+    {
+        if (i == first || EqualRect( &monitors[i].rcMonitor, &monitors[first].rcMonitor ))
+            monitor_count++;
+    }
+
+    monitor = heap_calloc( monitor_count, sizeof(*monitor) );
+    if (!monitor)
+        return FALSE;
+
+    for (i = first; i < nb_monitors; i++)
+    {
+        if (i == first || EqualRect( &monitors[i].rcMonitor, &monitors[first].rcMonitor ))
+        {
+            strcpyW( monitor[index].name, generic_nonpnp_monitorW );
+            monitor[index].rc_monitor = monitors[i].rcMonitor;
+            monitor[index].rc_work = monitors[i].rcWork;
+            /* Xinerama only reports monitors already attached */
+            monitor[index].state_flags = DISPLAY_DEVICE_ATTACHED;
+            if (!IsRectEmpty( &monitors[i].rcMonitor ))
+                monitor[index].state_flags |= DISPLAY_DEVICE_ACTIVE;
+
+            index++;
+        }
+    }
+
+    *new_monitors = monitor;
+    *count = monitor_count;
+    return TRUE;
+}
+
+static void xinerama_free_monitors( struct x11drv_monitor *monitors )
+{
+    heap_free( monitors );
+}
+
 void xinerama_init( unsigned int width, unsigned int height )
 {
+    struct x11drv_display_device_handler handler;
     MONITORINFOEXW *primary;
     int i;
     RECT rect;
@@ -234,6 +374,16 @@ void xinerama_init( unsigned int width, unsigned int height )
                (monitors[i].dwFlags & MONITORINFOF_PRIMARY) ? " (primary)" : "" );
     }
 
+    strcpy( handler.name, "Xinerama" );
+    handler.priority = 100;
+    handler.pGetGpus = xinerama_get_gpus;
+    handler.pGetAdapters = xinerama_get_adapters;
+    handler.pGetMonitors = xinerama_get_monitors;
+    handler.pFreeGpus = xinerama_free_gpus;
+    handler.pFreeAdapters = xinerama_free_adapters;
+    handler.pFreeMonitors = xinerama_free_monitors;
+    X11DRV_DisplayDevices_SetHandler( &handler );
+
     TRACE( "virtual size: %s primary: %s\n",
            wine_dbgstr_rect(&virtual_screen_rect), wine_dbgstr_rect(&primary->rcMonitor) );
 }
-- 
2.20.1





More information about the wine-devel mailing list