if (GetKeyState (VK_MENU) < 0)
event->key.state |= GDK_MOD1_MASK;
}
+ else
+ event->key.group = 1;
}
static gint
bytecount = ImmGetCompositionStringW (himc, GCS_RESULTSTR,
wbuf, sizeof (wbuf));
ucount = bytecount / 2;
+ event->key.hardware_keycode = wbuf[0]; /* ??? */
}
else
{
+ event->key.hardware_keycode = msg->wParam;
if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR)
{
bytecount = MIN ((msg->lParam & 0xFFFF), sizeof (buf));
}
}
- /* Convert from the window's current code page
+ /* Convert from the thread's current code page
* to Unicode. Then convert to UTF-8.
* We don't handle the surrogate stuff. Should we?
*/
- GDK_NOTE (EVENTS, g_print ("ciACP=%d\n", impl->charset_info.ciACP));
- ucount = MultiByteToWideChar (impl->charset_info.ciACP,
+ ucount = MultiByteToWideChar (_gdk_input_codepage,
0, buf, bytecount,
wbuf, G_N_ELEMENTS (wbuf));
}
event->key.group = 0; /* ??? */
if (msg->message == WM_CHAR || msg->message == WM_SYSCHAR)
- if (msg->wParam < ' ')
- event->key.keyval = msg->wParam + '@';
- else
- {
- buf = msg->wParam;
- MultiByteToWideChar (impl->charset_info.ciACP,
- 0, &buf, 1, &wbuf, 1);
-
- event->key.keyval = gdk_unicode_to_keyval (wbuf);
- }
+ {
+ event->key.hardware_keycode = msg->wParam;
+ if (msg->wParam < ' ')
+ event->key.keyval = msg->wParam + '@';
+ else
+ {
+ buf = msg->wParam;
+ MultiByteToWideChar (_gdk_input_codepage,
+ 0, &buf, 1, &wbuf, 1);
+
+ event->key.keyval = gdk_unicode_to_keyval (wbuf);
+ }
+ }
else
- event->key.keyval = GDK_VoidSymbol;
+ {
+ event->key.keyval = GDK_VoidSymbol;
+ event->key.hardware_keycode = 0; /* ??? */
+ }
build_key_event_state (event);
event->key.string = NULL;
event->key.length = 0;
else
escaped = g_strescape (event->key.string, NULL);
kvname = gdk_keyval_name (event->key.keyval);
- g_print ("%s %d:\"%s\" ",
+ g_print ("%#.02x %d %s %d:\"%s\" ",
+ event->key.hardware_keycode, event->key.group,
(kvname ? kvname : "??"),
event->key.length,
escaped);
HWND hwnd;
HCURSOR hcursor;
HRGN hrgn;
+ CHARSETINFO charset_info;
/* Invariant:
* window_impl == GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl)
switch (msg->message)
{
case WM_INPUTLANGCHANGE:
- GDK_NOTE (EVENTS,
- g_print ("WM_INPUTLANGCHANGE: %p charset %lu locale %lx\n",
- msg->hwnd, (gulong) msg->wParam, msg->lParam));
- window_impl->input_locale = (HKL) msg->lParam;
+ _gdk_input_locale = (HKL) msg->lParam;
TranslateCharsetInfo ((DWORD FAR *) msg->wParam,
- &window_impl->charset_info,
+ &charset_info,
TCI_SRCCHARSET);
+ _gdk_input_codepage = charset_info.ciACP;
+ _gdk_keymap_serial++;
+ GDK_NOTE (EVENTS,
+ g_print ("WM_INPUTLANGCHANGE: %p charset %lu locale %lx cp%d\n",
+ msg->hwnd, (gulong) msg->wParam, msg->lParam,
+ _gdk_input_codepage));
break;
case WM_SYSKEYUP:
keyup_or_down:
event->key.window = window;
- event->key.hardware_keycode = msg->wParam;
switch (msg->wParam)
{
event->key.state |= GDK_CONTROL_MASK;
if (msg->wParam != VK_MENU && GetKeyState (VK_MENU) < 0)
event->key.state |= GDK_MOD1_MASK;
- event->key.group = 0; /* ??? */
+ event->key.hardware_keycode = msg->wParam;
+ event->key.group = (event->key.state & GDK_MOD1_MASK) != 0;
event->key.string = NULL;
event->key.length = 0;
return_val = !GDK_WINDOW_DESTROYED (window);
guint _gdk_keymap_serial = 0;
-static gint min_keycode = 0;
-static gint max_keycode = 0;
-
static GdkKeymap *default_keymap = NULL;
+static guint *keysym_tab = NULL;
+
+static void
+update_keymap (void)
+{
+ static guint current_serial = 0;
+ guchar key_state[256];
+ guint scancode;
+ guint vk;
+
+ if (keysym_tab != NULL && current_serial == _gdk_keymap_serial)
+ return;
+
+ current_serial = _gdk_keymap_serial;
+
+ if (keysym_tab == NULL)
+ keysym_tab = g_new (guint, 4*256);
+
+ memset (key_state, 0, sizeof (key_state));
+
+ for (vk = 0; vk < 256; vk++)
+ {
+ if ((scancode = MapVirtualKey (vk, 0)) == 0)
+ keysym_tab[vk*4+0] =
+ keysym_tab[vk*4+1] =
+ keysym_tab[vk*4+2] =
+ keysym_tab[vk*4+3] = GDK_VoidSymbol;
+ else
+ {
+ gint i, k;
+
+ key_state[vk] = 0x80;
+ for (i = 0; i < 4; i++)
+ {
+ guint *ksymp = keysym_tab + vk*4 + i;
+ guchar chars[2];
+
+ switch (i)
+ {
+ case 0:
+ key_state[VK_SHIFT] = 0;
+ key_state[VK_CONTROL] = key_state[VK_MENU] = 0;
+ break;
+ case 1:
+ key_state[VK_SHIFT] = 0x80;
+ key_state[VK_CONTROL] = key_state[VK_MENU] = 0;
+ break;
+ case 2:
+ key_state[VK_SHIFT] = 0;
+ key_state[VK_CONTROL] = key_state[VK_MENU] = 0x80;
+ break;
+ case 3:
+ key_state[VK_SHIFT] = 0x80;
+ key_state[VK_CONTROL] = key_state[VK_MENU] = 0x80;
+ break;
+ }
+
+ *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).
+ */
+ switch (vk)
+ {
+ case VK_CANCEL:
+ *ksymp = GDK_Cancel; break;
+ case VK_BACK:
+ *ksymp = GDK_BackSpace; break;
+ case VK_TAB:
+ *ksymp = GDK_Tab; break;
+ case VK_CLEAR:
+ *ksymp = GDK_Clear; break;
+ case VK_RETURN:
+ *ksymp = GDK_Return; break;
+ case VK_SHIFT:
+ case VK_LSHIFT:
+ *ksymp = GDK_Shift_L; break;
+ case VK_CONTROL:
+ case VK_LCONTROL:
+ *ksymp = GDK_Control_L; break;
+ case VK_MENU:
+ case VK_LMENU:
+ *ksymp = GDK_Alt_L; break;
+ case VK_PAUSE:
+ *ksymp = GDK_Pause; break;
+ case VK_ESCAPE:
+ *ksymp = GDK_Escape; break;
+ case VK_PRIOR:
+ *ksymp = GDK_Prior; break;
+ case VK_NEXT:
+ *ksymp = GDK_Next; break;
+ case VK_END:
+ *ksymp = GDK_End; break;
+ case VK_HOME:
+ *ksymp = GDK_Home; break;
+ case VK_LEFT:
+ *ksymp = GDK_Left; break;
+ case VK_UP:
+ *ksymp = GDK_Up; break;
+ case VK_RIGHT:
+ *ksymp = GDK_Right; break;
+ case VK_DOWN:
+ *ksymp = GDK_Down; break;
+ case VK_SELECT:
+ *ksymp = GDK_Select; break;
+ case VK_PRINT:
+ *ksymp = GDK_Print; break;
+ case VK_EXECUTE:
+ *ksymp = GDK_Execute; break;
+ case VK_INSERT:
+ *ksymp = GDK_Insert; break;
+ case VK_DELETE:
+ *ksymp = GDK_Delete; break;
+ case VK_HELP:
+ *ksymp = GDK_Help; break;
+ case VK_LWIN:
+ *ksymp = GDK_Meta_L; break;
+ case VK_RWIN:
+ *ksymp = GDK_Meta_R; break;
+ case VK_MULTIPLY:
+ *ksymp = GDK_KP_Multiply; break;
+ case VK_ADD:
+ *ksymp = GDK_KP_Add; break;
+ case VK_SEPARATOR:
+ *ksymp = GDK_KP_Separator; break;
+ case VK_SUBTRACT:
+ *ksymp = GDK_KP_Subtract; break;
+ case VK_DECIMAL:
+ *ksymp = GDK_KP_Decimal; break;
+ case VK_DIVIDE:
+ *ksymp = GDK_KP_Divide; break;
+ case VK_F1:
+ *ksymp = GDK_F1; break;
+ case VK_F2:
+ *ksymp = GDK_F2; break;
+ case VK_F3:
+ *ksymp = GDK_F3; break;
+ case VK_F4:
+ *ksymp = GDK_F4; break;
+ case VK_F5:
+ *ksymp = GDK_F5; break;
+ case VK_F6:
+ *ksymp = GDK_F6; break;
+ case VK_F7:
+ *ksymp = GDK_F7; break;
+ case VK_F8:
+ *ksymp = GDK_F8; break;
+ case VK_F9:
+ *ksymp = GDK_F9; break;
+ case VK_F10:
+ *ksymp = GDK_F10; break;
+ case VK_F11:
+ *ksymp = GDK_F11; break;
+ case VK_F12:
+ *ksymp = GDK_F12; break;
+ case VK_F13:
+ *ksymp = GDK_F13; break;
+ case VK_F14:
+ *ksymp = GDK_F14; break;
+ case VK_F15:
+ *ksymp = GDK_F15; break;
+ case VK_F16:
+ *ksymp = GDK_F16; break;
+ case VK_F17:
+ *ksymp = GDK_F17; break;
+ case VK_F18:
+ *ksymp = GDK_F18; break;
+ case VK_F19:
+ *ksymp = GDK_F19; break;
+ case VK_F20:
+ *ksymp = GDK_F20; break;
+ case VK_F21:
+ *ksymp = GDK_F21; break;
+ case VK_F22:
+ *ksymp = GDK_F22; break;
+ case VK_F23:
+ *ksymp = GDK_F23; break;
+ case VK_F24:
+ *ksymp = GDK_F24; break;
+ case VK_NUMLOCK:
+ *ksymp = GDK_Num_Lock; break;
+ case VK_SCROLL:
+ *ksymp = GDK_Scroll_Lock; break;
+ case VK_RSHIFT:
+ *ksymp = GDK_Shift_R; break;
+ case VK_RCONTROL:
+ *ksymp = GDK_Control_R; break;
+ case VK_RMENU:
+ *ksymp = GDK_Alt_R; break;
+ }
+ if (*ksymp == 0)
+ {
+ if ((k = ToAsciiEx (vk, scancode, key_state,
+ (LPWORD) chars, 0,
+ _gdk_input_locale)) == 1)
+ {
+ if (_gdk_input_codepage == 1252 &&
+ chars[0] >= GDK_space && chars[0] <= GDK_asciitilde)
+ *ksymp = chars[0];
+ else
+ {
+ wchar_t wcs[1];
+ if (MultiByteToWideChar (_gdk_input_codepage, 0,
+ chars, 1, wcs, 1) > 0)
+ *ksymp = gdk_unicode_to_keyval (wcs[0]);
+ }
+ }
+ }
+ if (*ksymp == 0)
+ *ksymp = GDK_VoidSymbol;
+ }
+ key_state[vk] = 0;
+ }
+ }
+#ifdef G_ENABLE_DEBUG
+ if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
+ {
+ gint i, j;
+
+ g_print ("keymap:\n");
+ for (i = 0; i < 256; i++)
+ {
+ g_print ("%#.02x: ", i);
+ for (j = 0; j < 4; j++)
+ {
+ gchar *name = gdk_keyval_name (keysym_tab[i*4 + j]);
+ if (name == NULL)
+ name = "(none)";
+ g_print ("%s ", name);
+ }
+ g_print ("\n");
+ }
+ }
+#endif
+}
+
GdkKeymap*
gdk_keymap_get_default (void)
{
PangoDirection
gdk_keymap_get_direction (GdkKeymap *keymap)
{
- PangoDirection result;
- char kln[KL_NAMELENGTH];
- UINT acp = GetACP ();
+ update_keymap ();
- /* XXX : all this is untested, so if you are using a RTL language
- * please provide patches/hints if your cursor blinks at
- * the wrong place ...
- */
- if (!GetKeyboardLayoutName(kln))
- strcpy (kln, "?");
-
- switch (acp) {
- case 1255 : /* Hebrew */
- case 1256 : /* Arabic */
- result = PANGO_DIRECTION_RTL;
- break;
- default :
- result = PANGO_DIRECTION_LTR;
- }
-
- GDK_NOTE (MISC,
- g_print ("gdk_keymap_get_direction: selecting %s for '%s'\n",
- result == PANGO_DIRECTION_LTR ? "LTR" : "RTL", kln));
-
- return result;
+ switch (PRIMARYLANGID (LOWORD ((DWORD) _gdk_input_locale)))
+ {
+ case LANG_HEBREW:
+ case LANG_ARABIC:
+ /* Not 100% sure about these */
+ case LANG_URDU:
+ case LANG_FARSI:
+ /* Others? */
+ return PANGO_DIRECTION_RTL;
+
+ default:
+ return PANGO_DIRECTION_LTR;
+ }
}
/**
retval = g_array_new (FALSE, FALSE, sizeof (GdkKeymapKey));
- /* FIXME: implement */
+ /* Accept only the default keymap */
+ if (keymap == NULL || keymap == gdk_keymap_get_default ())
+ {
+ gint vk;
+
+ update_keymap ();
+
+ for (vk = 0; vk < 256; 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);
+ }
+ }
+ }
+ }
if (retval->len > 0)
{
g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
g_return_val_if_fail (n_entries != NULL, FALSE);
- if (hardware_keycode < min_keycode ||
- hardware_keycode > max_keycode)
+ if (hardware_keycode <= 0 ||
+ hardware_keycode >= 256)
{
if (keys)
*keys = NULL;
else
keyval_array = NULL;
- /* FIXME: implement */
+ /* Accept only the default keymap */
+ if (keymap == NULL || keymap == gdk_keymap_get_default ())
+ {
+ gint i;
+
+ update_keymap ();
+
+ for (i = 0; i < 4; i++)
+ {
+ if (key_array)
+ {
+ GdkKeymapKey key;
+
+ key.keycode = hardware_keycode;
+
+ key.group = i / 2;
+ key.level = i % 2;
+
+ g_array_append_val (key_array, key);
+ }
+
+ if (keyval_array)
+ g_array_append_val (keyval_array, keysym_tab[hardware_keycode*4+i]);
+ }
+ }
if ((key_array && key_array->len > 0) ||
(keyval_array && keyval_array->len > 0))
gdk_keymap_lookup_key (GdkKeymap *keymap,
const GdkKeymapKey *key)
{
+ guint sym;
+
g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), 0);
g_return_val_if_fail (key != NULL, 0);
g_return_val_if_fail (key->group < 4, 0);
- /* FIXME: implement */
+ /* Accept only the default keymap */
+ if (keymap != NULL && keymap != gdk_keymap_get_default ())
+ return 0;
- return 0;
+ update_keymap ();
+
+ if (key->keycode >= 256 ||
+ key->group < 0 || key->group >= 2 ||
+ key->level < 0 || key->level >= 2)
+ return 0;
+
+ sym = keysym_tab[key->keycode*4 + key->group*2 + key->level];
+
+ if (sym == GDK_VoidSymbol)
+ return 0;
+ else
+ return sym;
}
/**
gint *level,
GdkModifierType *consumed_modifiers)
{
+ guint tmp_keyval;
+ gint shift_level;
+
g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
g_return_val_if_fail (group < 4, FALSE);
- /* FIXME: implement */
+ if (keyval)
+ *keyval = 0;
+ if (effective_group)
+ *effective_group = 0;
+ if (level)
+ *level = 0;
+ if (consumed_modifiers)
+ *consumed_modifiers = 0;
+
+ /* Accept only the default keymap */
+ if (keymap != NULL && keymap != gdk_keymap_get_default ())
+ return FALSE;
+
+ if (hardware_keycode >= 256)
+ return FALSE;
+
+ if (group < 0 || group >= 2)
+ return FALSE;
+
+ if ((state & GDK_SHIFT_MASK) && (state & GDK_LOCK_MASK))
+ shift_level = 0; /* shift disables shift lock */
+ else if ((state & GDK_SHIFT_MASK) || (state & GDK_LOCK_MASK))
+ shift_level = 1;
+ else
+ shift_level = 0;
+
+ update_keymap ();
+
+ tmp_keyval = keysym_tab[hardware_keycode*4 + group*2 + shift_level];
+
+ if (effective_group)
+ *effective_group = group;
+
+ if (level)
+ *level = shift_level;
+
+ /* GDK_ISO_Left_Tab, as usually configured through XKB, really messes
+ * up the whole idea of "consumed modifiers" because shift is consumed.
+ * However, <shift>Tab is not _consistently_ GDK_ISO_Left_Tab, so people
+ * can't bind to GDK_ISO_Left_Tab instead. So, we force consistency here.
+ */
+ if (tmp_keyval == GDK_Tab && shift_level == 1)
+ {
+ tmp_keyval = GDK_ISO_Left_Tab;
+ }
+
+ if (consumed_modifiers)
+ *consumed_modifiers = GDK_SHIFT_MASK | GDK_LOCK_MASK;
+
+ if (keyval)
+ *keyval = tmp_keyval;
return FALSE;
}