Ken Thomases : winemac: Rebuild key map when Mac keyboard layout changes.

Alexandre Julliard julliard at winehq.org
Tue Feb 5 13:25:25 CST 2013


Module: wine
Branch: master
Commit: d0e1a0251583d5fb9ea199268d670b8f81b72abc
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d0e1a0251583d5fb9ea199268d670b8f81b72abc

Author: Ken Thomases <ken at codeweavers.com>
Date:   Sun Feb  3 17:20:15 2013 -0600

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(+), 0 deletions(-)

diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m
index 3751eef..a3a8cb5 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 d5e927d..98b4445 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 616f398..fb00260 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 d81cdd2..3591521 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 6b50b3d..d30c7ae 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 61dae50..d49992f 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,
@@ -142,6 +143,11 @@ typedef struct macdrv_event {
     macdrv_window       window;
     union {
         struct {
+            CFDataRef                   uchr;
+            CGEventSourceKeyboardType   keyboard_type;
+            int                         iso_keyboard;
+        }                                           keyboard_changed;
+        struct {
             int             button;
             int             pressed;
             int             x;




More information about the wine-cvs mailing list