summaryrefslogtreecommitdiff
path: root/gtk/gtksocket.c
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2002-02-24 01:52:14 +0000
committerOwen Taylor <otaylor@src.gnome.org>2002-02-24 01:52:14 +0000
commit6a802b24b3308daac4533c5bb19dc8660c4b3ab8 (patch)
tree91ddc37b158ba5d6ba430e4016e8d4b42d81c981 /gtk/gtksocket.c
parentf97ae50153c212d18b03c198046fcd54d6562c97 (diff)
downloadgtk+-6a802b24b3308daac4533c5bb19dc8660c4b3ab8.tar.gz
Implement accelerator propagation using a custom XEMBED_GTK_KEY_GRAB
Sat Feb 23 20:33:29 2002 Owen Taylor <otaylor@redhat.com> * 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.
Diffstat (limited to 'gtk/gtksocket.c')
-rw-r--r--gtk/gtksocket.c246
1 files changed, 125 insertions, 121 deletions
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,
@@ -130,16 +131,31 @@ gtk_socket_get_type (void)
}
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);
}
/**
@@ -337,6 +356,27 @@ gtk_socket_realize (GtkWidget *widget)
}
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)
{
GtkSocket *socket = GTK_SOCKET (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,123 +521,113 @@ 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)
- {
- key.accelerator_key = hardware_keycode;
- key.accelerator_mods = mods;
-
- found_key = g_hash_table_lookup (socket->grabbed_keys, &key);
+ grabbed_key = g_new (GrabbedKey, 1);
+
+ grabbed_key->accel_key = keyval;
+ grabbed_key->accel_mods = modifiers;
- if (found_key)
- {
- g_warning ("GtkSocket: request to add already present grabbed key %u,%#x\n",
- hardware_keycode, mods);
- return;
- }
+ if (gtk_accel_group_find (socket->accel_group,
+ find_accel_key,
+ &grabbed_key))
+ {
+ 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,
GtkSocket *socket)
@@ -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);