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/.
29 #include "gtkmarshalers.h"
31 #include "gtkprivate.h"
33 #include "gdk/gdkkeysyms.h"
36 #include "gtkxembed.h"
40 static void gtk_plug_class_init (GtkPlugClass *klass);
41 static void gtk_plug_init (GtkPlug *plug);
42 static void gtk_plug_finalize (GObject *object);
43 static void gtk_plug_realize (GtkWidget *widget);
44 static void gtk_plug_unrealize (GtkWidget *widget);
45 static void gtk_plug_show (GtkWidget *widget);
46 static void gtk_plug_hide (GtkWidget *widget);
47 static void gtk_plug_map (GtkWidget *widget);
48 static void gtk_plug_unmap (GtkWidget *widget);
49 static void gtk_plug_size_allocate (GtkWidget *widget,
50 GtkAllocation *allocation);
51 static gboolean gtk_plug_key_press_event (GtkWidget *widget,
53 static gboolean gtk_plug_focus_event (GtkWidget *widget,
54 GdkEventFocus *event);
55 static void gtk_plug_set_focus (GtkWindow *window,
57 static gboolean gtk_plug_focus (GtkWidget *widget,
58 GtkDirectionType direction);
59 static void gtk_plug_check_resize (GtkContainer *container);
60 static void gtk_plug_keys_changed (GtkWindow *window);
61 static GdkFilterReturn gtk_plug_filter_func (GdkXEvent *gdk_xevent,
65 static void handle_modality_off (GtkPlug *plug);
66 static void xembed_set_info (GdkWindow *window,
70 #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
72 static GtkWindowClass *parent_class = NULL;
73 static GtkBinClass *bin_class = NULL;
80 static guint plug_signals[LAST_SIGNAL] = { 0 };
83 gtk_plug_get_type (void)
85 static GType plug_type = 0;
89 static const GTypeInfo plug_info =
91 sizeof (GtkPlugClass),
93 NULL, /* base_finalize */
94 (GClassInitFunc) gtk_plug_class_init,
95 NULL, /* class_finalize */
96 NULL, /* class_data */
99 (GInstanceInitFunc) gtk_plug_init,
102 plug_type = g_type_register_static (GTK_TYPE_WINDOW, "GtkPlug",
110 gtk_plug_class_init (GtkPlugClass *class)
112 GObjectClass *gobject_class = (GObjectClass *)class;
113 GtkWidgetClass *widget_class = (GtkWidgetClass *)class;
114 GtkWindowClass *window_class = (GtkWindowClass *)class;
115 GtkContainerClass *container_class = (GtkContainerClass *)class;
117 parent_class = g_type_class_peek_parent (class);
118 bin_class = g_type_class_peek (GTK_TYPE_BIN);
120 gobject_class->finalize = gtk_plug_finalize;
122 widget_class->realize = gtk_plug_realize;
123 widget_class->unrealize = gtk_plug_unrealize;
124 widget_class->key_press_event = gtk_plug_key_press_event;
125 widget_class->focus_in_event = gtk_plug_focus_event;
126 widget_class->focus_out_event = gtk_plug_focus_event;
128 widget_class->show = gtk_plug_show;
129 widget_class->hide = gtk_plug_hide;
130 widget_class->map = gtk_plug_map;
131 widget_class->unmap = gtk_plug_unmap;
132 widget_class->size_allocate = gtk_plug_size_allocate;
134 widget_class->focus = gtk_plug_focus;
136 container_class->check_resize = gtk_plug_check_resize;
138 window_class->set_focus = gtk_plug_set_focus;
139 window_class->keys_changed = gtk_plug_keys_changed;
141 plug_signals[EMBEDDED] =
142 g_signal_new ("embedded",
143 G_OBJECT_CLASS_TYPE (class),
145 G_STRUCT_OFFSET (GtkPlugClass, embedded),
147 _gtk_marshal_VOID__VOID,
152 gtk_plug_init (GtkPlug *plug)
156 window = GTK_WINDOW (plug);
158 window->type = GTK_WINDOW_TOPLEVEL;
162 gtk_plug_set_is_child (GtkPlug *plug,
165 g_assert (!GTK_WIDGET (plug)->parent);
169 if (plug->modality_window)
170 handle_modality_off (plug);
172 if (plug->modality_group)
174 gtk_window_group_remove_window (plug->modality_group, GTK_WINDOW (plug));
175 g_object_unref (plug->modality_group);
176 plug->modality_group = NULL;
179 /* As a toplevel, the MAPPED flag doesn't correspond
180 * to whether the widget->window is mapped; we unmap
181 * here, but don't bother remapping -- we will get mapped
182 * by gtk_widget_set_parent ().
184 if (GTK_WIDGET_MAPPED (plug))
185 gtk_widget_unmap (GTK_WIDGET (plug));
187 GTK_WIDGET_UNSET_FLAGS (plug, GTK_TOPLEVEL);
188 gtk_container_set_resize_mode (GTK_CONTAINER (plug), GTK_RESIZE_PARENT);
190 _gtk_widget_propagate_hierarchy_changed (GTK_WIDGET (plug), GTK_WIDGET (plug));
194 if (GTK_WINDOW (plug)->focus_widget)
195 gtk_window_set_focus (GTK_WINDOW (plug), NULL);
196 if (GTK_WINDOW (plug)->default_widget)
197 gtk_window_set_default (GTK_WINDOW (plug), NULL);
199 plug->modality_group = gtk_window_group_new ();
200 gtk_window_group_add_window (plug->modality_group, GTK_WINDOW (plug));
202 GTK_WIDGET_SET_FLAGS (plug, GTK_TOPLEVEL);
203 gtk_container_set_resize_mode (GTK_CONTAINER (plug), GTK_RESIZE_QUEUE);
205 _gtk_widget_propagate_hierarchy_changed (GTK_WIDGET (plug), NULL);
210 * _gtk_plug_add_to_socket:
212 * @socket_: a #GtkSocket
214 * Adds a plug to a socket within the same application.
217 _gtk_plug_add_to_socket (GtkPlug *plug,
223 g_return_if_fail (GTK_IS_PLUG (plug));
224 g_return_if_fail (GTK_IS_SOCKET (socket));
225 g_return_if_fail (GTK_WIDGET_REALIZED (socket));
227 widget = GTK_WIDGET (plug);
229 gtk_plug_set_is_child (plug, TRUE);
230 plug->same_app = TRUE;
231 socket->same_app = TRUE;
232 socket->plug_widget = widget;
234 plug->socket_window = GTK_WIDGET (socket)->window;
236 if (GTK_WIDGET_REALIZED (widget))
238 gdk_drawable_get_size (GDK_DRAWABLE (widget->window), &w, &h);
239 gdk_window_reparent (widget->window, plug->socket_window, -w, -h);
242 gtk_widget_set_parent (widget, GTK_WIDGET (socket));
244 g_signal_emit_by_name (socket, "plug_added", 0);
248 send_delete_event (GtkWidget *widget)
250 GdkEvent *event = gdk_event_new (GDK_DELETE);
252 event->any.window = g_object_ref (widget->window);
253 event->any.send_event = FALSE;
255 gtk_widget_ref (widget);
257 if (!gtk_widget_event (widget, event))
258 gtk_widget_destroy (widget);
260 gtk_widget_unref (widget);
262 gdk_event_free (event);
266 * _gtk_plug_remove_from_socket:
268 * @socket_: a #GtkSocket
270 * Removes a plug from a socket within the same application.
273 _gtk_plug_remove_from_socket (GtkPlug *plug,
278 gboolean widget_was_visible;
280 g_return_if_fail (GTK_IS_PLUG (plug));
281 g_return_if_fail (GTK_IS_SOCKET (socket));
282 g_return_if_fail (GTK_WIDGET_REALIZED (plug));
284 widget = GTK_WIDGET (plug);
287 g_object_ref (socket);
289 widget_was_visible = GTK_WIDGET_VISIBLE (plug);
291 gdk_window_hide (widget->window);
292 gdk_window_reparent (widget->window,
293 gtk_widget_get_root_window (widget),
296 GTK_PRIVATE_SET_FLAG (plug, GTK_IN_REPARENT);
297 gtk_widget_unparent (GTK_WIDGET (plug));
298 GTK_PRIVATE_UNSET_FLAG (plug, GTK_IN_REPARENT);
300 socket->plug_widget = NULL;
301 if (socket->plug_window != NULL)
303 g_object_unref (socket->plug_window);
304 socket->plug_window = NULL;
307 socket->same_app = FALSE;
309 plug->same_app = FALSE;
310 plug->socket_window = NULL;
312 gtk_plug_set_is_child (plug, FALSE);
314 g_signal_emit_by_name (socket, "plug_removed", &result);
316 gtk_widget_destroy (GTK_WIDGET (socket));
318 send_delete_event (widget);
320 g_object_unref (plug);
322 if (widget_was_visible && GTK_WIDGET_VISIBLE (socket))
323 gtk_widget_queue_resize (GTK_WIDGET (socket));
325 g_object_unref (socket);
329 * gtk_plug_construct:
331 * @socket_id: the XID of the socket's window.
333 * Finish the initialization of @plug for a given #GtkSocket identified by
334 * @socket_id. This function will generally only be used by classes deriving from #GtkPlug.
337 gtk_plug_construct (GtkPlug *plug,
338 GdkNativeWindow socket_id)
340 gtk_plug_construct_for_display (plug, gdk_display_get_default (), socket_id);
344 * gtk_plug_construct_for_display:
346 * @display: the #GdkDisplay associated with @socket_id's
348 * @socket_id: the XID of the socket's window.
350 * Finish the initialization of @plug for a given #GtkSocket identified by
351 * @socket_id which is currently displayed on @display.
352 * This function will generally only be used by classes deriving from #GtkPlug.
357 gtk_plug_construct_for_display (GtkPlug *plug,
359 GdkNativeWindow socket_id)
363 gpointer user_data = NULL;
365 plug->socket_window = gdk_window_lookup_for_display (display, socket_id);
367 if (plug->socket_window)
368 gdk_window_get_user_data (plug->socket_window, &user_data);
370 plug->socket_window = gdk_window_foreign_new_for_display (display, socket_id);
374 if (GTK_IS_SOCKET (user_data))
375 _gtk_plug_add_to_socket (plug, user_data);
378 g_warning (G_STRLOC "Can't create GtkPlug as child of non-GtkSocket");
379 plug->socket_window = NULL;
383 if (plug->socket_window)
384 g_signal_emit (plug, plug_signals[EMBEDDED], 0);
390 * @socket_id: the window ID of the socket, or 0.
392 * Creates a new plug widget inside the #GtkSocket identified
393 * by @socket_id. If @socket_id is 0, the plug is left "unplugged" and
394 * can later be plugged into a #GtkSocket by gtk_socket_add_id().
396 * Return value: the new #GtkPlug widget.
399 gtk_plug_new (GdkNativeWindow socket_id)
401 return gtk_plug_new_for_display (gdk_display_get_default (), socket_id);
405 * gtk_plug_new_for_display:
406 * @display : the #GdkDisplay on which @socket_id is displayed
407 * @socket_id: the XID of the socket's window.
409 * Create a new plug widget inside the #GtkSocket identified by socket_id.
411 * Return value: the new #GtkPlug widget.
416 gtk_plug_new_for_display (GdkDisplay *display,
417 GdkNativeWindow socket_id)
421 plug = g_object_new (GTK_TYPE_PLUG, NULL);
422 gtk_plug_construct_for_display (plug, display, socket_id);
423 return GTK_WIDGET (plug);
430 * Gets the window ID of a #GtkPlug widget, which can then
431 * be used to embed this window inside another window, for
432 * instance with gtk_socket_add_id().
434 * Return value: the window ID for the plug
437 gtk_plug_get_id (GtkPlug *plug)
439 g_return_val_if_fail (GTK_IS_PLUG (plug), 0);
441 if (!GTK_WIDGET_REALIZED (plug))
442 gtk_widget_realize (GTK_WIDGET (plug));
444 return GDK_WINDOW_XWINDOW (GTK_WIDGET (plug)->window);
448 gtk_plug_finalize (GObject *object)
450 GtkPlug *plug = GTK_PLUG (object);
452 if (plug->grabbed_keys)
454 g_hash_table_destroy (plug->grabbed_keys);
455 plug->grabbed_keys = NULL;
458 G_OBJECT_CLASS (parent_class)->finalize (object);
462 gtk_plug_unrealize (GtkWidget *widget)
466 g_return_if_fail (GTK_IS_PLUG (widget));
468 plug = GTK_PLUG (widget);
470 if (plug->socket_window != NULL)
472 gdk_window_set_user_data (plug->socket_window, NULL);
473 g_object_unref (plug->socket_window);
474 plug->socket_window = NULL;
479 if (plug->modality_window)
480 handle_modality_off (plug);
482 gtk_window_group_remove_window (plug->modality_group, GTK_WINDOW (plug));
483 g_object_unref (plug->modality_group);
486 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
487 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
491 gtk_plug_realize (GtkWidget *widget)
495 GdkWindowAttr attributes;
496 gint attributes_mask;
498 g_return_if_fail (GTK_IS_PLUG (widget));
500 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
501 window = GTK_WINDOW (widget);
502 plug = GTK_PLUG (widget);
504 attributes.window_type = GDK_WINDOW_CHILD; /* XXX GDK_WINDOW_PLUG ? */
505 attributes.title = window->title;
506 attributes.wmclass_name = window->wmclass_name;
507 attributes.wmclass_class = window->wmclass_class;
508 attributes.width = widget->allocation.width;
509 attributes.height = widget->allocation.height;
510 attributes.wclass = GDK_INPUT_OUTPUT;
512 /* this isn't right - we should match our parent's visual/colormap.
513 * though that will require handling "foreign" colormaps */
514 attributes.visual = gtk_widget_get_visual (widget);
515 attributes.colormap = gtk_widget_get_colormap (widget);
516 attributes.event_mask = gtk_widget_get_events (widget);
517 attributes.event_mask |= (GDK_EXPOSURE_MASK |
519 GDK_KEY_RELEASE_MASK |
520 GDK_ENTER_NOTIFY_MASK |
521 GDK_LEAVE_NOTIFY_MASK |
524 attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
525 attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
526 attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
528 if (GTK_WIDGET_TOPLEVEL (widget))
530 attributes.window_type = GDK_WINDOW_TOPLEVEL;
532 gdk_error_trap_push ();
533 if (plug->socket_window)
534 widget->window = gdk_window_new (plug->socket_window,
535 &attributes, attributes_mask);
536 else /* If it's a passive plug, we use the root window */
537 widget->window = gdk_window_new (gtk_widget_get_root_window (widget),
538 &attributes, attributes_mask);
540 gdk_display_sync (gtk_widget_get_display (widget));
541 if (gdk_error_trap_pop ()) /* Uh-oh */
543 gdk_error_trap_push ();
544 gdk_window_destroy (widget->window);
546 gdk_error_trap_pop ();
547 widget->window = gdk_window_new (gtk_widget_get_root_window (widget),
548 &attributes, attributes_mask);
551 gdk_window_add_filter (widget->window, gtk_plug_filter_func, widget);
553 plug->modality_group = gtk_window_group_new ();
554 gtk_window_group_add_window (plug->modality_group, window);
556 xembed_set_info (widget->window, 0);
559 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
560 &attributes, attributes_mask);
562 gdk_window_set_user_data (widget->window, window);
564 widget->style = gtk_style_attach (widget->style, widget->window);
565 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
567 gdk_window_enable_synchronized_configure (widget->window);
571 gtk_plug_show (GtkWidget *widget)
573 if (GTK_WIDGET_TOPLEVEL (widget))
574 GTK_WIDGET_CLASS (parent_class)->show (widget);
576 GTK_WIDGET_CLASS (bin_class)->show (widget);
580 gtk_plug_hide (GtkWidget *widget)
582 if (GTK_WIDGET_TOPLEVEL (widget))
583 GTK_WIDGET_CLASS (parent_class)->hide (widget);
585 GTK_WIDGET_CLASS (bin_class)->hide (widget);
588 /* From gdkinternals.h */
589 void gdk_synthesize_window_state (GdkWindow *window,
590 GdkWindowState unset_flags,
591 GdkWindowState set_flags);
594 gtk_plug_map (GtkWidget *widget)
596 if (GTK_WIDGET_TOPLEVEL (widget))
598 GtkBin *bin = GTK_BIN (widget);
600 GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
603 GTK_WIDGET_VISIBLE (bin->child) &&
604 !GTK_WIDGET_MAPPED (bin->child))
605 gtk_widget_map (bin->child);
607 xembed_set_info (widget->window, XEMBED_MAPPED);
609 gdk_synthesize_window_state (widget->window,
610 GDK_WINDOW_STATE_WITHDRAWN,
614 GTK_WIDGET_CLASS (bin_class)->map (widget);
618 gtk_plug_unmap (GtkWidget *widget)
620 if (GTK_WIDGET_TOPLEVEL (widget))
622 GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
624 gdk_window_hide (widget->window);
625 xembed_set_info (widget->window, 0);
627 gdk_synthesize_window_state (widget->window,
629 GDK_WINDOW_STATE_WITHDRAWN);
632 GTK_WIDGET_CLASS (bin_class)->unmap (widget);
636 gtk_plug_size_allocate (GtkWidget *widget,
637 GtkAllocation *allocation)
639 if (GTK_WIDGET_TOPLEVEL (widget))
640 GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
643 GtkBin *bin = GTK_BIN (widget);
645 widget->allocation = *allocation;
647 if (GTK_WIDGET_REALIZED (widget))
648 gdk_window_move_resize (widget->window,
649 allocation->x, allocation->y,
650 allocation->width, allocation->height);
652 if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
654 GtkAllocation child_allocation;
656 child_allocation.x = child_allocation.y = GTK_CONTAINER (widget)->border_width;
657 child_allocation.width =
658 MAX (1, (gint)allocation->width - child_allocation.x * 2);
659 child_allocation.height =
660 MAX (1, (gint)allocation->height - child_allocation.y * 2);
662 gtk_widget_size_allocate (bin->child, &child_allocation);
669 gtk_plug_key_press_event (GtkWidget *widget,
672 if (GTK_WIDGET_TOPLEVEL (widget))
673 return GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event);
679 gtk_plug_focus_event (GtkWidget *widget,
680 GdkEventFocus *event)
682 /* We eat focus-in events and focus-out events, since they
683 * can be generated by something like a keyboard grab on
684 * a child of the plug.
690 gtk_plug_set_focus (GtkWindow *window,
693 GtkPlug *plug = GTK_PLUG (window);
695 GTK_WINDOW_CLASS (parent_class)->set_focus (window, focus);
697 /* Ask for focus from embedder
700 if (focus && !window->has_toplevel_focus)
702 _gtk_xembed_send_message (plug->socket_window,
703 XEMBED_REQUEST_FOCUS, 0, 0, 0);
709 guint accelerator_key;
710 GdkModifierType accelerator_mods;
714 grabbed_key_hash (gconstpointer a)
716 const GrabbedKey *key = a;
719 h = key->accelerator_key << 16;
720 h ^= key->accelerator_key >> 16;
721 h ^= key->accelerator_mods;
727 grabbed_key_equal (gconstpointer a, gconstpointer b)
729 const GrabbedKey *keya = a;
730 const GrabbedKey *keyb = b;
732 return (keya->accelerator_key == keyb->accelerator_key &&
733 keya->accelerator_mods == keyb->accelerator_mods);
737 add_grabbed_key (gpointer key, gpointer val, gpointer data)
739 GrabbedKey *grabbed_key = key;
740 GtkPlug *plug = data;
742 if (!plug->grabbed_keys ||
743 !g_hash_table_lookup (plug->grabbed_keys, grabbed_key))
745 _gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_GRAB_KEY, 0,
746 grabbed_key->accelerator_key, grabbed_key->accelerator_mods);
751 add_grabbed_key_always (gpointer key, gpointer val, gpointer data)
753 GrabbedKey *grabbed_key = key;
754 GtkPlug *plug = data;
756 _gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_GRAB_KEY, 0,
757 grabbed_key->accelerator_key, grabbed_key->accelerator_mods);
761 remove_grabbed_key (gpointer key, gpointer val, gpointer data)
763 GrabbedKey *grabbed_key = key;
764 GtkPlug *plug = data;
766 if (!plug->grabbed_keys ||
767 !g_hash_table_lookup (plug->grabbed_keys, grabbed_key))
769 _gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_UNGRAB_KEY, 0,
770 grabbed_key->accelerator_key, grabbed_key->accelerator_mods);
775 keys_foreach (GtkWindow *window,
777 GdkModifierType modifiers,
778 gboolean is_mnemonic,
781 GHashTable *new_grabbed_keys = data;
782 GrabbedKey *key = g_new (GrabbedKey, 1);
784 key->accelerator_key = keyval;
785 key->accelerator_mods = modifiers;
787 g_hash_table_replace (new_grabbed_keys, key, key);
791 gtk_plug_keys_changed (GtkWindow *window)
793 GHashTable *new_grabbed_keys, *old_grabbed_keys;
794 GtkPlug *plug = GTK_PLUG (window);
796 new_grabbed_keys = g_hash_table_new_full (grabbed_key_hash, grabbed_key_equal, (GDestroyNotify)g_free, NULL);
797 _gtk_window_keys_foreach (window, keys_foreach, new_grabbed_keys);
799 if (plug->socket_window)
800 g_hash_table_foreach (new_grabbed_keys, add_grabbed_key, plug);
802 old_grabbed_keys = plug->grabbed_keys;
803 plug->grabbed_keys = new_grabbed_keys;
805 if (old_grabbed_keys)
807 if (plug->socket_window)
808 g_hash_table_foreach (old_grabbed_keys, remove_grabbed_key, plug);
809 g_hash_table_destroy (old_grabbed_keys);
814 focus_to_parent (GtkPlug *plug,
815 GtkDirectionType direction)
817 XEmbedMessageType message = XEMBED_FOCUS_PREV; /* Quiet GCC */
823 case GTK_DIR_TAB_BACKWARD:
824 message = XEMBED_FOCUS_PREV;
828 case GTK_DIR_TAB_FORWARD:
829 message = XEMBED_FOCUS_NEXT;
833 _gtk_xembed_send_focus_message (plug->socket_window, message, 0);
837 gtk_plug_focus (GtkWidget *widget,
838 GtkDirectionType direction)
840 GtkBin *bin = GTK_BIN (widget);
841 GtkPlug *plug = GTK_PLUG (widget);
842 GtkWindow *window = GTK_WINDOW (widget);
843 GtkContainer *container = GTK_CONTAINER (widget);
844 GtkWidget *old_focus_child = container->focus_child;
847 /* We override GtkWindow's behavior, since we don't want wrapping here.
851 if (gtk_widget_child_focus (old_focus_child, direction))
854 if (window->focus_widget)
856 /* Wrapped off the end, clear the focus setting for the toplevel */
857 parent = window->focus_widget->parent;
860 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
861 parent = GTK_WIDGET (parent)->parent;
864 gtk_window_set_focus (GTK_WINDOW (container), NULL);
869 /* Try to focus the first widget in the window */
870 if (bin->child && gtk_widget_child_focus (bin->child, direction))
874 if (!GTK_CONTAINER (window)->focus_child)
875 focus_to_parent (plug, direction);
881 gtk_plug_check_resize (GtkContainer *container)
883 if (GTK_WIDGET_TOPLEVEL (container))
884 GTK_CONTAINER_CLASS (parent_class)->check_resize (container);
886 GTK_CONTAINER_CLASS (bin_class)->check_resize (container);
890 focus_first_last (GtkPlug *plug,
891 GtkDirectionType direction)
893 GtkWindow *window = GTK_WINDOW (plug);
896 if (window->focus_widget)
898 parent = window->focus_widget->parent;
901 gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
902 parent = GTK_WIDGET (parent)->parent;
905 gtk_window_set_focus (GTK_WINDOW (plug), NULL);
908 gtk_widget_child_focus (GTK_WIDGET (plug), direction);
912 handle_modality_on (GtkPlug *plug)
914 if (!plug->modality_window)
916 plug->modality_window = gtk_window_new (GTK_WINDOW_POPUP);
917 gtk_window_set_screen (GTK_WINDOW (plug->modality_window),
918 gtk_widget_get_screen (GTK_WIDGET (plug)));
919 gtk_widget_realize (plug->modality_window);
920 gtk_window_group_add_window (plug->modality_group, GTK_WINDOW (plug->modality_window));
921 gtk_grab_add (plug->modality_window);
926 handle_modality_off (GtkPlug *plug)
928 if (plug->modality_window)
930 gtk_widget_destroy (plug->modality_window);
931 plug->modality_window = NULL;
936 xembed_set_info (GdkWindow *window,
939 GdkDisplay *display = gdk_drawable_get_display (window);
940 unsigned long buffer[2];
942 Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO");
944 buffer[0] = GTK_XEMBED_PROTOCOL_VERSION;
947 XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
948 GDK_WINDOW_XWINDOW (window),
949 xembed_info_atom, xembed_info_atom, 32,
951 (unsigned char *)buffer, 2);
955 handle_xembed_message (GtkPlug *plug,
956 XEmbedMessageType message,
962 GtkWindow *window = GTK_WINDOW (plug);
964 GTK_NOTE (PLUGSOCKET,
965 g_message ("GtkPlug: Message of type %d received", message));
969 case XEMBED_EMBEDDED_NOTIFY:
971 case XEMBED_WINDOW_ACTIVATE:
972 _gtk_window_set_is_active (window, TRUE);
974 case XEMBED_WINDOW_DEACTIVATE:
975 _gtk_window_set_is_active (window, FALSE);
978 case XEMBED_MODALITY_ON:
979 handle_modality_on (plug);
981 case XEMBED_MODALITY_OFF:
982 handle_modality_off (plug);
985 case XEMBED_FOCUS_IN:
986 _gtk_window_set_has_toplevel_focus (window, TRUE);
989 case XEMBED_FOCUS_FIRST:
990 focus_first_last (plug, GTK_DIR_TAB_FORWARD);
992 case XEMBED_FOCUS_LAST:
993 focus_first_last (plug, GTK_DIR_TAB_BACKWARD);
995 case XEMBED_FOCUS_CURRENT:
1000 case XEMBED_FOCUS_OUT:
1001 _gtk_window_set_has_toplevel_focus (window, FALSE);
1004 case XEMBED_GRAB_KEY:
1005 case XEMBED_UNGRAB_KEY:
1006 case XEMBED_GTK_GRAB_KEY:
1007 case XEMBED_GTK_UNGRAB_KEY:
1008 case XEMBED_REQUEST_FOCUS:
1009 case XEMBED_FOCUS_NEXT:
1010 case XEMBED_FOCUS_PREV:
1011 g_warning ("GtkPlug: Invalid _XEMBED message of type %d received", message);
1015 GTK_NOTE(PLUGSOCKET,
1016 g_message ("GtkPlug: Ignoring unknown _XEMBED message of type %d", message));
1021 static GdkFilterReturn
1022 gtk_plug_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
1024 GdkScreen *screen = gdk_drawable_get_screen (event->any.window);
1025 GdkDisplay *display = gdk_screen_get_display (screen);
1026 GtkPlug *plug = GTK_PLUG (data);
1027 XEvent *xevent = (XEvent *)gdk_xevent;
1029 GdkFilterReturn return_val;
1031 return_val = GDK_FILTER_CONTINUE;
1033 switch (xevent->type)
1036 if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED"))
1038 _gtk_xembed_push_message (xevent);
1039 handle_xembed_message (plug,
1040 xevent->xclient.data.l[1],
1041 xevent->xclient.data.l[2],
1042 xevent->xclient.data.l[3],
1043 xevent->xclient.data.l[4],
1044 xevent->xclient.data.l[0]);
1045 _gtk_xembed_pop_message ();
1047 return GDK_FILTER_REMOVE;
1049 else if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW"))
1051 /* We filter these out because we take being reparented back to the
1052 * root window as the reliable end of the embedding protocol
1055 return GDK_FILTER_REMOVE;
1058 case ReparentNotify:
1060 XReparentEvent *xre = &xevent->xreparent;
1061 gboolean was_embedded = plug->socket_window != NULL;
1063 return_val = GDK_FILTER_REMOVE;
1065 g_object_ref (plug);
1069 /* End of embedding protocol for previous socket */
1071 /* FIXME: race if we remove from another socket and
1072 * then add to a local window before we get notification
1073 * Probably need check in _gtk_plug_add_to_socket
1076 if (xre->parent != GDK_WINDOW_XWINDOW (plug->socket_window))
1078 GtkWidget *widget = GTK_WIDGET (plug);
1080 gdk_window_set_user_data (plug->socket_window, NULL);
1081 g_object_unref (plug->socket_window);
1082 plug->socket_window = NULL;
1084 /* Emit a delete window, as if the user attempted
1085 * to close the toplevel. Simple as to how we
1086 * handle WM_DELETE_WINDOW, if it isn't handled
1087 * we destroy the widget. BUt only do this if
1088 * we are being reparented to the root window.
1089 * Moving from one embedder to another should
1090 * be invisible to the app.
1093 if (xre->parent == GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)))
1094 send_delete_event (widget);
1100 if (xre->parent != GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)))
1102 /* Start of embedding protocol */
1104 plug->socket_window = gdk_window_lookup_for_display (display, xre->parent);
1105 if (plug->socket_window)
1107 gpointer user_data = NULL;
1108 gdk_window_get_user_data (plug->socket_window, &user_data);
1112 g_warning (G_STRLOC "Plug reparented unexpectedly into window in the same process");
1113 plug->socket_window = NULL;
1117 g_object_ref (plug->socket_window);
1121 plug->socket_window = gdk_window_foreign_new_for_display (display, xre->parent);
1122 if (!plug->socket_window) /* Already gone */
1126 if (plug->grabbed_keys)
1127 g_hash_table_foreach (plug->grabbed_keys, add_grabbed_key_always, plug);
1130 g_signal_emit (plug, plug_signals[EMBEDDED], 0);
1134 g_object_unref (plug);
1140 return GDK_FILTER_CONTINUE;
1143 #define __GTK_PLUG_C__
1144 #include "gtkaliasdef.c"