[gtk+/gtk-2-24] GDK W32: Cache multiple keyboard layouts simultaneously
- From: Руслан Ижбулатов <ruslanizhb src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/gtk-2-24] GDK W32: Cache multiple keyboard layouts simultaneously
- Date: Fri, 25 Nov 2016 17:01:46 +0000 (UTC)
commit 0b06d401034bcbee3e1e50085769361d96a81aaf
Author: Руслан Ижбулатов <lrn1986 gmail com>
Date: Sat Jul 30 20:32:52 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 | 6 +-
gdk/win32/gdkevents-win32.c | 12 +-
gdk/win32/gdkkeys-win32.c | 1003 ++++++++++++++++++++++++++++--------------
gdk/win32/gdkmain-win32.c | 1 +
gdk/win32/gdkprivate-win32.h | 10 +-
5 files changed, 684 insertions(+), 348 deletions(-)
---
diff --git a/gdk/gdkkeyuni.c b/gdk/gdkkeyuni.c
index 7cd8514..42577fe 100644
--- a/gdk/gdkkeyuni.c
+++ b/gdk/gdkkeyuni.c
@@ -887,7 +887,11 @@ gdk_keyval_to_unicode (guint keyval)
#if defined(GDK_WINDOWING_WIN32)
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
/* binary search in table */
diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c
index ccb583b..9b09edd 100644
--- a/gdk/win32/gdkevents-win32.c
+++ b/gdk/win32/gdkevents-win32.c
@@ -634,6 +634,8 @@ static void
build_key_event_state (GdkEvent *event,
BYTE *key_state)
{
+ GdkWin32Keymap *keymap;
+
event->key.state = 0;
if (key_state[VK_SHIFT] & 0x80)
@@ -653,11 +655,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_keymap_get_default ());
+ 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;
@@ -666,7 +670,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)
@@ -2217,6 +2220,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_keymap_get_default ()), _gdk_input_locale);
_gdk_input_locale_is_ime = ImmIsIME (_gdk_input_locale);
GetLocaleInfo (MAKELCID (LOWORD (_gdk_input_locale), SORT_DEFAULT),
LOCALE_IDEFAULTANSICODEPAGE,
@@ -2336,7 +2340,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_keymap_get_default ())))
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 dd4cb0c..edc26b2 100644
--- a/gdk/win32/gdkkeys-win32.c
+++ b/gdk/win32/gdkkeys-win32.c
@@ -38,6 +38,25 @@
#include "gdkkeys.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,51 +65,108 @@ 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;
-
- 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++)
+ gint li;
+ GdkWin32KeyGroupOptions *options;
+ gint vk;
+ GdkWin32KeyLevelState level;
+ gint group_size = keymap->layout_handles->len;
+
+ 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,181 +433,361 @@ 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 (hkl != cached_hkl)
+ {
+ if (!GetKeyboardLayoutNameW (hkl_name))
+ wcscpy_s (hkl_name, KL_NAMELENGTH, L"(NULL)");
+
+ g_warning ("Cached active layout #%d (0x%p) does not match actual layout %S, 0x%p",
+ keymap->active_layout, cached_hkl, hkl_name, hkl);
+ }
+}
+
+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"));
- if (keysym_tab == NULL)
- keysym_tab = g_new (guint, 4*KEY_STATE_SIZE);
+ keysym_tab_size = hkls_len * 256 * 2 * 2;
- memset (key_state, 0, sizeof (key_state));
+ if (hkls_len != keymap->layout_handles->len)
+ keymap->keysym_tab = g_renew (guint, keymap->keysym_tab, keysym_tab_size);
- _gdk_keyboard_has_altgr = FALSE;
- gdk_shift_modifiers = GDK_SHIFT_MASK;
+ 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;
-
- if (vk == VK_RSHIFT)
- _scancode_rshift = scancode;
-
- key_state[vk] = 0x80;
- for (shift = 0; shift < 4; shift++)
- {
- guint *ksymp = keysym_tab + vk*4 + shift;
-
- set_shift_vks (key_state, shift);
-
- *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, shift);
-
- if ((*ksymp == 0) || ((vk == VK_DECIMAL) && (shift == 0)))
- {
- wchar_t wcs[10];
- gint k;
-
- wcs[0] = wcs[1] = 0;
- k = ToUnicodeEx (vk, scancode, key_state,
- wcs, G_N_ELEMENTS (wcs),
- 0, _gdk_input_locale);
+ 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*
gdk_keymap_get_for_display (GdkDisplay *display)
@@ -540,12 +800,10 @@ gdk_keymap_get_for_display (GdkDisplay *display)
return default_keymap;
}
-PangoDirection
-gdk_keymap_get_direction (GdkKeymap *keymap)
+static PangoDirection
+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,64 +819,115 @@ gdk_keymap_get_direction (GdkKeymap *keymap)
}
}
+PangoDirection
+gdk_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);
+}
+
gboolean
-gdk_keymap_have_bidi_layouts (GdkKeymap *keymap)
+gdk_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;
}
gboolean
gdk_keymap_get_caps_lock_state (GdkKeymap *keymap)
{
+ (void) keymap;
+
return ((GetKeyState (VK_CAPITAL) & 1) != 0);
}
gboolean
-gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap,
+gdk_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);
-
+
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;
-
- update_keymap ();
+ GdkWin32Keymap *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;
-
- for (i = 0; i < 4; i++)
- {
- if (keysym_tab[vk*4+i] == keyval)
- {
- GdkKeymapKey key;
-
- key.keycode = vk;
-
- /* 2 levels (normal, shift), two groups (normal, AltGr) */
- key.group = i / 2;
- key.level = i % 2;
-
- g_array_append_val (retval, key);
- }
- }
- }
+ {
+ gint group;
+
+ for (group = 0; group < keymap->layout_handles->len; group++)
+ {
+ GdkWin32KeyLevelState level;
+
+ for (level = GDK_WIN32_LEVEL_NONE; level < GDK_WIN32_LEVEL_COUNT; level++)
+ {
+ guint *keygroup;
+
+ keygroup = &keymap->keysym_tab[(vk * keymap->layout_handles->len + group) *
GDK_WIN32_LEVEL_COUNT];
+
+ 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
@@ -627,12 +936,12 @@ gdk_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
@@ -647,28 +956,33 @@ gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap,
*keys = NULL;
*n_keys = 0;
}
-
+
g_array_free (retval, retval->len > 0 ? FALSE : TRUE);
return *n_keys > 0;
}
gboolean
-gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap,
+gdk_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)
@@ -677,43 +991,47 @@ gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap,
*n_entries = 0;
return FALSE;
}
-
+
if (keys)
key_array = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
else
key_array = NULL;
-
+
if (keyvals)
keyval_array = g_array_new (FALSE, FALSE, sizeof (guint));
else
keyval_array = NULL;
-
- /* Accept only the default keymap */
- if (keymap == NULL || keymap == gdk_keymap_get_default ())
- {
- gint i;
- update_keymap ();
+ keymap = GDK_WIN32_KEYMAP (gdk_keymap_get_default ());
+ update_keymap (GDK_KEYMAP (keymap));
- for (i = 0; i < 4; i++)
- {
- if (key_array)
+ for (group = 0; group < keymap->layout_handles->len; group++)
+ {
+ GdkWin32KeyLevelState level;
+
+ 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))
{
@@ -722,11 +1040,6 @@ gdk_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
{
@@ -735,8 +1048,6 @@ gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap,
if (keyvals)
*keyvals = NULL;
-
- *n_entries = 0;
}
if (key_array)
@@ -748,28 +1059,29 @@ gdk_keymap_get_entries_for_keycode (GdkKeymap *keymap,
}
guint
-gdk_keymap_lookup_key (GdkKeymap *keymap,
+gdk_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;
else
@@ -777,7 +1089,7 @@ gdk_keymap_lookup_key (GdkKeymap *keymap,
}
gboolean
-gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
+gdk_keymap_translate_keyboard_state (GdkKeymap *gdk_keymap,
guint hardware_keycode,
GdkModifierType state,
gint group,
@@ -786,15 +1098,15 @@ gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
gint *level,
GdkModifierType *consumed_modifiers)
{
+ GdkWin32Keymap *keymap;
guint tmp_keyval;
- guint *keyvals;
- gint shift_level;
- gboolean ignore_shift = FALSE;
- gboolean ignore_group = FALSE;
-
- g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
- g_return_val_if_fail (group < 4, FALSE);
-
+ guint *keygroup;
+ GdkWin32KeyLevelState shift_level;
+ GdkWin32KeyGroupOptions *options;
+ GdkModifierType modifiers = GDK_SHIFT_MASK | GDK_LOCK_MASK | GDK_MOD2_MASK;
+
+ g_return_val_if_fail (gdk_keymap == NULL || GDK_IS_KEYMAP (gdk_keymap), FALSE);
+
#if 0
GDK_NOTE (EVENTS, g_print ("gdk_keymap_translate_keyboard_state: keycode=%#x state=%#x group=%d\n",
hardware_keycode, state, group));
@@ -809,83 +1121,103 @@ gdk_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;
}
@@ -899,15 +1231,11 @@ gdk_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;
@@ -928,11 +1256,6 @@ gdk_keymap_map_virtual_modifiers (GdkKeymap *keymap,
}
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 46d2774..820b0fc 100644
--- a/gdk/win32/gdkmain-win32.c
+++ b/gdk/win32/gdkmain-win32.c
@@ -90,6 +90,7 @@ _gdk_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_keymap_get_default ()), _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 35116a5..ef4fa56 100644
--- a/gdk/win32/gdkprivate-win32.h
+++ b/gdk/win32/gdkprivate-win32.h
@@ -38,6 +38,7 @@
#include <gdk/gdkprivate.h>
#include <gdk/win32/gdkwindow-win32.h>
#include <gdk/win32/gdkpixmap-win32.h>
+#include <gdk/win32/gdkwin32keys.h>
#include "gdkinternals.h"
@@ -407,8 +408,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;
@@ -500,7 +499,12 @@ void _gdk_win32_emit_configure_event (GdkWindow *window);
GdkWindow *_gdk_win32_find_window_for_mouse_event (GdkWindow* reported_window,
MSG* msg);
-guint32 _gdk_win32_keymap_get_decimal_mark (void);
+guint32 _gdk_win32_keymap_get_decimal_mark (GdkWin32Keymap *keymap);
+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);
/* Initialization */
void _gdk_windowing_window_init (GdkScreen *screen);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]