From 6a802b24b3308daac4533c5bb19dc8660c4b3ab8 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Sun, 24 Feb 2002 01:52:14 +0000 Subject: [PATCH] Implement accelerator propagation using a custom XEMBED_GTK_KEY_GRAB Sat Feb 23 20:33:29 2002 Owen Taylor * gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/xembed.h: Implement accelerator propagation using a custom XEMBED_GTK_KEY_GRAB XEMBED_GTK_KEY_UNGRAB pair of messages. * gtk/gtkwindow.[ch]: private export _gtk_window_keys_foreach(). * gtk/gtkplug.c (gtk_plug_set_is_child): Clear focus and default widgets. --- ChangeLog | 11 ++ ChangeLog.pre-2-0 | 11 ++ ChangeLog.pre-2-10 | 11 ++ ChangeLog.pre-2-2 | 11 ++ ChangeLog.pre-2-4 | 11 ++ ChangeLog.pre-2-6 | 11 ++ ChangeLog.pre-2-8 | 11 ++ gtk/gtkplug.c | 169 ++++++++++++------------------- gtk/gtkplug.h | 2 + gtk/gtksocket.c | 246 +++++++++++++++++++++++---------------------- gtk/gtksocket.h | 2 +- gtk/gtkwindow.c | 20 ++-- gtk/gtkwindow.h | 10 ++ gtk/xembed.h | 4 + 14 files changed, 293 insertions(+), 237 deletions(-) diff --git a/ChangeLog b/ChangeLog index dc6b004ee4..aba8ba2e35 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +Sat Feb 23 20:33:29 2002 Owen Taylor + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/xembed.h: Implement + accelerator propagation using a custom XEMBED_GTK_KEY_GRAB + XEMBED_GTK_KEY_UNGRAB pair of messages. + + * gtk/gtkwindow.[ch]: private export _gtk_window_keys_foreach(). + + * gtk/gtkplug.c (gtk_plug_set_is_child): Clear focus and default + widgets. + 2002-02-23 Havoc Pennington * gtk/gtktextbuffer.c (save_range): change gravity of start/end diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index dc6b004ee4..aba8ba2e35 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,14 @@ +Sat Feb 23 20:33:29 2002 Owen Taylor + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/xembed.h: Implement + accelerator propagation using a custom XEMBED_GTK_KEY_GRAB + XEMBED_GTK_KEY_UNGRAB pair of messages. + + * gtk/gtkwindow.[ch]: private export _gtk_window_keys_foreach(). + + * gtk/gtkplug.c (gtk_plug_set_is_child): Clear focus and default + widgets. + 2002-02-23 Havoc Pennington * gtk/gtktextbuffer.c (save_range): change gravity of start/end diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index dc6b004ee4..aba8ba2e35 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,14 @@ +Sat Feb 23 20:33:29 2002 Owen Taylor + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/xembed.h: Implement + accelerator propagation using a custom XEMBED_GTK_KEY_GRAB + XEMBED_GTK_KEY_UNGRAB pair of messages. + + * gtk/gtkwindow.[ch]: private export _gtk_window_keys_foreach(). + + * gtk/gtkplug.c (gtk_plug_set_is_child): Clear focus and default + widgets. + 2002-02-23 Havoc Pennington * gtk/gtktextbuffer.c (save_range): change gravity of start/end diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index dc6b004ee4..aba8ba2e35 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,14 @@ +Sat Feb 23 20:33:29 2002 Owen Taylor + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/xembed.h: Implement + accelerator propagation using a custom XEMBED_GTK_KEY_GRAB + XEMBED_GTK_KEY_UNGRAB pair of messages. + + * gtk/gtkwindow.[ch]: private export _gtk_window_keys_foreach(). + + * gtk/gtkplug.c (gtk_plug_set_is_child): Clear focus and default + widgets. + 2002-02-23 Havoc Pennington * gtk/gtktextbuffer.c (save_range): change gravity of start/end diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index dc6b004ee4..aba8ba2e35 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,14 @@ +Sat Feb 23 20:33:29 2002 Owen Taylor + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/xembed.h: Implement + accelerator propagation using a custom XEMBED_GTK_KEY_GRAB + XEMBED_GTK_KEY_UNGRAB pair of messages. + + * gtk/gtkwindow.[ch]: private export _gtk_window_keys_foreach(). + + * gtk/gtkplug.c (gtk_plug_set_is_child): Clear focus and default + widgets. + 2002-02-23 Havoc Pennington * gtk/gtktextbuffer.c (save_range): change gravity of start/end diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index dc6b004ee4..aba8ba2e35 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,14 @@ +Sat Feb 23 20:33:29 2002 Owen Taylor + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/xembed.h: Implement + accelerator propagation using a custom XEMBED_GTK_KEY_GRAB + XEMBED_GTK_KEY_UNGRAB pair of messages. + + * gtk/gtkwindow.[ch]: private export _gtk_window_keys_foreach(). + + * gtk/gtkplug.c (gtk_plug_set_is_child): Clear focus and default + widgets. + 2002-02-23 Havoc Pennington * gtk/gtktextbuffer.c (save_range): change gravity of start/end diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index dc6b004ee4..aba8ba2e35 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,14 @@ +Sat Feb 23 20:33:29 2002 Owen Taylor + + * gtk/gtkplug.[ch] gtk/gtksocket.[ch] gtk/xembed.h: Implement + accelerator propagation using a custom XEMBED_GTK_KEY_GRAB + XEMBED_GTK_KEY_UNGRAB pair of messages. + + * gtk/gtkwindow.[ch]: private export _gtk_window_keys_foreach(). + + * gtk/gtkplug.c (gtk_plug_set_is_child): Clear focus and default + widgets. + 2002-02-23 Havoc Pennington * gtk/gtktextbuffer.c (save_range): change gravity of start/end diff --git a/gtk/gtkplug.c b/gtk/gtkplug.c index eb4f10c228..b179fe865f 100644 --- a/gtk/gtkplug.c +++ b/gtk/gtkplug.c @@ -37,6 +37,7 @@ static void gtk_plug_class_init (GtkPlugClass *klass); static void gtk_plug_init (GtkPlug *plug); +static void gtk_plug_finalize (GObject *object); static void gtk_plug_realize (GtkWidget *widget); static void gtk_plug_unrealize (GtkWidget *widget); static void gtk_plug_show (GtkWidget *widget); @@ -47,23 +48,16 @@ static void gtk_plug_size_allocate (GtkWidget *widget, GtkAllocation *allocation); static gboolean gtk_plug_key_press_event (GtkWidget *widget, GdkEventKey *event); -static void gtk_plug_forward_key_press (GtkPlug *plug, - GdkEventKey *event); static void gtk_plug_set_focus (GtkWindow *window, GtkWidget *focus); static gboolean gtk_plug_focus (GtkWidget *widget, GtkDirectionType direction); static void gtk_plug_check_resize (GtkContainer *container); -#if 0 -static void gtk_plug_accel_entries_changed (GtkWindow *window); -#endif +static void gtk_plug_keys_changed (GtkWindow *window); static GdkFilterReturn gtk_plug_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data); -#if 0 -static void gtk_plug_free_grabbed_keys (GHashTable *key_table); -#endif static void handle_modality_off (GtkPlug *plug); static void send_xembed_message (GtkPlug *plug, glong message, @@ -116,6 +110,7 @@ gtk_plug_get_type () static void gtk_plug_class_init (GtkPlugClass *class) { + GObjectClass *gobject_class = (GObjectClass *)class; GtkWidgetClass *widget_class = (GtkWidgetClass *)class; GtkWindowClass *window_class = (GtkWindowClass *)class; GtkContainerClass *container_class = (GtkContainerClass *)class; @@ -123,6 +118,8 @@ gtk_plug_class_init (GtkPlugClass *class) parent_class = gtk_type_class (GTK_TYPE_WINDOW); bin_class = gtk_type_class (GTK_TYPE_BIN); + gobject_class->finalize = gtk_plug_finalize; + widget_class->realize = gtk_plug_realize; widget_class->unrealize = gtk_plug_unrealize; widget_class->key_press_event = gtk_plug_key_press_event; @@ -138,9 +135,7 @@ gtk_plug_class_init (GtkPlugClass *class) container_class->check_resize = gtk_plug_check_resize; window_class->set_focus = gtk_plug_set_focus; -#if 0 - window_class->accel_entries_changed = gtk_plug_accel_entries_changed; -#endif + window_class->keys_changed = gtk_plug_keys_changed; plug_signals[EMBEDDED] = g_signal_new ("embedded", @@ -195,6 +190,11 @@ gtk_plug_set_is_child (GtkPlug *plug, } else { + if (GTK_WINDOW (plug)->focus_widget) + gtk_window_set_focus (GTK_WINDOW (plug), NULL); + if (GTK_WINDOW (plug)->default_widget) + gtk_window_set_default (GTK_WINDOW (plug), NULL); + plug->modality_group = gtk_window_group_new (); gtk_window_group_add_window (plug->modality_group, GTK_WINDOW (plug)); @@ -364,6 +364,20 @@ gtk_plug_get_id (GtkPlug *plug) return GDK_WINDOW_XWINDOW (GTK_WIDGET (plug)->window); } +static void +gtk_plug_finalize (GObject *object) +{ + GtkPlug *plug = GTK_PLUG (object); + + if (plug->grabbed_keys) + { + g_hash_table_destroy (plug->grabbed_keys); + plug->grabbed_keys = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static void gtk_plug_unrealize (GtkWidget *widget) { @@ -568,48 +582,11 @@ gtk_plug_key_press_event (GtkWidget *widget, GdkEventKey *event) { if (GTK_WIDGET_TOPLEVEL (widget)) - { - if (!GTK_WINDOW (widget)->has_focus) - { - gtk_plug_forward_key_press (GTK_PLUG (widget), event); - return TRUE; - } - else - return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); - } + return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event); else return FALSE; } -static void -gtk_plug_forward_key_press (GtkPlug *plug, GdkEventKey *event) -{ - XEvent xevent; - - xevent.xkey.type = KeyPress; - xevent.xkey.display = GDK_WINDOW_XDISPLAY (GTK_WIDGET(plug)->window); - xevent.xkey.window = GDK_WINDOW_XWINDOW (plug->socket_window); - xevent.xkey.root = GDK_ROOT_WINDOW (); /* FIXME */ - xevent.xkey.time = event->time; - /* FIXME, the following might cause big problems for - * non-GTK apps */ - xevent.xkey.x = 0; - xevent.xkey.y = 0; - xevent.xkey.x_root = 0; - xevent.xkey.y_root = 0; - xevent.xkey.state = event->state; - xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), - event->keyval); - xevent.xkey.same_screen = TRUE; /* FIXME ? */ - - gdk_error_trap_push (); - XSendEvent (GDK_DISPLAY (), - GDK_WINDOW_XWINDOW (plug->socket_window), - False, NoEventMask, &xevent); - gdk_flush (); - gdk_error_trap_pop (); -} - static void gtk_plug_set_focus (GtkWindow *window, GtkWidget *focus) @@ -645,8 +622,6 @@ gtk_plug_set_focus (GtkWindow *window, } } -#if 0 - typedef struct { guint accelerator_key; @@ -677,7 +652,7 @@ grabbed_key_equal (gconstpointer a, gconstpointer b) } static void -add_grabbed_keys (gpointer key, gpointer val, gpointer data) +add_grabbed_key (gpointer key, gpointer val, gpointer data) { GrabbedKey *grabbed_key = key; GtkPlug *plug = data; @@ -685,14 +660,25 @@ add_grabbed_keys (gpointer key, gpointer val, gpointer data) if (!plug->grabbed_keys || !g_hash_table_lookup (plug->grabbed_keys, grabbed_key)) { - send_xembed_message (plug, XEMBED_GRAB_KEY, 0, + send_xembed_message (plug, XEMBED_GTK_GRAB_KEY, 0, grabbed_key->accelerator_key, grabbed_key->accelerator_mods, gtk_get_current_event_time ()); } } static void -remove_grabbed_keys (gpointer key, gpointer val, gpointer data) +add_grabbed_key_always (gpointer key, gpointer val, gpointer data) +{ + GrabbedKey *grabbed_key = key; + GtkPlug *plug = data; + + send_xembed_message (plug, XEMBED_GTK_GRAB_KEY, 0, + grabbed_key->accelerator_key, grabbed_key->accelerator_mods, + gtk_get_current_event_time ()); +} + +static void +remove_grabbed_key (gpointer key, gpointer val, gpointer data) { GrabbedKey *grabbed_key = key; GtkPlug *plug = data; @@ -700,74 +686,50 @@ remove_grabbed_keys (gpointer key, gpointer val, gpointer data) if (!plug->grabbed_keys || !g_hash_table_lookup (plug->grabbed_keys, grabbed_key)) { - send_xembed_message (plug, XEMBED_UNGRAB_KEY, 0, + send_xembed_message (plug, XEMBED_GTK_UNGRAB_KEY, 0, grabbed_key->accelerator_key, grabbed_key->accelerator_mods, gtk_get_current_event_time ()); } } static void -gtk_plug_free_grabbed_keys (GHashTable *key_table) +keys_foreach (GtkWindow *window, + guint keyval, + GdkModifierType modifiers, + gboolean is_mnemonic, + gpointer data) { - g_hash_table_foreach (key_table, (GHFunc)g_free, NULL); - g_hash_table_destroy (key_table); + GHashTable *new_grabbed_keys = data; + GrabbedKey *key = g_new (GrabbedKey, 1); + + key->accelerator_key = keyval; + key->accelerator_mods = modifiers; + + g_hash_table_replace (new_grabbed_keys, key, key); } static void -gtk_plug_accel_entries_changed (GtkWindow *window) +gtk_plug_keys_changed (GtkWindow *window) { GHashTable *new_grabbed_keys, *old_grabbed_keys; - GSList *accel_groups, *tmp_list; GtkPlug *plug = GTK_PLUG (window); - new_grabbed_keys = g_hash_table_new (grabbed_key_hash, grabbed_key_equal); + new_grabbed_keys = g_hash_table_new_full (grabbed_key_hash, grabbed_key_equal, (GDestroyNotify)g_free, NULL); + _gtk_window_keys_foreach (window, keys_foreach, new_grabbed_keys); - accel_groups = gtk_accel_groups_from_object (G_OBJECT (window)); - - tmp_list = accel_groups; - - while (tmp_list) - { - GtkAccelGroup *accel_group = tmp_list->data; - gint i, n_entries; - GtkAccelEntry *entries; - - gtk_accel_group_get_entries (accel_group, &entries, &n_entries); - - for (i = 0; i < n_entries; i++) - { - GdkKeymapKey *keys; - gint n_keys; - - if (gdk_keymap_get_entries_for_keyval (NULL, entries[i].accelerator_key, &keys, &n_keys)) - { - GrabbedKey *key = g_new (GrabbedKey, 1); - - key->accelerator_key = keys[0].keycode; - key->accelerator_mods = entries[i].accelerator_mods; - - g_hash_table_insert (new_grabbed_keys, key, key); - - g_free (keys); - } - } - - tmp_list = tmp_list->next; - } - - g_hash_table_foreach (new_grabbed_keys, add_grabbed_keys, plug); + if (plug->socket_window) + g_hash_table_foreach (new_grabbed_keys, add_grabbed_key, plug); old_grabbed_keys = plug->grabbed_keys; plug->grabbed_keys = new_grabbed_keys; if (old_grabbed_keys) { - g_hash_table_foreach (old_grabbed_keys, remove_grabbed_keys, plug); - gtk_plug_free_grabbed_keys (old_grabbed_keys); + if (plug->socket_window) + g_hash_table_foreach (old_grabbed_keys, remove_grabbed_key, plug); + g_hash_table_destroy (old_grabbed_keys); } - } -#endif static gboolean gtk_plug_focus (GtkWidget *widget, @@ -1009,11 +971,13 @@ handle_xembed_message (GtkPlug *plug, break; } + case XEMBED_GRAB_KEY: + case XEMBED_UNGRAB_KEY: + case XEMBED_GTK_GRAB_KEY: + case XEMBED_GTK_UNGRAB_KEY: case XEMBED_REQUEST_FOCUS: case XEMBED_FOCUS_NEXT: case XEMBED_FOCUS_PREV: - case XEMBED_GRAB_KEY: - case XEMBED_UNGRAB_KEY: g_warning ("GtkPlug: Invalid _XEMBED message of type %ld received", message); break; @@ -1137,7 +1101,8 @@ gtk_plug_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) break; } - /* FIXME: Add grabbed keys here */ + if (plug->grabbed_keys) + g_hash_table_foreach (plug->grabbed_keys, add_grabbed_key_always, plug); if (!was_embedded) g_signal_emit (G_OBJECT (plug), plug_signals[EMBEDDED], 0); diff --git a/gtk/gtkplug.h b/gtk/gtkplug.h index b711c021e8..17e4261698 100644 --- a/gtk/gtkplug.h +++ b/gtk/gtkplug.h @@ -56,6 +56,8 @@ struct _GtkPlug GdkWindow *socket_window; GtkWidget *modality_window; GtkWindowGroup *modality_group; + GHashTable *grabbed_keys; + guint same_app : 1; }; diff --git a/gtk/gtksocket.c b/gtk/gtksocket.c index 6a65e199b0..8546b95962 100644 --- a/gtk/gtksocket.c +++ b/gtk/gtksocket.c @@ -43,6 +43,7 @@ static void gtk_socket_class_init (GtkSocketClass *klass); static void gtk_socket_init (GtkSocket *socket); +static void gtk_socket_finalize (GObject *object); static void gtk_socket_realize (GtkWidget *widget); static void gtk_socket_unrealize (GtkWidget *widget); static void gtk_socket_size_request (GtkWidget *widget, @@ -129,17 +130,32 @@ gtk_socket_get_type (void) return socket_type; } +static void +gtk_socket_finalize (GObject *object) +{ + GtkSocket *socket = GTK_SOCKET (object); + + g_object_unref (socket->accel_group); + socket->accel_group = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static void gtk_socket_class_init (GtkSocketClass *class) { GtkWidgetClass *widget_class; GtkContainerClass *container_class; + GObjectClass *gobject_class; + gobject_class = (GObjectClass *) class; widget_class = (GtkWidgetClass*) class; container_class = (GtkContainerClass*) class; parent_class = gtk_type_class (GTK_TYPE_CONTAINER); + gobject_class->finalize = gtk_socket_finalize; + widget_class->realize = gtk_socket_realize; widget_class->unrealize = gtk_socket_unrealize; widget_class->size_request = gtk_socket_size_request; @@ -185,6 +201,9 @@ gtk_socket_init (GtkSocket *socket) socket->focus_in = FALSE; socket->have_size = FALSE; socket->need_map = FALSE; + + socket->accel_group = gtk_accel_group_new (); + g_object_set_data (G_OBJECT (socket->accel_group), "gtk-socket", socket); } /** @@ -336,6 +355,27 @@ gtk_socket_realize (GtkWidget *widget) gdk_flush(); } +static void +gtk_socket_end_embedding (GtkSocket *socket) +{ + GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); + gint i; + + if (toplevel && GTK_IS_WINDOW (toplevel)) + gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), + GDK_WINDOW_XWINDOW (socket->plug_window)); + + g_object_unref (socket->plug_window); + socket->plug_window = NULL; + + /* Remove from end to avoid indexes shiting. This is evil */ + for (i = socket->accel_group->n_accels; i >= 0; i--) + { + GtkAccelGroupEntry *accel_entry = &socket->accel_group->priv_accels[i]; + gtk_accel_group_disconnect (socket->accel_group, accel_entry->closure); + } +} + static void gtk_socket_unrealize (GtkWidget *widget) { @@ -349,24 +389,9 @@ gtk_socket_unrealize (GtkWidget *widget) } else if (socket->plug_window) { - GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); - if (toplevel && GTK_IS_WINDOW (toplevel)) - gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), - GDK_WINDOW_XWINDOW (socket->plug_window)); - - g_object_unref (socket->plug_window); - socket->plug_window = NULL; + gtk_socket_end_embedding (socket); } -#if 0 - if (socket->grabbed_keys) - { - g_hash_table_foreach (socket->grabbed_keys, (GHFunc)g_free, NULL); - g_hash_table_destroy (socket->grabbed_keys); - socket->grabbed_keys = NULL; - } -#endif - if (GTK_WIDGET_CLASS (parent_class)->unrealize) (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget); } @@ -496,122 +521,112 @@ gtk_socket_size_allocate (GtkWidget *widget, } } -#if 0 - typedef struct { - guint accelerator_key; - GdkModifierType accelerator_mods; + guint accel_key; + GdkModifierType accel_mods; } GrabbedKey; -static guint -grabbed_key_hash (gconstpointer a) +static void +activate_key (GtkAccelGroup *accel_group, + GrabbedKey *grabbed_key) { - const GrabbedKey *key = a; - guint h; + XEvent xevent; + GdkEvent *gdk_event = gtk_get_current_event (); - h = key->accelerator_key << 16; - h ^= key->accelerator_key >> 16; - h ^= key->accelerator_mods; + GtkSocket *socket = g_object_get_data (G_OBJECT (accel_group), "gtk-socket"); - return h; + if (gdk_event && gdk_event->type == GDK_KEY_PRESS && socket->plug_window) + { + xevent.xkey.type = KeyPress; + xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window); + xevent.xkey.root = GDK_ROOT_WINDOW (); + xevent.xkey.subwindow = None; + xevent.xkey.time = gdk_event->key.time; + xevent.xkey.x = 0; + xevent.xkey.y = 0; + xevent.xkey.x_root = 0; + xevent.xkey.y_root = 0; + xevent.xkey.state = gdk_event->key.state; + xevent.xkey.keycode = gdk_event->key.hardware_keycode; + xevent.xkey.same_screen = True; + + gdk_error_trap_push (); + XSendEvent (GDK_DISPLAY (), + GDK_WINDOW_XWINDOW (socket->plug_window), + False, KeyPressMask, &xevent); + gdk_flush (); + gdk_error_trap_pop (); + } + + if (gdk_event) + gdk_event_free (gdk_event); } static gboolean -grabbed_key_equal (gconstpointer a, gconstpointer b) +find_accel_key (GtkAccelKey *key, + GClosure *closure, + gpointer data) { - const GrabbedKey *keya = a; - const GrabbedKey *keyb = b; - - return (keya->accelerator_key == keyb->accelerator_key && - keya->accelerator_mods == keyb->accelerator_mods); + GrabbedKey *grabbed_key = data; + + return (key->accel_key == grabbed_key->accel_key && + key->accel_mods == grabbed_key->accel_mods); } static void -add_grabbed_key (GtkSocket *socket, - guint hardware_keycode, - GdkModifierType mods) +add_grabbed_key (GtkSocket *socket, + guint keyval, + GdkModifierType modifiers) { - GrabbedKey key; - GrabbedKey *new_key; - GrabbedKey *found_key; + GClosure *closure; + GrabbedKey *grabbed_key; - if (socket->grabbed_keys) + grabbed_key = g_new (GrabbedKey, 1); + + grabbed_key->accel_key = keyval; + grabbed_key->accel_mods = modifiers; + + if (gtk_accel_group_find (socket->accel_group, + find_accel_key, + &grabbed_key)) { - key.accelerator_key = hardware_keycode; - key.accelerator_mods = mods; - - found_key = g_hash_table_lookup (socket->grabbed_keys, &key); - - if (found_key) - { - g_warning ("GtkSocket: request to add already present grabbed key %u,%#x\n", - hardware_keycode, mods); - return; - } + g_warning ("GtkSocket: request to add already present grabbed key %u,%#x\n", + keyval, modifiers); + g_free (grabbed_key); + return; } - - if (!socket->grabbed_keys) - socket->grabbed_keys = g_hash_table_new (grabbed_key_hash, grabbed_key_equal); - new_key = g_new (GrabbedKey, 1); - - new_key->accelerator_key = hardware_keycode; - new_key->accelerator_mods = mods; + closure = g_cclosure_new (G_CALLBACK (activate_key), grabbed_key, (GClosureNotify)g_free); - g_hash_table_insert (socket->grabbed_keys, new_key, new_key); + gtk_accel_group_connect (socket->accel_group, keyval, modifiers, GTK_ACCEL_LOCKED, + closure); } static void remove_grabbed_key (GtkSocket *socket, - guint hardware_keycode, - GdkModifierType mods) + guint keyval, + GdkModifierType modifiers) { - GrabbedKey key; - GrabbedKey *found_key = NULL; + gint i; - if (socket->grabbed_keys) + for (i = 0; i < socket->accel_group->n_accels; i++) { - key.accelerator_key = hardware_keycode; - key.accelerator_mods = mods; - - found_key = g_hash_table_lookup (socket->grabbed_keys, &key); + GtkAccelGroupEntry *accel_entry = &socket->accel_group->priv_accels[i]; + if (accel_entry->key.accel_key == keyval && + accel_entry->key.accel_mods == modifiers) + { + gtk_accel_group_disconnect (socket->accel_group, + accel_entry->closure); + return; + } + } - if (found_key) - { - g_hash_table_remove (socket->grabbed_keys, &key); - g_free (found_key); - } - else - g_warning ("GtkSocket: request to remove non-present grabbed key %u,%#x\n", - hardware_keycode, mods); + g_warning ("GtkSocket: request to remove non-present grabbed key %u,%#x\n", + keyval, modifiers); } -static gboolean -toplevel_key_press_handler (GtkWidget *toplevel, - GdkEventKey *event, - GtkSocket *socket) -{ - GrabbedKey search_key; - - search_key.accelerator_key = event->hardware_keycode; - search_key.accelerator_mods = event->state; - - if (socket->grabbed_keys && - g_hash_table_lookup (socket->grabbed_keys, &search_key)) - { - gtk_socket_key_press_event (GTK_WIDGET (socket), event); - gtk_signal_emit_stop_by_name (GTK_OBJECT (toplevel), "key_press_event"); - - return TRUE; - } - else - return FALSE; -} - -#endif - static gboolean toplevel_focus_in_handler (GtkWidget *toplevel, GdkEventFocus *event, @@ -654,9 +669,7 @@ gtk_socket_hierarchy_changed (GtkWidget *widget, { if (socket->toplevel) { -#if 0 - gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_key_press_handler), socket); -#endif + gtk_window_remove_accel_group (GTK_WINDOW (socket->toplevel), socket->accel_group); gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket); gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket); } @@ -665,10 +678,7 @@ gtk_socket_hierarchy_changed (GtkWidget *widget, if (toplevel) { -#if 0 - gtk_signal_connect (GTK_OBJECT (socket->toplevel), "key_press_event", - GTK_SIGNAL_FUNC (toplevel_key_press_handler), socket); -#endif + gtk_window_add_accel_group (GTK_WINDOW (socket->toplevel), socket->accel_group); gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_in_event", GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket); gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_out_event", @@ -1184,15 +1194,15 @@ handle_xembed_message (GtkSocket *socket, break; } - case XEMBED_GRAB_KEY: -#if 0 + case XEMBED_GTK_GRAB_KEY: add_grabbed_key (socket, data1, data2); -#endif break; - case XEMBED_UNGRAB_KEY: -#if 0 + case XEMBED_GTK_UNGRAB_KEY: remove_grabbed_key (socket, data1, data2); -#endif + break; + + case XEMBED_GRAB_KEY: + case XEMBED_UNGRAB_KEY: break; default: @@ -1327,19 +1337,13 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) */ if (socket->plug_window && (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window))) { - GtkWidget *toplevel; gboolean result; GTK_NOTE(PLUGSOCKET, g_message ("GtkSocket - destroy notify")); - toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); - if (toplevel && GTK_IS_WINDOW (toplevel)) - gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), xdwe->window); - gdk_window_destroy_notify (socket->plug_window); - g_object_unref (socket->plug_window); - socket->plug_window = NULL; + gtk_socket_end_embedding (socket); g_object_ref (widget); g_signal_emit (G_OBJECT (widget), socket_signals[PLUG_REMOVED], 0, &result); diff --git a/gtk/gtksocket.h b/gtk/gtksocket.h index 814bb335d7..b6859cc8a9 100644 --- a/gtk/gtksocket.h +++ b/gtk/gtksocket.h @@ -63,7 +63,7 @@ struct _GtkSocket guint need_map : 1; guint is_mapped : 1; - GHashTable *grabbed_keys; + GtkAccelGroup *accel_group; GtkWidget *toplevel; }; diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 45267e1893..7f860fc587 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -5675,12 +5675,6 @@ 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, @@ -5688,7 +5682,7 @@ gtk_window_mnemonic_hash_foreach (gpointer key, { struct { GtkWindow *window; - GtkWindowKeysForeach func; + GtkWindowKeysForeachFunc func; gpointer func_data; } *info = data; @@ -5698,16 +5692,16 @@ gtk_window_mnemonic_hash_foreach (gpointer key, (*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) +void +_gtk_window_keys_foreach (GtkWindow *window, + GtkWindowKeysForeachFunc func, + gpointer func_data) { GSList *groups; struct { GtkWindow *window; - GtkWindowKeysForeach func; + GtkWindowKeysForeachFunc func; gpointer func_data; } info; @@ -5790,7 +5784,7 @@ gtk_window_get_key_hash (GtkWindow *window) 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); + _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; diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h index 2aaa13eb97..c8e79474b4 100644 --- a/gtk/gtkwindow.h +++ b/gtk/gtkwindow.h @@ -340,6 +340,16 @@ GtkWindowGroup *_gtk_window_get_group (GtkWindow *window); gboolean _gtk_window_activate_key (GtkWindow *window, GdkEventKey *event); +typedef void (*GtkWindowKeysForeachFunc) (GtkWindow *window, + guint keyval, + GdkModifierType modifiers, + gboolean is_mnemonic, + gpointer data); + +void _gtk_window_keys_foreach (GtkWindow *window, + GtkWindowKeysForeachFunc func, + gpointer func_data); + /* --- internal (GtkAcceleratable) --- */ gboolean _gtk_window_query_nonaccels (GtkWindow *window, guint accel_key, diff --git a/gtk/xembed.h b/gtk/xembed.h index d6de700f2a..14d55e604d 100644 --- a/gtk/xembed.h +++ b/gtk/xembed.h @@ -12,6 +12,10 @@ #define XEMBED_MODALITY_ON 10 #define XEMBED_MODALITY_OFF 11 +/* Non standard messages*/ +#define XEMBED_GTK_GRAB_KEY 108 +#define XEMBED_GTK_UNGRAB_KEY 109 + /* Details for XEMBED_FOCUS_IN: */ #define XEMBED_FOCUS_CURRENT 0 #define XEMBED_FOCUS_FIRST 1