use multi-value-get on a couple of properties for testing

2002-10-26  Havoc Pennington  <hp@pobox.com>

	* src/window.c (meta_window_new): use multi-value-get on a couple
	of properties for testing

	* src/xprops.c (meta_prop_get_values): implement multi-value-get

	* src/window.c (update_mwm_hints): XFree motif hints as we changed
	it to use Xmalloc

	* src/xprops.c: massively rework this to set up a
	get-multiple-properties-at-once API.

	* src/async-getprop.c (ag_Xmalloc): new function
This commit is contained in:
Havoc Pennington 2002-10-26 07:37:11 +00:00 committed by Havoc Pennington
parent e8097a6f8f
commit 5a8af8c2fb
7 changed files with 582 additions and 295 deletions

View File

@ -1,3 +1,18 @@
2002-10-26 Havoc Pennington <hp@pobox.com>
* src/window.c (meta_window_new): use multi-value-get on a couple
of properties for testing
* src/xprops.c (meta_prop_get_values): implement multi-value-get
* src/window.c (update_mwm_hints): XFree motif hints as we changed
it to use Xmalloc
* src/xprops.c: massively rework this to set up a
get-multiple-properties-at-once API.
* src/async-getprop.c (ag_Xmalloc): new function
2002-10-25 Havoc Pennington <hp@pobox.com> 2002-10-25 Havoc Pennington <hp@pobox.com>
Add "busy cursor on app startup" support, conditionally - works Add "busy cursor on app startup" support, conditionally - works

View File

@ -8,6 +8,8 @@ EGGFILES= \
eggaccelerators.h eggaccelerators.h
metacity_SOURCES= \ metacity_SOURCES= \
async-getprop.c \
async-getprop.h \
common.h \ common.h \
core.c \ core.c \
core.h \ core.h \

View File

@ -635,3 +635,9 @@ ag_get_next_completed_task (Display *display)
return (AgGetPropertyTask*) dd->completed_tasks; return (AgGetPropertyTask*) dd->completed_tasks;
} }
void*
ag_Xmalloc (unsigned long bytes)
{
return (void*) Xmalloc (bytes);
}

View File

@ -54,6 +54,9 @@ Display* ag_task_get_display (AgGetPropertyTask *task);
AgGetPropertyTask* ag_get_next_completed_task (Display *display); 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);
#endif #endif

View File

@ -153,7 +153,8 @@ wm_state_to_string (int state)
} }
MetaWindow* MetaWindow*
meta_window_new (MetaDisplay *display, Window xwindow, meta_window_new (MetaDisplay *display,
Window xwindow,
gboolean must_be_viewable) gboolean must_be_viewable)
{ {
MetaWindow *window; MetaWindow *window;
@ -161,8 +162,20 @@ meta_window_new (MetaDisplay *display, Window xwindow,
GSList *tmp; GSList *tmp;
MetaWorkspace *space; MetaWorkspace *space;
gulong existing_wm_state; gulong existing_wm_state;
char *str; #define N_INITIAL_PROPS 2
unsigned long cardinal; MetaPropValue initial_props[N_INITIAL_PROPS];
g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props));
memset (initial_props, '\0', sizeof (initial_props));
#define INITIAL_PROP_WM_CLIENT_MACHINE 0
initial_props[0].type = META_PROP_VALUE_STRING;
initial_props[0].atom = display->atom_wm_client_machine;
#define INITIAL_PROP_NET_WM_PID 1
initial_props[1].type = META_PROP_VALUE_CARDINAL;
initial_props[1].atom = display->atom_net_wm_pid;
meta_verbose ("Attempting to manage 0x%lx\n", xwindow); meta_verbose ("Attempting to manage 0x%lx\n", xwindow);
@ -427,21 +440,26 @@ meta_window_new (MetaDisplay *display, Window xwindow,
window->initial_workspace = 0; /* not used */ window->initial_workspace = 0; /* not used */
meta_display_register_x_window (display, &window->xwindow, window); meta_display_register_x_window (display, &window->xwindow, window);
if (meta_prop_get_latin1_string (window->display, window->xwindow, meta_prop_get_values (display, window->xwindow,
window->display->atom_wm_client_machine, initial_props, N_INITIAL_PROPS);
&str))
if (initial_props[INITIAL_PROP_WM_CLIENT_MACHINE].type !=
META_PROP_VALUE_INVALID)
{ {
window->wm_client_machine = g_strdup (str); window->wm_client_machine =
meta_XFree (str); g_strdup (initial_props[INITIAL_PROP_WM_CLIENT_MACHINE].v.str);
meta_XFree (initial_props[INITIAL_PROP_WM_CLIENT_MACHINE].v.str);
meta_verbose ("Window has client machine \"%s\"\n", meta_verbose ("Window has client machine \"%s\"\n",
window->wm_client_machine); window->wm_client_machine);
} }
if (meta_prop_get_cardinal (window->display, window->xwindow, if (initial_props[INITIAL_PROP_NET_WM_PID].type !=
window->display->atom_net_wm_pid, META_PROP_VALUE_INVALID)
&cardinal))
{ {
gulong cardinal = (int) initial_props[INITIAL_PROP_NET_WM_PID].v.cardinal;
if (cardinal <= 0) if (cardinal <= 0)
meta_warning (_("Application set a bogus _NET_WM_PID %ld\n"), meta_warning (_("Application set a bogus _NET_WM_PID %ld\n"),
cardinal); cardinal);
@ -4491,7 +4509,7 @@ update_mwm_hints (MetaWindow *window)
else else
meta_verbose ("Functions flag unset\n"); meta_verbose ("Functions flag unset\n");
g_free (hints); meta_XFree (hints);
recalc_window_features (window); recalc_window_features (window);
} }

View File

@ -2,6 +2,7 @@
/* /*
* Copyright (C) 2001 Havoc Pennington * Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2002 Red Hat Inc.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as * modify it under the terms of the GNU General Public License as
@ -23,41 +24,50 @@
#include "xprops.h" #include "xprops.h"
#include "errors.h" #include "errors.h"
#include "util.h" #include "util.h"
#include "async-getprop.h"
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <string.h> #include <string.h>
typedef struct
{
MetaDisplay *display;
Window xwindow;
Atom xatom;
Atom type;
int format;
unsigned long n_items;
unsigned long bytes_after;
unsigned char *prop;
} GetPropertyResults;
static gboolean static gboolean
check_type_and_format (MetaDisplay *display, validate_or_free_results (GetPropertyResults *results,
Window xwindow,
Atom xatom,
int expected_format, int expected_format,
Atom expected_type, Atom expected_type,
int n_items, /* -1 to not check this */ gboolean must_have_items)
int format,
Atom type)
{ {
char *type_name; char *type_name;
char *expected_name; char *expected_name;
char *prop_name; char *prop_name;
if (expected_format == format && if (expected_format == results->format &&
expected_type == type && expected_type == results->type &&
(n_items < 0 || n_items > 0)) (!must_have_items || results->n_items > 0))
return TRUE; return TRUE;
meta_error_trap_push (display); meta_error_trap_push (results->display);
type_name = XGetAtomName (display->xdisplay, type); type_name = XGetAtomName (results->display->xdisplay, results->type);
expected_name = XGetAtomName (display->xdisplay, expected_type); expected_name = XGetAtomName (results->display->xdisplay, expected_type);
prop_name = XGetAtomName (display->xdisplay, xatom); prop_name = XGetAtomName (results->display->xdisplay, results->xatom);
meta_error_trap_pop (display, TRUE); meta_error_trap_pop (results->display, TRUE);
meta_warning (_("Window 0x%lx has property %s that was expected to have type %s format %d and actually has type %s format %d n_items %d\n"), meta_warning (_("Window 0x%lx has property %s that was expected to have type %s format %d and actually has type %s format %d n_items %d\n"),
xwindow, results->xwindow,
prop_name ? prop_name : "(bad atom)", prop_name ? prop_name : "(bad atom)",
expected_name ? expected_name : "(bad atom)", expected_name ? expected_name : "(bad atom)",
expected_format, expected_format,
type_name ? type_name : "(bad atom)", type_name ? type_name : "(bad atom)",
format, n_items); results->format, (int) results->n_items);
if (type_name) if (type_name)
XFree (type_name); XFree (type_name);
@ -66,9 +76,71 @@ check_type_and_format (MetaDisplay *display,
if (prop_name) if (prop_name)
XFree (prop_name); XFree (prop_name);
if (results->prop)
{
XFree (results->prop);
results->prop = NULL;
}
return FALSE; return FALSE;
} }
static gboolean
get_property (MetaDisplay *display,
Window xwindow,
Atom xatom,
Atom req_type,
GetPropertyResults *results)
{
results->display = display;
results->xwindow = xwindow;
results->xatom = xatom;
results->prop = NULL;
results->n_items = 0;
results->type = None;
results->bytes_after = 0;
results->format = 0;
meta_error_trap_push_with_return (display);
if (XGetWindowProperty (display->xdisplay, xwindow, xatom,
0, G_MAXLONG,
False, req_type, &results->type, &results->format,
&results->n_items,
&results->bytes_after,
(guchar **)&results->prop) != Success ||
results->type == None)
{
if (results->prop)
XFree (results->prop);
meta_error_trap_pop_with_return (display, TRUE);
return FALSE;
}
if (meta_error_trap_pop_with_return (display, TRUE) != Success)
{
if (results->prop)
XFree (results->prop);
return FALSE;
}
return TRUE;
}
static gboolean
atom_list_from_results (GetPropertyResults *results,
Atom **atoms_p,
int *n_atoms_p)
{
if (!validate_or_free_results (results, 32, XA_ATOM, FALSE))
return FALSE;
*atoms_p = (Atom*) results->prop;
*n_atoms_p = results->n_items;
results->prop = NULL;
return TRUE;
}
gboolean gboolean
meta_prop_get_atom_list (MetaDisplay *display, meta_prop_get_atom_list (MetaDisplay *display,
Window xwindow, Window xwindow,
@ -76,38 +148,29 @@ meta_prop_get_atom_list (MetaDisplay *display,
Atom **atoms_p, Atom **atoms_p,
int *n_atoms_p) int *n_atoms_p)
{ {
Atom type; GetPropertyResults results;
int format;
gulong n_atoms;
gulong bytes_after;
Atom *atoms;
*atoms_p = NULL; *atoms_p = NULL;
*n_atoms_p = 0; *n_atoms_p = 0;
meta_error_trap_push_with_return (display); if (!get_property (display, xwindow, xatom, XA_ATOM,
if (XGetWindowProperty (display->xdisplay, xwindow, xatom, &results))
0, G_MAXLONG,
False, XA_ATOM, &type, &format, &n_atoms,
&bytes_after, (guchar **)&atoms) != Success ||
type == None)
{
meta_error_trap_pop_with_return (display, TRUE);
return FALSE; return FALSE;
return atom_list_from_results (&results, atoms_p, n_atoms_p);
} }
if (meta_error_trap_pop_with_return (display, TRUE) != Success) static gboolean
return FALSE; cardinal_list_from_results (GetPropertyResults *results,
gulong **cardinals_p,
if (!check_type_and_format (display, xwindow, xatom, 32, XA_ATOM, int *n_cardinals_p)
-1, format, type))
{ {
XFree (atoms); if (!validate_or_free_results (results, 32, XA_CARDINAL, FALSE))
return FALSE; return FALSE;
}
*atoms_p = atoms; *cardinals_p = (gulong*) results->prop;
*n_atoms_p = n_atoms; *n_cardinals_p = results->n_items;
results->prop = NULL;
return TRUE; return TRUE;
} }
@ -119,38 +182,61 @@ meta_prop_get_cardinal_list (MetaDisplay *display,
gulong **cardinals_p, gulong **cardinals_p,
int *n_cardinals_p) int *n_cardinals_p)
{ {
Atom type; GetPropertyResults results;
int format;
gulong n_cardinals;
gulong bytes_after;
gulong *cardinals;
*cardinals_p = NULL; *cardinals_p = NULL;
*n_cardinals_p = 0; *n_cardinals_p = 0;
meta_error_trap_push_with_return (display); if (!get_property (display, xwindow, xatom, XA_CARDINAL,
if (XGetWindowProperty (display->xdisplay, xwindow, xatom, &results))
0, G_MAXLONG, return FALSE;
False, XA_CARDINAL, &type, &format, &n_cardinals,
&bytes_after, (guchar **)&cardinals) != Success || return cardinal_list_from_results (&results, cardinals_p, n_cardinals_p);
type == None) }
static gboolean
motif_hints_from_results (GetPropertyResults *results,
MotifWmHints **hints_p)
{ {
meta_error_trap_pop_with_return (display, TRUE); int real_size, max_size;
#define MAX_ITEMS sizeof (MotifWmHints)/sizeof (gulong)
*hints_p = NULL;
if (results->type == None || results->n_items <= 0)
{
meta_verbose ("Motif hints had unexpected type or n_items\n");
if (results->prop)
{
XFree (results->prop);
results->prop = NULL;
}
return FALSE; return FALSE;
} }
if (meta_error_trap_pop_with_return (display, TRUE) != Success) /* The issue here is that some old crufty code will set a smaller
return FALSE; * MotifWmHints than the one we expect, apparently. I'm not sure of
* the history behind it. See bug #89841 for example.
if (!check_type_and_format (display, xwindow, xatom, 32, XA_CARDINAL, */
-1, format, type)) *hints_p = ag_Xmalloc (sizeof (MotifWmHints));
if (*hints_p == NULL)
{ {
XFree (cardinals); if (results->prop)
{
XFree (results->prop);
results->prop = NULL;
}
return FALSE; return FALSE;
} }
real_size = results->n_items * sizeof (gulong);
max_size = MAX_ITEMS * sizeof (gulong);
memcpy (*hints_p, results->prop, MIN (real_size, max_size));
*cardinals_p = cardinals; if (results->prop)
*n_cardinals_p = n_cardinals; {
XFree (results->prop);
results->prop = NULL;
}
return TRUE; return TRUE;
} }
@ -161,52 +247,28 @@ meta_prop_get_motif_hints (MetaDisplay *display,
Atom xatom, Atom xatom,
MotifWmHints **hints_p) MotifWmHints **hints_p)
{ {
Atom type; GetPropertyResults results;
int format;
gulong bytes_after;
MotifWmHints *hints;
gulong n_items;
int real_size, max_size;
#define MAX_ITEMS sizeof (MotifWmHints)/sizeof (gulong)
*hints_p = NULL; *hints_p = NULL;
hints = NULL; if (!get_property (display, xwindow, xatom, AnyPropertyType,
n_items = 0; &results))
meta_error_trap_push_with_return (display);
if (XGetWindowProperty (display->xdisplay, xwindow, xatom,
0, MAX_ITEMS,
False, AnyPropertyType, &type, &format, &n_items,
&bytes_after, (guchar **)&hints) != Success ||
type == None)
{
meta_error_trap_pop_with_return (display, TRUE);
return FALSE; return FALSE;
return motif_hints_from_results (&results, hints_p);
} }
if (meta_error_trap_pop_with_return (display, TRUE) != Success) static gboolean
return FALSE; latin1_string_from_results (GetPropertyResults *results,
char **str_p)
if (type == None || n_items <= 0)
{ {
meta_verbose ("Motif hints had unexpected type or n_items\n"); *str_p = NULL;
XFree (hints);
if (!validate_or_free_results (results, 8, XA_STRING, FALSE))
return FALSE; return FALSE;
}
g_assert (hints != NULL); *str_p = (char*) results->prop;
results->prop = NULL;
/* The issue here is that some old crufty code will set a smaller
* MotifWmHints than the one we expect, apparently. I'm not sure of
* the history behind it. See bug #89841 for example.
*/
*hints_p = g_new0 (MotifWmHints, 1);
real_size = n_items * sizeof (gulong);
max_size = MAX_ITEMS * sizeof (gulong);
memcpy (*hints_p, hints, MIN (real_size, max_size));
XFree (hints);
return TRUE; return TRUE;
} }
@ -217,36 +279,44 @@ meta_prop_get_latin1_string (MetaDisplay *display,
Atom xatom, Atom xatom,
char **str_p) char **str_p)
{ {
Atom type; GetPropertyResults results;
int format;
gulong bytes_after;
guchar *str;
gulong n_items;
*str_p = NULL; *str_p = NULL;
meta_error_trap_push_with_return (display); if (!get_property (display, xwindow, xatom, XA_STRING,
if (XGetWindowProperty (display->xdisplay, xwindow, xatom, &results))
0, G_MAXLONG, return FALSE;
False, XA_STRING, &type, &format, &n_items,
&bytes_after, (guchar **)&str) != Success || return latin1_string_from_results (&results, str_p);
type == None) }
static gboolean
utf8_string_from_results (GetPropertyResults *results,
char **str_p)
{ {
meta_error_trap_pop_with_return (display, TRUE); *str_p = NULL;
if (!validate_or_free_results (results, 8,
results->display->atom_utf8_string, FALSE))
return FALSE;
if (results->n_items > 0 &&
!g_utf8_validate (results->prop, results->n_items, NULL))
{
char *name;
name = XGetAtomName (results->display->xdisplay, results->xatom);
meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8\n"),
name, results->xwindow);
meta_XFree (name);
XFree (results->prop);
results->prop = NULL;
return FALSE; return FALSE;
} }
if (meta_error_trap_pop_with_return (display, TRUE) != Success) *str_p = (char*) results->prop;
return FALSE; results->prop = NULL;
if (!check_type_and_format (display, xwindow, xatom, 8, XA_STRING,
-1, format, type))
{
XFree (str);
return FALSE;
}
*str_p = str;
return TRUE; return TRUE;
} }
@ -257,67 +327,24 @@ meta_prop_get_utf8_string (MetaDisplay *display,
Atom xatom, Atom xatom,
char **str_p) char **str_p)
{ {
Atom type; GetPropertyResults results;
int format;
gulong bytes_after;
guchar *str;
gulong n_items;
*str_p = NULL; *str_p = NULL;
meta_error_trap_push_with_return (display); if (!get_property (display, xwindow, xatom,
if (XGetWindowProperty (display->xdisplay, xwindow, xatom,
0, G_MAXLONG,
False, display->atom_utf8_string,
&type, &format, &n_items,
&bytes_after, (guchar **)&str) != Success ||
type == None)
{
meta_error_trap_pop_with_return (display, TRUE);
return FALSE;
}
if (meta_error_trap_pop_with_return (display, TRUE) != Success)
return FALSE;
if (!check_type_and_format (display, xwindow, xatom, 8,
display->atom_utf8_string, display->atom_utf8_string,
-1, format, type)) &results))
{
XFree (str);
return FALSE; return FALSE;
return utf8_string_from_results (&results, str_p);
} }
if (!g_utf8_validate (str, n_items, NULL)) /* this one freakishly returns g_malloc memory */
{ static gboolean
char *name; utf8_list_from_results (GetPropertyResults *results,
name = XGetAtomName (display->xdisplay, xatom);
meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8\n"),
name, xwindow);
meta_XFree (name);
XFree (str);
return FALSE;
}
*str_p = str;
return TRUE;
}
gboolean
meta_prop_get_utf8_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
char ***str_p, char ***str_p,
int *n_str_p) int *n_str_p)
{ {
Atom type;
int format;
gulong bytes_after;
guchar *val;
gulong n_items;
int i; int i;
int n_strings; int n_strings;
char **retval; char **retval;
@ -326,48 +353,29 @@ meta_prop_get_utf8_list (MetaDisplay *display,
*str_p = NULL; *str_p = NULL;
*n_str_p = 0; *n_str_p = 0;
meta_error_trap_push_with_return (display); if (!validate_or_free_results (results, 8,
if (XGetWindowProperty (display->xdisplay, xwindow, xatom, results->display->atom_utf8_string, FALSE))
0, G_MAXLONG,
False, display->atom_utf8_string,
&type, &format, &n_items,
&bytes_after, (guchar **)&val) != Success ||
type == None)
{
meta_error_trap_pop_with_return (display, TRUE);
return FALSE; return FALSE;
}
if (meta_error_trap_pop_with_return (display, TRUE) != Success)
return FALSE;
if (!check_type_and_format (display, xwindow, xatom, 8,
display->atom_utf8_string,
-1, format, type))
{
XFree (val);
return FALSE;
}
/* I'm not sure this is right, but I'm guessing the /* I'm not sure this is right, but I'm guessing the
* property is nul-separated * property is nul-separated
*/ */
i = 0; i = 0;
n_strings = 1; n_strings = 1;
while (i < (int) n_items) while (i < (int) results->n_items)
{ {
if (val[i] == '\0') if (results->prop[i] == '\0')
++n_strings; ++n_strings;
++i; ++i;
} }
/* we're guaranteed that val has a nul on the end /* we're guaranteed that results->prop has a nul on the end
* by XGetWindowProperty * by XGetWindowProperty
*/ */
retval = g_new0 (char*, n_strings + 1); retval = g_new0 (char*, n_strings + 1);
p = val; p = results->prop;
i = 0; i = 0;
while (i < n_strings) while (i < n_strings)
{ {
@ -375,13 +383,14 @@ meta_prop_get_utf8_list (MetaDisplay *display,
{ {
char *name; char *name;
meta_error_trap_push (display); meta_error_trap_push (results->display);
name = XGetAtomName (display->xdisplay, xatom); name = XGetAtomName (results->display->xdisplay, results->xatom);
meta_error_trap_pop (display, TRUE); meta_error_trap_pop (results->display, TRUE);
meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n"), meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n"),
name, xwindow, i); name, results->xwindow, i);
meta_XFree (name); meta_XFree (name);
meta_XFree (val); meta_XFree (results->prop);
results->prop = NULL;
g_strfreev (retval); g_strfreev (retval);
return FALSE; return FALSE;
@ -396,7 +405,42 @@ meta_prop_get_utf8_list (MetaDisplay *display,
*str_p = retval; *str_p = retval;
*n_str_p = i; *n_str_p = i;
meta_XFree (val); meta_XFree (results->prop);
results->prop = NULL;
return TRUE;
}
/* returns g_malloc not Xmalloc memory */
gboolean
meta_prop_get_utf8_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
char ***str_p,
int *n_str_p)
{
GetPropertyResults results;
*str_p = NULL;
if (!get_property (display, xwindow, xatom,
display->atom_utf8_string,
&results))
return FALSE;
return utf8_list_from_results (&results, str_p, n_str_p);
}
static gboolean
window_from_results (GetPropertyResults *results,
Window *window_p)
{
if (!validate_or_free_results (results, 32, XA_WINDOW, TRUE))
return FALSE;
*window_p = *(Window*) results->prop;
XFree (results->prop);
results->prop = NULL;
return TRUE; return TRUE;
} }
@ -407,40 +451,15 @@ meta_prop_get_window (MetaDisplay *display,
Atom xatom, Atom xatom,
Window *window_p) Window *window_p)
{ {
Atom type; GetPropertyResults results;
int format;
gulong bytes_after;
Window *window;
gulong n_items;
*window_p = None; *window_p = None;
meta_error_trap_push_with_return (display); if (!get_property (display, xwindow, xatom, XA_WINDOW,
if (XGetWindowProperty (display->xdisplay, xwindow, xatom, &results))
0, G_MAXLONG,
False, XA_WINDOW, &type, &format, &n_items,
&bytes_after, (guchar **)&window) != Success ||
type == None)
{
meta_error_trap_pop_with_return (display, TRUE);
return FALSE;
}
if (meta_error_trap_pop_with_return (display, TRUE) != Success)
return FALSE; return FALSE;
if (!check_type_and_format (display, xwindow, xatom, 32, XA_WINDOW, return window_from_results (&results, window_p);
-1, format, type))
{
XFree (window);
return FALSE;
}
*window_p = *window;
XFree (window);
return TRUE;
} }
gboolean gboolean
@ -454,6 +473,21 @@ meta_prop_get_cardinal (MetaDisplay *display,
XA_CARDINAL, cardinal_p); XA_CARDINAL, cardinal_p);
} }
static gboolean
cardinal_with_atom_type_from_results (GetPropertyResults *results,
Atom prop_type,
gulong *cardinal_p)
{
if (!validate_or_free_results (results, 32, prop_type, TRUE))
return FALSE;
*cardinal_p = *(gulong*) results->prop;
XFree (results->prop);
results->prop = NULL;
return TRUE;
}
gboolean gboolean
meta_prop_get_cardinal_with_atom_type (MetaDisplay *display, meta_prop_get_cardinal_with_atom_type (MetaDisplay *display,
Window xwindow, Window xwindow,
@ -461,39 +495,189 @@ meta_prop_get_cardinal_with_atom_type (MetaDisplay *display,
Atom prop_type, Atom prop_type,
gulong *cardinal_p) gulong *cardinal_p)
{ {
Atom type; GetPropertyResults results;
int format;
gulong bytes_after;
gulong *cardinal;
gulong n_items;
*cardinal_p = 0; *cardinal_p = 0;
meta_error_trap_push_with_return (display); if (!get_property (display, xwindow, xatom, prop_type,
if (XGetWindowProperty (display->xdisplay, xwindow, xatom, &results))
0, G_MAXLONG, return FALSE;
False, prop_type, &type, &format, &n_items,
&bytes_after, (guchar **)&cardinal) != Success || return cardinal_with_atom_type_from_results (&results, prop_type, cardinal_p);
type == None) }
static AgGetPropertyTask*
get_task (MetaDisplay *display,
Window xwindow,
Atom xatom,
Atom req_type)
{ {
meta_error_trap_pop_with_return (display, TRUE); return ag_task_create (display->xdisplay,
return FALSE; xwindow,
xatom, 0, G_MAXLONG,
False, req_type);
} }
if (meta_error_trap_pop_with_return (display, TRUE) != Success) void
return FALSE; meta_prop_get_values (MetaDisplay *display,
Window xwindow,
if (!check_type_and_format (display, xwindow, xatom, 32, prop_type, MetaPropValue *values,
-1, format, type)) int n_values)
{ {
XFree (cardinal); int i;
return FALSE; AgGetPropertyTask **tasks;
meta_verbose ("Requesting %d properties of 0x%lx at once\n",
n_values, xwindow);
if (n_values == 0)
return;
tasks = g_new0 (AgGetPropertyTask*, n_values);
/* Start up tasks */
i = 0;
while (i < n_values)
{
if (values[i].required_type == None)
{
switch (values[i].type)
{
case META_PROP_VALUE_INVALID:
meta_bug ("META_PROP_VALUE_INVALID requested in %s\n", __FUNCTION__);
break;
case META_PROP_VALUE_UTF8_LIST:
case META_PROP_VALUE_UTF8:
values[i].required_type = display->atom_utf8_string;
break;
case META_PROP_VALUE_STRING:
values[i].required_type = XA_STRING;
break;
case META_PROP_VALUE_MOTIF_HINTS:
values[i].required_type = AnyPropertyType;
break;
case META_PROP_VALUE_CARDINAL_LIST:
case META_PROP_VALUE_CARDINAL:
values[i].required_type = XA_CARDINAL;
break;
case META_PROP_VALUE_WINDOW:
values[i].required_type = XA_WINDOW;
break;
case META_PROP_VALUE_ATOM_LIST:
values[i].required_type = XA_ATOM;
break;
}
} }
*cardinal_p = *cardinal; tasks[i] = get_task (display, xwindow,
values[i].atom, values[i].required_type);
XFree (cardinal); ++i;
}
return TRUE;
/* Get replies for all our tasks */
XSync (display->xdisplay, False);
/* Collect results, should arrive in order requested */
i = 0;
while (i < n_values)
{
AgGetPropertyTask *task;
GetPropertyResults results;
if (tasks[i] == NULL)
{
/* task creation failed for this property
* (doesn't actually happen I guess)
*/
values[i].type = META_PROP_VALUE_INVALID;
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;
results.prop = NULL;
results.n_items = 0;
results.type = None;
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,
(guchar **)&results.prop) != Success ||
results.type == None)
{
values[i].type = META_PROP_VALUE_INVALID;
if (results.prop)
{
XFree (results.prop);
results.prop = NULL;
}
goto next;
}
switch (values[i].type)
{
case META_PROP_VALUE_INVALID:
g_assert_not_reached ();
break;
case META_PROP_VALUE_UTF8_LIST:
if (!utf8_list_from_results (&results,
&values[i].v.string_list.strings,
&values[i].v.string_list.n_strings))
values[i].type = META_PROP_VALUE_INVALID;
break;
case META_PROP_VALUE_UTF8:
if (!utf8_string_from_results (&results,
&values[i].v.str))
values[i].type = META_PROP_VALUE_INVALID;
break;
case META_PROP_VALUE_STRING:
if (!latin1_string_from_results (&results,
&values[i].v.str))
values[i].type = META_PROP_VALUE_INVALID;
break;
case META_PROP_VALUE_MOTIF_HINTS:
if (!motif_hints_from_results (&results,
&values[i].v.motif_hints))
values[i].type = META_PROP_VALUE_INVALID;
break;
case META_PROP_VALUE_CARDINAL_LIST:
if (!cardinal_list_from_results (&results,
&values[i].v.cardinal_list.cardinals,
&values[i].v.cardinal_list.n_cardinals))
values[i].type = META_PROP_VALUE_INVALID;
break;
case META_PROP_VALUE_CARDINAL:
if (!cardinal_with_atom_type_from_results (&results,
values[i].required_type,
&values[i].v.cardinal))
values[i].type = META_PROP_VALUE_INVALID;
break;
case META_PROP_VALUE_WINDOW:
if (!window_from_results (&results,
&values[i].v.xwindow))
values[i].type = META_PROP_VALUE_INVALID;
break;
case META_PROP_VALUE_ATOM_LIST:
if (!atom_list_from_results (&results,
&values[i].v.atom_list.atoms,
&values[i].v.atom_list.n_atoms))
values[i].type = META_PROP_VALUE_INVALID;
break;
}
next:
++i;
}
g_free (tasks);
} }

View File

@ -108,6 +108,65 @@ gboolean meta_prop_get_cardinal_with_atom_type (MetaDisplay *display,
Atom prop_type, Atom prop_type,
gulong *cardinal_p); gulong *cardinal_p);
typedef enum
{
META_PROP_VALUE_INVALID,
META_PROP_VALUE_UTF8,
META_PROP_VALUE_STRING,
META_PROP_VALUE_MOTIF_HINTS,
META_PROP_VALUE_CARDINAL,
META_PROP_VALUE_WINDOW,
META_PROP_VALUE_CARDINAL_LIST,
META_PROP_VALUE_UTF8_LIST,
META_PROP_VALUE_ATOM_LIST
} MetaPropValueType;
/* used to request/return/store property values */
typedef struct
{
MetaPropValueType type;
Atom atom;
Atom required_type; /* autofilled if None */
union
{
char *str;
MotifWmHints *motif_hints;
Window xwindow;
gulong cardinal;
struct
{
gulong *cardinals;
int n_cardinals;
} cardinal_list;
struct
{
char **strings;
int n_strings;
} string_list;
struct
{
Atom *atoms;
int n_atoms;
} atom_list;
} v;
} MetaPropValue;
/* Each value has type and atom initialized. If there's an error,
* or property is unset, type comes back as INVALID;
* else type comes back as it originated, and the data
* is filled in.
*/
void meta_prop_get_values (MetaDisplay *display,
Window xwindow,
MetaPropValue *values,
int n_values);
#endif #endif