From d0e1a0251583d5fb9ea199268d670b8f81b72abc Mon Sep 17 00:00:00 2001 From: Ken Thomases Date: Sun, 3 Feb 2013 17:20:15 -0600 Subject: [PATCH] winemac: Rebuild key map when Mac keyboard layout changes. --- dlls/winemac.drv/cocoa_app.m | 50 +++++++++++++++++++++++++++++++++ dlls/winemac.drv/cocoa_event.m | 3 ++ dlls/winemac.drv/event.c | 7 +++++ dlls/winemac.drv/keyboard.c | 22 +++++++++++++++ dlls/winemac.drv/macdrv.h | 1 + dlls/winemac.drv/macdrv_cocoa.h | 6 ++++ 6 files changed, 89 insertions(+) diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m index 3751eef0b1..a3a8cb58f4 100644 --- a/dlls/winemac.drv/cocoa_app.m +++ b/dlls/winemac.drv/cocoa_app.m @@ -177,6 +177,47 @@ int macdrv_err_on; } } + - (void) keyboardSelectionDidChange + { + TISInputSourceRef inputSource; + + inputSource = TISCopyCurrentKeyboardLayoutInputSource(); + if (inputSource) + { + CFDataRef uchr; + uchr = TISGetInputSourceProperty(inputSource, + kTISPropertyUnicodeKeyLayoutData); + if (uchr) + { + macdrv_event event; + WineEventQueue* queue; + + event.type = KEYBOARD_CHANGED; + event.window = NULL; + event.keyboard_changed.keyboard_type = self.keyboardType; + event.keyboard_changed.iso_keyboard = (KBGetLayoutType(self.keyboardType) == kKeyboardISO); + event.keyboard_changed.uchr = CFDataCreateCopy(NULL, uchr); + + if (event.keyboard_changed.uchr) + { + [eventQueuesLock lock]; + + for (queue in eventQueues) + { + CFRetain(event.keyboard_changed.uchr); + [queue postEvent:&event]; + } + + [eventQueuesLock unlock]; + + CFRelease(event.keyboard_changed.uchr); + } + } + + CFRelease(inputSource); + } + } + /* * ---------- NSApplicationDelegate methods ---------- @@ -218,6 +259,15 @@ int macdrv_err_on; [keyWindows removeObjectIdenticalTo:window]; }]; + [nc addObserver:self + selector:@selector(keyboardSelectionDidChange) + name:NSTextInputContextKeyboardSelectionDidChangeNotification + object:nil]; + + /* The above notification isn't sent unless the NSTextInputContext + class has initialized itself. Poke it. */ + [NSTextInputContext self]; + self.keyboardType = LMGetKbdType(); } diff --git a/dlls/winemac.drv/cocoa_event.m b/dlls/winemac.drv/cocoa_event.m index d5e927d7b8..98b44451f0 100644 --- a/dlls/winemac.drv/cocoa_event.m +++ b/dlls/winemac.drv/cocoa_event.m @@ -277,6 +277,9 @@ void macdrv_cleanup_event(macdrv_event *event) switch (event->type) { + case KEYBOARD_CHANGED: + CFRelease(event->keyboard_changed.uchr); + break; case WINDOW_GOT_FOCUS: [(NSMutableSet*)event->window_got_focus.tried_windows release]; break; diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c index 616f398ce5..fb00260304 100644 --- a/dlls/winemac.drv/event.c +++ b/dlls/winemac.drv/event.c @@ -33,6 +33,7 @@ static const char *dbgstr_event(int type) { static const char * const event_names[] = { "APP_DEACTIVATED", + "KEYBOARD_CHANGED", "MOUSE_BUTTON", "WINDOW_CLOSE_REQUESTED", "WINDOW_DID_MINIMIZE", @@ -56,6 +57,9 @@ static macdrv_event_mask get_event_mask(DWORD mask) if ((mask & QS_ALLINPUT) == QS_ALLINPUT) return -1; + if (mask & QS_KEY) + event_mask |= event_mask_for_type(KEYBOARD_CHANGED); + if (mask & QS_MOUSEBUTTON) event_mask |= event_mask_for_type(MOUSE_BUTTON); @@ -94,6 +98,9 @@ void macdrv_handle_event(macdrv_event *event) case APP_DEACTIVATED: macdrv_app_deactivated(); break; + case KEYBOARD_CHANGED: + macdrv_keyboard_changed(event); + break; case MOUSE_BUTTON: macdrv_mouse_button(hwnd, event); break; diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c index d81cdd2aa2..3591521df8 100644 --- a/dlls/winemac.drv/keyboard.c +++ b/dlls/winemac.drv/keyboard.c @@ -661,3 +661,25 @@ void macdrv_compute_keyboard_layout(struct macdrv_thread_data *thread_data) TRACE("keyc 0x%04x -> vkey 0x%04x (spare vkey)\n", keyc, vkey); } } + + +/*********************************************************************** + * macdrv_keyboard_changed + * + * Handler for KEYBOARD_CHANGED events. + */ +void macdrv_keyboard_changed(const macdrv_event *event) +{ + struct macdrv_thread_data *thread_data = macdrv_thread_data(); + + TRACE("new keyboard layout uchr data %p, type %u, iso %d\n", event->keyboard_changed.uchr, + event->keyboard_changed.keyboard_type, event->keyboard_changed.iso_keyboard); + + if (thread_data->keyboard_layout_uchr) + CFRelease(thread_data->keyboard_layout_uchr); + thread_data->keyboard_layout_uchr = CFDataCreateCopy(NULL, event->keyboard_changed.uchr); + thread_data->keyboard_type = event->keyboard_changed.keyboard_type; + thread_data->iso_keyboard = event->keyboard_changed.iso_keyboard; + + macdrv_compute_keyboard_layout(thread_data); +} diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 6b50b3d3a7..d30c7ae1d4 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -134,5 +134,6 @@ extern void macdrv_window_did_unminimize(HWND hwnd) DECLSPEC_HIDDEN; extern void macdrv_mouse_button(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN; extern void macdrv_compute_keyboard_layout(struct macdrv_thread_data *thread_data) DECLSPEC_HIDDEN; +extern void macdrv_keyboard_changed(const macdrv_event *event) DECLSPEC_HIDDEN; #endif /* __WINE_MACDRV_H */ diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 61dae5049f..d49992f135 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -125,6 +125,7 @@ extern void macdrv_free_displays(struct macdrv_display* displays) DECLSPEC_HIDDE /* event */ enum { APP_DEACTIVATED, + KEYBOARD_CHANGED, MOUSE_BUTTON, WINDOW_CLOSE_REQUESTED, WINDOW_DID_MINIMIZE, @@ -141,6 +142,11 @@ typedef struct macdrv_event { int type; macdrv_window window; union { + struct { + CFDataRef uchr; + CGEventSourceKeyboardType keyboard_type; + int iso_keyboard; + } keyboard_changed; struct { int button; int pressed;