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