diff --git a/ChangeLog b/ChangeLog index 16dc7904f2..660a524e0f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ 2005-07-21 Tor Lillqvist + * gtk/gtksocket.c + * gtk/gtkplug.c: Splice out backend-dependend parts to separate + files, see below. + + * gtk/gtksocketprivate.h + * gtk/gtkplugprivate.h: New files. Declare the backend-specific + functions, and the private backend-independent functions they call + back to. + * gtk/gtksocket-stub.c * gtk/gtkplug-stub.c * gtk/gtksocket-x11.c diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 16dc7904f2..660a524e0f 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,5 +1,14 @@ 2005-07-21 Tor Lillqvist + * gtk/gtksocket.c + * gtk/gtkplug.c: Splice out backend-dependend parts to separate + files, see below. + + * gtk/gtksocketprivate.h + * gtk/gtkplugprivate.h: New files. Declare the backend-specific + functions, and the private backend-independent functions they call + back to. + * gtk/gtksocket-stub.c * gtk/gtkplug-stub.c * gtk/gtksocket-x11.c diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 16dc7904f2..660a524e0f 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,5 +1,14 @@ 2005-07-21 Tor Lillqvist + * gtk/gtksocket.c + * gtk/gtkplug.c: Splice out backend-dependend parts to separate + files, see below. + + * gtk/gtksocketprivate.h + * gtk/gtkplugprivate.h: New files. Declare the backend-specific + functions, and the private backend-independent functions they call + back to. + * gtk/gtksocket-stub.c * gtk/gtkplug-stub.c * gtk/gtksocket-x11.c diff --git a/gtk/gtkplug.c b/gtk/gtkplug.c index 45f06e0337..257afdb3af 100644 --- a/gtk/gtkplug.c +++ b/gtk/gtkplug.c @@ -29,11 +29,7 @@ #include "gtkmarshalers.h" #include "gtkplug.h" #include "gtkprivate.h" - -#include "gdk/gdkkeysyms.h" -#include "x11/gdkx.h" - -#include "gtkxembed.h" +#include "gtkplugprivate.h" #include "gtkalias.h" @@ -58,20 +54,16 @@ static gboolean gtk_plug_focus (GtkWidget *widget, GtkDirectionType direction); static void gtk_plug_check_resize (GtkContainer *container); static void gtk_plug_keys_changed (GtkWindow *window); -static GdkFilterReturn gtk_plug_filter_func (GdkXEvent *gdk_xevent, - GdkEvent *event, - gpointer data); -static void handle_modality_off (GtkPlug *plug); -static void xembed_set_info (GdkWindow *window, - unsigned long flags); - -/* From Tk */ -#define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20 - static GtkWindowClass *parent_class = NULL; static GtkBinClass *bin_class = NULL; +typedef struct +{ + guint accelerator_key; + GdkModifierType accelerator_mods; +} GrabbedKey; + enum { EMBEDDED, LAST_SIGNAL @@ -167,7 +159,7 @@ gtk_plug_set_is_child (GtkPlug *plug, if (is_child) { if (plug->modality_window) - handle_modality_off (plug); + _gtk_plug_handle_modality_off (plug); if (plug->modality_group) { @@ -206,6 +198,27 @@ gtk_plug_set_is_child (GtkPlug *plug, } } +/** + * gtk_plug_get_id: + * @plug: a #GtkPlug. + * + * Gets the window ID of a #GtkPlug widget, which can then + * be used to embed this window inside another window, for + * instance with gtk_socket_add_id(). + * + * Return value: the window ID for the plug + **/ +GdkNativeWindow +gtk_plug_get_id (GtkPlug *plug) +{ + g_return_val_if_fail (GTK_IS_PLUG (plug), 0); + + if (!GTK_WIDGET_REALIZED (plug)) + gtk_widget_realize (GTK_WIDGET (plug)); + + return _gtk_plug_windowing_get_id (plug); +} + /** * _gtk_plug_add_to_socket: * @plug: a #GtkPlug @@ -244,8 +257,16 @@ _gtk_plug_add_to_socket (GtkPlug *plug, g_signal_emit_by_name (socket, "plug_added", 0); } -static void -send_delete_event (GtkWidget *widget) +/** + * _gtk_plug_send_delete_event: + * widget: a #GtkWidget + * + * Send a GDK_DELETE event to the @widget and destroy it if + * necessary. Internal GTK function, called from this file or the + * backend-specific GtkPlug implementation. + */ +void +_gtk_plug_send_delete_event (GtkWidget *widget) { GdkEvent *event = gdk_event_new (GDK_DELETE); @@ -265,7 +286,7 @@ send_delete_event (GtkWidget *widget) /** * _gtk_plug_remove_from_socket: * @plug: a #GtkPlug - * @socket_: a #GtkSocket + * @socket: a #GtkSocket * * Removes a plug from a socket within the same application. **/ @@ -283,17 +304,19 @@ _gtk_plug_remove_from_socket (GtkPlug *plug, widget = GTK_WIDGET (plug); + if (GTK_WIDGET_IN_REPARENT (widget)) + return; + g_object_ref (plug); g_object_ref (socket); widget_was_visible = GTK_WIDGET_VISIBLE (plug); gdk_window_hide (widget->window); + GTK_PRIVATE_SET_FLAG (plug, GTK_IN_REPARENT); gdk_window_reparent (widget->window, gtk_widget_get_root_window (widget), 0, 0); - - GTK_PRIVATE_SET_FLAG (plug, GTK_IN_REPARENT); gtk_widget_unparent (GTK_WIDGET (plug)); GTK_PRIVATE_UNSET_FLAG (plug, GTK_IN_REPARENT); @@ -315,7 +338,8 @@ _gtk_plug_remove_from_socket (GtkPlug *plug, if (!result) gtk_widget_destroy (GTK_WIDGET (socket)); - send_delete_event (widget); + if (widget->window) + _gtk_plug_send_delete_event (widget); g_object_unref (plug); @@ -423,27 +447,6 @@ gtk_plug_new_for_display (GdkDisplay *display, return GTK_WIDGET (plug); } -/** - * gtk_plug_get_id: - * @plug: a #GtkPlug. - * - * Gets the window ID of a #GtkPlug widget, which can then - * be used to embed this window inside another window, for - * instance with gtk_socket_add_id(). - * - * Return value: the window ID for the plug - **/ -GdkNativeWindow -gtk_plug_get_id (GtkPlug *plug) -{ - g_return_val_if_fail (GTK_IS_PLUG (plug), 0); - - if (!GTK_WIDGET_REALIZED (plug)) - gtk_widget_realize (GTK_WIDGET (plug)); - - return GDK_WINDOW_XWINDOW (GTK_WIDGET (plug)->window); -} - static void gtk_plug_finalize (GObject *object) { @@ -477,7 +480,7 @@ gtk_plug_unrealize (GtkWidget *widget) if (!plug->same_app) { if (plug->modality_window) - handle_modality_off (plug); + _gtk_plug_handle_modality_off (plug); gtk_window_group_remove_window (plug->modality_group, GTK_WINDOW (plug)); g_object_unref (plug->modality_group); @@ -548,12 +551,14 @@ gtk_plug_realize (GtkWidget *widget) &attributes, attributes_mask); } - gdk_window_add_filter (widget->window, gtk_plug_filter_func, widget); + gdk_window_add_filter (widget->window, + _gtk_plug_windowing_filter_func, + widget); plug->modality_group = gtk_window_group_new (); gtk_window_group_add_window (plug->modality_group, window); - xembed_set_info (widget->window, 0); + _gtk_plug_windowing_realize_toplevel (plug); } else widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), @@ -596,6 +601,7 @@ gtk_plug_map (GtkWidget *widget) if (GTK_WIDGET_TOPLEVEL (widget)) { GtkBin *bin = GTK_BIN (widget); + GtkPlug *plug = GTK_PLUG (widget); GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED); @@ -604,7 +610,7 @@ gtk_plug_map (GtkWidget *widget) !GTK_WIDGET_MAPPED (bin->child)) gtk_widget_map (bin->child); - xembed_set_info (widget->window, XEMBED_MAPPED); + _gtk_plug_windowing_map_toplevel (plug); gdk_synthesize_window_state (widget->window, GDK_WINDOW_STATE_WITHDRAWN, @@ -619,10 +625,13 @@ gtk_plug_unmap (GtkWidget *widget) { if (GTK_WIDGET_TOPLEVEL (widget)) { + GtkPlug *plug = GTK_PLUG (widget); + GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED); gdk_window_hide (widget->window); - xembed_set_info (widget->window, 0); + + _gtk_plug_windowing_unmap_toplevel (plug); gdk_synthesize_window_state (widget->window, 0, @@ -698,18 +707,9 @@ gtk_plug_set_focus (GtkWindow *window, */ if (focus && !window->has_toplevel_focus) - { - _gtk_xembed_send_message (plug->socket_window, - XEMBED_REQUEST_FOCUS, 0, 0, 0); - } + _gtk_plug_windowing_set_focus (plug); } -typedef struct -{ - guint accelerator_key; - GdkModifierType accelerator_mods; -} GrabbedKey; - static guint grabbed_key_hash (gconstpointer a) { @@ -742,19 +742,38 @@ add_grabbed_key (gpointer key, gpointer val, gpointer data) if (!plug->grabbed_keys || !g_hash_table_lookup (plug->grabbed_keys, grabbed_key)) { - _gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_GRAB_KEY, 0, - grabbed_key->accelerator_key, grabbed_key->accelerator_mods); + _gtk_plug_windowing_add_grabbed_key (plug, + grabbed_key->accelerator_key, + grabbed_key->accelerator_mods); } } static void -add_grabbed_key_always (gpointer key, gpointer val, gpointer data) +add_grabbed_key_always (gpointer key, + gpointer val, + gpointer data) { GrabbedKey *grabbed_key = key; GtkPlug *plug = data; - _gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_GRAB_KEY, 0, - grabbed_key->accelerator_key, grabbed_key->accelerator_mods); + _gtk_plug_windowing_add_grabbed_key (plug, + grabbed_key->accelerator_key, + grabbed_key->accelerator_mods); +} + +/** + * _gtk_plug_add_all_grabbed_keys: + * + * @plug: a #GtkPlug + * + * Calls _gtk_plug_windowing_add_grabbed_key() on all the grabbed keys + * in the @plug. + */ +void +_gtk_plug_add_all_grabbed_keys (GtkPlug *plug) +{ + if (plug->grabbed_keys) + g_hash_table_foreach (plug->grabbed_keys, add_grabbed_key_always, plug); } static void @@ -766,8 +785,9 @@ remove_grabbed_key (gpointer key, gpointer val, gpointer data) if (!plug->grabbed_keys || !g_hash_table_lookup (plug->grabbed_keys, grabbed_key)) { - _gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_UNGRAB_KEY, 0, - grabbed_key->accelerator_key, grabbed_key->accelerator_mods); + _gtk_plug_windowing_remove_grabbed_key (plug, + grabbed_key->accelerator_key, + grabbed_key->accelerator_mods); } } @@ -810,29 +830,6 @@ gtk_plug_keys_changed (GtkWindow *window) } } -static void -focus_to_parent (GtkPlug *plug, - GtkDirectionType direction) -{ - XEmbedMessageType message = XEMBED_FOCUS_PREV; /* Quiet GCC */ - - switch (direction) - { - case GTK_DIR_UP: - case GTK_DIR_LEFT: - case GTK_DIR_TAB_BACKWARD: - message = XEMBED_FOCUS_PREV; - break; - case GTK_DIR_DOWN: - case GTK_DIR_RIGHT: - case GTK_DIR_TAB_FORWARD: - message = XEMBED_FOCUS_NEXT; - break; - } - - _gtk_xembed_send_focus_message (plug->socket_window, message, 0); -} - static gboolean gtk_plug_focus (GtkWidget *widget, GtkDirectionType direction) @@ -872,7 +869,7 @@ gtk_plug_focus (GtkWidget *widget, } if (!GTK_CONTAINER (window)->focus_child) - focus_to_parent (plug, direction); + _gtk_plug_windowing_focus_to_parent (plug, direction); return FALSE; } @@ -886,9 +883,58 @@ gtk_plug_check_resize (GtkContainer *container) GTK_CONTAINER_CLASS (bin_class)->check_resize (container); } -static void -focus_first_last (GtkPlug *plug, - GtkDirectionType direction) +/** + * _gtk_plug_handle_modality_on: + * + * @plug: a #GtkPlug + * + * Called from the GtkPlug backend when the corresponding socket has + * told the plug that it modality has toggled on. + */ +void +_gtk_plug_handle_modality_on (GtkPlug *plug) +{ + if (!plug->modality_window) + { + plug->modality_window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_screen (GTK_WINDOW (plug->modality_window), + gtk_widget_get_screen (GTK_WIDGET (plug))); + gtk_widget_realize (plug->modality_window); + gtk_window_group_add_window (plug->modality_group, GTK_WINDOW (plug->modality_window)); + gtk_grab_add (plug->modality_window); + } +} + +/** + * _gtk_plug_handle_modality_off: + * + * @plug: a #GtkPlug + * + * Called from the GtkPlug backend when the corresponding socket has + * told the plug that it modality has toggled off. + */ +void +_gtk_plug_handle_modality_off (GtkPlug *plug) +{ + if (plug->modality_window) + { + gtk_widget_destroy (plug->modality_window); + plug->modality_window = NULL; + } +} + +/** + * _gtk_plug_focus_first_last: + * + * @plug: a #GtkPlug + * @direction: a direction + * + * Called from the GtkPlug backend when the corresponding socket has + * told the plug that it has received the focus. + */ +void +_gtk_plug_focus_first_last (GtkPlug *plug, + GtkDirectionType direction) { GtkWindow *window = GTK_WINDOW (plug); GtkWidget *parent; @@ -908,237 +954,5 @@ focus_first_last (GtkPlug *plug, gtk_widget_child_focus (GTK_WIDGET (plug), direction); } -static void -handle_modality_on (GtkPlug *plug) -{ - if (!plug->modality_window) - { - plug->modality_window = gtk_window_new (GTK_WINDOW_POPUP); - gtk_window_set_screen (GTK_WINDOW (plug->modality_window), - gtk_widget_get_screen (GTK_WIDGET (plug))); - gtk_widget_realize (plug->modality_window); - gtk_window_group_add_window (plug->modality_group, GTK_WINDOW (plug->modality_window)); - gtk_grab_add (plug->modality_window); - } -} - -static void -handle_modality_off (GtkPlug *plug) -{ - if (plug->modality_window) - { - gtk_widget_destroy (plug->modality_window); - plug->modality_window = NULL; - } -} - -static void -xembed_set_info (GdkWindow *window, - unsigned long flags) -{ - GdkDisplay *display = gdk_drawable_get_display (window); - unsigned long buffer[2]; - - Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO"); - - buffer[0] = GTK_XEMBED_PROTOCOL_VERSION; - buffer[1] = flags; - - XChangeProperty (GDK_DISPLAY_XDISPLAY (display), - GDK_WINDOW_XWINDOW (window), - xembed_info_atom, xembed_info_atom, 32, - PropModeReplace, - (unsigned char *)buffer, 2); -} - -static void -handle_xembed_message (GtkPlug *plug, - XEmbedMessageType message, - glong detail, - glong data1, - glong data2, - guint32 time) -{ - GtkWindow *window = GTK_WINDOW (plug); - - GTK_NOTE (PLUGSOCKET, - g_message ("GtkPlug: Message of type %d received", message)); - - switch (message) - { - case XEMBED_EMBEDDED_NOTIFY: - break; - case XEMBED_WINDOW_ACTIVATE: - _gtk_window_set_is_active (window, TRUE); - break; - case XEMBED_WINDOW_DEACTIVATE: - _gtk_window_set_is_active (window, FALSE); - break; - - case XEMBED_MODALITY_ON: - handle_modality_on (plug); - break; - case XEMBED_MODALITY_OFF: - handle_modality_off (plug); - break; - - case XEMBED_FOCUS_IN: - _gtk_window_set_has_toplevel_focus (window, TRUE); - switch (detail) - { - case XEMBED_FOCUS_FIRST: - focus_first_last (plug, GTK_DIR_TAB_FORWARD); - break; - case XEMBED_FOCUS_LAST: - focus_first_last (plug, GTK_DIR_TAB_BACKWARD); - break; - case XEMBED_FOCUS_CURRENT: - break; - } - break; - - case XEMBED_FOCUS_OUT: - _gtk_window_set_has_toplevel_focus (window, FALSE); - break; - - case XEMBED_GRAB_KEY: - case XEMBED_UNGRAB_KEY: - case XEMBED_GTK_GRAB_KEY: - case XEMBED_GTK_UNGRAB_KEY: - case XEMBED_REQUEST_FOCUS: - case XEMBED_FOCUS_NEXT: - case XEMBED_FOCUS_PREV: - g_warning ("GtkPlug: Invalid _XEMBED message of type %d received", message); - break; - - default: - GTK_NOTE(PLUGSOCKET, - g_message ("GtkPlug: Ignoring unknown _XEMBED message of type %d", message)); - break; - } -} - -static GdkFilterReturn -gtk_plug_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) -{ - GdkScreen *screen = gdk_drawable_get_screen (event->any.window); - GdkDisplay *display = gdk_screen_get_display (screen); - GtkPlug *plug = GTK_PLUG (data); - XEvent *xevent = (XEvent *)gdk_xevent; - - GdkFilterReturn return_val; - - return_val = GDK_FILTER_CONTINUE; - - switch (xevent->type) - { - case ClientMessage: - if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED")) - { - _gtk_xembed_push_message (xevent); - handle_xembed_message (plug, - xevent->xclient.data.l[1], - xevent->xclient.data.l[2], - xevent->xclient.data.l[3], - xevent->xclient.data.l[4], - xevent->xclient.data.l[0]); - _gtk_xembed_pop_message (); - - return GDK_FILTER_REMOVE; - } - else if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW")) - { - /* We filter these out because we take being reparented back to the - * root window as the reliable end of the embedding protocol - */ - - return GDK_FILTER_REMOVE; - } - break; - case ReparentNotify: - { - XReparentEvent *xre = &xevent->xreparent; - gboolean was_embedded = plug->socket_window != NULL; - - return_val = GDK_FILTER_REMOVE; - - g_object_ref (plug); - - if (was_embedded) - { - /* End of embedding protocol for previous socket */ - - /* FIXME: race if we remove from another socket and - * then add to a local window before we get notification - * Probably need check in _gtk_plug_add_to_socket - */ - - if (xre->parent != GDK_WINDOW_XWINDOW (plug->socket_window)) - { - GtkWidget *widget = GTK_WIDGET (plug); - - gdk_window_set_user_data (plug->socket_window, NULL); - g_object_unref (plug->socket_window); - plug->socket_window = NULL; - - /* Emit a delete window, as if the user attempted - * to close the toplevel. Simple as to how we - * handle WM_DELETE_WINDOW, if it isn't handled - * we destroy the widget. BUt only do this if - * we are being reparented to the root window. - * Moving from one embedder to another should - * be invisible to the app. - */ - - if (xre->parent == GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen))) - send_delete_event (widget); - } - else - goto done; - } - - if (xre->parent != GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen))) - { - /* Start of embedding protocol */ - - plug->socket_window = gdk_window_lookup_for_display (display, xre->parent); - if (plug->socket_window) - { - gpointer user_data = NULL; - gdk_window_get_user_data (plug->socket_window, &user_data); - - if (user_data) - { - g_warning (G_STRLOC "Plug reparented unexpectedly into window in the same process"); - plug->socket_window = NULL; - break; - } - - g_object_ref (plug->socket_window); - } - else - { - plug->socket_window = gdk_window_foreign_new_for_display (display, xre->parent); - if (!plug->socket_window) /* Already gone */ - break; - } - - if (plug->grabbed_keys) - g_hash_table_foreach (plug->grabbed_keys, add_grabbed_key_always, plug); - - if (!was_embedded) - g_signal_emit (plug, plug_signals[EMBEDDED], 0); - } - - done: - g_object_unref (plug); - - break; - } - } - - return GDK_FILTER_CONTINUE; -} - #define __GTK_PLUG_C__ #include "gtkaliasdef.c" diff --git a/gtk/gtkplugprivate.h b/gtk/gtkplugprivate.h new file mode 100644 index 0000000000..fb173c1340 --- /dev/null +++ b/gtk/gtkplugprivate.h @@ -0,0 +1,141 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifndef __GTK_PLUG_PRIVATE_H__ +#define __GTK_PLUG_PRIVATE_H__ + +/* In gtkplug.c: */ +void _gtk_plug_send_delete_event (GtkWidget *widget); +void _gtk_plug_add_all_grabbed_keys (GtkPlug *plug); +void _gtk_plug_focus_first_last (GtkPlug *plug, + GtkDirectionType direction); +void _gtk_plug_handle_modality_on (GtkPlug *plug); +void _gtk_plug_handle_modality_off (GtkPlug *plug); + +/* In backend-specific file: */ + +/** + * _gtk_plug_windowing_get_id: + * + * @plug: a #GtkPlug + * + * Returns the native window system identifier for the plug's window. + */ +GdkNativeWindow _gtk_plug_windowing_get_id (GtkPlug *plug); + +/** + * _gtk_plug_windowing_realize_toplevel: + * + * @plug_window: a #GtkPlug's #GdkWindow + * + * Called from GtkPlug's realize method. Should tell the corresponding + * socket that the plug has been realized. + */ +void _gtk_plug_windowing_realize_toplevel (GtkPlug *plug); + +/** + * _gtk_plug_windowing_map_toplevel: + * + * @plug: a #GtkPlug + * + * Called from GtkPlug's map method. Should tell the corresponding + * #GtkSocket that the plug has been mapped. + */ +void _gtk_plug_windowing_map_toplevel (GtkPlug *plug); + +/** + * _gtk_plug_windowing_map_toplevel: + * + * @plug: a #GtkPlug + * + * Called from GtkPlug's unmap method. Should tell the corresponding + * #GtkSocket that the plug has been unmapped. + */ +void _gtk_plug_windowing_unmap_toplevel (GtkPlug *plug); + +/** + * _gtk_plug_windowing_set_focus: + * + * @plug: a #GtkPlug + * + * Called from GtkPlug's set_focus method. Should tell the corresponding + * #GtkSocket to request focus. + */ +void _gtk_plug_windowing_set_focus (GtkPlug *plug); + +/** + * _gtk_plug_windowing_add_grabbed_key: + * + * @plug: a #GtkPlug + * @accelerator_key: a key + * @accelerator_mods: modifiers for it + * + * Called from GtkPlug's keys_changed method. Should tell the + * corresponding #GtkSocket to grab the key. + */ +void _gtk_plug_windowing_add_grabbed_key (GtkPlug *plug, + guint accelerator_key, + GdkModifierType accelerator_mods); + +/** + * _gtk_plug_windowing_remove_grabbed_key: + * + * @plug: a #GtkPlug + * @accelerator_key: a key + * @accelerator_mods: modifiers for it + * + * Called from GtkPlug's keys_changed method. Should tell the + * corresponding #GtkSocket to remove the key grab. + */ +void _gtk_plug_windowing_remove_grabbed_key (GtkPlug *plug, + guint accelerator_key, + GdkModifierType accelerator_mods); + +/** + * _gtk_plug_windowing_focus_to_parent: + * + * @plug: a #GtkPlug + * @direction: a direction + * + * Called from GtkPlug's focus method. Should tell the corresponding + * #GtkSocket to move the focus. + */ +void _gtk_plug_windowing_focus_to_parent (GtkPlug *plug, + GtkDirectionType direction); + +/** + * _gtk_plug_windowing_filter_func: + * + * @gdk_xevent: a windowing system native event + * @event: a pre-allocated empty GdkEvent + * @data: the #GtkPlug + * + * Event filter function installed on plug windows. + */ +GdkFilterReturn _gtk_plug_windowing_filter_func (GdkXEvent *gdk_xevent, + GdkEvent *event, + gpointer data); + +#endif /* __GTK_PLUG_PRIVATE_H__ */ diff --git a/gtk/gtksocket.c b/gtk/gtksocket.c index a1679fbe6b..c2b28e31ea 100644 --- a/gtk/gtksocket.c +++ b/gtk/gtksocket.c @@ -35,20 +35,11 @@ #include "gtkplug.h" #include "gtkprivate.h" #include "gtksocket.h" +#include "gtksocketprivate.h" #include "gtkdnd.h" -#include "x11/gdkx.h" - -#include "gtkxembed.h" #include "gtkalias.h" -typedef struct _GtkSocketPrivate GtkSocketPrivate; - -struct _GtkSocketPrivate -{ - gint resize_count; -}; - /* Forward declararations */ static void gtk_socket_class_init (GtkSocketClass *klass); @@ -68,9 +59,6 @@ static void gtk_socket_grab_notify (GtkWidget *widget, gboolean was_grabbed); static gboolean gtk_socket_key_event (GtkWidget *widget, GdkEventKey *event); -static void gtk_socket_claim_focus (GtkSocket *socket, - gboolean send_event); -static void gtk_socket_send_configure_event (GtkSocket *socket); static gboolean gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction); static void gtk_socket_remove (GtkContainer *container, @@ -81,22 +69,14 @@ static void gtk_socket_forall (GtkContainer *container, gpointer callback_data); -static void gtk_socket_add_window (GtkSocket *socket, - GdkNativeWindow xid, - gboolean need_reparent); -static GdkFilterReturn gtk_socket_filter_func (GdkXEvent *gdk_xevent, - GdkEvent *event, - gpointer data); - -static gboolean xembed_get_info (GdkWindow *gdk_window, - unsigned long *version, - unsigned long *flags); - -/* From Tk */ -#define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20 - /* Local data */ +typedef struct +{ + guint accel_key; + GdkModifierType accel_mods; +} GrabbedKey; + enum { PLUG_ADDED, PLUG_REMOVED, @@ -107,8 +87,16 @@ static guint socket_signals[LAST_SIGNAL] = { 0 }; static GtkWidgetClass *parent_class = NULL; -static GtkSocketPrivate * -gtk_socket_get_private (GtkSocket *socket) +/** + * _gtk_socket_get_private: + * + * @socket: a #GtkSocket + * + * Returns the private data associated with a GtkSocket, creating it + * first if necessary. + */ +GtkSocketPrivate * +_gtk_socket_get_private (GtkSocket *socket) { GtkSocketPrivate *private; static GQuark private_quark = 0; @@ -271,7 +259,8 @@ gtk_socket_new (void) * before you can make this call. **/ void -gtk_socket_steal (GtkSocket *socket, GdkNativeWindow wid) +gtk_socket_steal (GtkSocket *socket, + GdkNativeWindow wid) { g_return_if_fail (GTK_IS_SOCKET (socket)); g_return_if_fail (GTK_WIDGET_ANCHORED (socket)); @@ -279,7 +268,7 @@ gtk_socket_steal (GtkSocket *socket, GdkNativeWindow wid) if (!GTK_WIDGET_REALIZED (socket)) gtk_widget_realize (GTK_WIDGET (socket)); - gtk_socket_add_window (socket, wid, TRUE); + _gtk_socket_add_window (socket, wid, TRUE); } /** @@ -301,7 +290,8 @@ gtk_socket_steal (GtkSocket *socket, GdkNativeWindow wid) * before you can make this call. **/ void -gtk_socket_add_id (GtkSocket *socket, GdkNativeWindow window_id) +gtk_socket_add_id (GtkSocket *socket, + GdkNativeWindow window_id) { g_return_if_fail (GTK_IS_SOCKET (socket)); g_return_if_fail (GTK_WIDGET_ANCHORED (socket)); @@ -309,7 +299,7 @@ gtk_socket_add_id (GtkSocket *socket, GdkNativeWindow window_id) if (!GTK_WIDGET_REALIZED (socket)) gtk_widget_realize (GTK_WIDGET (socket)); - gtk_socket_add_window (socket, window_id, TRUE); + _gtk_socket_add_window (socket, window_id, TRUE); } /** @@ -334,7 +324,7 @@ gtk_socket_get_id (GtkSocket *socket) if (!GTK_WIDGET_REALIZED (socket)) gtk_widget_realize (GTK_WIDGET (socket)); - return GDK_WINDOW_XWINDOW (GTK_WIDGET (socket)->window); + return _gtk_socket_windowing_get_id (socket); } static void @@ -343,7 +333,6 @@ gtk_socket_realize (GtkWidget *widget) GtkSocket *socket; GdkWindowAttr attributes; gint attributes_mask; - XWindowAttributes xattrs; g_return_if_fail (GTK_IS_SOCKET (widget)); @@ -369,16 +358,11 @@ gtk_socket_realize (GtkWidget *widget) widget->style = gtk_style_attach (widget->style, widget->window); gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); - XGetWindowAttributes (GDK_WINDOW_XDISPLAY (widget->window), - GDK_WINDOW_XWINDOW (widget->window), - &xattrs); + _gtk_socket_windowing_realize_window (socket); - XSelectInput (GDK_WINDOW_XDISPLAY (widget->window), - GDK_WINDOW_XWINDOW (widget->window), - xattrs.your_event_mask | - SubstructureNotifyMask | SubstructureRedirectMask); - - gdk_window_add_filter (widget->window, gtk_socket_filter_func, widget); + gdk_window_add_filter (widget->window, + _gtk_socket_windowing_filter_func, + widget); GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); @@ -389,16 +373,22 @@ gtk_socket_realize (GtkWidget *widget) gdk_display_sync (gtk_widget_get_display (widget)); } -static void -gtk_socket_end_embedding (GtkSocket *socket) +/** + * _gtk_socket_end_embedding: + * + * @socket: a #GtkSocket + * + * Called to end the embedding of a plug in the socket. + */ +void +_gtk_socket_end_embedding (GtkSocket *socket) { - GtkSocketPrivate *private = gtk_socket_get_private (socket); + GtkSocketPrivate *private = _gtk_socket_get_private (socket); GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); gint i; if (toplevel && GTK_IS_WINDOW (toplevel)) - gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel), - GDK_WINDOW_XWINDOW (socket->plug_window)); + _gtk_socket_windowing_end_embedding_toplevel (socket); g_object_unref (socket->plug_window); socket->plug_window = NULL; @@ -427,7 +417,7 @@ gtk_socket_unrealize (GtkWidget *widget) } else if (socket->plug_window) { - gtk_socket_end_embedding (socket); + _gtk_socket_end_embedding (socket); } if (GTK_WIDGET_CLASS (parent_class)->unrealize) @@ -447,34 +437,7 @@ gtk_socket_size_request (GtkWidget *widget, else { if (socket->is_mapped && !socket->have_size && socket->plug_window) - { - XSizeHints hints; - long supplied; - - gdk_error_trap_push (); - - socket->request_width = 1; - socket->request_height = 1; - - if (XGetWMNormalHints (GDK_WINDOW_XDISPLAY (socket->plug_window), - GDK_WINDOW_XWINDOW (socket->plug_window), - &hints, &supplied)) - { - if (hints.flags & PMinSize) - { - socket->request_width = hints.min_width; - socket->request_height = hints.min_height; - } - else if (hints.flags & PBaseSize) - { - socket->request_width = hints.base_width; - socket->request_height = hints.base_height; - } - } - socket->have_size = TRUE; - - gdk_error_trap_pop (); - } + _gtk_socket_windowing_size_request (socket); if (socket->is_mapped && socket->have_size) { @@ -520,7 +483,7 @@ gtk_socket_size_allocate (GtkWidget *widget, } else if (socket->plug_window) { - GtkSocketPrivate *private = gtk_socket_get_private (socket); + GtkSocketPrivate *private = _gtk_socket_get_private (socket); gdk_error_trap_push (); @@ -533,9 +496,9 @@ gtk_socket_size_allocate (GtkWidget *widget, if (private->resize_count) private->resize_count--; - GTK_NOTE(PLUGSOCKET, - g_message ("GtkSocket - allocated: %d %d", - allocation->width, allocation->height)); + GTK_NOTE (PLUGSOCKET, + g_message ("GtkSocket - allocated: %d %d", + allocation->width, allocation->height)); socket->current_width = allocation->width; socket->current_height = allocation->height; } @@ -548,11 +511,11 @@ gtk_socket_size_allocate (GtkWidget *widget, while (private->resize_count) { - gtk_socket_send_configure_event (socket); + _gtk_socket_windowing_send_configure_event (socket); private->resize_count--; - GTK_NOTE(PLUGSOCKET, - g_message ("GtkSocket - sending synthetic configure: %d %d", - allocation->width, allocation->height)); + GTK_NOTE (PLUGSOCKET, + g_message ("GtkSocket - sending synthetic configure: %d %d", + allocation->width, allocation->height)); } gdk_display_sync (gtk_widget_get_display (widget)); @@ -561,12 +524,6 @@ gtk_socket_size_allocate (GtkWidget *widget, } } -typedef struct -{ - guint accel_key; - GdkModifierType accel_mods; -} GrabbedKey; - static gboolean activate_key (GtkAccelGroup *accel_group, GObject *acceleratable, @@ -574,35 +531,14 @@ activate_key (GtkAccelGroup *accel_group, GdkModifierType accel_mods, GrabbedKey *grabbed_key) { - XEvent xevent; GdkEvent *gdk_event = gtk_get_current_event (); GtkSocket *socket = g_object_get_data (G_OBJECT (accel_group), "gtk-socket"); - GdkScreen *screen = gdk_drawable_get_screen (socket->plug_window); gboolean retval = FALSE; if (gdk_event && gdk_event->type == GDK_KEY_PRESS && socket->plug_window) { - xevent.xkey.type = KeyPress; - xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window); - xevent.xkey.root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)); - xevent.xkey.subwindow = None; - xevent.xkey.time = gdk_event->key.time; - xevent.xkey.x = 0; - xevent.xkey.y = 0; - xevent.xkey.x_root = 0; - xevent.xkey.y_root = 0; - xevent.xkey.state = gdk_event->key.state; - xevent.xkey.keycode = gdk_event->key.hardware_keycode; - xevent.xkey.same_screen = True; - - gdk_error_trap_push (); - XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window), - GDK_WINDOW_XWINDOW (socket->plug_window), - False, KeyPressMask, &xevent); - gdk_display_sync (gdk_screen_get_display (screen)); - gdk_error_trap_pop (); - + _gtk_socket_windowing_send_key_event (socket, gdk_event, TRUE); retval = TRUE; } @@ -623,10 +559,20 @@ find_accel_key (GtkAccelKey *key, key->accel_mods == grabbed_key->accel_mods); } -static void -add_grabbed_key (GtkSocket *socket, - guint keyval, - GdkModifierType modifiers) +/** + * _gtk_socket_add_grabbed_key: + * + * @socket: a #GtkSocket + * @keyval: a key + * @modifiers: modifiers for the key + * + * Called from the GtkSocket platform-specific backend when the + * corresponding plug has told the socket to grab a key. + */ +void +_gtk_socket_add_grabbed_key (GtkSocket *socket, + guint keyval, + GdkModifierType modifiers) { GClosure *closure; GrabbedKey *grabbed_key; @@ -652,10 +598,20 @@ add_grabbed_key (GtkSocket *socket, closure); } -static void -remove_grabbed_key (GtkSocket *socket, - guint keyval, - GdkModifierType modifiers) +/** + * _gtk_socket_remove_grabbed_key: + * + * @socket: a #GtkSocket + * @keyval: a key + * @modifiers: modifiers for the key + * + * Called from the GtkSocket backend when the corresponding plug has + * told the socket to remove a key grab. + */ +void +_gtk_socket_remove_grabbed_key (GtkSocket *socket, + guint keyval, + GdkModifierType modifiers) { gint i; @@ -683,6 +639,7 @@ socket_update_focus_in (GtkSocket *socket) if (socket->plug_window) { GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); + if (GTK_WIDGET_TOPLEVEL (toplevel) && GTK_WINDOW (toplevel)->has_toplevel_focus && gtk_widget_is_focus (GTK_WIDGET (socket))) @@ -693,12 +650,7 @@ socket_update_focus_in (GtkSocket *socket) { socket->focus_in = focus_in; - if (focus_in) - _gtk_xembed_send_focus_message (socket->plug_window, - XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT); - else - _gtk_xembed_send_message (socket->plug_window, - XEMBED_FOCUS_OUT, 0, 0, 0); + _gtk_socket_windowing_focus_change (socket, focus_in); } } @@ -710,6 +662,7 @@ socket_update_active (GtkSocket *socket) if (socket->plug_window) { GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket)); + if (GTK_WIDGET_TOPLEVEL (toplevel) && GTK_WINDOW (toplevel)->is_active) active = TRUE; @@ -719,9 +672,7 @@ socket_update_active (GtkSocket *socket) { socket->active = active; - _gtk_xembed_send_message (socket->plug_window, - active ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE, - 0, 0, 0); + _gtk_socket_windowing_update_active (socket, active); } } @@ -771,9 +722,7 @@ gtk_socket_grab_notify (GtkWidget *widget, GtkSocket *socket = GTK_SOCKET (widget); if (!socket->same_app) - _gtk_xembed_send_message (GTK_SOCKET (widget)->plug_window, - was_grabbed ? XEMBED_MODALITY_OFF : XEMBED_MODALITY_ON, - 0, 0, 0); + _gtk_socket_windowing_update_modality (socket, !was_grabbed); } static gboolean @@ -784,29 +733,8 @@ gtk_socket_key_event (GtkWidget *widget, if (GTK_WIDGET_HAS_FOCUS (socket) && socket->plug_window && !socket->plug_widget) { - GdkScreen *screen = gdk_drawable_get_screen (socket->plug_window); - XEvent xevent; - - xevent.xkey.type = (event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease; - xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window); - xevent.xkey.root = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)); - xevent.xkey.time = event->time; - /* FIXME, the following might cause problems for non-GTK apps */ - xevent.xkey.x = 0; - xevent.xkey.y = 0; - xevent.xkey.x_root = 0; - xevent.xkey.y_root = 0; - xevent.xkey.state = event->state; - xevent.xkey.keycode = event->hardware_keycode; - xevent.xkey.same_screen = TRUE; /* FIXME ? */ - - gdk_error_trap_push (); - XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window), - GDK_WINDOW_XWINDOW (socket->plug_window), - False, NoEventMask, &xevent); - gdk_display_sync (gtk_widget_get_display (widget)); - gdk_error_trap_pop (); - + _gtk_socket_windowing_send_key_event (socket, (GdkEvent *) event, FALSE); + return TRUE; } else @@ -819,13 +747,20 @@ gtk_socket_notify (GObject *object, { if (!strcmp (pspec->name, "is-focus")) return; - socket_update_focus_in (GTK_SOCKET (object)); } -static void -gtk_socket_claim_focus (GtkSocket *socket, - gboolean send_event) +/** + * _gtk_socket_claim_focus: + * + * @socket: a #GtkSocket + * @send_event: huh? + * + * Claims focus for the socket. XXX send_event? + */ +void +_gtk_socket_claim_focus (GtkSocket *socket, + gboolean send_event) { if (!send_event) socket->focus_in = TRUE; /* Otherwise, our notify handler will send FOCUS_IN */ @@ -838,10 +773,10 @@ gtk_socket_claim_focus (GtkSocket *socket, } static gboolean -gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction) +gtk_socket_focus (GtkWidget *widget, + GtkDirectionType direction) { GtkSocket *socket; - gint detail = -1; g_return_val_if_fail (GTK_IS_SOCKET (widget), FALSE); @@ -852,24 +787,8 @@ gtk_socket_focus (GtkWidget *widget, GtkDirectionType direction) if (!gtk_widget_is_focus (widget)) { - switch (direction) - { - case GTK_DIR_UP: - case GTK_DIR_LEFT: - case GTK_DIR_TAB_BACKWARD: - detail = XEMBED_FOCUS_LAST; - break; - case GTK_DIR_DOWN: - case GTK_DIR_RIGHT: - case GTK_DIR_TAB_FORWARD: - detail = XEMBED_FOCUS_FIRST; - break; - } - - _gtk_xembed_send_focus_message (socket->plug_window, - XEMBED_FOCUS_IN, detail); - - gtk_socket_claim_focus (socket, FALSE); + _gtk_socket_windowing_focus (socket, direction); + _gtk_socket_claim_focus (socket, FALSE); return TRUE; } @@ -900,48 +819,20 @@ gtk_socket_forall (GtkContainer *container, (* callback) (socket->plug_widget, callback_data); } -static void -gtk_socket_send_configure_event (GtkSocket *socket) -{ - XEvent event; - gint x, y; - - g_return_if_fail (socket->plug_window != NULL); - - event.xconfigure.type = ConfigureNotify; - - event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window); - event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window); - - /* The ICCCM says that synthetic events should have root relative - * coordinates. We still aren't really ICCCM compliant, since - * we don't send events when the real toplevel is moved. - */ - gdk_error_trap_push (); - gdk_window_get_origin (socket->plug_window, &x, &y); - gdk_error_trap_pop (); - - event.xconfigure.x = x; - event.xconfigure.y = y; - event.xconfigure.width = GTK_WIDGET(socket)->allocation.width; - event.xconfigure.height = GTK_WIDGET(socket)->allocation.height; - - event.xconfigure.border_width = 0; - event.xconfigure.above = None; - event.xconfigure.override_redirect = False; - - gdk_error_trap_push (); - XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window), - GDK_WINDOW_XWINDOW (socket->plug_window), - False, NoEventMask, &event); - gdk_display_sync (gtk_widget_get_display (GTK_WIDGET (socket))); - gdk_error_trap_pop (); -} - -static void -gtk_socket_add_window (GtkSocket *socket, - GdkNativeWindow xid, - gboolean need_reparent) +/** + * _gtk_socket_add_window: + * + * @socket: a #GtkSocket + * @xid: the native identifier for a window + * @need_reparent: whether the socket's plug's window needs to be + * reparented to the socket + * + * Adds a window to a GtkSocket. + */ +void +_gtk_socket_add_window (GtkSocket *socket, + GdkNativeWindow xid, + gboolean need_reparent) { GtkWidget *widget = GTK_WIDGET (socket); GdkDisplay *display = gtk_widget_get_display (widget); @@ -961,7 +852,7 @@ gtk_socket_add_window (GtkSocket *socket, if (!GTK_IS_PLUG (child_widget)) { - g_warning (G_STRLOC "Can't add non-GtkPlug to GtkSocket"); + g_warning (G_STRLOC ": Can't add non-GtkPlug to GtkSocket"); socket->plug_window = NULL; gdk_error_trap_pop (); @@ -974,8 +865,6 @@ gtk_socket_add_window (GtkSocket *socket, { GtkWidget *toplevel; GdkDragProtocol protocol; - unsigned long version; - unsigned long flags; gdk_error_trap_push (); @@ -989,10 +878,8 @@ gtk_socket_add_window (GtkSocket *socket, } } - XSelectInput (GDK_DISPLAY_XDISPLAY (display), - GDK_WINDOW_XWINDOW (socket->plug_window), - StructureNotifyMask | PropertyChangeMask); - + _gtk_socket_windowing_select_plug_window_input (socket); + if (gdk_error_trap_pop ()) { g_object_unref (socket->plug_window); @@ -1012,19 +899,8 @@ gtk_socket_add_window (GtkSocket *socket, socket->have_size = FALSE; - socket->xembed_version = -1; - if (xembed_get_info (socket->plug_window, &version, &flags)) - { - socket->xembed_version = MIN (GTK_XEMBED_PROTOCOL_VERSION, version); - socket->is_mapped = (flags & XEMBED_MAPPED) != 0; - } - else - { - /* FIXME, we should probably actually check the state before we started */ - - socket->is_mapped = TRUE; - } - + _gtk_socket_windowing_embed_get_info (socket); + socket->need_map = socket->is_mapped; if (gdk_drag_get_protocol_for_display (display, xid, &protocol)) @@ -1034,8 +910,9 @@ gtk_socket_add_window (GtkSocket *socket, gdk_display_sync (display); gdk_error_trap_pop (); - gdk_window_add_filter (socket->plug_window, - gtk_socket_filter_func, socket); + gdk_window_add_filter (socket->plug_window, + _gtk_socket_windowing_filter_func, + socket); /* Add a pointer to the socket on our toplevel window */ @@ -1043,10 +920,8 @@ gtk_socket_add_window (GtkSocket *socket, if (toplevel && GTK_IS_WINDOW (toplevel)) gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid); - _gtk_xembed_send_message (socket->plug_window, - XEMBED_EMBEDDED_NOTIFY, 0, - GDK_WINDOW_XWINDOW (widget->window), - socket->xembed_version); + _gtk_socket_windowing_embed_notify (socket); + socket_update_active (socket); socket_update_focus_in (socket); @@ -1057,61 +932,54 @@ gtk_socket_add_window (GtkSocket *socket, g_signal_emit (socket, socket_signals[PLUG_ADDED], 0); } -static gboolean -xembed_get_info (GdkWindow *window, - unsigned long *version, - unsigned long *flags) +/** + * _gtk_socket_handle_map_request: + * + * @socket: a #GtkSocket + * + * Called from the GtkSocket backend when the plug has been mapped. + */ +void +_gtk_socket_handle_map_request (GtkSocket *socket) { - GdkDisplay *display = gdk_drawable_get_display (window); - Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO"); - Atom type; - int format; - unsigned long nitems, bytes_after; - unsigned char *data; - unsigned long *data_long; - int status; - - gdk_error_trap_push(); - status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), - GDK_WINDOW_XWINDOW (window), - xembed_info_atom, - 0, 2, False, - xembed_info_atom, &type, &format, - &nitems, &bytes_after, &data); - gdk_error_trap_pop(); - - if (status != Success) - return FALSE; /* Window vanished? */ - - if (type == None) /* No info property */ - return FALSE; - - if (type != xembed_info_atom) + if (!socket->is_mapped) { - g_warning ("_XEMBED_INFO property has wrong type\n"); - return FALSE; + socket->is_mapped = TRUE; + socket->need_map = TRUE; + + gtk_widget_queue_resize (GTK_WIDGET (socket)); } - - if (nitems < 2) - { - g_warning ("_XEMBED_INFO too short\n"); - XFree (data); - return FALSE; - } - - data_long = (unsigned long *)data; - if (version) - *version = data_long[0]; - if (flags) - *flags = data_long[1] & XEMBED_MAPPED; - - XFree (data); - return TRUE; } -static void -advance_toplevel_focus (GtkSocket *socket, - GtkDirectionType direction) +/** + * _gtk_socket_unmap_notify: + * + * @socket: a #GtkSocket + * + * Called from the GtkSocket backend when the plug has been unmapped ??? + */ +void +_gtk_socket_unmap_notify (GtkSocket *socket) +{ + if (socket->is_mapped) + { + socket->is_mapped = FALSE; + gtk_widget_queue_resize (GTK_WIDGET (socket)); + } +} + +/** + * _gtk_socket_advance_toplevel_focus: + * + * @socket: a #GtkSocket + * @direction: a direction + * + * Called from the GtkSocket backend when the corresponding plug + * has told the socket to move the focus. + */ +void +_gtk_socket_advance_toplevel_focus (GtkSocket *socket, + GtkDirectionType direction) { GtkBin *bin; GtkWindow *window; @@ -1147,10 +1015,10 @@ advance_toplevel_focus (GtkSocket *socket, /* We are allowed exactly one wrap-around per sequence of focus * events */ - if (_gtk_xembed_get_focus_wrapped ()) + if (_gtk_socket_windowing_embed_get_focus_wrapped ()) return; else - _gtk_xembed_set_focus_wrapped (); + _gtk_socket_windowing_embed_set_focus_wrapped (); } if (window->focus_widget) @@ -1174,311 +1042,5 @@ advance_toplevel_focus (GtkSocket *socket, } } -static void -handle_xembed_message (GtkSocket *socket, - XEmbedMessageType message, - glong detail, - glong data1, - glong data2, - guint32 time) -{ - GTK_NOTE (PLUGSOCKET, - g_message ("GtkSocket: Message of type %d received", message)); - - switch (message) - { - case XEMBED_EMBEDDED_NOTIFY: - case XEMBED_WINDOW_ACTIVATE: - case XEMBED_WINDOW_DEACTIVATE: - case XEMBED_MODALITY_ON: - case XEMBED_MODALITY_OFF: - case XEMBED_FOCUS_IN: - case XEMBED_FOCUS_OUT: - g_warning ("GtkSocket: Invalid _XEMBED message of type %d received", message); - break; - - case XEMBED_REQUEST_FOCUS: - gtk_socket_claim_focus (socket, TRUE); - break; - - case XEMBED_FOCUS_NEXT: - case XEMBED_FOCUS_PREV: - advance_toplevel_focus (socket, - (message == XEMBED_FOCUS_NEXT ? - GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD)); - break; - - case XEMBED_GTK_GRAB_KEY: - add_grabbed_key (socket, data1, data2); - break; - case XEMBED_GTK_UNGRAB_KEY: - remove_grabbed_key (socket, data1, data2); - break; - - case XEMBED_GRAB_KEY: - case XEMBED_UNGRAB_KEY: - break; - - default: - GTK_NOTE (PLUGSOCKET, - g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %d", message)); - break; - } -} - -static void -map_request (GtkSocket *socket) -{ - if (!socket->is_mapped) - { - socket->is_mapped = TRUE; - socket->need_map = TRUE; - - gtk_widget_queue_resize (GTK_WIDGET (socket)); - } -} - -static void -unmap_notify (GtkSocket *socket) -{ - if (socket->is_mapped) - { - socket->is_mapped = FALSE; - gtk_widget_queue_resize (GTK_WIDGET (socket)); - } -} - -static GdkFilterReturn -gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) -{ - GtkSocket *socket; - GtkWidget *widget; - GdkDisplay *display; - XEvent *xevent; - - GdkFilterReturn return_val; - - socket = GTK_SOCKET (data); - widget = GTK_WIDGET (socket); - xevent = (XEvent *)gdk_xevent; - display = gtk_widget_get_display (widget); - - return_val = GDK_FILTER_CONTINUE; - - if (socket->plug_widget) - return return_val; - - switch (xevent->type) - { - case ClientMessage: - if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED")) - { - _gtk_xembed_push_message (xevent); - handle_xembed_message (socket, - xevent->xclient.data.l[1], - xevent->xclient.data.l[2], - xevent->xclient.data.l[3], - xevent->xclient.data.l[4], - xevent->xclient.data.l[0]); - _gtk_xembed_pop_message (); - - return_val = GDK_FILTER_REMOVE; - } - break; - - case CreateNotify: - { - XCreateWindowEvent *xcwe = &xevent->xcreatewindow; - - if (!socket->plug_window) - { - gtk_socket_add_window (socket, xcwe->window, FALSE); - - if (socket->plug_window) - { - GTK_NOTE(PLUGSOCKET, - g_message ("GtkSocket - window created")); - } - } - - return_val = GDK_FILTER_REMOVE; - - break; - } - - case ConfigureRequest: - { - XConfigureRequestEvent *xcre = &xevent->xconfigurerequest; - - if (!socket->plug_window) - gtk_socket_add_window (socket, xcre->window, FALSE); - - if (socket->plug_window) - { - GtkSocketPrivate *private = gtk_socket_get_private (socket); - - if (xcre->value_mask & (CWWidth | CWHeight)) - { - GTK_NOTE(PLUGSOCKET, - g_message ("GtkSocket - configure request: %d %d", - socket->request_width, - socket->request_height)); - - private->resize_count++; - gtk_widget_queue_resize (widget); - } - else if (xcre->value_mask & (CWX | CWY)) - { - gtk_socket_send_configure_event (socket); - } - /* Ignore stacking requests. */ - - return_val = GDK_FILTER_REMOVE; - } - break; - } - - case DestroyNotify: - { - XDestroyWindowEvent *xdwe = &xevent->xdestroywindow; - - /* Note that we get destroy notifies both from SubstructureNotify on - * our window and StructureNotify on socket->plug_window - */ - if (socket->plug_window && (xdwe->window == GDK_WINDOW_XWINDOW (socket->plug_window))) - { - gboolean result; - - GTK_NOTE(PLUGSOCKET, - g_message ("GtkSocket - destroy notify")); - - gdk_window_destroy_notify (socket->plug_window); - gtk_socket_end_embedding (socket); - - g_object_ref (widget); - g_signal_emit (widget, socket_signals[PLUG_REMOVED], 0, &result); - if (!result) - gtk_widget_destroy (widget); - g_object_unref (widget); - - return_val = GDK_FILTER_REMOVE; - } - break; - } - - case FocusIn: - if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS) - { - gtk_socket_claim_focus (socket, TRUE); - } - return_val = GDK_FILTER_REMOVE; - break; - case FocusOut: - return_val = GDK_FILTER_REMOVE; - break; - case MapRequest: - if (!socket->plug_window) - gtk_socket_add_window (socket, xevent->xmaprequest.window, FALSE); - - if (socket->plug_window) - { - GTK_NOTE(PLUGSOCKET, - g_message ("GtkSocket - Map Request")); - - map_request (socket); - return_val = GDK_FILTER_REMOVE; - } - break; - case PropertyNotify: - if (socket->plug_window && - xevent->xproperty.window == GDK_WINDOW_XWINDOW (socket->plug_window)) - { - GdkDragProtocol protocol; - - if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "WM_NORMAL_HINTS")) - { - socket->have_size = FALSE; - gtk_widget_queue_resize (widget); - return_val = GDK_FILTER_REMOVE; - } - else if ((xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "XdndAware")) || - (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_MOTIF_DRAG_RECEIVER_INFO"))) - { - gdk_error_trap_push (); - if (gdk_drag_get_protocol_for_display (display, - xevent->xproperty.window, - &protocol)) - gtk_drag_dest_set_proxy (GTK_WIDGET (socket), - socket->plug_window, - protocol, TRUE); - - gdk_display_sync (display); - gdk_error_trap_pop (); - return_val = GDK_FILTER_REMOVE; - } - else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO")) - { - unsigned long flags; - - if (xembed_get_info (socket->plug_window, NULL, &flags)) - { - gboolean was_mapped = socket->is_mapped; - gboolean is_mapped = (flags & XEMBED_MAPPED) != 0; - - if (was_mapped != is_mapped) - { - if (is_mapped) - map_request (socket); - else - { - gdk_error_trap_push (); - gdk_window_show (socket->plug_window); - gdk_flush (); - gdk_error_trap_pop (); - - unmap_notify (socket); - } - } - } - return_val = GDK_FILTER_REMOVE; - } - } - break; - case ReparentNotify: - { - XReparentEvent *xre = &xevent->xreparent; - - if (!socket->plug_window && xre->parent == GDK_WINDOW_XWINDOW (widget->window)) - { - gtk_socket_add_window (socket, xre->window, FALSE); - - if (socket->plug_window) - { - GTK_NOTE(PLUGSOCKET, - g_message ("GtkSocket - window reparented")); - } - - return_val = GDK_FILTER_REMOVE; - } - - break; - } - case UnmapNotify: - if (socket->plug_window && - xevent->xunmap.window == GDK_WINDOW_XWINDOW (socket->plug_window)) - { - GTK_NOTE(PLUGSOCKET, - g_message ("GtkSocket - Unmap notify")); - - unmap_notify (socket); - return_val = GDK_FILTER_REMOVE; - } - break; - - } - - return return_val; -} - #define __GTK_SOCKET_C__ #include "gtkaliasdef.c" diff --git a/gtk/gtksocketprivate.h b/gtk/gtksocketprivate.h new file mode 100644 index 0000000000..85852fb8d3 --- /dev/null +++ b/gtk/gtksocketprivate.h @@ -0,0 +1,171 @@ +/* GTK - The GIMP Toolkit + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS + * file for a list of people on the GTK+ Team. See the ChangeLog + * files for a list of changes. These files are distributed with + * GTK+ at ftp://ftp.gtk.org/pub/gtk/. + */ + +#ifndef __GTK_SOCKET_PRIVATE_H__ +#define __GTK_SOCKET_PRIVATE_H__ + +typedef struct _GtkSocketPrivate GtkSocketPrivate; + +struct _GtkSocketPrivate +{ + gint resize_count; +}; + +/* In gtksocket.c: */ +GtkSocketPrivate *_gtk_socket_get_private (GtkSocket *socket); + +void _gtk_socket_add_grabbed_key (GtkSocket *socket, + guint keyval, + GdkModifierType modifiers); +void _gtk_socket_remove_grabbed_key (GtkSocket *socket, + guint keyval, + GdkModifierType modifiers); +void _gtk_socket_claim_focus (GtkSocket *socket, + gboolean send_event); +void _gtk_socket_add_window (GtkSocket *socket, + GdkNativeWindow xid, + gboolean need_reparent); +void _gtk_socket_end_embedding (GtkSocket *socket); + +void _gtk_socket_handle_map_request (GtkSocket *socket); +void _gtk_socket_unmap_notify (GtkSocket *socket); +void _gtk_socket_advance_toplevel_focus (GtkSocket *socket, + GtkDirectionType direction); + +/* In backend-specific file: */ + +/** + * _gtk_socket_windowing_get_id: + * + * @socket: a #GtkSocket + * + * Returns the native windowing system identifier for the plug's window. + */ +GdkNativeWindow _gtk_socket_windowing_get_id (GtkSocket *socket); + +/** + * _gtk_socket_windowing_realize_window: + * + */ +void _gtk_socket_windowing_realize_window (GtkSocket *socket); + +/** + * _gtk_socket_windowing_end_embedding_toplevel: + * + */ +void _gtk_socket_windowing_end_embedding_toplevel (GtkSocket *socket); + +/** + * _gtk_socket_windowing_size_request: + * + */ +void _gtk_socket_windowing_size_request (GtkSocket *socket); + +/** + * _gtk_socket_windowing_send_key_event: + * + */ +void _gtk_socket_windowing_send_key_event (GtkSocket *socket, + GdkEvent *gdk_event, + gboolean mask_key_presses); + +/** + * _gtk_socket_windowing_focus_change: + * + */ +void _gtk_socket_windowing_focus_change (GtkSocket *socket, + gboolean focus_in); + +/** + * _gtk_socket_windowing_update_active: + * + */ +void _gtk_socket_windowing_update_active (GtkSocket *socket, + gboolean active); + +/** + * _gtk_socket_windowing_update_modality: + * + */ +void _gtk_socket_windowing_update_modality (GtkSocket *socket, + gboolean modality); + +/** + * _gtk_socket_windowing_focus: + * + */ +void _gtk_socket_windowing_focus (GtkSocket *socket, + GtkDirectionType direction); + +/** + * _gtk_socket_windowing_send_configure_event: + * + */ +void _gtk_socket_windowing_send_configure_event (GtkSocket *socket); + +/** + * _gtk_socket_windowing_select_plug_window_input: + * + * Asks the windowing system to send necessary events related to the + * plug window to the socket window. Called only for out-of-process + * embedding. + */ +void _gtk_socket_windowing_select_plug_window_input (GtkSocket *socket); + +/** + * _gtk_socket_windowing_embed_get_info: + * + * Gets whatever information necessary about an out-of-process plug + * window. + */ +void _gtk_socket_windowing_embed_get_info (GtkSocket *socket); + +/** + * _gtk_socket_windowing_embed_notify: + * + */ +void _gtk_socket_windowing_embed_notify (GtkSocket *socket); + +/** + * _gtk_socket_windowing_embed_get_focus_wrapped: + * + */ +gboolean _gtk_socket_windowing_embed_get_focus_wrapped (void); + +/** + * _gtk_socket_windowing_embed_set_focus_wrapped: + * + */ +void _gtk_socket_windowing_embed_set_focus_wrapped (void); + +/** + * _gtk_socket_windowing_filter_func: + * + */ +GdkFilterReturn _gtk_socket_windowing_filter_func (GdkXEvent *gdk_xevent, + GdkEvent *event, + gpointer data); + +#endif /* __GTK_SOCKET_PRIVATE_H__ */