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 "gdkconfig.h"
30 #if defined (GDK_WINDOWING_X11)
32 #elif defined (GDK_WINDOWING_WIN32)
33 #include "win32/gdkwin32.h"
34 #elif defined(GDK_WINDOWING_FB)
35 #include "linux-fb/gdkfb.h"
38 #include "gdk/gdkkeysyms.h"
40 #include "gtkwindow.h"
41 #include "gtksignal.h"
42 #include "gtksocket.h"
47 #ifdef GDK_WINDOWING_X11
49 /* Forward declararations */
51 static void gtk_socket_class_init (GtkSocketClass *klass);
52 static void gtk_socket_init (GtkSocket *socket);
53 static void gtk_socket_realize (GtkWidget *widget);
54 static void gtk_socket_unrealize (GtkWidget *widget);
55 static void gtk_socket_size_request (GtkWidget *widget,
56 GtkRequisition *requisition);
57 static void gtk_socket_size_allocate (GtkWidget *widget,
58 GtkAllocation *allocation);
59 static void gtk_socket_hierarchy_changed (GtkWidget *widget);
60 static void gtk_socket_grab_notify (GtkWidget *widget,
61 gboolean was_grabbed);
62 static gboolean gtk_socket_key_press_event (GtkWidget *widget,
64 static gboolean gtk_socket_focus_in_event (GtkWidget *widget,
65 GdkEventFocus *event);
66 static void gtk_socket_claim_focus (GtkSocket *socket);
67 static gboolean gtk_socket_focus_out_event (GtkWidget *widget,
68 GdkEventFocus *event);
69 static void gtk_socket_send_configure_event (GtkSocket *socket);
70 static gboolean gtk_socket_focus (GtkContainer *container,
71 GtkDirectionType direction);
72 static GdkFilterReturn gtk_socket_filter_func (GdkXEvent *gdk_xevent,
76 static void send_xembed_message (GtkSocket *socket,
84 #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20
88 static GtkWidgetClass *parent_class = NULL;
91 gtk_socket_get_type (void)
93 static GtkType socket_type = 0;
97 static const GTypeInfo socket_info =
99 sizeof (GtkSocketClass),
100 NULL, /* base_init */
101 NULL, /* base_finalize */
102 (GClassInitFunc) gtk_socket_class_init,
103 NULL, /* class_finalize */
104 NULL, /* class_data */
106 16, /* n_preallocs */
107 (GInstanceInitFunc) gtk_socket_init,
110 socket_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkSocket", &socket_info, 0);
117 gtk_socket_class_init (GtkSocketClass *class)
119 GtkWidgetClass *widget_class;
120 GtkContainerClass *container_class;
122 widget_class = (GtkWidgetClass*) class;
123 container_class = (GtkContainerClass*) class;
125 parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
127 widget_class->realize = gtk_socket_realize;
128 widget_class->unrealize = gtk_socket_unrealize;
129 widget_class->size_request = gtk_socket_size_request;
130 widget_class->size_allocate = gtk_socket_size_allocate;
131 widget_class->hierarchy_changed = gtk_socket_hierarchy_changed;
133 widget_class->grab_notify = gtk_socket_grab_notify;
135 widget_class->key_press_event = gtk_socket_key_press_event;
136 widget_class->focus_in_event = gtk_socket_focus_in_event;
137 widget_class->focus_out_event = gtk_socket_focus_out_event;
139 container_class->focus = gtk_socket_focus;
143 gtk_socket_init (GtkSocket *socket)
145 socket->request_width = 0;
146 socket->request_height = 0;
147 socket->current_width = 0;
148 socket->current_height = 0;
150 socket->plug_window = NULL;
151 socket->same_app = FALSE;
152 socket->focus_in = FALSE;
153 socket->have_size = FALSE;
154 socket->need_map = FALSE;
158 gtk_socket_new (void)
162 socket = g_object_new (GTK_TYPE_SOCKET, NULL);
164 return GTK_WIDGET (socket);
168 gtk_socket_steal (GtkSocket *socket, GdkNativeWindow id)
171 gpointer user_data = NULL;
173 widget = GTK_WIDGET (socket);
175 socket->plug_window = gdk_window_lookup (id);
177 gdk_error_trap_push ();
179 if (socket->plug_window)
180 gdk_window_get_user_data (socket->plug_window,
186 GtkWidget *child_widget;
188 child_widget = GTK_WIDGET (socket->plug_window->user_data);
191 g_warning("Stealing from same app not yet implemented");
193 socket->same_app = TRUE;
197 socket->plug_window = gdk_window_foreign_new (id);
198 if (!socket->plug_window) /* was deleted before we could get it */
200 gdk_error_trap_pop ();
204 socket->same_app = FALSE;
205 socket->have_size = FALSE;
207 XSelectInput (GDK_DISPLAY (),
208 GDK_WINDOW_XWINDOW(socket->plug_window),
209 StructureNotifyMask | PropertyChangeMask);
211 gtk_widget_queue_resize (widget);
214 gdk_window_hide (socket->plug_window);
215 gdk_window_reparent (socket->plug_window, widget->window, 0, 0);
218 gdk_error_trap_pop ();
220 socket->need_map = TRUE;
224 gtk_socket_realize (GtkWidget *widget)
227 GdkWindowAttr attributes;
228 gint attributes_mask;
229 XWindowAttributes xattrs;
231 g_return_if_fail (widget != NULL);
232 g_return_if_fail (GTK_IS_SOCKET (widget));
234 socket = GTK_SOCKET (widget);
235 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
237 attributes.window_type = GDK_WINDOW_CHILD;
238 attributes.x = widget->allocation.x;
239 attributes.y = widget->allocation.y;
240 attributes.width = widget->allocation.width;
241 attributes.height = widget->allocation.height;
242 attributes.wclass = GDK_INPUT_OUTPUT;
243 attributes.visual = gtk_widget_get_visual (widget);
244 attributes.colormap = gtk_widget_get_colormap (widget);
245 attributes.event_mask = GDK_FOCUS_CHANGE_MASK;
247 attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
249 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
250 &attributes, attributes_mask);
251 gdk_window_set_user_data (widget->window, socket);
253 widget->style = gtk_style_attach (widget->style, widget->window);
254 gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
256 XGetWindowAttributes (GDK_DISPLAY (),
257 GDK_WINDOW_XWINDOW (widget->window),
260 XSelectInput (GDK_DISPLAY (),
261 GDK_WINDOW_XWINDOW(widget->window),
262 xattrs.your_event_mask |
263 SubstructureNotifyMask | SubstructureRedirectMask);
265 gdk_window_add_filter (widget->window, gtk_socket_filter_func, widget);
267 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
269 /* We sync here so that we make sure that if the XID for
270 * our window is passed to another application, SubstructureRedirectMask
271 * will be set by the time the other app creates its window.
277 gtk_socket_unrealize (GtkWidget *widget)
281 g_return_if_fail (widget != NULL);
282 g_return_if_fail (GTK_IS_SOCKET (widget));
284 socket = GTK_SOCKET (widget);
286 if (socket->plug_window)
288 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
289 if (toplevel && GTK_IS_WINDOW (toplevel))
290 gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel),
291 GDK_WINDOW_XWINDOW (socket->plug_window));
293 socket->plug_window = NULL;
297 if (socket->grabbed_keys)
299 g_hash_table_foreach (socket->grabbed_keys, (GHFunc)g_free, NULL);
300 g_hash_table_destroy (socket->grabbed_keys);
301 socket->grabbed_keys = NULL;
305 if (GTK_WIDGET_CLASS (parent_class)->unrealize)
306 (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
310 gtk_socket_size_request (GtkWidget *widget,
311 GtkRequisition *requisition)
315 g_return_if_fail (widget != NULL);
316 g_return_if_fail (GTK_IS_SOCKET (widget));
317 g_return_if_fail (requisition != NULL);
319 socket = GTK_SOCKET (widget);
321 if (!socket->have_size && socket->plug_window)
326 gdk_error_trap_push ();
328 if (XGetWMNormalHints (GDK_DISPLAY(),
329 GDK_WINDOW_XWINDOW (socket->plug_window),
332 /* This is obsolete, according the X docs, but many programs
334 if (hints.flags & (PSize | USSize))
336 socket->request_width = hints.width;
337 socket->request_height = hints.height;
339 else if (hints.flags & PMinSize)
341 socket->request_width = hints.min_width;
342 socket->request_height = hints.min_height;
344 else if (hints.flags & PBaseSize)
346 socket->request_width = hints.base_width;
347 socket->request_height = hints.base_height;
350 socket->have_size = TRUE; /* don't check again? */
352 gdk_error_trap_pop ();
355 requisition->width = MAX (socket->request_width, 1);
356 requisition->height = MAX (socket->request_height, 1);
360 gtk_socket_size_allocate (GtkWidget *widget,
361 GtkAllocation *allocation)
365 g_return_if_fail (widget != NULL);
366 g_return_if_fail (GTK_IS_SOCKET (widget));
367 g_return_if_fail (allocation != NULL);
369 socket = GTK_SOCKET (widget);
371 widget->allocation = *allocation;
372 if (GTK_WIDGET_REALIZED (widget))
374 gdk_window_move_resize (widget->window,
375 allocation->x, allocation->y,
376 allocation->width, allocation->height);
378 if (socket->plug_window)
380 gdk_error_trap_push ();
382 if (!socket->need_map &&
383 (allocation->width == socket->current_width) &&
384 (allocation->height == socket->current_height))
386 gtk_socket_send_configure_event (socket);
388 g_message ("GtkSocket - allocated no change: %d %d",
389 allocation->width, allocation->height));
393 gdk_window_move_resize (socket->plug_window,
395 allocation->width, allocation->height);
397 g_message ("GtkSocket - allocated: %d %d",
398 allocation->width, allocation->height));
399 socket->current_width = allocation->width;
400 socket->current_height = allocation->height;
403 if (socket->need_map)
405 gdk_window_show (socket->plug_window);
406 socket->need_map = FALSE;
410 gdk_error_trap_pop ();
419 guint accelerator_key;
420 GdkModifierType accelerator_mods;
424 grabbed_key_hash (gconstpointer a)
426 const GrabbedKey *key = a;
429 h = key->accelerator_key << 16;
430 h ^= key->accelerator_key >> 16;
431 h ^= key->accelerator_mods;
437 grabbed_key_equal (gconstpointer a, gconstpointer b)
439 const GrabbedKey *keya = a;
440 const GrabbedKey *keyb = b;
442 return (keya->accelerator_key == keyb->accelerator_key &&
443 keya->accelerator_mods == keyb->accelerator_mods);
447 add_grabbed_key (GtkSocket *socket,
448 guint hardware_keycode,
449 GdkModifierType mods)
453 GrabbedKey *found_key;
455 if (socket->grabbed_keys)
457 key.accelerator_key = hardware_keycode;
458 key.accelerator_mods = mods;
460 found_key = g_hash_table_lookup (socket->grabbed_keys, &key);
464 g_warning ("GtkSocket: request to add already present grabbed key %u,%#x\n",
465 hardware_keycode, mods);
470 if (!socket->grabbed_keys)
471 socket->grabbed_keys = g_hash_table_new (grabbed_key_hash, grabbed_key_equal);
473 new_key = g_new (GrabbedKey, 1);
475 new_key->accelerator_key = hardware_keycode;
476 new_key->accelerator_mods = mods;
478 g_hash_table_insert (socket->grabbed_keys, new_key, new_key);
482 remove_grabbed_key (GtkSocket *socket,
483 guint hardware_keycode,
484 GdkModifierType mods)
487 GrabbedKey *found_key = NULL;
489 if (socket->grabbed_keys)
491 key.accelerator_key = hardware_keycode;
492 key.accelerator_mods = mods;
494 found_key = g_hash_table_lookup (socket->grabbed_keys, &key);
499 g_hash_table_remove (socket->grabbed_keys, &key);
503 g_warning ("GtkSocket: request to remove non-present grabbed key %u,%#x\n",
504 hardware_keycode, mods);
508 toplevel_key_press_handler (GtkWidget *toplevel,
512 GrabbedKey search_key;
514 search_key.accelerator_key = event->hardware_keycode;
515 search_key.accelerator_mods = event->state;
517 if (socket->grabbed_keys &&
518 g_hash_table_lookup (socket->grabbed_keys, &search_key))
520 gtk_socket_key_press_event (GTK_WIDGET (socket), event);
521 gtk_signal_emit_stop_by_name (GTK_OBJECT (toplevel), "key_press_event");
532 toplevel_focus_in_handler (GtkWidget *toplevel,
533 GdkEventFocus *event,
536 /* It appears spurious focus in events can occur when
537 * the window is hidden. So we'll just check to see if
538 * the window is visible before actually handling the
539 * event. (Comment from gtkwindow.c)
541 if (GTK_WIDGET_VISIBLE (toplevel))
542 send_xembed_message (socket, XEMBED_WINDOW_ACTIVATE, 0, 0, 0,
543 gtk_get_current_event_time ()); /* Will be GDK_CURRENT_TIME */
547 toplevel_focus_out_handler (GtkWidget *toplevel,
548 GdkEventFocus *event,
551 send_xembed_message (socket, XEMBED_WINDOW_DEACTIVATE, 0, 0, 0,
552 gtk_get_current_event_time ()); /* Will be GDK_CURRENT_TIME */
556 gtk_socket_hierarchy_changed (GtkWidget *widget)
558 GtkSocket *socket = GTK_SOCKET (widget);
559 GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
561 if (toplevel && !GTK_IS_WINDOW (toplevel))
564 if (toplevel != socket->toplevel)
566 if (socket->toplevel)
569 gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_key_press_handler), socket);
571 gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket);
572 gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket);
575 socket->toplevel = toplevel;
580 gtk_signal_connect (GTK_OBJECT (socket->toplevel), "key_press_event",
581 GTK_SIGNAL_FUNC (toplevel_key_press_handler), socket);
583 gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_in_event",
584 GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket);
585 gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_out_event",
586 GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket);
592 gtk_socket_grab_notify (GtkWidget *widget,
593 gboolean was_grabbed)
595 send_xembed_message (GTK_SOCKET (widget),
596 was_grabbed ? XEMBED_MODALITY_OFF : XEMBED_MODALITY_ON,
597 0, 0, 0, gtk_get_current_event_time ());
601 gtk_socket_key_press_event (GtkWidget *widget,
604 GtkSocket *socket = GTK_SOCKET (widget);
606 if (socket->plug_window)
610 xevent.xkey.type = KeyPress;
611 xevent.xkey.display = GDK_WINDOW_XDISPLAY (event->window);
612 xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
613 xevent.xkey.root = GDK_ROOT_WINDOW ();
614 xevent.xkey.time = event->time;
615 /* FIXME, the following might cause problems for non-GTK apps */
618 xevent.xkey.x_root = 0;
619 xevent.xkey.y_root = 0;
620 xevent.xkey.state = event->state;
621 xevent.xkey.keycode = event->hardware_keycode;
622 xevent.xkey.same_screen = TRUE; /* FIXME ? */
624 gdk_error_trap_push ();
625 XSendEvent (gdk_display,
626 GDK_WINDOW_XWINDOW (socket->plug_window),
627 False, NoEventMask, &xevent);
629 gdk_error_trap_pop ();
638 gtk_socket_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
640 GtkSocket *socket = GTK_SOCKET (widget);
642 if (!GTK_WIDGET_HAS_FOCUS (widget))
644 GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
646 if (socket->plug_window)
648 send_xembed_message (socket, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0,
649 gtk_get_current_event_time ());
657 gtk_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
659 GtkSocket *socket = GTK_SOCKET (widget);
661 GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
665 toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
669 XSetInputFocus (GDK_DISPLAY (),
670 GDK_WINDOW_XWINDOW (toplevel->window),
671 RevertToParent, CurrentTime); /* FIXME? */
676 if (socket->plug_window)
678 send_xembed_message (socket, XEMBED_FOCUS_OUT, 0, 0, 0,
679 gtk_get_current_event_time ());
682 socket->focus_in = FALSE;
688 gtk_socket_claim_focus (GtkSocket *socket)
691 socket->focus_in = TRUE;
693 /* Oh, the trickery... */
695 GTK_WIDGET_SET_FLAGS (socket, GTK_CAN_FOCUS);
696 gtk_widget_grab_focus (GTK_WIDGET (socket));
697 GTK_WIDGET_UNSET_FLAGS (socket, GTK_CAN_FOCUS);
699 /* FIXME: we might grab the focus even if we don't have
700 * it as an app... (and see _focus_in ()) */
701 if (socket->plug_window)
704 gdk_error_trap_push ();
705 XSetInputFocus (GDK_DISPLAY (),
706 GDK_WINDOW_XWINDOW (socket->plug_window),
707 RevertToParent, GDK_CURRENT_TIME);
709 gdk_error_trap_pop ();
715 gtk_socket_focus (GtkContainer *container, GtkDirectionType direction)
720 g_return_val_if_fail (GTK_IS_SOCKET (container), FALSE);
722 socket = GTK_SOCKET (container);
724 if (!GTK_WIDGET_HAS_FOCUS (container))
730 case GTK_DIR_TAB_BACKWARD:
731 detail = XEMBED_FOCUS_LAST;
735 case GTK_DIR_TAB_FORWARD:
736 detail = XEMBED_FOCUS_FIRST;
740 send_xembed_message (socket, XEMBED_FOCUS_IN, detail, 0, 0,
741 gtk_get_current_event_time ());
743 GTK_WIDGET_SET_FLAGS (container, GTK_HAS_FOCUS);
744 gtk_widget_grab_focus (GTK_WIDGET (container));
752 if (!socket->focus_in && socket->plug_window)
756 gtk_socket_claim_focus (socket);
758 xevent.xkey.type = KeyPress;
759 xevent.xkey.display = GDK_DISPLAY ();
760 xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
761 xevent.xkey.root = GDK_ROOT_WINDOW (); /* FIXME */
762 xevent.xkey.time = GDK_CURRENT_TIME; /* FIXME */
763 /* FIXME, the following might cause big problems for
767 xevent.xkey.x_root = 0;
768 xevent.xkey.y_root = 0;
769 xevent.xkey.state = 0;
770 xevent.xkey.same_screen = TRUE; /* FIXME ? */
775 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Up);
778 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Down);
781 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Left);
784 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Right);
786 case GTK_DIR_TAB_FORWARD:
787 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Tab);
789 case GTK_DIR_TAB_BACKWARD:
790 xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Tab);
791 xevent.xkey.state = ShiftMask;
796 gdk_error_trap_push ();
797 XSendEvent (gdk_display,
798 GDK_WINDOW_XWINDOW (socket->plug_window),
799 False, NoEventMask, &xevent);
801 gdk_error_trap_pop ();
813 gtk_socket_send_configure_event (GtkSocket *socket)
817 g_return_if_fail (socket->plug_window != NULL);
819 event.xconfigure.type = ConfigureNotify;
820 event.xconfigure.display = gdk_display;
822 event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window);
823 event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window);
825 event.xconfigure.x = 0;
826 event.xconfigure.y = 0;
827 event.xconfigure.width = GTK_WIDGET(socket)->allocation.width;
828 event.xconfigure.height = GTK_WIDGET(socket)->allocation.height;
830 event.xconfigure.border_width = 0;
831 event.xconfigure.above = None;
832 event.xconfigure.override_redirect = False;
834 gdk_error_trap_push ();
835 XSendEvent (gdk_display,
836 GDK_WINDOW_XWINDOW (socket->plug_window),
837 False, NoEventMask, &event);
839 gdk_error_trap_pop ();
843 gtk_socket_add_window (GtkSocket *socket, GdkNativeWindow xid)
845 socket->plug_window = gdk_window_lookup (xid);
846 socket->same_app = TRUE;
848 if (!socket->plug_window)
851 GdkDragProtocol protocol;
853 socket->plug_window = gdk_window_foreign_new (xid);
854 if (!socket->plug_window) /* Already gone */
857 socket->same_app = FALSE;
859 gdk_error_trap_push ();
860 XSelectInput (GDK_DISPLAY (),
861 GDK_WINDOW_XWINDOW(socket->plug_window),
862 StructureNotifyMask | PropertyChangeMask);
864 if (gdk_drag_get_protocol (xid, &protocol))
865 gtk_drag_dest_set_proxy (GTK_WIDGET (socket), socket->plug_window,
868 gdk_error_trap_pop ();
870 gdk_window_add_filter (socket->plug_window,
871 gtk_socket_filter_func, socket);
873 /* Add a pointer to the socket on our toplevel window */
875 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
876 if (toplevel && GTK_IS_WINDOW (toplevel))
878 gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid);
881 gtk_widget_queue_resize (GTK_WIDGET (socket));
887 send_xembed_message (GtkSocket *socket,
895 g_message ("GtkSocket: Sending XEMBED message of type %d", message));
897 if (socket->plug_window)
901 xevent.xclient.window = GDK_WINDOW_XWINDOW (socket->plug_window);
902 xevent.xclient.type = ClientMessage;
903 xevent.xclient.message_type = gdk_atom_intern ("_XEMBED", FALSE);
904 xevent.xclient.format = 32;
905 xevent.xclient.data.l[0] = time;
906 xevent.xclient.data.l[1] = message;
907 xevent.xclient.data.l[2] = detail;
908 xevent.xclient.data.l[3] = data1;
909 xevent.xclient.data.l[4] = data2;
911 gdk_error_trap_push ();
912 XSendEvent (gdk_display,
913 GDK_WINDOW_XWINDOW (socket->plug_window),
914 False, NoEventMask, &xevent);
916 gdk_error_trap_pop ();
921 handle_xembed_message (GtkSocket *socket,
930 case XEMBED_EMBEDDED_NOTIFY:
931 case XEMBED_WINDOW_ACTIVATE:
932 case XEMBED_WINDOW_DEACTIVATE:
933 case XEMBED_MODALITY_ON:
934 case XEMBED_MODALITY_OFF:
935 case XEMBED_FOCUS_IN:
936 case XEMBED_FOCUS_OUT:
937 g_warning ("GtkSocket: Invalid _XEMBED message of type %ld received", message);
940 case XEMBED_REQUEST_FOCUS:
941 gtk_socket_claim_focus (socket);
944 case XEMBED_FOCUS_NEXT:
945 case XEMBED_FOCUS_PREV:
947 GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
948 if (toplevel && GTK_IS_CONTAINER (toplevel))
950 gtk_container_focus (GTK_CONTAINER (toplevel),
951 (message == XEMBED_FOCUS_NEXT ?
952 GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD));
957 case XEMBED_GRAB_KEY:
959 add_grabbed_key (socket, data1, data2);
962 case XEMBED_UNGRAB_KEY:
964 remove_grabbed_key (socket, data1, data2);
970 g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %ld", message));
975 static GdkFilterReturn
976 gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
982 GdkFilterReturn return_val;
984 socket = GTK_SOCKET (data);
985 widget = GTK_WIDGET (socket);
986 xevent = (XEvent *)gdk_xevent;
988 return_val = GDK_FILTER_CONTINUE;
990 switch (xevent->type)
994 XCreateWindowEvent *xcwe = &xevent->xcreatewindow;
996 if (!socket->plug_window)
998 gtk_socket_add_window (socket, xcwe->window);
1000 gdk_error_trap_push ();
1001 gdk_window_move_resize(socket->plug_window,
1003 widget->allocation.width,
1004 widget->allocation.height);
1006 gdk_error_trap_pop ();
1008 socket->request_width = xcwe->width;
1009 socket->request_height = xcwe->height;
1010 socket->have_size = TRUE;
1012 GTK_NOTE(PLUGSOCKET,
1013 g_message ("GtkSocket - window created with size: %d %d",
1014 socket->request_width,
1015 socket->request_height));
1018 return_val = GDK_FILTER_REMOVE;
1023 case ConfigureRequest:
1025 XConfigureRequestEvent *xcre = &xevent->xconfigurerequest;
1027 if (!socket->plug_window)
1028 gtk_socket_add_window (socket, xcre->window);
1030 if (xcre->window == GDK_WINDOW_XWINDOW (socket->plug_window))
1032 if (xcre->value_mask & (CWWidth | CWHeight))
1034 socket->request_width = xcre->width;
1035 socket->request_height = xcre->height;
1036 socket->have_size = TRUE;
1038 GTK_NOTE(PLUGSOCKET,
1039 g_message ("GtkSocket - configure request: %d %d",
1040 socket->request_width,
1041 socket->request_height));
1043 gtk_widget_queue_resize (widget);
1045 else if (xcre->value_mask & (CWX | CWY))
1047 gtk_socket_send_configure_event (socket);
1049 /* Ignore stacking requests. */
1051 return_val = GDK_FILTER_REMOVE;
1058 XDestroyWindowEvent *xdwe = &xevent->xdestroywindow;
1060 if (socket->plug_window &&
1061 (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window)))
1063 GtkWidget *toplevel;
1065 GTK_NOTE(PLUGSOCKET,
1066 g_message ("GtkSocket - destroy notify"));
1068 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
1069 if (toplevel && GTK_IS_WINDOW (toplevel))
1070 gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), xdwe->window);
1072 gdk_window_destroy_notify (socket->plug_window);
1073 gtk_widget_destroy (widget);
1075 socket->plug_window = NULL;
1077 return_val = GDK_FILTER_REMOVE;
1083 if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
1085 gtk_socket_claim_focus (socket);
1087 else if (xevent->xfocus.detail == NotifyInferior)
1090 GtkWidget *toplevel;
1091 toplevel = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW);
1095 XSetInputFocus (GDK_DISPLAY (),
1096 GDK_WINDOW_XWINDOW (toplevel->window),
1097 RevertToParent, CurrentTime); /* FIXME? */
1101 return_val = GDK_FILTER_REMOVE;
1104 return_val = GDK_FILTER_REMOVE;
1107 if (!socket->plug_window)
1108 gtk_socket_add_window (socket, xevent->xmaprequest.window);
1110 if (xevent->xmaprequest.window ==
1111 GDK_WINDOW_XWINDOW (socket->plug_window))
1113 GTK_NOTE(PLUGSOCKET,
1114 g_message ("GtkSocket - Map Request"));
1116 gdk_error_trap_push ();
1117 gdk_window_show (socket->plug_window);
1119 gdk_error_trap_pop ();
1121 return_val = GDK_FILTER_REMOVE;
1124 case PropertyNotify:
1125 if (xevent->xproperty.window ==
1126 GDK_WINDOW_XWINDOW (socket->plug_window))
1128 GdkDragProtocol protocol;
1130 if ((xevent->xproperty.atom == gdk_atom_intern ("XdndAware", FALSE)) ||
1131 (xevent->xproperty.atom == gdk_atom_intern ("_MOTIF_DRAG_RECEIVER_INFO", FALSE)))
1133 gdk_error_trap_push ();
1134 if (gdk_drag_get_protocol (xevent->xproperty.window, &protocol))
1135 gtk_drag_dest_set_proxy (GTK_WIDGET (socket),
1136 socket->plug_window,
1139 gdk_error_trap_pop ();
1141 return_val = GDK_FILTER_REMOVE;
1145 if (xevent->xclient.message_type == gdk_atom_intern ("_XEMBED", FALSE))
1147 handle_xembed_message (socket,
1148 xevent->xclient.data.l[1],
1149 xevent->xclient.data.l[2],
1150 xevent->xclient.data.l[3],
1151 xevent->xclient.data.l[4],
1152 xevent->xclient.data.l[0]);
1155 return_val = GDK_FILTER_REMOVE;
1166 gtk_socket_get_type (void)
1168 g_error ("GtkSocket not implemented");
1175 g_error ("GtkSocket not implemented");
1180 gtk_socket_steal (GtkSocket *socket, GdkNativeWindow id)
1182 g_error ("GtkSocket not implemented");
1185 #endif /* GDK_WINDOWING */