winemac: Don't process QUERY_IME_CHAR_RECT while waiting in OnMainThread().

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@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Ken Thomases 2016-02-04 17:18:27 -06:00 committed by Alexandre Julliard
parent a1a93ce193
commit 33610da6b4
5 changed files with 12 additions and 3 deletions

View File

@ -24,6 +24,7 @@
enum { enum {
WineQueryProcessEvents = 1 << 0, WineQueryProcessEvents = 1 << 0,
WineQueryNoPreemptWait = 1 << 1,
}; };

View File

@ -296,11 +296,13 @@ - (void) discardEventsMatchingMask:(macdrv_event_mask)mask forWindow:(NSWindow*)
- (BOOL) query:(macdrv_query*)query timeout:(NSTimeInterval)timeout flags:(NSUInteger)flags - (BOOL) query:(macdrv_query*)query timeout:(NSTimeInterval)timeout flags:(NSUInteger)flags
{ {
int type;
macdrv_event* event; macdrv_event* event;
NSDate* timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeout]; NSDate* timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeout];
BOOL timedout; 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); event->query_event.query = macdrv_retain_query(query);
query->done = FALSE; query->done = FALSE;
@ -654,6 +656,7 @@ void macdrv_release_event(macdrv_event *event)
CFRelease(event->keyboard_changed.input_source); CFRelease(event->keyboard_changed.input_source);
break; break;
case QUERY_EVENT: case QUERY_EVENT:
case QUERY_EVENT_NO_PREEMPT_WAIT:
macdrv_release_query(event->query_event.query); macdrv_release_query(event->query_event.query);
break; break;
case WINDOW_GOT_FOCUS: case WINDOW_GOT_FOCUS:

View File

@ -649,7 +649,7 @@ - (NSRect) firstRectForCharacterRange:(NSRange)aRange actualRange:(NSRangePointe
query->ime_char_rect.data = [window imeData]; query->ime_char_rect.data = [window imeData];
query->ime_char_rect.range = CFRangeMake(aRange.location, aRange.length); 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); aRange = NSMakeRange(query->ime_char_rect.range.location, query->ime_char_rect.range.length);
ret = NSRectFromCGRect(query->ime_char_rect.rect); ret = NSRectFromCGRect(query->ime_char_rect.rect);

View File

@ -45,6 +45,7 @@ static const char *dbgstr_event(int type)
"MOUSE_MOVED_ABSOLUTE", "MOUSE_MOVED_ABSOLUTE",
"MOUSE_SCROLL", "MOUSE_SCROLL",
"QUERY_EVENT", "QUERY_EVENT",
"QUERY_EVENT_NO_PREEMPT_WAIT",
"REASSERT_WINDOW_POSITION", "REASSERT_WINDOW_POSITION",
"RELEASE_CAPTURE", "RELEASE_CAPTURE",
"SENT_TEXT_INPUT", "SENT_TEXT_INPUT",
@ -117,6 +118,7 @@ static macdrv_event_mask get_event_mask(DWORD mask)
if (mask & QS_SENDMESSAGE) if (mask & QS_SENDMESSAGE)
{ {
event_mask |= event_mask_for_type(QUERY_EVENT); 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(REASSERT_WINDOW_POSITION);
event_mask |= event_mask_for_type(RELEASE_CAPTURE); event_mask |= event_mask_for_type(RELEASE_CAPTURE);
event_mask |= event_mask_for_type(SENT_TEXT_INPUT); 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 * 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) 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); macdrv_mouse_scroll(hwnd, event);
break; break;
case QUERY_EVENT: case QUERY_EVENT:
case QUERY_EVENT_NO_PREEMPT_WAIT:
macdrv_query_event(hwnd, event); macdrv_query_event(hwnd, event);
break; break;
case REASSERT_WINDOW_POSITION: 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 && 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 != APP_QUIT_REQUESTED &&
data->current_event->type != WINDOW_DRAG_BEGIN) data->current_event->type != WINDOW_DRAG_BEGIN)
event_mask = 0; /* don't process nested events */ event_mask = 0; /* don't process nested events */

View File

@ -199,6 +199,7 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
MOUSE_MOVED_ABSOLUTE, MOUSE_MOVED_ABSOLUTE,
MOUSE_SCROLL, MOUSE_SCROLL,
QUERY_EVENT, QUERY_EVENT,
QUERY_EVENT_NO_PREEMPT_WAIT,
REASSERT_WINDOW_POSITION, REASSERT_WINDOW_POSITION,
RELEASE_CAPTURE, RELEASE_CAPTURE,
SENT_TEXT_INPUT, SENT_TEXT_INPUT,