From: Zhiyi Zhang Subject: [PATCH 3/3] winex11.drv: Handle display device events in the desktop thread. Message-Id: <269eb529-09e1-b7b9-9b76-269632c8c0dd@codeweavers.com> Date: Tue, 8 Oct 2019 22:43:11 +0800 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 --- 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