winemac: Make macdrv_process_text_input() asynchronous and process internal events while awaiting its result.

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>
This commit is contained in:
Ken Thomases 2016-02-04 17:18:25 -06:00 committed by Alexandre Julliard
parent 48d755f61d
commit 3482c47469
6 changed files with 43 additions and 21 deletions

View 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);
});
}

View 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;

View 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

View 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);
}

View 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 */

View 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 */