X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkplug.c;h=01fc9799e5225122b89be82f71bcc7932ae11edb;hb=d0895d6c0feb6c6ca14bfc05910926051b2bf63b;hp=8fbcfbd820cd48c188f3bef648f0abafd0902ab4;hpb=920e8b434367f9aa8aab306721cc024e66892e2e;p=~andy%2Fgtk diff --git a/gtk/gtkplug.c b/gtk/gtkplug.c index 8fbcfbd82..01fc9799e 100644 --- a/gtk/gtkplug.c +++ b/gtk/gtkplug.c @@ -12,8 +12,7 @@ * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * License along with this library. If not, see .Free */ /* By Owen Taylor 98/4/4 */ @@ -27,44 +26,62 @@ #include "config.h" +#include "gtkdebug.h" #include "gtkmain.h" #include "gtkmarshalers.h" #include "gtkplug.h" #include "gtkintl.h" #include "gtkprivate.h" -#include "gtkplugprivate.h" #include "gtksocketprivate.h" #include "gtkwidgetprivate.h" #include "gtkwindowprivate.h" +#include "gtkxembed.h" -#ifdef GDK_WINDOWING_X11 -#include "x11/gdkx.h" -#endif -#ifdef GDK_WINDOWING_WIN32 -#include "win32/gdkwin32.h" -#endif +#include /** * SECTION:gtkplug * @Short_description: Toplevel for embedding into other processes * @Title: GtkPlug + * @include: gtk/gtkx.h * @See_also: #GtkSocket * - * Together with #GtkSocket, #GtkPlug provides the ability - * to embed widgets from one process into another process - * in a fashion that is transparent to the user. One - * process creates a #GtkSocket widget and passes the - * ID of that widget's window to the other process, - * which then creates a #GtkPlug with that window ID. - * Any widgets contained in the #GtkPlug then will appear - * inside the first application's window. + * Together with #GtkSocket, #GtkPlug provides the ability to embed + * widgets from one process into another process in a fashion that is + * transparent to the user. One process creates a #GtkSocket widget + * and passes the ID of that widget's window to the other process, + * which then creates a #GtkPlug with that window ID. Any widgets + * contained in the #GtkPlug then will appear inside the first + * application's window. + * + * The communication between a #GtkSocket and a #GtkPlug follows the + * XEmbed + * protocol. This protocol has also been implemented in other toolkits, + * e.g. Qt, allowing the same level of + * integration when embedding a Qt widget + * in GTK+ or vice versa. * * - * The #GtkPlug and #GtkSocket widgets are currently not available - * on all platforms supported by GTK+. + * The #GtkPlug and #GtkSocket widgets are only available when GTK+ + * is compiled for the X11 platform and %GDK_WINDOWING_X11 is defined. + * They can only be used on a #GdkX11Display. To use #GtkPlug and + * #GtkSocket, you need to include the gtk/gtkx.h + * header. * */ +struct _GtkPlugPrivate +{ + GtkWidget *modality_window; + GtkWindowGroup *modality_group; + + GdkWindow *socket_window; + + GHashTable *grabbed_keys; + + guint same_app : 1; +}; + static void gtk_plug_get_property (GObject *object, guint prop_id, GValue *value, @@ -89,6 +106,9 @@ static gboolean gtk_plug_focus (GtkWidget *widget, static void gtk_plug_check_resize (GtkContainer *container); static void gtk_plug_keys_changed (GtkWindow *window); +static void xembed_set_info (GdkWindow *window, + unsigned long flags); + static GtkBinClass *bin_class = NULL; typedef struct @@ -162,6 +182,8 @@ gtk_plug_class_init (GtkPlugClass *class) widget_class->focus = gtk_plug_focus; + gtk_widget_class_set_accessible_role (widget_class, ATK_ROLE_PANEL); + container_class->check_resize = gtk_plug_check_resize; window_class->set_focus = gtk_plug_set_focus; @@ -223,6 +245,48 @@ gtk_plug_init (GtkPlug *plug) GtkPlugPrivate); } +/** + * gtk_plug_handle_modality_on: + * @plug: a #GtkPlug + * + * Called from the GtkPlug backend when the corresponding socket has + * told the plug that it modality has toggled on. + */ +static void +gtk_plug_handle_modality_on (GtkPlug *plug) +{ + GtkPlugPrivate *priv = plug->priv; + + if (!priv->modality_window) + { + priv->modality_window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_screen (GTK_WINDOW (priv->modality_window), + gtk_widget_get_screen (GTK_WIDGET (plug))); + gtk_widget_realize (priv->modality_window); + gtk_window_group_add_window (priv->modality_group, GTK_WINDOW (priv->modality_window)); + gtk_grab_add (priv->modality_window); + } +} + +/** + * gtk_plug_handle_modality_off: + * @plug: a #GtkPlug + * + * Called from the GtkPlug backend when the corresponding socket has + * told the plug that it modality has toggled off. + */ +static void +gtk_plug_handle_modality_off (GtkPlug *plug) +{ + GtkPlugPrivate *priv = plug->priv; + + if (priv->modality_window) + { + gtk_widget_destroy (priv->modality_window); + priv->modality_window = NULL; + } +} + static void gtk_plug_set_is_child (GtkPlug *plug, gboolean is_child) @@ -235,7 +299,7 @@ gtk_plug_set_is_child (GtkPlug *plug, if (is_child) { if (priv->modality_window) - _gtk_plug_handle_modality_off (plug); + gtk_plug_handle_modality_off (plug); if (priv->modality_group) { @@ -284,7 +348,7 @@ gtk_plug_set_is_child (GtkPlug *plug, * * Return value: the window ID for the plug **/ -GdkNativeWindow +Window gtk_plug_get_id (GtkPlug *plug) { g_return_val_if_fail (GTK_IS_PLUG (plug), 0); @@ -292,7 +356,7 @@ gtk_plug_get_id (GtkPlug *plug) if (!gtk_widget_get_realized (GTK_WIDGET (plug))) gtk_widget_realize (GTK_WIDGET (plug)); - return _gtk_plug_windowing_get_id (plug); + return GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (plug))); } /** @@ -377,16 +441,16 @@ _gtk_plug_add_to_socket (GtkPlug *plug, g_signal_emit_by_name (socket_, "plug-added"); } -/** - * _gtk_plug_send_delete_event: +/* + * gtk_plug_send_delete_event: * @widget: a #GtkWidget * * Send a GDK_DELETE event to the @widget and destroy it if * necessary. Internal GTK function, called from this file or the * backend-specific GtkPlug implementation. */ -void -_gtk_plug_send_delete_event (GtkWidget *widget) +static void +gtk_plug_send_delete_event (GtkWidget *widget) { GdkEvent *event = gdk_event_new (GDK_DELETE); @@ -466,7 +530,7 @@ _gtk_plug_remove_from_socket (GtkPlug *plug, gtk_widget_destroy (GTK_WIDGET (socket_)); if (window) - _gtk_plug_send_delete_event (widget); + gtk_plug_send_delete_event (widget); g_object_unref (plug); @@ -485,8 +549,8 @@ _gtk_plug_remove_from_socket (GtkPlug *plug, * @socket_id. This function will generally only be used by classes deriving from #GtkPlug. **/ void -gtk_plug_construct (GtkPlug *plug, - GdkNativeWindow socket_id) +gtk_plug_construct (GtkPlug *plug, + Window socket_id) { gtk_plug_construct_for_display (plug, gdk_display_get_default (), socket_id); } @@ -505,9 +569,9 @@ gtk_plug_construct (GtkPlug *plug, * Since: 2.2 **/ void -gtk_plug_construct_for_display (GtkPlug *plug, - GdkDisplay *display, - GdkNativeWindow socket_id) +gtk_plug_construct_for_display (GtkPlug *plug, + GdkDisplay *display, + Window socket_id) { GtkPlugPrivate *priv; @@ -520,11 +584,9 @@ gtk_plug_construct_for_display (GtkPlug *plug, { gpointer user_data = NULL; -#ifdef GDK_WINDOWING_X11 if (GDK_IS_X11_DISPLAY (display)) priv->socket_window = gdk_x11_window_lookup_for_display (display, socket_id); else -#endif priv->socket_window = NULL; if (priv->socket_window) @@ -544,15 +606,8 @@ gtk_plug_construct_for_display (GtkPlug *plug, else g_object_ref (priv->socket_window); } - else -#ifdef GDK_WINDOWING_X11 - if (GDK_IS_X11_DISPLAY (display)) + else if (GDK_IS_X11_DISPLAY (display)) priv->socket_window = gdk_x11_window_foreign_new_for_display (display, socket_id); -#endif -#ifdef GDK_WINDOWING_WIN32 - if (GDK_IS_WIN32_DISPLAY (display)) - priv->socket_window = gdk_win32_window_foreign_new_for_display (display, socket_id); -#endif if (priv->socket_window) { g_signal_emit (plug, plug_signals[EMBEDDED], 0); @@ -573,7 +628,7 @@ gtk_plug_construct_for_display (GtkPlug *plug, * Return value: the new #GtkPlug widget. **/ GtkWidget* -gtk_plug_new (GdkNativeWindow socket_id) +gtk_plug_new (Window socket_id) { return gtk_plug_new_for_display (gdk_display_get_default (), socket_id); } @@ -590,8 +645,8 @@ gtk_plug_new (GdkNativeWindow socket_id) * Since: 2.2 */ GtkWidget* -gtk_plug_new_for_display (GdkDisplay *display, - GdkNativeWindow socket_id) +gtk_plug_new_for_display (GdkDisplay *display, + Window socket_id) { GtkPlug *plug; @@ -609,11 +664,8 @@ gtk_plug_finalize (GObject *object) GtkPlugPrivate *priv = plug->priv; if (priv->grabbed_keys) - { - g_hash_table_destroy (priv->grabbed_keys); - priv->grabbed_keys = NULL; - } - + g_hash_table_destroy (priv->grabbed_keys); + G_OBJECT_CLASS (gtk_plug_parent_class)->finalize (object); } @@ -625,7 +677,7 @@ gtk_plug_unrealize (GtkWidget *widget) if (priv->socket_window != NULL) { - gdk_window_set_user_data (priv->socket_window, NULL); + gtk_widget_unregister_window (widget, priv->socket_window); g_object_unref (priv->socket_window); priv->socket_window = NULL; @@ -635,7 +687,7 @@ gtk_plug_unrealize (GtkWidget *widget) if (!priv->same_app) { if (priv->modality_window) - _gtk_plug_handle_modality_off (plug); + gtk_plug_handle_modality_off (plug); gtk_window_group_remove_window (priv->modality_group, GTK_WINDOW (plug)); g_object_unref (priv->modality_group); @@ -644,6 +696,316 @@ gtk_plug_unrealize (GtkWidget *widget) GTK_WIDGET_CLASS (gtk_plug_parent_class)->unrealize (widget); } +static void +xembed_set_info (GdkWindow *window, + unsigned long flags) +{ + GdkDisplay *display = gdk_window_get_display (window); + unsigned long buffer[2]; + + Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO"); + + buffer[0] = GTK_XEMBED_PROTOCOL_VERSION; + buffer[1] = flags; + + XChangeProperty (GDK_DISPLAY_XDISPLAY (display), + GDK_WINDOW_XID (window), + xembed_info_atom, xembed_info_atom, 32, + PropModeReplace, + (unsigned char *)buffer, 2); +} + +/** + * gtk_plug_focus_first_last: + * @plug: a #GtkPlug + * @direction: a direction + * + * Called from the GtkPlug backend when the corresponding socket has + * told the plug that it has received the focus. + */ +static void +gtk_plug_focus_first_last (GtkPlug *plug, + GtkDirectionType direction) +{ + GtkWindow *window = GTK_WINDOW (plug); + GtkWidget *focus_widget; + GtkWidget *parent; + + focus_widget = gtk_window_get_focus (window); + if (focus_widget) + { + parent = gtk_widget_get_parent (focus_widget); + while (parent) + { + gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL); + parent = gtk_widget_get_parent (parent); + } + + gtk_window_set_focus (GTK_WINDOW (plug), NULL); + } + + gtk_widget_child_focus (GTK_WIDGET (plug), direction); +} + +static void +handle_xembed_message (GtkPlug *plug, + XEmbedMessageType message, + glong detail, + glong data1, + glong data2, + guint32 time) +{ + GtkWindow *window = GTK_WINDOW (plug); + + GTK_NOTE (PLUGSOCKET, + g_message ("GtkPlug: %s received", _gtk_xembed_message_name (message))); + + switch (message) + { + case XEMBED_EMBEDDED_NOTIFY: + break; + case XEMBED_WINDOW_ACTIVATE: + _gtk_window_set_is_active (window, TRUE); + break; + case XEMBED_WINDOW_DEACTIVATE: + _gtk_window_set_is_active (window, FALSE); + break; + + case XEMBED_MODALITY_ON: + gtk_plug_handle_modality_on (plug); + break; + case XEMBED_MODALITY_OFF: + gtk_plug_handle_modality_off (plug); + break; + + case XEMBED_FOCUS_IN: + _gtk_window_set_has_toplevel_focus (window, TRUE); + switch (detail) + { + case XEMBED_FOCUS_FIRST: + gtk_plug_focus_first_last (plug, GTK_DIR_TAB_FORWARD); + break; + case XEMBED_FOCUS_LAST: + gtk_plug_focus_first_last (plug, GTK_DIR_TAB_BACKWARD); + break; + case XEMBED_FOCUS_CURRENT: + break; + } + break; + + case XEMBED_FOCUS_OUT: + _gtk_window_set_has_toplevel_focus (window, FALSE); + 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: + g_warning ("GtkPlug: Invalid _XEMBED message %s received", _gtk_xembed_message_name (message)); + break; + + default: + GTK_NOTE(PLUGSOCKET, + g_message ("GtkPlug: Ignoring unknown _XEMBED message of type %d", message)); + break; + } +} +static GdkFilterReturn +gtk_plug_filter_func (GdkXEvent *gdk_xevent, + GdkEvent *event, + gpointer data) +{ + GdkScreen *screen = gdk_window_get_screen (event->any.window); + GdkDisplay *display = gdk_screen_get_display (screen); + GtkPlug *plug = GTK_PLUG (data); + GtkPlugPrivate *priv = plug->priv; + XEvent *xevent = (XEvent *)gdk_xevent; + GHashTableIter iter; + gpointer key; + GdkFilterReturn return_val; + + return_val = GDK_FILTER_CONTINUE; + + switch (xevent->type) + { + case ClientMessage: + if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED")) + { + _gtk_xembed_push_message (xevent); + handle_xembed_message (plug, + xevent->xclient.data.l[1], + xevent->xclient.data.l[2], + xevent->xclient.data.l[3], + xevent->xclient.data.l[4], + xevent->xclient.data.l[0]); + _gtk_xembed_pop_message (); + + return_val = GDK_FILTER_REMOVE; + } + else if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW")) + { + /* We filter these out because we take being reparented back to the + * root window as the reliable end of the embedding protocol + */ + + return_val = GDK_FILTER_REMOVE; + } + break; + case ReparentNotify: + { + XReparentEvent *xre = &xevent->xreparent; + gboolean was_embedded = priv->socket_window != NULL; + + GTK_NOTE (PLUGSOCKET, g_message("GtkPlug: ReparentNotify received")); + + return_val = GDK_FILTER_REMOVE; + + g_object_ref (plug); + + if (was_embedded) + { + /* End of embedding protocol for previous socket */ + + GTK_NOTE (PLUGSOCKET, g_message ("GtkPlug: end of embedding")); + /* FIXME: race if we remove from another socket and + * then add to a local window before we get notification + * Probably need check in _gtk_plug_add_to_socket + */ + + if (xre->parent != GDK_WINDOW_XID (priv->socket_window)) + { + GtkWidget *widget = GTK_WIDGET (plug); + + gtk_widget_unregister_window (widget, priv->socket_window); + g_object_unref (priv->socket_window); + priv->socket_window = NULL; + + /* Emit a delete window, as if the user attempted + * to close the toplevel. Simple as to how we + * handle WM_DELETE_WINDOW, if it isn't handled + * we destroy the widget. BUt only do this if + * we are being reparented to the root window. + * Moving from one embedder to another should + * be invisible to the app. + */ + + if (xre->parent == GDK_WINDOW_XID (gdk_screen_get_root_window (screen))) + { + GTK_NOTE (PLUGSOCKET, g_message ("GtkPlug: calling gtk_plug_send_delete_event()")); + gtk_plug_send_delete_event (widget); + + g_object_notify (G_OBJECT (plug), "embedded"); + } + } + else + goto done; + } + + if (xre->parent != GDK_WINDOW_XID (gdk_screen_get_root_window (screen))) + { + /* Start of embedding protocol */ + + GTK_NOTE (PLUGSOCKET, g_message ("GtkPlug: start of embedding")); + + priv->socket_window = gdk_x11_window_lookup_for_display (display, xre->parent); + if (priv->socket_window) + { + gpointer user_data = NULL; + gdk_window_get_user_data (priv->socket_window, &user_data); + + if (user_data) + { + g_warning (G_STRLOC "Plug reparented unexpectedly into window in the same process"); + priv->socket_window = NULL; + break; /* FIXME: shouldn't this unref the plug? i.e. "goto done;" instead */ + } + + g_object_ref (priv->socket_window); + } + else + { + priv->socket_window = gdk_x11_window_foreign_new_for_display (display, xre->parent); + if (!priv->socket_window) /* Already gone */ + break; /* FIXME: shouldn't this unref the plug? i.e. "goto done;" instead */ + } + + if (priv->grabbed_keys) + { + g_hash_table_iter_init (&iter, priv->grabbed_keys); + while (g_hash_table_iter_next (&iter, &key, NULL)) + { + GrabbedKey *grabbed_key = key; + + _gtk_xembed_send_message (priv->socket_window, XEMBED_GTK_GRAB_KEY, 0, + grabbed_key->accelerator_key, + grabbed_key->accelerator_mods); + } + } + + if (!was_embedded) + g_signal_emit_by_name (plug, "embedded"); + + g_object_notify (G_OBJECT (plug), "embedded"); + } + + done: + g_object_unref (plug); + + break; + } + case KeyPress: + case KeyRelease: + { + GdkModifierType state, consumed; + GdkDeviceManager *device_manager; + GdkDevice *pointer, *keyboard; + GdkKeymap *keymap; + + if (xevent->type == KeyPress) + event->key.type = GDK_KEY_PRESS; + else + event->key.type = GDK_KEY_RELEASE; + + event->key.window = gdk_x11_window_lookup_for_display (display, xevent->xany.window); + event->key.send_event = TRUE; + event->key.time = xevent->xkey.time; + event->key.state = (GdkModifierType) xevent->xkey.state; + event->key.hardware_keycode = xevent->xkey.keycode; + event->key.keyval = GDK_KEY_VoidSymbol; + + device_manager = gdk_display_get_device_manager (display); + pointer = gdk_device_manager_get_client_pointer (device_manager); + keyboard = gdk_device_get_associated_device (pointer); + gdk_event_set_device (event, keyboard); + + keymap = gdk_keymap_get_for_display (display); + + event->key.group = gdk_x11_keymap_get_group_for_state (keymap, xevent->xkey.state); + event->key.is_modifier = gdk_x11_keymap_key_is_modifier (keymap, event->key.hardware_keycode); + + gdk_keymap_translate_keyboard_state (keymap, + event->key.hardware_keycode, + event->key.state, + event->key.group, + &event->key.keyval, + NULL, NULL, &consumed); + + state = event->key.state & ~consumed; + gdk_keymap_add_virtual_modifiers (keymap, &state); + event->key.state |= state; + + event->key.length = 0; + event->key.string = g_strdup (""); + + return_val = GDK_FILTER_TRANSLATE; + } + } + + return return_val; +} static void gtk_plug_realize (GtkWidget *widget) { @@ -711,13 +1073,13 @@ gtk_plug_realize (GtkWidget *widget) } gdk_window_add_filter (gdk_window, - _gtk_plug_windowing_filter_func, + gtk_plug_filter_func, widget); priv->modality_group = gtk_window_group_new (); gtk_window_group_add_window (priv->modality_group, window); - _gtk_plug_windowing_realize_toplevel (plug); + xembed_set_info (gtk_widget_get_window (GTK_WIDGET (plug)), 0); } else { @@ -726,12 +1088,10 @@ gtk_plug_realize (GtkWidget *widget) gtk_widget_set_window (widget, gdk_window); } - gdk_window_set_user_data (gdk_window, window); + gtk_widget_register_window (widget, gdk_window); gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window); - - gdk_window_enable_synchronized_configure (gdk_window); } static void @@ -765,16 +1125,16 @@ gtk_plug_map (GtkWidget *widget) GtkBin *bin = GTK_BIN (widget); GtkPlug *plug = GTK_PLUG (widget); GtkWidget *child; - + gtk_widget_set_mapped (widget, TRUE); child = gtk_bin_get_child (bin); if (child != NULL && gtk_widget_get_visible (child) && - !gtk_widget_get_mapped (child)) - gtk_widget_map (child); + !gtk_widget_get_mapped (child)) + gtk_widget_map (child); - _gtk_plug_windowing_map_toplevel (plug); + xembed_set_info (gtk_widget_get_window (GTK_WIDGET (plug)), XEMBED_MAPPED); gdk_synthesize_window_state (gtk_widget_get_window (widget), GDK_WINDOW_STATE_WITHDRAWN, @@ -791,6 +1151,7 @@ gtk_plug_unmap (GtkWidget *widget) { GtkPlug *plug = GTK_PLUG (widget); GdkWindow *window; + GtkWidget *child; window = gtk_widget_get_window (widget); @@ -798,7 +1159,11 @@ gtk_plug_unmap (GtkWidget *widget) gdk_window_hide (window); - _gtk_plug_windowing_unmap_toplevel (plug); + child = gtk_bin_get_child (GTK_BIN (widget)); + if (child != NULL) + gtk_widget_unmap (child); + + xembed_set_info (gtk_widget_get_window (GTK_WIDGET (plug)), 0); gdk_synthesize_window_state (window, 0, @@ -871,6 +1236,7 @@ gtk_plug_set_focus (GtkWindow *window, GtkWidget *focus) { GtkPlug *plug = GTK_PLUG (window); + GtkPlugPrivate *priv = plug->priv; GTK_WINDOW_CLASS (gtk_plug_parent_class)->set_focus (window, focus); @@ -878,7 +1244,8 @@ gtk_plug_set_focus (GtkWindow *window, */ if (focus && !gtk_window_has_toplevel_focus (window)) - _gtk_plug_windowing_set_focus (plug); + _gtk_xembed_send_message (priv->socket_window, + XEMBED_REQUEST_FOCUS, 0, 0, 0); } static guint @@ -914,42 +1281,12 @@ add_grabbed_key (gpointer key, gpointer val, gpointer data) if (!priv->grabbed_keys || !g_hash_table_lookup (priv->grabbed_keys, grabbed_key)) { - _gtk_plug_windowing_add_grabbed_key (plug, - grabbed_key->accelerator_key, - grabbed_key->accelerator_mods); + _gtk_xembed_send_message (priv->socket_window, XEMBED_GTK_GRAB_KEY, 0, + grabbed_key->accelerator_key, + grabbed_key->accelerator_mods); } } -static void -add_grabbed_key_always (gpointer key, - gpointer val, - gpointer data) -{ - GrabbedKey *grabbed_key = key; - GtkPlug *plug = data; - - _gtk_plug_windowing_add_grabbed_key (plug, - grabbed_key->accelerator_key, - grabbed_key->accelerator_mods); -} - -/** - * _gtk_plug_add_all_grabbed_keys: - * - * @plug: a #GtkPlug - * - * Calls _gtk_plug_windowing_add_grabbed_key() on all the grabbed keys - * in the @plug. - */ -void -_gtk_plug_add_all_grabbed_keys (GtkPlug *plug) -{ - GtkPlugPrivate *priv = plug->priv; - - if (priv->grabbed_keys) - g_hash_table_foreach (priv->grabbed_keys, add_grabbed_key_always, plug); -} - static void remove_grabbed_key (gpointer key, gpointer val, gpointer data) { @@ -960,9 +1297,9 @@ remove_grabbed_key (gpointer key, gpointer val, gpointer data) if (!priv->grabbed_keys || !g_hash_table_lookup (priv->grabbed_keys, grabbed_key)) { - _gtk_plug_windowing_remove_grabbed_key (plug, - grabbed_key->accelerator_key, - grabbed_key->accelerator_mods); + _gtk_xembed_send_message (priv->socket_window, XEMBED_GTK_UNGRAB_KEY, 0, + grabbed_key->accelerator_key, + grabbed_key->accelerator_mods); } } @@ -1007,11 +1344,39 @@ gtk_plug_keys_changed (GtkWindow *window) if (old_grabbed_keys) { if (priv->socket_window) - g_hash_table_foreach (old_grabbed_keys, remove_grabbed_key, plug); + g_hash_table_foreach (old_grabbed_keys, remove_grabbed_key, plug); g_hash_table_destroy (old_grabbed_keys); } } +static void +gtk_plug_focus_to_parent (GtkPlug *plug, + GtkDirectionType direction) +{ + GtkPlugPrivate *priv = plug->priv; + XEmbedMessageType message; + + switch (direction) + { + case GTK_DIR_UP: + case GTK_DIR_LEFT: + case GTK_DIR_TAB_BACKWARD: + message = XEMBED_FOCUS_PREV; + break; + case GTK_DIR_DOWN: + case GTK_DIR_RIGHT: + case GTK_DIR_TAB_FORWARD: + message = XEMBED_FOCUS_NEXT; + break; + default: + g_assert_not_reached (); + message = XEMBED_FOCUS_PREV; + break; + } + + _gtk_xembed_send_focus_message (priv->socket_window, message, 0); +} + static gboolean gtk_plug_focus (GtkWidget *widget, GtkDirectionType direction) @@ -1057,7 +1422,7 @@ gtk_plug_focus (GtkWidget *widget, } if (!gtk_container_get_focus_child (GTK_CONTAINER (window))) - _gtk_plug_windowing_focus_to_parent (plug, direction); + gtk_plug_focus_to_parent (plug, direction); return FALSE; } @@ -1071,79 +1436,3 @@ gtk_plug_check_resize (GtkContainer *container) GTK_CONTAINER_CLASS (bin_class)->check_resize (container); } -/** - * _gtk_plug_handle_modality_on: - * - * @plug: a #GtkPlug - * - * Called from the GtkPlug backend when the corresponding socket has - * told the plug that it modality has toggled on. - */ -void -_gtk_plug_handle_modality_on (GtkPlug *plug) -{ - GtkPlugPrivate *priv = plug->priv; - - if (!priv->modality_window) - { - priv->modality_window = gtk_window_new (GTK_WINDOW_POPUP); - gtk_window_set_screen (GTK_WINDOW (priv->modality_window), - gtk_widget_get_screen (GTK_WIDGET (plug))); - gtk_widget_realize (priv->modality_window); - gtk_window_group_add_window (priv->modality_group, GTK_WINDOW (priv->modality_window)); - gtk_grab_add (priv->modality_window); - } -} - -/** - * _gtk_plug_handle_modality_off: - * - * @plug: a #GtkPlug - * - * Called from the GtkPlug backend when the corresponding socket has - * told the plug that it modality has toggled off. - */ -void -_gtk_plug_handle_modality_off (GtkPlug *plug) -{ - GtkPlugPrivate *priv = plug->priv; - - if (priv->modality_window) - { - gtk_widget_destroy (priv->modality_window); - priv->modality_window = NULL; - } -} - -/** - * _gtk_plug_focus_first_last: - * - * @plug: a #GtkPlug - * @direction: a direction - * - * Called from the GtkPlug backend when the corresponding socket has - * told the plug that it has received the focus. - */ -void -_gtk_plug_focus_first_last (GtkPlug *plug, - GtkDirectionType direction) -{ - GtkWindow *window = GTK_WINDOW (plug); - GtkWidget *focus_widget; - GtkWidget *parent; - - focus_widget = gtk_window_get_focus (window); - if (focus_widget) - { - parent = gtk_widget_get_parent (focus_widget); - while (parent) - { - gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL); - parent = gtk_widget_get_parent (parent); - } - - gtk_window_set_focus (GTK_WINDOW (plug), NULL); - } - - gtk_widget_child_focus (GTK_WIDGET (plug), direction); -}