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/.
28 #include "gdk/gdkkeysyms.h"
30 #include "gtkwindow.h"
31 #include "gtksignal.h"
32 #include "gtksocket.h"
39 /* Forward declararations */
41 static void gtk_socket_class_init (GtkSocketClass *klass);
42 static void gtk_socket_init (GtkSocket *socket);
43 static void gtk_socket_realize (GtkWidget *widget);
44 static void gtk_socket_unrealize (GtkWidget *widget);
45 static void gtk_socket_size_request (GtkWidget *widget,
46 GtkRequisition *requisition);
47 static void gtk_socket_size_allocate (GtkWidget *widget,
48 GtkAllocation *allocation);
49 static void gtk_socket_hierarchy_changed (GtkWidget *widget);
50 static void gtk_socket_grab_notify (GtkWidget *widget,
51 gboolean was_grabbed);
52 static gboolean gtk_socket_key_press_event (GtkWidget *widget,
54 static gboolean gtk_socket_focus_in_event (GtkWidget *widget,
55 GdkEventFocus *event);
56 static void gtk_socket_claim_focus (GtkSocket *socket);
57 static gboolean gtk_socket_focus_out_event (GtkWidget *widget,
58 GdkEventFocus *event);
59 static void gtk_socket_send_configure_event (GtkSocket *socket);
60 static gboolean gtk_socket_focus (GtkWidget *widget,
61 GtkDirectionType direction);
62 static GdkFilterReturn gtk_socket_filter_func (GdkXEvent *gdk_xevent,
66 static void send_xembed_message (GtkSocket *socket,
74 #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
78 static GtkWidgetClass *parent_class = NULL;
81 gtk_socket_get_type (void)
83 static GtkType socket_type = 0;
87 static const GTypeInfo socket_info =
89 sizeof (GtkSocketClass),
91 NULL, /* base_finalize */
92 (GClassInitFunc) gtk_socket_class_init,
93 NULL, /* class_finalize */
94 NULL, /* class_data */
97 (GInstanceInitFunc) gtk_socket_init,
100 socket_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkSocket", &socket_info, 0);
107 gtk_socket_class_init (GtkSocketClass *class)
109 GtkWidgetClass *widget_class;
110 GtkContainerClass *container_class;
112 widget_class = (GtkWidgetClass*) class;
113 container_class = (GtkContainerClass*) class;
115 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
117 widget_class->realize = gtk_socket_realize;
118 widget_class->unrealize = gtk_socket_unrealize;
119 widget_class->size_request = gtk_socket_size_request;
120 widget_class->size_allocate = gtk_socket_size_allocate;
121 widget_class->hierarchy_changed = gtk_socket_hierarchy_changed;
123 widget_class->grab_notify = gtk_socket_grab_notify;
125 widget_class->key_press_event = gtk_socket_key_press_event;
126 widget_class->focus_in_event = gtk_socket_focus_in_event;
127 widget_class->focus_out_event = gtk_socket_focus_out_event;
129 widget_class->focus = gtk_socket_focus;
133 gtk_socket_init (GtkSocket *socket)
135 socket->request_width = 0;
136 socket->request_height = 0;
137 socket->current_width = 0;
138 socket->current_height = 0;
140 socket->plug_window = NULL;
141 socket->same_app = FALSE;
142 socket->focus_in = FALSE;
143 socket->have_size = FALSE;
144 socket->need_map = FALSE;
148 gtk_socket_new (void)
152 socket = g_object_new (GTK_TYPE_SOCKET, NULL);
154 return GTK_WIDGET (socket);
158 gtk_socket_steal (GtkSocket *socket, GdkNativeWindow id)
161 gpointer user_data = NULL;
163 widget = GTK_WIDGET (socket);
165 socket->plug_window = gdk_window_lookup (id);
167 gdk_error_trap_push ();
169 if (socket->plug_window)
170 gdk_window_get_user_data (socket->plug_window,
176 GtkWidget *child_widget;
178 child_widget = GTK_WIDGET (socket->plug_window->user_data);
181 g_warning("Stealing from same app not yet implemented");
183 socket->same_app = TRUE;
187 socket->plug_window = gdk_window_foreign_new (id);
188 if (!socket->plug_window) /* was deleted before we could get it */
190 gdk_error_trap_pop ();
194 socket->same_app = FALSE;
195 socket->have_size = FALSE;
197 XSelectInput (GDK_DISPLAY (),
198 GDK_WINDOW_XWINDOW(socket->plug_window),
199 StructureNotifyMask | PropertyChangeMask);
201 gtk_widget_queue_resize (widget);
204 gdk_window_hide (socket->plug_window);
205 gdk_window_reparent (socket->plug_window, widget->window, 0, 0);
208 gdk_error_trap_pop ();
210 socket->need_map = TRUE;
214 gtk_socket_realize (GtkWidget *widget)
217 GdkWindowAttr attributes;
218 gint attributes_mask;
219 XWindowAttributes xattrs;
221 g_return_if_fail (widget != NULL);
222 g_return_if_fail (GTK_IS_SOCKET (widget));
224 socket = GTK_SOCKET (widget);
225 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
227 attributes.window_type = GDK_WINDOW_CHILD;
228 attributes.x = widget->allocation.x;
229 attributes.y = widget->allocation.y;
230 attributes.width = widget->allocation.width;
231 attributes.height = widget->allocation.height;
232 attributes.wclass = GDK_INPUT_OUTPUT;
233 attributes.visual = gtk_widget_get_visual (widget);
234 attributes.colormap = gtk_widget_get_colormap (widget);
235 attributes.event_mask = GDK_FOCUS_CHANGE_MASK;
237 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
239 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
240 &attributes, attributes_mask);
241 gdk_window_set_user_data (widget->window, socket);
243 widget->style = gtk_style_attach (widget->style, widget->window);
244 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
246 XGetWindowAttributes (GDK_DISPLAY (),
247 GDK_WINDOW_XWINDOW (widget->window),
250 XSelectInput (GDK_DISPLAY (),
251 GDK_WINDOW_XWINDOW(widget->window),
252 xattrs.your_event_mask |
253 SubstructureNotifyMask | SubstructureRedirectMask);
255 gdk_window_add_filter (widget->window, gtk_socket_filter_func, widget);
257 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
259 /* We sync here so that we make sure that if the XID for
260 * our window is passed to another application, SubstructureRedirectMask
261 * will be set by the time the other app creates its window.
267 gtk_socket_unrealize (GtkWidget *widget)
271 g_return_if_fail (widget != NULL);
272 g_return_if_fail (GTK_IS_SOCKET (widget));
274 socket = GTK_SOCKET (widget);
276 if (socket->plug_window)
278 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
279 if (toplevel && GTK_IS_WINDOW (toplevel))
280 gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel),
281 GDK_WINDOW_XWINDOW (socket->plug_window));
283 socket->plug_window = NULL;
287 if (socket->grabbed_keys)
289 g_hash_table_foreach (socket->grabbed_keys, (GHFunc)g_free, NULL);
290 g_hash_table_destroy (socket->grabbed_keys);
291 socket->grabbed_keys = NULL;
295 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
296 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
300 gtk_socket_size_request (GtkWidget *widget,
301 GtkRequisition *requisition)
305 g_return_if_fail (widget != NULL);
306 g_return_if_fail (GTK_IS_SOCKET (widget));
307 g_return_if_fail (requisition != NULL);
309 socket = GTK_SOCKET (widget);
311 if (!socket->have_size && socket->plug_window)
316 gdk_error_trap_push ();
318 if (XGetWMNormalHints (GDK_DISPLAY(),
319 GDK_WINDOW_XWINDOW (socket->plug_window),
322 /* This is obsolete, according the X docs, but many programs
324 if (hints.flags & (PSize | USSize))
326 socket->request_width = hints.width;
327 socket->request_height = hints.height;
329 else if (hints.flags & PMinSize)
331 socket->request_width = hints.min_width;
332 socket->request_height = hints.min_height;
334 else if (hints.flags & PBaseSize)
336 socket->request_width = hints.base_width;
337 socket->request_height = hints.base_height;
340 socket->have_size = TRUE; /* don't check again? */
342 gdk_error_trap_pop ();
345 requisition->width = MAX (socket->request_width, 1);
346 requisition->height = MAX (socket->request_height, 1);
350 gtk_socket_size_allocate (GtkWidget *widget,
351 GtkAllocation *allocation)
355 g_return_if_fail (widget != NULL);
356 g_return_if_fail (GTK_IS_SOCKET (widget));
357 g_return_if_fail (allocation != NULL);
359 socket = GTK_SOCKET (widget);
361 widget->allocation = *allocation;
362 if (GTK_WIDGET_REALIZED (widget))
364 gdk_window_move_resize (widget->window,
365 allocation->x, allocation->y,
366 allocation->width, allocation->height);
368 if (socket->plug_window)
370 gdk_error_trap_push ();
372 if (!socket->need_map &&
373 (allocation->width == socket->current_width) &&
374 (allocation->height == socket->current_height))
376 gtk_socket_send_configure_event (socket);
378 g_message ("GtkSocket - allocated no change: %d %d",
379 allocation->width, allocation->height));
383 gdk_window_move_resize (socket->plug_window,
385 allocation->width, allocation->height);
387 g_message ("GtkSocket - allocated: %d %d",
388 allocation->width, allocation->height));
389 socket->current_width = allocation->width;
390 socket->current_height = allocation->height;
393 if (socket->need_map)
395 gdk_window_show (socket->plug_window);
396 socket->need_map = FALSE;
400 gdk_error_trap_pop ();
409 guint accelerator_key;
410 GdkModifierType accelerator_mods;
414 grabbed_key_hash (gconstpointer a)
416 const GrabbedKey *key = a;
419 h = key->accelerator_key << 16;
420 h ^= key->accelerator_key >> 16;
421 h ^= key->accelerator_mods;
427 grabbed_key_equal (gconstpointer a, gconstpointer b)
429 const GrabbedKey *keya = a;
430 const GrabbedKey *keyb = b;
432 return (keya->accelerator_key == keyb->accelerator_key &&
433 keya->accelerator_mods == keyb->accelerator_mods);
437 add_grabbed_key (GtkSocket *socket,
438 guint hardware_keycode,
439 GdkModifierType mods)
443 GrabbedKey *found_key;
445 if (socket->grabbed_keys)
447 key.accelerator_key = hardware_keycode;
448 key.accelerator_mods = mods;
450 found_key = g_hash_table_lookup (socket->grabbed_keys, &key);
454 g_warning ("GtkSocket: request to add already present grabbed key %u,%#x\n",
455 hardware_keycode, mods);
460 if (!socket->grabbed_keys)
461 socket->grabbed_keys = g_hash_table_new (grabbed_key_hash, grabbed_key_equal);
463 new_key = g_new (GrabbedKey, 1);
465 new_key->accelerator_key = hardware_keycode;
466 new_key->accelerator_mods = mods;
468 g_hash_table_insert (socket->grabbed_keys, new_key, new_key);
472 remove_grabbed_key (GtkSocket *socket,
473 guint hardware_keycode,
474 GdkModifierType mods)
477 GrabbedKey *found_key = NULL;
479 if (socket->grabbed_keys)
481 key.accelerator_key = hardware_keycode;
482 key.accelerator_mods = mods;
484 found_key = g_hash_table_lookup (socket->grabbed_keys, &key);
489 g_hash_table_remove (socket->grabbed_keys, &key);
493 g_warning ("GtkSocket: request to remove non-present grabbed key %u,%#x\n",
494 hardware_keycode, mods);
498 toplevel_key_press_handler (GtkWidget *toplevel,
502 GrabbedKey search_key;
504 search_key.accelerator_key = event->hardware_keycode;
505 search_key.accelerator_mods = event->state;
507 if (socket->grabbed_keys &&
508 g_hash_table_lookup (socket->grabbed_keys, &search_key))
510 gtk_socket_key_press_event (GTK_WIDGET (socket), event);
511 gtk_signal_emit_stop_by_name (GTK_OBJECT (toplevel), "key_press_event");
522 toplevel_focus_in_handler (GtkWidget *toplevel,
523 GdkEventFocus *event,
526 /* It appears spurious focus in events can occur when
527 * the window is hidden. So we'll just check to see if
528 * the window is visible before actually handling the
529 * event. (Comment from gtkwindow.c)
531 if (GTK_WIDGET_VISIBLE (toplevel))
532 send_xembed_message (socket, XEMBED_WINDOW_ACTIVATE, 0, 0, 0,
533 gtk_get_current_event_time ()); /* Will be GDK_CURRENT_TIME */
537 toplevel_focus_out_handler (GtkWidget *toplevel,
538 GdkEventFocus *event,
541 send_xembed_message (socket, XEMBED_WINDOW_DEACTIVATE, 0, 0, 0,
542 gtk_get_current_event_time ()); /* Will be GDK_CURRENT_TIME */
546 gtk_socket_hierarchy_changed (GtkWidget *widget)
548 GtkSocket *socket = GTK_SOCKET (widget);
549 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
551 if (toplevel && !GTK_IS_WINDOW (toplevel))
554 if (toplevel != socket->toplevel)
556 if (socket->toplevel)
559 gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_key_press_handler), socket);
561 gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket);
562 gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket);
565 socket->toplevel = toplevel;
570 gtk_signal_connect (GTK_OBJECT (socket->toplevel), "key_press_event",
571 GTK_SIGNAL_FUNC (toplevel_key_press_handler), socket);
573 gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_in_event",
574 GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket);
575 gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_out_event",
576 GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket);
582 gtk_socket_grab_notify (GtkWidget *widget,
583 gboolean was_grabbed)
585 send_xembed_message (GTK_SOCKET (widget),
586 was_grabbed ? XEMBED_MODALITY_OFF : XEMBED_MODALITY_ON,
587 0, 0, 0, gtk_get_current_event_time ());
591 gtk_socket_key_press_event (GtkWidget *widget,
594 GtkSocket *socket = GTK_SOCKET (widget);
596 if (socket->plug_window)
600 xevent.xkey.type = KeyPress;
601 xevent.xkey.display = GDK_WINDOW_XDISPLAY (event->window);
602 xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
603 xevent.xkey.root = GDK_ROOT_WINDOW ();
604 xevent.xkey.time = event->time;
605 /* FIXME, the following might cause problems for non-GTK apps */
608 xevent.xkey.x_root = 0;
609 xevent.xkey.y_root = 0;
610 xevent.xkey.state = event->state;
611 xevent.xkey.keycode = event->hardware_keycode;
612 xevent.xkey.same_screen = TRUE; /* FIXME ? */
614 gdk_error_trap_push ();
615 XSendEvent (gdk_display,
616 GDK_WINDOW_XWINDOW (socket->plug_window),
617 False, NoEventMask, &xevent);
619 gdk_error_trap_pop ();
628 gtk_socket_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
630 GtkSocket *socket = GTK_SOCKET (widget);
632 if (!GTK_WIDGET_HAS_FOCUS (widget))
634 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
636 if (socket->plug_window)
638 send_xembed_message (socket, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0,
639 gtk_get_current_event_time ());
647 gtk_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
649 GtkSocket *socket = GTK_SOCKET (widget);
651 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
655 toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
659 XSetInputFocus (GDK_DISPLAY (),
660 GDK_WINDOW_XWINDOW (toplevel->window),
661 RevertToParent, CurrentTime); /* FIXME? */
666 if (socket->plug_window)
668 send_xembed_message (socket, XEMBED_FOCUS_OUT, 0, 0, 0,
669 gtk_get_current_event_time ());
672 socket->focus_in = FALSE;
678 gtk_socket_claim_focus (GtkSocket *socket)
681 socket->focus_in = TRUE;
683 /* Oh, the trickery... */
685 GTK_WIDGET_SET_FLAGS (socket, GTK_CAN_FOCUS);
686 gtk_widget_grab_focus (GTK_WIDGET (socket));
687 GTK_WIDGET_UNSET_FLAGS (socket, GTK_CAN_FOCUS);
689 /* FIXME: we might grab the focus even if we don't have
690 * it as an app... (and see _focus_in ()) */
691 if (socket->plug_window)
694 gdk_error_trap_push ();
695 XSetInputFocus (GDK_DISPLAY (),
696 GDK_WINDOW_XWINDOW (socket->plug_window),
697 RevertToParent, GDK_CURRENT_TIME);
699 gdk_error_trap_pop ();
705 gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction)
710 g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE);
712 socket = GTK_SOCKET (widget);
714 if (!GTK_WIDGET_HAS_FOCUS (widget))
720 case GTK_DIR_TAB_BACKWARD:
721 detail = XEMBED_FOCUS_LAST;
725 case GTK_DIR_TAB_FORWARD:
726 detail = XEMBED_FOCUS_FIRST;
730 send_xembed_message (socket, XEMBED_FOCUS_IN, detail, 0, 0,
731 gtk_get_current_event_time ());
733 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
734 gtk_widget_grab_focus (widget);
742 if (!socket->focus_in && socket->plug_window)
746 gtk_socket_claim_focus (socket);
748 xevent.xkey.type = KeyPress;
749 xevent.xkey.display = GDK_DISPLAY ();
750 xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
751 xevent.xkey.root = GDK_ROOT_WINDOW (); /* FIXME */
752 xevent.xkey.time = GDK_CURRENT_TIME; /* FIXME */
753 /* FIXME, the following might cause big problems for
757 xevent.xkey.x_root = 0;
758 xevent.xkey.y_root = 0;
759 xevent.xkey.state = 0;
760 xevent.xkey.same_screen = TRUE; /* FIXME ? */
765 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Up);
768 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Down);
771 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Left);
774 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Right);
776 case GTK_DIR_TAB_FORWARD:
777 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Tab);
779 case GTK_DIR_TAB_BACKWARD:
780 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Tab);
781 xevent.xkey.state = ShiftMask;
786 gdk_error_trap_push ();
787 XSendEvent (gdk_display,
788 GDK_WINDOW_XWINDOW (socket->plug_window),
789 False, NoEventMask, &xevent);
791 gdk_error_trap_pop ();
803 gtk_socket_send_configure_event (GtkSocket *socket)
807 g_return_if_fail (socket->plug_window != NULL);
809 event.xconfigure.type = ConfigureNotify;
810 event.xconfigure.display = gdk_display;
812 event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window);
813 event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window);
815 event.xconfigure.x = 0;
816 event.xconfigure.y = 0;
817 event.xconfigure.width = GTK_WIDGET(socket)->allocation.width;
818 event.xconfigure.height = GTK_WIDGET(socket)->allocation.height;
820 event.xconfigure.border_width = 0;
821 event.xconfigure.above = None;
822 event.xconfigure.override_redirect = False;
824 gdk_error_trap_push ();
825 XSendEvent (gdk_display,
826 GDK_WINDOW_XWINDOW (socket->plug_window),
827 False, NoEventMask, &event);
829 gdk_error_trap_pop ();
833 gtk_socket_add_window (GtkSocket *socket, GdkNativeWindow xid)
835 socket->plug_window = gdk_window_lookup (xid);
836 socket->same_app = TRUE;
838 if (!socket->plug_window)
841 GdkDragProtocol protocol;
843 socket->plug_window = gdk_window_foreign_new (xid);
844 if (!socket->plug_window) /* Already gone */
847 socket->same_app = FALSE;
849 gdk_error_trap_push ();
850 XSelectInput (GDK_DISPLAY (),
851 GDK_WINDOW_XWINDOW(socket->plug_window),
852 StructureNotifyMask | PropertyChangeMask);
854 if (gdk_drag_get_protocol (xid, &protocol))
855 gtk_drag_dest_set_proxy (GTK_WIDGET (socket), socket->plug_window,
858 gdk_error_trap_pop ();
860 gdk_window_add_filter (socket->plug_window,
861 gtk_socket_filter_func, socket);
863 /* Add a pointer to the socket on our toplevel window */
865 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
866 if (toplevel && GTK_IS_WINDOW (toplevel))
868 gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid);
871 gtk_widget_queue_resize (GTK_WIDGET (socket));
877 send_xembed_message (GtkSocket *socket,
885 g_message ("GtkSocket: Sending XEMBED message of type %d", message));
887 if (socket->plug_window)
891 xevent.xclient.window = GDK_WINDOW_XWINDOW (socket->plug_window);
892 xevent.xclient.type = ClientMessage;
893 xevent.xclient.message_type = gdk_atom_intern ("_XEMBED", FALSE);
894 xevent.xclient.format = 32;
895 xevent.xclient.data.l[0] = time;
896 xevent.xclient.data.l[1] = message;
897 xevent.xclient.data.l[2] = detail;
898 xevent.xclient.data.l[3] = data1;
899 xevent.xclient.data.l[4] = data2;
901 gdk_error_trap_push ();
902 XSendEvent (gdk_display,
903 GDK_WINDOW_XWINDOW (socket->plug_window),
904 False, NoEventMask, &xevent);
906 gdk_error_trap_pop ();
911 handle_xembed_message (GtkSocket *socket,
920 case XEMBED_EMBEDDED_NOTIFY:
921 case XEMBED_WINDOW_ACTIVATE:
922 case XEMBED_WINDOW_DEACTIVATE:
923 case XEMBED_MODALITY_ON:
924 case XEMBED_MODALITY_OFF:
925 case XEMBED_FOCUS_IN:
926 case XEMBED_FOCUS_OUT:
927 g_warning ("GtkSocket: Invalid _XEMBED message of type %ld received", message);
930 case XEMBED_REQUEST_FOCUS:
931 gtk_socket_claim_focus (socket);
934 case XEMBED_FOCUS_NEXT:
935 case XEMBED_FOCUS_PREV:
937 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
940 gtk_widget_child_focus (toplevel,
941 (message == XEMBED_FOCUS_NEXT ?
942 GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD));
947 case XEMBED_GRAB_KEY:
949 add_grabbed_key (socket, data1, data2);
952 case XEMBED_UNGRAB_KEY:
954 remove_grabbed_key (socket, data1, data2);
960 g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %ld", message));
965 static GdkFilterReturn
966 gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
972 GdkFilterReturn return_val;
974 socket = GTK_SOCKET (data);
975 widget = GTK_WIDGET (socket);
976 xevent = (XEvent *)gdk_xevent;
978 return_val = GDK_FILTER_CONTINUE;
980 switch (xevent->type)
984 XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
986 if (!socket->plug_window)
988 gtk_socket_add_window (socket, xcwe->window);
990 gdk_error_trap_push ();
991 gdk_window_move_resize(socket->plug_window,
993 widget->allocation.width,
994 widget->allocation.height);
996 gdk_error_trap_pop ();
998 socket->request_width = xcwe->width;
999 socket->request_height = xcwe->height;
1000 socket->have_size = TRUE;
1002 GTK_NOTE(PLUGSOCKET,
1003 g_message ("GtkSocket - window created with size: %d %d",
1004 socket->request_width,
1005 socket->request_height));
1008 return_val = GDK_FILTER_REMOVE;
1013 case ConfigureRequest:
1015 XConfigureRequestEvent *xcre = &xevent->xconfigurerequest;
1017 if (!socket->plug_window)
1018 gtk_socket_add_window (socket, xcre->window);
1020 if (xcre->window == GDK_WINDOW_XWINDOW (socket->plug_window))
1022 if (xcre->value_mask & (CWWidth | CWHeight))
1024 socket->request_width = xcre->width;
1025 socket->request_height = xcre->height;
1026 socket->have_size = TRUE;
1028 GTK_NOTE(PLUGSOCKET,
1029 g_message ("GtkSocket - configure request: %d %d",
1030 socket->request_width,
1031 socket->request_height));
1033 gtk_widget_queue_resize (widget);
1035 else if (xcre->value_mask & (CWX | CWY))
1037 gtk_socket_send_configure_event (socket);
1039 /* Ignore stacking requests. */
1041 return_val = GDK_FILTER_REMOVE;
1048 XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;
1050 if (socket->plug_window &&
1051 (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
1053 GtkWidget *toplevel;
1055 GTK_NOTE(PLUGSOCKET,
1056 g_message ("GtkSocket - destroy notify"));
1058 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
1059 if (toplevel && GTK_IS_WINDOW (toplevel))
1060 gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), xdwe->window);
1062 gdk_window_destroy_notify (socket->plug_window);
1063 gtk_widget_destroy (widget);
1065 socket->plug_window = NULL;
1067 return_val = GDK_FILTER_REMOVE;
1073 if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
1075 gtk_socket_claim_focus (socket);
1077 else if (xevent->xfocus.detail == NotifyInferior)
1080 GtkWidget *toplevel;
1081 toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
1085 XSetInputFocus (GDK_DISPLAY (),
1086 GDK_WINDOW_XWINDOW (toplevel->window),
1087 RevertToParent, CurrentTime); /* FIXME? */
1091 return_val = GDK_FILTER_REMOVE;
1094 return_val = GDK_FILTER_REMOVE;
1097 if (!socket->plug_window)
1098 gtk_socket_add_window (socket, xevent->xmaprequest.window);
1100 if (xevent->xmaprequest.window ==
1101 GDK_WINDOW_XWINDOW (socket->plug_window))
1103 GTK_NOTE(PLUGSOCKET,
1104 g_message ("GtkSocket - Map Request"));
1106 gdk_error_trap_push ();
1107 gdk_window_show (socket->plug_window);
1109 gdk_error_trap_pop ();
1111 return_val = GDK_FILTER_REMOVE;
1114 case PropertyNotify:
1115 if (xevent->xproperty.window ==
1116 GDK_WINDOW_XWINDOW (socket->plug_window))
1118 GdkDragProtocol protocol;
1120 if ((xevent->xproperty.atom == gdk_atom_intern ("XdndAware", FALSE)) ||
1121 (xevent->xproperty.atom == gdk_atom_intern ("_MOTIF_DRAG_RECEIVER_INFO", FALSE)))
1123 gdk_error_trap_push ();
1124 if (gdk_drag_get_protocol (xevent->xproperty.window, &protocol))
1125 gtk_drag_dest_set_proxy (GTK_WIDGET (socket),
1126 socket->plug_window,
1129 gdk_error_trap_pop ();
1131 return_val = GDK_FILTER_REMOVE;
1135 if (xevent->xclient.message_type == gdk_atom_intern ("_XEMBED", FALSE))
1137 handle_xembed_message (socket,
1138 xevent->xclient.data.l[1],
1139 xevent->xclient.data.l[2],
1140 xevent->xclient.data.l[3],
1141 xevent->xclient.data.l[4],
1142 xevent->xclient.data.l[0]);
1145 return_val = GDK_FILTER_REMOVE;