From 413aad39135b0b0f8255500b85fcc05337a5f138 Mon Sep 17 00:00:00 2001 From: Zhiyi Zhang Date: Fri, 1 Nov 2019 21:20:21 +0800 Subject: [PATCH] winex11.drv: Handle display device events in the desktop thread. 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 Signed-off-by: Alexandre Julliard --- 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 a323b795b81..ee867343aef 100644 --- a/dlls/winex11.drv/display.c +++ b/dlls/winex11.drv/display.c @@ -241,6 +241,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 4e01eb201c9..f3c6a1b3cb1 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 a06cf3ffd83..35e27334db5 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -743,10 +743,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 b5620d3403c..57c77d62733 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 412400e3f62..0a64613facc 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -1063,10 +1063,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 @@ -1115,16 +1134,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 }