[PATCH v3 01/10] winex11.drv: Make it possible to merge events across process_events calls.

Rémi Bernon rbernon at codeweavers.com
Mon Oct 7 08:02:07 CDT 2019


We will have to wait for several process_events calls while delaying
FocusIn events.

Signed-off-by: Rémi Bernon <rbernon at 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 135faa8989b..e44239d834f 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 */
-- 
2.23.0




More information about the wine-devel mailing list