[PATCH v2 1/2] winex11: Prevent the call sequence change between xim preedit callback and key event handlers.

Byeongsik Jeon bsjeon at hanmail.net
Thu Apr 7 16:59:19 CDT 2022


Signed-off-by: Byeongsik Jeon <bsjeon at hanmail.net>
---
v2: rework. update merge_events().

"xim preedit callback" is called from within the XFilterEvent().

Because of the [2/2]'s action, the strings on the 'ERASED' line are
erased.

### xim server sended event sequence ###
preedit start::
preedit draw:: caret 1 chg_first  0 chg_length  0 string 'ㄱ'
preedit draw:: caret 1 chg_first  0 chg_length  1 string '가'
preedit draw:: caret 1 chg_first  0 chg_length  1 string '간'
preedit draw:: caret 0 chg_first  0 chg_length  1 NULL
preedit done::
lookup chars::  keycode    0 string  3 '가'         <== HERE
preedit start::
preedit draw:: caret 1 chg_first  0 chg_length  0 string '나'

### Wine process_events() simulated event sequence ###
preedit start::
preedit draw:: caret 1 chg_first  0 chg_length  0 string 'ㄱ'
preedit draw:: caret 1 chg_first  0 chg_length  1 string '가'
preedit draw:: caret 1 chg_first  0 chg_length  1 string '간'
preedit draw:: caret 0 chg_first  0 chg_length  1 NULL
preedit done::
preedit start::
preedit draw:: caret 1 chg_first  0 chg_length  0 string '나' <== ERASED 
lookup chars::  keycode    0 string  3 '가'         <== HERE


 dlls/winex11.drv/event.c | 60 ++++++++++++++++++++++++++--------------
 1 file changed, 40 insertions(+), 20 deletions(-)

diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index c20ceeacca1..581e28787a0 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -261,10 +261,11 @@ static Bool filter_event( Display *display, XEvent *event, char *arg )
 
 enum event_merge_action
 {
-    MERGE_DISCARD,  /* discard the old event */
-    MERGE_HANDLE,   /* handle the old event */
+    MERGE_FLUSH,    /* handle all the events */
     MERGE_KEEP,     /* keep the old event for future merging */
-    MERGE_IGNORE    /* ignore the new event, keep the old one */
+    MERGE_IGNORE,   /* ignore the new event, keep the old one */
+    MERGE_DISCARD,  /* discard the old event */
+    MERGE_HANDLE    /* handle the old event */
 };
 
 /***********************************************************************
@@ -316,6 +317,19 @@ static enum event_merge_action merge_events( XEvent *prev, XEvent *next )
 {
     switch (prev->type)
     {
+    case 0:
+        switch (next->type)
+        {
+        case ConfigureNotify:
+        case MotionNotify:
+#ifdef HAVE_X11_EXTENSIONS_XINPUT2_H
+        case GenericEvent:
+#endif
+            return MERGE_DISCARD;
+        default:
+            return MERGE_KEEP;
+        }
+        break;
     case ConfigureNotify:
         switch (next->type)
         {
@@ -325,7 +339,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,30 +354,30 @@ 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;
-            if (next->xcookie.evtype != XI_RawMotion) break;
-            if (x11drv_thread_data()->warp_serial) break;
+            if (next->xcookie.extension != xinput2_opcode) return MERGE_HANDLE;
+            if (next->xcookie.evtype != XI_RawMotion) return MERGE_HANDLE;
+            if (x11drv_thread_data()->warp_serial) return MERGE_HANDLE;
             return MERGE_KEEP;
         }
         break;
     case GenericEvent:
-        if (prev->xcookie.extension != xinput2_opcode) break;
-        if (prev->xcookie.evtype != XI_RawMotion) break;
+        if (prev->xcookie.extension != xinput2_opcode) return MERGE_HANDLE;
+        if (prev->xcookie.evtype != XI_RawMotion) return MERGE_HANDLE;
         switch (next->type)
         {
         case GenericEvent:
-            if (next->xcookie.extension != xinput2_opcode) break;
-            if (next->xcookie.evtype != XI_RawMotion) break;
-            if (x11drv_thread_data()->warp_serial) break;
+            if (next->xcookie.extension != xinput2_opcode) return MERGE_HANDLE;
+            if (next->xcookie.evtype != XI_RawMotion) return MERGE_HANDLE;
+            if (x11drv_thread_data()->warp_serial) return MERGE_HANDLE;
             return merge_raw_motion_events( prev->xcookie.data, next->xcookie.data );
 #endif
         }
         break;
     }
-    return MERGE_HANDLE;
+    return MERGE_FLUSH;
 }
 
 
@@ -445,23 +459,29 @@ 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 );
+        action = merge_events( &prev_event, &event );
         switch( action )
         {
-        case MERGE_HANDLE:  /* handle prev, keep new */
+        case MERGE_FLUSH:  /* handle all the events */
             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;
+            prev_event.type = 0;
+            /* fall through */
         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;
+        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;
         }
     }
     if (prev_event.type) queued |= call_event_handler( display, &prev_event );
-- 
2.35.1




More information about the wine-devel mailing list