summaryrefslogtreecommitdiff
path: root/gdk/x11
diff options
context:
space:
mode:
Diffstat (limited to 'gdk/x11')
-rw-r--r--gdk/x11/gdkasync.c301
-rw-r--r--gdk/x11/gdkasync.h22
-rw-r--r--gdk/x11/gdkdnd-x11.c134
3 files changed, 373 insertions, 84 deletions
diff --git a/gdk/x11/gdkasync.c b/gdk/x11/gdkasync.c
index 1ba90be295..06dc6d8ca7 100644
--- a/gdk/x11/gdkasync.c
+++ b/gdk/x11/gdkasync.c
@@ -47,9 +47,37 @@ in this Software without prior written authorization from The Open Group.
#include "gdkasync.h"
#include "gdkx.h"
+typedef struct _ChildInfoChildState ChildInfoChildState;
+typedef struct _ChildInfoState ChildInfoState;
typedef struct _SendEventState SendEventState;
typedef struct _SetInputFocusState SetInputFocusState;
+typedef enum {
+ CHILD_INFO_GET_PROPERTY,
+ CHILD_INFO_GET_WA,
+ CHILD_INFO_GET_GEOMETRY
+} ChildInfoReq;
+
+struct _ChildInfoChildState
+{
+ gulong seq[3];
+};
+
+struct _ChildInfoState
+{
+ gboolean get_wm_state;
+ Window *children;
+ guint nchildren;
+ GdkChildInfoX11 *child_info;
+ ChildInfoChildState *child_states;
+
+ guint current_child;
+ guint n_children_found;
+ gint current_request;
+ gboolean have_error;
+ gboolean child_has_error;
+};
+
struct _SendEventState
{
Display *dpy;
@@ -81,13 +109,11 @@ send_event_handler (Display *dpy,
if (dpy->last_request_read == state->send_event_req)
{
- if (rep->generic.type == X_Error)
+ if (rep->generic.type == X_Error &&
+ rep->error.errorCode == BadWindow)
{
- if (rep->error.errorCode == BadWindow)
- {
- state->have_error = TRUE;
- return True;
- }
+ state->have_error = TRUE;
+ return True;
}
}
else if (dpy->last_request_read == state->get_input_focus_req)
@@ -97,6 +123,9 @@ send_event_handler (Display *dpy,
if (rep->generic.type != X_Error)
{
+ /* Actually does nothing, since there are no additional bytes
+ * to read, but maintain good form.
+ */
repl = (xGetInputFocusReply *)
_XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
(sizeof(xGetInputFocusReply) - sizeof(xReply)) >> 2,
@@ -108,22 +137,20 @@ send_event_handler (Display *dpy,
DeqAsyncHandler(state->dpy, &state->async);
- g_free (state);
-
- return True;
+ return (rep->generic.type != X_Error);
}
return False;
}
void
-_gdk_send_xevent_async (GdkDisplay *display,
- Window window,
- gboolean propagate,
- glong event_mask,
- XEvent *event_send,
- GdkSendXEventCallback callback,
- gpointer data)
+_gdk_x11_send_xevent_async (GdkDisplay *display,
+ Window window,
+ gboolean propagate,
+ glong event_mask,
+ XEvent *event_send,
+ GdkSendXEventCallback callback,
+ gpointer data)
{
Display *dpy;
SendEventState *state;
@@ -288,3 +315,245 @@ _gdk_x11_set_input_focus_safe (GdkDisplay *display,
UnlockDisplay(dpy);
SyncHandle();
}
+
+static void
+handle_get_wa_reply (Display *dpy,
+ ChildInfoState *state,
+ xGetWindowAttributesReply *repl)
+{
+ GdkChildInfoX11 *child = &state->child_info[state->n_children_found];
+ child->is_mapped = repl->mapState != IsUnmapped;
+ child->window_class = repl->class;
+}
+
+static void
+handle_get_geometry_reply (Display *dpy,
+ ChildInfoState *state,
+ xGetGeometryReply *repl)
+{
+ GdkChildInfoX11 *child = &state->child_info[state->n_children_found];
+
+ child->x = cvtINT16toInt (repl->x);
+ child->y = cvtINT16toInt (repl->y);
+ child->width = repl->width;
+ child->height = repl->height;
+}
+
+static void
+handle_get_property_reply (Display *dpy,
+ ChildInfoState *state,
+ xGetPropertyReply *repl)
+{
+ GdkChildInfoX11 *child = &state->child_info[state->n_children_found];
+ child->has_wm_state = repl->propertyType != None;
+
+ /* Since we called GetProperty with longLength of 0, we don't
+ * have to worry about consuming the property data that would
+ * normally follow after the reply
+ */
+}
+
+static void
+next_child (ChildInfoState *state)
+{
+ if (state->current_request == CHILD_INFO_GET_GEOMETRY)
+ {
+ if (!state->have_error && !state->child_has_error)
+ {
+ state->child_info[state->n_children_found].window = state->children[state->current_child];
+ state->n_children_found++;
+ }
+ state->current_child++;
+ if (state->get_wm_state)
+ state->current_request = CHILD_INFO_GET_PROPERTY;
+ else
+ state->current_request = CHILD_INFO_GET_WA;
+ state->child_has_error = FALSE;
+ state->have_error = FALSE;
+ }
+ else
+ state->current_request++;
+}
+
+static Bool
+get_child_info_handler (Display *dpy,
+ xReply *rep,
+ char *buf,
+ int len,
+ XPointer data)
+{
+ Bool result = True;
+
+ ChildInfoState *state = (ChildInfoState *)data;
+
+ if (dpy->last_request_read != state->child_states[state->current_child].seq[state->current_request])
+ return False;
+
+ if (rep->generic.type == X_Error)
+ {
+ state->child_has_error = TRUE;
+ if (rep->error.errorCode != BadDrawable ||
+ rep->error.errorCode != BadWindow)
+ {
+ state->have_error = TRUE;
+ result = False;
+ }
+ }
+ else
+ {
+ switch (state->current_request)
+ {
+ case CHILD_INFO_GET_PROPERTY:
+ {
+ xGetPropertyReply replbuf;
+ xGetPropertyReply *repl;
+
+ repl = (xGetPropertyReply *)
+ _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
+ (sizeof(xGetPropertyReply) - sizeof(xReply)) >> 2,
+ True);
+
+ handle_get_property_reply (dpy, state, repl);
+ }
+ break;
+ case CHILD_INFO_GET_WA:
+ {
+ xGetWindowAttributesReply replbuf;
+ xGetWindowAttributesReply *repl;
+
+ repl = (xGetWindowAttributesReply *)
+ _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
+ (sizeof(xGetWindowAttributesReply) - sizeof(xReply)) >> 2,
+ True);
+
+ handle_get_wa_reply (dpy, state, repl);
+ }
+ break;
+ case CHILD_INFO_GET_GEOMETRY:
+ {
+ xGetGeometryReply replbuf;
+ xGetGeometryReply *repl;
+
+ repl = (xGetGeometryReply *)
+ _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
+ (sizeof(xGetGeometryReply) - sizeof(xReply)) >> 2,
+ True);
+
+ handle_get_geometry_reply (dpy, state, repl);
+ }
+ break;
+ }
+ }
+
+ next_child (state);
+
+ return result;
+}
+
+gboolean
+_gdk_x11_get_window_child_info (GdkDisplay *display,
+ Window window,
+ gboolean get_wm_state,
+ GdkChildInfoX11 **children,
+ guint *nchildren)
+{
+ Display *dpy;
+ _XAsyncHandler async;
+ ChildInfoState state;
+ Window root, parent;
+ Atom wm_state_atom;
+ Bool result;
+ guint i;
+
+ *children = NULL;
+ *nchildren = 0;
+
+ dpy = GDK_DISPLAY_XDISPLAY (display);
+ wm_state_atom = gdk_x11_get_xatom_by_name_for_display (display, "WM_STATE");
+
+ gdk_error_trap_push ();
+ result = XQueryTree (dpy, window, &root, &parent,
+ &state.children, &state.nchildren);
+ gdk_error_trap_pop ();
+ if (!result)
+ return FALSE;
+
+ state.get_wm_state = get_wm_state;
+ state.child_info = g_new (GdkChildInfoX11, state.nchildren);
+ state.child_states = g_new (ChildInfoChildState, state.nchildren);
+ state.current_child = 0;
+ state.n_children_found = 0;
+ if (get_wm_state)
+ state.current_request = CHILD_INFO_GET_PROPERTY;
+ else
+ state.current_request = CHILD_INFO_GET_WA;
+ state.have_error = FALSE;
+ state.child_has_error = FALSE;
+
+ LockDisplay(dpy);
+
+ async.next = dpy->async_handlers;
+ async.handler = get_child_info_handler;
+ async.data = (XPointer) &state;
+ dpy->async_handlers = &async;
+
+ for (i = 0; i < state.nchildren; i++)
+ {
+ xResourceReq *resource_req;
+ xGetPropertyReq *prop_req;
+ Window window = state.children[i];
+
+ if (get_wm_state)
+ {
+ GetReq (GetProperty, prop_req);
+ prop_req->window = window;
+ prop_req->property = wm_state_atom;
+ prop_req->type = AnyPropertyType;
+ prop_req->delete = False;
+ prop_req->longOffset = 0;
+ prop_req->longLength = 0;
+
+ state.child_states[i].seq[CHILD_INFO_GET_PROPERTY] = dpy->request;
+ }
+
+ GetResReq(GetWindowAttributes, window, resource_req);
+ state.child_states[i].seq[CHILD_INFO_GET_WA] = dpy->request;
+
+ GetResReq(GetGeometry, window, resource_req);
+ state.child_states[i].seq[CHILD_INFO_GET_GEOMETRY] = dpy->request;
+ }
+
+ if (i != 0)
+ {
+ /* Wait for the last reply
+ */
+ xGetGeometryReply rep;
+
+ /* On error, our async handler will get called
+ */
+ if (_XReply (dpy, (xReply *)&rep, 0, xTrue))
+ handle_get_geometry_reply (dpy, &state, &rep);
+
+ next_child (&state);
+ }
+
+ if (!state.have_error)
+ {
+ *children = state.child_info;
+ *nchildren = state.n_children_found;
+ }
+ else
+ {
+ g_free (state.child_info);
+ }
+
+ XFree (state.children);
+ g_free (state.child_states);
+
+ DeqAsyncHandler(dpy, &async);
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ return !state.have_error;
+}
+
diff --git a/gdk/x11/gdkasync.h b/gdk/x11/gdkasync.h
index ea2d7b0746..36f76997f7 100644
--- a/gdk/x11/gdkasync.h
+++ b/gdk/x11/gdkasync.h
@@ -26,11 +26,25 @@
G_BEGIN_DECLS
+typedef struct _GdkChildInfoX11 GdkChildInfoX11;
+
typedef void (*GdkSendXEventCallback) (Window window,
gboolean success,
gpointer data);
-void _gdk_send_xevent_async (GdkDisplay *display,
+struct _GdkChildInfoX11
+{
+ Window window;
+ gint x;
+ gint y;
+ gint width;
+ gint height;
+ guint is_mapped : 1;
+ guint has_wm_state : 1;
+ guint window_class : 2;
+};
+
+void _gdk_x11_send_xevent_async (GdkDisplay *display,
Window window,
gboolean propagate,
glong event_mask,
@@ -42,6 +56,12 @@ void _gdk_x11_set_input_focus_safe (GdkDisplay *display,
int revert_to,
Time time);
+gboolean _gdk_x11_get_window_child_info (GdkDisplay *display,
+ Window window,
+ gboolean get_wm_state,
+ GdkChildInfoX11 **children,
+ guint *nchildren);
+
G_END_DECLS
#endif /* __GDK_ASYNC_H__ */
diff --git a/gdk/x11/gdkdnd-x11.c b/gdk/x11/gdkdnd-x11.c
index 00df75ca37..5b06b6371a 100644
--- a/gdk/x11/gdkdnd-x11.c
+++ b/gdk/x11/gdkdnd-x11.c
@@ -449,11 +449,10 @@ static GdkWindowCache *
gdk_window_cache_new (GdkScreen *screen)
{
XWindowAttributes xwa;
- Window root, parent, *children;
- unsigned int nchildren;
- int i;
Display *xdisplay = GDK_SCREEN_XDISPLAY (screen);
GdkWindow *root_window = gdk_screen_get_root_window (screen);
+ GdkChildInfoX11 *children;
+ guint nchildren, i;
GdkWindowCache *result = g_new (GdkWindowCache, 1);
@@ -467,25 +466,19 @@ gdk_window_cache_new (GdkScreen *screen)
result->old_event_mask | SubstructureNotifyMask);
gdk_window_add_filter (root_window, gdk_window_cache_filter, result);
- gdk_error_trap_push ();
+ if (!_gdk_x11_get_window_child_info (gdk_screen_get_display (screen),
+ GDK_WINDOW_XWINDOW (root_window),
+ FALSE, &children, &nchildren))
+ return result;
- if (!XQueryTree(xdisplay, GDK_WINDOW_XWINDOW (root_window),
- &root, &parent, &children, &nchildren))
- {
- gdk_error_trap_pop ();
- return result;
- }
-
for (i = 0; i < nchildren ; i++)
{
- if (XGetWindowAttributes (xdisplay, children[i], &xwa))
- gdk_window_cache_add (result, children[i],
- xwa.x, xwa.y, xwa.width, xwa.height,
- xwa.map_state != IsUnmapped);
+ gdk_window_cache_add (result, children[i].window,
+ children[i].x, children[i].y, children[i].width, children[i].height,
+ children[i].is_mapped);
}
- XFree (children);
- gdk_error_trap_pop ();
+ g_free (children);
return result;
}
@@ -507,67 +500,70 @@ gdk_window_cache_destroy (GdkWindowCache *cache)
g_free (cache);
}
-static Window
-get_client_window_at_coords_recurse (GdkDisplay *display,
- Window win,
- gint x,
- gint y)
+static gboolean
+window_has_wm_state (GdkDisplay *display,
+ Window win)
{
- Window root, tmp_parent, *children;
- unsigned int nchildren;
- int i;
- Window child = None;
Atom type = None;
int format;
unsigned long nitems, after;
unsigned char *data;
-
+
if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY(display), win,
gdk_x11_get_xatom_by_name_for_display (display, "WM_STATE"),
0, 0, False, AnyPropertyType,
&type, &format, &nitems, &after, &data) != Success)
- return None;
-
+ return FALSE;
+
if (type != None)
{
XFree (data);
- return win;
+ return TRUE;
}
-#if 0
- /* This is beautiful! Damn Enlightenment and click-to-focus */
- if (!XTranslateCoordinates (gdk_display, _gdk_root_window, win,
- x_root, y_root, &dest_x, &dest_y, &child))
+ return FALSE;
+}
+
+static Window
+get_client_window_at_coords_recurse (GdkDisplay *display,
+ Window win,
+ gint x,
+ gint y)
+{
+ GdkChildInfoX11 *children;
+ unsigned int nchildren;
+ int i;
+ gboolean found_child = FALSE;
+ GdkChildInfoX11 child;
+
+ if (!_gdk_x11_get_window_child_info (display, win, TRUE,
+ &children, &nchildren))
return None;
-
-#else
- if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), win,
- &root, &tmp_parent, &children, &nchildren))
- return 0;
-
- for (i = nchildren - 1; (i >= 0) && (child == None); i--)
+
+ for (i = nchildren - 1; (i >= 0) && !found_child; i--)
{
- XWindowAttributes xwa;
-
- if (XGetWindowAttributes (GDK_DISPLAY_XDISPLAY (display),
- children[i], &xwa))
- {
- if ((xwa.map_state == IsViewable) && (xwa.class == InputOutput) &&
- (x >= xwa.x) && (x < xwa.x + (gint)xwa.width) &&
- (y >= xwa.y) && (y < xwa.y + (gint)xwa.height))
- {
- x -= xwa.x;
- y -= xwa.y;
- child = children[i];
- }
- }
+ GdkChildInfoX11 *cur_child = &children[i];
+
+ if ((cur_child->is_mapped) && (cur_child->window_class == InputOutput) &&
+ (x >= cur_child->x) && (x < cur_child->x + cur_child->width) &&
+ (y >= cur_child->y) && (y < cur_child->y + cur_child->height))
+ {
+ x -= cur_child->x;
+ y -= cur_child->y;
+ child = *cur_child;
+ found_child = TRUE;
+ }
+ }
+
+ g_free (children);
+
+ if (found_child)
+ {
+ if (child.has_wm_state)
+ return child.window;
+ else
+ return get_client_window_at_coords_recurse (display, child.window, x, y);
}
-
- XFree (children);
-#endif
-
- if (child)
- return get_client_window_at_coords_recurse (display, child, x, y);
else
return None;
}
@@ -594,10 +590,13 @@ get_client_window_at_coords (GdkWindowCache *cache,
if ((x_root >= child->x) && (x_root < child->x + child->width) &&
(y_root >= child->y) && (y_root < child->y + child->height))
{
- retval = get_client_window_at_coords_recurse (gdk_screen_get_display (cache->screen),
- child->xid,
- x_root - child->x,
- y_root - child->y);
+ if (window_has_wm_state (gdk_screen_get_display (cache->screen), child->xid))
+ retval = child->xid;
+ else
+ retval = get_client_window_at_coords_recurse (gdk_screen_get_display (cache->screen),
+ child->xid,
+ x_root - child->x,
+ y_root - child->y);
if (!retval)
retval = child->xid;
}
@@ -2160,8 +2159,9 @@ send_xevent_async (GdkDragContext *context,
g_object_ref (context);
- _gdk_send_xevent_async (display, window, propagate, event_mask, event_send,
- send_xevent_async_cb, context);
+ _gdk_x11_send_xevent_async (display, window,
+ propagate, event_mask, event_send,
+ send_xevent_async_cb, context);
}
static gboolean