[PATCH v5] winex11: Prevent the call sequence change between xim preedit callback and event handlers.

Byeongsik Jeon bsjeon at hanmail.net
Wed Apr 20 02:26:15 CDT 2022


Signed-off-by: Byeongsik Jeon <bsjeon at hanmail.net>
---
v1: first implemetation.
v2: rework. update merge_events().
v3: delete the incorrect description.
v4: MERGE_FLUSH enumeration change.
v5: update merge_events() more. fix GenericEvent processing.

The current process_events() pseudecode for non-mergeable events may be
simplified as follows:

process_events()
{
    prev_event.type = 0;

    while (XCheckIfEvent( &event ))
    {
        if (XFilterEvent( &event )) continue;

        if (prev_event.type) call_event_handler( &prev_event );

        prev_event = event;
    }

    if (prev_event.type) call_event_handler( &prev_event );
}

- "xim preedit callbacks" are called from within the XFilterEvent().
- Depending on the XCheckIfEvent(), XFilterEvent() return value,
  the call_event_handler() may be called after one or more loop steps.

So, call_event_handler() may be delayed after the next "xim preedit callback" call.

 dlls/winex11.drv/event.c | 34 +++++++++++++++++++++++++++-------
 1 file changed, 27 insertions(+), 7 deletions(-)

diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index 900f24c4002..bee37f3368b 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -263,6 +263,7 @@ enum event_merge_action
 {
     MERGE_DISCARD,  /* discard the old event */
     MERGE_HANDLE,   /* handle the old event */
+    MERGE_FLUSH,    /* handle the old and new event */
     MERGE_KEEP,     /* keep the old event for future merging */
     MERGE_IGNORE    /* ignore the new event, keep the old one */
 };
@@ -316,6 +317,22 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next )
 {
     switch (prev->type)
     {
+    case 0:
+        switch (next->type)
+        {
+#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
+        case GenericEvent:
+            if (next->xcookie.extension != xinput2_opcode) break;
+            if (next->xcookie.evtype != XI_RawMotion) break;
+            if (x11drv_thread_data()->warp_serial) break;
+            /* fall through */
+#endif
+        case ConfigureNotify:
+        case MotionNotify:
+            return MERGE_DISCARD;
+        }
+        return MERGE_KEEP;
+
     case ConfigureNotify:
         switch (next->type)
         {
@@ -325,7 +342,7 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next )
                 TRACE( "discarding duplicate ConfigureNotify for window %lx\n", prev->xany.window );
                 return MERGE_DISCARD;
             }
-            break;
+            return MERGE_HANDLE;
         case Expose:
         case PropertyNotify:
             return MERGE_KEEP;
@@ -340,7 +357,7 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next )
                 TRACE( "discarding duplicate MotionNotify for window %lx\n", prev->xany.window );
                 return MERGE_DISCARD;
             }
-            break;
+            return MERGE_HANDLE;
 #ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
         case GenericEvent:
             if (next->xcookie.extension != xinput2_opcode) break;
@@ -350,8 +367,6 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next )
         }
         break;
     case GenericEvent:
-        if (prev->xcookie.extension != xinput2_opcode) break;
-        if (prev->xcookie.evtype != XI_RawMotion) break;
         switch (next->type)
         {
         case GenericEvent:
@@ -363,7 +378,7 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next )
         }
         break;
     }
-    return MERGE_HANDLE;
+    return MERGE_FLUSH;
 }
 
 
@@ -409,7 +424,7 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X
     XEvent event, prev_event;
     int count = 0;
     BOOL queued = FALSE;
-    enum event_merge_action action = MERGE_DISCARD;
+    enum event_merge_action action;
 
     prev_event.type = 0;
     while (XCheckIfEvent( display, &event, filter, (char *)arg ))
@@ -446,7 +461,7 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X
                 continue;  /* filtered, ignore it */
         }
         get_event_data( &event );
-        if (prev_event.type) action = merge_events( &prev_event, &event );
+        action = merge_events( &prev_event, &event );
         switch( action )
         {
         case MERGE_HANDLE:  /* handle prev, keep new */
@@ -456,6 +471,11 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X
             free_event_data( &prev_event );
             prev_event = event;
             break;
+        case MERGE_FLUSH: /* handle prev and new */
+            queued |= call_event_handler( display, &prev_event );
+            free_event_data( &prev_event );
+            prev_event.type = 0;
+            /* fall through */
         case MERGE_KEEP:  /* handle new, keep prev for future merging */
             queued |= call_event_handler( display, &event );
             /* fall through */
-- 
2.36.0




More information about the wine-devel mailing list