Commit 60149b32 authored by Owen Taylor's avatar Owen Taylor Committed by Owen Taylor

Add a function to XSendEvent() and call a calback on failure/success.

Fri Jul  4 22:57:18 2003  Owen Taylor  <otaylor@redhat.com>

        * gdk/x11/gdkasync.[ch] (_gdk_send_xevent_async): Add
        a function to XSendEvent() and call a calback on
        failure/success.

        * gdk/x11/gdkdnd-x11.c (xdnd_send_xevent): Short-circuit
        messages to the same process, use _gdk_send_xevent_async().
parent 86250658
Fri Jul 4 22:57:18 2003 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkasync.[ch] (_gdk_send_xevent_async): Add
a function to XSendEvent() and call a calback on
failure/success.
* gdk/x11/gdkdnd-x11.c (xdnd_send_xevent): Short-circuit
messages to the same process, use _gdk_send_xevent_async().
Fri Jul 4 22:26:27 2003 Owen Taylor <otaylor@redhat.com> Fri Jul 4 22:26:27 2003 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkwindow-x11.[ch] gdkevents-x11.c: Split * gdk/x11/gdkwindow-x11.[ch] gdkevents-x11.c: Split
......
Fri Jul 4 22:57:18 2003 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkasync.[ch] (_gdk_send_xevent_async): Add
a function to XSendEvent() and call a calback on
failure/success.
* gdk/x11/gdkdnd-x11.c (xdnd_send_xevent): Short-circuit
messages to the same process, use _gdk_send_xevent_async().
Fri Jul 4 22:26:27 2003 Owen Taylor <otaylor@redhat.com> Fri Jul 4 22:26:27 2003 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkwindow-x11.[ch] gdkevents-x11.c: Split * gdk/x11/gdkwindow-x11.[ch] gdkevents-x11.c: Split
......
Fri Jul 4 22:57:18 2003 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkasync.[ch] (_gdk_send_xevent_async): Add
a function to XSendEvent() and call a calback on
failure/success.
* gdk/x11/gdkdnd-x11.c (xdnd_send_xevent): Short-circuit
messages to the same process, use _gdk_send_xevent_async().
Fri Jul 4 22:26:27 2003 Owen Taylor <otaylor@redhat.com> Fri Jul 4 22:26:27 2003 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkwindow-x11.[ch] gdkevents-x11.c: Split * gdk/x11/gdkwindow-x11.[ch] gdkevents-x11.c: Split
......
Fri Jul 4 22:57:18 2003 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkasync.[ch] (_gdk_send_xevent_async): Add
a function to XSendEvent() and call a calback on
failure/success.
* gdk/x11/gdkdnd-x11.c (xdnd_send_xevent): Short-circuit
messages to the same process, use _gdk_send_xevent_async().
Fri Jul 4 22:26:27 2003 Owen Taylor <otaylor@redhat.com> Fri Jul 4 22:26:27 2003 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkwindow-x11.[ch] gdkevents-x11.c: Split * gdk/x11/gdkwindow-x11.[ch] gdkevents-x11.c: Split
......
Fri Jul 4 22:57:18 2003 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkasync.[ch] (_gdk_send_xevent_async): Add
a function to XSendEvent() and call a calback on
failure/success.
* gdk/x11/gdkdnd-x11.c (xdnd_send_xevent): Short-circuit
messages to the same process, use _gdk_send_xevent_async().
Fri Jul 4 22:26:27 2003 Owen Taylor <otaylor@redhat.com> Fri Jul 4 22:26:27 2003 Owen Taylor <otaylor@redhat.com>
* gdk/x11/gdkwindow-x11.[ch] gdkevents-x11.c: Split * gdk/x11/gdkwindow-x11.[ch] gdkevents-x11.c: Split
......
...@@ -47,17 +47,155 @@ in this Software without prior written authorization from The Open Group. ...@@ -47,17 +47,155 @@ in this Software without prior written authorization from The Open Group.
#include "gdkasync.h" #include "gdkasync.h"
#include "gdkx.h" #include "gdkx.h"
typedef struct _SendEventState SendEventState;
typedef struct _SetInputFocusState SetInputFocusState; typedef struct _SetInputFocusState SetInputFocusState;
struct _SetInputFocusState struct _SendEventState
{ {
Display *dpy; Display *dpy;
Window window; Window window;
_XAsyncHandler async; _XAsyncHandler async;
gulong send_event_req;
gulong get_input_focus_req;
gboolean have_error;
GdkSendXEventCallback callback;
gpointer data;
};
struct _SetInputFocusState
{
Display *dpy;
_XAsyncHandler async;
gulong set_input_focus_req; gulong set_input_focus_req;
gulong get_input_focus_req; gulong get_input_focus_req;
}; };
static Bool
send_event_handler (Display *dpy,
xReply *rep,
char *buf,
int len,
XPointer data)
{
SendEventState *state = (SendEventState *)data;
if (dpy->last_request_read == state->send_event_req)
{
if (rep->generic.type == X_Error)
{
if (rep->error.errorCode == BadWindow)
{
state->have_error = TRUE;
return True;
}
}
}
else if (dpy->last_request_read == state->get_input_focus_req)
{
xGetInputFocusReply replbuf;
xGetInputFocusReply *repl;
if (rep->generic.type != X_Error)
{
repl = (xGetInputFocusReply *)
_XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
(sizeof(xGetInputFocusReply) - sizeof(xReply)) >> 2,
True);
}
if (state->callback)
state->callback (state->window, !state->have_error, state->data);
DeqAsyncHandler(state->dpy, &state->async);
g_free (state);
return True;
}
return False;
}
void
_gdk_send_xevent_async (GdkDisplay *display,
Window window,
gboolean propagate,
glong event_mask,
XEvent *event_send,
GdkSendXEventCallback callback,
gpointer data)
{
Display *dpy;
SendEventState *state;
Status status;
dpy = GDK_DISPLAY_XDISPLAY (display);
state = g_new (SendEventState, 1);
state->dpy = dpy;
state->window = window;
state->callback = callback;
state->data = data;
state->have_error = FALSE;
LockDisplay(dpy);
state->async.next = dpy->async_handlers;
state->async.handler = send_event_handler;
state->async.data = (XPointer) state;
dpy->async_handlers = &state->async;
{
register xSendEventReq *req;
xEvent ev;
register Status (**fp)();
/* call through display to find proper conversion routine */
fp = &dpy->wire_vec[event_send->type & 0177];
if (*fp == NULL) *fp = _XEventToWire;
status = (**fp)(dpy, event_send, &ev);
if (!status)
{
g_warning ("Error converting event to wire");
DeqAsyncHandler(dpy, &state->async);
UnlockDisplay(dpy);
SyncHandle();
g_free (state);
return;
}
GetReq(SendEvent, req);
req->destination = window;
req->propagate = propagate;
req->eventMask = event_mask;
/* gross, matches Xproto.h */
#ifdef WORD64
memcpy ((char *) req->eventdata, (char *) &ev, SIZEOF(xEvent));
#else
memcpy ((char *) &req->event, (char *) &ev, SIZEOF(xEvent));
#endif
state->send_event_req = dpy->request;
}
/*
* XSync (dpy, 0)
*/
{
xReq *req;
GetEmptyReq(GetInputFocus, req);
state->get_input_focus_req = dpy->request;
}
UnlockDisplay(dpy);
SyncHandle();
}
static Bool static Bool
set_input_focus_handler (Display *dpy, set_input_focus_handler (Display *dpy,
xReply *rep, xReply *rep,
...@@ -119,7 +257,6 @@ _gdk_x11_set_input_focus_safe (GdkDisplay *display, ...@@ -119,7 +257,6 @@ _gdk_x11_set_input_focus_safe (GdkDisplay *display,
state = g_new (SetInputFocusState, 1); state = g_new (SetInputFocusState, 1);
state->dpy = dpy; state->dpy = dpy;
state->window = window;
LockDisplay(dpy); LockDisplay(dpy);
......
...@@ -26,10 +26,21 @@ ...@@ -26,10 +26,21 @@
G_BEGIN_DECLS G_BEGIN_DECLS
void _gdk_x11_set_input_focus_safe (GdkDisplay *display, typedef void (*GdkSendXEventCallback) (Window window,
Window window, gboolean success,
int revert_to, gpointer data);
Time time);
void _gdk_send_xevent_async (GdkDisplay *display,
Window window,
gboolean propagate,
glong event_mask,
XEvent *event_send,
GdkSendXEventCallback callback,
gpointer data);
void _gdk_x11_set_input_focus_safe (GdkDisplay *display,
Window window,
int revert_to,
Time time);
G_END_DECLS G_END_DECLS
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "gdk.h" /* For gdk_flush() */ #include "gdk.h" /* For gdk_flush() */
#include "gdkx.h" #include "gdkx.h"
#include "gdkasync.h"
#include "gdkdnd.h" #include "gdkdnd.h"
#include "gdkproperty.h" #include "gdkproperty.h"
#include "gdkprivate-x11.h" #include "gdkprivate-x11.h"
...@@ -98,29 +99,24 @@ static GdkFilterReturn motif_dnd_filter (GdkXEvent *xev, ...@@ -98,29 +99,24 @@ static GdkFilterReturn motif_dnd_filter (GdkXEvent *xev,
GdkEvent *event, GdkEvent *event,
gpointer data); gpointer data);
static GdkFilterReturn xdnd_enter_filter (GdkXEvent *xev, static GdkFilterReturn xdnd_enter_filter (GdkXEvent *xev,
GdkEvent *event, GdkEvent *event,
gpointer data); gpointer data);
static GdkFilterReturn xdnd_leave_filter (GdkXEvent *xev,
static GdkFilterReturn xdnd_leave_filter (GdkXEvent *xev, GdkEvent *event,
GdkEvent *event, gpointer data);
gpointer data);
static GdkFilterReturn xdnd_position_filter (GdkXEvent *xev, static GdkFilterReturn xdnd_position_filter (GdkXEvent *xev,
GdkEvent *event, GdkEvent *event,
gpointer data); gpointer data);
static GdkFilterReturn xdnd_status_filter (GdkXEvent *xev,
static GdkFilterReturn xdnd_status_filter (GdkXEvent *xev, GdkEvent *event,
GdkEvent *event, gpointer data);
gpointer data);
static GdkFilterReturn xdnd_finished_filter (GdkXEvent *xev, static GdkFilterReturn xdnd_finished_filter (GdkXEvent *xev,
GdkEvent *event, GdkEvent *event,
gpointer data); gpointer data);
static GdkFilterReturn xdnd_drop_filter (GdkXEvent *xev,
static GdkFilterReturn xdnd_drop_filter (GdkXEvent *xev, GdkEvent *event,
GdkEvent *event, gpointer data);
gpointer data);
static void xdnd_manage_source_filter (GdkDragContext *context, static void xdnd_manage_source_filter (GdkDragContext *context,
GdkWindow *window, GdkWindow *window,
...@@ -133,6 +129,18 @@ static void gdk_drag_context_finalize (GObject *object); ...@@ -133,6 +129,18 @@ static void gdk_drag_context_finalize (GObject *object);
static gpointer parent_class = NULL; static gpointer parent_class = NULL;
static GList *contexts; static GList *contexts;
const static struct {
const char *atom_name;
GdkFilterFunc func;
} xdnd_filters[] = {
{ "XdndEnter", xdnd_enter_filter },
{ "XdndLeave", xdnd_leave_filter },
{ "XdndPosition", xdnd_position_filter },
{ "XdndStatus", xdnd_status_filter },
{ "XdndFinished", xdnd_finished_filter },
{ "XdndDrop", xdnd_drop_filter },
};
GType GType
gdk_drag_context_get_type (void) gdk_drag_context_get_type (void)
{ {
...@@ -2090,28 +2098,116 @@ xdnd_set_actions (GdkDragContext *context) ...@@ -2090,28 +2098,116 @@ xdnd_set_actions (GdkDragContext *context)
private->xdnd_actions = context->actions; private->xdnd_actions = context->actions;
} }
/************************************************************* static void
* xdnd_send_xevent: send_xevent_async_cb (Window window,
* Like gdk_send_event, but if the target is the root gboolean success,
* window, sets an event mask of ButtonPressMask, otherwise gpointer data)
* an event mask of 0. {
* arguments: GdkDragContext *context = data;
* GDK_NOTE (DND,
* results: g_message ("Got async callback for #%lx, success = %d",
*************************************************************/ window, success));
/* On failure, we immediately continue with the protocol
* so we don't end up blocking for a timeout
*/
if (!success &&
context->dest_window &&
window == GDK_WINDOW_XID (context->dest_window))
{
GdkEvent temp_event;
GdkDragContextPrivateX11 *private = PRIVATE_DATA (context);
g_object_unref (context->dest_window);
context->dest_window = NULL;
context->action = 0;
private->drag_status = GDK_DRAG_STATUS_DRAG;
temp_event.dnd.type = GDK_DRAG_STATUS;
temp_event.dnd.window = context->source_window;
temp_event.dnd.send_event = TRUE;
temp_event.dnd.context = context;
temp_event.dnd.time = GDK_CURRENT_TIME;
gdk_event_put (&temp_event);
}
g_object_unref (context);
}
static GdkDisplay *
gdk_drag_context_get_display (GdkDragContext *context)
{
if (context->source_window)
return GDK_DRAWABLE_DISPLAY (context->source_window);
else if (context->dest_window)
return GDK_DRAWABLE_DISPLAY (context->dest_window);
g_assert_not_reached ();
return NULL;
}
static void
send_xevent_async (GdkDragContext *context,
Window window,
gboolean propagate,
glong event_mask,
XEvent *event_send)
{
GdkDisplay *display = gdk_drag_context_get_display (context);
g_object_ref (context);
_gdk_send_xevent_async (display, window, propagate, event_mask, event_send,
send_xevent_async_cb, context);
}
static gboolean static gboolean
xdnd_send_xevent (GdkDisplay *display, xdnd_send_xevent (GdkDragContext *context,
Window window, GdkWindow *window,
gboolean propagate, gboolean propagate,
XEvent *event_send) XEvent *event_send)
{ {
if (_gdk_x11_display_is_root_window (display, window)) GdkDisplay *display = gdk_drag_context_get_display (context);
return _gdk_send_xevent (display, window, propagate, ButtonPressMask, event_send); Window xwindow;
glong event_mask;
/* We short-circuit messages to ourselves */
if (gdk_window_get_window_type (window) != GDK_WINDOW_FOREIGN &&
event_send->xany.type == ClientMessage)
{
gint i;
for (i = 0; i < G_N_ELEMENTS (xdnd_filters); i++)
{
if (gdk_x11_get_xatom_by_name_for_display (display, xdnd_filters[i].atom_name) ==
event_send->xclient.message_type)
{
GdkEvent temp_event;
temp_event.any.window = window;
if ((*xdnd_filters[i].func) (event_send, &temp_event, NULL) == GDK_FILTER_TRANSLATE)
gdk_event_put (&temp_event);
return TRUE;
}
}
}
xwindow = GDK_WINDOW_XWINDOW (window);
if (_gdk_x11_display_is_root_window (display, xwindow))
event_mask = ButtonPressMask;
else else
return _gdk_send_xevent (display, window, propagate, 0, event_send); event_mask = 0;
}
send_xevent_async (context, xwindow, propagate, event_mask, event_send);
return TRUE;
}
static void static void
xdnd_send_enter (GdkDragContext *context) xdnd_send_enter (GdkDragContext *context)
{ {
...@@ -2154,8 +2250,7 @@ xdnd_send_enter (GdkDragContext *context) ...@@ -2154,8 +2250,7 @@ xdnd_send_enter (GdkDragContext *context)
} }
} }
if (!xdnd_send_xevent (display, if (!xdnd_send_xevent (context, context->dest_window,
GDK_DRAWABLE_XID (context->dest_window),
FALSE, &xev)) FALSE, &xev))
{ {
GDK_NOTE (DND, GDK_NOTE (DND,
...@@ -2186,8 +2281,7 @@ xdnd_send_leave (GdkDragContext *context) ...@@ -2186,8 +2281,7 @@ xdnd_send_leave (GdkDragContext *context)
xev.xclient.data.l[3] = 0; xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0; xev.xclient.data.l[4] = 0;
if (!xdnd_send_xevent (display, if (!xdnd_send_xevent (context, context->dest_window,
GDK_DRAWABLE_XID (context->dest_window),
FALSE, &xev)) FALSE, &xev))
{ {
GDK_NOTE (DND, GDK_NOTE (DND,
...@@ -2217,8 +2311,7 @@ xdnd_send_drop (GdkDragContext *context, guint32 time) ...@@ -2217,8 +2311,7 @@ xdnd_send_drop (GdkDragContext *context, guint32 time)
xev.xclient.data.l[3] = 0; xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = 0; xev.xclient.data.l[4] = 0;
if (!xdnd_send_xevent (display, if (!xdnd_send_xevent (context, context->dest_window,
GDK_DRAWABLE_XID (context->dest_window),
FALSE, &xev)) FALSE, &xev))
{ {
GDK_NOTE (DND, GDK_NOTE (DND,
...@@ -2252,8 +2345,7 @@ xdnd_send_motion (GdkDragContext *context, ...@@ -2252,8 +2345,7 @@ xdnd_send_motion (GdkDragContext *context,
xev.xclient.data.l[3] = time; xev.xclient.data.l[3] = time;
xev.xclient.data.l[4] = xdnd_action_to_atom (display, action); xev.xclient.data.l[4] = xdnd_action_to_atom (display, action);
if (!xdnd_send_xevent (display, if (!xdnd_send_xevent (context, context->dest_window,
GDK_DRAWABLE_XID (context->dest_window),
FALSE, &xev)) FALSE, &xev))
{ {
GDK_NOTE (DND, GDK_NOTE (DND,
...@@ -2700,36 +2792,21 @@ xdnd_drop_filter (GdkXEvent *xev, ...@@ -2700,36 +2792,21 @@ xdnd_drop_filter (GdkXEvent *xev,
void void
_gdk_dnd_init (GdkDisplay *display) _gdk_dnd_init (GdkDisplay *display)
{ {
int i;
init_byte_order (); init_byte_order ();
gdk_display_add_client_message_filter ( gdk_display_add_client_message_filter (
display, display,
gdk_atom_intern ("_MOTIF_DRAG_AND_DROP_MESSAGE", FALSE), gdk_atom_intern ("_MOTIF_DRAG_AND_DROP_MESSAGE", FALSE),
motif_dnd_filter, NULL); motif_dnd_filter, NULL);
gdk_display_add_client_message_filter (
display, for (i = 0; i < G_N_ELEMENTS (xdnd_filters); i++)
gdk_atom_intern ("XdndEnter", FALSE), {
xdnd_enter_filter, NULL); gdk_display_add_client_message_filter (
gdk_display_add_client_message_filter (
display,
gdk_atom_intern ("XdndLeave", FALSE),
xdnd_leave_filter, NULL);
gdk_display_add_client_message_filter (
display,
gdk_atom_intern ("XdndPosition", FALSE),
xdnd_position_filter, NULL);
gdk_display_add_client_message_filter (
display,
gdk_atom_intern ("XdndStatus", FALSE),
xdnd_status_filter, NULL);
gdk_display_add_client_message_filter (
display, display,
gdk_atom_intern ("XdndFinished", FALSE), gdk_atom_intern (xdnd_filters[i].atom_name, FALSE),
xdnd_finished_filter, NULL); xdnd_filters[i].func, NULL);
gdk_display_add_client_message_filter ( }
display,
gdk_atom_intern ("XdndDrop", FALSE),
xdnd_drop_filter, NULL);
} }
/* Source side */ /* Source side */
...@@ -3321,8 +3398,7 @@ gdk_drag_status (GdkDragContext *context, ...@@ -3321,8 +3398,7 @@ gdk_drag_status (GdkDragContext *context,
xev.xclient.data.l[3] = 0; xev.xclient.data.l[3] = 0;
xev.xclient.data.l[4] = xdnd_action_to_atom (display, action); xev.xclient.data.l[4] = xdnd_action_to_atom (display, action);
if (!xdnd_send_xevent (display,