diff options
author | Benjamin Otte <otte@redhat.com> | 2011-01-28 12:06:24 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2011-01-28 17:06:07 +0100 |
commit | 1d804004785fb78df40d95afefa0235f39bed5b2 (patch) | |
tree | da77f942a06d61b6579bbd82f952ef9c99aa081e | |
parent | c7f0cffd8a623cee9e057f99b6478ca7d9a30c3a (diff) | |
download | gtk+-1d804004785fb78df40d95afefa0235f39bed5b2.tar.gz |
plug: Merge gtkplug-x11.c back into gtkplug.c
-rw-r--r-- | gtk/Makefile.am | 2 | ||||
-rw-r--r-- | gtk/gtkplug-x11.c | 390 | ||||
-rw-r--r-- | gtk/gtkplug.c | 537 | ||||
-rw-r--r-- | gtk/gtkplugprivate.h | 153 |
4 files changed, 415 insertions, 667 deletions
diff --git a/gtk/Makefile.am b/gtk/Makefile.am index 877ba7cace..1fa1d0417f 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -408,7 +408,6 @@ gtk_private_h_sources = \ gtknumerableiconprivate.h \ gtkpango.h \ gtkpathbar.h \ - gtkplugprivate.h \ gtkprintoperation-private.h \ gtkprintutils.h \ gtkprivate.h \ @@ -724,7 +723,6 @@ endif gtk_use_x11_c_sources = \ gtkplug.c \ - gtkplug-x11.c \ gtksocket.c \ gtksocket-x11.c \ gtkxembed.c \ diff --git a/gtk/gtkplug-x11.c b/gtk/gtkplug-x11.c deleted file mode 100644 index 4e1a7b1429..0000000000 --- a/gtk/gtkplug-x11.c +++ /dev/null @@ -1,390 +0,0 @@ -/* GTK - The GIMP Toolkit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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. - */ - -/* By Owen Taylor <otaylor@gtk.org> 98/4/4 */ - -/* - * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS - * file for a list of people on the GTK+ Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. - */ - -#include "config.h" - -#include "gtkmain.h" -#include "gtkmarshalers.h" -#include "gtkplug.h" -#include "gtkprivate.h" -#include "gtkplugprivate.h" -#include "gtkwindowprivate.h" -#include "gtkdebug.h" - -#include "x11/gdkx.h" - -#include "gtkxembed.h" - -static void xembed_set_info (GdkWindow *window, - unsigned long flags); - -GdkNativeWindow -_gtk_plug_windowing_get_id (GtkPlug *plug) -{ - return GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (plug))); -} - -void -_gtk_plug_windowing_realize_toplevel (GtkPlug *plug) -{ - xembed_set_info (gtk_widget_get_window (GTK_WIDGET (plug)), 0); -} - -void -_gtk_plug_windowing_map_toplevel (GtkPlug *plug) -{ - xembed_set_info (gtk_widget_get_window (GTK_WIDGET (plug)), XEMBED_MAPPED); -} - -void -_gtk_plug_windowing_unmap_toplevel (GtkPlug *plug) -{ - xembed_set_info (gtk_widget_get_window (GTK_WIDGET (plug)), 0); -} - -void -_gtk_plug_windowing_set_focus (GtkPlug *plug) -{ - GtkPlugPrivate *priv = plug->priv; - - _gtk_xembed_send_message (priv->socket_window, - XEMBED_REQUEST_FOCUS, 0, 0, 0); -} - -void -_gtk_plug_windowing_add_grabbed_key (GtkPlug *plug, - guint accelerator_key, - GdkModifierType accelerator_mods) -{ - GtkPlugPrivate *priv = plug->priv; - - _gtk_xembed_send_message (priv->socket_window, XEMBED_GTK_GRAB_KEY, 0, - accelerator_key, accelerator_mods); -} - -void -_gtk_plug_windowing_remove_grabbed_key (GtkPlug *plug, - guint accelerator_key, - GdkModifierType accelerator_mods) -{ - GtkPlugPrivate *priv = plug->priv; - - _gtk_xembed_send_message (priv->socket_window, XEMBED_GTK_UNGRAB_KEY, 0, - accelerator_key, accelerator_mods); -} - -void -_gtk_plug_windowing_focus_to_parent (GtkPlug *plug, - GtkDirectionType direction) -{ - GtkPlugPrivate *priv = plug->priv; - XEmbedMessageType message = XEMBED_FOCUS_PREV; /* Quiet GCC */ - - 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; - } - - _gtk_xembed_send_focus_message (priv->socket_window, message, 0); -} - -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); -} - -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; - } -} - -GdkFilterReturn -_gtk_plug_windowing_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; - - 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); - - gdk_window_set_user_data (priv->socket_window, NULL); - 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 */ - } - - _gtk_plug_add_all_grabbed_keys (plug); - - 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); - 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 (""); - - /* FIXME: These should be filled in properly */ - event->key.group = 0; - event->key.is_modifier = FALSE; - - return_val = GDK_FILTER_TRANSLATE; - } - } - - return return_val; -} diff --git a/gtk/gtkplug.c b/gtk/gtkplug.c index 0ccb6de8d1..1c5d6bead2 100644 --- a/gtk/gtkplug.c +++ b/gtk/gtkplug.c @@ -27,15 +27,16 @@ #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" #include <gdk/gdkx.h> @@ -67,6 +68,18 @@ * </note> */ +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, @@ -91,6 +104,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 @@ -225,6 +241,50 @@ 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) @@ -237,7 +297,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) { @@ -294,7 +354,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))); } /** @@ -628,7 +688,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); @@ -638,6 +698,315 @@ gtk_plug_unrealize (GtkWidget *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); + + gdk_window_set_user_data (priv->socket_window, NULL); + 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 */ + } + + 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); + 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 (""); + + /* FIXME: These should be filled in properly */ + event->key.group = 0; + event->key.is_modifier = FALSE; + + return_val = GDK_FILTER_TRANSLATE; + } + } + + return return_val; +} +static void gtk_plug_realize (GtkWidget *widget) { GtkAllocation allocation; @@ -704,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 { @@ -767,7 +1136,7 @@ gtk_plug_map (GtkWidget *widget) !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,7 +1160,7 @@ gtk_plug_unmap (GtkWidget *widget) gdk_window_hide (window); - _gtk_plug_windowing_unmap_toplevel (plug); + xembed_set_info (gtk_widget_get_window (GTK_WIDGET (plug)), 0); gdk_synthesize_window_state (window, 0, @@ -864,6 +1233,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); @@ -871,7 +1241,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 @@ -907,43 +1278,13 @@ 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) { GrabbedKey *grabbed_key = key; @@ -953,9 +1294,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); } } @@ -1005,6 +1346,34 @@ gtk_plug_keys_changed (GtkWindow *window) } } +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) @@ -1050,7 +1419,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; } @@ -1064,79 +1433,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); -} diff --git a/gtk/gtkplugprivate.h b/gtk/gtkplugprivate.h deleted file mode 100644 index 68a2fe15c7..0000000000 --- a/gtk/gtkplugprivate.h +++ /dev/null @@ -1,153 +0,0 @@ -/* GTK - The GIMP Toolkit - * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * 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. - */ - -/* - * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS - * file for a list of people on the GTK+ Team. See the ChangeLog - * files for a list of changes. These files are distributed with - * GTK+ at ftp://ftp.gtk.org/pub/gtk/. - */ - -#ifndef __GTK_PLUG_PRIVATE_H__ -#define __GTK_PLUG_PRIVATE_H__ - -struct _GtkPlugPrivate -{ - GtkWidget *modality_window; - GtkWindowGroup *modality_group; - - GdkWindow *socket_window; - - GHashTable *grabbed_keys; - - guint same_app : 1; -}; - -/* In gtkplug.c: */ -void _gtk_plug_send_delete_event (GtkWidget *widget); -void _gtk_plug_add_all_grabbed_keys (GtkPlug *plug); -void _gtk_plug_focus_first_last (GtkPlug *plug, - GtkDirectionType direction); -void _gtk_plug_handle_modality_on (GtkPlug *plug); -void _gtk_plug_handle_modality_off (GtkPlug *plug); - -/* In backend-specific file: */ - -/* - * _gtk_plug_windowing_get_id: - * - * @plug: a #GtkPlug - * - * Returns the native window system identifier for the plug's window. - */ -GdkNativeWindow _gtk_plug_windowing_get_id (GtkPlug *plug); - -/* - * _gtk_plug_windowing_realize_toplevel: - * - * @plug_window: a #GtkPlug's #GdkWindow - * - * Called from GtkPlug's realize method. Should tell the corresponding - * socket that the plug has been realized. - */ -void _gtk_plug_windowing_realize_toplevel (GtkPlug *plug); - -/* - * _gtk_plug_windowing_map_toplevel: - * - * @plug: a #GtkPlug - * - * Called from GtkPlug's map method. Should tell the corresponding - * #GtkSocket that the plug has been mapped. - */ -void _gtk_plug_windowing_map_toplevel (GtkPlug *plug); - -/* - * _gtk_plug_windowing_map_toplevel: - * - * @plug: a #GtkPlug - * - * Called from GtkPlug's unmap method. Should tell the corresponding - * #GtkSocket that the plug has been unmapped. - */ -void _gtk_plug_windowing_unmap_toplevel (GtkPlug *plug); - -/* - * _gtk_plug_windowing_set_focus: - * - * @plug: a #GtkPlug - * - * Called from GtkPlug's set_focus method. Should tell the corresponding - * #GtkSocket to request focus. - */ -void _gtk_plug_windowing_set_focus (GtkPlug *plug); - -/* - * _gtk_plug_windowing_add_grabbed_key: - * - * @plug: a #GtkPlug - * @accelerator_key: a key - * @accelerator_mods: modifiers for it - * - * Called from GtkPlug's keys_changed method. Should tell the - * corresponding #GtkSocket to grab the key. - */ -void _gtk_plug_windowing_add_grabbed_key (GtkPlug *plug, - guint accelerator_key, - GdkModifierType accelerator_mods); - -/* - * _gtk_plug_windowing_remove_grabbed_key: - * - * @plug: a #GtkPlug - * @accelerator_key: a key - * @accelerator_mods: modifiers for it - * - * Called from GtkPlug's keys_changed method. Should tell the - * corresponding #GtkSocket to remove the key grab. - */ -void _gtk_plug_windowing_remove_grabbed_key (GtkPlug *plug, - guint accelerator_key, - GdkModifierType accelerator_mods); - -/* - * _gtk_plug_windowing_focus_to_parent: - * - * @plug: a #GtkPlug - * @direction: a direction - * - * Called from GtkPlug's focus method. Should tell the corresponding - * #GtkSocket to move the focus. - */ -void _gtk_plug_windowing_focus_to_parent (GtkPlug *plug, - GtkDirectionType direction); - -/* - * _gtk_plug_windowing_filter_func: - * - * @gdk_xevent: a windowing system native event - * @event: a pre-allocated empty GdkEvent - * @data: the #GtkPlug - * - * Event filter function installed on plug windows. - */ -GdkFilterReturn _gtk_plug_windowing_filter_func (GdkXEvent *gdk_xevent, - GdkEvent *event, - gpointer data); - -#endif /* __GTK_PLUG_PRIVATE_H__ */ |