From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index bf7d503ac76..04aef2249e9 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -348,6 +348,24 @@ static enum event_merge_action merge_raw_motion_events( XIRawEvent *prev, XIRawE } #endif
+/* merge ConfigureNotify events to reduce the chances of window resize feedback loops */ +static BOOL merge_configure_events( Display *display, XEvent *prev, XEvent *next ) +{ + BOOL queued = FALSE; + + /* allow merging ConfigureNotify across Expose and PropertyNotify events */ + if (next->type == Expose || next->type == PropertyNotify) return FALSE; + if (next->type != ConfigureNotify) return handle_delayed_event( display, prev ); + + if (!prev->type || prev->xany.window != next->xany.window) queued |= handle_delayed_event( display, prev ); + else WARN( "discarding duplicate ConfigureNotify for window %lx\n", next->xany.window ); + + TRACE( "delaying ConfigureNotify for window %lx for merging\n", next->xany.window ); + *prev = *next; + next->type = 0; + return queued; +} + /*********************************************************************** * merge_events * @@ -357,21 +375,6 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next ) { switch (prev->type) { - case ConfigureNotify: - switch (next->type) - { - case ConfigureNotify: - if (prev->xany.window == next->xany.window) - { - TRACE( "discarding duplicate ConfigureNotify for window %lx\n", prev->xany.window ); - return MERGE_DISCARD; - } - break; - case Expose: - case PropertyNotify: - return MERGE_KEEP; - } - break; case MotionNotify: switch (next->type) { @@ -415,7 +418,7 @@ BOOL X11DRV_ProcessEvents( DWORD mask ) { struct x11drv_thread_data *data = x11drv_thread_data(); Display *display = data->display; - XEvent event, prev_event; + XEvent event, prev_configure = {0}, prev_event; int count = 0; BOOL queued = FALSE; enum event_merge_action action = MERGE_DISCARD; @@ -458,7 +461,9 @@ BOOL X11DRV_ProcessEvents( DWORD mask ) continue; /* filtered, ignore it */ } get_event_data( &event ); - if (prev_event.type) action = merge_events( &prev_event, &event ); + queued |= merge_configure_events( display, &prev_configure, &event ); + if (!event.type) action = MERGE_IGNORE; + else if (prev_event.type) action = merge_events( &prev_event, &event ); switch( action ) { case MERGE_HANDLE: /* handle prev, keep new */ @@ -477,6 +482,7 @@ BOOL X11DRV_ProcessEvents( DWORD mask ) break; } } + queued |= handle_delayed_event( display, &prev_configure ); queued |= handle_delayed_event( display, &prev_event ); XFlush( gdi_display ); if (count) TRACE( "processed %d events, returning %d\n", count, queued );