Add a keys_changed signal emitted when the keymap changes. (#72148)

Mon Sep 23 16:48:46 2002  Owen Taylor  <otaylor@redhat.com>

        * gdk/gdkkeys.[ch] gdk/x11/gdkkeys-x11.c gdk/x11/gdkevents-x11.c:
        Add a keys_changed signal emitted when the keymap changes.
        (#72148)

        * gtk/gtkkeyhash.c (_gtk_key_hash_remove_entry):
        Hook up code to handle keymap changes, change to keep
        a linked list of keymap entries so that we can reinsert
        them in the same order on a keymap change.
This commit is contained in:
Owen Taylor 2002-09-23 21:35:00 +00:00 committed by Owen Taylor
parent be19be61b7
commit a16b63eb35
12 changed files with 234 additions and 63 deletions

View File

@ -1,3 +1,24 @@
Mon Sep 23 16:48:46 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.[ch] gdk/x11/gdkkeys-x11.c gdk/x11/gdkevents-x11.c:
Add a keys_changed signal emitted when the keymap changes.
(#72148)
* gtk/gtkkeyhash.c (_gtk_key_hash_remove_entry):
Hook up code to handle keymap changes, change to keep
a linked list of keymap entries so that we can reinsert
them in the same order on a keymap change.
Mon Sep 23 14:58:04 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkhandlebox.h gtk/gtktextbtree.[ch]:
Use 'signed int' not 'gint' for signed bitfields.
(#93020, Vitaly Tishkov)
* gtk/gtktextlayout.h gtk/gtktextbtree.[ch]:
Fix some 'gint' bitfields that should have been
unsigned.
Mon Sep 23 12:24:14 2002 Owen Taylor <otaylor@redhat.com> Mon Sep 23 12:24:14 2002 Owen Taylor <otaylor@redhat.com>
* modules/input/gtkimcontextxim.c (status_window_get): * modules/input/gtkimcontextxim.c (status_window_get):

View File

@ -1,3 +1,24 @@
Mon Sep 23 16:48:46 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.[ch] gdk/x11/gdkkeys-x11.c gdk/x11/gdkevents-x11.c:
Add a keys_changed signal emitted when the keymap changes.
(#72148)
* gtk/gtkkeyhash.c (_gtk_key_hash_remove_entry):
Hook up code to handle keymap changes, change to keep
a linked list of keymap entries so that we can reinsert
them in the same order on a keymap change.
Mon Sep 23 14:58:04 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkhandlebox.h gtk/gtktextbtree.[ch]:
Use 'signed int' not 'gint' for signed bitfields.
(#93020, Vitaly Tishkov)
* gtk/gtktextlayout.h gtk/gtktextbtree.[ch]:
Fix some 'gint' bitfields that should have been
unsigned.
Mon Sep 23 12:24:14 2002 Owen Taylor <otaylor@redhat.com> Mon Sep 23 12:24:14 2002 Owen Taylor <otaylor@redhat.com>
* modules/input/gtkimcontextxim.c (status_window_get): * modules/input/gtkimcontextxim.c (status_window_get):

View File

@ -1,3 +1,24 @@
Mon Sep 23 16:48:46 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.[ch] gdk/x11/gdkkeys-x11.c gdk/x11/gdkevents-x11.c:
Add a keys_changed signal emitted when the keymap changes.
(#72148)
* gtk/gtkkeyhash.c (_gtk_key_hash_remove_entry):
Hook up code to handle keymap changes, change to keep
a linked list of keymap entries so that we can reinsert
them in the same order on a keymap change.
Mon Sep 23 14:58:04 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkhandlebox.h gtk/gtktextbtree.[ch]:
Use 'signed int' not 'gint' for signed bitfields.
(#93020, Vitaly Tishkov)
* gtk/gtktextlayout.h gtk/gtktextbtree.[ch]:
Fix some 'gint' bitfields that should have been
unsigned.
Mon Sep 23 12:24:14 2002 Owen Taylor <otaylor@redhat.com> Mon Sep 23 12:24:14 2002 Owen Taylor <otaylor@redhat.com>
* modules/input/gtkimcontextxim.c (status_window_get): * modules/input/gtkimcontextxim.c (status_window_get):

View File

@ -1,3 +1,24 @@
Mon Sep 23 16:48:46 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.[ch] gdk/x11/gdkkeys-x11.c gdk/x11/gdkevents-x11.c:
Add a keys_changed signal emitted when the keymap changes.
(#72148)
* gtk/gtkkeyhash.c (_gtk_key_hash_remove_entry):
Hook up code to handle keymap changes, change to keep
a linked list of keymap entries so that we can reinsert
them in the same order on a keymap change.
Mon Sep 23 14:58:04 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkhandlebox.h gtk/gtktextbtree.[ch]:
Use 'signed int' not 'gint' for signed bitfields.
(#93020, Vitaly Tishkov)
* gtk/gtktextlayout.h gtk/gtktextbtree.[ch]:
Fix some 'gint' bitfields that should have been
unsigned.
Mon Sep 23 12:24:14 2002 Owen Taylor <otaylor@redhat.com> Mon Sep 23 12:24:14 2002 Owen Taylor <otaylor@redhat.com>
* modules/input/gtkimcontextxim.c (status_window_get): * modules/input/gtkimcontextxim.c (status_window_get):

View File

@ -1,3 +1,24 @@
Mon Sep 23 16:48:46 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.[ch] gdk/x11/gdkkeys-x11.c gdk/x11/gdkevents-x11.c:
Add a keys_changed signal emitted when the keymap changes.
(#72148)
* gtk/gtkkeyhash.c (_gtk_key_hash_remove_entry):
Hook up code to handle keymap changes, change to keep
a linked list of keymap entries so that we can reinsert
them in the same order on a keymap change.
Mon Sep 23 14:58:04 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkhandlebox.h gtk/gtktextbtree.[ch]:
Use 'signed int' not 'gint' for signed bitfields.
(#93020, Vitaly Tishkov)
* gtk/gtktextlayout.h gtk/gtktextbtree.[ch]:
Fix some 'gint' bitfields that should have been
unsigned.
Mon Sep 23 12:24:14 2002 Owen Taylor <otaylor@redhat.com> Mon Sep 23 12:24:14 2002 Owen Taylor <otaylor@redhat.com>
* modules/input/gtkimcontextxim.c (status_window_get): * modules/input/gtkimcontextxim.c (status_window_get):

View File

@ -1,3 +1,24 @@
Mon Sep 23 16:48:46 2002 Owen Taylor <otaylor@redhat.com>
* gdk/gdkkeys.[ch] gdk/x11/gdkkeys-x11.c gdk/x11/gdkevents-x11.c:
Add a keys_changed signal emitted when the keymap changes.
(#72148)
* gtk/gtkkeyhash.c (_gtk_key_hash_remove_entry):
Hook up code to handle keymap changes, change to keep
a linked list of keymap entries so that we can reinsert
them in the same order on a keymap change.
Mon Sep 23 14:58:04 2002 Owen Taylor <otaylor@redhat.com>
* gtk/gtkhandlebox.h gtk/gtktextbtree.[ch]:
Use 'signed int' not 'gint' for signed bitfields.
(#93020, Vitaly Tishkov)
* gtk/gtktextlayout.h gtk/gtktextbtree.[ch]:
Fix some 'gint' bitfields that should have been
unsigned.
Mon Sep 23 12:24:14 2002 Owen Taylor <otaylor@redhat.com> Mon Sep 23 12:24:14 2002 Owen Taylor <otaylor@redhat.com>
* modules/input/gtkimcontextxim.c (status_window_get): * modules/input/gtkimcontextxim.c (status_window_get):

View File

@ -31,6 +31,7 @@
enum { enum {
DIRECTION_CHANGED, DIRECTION_CHANGED,
KEYS_CHANGED,
LAST_SIGNAL LAST_SIGNAL
}; };
@ -80,6 +81,15 @@ gdk_keymap_class_init (GdkKeymapClass *klass)
g_cclosure_marshal_VOID__VOID, g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, G_TYPE_NONE,
0); 0);
signals[KEYS_CHANGED] =
g_signal_new ("keys_changed",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GdkKeymapClass, direction_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0);
} }
/* Other key-handling stuff /* Other key-handling stuff

View File

@ -72,6 +72,7 @@ struct _GdkKeymapClass
GObjectClass parent_class; GObjectClass parent_class;
void (*direction_changed) (GdkKeymap *keymap); void (*direction_changed) (GdkKeymap *keymap);
void (*keys_changed) (GdkKeymap *keymap);
}; };
GType gdk_keymap_get_type (void) G_GNUC_CONST; GType gdk_keymap_get_type (void) G_GNUC_CONST;

View File

@ -1606,7 +1606,7 @@ gdk_event_translate (GdkDisplay *display,
/* Let XLib know that there is a new keyboard mapping. /* Let XLib know that there is a new keyboard mapping.
*/ */
XRefreshKeyboardMapping (&xevent->xmapping); XRefreshKeyboardMapping (&xevent->xmapping);
++display_x11->keymap_serial; _gdk_keymap_keys_changed (display);
return_val = FALSE; return_val = FALSE;
break; break;
@ -1619,7 +1619,7 @@ gdk_event_translate (GdkDisplay *display,
switch (xkb_event->any.xkb_type) switch (xkb_event->any.xkb_type)
{ {
case XkbMapNotify: case XkbMapNotify:
++display_x11->keymap_serial; _gdk_keymap_keys_changed (display);
return_val = FALSE; return_val = FALSE;
break; break;

View File

@ -373,6 +373,18 @@ _gdk_keymap_state_changed (GdkDisplay *display)
} }
} }
} }
void
_gdk_keymap_keys_changed (GdkDisplay *display)
{
GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
++display_x11->keymap_serial;
if (display_x11->keymap)
g_signal_emit_by_name (display_x11->keymap, "keys_changed", 0);
}
#endif /* HAVE_XKB */ #endif /* HAVE_XKB */
PangoDirection PangoDirection

View File

@ -156,6 +156,7 @@ gboolean _gdk_moveresize_configure_done (GdkDisplay *display,
GdkWindow *window); GdkWindow *window);
void _gdk_keymap_state_changed (GdkDisplay *display); void _gdk_keymap_state_changed (GdkDisplay *display);
void _gdk_keymap_keys_changed (GdkDisplay *display);
gint _gdk_x11_get_group_for_state (GdkDisplay *display, gint _gdk_x11_get_group_for_state (GdkDisplay *display,
GdkModifierType state); GdkModifierType state);

View File

@ -21,20 +21,18 @@
#include "gtkdebug.h" #include "gtkdebug.h"
#include "gtkkeyhash.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; typedef struct _GtkKeyHashEntry GtkKeyHashEntry;
struct _GtkKeyHashEntry struct _GtkKeyHashEntry
{ {
guint keyval; guint keyval;
GdkModifierType modifiers; GdkModifierType modifiers;
gpointer value;
/* Set as a side effect of generating key_hash->keycode_hash
*/
GdkKeymapKey *keys; GdkKeymapKey *keys;
gint n_keys; gint n_keys;
gpointer value;
}; };
struct _GtkKeyHash struct _GtkKeyHash
@ -42,6 +40,7 @@ struct _GtkKeyHash
GdkKeymap *keymap; GdkKeymap *keymap;
GHashTable *keycode_hash; GHashTable *keycode_hash;
GHashTable *reverse_hash; GHashTable *reverse_hash;
GList *entries_list;
GDestroyNotify destroy_notify; GDestroyNotify destroy_notify;
}; };
@ -60,6 +59,7 @@ key_hash_insert_entry (GtkKeyHash *key_hash,
{ {
gint i; gint i;
g_free (entry->keys);
gdk_keymap_get_entries_for_keyval (key_hash->keymap, gdk_keymap_get_entries_for_keyval (key_hash->keymap,
entry->keyval, entry->keyval,
&entry->keys, &entry->n_keys); &entry->keys, &entry->n_keys);
@ -75,33 +75,39 @@ key_hash_insert_entry (GtkKeyHash *key_hash,
} }
} }
#ifdef HAVE_CHANGED_SIGNAL static GHashTable *
static void key_hash_get_keycode_hash (GtkKeyHash *key_hash)
key_hash_reinsert_entry (gpointer key,
gpointer value,
gpointer data)
{ {
GtkKeyHashEntry *entry = value; if (!key_hash->keycode_hash)
GtkKeyHash *key_hash = data; {
GList *tmp_list;
g_free (entry->keys); key_hash->keycode_hash = g_hash_table_new (g_direct_hash, NULL);
key_hash_insert_entry (key_hash, entry);
/* Preserve the original insertion order
*/
for (tmp_list = g_list_last (key_hash->entries_list);
tmp_list;
tmp_list = tmp_list->prev)
key_hash_insert_entry (key_hash, tmp_list->data);
}
return key_hash->keycode_hash;
} }
static void static void
key_hash_keymap_changed (GdkKeymap *keymap, key_hash_keys_changed (GdkKeymap *keymap,
GtkKeyHash *key_hash) GtkKeyHash *key_hash)
{ {
/* The keymap changed, so we have to clear and reinsert all our entries /* The keymap changed, so we have to regenerate the keycode hash
*/ */
if (key_hash->keycode_hash)
{
g_hash_table_foreach (key_hash->keycode_hash, key_hash_clear_keycode, NULL); g_hash_table_foreach (key_hash->keycode_hash, key_hash_clear_keycode, NULL);
g_hash_table_destroy (key_hash->keycode_hash);
/* FIXME: Here we reinsert in random order, but I think we actually have to key_hash->keycode_hash = NULL;
* 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: * _gtk_key_hash_new:
@ -120,12 +126,11 @@ _gtk_key_hash_new (GdkKeymap *keymap,
GtkKeyHash *key_hash = g_new (GtkKeyHash, 1); GtkKeyHash *key_hash = g_new (GtkKeyHash, 1);
key_hash->keymap = keymap; key_hash->keymap = keymap;
#ifdef HAVE_CHANGED_SIGNAL g_signal_connect (keymap, "keys_changed",
g_signal_connect (keymap, "changed", G_CALLBACK (key_hash_keys_changed), key_hash);
G_CALLBACK (key_hash_keymap_changed), key_hash);
#endif
key_hash->keycode_hash = g_hash_table_new (g_direct_hash, NULL); key_hash->entries_list = NULL;
key_hash->keycode_hash = NULL;
key_hash->reverse_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; key_hash->destroy_notify = item_destroy_notify;
@ -144,8 +149,7 @@ key_hash_free_entry (GtkKeyHash *key_hash,
} }
static void static void
key_hash_free_entry_foreach (gpointer key, key_hash_free_entry_foreach (gpointer value,
gpointer value,
gpointer data) gpointer data)
{ {
GtkKeyHashEntry *entry = value; GtkKeyHashEntry *entry = value;
@ -163,16 +167,20 @@ key_hash_free_entry_foreach (gpointer key,
void void
_gtk_key_hash_free (GtkKeyHash *key_hash) _gtk_key_hash_free (GtkKeyHash *key_hash)
{ {
#if HAVE_CHANGED_SIGNAL
g_signal_handlers_disconnect_by_func (key_hash->keymap, g_signal_handlers_disconnect_by_func (key_hash->keymap,
G_CALLBACK (key_hash_keymap_changed), key_hash); G_CALLBACK (key_hash_keys_changed), key_hash);
#endif
if (key_hash->keycode_hash)
{
g_hash_table_foreach (key_hash->keycode_hash, key_hash_clear_keycode, NULL); 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->keycode_hash);
}
g_hash_table_destroy (key_hash->reverse_hash); g_hash_table_destroy (key_hash->reverse_hash);
g_list_foreach (key_hash->entries_list, key_hash_free_entry_foreach, key_hash);
g_list_free (key_hash->entries_list);
g_free (key_hash); g_free (key_hash);
} }
@ -196,8 +204,12 @@ _gtk_key_hash_add_entry (GtkKeyHash *key_hash,
entry->value = value; entry->value = value;
entry->keyval = keyval; entry->keyval = keyval;
entry->modifiers = modifiers; entry->modifiers = modifiers;
entry->keys = NULL;
g_hash_table_insert (key_hash->reverse_hash, value, entry); key_hash->entries_list = g_list_prepend (key_hash->entries_list, entry);
g_hash_table_insert (key_hash->reverse_hash, value, key_hash->entries_list);
if (key_hash->keycode_hash)
key_hash_insert_entry (key_hash, entry); key_hash_insert_entry (key_hash, entry);
} }
@ -213,8 +225,13 @@ void
_gtk_key_hash_remove_entry (GtkKeyHash *key_hash, _gtk_key_hash_remove_entry (GtkKeyHash *key_hash,
gpointer value) gpointer value)
{ {
GtkKeyHashEntry *entry = g_hash_table_lookup (key_hash->reverse_hash, value); GList *entry_node = g_hash_table_lookup (key_hash->reverse_hash, value);
if (entry)
if (entry_node)
{
GtkKeyHashEntry *entry = entry_node->data;
if (key_hash->keycode_hash)
{ {
gint i; gint i;
@ -235,8 +252,10 @@ _gtk_key_hash_remove_entry (GtkKeyHash *key_hash,
GUINT_TO_POINTER (entry->keys[i].keycode)); GUINT_TO_POINTER (entry->keys[i].keycode));
} }
} }
}
g_hash_table_remove (key_hash->reverse_hash, value); g_hash_table_remove (key_hash->reverse_hash, entry_node);
key_hash->entries_list = g_list_delete_link (key_hash->entries_list, entry_node);
key_hash_free_entry (key_hash, entry); key_hash_free_entry (key_hash, entry);
} }
@ -304,7 +323,8 @@ _gtk_key_hash_lookup (GtkKeyHash *key_hash,
GdkModifierType state, GdkModifierType state,
gint group) gint group)
{ {
GSList *keys = g_hash_table_lookup (key_hash->keycode_hash, GUINT_TO_POINTER ((guint)hardware_keycode)); GHashTable *keycode_hash = key_hash_get_keycode_hash (key_hash);
GSList *keys = g_hash_table_lookup (keycode_hash, GUINT_TO_POINTER ((guint)hardware_keycode));
GSList *results = NULL; GSList *results = NULL;
gboolean have_exact = FALSE; gboolean have_exact = FALSE;
guint keyval; guint keyval;
@ -404,7 +424,8 @@ _gtk_key_hash_lookup_keyval (GtkKeyHash *key_hash,
if (n_keys) if (n_keys)
{ {
GSList *entries = g_hash_table_lookup (key_hash->keycode_hash, GUINT_TO_POINTER (keys[0].keycode)); GHashTable *keycode_hash = key_hash_get_keycode_hash (key_hash);
GSList *entries = g_hash_table_lookup (keycode_hash, GUINT_TO_POINTER (keys[0].keycode));
while (entries) while (entries)
{ {