summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile21
-rw-r--r--test.c141
-rw-r--r--xas.c893
-rw-r--r--xas.h114
4 files changed, 1169 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1516352
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+LIBS=`pkg-config --libs x11`
+INCS=`pkg-config --cflags x11`
+
+OBJS=xas.o test.o
+
+HEADERS=xas.h
+
+.c.o:
+ $(CC) -g -Wall $(CFLAGS) $(INCS) -c $*.c
+
+
+test-async: $(OBJS)
+ $(CC) -g -Wall $(CFLAGS) -o $@ $(OBJS) $(LIBS)
+
+
+$(OBJS): $(HEADERS)
+
+clean:
+ rm -fr *.o test-async
+
+
diff --git a/test.c b/test.c
new file mode 100644
index 0000000..715c62b
--- /dev/null
+++ b/test.c
@@ -0,0 +1,141 @@
+#include "xas.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <X11/Xatom.h> /* XA_CARDINAL */
+
+int
+main(int argc, char **argv)
+{
+ Display *xdpy;
+ int xscreen;
+ Window xwin_root;
+ Atom atom, atom2;
+ XasContext *xas_ctx;
+ XasCookie cookie, cookie2, cookie3, cookie4;
+ XWindowAttributes wattr;
+
+ if ((xdpy = XOpenDisplay(getenv("DISPLAY"))) == NULL)
+ {
+ fprintf(stderr, "failed to open DISPLAY\n");
+ exit(-1);
+ }
+
+ xscreen = DefaultScreen(xdpy);
+ xwin_root = RootWindow(xdpy, xscreen);
+
+ xas_ctx = xas_context_new(xdpy);
+
+ atom = XInternAtom(xdpy, "_NET_CURRENT_DESKTOP", False);
+ atom2 = XInternAtom(xdpy, "_NET_NUMBER_OF_DESKTOPS", False);
+
+ cookie = xas_get_property(xas_ctx,
+ xwin_root,
+ atom,
+ 0, 1L,
+ False,
+ XA_CARDINAL);
+
+ /* Whack this in, in attempt to mess things up */
+ XGetWindowAttributes(xdpy, xwin_root, &wattr);
+ XSync(xdpy, False);
+
+ cookie2 = xas_get_property(xas_ctx,
+ xwin_root,
+ atom2,
+ 0, 1L,
+ False,
+ XA_CARDINAL);
+
+ cookie3 = xas_get_window_attributes(xas_ctx, xwin_root);
+
+ cookie4 = xas_get_geometry(xas_ctx, (Drawable)xwin_root);
+
+ /* Make sure all our queued requested get processed by server */
+ XSync(xdpy, False);
+
+ { /* Now grab various results */
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems;
+ unsigned long bytesafter;
+ int *result;
+
+ XasWindowAttributes *attr;
+
+ int x_return;
+ int y_return;
+ unsigned int width_return;
+ unsigned int height_return;
+ unsigned int border_width_return;
+ unsigned int depth_return;
+
+ int err;
+ char msg[255];
+
+ xas_get_property_reply(xas_ctx,
+ cookie,
+ &actual_type,
+ &actual_format,
+ &nitems,
+ &bytesafter,
+ (unsigned char**)&result,
+ NULL);
+
+ printf("got %li vs %li %li items, looks like %i\n",
+ XA_CARDINAL, actual_type, nitems, *result);
+
+ xas_get_property_reply(xas_ctx,
+ cookie2,
+ &actual_type,
+ &actual_format,
+ &nitems,
+ &bytesafter,
+ (unsigned char**)&result,
+ NULL);
+
+ printf("got %li vs %li %li items, looks like %i\n",
+ XA_CARDINAL, actual_type, nitems, *result);
+
+
+ attr = xas_get_window_attributes_reply(xas_ctx, cookie3, &err);
+
+ if (attr)
+ {
+ printf("got window attr ok..\n");
+ XFree(attr);
+ }
+
+ if (xas_get_geometry_reply (xas_ctx, cookie4,
+ &x_return,
+ &y_return,
+ &width_return,
+ &height_return,
+ &border_width_return,
+ &depth_return,
+ &err))
+ {
+ printf("xas_get_geometry_reply() success, x:%i, y%i, width:%i, height:%i, border:%i, depth:%i\n",
+ x_return,
+ y_return,
+ width_return,
+ height_return,
+ border_width_return,
+ depth_return);
+ }
+ else
+ {
+ printf("xas_get_geometry_reply() failed.");
+ if (err)
+ {
+ XGetErrorText(xdpy, err, msg, sizeof(msg));
+ printf(" Error was (%i) :'%s'\n", err, msg);
+ }
+ else
+ printf("No Error set\n");
+ }
+ }
+
+ return 0;
+}
diff --git a/xas.c b/xas.c
new file mode 100644
index 0000000..eb5712a
--- /dev/null
+++ b/xas.c
@@ -0,0 +1,893 @@
+/* Asynchronous Xlib hack utiltys lib
+ *
+ * Copyright (c) 2005 Matthew Allum
+ *
+ * Contains portions of code from Metacity and Xlib thus;
+ *
+ * Copyright (C) 2002 Havoc Pennington
+ * Copyright (C) 1986, 1998 The Open Group
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation.
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of The Open Group shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from The Open Group.
+ */
+
+#include "xas.h"
+
+#define WANT_DEBUG 1
+#define WANT_ASSERT 1
+
+#ifdef WANT_DEBUG
+#include <stdio.h>
+#define XAS_DBG(x, a...) \
+ fprintf(stderr, __FILE__ ":%d,%s() " x "\n", __LINE__, __func__, ##a)
+#else
+#define XAS_DBG(x, a...) do {} while (0)
+#endif
+#define XAS_MARK() XAS_DBG("--mark--");
+
+#ifdef WANT_ASSERT
+#include <assert.h>
+#define XAS_ASSERT(x) assert(x)
+#else
+#define XAS_ASSERT(x) do {} while (0)
+#endif
+
+#define XAS_ALIGN_VALUE(this, boundary) \
+ (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
+
+#define NEED_REPLIES
+#include <X11/Xlibint.h>
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+typedef struct XasTask XasTask;
+typedef struct XasTaskGetProperty XasTaskGetProperty;
+typedef struct XasTaskGetWinAttr XasTaskGetWinAttr;
+typedef struct XasTaskGetGeom XasTaskGetGeom;
+
+#define XAS_TASK(t) (XasTask*)(t)
+
+typedef enum XasTaskType
+{
+ XAS_TASK_UNKNOWN,
+ XAS_TASK_GET_PROPERTY,
+ XAS_TASK_GET_WIN_ATTR,
+ XAS_TASK_GET_GEOM,
+
+} XasTaskType;
+
+struct XasContext
+{
+ _XAsyncHandler async;
+ Display *xdpy;
+ XasTask *tasks_pending;
+ int n_tasks_pending;
+ XasTask *tasks_completed;
+ int n_tasks_completed;
+};
+
+struct XasTask
+{
+ XasTask *next;
+ XasTaskType type;
+ XasContext *ctx;
+ unsigned long request_seq;
+ Bool have_reply;
+ int error;
+
+};
+
+struct XasTaskGetProperty
+{
+ XasTask task;
+
+ Window window;
+ Atom property;
+
+ Atom actual_type;
+ int actual_format;
+
+ unsigned long n_items;
+ unsigned long bytes_after;
+ unsigned char *data;
+};
+
+struct XasTaskGetWinAttr
+{
+ XasTask task;
+ Window window;
+ XasWindowAttributes *attr;
+};
+
+struct XasTaskGetGeom
+{
+ XasTask task;
+ Drawable drw;
+ Window root;
+ int x;
+ int y;
+ unsigned int width;
+ unsigned int height;
+ unsigned int border;
+ unsigned int depth;
+};
+
+static XasTask*
+task_list_append(XasTask *tasks, XasTask *task)
+{
+ XasTask *t = NULL;
+
+ /* FIXME: use hash on seq_req key instead ? */
+
+ if (tasks == NULL) return task;
+
+ for (t = tasks; t->next != NULL; t = t->next);
+
+ t->next = task;
+
+ return tasks;
+}
+
+XasTask*
+task_list_remove(XasTask *tasks, XasTask *task)
+{
+ XasTask *t = NULL, *p = NULL;
+
+ if (task == tasks)
+ {
+ t = task->next;
+ tasks->next = NULL;
+ return t;
+ }
+
+ p = tasks;
+ t = tasks->next;
+
+ while (t != NULL)
+ {
+ if (t == task)
+ {
+ p->next = t->next;
+ task->next = NULL;
+ return tasks;
+ }
+ p = t; t = t->next;
+ }
+
+ return tasks;
+}
+
+static void
+task_init(XasContext *ctx, XasTask *task, XasTaskType type)
+{
+ task->ctx = ctx;
+ task->next = NULL;
+ task->type = type;
+ task->request_seq = ctx->xdpy->request;
+ task->have_reply = False;
+}
+
+static void
+task_complete(XasContext *ctx, XasTask *task)
+{
+ ctx->tasks_pending = task_list_remove(ctx->tasks_pending, task);
+ ctx->n_tasks_pending--;
+ ctx->tasks_completed = task_list_append(ctx->tasks_completed, task);
+ ctx->n_tasks_completed++;
+}
+
+static XasTask*
+xas_find_task_for_request_seq(XasContext *ctx,
+ XasTask *task_list,
+ unsigned long request_seq)
+{
+ XasTask *task = NULL;
+
+ task = task_list;
+
+ while (task != NULL)
+ {
+ if (task->request_seq == request_seq)
+ return task;
+ task = task->next;
+ }
+
+ return NULL;
+}
+
+static Bool
+xas_async_get_geom_handler (XasContext *ctx,
+ XasTaskGetGeom *task,
+ xReply *rep,
+ char *buf,
+ int len)
+{
+ Display *dpy;
+ xGetGeometryReply *repl;
+ xGetGeometryReply replbuf;
+
+ dpy = ctx->xdpy;
+
+ task->task.have_reply = True;
+
+ task_complete (ctx, XAS_TASK(task));
+
+ if (rep->generic.type == X_Error)
+ {
+ xError errbuf;
+ task->task.error = rep->error.errorCode;
+ _XGetAsyncReply (dpy, (char *)&errbuf, rep, buf, len,
+ (SIZEOF (xError) - SIZEOF (xReply)) >> 2,
+ False);
+ return True;
+ }
+
+ repl = (xGetGeometryReply *)
+ _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
+ (SIZEOF(xGetGeometryReply) - SIZEOF(xReply)) >> 2,
+ True);
+
+ task->root = repl->root;
+ task->x = cvtINT16toInt (repl->x);
+ task->y = cvtINT16toInt (repl->y);
+ task->width = repl->width;
+ task->height = repl->height;
+ task->border = repl->borderWidth;
+ task->depth = repl->depth;
+
+ return True;
+}
+
+
+static Bool
+xas_async_get_win_attr_handler (XasContext *ctx,
+ XasTaskGetWinAttr *task,
+ xReply *rep,
+ char *buf,
+ int len)
+{
+ Display *dpy;
+ xGetWindowAttributesReply replbuf;
+ xGetWindowAttributesReply *repl;
+
+ dpy = ctx->xdpy;
+
+ task->task.have_reply = True;
+
+ task_complete (ctx, XAS_TASK(task));
+
+ if (rep->generic.type == X_Error)
+ {
+ xError errbuf;
+ task->task.error = rep->error.errorCode;
+ _XGetAsyncReply (dpy, (char *)&errbuf, rep, buf, len,
+ (SIZEOF (xError) - SIZEOF (xReply)) >> 2,
+ False);
+ return True;
+ }
+
+ repl = (xGetWindowAttributesReply *)
+ _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
+ (SIZEOF(xGetWindowAttributesReply) - SIZEOF(xReply)) >> 2,
+ True);
+
+ task->attr = (XasWindowAttributes *)Xmalloc(sizeof(XasWindowAttributes));
+
+ if (task->attr == NULL)
+ {
+ task->task.error = BadAlloc;
+ return True;
+ }
+
+ task->attr->class = repl->class;
+ task->attr->bit_gravity = repl->bitGravity;
+ task->attr->win_gravity = repl->winGravity;
+ task->attr->backing_store = repl->backingStore;
+ task->attr->backing_planes = repl->backingBitPlanes;
+ task->attr->backing_pixel = repl->backingPixel;
+ task->attr->save_under = repl->saveUnder;
+ task->attr->colormap = repl->colormap;
+ task->attr->map_installed = repl->mapInstalled;
+ task->attr->map_state = repl->mapState;
+ task->attr->all_event_masks = repl->allEventMasks;
+ task->attr->your_event_mask = repl->yourEventMask;
+ task->attr->do_not_propagate_mask = repl->doNotPropagateMask;
+ task->attr->override_redirect = repl->override;
+ task->attr->visual = _XVIDtoVisual (dpy, repl->visualID);
+
+ return True;
+}
+
+static Bool
+xas_async_get_property_handler (XasContext *ctx,
+ XasTaskGetProperty *task,
+ xReply *rep,
+ char *buf,
+ int len)
+{
+ Display *dpy;
+ xGetPropertyReply replbuf;
+ xGetPropertyReply *reply;
+ int bytes_read;
+
+ /* Code and comments here wripped out of Metacity, Copyright
+ * Havoc Pennington.
+ */
+
+ /* FIXME: Really check this code is really reliable/safe.*/
+
+ XAS_DBG ("seeing request seq %ld buflen %d",
+ dpy->last_request_read, len);
+
+ dpy = ctx->xdpy;
+
+ task_complete (ctx, XAS_TASK(task));
+
+ /* read bytes so far */
+ bytes_read = SIZEOF (xReply);
+
+ if (rep->generic.type == X_Error)
+ {
+ xError errbuf;
+
+ task->task.error = rep->error.errorCode;
+
+ /* We return True (meaning we consumed the reply)
+ * because otherwise it would invoke the X error handler,
+ * and an async API is useless if you have to synchronously
+ * trap X errors. Also GetProperty can always fail, pretty
+ * much, so trapping errors is always what you want.
+ *
+ * We have to eat all the error reply data here.
+ * (kind of a charade as we know sizeof(xError) == sizeof(xReply))
+ *
+ * Passing discard = True seems to break things; I don't understand
+ * why, because there should be no extra data in an error reply,
+ * right?
+ */
+ _XGetAsyncReply (dpy, (char *)&errbuf, rep, buf, len,
+ (SIZEOF (xError) - bytes_read) >> 2, /* 32-bit words */
+ False); /* really seems like it should be True */
+ return True;
+ }
+
+ XAS_DBG ("already read %d bytes reading %d more for total of %d; generic.length = %ld",
+ bytes_read, (SIZEOF (xGetPropertyReply) - bytes_read) >> 2,
+ SIZEOF (xGetPropertyReply), rep->generic.length);
+
+ reply = (xGetPropertyReply *)
+ _XGetAsyncReply (dpy, (char *)&replbuf, rep, buf, len,
+ (SIZEOF (xGetPropertyReply) - bytes_read) >> 2,
+ False); /* False means expecting more data to follow,
+ * don't eat the rest of the reply
+ */
+
+ bytes_read = SIZEOF (xGetPropertyReply);
+
+ XAS_DBG ("have reply propertyType = %ld format = %d n_items = %ld",
+ reply->propertyType, reply->format, reply->nItems);
+
+ /* This is all copied from XGetWindowProperty(). Not sure we should
+ * LockDisplay(). Not sure I'm passing the right args to
+ * XGetAsyncData(). Not sure about a lot of things.
+ */
+
+ /* LockDisplay (dpy); */
+
+ if (reply->propertyType != None)
+ {
+ long nbytes, netbytes;
+
+ /* this alignment macro from orbit2 */
+
+ switch (reply->format)
+ {
+ /*
+ * One extra byte is malloced than is needed to contain the property
+ * data, but this last byte is null terminated and convenient for
+ * returning string properties, so the client doesn't then have to
+ * recopy the string to make it null terminated.
+ */
+ case 8:
+ nbytes = reply->nItems;
+ /* there's padding to word boundary */
+ netbytes = XAS_ALIGN_VALUE (nbytes, 4);
+ if (nbytes + 1 > 0 &&
+ (task->data = (unsigned char *) Xmalloc ((unsigned)nbytes + 1)))
+ {
+
+ XAS_DBG ("already read %d bytes using %ld, more eating %ld more",
+ bytes_read, nbytes, netbytes);
+
+ /* _XReadPad (dpy, (char *) task->data, netbytes); */
+ _XGetAsyncData (dpy, task->data, buf, len,
+ bytes_read, nbytes,
+ netbytes);
+ }
+ break;
+
+ case 16:
+ nbytes = reply->nItems * sizeof (short);
+ netbytes = reply->nItems << 1;
+ netbytes = XAS_ALIGN_VALUE (netbytes, 4); /* to word boundary */
+ if (nbytes + 1 > 0 &&
+ (task->data = (unsigned char *) Xmalloc ((unsigned)nbytes + 1)))
+ {
+ XAS_DBG ("%s: already read %d bytes using %ld more, eating %ld more\n",
+ __FUNCTION__, bytes_read, nbytes, netbytes);
+
+ /* _XRead16Pad (dpy, (short *) task->data, netbytes); */
+ _XGetAsyncData (dpy, task->data, buf, len,
+ bytes_read, nbytes, netbytes);
+ }
+ break;
+
+ case 32:
+ /* NOTE buffer is in longs to match XGetWindowProperty() */
+ nbytes = reply->nItems * sizeof (long);
+ netbytes = reply->nItems << 2; /* wire size always 32 bits though */
+ if (nbytes + 1 > 0 &&
+ (task->data = (unsigned char *) Xmalloc ((unsigned)nbytes + 1)))
+ {
+ XAS_DBG ("already read %d bytes using %ld more, eating %ld more",
+ bytes_read, nbytes, netbytes);
+
+ /* We have to copy the XGetWindowProperty() crackrock
+ * and get format 32 as long even on 64-bit platforms.
+ */
+ if (sizeof (long) == 8)
+ {
+ unsigned char *netdata;
+ unsigned char *lptr;
+ unsigned char *end_lptr;
+
+ /* Store the 32-bit values in the end of the array */
+ netdata = task->data + nbytes / 2;
+
+ _XGetAsyncData (dpy, netdata, buf, len,
+ bytes_read, netbytes,
+ netbytes);
+
+ /* Now move the 32-bit values to the front */
+
+ lptr = task->data;
+ end_lptr = task->data + nbytes;
+ while (lptr != end_lptr)
+ {
+ *(long*) lptr = *(CARD32*) netdata;
+ lptr += sizeof (long);
+ netdata += sizeof (CARD32);
+ }
+ }
+ else
+ {
+ /* Here the wire format matches our actual format */
+ _XGetAsyncData (dpy, task->data, buf, len,
+ bytes_read, netbytes,
+ netbytes);
+ }
+ }
+ break;
+
+ default:
+ /*
+ * This part of the code should never be reached. If it is,
+ * the server sent back a property with an invalid format.
+ * This is a BadImplementation error.
+ *
+ * However this async GetProperty API doesn't report errors
+ * via the standard X mechanism, so don't do anything about
+ * it, other than store it in task->error.
+ */
+ task->task.error = BadImplementation;
+ nbytes = netbytes = 0L;
+ break;
+ }
+
+ if (task->data == NULL)
+ {
+ task->task.error = BadAlloc;
+
+ XAS_DBG ("already read %d bytes eating %ld", bytes_read, netbytes);
+
+ /* _XEatData (dpy, (unsigned long) netbytes); */
+ _XGetAsyncData (dpy, NULL, buf, len, bytes_read, 0, netbytes);
+
+ /* UnlockDisplay (dpy); */
+ return BadAlloc; /* not Success */
+ }
+
+ (task->data)[nbytes] = '\0';
+ }
+
+ XAS_DBG ("have data");
+
+ task->actual_type = reply->propertyType;
+ task->actual_format = reply->format;
+ task->n_items = reply->nItems;
+ task->bytes_after = reply->bytesAfter;
+
+ /* UnlockDisplay (dpy); */
+
+ return True;
+}
+
+static Bool
+xas_async_handler (Display *dpy,
+ xReply *rep,
+ char *buf,
+ int len,
+ XPointer data)
+{
+ XasContext *ctx = (XasContext *)data;
+ XasTask *task;
+
+ XAS_ASSERT(ctx->xdpy == dpy);
+
+ task = xas_find_task_for_request_seq(ctx,
+ ctx->tasks_pending,
+ dpy->last_request_read);
+ if (!task)
+ return False;
+
+ switch (task->type)
+ {
+ case XAS_TASK_GET_PROPERTY:
+ return xas_async_get_property_handler (ctx,
+ (XasTaskGetProperty*)task,
+ rep, buf, len);
+ case XAS_TASK_GET_WIN_ATTR:
+ return xas_async_get_win_attr_handler (ctx,
+ (XasTaskGetWinAttr*)task,
+ rep, buf, len);
+ case XAS_TASK_GET_GEOM:
+ return xas_async_get_geom_handler (ctx,
+ (XasTaskGetGeom*)task,
+ rep, buf, len);
+ case XAS_TASK_UNKNOWN:
+ default:
+ /* Should never get here */
+ return False;
+ }
+
+ return False;
+}
+
+/* public */
+
+XasContext*
+xas_context_new(Display *xdpy)
+{
+ XasContext *ctx = NULL;
+
+ ctx = (XasContext *)Xmalloc(sizeof(XasContext));
+
+ ctx->xdpy = xdpy;
+ ctx->async.next = xdpy->async_handlers;
+ ctx->async.handler = xas_async_handler;
+ ctx->async.data = (XPointer) ctx;
+ ctx->xdpy->async_handlers = &ctx->async;
+
+ ctx->tasks_pending = NULL;
+ ctx->n_tasks_pending = 0;
+ ctx->tasks_completed = NULL;
+ ctx->n_tasks_completed = 0;
+
+ return ctx;
+}
+
+void
+xas_context_destroy(XasContext *ctx)
+{
+ DeqAsyncHandler (ctx->xdpy, &ctx->async);
+
+ /* FIXME: empty pending and completed lists */
+
+ free(ctx);
+}
+
+XasCookie
+xas_get_property(XasContext *ctx,
+ Window win,
+ Atom property,
+ long offset,
+ long length,
+ Bool delete,
+ Atom req_type)
+{
+ Display *dpy ;
+ XasTaskGetProperty *task;
+ xGetPropertyReq *req;
+
+ LockDisplay (ctx->xdpy);
+
+ dpy = ctx->xdpy; /* GetReq() needs this */
+
+ task = Xcalloc (1, sizeof (XasTaskGetProperty));
+ if (task == NULL)
+ {
+ UnlockDisplay (dpy);
+ return 0;
+ }
+
+ GetReq (GetProperty, req);
+ req->window = win;
+ req->property = property;
+ req->type = req_type;
+ req->delete = delete;
+ req->longOffset = offset;
+ req->longLength = length;
+
+ /* needed ? error.sequenceNumber = ctx->xdpy->request;*/
+
+ task_init(ctx, XAS_TASK(task), XAS_TASK_GET_PROPERTY);
+
+ task->window = win;
+ task->property = property;
+
+ ctx->tasks_pending = task_list_append(ctx->tasks_pending, &task->task);
+
+ ctx->n_tasks_pending ++;
+
+ UnlockDisplay (dpy);
+
+ SyncHandle ();
+
+ return task->task.request_seq;
+}
+
+Bool
+xas_have_reply(XasContext *ctx,
+ XasCookie cookie)
+{
+ return (xas_find_task_for_request_seq(ctx, ctx->tasks_completed, cookie) != NULL);
+}
+
+
+Status
+xas_get_property_reply(XasContext *ctx,
+ XasCookie cookie,
+ Atom *actual_type_return,
+ int *actual_format_return,
+ unsigned long *nitems_return,
+ unsigned long *bytes_after_return,
+ unsigned char **prop_return,
+ int *x_error_code)
+{
+ Display *dpy;
+ XasTaskGetProperty *task = NULL;
+ Bool result = False;
+
+ dpy = ctx->xdpy; /* For SyncHandle (); */
+
+ if (x_error_code) *x_error_code = 0; /* No error as yet */
+
+ task = (XasTaskGetProperty *) xas_find_task_for_request_seq(ctx,
+ ctx->tasks_completed,
+ cookie);
+ if (task == NULL)
+ {
+ XAS_DBG("Failed to find cookie");
+ return False;
+ }
+
+ if (!task->task.error)
+ {
+ *actual_type_return = task->actual_type;
+ *actual_format_return = task->actual_format;
+ *nitems_return = task->n_items;
+ *bytes_after_return = task->bytes_after;
+ *prop_return = task->data;
+
+ result = True;
+ }
+ else
+ {
+ XAS_DBG("is error");
+ if (x_error_code)
+ *x_error_code = task->task.error;
+ result = False;;
+ }
+
+ SyncHandle ();
+
+ ctx->tasks_completed = task_list_remove(ctx->tasks_completed,
+ XAS_TASK(task));
+ ctx->n_tasks_completed--;
+
+ XFree (task);
+
+ return result;
+}
+
+XasCookie
+xas_get_window_attributes(XasContext *ctx,
+ Window win)
+{
+ xResourceReq *req;
+ Display *dpy ;
+ XasTaskGetWinAttr *task;
+
+ LockDisplay (ctx->xdpy);
+
+ dpy = ctx->xdpy; /* GetReq() needs this */
+
+ task = Xcalloc (1, sizeof (XasTaskGetWinAttr));
+ if (task == NULL)
+ {
+ UnlockDisplay (dpy);
+ return 0;
+ }
+
+ GetResReq(GetWindowAttributes, win, req);
+
+ task_init(ctx, XAS_TASK(task), XAS_TASK_GET_WIN_ATTR);
+
+ task->window = win;
+
+ ctx->tasks_pending = task_list_append(ctx->tasks_pending, &task->task);
+ ctx->n_tasks_pending ++;
+
+ UnlockDisplay (dpy);
+
+ SyncHandle ();
+
+ return task->task.request_seq;
+}
+
+XasWindowAttributes*
+xas_get_window_attributes_reply(XasContext *ctx,
+ XasCookie cookie,
+ int *x_error_code)
+{
+ Display *dpy;
+ XasTaskGetWinAttr *task = NULL;
+ XasWindowAttributes *result = NULL;
+
+ dpy = ctx->xdpy; /* For SyncHandle (); */
+
+ if (x_error_code) *x_error_code = 0; /* No error as yet */
+
+ task = (XasTaskGetWinAttr *) xas_find_task_for_request_seq(ctx,
+ ctx->tasks_completed,
+ cookie);
+
+ if (task == NULL)
+ return NULL;
+
+ if (task->task.type != XAS_TASK_GET_WIN_ATTR)
+ return NULL;
+
+ if (!task->task.error)
+ {
+ result = task->attr;
+ }
+ else
+ {
+ XAS_DBG("is error");
+ if (x_error_code)
+ *x_error_code = task->task.error;
+ }
+
+ SyncHandle ();
+
+ ctx->tasks_completed = task_list_remove(ctx->tasks_completed,
+ XAS_TASK(task));
+ ctx->n_tasks_completed--;
+
+ XFree (task);
+
+ return result;
+}
+
+XasCookie
+xas_get_geometry(XasContext *ctx,
+ Drawable d)
+{
+ xResourceReq *req;
+ Display *dpy ;
+ XasTaskGetGeom *task;
+
+ LockDisplay (ctx->xdpy);
+
+ dpy = ctx->xdpy; /* GetReq() needs this */
+
+ task = Xcalloc (1, sizeof (XasTaskGetGeom));
+ if (task == NULL)
+ {
+ UnlockDisplay (dpy);
+ return 0;
+ }
+
+ GetResReq(GetGeometry, d, req);
+
+ task_init(ctx, XAS_TASK(task), XAS_TASK_GET_GEOM);
+
+ task->drw = d;
+
+ ctx->tasks_pending = task_list_append(ctx->tasks_pending, &task->task);
+ ctx->n_tasks_pending ++;
+
+ UnlockDisplay (dpy);
+
+ SyncHandle ();
+
+ return task->task.request_seq;
+}
+
+Status
+xas_get_geometry_reply (XasContext *ctx,
+ XasCookie cookie,
+ int *x_return,
+ int *y_return,
+ unsigned int *width_return,
+ unsigned int *height_return,
+ unsigned int *border_width_return,
+ unsigned int *depth_return,
+ int *x_error_code)
+{
+ Display *dpy;
+ XasTaskGetGeom *task = NULL;
+ Status result = False;
+
+ dpy = ctx->xdpy; /* For SyncHandle (); */
+
+ if (x_error_code) *x_error_code = 0; /* No error as yet */
+
+ task = (XasTaskGetGeom *) xas_find_task_for_request_seq(ctx,
+ ctx->tasks_completed,
+ cookie);
+
+ if (task == NULL || task->task.type != XAS_TASK_GET_GEOM)
+ return False;
+
+ if (!task->task.error)
+ {
+ *x_return = task->x;
+ *y_return = task->y;
+ *width_return = task->width;
+ *height_return = task->height;
+ *border_width_return = task->border;
+ *depth_return = task->depth;
+ result = True;
+ }
+ else
+ {
+ XAS_DBG("is error");
+ if (x_error_code)
+ *x_error_code = task->task.error;
+ }
+
+ SyncHandle ();
+
+ ctx->tasks_completed = task_list_remove(ctx->tasks_completed,
+ XAS_TASK(task));
+ ctx->n_tasks_completed--;
+
+ XFree (task);
+
+ return result;
+}
+
+
+
diff --git a/xas.h b/xas.h
new file mode 100644
index 0000000..e9b7ca8
--- /dev/null
+++ b/xas.h
@@ -0,0 +1,114 @@
+/* Asynchronous Xlib hack utiltys lib
+ *
+ * Copyright (c) 2005 Matthew Allum
+ *
+ * Contains portions of code from Metacity and Xlib.
+ *
+ * Copyright (C) 2002 Havoc Pennington
+ * Copyright (C) 1986, 1998 The Open Group
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation.
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of The Open Group shall not be
+ * used in advertising or otherwise to promote the sale, use or other dealings
+ * in this Software without prior written authorization from The Open Group.
+ */
+
+#ifndef _HAVE_XAS_H
+#define _HAVE_XAS_H
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+
+typedef struct XasContext XasContext;
+typedef unsigned long XasCookie;
+typedef struct XasWindowAttributes XasWindowAttributes;
+
+/* XWindowAttributes without geom info */
+struct XasWindowAttributes {
+ Visual *visual;
+ Window root;
+ int class;
+ int bit_gravity;
+ int win_gravity;
+ int backing_store;
+ unsigned long backing_planes;
+ unsigned long backing_pixel;
+ Bool save_under;
+ Colormap colormap;
+ Bool map_installed;
+ int map_state;
+ long all_event_masks;
+ long your_event_mask;
+ long do_not_propagate_mask;
+ Bool override_redirect;
+};
+
+XasContext*
+xas_context_new(Display *xdpy);
+
+void
+xas_context_destroy(XasContext *ctx);
+
+XasCookie
+xas_get_property(XasContext *ctx,
+ Window win,
+ Atom property,
+ long offset,
+ long length,
+ Bool delete,
+ Atom req_type);
+
+Status
+xas_get_property_reply(XasContext *ctx,
+ XasCookie cookie,
+ Atom *actual_type_return,
+ int *actual_format_return,
+ unsigned long *nitems_return,
+ unsigned long *bytes_after_return,
+ unsigned char **prop_return,
+ int *x_error_code);
+
+XasCookie
+xas_get_window_attributes(XasContext *ctx,
+ Window win);
+
+XasWindowAttributes*
+xas_get_window_attributes_reply(XasContext *ctx,
+ XasCookie cookie,
+ int *x_error_code);
+
+XasCookie
+xas_get_geometry(XasContext *ctx,
+ Drawable d);
+
+Status
+xas_get_geometry_reply (XasContext *ctx,
+ XasCookie cookie,
+ int *x_return,
+ int *y_return,
+ unsigned int *width_return,
+ unsigned int *height_return,
+ unsigned int *border_width_return,
+ unsigned int *depth_return,
+ int *x_error_code);
+Bool
+xas_have_reply(XasContext *ctx,
+ XasCookie cookie);
+
+#endif