diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c index ae8df76b75a..7b773e3347f 100644 --- a/dlls/winemac.drv/keyboard.c +++ b/dlls/winemac.drv/keyboard.c @@ -846,6 +846,93 @@ void macdrv_keyboard_changed(const macdrv_event *event) } +/*********************************************************************** + * get_locale_keyboard_layout + */ +static HKL get_locale_keyboard_layout(void) +{ + ULONG_PTR layout; + LANGID langid; + + layout = GetUserDefaultLCID(); + + /* + * Microsoft Office expects this value to be something specific + * for Japanese and Korean Windows with an IME the value is 0xe001 + * We should probably check to see if an IME exists and if so then + * set this word properly. + */ + langid = PRIMARYLANGID(LANGIDFROMLCID(layout)); + if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN) + layout |= 0xe001 << 16; /* IME */ + else + layout |= layout << 16; + + return (HKL)layout; +} + + +/*********************************************************************** + * match_keyboard_layout + */ +static BOOL match_keyboard_layout(HKL hkl) +{ + const DWORD isIME = 0xE0000000; + HKL current_hkl = get_locale_keyboard_layout(); + + /* if the layout is an IME, only match the low word (LCID) */ + if (((ULONG_PTR)hkl & isIME) == isIME) + return (LOWORD(hkl) == LOWORD(current_hkl)); + else + return (hkl == current_hkl); +} + + +/*********************************************************************** + * ActivateKeyboardLayout (MACDRV.@) + */ +HKL CDECL macdrv_ActivateKeyboardLayout(HKL hkl, UINT flags) +{ + HKL oldHkl = 0; + struct macdrv_thread_data *thread_data = macdrv_init_thread_data(); + + /* FIXME: Use Text Input Services or NSTextInputContext to actually + change the Mac keyboard input source. */ + + FIXME("hkl %p flags %04x: semi-stub!\n", hkl, flags); + if (flags & KLF_SETFORPROCESS) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + FIXME("KLF_SETFORPROCESS not supported\n"); + return 0; + } + + if (flags) + FIXME("flags %x not supported\n",flags); + + if (hkl == (HKL)HKL_NEXT || hkl == (HKL)HKL_PREV) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + FIXME("HKL_NEXT and HKL_PREV not supported\n"); + return 0; + } + + if (!match_keyboard_layout(hkl)) + { + SetLastError(ERROR_CALL_NOT_IMPLEMENTED); + FIXME("setting keyboard of different locales not supported\n"); + return 0; + } + + oldHkl = thread_data->active_keyboard_layout; + if (!oldHkl) oldHkl = get_locale_keyboard_layout(); + + thread_data->active_keyboard_layout = hkl; + + return oldHkl; +} + + /*********************************************************************** * Beep (MACDRV.@) */ @@ -944,6 +1031,46 @@ INT CDECL macdrv_GetKeyNameText(LONG lparam, LPWSTR buffer, INT size) } +/*********************************************************************** + * GetKeyboardLayout (MACDRV.@) + */ +HKL CDECL macdrv_GetKeyboardLayout(DWORD thread_id) +{ + if (!thread_id || thread_id == GetCurrentThreadId()) + { + struct macdrv_thread_data *thread_data = macdrv_thread_data(); + if (thread_data && thread_data->active_keyboard_layout) + return thread_data->active_keyboard_layout; + } + else + FIXME("couldn't return keyboard layout for thread %04x\n", thread_id); + + /* FIXME: Use TISGetInputSourceProperty() and kTISPropertyInputSourceLanguages + * to get input source language ID string. Use + * CFLocaleGetWindowsLocaleCodeFromLocaleIdentifier() to convert that + * to a Windows locale ID and from there to a layout handle. + */ + + return get_locale_keyboard_layout(); +} + + +/*********************************************************************** + * GetKeyboardLayoutName (MACDRV.@) + */ +BOOL CDECL macdrv_GetKeyboardLayoutName(LPWSTR name) +{ + static const WCHAR formatW[] = {'%','0','8','x',0}; + DWORD layout; + + layout = HandleToUlong(get_locale_keyboard_layout()); + if (HIWORD(layout) == LOWORD(layout)) layout = LOWORD(layout); + sprintfW(name, formatW, layout); + TRACE("returning %s\n", debugstr_w(name)); + return TRUE; +} + + /*********************************************************************** * MapVirtualKeyEx (MACDRV.@) */ diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 4dc1e3e04ab..e24d8ab57af 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -89,6 +89,7 @@ static inline RECT rect_from_cgrect(CGRect cgrect) int iso_keyboard; CGEventFlags last_modifiers; UInt32 dead_key_state; + HKL active_keyboard_layout; WORD keyc2vkey[128]; WORD keyc2scan[128]; }; diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec index 1bb7d8c162a..30df9d6165a 100644 --- a/dlls/winemac.drv/winemac.drv.spec +++ b/dlls/winemac.drv/winemac.drv.spec @@ -4,11 +4,14 @@ # USER driver +@ cdecl ActivateKeyboardLayout(long long) macdrv_ActivateKeyboardLayout @ cdecl Beep() macdrv_Beep @ cdecl CreateDesktopWindow(long) macdrv_CreateDesktopWindow @ cdecl CreateWindow(long) macdrv_CreateWindow @ cdecl DestroyWindow(long) macdrv_DestroyWindow @ cdecl EnumDisplayMonitors(long ptr ptr long) macdrv_EnumDisplayMonitors +@ cdecl GetKeyboardLayout(long) macdrv_GetKeyboardLayout +@ cdecl GetKeyboardLayoutName(ptr) macdrv_GetKeyboardLayoutName @ cdecl GetKeyNameText(long ptr long) macdrv_GetKeyNameText @ cdecl GetMonitorInfo(long ptr) macdrv_GetMonitorInfo @ cdecl MapVirtualKeyEx(long long long) macdrv_MapVirtualKeyEx