Signed-off-by: Byeongsik Jeon bsjeon@hanmail.net --- v2: rework. update merge_events(). v3: remove the wrong explanatory paragraph.
"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 | 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 );
Signed-off-by: Byeongsik Jeon bsjeon@hanmail.net --- v2: rework. minimize change from e4d94e48138f v3: no changes
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 <== HERE preedit done:: lookup chars:: keycode 0 string 3 '가' <== IME_SetResultString preedit start:: preedit draw:: caret 1 chg_first 0 chg_length 0 string '나'
Some xim server generate the "events" that erase the "preedit draw" string before "lookup chars". These translates to WM_IME_ messages. In this case, the corresponding action of IME_SetResultString() is not required. I tried to reduce the side effects because I can't test the issue of e4d94e48138f .
dlls/winex11.drv/ime.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index c1584930861..1e50d187f19 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -1022,15 +1022,21 @@ void IME_SetResultString(LPWSTR lpResult, DWORD dwResultLen) HIMCC newCompStr; LPIMEPRIVATE myPrivate; BOOL inComp; + LPBYTE compdata; + DWORD compstr_len;
imc = RealIMC(FROM_X11); lpIMC = ImmLockIMC(imc); if (lpIMC == NULL) return;
- newCompStr = updateCompStr(lpIMC->hCompStr, NULL, 0); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = newCompStr; + if (lpIMC->hCompStr && (compdata = ImmLockIMCC( lpIMC->hCompStr )) && + (compstr_len = ((LPCOMPOSITIONSTRING)compdata)->dwCompStrLen)) + { + newCompStr = updateCompStr( lpIMC->hCompStr, NULL, 0 ); + ImmDestroyIMCC( lpIMC->hCompStr ); + lpIMC->hCompStr = newCompStr; + }
newCompStr = updateResultStr(lpIMC->hCompStr, lpResult, dwResultLen); ImmDestroyIMCC(lpIMC->hCompStr); @@ -1040,7 +1046,7 @@ void IME_SetResultString(LPWSTR lpResult, DWORD dwResultLen) inComp = myPrivate->bInComposition; ImmUnlockIMCC(lpIMC->hPrivate);
- if (!inComp) + if (!inComp && compstr_len) { ImmSetOpenStatus(imc, TRUE); GenerateIMEMessage(imc, WM_IME_STARTCOMPOSITION, 0, 0); @@ -1050,7 +1056,7 @@ void IME_SetResultString(LPWSTR lpResult, DWORD dwResultLen) GenerateIMEMessage(imc, WM_IME_COMPOSITION, lpResult[0], GCS_RESULTSTR|GCS_RESULTCLAUSE); GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0);
- if (!inComp) + if (!inComp && compstr_len) ImmSetOpenStatus(imc, FALSE);
ImmUnlockIMC(imc);