[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