From 0e73ceb4bd101c12d273a5eb903134a134ee095d Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Wed, 17 Jun 2015 17:43:04 -0700 Subject: [PATCH] x11: Remove async-getprop xcb can do this for us now. --- src/Makefile-tests.am | 7 +- src/Makefile.am | 2 - src/x11/async-getprop.c | 680 ------------------------------------- src/x11/async-getprop.h | 67 ---- src/x11/testasyncgetprop.c | 496 --------------------------- src/x11/xprops.c | 179 +++++----- 6 files changed, 85 insertions(+), 1346 deletions(-) delete mode 100644 src/x11/async-getprop.c delete mode 100644 src/x11/async-getprop.h delete mode 100644 src/x11/testasyncgetprop.c 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 - -#undef DEBUG_SPEW -#ifdef DEBUG_SPEW -#include -#endif - -#include "async-getprop.h" - -#define NEED_REPLIES -#include - -#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 -#include - -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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef NULL -#define NULL ((void*) 0) -#endif - -#ifdef HAVE_BACKTRACE -#include -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 (¤t_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 (¤t_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 (¤t_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 (¤t_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 +#include "config.h" + +#include +#include + #include "xprops.h" #include #include "util-private.h" -#include "async-getprop.h" #include "ui.h" #include "mutter-Xatomtype.h" -#include -#include #include "window-private.h" +#include +#include + 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; } }