1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* By Owen Taylor <otaylor@gtk.org> 98/4/4 */
22 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
30 #include "gtksocket.h"
35 #include "gtkmarshalers.h"
36 #include "gtksizerequest.h"
37 #include "gtkwindowprivate.h"
39 #include "gtkprivate.h"
40 #include "gtksocketprivate.h"
44 #include "gtkwidgetprivate.h"
46 #ifdef GDK_WINDOWING_X11
53 * @Short_description: Container for widgets from other processes
55 * @See_also: #GtkPlug, <ulink url="http://www.freedesktop.org/Standards/xembed-spec">XEmbed</ulink>
57 * Together with #GtkPlug, #GtkSocket provides the ability
58 * to embed widgets from one process into another process
59 * in a fashion that is transparent to the user. One
60 * process creates a #GtkSocket widget and passes
61 * that widget's window ID to the other process,
62 * which then creates a #GtkPlug with that window ID.
63 * Any widgets contained in the #GtkPlug then will appear
64 * inside the first application's window.
66 * The socket's window ID is obtained by using
67 * gtk_socket_get_id(). Before using this function,
68 * the socket must have been realized, and for hence,
69 * have been added to its parent.
72 * <title>Obtaining the window ID of a socket.</title>
74 * GtkWidget *socket = gtk_socket_new (<!-- -->);
75 * gtk_widget_show (socket);
76 * gtk_container_add (GTK_CONTAINER (parent), socket);
78 * /<!---->* The following call is only necessary if one of
79 * * the ancestors of the socket is not yet visible.
81 * gtk_widget_realize (socket);
82 * g_print ("The ID of the sockets window is %#x\n",
83 * gtk_socket_get_id (socket));
87 * Note that if you pass the window ID of the socket to another
88 * process that will create a plug in the socket, you
89 * must make sure that the socket widget is not destroyed
90 * until that plug is created. Violating this rule will
91 * cause unpredictable consequences, the most likely
92 * consequence being that the plug will appear as a
93 * separate toplevel window. You can check if the plug
94 * has been created by using gtk_socket_get_plug_window(). If
95 * it returns a non-%NULL value, then the plug has been
96 * successfully created inside of the socket.
98 * When GTK+ is notified that the embedded window has been
99 * destroyed, then it will destroy the socket as well. You
100 * should always, therefore, be prepared for your sockets
101 * to be destroyed at any time when the main event loop
102 * is running. To prevent this from happening, you can
103 * connect to the #GtkSocket::plug-removed signal.
105 * The communication between a #GtkSocket and a #GtkPlug follows the
106 * <ulink url="http://www.freedesktop.org/Standards/xembed-spec">XEmbed</ulink>
107 * protocol. This protocol has also been implemented in other toolkits, e.g.
108 * <application>Qt</application>, allowing the same level of integration
109 * when embedding a <application>Qt</application> widget in GTK or vice versa.
112 * The #GtkPlug and #GtkSocket widgets are currently not available
113 * on all platforms supported by GTK+.
117 /* Forward declararations */
119 static void gtk_socket_finalize (GObject *object);
120 static void gtk_socket_notify (GObject *object,
122 static void gtk_socket_realize (GtkWidget *widget);
123 static void gtk_socket_unrealize (GtkWidget *widget);
124 static void gtk_socket_get_preferred_width (GtkWidget *widget,
127 static void gtk_socket_get_preferred_height (GtkWidget *widget,
130 static void gtk_socket_size_allocate (GtkWidget *widget,
131 GtkAllocation *allocation);
132 static void gtk_socket_hierarchy_changed (GtkWidget *widget,
133 GtkWidget *old_toplevel);
134 static void gtk_socket_grab_notify (GtkWidget *widget,
135 gboolean was_grabbed);
136 static gboolean gtk_socket_key_event (GtkWidget *widget,
138 static gboolean gtk_socket_focus (GtkWidget *widget,
139 GtkDirectionType direction);
140 static void gtk_socket_remove (GtkContainer *container,
142 static void gtk_socket_forall (GtkContainer *container,
143 gboolean include_internals,
144 GtkCallback callback,
145 gpointer callback_data);
153 GdkModifierType accel_mods;
162 static guint socket_signals[LAST_SIGNAL] = { 0 };
164 G_DEFINE_TYPE (GtkSocket, gtk_socket, GTK_TYPE_CONTAINER)
167 gtk_socket_finalize (GObject *object)
169 GtkSocket *socket = GTK_SOCKET (object);
170 GtkSocketPrivate *priv = socket->priv;
172 g_object_unref (priv->accel_group);
174 G_OBJECT_CLASS (gtk_socket_parent_class)->finalize (object);
178 gtk_socket_class_init (GtkSocketClass *class)
180 GtkWidgetClass *widget_class;
181 GtkContainerClass *container_class;
182 GObjectClass *gobject_class;
184 gobject_class = (GObjectClass *) class;
185 widget_class = (GtkWidgetClass*) class;
186 container_class = (GtkContainerClass*) class;
188 gobject_class->finalize = gtk_socket_finalize;
189 gobject_class->notify = gtk_socket_notify;
191 widget_class->realize = gtk_socket_realize;
192 widget_class->unrealize = gtk_socket_unrealize;
193 widget_class->get_preferred_width = gtk_socket_get_preferred_width;
194 widget_class->get_preferred_height = gtk_socket_get_preferred_height;
195 widget_class->size_allocate = gtk_socket_size_allocate;
196 widget_class->hierarchy_changed = gtk_socket_hierarchy_changed;
197 widget_class->grab_notify = gtk_socket_grab_notify;
198 widget_class->key_press_event = gtk_socket_key_event;
199 widget_class->key_release_event = gtk_socket_key_event;
200 widget_class->focus = gtk_socket_focus;
202 /* We don't want to show_all the in-process plug, if any.
204 widget_class->show_all = gtk_widget_show;
206 container_class->remove = gtk_socket_remove;
207 container_class->forall = gtk_socket_forall;
210 * GtkSocket::plug-added:
211 * @socket_: the object which received the signal
213 * This signal is emitted when a client is successfully
214 * added to the socket.
216 socket_signals[PLUG_ADDED] =
217 g_signal_new (I_("plug-added"),
218 G_OBJECT_CLASS_TYPE (class),
220 G_STRUCT_OFFSET (GtkSocketClass, plug_added),
222 _gtk_marshal_VOID__VOID,
226 * GtkSocket::plug-removed:
227 * @socket_: the object which received the signal
229 * This signal is emitted when a client is removed from the socket.
230 * The default action is to destroy the #GtkSocket widget, so if you
231 * want to reuse it you must add a signal handler that returns %TRUE.
233 * Return value: %TRUE to stop other handlers from being invoked.
235 socket_signals[PLUG_REMOVED] =
236 g_signal_new (I_("plug-removed"),
237 G_OBJECT_CLASS_TYPE (class),
239 G_STRUCT_OFFSET (GtkSocketClass, plug_removed),
240 _gtk_boolean_handled_accumulator, NULL,
241 _gtk_marshal_BOOLEAN__VOID,
244 g_type_class_add_private (gobject_class, sizeof (GtkSocketPrivate));
248 gtk_socket_init (GtkSocket *socket)
250 GtkSocketPrivate *priv;
252 priv = G_TYPE_INSTANCE_GET_PRIVATE (socket,
256 priv->request_width = 0;
257 priv->request_height = 0;
258 priv->current_width = 0;
259 priv->current_height = 0;
261 priv->plug_window = NULL;
262 priv->plug_widget = NULL;
263 priv->focus_in = FALSE;
264 priv->have_size = FALSE;
265 priv->need_map = FALSE;
266 priv->active = FALSE;
268 priv->accel_group = gtk_accel_group_new ();
269 g_object_set_data (G_OBJECT (priv->accel_group), I_("gtk-socket"), socket);
275 * Create a new empty #GtkSocket.
277 * Return value: the new #GtkSocket.
280 gtk_socket_new (void)
284 socket = g_object_new (GTK_TYPE_SOCKET, NULL);
286 return GTK_WIDGET (socket);
291 * @socket_: a #GtkSocket
292 * @window_id: the window ID of a client participating in the XEMBED protocol.
294 * Adds an XEMBED client, such as a #GtkPlug, to the #GtkSocket. The
295 * client may be in the same process or in a different process.
297 * To embed a #GtkPlug in a #GtkSocket, you can either create the
298 * #GtkPlug with <literal>gtk_plug_new (0)</literal>, call
299 * gtk_plug_get_id() to get the window ID of the plug, and then pass that to the
300 * gtk_socket_add_id(), or you can call gtk_socket_get_id() to get the
301 * window ID for the socket, and call gtk_plug_new() passing in that
304 * The #GtkSocket must have already be added into a toplevel window
305 * before you can make this call.
308 gtk_socket_add_id (GtkSocket *socket,
309 GdkNativeWindow window_id)
311 g_return_if_fail (GTK_IS_SOCKET (socket));
312 g_return_if_fail (_gtk_widget_get_anchored (GTK_WIDGET (socket)));
314 if (!gtk_widget_get_realized (GTK_WIDGET (socket)))
315 gtk_widget_realize (GTK_WIDGET (socket));
317 _gtk_socket_add_window (socket, window_id, TRUE);
322 * @socket_: a #GtkSocket.
324 * Gets the window ID of a #GtkSocket widget, which can then
325 * be used to create a client embedded inside the socket, for
326 * instance with gtk_plug_new().
328 * The #GtkSocket must have already be added into a toplevel window
329 * before you can make this call.
331 * Return value: the window ID for the socket
334 gtk_socket_get_id (GtkSocket *socket)
336 g_return_val_if_fail (GTK_IS_SOCKET (socket), 0);
337 g_return_val_if_fail (_gtk_widget_get_anchored (GTK_WIDGET (socket)), 0);
339 if (!gtk_widget_get_realized (GTK_WIDGET (socket)))
340 gtk_widget_realize (GTK_WIDGET (socket));
342 return _gtk_socket_windowing_get_id (socket);
346 * gtk_socket_get_plug_window:
347 * @socket_: a #GtkSocket.
349 * Retrieves the window of the plug. Use this to check if the plug has
350 * been created inside of the socket.
352 * Return value: (transfer none): the window of the plug if available, or %NULL
357 gtk_socket_get_plug_window (GtkSocket *socket)
359 g_return_val_if_fail (GTK_IS_SOCKET (socket), NULL);
361 return socket->priv->plug_window;
365 gtk_socket_realize (GtkWidget *widget)
367 GtkAllocation allocation;
368 GtkSocket *socket = GTK_SOCKET (widget);
370 GdkWindowAttr attributes;
371 gint attributes_mask;
373 gtk_widget_set_realized (widget, TRUE);
375 gtk_widget_get_allocation (widget, &allocation);
377 attributes.window_type = GDK_WINDOW_CHILD;
378 attributes.x = allocation.x;
379 attributes.y = allocation.y;
380 attributes.width = allocation.width;
381 attributes.height = allocation.height;
382 attributes.wclass = GDK_INPUT_OUTPUT;
383 attributes.visual = gtk_widget_get_visual (widget);
384 attributes.event_mask = GDK_FOCUS_CHANGE_MASK;
386 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
388 window = gdk_window_new (gtk_widget_get_parent_window (widget),
389 &attributes, attributes_mask);
390 gtk_widget_set_window (widget, window);
391 gdk_window_set_user_data (window, socket);
393 gtk_style_context_set_background (gtk_widget_get_style_context (widget),
396 _gtk_socket_windowing_realize_window (socket);
398 gdk_window_add_filter (window,
399 _gtk_socket_windowing_filter_func,
402 /* We sync here so that we make sure that if the XID for
403 * our window is passed to another application, SubstructureRedirectMask
404 * will be set by the time the other app creates its window.
406 gdk_display_sync (gtk_widget_get_display (widget));
410 * _gtk_socket_end_embedding:
412 * @socket: a #GtkSocket
414 * Called to end the embedding of a plug in the socket.
417 _gtk_socket_end_embedding (GtkSocket *socket)
419 GtkSocketPrivate *private = socket->priv;
420 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
422 if (GTK_IS_WINDOW (toplevel))
423 _gtk_socket_windowing_end_embedding_toplevel (socket);
425 g_object_unref (private->plug_window);
426 private->plug_window = NULL;
427 private->current_width = 0;
428 private->current_height = 0;
429 private->resize_count = 0;
431 gtk_accel_group_disconnect (private->accel_group, NULL);
435 gtk_socket_unrealize (GtkWidget *widget)
437 GtkSocket *socket = GTK_SOCKET (widget);
438 GtkSocketPrivate *private = socket->priv;
440 gtk_widget_set_realized (widget, FALSE);
442 if (private->plug_widget)
444 _gtk_plug_remove_from_socket (GTK_PLUG (private->plug_widget), socket);
446 else if (private->plug_window)
448 _gtk_socket_end_embedding (socket);
451 GTK_WIDGET_CLASS (gtk_socket_parent_class)->unrealize (widget);
455 gtk_socket_get_preferred_width (GtkWidget *widget,
459 GtkSocket *socket = GTK_SOCKET (widget);
460 GtkSocketPrivate *private = socket->priv;
462 if (private->plug_widget)
464 gtk_widget_get_preferred_width (private->plug_widget, minimum, natural);
468 if (private->is_mapped && !private->have_size && private->plug_window)
469 _gtk_socket_windowing_size_request (socket);
471 if (private->is_mapped && private->have_size)
472 *minimum = *natural = MAX (private->request_width, 1);
474 *minimum = *natural = 1;
479 gtk_socket_get_preferred_height (GtkWidget *widget,
483 GtkSocket *socket = GTK_SOCKET (widget);
484 GtkSocketPrivate *private = socket->priv;
486 if (private->plug_widget)
488 gtk_widget_get_preferred_height (private->plug_widget, minimum, natural);
492 if (private->is_mapped && !private->have_size && private->plug_window)
493 _gtk_socket_windowing_size_request (socket);
495 if (private->is_mapped && private->have_size)
496 *minimum = *natural = MAX (private->request_height, 1);
498 *minimum = *natural = 1;
503 gtk_socket_size_allocate (GtkWidget *widget,
504 GtkAllocation *allocation)
506 GtkSocket *socket = GTK_SOCKET (widget);
507 GtkSocketPrivate *private = socket->priv;
509 gtk_widget_set_allocation (widget, allocation);
510 if (gtk_widget_get_realized (widget))
512 gdk_window_move_resize (gtk_widget_get_window (widget),
513 allocation->x, allocation->y,
514 allocation->width, allocation->height);
516 if (private->plug_widget)
518 GtkAllocation child_allocation;
520 child_allocation.x = 0;
521 child_allocation.y = 0;
522 child_allocation.width = allocation->width;
523 child_allocation.height = allocation->height;
525 gtk_widget_size_allocate (private->plug_widget, &child_allocation);
527 else if (private->plug_window)
529 gdk_error_trap_push ();
531 if (allocation->width != private->current_width ||
532 allocation->height != private->current_height)
534 gdk_window_move_resize (private->plug_window,
536 allocation->width, allocation->height);
537 if (private->resize_count)
538 private->resize_count--;
540 GTK_NOTE (PLUGSOCKET,
541 g_message ("GtkSocket - allocated: %d %d",
542 allocation->width, allocation->height));
543 private->current_width = allocation->width;
544 private->current_height = allocation->height;
547 if (private->need_map)
549 gdk_window_show (private->plug_window);
550 private->need_map = FALSE;
553 while (private->resize_count)
555 _gtk_socket_windowing_send_configure_event (socket);
556 private->resize_count--;
557 GTK_NOTE (PLUGSOCKET,
558 g_message ("GtkSocket - sending synthetic configure: %d %d",
559 allocation->width, allocation->height));
562 gdk_error_trap_pop_ignored ();
568 activate_key (GtkAccelGroup *accel_group,
569 GObject *acceleratable,
571 GdkModifierType accel_mods,
572 GrabbedKey *grabbed_key)
574 GdkEvent *gdk_event = gtk_get_current_event ();
576 GtkSocket *socket = g_object_get_data (G_OBJECT (accel_group), "gtk-socket");
577 gboolean retval = FALSE;
579 if (gdk_event && gdk_event->type == GDK_KEY_PRESS && socket->priv->plug_window)
581 _gtk_socket_windowing_send_key_event (socket, gdk_event, FALSE);
586 gdk_event_free (gdk_event);
592 find_accel_key (GtkAccelKey *key,
596 GrabbedKey *grabbed_key = data;
598 return (key->accel_key == grabbed_key->accel_key &&
599 key->accel_mods == grabbed_key->accel_mods);
603 * _gtk_socket_add_grabbed_key:
605 * @socket: a #GtkSocket
607 * @modifiers: modifiers for the key
609 * Called from the GtkSocket platform-specific backend when the
610 * corresponding plug has told the socket to grab a key.
613 _gtk_socket_add_grabbed_key (GtkSocket *socket,
615 GdkModifierType modifiers)
618 GrabbedKey *grabbed_key;
620 grabbed_key = g_new (GrabbedKey, 1);
622 grabbed_key->accel_key = keyval;
623 grabbed_key->accel_mods = modifiers;
625 if (gtk_accel_group_find (socket->priv->accel_group,
629 g_warning ("GtkSocket: request to add already present grabbed key %u,%#x\n",
631 g_free (grabbed_key);
635 closure = g_cclosure_new (G_CALLBACK (activate_key), grabbed_key, (GClosureNotify)g_free);
637 gtk_accel_group_connect (socket->priv->accel_group, keyval, modifiers, GTK_ACCEL_LOCKED,
642 * _gtk_socket_remove_grabbed_key:
644 * @socket: a #GtkSocket
646 * @modifiers: modifiers for the key
648 * Called from the GtkSocket backend when the corresponding plug has
649 * told the socket to remove a key grab.
652 _gtk_socket_remove_grabbed_key (GtkSocket *socket,
654 GdkModifierType modifiers)
656 if (!gtk_accel_group_disconnect_key (socket->priv->accel_group, keyval, modifiers))
657 g_warning ("GtkSocket: request to remove non-present grabbed key %u,%#x\n",
662 socket_update_focus_in (GtkSocket *socket)
664 GtkSocketPrivate *private = socket->priv;
665 gboolean focus_in = FALSE;
667 if (private->plug_window)
669 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
671 if (gtk_widget_is_toplevel (toplevel) &&
672 gtk_window_has_toplevel_focus (GTK_WINDOW (toplevel)) &&
673 gtk_widget_is_focus (GTK_WIDGET (socket)))
677 if (focus_in != private->focus_in)
679 private->focus_in = focus_in;
681 _gtk_socket_windowing_focus_change (socket, focus_in);
686 socket_update_active (GtkSocket *socket)
688 GtkSocketPrivate *private = socket->priv;
689 gboolean active = FALSE;
691 if (private->plug_window)
693 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
695 if (gtk_widget_is_toplevel (toplevel) &&
696 gtk_window_is_active (GTK_WINDOW (toplevel)))
700 if (active != private->active)
702 private->active = active;
704 _gtk_socket_windowing_update_active (socket, active);
709 gtk_socket_hierarchy_changed (GtkWidget *widget,
710 GtkWidget *old_toplevel)
712 GtkSocket *socket = GTK_SOCKET (widget);
713 GtkSocketPrivate *private = socket->priv;
714 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
716 if (toplevel && !GTK_IS_WINDOW (toplevel))
719 if (toplevel != private->toplevel)
721 if (private->toplevel)
723 gtk_window_remove_accel_group (GTK_WINDOW (private->toplevel), private->accel_group);
724 g_signal_handlers_disconnect_by_func (private->toplevel,
725 socket_update_focus_in,
727 g_signal_handlers_disconnect_by_func (private->toplevel,
728 socket_update_active,
732 private->toplevel = toplevel;
736 gtk_window_add_accel_group (GTK_WINDOW (private->toplevel), private->accel_group);
737 g_signal_connect_swapped (private->toplevel, "notify::has-toplevel-focus",
738 G_CALLBACK (socket_update_focus_in), socket);
739 g_signal_connect_swapped (private->toplevel, "notify::is-active",
740 G_CALLBACK (socket_update_active), socket);
743 socket_update_focus_in (socket);
744 socket_update_active (socket);
749 gtk_socket_grab_notify (GtkWidget *widget,
750 gboolean was_grabbed)
752 GtkSocket *socket = GTK_SOCKET (widget);
754 if (!socket->priv->same_app)
755 _gtk_socket_windowing_update_modality (socket, !was_grabbed);
759 gtk_socket_key_event (GtkWidget *widget,
762 GtkSocket *socket = GTK_SOCKET (widget);
763 GtkSocketPrivate *private = socket->priv;
765 if (gtk_widget_has_focus (widget) && private->plug_window && !private->plug_widget)
767 _gtk_socket_windowing_send_key_event (socket, (GdkEvent *) event, FALSE);
776 gtk_socket_notify (GObject *object,
779 if (!strcmp (pspec->name, "is-focus"))
781 socket_update_focus_in (GTK_SOCKET (object));
785 * _gtk_socket_claim_focus:
787 * @socket: a #GtkSocket
790 * Claims focus for the socket. XXX send_event?
793 _gtk_socket_claim_focus (GtkSocket *socket,
796 GtkWidget *widget = GTK_WIDGET (socket);
797 GtkSocketPrivate *private = socket->priv;
800 private->focus_in = TRUE; /* Otherwise, our notify handler will send FOCUS_IN */
802 /* Oh, the trickery... */
804 gtk_widget_set_can_focus (widget, TRUE);
805 gtk_widget_grab_focus (widget);
806 gtk_widget_set_can_focus (widget, FALSE);
810 gtk_socket_focus (GtkWidget *widget,
811 GtkDirectionType direction)
813 GtkSocket *socket = GTK_SOCKET (widget);
814 GtkSocketPrivate *private = socket->priv;
816 if (private->plug_widget)
817 return gtk_widget_child_focus (private->plug_widget, direction);
819 if (!gtk_widget_is_focus (widget))
821 _gtk_socket_windowing_focus (socket, direction);
822 _gtk_socket_claim_focus (socket, FALSE);
831 gtk_socket_remove (GtkContainer *container,
834 GtkSocket *socket = GTK_SOCKET (container);
835 GtkSocketPrivate *private = socket->priv;
837 g_return_if_fail (child == private->plug_widget);
839 _gtk_plug_remove_from_socket (GTK_PLUG (private->plug_widget), socket);
843 gtk_socket_forall (GtkContainer *container,
844 gboolean include_internals,
845 GtkCallback callback,
846 gpointer callback_data)
848 GtkSocket *socket = GTK_SOCKET (container);
849 GtkSocketPrivate *private = socket->priv;
851 if (private->plug_widget)
852 (* callback) (private->plug_widget, callback_data);
856 * _gtk_socket_add_window:
858 * @socket: a #GtkSocket
859 * @xid: the native identifier for a window
860 * @need_reparent: whether the socket's plug's window needs to be
861 * reparented to the socket
863 * Adds a window to a GtkSocket.
866 _gtk_socket_add_window (GtkSocket *socket,
868 gboolean need_reparent)
870 GtkWidget *widget = GTK_WIDGET (socket);
871 GdkDisplay *display = gtk_widget_get_display (widget);
872 gpointer user_data = NULL;
873 GtkSocketPrivate *private = socket->priv;
875 #ifdef GDK_WINDOWING_X11
876 if (GDK_IS_X11_DISPLAY (display))
877 private->plug_window = gdk_x11_window_lookup_for_display (display, xid);
880 private->plug_window = NULL;
882 if (private->plug_window)
884 g_object_ref (private->plug_window);
885 gdk_window_get_user_data (private->plug_window, &user_data);
888 if (user_data) /* A widget's window in this process */
890 GtkWidget *child_widget = user_data;
892 if (!GTK_IS_PLUG (child_widget))
894 g_warning (G_STRLOC ": Can't add non-GtkPlug to GtkSocket");
895 private->plug_window = NULL;
896 gdk_error_trap_pop_ignored ();
901 _gtk_plug_add_to_socket (GTK_PLUG (child_widget), socket);
903 else /* A foreign window */
906 GdkDragProtocol protocol;
908 gdk_error_trap_push ();
910 if (!private->plug_window)
912 #ifdef GDK_WINDOWING_X11
913 if (GDK_IS_X11_DISPLAY (display))
914 private->plug_window = gdk_x11_window_foreign_new_for_display (display, xid);
916 if (!private->plug_window) /* was deleted before we could get it */
918 gdk_error_trap_pop_ignored ();
923 _gtk_socket_windowing_select_plug_window_input (socket);
925 if (gdk_error_trap_pop ())
927 g_object_unref (private->plug_window);
928 private->plug_window = NULL;
932 /* OK, we now will reliably get destroy notification on socket->plug_window */
934 gdk_error_trap_push ();
938 gdk_window_hide (private->plug_window); /* Shouldn't actually be necessary for XEMBED, but just in case */
939 gdk_window_reparent (private->plug_window,
940 gtk_widget_get_window (widget),
944 private->have_size = FALSE;
946 _gtk_socket_windowing_embed_get_info (socket);
948 private->need_map = private->is_mapped;
950 if (gdk_drag_get_protocol_for_display (display, xid, &protocol))
951 gtk_drag_dest_set_proxy (GTK_WIDGET (socket), private->plug_window,
954 gdk_error_trap_pop_ignored ();
956 gdk_window_add_filter (private->plug_window,
957 _gtk_socket_windowing_filter_func,
960 /* Add a pointer to the socket on our toplevel window */
962 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
963 if (GTK_IS_WINDOW (toplevel))
964 gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid);
966 _gtk_socket_windowing_embed_notify (socket);
968 socket_update_active (socket);
969 socket_update_focus_in (socket);
971 gtk_widget_queue_resize (GTK_WIDGET (socket));
974 if (private->plug_window)
975 g_signal_emit (socket, socket_signals[PLUG_ADDED], 0);
979 * _gtk_socket_handle_map_request:
981 * @socket: a #GtkSocket
983 * Called from the GtkSocket backend when the plug has been mapped.
986 _gtk_socket_handle_map_request (GtkSocket *socket)
988 GtkSocketPrivate *private = socket->priv;
989 if (!private->is_mapped)
991 private->is_mapped = TRUE;
992 private->need_map = TRUE;
994 gtk_widget_queue_resize (GTK_WIDGET (socket));
999 * _gtk_socket_unmap_notify:
1001 * @socket: a #GtkSocket
1003 * Called from the GtkSocket backend when the plug has been unmapped ???
1006 _gtk_socket_unmap_notify (GtkSocket *socket)
1008 GtkSocketPrivate *private = socket->priv;
1009 if (private->is_mapped)
1011 private->is_mapped = FALSE;
1012 gtk_widget_queue_resize (GTK_WIDGET (socket));
1017 * _gtk_socket_advance_toplevel_focus:
1019 * @socket: a #GtkSocket
1020 * @direction: a direction
1022 * Called from the GtkSocket backend when the corresponding plug
1023 * has told the socket to move the focus.
1026 _gtk_socket_advance_toplevel_focus (GtkSocket *socket,
1027 GtkDirectionType direction)
1031 GtkContainer *container;
1033 GtkWidget *focus_widget;
1034 GtkWidget *toplevel;
1035 GtkWidget *old_focus_child;
1038 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
1042 if (!gtk_widget_is_toplevel (toplevel) || GTK_IS_PLUG (toplevel))
1044 gtk_widget_child_focus (toplevel,direction);
1048 container = GTK_CONTAINER (toplevel);
1049 window = GTK_WINDOW (toplevel);
1050 bin = GTK_BIN (toplevel);
1052 /* This is a copy of gtk_window_focus(), modified so that we
1053 * can detect wrap-around.
1055 old_focus_child = gtk_container_get_focus_child (container);
1057 if (old_focus_child)
1059 if (gtk_widget_child_focus (old_focus_child, direction))
1062 /* We are allowed exactly one wrap-around per sequence of focus
1065 if (_gtk_socket_windowing_embed_get_focus_wrapped ())
1068 _gtk_socket_windowing_embed_set_focus_wrapped ();
1071 focus_widget = gtk_window_get_focus (window);
1074 /* Wrapped off the end, clear the focus setting for the toplevel */
1075 parent = gtk_widget_get_parent (focus_widget);
1078 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
1079 parent = gtk_widget_get_parent (parent);
1082 gtk_window_set_focus (GTK_WINDOW (container), NULL);
1085 /* Now try to focus the first widget in the window */
1086 child = gtk_bin_get_child (bin);
1089 if (gtk_widget_child_focus (child, direction))