summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2015-06-17 17:43:04 -0700
committerJasper St. Pierre <jstpierre@mecheye.net>2015-06-17 18:08:11 -0700
commit0e73ceb4bd101c12d273a5eb903134a134ee095d (patch)
treedb161d8f68a59418e51b719dd9db7a4faa281e73
parent82a7060cdbc7336542dd1ac60265b2b9b701f0ec (diff)
downloadmutter-0e73ceb4bd101c12d273a5eb903134a134ee095d.tar.gz
x11: Remove async-getprop
xcb can do this for us now.
-rw-r--r--src/Makefile-tests.am7
-rw-r--r--src/Makefile.am2
-rw-r--r--src/x11/async-getprop.c680
-rw-r--r--src/x11/async-getprop.h67
-rw-r--r--src/x11/testasyncgetprop.c496
-rw-r--r--src/x11/xprops.c179
6 files changed, 85 insertions, 1346 deletions
diff --git a/src/Makefile-tests.am b/src/Makefile-tests.am
index ac3d5d79f..a9554a0e0 100644
--- a/src/Makefile-tests.am
+++ b/src/Makefile-tests.am
@@ -41,9 +41,6 @@ endif
# Some random test programs for bits of the code
testboxes_SOURCES = core/testboxes.c
-testasyncgetprop_SOURCES = x11/testasyncgetprop.c
-
-noinst_PROGRAMS+=testboxes testasyncgetprop
-
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
-testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
+
+noinst_PROGRAMS += testboxes
diff --git a/src/Makefile.am b/src/Makefile.am
index 301452d43..9316e954d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -210,8 +210,6 @@ libmutter_la_SOURCES = \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
- x11/async-getprop.c \
- x11/async-getprop.h \
x11/atomnames.h \
x11/events.c \
x11/events.h \
diff --git a/src/x11/async-getprop.c b/src/x11/async-getprop.c
deleted file mode 100644
index 72fe0d3b7..000000000
--- a/src/x11/async-getprop.c
+++ /dev/null
@@ -1,680 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Asynchronous X property getting hack */
-
-/*
- * 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 <assert.h>
-
-#undef DEBUG_SPEW
-#ifdef DEBUG_SPEW
-#include <stdio.h>
-#endif
-
-#include "async-getprop.h"
-
-#define NEED_REPLIES
-#include <X11/Xlibint.h>
-
-#ifndef NULL
-#define NULL ((void*)0)
-#endif
-
-typedef struct _ListNode ListNode;
-typedef struct _AgPerDisplayData AgPerDisplayData;
-
-struct _ListNode
-{
- ListNode *next;
-};
-
-struct _AgGetPropertyTask
-{
- ListNode node;
-
- AgPerDisplayData *dd;
- Window window;
- Atom property;
-
- unsigned long request_seq;
- int error;
-
- Atom actual_type;
- int actual_format;
-
- unsigned long n_items;
- unsigned long bytes_after;
- char *data;
-
- Bool have_reply;
-};
-
-struct _AgPerDisplayData
-{
- ListNode node;
- _XAsyncHandler async;
-
- Display *display;
- ListNode *pending_tasks;
- ListNode *pending_tasks_tail;
- ListNode *completed_tasks;
- ListNode *completed_tasks_tail;
- int n_tasks_pending;
- int n_tasks_completed;
-};
-
-static ListNode *display_datas = NULL;
-static ListNode *display_datas_tail = NULL;
-
-static void
-append_to_list (ListNode **head,
- ListNode **tail,
- ListNode *task)
-{
- task->next = NULL;
-
- if (*tail == NULL)
- {
- assert (*head == NULL);
- *head = task;
- *tail = task;
- }
- else
- {
- (*tail)->next = task;
- *tail = task;
- }
-}
-
-static void
-remove_from_list (ListNode **head,
- ListNode **tail,
- ListNode *task)
-{
- ListNode *prev;
- ListNode *node;
-
- prev = NULL;
- node = *head;
- while (node != NULL)
- {
- if (node == task)
- {
- if (prev)
- prev->next = node->next;
- else
- *head = node->next;
-
- if (node == *tail)
- *tail = prev;
-
- break;
- }
-
- prev = node;
- node = node->next;
- }
-
- /* can't remove what's not there */
- assert (node != NULL);
-
- node->next = NULL;
-}
-
-static void
-move_to_completed (AgPerDisplayData *dd,
- AgGetPropertyTask *task)
-{
- remove_from_list (&dd->pending_tasks,
- &dd->pending_tasks_tail,
- &task->node);
-
- append_to_list (&dd->completed_tasks,
- &dd->completed_tasks_tail,
- &task->node);
-
- dd->n_tasks_pending -= 1;
- dd->n_tasks_completed += 1;
-}
-
-static AgGetPropertyTask*
-find_pending_by_request_sequence (AgPerDisplayData *dd,
- unsigned long request_seq)
-{
- ListNode *node;
-
- /* if the sequence is after our last pending task, we
- * aren't going to find a match
- */
- {
- AgGetPropertyTask *task = (AgGetPropertyTask*) dd->pending_tasks_tail;
- if (task != NULL)
- {
- if (task->request_seq < request_seq)
- return NULL;
- else if (task->request_seq == request_seq)
- return task; /* why not check this */
- }
- }
-
- /* Generally we should get replies in the order we sent
- * requests, so we should usually be using the task
- * at the head of the list, if we use any task at all.
- * I'm not sure this is 100% guaranteed, if it is,
- * it would be a big speedup.
- */
-
- node = dd->pending_tasks;
- while (node != NULL)
- {
- AgGetPropertyTask *task = (AgGetPropertyTask*) node;
-
- if (task->request_seq == request_seq)
- return task;
-
- node = node->next;
- }
-
- return NULL;
-}
-
-static Bool
-async_get_property_handler (Display *dpy,
- xReply *rep,
- char *buf,
- int len,
- XPointer data)
-{
- xGetPropertyReply replbuf;
- xGetPropertyReply *reply;
- AgGetPropertyTask *task;
- AgPerDisplayData *dd;
- int bytes_read;
-
- dd = (AgPerDisplayData*) data;
-
-#if 0
- printf ("%s: seeing request seq %ld buflen %d\n", __FUNCTION__,
- dpy->last_request_read, len);
-#endif
-
- task = find_pending_by_request_sequence (dd, dpy->last_request_read);
-
- if (task == NULL)
- return False;
-
- assert (dpy->last_request_read == task->request_seq);
-
- task->have_reply = True;
- move_to_completed (dd, task);
-
- /* read bytes so far */
- bytes_read = SIZEOF (xReply);
-
- if (rep->generic.type == X_Error)
- {
- xError errbuf;
-
- task->error = rep->error.errorCode;
-
-#ifdef DEBUG_SPEW
- printf ("%s: error code = %d (ignoring error, eating %d bytes, generic.length = %ld)\n",
- __FUNCTION__, task->error, (SIZEOF (xError) - bytes_read),
- rep->generic.length);
-#endif
-
- /* 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, /* in 32-bit words */
- False); /* really seems like it should be True */
-
- return True;
- }
-
-#ifdef DEBUG_SPEW
- printf ("%s: already read %d bytes reading %d more for total of %d; generic.length = %ld\n",
- __FUNCTION__, bytes_read, (SIZEOF (xGetPropertyReply) - bytes_read) >> 2,
- SIZEOF (xGetPropertyReply), rep->generic.length);
-#endif
-
- /* (kind of a silly as we know sizeof(xGetPropertyReply) == sizeof(xReply)) */
- reply = (xGetPropertyReply *)
- _XGetAsyncReply (dpy, (char *)&replbuf, rep, buf, len,
- (SIZEOF (xGetPropertyReply) - bytes_read) >> 2, /* in 32-bit words */
- False); /* False means expecting more data to follow,
- * don't eat the rest of the reply
- */
-
- bytes_read = SIZEOF (xGetPropertyReply);
-
-#ifdef DEBUG_SPEW
- printf ("%s: have reply propertyType = %ld format = %d n_items = %ld\n",
- __FUNCTION__, reply->propertyType, reply->format, reply->nItems);
-#endif
-
- assert (task->data == NULL);
-
- /* 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 */
-#define ALIGN_VALUE(this, boundary) \
- (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
-
- 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 = ALIGN_VALUE (nbytes, 4);
- if (nbytes + 1 > 0 &&
- (task->data = (char *) Xmalloc ((unsigned)nbytes + 1)))
- {
-#ifdef DEBUG_SPEW
- printf ("%s: already read %d bytes using %ld, more eating %ld more\n",
- __FUNCTION__, bytes_read, nbytes, netbytes);
-#endif
- /* _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 = ALIGN_VALUE (netbytes, 4); /* align to word boundary */
- if (nbytes + 1 > 0 &&
- (task->data = (char *) Xmalloc ((unsigned)nbytes + 1)))
- {
-#ifdef DEBUG_SPEW
- printf ("%s: already read %d bytes using %ld more, eating %ld more\n",
- __FUNCTION__, bytes_read, nbytes, netbytes);
-#endif
- /* _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 is always 32 bits though */
- if (nbytes + 1 > 0 &&
- (task->data = (char *) Xmalloc ((unsigned)nbytes + 1)))
- {
-#ifdef DEBUG_SPEW
- printf ("%s: already read %d bytes using %ld more, eating %ld more\n",
- __FUNCTION__, bytes_read, nbytes, netbytes);
-#endif
-
- /* We have to copy the XGetWindowProperty() crackrock
- * and get format 32 as long even on 64-bit platforms.
- */
- if (sizeof (long) == 8)
- {
- char *netdata;
- char *lptr;
- 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.
- */
- {
-#if 0
- xError error;
-#endif
-
- task->error = BadImplementation;
-
-#if 0
- error.sequenceNumber = task->request_seq;
- error.type = X_Error;
- error.majorCode = X_GetProperty;
- error.minorCode = 0;
- error.errorCode = BadImplementation;
-
- _XError (dpy, &error);
-#endif
- }
-
- nbytes = netbytes = 0L;
- break;
- }
-
- if (task->data == NULL)
- {
- task->error = BadAlloc;
-
-#ifdef DEBUG_SPEW
- printf ("%s: already read %d bytes eating %ld\n",
- __FUNCTION__, bytes_read, netbytes);
-#endif
- /* _XEatData (dpy, (unsigned long) netbytes); */
- _XGetAsyncData (dpy, NULL, buf, len,
- bytes_read, 0, netbytes);
-
- /* UnlockDisplay (dpy); */
- return BadAlloc; /* not Success */
- }
-
- (task->data)[nbytes] = '\0';
- }
-
-#ifdef DEBUG_SPEW
- printf ("%s: have data\n", __FUNCTION__);
-#endif
-
- 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 AgPerDisplayData*
-get_display_data (Display *display,
- Bool create)
-{
- ListNode *node;
- AgPerDisplayData *dd;
-
- node = display_datas;
- while (node != NULL)
- {
- dd = (AgPerDisplayData*) node;
-
- if (dd->display == display)
- return dd;
-
- node = node->next;
- }
-
- if (!create)
- return NULL;
-
- dd = Xcalloc (1, sizeof (AgPerDisplayData));
- if (dd == NULL)
- return NULL;
-
- dd->display = display;
- dd->async.next = display->async_handlers;
- dd->async.handler = async_get_property_handler;
- dd->async.data = (XPointer) dd;
- dd->display->async_handlers = &dd->async;
-
- append_to_list (&display_datas,
- &display_datas_tail,
- &dd->node);
-
- return dd;
-}
-
-static void
-maybe_free_display_data (AgPerDisplayData *dd)
-{
- if (dd->pending_tasks == NULL &&
- dd->completed_tasks == NULL)
- {
- DeqAsyncHandler (dd->display, &dd->async);
- remove_from_list (&display_datas, &display_datas_tail,
- &dd->node);
- XFree (dd);
- }
-}
-
-AgGetPropertyTask*
-ag_task_create (Display *dpy,
- Window window,
- Atom property,
- long offset,
- long length,
- Bool delete,
- Atom req_type)
-{
- AgGetPropertyTask *task;
- xGetPropertyReq *req;
- AgPerDisplayData *dd;
-
- /* Fire up our request */
- LockDisplay (dpy);
-
- dd = get_display_data (dpy, True);
- if (dd == NULL)
- {
- UnlockDisplay (dpy);
- return NULL;
- }
-
- GetReq (GetProperty, req);
- req->window = window;
- req->property = property;
- req->type = req_type;
- req->delete = delete;
- req->longOffset = offset;
- req->longLength = length;
-
- /* Queue up our async task */
- task = Xcalloc (1, sizeof (AgGetPropertyTask));
- if (task == NULL)
- {
- UnlockDisplay (dpy);
- return NULL;
- }
-
- task->dd = dd;
- task->window = window;
- task->property = property;
- task->request_seq = dpy->request;
-
- append_to_list (&dd->pending_tasks,
- &dd->pending_tasks_tail,
- &task->node);
- dd->n_tasks_pending += 1;
-
- UnlockDisplay (dpy);
-
- SyncHandle ();
-
- return task;
-}
-
-static void
-free_task (AgGetPropertyTask *task)
-{
- remove_from_list (&task->dd->completed_tasks,
- &task->dd->completed_tasks_tail,
- &task->node);
- task->dd->n_tasks_completed -= 1;
- maybe_free_display_data (task->dd);
- XFree (task);
-}
-
-Status
-ag_task_get_reply_and_free (AgGetPropertyTask *task,
- Atom *actual_type,
- int *actual_format,
- unsigned long *nitems,
- unsigned long *bytesafter,
- unsigned char **prop)
-{
- Display *dpy;
-
- *prop = NULL;
-
- dpy = task->dd->display; /* Xlib macros require a variable named "dpy" */
-
- if (task->error != Success)
- {
- Status s = task->error;
-
- free_task (task);
-
- return s;
- }
-
- if (!task->have_reply)
- {
- free_task (task);
-
- return BadAlloc; /* not Success */
- }
-
- *actual_type = task->actual_type;
- *actual_format = task->actual_format;
- *nitems = task->n_items;
- *bytesafter = task->bytes_after;
-
- *prop = (unsigned char*) task->data; /* pass out ownership of task->data */
-
- SyncHandle ();
-
- free_task (task);
-
- return Success;
-}
-
-Bool
-ag_task_have_reply (AgGetPropertyTask *task)
-{
- return task->have_reply;
-}
-
-Atom
-ag_task_get_property (AgGetPropertyTask *task)
-{
- return task->property;
-}
-
-Window
-ag_task_get_window (AgGetPropertyTask *task)
-{
- return task->window;
-}
-
-Display*
-ag_task_get_display (AgGetPropertyTask *task)
-{
- return task->dd->display;
-}
-
-AgGetPropertyTask*
-ag_get_next_completed_task (Display *display)
-{
- AgPerDisplayData *dd;
-
- dd = get_display_data (display, False);
-
- if (dd == NULL)
- return NULL;
-
-#ifdef DEBUG_SPEW
- printf ("%d pending %d completed\n",
- dd->n_tasks_pending,
- dd->n_tasks_completed);
-#endif
-
- return (AgGetPropertyTask*) dd->completed_tasks;
-}
-
-void*
-ag_Xmalloc (unsigned long bytes)
-{
- return (void*) Xmalloc (bytes);
-}
-
-void*
-ag_Xmalloc0 (unsigned long bytes)
-{
- return (void*) Xcalloc (bytes, 1);
-}
diff --git a/src/x11/async-getprop.h b/src/x11/async-getprop.h
deleted file mode 100644
index b975d0f00..000000000
--- a/src/x11/async-getprop.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/* Asynchronous X property getting hack */
-
-/*
- * Copyright (C) 2002 Havoc Pennington
- *
- * 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 ASYNC_GETPROP_H
-#define ASYNC_GETPROP_H
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-
-typedef struct _AgGetPropertyTask AgGetPropertyTask;
-
-AgGetPropertyTask* ag_task_create (Display *display,
- Window window,
- Atom property,
- long offset,
- long length,
- Bool delete,
- Atom req_type);
-Status ag_task_get_reply_and_free (AgGetPropertyTask *task,
- Atom *actual_type,
- int *actual_format,
- unsigned long *nitems,
- unsigned long *bytesafter,
- unsigned char **prop);
-
-Bool ag_task_have_reply (AgGetPropertyTask *task);
-Atom ag_task_get_property (AgGetPropertyTask *task);
-Window ag_task_get_window (AgGetPropertyTask *task);
-Display* ag_task_get_display (AgGetPropertyTask *task);
-
-AgGetPropertyTask* ag_get_next_completed_task (Display *display);
-
-/* so other headers don't have to include internal Xlib goo */
-void* ag_Xmalloc (unsigned long bytes);
-void* ag_Xmalloc0 (unsigned long bytes);
-
-#endif
-
-
-
-
diff --git a/src/x11/testasyncgetprop.c b/src/x11/testasyncgetprop.c
deleted file mode 100644
index 7ceed24ec..000000000
--- a/src/x11/testasyncgetprop.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
-
-/*
- * Copyright (C) 2002 Havoc Pennington
- *
- * 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 "async-getprop.h"
-
-#include <time.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <signal.h>
-#include <assert.h>
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef NULL
-#define NULL ((void*) 0)
-#endif
-
-#ifdef HAVE_BACKTRACE
-#include <execinfo.h>
-static void
-print_backtrace (void)
-{
- void *bt[500];
- int bt_size;
- int i;
- char **syms;
-
- bt_size = backtrace (bt, 500);
-
- syms = backtrace_symbols (bt, bt_size);
-
- i = 0;
- while (i < bt_size)
- {
- fprintf (stderr, " %s\n", syms[i]);
- ++i;
- }
-
- free (syms);
-}
-#else
-static void
-print_backtrace (void)
-{
- fprintf (stderr, "Not compiled with backtrace support\n");
-}
-#endif
-
-static int error_trap_depth = 0;
-
-static int
-x_error_handler (Display *xdisplay,
- XErrorEvent *error)
-{
- char buf[64];
-
- XGetErrorText (xdisplay, error->error_code, buf, 63);
-
- if (error_trap_depth == 0)
- {
- print_backtrace ();
-
- fprintf (stderr, "Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
- buf,
- error->serial,
- error->error_code,
- error->request_code,
- error->minor_code);
-
- exit (1);
- }
-
- return 1; /* return value is meaningless */
-}
-
-static void
-error_trap_push (Display *xdisplay)
-{
- ++error_trap_depth;
-}
-
-static void
-error_trap_pop (Display *xdisplay)
-{
- if (error_trap_depth == 0)
- {
- fprintf (stderr, "Error trap underflow!\n");
- exit (1);
- }
-
- XSync (xdisplay, False); /* get all errors out of the queue */
- --error_trap_depth;
-}
-
-static char*
-my_strdup (const char *str)
-{
- char *s;
-
- s = malloc (strlen (str) + 1);
- if (s == NULL)
- {
- fprintf (stderr, "malloc failed\n");
- exit (1);
- }
- strcpy (s, str);
-
- return s;
-}
-
-static char*
-atom_name (Display *display,
- Atom atom)
-{
- if (atom == None)
- {
- return my_strdup ("None");
- }
- else
- {
- char *xname;
- char *ret;
-
- error_trap_push (display);
- xname = XGetAtomName (display, atom);
- error_trap_pop (display);
- if (xname == NULL)
- return my_strdup ("[unknown atom]");
-
- ret = my_strdup (xname);
- XFree (xname);
-
- return ret;
- }
-}
-
-
-#define ELAPSED(start_time, current_time) \
- (((((double)current_time.tv_sec - start_time.tv_sec) * 1000000 + \
- (current_time.tv_usec - start_time.tv_usec))) / 1000.0)
-
-static struct timeval program_start_time;
-
-static Bool
-try_get_reply (Display *xdisplay,
- AgGetPropertyTask *task)
-{
- if (ag_task_have_reply (task))
- {
- int result;
- Atom actual_type;
- int actual_format;
- unsigned long n_items;
- unsigned long bytes_after;
- unsigned char *data;
- char *name;
- struct timeval current_time;
-
- gettimeofday (&current_time, NULL);
-
- printf (" %gms (we have a reply for property %ld)\n",
- ELAPSED (program_start_time, current_time),
- ag_task_get_property (task));
-
- data = NULL;
-
- name = atom_name (xdisplay,
- ag_task_get_property (task));
- printf (" %s on 0x%lx:\n", name,
- ag_task_get_window (task));
- free (name);
-
- result = ag_task_get_reply_and_free (task,
- &actual_type,
- &actual_format,
- &n_items,
- &bytes_after,
- &data);
- task = NULL;
-
- if (result != Success)
- {
- fprintf (stderr, " error code %d getting reply\n", result);
- }
- else
- {
- name = atom_name (xdisplay, actual_type);
- printf (" actual_type = %s\n", name);
- free (name);
-
- printf (" actual_format = %d\n", actual_format);
-
- printf (" n_items = %lu\n", n_items);
- printf (" bytes_after = %lu\n", bytes_after);
-
- printf (" data = \"%s\"\n", data ? (char*) data : "NULL");
- }
-
- return True;
- }
-
- return False;
-}
-
-static void run_speed_comparison (Display *xdisplay,
- Window window);
-
-int
-main (int argc, char **argv)
-{
- Display *xdisplay;
- int i;
- int n_left;
- int n_props;
- Window window;
- const char *window_str;
- char *end;
- Atom *props;
- struct timeval current_time;
-
- if (argc < 2)
- {
- fprintf (stderr, "specify window ID\n");
- return 1;
- }
-
- window_str = argv[1];
-
- end = NULL;
- window = strtoul (window_str, &end, 0);
- if (end == NULL || *end != '\0')
- {
- fprintf (stderr, "\"%s\" does not parse as a window ID\n", window_str);
- return 1;
- }
-
- xdisplay = XOpenDisplay (NULL);
- if (xdisplay == NULL)
- {
- fprintf (stderr, "Could not open display\n");
- return 1;
- }
-
- if (getenv ("MUTTER_SYNC") != NULL)
- XSynchronize (xdisplay, True);
-
- XSetErrorHandler (x_error_handler);
-
- n_props = 0;
- props = XListProperties (xdisplay, window, &n_props);
- if (n_props == 0 || props == NULL)
- {
- fprintf (stderr, "Window has no properties\n");
- return 1;
- }
-
- gettimeofday (&program_start_time, NULL);
-
- i = 0;
- while (i < n_props)
- {
- gettimeofday (&current_time, NULL);
- printf (" %gms (sending request for property %ld)\n",
- ELAPSED (program_start_time, current_time),
- props[i]);
- if (ag_task_create (xdisplay,
- window, props[i],
- 0, 0xffffffff,
- False,
- AnyPropertyType) == NULL)
- {
- fprintf (stderr, "Failed to send request\n");
- return 1;
- }
-
- ++i;
- }
-
- XFree (props);
- props = NULL;
-
- n_left = n_props;
-
- while (TRUE)
- {
- XEvent xevent;
- int connection;
- fd_set set;
- AgGetPropertyTask *task;
-
- /* Mop up event queue */
- while (XPending (xdisplay) > 0)
- {
- XNextEvent (xdisplay, &xevent);
- gettimeofday (&current_time, NULL);
- printf (" %gms (processing event type %d)\n",
- ELAPSED (program_start_time, current_time),
- xevent.xany.type);
- }
-
- while ((task = ag_get_next_completed_task (xdisplay)))
- {
- try_get_reply (xdisplay, task);
- n_left -= 1;
- }
-
- if (n_left == 0)
- {
- printf ("All %d replies received.\n", n_props);
- break;
- }
-
- /* Wake up if we may have a reply */
- connection = ConnectionNumber (xdisplay);
-
- FD_ZERO (&set);
- FD_SET (connection, &set);
-
- gettimeofday (&current_time, NULL);
- printf (" %gms (blocking for data %d left)\n",
- ELAPSED (program_start_time, current_time), n_left);
- select (connection + 1, &set, NULL, NULL, NULL);
- }
-
- run_speed_comparison (xdisplay, window);
-
- return 0;
-}
-
-/* This function doesn't have all the printf's
- * and other noise, it just compares async to sync
- */
-static void
-run_speed_comparison (Display *xdisplay,
- Window window)
-{
- int i;
- int n_props;
- struct timeval start, end;
- int n_left;
-
- /* We just use atom values (0 to n_props) % 200, many are probably
- * BadAtom, that's fine, but the %200 keeps most of them valid. The
- * async case is about twice as advantageous when using valid atoms
- * (or the issue may be that it's more advantageous when the
- * properties are present and data is transmitted).
- */
- n_props = 4000;
- printf ("Timing with %d property requests\n", n_props);
-
- gettimeofday (&start, NULL);
-
- i = 0;
- while (i < n_props)
- {
- if (ag_task_create (xdisplay,
- window, (Atom) i % 200,
- 0, 0xffffffff,
- False,
- AnyPropertyType) == NULL)
- {
- fprintf (stderr, "Failed to send request\n");
- exit (1);
- }
-
- ++i;
- }
-
- n_left = n_props;
-
- while (TRUE)
- {
- int connection;
- fd_set set;
- XEvent xevent;
- AgGetPropertyTask *task;
-
- /* Mop up event queue */
- while (XPending (xdisplay) > 0)
- XNextEvent (xdisplay, &xevent);
-
- while ((task = ag_get_next_completed_task (xdisplay)))
- {
- Atom actual_type;
- int actual_format;
- unsigned long n_items;
- unsigned long bytes_after;
- unsigned char *data;
-
- assert (ag_task_have_reply (task));
-
- data = NULL;
- ag_task_get_reply_and_free (task,
- &actual_type,
- &actual_format,
- &n_items,
- &bytes_after,
- &data);
-
- if (data)
- XFree (data);
-
- n_left -= 1;
- }
-
- if (n_left == 0)
- break;
-
- /* Wake up if we may have a reply */
- connection = ConnectionNumber (xdisplay);
-
- FD_ZERO (&set);
- FD_SET (connection, &set);
-
- select (connection + 1, &set, NULL, NULL, NULL);
- }
-
- gettimeofday (&end, NULL);
-
- printf ("Async time: %gms\n",
- ELAPSED (start, end));
-
- gettimeofday (&start, NULL);
-
- error_trap_push (xdisplay);
-
- i = 0;
- while (i < n_props)
- {
- Atom actual_type;
- int actual_format;
- unsigned long n_items;
- unsigned long bytes_after;
- unsigned char *data;
-
- data = NULL;
- if (XGetWindowProperty (xdisplay, window,
- (Atom) i % 200,
- 0, 0xffffffff,
- False,
- AnyPropertyType,
- &actual_type,
- &actual_format,
- &n_items,
- &bytes_after,
- &data) == Success)
- {
- if (data)
- XFree (data);
- }
-
- ++i;
- }
-
- error_trap_pop (xdisplay);
-
- gettimeofday (&end, NULL);
-
- printf ("Sync time: %gms\n",
- ELAPSED (start, end));
-}
diff --git a/src/x11/xprops.c b/src/x11/xprops.c
index 35b37494a..ae3068fe4 100644
--- a/src/x11/xprops.c
+++ b/src/x11/xprops.c
@@ -78,17 +78,21 @@ from The Open Group.
*/
-#include <config.h>
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+
#include "xprops.h"
#include <meta/errors.h>
#include "util-private.h"
-#include "async-getprop.h"
#include "ui.h"
#include "mutter-Xatomtype.h"
-#include <X11/Xatom.h>
-#include <string.h>
#include "window-private.h"
+#include <X11/Xatom.h>
+#include <X11/Xlib-xcb.h>
+
typedef struct
{
MetaDisplay *display;
@@ -168,13 +172,50 @@ validate_or_free_results (GetPropertyResults *results,
if (results->prop)
{
- XFree (results->prop);
+ g_free (results->prop);
results->prop = NULL;
}
return FALSE;
}
+static xcb_get_property_cookie_t
+async_get_property (xcb_connection_t *xcb_conn, Window xwindow,
+ Atom xatom, Atom required_type)
+{
+ return xcb_get_property (xcb_conn, False, xwindow,
+ xatom, required_type, 0, G_MAXULONG);
+}
+
+static gboolean
+async_get_property_finish (xcb_connection_t *xcb_conn,
+ xcb_get_property_cookie_t cookie,
+ GetPropertyResults *results)
+{
+ xcb_get_property_reply_t *reply;
+ xcb_generic_error_t *error;
+
+ reply = xcb_get_property_reply (xcb_conn, cookie, &error);
+ if (error)
+ {
+ free (error);
+ return FALSE;
+ }
+
+ results->n_items = reply->value_len;
+ results->type = reply->type;
+ results->bytes_after = reply->bytes_after;
+ results->format = reply->format;
+ results->prop = NULL;
+
+ if (results->type != None)
+ results->prop = g_memdup (xcb_get_property_value (reply),
+ xcb_get_property_value_length (reply));
+
+ free (reply);
+ return (results->prop != NULL);
+}
+
static gboolean
get_property (MetaDisplay *display,
Window xwindow,
@@ -182,6 +223,9 @@ get_property (MetaDisplay *display,
Atom req_type,
GetPropertyResults *results)
{
+ xcb_get_property_cookie_t cookie;
+ xcb_connection_t *xcb_conn = XGetXCBConnection (display->xdisplay);
+
results->display = display;
results->xwindow = xwindow;
results->xatom = xatom;
@@ -191,29 +235,8 @@ get_property (MetaDisplay *display,
results->bytes_after = 0;
results->format = 0;
- meta_error_trap_push (display);
- if (XGetWindowProperty (display->xdisplay, xwindow, xatom,
- 0, G_MAXLONG,
- False, req_type, &results->type, &results->format,
- &results->n_items,
- &results->bytes_after,
- &results->prop) != Success ||
- results->type == None)
- {
- if (results->prop)
- XFree (results->prop);
- meta_error_trap_pop_with_return (display);
- return FALSE;
- }
-
- if (meta_error_trap_pop_with_return (display) != Success)
- {
- if (results->prop)
- XFree (results->prop);
- return FALSE;
- }
-
- return TRUE;
+ cookie = async_get_property (xcb_conn, xwindow, xatom, req_type);
+ return async_get_property_finish (xcb_conn, cookie, results);
}
static gboolean
@@ -318,7 +341,7 @@ motif_hints_from_results (GetPropertyResults *results,
* MotifWmHints than the one we expect, apparently. I'm not sure of
* the history behind it. See bug #89841 for example.
*/
- *hints_p = ag_Xmalloc (sizeof (MotifWmHints));
+ *hints_p = malloc (sizeof (MotifWmHints));
if (*hints_p == NULL)
{
if (results->prop)
@@ -409,7 +432,7 @@ utf8_string_from_results (GetPropertyResults *results,
meta_warning ("Property %s on window 0x%lx contained invalid UTF-8\n",
name, results->xwindow);
meta_XFree (name);
- XFree (results->prop);
+ g_free (results->prop);
results->prop = NULL;
return FALSE;
@@ -492,7 +515,7 @@ utf8_list_from_results (GetPropertyResults *results,
meta_warning ("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n",
name, results->xwindow, i);
meta_XFree (name);
- meta_XFree (results->prop);
+ g_free (results->prop);
results->prop = NULL;
g_strfreev (retval);
@@ -508,7 +531,7 @@ utf8_list_from_results (GetPropertyResults *results,
*str_p = retval;
*n_str_p = i;
- meta_XFree (results->prop);
+ g_free (results->prop);
results->prop = NULL;
return TRUE;
@@ -585,7 +608,7 @@ latin1_list_from_results (GetPropertyResults *results,
*str_p = retval;
*n_str_p = i;
- meta_XFree (results->prop);
+ g_free (results->prop);
results->prop = NULL;
return TRUE;
@@ -844,7 +867,7 @@ wm_hints_from_results (GetPropertyResults *results,
return FALSE;
}
- hints = ag_Xmalloc0 (sizeof (XWMHints));
+ hints = calloc (1, sizeof (XWMHints));
raw = (xPropWMHints*) results->prop;
@@ -902,7 +925,7 @@ class_hint_from_results (GetPropertyResults *results,
return FALSE;
len_name = strlen ((char *) results->prop);
- if (! (class_hint->res_name = ag_Xmalloc (len_name+1)))
+ if (! (class_hint->res_name = malloc (len_name+1)))
{
XFree (results->prop);
results->prop = NULL;
@@ -916,7 +939,7 @@ class_hint_from_results (GetPropertyResults *results,
len_class = strlen ((char *)results->prop + len_name + 1);
- if (! (class_hint->res_class = ag_Xmalloc(len_class+1)))
+ if (! (class_hint->res_class = malloc(len_class+1)))
{
XFree(class_hint->res_name);
class_hint->res_name = NULL;
@@ -970,7 +993,7 @@ size_hints_from_results (GetPropertyResults *results,
raw = (xPropSizeHints*) results->prop;
- hints = ag_Xmalloc (sizeof (XSizeHints));
+ hints = malloc (sizeof (XSizeHints));
/* XSizeHints misdeclares these as int instead of long */
hints->flags = raw->flags;
@@ -1027,18 +1050,6 @@ meta_prop_get_size_hints (MetaDisplay *display,
return size_hints_from_results (&results, hints_p, flags_p);
}
-static AgGetPropertyTask*
-get_task (MetaDisplay *display,
- Window xwindow,
- Atom xatom,
- Atom req_type)
-{
- return ag_task_create (display->xdisplay,
- xwindow,
- xatom, 0, G_MAXLONG,
- False, req_type);
-}
-
static char*
latin1_to_utf8 (const char *text)
{
@@ -1064,7 +1075,8 @@ meta_prop_get_values (MetaDisplay *display,
int n_values)
{
int i;
- AgGetPropertyTask **tasks;
+ xcb_get_property_cookie_t *tasks;
+ xcb_connection_t *xcb_conn = XGetXCBConnection (display->xdisplay);
meta_verbose ("Requesting %d properties of 0x%lx at once\n",
n_values, xwindow);
@@ -1072,7 +1084,7 @@ meta_prop_get_values (MetaDisplay *display,
if (n_values == 0)
return;
- tasks = g_new0 (AgGetPropertyTask*, n_values);
+ tasks = g_new0 (xcb_get_property_cookie_t, n_values);
/* Start up tasks. The "values" array can have values
* with atom == None, which means to ignore that element.
@@ -1132,9 +1144,7 @@ meta_prop_get_values (MetaDisplay *display,
}
if (values[i].atom != None)
- tasks[i] = get_task (display, xwindow,
- values[i].atom, values[i].required_type);
-
+ tasks[i] = async_get_property (xcb_conn, xwindow, values[i].atom, values[i].required_type);
++i;
}
@@ -1147,10 +1157,11 @@ meta_prop_get_values (MetaDisplay *display,
i = 0;
while (i < n_values)
{
- AgGetPropertyTask *task;
GetPropertyResults results;
- if (tasks[i] == NULL)
+ /* We're relying on the fact that sequence numbers can never be zero
+ * in Xorg. This is a bit disgusting... */
+ if (tasks[i].sequence == 0)
{
/* Probably values[i].type was None, or ag_task_create()
* returned NULL.
@@ -1159,10 +1170,6 @@ meta_prop_get_values (MetaDisplay *display,
goto next;
}
- task = ag_get_next_completed_task (display->xdisplay);
- g_assert (task != NULL);
- g_assert (ag_task_have_reply (task));
-
results.display = display;
results.xwindow = xwindow;
results.xatom = values[i].atom;
@@ -1172,21 +1179,8 @@ meta_prop_get_values (MetaDisplay *display,
results.bytes_after = 0;
results.format = 0;
- if (ag_task_get_reply_and_free (task,
- &results.type, &results.format,
- &results.n_items,
- &results.bytes_after,
- &results.prop) != Success ||
- results.type == None)
- {
- values[i].type = META_PROP_VALUE_INVALID;
- if (results.prop)
- {
- XFree (results.prop);
- results.prop = NULL;
- }
- goto next;
- }
+ if (!async_get_property_finish (xcb_conn, tasks[i], &results))
+ goto next;
switch (values[i].type)
{
@@ -1216,18 +1210,9 @@ meta_prop_get_values (MetaDisplay *display,
else
{
char *new_str;
- char *xmalloc_new_str;
-
new_str = latin1_to_utf8 (values[i].v.str);
- xmalloc_new_str = ag_Xmalloc (strlen (new_str) + 1);
- if (xmalloc_new_str != NULL)
- {
- strcpy (xmalloc_new_str, new_str);
- meta_XFree (values[i].v.str);
- values[i].v.str = xmalloc_new_str;
- }
-
- g_free (new_str);
+ free (values[i].v.str);
+ values[i].v.str = new_str;
}
break;
case META_PROP_VALUE_MOTIF_HINTS:
@@ -1305,42 +1290,44 @@ free_value (MetaPropValue *value)
break;
case META_PROP_VALUE_UTF8:
case META_PROP_VALUE_STRING:
+ free (value->v.str);
+ break;
case META_PROP_VALUE_STRING_AS_UTF8:
- meta_XFree (value->v.str);
+ g_free (value->v.str);
break;
case META_PROP_VALUE_MOTIF_HINTS:
- meta_XFree (value->v.motif_hints);
+ free (value->v.motif_hints);
break;
case META_PROP_VALUE_CARDINAL:
break;
case META_PROP_VALUE_WINDOW:
break;
case META_PROP_VALUE_ATOM_LIST:
- meta_XFree (value->v.atom_list.atoms);
+ free (value->v.atom_list.atoms);
break;
case META_PROP_VALUE_TEXT_PROPERTY:
- meta_XFree (value->v.str);
+ free (value->v.str);
break;
case META_PROP_VALUE_WM_HINTS:
- meta_XFree (value->v.wm_hints);
+ free (value->v.wm_hints);
break;
case META_PROP_VALUE_CLASS_HINT:
- meta_XFree (value->v.class_hint.res_class);
- meta_XFree (value->v.class_hint.res_name);
+ free (value->v.class_hint.res_class);
+ free (value->v.class_hint.res_name);
break;
case META_PROP_VALUE_SIZE_HINTS:
- meta_XFree (value->v.size_hints.hints);
+ free (value->v.size_hints.hints);
break;
case META_PROP_VALUE_UTF8_LIST:
g_strfreev (value->v.string_list.strings);
break;
case META_PROP_VALUE_CARDINAL_LIST:
- meta_XFree (value->v.cardinal_list.cardinals);
+ free (value->v.cardinal_list.cardinals);
break;
case META_PROP_VALUE_SYNC_COUNTER:
break;
case META_PROP_VALUE_SYNC_COUNTER_LIST:
- meta_XFree (value->v.xcounter_list.counters);
+ free (value->v.xcounter_list.counters);
break;
}
}