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>
* 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>
* 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>
* 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>
* 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>
* 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>
* modules/input/gtkimcontextxim.c (status_window_get):

View File

@ -31,6 +31,7 @@
enum {
DIRECTION_CHANGED,
KEYS_CHANGED,
LAST_SIGNAL
};
@ -80,6 +81,15 @@ gdk_keymap_class_init (GdkKeymapClass *klass)
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
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

View File

@ -72,6 +72,7 @@ struct _GdkKeymapClass
GObjectClass parent_class;
void (*direction_changed) (GdkKeymap *keymap);
void (*keys_changed) (GdkKeymap *keymap);
};
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.
*/
XRefreshKeyboardMapping (&xevent->xmapping);
++display_x11->keymap_serial;
_gdk_keymap_keys_changed (display);
return_val = FALSE;
break;
@ -1619,7 +1619,7 @@ gdk_event_translate (GdkDisplay *display,
switch (xkb_event->any.xkb_type)
{
case XkbMapNotify:
++display_x11->keymap_serial;
_gdk_keymap_keys_changed (display);
return_val = FALSE;
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 */
PangoDirection

View File

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

View File

@ -21,20 +21,18 @@
#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;
/* Set as a side effect of generating key_hash->keycode_hash
*/
GdkKeymapKey *keys;
gint n_keys;
};
struct _GtkKeyHash
@ -42,6 +40,7 @@ struct _GtkKeyHash
GdkKeymap *keymap;
GHashTable *keycode_hash;
GHashTable *reverse_hash;
GList *entries_list;
GDestroyNotify destroy_notify;
};
@ -60,6 +59,7 @@ key_hash_insert_entry (GtkKeyHash *key_hash,
{
gint i;
g_free (entry->keys);
gdk_keymap_get_entries_for_keyval (key_hash->keymap,
entry->keyval,
&entry->keys, &entry->n_keys);
@ -75,33 +75,39 @@ key_hash_insert_entry (GtkKeyHash *key_hash,
}
}
#ifdef HAVE_CHANGED_SIGNAL
static void
key_hash_reinsert_entry (gpointer key,
gpointer value,
gpointer data)
static GHashTable *
key_hash_get_keycode_hash (GtkKeyHash *key_hash)
{
GtkKeyHashEntry *entry = value;
GtkKeyHash *key_hash = data;
if (!key_hash->keycode_hash)
{
GList *tmp_list;
key_hash->keycode_hash = g_hash_table_new (g_direct_hash, NULL);
/* 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);
}
g_free (entry->keys);
key_hash_insert_entry (key_hash, entry);
return key_hash->keycode_hash;
}
static void
key_hash_keymap_changed (GdkKeymap *keymap,
GtkKeyHash *key_hash)
key_hash_keys_changed (GdkKeymap *keymap,
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
*/
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);
if (key_hash->keycode_hash)
{
g_hash_table_foreach (key_hash->keycode_hash, key_hash_clear_keycode, NULL);
g_hash_table_destroy (key_hash->keycode_hash);
key_hash->keycode_hash = NULL;
}
}
#endif /* HAVE_CHANGED_SIGNAL */
/**
* _gtk_key_hash_new:
@ -120,12 +126,11 @@ _gtk_key_hash_new (GdkKeymap *keymap,
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
g_signal_connect (keymap, "keys_changed",
G_CALLBACK (key_hash_keys_changed), key_hash);
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->destroy_notify = item_destroy_notify;
@ -144,8 +149,7 @@ key_hash_free_entry (GtkKeyHash *key_hash,
}
static void
key_hash_free_entry_foreach (gpointer key,
gpointer value,
key_hash_free_entry_foreach (gpointer value,
gpointer data)
{
GtkKeyHashEntry *entry = value;
@ -163,16 +167,20 @@ key_hash_free_entry_foreach (gpointer key,
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_CALLBACK (key_hash_keys_changed), key_hash);
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);
if (key_hash->keycode_hash)
{
g_hash_table_foreach (key_hash->keycode_hash, key_hash_clear_keycode, NULL);
g_hash_table_destroy (key_hash->keycode_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);
}
@ -196,9 +204,13 @@ _gtk_key_hash_add_entry (GtkKeyHash *key_hash,
entry->value = value;
entry->keyval = keyval;
entry->modifiers = modifiers;
entry->keys = NULL;
g_hash_table_insert (key_hash->reverse_hash, value, entry);
key_hash_insert_entry (key_hash, 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);
}
/**
@ -213,30 +225,37 @@ void
_gtk_key_hash_remove_entry (GtkKeyHash *key_hash,
gpointer value)
{
GtkKeyHashEntry *entry = g_hash_table_lookup (key_hash->reverse_hash, value);
if (entry)
GList *entry_node = g_hash_table_lookup (key_hash->reverse_hash, value);
if (entry_node)
{
gint i;
GtkKeyHashEntry *entry = entry_node->data;
for (i = 0; i < entry->n_keys; i++)
if (key_hash->keycode_hash)
{
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 (new_keys != old_keys)
gint i;
for (i = 0; i < entry->n_keys; i++)
{
if (new_keys)
g_hash_table_insert (key_hash->keycode_hash,
GUINT_TO_POINTER (entry->keys[i].keycode),
new_keys);
else
g_hash_table_remove (key_hash->keycode_hash,
GUINT_TO_POINTER (entry->keys[i].keycode));
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 (new_keys != old_keys)
{
if (new_keys)
g_hash_table_insert (key_hash->keycode_hash,
GUINT_TO_POINTER (entry->keys[i].keycode),
new_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);
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);
}
@ -304,7 +323,8 @@ _gtk_key_hash_lookup (GtkKeyHash *key_hash,
GdkModifierType state,
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;
gboolean have_exact = FALSE;
guint keyval;
@ -404,7 +424,8 @@ _gtk_key_hash_lookup_keyval (GtkKeyHash *key_hash,
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)
{