[gtk+] GDK W32: Cache multiple keyboard layouts simultaneously
- From: Руслан Ижбулатов <ruslanizhb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] GDK W32: Cache multiple keyboard layouts simultaneously
- Date: Thu, 4 Aug 2016 16:41:55 +0000 (UTC)
commit 52c7e07948f0d82ade7c730e99c53dea3e13ca67
Author: Руслан Ижбулатов <lrn1986 gmail com>
Date: Wed Jul 13 11:41:35 2016 +0000
GDK W32: Cache multiple keyboard layouts simultaneously
This changes the group/level semantic.
Previously W32 backend used "group 0/1" to denote "AltGr OFF/ON"
and "level 0/1" to denote "Shift is OFF/ON".
Now "group" means "keyboard layout" and there can be up to 255 groups,
while AltGr and Shift are combined into a single level enum that
takes values between 0 and 4.
Unlike X, W32 doesn't do effective group overriding, meaning that
it will never tell the caller that a different group was actually
used (even for universal keys, such as Enter), because key symbol
table is completely fabricated and there's no point in trying to
save a few of kilobytes of RAM by not duplicating universal key
records for all groups.
Also contains many whitespace changes (tab elimination, fixed
indentation) and cleanup (axed a few global variables, these are
now accessed via the default keymap).
https://bugzilla.gnome.org/show_bug.cgi?id=768722
gdk/gdkkeyuni.c | 8 +-
gdk/win32/gdkevents-win32.c | 12 +-
gdk/win32/gdkkeys-win32.c | 983 ++++++++++++++++++++++++++++--------------
gdk/win32/gdkmain-win32.c | 1 +
gdk/win32/gdkprivate-win32.h | 12 +-
5 files changed, 679 insertions(+), 337 deletions(-)
---
diff --git a/gdk/gdkkeyuni.c b/gdk/gdkkeyuni.c
index 4b4431f..4bf77b2 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 7f050a4..2f397f9 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 e1ad6cf..f250187 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 GdkModifierType gdk_shift_modifiers = GDK_SHIFT_MASK;
-
-static GdkKeymap *default_keymap = NULL;
+static void
+gdk_win32_keymap_finalize (GObject *object)
+{
+ GdkWin32Keymap *keymap = GDK_WIN32_KEYMAP (object);
-static guint *keysym_tab = NULL;
-static wchar_t decimal_mark = 0;
+ 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);
-#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;
-
- 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");
+ 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)" : "");
+
+ 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 (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) '.';
+}
+
+static gboolean
+layouts_are_the_same (GArray *array, HKL *hkls, gint hkls_len)
{
- if (decimal_mark)
- return (decimal_mark);
+ gint i;
+
+ if (hkls_len != array->len)
+ return FALSE;
- return ((guint32) '.');
+ 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 (hkl != cached_hkl)
+ {
+ if (!GetKeyboardLayoutNameW (hkl_name))
+ wcscpy_s (hkl_name, KL_NAMELENGTH, L"(NULL)");
- if (keysym_tab == NULL)
- keysym_tab = g_new (guint, 4*KEY_STATE_SIZE);
+ g_warning ("Cached active layout #%d (0x%p) does not match actual layout %S, 0x%p",
+ keymap->active_layout, cached_hkl, hkl_name, hkl);
+ }
+}
- memset (key_state, 0, sizeof (key_state));
+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;
- _gdk_keyboard_has_altgr = FALSE;
- gdk_shift_modifiers = GDK_SHIFT_MASK;
+ no_list = FALSE;
+ hkls_len = GetKeyboardLayoutList (0, NULL);
- for (vk = 0; vk < KEY_STATE_SIZE; vk++)
+ if (hkls_len <= 0)
{
- 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;
+ hkls_len = 1;
+ no_list = TRUE;
+ }
+ else if (hkls_len > 255)
+ {
+ hkls_len = 255;
+ }
- if (vk == VK_RSHIFT)
- _scancode_rshift = scancode;
+ if (hkls_size < hkls_len)
+ {
+ hkls = g_renew (HKL, hkls, hkls_len);
+ hkls_size = hkls_len;
+ }
- key_state[vk] = 0x80;
- for (shift = 0; shift < 4; shift++)
- {
- guint *ksymp = keysym_tab + vk*4 + shift;
+ 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];
- set_shift_vks (key_state, shift);
+ if (!GetKeyboardLayoutNameW (hkl_name))
+ wcscpy_s (hkl_name, KL_NAMELENGTH, L"(NULL)");
- *ksymp = 0;
+ GDK_NOTE (EVENTS, g_print ("(active, %S)", hkl_name));
+ }
+ }
- /* 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);
+ GDK_NOTE (EVENTS, g_print ("\n"));
- if ((*ksymp == 0) || ((vk == VK_DECIMAL) && (shift == 0)))
- {
- wchar_t wcs[10];
- gint k;
+ keysym_tab_size = hkls_len * 256 * 2 * 2;
- wcs[0] = wcs[1] = 0;
- k = ToUnicodeEx (vk, scancode, key_state,
- wcs, G_N_ELEMENTS (wcs),
- 0, _gdk_input_locale);
+ 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++)
+ {
+ 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 (scancode == 0 &&
+ vk != VK_DIVIDE)
+ {
+ for (level = GDK_WIN32_LEVEL_NONE; level < GDK_WIN32_LEVEL_COUNT; level++)
+ keygroup[level] = GDK_KEY_VoidSymbol;
+
+ continue;
+ }
+
+ if (vk == VK_RSHIFT)
+ options->scancode_rshift = scancode;
+
+ key_state[vk] = 0x80;
+
+ for (level = GDK_WIN32_LEVEL_NONE; level < GDK_WIN32_LEVEL_COUNT; level++)
+ {
+ guint *ksymp = &keygroup[level];
+
+ set_level_vks (key_state, level);
+
+ *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]);
-
- /* 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);
-
- /* 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
- {
+ 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, hkls[group]);
+
+ /* 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;
-
- /* 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 (!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];
-
- 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, _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;
- }
- }
- }
+ break;
+ }
+ }
+
+ if (*ksymp == 0)
+ *ksymp = GDK_KEY_VoidSymbol;
+ }
+
+ key_state[vk] = 0;
+
+ /* 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;
+
+ 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];
+
+ 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 PangoDirection
+gdk_win32_keymap_get_direction (GdkKeymap *gdk_keymap)
+{
+ 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 *keymap)
+gdk_win32_keymap_have_bidi_layouts (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;
+ 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 (group = 0; group < keymap->layout_handles->len; group++)
+ {
+ GdkWin32KeyLevelState level;
- for (i = 0; i < 4; i++)
- {
- if (keysym_tab[vk*4+i] == keyval)
- {
- GdkKeymapKey key;
+ for (level = GDK_WIN32_LEVEL_NONE; level < GDK_WIN32_LEVEL_COUNT; level++)
+ {
+ guint *keygroup;
- key.keycode = vk;
+ keygroup = &keymap->keysym_tab[(vk * keymap->layout_handles->len + group) *
GDK_WIN32_LEVEL_COUNT];
- /* 2 levels (normal, shift), two groups (normal, AltGr) */
- key.group = i / 2;
- key.level = i % 2;
+ if (keygroup[level] == keyval)
+ {
+ GdkKeymapKey key;
- g_array_append_val (retval, 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 ())
- {
- gint i;
+ keymap = GDK_WIN32_KEYMAP (gdk_keymap_get_default ());
+ update_keymap (GDK_KEYMAP (keymap));
- update_keymap ();
+ for (group = 0; group < keymap->layout_handles->len; group++)
+ {
+ GdkWin32KeyLevelState level;
- 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)
- return FALSE;
+ keymap = GDK_WIN32_KEYMAP (gdk_keymap_get_default ());
+ update_keymap (GDK_KEYMAP (keymap));
- update_keymap ();
+ if (group < 0 || group >= keymap->layout_handles->len)
+ return FALSE;
- 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
- * the key for those.
- */
- if (shift_level == 1 &&
- keyvals[group*2 + 1] == GDK_KEY_VoidSymbol &&
- keyvals[group*2] != GDK_KEY_VoidSymbol)
+ if (shift_level == GDK_WIN32_LEVEL_NONE)
{
- shift_level = 0;
- ignore_shift = TRUE;
+ if (state & GDK_MOD2_MASK)
+ shift_level = GDK_WIN32_LEVEL_ALTGR;
}
-
- if (group == 1 &&
- keyvals[2 + shift_level] == GDK_KEY_VoidSymbol &&
- keyvals[0 + shift_level] != GDK_KEY_VoidSymbol)
+ else
{
- group = 0;
- ignore_group = TRUE;
+ if (state & GDK_MOD2_MASK)
+ shift_level = GDK_WIN32_LEVEL_SHIFT_ALTGR;
}
- if (keyvals[group *2 + shift_level] == GDK_KEY_VoidSymbol &&
- keyvals[0 + 0] != GDK_KEY_VoidSymbol)
+ /* Drop altgr and shift if there are no keysymbols on
+ * the key for those.
+ */
+ if (keygroup[shift_level] == 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,24 +1261,19 @@ 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)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
diff --git a/gdk/win32/gdkmain-win32.c b/gdk/win32/gdkmain-win32.c
index b170612..de2d1f8 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 dac65f4..c8491cb 100644
--- a/gdk/win32/gdkprivate-win32.h
+++ b/gdk/win32/gdkprivate-win32.h
@@ -39,6 +39,7 @@
#include <gdk/win32/gdkwindow-win32.h>
#include <gdk/win32/gdkwin32display.h>
#include <gdk/win32/gdkwin32screen.h>
+#include <gdk/win32/gdkwin32keys.h>
#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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]