[PATCH 3/3] winemac: Don't process QUERY_IME_CHAR_RECT while waiting in OnMainThread().

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


Most queries are handled even by threads which are otherwise blocked in
OnMainThread().  There's a problem with QUERY_IME_CHAR_RECT, though, in that it
can be handled before a previously-queued IM_SET_TEXT event, in which case its
character range may be out of bounds.  Some apps (e.g. Excel 2007) hang due to
the bad range.

Signed-off-by: Ken Thomases <ken at codeweavers.com>
---
 dlls/winemac.drv/cocoa_event.h  | 1 +
 dlls/winemac.drv/cocoa_event.m  | 5 ++++-
 dlls/winemac.drv/cocoa_window.m | 2 +-
 dlls/winemac.drv/event.c        | 6 +++++-
 dlls/winemac.drv/macdrv_cocoa.h | 1 +
 5 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/dlls/winemac.drv/cocoa_event.h b/dlls/winemac.drv/cocoa_event.h
index 472c667..4d814a2 100644
--- a/dlls/winemac.drv/cocoa_event.h
+++ b/dlls/winemac.drv/cocoa_event.h
@@ -24,6 +24,7 @@
 
 enum {
     WineQueryProcessEvents = 1 << 0,
+    WineQueryNoPreemptWait = 1 << 1,
 };
 
 
diff --git a/dlls/winemac.drv/cocoa_event.m b/dlls/winemac.drv/cocoa_event.m
index 1a360a1..9ce43fb 100644
--- a/dlls/winemac.drv/cocoa_event.m
+++ b/dlls/winemac.drv/cocoa_event.m
@@ -296,11 +296,13 @@ - (void) discardEventsMatchingMask:(macdrv_event_mask)mask forWindow:(NSWindow*)
 
     - (BOOL) query:(macdrv_query*)query timeout:(NSTimeInterval)timeout flags:(NSUInteger)flags
     {
+        int type;
         macdrv_event* event;
         NSDate* timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeout];
         BOOL timedout;
 
-        event = macdrv_create_event(QUERY_EVENT, (WineWindow*)query->window);
+        type = (flags & WineQueryNoPreemptWait) ? QUERY_EVENT_NO_PREEMPT_WAIT : QUERY_EVENT;
+        event = macdrv_create_event(type, (WineWindow*)query->window);
         event->query_event.query = macdrv_retain_query(query);
         query->done = FALSE;
 
@@ -654,6 +656,7 @@ void macdrv_release_event(macdrv_event *event)
                 CFRelease(event->keyboard_changed.input_source);
                 break;
             case QUERY_EVENT:
+            case QUERY_EVENT_NO_PREEMPT_WAIT:
                 macdrv_release_query(event->query_event.query);
                 break;
             case WINDOW_GOT_FOCUS:
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index 3e2dae8..3012118 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -649,7 +649,7 @@ - (NSRect) firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointe
         query->ime_char_rect.data = [window imeData];
         query->ime_char_rect.range = CFRangeMake(aRange.location, aRange.length);
 
-        if ([window.queue query:query timeout:1])
+        if ([window.queue query:query timeout:0.3 flags:WineQueryNoPreemptWait])
         {
             aRange = NSMakeRange(query->ime_char_rect.range.location, query->ime_char_rect.range.length);
             ret = NSRectFromCGRect(query->ime_char_rect.rect);
diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c
index be3159b..2b3d6ce 100644
--- a/dlls/winemac.drv/event.c
+++ b/dlls/winemac.drv/event.c
@@ -45,6 +45,7 @@ static const char *dbgstr_event(int type)
         "MOUSE_MOVED_ABSOLUTE",
         "MOUSE_SCROLL",
         "QUERY_EVENT",
+        "QUERY_EVENT_NO_PREEMPT_WAIT",
         "REASSERT_WINDOW_POSITION",
         "RELEASE_CAPTURE",
         "SENT_TEXT_INPUT",
@@ -117,6 +118,7 @@ static macdrv_event_mask get_event_mask(DWORD mask)
     if (mask & QS_SENDMESSAGE)
     {
         event_mask |= event_mask_for_type(QUERY_EVENT);
+        event_mask |= event_mask_for_type(QUERY_EVENT_NO_PREEMPT_WAIT);
         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);
@@ -137,7 +139,7 @@ static macdrv_event_mask get_event_mask(DWORD mask)
 /***********************************************************************
  *              macdrv_query_event
  *
- * Handler for QUERY_EVENT queries.
+ * Handler for QUERY_EVENT and QUERY_EVENT_NO_PREEMPT_WAIT queries.
  */
 static void macdrv_query_event(HWND hwnd, const macdrv_event *event)
 {
@@ -239,6 +241,7 @@ void macdrv_handle_event(const macdrv_event *event)
         macdrv_mouse_scroll(hwnd, event);
         break;
     case QUERY_EVENT:
+    case QUERY_EVENT_NO_PREEMPT_WAIT:
         macdrv_query_event(hwnd, event);
         break;
     case REASSERT_WINDOW_POSITION:
@@ -341,6 +344,7 @@ DWORD CDECL macdrv_MsgWaitForMultipleObjectsEx(DWORD count, const HANDLE *handle
     }
 
     if (data->current_event && data->current_event->type != QUERY_EVENT &&
+        data->current_event->type != QUERY_EVENT_NO_PREEMPT_WAIT &&
         data->current_event->type != APP_QUIT_REQUESTED &&
         data->current_event->type != WINDOW_DRAG_BEGIN)
         event_mask = 0;  /* don't process nested events */
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 647ef08..5dc84e2 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -199,6 +199,7 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
     MOUSE_MOVED_ABSOLUTE,
     MOUSE_SCROLL,
     QUERY_EVENT,
+    QUERY_EVENT_NO_PREEMPT_WAIT,
     REASSERT_WINDOW_POSITION,
     RELEASE_CAPTURE,
     SENT_TEXT_INPUT,
-- 
2.6.0




More information about the wine-patches mailing list