We will have to wait for several process_events calls while delaying FocusIn/WM_TAKE_FOCUS events.
Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/winex11.drv/event.c | 73 +++++++++++++++++++++++++-------------- dlls/winex11.drv/x11drv.h | 1 + 2 files changed, 48 insertions(+), 26 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 25730192d3d..32fdf23bf35 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -404,22 +404,50 @@ static inline BOOL call_event_handler( Display *display, XEvent *event ) return ret; }
+static inline BOOL merge_and_handle_events( Display *display, XEvent *prev, XEvent *next ) +{ + enum event_merge_action action = MERGE_DISCARD; + BOOL queued = FALSE; + + if (prev->type) action = merge_events( prev, next ); + switch( action ) + { + case MERGE_HANDLE: /* handle prev, keep new */ + queued |= call_event_handler( display, prev ); + /* fall through */ + case MERGE_DISCARD: /* discard prev, keep new */ + free_event_data( prev ); + *prev = *next; + break; + case MERGE_KEEP: /* handle new, keep prev for future merging */ + if (!next->type) break; + queued |= call_event_handler( display, next ); + /* fall through */ + case MERGE_IGNORE: /* ignore new, keep prev for future merging */ + free_event_data( next ); + break; + } + + return queued; +}
/*********************************************************************** * process_events */ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,XPointer), ULONG_PTR arg ) { - XEvent event, prev_event; + struct x11drv_thread_data *thread_data = x11drv_thread_data(); + XEvent event, *next = &event, *prev = &thread_data->prev_event; int count = 0; BOOL queued = FALSE; - enum event_merge_action action = MERGE_DISCARD;
- prev_event.type = 0; - while (XCheckIfEvent( display, &event, filter, (char *)arg )) + next->type = 0; + if (prev->type) get_event_data( prev ); + + while (XCheckIfEvent( display, next, filter, (char *)arg )) { count++; - if (XFilterEvent( &event, None )) + if (XFilterEvent( next, None )) { /* * SCIM on linux filters key events strangely. It does not filter the @@ -433,7 +461,7 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X if (event.type == KeyRelease) { KeySym keysym = 0; - XKeyEvent *keyevent = &event.xkey; + XKeyEvent *keyevent = &next->xkey;
XLookupString(keyevent, NULL, 0, &keysym, NULL); if (!(keysym == XK_Shift_L || @@ -449,27 +477,20 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X else continue; /* filtered, ignore it */ } - get_event_data( &event ); - if (prev_event.type) action = merge_events( &prev_event, &event ); - switch( action ) - { - case MERGE_HANDLE: /* handle prev, keep new */ - queued |= call_event_handler( display, &prev_event ); - /* fall through */ - case MERGE_DISCARD: /* discard prev, keep new */ - free_event_data( &prev_event ); - prev_event = event; - break; - case MERGE_KEEP: /* handle new, keep prev for future merging */ - queued |= call_event_handler( display, &event ); - /* fall through */ - case MERGE_IGNORE: /* ignore new, keep prev for future merging */ - free_event_data( &event ); - break; - } + get_event_data( next ); + queued |= merge_and_handle_events( display, prev, next ); } - if (prev_event.type) queued |= call_event_handler( display, &prev_event ); - free_event_data( &prev_event ); + + if (prev->type && !thread_data->current_event) + { + next->type = 0; + queued |= merge_and_handle_events( display, prev, next ); + free_event_data( prev ); + + /* retry handling prev next time */ + if (prev->type) queued |= 1; + } + XFlush( gdi_display ); if (count) TRACE( "processed %d events, returning %d\n", count, queued ); return queued; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index d4e476facb2..65cb5ecf6f2 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -323,6 +323,7 @@ struct x11drv_valuator_data struct x11drv_thread_data { Display *display; + XEvent prev_event; /* event to be eventually merged */ XEvent *current_event; /* event currently being processed */ HWND grab_hwnd; /* window that currently grabs the mouse */ HWND last_focus; /* last window that had focus */