Huw Davies : winemac: Update the layout list if the enabled input sources change.

Alexandre Julliard julliard at winehq.org
Wed Nov 20 13:38:57 CST 2013


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

Author: Huw Davies <huw at codeweavers.com>
Date:   Wed Nov 20 15:30:35 2013 +0000

winemac: Update the layout list if the enabled input sources change.

---

 dlls/winemac.drv/cocoa_app.m    |   10 +++++++
 dlls/winemac.drv/keyboard.c     |   57 +++++++++++++++++++++++++++++++++-----
 dlls/winemac.drv/macdrv_cocoa.h |    1 +
 3 files changed, 60 insertions(+), 8 deletions(-)

diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m
index d576b81..284023b 100644
--- a/dlls/winemac.drv/cocoa_app.m
+++ b/dlls/winemac.drv/cocoa_app.m
@@ -411,6 +411,11 @@ int macdrv_err_on;
         }
     }
 
+    - (void) enabledKeyboardInputSourcesChanged
+    {
+        macdrv_layout_list_needs_update = TRUE;
+    }
+
     - (CGFloat) primaryScreenHeight
     {
         if (!primaryScreenHeightValid)
@@ -1930,6 +1935,11 @@ int macdrv_err_on;
                            name:@"com.apple.HIToolbox.beginMenuTrackingNotification"
                          object:nil
              suspensionBehavior:NSNotificationSuspensionBehaviorDrop];
+
+        [dnc addObserver:self
+                selector:@selector(enabledKeyboardInputSourcesChanged)
+                    name:(NSString*)kTISNotifyEnabledKeyboardInputSourcesChanged
+                  object:nil];
     }
 
     - (BOOL) inputSourceIsInputMethod
diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c
index 09eff95..52f97da 100644
--- a/dlls/winemac.drv/keyboard.c
+++ b/dlls/winemac.drv/keyboard.c
@@ -435,6 +435,7 @@ struct layout
     struct list entry;
     HKL hkl;
     TISInputSourceRef input_source;
+    BOOL enabled; /* is the input source enabled - ie displayed in the input source selector UI */
 };
 
 static CRITICAL_SECTION layout_list_section;
@@ -446,6 +447,8 @@ static CRITICAL_SECTION_DEBUG critsect_debug =
 };
 static CRITICAL_SECTION layout_list_section = { &critsect_debug, -1, 0, 0, 0, 0 };
 
+int macdrv_layout_list_needs_update = TRUE;
+
 static DWORD get_lcid(CFStringRef lang)
 {
     CFRange range;
@@ -481,10 +484,36 @@ static HKL get_hkl(CFStringRef lang, CFStringRef type)
     return (HKL)lcid;
 }
 
+/******************************************************************
+ *                get_layout_from_source
+ *
+ * Must be called while holding the layout_list_section.
+ * Note, returned layout may not currently be enabled.
+ */
+static struct layout *get_layout_from_source(TISInputSourceRef input)
+{
+    struct layout *ret = NULL, *layout;
+
+    LIST_FOR_EACH_ENTRY(layout, &layout_list, struct layout, entry)
+    {
+        if (CFEqual(input, layout->input_source))
+        {
+            ret = layout;
+            break;
+        }
+    }
+    return ret;
+}
+
 /***********************************************************************
  *            update_layout_list
  *
  * Must be called while holding the layout_list_section
+ *
+ * If an input source has been disabled (ie. removed from the UI) its
+ * entry remains in the layout list but is marked as such and is not
+ * enumerated by GetKeyboardLayoutList.  This is to ensure the
+ * HKL <-> input source mapping is unique.
  */
 static void update_layout_list(void)
 {
@@ -492,23 +521,34 @@ static void update_layout_list(void)
     struct layout *layout;
     int i;
 
-    if (!list_empty(&layout_list)) return;
+    if (!InterlockedExchange(&macdrv_layout_list_needs_update, FALSE)) return;
 
     sources = macdrv_create_input_source_list();
 
+    LIST_FOR_EACH_ENTRY(layout, &layout_list, struct layout, entry)
+        layout->enabled = FALSE;
+
     for (i = 0; i < CFArrayGetCount(sources); i++)
     {
         CFDictionaryRef dict = CFArrayGetValueAtIndex(sources, i);
         TISInputSourceRef input = (TISInputSourceRef)CFDictionaryGetValue(dict, macdrv_input_source_input_key);
-        CFStringRef type = CFDictionaryGetValue(dict, macdrv_input_source_type_key);
-        CFStringRef lang = CFDictionaryGetValue(dict, macdrv_input_source_lang_key);
+        layout = get_layout_from_source(input);
+        if (!layout)
+        {
+            CFStringRef type = CFDictionaryGetValue(dict, macdrv_input_source_type_key);
+            CFStringRef lang = CFDictionaryGetValue(dict, macdrv_input_source_lang_key);
+
+            layout = HeapAlloc(GetProcessHeap(), 0, sizeof(*layout));
+            layout->input_source = (TISInputSourceRef)CFRetain(input);
+            layout->hkl = get_hkl(lang, type);
 
-        layout = HeapAlloc(GetProcessHeap(), 0, sizeof(*layout));
-        layout->input_source = (TISInputSourceRef)CFRetain(input);
-        layout->hkl = get_hkl(lang, type);
+            list_add_tail(&layout_list, &layout->entry);
+            TRACE("adding new layout %p\n", layout->hkl);
+        }
+        else
+            TRACE("enabling already existing layout %p\n", layout->hkl);
 
-        list_add_tail(&layout_list, &layout->entry);
-        TRACE("adding new layout %p\n", layout->hkl);
+        layout->enabled = TRUE;
     }
 
     CFRelease(sources);
@@ -1322,6 +1362,7 @@ UINT CDECL macdrv_GetKeyboardLayoutList(INT size, HKL *list)
 
     LIST_FOR_EACH_ENTRY(layout, &layout_list, struct layout, entry)
     {
+        if (!layout->enabled) continue;
         if (list)
         {
             if (count >= size) break;
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index 3ce1c26..1c2277f 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -416,6 +416,7 @@ extern CFArrayRef macdrv_create_input_source_list(void) DECLSPEC_HIDDEN;
 extern const CFStringRef macdrv_input_source_input_key DECLSPEC_HIDDEN;
 extern const CFStringRef macdrv_input_source_type_key DECLSPEC_HIDDEN;
 extern const CFStringRef macdrv_input_source_lang_key DECLSPEC_HIDDEN;
+extern int macdrv_layout_list_needs_update DECLSPEC_HIDDEN;
 
 
 /* clipboard */




More information about the wine-cvs mailing list