summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2002-10-18 19:26:43 +0000
committerOwen Taylor <otaylor@src.gnome.org>2002-10-18 19:26:43 +0000
commit30faa38aec228c0b20c665f409b09447f801bcdd (patch)
tree6f6ebb34500f74a103e8b7ab0d79eb9c90791d31 /gdk
parentd0c4e085357c46991ac4b83a5a0b0a58bc3583c9 (diff)
downloadgdk-pixbuf-30faa38aec228c0b20c665f409b09447f801bcdd.tar.gz
Fix use of uninitialized variable.
Thu Oct 17 17:17:05 2002 Owen Taylor <otaylor@redhat.com> * gtk/gtkcheckbutton.c (gtk_check_button_size_request): Fix use of uninitialized variable. Thu Oct 17 14:38:37 2002 Owen Taylor <otaylor@redhat.com> * gtk/gtkaccellabel.c (gtk_accel_label_expose_event): Align the baseline of the accelerator label with the first baseline of the main label of the menu item. (#76593) Wed Oct 16 18:25:24 2002 Owen Taylor <otaylor@redhat.com> * gdk/x11/gdkevents-x11.c (translate_key_event): Use gdk_keymap_translate_keyboard_state() rather than XLookupString() to get the keysymbol, since XLookupString can confuse the input method handling. (#93575) * gdk/x11/gdkkeys-x11.c: Rewrite the handling of key translation for the non-XKB case to properly handle Shift_Lock, Caps_Lock, Num_Lock according to the Xlib spec. (#67066)
Diffstat (limited to 'gdk')
-rw-r--r--gdk/x11/gdkevents-x11.c165
-rw-r--r--gdk/x11/gdkkeys-x11.c184
2 files changed, 216 insertions, 133 deletions
diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c
index e8bedf9e3..c1a44b94b 100644
--- a/gdk/x11/gdkevents-x11.c
+++ b/gdk/x11/gdkevents-x11.c
@@ -512,6 +512,94 @@ set_screen_from_root (GdkDisplay *display,
gdk_event_set_screen (event, screen);
}
+static void
+translate_key_event (GdkDisplay *display,
+ GdkEvent *event,
+ XEvent *xevent)
+{
+ GdkKeymap *keymap = gdk_keymap_get_for_display (display);
+ gunichar c = 0;
+ guchar buf[7];
+
+ event->key.type = xevent->xany.type == KeyPress ? GDK_KEY_PRESS : GDK_KEY_RELEASE;
+ event->key.time = xevent->xkey.time;
+
+ event->key.state = (GdkModifierType) xevent->xkey.state;
+ event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
+ event->key.hardware_keycode = xevent->xkey.keycode;
+
+ event->key.keyval = GDK_VoidSymbol;
+
+ gdk_keymap_translate_keyboard_state (keymap,
+ event->key.hardware_keycode,
+ event->key.state,
+ event->key.group,
+ &event->key.keyval,
+ NULL, NULL, NULL);
+
+ /* Fill in event->string crudely, since various programs
+ * depend on it.
+ */
+ event->key.string = NULL;
+
+ if (event->key.keyval != GDK_VoidSymbol)
+ c = gdk_keyval_to_unicode (event->key.keyval);
+
+ if (c)
+ {
+ gsize bytes_written;
+ gint len;
+
+ /* Apply the control key - Taken from Xlib
+ */
+ if (event->key.state & GDK_CONTROL_MASK)
+ {
+ if ((c >= '@' && c < '\177') || c == ' ') c &= 0x1F;
+ else if (c == '2')
+ {
+ event->key.string = g_memdup ("\0\0", 2);
+ event->key.length = 1;
+ buf[0] = '\0';
+ goto out;
+ }
+ else if (c >= '3' && c <= '7') c -= ('3' - '\033');
+ else if (c == '8') c = '\177';
+ else if (c == '/') c = '_' & 0x1F;
+ }
+
+ len = g_unichar_to_utf8 (c, buf);
+ buf[len] = '\0';
+
+ event->key.string = g_locale_from_utf8 (buf, len,
+ NULL, &bytes_written,
+ NULL);
+ if (event->key.string)
+ event->key.length = bytes_written;
+ }
+
+ if (!event->key.string)
+ {
+ event->key.length = 0;
+ event->key.string = g_strdup ("");
+ }
+
+ out:
+#ifdef G_ENABLE_DEBUG
+ if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
+ {
+ g_message ("%s:\t\twindow: %ld key: %12s %d",
+ event->type == GDK_KEY_PRESS ? "key press " : "key release",
+ xevent->xkey.window,
+ event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
+ event->key.keyval);
+
+ if (event->key.length > 0)
+ g_message ("\t\tlength: %4d string: \"%s\"",
+ event->key.length, buf);
+ }
+#endif /* G_ENABLE_DEBUG */
+}
+
/* Return the window this has to do with, if any, rather
* than the frame or root window that was selecting
* for substructure
@@ -569,10 +657,6 @@ gdk_event_translate (GdkDisplay *display,
GdkWindow *window;
GdkWindowObject *window_private;
GdkWindowImplX11 *window_impl = NULL;
- static XComposeStatus compose;
- KeySym keysym;
- int charcount;
- char buf[16];
gint return_val;
gint xoffset, yoffset;
GdkScreen *screen = NULL;
@@ -750,48 +834,9 @@ gdk_event_translate (GdkDisplay *display,
return_val = FALSE;
break;
}
-
- /* Lookup the string corresponding to the given keysym.
- */
-
- charcount = XLookupString (&xevent->xkey, buf, 16,
- &keysym, &compose);
- event->key.keyval = keysym;
- event->key.hardware_keycode = xevent->xkey.keycode;
-
- if (charcount > 0 && buf[charcount-1] == '\0')
- charcount --;
- else
- buf[charcount] = '\0';
-
-#ifdef G_ENABLE_DEBUG
- if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
- {
- g_message ("key press:\twindow: %ld key: %12s %d",
- xevent->xkey.window,
- event->key.keyval ? XKeysymToString (event->key.keyval) : "(none)",
- event->key.keyval);
- if (charcount > 0)
- g_message ("\t\tlength: %4d string: \"%s\"",
- charcount, buf);
- }
-#endif /* G_ENABLE_DEBUG */
-
- event->key.type = GDK_KEY_PRESS;
- event->key.window = window;
- event->key.time = xevent->xkey.time;
- event->key.state = (GdkModifierType) xevent->xkey.state;
- event->key.string = g_strdup (buf);
- event->key.length = charcount;
-
- /* bits 13 and 14 in the "state" field are the keyboard group */
-#define KEYBOARD_GROUP_SHIFT 13
-#define KEYBOARD_GROUP_MASK ((1 << 13) | (1 << 14))
-
- event->key.group = _gdk_x11_get_group_for_state (display, xevent->xkey.state);
-
+ translate_key_event (display, event, xevent);
break;
-
+
case KeyRelease:
if (window_private == NULL)
{
@@ -799,9 +844,6 @@ gdk_event_translate (GdkDisplay *display,
break;
}
- /* Lookup the string corresponding to the given keysym.
- */
-
/* Emulate detectable auto-repeat by checking to see
* if the next event is a key press with the same
* keycode and timestamp, and if so, ignoring the event.
@@ -816,30 +858,13 @@ gdk_event_translate (GdkDisplay *display,
if (next_event.type == KeyPress &&
next_event.xkey.keycode == xevent->xkey.keycode &&
next_event.xkey.time == xevent->xkey.time)
- break;
+ {
+ return_val = FALSE;
+ break;
+ }
}
-
- keysym = GDK_VoidSymbol;
- charcount = XLookupString (&xevent->xkey, buf, 16,
- &keysym, &compose);
- event->key.keyval = keysym;
- event->key.hardware_keycode = xevent->xkey.keycode;
-
- GDK_NOTE (EVENTS,
- g_message ("key release:\t\twindow: %ld key: %12s %d",
- xevent->xkey.window,
- XKeysymToString (event->key.keyval),
- event->key.keyval));
-
- event->key.type = GDK_KEY_RELEASE;
- event->key.window = window;
- event->key.time = xevent->xkey.time;
- event->key.state = (GdkModifierType) xevent->xkey.state;
- event->key.length = 0;
- event->key.string = NULL;
-
- event->key.group = (xevent->xkey.state & KEYBOARD_GROUP_MASK) >> KEYBOARD_GROUP_SHIFT;
+ translate_key_event (display, event, xevent);
break;
case ButtonPress:
diff --git a/gdk/x11/gdkkeys-x11.c b/gdk/x11/gdkkeys-x11.c
index cafc03b2b..21cc28fa3 100644
--- a/gdk/x11/gdkkeys-x11.c
+++ b/gdk/x11/gdkkeys-x11.c
@@ -67,7 +67,9 @@ struct _GdkKeymapX11
KeySym* keymap;
gint keysyms_per_keycode;
XModifierKeymap* mod_keymap;
+ guint lock_keysym;
GdkModifierType group_switch_mask;
+ GdkModifierType num_lock_mask;
PangoDirection current_direction;
gboolean have_direction;
guint current_serial;
@@ -121,7 +123,9 @@ gdk_keymap_x11_init (GdkKeymapX11 *keymap)
keymap->keysyms_per_keycode = 0;
keymap->mod_keymap = NULL;
+ keymap->num_lock_mask = 0;
keymap->group_switch_mask = 0;
+ keymap->lock_keysym = GDK_Caps_Lock;
keymap->have_direction = FALSE;
#ifdef HAVE_XKB
@@ -201,6 +205,8 @@ gdk_keymap_get_for_display (GdkDisplay *display)
*/
#define KEYSYM_INDEX(keymap_impl, group, level) \
(2 * ((group) % (keymap_impl->keysyms_per_keycode / 2)) + (level))
+#define KEYSYM_IS_KEYPAD(s) (((s) >= 0xff80 && (s) <= 0xffbd) || \
+ ((s) >= 0x11000000 && (s) <= 0x1100ffff))
static void
update_keymaps (GdkKeymapX11 *keymap_x11)
@@ -273,8 +279,9 @@ update_keymaps (GdkKeymapX11 *keymap_x11)
keymap_x11->mod_keymap = XGetModifierMapping (xdisplay);
-
+ keymap_x11->lock_keysym = GDK_VoidSymbol;
keymap_x11->group_switch_mask = 0;
+ keymap_x11->num_lock_mask = 0;
/* there are 8 modifiers, and the first 3 are shift, shift lock,
* and control
@@ -292,7 +299,7 @@ update_keymaps (GdkKeymapX11 *keymap_x11)
if (keycode >= keymap_x11->min_keycode &&
keycode <= keymap_x11->max_keycode)
{
- gint j = 0;
+ gint j;
KeySym *syms = keymap_x11->keymap + (keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
/* GDK_MOD1_MASK is 1 << 3 for example, i.e. the
* fourth modifier, i / keyspermod is the modifier
@@ -300,6 +307,17 @@ update_keymaps (GdkKeymapX11 *keymap_x11)
*/
guint mask = 1 << ( i / keymap_x11->mod_keymap->max_keypermod);
+ if (mask == GDK_LOCK_MASK)
+ {
+ for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
+ {
+ if (syms[j] == GDK_Caps_Lock)
+ keymap_x11->lock_keysym = syms[j];
+ else if (syms[j] == GDK_Shift_Lock && keymap_x11->lock_keysym == GDK_VoidSymbol)
+ keymap_x11->lock_keysym = syms[j];
+ }
+ }
+
/* Some keyboard maps are known to map Mode_Switch as an extra
* Mod1 key. In circumstances like that, it won't be used to
* switch groups.
@@ -308,17 +326,20 @@ update_keymaps (GdkKeymapX11 *keymap_x11)
mask == GDK_LOCK_MASK || mask == GDK_MOD1_MASK)
goto next;
- while (j < keymap_x11->keysyms_per_keycode)
+ for (j = 0; j < keymap_x11->keysyms_per_keycode; j++)
{
if (syms[j] == GDK_Mode_switch)
{
/* This modifier swaps groups */
keymap_x11->group_switch_mask |= mask;
- break;
}
-
- ++j;
+ if (syms[j] == GDK_Num_Lock)
+ {
+ /* This modifier swaps groups */
+
+ keymap_x11->num_lock_mask |= mask;
+ }
}
}
@@ -927,6 +948,75 @@ MyEnhancedXkbTranslateKeyCode(register XkbDescPtr xkb,
}
#endif /* HAVE_XKB */
+/* Translates from keycode/state to keysymbol using the traditional interpretation
+ * of the keyboard map. See section 12.7 of the Xlib reference manual
+ */
+static guint
+translate_keysym (GdkKeymapX11 *keymap_x11,
+ guint hardware_keycode,
+ gint group,
+ GdkModifierType state,
+ guint *effective_group,
+ guint *effective_level)
+{
+ const KeySym *map = get_keymap (keymap_x11);
+ const KeySym *syms = map + (hardware_keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
+
+#define SYM(k,g,l) syms[KEYSYM_INDEX (k,g,l)]
+
+ GdkModifierType shift_modifiers;
+ gint shift_level;
+ guint tmp_keyval;
+
+ shift_modifiers = GDK_SHIFT_MASK;
+ if (keymap_x11->lock_keysym == GDK_Shift_Lock)
+ shift_modifiers |= GDK_LOCK_MASK;
+
+ /* Fall back to the first group if the passed in group is empty
+ */
+ if (!(SYM (keymap_x11, group, 0) || SYM (keymap_x11, group, 1)) &&
+ (SYM (keymap_x11, 0, 0) || SYM (keymap_x11, 0, 1)))
+ group = 0;
+
+ if ((state & GDK_SHIFT_MASK) != 0 &&
+ KEYSYM_IS_KEYPAD (SYM (keymap_x11, group, 1)))
+ {
+ /* Shift, Shift_Lock cancel Num_Lock
+ */
+ shift_level = (state & shift_modifiers) ? 0 : 1;
+
+ tmp_keyval = SYM (keymap_x11, group, shift_level);
+ }
+ else
+ {
+ /* Fall back to the the first level if no symbol for the level
+ * we were passed.
+ */
+ shift_level = (state & shift_modifiers) ? 1 : 0;
+ if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, group, 0))
+ shift_level = 0;
+
+ tmp_keyval = SYM (keymap_x11, group, shift_level);
+
+ if (keymap_x11->lock_keysym == GDK_Caps_Lock && (state & GDK_SHIFT_MASK) != 0)
+ {
+ guint upper = gdk_keyval_to_upper (tmp_keyval);
+ if (upper != tmp_keyval)
+ tmp_keyval = upper;
+ }
+ }
+
+ if (effective_group)
+ *effective_group = group;
+
+ if (effective_level)
+ *effective_level = shift_level;
+
+ return tmp_keyval;
+
+#undef SYM
+}
+
/**
* gdk_keymap_translate_keyboard_state:
* @keymap: a #GdkKeymap, or %NULL to use the default
@@ -1013,68 +1103,36 @@ gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
else
#endif
{
- const KeySym *map = get_keymap (keymap_x11);
- const KeySym *syms;
- gint shift_level;
- gboolean ignore_shift = FALSE;
- gboolean ignore_group = FALSE;
+ GdkModifierType bit;
- 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;
-
- syms = map + (hardware_keycode - keymap_x11->min_keycode) * keymap_x11->keysyms_per_keycode;
-
-#define SYM(k,g,l) syms[KEYSYM_INDEX (k,g,l)]
+ tmp_modifiers = 0;
- /* Drop group and shift if there are no keysymbols on
- * the specified key.
+ /* We see what modifiers matter by trying the translation with
+ * and without each possible modifier
*/
- if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, group, 0))
- {
- shift_level = 0;
- ignore_shift = TRUE;
- }
- if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, 0, shift_level))
+ for (bit = GDK_SHIFT_MASK; bit < GDK_BUTTON1_MASK; bit <<= 1)
{
- group = 0;
- ignore_group = TRUE;
+ /* Handling of the group here is a bit funky; a traditional
+ * X keyboard map can have more than two groups, but no way
+ * of accessing the extra groups is defined. We allow a
+ * caller to pass in any group to this function, but we
+ * only can represent switching between group 0 and 1 in
+ * consumed modifiers.
+ */
+ if (translate_keysym (keymap_x11, hardware_keycode,
+ (bit == keymap_x11->group_switch_mask) ? 0 : group,
+ state & ~bit,
+ NULL, NULL) !=
+ translate_keysym (keymap_x11, hardware_keycode,
+ (bit == keymap_x11->group_switch_mask) ? 1 : group,
+ state | bit,
+ NULL, NULL))
+ tmp_modifiers |= bit;
}
- if (!SYM (keymap_x11, group, shift_level) && SYM (keymap_x11, 0, 0))
- {
- shift_level = 0;
- group = 0;
- ignore_group = TRUE;
- ignore_shift = TRUE;
- }
-
- /* See whether the group and shift level actually mattered
- * to know what to put in consumed_modifiers
- */
- if (!SYM (keymap_x11, group, 1) ||
- SYM (keymap_x11, group, 0) == SYM (keymap_x11, group, 1))
- ignore_shift = TRUE;
-
- if (!SYM (keymap_x11, 1, shift_level) ||
- SYM (keymap_x11, 0, shift_level) == SYM (keymap_x11, 1, shift_level))
- ignore_group = TRUE;
-
- tmp_keyval = SYM (keymap_x11, group, shift_level);
-
- tmp_modifiers = ignore_group ? 0 : keymap_x11->group_switch_mask;
- tmp_modifiers |= ignore_shift ? 0 : (GDK_SHIFT_MASK | GDK_LOCK_MASK);
-
- if (effective_group)
- *effective_group = group;
-
- if (level)
- *level = shift_level;
-#undef SYM
+
+ tmp_keyval = translate_keysym (keymap_x11, hardware_keycode,
+ group, state,
+ level, effective_group);
}
if (consumed_modifiers)