[PATCH 1/3] winemac: Make macdrv_process_text_input() asynchronous and process internal events while awaiting its result.

Ken Thomases ken at codeweavers.com
Thu Feb 4 17:18:25 CST 2016


It had been using the synchronous OnMainThread() to submit its work to the
Cocoa thread, but only queries are processed while OnMainThread() waits for the
work to complete.  This led to QUERY_IME_CHAR_RECT queries being processed out
of order relative to IM_SET_TEXT events, making the character range out of
bounds with respect to the composition string.

Signed-off-by: Ken Thomases <ken at codeweavers.com>
---
 dlls/winemac.drv/cocoa_window.m | 16 ++++++++++------
 dlls/winemac.drv/event.c        |  5 +++++
 dlls/winemac.drv/ime.c          | 18 +++++++++++++++---
 dlls/winemac.drv/keyboard.c     | 11 +++--------
 dlls/winemac.drv/macdrv.h       |  5 +++--
 dlls/winemac.drv/macdrv_cocoa.h |  9 +++++++--
 6 files changed, 43 insertions(+), 21 deletions(-)

diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index bcc1cf5..e9c2cc7 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -3230,11 +3230,11 @@ uint32_t macdrv_window_background_color(void)
 /***********************************************************************
  *              macdrv_send_text_input_event
  */
-int macdrv_send_text_input_event(int pressed, unsigned int flags, int repeat, int keyc, void* data)
+void macdrv_send_text_input_event(int pressed, unsigned int flags, int repeat, int keyc, void* data, int* done)
 {
-    __block BOOL ret;
-
-    OnMainThread(^{
+    OnMainThreadAsync(^{
+        BOOL ret;
+        macdrv_event* event;
         WineWindow* window = (WineWindow*)[NSApp keyWindow];
         if (![window isKindOfClass:[WineWindow class]])
         {
@@ -3266,7 +3266,11 @@ int macdrv_send_text_input_event(int pressed, unsigned int flags, int repeat, in
         }
         else
             ret = FALSE;
-    });
 
-    return ret;
+        event = macdrv_create_event(SENT_TEXT_INPUT, window);
+        event->sent_text_input.handled = ret;
+        event->sent_text_input.done = done;
+        [[window queue] postEvent:event];
+        macdrv_release_event(event);
+    });
 }
diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c
index 785bc0a..be3159b 100644
--- a/dlls/winemac.drv/event.c
+++ b/dlls/winemac.drv/event.c
@@ -47,6 +47,7 @@ static const char *dbgstr_event(int type)
         "QUERY_EVENT",
         "REASSERT_WINDOW_POSITION",
         "RELEASE_CAPTURE",
+        "SENT_TEXT_INPUT",
         "STATUS_ITEM_MOUSE_BUTTON",
         "STATUS_ITEM_MOUSE_MOVE",
         "WINDOW_BROUGHT_FORWARD",
@@ -118,6 +119,7 @@ static macdrv_event_mask get_event_mask(DWORD mask)
         event_mask |= event_mask_for_type(QUERY_EVENT);
         event_mask |= event_mask_for_type(REASSERT_WINDOW_POSITION);
         event_mask |= event_mask_for_type(RELEASE_CAPTURE);
+        event_mask |= event_mask_for_type(SENT_TEXT_INPUT);
         event_mask |= event_mask_for_type(WINDOW_BROUGHT_FORWARD);
         event_mask |= event_mask_for_type(WINDOW_CLOSE_REQUESTED);
         event_mask |= event_mask_for_type(WINDOW_DRAG_BEGIN);
@@ -245,6 +247,9 @@ void macdrv_handle_event(const macdrv_event *event)
     case RELEASE_CAPTURE:
         macdrv_release_capture(hwnd, event);
         break;
+    case SENT_TEXT_INPUT:
+        macdrv_sent_text_input(event);
+        break;
     case STATUS_ITEM_MOUSE_BUTTON:
         macdrv_status_item_mouse_button(event);
         break;
diff --git a/dlls/winemac.drv/ime.c b/dlls/winemac.drv/ime.c
index 7f98914..295c6cc 100644
--- a/dlls/winemac.drv/ime.c
+++ b/dlls/winemac.drv/ime.c
@@ -690,7 +690,7 @@ UINT WINAPI ImeToAsciiEx(UINT uVKey, UINT uScanCode, const LPBYTE lpbKeyState,
     LPIMEPRIVATE myPrivate;
     HWND hwndDefault;
     UINT repeat;
-    INT rc;
+    int done = 0;
 
     TRACE("uVKey 0x%04x uScanCode 0x%04x fuState %u hIMC %p\n", uVKey, uScanCode, fuState, hIMC);
 
@@ -717,9 +717,12 @@ UINT WINAPI ImeToAsciiEx(UINT uVKey, UINT uScanCode, const LPBYTE lpbKeyState,
     UnlockRealIMC(hIMC);
 
     TRACE("Processing Mac 0x%04x\n", vkey);
-    rc = macdrv_process_text_input(uVKey, uScanCode, repeat, lpbKeyState, hIMC);
+    macdrv_process_text_input(uVKey, uScanCode, repeat, lpbKeyState, hIMC, &done);
 
-    if (!rc)
+    while (!done)
+        MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_POSTMESSAGE | QS_SENDMESSAGE, 0);
+
+    if (done < 0)
     {
         UINT msgs = 0;
         UINT msg = (uScanCode & 0x8000) ? WM_KEYUP : WM_KEYDOWN;
@@ -1482,6 +1485,15 @@ void macdrv_im_set_text(const macdrv_event *event)
         IME_NotifyComplete(himc);
 }
 
+/***********************************************************************
+ *              macdrv_sent_text_input
+ */
+void macdrv_sent_text_input(const macdrv_event *event)
+{
+    TRACE("handled: %s\n", event->sent_text_input.handled ? "TRUE" : "FALSE");
+    *event->sent_text_input.done = event->sent_text_input.handled ? 1 : -1;
+}
+
 
 /**************************************************************************
  *              query_ime_char_rect
diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c
index 9c0c3a6..6f38885 100644
--- a/dlls/winemac.drv/keyboard.c
+++ b/dlls/winemac.drv/keyboard.c
@@ -1117,12 +1117,11 @@ void macdrv_hotkey_press(const macdrv_event *event)
 /***********************************************************************
  *              macdrv_process_text_input
  */
-BOOL macdrv_process_text_input(UINT vkey, UINT scan, UINT repeat, const BYTE *key_state, void *himc)
+void macdrv_process_text_input(UINT vkey, UINT scan, UINT repeat, const BYTE *key_state, void *himc, int* done)
 {
     struct macdrv_thread_data *thread_data = macdrv_thread_data();
     unsigned int flags;
     int keyc;
-    BOOL ret = FALSE;
 
     TRACE("vkey 0x%04x scan 0x%04x repeat %u himc %p\n", vkey, scan, repeat, himc);
 
@@ -1149,15 +1148,11 @@ BOOL macdrv_process_text_input(UINT vkey, UINT scan, UINT repeat, const BYTE *ke
         if (thread_data->keyc2vkey[keyc] == vkey) break;
 
     if (keyc >= sizeof(thread_data->keyc2vkey)/sizeof(thread_data->keyc2vkey[0]))
-        goto done;
+        return;
 
     TRACE("flags 0x%08x keyc 0x%04x\n", flags, keyc);
 
-    ret = macdrv_send_text_input_event(((scan & 0x8000) == 0), flags, repeat, keyc, himc);
-
-done:
-    TRACE(" -> %s\n", ret ? "TRUE" : "FALSE");
-    return ret;
+    macdrv_send_text_input_event(((scan & 0x8000) == 0), flags, repeat, keyc, himc, done);
 }
 
 
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h
index 44b79ac..f3b5e65 100644
--- a/dlls/winemac.drv/macdrv.h
+++ b/dlls/winemac.drv/macdrv.h
@@ -224,10 +224,11 @@ extern CGImageRef create_cgimage_from_icon_bitmaps(HDC hdc, HANDLE icon, HBITMAP
  * Mac IME driver
  */
 
-extern BOOL macdrv_process_text_input(UINT vkey, UINT scan, UINT repeat, const BYTE *key_state,
-                                      void *himc) DECLSPEC_HIDDEN;
+extern void macdrv_process_text_input(UINT vkey, UINT scan, UINT repeat, const BYTE *key_state,
+                                      void *himc, int* done) DECLSPEC_HIDDEN;
 
 extern void macdrv_im_set_text(const macdrv_event *event) DECLSPEC_HIDDEN;
+extern void macdrv_sent_text_input(const macdrv_event *event) DECLSPEC_HIDDEN;
 extern BOOL query_ime_char_rect(macdrv_query* query) DECLSPEC_HIDDEN;
 
 #endif  /* __WINE_MACDRV_H */
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 5d607fc..647ef08 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -201,6 +201,7 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
     QUERY_EVENT,
     REASSERT_WINDOW_POSITION,
     RELEASE_CAPTURE,
+    SENT_TEXT_INPUT,
     STATUS_ITEM_MOUSE_BUTTON,
     STATUS_ITEM_MOUSE_MOVE,
     WINDOW_BROUGHT_FORWARD,
@@ -286,6 +287,10 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
             struct macdrv_query *query;
         }                                           query_event;
         struct {
+            int handled;
+            int *done;
+        }                                           sent_text_input;
+        struct {
             macdrv_status_item  item;
             int                 button;
             int                 down;
@@ -438,8 +443,8 @@ extern void macdrv_set_window_color_key(macdrv_window w, CGFloat keyRed, CGFloat
 extern void macdrv_add_view_opengl_context(macdrv_view v, macdrv_opengl_context c) DECLSPEC_HIDDEN;
 extern void macdrv_remove_view_opengl_context(macdrv_view v, macdrv_opengl_context c) DECLSPEC_HIDDEN;
 extern uint32_t macdrv_window_background_color(void) DECLSPEC_HIDDEN;
-extern int macdrv_send_text_input_event(int pressed, unsigned int flags, int repeat, int keyc,
-                                        void* data) DECLSPEC_HIDDEN;
+extern void macdrv_send_text_input_event(int pressed, unsigned int flags, int repeat, int keyc,
+                                         void* data, int* done) DECLSPEC_HIDDEN;
 
 
 /* keyboard */
-- 
2.6.0




More information about the wine-patches mailing list