[PATCH v4 1/3] winex11: Prevent the call sequence change between xim preedit callback and key event handlers.
Byeongsik Jeon
bsjeon at hanmail.net
Fri Apr 8 07:45:39 CDT 2022
Signed-off-by: Byeongsik Jeon <bsjeon at hanmail.net>
---
v2: rework. update merge_events().
v3: remove the wrong explanatory paragraph.
v4: reorder enum event_merge_action for more clean patch.
"xim preedit callback" is called from within the XFilterEvent().
### 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 '나' <== HERE
### 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 '나' <== HERE
lookup chars:: keycode 0 string 3 '가' <== HERE
dlls/winex11.drv/event.c | 44 +++++++++++++++++++++++++++++-----------
1 file changed, 32 insertions(+), 12 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index c20ceeacca1..a744ce7e4e5 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 all the events */
MERGE_KEEP, /* keep the old event for future merging */
MERGE_IGNORE /* ignore the new event, keep the old one */
};
@@ -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,8 +459,9 @@ 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 */
@@ -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 all the events */
+ 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.35.1
More information about the wine-devel
mailing list