[PATCH resend] winex11.drv: Avoid duplicate executions of event processing

Hodong Kim hodong at nimfsoft.com
Sat Jan 8 17:40:19 CST 2022


In the Korean locale, wine uses the on-the-spot style.

export LC_ALL="ko_KR.UTF-8"
wine64 notepad

In this case, the problem is that the preedit string is not displayed
properly.

If XIM_COMMIT and XIM_PREEDIT_DRAW are sent from the input method,
X11DRV_KeyEvent() is repeatedly executed in wine, and as a result,
the order of commit string and preedit string is frequently changed.
So, it often happens that the preedit string is not displayed when
entering Korean.

Also, the X11DRV_MsgWaitForMultipleObjectsEx() function in evenc.c runs
periodically at about 0.25 second intervals, even if there are
no events. Therefore, there is a possibility that the process_events()
is executed repeatedly for a certain event.

This patch prevents duplicate execution of X11DRV_KeyEvent() and
X11DRV_MsgWaitForMultipleObjectsEx(). As a result, it prevents
the order of commit string and preedit string from being reversed.

Signed-off-by: Hodong Kim <hodong at nimfsoft.com>
---
 dlls/winex11.drv/event.c | 35 +++++++++++++++++++++++++++--------
 1 file changed, 27 insertions(+), 8 deletions(-)

diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
index 170111e9c28..d56b4fc2fde 100644
--- a/dlls/winex11.drv/event.c
+++ b/dlls/winex11.drv/event.c
@@ -80,6 +80,15 @@ extern BOOL ximInComposeMode;
 #define XEMBED_UNREGISTER_ACCELERATOR 13
 #define XEMBED_ACTIVATE_ACCELERATOR   14
 
+static CRITICAL_SECTION event_section;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+    0, 0, &event_section,
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": event_section") }
+};
+static CRITICAL_SECTION event_section = { &critsect_debug, -1, 0, 0, 0, 0 };
+
 Bool (*pXGetEventData)( Display *display, XEvent /*XGenericEventCookie*/ *event ) = NULL;
 void (*pXFreeEventData)( Display *display, XEvent /*XGenericEventCookie*/ *event ) = NULL;
 
@@ -407,10 +416,13 @@ static inline BOOL call_event_handler( Display *display, XEvent *event )
 static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,XPointer), ULONG_PTR arg )
 {
     XEvent event, prev_event;
-    int count = 0;
-    BOOL queued = FALSE;
-    enum event_merge_action action = MERGE_DISCARD;
-
+    int count;
+    BOOL queued;
+    enum event_merge_action action;
+    EnterCriticalSection( &event_section );
+    count = 0;
+    queued = FALSE;
+    action = MERGE_DISCARD;
     prev_event.type = 0;
     while (XCheckIfEvent( display, &event, filter, (char *)arg ))
     {
@@ -445,6 +457,12 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X
             else
                 continue;  /* filtered, ignore it */
         }
+        else if (event.type == KeyPress || event.type == KeyRelease)
+        {
+            BOOL ret = call_event_handler( display, &event );
+            LeaveCriticalSection( &event_section );
+            return ret;
+        }
         get_event_data( &event );
         if (prev_event.type) action = merge_events( &prev_event, &event );
         switch( action )
@@ -468,6 +486,7 @@ static BOOL process_events( Display *display, Bool (*filter)(Display*, XEvent*,X
     free_event_data( &prev_event );
     XFlush( gdi_display );
     if (count) TRACE( "processed %d events, returning %d\n", count, queued );
+    LeaveCriticalSection( &event_section );
     return queued;
 }
 
@@ -521,7 +540,7 @@ DWORD EVENT_x11_time_to_win32_time(Time time)
   }
   else
   {
-      /* If we got an event in the 'future', then our clock is clearly wrong. 
+      /* If we got an event in the 'future', then our clock is clearly wrong.
          If we got it more than 10000 ms in the future, then it's most likely
          that the clock has wrapped.  */
 
@@ -728,7 +747,7 @@ static void handle_wm_protocols( HWND hwnd, XClientMessageEvent *event )
     {
       XClientMessageEvent xev;
       xev = *event;
-      
+
       TRACE("NET_WM Ping\n");
       xev.window = DefaultRootWindow(xev.display);
       XSendEvent(xev.display, xev.window, False, SubstructureRedirectMask | SubstructureNotifyMask, (XEvent*)&xev);
@@ -1445,7 +1464,7 @@ static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
     RECT tempRect;
 
     if (!IsWindowEnabled(hQueryWnd)) return 0;
-    
+
     GetWindowRect(hQueryWnd, &tempRect);
 
     if(!PtInRect(&tempRect, *lpPt)) return 0;
@@ -1468,7 +1487,7 @@ static HWND find_drop_window( HWND hQueryWnd, LPPOINT lpPt )
     }
 
     if(!(GetWindowLongA( hQueryWnd, GWL_EXSTYLE ) & WS_EX_ACCEPTFILES)) return 0;
-    
+
     ScreenToClient(hQueryWnd, lpPt);
 
     return hQueryWnd;
-- 
2.30.2






More information about the wine-devel mailing list