[PATCH 5/6] winex11.drv: Add XRandR 1.4 display settings handler.

Zhiyi Zhang zzhang at codeweavers.com
Fri Jul 24 04:23:21 CDT 2020


Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/user32/tests/monitor.c   |   1 -
 dlls/user32/tests/sysparams.c |  23 +--
 dlls/winex11.drv/xrandr.c     | 376 ++++++++++++++++++++++++++++++++--
 3 files changed, 372 insertions(+), 28 deletions(-)

diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c
index badbfdaacf3..005627f28b0 100644
--- a/dlls/user32/tests/monitor.c
+++ b/dlls/user32/tests/monitor.c
@@ -318,7 +318,6 @@ static void _expect_dm(INT line, DEVMODEA expected, const CHAR *device, DWORD te
     ok(get_primary_adapter(primary_adapter), "Failed to get primary adapter name.\n");
     is_primary = !lstrcmpA(primary_adapter, device);
 
-    todo_wine_if(expected.dmFields & DM_POSITION)
     ok_(__FILE__, line)((dm.dmFields & expected.dmFields) == expected.dmFields,
             "Device %s test %d expect dmFields to contain %#x, got %#x\n", device, test, expected.dmFields, dm.dmFields);
     /* Wine doesn't support changing color depth yet */
diff --git a/dlls/user32/tests/sysparams.c b/dlls/user32/tests/sysparams.c
index f71b73930f2..f544e1a4df2 100644
--- a/dlls/user32/tests/sysparams.c
+++ b/dlls/user32/tests/sysparams.c
@@ -3115,7 +3115,7 @@ static BOOL CALLBACK test_enum_display_settings(HMONITOR hmonitor, HDC hdc, LPRE
     ret = EnumDisplaySettingsA(mi.szDevice, ENUM_CURRENT_SETTINGS, &dm);
     ok(ret, "EnumDisplaySettingsA failed, error %#x\n", GetLastError());
 
-    todo_wine ok((dm.dmFields & (DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT)) == (DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT),
+    ok((dm.dmFields & (DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT)) == (DM_POSITION | DM_PELSWIDTH | DM_PELSHEIGHT),
             "Unexpected dmFields %#x.\n", dm.dmFields);
     /* Wine currently reports primary adapter positions for all adapters, same for other todo_wines in this function */
     ret = get_primary_adapter_name(primary_adapter);
@@ -3187,7 +3187,7 @@ static void test_EnumDisplaySettings(void)
     ok(ret, "EnumDisplaySettingsA failed, error %#x\n", GetLastError());
     ok(dm.dmSize == FIELD_OFFSET(DEVMODEA, dmICMMethod), "Expect dmSize %u, got %u\n",
             FIELD_OFFSET(DEVMODEA, dmICMMethod), dm.dmSize);
-    todo_wine ok((dm.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#x, got %#x\n",
+    ok((dm.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#x, got %#x\n",
             setting_fields, dm.dmFields);
 
     memset(&dm, 0, sizeof(dm));
@@ -3196,7 +3196,7 @@ static void test_EnumDisplaySettings(void)
     ok(ret, "EnumDisplaySettingsA failed, error %#x\n", GetLastError());
     ok(dm.dmSize == FIELD_OFFSET(DEVMODEA, dmICMMethod), "Expect dmSize %u, got %u\n",
             FIELD_OFFSET(DEVMODEA, dmICMMethod), dm.dmSize);
-    todo_wine ok((dm.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#x, got %#x\n",
+    ok((dm.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#x, got %#x\n",
             setting_fields, dm.dmFields);
 
     memset(&dmW, 0, sizeof(dmW));
@@ -3204,7 +3204,7 @@ static void test_EnumDisplaySettings(void)
     ok(ret, "EnumDisplaySettingsW failed, error %#x\n", GetLastError());
     ok(dmW.dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod), "Expect dmSize %u, got %u\n",
             FIELD_OFFSET(DEVMODEW, dmICMMethod), dmW.dmSize);
-    todo_wine ok((dmW.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#x, got %#x\n",
+    ok((dmW.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#x, got %#x\n",
             setting_fields, dmW.dmFields);
 
     memset(&dmW, 0, sizeof(dmW));
@@ -3213,7 +3213,7 @@ static void test_EnumDisplaySettings(void)
     ok(ret, "EnumDisplaySettingsW failed, error %#x\n", GetLastError());
     ok(dmW.dmSize == FIELD_OFFSET(DEVMODEW, dmICMMethod), "Expect dmSize %u, got %u\n",
             FIELD_OFFSET(DEVMODEW, dmICMMethod), dmW.dmSize);
-    todo_wine ok((dmW.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#x, got %#x\n",
+    ok((dmW.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#x, got %#x\n",
             setting_fields, dmW.dmFields);
 
     /* EnumDisplaySettingsExA/W need dmSize to be at least FIELD_OFFSET(DEVMODEA/W, dmFields) + 1 to have valid dmFields */
@@ -3271,7 +3271,7 @@ static void test_EnumDisplaySettings(void)
     dm.dmSize = sizeof(dm);
     ret = EnumDisplaySettingsExA(NULL, ENUM_CURRENT_SETTINGS, &dm, 0);
     ok(ret, "EnumDisplaySettingsExA failed, error %#x\n", GetLastError());
-    todo_wine ok((dm.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#x, got %#x\n",
+    ok((dm.dmFields & setting_fields) == setting_fields, "Expect dmFields to contain %#x, got %#x\n",
             setting_fields, dm.dmFields);
     ok(dm.dmBitsPerPel == val, "Expect dmBitsPerPel %d, got %d\n", val, dm.dmBitsPerPel);
 
@@ -3314,12 +3314,11 @@ static void test_EnumDisplaySettings(void)
         {
             if (mode == ENUM_CURRENT_SETTINGS)
             {
-                todo_wine ok((dm.dmFields & setting_fields) == setting_fields,
+                ok((dm.dmFields & setting_fields) == setting_fields,
                         "Expect dmFields to contain %#x, got %#x\n", setting_fields, dm.dmFields);
             }
             else
             {
-                todo_wine_if(mode != ENUM_REGISTRY_SETTINGS)
                 ok((dm.dmFields & mode_fields) == mode_fields, "Expect dmFields to contain %#x, got %#x\n",
                         mode_fields, dm.dmFields);
             }
@@ -3330,10 +3329,10 @@ static void test_EnumDisplaySettings(void)
 
             if (mode == ENUM_CURRENT_SETTINGS && !attached)
             {
-                todo_wine ok(dm.dmBitsPerPel == 0, "Expect dmBitsPerPel zero, got %u\n", dm.dmBitsPerPel);
-                todo_wine ok(dm.dmPelsWidth == 0, "Expect dmPelsWidth zero, got %u\n", dm.dmPelsWidth);
-                todo_wine ok(dm.dmPelsHeight == 0, "Expect dmPelsHeight zero, got %u\n", dm.dmPelsHeight);
-                todo_wine ok(dm.dmDisplayFrequency == 0, "Expect dmDisplayFrequency zero, got %u\n", dm.dmDisplayFrequency);
+                ok(dm.dmBitsPerPel == 0, "Expect dmBitsPerPel zero, got %u\n", dm.dmBitsPerPel);
+                ok(dm.dmPelsWidth == 0, "Expect dmPelsWidth zero, got %u\n", dm.dmPelsWidth);
+                ok(dm.dmPelsHeight == 0, "Expect dmPelsHeight zero, got %u\n", dm.dmPelsHeight);
+                ok(dm.dmDisplayFrequency == 0, "Expect dmDisplayFrequency zero, got %u\n", dm.dmDisplayFrequency);
             }
             else if (mode != ENUM_REGISTRY_SETTINGS)
             {
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c
index 4bbba15a259..5ad70ea95ac 100644
--- a/dlls/winex11.drv/xrandr.c
+++ b/dlls/winex11.drv/xrandr.c
@@ -22,6 +22,10 @@
 
 #include "config.h"
 #include "wine/port.h"
+
+#define NONAMELESSSTRUCT
+#define NONAMELESSUNION
+
 #include "wine/debug.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(xrandr);
@@ -31,6 +35,7 @@ WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
 #ifdef SONAME_LIBXRANDR
 
+#include <assert.h>
 #include <X11/Xlib.h>
 #include <X11/extensions/Xrandr.h>
 #include "x11drv.h"
@@ -845,7 +850,9 @@ done:
     return ret;
 }
 
-static BOOL xrandr14_get_gpus( struct x11drv_gpu **new_gpus, int *count )
+/* Get a list of GPUs reported by XRandR 1.4. Set get_properties to FALSE if GPU properties are
+ * not needed to avoid unnecessary querying */
+static BOOL xrandr14_get_gpus2( struct x11drv_gpu **new_gpus, int *count, BOOL get_properties )
 {
     static const WCHAR wine_adapterW[] = {'W','i','n','e',' ','A','d','a','p','t','e','r',0};
     struct x11drv_gpu *gpus = NULL;
@@ -907,9 +914,12 @@ static BOOL xrandr14_get_gpus( struct x11drv_gpu **new_gpus, int *count )
         }
 
         gpus[i].id = provider_resources->providers[i];
-        if (!get_gpu_properties_from_vulkan( &gpus[i], provider_info ))
-            MultiByteToWideChar( CP_UTF8, 0, provider_info->name, -1, gpus[i].name, ARRAY_SIZE(gpus[i].name) );
-        /* FIXME: Add an alternate method of getting PCI IDs, for systems that don't support Vulkan */
+        if (get_properties)
+        {
+            if (!get_gpu_properties_from_vulkan( &gpus[i], provider_info ))
+                MultiByteToWideChar( CP_UTF8, 0, provider_info->name, -1, gpus[i].name, ARRAY_SIZE(gpus[i].name) );
+            /* FIXME: Add an alternate method of getting PCI IDs, for systems that don't support Vulkan */
+        }
         pXRRFreeProviderInfo( provider_info );
     }
 
@@ -937,6 +947,11 @@ done:
     return ret;
 }
 
+static BOOL xrandr14_get_gpus( struct x11drv_gpu **new_gpus, int *count )
+{
+    return xrandr14_get_gpus2( new_gpus, count, TRUE );
+}
+
 static void xrandr14_free_gpus( struct x11drv_gpu *gpus )
 {
     heap_free( gpus );
@@ -1284,11 +1299,330 @@ static void xrandr14_register_event_handlers(void)
                                    "XRandR ProviderChange" );
 }
 
+/* XRandR 1.4 display settings handler */
+static BOOL xrandr14_get_id( const WCHAR *device_name, ULONG_PTR *id )
+{
+    INT gpu_count, adapter_count, display_count = 0;
+    INT gpu_idx, adapter_idx, display_idx;
+    struct x11drv_adapter *adapters;
+    struct x11drv_gpu *gpus;
+    WCHAR *end;
+
+    /* Parse \\.\DISPLAY%d */
+    display_idx = strtolW( device_name + 11, &end, 10 ) - 1;
+    if (*end)
+        return FALSE;
+
+    if (!xrandr14_get_gpus2( &gpus, &gpu_count, FALSE ))
+        return FALSE;
+
+    for (gpu_idx = 0; gpu_idx < gpu_count; ++gpu_idx)
+    {
+        if (!xrandr14_get_adapters( gpus[gpu_idx].id, &adapters, &adapter_count ))
+        {
+            xrandr14_free_gpus( gpus );
+            return FALSE;
+        }
+
+        adapter_idx = display_idx - display_count;
+        if (adapter_idx < adapter_count)
+        {
+            *id = adapters[adapter_idx].id;
+            xrandr14_free_adapters( adapters );
+            xrandr14_free_gpus( gpus );
+            return TRUE;
+        }
+
+        display_count += adapter_count;
+        xrandr14_free_adapters( adapters );
+    }
+    xrandr14_free_gpus( gpus );
+    return FALSE;
+}
+
+static void add_xrandr14_mode( DEVMODEW *mode, XRRModeInfo *info, DWORD depth, DWORD frequency )
+{
+    mode->dmSize = sizeof(*mode);
+    mode->dmDriverExtra = sizeof(RRMode);
+    mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH |
+                     DM_PELSHEIGHT | DM_DISPLAYFLAGS;
+    if (frequency)
+    {
+        mode->dmFields |= DM_DISPLAYFREQUENCY;
+        mode->dmDisplayFrequency = frequency;
+    }
+    mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
+    mode->dmBitsPerPel = depth;
+    mode->dmPelsWidth = info->width;
+    mode->dmPelsHeight = info->height;
+    mode->u2.dmDisplayFlags = 0;
+    memcpy( (BYTE *)mode + sizeof(*mode), &info->id, sizeof(info->id) );
+}
+
+static BOOL xrandr14_get_modes( ULONG_PTR id, DWORD flags, DEVMODEW **new_modes, UINT *mode_count )
+{
+    XRRScreenResources *screen_resources;
+    XRROutputInfo *output_info = NULL;
+    RROutput output = (RROutput)id;
+    UINT depth_idx, mode_idx = 0;
+    XRRModeInfo *mode_info;
+    DEVMODEW *mode, *modes;
+    BOOL ret = FALSE;
+    DWORD frequency;
+    INT i, j;
+
+    screen_resources = xrandr_get_screen_resources();
+    if (!screen_resources)
+        goto done;
+
+    output_info = pXRRGetOutputInfo( gdi_display, screen_resources, output );
+    if (!output_info)
+        goto done;
+
+    if (output_info->connection != RR_Connected)
+    {
+        ret = TRUE;
+        *new_modes = NULL;
+        *mode_count = 0;
+        goto done;
+    }
+
+    /* Allocate space for display modes in different color depths.
+     * Store a RRMode at the end of each DEVMODEW as private driver data */
+    modes = heap_calloc( output_info->nmode * DEPTH_COUNT, sizeof(*modes) + sizeof(RRMode) );
+    if (!modes)
+        goto done;
+
+    for (i = 0; i < output_info->nmode; ++i)
+    {
+        for (j = 0; j < screen_resources->nmode; ++j)
+        {
+            if (output_info->modes[i] != screen_resources->modes[j].id)
+                continue;
+
+            mode_info = &screen_resources->modes[j];
+            frequency = get_frequency( mode_info );
+
+            for (depth_idx = 0; depth_idx < DEPTH_COUNT; ++depth_idx)
+            {
+                mode = (DEVMODEW *)((BYTE *)modes + (sizeof(*modes) + sizeof(RRMode)) * mode_idx);
+                add_xrandr14_mode( mode, mode_info, depths[depth_idx], frequency );
+                ++mode_idx;
+            }
+
+            break;
+        }
+    }
+
+    ret = TRUE;
+    *new_modes = modes;
+    *mode_count = mode_idx;
+done:
+    if (output_info)
+        pXRRFreeOutputInfo( output_info );
+    if (screen_resources)
+        pXRRFreeScreenResources( screen_resources );
+    return ret;
+}
+
+static void xrandr14_free_modes( DEVMODEW *modes )
+{
+    heap_free( modes );
+}
+
+static BOOL xrandr14_get_current_mode( ULONG_PTR id, DEVMODEW *mode )
+{
+    XRRScreenResources *screen_resources;
+    XRROutputInfo *output_info = NULL;
+    RROutput output = (RROutput)id;
+    XRRModeInfo *mode_info = NULL;
+    XRRCrtcInfo *crtc_info = NULL;
+    BOOL ret = FALSE;
+    RECT primary;
+    INT mode_idx;
+
+    screen_resources = xrandr_get_screen_resources();
+    if (!screen_resources)
+        goto done;
+
+    output_info = pXRRGetOutputInfo( gdi_display, screen_resources, output );
+    if (!output_info)
+        goto done;
+
+    if (output_info->crtc)
+    {
+        crtc_info = pXRRGetCrtcInfo( gdi_display, screen_resources, output_info->crtc );
+        if (!crtc_info)
+            goto done;
+    }
+
+    /* Detached */
+    if (output_info->connection != RR_Connected || !output_info->crtc || !crtc_info->mode)
+    {
+        mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
+                         DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION;
+        mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
+        mode->dmBitsPerPel = 0;
+        mode->dmPelsWidth = 0;
+        mode->dmPelsHeight = 0;
+        mode->u2.dmDisplayFlags = 0;
+        mode->dmDisplayFrequency = 0;
+        mode->u1.s2.dmPosition.x = 0;
+        mode->u1.s2.dmPosition.y = 0;
+        ret = TRUE;
+        goto done;
+    }
+
+    /* Attached */
+    for (mode_idx = 0; mode_idx < screen_resources->nmode; ++mode_idx)
+    {
+        if (crtc_info->mode == screen_resources->modes[mode_idx].id)
+        {
+            mode_info = &screen_resources->modes[mode_idx];
+            break;
+        }
+    }
+
+    if (!mode_info)
+        goto done;
+
+    mode->dmFields = DM_DISPLAYORIENTATION | DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT |
+                     DM_DISPLAYFLAGS | DM_DISPLAYFREQUENCY | DM_POSITION;
+    mode->u1.s2.dmDisplayOrientation = DMDO_DEFAULT;
+    mode->dmBitsPerPel = screen_bpp;
+    mode->dmPelsWidth = mode_info->width;
+    mode->dmPelsHeight = mode_info->height;
+    mode->u2.dmDisplayFlags = 0;
+    mode->dmDisplayFrequency = get_frequency( mode_info );
+    /* Convert RandR coordinates to virtual screen coordinates */
+    primary = get_primary_rect( screen_resources );
+    mode->u1.s2.dmPosition.x = crtc_info->x - primary.left;
+    mode->u1.s2.dmPosition.y = crtc_info->y - primary.top;
+    ret = TRUE;
+done:
+    if (crtc_info)
+        pXRRFreeCrtcInfo( crtc_info );
+    if (output_info)
+        pXRRFreeOutputInfo( output_info );
+    if (screen_resources)
+        pXRRFreeScreenResources( screen_resources );
+    return ret;
+}
+
+static LONG xrandr14_set_current_mode( ULONG_PTR id, DEVMODEW *mode )
+{
+    unsigned int screen_width, screen_height;
+    RROutput output = (RROutput)id, *outputs;
+    XRRScreenResources *screen_resources;
+    XRROutputInfo *output_info = NULL;
+    XRRCrtcInfo *crtc_info = NULL;
+    LONG ret = DISP_CHANGE_FAILED;
+    INT crtc_idx, output_count;
+    Rotation rotation;
+    RRCrtc crtc = 0;
+    Status status;
+    RRMode rrmode;
+
+    if (mode->dmFields & DM_BITSPERPEL && mode->dmBitsPerPel != screen_bpp)
+        WARN("Cannot change screen color depth from %ubits to %ubits!\n", screen_bpp, mode->dmBitsPerPel);
+
+    screen_resources = xrandr_get_screen_resources();
+    if (!screen_resources)
+        return ret;
+
+    XGrabServer( gdi_display );
+
+    output_info = pXRRGetOutputInfo( gdi_display, screen_resources, output );
+    if (!output_info || output_info->connection != RR_Connected)
+        goto done;
+
+    /* Attached */
+    if (output_info->crtc)
+    {
+        crtc = output_info->crtc;
+    }
+    /* Detached, need to find a free CRTC */
+    else
+    {
+        for (crtc_idx = 0; crtc_idx < output_info->ncrtc; ++crtc_idx)
+        {
+            crtc_info = pXRRGetCrtcInfo( gdi_display, screen_resources, output_info->crtcs[crtc_idx] );
+            if (!crtc_info)
+                goto done;
+
+            if (!crtc_info->noutput)
+            {
+                crtc = output_info->crtcs[crtc_idx];
+                pXRRFreeCrtcInfo( crtc_info );
+                crtc_info = NULL;
+                break;
+            }
+
+            pXRRFreeCrtcInfo( crtc_info );
+            crtc_info = NULL;
+        }
+
+        /* Failed to find a free CRTC */
+        if (crtc_idx == output_info->ncrtc)
+            goto done;
+    }
+
+    crtc_info = pXRRGetCrtcInfo( gdi_display, screen_resources, crtc );
+    if (!crtc_info)
+        goto done;
+
+    assert( mode->dmDriverExtra == sizeof(RRMode) );
+    memcpy( &rrmode, (BYTE *)mode + sizeof(*mode), sizeof(rrmode) );
+
+    if (crtc_info->noutput)
+    {
+        outputs = crtc_info->outputs;
+        output_count = crtc_info->noutput;
+        rotation = crtc_info->rotation;
+    }
+    else
+    {
+        outputs = &output;
+        output_count = 1;
+        rotation = RR_Rotate_0;
+    }
+
+    /* According to the RandR spec, the entire CRTC must fit inside the screen.
+     * Since we use the union of all enabled CRTCs to determine the necessary
+     * screen size, this might involve shrinking the screen, so we must disable
+     * the CRTC in question first. */
+    status = pXRRSetCrtcConfig( gdi_display, screen_resources, crtc, CurrentTime, 0, 0, None,
+                                RR_Rotate_0, NULL, 0 );
+    if (status != RRSetConfigSuccess)
+        goto done;
+
+    get_screen_size( screen_resources, &screen_width, &screen_height );
+    screen_width = max( screen_width, crtc_info->x + mode->dmPelsWidth );
+    screen_height = max( screen_height, crtc_info->y + mode->dmPelsHeight );
+    set_screen_size( screen_width, screen_height );
+
+    status = pXRRSetCrtcConfig( gdi_display, screen_resources, crtc, CurrentTime,
+                                crtc_info->x, crtc_info->y, rrmode, rotation, outputs, output_count );
+    if (status == RRSetConfigSuccess)
+        ret = DISP_CHANGE_SUCCESSFUL;
+
+done:
+    XUngrabServer( gdi_display );
+    XFlush( gdi_display );
+    if (crtc_info)
+        pXRRFreeCrtcInfo( crtc_info );
+    if (output_info)
+        pXRRFreeOutputInfo( output_info );
+    pXRRFreeScreenResources( screen_resources );
+    return ret;
+}
+
 #endif
 
 void X11DRV_XRandR_Init(void)
 {
-    struct x11drv_display_device_handler handler;
+    struct x11drv_display_device_handler display_handler;
+    struct x11drv_settings_handler settings_handler;
     int event_base, error_base, minor, ret;
     static int major;
     Bool ok;
@@ -1322,16 +1656,28 @@ void X11DRV_XRandR_Init(void)
 #ifdef HAVE_XRRGETPROVIDERRESOURCES
     if (ret >= 4 && (major > 1 || (major == 1 && minor >= 4)))
     {
-        handler.name = "XRandR 1.4";
-        handler.priority = 200;
-        handler.get_gpus = xrandr14_get_gpus;
-        handler.get_adapters = xrandr14_get_adapters;
-        handler.get_monitors = xrandr14_get_monitors;
-        handler.free_gpus = xrandr14_free_gpus;
-        handler.free_adapters = xrandr14_free_adapters;
-        handler.free_monitors = xrandr14_free_monitors;
-        handler.register_event_handlers = xrandr14_register_event_handlers;
-        X11DRV_DisplayDevices_SetHandler( &handler );
+        display_handler.name = "XRandR 1.4";
+        display_handler.priority = 200;
+        display_handler.get_gpus = xrandr14_get_gpus;
+        display_handler.get_adapters = xrandr14_get_adapters;
+        display_handler.get_monitors = xrandr14_get_monitors;
+        display_handler.free_gpus = xrandr14_free_gpus;
+        display_handler.free_adapters = xrandr14_free_adapters;
+        display_handler.free_monitors = xrandr14_free_monitors;
+        display_handler.register_event_handlers = xrandr14_register_event_handlers;
+        X11DRV_DisplayDevices_SetHandler( &display_handler );
+
+        if (is_broken_driver())
+            return;
+
+        settings_handler.name = "XRandR 1.4";
+        settings_handler.priority = 300;
+        settings_handler.get_id = xrandr14_get_id;
+        settings_handler.get_modes = xrandr14_get_modes;
+        settings_handler.free_modes = xrandr14_free_modes;
+        settings_handler.get_current_mode = xrandr14_get_current_mode;
+        settings_handler.set_current_mode = xrandr14_set_current_mode;
+        X11DRV_Settings_SetHandler( &settings_handler );
     }
 #endif
 }
-- 
2.25.1




More information about the wine-devel mailing list