* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#include <config.h>
+#include <string.h>
+
#include "gdk/gdkkeysyms.h"
+#include "gtkalias.h"
#include "gtkmain.h"
#include "gtkmarshalers.h"
#include "gtkwindow.h"
#include "gtkplug.h"
#include "gtkprivate.h"
-#include "gtksignal.h"
#include "gtksocket.h"
#include "gtkdnd.h"
#include "x11/gdkx.h"
-#include "xembed.h"
+#include "gtkxembed.h"
+
+typedef struct _GtkSocketPrivate GtkSocketPrivate;
+
+struct _GtkSocketPrivate
+{
+ gint resize_count;
+};
/* Forward declararations */
static void gtk_socket_class_init (GtkSocketClass *klass);
static void gtk_socket_init (GtkSocket *socket);
static void gtk_socket_finalize (GObject *object);
+static void gtk_socket_notify (GObject *object,
+ GParamSpec *pspec);
static void gtk_socket_realize (GtkWidget *widget);
static void gtk_socket_unrealize (GtkWidget *widget);
static void gtk_socket_size_request (GtkWidget *widget,
GtkWidget *old_toplevel);
static void gtk_socket_grab_notify (GtkWidget *widget,
gboolean was_grabbed);
-static gboolean gtk_socket_key_press_event (GtkWidget *widget,
+static gboolean gtk_socket_key_event (GtkWidget *widget,
GdkEventKey *event);
-static gboolean gtk_socket_focus_in_event (GtkWidget *widget,
- GdkEventFocus *event);
-static void gtk_socket_claim_focus (GtkSocket *socket);
-static gboolean gtk_socket_focus_out_event (GtkWidget *widget,
- GdkEventFocus *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);
GdkEvent *event,
gpointer data);
-static void send_xembed_message (GtkSocket *socket,
- glong message,
- glong detail,
- glong data1,
- glong data2,
- guint32 time);
static gboolean xembed_get_info (GdkWindow *gdk_window,
unsigned long *version,
unsigned long *flags);
static GtkWidgetClass *parent_class = NULL;
-GtkType
+static GtkSocketPrivate *
+gtk_socket_get_private (GtkSocket *socket)
+{
+ GtkSocketPrivate *private;
+ static GQuark private_quark = 0;
+
+ if (!private_quark)
+ private_quark = g_quark_from_static_string ("gtk-socket-private");
+
+ private = g_object_get_qdata (G_OBJECT (socket), private_quark);
+
+ if (!private)
+ {
+ private = g_new0 (GtkSocketPrivate, 1);
+ private->resize_count = 0;
+
+ g_object_set_qdata_full (G_OBJECT (socket), private_quark,
+ private, (GDestroyNotify) g_free);
+ }
+
+ return private;
+}
+
+GType
gtk_socket_get_type (void)
{
- static GtkType socket_type = 0;
+ static GType socket_type = 0;
if (!socket_type)
{
(GInstanceInitFunc) gtk_socket_init,
};
- socket_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkSocket", &socket_info, 0);
+ socket_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkSocket",
+ &socket_info, 0);
}
return socket_type;
widget_class = (GtkWidgetClass*) class;
container_class = (GtkContainerClass*) class;
- parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
+ parent_class = g_type_class_peek_parent (class);
gobject_class->finalize = gtk_socket_finalize;
+ gobject_class->notify = gtk_socket_notify;
widget_class->realize = gtk_socket_realize;
widget_class->unrealize = gtk_socket_unrealize;
widget_class->size_allocate = gtk_socket_size_allocate;
widget_class->hierarchy_changed = gtk_socket_hierarchy_changed;
widget_class->grab_notify = gtk_socket_grab_notify;
- widget_class->key_press_event = gtk_socket_key_press_event;
- widget_class->focus_in_event = gtk_socket_focus_in_event;
- widget_class->focus_out_event = gtk_socket_focus_out_event;
+ widget_class->key_press_event = gtk_socket_key_event;
+ widget_class->key_release_event = gtk_socket_key_event;
widget_class->focus = gtk_socket_focus;
+
+ /* We don't want to show_all/hide_all the in-process
+ * plug, if any.
+ */
+ widget_class->show_all = gtk_widget_show;
+ widget_class->hide_all = gtk_widget_hide;
container_class->remove = gtk_socket_remove;
container_class->forall = gtk_socket_forall;
G_STRUCT_OFFSET (GtkSocketClass, plug_added),
NULL, NULL,
_gtk_marshal_VOID__VOID,
- GTK_TYPE_NONE, 0);
+ G_TYPE_NONE, 0);
socket_signals[PLUG_REMOVED] =
g_signal_new ("plug_removed",
G_OBJECT_CLASS_TYPE (class),
socket->focus_in = FALSE;
socket->have_size = FALSE;
socket->need_map = FALSE;
+ socket->active = FALSE;
socket->accel_group = gtk_accel_group_new ();
g_object_set_data (G_OBJECT (socket->accel_group), "gtk-socket", socket);
/**
* gtk_socket_steal:
- * @socket: a #GtkSocket
+ * @socket_: a #GtkSocket
* @wid: the window ID of an existing toplevel window.
*
* Reparents a pre-existing toplevel window into a #GtkSocket. This is
/**
* gtk_socket_add_id:
- * @socket: a #GtkSocket
+ * @socket_: a #GtkSocket
* @window_id: the window ID of a client participating in the XEMBED protocol.
*
* Adds an XEMBED client, such as a #GtkPlug, to the #GtkSocket. The
/**
* gtk_socket_get_id:
- * @socket: a #GtkSocket.
+ * @socket_: a #GtkSocket.
*
* Gets the window ID of a #GtkSocket widget, which can then
* be used to create a client embedded inside the socket, for
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
- XGetWindowAttributes (GDK_DISPLAY (),
+ XGetWindowAttributes (GDK_WINDOW_XDISPLAY (widget->window),
GDK_WINDOW_XWINDOW (widget->window),
&xattrs);
- XSelectInput (GDK_DISPLAY (),
- GDK_WINDOW_XWINDOW(widget->window),
+ XSelectInput (GDK_WINDOW_XDISPLAY (widget->window),
+ GDK_WINDOW_XWINDOW (widget->window),
xattrs.your_event_mask |
SubstructureNotifyMask | SubstructureRedirectMask);
* our window is passed to another application, SubstructureRedirectMask
* will be set by the time the other app creates its window.
*/
- gdk_flush();
+ gdk_display_sync (gtk_widget_get_display (widget));
}
static void
gtk_socket_end_embedding (GtkSocket *socket)
{
+ GtkSocketPrivate *private = gtk_socket_get_private (socket);
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
gint i;
g_object_unref (socket->plug_window);
socket->plug_window = NULL;
+ socket->current_width = 0;
+ socket->current_height = 0;
+ private->resize_count = 0;
- /* Remove from end to avoid indexes shiting. This is evil */
- for (i = socket->accel_group->n_accels; i >= 0; i--)
+ /* Remove from end to avoid indexes shifting. This is evil */
+ for (i = socket->accel_group->n_accels - 1; i >= 0; i--)
{
GtkAccelGroupEntry *accel_entry = &socket->accel_group->priv_accels[i];
gtk_accel_group_disconnect (socket->accel_group, accel_entry->closure);
long supplied;
gdk_error_trap_push ();
+
+ socket->request_width = 1;
+ socket->request_height = 1;
- if (XGetWMNormalHints (GDK_DISPLAY(),
+ if (XGetWMNormalHints (GDK_WINDOW_XDISPLAY (socket->plug_window),
GDK_WINDOW_XWINDOW (socket->plug_window),
&hints, &supplied))
{
- /* This is obsolete, according the X docs, but many programs
- * still use it */
- if (hints.flags & (PSize | USSize))
- {
- socket->request_width = hints.width;
- socket->request_height = hints.height;
- }
- else if (hints.flags & PMinSize)
+ if (hints.flags & PMinSize)
{
socket->request_width = hints.min_width;
socket->request_height = hints.min_height;
socket->request_height = hints.base_height;
}
}
- socket->have_size = TRUE; /* don't check again? */
+ socket->have_size = TRUE;
gdk_error_trap_pop ();
}
}
else if (socket->plug_window)
{
+ GtkSocketPrivate *private = gtk_socket_get_private (socket);
+
gdk_error_trap_push ();
- if (!socket->need_map &&
- (allocation->width == socket->current_width) &&
- (allocation->height == socket->current_height))
- {
- gtk_socket_send_configure_event (socket);
- GTK_NOTE(PLUGSOCKET,
- g_message ("GtkSocket - allocated no change: %d %d",
- allocation->width, allocation->height));
- }
- else
+ if (allocation->width != socket->current_width ||
+ allocation->height != socket->current_height)
{
gdk_window_move_resize (socket->plug_window,
0, 0,
allocation->width, allocation->height);
+ if (private->resize_count)
+ private->resize_count--;
+
GTK_NOTE(PLUGSOCKET,
g_message ("GtkSocket - allocated: %d %d",
allocation->width, allocation->height));
socket->need_map = FALSE;
}
- gdk_flush ();
+ while (private->resize_count)
+ {
+ gtk_socket_send_configure_event (socket);
+ private->resize_count--;
+ GTK_NOTE(PLUGSOCKET,
+ g_message ("GtkSocket - sending synthetic configure: %d %d",
+ allocation->width, allocation->height));
+ }
+
+ gdk_display_sync (gtk_widget_get_display (widget));
gdk_error_trap_pop ();
}
}
GdkModifierType accel_mods;
} GrabbedKey;
-static void
-activate_key (GtkAccelGroup *accel_group,
- GrabbedKey *grabbed_key)
+static gboolean
+activate_key (GtkAccelGroup *accel_group,
+ GObject *acceleratable,
+ guint accel_key,
+ 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_ROOT_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.same_screen = True;
gdk_error_trap_push ();
- XSendEvent (GDK_DISPLAY (),
+ XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
GDK_WINDOW_XWINDOW (socket->plug_window),
False, KeyPressMask, &xevent);
- gdk_flush ();
+ gdk_display_sync (gdk_screen_get_display (screen));
gdk_error_trap_pop ();
+
+ retval = TRUE;
}
if (gdk_event)
gdk_event_free (gdk_event);
+
+ return retval;
}
static gboolean
accel_entry->closure);
return;
}
-
}
g_warning ("GtkSocket: request to remove non-present grabbed key %u,%#x\n",
keyval, modifiers);
}
-static gboolean
-toplevel_focus_in_handler (GtkWidget *toplevel,
- GdkEventFocus *event,
- GtkSocket *socket)
+static void
+socket_update_focus_in (GtkSocket *socket)
{
- /* It appears spurious focus in events can occur when
- * the window is hidden. So we'll just check to see if
- * the window is visible before actually handling the
- * event. (Comment from gtkwindow.c)
- */
- if (GTK_WIDGET_VISIBLE (toplevel))
- send_xembed_message (socket, XEMBED_WINDOW_ACTIVATE, 0, 0, 0,
- gtk_get_current_event_time ()); /* Will be GDK_CURRENT_TIME */
+ gboolean focus_in = FALSE;
- return FALSE;
+ 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)))
+ focus_in = TRUE;
+ }
+
+ if (focus_in != socket->focus_in)
+ {
+ 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);
+ }
}
-static gboolean
-toplevel_focus_out_handler (GtkWidget *toplevel,
- GdkEventFocus *event,
- GtkSocket *socket)
+static void
+socket_update_active (GtkSocket *socket)
{
- send_xembed_message (socket, XEMBED_WINDOW_DEACTIVATE, 0, 0, 0,
- gtk_get_current_event_time ()); /* Will be GDK_CURRENT_TIME */
+ gboolean active = FALSE;
+
+ 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;
+ }
- return FALSE;
+ if (active != socket->active)
+ {
+ socket->active = active;
+
+ _gtk_xembed_send_message (socket->plug_window,
+ active ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE,
+ 0, 0, 0);
+ }
}
static void
if (socket->toplevel)
{
gtk_window_remove_accel_group (GTK_WINDOW (socket->toplevel), socket->accel_group);
- gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket);
- gtk_signal_disconnect_by_func (GTK_OBJECT (socket->toplevel), GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket);
+ g_signal_handlers_disconnect_by_func (socket->toplevel,
+ socket_update_focus_in,
+ socket);
+ g_signal_handlers_disconnect_by_func (socket->toplevel,
+ socket_update_active,
+ socket);
}
socket->toplevel = toplevel;
if (toplevel)
{
gtk_window_add_accel_group (GTK_WINDOW (socket->toplevel), socket->accel_group);
- gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_in_event",
- GTK_SIGNAL_FUNC (toplevel_focus_in_handler), socket);
- gtk_signal_connect (GTK_OBJECT (socket->toplevel), "focus_out_event",
- GTK_SIGNAL_FUNC (toplevel_focus_out_handler), socket);
+ g_signal_connect_swapped (socket->toplevel, "notify::has-toplevel-focus",
+ G_CALLBACK (socket_update_focus_in), socket);
+ g_signal_connect_swapped (socket->toplevel, "notify::is-active",
+ G_CALLBACK (socket_update_active), socket);
}
+
+ socket_update_focus_in (socket);
+ socket_update_active (socket);
}
}
GtkSocket *socket = GTK_SOCKET (widget);
if (!socket->same_app)
- send_xembed_message (GTK_SOCKET (widget),
- was_grabbed ? XEMBED_MODALITY_OFF : XEMBED_MODALITY_ON,
- 0, 0, 0, gtk_get_current_event_time ());
+ _gtk_xembed_send_message (GTK_SOCKET (widget)->plug_window,
+ was_grabbed ? XEMBED_MODALITY_OFF : XEMBED_MODALITY_ON,
+ 0, 0, 0);
}
static gboolean
-gtk_socket_key_press_event (GtkWidget *widget,
- GdkEventKey *event)
+gtk_socket_key_event (GtkWidget *widget,
+ GdkEventKey *event)
{
GtkSocket *socket = GTK_SOCKET (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 = KeyPress;
- xevent.xkey.display = GDK_WINDOW_XDISPLAY (event->window);
+ xevent.xkey.type = (event->type == GDK_KEY_PRESS) ? KeyPress : KeyRelease;
xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
- xevent.xkey.root = GDK_ROOT_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.same_screen = TRUE; /* FIXME ? */
gdk_error_trap_push ();
- XSendEvent (GDK_DISPLAY (),
+ XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
GDK_WINDOW_XWINDOW (socket->plug_window),
False, NoEventMask, &xevent);
- gdk_flush ();
+ gdk_display_sync (gtk_widget_get_display (widget));
gdk_error_trap_pop ();
return TRUE;
return FALSE;
}
-static gboolean
-gtk_socket_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
+static void
+gtk_socket_notify (GObject *object,
+ GParamSpec *pspec)
{
- GtkSocket *socket = GTK_SOCKET (widget);
+ if (!strcmp (pspec->name, "is_focus"))
+ return;
- if (socket->plug_window)
- send_xembed_message (socket, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0,
- gtk_get_current_event_time ());
-
- return TRUE;
-}
-
-static gboolean
-gtk_socket_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
-{
- GtkSocket *socket = GTK_SOCKET (widget);
-
-#if 0
- GtkWidget *toplevel;
- toplevel = gtk_widget_get_toplevel (widget);
-
- if (toplevel && GTK_IS_WINDOW (toplevel))
- {
- XSetInputFocus (GDK_DISPLAY (),
- GDK_WINDOW_XWINDOW (toplevel->window),
- RevertToParent, CurrentTime); /* FIXME? */
- }
-
-#endif
-
- if (socket->plug_window)
- {
- send_xembed_message (socket, XEMBED_FOCUS_OUT, 0, 0, 0,
- gtk_get_current_event_time ());
- }
-
- socket->focus_in = FALSE;
-
- return TRUE;
+ socket_update_focus_in (GTK_SOCKET (object));
}
static void
-gtk_socket_claim_focus (GtkSocket *socket)
+gtk_socket_claim_focus (GtkSocket *socket,
+ gboolean send_event)
{
+ if (!send_event)
+ socket->focus_in = TRUE; /* Otherwise, our notify handler will send FOCUS_IN */
- socket->focus_in = TRUE;
-
/* Oh, the trickery... */
GTK_WIDGET_SET_FLAGS (socket, GTK_CAN_FOCUS);
gtk_widget_grab_focus (GTK_WIDGET (socket));
GTK_WIDGET_UNSET_FLAGS (socket, GTK_CAN_FOCUS);
-
- /* FIXME: we might grab the focus even if we don't have
- * it as an app... (and see _focus_in ()) */
- if (socket->plug_window)
- {
-#if 0
- gdk_error_trap_push ();
- XSetInputFocus (GDK_DISPLAY (),
- GDK_WINDOW_XWINDOW (socket->plug_window),
- RevertToParent, GDK_CURRENT_TIME);
- gdk_flush ();
- gdk_error_trap_pop ();
-#endif
- }
}
static gboolean
if (socket->plug_widget)
return gtk_widget_child_focus (socket->plug_widget, direction);
- if (!GTK_WIDGET_HAS_FOCUS (widget))
+ if (!gtk_widget_is_focus (widget))
{
switch (direction)
{
break;
}
- send_xembed_message (socket, XEMBED_FOCUS_IN, detail, 0, 0,
- gtk_get_current_event_time ());
+ _gtk_xembed_send_focus_message (socket->plug_window,
+ XEMBED_FOCUS_IN, detail);
- GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
- gtk_widget_grab_focus (widget);
+ gtk_socket_claim_focus (socket, FALSE);
return TRUE;
}
else
return FALSE;
-
-#if 0
- if (!socket->focus_in && socket->plug_window)
- {
- XEvent xevent;
-
- gtk_socket_claim_focus (socket);
-
- xevent.xkey.type = KeyPress;
- xevent.xkey.display = GDK_DISPLAY ();
- xevent.xkey.window = GDK_WINDOW_XWINDOW (socket->plug_window);
- xevent.xkey.root = GDK_ROOT_WINDOW (); /* FIXME */
- xevent.xkey.time = GDK_CURRENT_TIME; /* FIXME */
- /* FIXME, the following might cause big 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 = 0;
- xevent.xkey.same_screen = TRUE; /* FIXME ? */
-
- switch (direction)
- {
- case GTK_DIR_UP:
- xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Up);
- break;
- case GTK_DIR_DOWN:
- xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Down);
- break;
- case GTK_DIR_LEFT:
- xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Left);
- break;
- case GTK_DIR_RIGHT:
- xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Right);
- break;
- case GTK_DIR_TAB_FORWARD:
- xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Tab);
- break;
- case GTK_DIR_TAB_BACKWARD:
- xevent.xkey.keycode = XKeysymToKeycode(GDK_DISPLAY(), GDK_Tab);
- xevent.xkey.state = ShiftMask;
- break;
- }
-
-
- gdk_error_trap_push ();
- XSendEvent (GDK_DISPLAY (),
- GDK_WINDOW_XWINDOW (socket->plug_window),
- False, NoEventMask, &xevent);
- gdk_flush();
- gdk_error_trap_pop ();
-
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-#endif
}
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.display = GDK_DISPLAY ();
event.xconfigure.event = GDK_WINDOW_XWINDOW (socket->plug_window);
event.xconfigure.window = GDK_WINDOW_XWINDOW (socket->plug_window);
- event.xconfigure.x = 0;
- event.xconfigure.y = 0;
+ /* 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.override_redirect = False;
gdk_error_trap_push ();
- XSendEvent (GDK_DISPLAY (),
+ XSendEvent (GDK_WINDOW_XDISPLAY (socket->plug_window),
GDK_WINDOW_XWINDOW (socket->plug_window),
False, NoEventMask, &event);
- gdk_flush ();
+ gdk_display_sync (gtk_widget_get_display (GTK_WIDGET (socket)));
gdk_error_trap_pop ();
}
GdkNativeWindow xid,
gboolean need_reparent)
{
-
GtkWidget *widget = GTK_WIDGET (socket);
+ GdkDisplay *display = gtk_widget_get_display (widget);
gpointer user_data = NULL;
- socket->plug_window = gdk_window_lookup (xid);
+ socket->plug_window = gdk_window_lookup_for_display (display, xid);
if (socket->plug_window)
{
if (!socket->plug_window)
{
- socket->plug_window = gdk_window_foreign_new (xid);
+ socket->plug_window = gdk_window_foreign_new_for_display (display, xid);
if (!socket->plug_window) /* was deleted before we could get it */
{
gdk_error_trap_pop ();
}
}
- XSelectInput (GDK_DISPLAY (),
- GDK_WINDOW_XWINDOW(socket->plug_window),
+ XSelectInput (GDK_DISPLAY_XDISPLAY (display),
+ GDK_WINDOW_XWINDOW (socket->plug_window),
StructureNotifyMask | PropertyChangeMask);
if (gdk_error_trap_pop ())
{
- gdk_window_unref (socket->plug_window);
+ g_object_unref (socket->plug_window);
socket->plug_window = NULL;
return;
}
socket->xembed_version = -1;
if (xembed_get_info (socket->plug_window, &version, &flags))
{
- socket->xembed_version = version;
+ 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 = need_reparent ? TRUE : FALSE;
+ socket->is_mapped = TRUE;
}
socket->need_map = socket->is_mapped;
- if (gdk_drag_get_protocol (xid, &protocol))
+ if (gdk_drag_get_protocol_for_display (display, xid, &protocol))
gtk_drag_dest_set_proxy (GTK_WIDGET (socket), socket->plug_window,
protocol, TRUE);
-
- gdk_flush ();
+
+ gdk_display_sync (display);
gdk_error_trap_pop ();
gdk_window_add_filter (socket->plug_window,
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);
+ socket_update_active (socket);
+ socket_update_focus_in (socket);
+
gtk_widget_queue_resize (GTK_WIDGET (socket));
}
if (socket->plug_window)
- g_signal_emit (G_OBJECT (socket), socket_signals[PLUG_ADDED], 0);
-}
-
-
-static void
-send_xembed_message (GtkSocket *socket,
- glong message,
- glong detail,
- glong data1,
- glong data2,
- guint32 time)
-{
- GTK_NOTE(PLUGSOCKET,
- g_message ("GtkSocket: Sending XEMBED message of type %ld", message));
-
- if (socket->plug_window)
- {
- XEvent xevent;
-
- xevent.xclient.window = GDK_WINDOW_XWINDOW (socket->plug_window);
- xevent.xclient.type = ClientMessage;
- xevent.xclient.message_type = gdk_x11_get_xatom_by_name ("_XEMBED");
- xevent.xclient.format = 32;
- xevent.xclient.data.l[0] = time;
- xevent.xclient.data.l[1] = message;
- xevent.xclient.data.l[2] = detail;
- xevent.xclient.data.l[3] = data1;
- xevent.xclient.data.l[4] = data2;
-
- gdk_error_trap_push ();
- XSendEvent (GDK_DISPLAY (),
- GDK_WINDOW_XWINDOW (socket->plug_window),
- False, NoEventMask, &xevent);
- gdk_flush ();
- gdk_error_trap_pop ();
- }
+ g_signal_emit (socket, socket_signals[PLUG_ADDED], 0);
}
static gboolean
-xembed_get_info (GdkWindow *gdk_window,
+xembed_get_info (GdkWindow *window,
unsigned long *version,
unsigned long *flags)
{
- Display *display = GDK_WINDOW_XDISPLAY (gdk_window);
- Window window = GDK_WINDOW_XWINDOW (gdk_window);
- Atom xembed_info_atom = gdk_x11_get_xatom_by_name ("_XEMBED_INFO");
+ 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;
int status;
gdk_error_trap_push();
- status = XGetWindowProperty (display, window,
+ status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
+ GDK_WINDOW_XWINDOW (window),
xembed_info_atom,
0, 2, False,
xembed_info_atom, &type, &format,
}
static void
-handle_xembed_message (GtkSocket *socket,
- glong message,
- glong detail,
- glong data1,
- glong data2,
- guint32 time)
+advance_toplevel_focus (GtkSocket *socket,
+ GtkDirectionType direction)
{
+ GtkBin *bin;
+ GtkWindow *window;
+ GtkContainer *container;
+ GtkWidget *toplevel;
+ GtkWidget *old_focus_child;
+ GtkWidget *parent;
+
+ toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
+ if (!toplevel)
+ return;
+
+ if (!GTK_WIDGET_TOPLEVEL (toplevel) || GTK_IS_PLUG (toplevel))
+ {
+ gtk_widget_child_focus (toplevel,direction);
+ return;
+ }
+
+ container = GTK_CONTAINER (toplevel);
+ window = GTK_WINDOW (toplevel);
+ bin = GTK_BIN (toplevel);
+
+ /* This is a copy of gtk_window_focus(), modified so that we
+ * can detect wrap-around.
+ */
+ old_focus_child = container->focus_child;
+
+ if (old_focus_child)
+ {
+ if (gtk_widget_child_focus (old_focus_child, direction))
+ return;
+
+ /* We are allowed exactly one wrap-around per sequence of focus
+ * events
+ */
+ if (_gtk_xembed_get_focus_wrapped ())
+ return;
+ else
+ _gtk_xembed_set_focus_wrapped ();
+ }
+
+ if (window->focus_widget)
+ {
+ /* Wrapped off the end, clear the focus setting for the toplevel */
+ parent = window->focus_widget->parent;
+ while (parent)
+ {
+ gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL);
+ parent = GTK_WIDGET (parent)->parent;
+ }
+
+ gtk_window_set_focus (GTK_WINDOW (container), NULL);
+ }
+
+ /* Now try to focus the first widget in the window */
+ if (bin->child)
+ {
+ if (gtk_widget_child_focus (bin->child, direction))
+ return;
+ }
+}
+
+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_MODALITY_OFF:
case XEMBED_FOCUS_IN:
case XEMBED_FOCUS_OUT:
- g_warning ("GtkSocket: Invalid _XEMBED message of type %ld received", message);
+ g_warning ("GtkSocket: Invalid _XEMBED message of type %d received", message);
break;
case XEMBED_REQUEST_FOCUS:
- gtk_socket_claim_focus (socket);
+ gtk_socket_claim_focus (socket, TRUE);
break;
case XEMBED_FOCUS_NEXT:
case XEMBED_FOCUS_PREV:
- {
- GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (socket));
- if (toplevel)
- {
- gtk_widget_child_focus (toplevel,
- (message == XEMBED_FOCUS_NEXT ?
- GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD));
- }
- break;
- }
+ 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;
default:
- GTK_NOTE(PLUGSOCKET,
- g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %ld", message));
+ GTK_NOTE (PLUGSOCKET,
+ g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %d", message));
break;
}
}
{
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;
switch (xevent->type)
{
case ClientMessage:
- if (xevent->xclient.message_type == gdk_x11_get_xatom_by_name ("_XEMBED"))
+ 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;
}
if (socket->plug_window)
{
- socket->request_width = xcwe->width;
- socket->request_height = xcwe->height;
- socket->have_size = TRUE;
-
GTK_NOTE(PLUGSOCKET,
- g_message ("GtkSocket - window created with size: %d %d",
- socket->request_width,
- socket->request_height));
+ g_message ("GtkSocket - window created"));
}
}
if (socket->plug_window)
{
+ GtkSocketPrivate *private = gtk_socket_get_private (socket);
+
if (xcre->value_mask & (CWWidth | CWHeight))
{
- socket->request_width = xcre->width;
- socket->request_height = xcre->height;
- socket->have_size = TRUE;
-
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_end_embedding (socket);
g_object_ref (widget);
- g_signal_emit (G_OBJECT (widget), socket_signals[PLUG_REMOVED], 0, &result);
+ g_signal_emit (widget, socket_signals[PLUG_REMOVED], 0, &result);
if (!result)
gtk_widget_destroy (widget);
g_object_unref (widget);
case FocusIn:
if (xevent->xfocus.mode == EMBEDDED_APP_WANTS_FOCUS)
{
- gtk_socket_claim_focus (socket);
- }
- else if (xevent->xfocus.detail == NotifyInferior)
- {
-#if 0
- GtkWidget *toplevel;
- toplevel = gtk_widget_get_toplevel (widget);
-
- if (toplevel && GTK_IS_WINDOW (topelevel))
- {
- XSetInputFocus (GDK_DISPLAY (),
- GDK_WINDOW_XWINDOW (toplevel->window),
- RevertToParent, CurrentTime); /* FIXME? */
- }
-#endif
+ gtk_socket_claim_focus (socket, TRUE);
}
return_val = GDK_FILTER_REMOVE;
break;
{
GdkDragProtocol protocol;
- if ((xevent->xproperty.atom == gdk_x11_get_xatom_by_name ("XdndAware")) ||
- (xevent->xproperty.atom == gdk_x11_get_xatom_by_name ("_MOTIF_DRAG_RECEIVER_INFO")))
+ 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 (xevent->xproperty.window, &protocol))
+ 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_flush ();
+
+ gdk_display_sync (display);
gdk_error_trap_pop ();
+ return_val = GDK_FILTER_REMOVE;
}
- else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name ("_XEMBED_INFO"))
+ else if (xevent->xproperty.atom == gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO"))
{
unsigned long flags;
}
}
}
+ return_val = GDK_FILTER_REMOVE;
}
-
- return_val = GDK_FILTER_REMOVE;
}
break;
case ReparentNotify: