mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-25 05:01:09 +00:00
Implement "fuzzy" key binding lookups; allow matches on key and level but
Wed Feb 20 14:26:47 2002 Owen Taylor <otaylor@redhat.com> * gtk/gtkkeyhash.[ch]: Implement "fuzzy" key binding lookups; allow matches on key and level but not group. Also, implement ignoring "consumed modifiers correctly." * gtk/gtkaccelgroup.c gtk/gtkbindings.c: Convert to using GtkKeyHash. * gtk/gtkdebug.h gtk/gtkmain.c: Support GTK_DEBUG=keybindings * gdk/x11/gdkevents-x11.c (gdk_event_translate): Fill in the group for key release events as well as key press events. * gdk/gdkkeys.h gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state): Rename unused_modifiers to consumed_modifiers, make the docs and non-Xkb implementation match the Xkb implementation. * gdk/linux-fb/gdkkeyboard-fb.c gdk/win32/gdkkeys-win32.c: Propagate doc and parameter name changes. * gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state): XkbTranslateKeyCode doesn't handle LockMask, we need to handle it ourselves. * gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state): Force <Shift>Tab to give GDK_ISO_Left_Tab, since we need consistency to allow dealing with ISO_Left_Tab. * gtk/gtkwindow.c gtk/gtktextview.c gtk/gtkscrolledwindow.c gtk/gtkpaned.c gtk/gtkcombo.c gtk/gtknotebook.c: Remove inappropriate uses of GDK_ISO_Left_Tab. (GDK_ISO_Left_Tab or <Shift>Tab both are equivalent as a binding specifier.) * gtk/gtkbutton.c (gtk_button_class_init): Make ::activate GTK_RUN_ACTION, so you can bind an accelerator to it. * gtk/gtklabel.c (gtk_label_set_uline_text_internal): Call gdk_unicode_to_keyval on the mnemonic character. * tests/testgtk.c: Add a test for the new fuzzy key binding matching.
This commit is contained in:
parent
3b94ae4be5
commit
708e1a9574
42
ChangeLog
42
ChangeLog
@ -1,3 +1,45 @@
|
||||
Wed Feb 20 14:26:47 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkkeyhash.[ch]: Implement "fuzzy" key binding lookups;
|
||||
allow matches on key and level but not group. Also, implement
|
||||
ignoring "consumed modifiers correctly."
|
||||
|
||||
* gtk/gtkaccelgroup.c gtk/gtkbindings.c: Convert to using
|
||||
GtkKeyHash.
|
||||
|
||||
* gtk/gtkdebug.h gtk/gtkmain.c: Support GTK_DEBUG=keybindings
|
||||
|
||||
* gdk/x11/gdkevents-x11.c (gdk_event_translate): Fill in
|
||||
the group for key release events as well as key press events.
|
||||
|
||||
* gdk/gdkkeys.h gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
Rename unused_modifiers to consumed_modifiers, make the docs and
|
||||
non-Xkb implementation match the Xkb implementation.
|
||||
|
||||
* gdk/linux-fb/gdkkeyboard-fb.c gdk/win32/gdkkeys-win32.c: Propagate
|
||||
doc and parameter name changes.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
XkbTranslateKeyCode doesn't handle LockMask, we need to handle
|
||||
it ourselves.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state): Force
|
||||
<Shift>Tab to give GDK_ISO_Left_Tab, since we need consistency
|
||||
to allow dealing with ISO_Left_Tab.
|
||||
|
||||
* gtk/gtkwindow.c gtk/gtktextview.c gtk/gtkscrolledwindow.c
|
||||
gtk/gtkpaned.c gtk/gtkcombo.c gtk/gtknotebook.c:
|
||||
Remove inappropriate uses of GDK_ISO_Left_Tab. (GDK_ISO_Left_Tab
|
||||
or <Shift>Tab both are equivalent as a binding specifier.)
|
||||
|
||||
* gtk/gtkbutton.c (gtk_button_class_init): Make ::activate
|
||||
GTK_RUN_ACTION, so you can bind an accelerator to it.
|
||||
|
||||
* gtk/gtklabel.c (gtk_label_set_uline_text_internal): Call
|
||||
gdk_unicode_to_keyval on the mnemonic character.
|
||||
|
||||
* tests/testgtk.c: Add a test for the new fuzzy key binding matching.
|
||||
|
||||
2002-02-21 jacob berkman <jacob@ximian.com>
|
||||
|
||||
* gtk/theme-bits/Makefile.am (EXTRA_DIST): inconsitent files are
|
||||
|
@ -1,3 +1,45 @@
|
||||
Wed Feb 20 14:26:47 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkkeyhash.[ch]: Implement "fuzzy" key binding lookups;
|
||||
allow matches on key and level but not group. Also, implement
|
||||
ignoring "consumed modifiers correctly."
|
||||
|
||||
* gtk/gtkaccelgroup.c gtk/gtkbindings.c: Convert to using
|
||||
GtkKeyHash.
|
||||
|
||||
* gtk/gtkdebug.h gtk/gtkmain.c: Support GTK_DEBUG=keybindings
|
||||
|
||||
* gdk/x11/gdkevents-x11.c (gdk_event_translate): Fill in
|
||||
the group for key release events as well as key press events.
|
||||
|
||||
* gdk/gdkkeys.h gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
Rename unused_modifiers to consumed_modifiers, make the docs and
|
||||
non-Xkb implementation match the Xkb implementation.
|
||||
|
||||
* gdk/linux-fb/gdkkeyboard-fb.c gdk/win32/gdkkeys-win32.c: Propagate
|
||||
doc and parameter name changes.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
XkbTranslateKeyCode doesn't handle LockMask, we need to handle
|
||||
it ourselves.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state): Force
|
||||
<Shift>Tab to give GDK_ISO_Left_Tab, since we need consistency
|
||||
to allow dealing with ISO_Left_Tab.
|
||||
|
||||
* gtk/gtkwindow.c gtk/gtktextview.c gtk/gtkscrolledwindow.c
|
||||
gtk/gtkpaned.c gtk/gtkcombo.c gtk/gtknotebook.c:
|
||||
Remove inappropriate uses of GDK_ISO_Left_Tab. (GDK_ISO_Left_Tab
|
||||
or <Shift>Tab both are equivalent as a binding specifier.)
|
||||
|
||||
* gtk/gtkbutton.c (gtk_button_class_init): Make ::activate
|
||||
GTK_RUN_ACTION, so you can bind an accelerator to it.
|
||||
|
||||
* gtk/gtklabel.c (gtk_label_set_uline_text_internal): Call
|
||||
gdk_unicode_to_keyval on the mnemonic character.
|
||||
|
||||
* tests/testgtk.c: Add a test for the new fuzzy key binding matching.
|
||||
|
||||
2002-02-21 jacob berkman <jacob@ximian.com>
|
||||
|
||||
* gtk/theme-bits/Makefile.am (EXTRA_DIST): inconsitent files are
|
||||
|
@ -1,3 +1,45 @@
|
||||
Wed Feb 20 14:26:47 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkkeyhash.[ch]: Implement "fuzzy" key binding lookups;
|
||||
allow matches on key and level but not group. Also, implement
|
||||
ignoring "consumed modifiers correctly."
|
||||
|
||||
* gtk/gtkaccelgroup.c gtk/gtkbindings.c: Convert to using
|
||||
GtkKeyHash.
|
||||
|
||||
* gtk/gtkdebug.h gtk/gtkmain.c: Support GTK_DEBUG=keybindings
|
||||
|
||||
* gdk/x11/gdkevents-x11.c (gdk_event_translate): Fill in
|
||||
the group for key release events as well as key press events.
|
||||
|
||||
* gdk/gdkkeys.h gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
Rename unused_modifiers to consumed_modifiers, make the docs and
|
||||
non-Xkb implementation match the Xkb implementation.
|
||||
|
||||
* gdk/linux-fb/gdkkeyboard-fb.c gdk/win32/gdkkeys-win32.c: Propagate
|
||||
doc and parameter name changes.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
XkbTranslateKeyCode doesn't handle LockMask, we need to handle
|
||||
it ourselves.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state): Force
|
||||
<Shift>Tab to give GDK_ISO_Left_Tab, since we need consistency
|
||||
to allow dealing with ISO_Left_Tab.
|
||||
|
||||
* gtk/gtkwindow.c gtk/gtktextview.c gtk/gtkscrolledwindow.c
|
||||
gtk/gtkpaned.c gtk/gtkcombo.c gtk/gtknotebook.c:
|
||||
Remove inappropriate uses of GDK_ISO_Left_Tab. (GDK_ISO_Left_Tab
|
||||
or <Shift>Tab both are equivalent as a binding specifier.)
|
||||
|
||||
* gtk/gtkbutton.c (gtk_button_class_init): Make ::activate
|
||||
GTK_RUN_ACTION, so you can bind an accelerator to it.
|
||||
|
||||
* gtk/gtklabel.c (gtk_label_set_uline_text_internal): Call
|
||||
gdk_unicode_to_keyval on the mnemonic character.
|
||||
|
||||
* tests/testgtk.c: Add a test for the new fuzzy key binding matching.
|
||||
|
||||
2002-02-21 jacob berkman <jacob@ximian.com>
|
||||
|
||||
* gtk/theme-bits/Makefile.am (EXTRA_DIST): inconsitent files are
|
||||
|
@ -1,3 +1,45 @@
|
||||
Wed Feb 20 14:26:47 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkkeyhash.[ch]: Implement "fuzzy" key binding lookups;
|
||||
allow matches on key and level but not group. Also, implement
|
||||
ignoring "consumed modifiers correctly."
|
||||
|
||||
* gtk/gtkaccelgroup.c gtk/gtkbindings.c: Convert to using
|
||||
GtkKeyHash.
|
||||
|
||||
* gtk/gtkdebug.h gtk/gtkmain.c: Support GTK_DEBUG=keybindings
|
||||
|
||||
* gdk/x11/gdkevents-x11.c (gdk_event_translate): Fill in
|
||||
the group for key release events as well as key press events.
|
||||
|
||||
* gdk/gdkkeys.h gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
Rename unused_modifiers to consumed_modifiers, make the docs and
|
||||
non-Xkb implementation match the Xkb implementation.
|
||||
|
||||
* gdk/linux-fb/gdkkeyboard-fb.c gdk/win32/gdkkeys-win32.c: Propagate
|
||||
doc and parameter name changes.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
XkbTranslateKeyCode doesn't handle LockMask, we need to handle
|
||||
it ourselves.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state): Force
|
||||
<Shift>Tab to give GDK_ISO_Left_Tab, since we need consistency
|
||||
to allow dealing with ISO_Left_Tab.
|
||||
|
||||
* gtk/gtkwindow.c gtk/gtktextview.c gtk/gtkscrolledwindow.c
|
||||
gtk/gtkpaned.c gtk/gtkcombo.c gtk/gtknotebook.c:
|
||||
Remove inappropriate uses of GDK_ISO_Left_Tab. (GDK_ISO_Left_Tab
|
||||
or <Shift>Tab both are equivalent as a binding specifier.)
|
||||
|
||||
* gtk/gtkbutton.c (gtk_button_class_init): Make ::activate
|
||||
GTK_RUN_ACTION, so you can bind an accelerator to it.
|
||||
|
||||
* gtk/gtklabel.c (gtk_label_set_uline_text_internal): Call
|
||||
gdk_unicode_to_keyval on the mnemonic character.
|
||||
|
||||
* tests/testgtk.c: Add a test for the new fuzzy key binding matching.
|
||||
|
||||
2002-02-21 jacob berkman <jacob@ximian.com>
|
||||
|
||||
* gtk/theme-bits/Makefile.am (EXTRA_DIST): inconsitent files are
|
||||
|
@ -1,3 +1,45 @@
|
||||
Wed Feb 20 14:26:47 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkkeyhash.[ch]: Implement "fuzzy" key binding lookups;
|
||||
allow matches on key and level but not group. Also, implement
|
||||
ignoring "consumed modifiers correctly."
|
||||
|
||||
* gtk/gtkaccelgroup.c gtk/gtkbindings.c: Convert to using
|
||||
GtkKeyHash.
|
||||
|
||||
* gtk/gtkdebug.h gtk/gtkmain.c: Support GTK_DEBUG=keybindings
|
||||
|
||||
* gdk/x11/gdkevents-x11.c (gdk_event_translate): Fill in
|
||||
the group for key release events as well as key press events.
|
||||
|
||||
* gdk/gdkkeys.h gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
Rename unused_modifiers to consumed_modifiers, make the docs and
|
||||
non-Xkb implementation match the Xkb implementation.
|
||||
|
||||
* gdk/linux-fb/gdkkeyboard-fb.c gdk/win32/gdkkeys-win32.c: Propagate
|
||||
doc and parameter name changes.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
XkbTranslateKeyCode doesn't handle LockMask, we need to handle
|
||||
it ourselves.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state): Force
|
||||
<Shift>Tab to give GDK_ISO_Left_Tab, since we need consistency
|
||||
to allow dealing with ISO_Left_Tab.
|
||||
|
||||
* gtk/gtkwindow.c gtk/gtktextview.c gtk/gtkscrolledwindow.c
|
||||
gtk/gtkpaned.c gtk/gtkcombo.c gtk/gtknotebook.c:
|
||||
Remove inappropriate uses of GDK_ISO_Left_Tab. (GDK_ISO_Left_Tab
|
||||
or <Shift>Tab both are equivalent as a binding specifier.)
|
||||
|
||||
* gtk/gtkbutton.c (gtk_button_class_init): Make ::activate
|
||||
GTK_RUN_ACTION, so you can bind an accelerator to it.
|
||||
|
||||
* gtk/gtklabel.c (gtk_label_set_uline_text_internal): Call
|
||||
gdk_unicode_to_keyval on the mnemonic character.
|
||||
|
||||
* tests/testgtk.c: Add a test for the new fuzzy key binding matching.
|
||||
|
||||
2002-02-21 jacob berkman <jacob@ximian.com>
|
||||
|
||||
* gtk/theme-bits/Makefile.am (EXTRA_DIST): inconsitent files are
|
||||
|
@ -1,3 +1,45 @@
|
||||
Wed Feb 20 14:26:47 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkkeyhash.[ch]: Implement "fuzzy" key binding lookups;
|
||||
allow matches on key and level but not group. Also, implement
|
||||
ignoring "consumed modifiers correctly."
|
||||
|
||||
* gtk/gtkaccelgroup.c gtk/gtkbindings.c: Convert to using
|
||||
GtkKeyHash.
|
||||
|
||||
* gtk/gtkdebug.h gtk/gtkmain.c: Support GTK_DEBUG=keybindings
|
||||
|
||||
* gdk/x11/gdkevents-x11.c (gdk_event_translate): Fill in
|
||||
the group for key release events as well as key press events.
|
||||
|
||||
* gdk/gdkkeys.h gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
Rename unused_modifiers to consumed_modifiers, make the docs and
|
||||
non-Xkb implementation match the Xkb implementation.
|
||||
|
||||
* gdk/linux-fb/gdkkeyboard-fb.c gdk/win32/gdkkeys-win32.c: Propagate
|
||||
doc and parameter name changes.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
XkbTranslateKeyCode doesn't handle LockMask, we need to handle
|
||||
it ourselves.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state): Force
|
||||
<Shift>Tab to give GDK_ISO_Left_Tab, since we need consistency
|
||||
to allow dealing with ISO_Left_Tab.
|
||||
|
||||
* gtk/gtkwindow.c gtk/gtktextview.c gtk/gtkscrolledwindow.c
|
||||
gtk/gtkpaned.c gtk/gtkcombo.c gtk/gtknotebook.c:
|
||||
Remove inappropriate uses of GDK_ISO_Left_Tab. (GDK_ISO_Left_Tab
|
||||
or <Shift>Tab both are equivalent as a binding specifier.)
|
||||
|
||||
* gtk/gtkbutton.c (gtk_button_class_init): Make ::activate
|
||||
GTK_RUN_ACTION, so you can bind an accelerator to it.
|
||||
|
||||
* gtk/gtklabel.c (gtk_label_set_uline_text_internal): Call
|
||||
gdk_unicode_to_keyval on the mnemonic character.
|
||||
|
||||
* tests/testgtk.c: Add a test for the new fuzzy key binding matching.
|
||||
|
||||
2002-02-21 jacob berkman <jacob@ximian.com>
|
||||
|
||||
* gtk/theme-bits/Makefile.am (EXTRA_DIST): inconsitent files are
|
||||
|
@ -1,3 +1,45 @@
|
||||
Wed Feb 20 14:26:47 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/gtkkeyhash.[ch]: Implement "fuzzy" key binding lookups;
|
||||
allow matches on key and level but not group. Also, implement
|
||||
ignoring "consumed modifiers correctly."
|
||||
|
||||
* gtk/gtkaccelgroup.c gtk/gtkbindings.c: Convert to using
|
||||
GtkKeyHash.
|
||||
|
||||
* gtk/gtkdebug.h gtk/gtkmain.c: Support GTK_DEBUG=keybindings
|
||||
|
||||
* gdk/x11/gdkevents-x11.c (gdk_event_translate): Fill in
|
||||
the group for key release events as well as key press events.
|
||||
|
||||
* gdk/gdkkeys.h gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
Rename unused_modifiers to consumed_modifiers, make the docs and
|
||||
non-Xkb implementation match the Xkb implementation.
|
||||
|
||||
* gdk/linux-fb/gdkkeyboard-fb.c gdk/win32/gdkkeys-win32.c: Propagate
|
||||
doc and parameter name changes.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state):
|
||||
XkbTranslateKeyCode doesn't handle LockMask, we need to handle
|
||||
it ourselves.
|
||||
|
||||
* gdk/x11/gdkkeys-x11.c (gdk_keymap_translate_keyboard_state): Force
|
||||
<Shift>Tab to give GDK_ISO_Left_Tab, since we need consistency
|
||||
to allow dealing with ISO_Left_Tab.
|
||||
|
||||
* gtk/gtkwindow.c gtk/gtktextview.c gtk/gtkscrolledwindow.c
|
||||
gtk/gtkpaned.c gtk/gtkcombo.c gtk/gtknotebook.c:
|
||||
Remove inappropriate uses of GDK_ISO_Left_Tab. (GDK_ISO_Left_Tab
|
||||
or <Shift>Tab both are equivalent as a binding specifier.)
|
||||
|
||||
* gtk/gtkbutton.c (gtk_button_class_init): Make ::activate
|
||||
GTK_RUN_ACTION, so you can bind an accelerator to it.
|
||||
|
||||
* gtk/gtklabel.c (gtk_label_set_uline_text_internal): Call
|
||||
gdk_unicode_to_keyval on the mnemonic character.
|
||||
|
||||
* tests/testgtk.c: Add a test for the new fuzzy key binding matching.
|
||||
|
||||
2002-02-21 jacob berkman <jacob@ximian.com>
|
||||
|
||||
* gtk/theme-bits/Makefile.am (EXTRA_DIST): inconsitent files are
|
||||
|
@ -1,3 +1,7 @@
|
||||
Thu Feb 21 12:11:42 2002 Owen Taylor <otaylor@redhat.com>
|
||||
|
||||
* gtk/Makefile.am (IGNORE_HFILES): Add gtkkeyhash.h
|
||||
|
||||
2002-02-20 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* gtk/gtk-sections.txt
|
||||
|
@ -139,8 +139,10 @@ be mapped to a keyval.
|
||||
@keyval:
|
||||
@effective_group:
|
||||
@level:
|
||||
@unused_modifiers:
|
||||
@consumed_modifiers:
|
||||
@Returns:
|
||||
<!-- # Unused Parameters # -->
|
||||
@unused_modifiers:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gdk_keymap_get_entries_for_keyval ##### -->
|
||||
|
@ -33,6 +33,7 @@ IGNORE_HFILES= \
|
||||
gtkhsv.h \
|
||||
gtkimmodule.h \
|
||||
gtkintl.h \
|
||||
gtkkeyhash.h \
|
||||
gtkmarshal.h \
|
||||
gtkprivate.h \
|
||||
gtktreeprivate.h \
|
||||
|
@ -88,7 +88,7 @@ gboolean gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
|
||||
guint *keyval,
|
||||
gint *effective_group,
|
||||
gint *level,
|
||||
GdkModifierType *unused_modifiers);
|
||||
GdkModifierType *consumed_modifiers);
|
||||
gboolean gdk_keymap_get_entries_for_keyval (GdkKeymap *keymap,
|
||||
guint keyval,
|
||||
GdkKeymapKey **keys,
|
||||
|
@ -61,7 +61,7 @@ struct _GdkFBKeyboardDevice {
|
||||
guint *keyval,
|
||||
gint *effective_group,
|
||||
gint *level,
|
||||
GdkModifierType *unused_modifiers);
|
||||
GdkModifierType *consumed_modifiers);
|
||||
gboolean (*get_entries_for_keyval) (GdkFBKeyboard *kb,
|
||||
guint keyval,
|
||||
GdkKeymapKey **keys,
|
||||
@ -89,7 +89,7 @@ static gboolean xlate_translate (GdkFBKeyboard *kb,
|
||||
guint *keyval,
|
||||
gint *effective_group,
|
||||
gint *level,
|
||||
GdkModifierType *unused_modifiers);
|
||||
GdkModifierType *consumed_modifiers);
|
||||
static gboolean xlate_get_for_keyval (GdkFBKeyboard *kb,
|
||||
guint keyval,
|
||||
GdkKeymapKey **keys,
|
||||
@ -111,7 +111,7 @@ static gboolean raw_translate (GdkFBKeyboard *kb,
|
||||
guint *keyval,
|
||||
gint *effective_group,
|
||||
gint *level,
|
||||
GdkModifierType *unused_modifiers);
|
||||
GdkModifierType *consumed_modifiers);
|
||||
static gboolean raw_get_for_keyval (GdkFBKeyboard *kb,
|
||||
guint keyval,
|
||||
GdkKeymapKey **keys,
|
||||
@ -335,13 +335,13 @@ gdk_keymap_lookup_key (GdkKeymap *keymap,
|
||||
* @keyval: return location for keyval
|
||||
* @effective_group: return location for effective group
|
||||
* @level: return location for level
|
||||
* @unused_modifiers: return location for modifiers that didn't affect the group or level
|
||||
* @consumed_modifiers: return location for modifiers that were used to determine the group or level
|
||||
*
|
||||
*
|
||||
* Translates the contents of a #GdkEventKey into a keyval, effective
|
||||
* group, and level. Modifiers that didn't affect the translation and
|
||||
* are thus available for application use are returned in
|
||||
* @unused_modifiers. See gdk_keyval_get_keys() for an explanation of
|
||||
* group, and level. Modifiers that affected the translation and
|
||||
* are thus unavailable for application use are returned in
|
||||
* @consumed_modifiers. See gdk_keyval_get_keys() for an explanation of
|
||||
* groups and levels. The @effective_group is the group that was
|
||||
* actually used for the translation; some keys such as Enter are not
|
||||
* affected by the active keyboard group. The @level is derived from
|
||||
@ -358,7 +358,7 @@ gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
|
||||
guint *keyval,
|
||||
gint *effective_group,
|
||||
gint *level,
|
||||
GdkModifierType *unused_modifiers)
|
||||
GdkModifierType *consumed_modifiers)
|
||||
{
|
||||
g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
|
||||
g_return_val_if_fail (group < 4, FALSE);
|
||||
@ -370,7 +370,7 @@ gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
|
||||
keyval,
|
||||
effective_group,
|
||||
level,
|
||||
unused_modifiers);
|
||||
consumed_modifiers);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -934,7 +934,7 @@ xlate_translate (GdkFBKeyboard *kb,
|
||||
guint *keyval,
|
||||
gint *effective_group,
|
||||
gint *level,
|
||||
GdkModifierType *unused_modifiers)
|
||||
GdkModifierType *consumed_modifiers)
|
||||
{
|
||||
g_warning ("xlate_translate() NIY");
|
||||
return FALSE;
|
||||
@ -1445,7 +1445,7 @@ raw_translate (GdkFBKeyboard *kb,
|
||||
guint *keyval,
|
||||
gint *effective_group,
|
||||
gint *level,
|
||||
GdkModifierType *unused_modifiers)
|
||||
GdkModifierType *consumed_modifiers)
|
||||
{
|
||||
g_warning ("raw_translate() NIY");
|
||||
return FALSE;
|
||||
|
@ -261,13 +261,13 @@ gdk_keymap_lookup_key (GdkKeymap *keymap,
|
||||
* @keyval: return location for keyval
|
||||
* @effective_group: return location for effective group
|
||||
* @level: return location for level
|
||||
* @unused_modifiers: return location for modifiers that didn't affect the group or level
|
||||
* @consumed_modifiers: return location for modifiers that were used to determine the group or level
|
||||
*
|
||||
*
|
||||
* Translates the contents of a #GdkEventKey into a keyval, effective
|
||||
* group, and level. Modifiers that didn't affect the translation and
|
||||
* are thus available for application use are returned in
|
||||
* @unused_modifiers. See gdk_keyval_get_keys() for an explanation of
|
||||
* group, and level. Modifiers that affected the translation and
|
||||
* are thus unavailable for application use are returned in
|
||||
* @consumed_modifiers. See gdk_keyval_get_keys() for an explanation of
|
||||
* groups and levels. The @effective_group is the group that was
|
||||
* actually used for the translation; some keys such as Enter are not
|
||||
* affected by the active keyboard group. The @level is derived from
|
||||
@ -284,7 +284,7 @@ gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
|
||||
guint *keyval,
|
||||
gint *effective_group,
|
||||
gint *level,
|
||||
GdkModifierType *unused_modifiers)
|
||||
GdkModifierType *consumed_modifiers)
|
||||
{
|
||||
g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
|
||||
g_return_val_if_fail (group < 4, FALSE);
|
||||
|
@ -679,6 +679,8 @@ gdk_event_translate (GdkEvent *event,
|
||||
event->key.length = 0;
|
||||
event->key.string = NULL;
|
||||
|
||||
event->key.group = (xevent->xkey.state & KEYBOARD_GROUP_MASK) >> KEYBOARD_GROUP_SHIFT;
|
||||
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
|
@ -735,13 +735,13 @@ MyEnhancedXkbTranslateKeyCode(register XkbDescPtr xkb,
|
||||
* @keyval: return location for keyval
|
||||
* @effective_group: return location for effective group
|
||||
* @level: return location for level
|
||||
* @unused_modifiers: return location for modifiers that didn't affect the group or level
|
||||
* @consumed_modifiers: return location for modifiers that were used to determine the group or level
|
||||
*
|
||||
*
|
||||
* Translates the contents of a #GdkEventKey into a keyval, effective
|
||||
* group, and level. Modifiers that didn't affect the translation and
|
||||
* are thus available for application use are returned in
|
||||
* @unused_modifiers. See gdk_keyval_get_keys() for an explanation of
|
||||
* group, and level. Modifiers that affected the translation and
|
||||
* are thus unavailable for application use are returned in
|
||||
* @consumed_modifiers. See gdk_keyval_get_keys() for an explanation of
|
||||
* groups and levels. The @effective_group is the group that was
|
||||
* actually used for the translation; some keys such as Enter are not
|
||||
* affected by the active keyboard group. The @level is derived from
|
||||
@ -758,9 +758,10 @@ gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
|
||||
guint *keyval,
|
||||
gint *effective_group,
|
||||
gint *level,
|
||||
GdkModifierType *unused_modifiers)
|
||||
GdkModifierType *consumed_modifiers)
|
||||
{
|
||||
KeySym tmp_keyval = NoSymbol;
|
||||
guint tmp_modifiers;
|
||||
|
||||
g_return_val_if_fail (keymap == NULL || GDK_IS_KEYMAP (keymap), FALSE);
|
||||
g_return_val_if_fail (group < 4, FALSE);
|
||||
@ -771,8 +772,8 @@ gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
|
||||
*effective_group = 0;
|
||||
if (level)
|
||||
*level = 0;
|
||||
if (unused_modifiers)
|
||||
*unused_modifiers = state;
|
||||
if (consumed_modifiers)
|
||||
*consumed_modifiers = 0;
|
||||
|
||||
update_keyrange ();
|
||||
|
||||
@ -792,13 +793,18 @@ gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
|
||||
MyEnhancedXkbTranslateKeyCode (xkb,
|
||||
hardware_keycode,
|
||||
state,
|
||||
unused_modifiers,
|
||||
&tmp_modifiers,
|
||||
&tmp_keyval,
|
||||
effective_group,
|
||||
level);
|
||||
|
||||
if (keyval)
|
||||
*keyval = tmp_keyval;
|
||||
if (state & ~tmp_modifiers & LockMask)
|
||||
tmp_keyval = gdk_keyval_to_upper (tmp_keyval);
|
||||
|
||||
/* We need to augment the consumed modifiers with LockMask, since
|
||||
* we handle that ourselves, and also with the group bits
|
||||
*/
|
||||
tmp_modifiers |= LockMask | 1 << 13 | 1 << 14;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -819,14 +825,7 @@ gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
|
||||
tmp_keyval = XKeycodeToKeysym (gdk_display, hardware_keycode,
|
||||
group * keysyms_per_keycode + shift_level);
|
||||
|
||||
if (keyval)
|
||||
*keyval = tmp_keyval;
|
||||
|
||||
if (unused_modifiers)
|
||||
{
|
||||
*unused_modifiers = state;
|
||||
*unused_modifiers &= ~(GDK_SHIFT_MASK | GDK_LOCK_MASK | group_switch_mask);
|
||||
}
|
||||
tmp_modifiers = GDK_SHIFT_MASK | GDK_LOCK_MASK | group_switch_mask;
|
||||
|
||||
if (effective_group)
|
||||
*effective_group = (state & group_switch_mask) ? 1 : 0;
|
||||
@ -835,6 +834,23 @@ gdk_keymap_translate_keyboard_state (GdkKeymap *keymap,
|
||||
*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 && (tmp_modifiers & GDK_SHIFT_MASK == 0))
|
||||
{
|
||||
tmp_keyval = GDK_ISO_Left_Tab;
|
||||
tmp_modifiers |= GDK_SHIFT_MASK;
|
||||
}
|
||||
|
||||
if (consumed_modifiers)
|
||||
*consumed_modifiers = tmp_modifiers;
|
||||
|
||||
if (keyval)
|
||||
*keyval = tmp_keyval;
|
||||
|
||||
return tmp_keyval != NoSymbol;
|
||||
}
|
||||
|
||||
|
@ -308,6 +308,8 @@ gtk_c_sources = @STRIP_BEGIN@ \
|
||||
gtkinvisible.c \
|
||||
gtkitem.c \
|
||||
gtkitemfactory.c \
|
||||
gtkkeyhash.c \
|
||||
gtkkeyhash.h \
|
||||
gtklabel.c \
|
||||
gtklayout.c \
|
||||
gtklist.c \
|
||||
|
@ -714,7 +714,7 @@ gtk_accel_group_from_accel_closure (GClosure *closure)
|
||||
|
||||
g_return_val_if_fail (closure != NULL, NULL);
|
||||
|
||||
/* a few remarks on wat we do here. in general, we need a way to reverse lookup
|
||||
/* a few remarks on what we do here. in general, we need a way to reverse lookup
|
||||
* accel_groups from closures that are being used in accel groups. this could
|
||||
* be done e.g via a hashtable. it is however cheaper (memory wise) to just
|
||||
* use the invalidation notifier on the closure itself (which we need to install
|
||||
|
@ -29,7 +29,9 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <gdkkeysyms.h>
|
||||
#include "gtkbindings.h"
|
||||
#include "gtkkeyhash.h"
|
||||
#include "gtksignal.h"
|
||||
#include "gtkwidget.h"
|
||||
#include "gtkrc.h"
|
||||
@ -49,6 +51,7 @@ typedef struct {
|
||||
|
||||
/* --- variables --- */
|
||||
static GHashTable *binding_entry_hash_table = NULL;
|
||||
static GSList *binding_key_hashes = NULL;
|
||||
static GSList *binding_set_list = NULL;
|
||||
static const gchar *key_class_binding_set = "gtk-class-binding-set";
|
||||
static GQuark key_id_class_binding_set = 0;
|
||||
@ -107,11 +110,81 @@ binding_entries_compare (gconstpointer a,
|
||||
return (ea->keyval == eb->keyval && ea->modifiers == eb->modifiers);
|
||||
}
|
||||
|
||||
static void
|
||||
binding_key_hash_insert_entry (GtkKeyHash *key_hash,
|
||||
GtkBindingEntry *entry)
|
||||
{
|
||||
guint keyval = entry->keyval;
|
||||
|
||||
/* We store lowercased accelerators. To deal with this, if <Shift>
|
||||
* was specified, uppercase.
|
||||
*/
|
||||
if (entry->modifiers & GDK_SHIFT_MASK)
|
||||
{
|
||||
if (keyval == GDK_Tab)
|
||||
keyval = GDK_ISO_Left_Tab;
|
||||
else
|
||||
keyval = gdk_keyval_to_upper (keyval);
|
||||
}
|
||||
|
||||
_gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers & ~GDK_RELEASE_MASK, entry);
|
||||
}
|
||||
|
||||
static void
|
||||
binding_key_hash_destroy (gpointer data)
|
||||
{
|
||||
GtkKeyHash *key_hash = data;
|
||||
|
||||
binding_key_hashes = g_slist_remove (binding_key_hashes, key_hash);
|
||||
_gtk_key_hash_free (key_hash);
|
||||
}
|
||||
|
||||
static void
|
||||
insert_entries_into_key_hash (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
GtkKeyHash *key_hash = data;
|
||||
GtkBindingEntry *entry = value;
|
||||
|
||||
for (; entry; entry = entry->hash_next)
|
||||
binding_key_hash_insert_entry (key_hash, entry);
|
||||
}
|
||||
|
||||
static GtkKeyHash *
|
||||
binding_key_hash_for_keymap (GdkKeymap *keymap)
|
||||
{
|
||||
static GQuark key_hash_quark = 0;
|
||||
GtkKeyHash *key_hash;
|
||||
|
||||
if (!key_hash_quark)
|
||||
key_hash_quark = g_quark_from_static_string ("gtk-binding-key-hash");
|
||||
|
||||
key_hash = g_object_get_qdata (G_OBJECT (keymap), key_hash_quark);
|
||||
|
||||
if (!key_hash)
|
||||
{
|
||||
key_hash = _gtk_key_hash_new (keymap, NULL);
|
||||
g_object_set_qdata_full (G_OBJECT (keymap), key_hash_quark, key_hash, binding_key_hash_destroy);
|
||||
|
||||
if (binding_entry_hash_table)
|
||||
g_hash_table_foreach (binding_entry_hash_table,
|
||||
insert_entries_into_key_hash,
|
||||
key_hash);
|
||||
|
||||
binding_key_hashes = g_slist_prepend (binding_key_hashes, key_hash);
|
||||
}
|
||||
|
||||
return key_hash;
|
||||
}
|
||||
|
||||
|
||||
static GtkBindingEntry*
|
||||
binding_entry_new (GtkBindingSet *binding_set,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers)
|
||||
{
|
||||
GSList *tmp_list;
|
||||
GtkBindingEntry *entry;
|
||||
|
||||
if (!binding_entry_hash_table)
|
||||
@ -132,6 +205,12 @@ binding_entry_new (GtkBindingSet *binding_set,
|
||||
if (entry->hash_next)
|
||||
g_hash_table_remove (binding_entry_hash_table, entry->hash_next);
|
||||
g_hash_table_insert (binding_entry_hash_table, entry, entry);
|
||||
|
||||
for (tmp_list = binding_key_hashes; tmp_list; tmp_list = tmp_list->next)
|
||||
{
|
||||
GtkKeyHash *key_hash = tmp_list->data;
|
||||
binding_key_hash_insert_entry (key_hash, entry);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
@ -167,6 +246,7 @@ binding_entry_destroy (GtkBindingEntry *entry)
|
||||
register GtkBindingEntry *tmp;
|
||||
GtkBindingEntry *begin;
|
||||
register GtkBindingEntry *last;
|
||||
GSList *tmp_list;
|
||||
|
||||
/* unlink from binding set
|
||||
*/
|
||||
@ -214,27 +294,18 @@ binding_entry_destroy (GtkBindingEntry *entry)
|
||||
g_hash_table_insert (binding_entry_hash_table, begin, begin);
|
||||
}
|
||||
|
||||
for (tmp_list = binding_key_hashes; tmp_list; tmp_list = tmp_list->next)
|
||||
{
|
||||
GtkKeyHash *key_hash = tmp_list->data;
|
||||
_gtk_key_hash_remove_entry (key_hash, entry);
|
||||
}
|
||||
|
||||
entry->destroyed = TRUE;
|
||||
|
||||
if (!entry->in_emission)
|
||||
binding_entry_free (entry);
|
||||
}
|
||||
|
||||
static GtkBindingEntry*
|
||||
binding_ht_lookup_list (guint keyval,
|
||||
GdkModifierType modifiers)
|
||||
{
|
||||
GtkBindingEntry lookup_entry = { 0 };
|
||||
|
||||
if (!binding_entry_hash_table)
|
||||
return NULL;
|
||||
|
||||
lookup_entry.keyval = keyval;
|
||||
lookup_entry.modifiers = modifiers;
|
||||
|
||||
return g_hash_table_lookup (binding_entry_hash_table, &lookup_entry);
|
||||
}
|
||||
|
||||
static GtkBindingEntry*
|
||||
binding_ht_lookup_entry (GtkBindingSet *set,
|
||||
guint keyval,
|
||||
@ -835,7 +906,7 @@ gtk_binding_set_add_path (GtkBindingSet *binding_set,
|
||||
}
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
static gboolean
|
||||
binding_match_activate (GSList *pspec_list,
|
||||
GtkObject *object,
|
||||
guint path_length,
|
||||
@ -877,20 +948,25 @@ gtk_binding_pattern_compare (gconstpointer new_pattern,
|
||||
return np->seq_id < ep->seq_id;
|
||||
}
|
||||
|
||||
static inline GSList*
|
||||
gtk_binding_entries_sort_patterns (GtkBindingEntry *entries,
|
||||
GtkPathType path_id)
|
||||
static GSList*
|
||||
gtk_binding_entries_sort_patterns (GSList *entries,
|
||||
GtkPathType path_id,
|
||||
gboolean is_release)
|
||||
{
|
||||
GSList *patterns;
|
||||
|
||||
patterns = NULL;
|
||||
while (entries)
|
||||
for (; entries; entries = entries->next)
|
||||
{
|
||||
register GtkBindingSet *binding_set;
|
||||
GtkBindingEntry *entry = entries->data;
|
||||
GtkBindingSet *binding_set;
|
||||
GSList *slist = NULL;
|
||||
|
||||
binding_set = entries->binding_set;
|
||||
binding_set->current = entries;
|
||||
if (is_release != ((entry->modifiers & GDK_RELEASE_MASK) != 0))
|
||||
continue;
|
||||
|
||||
binding_set = entry->binding_set;
|
||||
binding_set->current = entry;
|
||||
|
||||
switch (path_id)
|
||||
{
|
||||
@ -912,35 +988,19 @@ gtk_binding_entries_sort_patterns (GtkBindingEntry *entries,
|
||||
pspec = slist->data;
|
||||
patterns = g_slist_insert_sorted (patterns, pspec, gtk_binding_pattern_compare);
|
||||
}
|
||||
|
||||
entries = entries->hash_next;
|
||||
}
|
||||
|
||||
return patterns;
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
gtk_bindings_activate (GtkObject *object,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers)
|
||||
static gboolean
|
||||
gtk_bindings_activate_list (GtkObject *object,
|
||||
GSList *entries,
|
||||
gboolean is_release)
|
||||
{
|
||||
GtkBindingEntry *entries;
|
||||
GtkWidget *widget;
|
||||
GtkWidget *widget = GTK_WIDGET (object);
|
||||
gboolean handled = FALSE;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
|
||||
|
||||
if (!GTK_IS_WIDGET (object))
|
||||
return FALSE;
|
||||
|
||||
widget = GTK_WIDGET (object);
|
||||
|
||||
keyval = gdk_keyval_to_lower (keyval);
|
||||
modifiers = modifiers & BINDING_MOD_MASK ();
|
||||
|
||||
entries = binding_ht_lookup_list (keyval, modifiers);
|
||||
|
||||
if (!entries)
|
||||
return FALSE;
|
||||
|
||||
@ -951,7 +1011,7 @@ gtk_bindings_activate (GtkObject *object,
|
||||
GSList *patterns;
|
||||
|
||||
gtk_widget_path (widget, &path_length, &path, &path_reversed);
|
||||
patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET);
|
||||
patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET, is_release);
|
||||
handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
|
||||
g_slist_free (patterns);
|
||||
g_free (path);
|
||||
@ -965,7 +1025,7 @@ gtk_bindings_activate (GtkObject *object,
|
||||
GSList *patterns;
|
||||
|
||||
gtk_widget_class_path (widget, &path_length, &path, &path_reversed);
|
||||
patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET_CLASS);
|
||||
patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_WIDGET_CLASS, is_release);
|
||||
handled = binding_match_activate (patterns, object, path_length, path, path_reversed);
|
||||
g_slist_free (patterns);
|
||||
g_free (path);
|
||||
@ -977,7 +1037,7 @@ gtk_bindings_activate (GtkObject *object,
|
||||
GSList *patterns;
|
||||
GtkType class_type;
|
||||
|
||||
patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_CLASS);
|
||||
patterns = gtk_binding_entries_sort_patterns (entries, GTK_PATH_CLASS, is_release);
|
||||
class_type = GTK_OBJECT_TYPE (object);
|
||||
while (class_type && !handled)
|
||||
{
|
||||
@ -1000,6 +1060,71 @@ gtk_bindings_activate (GtkObject *object,
|
||||
return handled;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gtk_bindings_activate (GtkObject *object,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers)
|
||||
{
|
||||
GSList *entries = NULL;
|
||||
GtkKeyHash *key_hash;
|
||||
gboolean handled = FALSE;
|
||||
gboolean is_release;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
|
||||
|
||||
if (!GTK_IS_WIDGET (object))
|
||||
return FALSE;
|
||||
|
||||
is_release = (BINDING_MOD_MASK () & GDK_RELEASE_MASK) != 0;
|
||||
modifiers = modifiers & BINDING_MOD_MASK () & ~GDK_RELEASE_MASK;
|
||||
|
||||
key_hash = binding_key_hash_for_keymap (gdk_keymap_get_default ());
|
||||
entries = _gtk_key_hash_lookup_keyval (key_hash, keyval, modifiers);
|
||||
|
||||
handled = gtk_bindings_activate_list (object, entries, is_release);
|
||||
|
||||
g_slist_free (entries);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_bindings_activate_event:
|
||||
* @object: a #GtkObject (generally must be a widget)
|
||||
* @event: a #GdkEventKey
|
||||
*
|
||||
* Looks up key bindings for @object to find one matching
|
||||
* @event, and if one was found, activate it.
|
||||
*
|
||||
* Return value: %TRUE if a matching key binding was found
|
||||
**/
|
||||
gboolean
|
||||
_gtk_bindings_activate_event (GtkObject *object,
|
||||
GdkEventKey *event)
|
||||
{
|
||||
GSList *entries = NULL;
|
||||
GtkKeyHash *key_hash;
|
||||
gboolean handled = FALSE;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_OBJECT (object), FALSE);
|
||||
|
||||
if (!GTK_IS_WIDGET (object))
|
||||
return FALSE;
|
||||
|
||||
key_hash = binding_key_hash_for_keymap (gdk_keymap_get_default ());
|
||||
entries = _gtk_key_hash_lookup (key_hash,
|
||||
event->hardware_keycode,
|
||||
event->state & BINDING_MOD_MASK () & ~GDK_RELEASE_MASK,
|
||||
event->group);
|
||||
|
||||
handled = gtk_bindings_activate_list (object, entries,
|
||||
event->type == GDK_KEY_RELEASE);
|
||||
|
||||
g_slist_free (entries);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_binding_parse_signal (GScanner *scanner,
|
||||
GtkBindingSet *binding_set,
|
||||
|
@ -136,7 +136,9 @@ void gtk_binding_entry_add_signall (GtkBindingSet *binding_set,
|
||||
guint gtk_binding_parse_binding (GScanner *scanner);
|
||||
|
||||
|
||||
void _gtk_binding_reset_parsed (void);
|
||||
gboolean _gtk_bindings_activate_event (GtkObject *object,
|
||||
GdkEventKey *event);
|
||||
void _gtk_binding_reset_parsed (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -253,7 +253,7 @@ gtk_button_class_init (GtkButtonClass *klass)
|
||||
GTK_TYPE_NONE, 0);
|
||||
button_signals[ACTIVATE] =
|
||||
gtk_signal_new ("activate",
|
||||
GTK_RUN_FIRST,
|
||||
GTK_RUN_FIRST | GTK_RUN_ACTION,
|
||||
GTK_CLASS_TYPE (object_class),
|
||||
GTK_SIGNAL_OFFSET (GtkButtonClass, activate),
|
||||
_gtk_marshal_VOID__VOID,
|
||||
|
@ -199,7 +199,6 @@ gtk_combo_entry_key_press (GtkEntry * entry, GdkEventKey * event, GtkCombo * com
|
||||
|
||||
/* completion */
|
||||
if ((event->keyval == GDK_Tab ||
|
||||
event->keyval == GDK_ISO_Left_Tab ||
|
||||
event->keyval == GDK_KP_Tab) &&
|
||||
(event->state & GDK_MOD1_MASK))
|
||||
{
|
||||
|
@ -27,16 +27,17 @@
|
||||
#ifndef __GTK_DEBUG_H__
|
||||
#define __GTK_DEBUG_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef enum {
|
||||
GTK_DEBUG_MISC = 1 << 0,
|
||||
GTK_DEBUG_PLUGSOCKET = 1 << 1,
|
||||
GTK_DEBUG_TEXT = 1 << 2,
|
||||
GTK_DEBUG_TREE = 1 << 3,
|
||||
GTK_DEBUG_UPDATES = 1 << 4
|
||||
GTK_DEBUG_MISC = 1 << 0,
|
||||
GTK_DEBUG_PLUGSOCKET = 1 << 1,
|
||||
GTK_DEBUG_TEXT = 1 << 2,
|
||||
GTK_DEBUG_TREE = 1 << 3,
|
||||
GTK_DEBUG_UPDATES = 1 << 4,
|
||||
GTK_DEBUG_KEYBINDINGS = 1 << 5
|
||||
} GtkDebugFlag;
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
@ -63,9 +64,6 @@ typedef enum {
|
||||
|
||||
GTKVAR guint gtk_debug_flags;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_DEBUG_H__ */
|
||||
|
379
gtk/gtkkeyhash.c
Normal file
379
gtk/gtkkeyhash.c
Normal file
@ -0,0 +1,379 @@
|
||||
/* gtkkeyhash.c: Keymap aware matching of key bindings
|
||||
*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2002, Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include "gtkdebug.h"
|
||||
#include "gtkkeyhash.h"
|
||||
|
||||
/* We need to add a ::changed signal to GdkKeyMap to properly deal
|
||||
* with changes to the key map while we are running.
|
||||
*/
|
||||
#undef HAVE_CHANGED_SIGNAL
|
||||
|
||||
typedef struct _GtkKeyHashEntry GtkKeyHashEntry;
|
||||
|
||||
struct _GtkKeyHashEntry
|
||||
{
|
||||
guint keyval;
|
||||
GdkModifierType modifiers;
|
||||
GdkKeymapKey *keys;
|
||||
gint n_keys;
|
||||
gpointer value;
|
||||
};
|
||||
|
||||
struct _GtkKeyHash
|
||||
{
|
||||
GdkKeymap *keymap;
|
||||
GHashTable *keycode_hash;
|
||||
GHashTable *reverse_hash;
|
||||
GDestroyNotify destroy_notify;
|
||||
};
|
||||
|
||||
static void
|
||||
key_hash_clear_keycode (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
GSList *keys = value;
|
||||
g_slist_free (keys);
|
||||
}
|
||||
|
||||
static void
|
||||
key_hash_insert_entry (GtkKeyHash *key_hash,
|
||||
GtkKeyHashEntry *entry)
|
||||
{
|
||||
gint i;
|
||||
|
||||
gdk_keymap_get_entries_for_keyval (key_hash->keymap,
|
||||
entry->keyval,
|
||||
&entry->keys, &entry->n_keys);
|
||||
|
||||
for (i = 0; i < entry->n_keys; i++)
|
||||
{
|
||||
GSList *old_keys = g_hash_table_lookup (key_hash->keycode_hash,
|
||||
GUINT_TO_POINTER (entry->keys[i].keycode));
|
||||
old_keys = g_slist_prepend (old_keys, entry);
|
||||
g_hash_table_insert (key_hash->keycode_hash,
|
||||
GUINT_TO_POINTER (entry->keys[i].keycode),
|
||||
old_keys);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_CHANGED_SIGNAL
|
||||
static void
|
||||
key_hash_reinsert_entry (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
GtkKeyHashEntry *entry = value;
|
||||
GtkKeyHash *key_hash = data;
|
||||
|
||||
g_free (entry->keys);
|
||||
key_hash_insert_entry (key_hash, entry);
|
||||
}
|
||||
|
||||
static void
|
||||
key_hash_keymap_changed (GdkKeymap *keymap,
|
||||
GtkKeyHash *key_hash)
|
||||
{
|
||||
/* The keymap changed, so we have to clear and reinsert all our entries
|
||||
*/
|
||||
g_hash_table_foreach (key_hash->keycode_hash, key_hash_clear_keycode, NULL);
|
||||
|
||||
/* FIXME: Here we reinsert in random order, but I think we actually have to
|
||||
* insert in the same order as the original order to keep GtkBindingSet happy.
|
||||
*/
|
||||
g_hash_table_foreach (key_hash->reverse_hash, key_hash_reinsert_entry, key_hash);
|
||||
}
|
||||
#endif /* HAVE_CHANGED_SIGNAL */
|
||||
|
||||
/**
|
||||
* _gtk_key_hash_new:
|
||||
* @keymap: a #GdkKeymap
|
||||
* @item_destroy_notify: function to be called when items are removed
|
||||
* from the hash or %NULL.
|
||||
*
|
||||
* Create a new key hash object for doing binding resolution.
|
||||
*
|
||||
* Return value: the newly created object. Free with _gtk_key_hash_free().
|
||||
**/
|
||||
GtkKeyHash *
|
||||
_gtk_key_hash_new (GdkKeymap *keymap,
|
||||
GDestroyNotify item_destroy_notify)
|
||||
{
|
||||
GtkKeyHash *key_hash = g_new (GtkKeyHash, 1);
|
||||
|
||||
key_hash->keymap = keymap;
|
||||
#ifdef HAVE_CHANGED_SIGNAL
|
||||
g_signal_connect (keymap, "changed",
|
||||
G_CALLBACK (key_hash_keymap_changed), key_hash);
|
||||
#endif
|
||||
|
||||
key_hash->keycode_hash = g_hash_table_new (g_direct_hash, NULL);
|
||||
key_hash->reverse_hash = g_hash_table_new (g_direct_hash, NULL);
|
||||
key_hash->destroy_notify = item_destroy_notify;
|
||||
|
||||
return key_hash;
|
||||
}
|
||||
|
||||
static void
|
||||
key_hash_free_entry (GtkKeyHash *key_hash,
|
||||
GtkKeyHashEntry *entry)
|
||||
{
|
||||
if (key_hash->destroy_notify)
|
||||
(*key_hash->destroy_notify) (entry->value);
|
||||
|
||||
g_free (entry->keys);
|
||||
g_free (entry);
|
||||
}
|
||||
|
||||
static void
|
||||
key_hash_free_entry_foreach (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
GtkKeyHashEntry *entry = value;
|
||||
GtkKeyHash *key_hash = data;
|
||||
|
||||
key_hash_free_entry (key_hash, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_key_hash_free:
|
||||
* @key_hash: a #GtkKeyHash
|
||||
*
|
||||
* Destroys a key hash created with gtk_key_hash_new()
|
||||
**/
|
||||
void
|
||||
_gtk_key_hash_free (GtkKeyHash *key_hash)
|
||||
{
|
||||
#if HAVE_CHANGED_SIGNAL
|
||||
g_signal_handlers_disconnect_by_func (key_hash->keymap,
|
||||
G_CALLBACK (key_hash_keymap_changed), key_hash);
|
||||
#endif
|
||||
|
||||
g_hash_table_foreach (key_hash->keycode_hash, key_hash_clear_keycode, NULL);
|
||||
g_hash_table_foreach (key_hash->reverse_hash, key_hash_free_entry_foreach, key_hash);
|
||||
g_hash_table_destroy (key_hash->keycode_hash);
|
||||
g_hash_table_destroy (key_hash->reverse_hash);
|
||||
|
||||
g_free (key_hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_key_hash_add_entry:
|
||||
* @key_hash: a #GtkKeyHash
|
||||
* @keyval: key symbol for this binding
|
||||
* @modifiers: modifiers for this binding
|
||||
* @value: value to insert in the key hash
|
||||
*
|
||||
* Inserts a pair of key symbol and modifier mask into the key hash.
|
||||
**/
|
||||
void
|
||||
_gtk_key_hash_add_entry (GtkKeyHash *key_hash,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers,
|
||||
gpointer value)
|
||||
{
|
||||
GtkKeyHashEntry *entry = g_new (GtkKeyHashEntry, 1);
|
||||
|
||||
entry->value = value;
|
||||
entry->keyval = keyval;
|
||||
entry->modifiers = modifiers;
|
||||
|
||||
g_hash_table_insert (key_hash->reverse_hash, value, entry);
|
||||
key_hash_insert_entry (key_hash, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_key_hash_remove_entry:
|
||||
* @key_hash: a #GtkKeyHash
|
||||
* @value: value previously added with _gtk_key_hash_add_entry()
|
||||
*
|
||||
* Removes a value previously added to the key hash with
|
||||
* _gtk_key_hash_add_entry().
|
||||
**/
|
||||
void
|
||||
_gtk_key_hash_remove_entry (GtkKeyHash *key_hash,
|
||||
gpointer value)
|
||||
{
|
||||
GtkKeyHashEntry *entry = g_hash_table_lookup (key_hash->reverse_hash, value);
|
||||
if (entry)
|
||||
{
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < entry->n_keys; i++)
|
||||
{
|
||||
GSList *old_keys = g_hash_table_lookup (key_hash->keycode_hash,
|
||||
GUINT_TO_POINTER (entry->keys[i].keycode));
|
||||
|
||||
GSList *new_keys = g_slist_remove (old_keys, entry);
|
||||
if (old_keys != new_keys)
|
||||
{
|
||||
if (old_keys)
|
||||
g_hash_table_insert (key_hash->keycode_hash,
|
||||
GUINT_TO_POINTER (entry->keys[i].keycode),
|
||||
old_keys);
|
||||
else
|
||||
g_hash_table_remove (key_hash->keycode_hash,
|
||||
GUINT_TO_POINTER (entry->keys[i].keycode));
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_remove (key_hash->reverse_hash, value);
|
||||
|
||||
key_hash_free_entry (key_hash, entry);
|
||||
g_free (entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_key_hash_lookup:
|
||||
* @key_hash: a #GtkKeyHash
|
||||
* @hardware_keycode: hardware keycode field from a #GdkEventKey
|
||||
* @state: state field from a #GdkEventKey
|
||||
* @group: group field from a #GdkEventKey
|
||||
*
|
||||
* Looks up the best matching entry or entries in the hash table for
|
||||
* a given event.
|
||||
*
|
||||
* Return value: A #GSList of all matching entries. If there were exact
|
||||
* matches, they are returned, otherwise all fuzzy matches are
|
||||
* returned. (A fuzzy match is a match in keycode and level, but not
|
||||
* in group.)
|
||||
**/
|
||||
GSList *
|
||||
_gtk_key_hash_lookup (GtkKeyHash *key_hash,
|
||||
guint16 hardware_keycode,
|
||||
GdkModifierType state,
|
||||
gint group)
|
||||
{
|
||||
GSList *keys = g_hash_table_lookup (key_hash->keycode_hash, GUINT_TO_POINTER ((guint)hardware_keycode));
|
||||
GSList *results = NULL;
|
||||
gboolean have_exact = FALSE;
|
||||
guint keyval;
|
||||
gint effective_group;
|
||||
gint level;
|
||||
GdkModifierType consumed_modifiers;
|
||||
|
||||
gdk_keymap_translate_keyboard_state (key_hash->keymap,
|
||||
hardware_keycode, state, group,
|
||||
&keyval, &effective_group, &level, &consumed_modifiers);
|
||||
|
||||
GTK_NOTE (KEYBINDINGS,
|
||||
g_message ("Looking up keycode = %u, modifiers = 0x%04x,\n"
|
||||
" keyval = %u, group = %d, level = %d, consumed_modifiers = 0x%04x",
|
||||
hardware_keycode, state, keyval, effective_group, level, consumed_modifiers));
|
||||
|
||||
if (keys)
|
||||
{
|
||||
GSList *tmp_list = keys;
|
||||
while (tmp_list)
|
||||
{
|
||||
GtkKeyHashEntry *entry = tmp_list->data;
|
||||
|
||||
if ((entry->modifiers & ~consumed_modifiers) == (state & ~consumed_modifiers))
|
||||
{
|
||||
gint i;
|
||||
|
||||
if (keyval == entry->keyval) /* Exact match */
|
||||
{
|
||||
GTK_NOTE (KEYBINDINGS,
|
||||
g_message (" found exact match, keyval = %u, modifiers = 0x%04x",
|
||||
entry->keyval, entry->modifiers));
|
||||
|
||||
if (!have_exact)
|
||||
{
|
||||
g_slist_free (results);
|
||||
results = NULL;
|
||||
}
|
||||
|
||||
have_exact = TRUE;
|
||||
results = g_slist_prepend (results, entry->value);
|
||||
}
|
||||
|
||||
if (!have_exact)
|
||||
{
|
||||
for (i = 0; i < entry->n_keys; i++)
|
||||
{
|
||||
if (entry->keys[i].keycode == hardware_keycode &&
|
||||
entry->keys[i].level == level) /* Match for all but group */
|
||||
{
|
||||
GTK_NOTE (KEYBINDINGS,
|
||||
g_message (" found group = %d, level = %d",
|
||||
entry->keys[i].group, entry->keys[i].level));
|
||||
results = g_slist_prepend (results, entry->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tmp_list = tmp_list->next;
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_key_hash_lookup_keyval:
|
||||
* @key_hash: a #GtkKeyHash
|
||||
* @event: a #GtkEvent
|
||||
*
|
||||
* Looks up the best matching entry or entries in the hash table for a
|
||||
* given keyval/modifiers pair. It's better to use
|
||||
* _gtk_key_hash_lookup() if you have the original #GdkEventKey
|
||||
* available.
|
||||
*
|
||||
* Return value: A #GSList of all matching entries.
|
||||
**/
|
||||
GSList *
|
||||
_gtk_key_hash_lookup_keyval (GtkKeyHash *key_hash,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers)
|
||||
{
|
||||
GdkKeymapKey *keys;
|
||||
gint n_keys;
|
||||
GSList *results = NULL;
|
||||
|
||||
/* Find some random keycode for this keycode
|
||||
*/
|
||||
gdk_keymap_get_entries_for_keyval (key_hash->keymap, keyval,
|
||||
&keys, &n_keys);
|
||||
|
||||
if (n_keys)
|
||||
{
|
||||
GSList *entries = g_hash_table_lookup (key_hash->keycode_hash, GUINT_TO_POINTER (keys[0].keycode));
|
||||
|
||||
while (entries)
|
||||
{
|
||||
GtkKeyHashEntry *entry = entries->data;
|
||||
|
||||
if (entry->keyval == keyval && entry->modifiers == modifiers)
|
||||
results = g_slist_prepend (results, entry->value);
|
||||
|
||||
entries = entries->next;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (keys);
|
||||
|
||||
return results;
|
||||
}
|
50
gtk/gtkkeyhash.h
Normal file
50
gtk/gtkkeyhash.h
Normal file
@ -0,0 +1,50 @@
|
||||
/* gtkkeyhash.h: Keymap aware matching of key bindings
|
||||
*
|
||||
* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2002, Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_KEY_HASH_H__
|
||||
#define __GTK_KEY_HASH_H__
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkKeyHash GtkKeyHash;
|
||||
|
||||
GtkKeyHash *_gtk_key_hash_new (GdkKeymap *keymap,
|
||||
GDestroyNotify item_destroy_notify);
|
||||
void _gtk_key_hash_add_entry (GtkKeyHash *key_hash,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers,
|
||||
gpointer value);
|
||||
void _gtk_key_hash_remove_entry (GtkKeyHash *key_hash,
|
||||
gpointer value);
|
||||
GSList * _gtk_key_hash_lookup (GtkKeyHash *key_hash,
|
||||
guint16 hardware_keycode,
|
||||
GdkModifierType state,
|
||||
gint group);
|
||||
GSList * _gtk_key_hash_lookup_keyval (GtkKeyHash *key_hash,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers);
|
||||
void _gtk_key_hash_free (GtkKeyHash *key_hash);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_KEY_HASH_H__ */
|
@ -1827,7 +1827,7 @@ gtk_label_set_uline_text_internal (GtkLabel *label,
|
||||
{
|
||||
*pattern_dest++ = '_';
|
||||
if (accel_key == GDK_VoidSymbol)
|
||||
accel_key = gdk_keyval_to_lower (c);
|
||||
accel_key = gdk_keyval_to_lower (gdk_unicode_to_keyval (c));
|
||||
}
|
||||
|
||||
while (src < next_src)
|
||||
|
@ -155,7 +155,8 @@ static const GDebugKey gtk_debug_keys[] = {
|
||||
{"plugsocket", GTK_DEBUG_PLUGSOCKET},
|
||||
{"text", GTK_DEBUG_TEXT},
|
||||
{"tree", GTK_DEBUG_TREE},
|
||||
{"updates", GTK_DEBUG_UPDATES}
|
||||
{"updates", GTK_DEBUG_UPDATES},
|
||||
{"keybindings", GTK_DEBUG_KEYBINDINGS}
|
||||
};
|
||||
|
||||
static const guint gtk_ndebug_keys = sizeof (gtk_debug_keys) / sizeof (GDebugKey);
|
||||
|
@ -294,9 +294,6 @@ add_tab_bindings (GtkBindingSet *binding_set,
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
|
||||
"move_focus_out", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, direction);
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, modifiers,
|
||||
"move_focus_out", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, direction);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -145,9 +145,6 @@ add_tab_bindings (GtkBindingSet *binding_set,
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
|
||||
"cycle_handle_focus", 1,
|
||||
G_TYPE_BOOLEAN, reverse);
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, modifiers,
|
||||
"cycle_handle_focus", 1,
|
||||
G_TYPE_BOOLEAN, reverse);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -191,9 +191,6 @@ add_tab_bindings (GtkBindingSet *binding_set,
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
|
||||
"move_focus_out", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, direction);
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, modifiers,
|
||||
"move_focus_out", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, direction);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -933,9 +933,6 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, GDK_CONTROL_MASK,
|
||||
"move_focus", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, GDK_CONTROL_MASK,
|
||||
"move_focus", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_FORWARD);
|
||||
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
|
||||
"move_focus", 1,
|
||||
@ -943,9 +940,6 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
|
||||
"move_focus", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, GDK_SHIFT_MASK | GDK_CONTROL_MASK,
|
||||
"move_focus", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, GTK_DIR_TAB_BACKWARD);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3641,8 +3635,7 @@ gtk_text_view_key_press_event (GtkWidget *widget, GdkEventKey *event)
|
||||
}
|
||||
/* Pass through Tab as literal tab, unless Control is held down */
|
||||
else if ((event->keyval == GDK_Tab ||
|
||||
event->keyval == GDK_KP_Tab ||
|
||||
event->keyval == GDK_ISO_Left_Tab) &&
|
||||
event->keyval == GDK_KP_Tab) &&
|
||||
!(event->state & GDK_CONTROL_MASK))
|
||||
{
|
||||
/* If the text isn't editable, move the focus instead */
|
||||
|
@ -2871,9 +2871,7 @@ gtk_widget_real_key_press_event (GtkWidget *widget,
|
||||
gboolean handled = FALSE;
|
||||
|
||||
if (!handled)
|
||||
handled = gtk_bindings_activate (GTK_OBJECT (widget),
|
||||
event->keyval,
|
||||
event->state);
|
||||
handled = _gtk_bindings_activate_event (GTK_OBJECT (widget), event);
|
||||
|
||||
return handled;
|
||||
}
|
||||
@ -2885,9 +2883,7 @@ gtk_widget_real_key_release_event (GtkWidget *widget,
|
||||
gboolean handled = FALSE;
|
||||
|
||||
if (!handled)
|
||||
handled = gtk_bindings_activate (GTK_OBJECT (widget),
|
||||
event->keyval,
|
||||
event->state | GDK_RELEASE_MASK);
|
||||
handled = _gtk_bindings_activate_event (GTK_OBJECT (widget), event);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
207
gtk/gtkwindow.c
207
gtk/gtkwindow.c
@ -35,6 +35,7 @@
|
||||
#include "gtkwindow.h"
|
||||
#include "gtkwindow-decorate.h"
|
||||
#include "gtkbindings.h"
|
||||
#include "gtkkeyhash.h"
|
||||
#include "gtkmain.h"
|
||||
#include "gtkiconfactory.h"
|
||||
#include "gtkintl.h"
|
||||
@ -174,6 +175,7 @@ static void gtk_window_real_activate_default (GtkWindow *window);
|
||||
static void gtk_window_real_activate_focus (GtkWindow *window);
|
||||
static void gtk_window_move_focus (GtkWindow *window,
|
||||
GtkDirectionType dir);
|
||||
static void gtk_window_keys_changed (GtkWindow *window);
|
||||
static void gtk_window_read_rcfiles (GtkWidget *widget,
|
||||
GdkEventClient *event);
|
||||
static void gtk_window_paint (GtkWidget *widget,
|
||||
@ -222,7 +224,12 @@ static void gtk_window_set_default_size_internal (GtkWindow *window,
|
||||
|
||||
static void gtk_window_realize_icon (GtkWindow *window);
|
||||
static void gtk_window_unrealize_icon (GtkWindow *window);
|
||||
static void gtk_window_notify_keys_changed (GtkWindow *window);
|
||||
|
||||
static void gtk_window_notify_keys_changed (GtkWindow *window);
|
||||
static gboolean gtk_window_activate_key (GtkWindow *window,
|
||||
GdkEventKey *event);
|
||||
static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window);
|
||||
static void gtk_window_free_key_hash (GtkWindow *window);
|
||||
|
||||
static GSList *toplevel_list = NULL;
|
||||
static GHashTable *mnemonic_hash_table = NULL;
|
||||
@ -308,9 +315,6 @@ add_tab_bindings (GtkBindingSet *binding_set,
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_KP_Tab, modifiers,
|
||||
"move_focus", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, direction);
|
||||
gtk_binding_entry_add_signal (binding_set, GDK_ISO_Left_Tab, modifiers,
|
||||
"move_focus", 1,
|
||||
GTK_TYPE_DIRECTION_TYPE, direction);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -388,7 +392,7 @@ gtk_window_class_init (GtkWindowClass *klass)
|
||||
klass->activate_default = gtk_window_real_activate_default;
|
||||
klass->activate_focus = gtk_window_real_activate_focus;
|
||||
klass->move_focus = gtk_window_move_focus;
|
||||
klass->keys_changed = NULL;
|
||||
klass->keys_changed = gtk_window_keys_changed;
|
||||
|
||||
/* Construct */
|
||||
g_object_class_install_property (gobject_class,
|
||||
@ -2901,7 +2905,9 @@ gtk_window_destroy (GtkObject *object)
|
||||
if (window->group)
|
||||
gtk_window_group_remove_window (window->group, window);
|
||||
|
||||
GTK_OBJECT_CLASS (parent_class)->destroy (object);
|
||||
gtk_window_free_key_hash (window);
|
||||
|
||||
GTK_OBJECT_CLASS (parent_class)->destroy (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -3525,13 +3531,10 @@ gtk_window_key_press_event (GtkWidget *widget,
|
||||
|
||||
handled = FALSE;
|
||||
|
||||
/* Check for mnemonics and accelerators
|
||||
*/
|
||||
if (!handled)
|
||||
handled = gtk_window_mnemonic_activate (window,
|
||||
event->keyval,
|
||||
event->state);
|
||||
|
||||
if (!handled)
|
||||
handled = gtk_accel_groups_activate (G_OBJECT (window), event->keyval, event->state);
|
||||
handled = gtk_window_activate_key (window, event);
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
@ -5676,3 +5679,183 @@ gtk_window_parse_geometry (GtkWindow *window,
|
||||
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
typedef void (*GtkWindowKeysForeach) (GtkWindow *window,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers,
|
||||
gboolean is_mnemonic,
|
||||
gpointer data);
|
||||
|
||||
static void
|
||||
gtk_window_mnemonic_hash_foreach (gpointer key,
|
||||
gpointer value,
|
||||
gpointer data)
|
||||
{
|
||||
struct {
|
||||
GtkWindow *window;
|
||||
GtkWindowKeysForeach func;
|
||||
gpointer func_data;
|
||||
} *info = data;
|
||||
|
||||
GtkWindowMnemonic *mnemonic = value;
|
||||
|
||||
if (mnemonic->window == info->window)
|
||||
(*info->func) (info->window, mnemonic->keyval, info->window->mnemonic_modifier, TRUE, info->func_data);
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_keys_foreach (GtkWindow *window,
|
||||
GtkWindowKeysForeach func,
|
||||
gpointer func_data)
|
||||
{
|
||||
GSList *groups;
|
||||
|
||||
struct {
|
||||
GtkWindow *window;
|
||||
GtkWindowKeysForeach func;
|
||||
gpointer func_data;
|
||||
} info;
|
||||
|
||||
info.window = window;
|
||||
info.func = func;
|
||||
info.func_data = func_data;
|
||||
|
||||
g_hash_table_foreach (mnemonic_hash_table,
|
||||
gtk_window_mnemonic_hash_foreach,
|
||||
&info);
|
||||
|
||||
groups = gtk_accel_groups_from_object (G_OBJECT (window));
|
||||
while (groups)
|
||||
{
|
||||
GtkAccelGroup *group = groups->data;
|
||||
gint i;
|
||||
|
||||
for (i = 0; i < group->n_accels; i++)
|
||||
{
|
||||
GtkAccelKey *key = &group->priv_accels[i].key;
|
||||
|
||||
if (key->accel_key)
|
||||
(*func) (window, key->accel_key, key->accel_mods, FALSE, func_data);
|
||||
}
|
||||
|
||||
groups = groups->next;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_keys_changed (GtkWindow *window)
|
||||
{
|
||||
gtk_window_free_key_hash (window);
|
||||
gtk_window_get_key_hash (window);
|
||||
}
|
||||
|
||||
typedef struct _GtkWindowKeyEntry GtkWindowKeyEntry;
|
||||
|
||||
struct _GtkWindowKeyEntry
|
||||
{
|
||||
guint keyval;
|
||||
guint modifiers;
|
||||
gboolean is_mnemonic;
|
||||
};
|
||||
|
||||
static void
|
||||
add_to_key_hash (GtkWindow *window,
|
||||
guint keyval,
|
||||
GdkModifierType modifiers,
|
||||
gboolean is_mnemonic,
|
||||
gpointer data)
|
||||
{
|
||||
GtkKeyHash *key_hash = data;
|
||||
|
||||
GtkWindowKeyEntry *entry = g_new (GtkWindowKeyEntry, 1);
|
||||
|
||||
entry->keyval = keyval;
|
||||
entry->modifiers = modifiers;
|
||||
entry->is_mnemonic = is_mnemonic;
|
||||
|
||||
/* GtkAccelGroup stores lowercased accelerators. To deal
|
||||
* with this, if <Shift> was specified, uppercase.
|
||||
*/
|
||||
if (modifiers & GDK_SHIFT_MASK)
|
||||
{
|
||||
if (keyval == GDK_Tab)
|
||||
keyval = GDK_ISO_Left_Tab;
|
||||
else
|
||||
keyval = gdk_keyval_to_upper (keyval);
|
||||
}
|
||||
|
||||
_gtk_key_hash_add_entry (key_hash, keyval, entry->modifiers, entry);
|
||||
}
|
||||
|
||||
static GtkKeyHash *
|
||||
gtk_window_get_key_hash (GtkWindow *window)
|
||||
{
|
||||
GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
|
||||
if (key_hash)
|
||||
return key_hash;
|
||||
|
||||
key_hash = _gtk_key_hash_new (gdk_keymap_get_default(), (GDestroyNotify)g_free);
|
||||
gtk_window_keys_foreach (window, add_to_key_hash, key_hash);
|
||||
g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", key_hash);
|
||||
|
||||
return key_hash;
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_window_free_key_hash (GtkWindow *window)
|
||||
{
|
||||
GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
|
||||
if (key_hash)
|
||||
{
|
||||
_gtk_key_hash_free (key_hash);
|
||||
g_object_set_data (G_OBJECT (window), "gtk-window-key-hash", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_window_activate_key (GtkWindow *window,
|
||||
GdkEventKey *event)
|
||||
{
|
||||
GtkKeyHash *key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
|
||||
GtkWindowKeyEntry *found_entry = NULL;
|
||||
|
||||
if (!key_hash)
|
||||
{
|
||||
gtk_window_keys_changed (window);
|
||||
key_hash = g_object_get_data (G_OBJECT (window), "gtk-window-key-hash");
|
||||
}
|
||||
|
||||
if (key_hash)
|
||||
{
|
||||
GSList *entries = _gtk_key_hash_lookup (key_hash,
|
||||
event->hardware_keycode,
|
||||
event->state & gtk_accelerator_get_default_mod_mask (),
|
||||
event->group);
|
||||
GSList *tmp_list;
|
||||
|
||||
for (tmp_list = entries; tmp_list; tmp_list = tmp_list->next)
|
||||
{
|
||||
GtkWindowKeyEntry *entry = tmp_list->data;
|
||||
if (entry->is_mnemonic)
|
||||
{
|
||||
found_entry = entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_entry && entries)
|
||||
found_entry = entries->data;
|
||||
|
||||
g_slist_free (entries);
|
||||
}
|
||||
|
||||
if (found_entry)
|
||||
{
|
||||
if (found_entry->is_mnemonic)
|
||||
return gtk_window_mnemonic_activate (window, found_entry->keyval, found_entry->modifiers);
|
||||
else
|
||||
return gtk_accel_groups_activate (G_OBJECT (window), found_entry->keyval, found_entry->modifiers);
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -125,7 +125,8 @@ struct _GtkWindowClass
|
||||
void (* activate_focus) (GtkWindow *window);
|
||||
void (* activate_default) (GtkWindow *window);
|
||||
void (* move_focus) (GtkWindow *window,
|
||||
GtkDirectionType direction);
|
||||
GtkDirectionType direction);
|
||||
|
||||
void (*keys_changed) (GtkWindow *window);
|
||||
};
|
||||
|
||||
|
@ -3433,6 +3433,83 @@ create_item_factory (void)
|
||||
gtk_widget_destroy (window);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
accel_button_new (GtkAccelGroup *accel_group,
|
||||
const gchar *text,
|
||||
const gchar *accel)
|
||||
{
|
||||
guint keyval;
|
||||
GdkModifierType modifiers;
|
||||
GtkWidget *button;
|
||||
GtkWidget *label;
|
||||
|
||||
gtk_accelerator_parse (accel, &keyval, &modifiers);
|
||||
g_assert (keyval);
|
||||
|
||||
button = gtk_button_new ();
|
||||
gtk_widget_add_accelerator (button, "activate", accel_group,
|
||||
keyval, modifiers, GTK_ACCEL_VISIBLE | GTK_ACCEL_LOCKED);
|
||||
|
||||
label = gtk_accel_label_new (text);
|
||||
gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (label), button);
|
||||
gtk_widget_show (label);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (button), label);
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
static void
|
||||
create_key_lookup (void)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkAccelGroup *accel_group = gtk_accel_group_new ();
|
||||
GtkWidget *button;
|
||||
|
||||
window = gtk_dialog_new_with_buttons ("Key Lookup", NULL, 0,
|
||||
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
|
||||
NULL);
|
||||
|
||||
/* We have to expand it so the accel labels will draw their labels
|
||||
*/
|
||||
gtk_window_set_default_size (GTK_WINDOW (window), 300, -1);
|
||||
|
||||
gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
|
||||
|
||||
button = gtk_button_new_with_mnemonic ("Button 1 (_a)");
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
|
||||
button = gtk_button_new_with_mnemonic ("Button 2 (_A)");
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
|
||||
button = gtk_button_new_with_mnemonic ("Button 3 (_ф)");
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
|
||||
button = gtk_button_new_with_mnemonic ("Button 4 (_Ф)");
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
|
||||
button = gtk_button_new_with_mnemonic ("Button 6 (_b)");
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
|
||||
button = accel_button_new (accel_group, "Button 7", "<Alt><Shift>b");
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
|
||||
button = accel_button_new (accel_group, "Button 8", "<Alt>d");
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
|
||||
button = accel_button_new (accel_group, "Button 9", "<Alt>Cyrillic_ve");
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
|
||||
button = gtk_button_new_with_mnemonic ("Button 10 (_1)");
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
|
||||
button = gtk_button_new_with_mnemonic ("Button 11 (_!)");
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (window)->vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
g_signal_connect (window, "response", G_CALLBACK (gtk_object_destroy), NULL);
|
||||
|
||||
gtk_widget_show_all (window);
|
||||
}
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
create_modal_window
|
||||
*/
|
||||
@ -11350,6 +11427,7 @@ struct {
|
||||
{ "image from drawable", create_get_image },
|
||||
{ "image", create_image },
|
||||
{ "item factory", create_item_factory },
|
||||
{ "key lookup", create_key_lookup },
|
||||
{ "labels", create_labels },
|
||||
{ "layout", create_layout },
|
||||
{ "list", create_list },
|
||||
|
Loading…
Reference in New Issue
Block a user