Signed-off-by: Byeongsik Jeon bsjeon@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 */
Signed-off-by: Byeongsik Jeon bsjeon@hanmail.net --- v2: rework. minimize change from e4d94e48138f v3: no changes v4: 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);
On Fri, 8 Apr 2022 21:45:40 +0900, Byeongsik Jeon wrote: [...]
@@ -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);
Hi, From my point of view, the purpose of these !inComp blocks is to synchronize the status when root window style is used, i.e. no preedit callbacks happen. Moreover, the composition string length is mostly zero unless XIMPreEditDrawCallback is called. I'd suggest you to omit status updates if the preedit callback is used before.
I leave the review of other two patches to the maintainers because I'm not familiar with X event handlers.
Akihiro Sagawa
On 4/10/22 8:52 PM, Akihiro Sagawa wrote:
On Fri, 8 Apr 2022 21:45:40 +0900, Byeongsik Jeon wrote: [...]
@@ -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);
Hi, From my point of view, the purpose of these !inComp blocks is to synchronize the status when root window style is used, i.e. no preedit callbacks happen. Moreover, the composition string length is mostly zero unless XIMPreEditDrawCallback is called. I'd suggest you to omit status updates if the preedit callback is used before.
Hi, Thank you for review :-)
The patch was defensively written because the e4d94e48138f situation was not known exactly. I will try to improve the patch by referring to this review.
I found something strange during this issue test. This is probably related to the issue that Alex Kwak found. It's going to take some time to analyze.
https://www.winehq.org/pipermail/wine-devel/2022-April/212598.html
I leave the review of other two patches to the maintainers because I'm not familiar with X event handlers.
I don't know if there's any way to write 'Wine test code' for this issue. Instead, I wrote a small "xim event print" program.
$ XMODIFIERS=@im=ibus ./xim-test $ XMODIFIERS=@im=ibus ./xim-test --wine
If events are generated in the sequence "result_string >> composition_string" by one key input, the sequence will change. My Japanese test sample is "日本の" and the key sequence is "nihon<SPACE>no".
It happens very often in the Korean "du-bul-sik" keymap automata, and "du-bul-sik" is the dominant automata.
Because composition_string occurs in XFilterEvent() and result_string occurs in XKeyEvent handler, the sequence will change in the current Wine merge_events() implementation.
Akihiro Sagawa
Hi, Jeon
( from: https://source.winehq.org/patches/data/231475 )
Sorry for late reply. I didn't see my email.
I'm so happy to have someone interested in this issue.
But, one thing i don't understand that why must signaling WM_IME_ENDCOMPOSITION.
It will handled from preedit callbacks.
Doesn't the WM_IME_ENDCOMPOSITION signal occur twice?
Regards.,
Alex
On 22. 4. 11. 16:57, Byeongsik Jeon wrote:
On 4/10/22 8:52 PM, Akihiro Sagawa wrote:
On Fri, 8 Apr 2022 21:45:40 +0900, Byeongsik Jeon wrote: [...]
@@ -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);
Hi, From my point of view, the purpose of these !inComp blocks is to synchronize the status when root window style is used, i.e. no preedit callbacks happen. Moreover, the composition string length is mostly zero unless XIMPreEditDrawCallback is called. I'd suggest you to omit status updates if the preedit callback is used before.
Hi, Thank you for review :-)
The patch was defensively written because the e4d94e48138f situation was not known exactly. I will try to improve the patch by referring to this review.
I found something strange during this issue test. This is probably related to the issue that Alex Kwak found. It's going to take some time to analyze.
https://www.winehq.org/pipermail/wine-devel/2022-April/212598.html
I leave the review of other two patches to the maintainers because I'm not familiar with X event handlers.
I don't know if there's any way to write 'Wine test code' for this issue. Instead, I wrote a small "xim event print" program.
$ XMODIFIERS=@im=ibus ./xim-test $ XMODIFIERS=@im=ibus ./xim-test --wine
If events are generated in the sequence "result_string >> composition_string" by one key input, the sequence will change. My Japanese test sample is "日本の" and the key sequence is "nihon<SPACE>no".
It happens very often in the Korean "du-bul-sik" keymap automata, and "du-bul-sik" is the dominant automata.
Because composition_string occurs in XFilterEvent() and result_string occurs in XKeyEvent handler, the sequence will change in the current Wine merge_events() implementation.
Akihiro Sagawa
On 4/11/22 5:50 PM, Alex Kwak wrote:
Hi, Jeon
( from: https://source.winehq.org/patches/data/231475 )
Sorry for late reply. I didn't see my email.
I'm so happy to have someone interested in this issue.
But, one thing i don't understand that why must signaling WM_IME_ENDCOMPOSITION.
It will handled from preedit callbacks.
Doesn't the WM_IME_ENDCOMPOSITION signal occur twice?
Hi,
Actually, I don't know why.
### 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 1 preedit start:: <== HERE 2 preedit draw:: caret 1 chg_first 0 chg_length 0 string '나' <== HERE 3
I'm not sure, but if I guess. By "[PATCH v4 1/3]" issue, the sequence of events changes as follows:
### current 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:: <== HERE 4 preedit draw:: caret 1 chg_first 0 chg_length 0 string '나' <== HERE 5 lookup chars:: keycode 0 string 3 '가' <== HERE 6
IME_SetResultString() is in "HERE 6".
At this time, it is "inComp = TRUE" and WM_IME_STARTCOMPOSITION occurred. it may be thought that WM_IME_ENDCOMPOSITION is necessary.
When it and "if (!inComp) GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0);" combine, WM_IME_ENDCOMPOSITION come out of 'if'.
It's just guess.
Regards.,
Alex
On 22. 4. 11. 16:57, Byeongsik Jeon wrote:
On 4/10/22 8:52 PM, Akihiro Sagawa wrote:
On Fri, 8 Apr 2022 21:45:40 +0900, Byeongsik Jeon wrote: [...]
@@ -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);
Hi, From my point of view, the purpose of these !inComp blocks is to synchronize the status when root window style is used, i.e. no preedit callbacks happen. Moreover, the composition string length is mostly zero unless XIMPreEditDrawCallback is called. I'd suggest you to omit status updates if the preedit callback is used before.
Hi, Thank you for review :-)
The patch was defensively written because the e4d94e48138f situation was not known exactly. I will try to improve the patch by referring to this review.
I found something strange during this issue test. This is probably related to the issue that Alex Kwak found. It's going to take some time to analyze.
https://www.winehq.org/pipermail/wine-devel/2022-April/212598.html
I leave the review of other two patches to the maintainers because I'm not familiar with X event handlers.
I don't know if there's any way to write 'Wine test code' for this issue. Instead, I wrote a small "xim event print" program.
$ XMODIFIERS=@im=ibus ./xim-test $ XMODIFIERS=@im=ibus ./xim-test --wine
If events are generated in the sequence "result_string >> composition_string" by one key input, the sequence will change. My Japanese test sample is "日本の" and the key sequence is "nihon<SPACE>no".
It happens very often in the Korean "du-bul-sik" keymap automata, and "du-bul-sik" is the dominant automata.
Because composition_string occurs in XFilterEvent() and result_string occurs in XKeyEvent handler, the sequence will change in the current Wine merge_events() implementation.
Akihiro Sagawa
Hi Jeon,
I tested your code with riched20 ( wine ver, windows ver )
For example, trying to type "가나" words.
following messages generated.
WM_IME_STARTCOMPOSITION GCS_COMPSTR L"\3131" GCS_COMPSTR L"\ac00" GCS_COMPSTR L"\ac04" GCS_COMPSTR L"" GCS_RESULTSTR L"\ac00" WM_IME_ENDCOMPOSITION GCS_COMPSTR L"\b098"
In the above scenario, STARTCCOMPOSITION does not occur after ENDCOMPOSITION.
in that result, "나" needs to selection. but, it isn't.
In most cases, the location of the Cursor is specified for STARTCOMPOSITION, and in ENDCOMPOSITION, the input operation is completed.
therefore, other problems arise.
Regards,.
Alex
On 22. 4. 11. 19:07, Byeongsik Jeon wrote:
Hi,
Actually, I don't know why.
### 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 1 preedit start:: <== HERE 2 preedit draw:: caret 1 chg_first 0 chg_length 0 string '나' <== HERE 3
I'm not sure, but if I guess. By "[PATCH v4 1/3]" issue, the sequence of events changes as follows:
### current 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:: <== HERE 4 preedit draw:: caret 1 chg_first 0 chg_length 0 string '나' <== HERE 5 lookup chars:: keycode 0 string 3 '가' <== HERE 6
IME_SetResultString() is in "HERE 6".
At this time, it is "inComp = TRUE" and WM_IME_STARTCOMPOSITION occurred. it may be thought that WM_IME_ENDCOMPOSITION is necessary.
When it and "if (!inComp) GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0);" combine, WM_IME_ENDCOMPOSITION come out of 'if'.
It's just guess.
On 4/12/22 11:19 AM, Alex Kwak wrote:
Hi Jeon,
I tested your code with riched20 ( wine ver, windows ver )
It's good point. We should not write the xim ime code based on the Wine builtin richedit control.
For example, trying to type "가나" words.
following messages generated.
WM_IME_STARTCOMPOSITION GCS_COMPSTR L"\3131" GCS_COMPSTR L"\ac00" GCS_COMPSTR L"\ac04" GCS_COMPSTR L"" GCS_RESULTSTR L"\ac00" WM_IME_ENDCOMPOSITION GCS_COMPSTR L"\b098"
In the above scenario, STARTCCOMPOSITION does not occur after ENDCOMPOSITION.
in that result, "나" needs to selection. but, it isn't.
In most cases, the location of the Cursor is specified for STARTCOMPOSITION, and in ENDCOMPOSITION, the input operation is completed.
therefore, other problems arise.
OK. I agree that WM_IME_ENDCOMPOSITON should be modified.
My comment is an effort to understand the e4d94e48138f code and the situation at the time. What needs to be modified should be modified.
I think the Wine xim ime code modification should be done after [PATCH v4 1/3]. If we create code based on the XKey events rearranged by process_events(), we may have a strange patch.
Since the Wine xim ime code has been written based on the current process_events(), applying [1/3] can result in regression in some codes. But I think this is the right direction.
[PATCH v4 2/3] is currently in rework. In the process of tracking ImmSetOpenStatus(), I found that there were more fundamental problem. I think it will take time to make the appropriate patch.
[PATCH v4 3/3] is also reworking. If we actively use XFilterEvent(), Wine can generate WM_KEYDOWN message even under XIM activity.
Regards,.
Alex
On 22. 4. 11. 19:07, Byeongsik Jeon wrote:
Hi,
Actually, I don't know why.
### 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 1 preedit start:: <== HERE 2 preedit draw:: caret 1 chg_first 0 chg_length 0 string '나' <== HERE 3
I'm not sure, but if I guess. By "[PATCH v4 1/3]" issue, the sequence of events changes as follows:
### current 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:: <== HERE 4 preedit draw:: caret 1 chg_first 0 chg_length 0 string '나' <== HERE 5 lookup chars:: keycode 0 string 3 '가' <== HERE 6
IME_SetResultString() is in "HERE 6".
At this time, it is "inComp = TRUE" and WM_IME_STARTCOMPOSITION occurred. it may be thought that WM_IME_ENDCOMPOSITION is necessary.
When it and "if (!inComp) GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0);" combine, WM_IME_ENDCOMPOSITION come out of 'if'.
It's just guess.
Signed-off-by: Byeongsik Jeon bsjeon@hanmail.net --- v4: add new patch
XFilterEvent() invoked "xim callbacks" can also be treated as event handlers.
dlls/winex11.drv/event.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index a744ce7e4e5..02fb37eec05 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -424,13 +424,19 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X int count = 0; BOOL queued = FALSE; enum event_merge_action action = MERGE_DISCARD; + struct x11drv_thread_data *thread_data = x11drv_thread_data();
prev_event.type = 0; while (XCheckIfEvent( display, &event, filter, (char *)arg )) { + XEvent *prev = thread_data->current_event; + thread_data->current_event = &event; count++; if (XFilterEvent( &event, None )) { + thread_data->current_event = prev; + queued = TRUE; + /* * SCIM on linux filters key events strangely. It does not filter the * KeyPress events for these keys however it does filter the @@ -459,6 +465,7 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X else continue; /* filtered, ignore it */ } + thread_data->current_event = prev;
get_event_data( &event ); action = merge_events( &prev_event, &event );