Store window properties in the server. Moved property.c to dlls/user.
diff --git a/server/protocol.def b/server/protocol.def
index fa0b81e..95bc13a 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -133,6 +133,14 @@
int signaled; /* wait result */
};
+/* structure returned in the list of window properties */
+typedef struct
+{
+ atom_t atom; /* property atom */
+ short string; /* was atom a string originally? */
+ handle_t handle; /* handle stored in property */
+} property_data_t;
+
/****************************************************************/
/* Request declarations */
@@ -1469,3 +1477,38 @@
user_handle_t first_child; /* first child */
user_handle_t last_child; /* last child */
@END
+
+
+/* Set a window property */
+@REQ(set_window_property)
+ user_handle_t window; /* handle to the window */
+ atom_t atom; /* property atom (high-word set if it was a string) */
+ int string; /* was atom a string originally? */
+ handle_t handle; /* handle to store */
+@END
+
+
+/* Remove a window property */
+@REQ(remove_window_property)
+ user_handle_t window; /* handle to the window */
+ atom_t atom; /* property atom */
+@REPLY
+ handle_t handle; /* handle stored in property */
+@END
+
+
+/* Get a window property */
+@REQ(get_window_property)
+ user_handle_t window; /* handle to the window */
+ atom_t atom; /* property atom */
+@REPLY
+ handle_t handle; /* handle stored in property */
+@END
+
+
+/* Get the list of properties of a window */
+@REQ(get_window_properties)
+ user_handle_t window; /* handle to the window */
+@REPLY
+ VARARG(props,properties); /* list of properties */
+@END
diff --git a/server/request.h b/server/request.h
index 1269e17..8939854 100644
--- a/server/request.h
+++ b/server/request.h
@@ -194,6 +194,10 @@
DECL_HANDLER(get_window_parents);
DECL_HANDLER(get_window_children);
DECL_HANDLER(get_window_tree);
+DECL_HANDLER(set_window_property);
+DECL_HANDLER(remove_window_property);
+DECL_HANDLER(get_window_property);
+DECL_HANDLER(get_window_properties);
#ifdef WANT_REQUEST_HANDLERS
@@ -329,6 +333,10 @@
(req_handler)req_get_window_parents,
(req_handler)req_get_window_children,
(req_handler)req_get_window_tree,
+ (req_handler)req_set_window_property,
+ (req_handler)req_remove_window_property,
+ (req_handler)req_get_window_property,
+ (req_handler)req_get_window_properties,
};
#endif /* WANT_REQUEST_HANDLERS */
diff --git a/server/trace.c b/server/trace.c
index 094ff25..bd4de67 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -271,6 +271,23 @@
return get_size(req);
}
+static size_t dump_varargs_properties( const void *req )
+{
+ const property_data_t *prop = get_data(req);
+ size_t len = get_size(req) / sizeof(*prop);
+
+ fputc( '{', stderr );
+ while (len > 0)
+ {
+ fprintf( stderr, "{atom=%04x,str=%d,handle=%08x}",
+ prop->atom, prop->string, prop->handle );
+ prop++;
+ if (--len) fputc( ',', stderr );
+ }
+ fputc( '}', stderr );
+ return get_size(req);
+}
+
typedef void (*dump_func)( const void *req );
/* Everything below this line is generated automatically by tools/make_requests */
@@ -1743,6 +1760,47 @@
fprintf( stderr, " last_child=%08x", req->last_child );
}
+static void dump_set_window_property_request( const struct set_window_property_request *req )
+{
+ fprintf( stderr, " window=%08x,", req->window );
+ fprintf( stderr, " atom=%04x,", req->atom );
+ fprintf( stderr, " string=%d,", req->string );
+ fprintf( stderr, " handle=%d", req->handle );
+}
+
+static void dump_remove_window_property_request( const struct remove_window_property_request *req )
+{
+ fprintf( stderr, " window=%08x,", req->window );
+ fprintf( stderr, " atom=%04x", req->atom );
+}
+
+static void dump_remove_window_property_reply( const struct remove_window_property_request *req )
+{
+ fprintf( stderr, " handle=%d", req->handle );
+}
+
+static void dump_get_window_property_request( const struct get_window_property_request *req )
+{
+ fprintf( stderr, " window=%08x,", req->window );
+ fprintf( stderr, " atom=%04x", req->atom );
+}
+
+static void dump_get_window_property_reply( const struct get_window_property_request *req )
+{
+ fprintf( stderr, " handle=%d", req->handle );
+}
+
+static void dump_get_window_properties_request( const struct get_window_properties_request *req )
+{
+ fprintf( stderr, " window=%08x", req->window );
+}
+
+static void dump_get_window_properties_reply( const struct get_window_properties_request *req )
+{
+ fprintf( stderr, " props=" );
+ cur_pos += dump_varargs_properties( req );
+}
+
static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(dump_func)dump_new_process_request,
(dump_func)dump_get_new_process_info_request,
@@ -1873,6 +1931,10 @@
(dump_func)dump_get_window_parents_request,
(dump_func)dump_get_window_children_request,
(dump_func)dump_get_window_tree_request,
+ (dump_func)dump_set_window_property_request,
+ (dump_func)dump_remove_window_property_request,
+ (dump_func)dump_get_window_property_request,
+ (dump_func)dump_get_window_properties_request,
};
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
@@ -2005,6 +2067,10 @@
(dump_func)dump_get_window_parents_reply,
(dump_func)dump_get_window_children_reply,
(dump_func)dump_get_window_tree_reply,
+ (dump_func)0,
+ (dump_func)dump_remove_window_property_reply,
+ (dump_func)dump_get_window_property_reply,
+ (dump_func)dump_get_window_properties_reply,
};
static const char * const req_names[REQ_NB_REQUESTS] = {
@@ -2137,6 +2203,10 @@
"get_window_parents",
"get_window_children",
"get_window_tree",
+ "set_window_property",
+ "remove_window_property",
+ "get_window_property",
+ "get_window_properties",
};
/* ### make_requests end ### */
diff --git a/server/window.c b/server/window.c
index c57aadf..ff9ba82 100644
--- a/server/window.c
+++ b/server/window.c
@@ -12,6 +12,22 @@
#include "process.h"
#include "user.h"
+/* a window property */
+struct property
+{
+ unsigned short type; /* property type (see below) */
+ atom_t atom; /* property atom */
+ handle_t handle; /* property handle (user-defined storage) */
+};
+
+enum property_type
+{
+ PROP_TYPE_FREE, /* free entry */
+ PROP_TYPE_STRING, /* atom that was originally a string */
+ PROP_TYPE_ATOM /* plain atom */
+};
+
+
struct window
{
struct window *parent; /* parent window */
@@ -23,7 +39,10 @@
struct window *prev; /* prev window in Z-order */
user_handle_t handle; /* full handle for this window */
struct thread *thread; /* thread owning the window */
- unsigned int atom; /* class atom */
+ atom_t atom; /* class atom */
+ int prop_inuse; /* number of in-use window properties */
+ int prop_alloc; /* number of allocated window properties */
+ struct property *properties; /* window properties array */
};
static struct window *top_window; /* top-level (desktop) window */
@@ -83,6 +102,118 @@
}
}
+/* set a window property */
+static void set_property( struct window *win, atom_t atom, handle_t handle,
+ enum property_type type )
+{
+ int i, free = -1;
+ struct property *new_props;
+
+ /* check if it exists already */
+ for (i = 0; i < win->prop_inuse; i++)
+ {
+ if (win->properties[i].type == PROP_TYPE_FREE)
+ {
+ free = i;
+ continue;
+ }
+ if (win->properties[i].atom == atom)
+ {
+ win->properties[i].type = type;
+ win->properties[i].handle = handle;
+ return;
+ }
+ }
+
+ /* need to add an entry */
+ if (!grab_global_atom( atom )) return;
+ if (free == -1)
+ {
+ /* no free entry */
+ if (win->prop_inuse >= win->prop_alloc)
+ {
+ /* need to grow the array */
+ if (!(new_props = realloc( win->properties,
+ sizeof(*new_props) * (win->prop_alloc + 16) )))
+ {
+ set_error( STATUS_NO_MEMORY );
+ release_global_atom( atom );
+ return;
+ }
+ win->prop_alloc += 16;
+ win->properties = new_props;
+ }
+ free = win->prop_inuse++;
+ }
+ win->properties[free].atom = atom;
+ win->properties[free].type = type;
+ win->properties[free].handle = handle;
+}
+
+/* remove a window property */
+static handle_t remove_property( struct window *win, atom_t atom )
+{
+ int i;
+
+ for (i = 0; i < win->prop_inuse; i++)
+ {
+ if (win->properties[i].type == PROP_TYPE_FREE) continue;
+ if (win->properties[i].atom == atom)
+ {
+ release_global_atom( atom );
+ win->properties[i].type = PROP_TYPE_FREE;
+ return win->properties[i].handle;
+ }
+ }
+ /* FIXME: last error? */
+ return 0;
+}
+
+/* find a window property */
+static handle_t get_property( struct window *win, atom_t atom )
+{
+ int i;
+
+ for (i = 0; i < win->prop_inuse; i++)
+ {
+ if (win->properties[i].type == PROP_TYPE_FREE) continue;
+ if (win->properties[i].atom == atom) return win->properties[i].handle;
+ }
+ /* FIXME: last error? */
+ return 0;
+}
+
+/* destroy all properties of a window */
+inline static void destroy_properties( struct window *win )
+{
+ int i;
+
+ if (!win->properties) return;
+ for (i = 0; i < win->prop_inuse; i++)
+ {
+ if (win->properties[i].type == PROP_TYPE_FREE) continue;
+ release_global_atom( win->properties[i].atom );
+ }
+ free( win->properties );
+}
+
+/* enum all properties into the data array */
+static int enum_properties( struct window *win, property_data_t *data, int max )
+{
+ int i, count;
+
+ for (i = count = 0; i < win->prop_inuse && count < max; i++)
+ {
+ if (win->properties[i].type == PROP_TYPE_FREE) continue;
+ data->atom = win->properties[i].atom;
+ data->string = (win->properties[i].type == PROP_TYPE_STRING);
+ data->handle = win->properties[i].handle;
+ data++;
+ count++;
+ }
+ return count;
+}
+
/* destroy a window */
static void destroy_window( struct window *win )
{
@@ -104,14 +235,14 @@
if (win->thread->queue) queue_cleanup_window( win->thread, win->handle );
free_user_handle( win->handle );
+ destroy_properties( win );
unlink_window( win );
memset( win, 0x55, sizeof(*win) );
free( win );
}
/* create a new window structure (note: the window is not linked in the window tree) */
-static struct window *create_window( struct window *parent, struct window *owner,
- unsigned int atom )
+static struct window *create_window( struct window *parent, struct window *owner, atom_t atom )
{
struct window *win = mem_alloc( sizeof(*win) );
if (!win) return NULL;
@@ -128,6 +259,9 @@
win->first_unlinked = NULL;
win->thread = current;
win->atom = atom;
+ win->prop_inuse = 0;
+ win->prop_alloc = 0;
+ win->properties = NULL;
if (parent) /* put it on parent unlinked list */
{
@@ -340,3 +474,43 @@
req->first_child = win->first_child ? win->first_child->handle : 0;
req->last_child = win->last_child ? win->last_child->handle : 0;
}
+
+
+/* set a window property */
+DECL_HANDLER(set_window_property)
+{
+ struct window *win = get_window( req->window );
+
+ if (win) set_property( win, req->atom, req->handle,
+ req->string ? PROP_TYPE_STRING : PROP_TYPE_ATOM );
+}
+
+
+/* remove a window property */
+DECL_HANDLER(remove_window_property)
+{
+ struct window *win = get_window( req->window );
+ req->handle = 0;
+ if (win) req->handle = remove_property( win, req->atom );
+}
+
+
+/* get a window property */
+DECL_HANDLER(get_window_property)
+{
+ struct window *win = get_window( req->window );
+ req->handle = 0;
+ if (win) req->handle = get_property( win, req->atom );
+}
+
+
+/* get the list of properties of a window */
+DECL_HANDLER(get_window_properties)
+{
+ int count = 0;
+ property_data_t *data = get_req_data(req);
+ struct window *win = get_window( req->window );
+
+ if (win) count = enum_properties( win, data, get_req_data_size(req) / sizeof(*data) );
+ set_req_data_size( req, count * sizeof(*data) );
+}