<html>
<head>
    <style>
        p{margin-top:0;margin-bottom:0}
    </style>
</head>
<body>
    <div style="color:#111;font-family:Apple SD Gothic Neo,Malgun Gothic,'맑은 고딕',sans-serif;font-size:10pt;line-height:1.5;">In the Korean locale, wine uses the on-the-spot style.<br>
<br>
export LC_ALL="ko_KR.UTF-8"<br>
wine64 notepad<br>
<br>
In this case, the problem is that the preedit string is not displayed<br>
properly.<br>
<br>
If XIM_COMMIT and XIM_PREEDIT_DRAW are sent from the input method,<br>
X11DRV_KeyEvent() is repeatedly executed in wine, and as a result,<br>
the order of commit string and preedit string is frequently changed.<br>
So, it often happens that the preedit string is not displayed when<br>
entering Korean.<br>
<br>
Also, the X11DRV_MsgWaitForMultipleObjectsEx() function in evenc.c runs<br>
periodically at about 0.25 second intervals, even if there are<br>
no events. Therefore, there is a possibility that the process_events()<br>
is executed repeatedly for a certain event.<br>
<br>
This patch prevents duplicate execution of X11DRV_KeyEvent() and<br>
X11DRV_MsgWaitForMultipleObjectsEx(). As a result, it prevents<br>
the order of commit string and preedit string from being reversed.<br>
<br>
Signed-off-by: Hodong Kim <hodong@nimfsoft.com><br>
---<br>
 dlls/winex11.drv/event.c | 35 +++++++++++++++++++++++++++--------<br>
 1 file changed, 27 insertions(+), 8 deletions(-)<br>
<br>
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c<br>
index 170111e9c28..d56b4fc2fde 100644<br>
--- a/dlls/winex11.drv/event.c<br>
+++ b/dlls/winex11.drv/event.c<br>
@@ -80,6 +80,15 @@ extern BOOL ximInComposeMode;<br>
 #define XEMBED_UNREGISTER_ACCELERATOR 13<br>
 #define XEMBED_ACTIVATE_ACCELERATOR   14<br>
 <br>
+static CRITICAL_SECTION event_section;<br>
+static CRITICAL_SECTION_DEBUG critsect_debug =<br>
+{<br>
+    0, 0, &event_section,<br>
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },<br>
+      0, 0, { (DWORD_PTR)(__FILE__ ": event_section") }<br>
+};<br>
+static CRITICAL_SECTION event_section = { &critsect_debug, -1, 0, 0, 0, 0 };<br>
+<br>
 Bool (*pXGetEventData)( Display *display, XEvent /*XGenericEventCookie*/ *event ) = NULL;<br>
 void (*pXFreeEventData)( Display *display, XEvent /*XGenericEventCookie*/ *event ) = NULL;<br>
 <br>
@@ -407,10 +416,13 @@ static inline BOOL call_event_handler( Display *display, XEvent *event )<br>
 static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,XPointer), ULONG_PTR arg )<br>
 {<br>
     XEvent event, prev_event;<br>
-    int count = 0;<br>
-    BOOL queued = FALSE;<br>
-    enum event_merge_action action = MERGE_DISCARD;<br>
-<br>
+    int count;<br>
+    BOOL queued;<br>
+    enum event_merge_action action;<br>
+    EnterCriticalSection( &event_section );<br>
+    count = 0;<br>
+    queued = FALSE;<br>
+    action = MERGE_DISCARD;<br>
     prev_event.type = 0;<br>
     while (XCheckIfEvent( display, &event, filter, (char *)arg ))<br>
     {<br>
@@ -445,6 +457,12 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X<br>
             else<br>
                 continue;  /* filtered, ignore it */<br>
         }<br>
+        else if (event.type == KeyPress || event.type == KeyRelease)<br>
+        {<br>
+            BOOL ret = call_event_handler( display, &event );<br>
+            LeaveCriticalSection( &event_section );<br>
+            return ret;<br>
+        }<br>
         get_event_data( &event );<br>
         if (prev_event.type) action = merge_events( &prev_event, &event );<br>
         switch( action )<br>
@@ -468,6 +486,7 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X<br>
     free_event_data( &prev_event );<br>
     XFlush( gdi_display );<br>
     if (count) TRACE( "processed %d events, returning %d\n", count, queued );<br>
+    LeaveCriticalSection( &event_section );<br>
     return queued;<br>
 }<br>
 <br>
@@ -521,7 +540,7 @@ DWORD EVENT_x11_time_to_win32_time(Time time)<br>
   }<br>
   else<br>
   {<br>
-      /* If we got an event in the 'future', then our clock is clearly wrong. <br>
+      /* If we got an event in the 'future', then our clock is clearly wrong.<br>
          If we got it more than 10000 ms in the future, then it's most likely<br>
          that the clock has wrapped.  */<br>
 <br>
@@ -728,7 +747,7 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )<br>
     {<br>
       XClientMessageEvent xev;<br>
       xev = *event;<br>
-      <br>
+<br>
       TRACE("NET_WM Ping\n");<br>
       xev.window = DefaultRootWindow(xev.display);<br>
       XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);<br>
@@ -1445,7 +1464,7 @@ static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )<br>
     RECT tempRect;<br>
 <br>
     if (!IsWindowEnabled(hQueryWnd)) return 0;<br>
-    <br>
+<br>
     GetWindowRect(hQueryWnd, &tempRect);<br>
 <br>
     if(!PtInRect(&tempRect, *lpPt)) return 0;<br>
@@ -1468,7 +1487,7 @@ static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )<br>
     }<br>
 <br>
     if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;<br>
-    <br>
+<br>
     ScreenToClient(hQueryWnd, lpPt);<br>
 <br>
     return hQueryWnd;<br>
-- <br>
2.30.2<br>
</div>
</body>
</html>
<img src="https://confirm.mail.daum.net/confirmapi/v1/users/vnodes%40hanmail%2Enet/cmails/20220109082102%2EMK0HasrFT1e7syAI8zmKJg%40vnodes%2Ehanmail%2Enet/recipients/wine-devel%40winehq%2Eorg">