2006-10-01 18:30:10 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
2002-10-06 05:04:39 -04:00
|
|
|
/*
|
|
|
|
* 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;
|
2008-12-01 17:54:57 -05:00
|
|
|
unsigned char *data;
|
2002-10-06 05:04:39 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
Comprehensively rename to Mutter
Code:
All references in the code not related to themes, keybindings, or
GConf were changed from 'metacity' to 'mutter'. This includes, among other
things, strings, comments, the atoms used in the message protocol, and
the envvars used for debugging. The GConf schema file was reduced to
the 3 settings new to mutter.
The overall version was brought up to 2.27 to match current gnome.
Structure:
All files named '*metacity*' were renamed '*mutter*' with appropriate
changes in the automake system. Files removed are
doc/creating_themes, src/themes, doc/metacity-theme.dtd,
metacity.doap. These files will eventually end up in an external
gnome-wm-data module.
Installation location:
On the filesystem the mutter-plugindir was change from
$(libdir)/metacity/plugins/clutter to just $(libdir)/mutter/plugins.
The mutter-plugins.pc.in reflects these changes.
Note:
mutter.desktop.in and mutter-wm.desktop both continue to have
X-GNOME-WMSettingsModule=metacity set. This allows
gnome-control-center to continue using libmetacity.so for
configuration. This is fine since most the general keybindings and wm
settings are being read from /apps/metacity/* in gconf.
2009-06-10 06:29:20 -04:00
|
|
|
if (getenv ("MUTTER_SYNC") != NULL)
|
2002-10-06 05:04:39 -04:00
|
|
|
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;
|
|
|
|
|
2002-10-06 15:50:31 -04:00
|
|
|
/* 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).
|
2002-10-06 05:04:39 -04:00
|
|
|
*/
|
2002-10-06 13:53:29 -04:00
|
|
|
n_props = 4000;
|
|
|
|
printf ("Timing with %d property requests\n", n_props);
|
|
|
|
|
2002-10-06 05:04:39 -04:00
|
|
|
gettimeofday (&start, NULL);
|
|
|
|
|
|
|
|
i = 0;
|
|
|
|
while (i < n_props)
|
|
|
|
{
|
|
|
|
if (ag_task_create (xdisplay,
|
2002-10-06 15:50:31 -04:00
|
|
|
window, (Atom) i % 200,
|
2002-10-06 05:04:39 -04:00
|
|
|
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;
|
2008-12-01 17:54:57 -05:00
|
|
|
unsigned char *data;
|
2002-10-06 05:04:39 -04:00
|
|
|
|
|
|
|
assert (ag_task_have_reply (task));
|
|
|
|
|
|
|
|
data = NULL;
|
2011-01-24 15:44:12 -05:00
|
|
|
ag_task_get_reply_and_free (task,
|
|
|
|
&actual_type,
|
|
|
|
&actual_format,
|
|
|
|
&n_items,
|
|
|
|
&bytes_after,
|
|
|
|
&data);
|
2002-10-06 05:04:39 -04:00
|
|
|
|
|
|
|
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,
|
2002-10-06 15:50:31 -04:00
|
|
|
(Atom) i % 200,
|
2002-10-06 05:04:39 -04:00
|
|
|
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));
|
|
|
|
}
|