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/.
31 #include "gdk/gdkkeysyms.h"
33 #include "gtkmarshalers.h"
34 #include "gtkwindow.h"
36 #include "gtkprivate.h"
37 #include "gtksocket.h"
38 #include "gtksocketprivate.h"
43 /* Forward declararations */
45 static void gtk_socket_class_init (GtkSocketClass *klass);
46 static void gtk_socket_init (GtkSocket *socket);
47 static void gtk_socket_finalize (GObject *object);
48 static void gtk_socket_notify (GObject *object,
50 static void gtk_socket_realize (GtkWidget *widget);
51 static void gtk_socket_unrealize (GtkWidget *widget);
52 static void gtk_socket_size_request (GtkWidget *widget,
53 GtkRequisition *requisition);
54 static void gtk_socket_size_allocate (GtkWidget *widget,
55 GtkAllocation *allocation);
56 static void gtk_socket_hierarchy_changed (GtkWidget *widget,
57 GtkWidget *old_toplevel);
58 static void gtk_socket_grab_notify (GtkWidget *widget,
59 gboolean was_grabbed);
60 static gboolean gtk_socket_key_event (GtkWidget *widget,
62 static gboolean gtk_socket_focus (GtkWidget *widget,
63 GtkDirectionType direction);
64 static void gtk_socket_remove (GtkContainer *container,
66 static void gtk_socket_forall (GtkContainer *container,
67 gboolean include_internals,
69 gpointer callback_data);
77 GdkModifierType accel_mods;
86 static guint socket_signals[LAST_SIGNAL] = { 0 };
88 static GtkWidgetClass *parent_class = NULL;
91 * _gtk_socket_get_private:
93 * @socket: a #GtkSocket
95 * Returns the private data associated with a GtkSocket, creating it
99 _gtk_socket_get_private (GtkSocket *socket)
101 GtkSocketPrivate *private;
102 static GQuark private_quark = 0;
105 private_quark = g_quark_from_static_string ("gtk-socket-private");
107 private = g_object_get_qdata (G_OBJECT (socket), private_quark);
111 private = g_new0 (GtkSocketPrivate, 1);
112 private->resize_count = 0;
114 g_object_set_qdata_full (G_OBJECT (socket), private_quark,
115 private, (GDestroyNotify) g_free);
122 gtk_socket_get_type (void)
124 static GType socket_type = 0;
128 static const GTypeInfo socket_info =
130 sizeof (GtkSocketClass),
131 NULL, /* base_init */
132 NULL, /* base_finalize */
133 (GClassInitFunc) gtk_socket_class_init,
134 NULL, /* class_finalize */
135 NULL, /* class_data */
137 16, /* n_preallocs */
138 (GInstanceInitFunc) gtk_socket_init,
141 socket_type = g_type_register_static (GTK_TYPE_CONTAINER, g_intern_static_string ("GtkSocket"),
149 gtk_socket_finalize (GObject *object)
151 GtkSocket *socket = GTK_SOCKET (object);
153 g_object_unref (socket->accel_group);
154 socket->accel_group = NULL;
156 G_OBJECT_CLASS (parent_class)->finalize (object);
160 gtk_socket_class_init (GtkSocketClass *class)
162 GtkWidgetClass *widget_class;
163 GtkContainerClass *container_class;
164 GObjectClass *gobject_class;
166 gobject_class = (GObjectClass *) class;
167 widget_class = (GtkWidgetClass*) class;
168 container_class = (GtkContainerClass*) class;
170 parent_class = g_type_class_peek_parent (class);
172 gobject_class->finalize = gtk_socket_finalize;
173 gobject_class->notify = gtk_socket_notify;
175 widget_class->realize = gtk_socket_realize;
176 widget_class->unrealize = gtk_socket_unrealize;
177 widget_class->size_request = gtk_socket_size_request;
178 widget_class->size_allocate = gtk_socket_size_allocate;
179 widget_class->hierarchy_changed = gtk_socket_hierarchy_changed;
180 widget_class->grab_notify = gtk_socket_grab_notify;
181 widget_class->key_press_event = gtk_socket_key_event;
182 widget_class->key_release_event = gtk_socket_key_event;
183 widget_class->focus = gtk_socket_focus;
185 /* We don't want to show_all/hide_all the in-process
188 widget_class->show_all = gtk_widget_show;
189 widget_class->hide_all = gtk_widget_hide;
191 container_class->remove = gtk_socket_remove;
192 container_class->forall = gtk_socket_forall;
194 socket_signals[PLUG_ADDED] =
195 g_signal_new ("plug_added",
196 G_OBJECT_CLASS_TYPE (class),
198 G_STRUCT_OFFSET (GtkSocketClass, plug_added),
200 _gtk_marshal_VOID__VOID,
202 socket_signals[PLUG_REMOVED] =
203 g_signal_new ("plug_removed",
204 G_OBJECT_CLASS_TYPE (class),
206 G_STRUCT_OFFSET (GtkSocketClass, plug_removed),
207 _gtk_boolean_handled_accumulator, NULL,
208 _gtk_marshal_BOOLEAN__VOID,
213 gtk_socket_init (GtkSocket *socket)
215 socket->request_width = 0;
216 socket->request_height = 0;
217 socket->current_width = 0;
218 socket->current_height = 0;
220 socket->plug_window = NULL;
221 socket->plug_widget = NULL;
222 socket->focus_in = FALSE;
223 socket->have_size = FALSE;
224 socket->need_map = FALSE;
225 socket->active = FALSE;
227 socket->accel_group = gtk_accel_group_new ();
228 g_object_set_data (G_OBJECT (socket->accel_group), "gtk-socket", socket);
234 * Create a new empty #GtkSocket.
236 * Return value: the new #GtkSocket.
239 gtk_socket_new (void)
243 socket = g_object_new (GTK_TYPE_SOCKET, NULL);
245 return GTK_WIDGET (socket);
250 * @socket_: a #GtkSocket
251 * @wid: the window ID of an existing toplevel window.
253 * Reparents a pre-existing toplevel window into a #GtkSocket. This is
254 * meant to embed clients that do not know about embedding into a
255 * #GtkSocket, however doing so is inherently unreliable, and using
256 * this function is not recommended.
258 * The #GtkSocket must have already be added into a toplevel window
259 * before you can make this call.
262 gtk_socket_steal (GtkSocket *socket,
265 g_return_if_fail (GTK_IS_SOCKET (socket));
266 g_return_if_fail (GTK_WIDGET_ANCHORED (socket));
268 if (!GTK_WIDGET_REALIZED (socket))
269 gtk_widget_realize (GTK_WIDGET (socket));
271 _gtk_socket_add_window (socket, wid, TRUE);
276 * @socket_: a #GtkSocket
277 * @window_id: the window ID of a client participating in the XEMBED protocol.
279 * Adds an XEMBED client, such as a #GtkPlug, to the #GtkSocket. The
280 * client may be in the same process or in a different process.
282 * To embed a #GtkPlug in a #GtkSocket, you can either create the
283 * #GtkPlug with <literal>gtk_plug_new (0)</literal>, call
284 * gtk_plug_get_id() to get the window ID of the plug, and then pass that to the
285 * gtk_socket_add_id(), or you can call gtk_socket_get_id() to get the
286 * window ID for the socket, and call gtk_plug_new() passing in that
289 * The #GtkSocket must have already be added into a toplevel window
290 * before you can make this call.
293 gtk_socket_add_id (GtkSocket *socket,
294 GdkNativeWindow window_id)
296 g_return_if_fail (GTK_IS_SOCKET (socket));
297 g_return_if_fail (GTK_WIDGET_ANCHORED (socket));
299 if (!GTK_WIDGET_REALIZED (socket))
300 gtk_widget_realize (GTK_WIDGET (socket));
302 _gtk_socket_add_window (socket, window_id, TRUE);
307 * @socket_: a #GtkSocket.
309 * Gets the window ID of a #GtkSocket widget, which can then
310 * be used to create a client embedded inside the socket, for
311 * instance with gtk_plug_new().
313 * The #GtkSocket must have already be added into a toplevel window
314 * before you can make this call.
316 * Return value: the window ID for the socket
319 gtk_socket_get_id (GtkSocket *socket)
321 g_return_val_if_fail (GTK_IS_SOCKET (socket), 0);
322 g_return_val_if_fail (GTK_WIDGET_ANCHORED (socket), 0);
324 if (!GTK_WIDGET_REALIZED (socket))
325 gtk_widget_realize (GTK_WIDGET (socket));
327 return _gtk_socket_windowing_get_id (socket);
331 gtk_socket_realize (GtkWidget *widget)
334 GdkWindowAttr attributes;
335 gint attributes_mask;
337 g_return_if_fail (GTK_IS_SOCKET (widget));
339 socket = GTK_SOCKET (widget);
340 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
342 attributes.window_type = GDK_WINDOW_CHILD;
343 attributes.x = widget->allocation.x;
344 attributes.y = widget->allocation.y;
345 attributes.width = widget->allocation.width;
346 attributes.height = widget->allocation.height;
347 attributes.wclass = GDK_INPUT_OUTPUT;
348 attributes.visual = gtk_widget_get_visual (widget);
349 attributes.colormap = gtk_widget_get_colormap (widget);
350 attributes.event_mask = GDK_FOCUS_CHANGE_MASK;
352 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
354 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
355 &attributes, attributes_mask);
356 gdk_window_set_user_data (widget->window, socket);
358 widget->style = gtk_style_attach (widget->style, widget->window);
359 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
361 _gtk_socket_windowing_realize_window (socket);
363 gdk_window_add_filter (widget->window,
364 _gtk_socket_windowing_filter_func,
367 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
369 /* We sync here so that we make sure that if the XID for
370 * our window is passed to another application, SubstructureRedirectMask
371 * will be set by the time the other app creates its window.
373 gdk_display_sync (gtk_widget_get_display (widget));
377 * _gtk_socket_end_embedding:
379 * @socket: a #GtkSocket
381 * Called to end the embedding of a plug in the socket.
384 _gtk_socket_end_embedding (GtkSocket *socket)
386 GtkSocketPrivate *private = _gtk_socket_get_private (socket);
387 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
390 if (toplevel && GTK_IS_WINDOW (toplevel))
391 _gtk_socket_windowing_end_embedding_toplevel (socket);
393 g_object_unref (socket->plug_window);
394 socket->plug_window = NULL;
395 socket->current_width = 0;
396 socket->current_height = 0;
397 private->resize_count = 0;
399 /* Remove from end to avoid indexes shifting. This is evil */
400 for (i = socket->accel_group->n_accels - 1; i >= 0; i--)
402 GtkAccelGroupEntry *accel_entry = &socket->accel_group->priv_accels[i];
403 gtk_accel_group_disconnect (socket->accel_group, accel_entry->closure);
408 gtk_socket_unrealize (GtkWidget *widget)
410 GtkSocket *socket = GTK_SOCKET (widget);
412 GTK_WIDGET_UNSET_FLAGS (widget, GTK_REALIZED);
414 if (socket->plug_widget)
416 _gtk_plug_remove_from_socket (GTK_PLUG (socket->plug_widget), socket);
418 else if (socket->plug_window)
420 _gtk_socket_end_embedding (socket);
423 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
424 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
428 gtk_socket_size_request (GtkWidget *widget,
429 GtkRequisition *requisition)
431 GtkSocket *socket = GTK_SOCKET (widget);
433 if (socket->plug_widget)
435 gtk_widget_size_request (socket->plug_widget, requisition);
439 if (socket->is_mapped && !socket->have_size && socket->plug_window)
440 _gtk_socket_windowing_size_request (socket);
442 if (socket->is_mapped && socket->have_size)
444 requisition->width = MAX (socket->request_width, 1);
445 requisition->height = MAX (socket->request_height, 1);
449 requisition->width = 1;
450 requisition->height = 1;
456 gtk_socket_size_allocate (GtkWidget *widget,
457 GtkAllocation *allocation)
461 g_return_if_fail (GTK_IS_SOCKET (widget));
462 g_return_if_fail (allocation != NULL);
464 socket = GTK_SOCKET (widget);
466 widget->allocation = *allocation;
467 if (GTK_WIDGET_REALIZED (widget))
469 gdk_window_move_resize (widget->window,
470 allocation->x, allocation->y,
471 allocation->width, allocation->height);
473 if (socket->plug_widget)
475 GtkAllocation child_allocation;
477 child_allocation.x = 0;
478 child_allocation.y = 0;
479 child_allocation.width = allocation->width;
480 child_allocation.height = allocation->height;
482 gtk_widget_size_allocate (socket->plug_widget, &child_allocation);
484 else if (socket->plug_window)
486 GtkSocketPrivate *private = _gtk_socket_get_private (socket);
488 gdk_error_trap_push ();
490 if (allocation->width != socket->current_width ||
491 allocation->height != socket->current_height)
493 gdk_window_move_resize (socket->plug_window,
495 allocation->width, allocation->height);
496 if (private->resize_count)
497 private->resize_count--;
499 GTK_NOTE (PLUGSOCKET,
500 g_message ("GtkSocket - allocated: %d %d",
501 allocation->width, allocation->height));
502 socket->current_width = allocation->width;
503 socket->current_height = allocation->height;
506 if (socket->need_map)
508 gdk_window_show (socket->plug_window);
509 socket->need_map = FALSE;
512 while (private->resize_count)
514 _gtk_socket_windowing_send_configure_event (socket);
515 private->resize_count--;
516 GTK_NOTE (PLUGSOCKET,
517 g_message ("GtkSocket - sending synthetic configure: %d %d",
518 allocation->width, allocation->height));
521 gdk_display_sync (gtk_widget_get_display (widget));
522 gdk_error_trap_pop ();
528 activate_key (GtkAccelGroup *accel_group,
529 GObject *acceleratable,
531 GdkModifierType accel_mods,
532 GrabbedKey *grabbed_key)
534 GdkEvent *gdk_event = gtk_get_current_event ();
536 GtkSocket *socket = g_object_get_data (G_OBJECT (accel_group), "gtk-socket");
537 gboolean retval = FALSE;
539 if (gdk_event && gdk_event->type == GDK_KEY_PRESS && socket->plug_window)
541 _gtk_socket_windowing_send_key_event (socket, gdk_event, TRUE);
546 gdk_event_free (gdk_event);
552 find_accel_key (GtkAccelKey *key,
556 GrabbedKey *grabbed_key = data;
558 return (key->accel_key == grabbed_key->accel_key &&
559 key->accel_mods == grabbed_key->accel_mods);
563 * _gtk_socket_add_grabbed_key:
565 * @socket: a #GtkSocket
567 * @modifiers: modifiers for the key
569 * Called from the GtkSocket platform-specific backend when the
570 * corresponding plug has told the socket to grab a key.
573 _gtk_socket_add_grabbed_key (GtkSocket *socket,
575 GdkModifierType modifiers)
578 GrabbedKey *grabbed_key;
580 grabbed_key = g_new (GrabbedKey, 1);
582 grabbed_key->accel_key = keyval;
583 grabbed_key->accel_mods = modifiers;
585 if (gtk_accel_group_find (socket->accel_group,
589 g_warning ("GtkSocket: request to add already present grabbed key %u,%#x\n",
591 g_free (grabbed_key);
595 closure = g_cclosure_new (G_CALLBACK (activate_key), grabbed_key, (GClosureNotify)g_free);
597 gtk_accel_group_connect (socket->accel_group, keyval, modifiers, GTK_ACCEL_LOCKED,
602 * _gtk_socket_remove_grabbed_key:
604 * @socket: a #GtkSocket
606 * @modifiers: modifiers for the key
608 * Called from the GtkSocket backend when the corresponding plug has
609 * told the socket to remove a key grab.
612 _gtk_socket_remove_grabbed_key (GtkSocket *socket,
614 GdkModifierType modifiers)
618 for (i = 0; i < socket->accel_group->n_accels; i++)
620 GtkAccelGroupEntry *accel_entry = &socket->accel_group->priv_accels[i];
621 if (accel_entry->key.accel_key == keyval &&
622 accel_entry->key.accel_mods == modifiers)
624 gtk_accel_group_disconnect (socket->accel_group,
625 accel_entry->closure);
630 g_warning ("GtkSocket: request to remove non-present grabbed key %u,%#x\n",
635 socket_update_focus_in (GtkSocket *socket)
637 gboolean focus_in = FALSE;
639 if (socket->plug_window)
641 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
643 if (GTK_WIDGET_TOPLEVEL (toplevel) &&
644 GTK_WINDOW (toplevel)->has_toplevel_focus &&
645 gtk_widget_is_focus (GTK_WIDGET (socket)))
649 if (focus_in != socket->focus_in)
651 socket->focus_in = focus_in;
653 _gtk_socket_windowing_focus_change (socket, focus_in);
658 socket_update_active (GtkSocket *socket)
660 gboolean active = FALSE;
662 if (socket->plug_window)
664 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
666 if (GTK_WIDGET_TOPLEVEL (toplevel) &&
667 GTK_WINDOW (toplevel)->is_active)
671 if (active != socket->active)
673 socket->active = active;
675 _gtk_socket_windowing_update_active (socket, active);
680 gtk_socket_hierarchy_changed (GtkWidget *widget,
681 GtkWidget *old_toplevel)
683 GtkSocket *socket = GTK_SOCKET (widget);
684 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
686 if (toplevel && !GTK_IS_WINDOW (toplevel))
689 if (toplevel != socket->toplevel)
691 if (socket->toplevel)
693 gtk_window_remove_accel_group (GTK_WINDOW (socket->toplevel), socket->accel_group);
694 g_signal_handlers_disconnect_by_func (socket->toplevel,
695 socket_update_focus_in,
697 g_signal_handlers_disconnect_by_func (socket->toplevel,
698 socket_update_active,
702 socket->toplevel = toplevel;
706 gtk_window_add_accel_group (GTK_WINDOW (socket->toplevel), socket->accel_group);
707 g_signal_connect_swapped (socket->toplevel, "notify::has-toplevel-focus",
708 G_CALLBACK (socket_update_focus_in), socket);
709 g_signal_connect_swapped (socket->toplevel, "notify::is-active",
710 G_CALLBACK (socket_update_active), socket);
713 socket_update_focus_in (socket);
714 socket_update_active (socket);
719 gtk_socket_grab_notify (GtkWidget *widget,
720 gboolean was_grabbed)
722 GtkSocket *socket = GTK_SOCKET (widget);
724 if (!socket->same_app)
725 _gtk_socket_windowing_update_modality (socket, !was_grabbed);
729 gtk_socket_key_event (GtkWidget *widget,
732 GtkSocket *socket = GTK_SOCKET (widget);
734 if (GTK_WIDGET_HAS_FOCUS (socket) && socket->plug_window && !socket->plug_widget)
736 _gtk_socket_windowing_send_key_event (socket, (GdkEvent *) event, FALSE);
745 gtk_socket_notify (GObject *object,
748 if (!strcmp (pspec->name, "is-focus"))
750 socket_update_focus_in (GTK_SOCKET (object));
754 * _gtk_socket_claim_focus:
756 * @socket: a #GtkSocket
759 * Claims focus for the socket. XXX send_event?
762 _gtk_socket_claim_focus (GtkSocket *socket,
766 socket->focus_in = TRUE; /* Otherwise, our notify handler will send FOCUS_IN */
768 /* Oh, the trickery... */
770 GTK_WIDGET_SET_FLAGS (socket, GTK_CAN_FOCUS);
771 gtk_widget_grab_focus (GTK_WIDGET (socket));
772 GTK_WIDGET_UNSET_FLAGS (socket, GTK_CAN_FOCUS);
776 gtk_socket_focus (GtkWidget *widget,
777 GtkDirectionType direction)
781 g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE);
783 socket = GTK_SOCKET (widget);
785 if (socket->plug_widget)
786 return gtk_widget_child_focus (socket->plug_widget, direction);
788 if (!gtk_widget_is_focus (widget))
790 _gtk_socket_windowing_focus (socket, direction);
791 _gtk_socket_claim_focus (socket, FALSE);
800 gtk_socket_remove (GtkContainer *container,
803 GtkSocket *socket = GTK_SOCKET (container);
805 g_return_if_fail (child == socket->plug_widget);
807 _gtk_plug_remove_from_socket (GTK_PLUG (socket->plug_widget), socket);
811 gtk_socket_forall (GtkContainer *container,
812 gboolean include_internals,
813 GtkCallback callback,
814 gpointer callback_data)
816 GtkSocket *socket = GTK_SOCKET (container);
818 if (socket->plug_widget)
819 (* callback) (socket->plug_widget, callback_data);
823 * _gtk_socket_add_window:
825 * @socket: a #GtkSocket
826 * @xid: the native identifier for a window
827 * @need_reparent: whether the socket's plug's window needs to be
828 * reparented to the socket
830 * Adds a window to a GtkSocket.
833 _gtk_socket_add_window (GtkSocket *socket,
835 gboolean need_reparent)
837 GtkWidget *widget = GTK_WIDGET (socket);
838 GdkDisplay *display = gtk_widget_get_display (widget);
839 gpointer user_data = NULL;
841 socket->plug_window = gdk_window_lookup_for_display (display, xid);
843 if (socket->plug_window)
845 g_object_ref (socket->plug_window);
846 gdk_window_get_user_data (socket->plug_window, &user_data);
849 if (user_data) /* A widget's window in this process */
851 GtkWidget *child_widget = user_data;
853 if (!GTK_IS_PLUG (child_widget))
855 g_warning (G_STRLOC ": Can't add non-GtkPlug to GtkSocket");
856 socket->plug_window = NULL;
857 gdk_error_trap_pop ();
862 _gtk_plug_add_to_socket (GTK_PLUG (child_widget), socket);
864 else /* A foreign window */
867 GdkDragProtocol protocol;
869 gdk_error_trap_push ();
871 if (!socket->plug_window)
873 socket->plug_window = gdk_window_foreign_new_for_display (display, xid);
874 if (!socket->plug_window) /* was deleted before we could get it */
876 gdk_error_trap_pop ();
881 _gtk_socket_windowing_select_plug_window_input (socket);
883 if (gdk_error_trap_pop ())
885 g_object_unref (socket->plug_window);
886 socket->plug_window = NULL;
890 /* OK, we now will reliably get destroy notification on socket->plug_window */
892 gdk_error_trap_push ();
896 gdk_window_hide (socket->plug_window); /* Shouldn't actually be necessary for XEMBED, but just in case */
897 gdk_window_reparent (socket->plug_window, widget->window, 0, 0);
900 socket->have_size = FALSE;
902 _gtk_socket_windowing_embed_get_info (socket);
904 socket->need_map = socket->is_mapped;
906 if (gdk_drag_get_protocol_for_display (display, xid, &protocol))
907 gtk_drag_dest_set_proxy (GTK_WIDGET (socket), socket->plug_window,
910 gdk_display_sync (display);
911 gdk_error_trap_pop ();
913 gdk_window_add_filter (socket->plug_window,
914 _gtk_socket_windowing_filter_func,
917 /* Add a pointer to the socket on our toplevel window */
919 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
920 if (toplevel && GTK_IS_WINDOW (toplevel))
921 gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid);
923 _gtk_socket_windowing_embed_notify (socket);
925 socket_update_active (socket);
926 socket_update_focus_in (socket);
928 gtk_widget_queue_resize (GTK_WIDGET (socket));
931 if (socket->plug_window)
932 g_signal_emit (socket, socket_signals[PLUG_ADDED], 0);
936 * _gtk_socket_handle_map_request:
938 * @socket: a #GtkSocket
940 * Called from the GtkSocket backend when the plug has been mapped.
943 _gtk_socket_handle_map_request (GtkSocket *socket)
945 if (!socket->is_mapped)
947 socket->is_mapped = TRUE;
948 socket->need_map = TRUE;
950 gtk_widget_queue_resize (GTK_WIDGET (socket));
955 * _gtk_socket_unmap_notify:
957 * @socket: a #GtkSocket
959 * Called from the GtkSocket backend when the plug has been unmapped ???
962 _gtk_socket_unmap_notify (GtkSocket *socket)
964 if (socket->is_mapped)
966 socket->is_mapped = FALSE;
967 gtk_widget_queue_resize (GTK_WIDGET (socket));
972 * _gtk_socket_advance_toplevel_focus:
974 * @socket: a #GtkSocket
975 * @direction: a direction
977 * Called from the GtkSocket backend when the corresponding plug
978 * has told the socket to move the focus.
981 _gtk_socket_advance_toplevel_focus (GtkSocket *socket,
982 GtkDirectionType direction)
986 GtkContainer *container;
988 GtkWidget *old_focus_child;
991 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
995 if (!GTK_WIDGET_TOPLEVEL (toplevel) || GTK_IS_PLUG (toplevel))
997 gtk_widget_child_focus (toplevel,direction);
1001 container = GTK_CONTAINER (toplevel);
1002 window = GTK_WINDOW (toplevel);
1003 bin = GTK_BIN (toplevel);
1005 /* This is a copy of gtk_window_focus(), modified so that we
1006 * can detect wrap-around.
1008 old_focus_child = container->focus_child;
1010 if (old_focus_child)
1012 if (gtk_widget_child_focus (old_focus_child, direction))
1015 /* We are allowed exactly one wrap-around per sequence of focus
1018 if (_gtk_socket_windowing_embed_get_focus_wrapped ())
1021 _gtk_socket_windowing_embed_set_focus_wrapped ();
1024 if (window->focus_widget)
1026 /* Wrapped off the end, clear the focus setting for the toplevel */
1027 parent = window->focus_widget->parent;
1030 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
1031 parent = GTK_WIDGET (parent)->parent;
1034 gtk_window_set_focus (GTK_WINDOW (container), NULL);
1037 /* Now try to focus the first widget in the window */
1040 if (gtk_widget_child_focus (bin->child, direction))
1045 #define __GTK_SOCKET_C__
1046 #include "gtkaliasdef.c"