winemac: Make macdrv_process_text_input() asynchronous and process internal events...
authorKen Thomases <ken@codeweavers.com>
Thu, 4 Feb 2016 23:18:25 +0000 (17:18 -0600)
committerAlexandre Julliard <julliard@winehq.org>
Fri, 5 Feb 2016 04:53:13 +0000 (13:53 +0900)
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@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
dlls/winemac.drv/cocoa_window.m
dlls/winemac.drv/event.c
dlls/winemac.drv/ime.c
dlls/winemac.drv/keyboard.c
dlls/winemac.drv/macdrv.h
dlls/winemac.drv/macdrv_cocoa.h

index bcc1cf527faae1f96838978bd1af181202fd9303..e9c2cc70cec6c786f86dafcb8b7754e4284a3754 100644 (file)
@@ -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);
+    });
 }
index 785bc0af6d795216dc37494e79d06b0ebd289c08..be3159b9944c7f1bd1007f2fe8bcc3d514a14d69 100644 (file)
@@ -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;
index 7f989142479cf040b9f4793362cdf1bdfdfefd75..295c6ccb080bcc134b827b9fdec4338e19d8fe25 100644 (file)
@@ -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
index 9c0c3a68cdb13f52ebee9d35a40cdbf2aa794d7c..6f3888582d4a9bc14fd6f97e6fc45373c5eb2db3 100644 (file)
@@ -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);
 }
 
 
index 44b79ac099229362ceec2230952c673c3129ed78..f3b5e65ccb02ade8e3823b7e6da7988b1e021977 100644 (file)
@@ -224,10 +224,11 @@ extern void macdrv_status_item_mouse_move(const macdrv_event *event) DECLSPEC_HI
  * 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 */
index 5d607fc9bf67ca7072d287d51abd57213686e7ca..647ef08558f3623a89731df92fc16e35ab5cf7c0 100644 (file)
@@ -201,6 +201,7 @@ enum {
     QUERY_EVENT,
     REASSERT_WINDOW_POSITION,
     RELEASE_CAPTURE,
+    SENT_TEXT_INPUT,
     STATUS_ITEM_MOUSE_BUTTON,
     STATUS_ITEM_MOUSE_MOVE,
     WINDOW_BROUGHT_FORWARD,
@@ -285,6 +286,10 @@ typedef struct macdrv_event {
         struct {
             struct macdrv_query *query;
         }                                           query_event;
+        struct {
+            int handled;
+            int *done;
+        }                                           sent_text_input;
         struct {
             macdrv_status_item  item;
             int                 button;
@@ -438,8 +443,8 @@ extern void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGR
 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 */