From: Anton Baskanov baskanov@gmail.com
We have to invalidate the current mode cache if there are pending RRNotify events. The performance hit on EnumDisplaySettingsExW is around 7%.
Also call X11DRV_DisplayDevices_RegisterEventHandlers in x11drv_init. Otherwise, RRNotify events will only be handled in the explorer process. --- dlls/user32/tests/monitor.c | 2 +- dlls/winex11.drv/event.c | 2 +- dlls/winex11.drv/window.c | 1 - dlls/winex11.drv/x11drv.h | 1 + dlls/winex11.drv/x11drv_main.c | 1 + dlls/winex11.drv/xrandr.c | 28 ++++++++++++++++++++++++++++ 6 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c index 425c32c85e2..4badd97ab04 100644 --- a/dlls/user32/tests/monitor.c +++ b/dlls/user32/tests/monitor.c @@ -1262,7 +1262,7 @@ static void test_ChangeDisplaySettingsEx(int myARGC, char **myARGV) dm.dmPelsWidth = 640; dm.dmPelsHeight = 480; dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT; - expect_dm(&dm, devices[0].name, 0, TRUE); + expect_dm(&dm, devices[0].name, 0, FALSE);
SetEvent(exit_event1); wait_result = WaitForSingleObject(process1, 10000); diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 8b02361aaff..b1c8dd778d9 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -405,7 +405,7 @@ static inline BOOL call_event_handler( Display *display, XEvent *event ) /*********************************************************************** * process_events */ -static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,XPointer), ULONG_PTR arg ) +BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,XPointer), ULONG_PTR arg ) { XEvent event, prev_event; int count = 0; diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 84878e95e37..e90a36a254e 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2040,7 +2040,6 @@ BOOL X11DRV_CreateWindow( HWND hwnd ) CWOverrideRedirect | CWEventMask, &attr ); XFlush( data->display ); NtUserSetProp( hwnd, clip_window_prop, (HANDLE)data->clip_window ); - X11DRV_DisplayDevices_RegisterEventHandlers(); } return TRUE; } diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 9c1b8012466..3abdd14e600 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -682,6 +682,7 @@ extern void retry_grab_clipping_window(void); extern void ungrab_clipping_window(void); extern void move_resize_window( HWND hwnd, int dir ); extern void X11DRV_InitKeyboard( Display *display ); +extern BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*, XPointer), ULONG_PTR arg ); extern BOOL X11DRV_ProcessEvents( DWORD mask ); extern HWND *build_hwnd_list(void);
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index 0925fe54b9c..c4d56c2d542 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -703,6 +703,7 @@ static NTSTATUS x11drv_init( void *arg )
init_user_driver(); X11DRV_DisplayDevices_Init(FALSE); + X11DRV_DisplayDevices_RegisterEventHandlers(); return STATUS_SUCCESS; }
diff --git a/dlls/winex11.drv/xrandr.c b/dlls/winex11.drv/xrandr.c index d77eb1a0163..bc4ae0209ac 100644 --- a/dlls/winex11.drv/xrandr.c +++ b/dlls/winex11.drv/xrandr.c @@ -1213,6 +1213,32 @@ static void xrandr14_register_event_handlers(void) "XRandR ProviderChange" ); }
+static Bool filter_rrnotify_event( Display *display, XEvent *event, char *arg ) +{ + ULONG_PTR event_base = (ULONG_PTR)arg; + + if (event->type == event_base + RRNotify_CrtcChange + || event->type == event_base + RRNotify_OutputChange + || event->type == event_base + RRNotify_ProviderChange) + return 1; + + return 0; +} + +static void process_rrnotify_events(void) +{ + struct x11drv_thread_data *data = x11drv_thread_data(); + int event_base, error_base; + + if (!data) return; + if (data->current_event) return; /* don't process nested events */ + + if (!pXRRQueryExtension( data->display, &event_base, &error_base )) + return; + + process_events( data->display, filter_rrnotify_event, event_base ); +} + /* XRandR 1.4 display settings handler */ static BOOL xrandr14_get_id( const WCHAR *device_name, BOOL is_primary, x11drv_settings_id *id ) { @@ -1228,6 +1254,8 @@ static BOOL xrandr14_get_id( const WCHAR *device_name, BOOL is_primary, x11drv_s if (*end) return FALSE;
+ process_rrnotify_events(); + /* Update cache */ pthread_mutex_lock( &xrandr_mutex ); if (!current_modes)