diff --git a/gdk/gdkkeyuni.c b/gdk/gdkkeyuni.c index 4b4431f997..4bf77b22d8 100644 --- a/gdk/gdkkeyuni.c +++ b/gdk/gdkkeyuni.c @@ -904,10 +904,12 @@ gdk_keyval_to_unicode (guint keyval) return keyval & 0x00ffffff; #if defined(GDK_WINDOWING_WIN32) - if (GDK_IS_WIN32_DISPLAY (gdk_display_get_default ())) + if (GDK_IS_WIN32_DISPLAY (gdk_display_get_default ()) && + keyval == 0xffae) { - if (keyval == 0xffae) - return (guint32) _gdk_win32_keymap_get_decimal_mark (); + GdkWin32Keymap *keymap = GDK_WIN32_KEYMAP (gdk_keymap_get_default ()); + + return (guint32) _gdk_win32_keymap_get_decimal_mark (keymap); } #endif diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c index 7f050a4e73..2f397f9619 100644 --- a/gdk/win32/gdkevents-win32.c +++ b/gdk/win32/gdkevents-win32.c @@ -505,6 +505,8 @@ static void build_key_event_state (GdkEvent *event, BYTE *key_state) { + GdkWin32Keymap *keymap; + event->key.state = 0; if (key_state[VK_SHIFT] & 0x80) @@ -524,11 +526,13 @@ build_key_event_state (GdkEvent *event, if (key_state[VK_XBUTTON2] & 0x80) event->key.state |= GDK_BUTTON5_MASK; - if (_gdk_keyboard_has_altgr && + keymap = GDK_WIN32_KEYMAP (_gdk_win32_display_get_keymap (_gdk_display)); + event->key.group = _gdk_win32_keymap_get_active_group (keymap); + + if (_gdk_win32_keymap_has_altgr (keymap) && (key_state[VK_LCONTROL] & 0x80) && (key_state[VK_RMENU] & 0x80)) { - event->key.group = 1; event->key.state |= GDK_MOD2_MASK; if (key_state[VK_RCONTROL] & 0x80) event->key.state |= GDK_CONTROL_MASK; @@ -537,7 +541,6 @@ build_key_event_state (GdkEvent *event, } else { - event->key.group = 0; if (key_state[VK_CONTROL] & 0x80) event->key.state |= GDK_CONTROL_MASK; if (key_state[VK_MENU] & 0x80) @@ -2224,6 +2227,7 @@ gdk_event_translate (MSG *msg, { case WM_INPUTLANGCHANGE: _gdk_input_locale = (HKL) msg->lParam; + _gdk_win32_keymap_set_active_layout (GDK_WIN32_KEYMAP (_gdk_win32_display_get_keymap (_gdk_display)), _gdk_input_locale); _gdk_input_locale_is_ime = ImmIsIME (_gdk_input_locale); GetLocaleInfo (MAKELCID (LOWORD (_gdk_input_locale), SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, @@ -2391,7 +2395,7 @@ gdk_event_translate (MSG *msg, } } else if (msg->wParam == VK_SHIFT && - LOBYTE (HIWORD (msg->lParam)) == _scancode_rshift) + LOBYTE (HIWORD (msg->lParam)) == _gdk_win32_keymap_get_rshift_scancode (GDK_WIN32_KEYMAP (_gdk_win32_display_get_keymap (_gdk_display)))) event->key.hardware_keycode = VK_RSHIFT; /* g_print ("ctrl:%02x lctrl:%02x rctrl:%02x alt:%02x lalt:%02x ralt:%02x\n", key_state[VK_CONTROL], key_state[VK_LCONTROL], key_state[VK_RCONTROL], key_state[VK_MENU], key_state[VK_LMENU], key_state[VK_RMENU]); */ diff --git a/gdk/win32/gdkkeys-win32.c b/gdk/win32/gdkkeys-win32.c index e1ad6cfda4..f2501875b1 100644 --- a/gdk/win32/gdkkeys-win32.c +++ b/gdk/win32/gdkkeys-win32.c @@ -38,6 +38,25 @@ #include "gdkkeysprivate.h" #include "gdkwin32keys.h" +struct _GdkWin32KeyGroupOptions +{ + /* character that should be used as the decimal separator */ + wchar_t decimal_mark; + + /* the bits that indicate level shift when set (usually Shift, sometimes also CapsLock) */ + GdkModifierType shift_modifiers; + + /* Scancode for the VK_RSHIFT */ + guint scancode_rshift; + + /* TRUE if Ctrl+Alt emulates AltGr */ + gboolean has_altgr; + + gboolean capslock_tested; +}; + +typedef struct _GdkWin32KeyGroupOptions GdkWin32KeyGroupOptions; + struct _GdkWin32KeymapClass { GdkKeymapClass parent_class; @@ -46,50 +65,107 @@ struct _GdkWin32KeymapClass struct _GdkWin32Keymap { GdkKeymap parent_instance; + + /* length = what GetKeyboardLayoutList() returns, type = HKL. + * When it changes, recreate the keymap and repopulate the options. + */ + GArray *layout_handles; + + /* VirtualKeyCode -> gdk_keyval table + * length = 256 * length(layout_handles) * 2 * 2 + * 256 is the number of virtual key codes, + * 2x2 is the number of Shift/AltGr combinations (level), + * length(layout_handles) is the number of layout handles (group). + */ + guint *keysym_tab; + + /* length = length(layout_handles), type = GdkWin32KeyGroupOptions + * Kept separate from layout_handles because layout_handles is + * populated by W32 API. + */ + GArray *options; + + /* Index of a handle in layout_handles, + * at any point it should be the same handle as GetKeyboardLayout(0) returns, + * but GDK caches it to avoid calling GetKeyboardLayout (0) every time. + */ + guint8 active_layout; }; +enum _GdkWin32KeyLevelState +{ + GDK_WIN32_LEVEL_NONE = 0, + GDK_WIN32_LEVEL_SHIFT, + GDK_WIN32_LEVEL_ALTGR, + GDK_WIN32_LEVEL_SHIFT_ALTGR, + GDK_WIN32_LEVEL_COUNT +}; + +typedef enum _GdkWin32KeyLevelState GdkWin32KeyLevelState; + G_DEFINE_TYPE (GdkWin32Keymap, gdk_win32_keymap, GDK_TYPE_KEYMAP) +guint _gdk_keymap_serial = 0; + +static GdkKeymap *default_keymap = NULL; + +#define KEY_STATE_SIZE 256 + +static void update_keymap (GdkKeymap *gdk_keymap); + static void gdk_win32_keymap_init (GdkWin32Keymap *keymap) { + keymap->layout_handles = g_array_new (FALSE, FALSE, sizeof (HKL)); + keymap->options = g_array_new (FALSE, FALSE, sizeof (GdkWin32KeyGroupOptions)); + keymap->keysym_tab = NULL; + keymap->active_layout = 0; + update_keymap (GDK_KEYMAP (keymap)); } -guint _gdk_keymap_serial = 0; -gboolean _gdk_keyboard_has_altgr = FALSE; -guint _scancode_rshift = 0; +static void +gdk_win32_keymap_finalize (GObject *object) +{ + GdkWin32Keymap *keymap = GDK_WIN32_KEYMAP (object); -static GdkModifierType gdk_shift_modifiers = GDK_SHIFT_MASK; + g_clear_pointer (&keymap->keysym_tab, g_free); + g_clear_pointer (&keymap->layout_handles, g_array_unref); + g_clear_pointer (&keymap->options, g_array_unref); -static GdkKeymap *default_keymap = NULL; - -static guint *keysym_tab = NULL; -static wchar_t decimal_mark = 0; - -#define KEY_STATE_SIZE 256 + G_OBJECT_CLASS (gdk_win32_keymap_parent_class)->finalize (object); +} #ifdef G_ENABLE_DEBUG static void -print_keysym_tab (void) +print_keysym_tab (GdkWin32Keymap *keymap) { - gint vk; + gint li; + GdkWin32KeyGroupOptions *options; + gint vk; + GdkWin32KeyLevelState level; + gint group_size = keymap->layout_handles->len; - g_print ("keymap:%s%s\n", - _gdk_keyboard_has_altgr ? " (uses AltGr)" : "", - (gdk_shift_modifiers & GDK_LOCK_MASK) ? " (has ShiftLock)" : ""); - for (vk = 0; vk < KEY_STATE_SIZE; vk++) + for (li = 0; li < group_size; li++) { - gint state; + options = &g_array_index (keymap->options, GdkWin32KeyGroupOptions, li); + g_print ("keymap %d (0x%p):%s%s\n", + li, g_array_index (keymap->layout_handles, HKL, li), + options->has_altgr ? " (uses AltGr)" : "", + (options->shift_modifiers & GDK_LOCK_MASK) ? " (has ShiftLock)" : ""); - g_print ("%#.02x: ", vk); - for (state = 0; state < 4; state++) - { - gchar *name = gdk_keyval_name (keysym_tab[vk*4 + state]); - if (name == NULL) - name = "(none)"; - g_print ("%s ", name); - } - g_print ("\n"); + for (vk = 0; vk < KEY_STATE_SIZE; vk++) + { + g_print ("%#.02x: ", vk); + + for (level = 0; level < GDK_WIN32_LEVEL_COUNT; level++) + { + gchar *name = gdk_keyval_name (keymap->keysym_tab[vk * group_size * GDK_WIN32_LEVEL_COUNT + level]); + + g_print ("%s ", name ? name : "(none)"); + } + + g_print ("\n"); + } } } #endif @@ -259,34 +335,38 @@ handle_special (guint vk, } static void -set_shift_vks (guchar *key_state, - gint shift) +set_level_vks (guchar *key_state, + GdkWin32KeyLevelState level) { - switch (shift) + switch (level) { - case 0: + case GDK_WIN32_LEVEL_NONE: key_state[VK_SHIFT] = 0; key_state[VK_CONTROL] = key_state[VK_MENU] = 0; break; - case 1: + case GDK_WIN32_LEVEL_SHIFT: key_state[VK_SHIFT] = 0x80; key_state[VK_CONTROL] = key_state[VK_MENU] = 0; break; - case 2: + case GDK_WIN32_LEVEL_ALTGR: key_state[VK_SHIFT] = 0; key_state[VK_CONTROL] = key_state[VK_MENU] = 0x80; break; - case 3: + case GDK_WIN32_LEVEL_SHIFT_ALTGR: key_state[VK_SHIFT] = 0x80; key_state[VK_CONTROL] = key_state[VK_MENU] = 0x80; break; + case GDK_WIN32_LEVEL_COUNT: + g_assert_not_reached (); + break; } } static void -reset_after_dead (guchar key_state[KEY_STATE_SIZE]) +reset_after_dead (guchar key_state[KEY_STATE_SIZE], + HKL handle) { - guchar temp_key_state[KEY_STATE_SIZE]; + guchar temp_key_state[KEY_STATE_SIZE]; wchar_t wcs[2]; memmove (temp_key_state, key_state, KEY_STATE_SIZE); @@ -297,7 +377,7 @@ reset_after_dead (guchar key_state[KEY_STATE_SIZE]) ToUnicodeEx (VK_SPACE, MapVirtualKey (VK_SPACE, 0), temp_key_state, wcs, G_N_ELEMENTS (wcs), - 0, _gdk_input_locale); + 0, handle); } static void @@ -353,180 +433,360 @@ handle_dead (guint keysym, * return current decimal mark as unicode character */ guint32 -_gdk_win32_keymap_get_decimal_mark (void) +_gdk_win32_keymap_get_decimal_mark (GdkWin32Keymap *keymap) { - if (decimal_mark) - return (decimal_mark); + if (keymap != NULL && + keymap->layout_handles->len > 0 && + g_array_index (keymap->options, GdkWin32KeyGroupOptions, keymap->active_layout).decimal_mark) + return g_array_index (keymap->options, GdkWin32KeyGroupOptions, keymap->active_layout).decimal_mark; - return ((guint32) '.'); + return (guint32) '.'; +} + +static gboolean +layouts_are_the_same (GArray *array, HKL *hkls, gint hkls_len) +{ + gint i; + + if (hkls_len != array->len) + return FALSE; + + for (i = 0; i < hkls_len; i++) + if (hkls[i] != g_array_index (array, HKL, i)) + return FALSE; + + return TRUE; } static void -update_keymap (void) +check_that_active_layout_is_in_sync (GdkWin32Keymap *keymap) { - static guint current_serial = 0; - guchar key_state[KEY_STATE_SIZE]; - guint scancode; - guint vk; - gboolean capslock_tested = FALSE; + HKL hkl; + HKL cached_hkl; + wchar_t hkl_name[KL_NAMELENGTH]; - if (keysym_tab != NULL && current_serial == _gdk_keymap_serial) + if (keymap->layout_handles->len <= 0) return; - current_serial = _gdk_keymap_serial; + hkl = GetKeyboardLayout (0); + cached_hkl = g_array_index (keymap->layout_handles, HKL, keymap->active_layout); - if (keysym_tab == NULL) - keysym_tab = g_new (guint, 4*KEY_STATE_SIZE); + if (hkl != cached_hkl) + { + if (!GetKeyboardLayoutNameW (hkl_name)) + wcscpy_s (hkl_name, KL_NAMELENGTH, L"(NULL)"); - memset (key_state, 0, sizeof (key_state)); + g_warning ("Cached active layout #%d (0x%p) does not match actual layout %S, 0x%p", + keymap->active_layout, cached_hkl, hkl_name, hkl); + } +} - _gdk_keyboard_has_altgr = FALSE; - gdk_shift_modifiers = GDK_SHIFT_MASK; +static void +update_keymap (GdkKeymap *gdk_keymap) +{ + int hkls_len; + static int hkls_size = 0; + static HKL *hkls = NULL; + gboolean no_list; + static guint current_serial = 0; + gint i, group; + GdkWin32KeyLevelState level; + GdkWin32KeyGroupOptions *options; + GdkWin32Keymap *keymap = GDK_WIN32_KEYMAP (gdk_keymap); + gint keysym_tab_size; + + guchar key_state[KEY_STATE_SIZE]; + guint scancode; + guint vk; + guint *keygroup; + + if (keymap->keysym_tab != NULL && + current_serial == _gdk_keymap_serial) + return; + + no_list = FALSE; + hkls_len = GetKeyboardLayoutList (0, NULL); + + if (hkls_len <= 0) + { + hkls_len = 1; + no_list = TRUE; + } + else if (hkls_len > 255) + { + hkls_len = 255; + } + + if (hkls_size < hkls_len) + { + hkls = g_renew (HKL, hkls, hkls_len); + hkls_size = hkls_len; + } + + if (hkls_len != GetKeyboardLayoutList (hkls_len, hkls)) + { + if (!no_list) + return; + + hkls[0] = GetKeyboardLayout (0); + hkls_len = 1; + } + + if (layouts_are_the_same (keymap->layout_handles, hkls, hkls_len)) + { + check_that_active_layout_is_in_sync (keymap); + current_serial = _gdk_keymap_serial; + + return; + } + + GDK_NOTE (EVENTS, g_print ("\nHave %d keyboard layouts:", hkls_len)); + + for (i = 0; i < hkls_len; i++) + { + GDK_NOTE (EVENTS, g_print (" 0x%p", hkls[i])); + + if (GetKeyboardLayout (0) == hkls[i]) + { + wchar_t hkl_name[KL_NAMELENGTH]; + + if (!GetKeyboardLayoutNameW (hkl_name)) + wcscpy_s (hkl_name, KL_NAMELENGTH, L"(NULL)"); + + GDK_NOTE (EVENTS, g_print ("(active, %S)", hkl_name)); + } + } + + GDK_NOTE (EVENTS, g_print ("\n")); + + keysym_tab_size = hkls_len * 256 * 2 * 2; + + if (hkls_len != keymap->layout_handles->len) + keymap->keysym_tab = g_renew (guint, keymap->keysym_tab, keysym_tab_size); + + memset (keymap->keysym_tab, 0, keysym_tab_size); + g_array_set_size (keymap->layout_handles, hkls_len); + g_array_set_size (keymap->options, hkls_len); + + for (i = 0; i < hkls_len; i++) + { + options = &g_array_index (keymap->options, GdkWin32KeyGroupOptions, i); + + options->decimal_mark = 0; + options->shift_modifiers = GDK_SHIFT_MASK; + options->scancode_rshift = 0; + options->has_altgr = FALSE; + options->capslock_tested = FALSE; + + g_array_index (keymap->layout_handles, HKL, i) = hkls[i]; + + if (hkls[i] == _gdk_input_locale) + keymap->active_layout = i; + } for (vk = 0; vk < KEY_STATE_SIZE; vk++) { - if ((scancode = MapVirtualKey (vk, 0)) == 0 && - vk != VK_DIVIDE) - keysym_tab[vk*4+0] = - keysym_tab[vk*4+1] = - keysym_tab[vk*4+2] = - keysym_tab[vk*4+3] = GDK_KEY_VoidSymbol; - else - { - gint shift; + for (group = 0; group < hkls_len; group++) + { + options = &g_array_index (keymap->options, GdkWin32KeyGroupOptions, group); + scancode = MapVirtualKeyEx (vk, 0, hkls[group]); + keygroup = &keymap->keysym_tab[(vk * hkls_len + group) * GDK_WIN32_LEVEL_COUNT]; - if (vk == VK_RSHIFT) - _scancode_rshift = scancode; + if (scancode == 0 && + vk != VK_DIVIDE) + { + for (level = GDK_WIN32_LEVEL_NONE; level < GDK_WIN32_LEVEL_COUNT; level++) + keygroup[level] = GDK_KEY_VoidSymbol; - key_state[vk] = 0x80; - for (shift = 0; shift < 4; shift++) - { - guint *ksymp = keysym_tab + vk*4 + shift; + continue; + } - set_shift_vks (key_state, shift); + if (vk == VK_RSHIFT) + options->scancode_rshift = scancode; - *ksymp = 0; + key_state[vk] = 0x80; - /* First, handle those virtual keys that we always want - * as special GDK_* keysyms, even if ToAsciiEx might - * turn some them into a ASCII character (like TAB and - * ESC). - */ - handle_special (vk, ksymp, shift); + for (level = GDK_WIN32_LEVEL_NONE; level < GDK_WIN32_LEVEL_COUNT; level++) + { + guint *ksymp = &keygroup[level]; - if ((*ksymp == 0) || ((vk == VK_DECIMAL) && (shift == 0))) - { - wchar_t wcs[10]; - gint k; + set_level_vks (key_state, level); - wcs[0] = wcs[1] = 0; - k = ToUnicodeEx (vk, scancode, key_state, - wcs, G_N_ELEMENTS (wcs), - 0, _gdk_input_locale); + *ksymp = 0; + + /* First, handle those virtual keys that we always want + * as special GDK_* keysyms, even if ToAsciiEx might + * turn some them into a ASCII character (like TAB and + * ESC). + */ + handle_special (vk, ksymp, level); + + if ((*ksymp == 0) || + ((vk == VK_DECIMAL) && (level == GDK_WIN32_LEVEL_NONE))) + { + wchar_t wcs[10]; + gint k; + guint keysym; + + wcs[0] = wcs[1] = 0; + k = ToUnicodeEx (vk, scancode, key_state, + wcs, G_N_ELEMENTS (wcs), + 0, hkls[group]); #if 0 - g_print ("ToUnicodeEx(%#02x, %d: %d): %d, %04x %04x\n", - vk, scancode, shift, k, - wcs[0], wcs[1]); + g_print ("ToUnicodeEx(%#02x, %d: %d): %d, %04x %04x\n", + vk, scancode, level, k, + wcs[0], wcs[1]); #endif - if ((vk == VK_DECIMAL) && (shift == 0)) - { - if (k == 1) - decimal_mark = wcs[0]; - } - else if (k == 1) - *ksymp = gdk_unicode_to_keyval (wcs[0]); - else if (k == -1) - { - guint keysym = gdk_unicode_to_keyval (wcs[0]); + switch (k) + { + case 1: + if ((vk == VK_DECIMAL) && (level == GDK_WIN32_LEVEL_NONE)) + options->decimal_mark = wcs[0]; + else + *ksymp = gdk_unicode_to_keyval (wcs[0]); + break; + case -1: + keysym = gdk_unicode_to_keyval (wcs[0]); - /* It is a dead key, and it has been stored in - * the keyboard layout's state by - * ToAsciiEx()/ToUnicodeEx(). Yes, this is an - * incredibly silly API! Make the keyboard - * layout forget it by calling - * ToAsciiEx()/ToUnicodeEx() once more, with the - * virtual key code and scancode for the - * spacebar, without shift or AltGr. Otherwise - * the next call to ToAsciiEx() with a different - * key would try to combine with the dead key. - */ - reset_after_dead (key_state); + /* It is a dead key, and it has been stored in + * the keyboard layout's state by + * ToAsciiEx()/ToUnicodeEx(). Yes, this is an + * incredibly silly API! Make the keyboard + * layout forget it by calling + * ToAsciiEx()/ToUnicodeEx() once more, with the + * virtual key code and scancode for the + * spacebar, without shift or AltGr. Otherwise + * the next call to ToAsciiEx() with a different + * key would try to combine with the dead key. + */ + reset_after_dead (key_state, hkls[group]); - /* Use dead keysyms instead of "undead" ones */ - handle_dead (keysym, ksymp); - } - else if (k == 0) - { - /* Seems to be necessary to "reset" the keyboard layout - * in this case, too. Otherwise problems on NT4. - */ - reset_after_dead (key_state); - } - else - { + /* Use dead keysyms instead of "undead" ones */ + handle_dead (keysym, ksymp); + break; + case 0: + /* Seems to be necessary to "reset" the keyboard layout + * in this case, too. Otherwise problems on NT4. + */ + reset_after_dead (key_state, hkls[group]); + break; + default: #if 0 - GDK_NOTE (EVENTS, - g_print ("ToUnicodeEx returns %d " - "for vk:%02x, sc:%02x%s%s\n", - k, vk, scancode, - (shift&0x1 ? " shift" : ""), - (shift&0x2 ? " altgr" : ""))); + GDK_NOTE (EVENTS, + g_print ("ToUnicodeEx returns %d " + "for vk:%02x, sc:%02x%s%s\n", + k, vk, scancode, + (shift&0x1 ? " shift" : ""), + (shift&0x2 ? " altgr" : ""))); #endif - } - } - if (*ksymp == 0) - *ksymp = GDK_KEY_VoidSymbol; - } - key_state[vk] = 0; + break; + } + } - /* Check if keyboard has an AltGr key by checking if - * the mapping with Control+Alt is different. - */ - if (!_gdk_keyboard_has_altgr) - if ((keysym_tab[vk*4 + 2] != GDK_KEY_VoidSymbol && - keysym_tab[vk*4] != keysym_tab[vk*4 + 2]) || - (keysym_tab[vk*4 + 3] != GDK_KEY_VoidSymbol && - keysym_tab[vk*4 + 1] != keysym_tab[vk*4 + 3])) - _gdk_keyboard_has_altgr = TRUE; + if (*ksymp == 0) + *ksymp = GDK_KEY_VoidSymbol; + } - if (!capslock_tested) - { - /* Can we use this virtual key to determine the CapsLock - * key behaviour: CapsLock or ShiftLock? If it generates - * keysyms for printable characters and has a shifted - * keysym that isn't just the upperacase of the - * unshifted keysym, check the behaviour of VK_CAPITAL. - */ - if (g_unichar_isgraph (gdk_keyval_to_unicode (keysym_tab[vk*4 + 0])) && - keysym_tab[vk*4 + 1] != keysym_tab[vk*4 + 0] && - g_unichar_isgraph (gdk_keyval_to_unicode (keysym_tab[vk*4 + 1])) && - keysym_tab[vk*4 + 1] != gdk_keyval_to_upper (keysym_tab[vk*4 + 0])) - { - guchar chars[2]; + key_state[vk] = 0; - capslock_tested = TRUE; + /* Check if keyboard has an AltGr key by checking if + * the mapping with Control+Alt is different. + */ + if (!options->has_altgr) + if ((keygroup[GDK_WIN32_LEVEL_ALTGR] != GDK_KEY_VoidSymbol && + keygroup[GDK_WIN32_LEVEL_NONE] != keygroup[GDK_WIN32_LEVEL_ALTGR]) || + (keygroup[GDK_WIN32_LEVEL_SHIFT_ALTGR] != GDK_KEY_VoidSymbol && + keygroup[GDK_WIN32_LEVEL_SHIFT] != keygroup[GDK_WIN32_LEVEL_SHIFT_ALTGR])) + options->has_altgr = TRUE; - key_state[VK_SHIFT] = 0; - key_state[VK_CONTROL] = key_state[VK_MENU] = 0; - key_state[VK_CAPITAL] = 1; + if (!options->capslock_tested) + { + /* Can we use this virtual key to determine the CapsLock + * key behaviour: CapsLock or ShiftLock? If it generates + * keysyms for printable characters and has a shifted + * keysym that isn't just the upperacase of the + * unshifted keysym, check the behaviour of VK_CAPITAL. + */ + if (g_unichar_isgraph (gdk_keyval_to_unicode (keygroup[GDK_WIN32_LEVEL_NONE])) && + keygroup[GDK_WIN32_LEVEL_SHIFT] != keygroup[GDK_WIN32_LEVEL_NONE] && + g_unichar_isgraph (gdk_keyval_to_unicode (keygroup[GDK_WIN32_LEVEL_SHIFT])) && + keygroup[GDK_WIN32_LEVEL_SHIFT] != gdk_keyval_to_upper (keygroup[GDK_WIN32_LEVEL_NONE])) + { + guchar chars[2]; - if (ToAsciiEx (vk, scancode, key_state, - (LPWORD) chars, 0, _gdk_input_locale) == 1) - { - if (chars[0] >= GDK_KEY_space && - chars[0] <= GDK_KEY_asciitilde && - chars[0] == keysym_tab[vk*4 + 1]) - { - /* CapsLock acts as ShiftLock */ - gdk_shift_modifiers |= GDK_LOCK_MASK; - } - } - key_state[VK_CAPITAL] = 0; - } - } - } + options->capslock_tested = TRUE; + + key_state[VK_SHIFT] = 0; + key_state[VK_CONTROL] = key_state[VK_MENU] = 0; + key_state[VK_CAPITAL] = 1; + + if (ToAsciiEx (vk, scancode, key_state, + (LPWORD) chars, 0, hkls[group]) == 1) + { + if (chars[0] >= GDK_KEY_space && + chars[0] <= GDK_KEY_asciitilde && + chars[0] == keygroup[GDK_WIN32_LEVEL_SHIFT]) + { + /* CapsLock acts as ShiftLock */ + options->shift_modifiers |= GDK_LOCK_MASK; + } + } + + key_state[VK_CAPITAL] = 0; + } + } + } } - GDK_NOTE (EVENTS, print_keysym_tab ()); + + GDK_NOTE (EVENTS, print_keysym_tab (keymap)); + + check_that_active_layout_is_in_sync (keymap); + current_serial = _gdk_keymap_serial; +} + +guint8 +_gdk_win32_keymap_get_rshift_scancode (GdkWin32Keymap *keymap) +{ + if (keymap != NULL && + keymap->layout_handles->len > 0) + return g_array_index (keymap->options, GdkWin32KeyGroupOptions, keymap->active_layout).scancode_rshift; + + return 0; +} + +void +_gdk_win32_keymap_set_active_layout (GdkWin32Keymap *keymap, + HKL hkl) +{ + if (keymap != NULL && + keymap->layout_handles->len > 0) + { + gint group; + + for (group = 0; group < keymap->layout_handles->len; group++) + if (g_array_index (keymap->layout_handles, HKL, group) == hkl) + keymap->active_layout = group; + } +} + +gboolean +_gdk_win32_keymap_has_altgr (GdkWin32Keymap *keymap) +{ + if (keymap != NULL && + keymap->layout_handles->len > 0) + return g_array_index (keymap->options, GdkWin32KeyGroupOptions, keymap->active_layout).has_altgr; + + return FALSE; +} + +guint8 +_gdk_win32_keymap_get_active_group (GdkWin32Keymap *keymap) +{ + if (keymap != NULL && + keymap->layout_handles->len > 0) + return keymap->active_layout; + + return 0; } GdkKeymap* @@ -541,11 +801,9 @@ _gdk_win32_display_get_keymap (GdkDisplay *display) } static PangoDirection -gdk_win32_keymap_get_direction (GdkKeymap *keymap) +get_hkl_direction (HKL hkl) { - update_keymap (); - - switch (PRIMARYLANGID (LOWORD ((DWORD) (gintptr) _gdk_input_locale))) + switch (PRIMARYLANGID (LOWORD ((DWORD) (gintptr) hkl))) { case LANG_HEBREW: case LANG_ARABIC: @@ -561,43 +819,86 @@ gdk_win32_keymap_get_direction (GdkKeymap *keymap) } } -static gboolean -gdk_win32_keymap_have_bidi_layouts (GdkKeymap *keymap) +static PangoDirection +gdk_win32_keymap_get_direction (GdkKeymap *gdk_keymap) { - /* Should we check if the kayboard layouts switchable at the moment - * cover both directionalities? What does the doc comment in - * ../x11/gdkkeys-x11.c exactly mean? - */ - return FALSE; + HKL active_hkl; + GdkWin32Keymap *keymap; + + if (gdk_keymap == NULL || gdk_keymap != gdk_keymap_get_default ()) + keymap = GDK_WIN32_KEYMAP (gdk_keymap_get_default ()); + else + keymap = GDK_WIN32_KEYMAP (gdk_keymap); + + update_keymap (GDK_KEYMAP (keymap)); + + if (keymap->layout_handles->len <= 0) + active_hkl = GetKeyboardLayout (0); + else + active_hkl = g_array_index (keymap->layout_handles, HKL, keymap->active_layout); + + return get_hkl_direction (active_hkl); +} + +static gboolean +gdk_win32_keymap_have_bidi_layouts (GdkKeymap *gdk_keymap) +{ + GdkWin32Keymap *keymap; + gboolean have_rtl = FALSE; + gboolean have_ltr = FALSE; + gint group; + + if (gdk_keymap == NULL || gdk_keymap != gdk_keymap_get_default ()) + keymap = GDK_WIN32_KEYMAP (gdk_keymap_get_default ()); + else + keymap = GDK_WIN32_KEYMAP (gdk_keymap); + + update_keymap (GDK_KEYMAP (keymap)); + + for (group = 0; group < keymap->layout_handles->len; group++) + { + if (get_hkl_direction (g_array_index (keymap->layout_handles, HKL, group)) == PANGO_DIRECTION_RTL) + have_rtl = TRUE; + else + have_ltr = TRUE; + } + + return have_ltr && have_rtl; } static gboolean gdk_win32_keymap_get_caps_lock_state (GdkKeymap *keymap) { + (void) keymap; + return ((GetKeyState (VK_CAPITAL) & 1) != 0); } static gboolean gdk_win32_keymap_get_num_lock_state (GdkKeymap *keymap) { + (void) keymap; + return ((GetKeyState (VK_NUMLOCK) & 1) != 0); } static gboolean gdk_win32_keymap_get_scroll_lock_state (GdkKeymap *keymap) { + (void) keymap; + return ((GetKeyState (VK_SCROLL) & 1) != 0); } static gboolean -gdk_win32_keymap_get_entries_for_keyval (GdkKeymap *keymap, - guint keyval, - GdkKeymapKey **keys, - gint *n_keys) +gdk_win32_keymap_get_entries_for_keyval (GdkKeymap *gdk_keymap, + guint keyval, + GdkKeymapKey **keys, + gint *n_keys) { GArray *retval; - g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE); + g_return_val_if_fail (gdk_keymap == NULL || GDK_IS_KEYMAP (gdk_keymap), FALSE); g_return_val_if_fail (keys != NULL, FALSE); g_return_val_if_fail (n_keys != NULL, FALSE); g_return_val_if_fail (keyval != 0, FALSE); @@ -605,32 +906,44 @@ gdk_win32_keymap_get_entries_for_keyval (GdkKeymap *keymap, retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey)); /* Accept only the default keymap */ - if (keymap == NULL || keymap == gdk_keymap_get_default ()) + if (gdk_keymap == NULL || gdk_keymap == gdk_keymap_get_default ()) { gint vk; + GdkWin32Keymap *keymap; - update_keymap (); + if (gdk_keymap == NULL) + keymap = GDK_WIN32_KEYMAP (gdk_keymap_get_default ()); + else + keymap = GDK_WIN32_KEYMAP (gdk_keymap); + + update_keymap (gdk_keymap); for (vk = 0; vk < KEY_STATE_SIZE; vk++) - { - gint i; + { + gint group; - for (i = 0; i < 4; i++) - { - if (keysym_tab[vk*4+i] == keyval) - { - GdkKeymapKey key; + for (group = 0; group < keymap->layout_handles->len; group++) + { + GdkWin32KeyLevelState level; - key.keycode = vk; + for (level = GDK_WIN32_LEVEL_NONE; level < GDK_WIN32_LEVEL_COUNT; level++) + { + guint *keygroup; - /* 2 levels (normal, shift), two groups (normal, AltGr) */ - key.group = i / 2; - key.level = i % 2; + keygroup = &keymap->keysym_tab[(vk * keymap->layout_handles->len + group) * GDK_WIN32_LEVEL_COUNT]; - g_array_append_val (retval, key); - } - } - } + if (keygroup[level] == keyval) + { + GdkKeymapKey key; + + key.keycode = vk; + key.group = group; + key.level = level; + g_array_append_val (retval, key); + } + } + } + } } #ifdef G_ENABLE_DEBUG @@ -639,12 +952,12 @@ gdk_win32_keymap_get_entries_for_keyval (GdkKeymap *keymap, guint i; g_print ("gdk_keymap_get_entries_for_keyval: %#.04x (%s):", - keyval, gdk_keyval_name (keyval)); + keyval, gdk_keyval_name (keyval)); for (i = 0; i < retval->len; i++) - { - GdkKeymapKey *entry = (GdkKeymapKey *) retval->data + i; - g_print (" %#.02x %d %d", entry->keycode, entry->group, entry->level); - } + { + GdkKeymapKey *entry = (GdkKeymapKey *) retval->data + i; + g_print (" %#.02x %d %d", entry->keycode, entry->group, entry->level); + } g_print ("\n"); } #endif @@ -666,21 +979,26 @@ gdk_win32_keymap_get_entries_for_keyval (GdkKeymap *keymap, } static gboolean -gdk_win32_keymap_get_entries_for_keycode (GdkKeymap *keymap, - guint hardware_keycode, - GdkKeymapKey **keys, - guint **keyvals, - gint *n_entries) +gdk_win32_keymap_get_entries_for_keycode (GdkKeymap *gdk_keymap, + guint hardware_keycode, + GdkKeymapKey **keys, + guint **keyvals, + gint *n_entries) { - GArray *key_array; - GArray *keyval_array; + GArray *key_array; + GArray *keyval_array; + gint group; + GdkWin32Keymap *keymap; - g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE); + g_return_val_if_fail (gdk_keymap == NULL || GDK_IS_KEYMAP (gdk_keymap), FALSE); g_return_val_if_fail (n_entries != NULL, FALSE); if (hardware_keycode <= 0 || - hardware_keycode >= KEY_STATE_SIZE) + hardware_keycode >= KEY_STATE_SIZE || + (keys == NULL && keyvals == NULL) || + (gdk_keymap != NULL && gdk_keymap != gdk_keymap_get_default ())) { + /* Wrong keycode or NULL output arrays or wrong keymap */ if (keys) *keys = NULL; if (keyvals) @@ -700,32 +1018,36 @@ gdk_win32_keymap_get_entries_for_keycode (GdkKeymap *keymap, else keyval_array = NULL; - /* Accept only the default keymap */ - if (keymap == NULL || keymap == gdk_keymap_get_default ()) + keymap = GDK_WIN32_KEYMAP (gdk_keymap_get_default ()); + update_keymap (GDK_KEYMAP (keymap)); + + for (group = 0; group < keymap->layout_handles->len; group++) { - gint i; + GdkWin32KeyLevelState level; - update_keymap (); - - for (i = 0; i < 4; i++) - { - if (key_array) + for (level = GDK_WIN32_LEVEL_NONE; level < GDK_WIN32_LEVEL_COUNT; level++) + { + if (key_array) { GdkKeymapKey key; key.keycode = hardware_keycode; - - key.group = i / 2; - key.level = i % 2; - + key.group = group; + key.level = level; g_array_append_val (key_array, key); } if (keyval_array) - g_array_append_val (keyval_array, keysym_tab[hardware_keycode*4+i]); - } + { + guint keyval = keymap->keysym_tab[(hardware_keycode * keymap->layout_handles->len + group) * GDK_WIN32_LEVEL_COUNT + level]; + + g_array_append_val (keyval_array, keyval); + } + } } + *n_entries = group * GDK_WIN32_LEVEL_COUNT; + if ((key_array && key_array->len > 0) || (keyval_array && keyval_array->len > 0)) { @@ -734,11 +1056,6 @@ gdk_win32_keymap_get_entries_for_keycode (GdkKeymap *keymap, if (keyvals) *keyvals = (guint*) keyval_array->data; - - if (key_array) - *n_entries = key_array->len; - else - *n_entries = keyval_array->len; } else { @@ -747,8 +1064,6 @@ gdk_win32_keymap_get_entries_for_keycode (GdkKeymap *keymap, if (keyvals) *keyvals = NULL; - - *n_entries = 0; } if (key_array) @@ -760,27 +1075,29 @@ gdk_win32_keymap_get_entries_for_keycode (GdkKeymap *keymap, } static guint -gdk_win32_keymap_lookup_key (GdkKeymap *keymap, - const GdkKeymapKey *key) +gdk_win32_keymap_lookup_key (GdkKeymap *gdk_keymap, + const GdkKeymapKey *key) { guint sym; + GdkWin32Keymap *keymap; - g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0); + g_return_val_if_fail (gdk_keymap == NULL || GDK_IS_KEYMAP (gdk_keymap), 0); g_return_val_if_fail (key != NULL, 0); g_return_val_if_fail (key->group < 4, 0); /* Accept only the default keymap */ - if (keymap != NULL && keymap != gdk_keymap_get_default ()) + if (gdk_keymap != NULL && gdk_keymap != gdk_keymap_get_default ()) return 0; - update_keymap (); + keymap = GDK_WIN32_KEYMAP (gdk_keymap_get_default ()); + update_keymap (GDK_KEYMAP (keymap)); if (key->keycode >= KEY_STATE_SIZE || - key->group < 0 || key->group >= 2 || - key->level < 0 || key->level >= 2) + key->group < 0 || key->group >= keymap->layout_handles->len || + key->level < 0 || key->level >= GDK_WIN32_LEVEL_COUNT) return 0; - sym = keysym_tab[key->keycode*4 + key->group*2 + key->level]; + sym = keymap->keysym_tab[(key->keycode * keymap->layout_handles->len + key->group) * GDK_WIN32_LEVEL_COUNT + key->level]; if (sym == GDK_KEY_VoidSymbol) return 0; @@ -789,22 +1106,23 @@ gdk_win32_keymap_lookup_key (GdkKeymap *keymap, } static gboolean -gdk_win32_keymap_translate_keyboard_state (GdkKeymap *keymap, - guint hardware_keycode, - GdkModifierType state, - gint group, - guint *keyval, - gint *effective_group, - gint *level, - GdkModifierType *consumed_modifiers) +gdk_win32_keymap_translate_keyboard_state (GdkKeymap *gdk_keymap, + guint hardware_keycode, + GdkModifierType state, + gint group, + guint *keyval, + gint *effective_group, + gint *level, + GdkModifierType *consumed_modifiers) { + GdkWin32Keymap *keymap; guint tmp_keyval; - guint *keyvals; - gint shift_level; - gboolean ignore_shift = FALSE; - gboolean ignore_group = FALSE; + guint *keygroup; + GdkWin32KeyLevelState shift_level; + GdkWin32KeyGroupOptions *options; + GdkModifierType modifiers = GDK_SHIFT_MASK | GDK_LOCK_MASK | GDK_MOD2_MASK; - g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE); + g_return_val_if_fail (gdk_keymap == NULL || GDK_IS_KEYMAP (gdk_keymap), FALSE); g_return_val_if_fail (group < 4, FALSE); #if 0 @@ -821,83 +1139,103 @@ gdk_win32_keymap_translate_keyboard_state (GdkKeymap *keymap, *consumed_modifiers = 0; /* Accept only the default keymap */ - if (keymap != NULL && keymap != gdk_keymap_get_default ()) + if (gdk_keymap != NULL && gdk_keymap != gdk_keymap_get_default ()) return FALSE; if (hardware_keycode >= KEY_STATE_SIZE) return FALSE; - if (group < 0 || group >= 2) + keymap = GDK_WIN32_KEYMAP (gdk_keymap_get_default ()); + update_keymap (GDK_KEYMAP (keymap)); + + if (group < 0 || group >= keymap->layout_handles->len) return FALSE; - update_keymap (); - - keyvals = keysym_tab + hardware_keycode*4; + options = &g_array_index (keymap->options, GdkWin32KeyGroupOptions, group); + keygroup = &keymap->keysym_tab[(hardware_keycode * keymap->layout_handles->len + group) * GDK_WIN32_LEVEL_COUNT]; if ((state & GDK_LOCK_MASK) && (state & GDK_SHIFT_MASK) && - ((gdk_shift_modifiers & GDK_LOCK_MASK) || - (keyvals[group*2 + 1] == gdk_keyval_to_upper (keyvals[group*2 + 0])))) + ((options->shift_modifiers & GDK_LOCK_MASK) || + (keygroup[GDK_WIN32_LEVEL_SHIFT] == gdk_keyval_to_upper (keygroup[GDK_WIN32_LEVEL_NONE])))) /* Shift always disables ShiftLock. Shift disables CapsLock for * keys with lowercase/uppercase letter pairs. */ - shift_level = 0; - else if (state & gdk_shift_modifiers) - shift_level = 1; + shift_level = GDK_WIN32_LEVEL_NONE; + else if (state & options->shift_modifiers) + shift_level = GDK_WIN32_LEVEL_SHIFT; else - shift_level = 0; + shift_level = GDK_WIN32_LEVEL_NONE; - /* Drop group and shift if there are no keysymbols on + if (shift_level == GDK_WIN32_LEVEL_NONE) + { + if (state & GDK_MOD2_MASK) + shift_level = GDK_WIN32_LEVEL_ALTGR; + } + else + { + if (state & GDK_MOD2_MASK) + shift_level = GDK_WIN32_LEVEL_SHIFT_ALTGR; + } + + /* Drop altgr and shift if there are no keysymbols on * the key for those. */ - if (shift_level == 1 && - keyvals[group*2 + 1] == GDK_KEY_VoidSymbol && - keyvals[group*2] != GDK_KEY_VoidSymbol) + if (keygroup[shift_level] == GDK_KEY_VoidSymbol) { - shift_level = 0; - ignore_shift = TRUE; - } - - if (group == 1 && - keyvals[2 + shift_level] == GDK_KEY_VoidSymbol && - keyvals[0 + shift_level] != GDK_KEY_VoidSymbol) - { - group = 0; - ignore_group = TRUE; - } - - if (keyvals[group *2 + shift_level] == GDK_KEY_VoidSymbol && - keyvals[0 + 0] != GDK_KEY_VoidSymbol) - { - shift_level = 0; - group = 0; - ignore_group = TRUE; - ignore_shift = TRUE; + switch (shift_level) + { + case GDK_WIN32_LEVEL_NONE: + case GDK_WIN32_LEVEL_ALTGR: + if (keygroup[GDK_WIN32_LEVEL_NONE] != GDK_KEY_VoidSymbol) + shift_level = GDK_WIN32_LEVEL_NONE; + break; + case GDK_WIN32_LEVEL_SHIFT: + if (keygroup[GDK_WIN32_LEVEL_NONE] != GDK_KEY_VoidSymbol) + shift_level = GDK_WIN32_LEVEL_NONE; + break; + case GDK_WIN32_LEVEL_SHIFT_ALTGR: + if (keygroup[GDK_WIN32_LEVEL_ALTGR] != GDK_KEY_VoidSymbol) + shift_level = GDK_WIN32_LEVEL_ALTGR; + else if (keygroup[GDK_WIN32_LEVEL_SHIFT] != GDK_KEY_VoidSymbol) + shift_level = GDK_WIN32_LEVEL_SHIFT; + else if (keygroup[GDK_WIN32_LEVEL_NONE] != GDK_KEY_VoidSymbol) + shift_level = GDK_WIN32_LEVEL_NONE; + break; + case GDK_WIN32_LEVEL_COUNT: + g_assert_not_reached (); + } } /* See whether the group and shift level actually mattered * to know what to put in consumed_modifiers */ - if (keyvals[group*2 + 1] == GDK_KEY_VoidSymbol || - keyvals[group*2 + 0] == keyvals[group*2 + 1]) - ignore_shift = TRUE; + if ((keygroup[GDK_WIN32_LEVEL_SHIFT] == GDK_KEY_VoidSymbol || + keygroup[GDK_WIN32_LEVEL_NONE] == keygroup[GDK_WIN32_LEVEL_SHIFT]) && + (keygroup[GDK_WIN32_LEVEL_SHIFT_ALTGR] == GDK_KEY_VoidSymbol || + keygroup[GDK_WIN32_LEVEL_ALTGR] == keygroup[GDK_WIN32_LEVEL_SHIFT_ALTGR])) + modifiers &= ~(GDK_SHIFT_MASK | GDK_LOCK_MASK); - if (keyvals[2 + shift_level] == GDK_KEY_VoidSymbol || - keyvals[0 + shift_level] == keyvals[2 + shift_level]) - ignore_group = TRUE; + if ((keygroup[GDK_WIN32_LEVEL_ALTGR] == GDK_KEY_VoidSymbol || + keygroup[GDK_WIN32_LEVEL_NONE] == keygroup[GDK_WIN32_LEVEL_ALTGR]) && + (keygroup[GDK_WIN32_LEVEL_SHIFT_ALTGR] == GDK_KEY_VoidSymbol || + keygroup[GDK_WIN32_LEVEL_SHIFT] == keygroup[GDK_WIN32_LEVEL_SHIFT_ALTGR])) + modifiers &= ~GDK_MOD2_MASK; - tmp_keyval = keyvals[group*2 + shift_level]; + tmp_keyval = keygroup[shift_level]; /* If a true CapsLock is toggled, and Shift is not down, * and the shifted keysym is the uppercase of the unshifted, * use it. */ - if (!(gdk_shift_modifiers & GDK_LOCK_MASK) && + if (!(options->shift_modifiers & GDK_LOCK_MASK) && !(state & GDK_SHIFT_MASK) && - (state & GDK_LOCK_MASK)) + (state & GDK_LOCK_MASK) && + (shift_level < GDK_WIN32_LEVEL_SHIFT_ALTGR)) { guint upper = gdk_keyval_to_upper (tmp_keyval); - if (upper == keyvals[group*2 + 1]) + + if (upper == keygroup[shift_level + 1]) tmp_keyval = upper; } @@ -911,15 +1249,11 @@ gdk_win32_keymap_translate_keyboard_state (GdkKeymap *keymap, *level = shift_level; if (consumed_modifiers) - { - *consumed_modifiers = - (ignore_group ? 0 : GDK_MOD2_MASK) | - (ignore_shift ? 0 : (GDK_SHIFT_MASK|GDK_LOCK_MASK)); - } + *consumed_modifiers = modifiers; #if 0 GDK_NOTE (EVENTS, g_print ("... group=%d level=%d cmods=%#x keyval=%s\n", - group, shift_level, tmp_modifiers, gdk_keyval_name (tmp_keyval))); + group, shift_level, modifiers, gdk_keyval_name (tmp_keyval))); #endif return tmp_keyval != GDK_KEY_VoidSymbol; @@ -927,23 +1261,18 @@ gdk_win32_keymap_translate_keyboard_state (GdkKeymap *keymap, static void gdk_win32_keymap_add_virtual_modifiers (GdkKeymap *keymap, - GdkModifierType *state) + GdkModifierType *state) { } static gboolean gdk_win32_keymap_map_virtual_modifiers (GdkKeymap *keymap, - GdkModifierType *state) + GdkModifierType *state) { /* FIXME: Is this the right thing to do? */ return TRUE; } -static void -gdk_win32_keymap_finalize (GObject *object) -{ -} - static void gdk_win32_keymap_class_init (GdkWin32KeymapClass *klass) { diff --git a/gdk/win32/gdkmain-win32.c b/gdk/win32/gdkmain-win32.c index b170612a71..de2d1f8970 100644 --- a/gdk/win32/gdkmain-win32.c +++ b/gdk/win32/gdkmain-win32.c @@ -89,6 +89,7 @@ _gdk_win32_windowing_init (void) _gdk_app_hmodule = GetModuleHandle (NULL); _gdk_display_hdc = CreateDC ("DISPLAY", NULL, NULL, NULL); _gdk_input_locale = GetKeyboardLayout (0); + _gdk_win32_keymap_set_active_layout (GDK_WIN32_KEYMAP (_gdk_win32_display_get_keymap (_gdk_display)), _gdk_input_locale); _gdk_input_locale_is_ime = ImmIsIME (_gdk_input_locale); GetLocaleInfo (MAKELCID (LOWORD (_gdk_input_locale), SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h index dac65f4af4..c8491cb36b 100644 --- a/gdk/win32/gdkprivate-win32.h +++ b/gdk/win32/gdkprivate-win32.h @@ -39,6 +39,7 @@ #include #include #include +#include #include "gdkinternals.h" @@ -290,8 +291,6 @@ extern gboolean _gdk_input_locale_is_ime; extern UINT _gdk_input_codepage; extern guint _gdk_keymap_serial; -extern gboolean _gdk_keyboard_has_altgr; -extern guint _scancode_rshift; /* GdkAtoms: properties, targets and types */ extern GdkAtom _gdk_selection; @@ -474,6 +473,13 @@ gint _gdk_win32_display_text_property_to_utf8_list (GdkDisplay *display, gchar ***list); gchar *_gdk_win32_display_utf8_to_string_target (GdkDisplay *display, const gchar *str); +gboolean _gdk_win32_keymap_has_altgr (GdkWin32Keymap *keymap); +guint8 _gdk_win32_keymap_get_active_group (GdkWin32Keymap *keymap); +guint8 _gdk_win32_keymap_get_rshift_scancode (GdkWin32Keymap *keymap); +void _gdk_win32_keymap_set_active_layout (GdkWin32Keymap *keymap, + HKL hkl); + + GdkKeymap *_gdk_win32_display_get_keymap (GdkDisplay *display); void _gdk_win32_display_create_window_impl (GdkDisplay *display, @@ -534,7 +540,7 @@ void _gdk_win32_append_event (GdkEvent *event); void _gdk_win32_emit_configure_event (GdkWindow *window); -guint32 _gdk_win32_keymap_get_decimal_mark (void); +guint32 _gdk_win32_keymap_get_decimal_mark (GdkWin32Keymap *keymap); void _gdk_win32_window_handle_aerosnap (GdkWindow *window, GdkWin32AeroSnapCombo combo);