[PATCH 3/3] winex11.drv: Handle display device events in the desktop thread.

Zhiyi Zhang zzhang at codeweavers.com
Tue Oct 8 09:43:11 CDT 2019


This fixes a regression from 22795243b2d21e1a667215f54c3a15634735749c,
which calls thread_init_display() and eventually XOpenIM() before
X11DRV_InitXIM() is called.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47821
Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
---
 dlls/winex11.drv/display.c  |  6 ++++++
 dlls/winex11.drv/window.c   |  1 +
 dlls/winex11.drv/x11drv.h   |  5 +++++
 dlls/winex11.drv/xinerama.c |  1 +
 dlls/winex11.drv/xrandr.c   | 35 +++++++++++++++++++++++------------
 5 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/dlls/winex11.drv/display.c b/dlls/winex11.drv/display.c
index 5b0b062ff6..e351484e31 100644
--- a/dlls/winex11.drv/display.c
+++ b/dlls/winex11.drv/display.c
@@ -243,6 +243,12 @@ void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler
     }
 }
 
+void X11DRV_DisplayDevices_RegisterEventHandlers(void)
+{
+    if (handler.register_event_handlers)
+        handler.register_event_handlers();
+}
+
 /* Initialize a GPU instance and return its GUID string in guid_string and driver value in driver parameter */
 static BOOL X11DRV_InitGpu(HDEVINFO devinfo, const struct x11drv_gpu *gpu, INT gpu_index, WCHAR *guid_string,
                            WCHAR *driver)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 4e01eb201c..f3c6a1b3cb 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -1833,6 +1833,7 @@ BOOL CDECL X11DRV_CreateWindow( HWND hwnd )
         XFlush( data->display );
         SetPropA( hwnd, clip_window_prop, (HANDLE)data->clip_window );
         X11DRV_InitClipboard();
+        X11DRV_DisplayDevices_RegisterEventHandlers();
     }
     return TRUE;
 }
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h
index 4b5c5d479f..e73cdc62d3 100644
--- a/dlls/winex11.drv/x11drv.h
+++ b/dlls/winex11.drv/x11drv.h
@@ -741,10 +741,15 @@ struct x11drv_display_device_handler
 
     /* free_monitors will be called to free a monitor list from get_monitors */
     void (*free_monitors)(struct x11drv_monitor *monitors);
+
+    /* register_event_handlers will be called to register event handlers.
+     * This function pointer is optional and can be NULL when driver doesn't support it */
+    void (*register_event_handlers)(void);
 };
 
 extern void X11DRV_DisplayDevices_SetHandler(const struct x11drv_display_device_handler *handler) DECLSPEC_HIDDEN;
 extern void X11DRV_DisplayDevices_Init(BOOL force) DECLSPEC_HIDDEN;
+extern void X11DRV_DisplayDevices_RegisterEventHandlers(void) DECLSPEC_HIDDEN;
 
 /* XIM support */
 extern BOOL X11DRV_InitXIM( const char *input_style ) DECLSPEC_HIDDEN;
diff --git a/dlls/winex11.drv/xinerama.c b/dlls/winex11.drv/xinerama.c
index b5620d3403..57c77d6273 100644
--- a/dlls/winex11.drv/xinerama.c
+++ b/dlls/winex11.drv/xinerama.c
@@ -344,5 +344,6 @@ void xinerama_init( unsigned int width, unsigned int height )
     handler.free_gpus = xinerama_free_gpus;
     handler.free_adapters = xinerama_free_adapters;
     handler.free_monitors = xinerama_free_monitors;
+    handler.register_event_handlers = NULL;
     X11DRV_DisplayDevices_SetHandler( &handler );
 }
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c
index 4933b6835f..0b9bfa2cd1 100644
--- a/dlls/winex11.drv/xrandr.c
+++ b/dlls/winex11.drv/xrandr.c
@@ -1061,10 +1061,29 @@ static void xrandr14_free_monitors( struct x11drv_monitor *monitors )
     heap_free( monitors );
 }
 
-static BOOL xrandr14_device_change_event( HWND hwnd, XEvent *event )
+static BOOL xrandr14_device_change_handler( HWND hwnd, XEvent *event )
 {
-    X11DRV_DisplayDevices_Init( TRUE );
-    return TRUE;
+    if (hwnd == GetDesktopWindow() && GetWindowThreadProcessId( hwnd, NULL ) == GetCurrentThreadId())
+        X11DRV_DisplayDevices_Init( TRUE );
+    return FALSE;
+}
+
+static void xrandr14_register_event_handlers(void)
+{
+    Display *display = thread_init_display();
+    int event_base, error_base;
+
+    if (!pXRRQueryExtension( display, &event_base, &error_base ))
+        return;
+
+    pXRRSelectInput( display, root_window,
+                     RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RRProviderChangeNotifyMask );
+    X11DRV_register_event_handler( event_base + RRNotify_CrtcChange, xrandr14_device_change_handler,
+                                   "XRandR CrtcChange" );
+    X11DRV_register_event_handler( event_base + RRNotify_OutputChange, xrandr14_device_change_handler,
+                                   "XRandR OutputChange" );
+    X11DRV_register_event_handler( event_base + RRNotify_ProviderChange, xrandr14_device_change_handler,
+                                   "XRandR ProviderChange" );
 }
 
 #endif
@@ -1113,16 +1132,8 @@ void X11DRV_XRandR_Init(void)
         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 );
-
-        pXRRSelectInput( thread_init_display(), root_window,
-                         RRCrtcChangeNotifyMask | RROutputChangeNotifyMask | RRProviderChangeNotifyMask);
-        X11DRV_register_event_handler( event_base + RRNotify_CrtcChange, xrandr14_device_change_event,
-                                       "XRandR CrtcChange" );
-        X11DRV_register_event_handler( event_base + RRNotify_OutputChange, xrandr14_device_change_event,
-                                       "XRandR OutputChange" );
-        X11DRV_register_event_handler( event_base + RRNotify_ProviderChange, xrandr14_device_change_event,
-                                       "XRandR ProviderChange" );
     }
 #endif
 }
-- 
2.23.0




More information about the wine-devel mailing list