Commit eb410261 authored by Owen Taylor's avatar Owen Taylor Committed by Owen Taylor

Send the focus on to the parent when there was no focus widget before and

Wed Aug 20 21:26:49 2003  Owen Taylor  <otaylor@redhat.com>

        * gtk/gtkplug.c (gtk_plug_focus): Send the focus on
        to the parent when there was no focus widget before
        and no focus widget after - that is, when there are
        no focusable widgets. (#108678, help tracking it
        down from Padraig O'Briain, Federico Mena Quintero, )

        * gtk/gtkxembed.[ch]: Move various shared utilities
        for the XEMBED protocol eused by GtkPlug and GtkSocket
        here.

        * gtk/gtkxembed.[ch] gtkplug.c gtksocket.c: Implement
        a flag bit that is sent with focus mesages to indicate
        that the focus has wrapped around on the toplevel;
        use this bit to catch infinite loops when there is no
        focusable widget at ll in the entire toplevel.

        * tests/testsocket.c (child_read_watch): Remove an
        extraneous unref.

        * gtk/gtkplug.c gtk/gtksocket.c gtk/gtkxembed.h:
        Up XEMBED protocol version to 1, add logic for
        sending the right version in XEMBED_EMBEDDED_NOTIFY.

        * gtk/gtksocket.c (gtk_socket_add_window): Send
        the embedder window in the XEMBED_EMBEDDED_NOTIFY
        as the spec requires.
parent 9eb2d7c2
......@@ -46,6 +46,7 @@ IGNORE_HFILES= \
gtktexttypes.h \
gtktextutil.h \
gtktypebuiltins.h \
gtkxembed.h \
xembed.h
# CFLAGS and LDFLAGS for compiling scan program. Only needed
......
......@@ -445,7 +445,9 @@ gtk_c_sources = \
gtk_plug_c_sources = \
gtkplug.c \
gtksocket.c
gtksocket.c \
gtkxembed.c \
gtkxembed.h
# we use our own built_sources variable rules to avoid automake's
# BUILT_SOURCES oddities
......
......@@ -33,7 +33,7 @@
#include "gdk/gdkkeysyms.h"
#include "x11/gdkx.h"
#include "xembed.h"
#include "gtkxembed.h"
static void gtk_plug_class_init (GtkPlugClass *klass);
static void gtk_plug_init (GtkPlug *plug);
......@@ -61,12 +61,6 @@ static GdkFilterReturn gtk_plug_filter_func (GdkXEvent *gdk_xev
gpointer data);
static void handle_modality_off (GtkPlug *plug);
static void send_xembed_message (GtkPlug *plug,
glong message,
glong detail,
glong data1,
glong data2,
guint32 time);
static void xembed_set_info (GdkWindow *window,
unsigned long flags);
......@@ -698,8 +692,8 @@ gtk_plug_set_focus (GtkWindow *window,
if (focus && !window->has_toplevel_focus)
{
send_xembed_message (plug, XEMBED_REQUEST_FOCUS, 0, 0, 0,
gtk_get_current_event_time ());
_gtk_xembed_send_message (plug->socket_window,
XEMBED_REQUEST_FOCUS, 0, 0, 0);
}
}
......@@ -741,9 +735,8 @@ add_grabbed_key (gpointer key, gpointer val, gpointer data)
if (!plug->grabbed_keys ||
!g_hash_table_lookup (plug->grabbed_keys, grabbed_key))
{
send_xembed_message (plug, XEMBED_GTK_GRAB_KEY, 0,
grabbed_key->accelerator_key, grabbed_key->accelerator_mods,
gtk_get_current_event_time ());
_gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_GRAB_KEY, 0,
grabbed_key->accelerator_key, grabbed_key->accelerator_mods);
}
}
......@@ -753,9 +746,8 @@ add_grabbed_key_always (gpointer key, gpointer val, gpointer data)
GrabbedKey *grabbed_key = key;
GtkPlug *plug = data;
send_xembed_message (plug, XEMBED_GTK_GRAB_KEY, 0,
grabbed_key->accelerator_key, grabbed_key->accelerator_mods,
gtk_get_current_event_time ());
_gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_GRAB_KEY, 0,
grabbed_key->accelerator_key, grabbed_key->accelerator_mods);
}
static void
......@@ -767,9 +759,8 @@ remove_grabbed_key (gpointer key, gpointer val, gpointer data)
if (!plug->grabbed_keys ||
!g_hash_table_lookup (plug->grabbed_keys, grabbed_key))
{
send_xembed_message (plug, XEMBED_GTK_UNGRAB_KEY, 0,
grabbed_key->accelerator_key, grabbed_key->accelerator_mods,
gtk_get_current_event_time ());
_gtk_xembed_send_message (plug->socket_window, XEMBED_GTK_UNGRAB_KEY, 0,
grabbed_key->accelerator_key, grabbed_key->accelerator_mods);
}
}
......@@ -812,6 +803,29 @@ 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)
......@@ -841,40 +855,18 @@ gtk_plug_focus (GtkWidget *widget,
}
gtk_window_set_focus (GTK_WINDOW (container), NULL);
if (!GTK_CONTAINER (window)->focus_child)
{
gint message = -1;
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;
}
send_xembed_message (plug, message, 0, 0, 0,
gtk_get_current_event_time ());
}
}
return FALSE;
}
else
{
/* Try to focus the first widget in the window */
if (bin->child && gtk_widget_child_focus (bin->child, direction))
return TRUE;
}
if (!GTK_CONTAINER (window)->focus_child)
focus_to_parent (plug, direction);
return FALSE;
}
......@@ -887,48 +879,13 @@ gtk_plug_check_resize (GtkContainer *container)
GTK_CONTAINER_CLASS (bin_class)->check_resize (container);
}
static void
send_xembed_message (GtkPlug *plug,
glong message,
glong detail,
glong data1,
glong data2,
guint32 time)
{
if (plug->socket_window)
{
GdkDisplay *display = gdk_drawable_get_display (plug->socket_window);
XEvent xevent;
GTK_NOTE(PLUGSOCKET,
g_message ("GtkPlug: Sending XEMBED message of type %ld", message));
xevent.xclient.window = GDK_WINDOW_XWINDOW (plug->socket_window);
xevent.xclient.type = ClientMessage;
xevent.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_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_WINDOW_XDISPLAY(plug->socket_window),
GDK_WINDOW_XWINDOW (plug->socket_window),
False, NoEventMask, &xevent);
gdk_display_sync (display);
gdk_error_trap_pop ();
}
}
static void
focus_first_last (GtkPlug *plug,
GtkDirectionType direction)
{
GtkWindow *window = GTK_WINDOW (plug);
GtkWidget *parent;
if (window->focus_widget)
{
parent = window->focus_widget->parent;
......@@ -977,7 +934,7 @@ xembed_set_info (GdkWindow *window,
Atom xembed_info_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_INFO");
buffer[1] = 0; /* Protocol version */
buffer[1] = GTK_XEMBED_PROTOCOL_VERSION;
buffer[1] = flags;
XChangeProperty (GDK_DISPLAY_XDISPLAY (display),
......@@ -988,17 +945,17 @@ xembed_set_info (GdkWindow *window,
}
static void
handle_xembed_message (GtkPlug *plug,
glong message,
glong detail,
glong data1,
glong data2,
guint32 time)
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 %ld received", message));
g_message ("GtkPlug: Message of type %d received", message));
switch (message)
{
......@@ -1044,12 +1001,12 @@ handle_xembed_message (GtkPlug *plug,
case XEMBED_REQUEST_FOCUS:
case XEMBED_FOCUS_NEXT:
case XEMBED_FOCUS_PREV:
g_warning ("GtkPlug: Invalid _XEMBED message of type %ld received", message);
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 %ld", message));
g_message ("GtkPlug: Ignoring unknown _XEMBED message of type %d", message));
break;
}
}
......@@ -1071,14 +1028,15 @@ gtk_plug_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
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"))
......
......@@ -38,7 +38,7 @@
#include "x11/gdkx.h"
#include "xembed.h"
#include "gtkxembed.h"
typedef struct _GtkSocketPrivate GtkSocketPrivate;
......@@ -86,12 +86,6 @@ static GdkFilterReturn gtk_socket_filter_func (GdkXEvent *gdk_xevent,
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);
......@@ -690,16 +684,11 @@ socket_update_focus_in (GtkSocket *socket)
socket->focus_in = focus_in;
if (focus_in)
{
send_xembed_message (socket, XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT, 0, 0,
gtk_get_current_event_time ());
}
_gtk_xembed_send_focus_message (socket->plug_window,
XEMBED_FOCUS_IN, XEMBED_FOCUS_CURRENT);
else
{
send_xembed_message (socket, XEMBED_FOCUS_OUT, 0, 0, 0,
gtk_get_current_event_time ());
}
_gtk_xembed_send_message (socket->plug_window,
XEMBED_FOCUS_OUT, 0, 0, 0);
}
}
......@@ -720,10 +709,9 @@ socket_update_active (GtkSocket *socket)
{
socket->active = active;
send_xembed_message (socket,
active ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE,
0, 0, 0,
gtk_get_current_event_time ());
_gtk_xembed_send_message (socket->plug_window,
active ? XEMBED_WINDOW_ACTIVATE : XEMBED_WINDOW_DEACTIVATE,
0, 0, 0);
}
}
......@@ -773,9 +761,9 @@ gtk_socket_grab_notify (GtkWidget *widget,
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
......@@ -868,8 +856,8 @@ gtk_socket_focus (GtkWidget *widget, GtkDirectionType 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_socket_claim_focus (socket, FALSE);
......@@ -1017,7 +1005,7 @@ gtk_socket_add_window (GtkSocket *socket,
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
......@@ -1045,8 +1033,10 @@ gtk_socket_add_window (GtkSocket *socket,
if (toplevel && GTK_IS_WINDOW (toplevel))
gtk_window_add_embedded_xid (GTK_WINDOW (toplevel), xid);
send_xembed_message (socket, XEMBED_EMBEDDED_NOTIFY, 0, 0, 0,
gtk_get_current_event_time ());
_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);
......@@ -1057,42 +1047,6 @@ gtk_socket_add_window (GtkSocket *socket,
g_signal_emit (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)
{
GdkDisplay *display = gtk_widget_get_display (GTK_WIDGET (socket));
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_for_display (display, "_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_XDISPLAY (display),
GDK_WINDOW_XWINDOW (socket->plug_window),
False, NoEventMask, &xevent);
gdk_display_sync (display);
gdk_error_trap_pop ();
}
}
static gboolean
xembed_get_info (GdkWindow *window,
unsigned long *version,
......@@ -1146,15 +1100,80 @@ xembed_get_info (GdkWindow *window,
}
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 %ld received", message));
g_message ("GtkSocket: Message of type %d received", message));
switch (message)
{
......@@ -1165,7 +1184,7 @@ handle_xembed_message (GtkSocket *socket,
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:
......@@ -1174,16 +1193,10 @@ handle_xembed_message (GtkSocket *socket,
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);
......@@ -1198,7 +1211,7 @@ handle_xembed_message (GtkSocket *socket,
default:
GTK_NOTE (PLUGSOCKET,
g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %ld", message));
g_message ("GtkSocket: Ignoring unknown _XEMBED message of type %d", message));
break;
}
}
......@@ -1250,13 +1263,14 @@ gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
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;
}
......
/* GTK - The GIMP Toolkit
* gtkxembed.c: Utilities for the XEMBED protocol
* Copyright (C) 2001, 2003, Red Hat, Inc.
*
* 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gtkmain.h"
#include "gtkprivate.h"
#include "gtkxembed.h"
typedef struct _GtkXEmbedMessage GtkXEmbedMessage;
struct _GtkXEmbedMessage
{
glong message;
glong detail;
glong data1;
glong data2;
guint32 time;
};
static GSList *current_messages;
/**
* _gtk_xembed_push_message:
* @xevent: a XEvent
*
* Adds a client message to the stack of current XEMBED events.
**/
void
_gtk_xembed_push_message (XEvent *xevent)
{
GtkXEmbedMessage *message = g_new (GtkXEmbedMessage, 1);
message->time = xevent->xclient.data.l[0];
message->message = xevent->xclient.data.l[1];
message->detail = xevent->xclient.data.l[2];
message->data1 = xevent->xclient.data.l[3];
message->data2 = xevent->xclient.data.l[4];
current_messages = g_slist_prepend (current_messages, message);
}
/**
* _gtk_xembed_pop_message:
*
* Removes an event added with _gtk_xembed_push_message()
**/
void
_gtk_xembed_pop_message (void)
{
GtkXEmbedMessage *message = current_messages->data;
current_messages = g_slist_delete_link (current_messages, current_messages);
g_free (message);
}
/**
* _gtk_xembed_set_focus_wrapped:
*
* Sets a flag indicating that the current focus sequence wrapped
* around to the beginning of the ultimate toplevel.
**/
void
_gtk_xembed_set_focus_wrapped (void)
{
GtkXEmbedMessage *message;
g_return_if_fail (current_messages != NULL);
message = current_messages->data;
g_return_if_fail (message->message == XEMBED_FOCUS_PREV || message->message == XEMBED_FOCUS_NEXT);
message->data1 |= XEMBED_FOCUS_WRAPAROUND;
}
/**
* _gtk_xembed_get_focus_wrapped:
*
* Gets whether the current focus sequence has wrapped around
* to the beginning of the ultimate toplevel.
*
* Return value: %TRUE if the focus sequence has wrapped around.
**/
gboolean
_gtk_xembed_get_focus_wrapped (void)
{
GtkXEmbedMessage *message;
g_return_val_if_fail (current_messages != NULL, FALSE);
message = current_messages->data;
return (message->data1 & XEMBED_FOCUS_WRAPAROUND) != 0;
}
static guint32
gtk_xembed_get_time (void)
{
if (current_messages)
{
GtkXEmbedMessage *message = current_messages->data;
return message->time;
}
else
return gtk_get_current_event_time ();
}
/**
* _gtk_xembed_send_message:
* @recipient: window to which to send the window, or %NULL
* in which case nothing wil be sent
* @message: type of message
* @detail: detail field of message
* @data1: data1 field of message
* @data2: data2 field of message
*
* Sends a generic XEMBED message to a particular window.
**/
void
_gtk_xembed_send_message (GdkWindow *recipient,
XEmbedMessageType message,
glong detail,
glong data1,
glong data2)
{
GdkDisplay *display;
XEvent xevent;
if (!recipient)
return;
g_return_if_fail (GDK_IS_WINDOW (recipient));
display = gdk_drawable_get_display (recipient);
GTK_NOTE (PLUGSOCKET,
g_message ("Sending XEMBED message of type %d", message));
xevent.xclient.window = GDK_WINDOW_XWINDOW (recipient);
xevent.xclient.type = ClientMessage;
xevent.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED");
xevent.xclient.format = 32;
xevent.xclient.data.l[0] = gtk_xembed_get_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_WINDOW_XDISPLAY(recipient),
GDK_WINDOW_XWINDOW (recipient),
False, NoEventMask, &xevent);
gdk_display_sync (display);
gdk_error_trap_pop ();
}
/**
* _gtk_xembed_send_focus_message:
* @recipient: window to which to send the window, or %NULL
* in which case nothing wil be sent
* @message: type of message
* @detail: detail field of message
*
* Sends a XEMBED message for moving the focus along the focus
* chain to a window. The flags field that these messages share
* will be correctly filled in.
**/
void
_gtk_xembed_send_focus_message (GdkWindow *recipient,
XEmbedMessageType message,
glong detail)
{
gulong flags = 0;
g_return_if_fail (GDK_IS_WINDOW (recipient));
g_return_if_fail (message == XEMBED_FOCUS_IN ||
message == XEMBED_FOCUS_NEXT ||
message == XEMBED_FOCUS_PREV);
if (current_messages)
{
GtkXEmbedMessage *message = current_messages->data;
switch (message->message)
{
case XEMBED_FOCUS_IN:
case XEMBED_FOCUS_NEXT:
case XEMBED_FOCUS_PREV: