Huw Davies : winemac: Implement GetKeyboardLayoutList.

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


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

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

winemac: Implement GetKeyboardLayoutList.

---

 dlls/winemac.drv/cocoa_app.m      |   49 ++++++++++++++++
 dlls/winemac.drv/keyboard.c       |  115 +++++++++++++++++++++++++++++++++++++
 dlls/winemac.drv/macdrv_cocoa.h   |    5 ++
 dlls/winemac.drv/winemac.drv.spec |    1 +
 4 files changed, 170 insertions(+), 0 deletions(-)

diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m
index f351f33..d576b81 100644
--- a/dlls/winemac.drv/cocoa_app.m
+++ b/dlls/winemac.drv/cocoa_app.m
@@ -2446,3 +2446,52 @@ void macdrv_set_mouse_capture_window(macdrv_window window)
         [[WineApplicationController sharedController] setMouseCaptureWindow:w];
     });
 }
+
+const CFStringRef macdrv_input_source_input_key = CFSTR("input");
+const CFStringRef macdrv_input_source_type_key = CFSTR("type");
+const CFStringRef macdrv_input_source_lang_key = CFSTR("lang");
+
+/***********************************************************************
+ *              macdrv_create_input_source_list
+ */
+CFArrayRef macdrv_create_input_source_list(void)
+{
+    CFMutableArrayRef ret = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+    OnMainThread(^{
+        CFArrayRef input_list;
+        CFDictionaryRef filter_dict;
+        const void *filter_keys[2] = { kTISPropertyInputSourceCategory, kTISPropertyInputSourceIsSelectCapable };
+        const void *filter_values[2] = { kTISCategoryKeyboardInputSource, kCFBooleanTrue };
+        int i;
+
+        filter_dict = CFDictionaryCreate(NULL, filter_keys, filter_values, sizeof(filter_keys)/sizeof(filter_keys[0]),
+                                         &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+        input_list = TISCreateInputSourceList(filter_dict, false);
+
+        for (i = 0; i < CFArrayGetCount(input_list); i++)
+        {
+            TISInputSourceRef input = (TISInputSourceRef)CFArrayGetValueAtIndex(input_list, i);
+            CFArrayRef source_langs = TISGetInputSourceProperty(input, kTISPropertyInputSourceLanguages);
+            CFDictionaryRef entry;
+            const void *input_keys[3] = { macdrv_input_source_input_key,
+                                          macdrv_input_source_type_key,
+                                          macdrv_input_source_lang_key };
+            const void *input_values[3];
+
+            input_values[0] = input;
+            input_values[1] = TISGetInputSourceProperty(input, kTISPropertyInputSourceType);
+            input_values[2] = CFArrayGetValueAtIndex(source_langs, 0);
+
+            entry = CFDictionaryCreate(NULL, input_keys, input_values, sizeof(input_keys) / sizeof(input_keys[0]),
+                                       &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+            CFArrayAppendValue(ret, entry);
+            CFRelease(entry);
+        }
+        CFRelease(input_list);
+        CFRelease(filter_dict);
+    });
+
+    return ret;
+}
diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c
index 1fffa22..09eff95 100644
--- a/dlls/winemac.drv/keyboard.c
+++ b/dlls/winemac.drv/keyboard.c
@@ -176,6 +176,7 @@ enum {
     kVK_UpArrow             = 0x7E,
 };
 
+extern const CFStringRef kTISTypeKeyboardLayout;
 
 /* Indexed by Mac virtual keycode values defined above. */
 static const struct {
@@ -428,6 +429,90 @@ static int strip_apple_private_chars(LPWSTR bufW, int len)
     return len;
 }
 
+static struct list layout_list = LIST_INIT( layout_list );
+struct layout
+{
+    struct list entry;
+    HKL hkl;
+    TISInputSourceRef input_source;
+};
+
+static CRITICAL_SECTION layout_list_section;
+static CRITICAL_SECTION_DEBUG critsect_debug =
+{
+    0, 0, &layout_list_section,
+    { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
+    0, 0, { (DWORD_PTR)(__FILE__ ": layout_list_section") }
+};
+static CRITICAL_SECTION layout_list_section = { &critsect_debug, -1, 0, 0, 0, 0 };
+
+static DWORD get_lcid(CFStringRef lang)
+{
+    CFRange range;
+    WCHAR str[10];
+
+    range.location = 0;
+    range.length = min(CFStringGetLength(lang), sizeof(str) / sizeof(str[0]) - 1);
+    CFStringGetCharacters(lang, range, str);
+    str[range.length] = 0;
+    return LocaleNameToLCID(str, 0);
+}
+
+static HKL get_hkl(CFStringRef lang, CFStringRef type)
+{
+    ULONG_PTR lcid = get_lcid(lang);
+    struct layout *layout;
+
+    /* Look for the last occurrence of this lcid in the list and if
+       present use that value + 0x10000 */
+    LIST_FOR_EACH_ENTRY_REV(layout, &layout_list, struct layout, entry)
+    {
+        ULONG_PTR hkl = HandleToUlong(layout->hkl);
+
+        if (LOWORD(hkl) == lcid)
+        {
+            lcid = (hkl & ~0xe0000000) + 0x10000;
+            break;
+        }
+    }
+
+    if (!CFEqual(type, kTISTypeKeyboardLayout)) lcid |= 0xe0000000;
+
+    return (HKL)lcid;
+}
+
+/***********************************************************************
+ *            update_layout_list
+ *
+ * Must be called while holding the layout_list_section
+ */
+static void update_layout_list(void)
+{
+    CFArrayRef sources;
+    struct layout *layout;
+    int i;
+
+    if (!list_empty(&layout_list)) return;
+
+    sources = macdrv_create_input_source_list();
+
+    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 = 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);
+    }
+
+    CFRelease(sources);
+}
 
 /***********************************************************************
  *              macdrv_compute_keyboard_layout
@@ -1222,6 +1307,36 @@ HKL CDECL macdrv_GetKeyboardLayout(DWORD thread_id)
 
 
 /***********************************************************************
+ *     GetKeyboardLayoutList (MACDRV.@)
+ */
+UINT CDECL macdrv_GetKeyboardLayoutList(INT size, HKL *list)
+{
+    int count = 0;
+    struct layout *layout;
+
+    TRACE("%d, %p\n", size, list);
+
+    EnterCriticalSection(&layout_list_section);
+
+    update_layout_list();
+
+    LIST_FOR_EACH_ENTRY(layout, &layout_list, struct layout, entry)
+    {
+        if (list)
+        {
+            if (count >= size) break;
+            list[count] = layout->hkl;
+            TRACE("\t%d: %p\n", count, list[count]);
+        }
+        count++;
+    }
+    LeaveCriticalSection(&layout_list_section);
+
+    TRACE("returning %d\n", count);
+    return count;
+}
+
+/***********************************************************************
  *              GetKeyboardLayoutName (MACDRV.@)
  */
 BOOL CDECL macdrv_GetKeyboardLayoutName(LPWSTR name)
diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h
index b452461..3ce1c26 100644
--- a/dlls/winemac.drv/macdrv_cocoa.h
+++ b/dlls/winemac.drv/macdrv_cocoa.h
@@ -123,6 +123,7 @@ enum {
     MACDRV_HOTKEY_FAILURE,
 };
 
+typedef struct __TISInputSource *TISInputSourceRef;
 
 typedef struct macdrv_opaque_window* macdrv_window;
 typedef struct macdrv_opaque_event_queue* macdrv_event_queue;
@@ -411,6 +412,10 @@ extern int macdrv_send_text_input_event(int pressed, unsigned int flags, int rep
 
 /* keyboard */
 extern CFDataRef macdrv_copy_keyboard_layout(CGEventSourceKeyboardType* keyboard_type, int* is_iso) DECLSPEC_HIDDEN;
+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;
 
 
 /* clipboard */
diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec
index f3739a8..58a894b 100644
--- a/dlls/winemac.drv/winemac.drv.spec
+++ b/dlls/winemac.drv/winemac.drv.spec
@@ -22,6 +22,7 @@
 @ cdecl GetClipboardData(long) macdrv_GetClipboardData
 @ cdecl GetCursorPos(ptr) macdrv_GetCursorPos
 @ cdecl GetKeyboardLayout(long) macdrv_GetKeyboardLayout
+@ cdecl GetKeyboardLayoutList(long ptr) macdrv_GetKeyboardLayoutList
 @ cdecl GetKeyboardLayoutName(ptr) macdrv_GetKeyboardLayoutName
 @ cdecl GetKeyNameText(long ptr long) macdrv_GetKeyNameText
 @ cdecl GetMonitorInfo(long ptr) macdrv_GetMonitorInfo




More information about the wine-cvs mailing list