Commit 7a2017dd authored by Alexandre Julliard's avatar Alexandre Julliard

Store window properties in the server. Moved property.c to dlls/user.

parent d8a8c113
......@@ -23,6 +23,7 @@ C_SRCS = \
mouse.c \
msg16.c \
network.c \
property.c \
resource.c \
text.c \
thunk.c \
......
/*
* Window properties
*
* Copyright 1995, 1996, 2001 Alexandre Julliard
*/
#include <string.h>
#include "windef.h"
#include "wingdi.h"
#include "wine/winuser16.h"
#include "wine/server.h"
#include "heap.h"
/* size of buffer needed to store an atom string */
#define ATOM_BUFFER_SIZE 256
/***********************************************************************
* get_properties
*
* Retrieve the list of properties of a given window.
* Returned buffer must be freed by caller.
*/
static property_data_t *get_properties( HWND hwnd, int *count )
{
property_data_t *ret = NULL;
SERVER_START_VAR_REQ( get_window_properties, REQUEST_MAX_VAR_SIZE )
{
req->window = hwnd;
if (!SERVER_CALL())
{
size_t size = server_data_size(req);
if (size)
{
property_data_t *data = server_data_ptr(req);
if ((ret = HeapAlloc( GetProcessHeap(), 0, size ))) memcpy( ret, data, size );
*count = size / sizeof(*data);
}
}
}
SERVER_END_VAR_REQ;
return ret;
}
/***********************************************************************
* EnumPropsA_relay
*
* relay to call the EnumProps callback function from EnumPropsEx
*/
static BOOL CALLBACK EnumPropsA_relay( HWND hwnd, LPCSTR str, HANDLE handle, ULONG_PTR lparam )
{
PROPENUMPROCA func = (PROPENUMPROCA)lparam;
return func( hwnd, str, handle );
}
/***********************************************************************
* EnumPropsW_relay
*
* relay to call the EnumProps callback function from EnumPropsEx
*/
static BOOL CALLBACK EnumPropsW_relay( HWND hwnd, LPCWSTR str, HANDLE handle, ULONG_PTR lparam )
{
PROPENUMPROCW func = (PROPENUMPROCW)lparam;
return func( hwnd, str, handle );
}
/***********************************************************************
* EnumPropsA (USER32.@)
*/
INT WINAPI EnumPropsA( HWND hwnd, PROPENUMPROCA func )
{
return EnumPropsExA( hwnd, EnumPropsA_relay, (LPARAM)func );
}
/***********************************************************************
* EnumPropsW (USER32.@)
*/
INT WINAPI EnumPropsW( HWND hwnd, PROPENUMPROCW func )
{
return EnumPropsExW( hwnd, EnumPropsW_relay, (LPARAM)func );
}
/***********************************************************************
* GetPropA (USER32.@)
*/
HANDLE WINAPI GetPropA( HWND hwnd, LPCSTR str )
{
ATOM atom;
HANDLE ret = 0;
if (!HIWORD(str)) atom = LOWORD(str);
else if (!(atom = GlobalFindAtomA( str ))) return 0;
SERVER_START_REQ( get_window_property )
{
req->window = hwnd;
req->atom = atom;
if (!SERVER_CALL_ERR()) ret = req->handle;
}
SERVER_END_REQ;
return ret;
}
/***********************************************************************
* GetPropW (USER32.@)
*/
HANDLE WINAPI GetPropW( HWND hwnd, LPCWSTR str )
{
ATOM atom;
HANDLE ret = 0;
if (!HIWORD(str)) atom = LOWORD(str);
else if (!(atom = GlobalFindAtomW( str ))) return 0;
SERVER_START_REQ( get_window_property )
{
req->window = hwnd;
req->atom = atom;
if (!SERVER_CALL_ERR()) ret = req->handle;
}
SERVER_END_REQ;
return ret;
}
/***********************************************************************
* SetPropA (USER32.@)
*/
BOOL WINAPI SetPropA( HWND hwnd, LPCSTR str, HANDLE handle )
{
ATOM atom;
BOOL ret;
if (!HIWORD(str)) atom = LOWORD(str);
else if (!(atom = GlobalAddAtomA( str ))) return FALSE;
SERVER_START_REQ( set_window_property )
{
req->window = hwnd;
req->atom = atom;
req->string = (HIWORD(str) != 0);
req->handle = handle;
ret = !SERVER_CALL_ERR();
}
SERVER_END_REQ;
if (HIWORD(str)) GlobalDeleteAtom( atom );
return ret;
}
/***********************************************************************
* SetPropW (USER32.@)
*/
BOOL WINAPI SetPropW( HWND hwnd, LPCWSTR str, HANDLE handle )
{
ATOM atom;
BOOL ret;
if (!HIWORD(str)) atom = LOWORD(str);
else if (!(atom = GlobalAddAtomW( str ))) return FALSE;
SERVER_START_REQ( set_window_property )
{
req->window = hwnd;
req->atom = atom;
req->string = (HIWORD(str) != 0);
req->handle = handle;
ret = !SERVER_CALL_ERR();
}
SERVER_END_REQ;
if (HIWORD(str)) GlobalDeleteAtom( atom );
return ret;
}
/***********************************************************************
* RemovePropA (USER32.@)
*/
HANDLE WINAPI RemovePropA( HWND hwnd, LPCSTR str )
{
ATOM atom;
HANDLE ret = 0;
if (!HIWORD(str)) return RemovePropW( hwnd, MAKEINTATOMW(LOWORD(str)) );
if ((atom = GlobalAddAtomA( str )))
{
ret = RemovePropW( hwnd, MAKEINTATOMW(atom) );
GlobalDeleteAtom( atom );
}
return ret;
}
/***********************************************************************
* RemovePropW (USER32.@)
*/
HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str )
{
ATOM atom;
HANDLE ret = 0;
if (!HIWORD(str)) atom = LOWORD(str);
else if (!(atom = GlobalAddAtomW( str ))) return 0;
SERVER_START_REQ( remove_window_property )
{
req->window = hwnd;
req->atom = atom;
if (!SERVER_CALL_ERR()) ret = req->handle;
}
SERVER_END_REQ;
if (HIWORD(str)) GlobalDeleteAtom( atom );
return ret;
}
/***********************************************************************
* EnumPropsExA (USER32.@)
*/
INT WINAPI EnumPropsExA(HWND hwnd, PROPENUMPROCEXA func, LPARAM lParam)
{
int ret = -1, i, count;
property_data_t *list = get_properties( hwnd, &count );
if (list)
{
for (i = 0; i < count; i++)
{
char string[ATOM_BUFFER_SIZE];
if (!GlobalGetAtomNameA( list[i].atom, string, ATOM_BUFFER_SIZE )) continue;
if (!(ret = func( hwnd, string, list[i].handle, lParam ))) break;
}
HeapFree( GetProcessHeap(), 0, list );
}
return ret;
}
/***********************************************************************
* EnumPropsExW (USER32.@)
*/
INT WINAPI EnumPropsExW(HWND hwnd, PROPENUMPROCEXW func, LPARAM lParam)
{
int ret = -1, i, count;
property_data_t *list = get_properties( hwnd, &count );
if (list)
{
for (i = 0; i < count; i++)
{
WCHAR string[ATOM_BUFFER_SIZE];
if (!GlobalGetAtomNameW( list[i].atom, string, ATOM_BUFFER_SIZE )) continue;
if (!(ret = func( hwnd, string, list[i].handle, lParam ))) break;
}
HeapFree( GetProcessHeap(), 0, list );
}
return ret;
}
/***********************************************************************
* EnumProps (USER.27)
*/
INT16 WINAPI EnumProps16( HWND16 hwnd, PROPENUMPROC16 func )
{
int ret = -1, i, count;
property_data_t *list = get_properties( hwnd, &count );
if (list)
{
char *string = SEGPTR_ALLOC( ATOM_BUFFER_SIZE );
for (i = 0; i < count; i++)
{
if (list[i].string) /* it was a string originally */
{
if (!GlobalGetAtomNameA( list[i].atom, string, ATOM_BUFFER_SIZE )) continue;
ret = func( hwnd, SEGPTR_GET(string), list[i].handle );
}
else
ret = func( hwnd, list[i].atom, list[i].handle );
if (!ret) break;
}
SEGPTR_FREE( string );
HeapFree( GetProcessHeap(), 0, list );
}
return ret;
}
......@@ -35,7 +35,6 @@ typedef struct tagWND
LPWSTR text; /* Window text */
void *pVScroll; /* Vertical scroll-bar info */
void *pHScroll; /* Horizontal scroll-bar info */
void *pProp; /* Pointer to properties list */
struct tagDCE *dce; /* Window DCE (if CS_OWNDC or CS_CLASSDC) */
HGLOBAL16 hmemTaskQ; /* Task queue global memory handle */
HRGN hrgnUpdate; /* Update region */
......@@ -122,8 +121,6 @@ extern void CARET_GetRect(LPRECT lprc); /* windows/caret.c */
extern BOOL16 DRAG_QueryUpdate( HWND, SEGPTR, BOOL );
extern HBRUSH DEFWND_ControlColor( HDC hDC, UINT ctlType ); /* windows/defwnd.c */
extern void PROPERTY_RemoveWindowProps( HWND hwnd ); /* windows/property.c */
/* Classes functions */
struct tagCLASS; /* opaque structure */
struct builtin_class_descr;
......
......@@ -132,6 +132,14 @@ struct wake_up_reply
};
typedef struct
{
atom_t atom;
short string;
handle_t handle;
} property_data_t;
......@@ -1644,6 +1652,46 @@ struct get_window_tree_request
};
struct set_window_property_request
{
struct request_header __header;
user_handle_t window;
atom_t atom;
int string;
handle_t handle;
};
struct remove_window_property_request
{
struct request_header __header;
user_handle_t window;
atom_t atom;
handle_t handle;
};
struct get_window_property_request
{
struct request_header __header;
user_handle_t window;
atom_t atom;
handle_t handle;
};
struct get_window_properties_request
{
struct request_header __header;
user_handle_t window;
/* VARARG(props,properties); */
};
enum request
{
REQ_new_process,
......@@ -1775,6 +1823,10 @@ enum request
REQ_get_window_parents,
REQ_get_window_children,
REQ_get_window_tree,
REQ_set_window_property,
REQ_remove_window_property,
REQ_get_window_property,
REQ_get_window_properties,
REQ_NB_REQUESTS
};
......@@ -1911,8 +1963,12 @@ union generic_request
struct get_window_parents_request get_window_parents;
struct get_window_children_request get_window_children;
struct get_window_tree_request get_window_tree;
struct set_window_property_request set_window_property;
struct remove_window_property_request remove_window_property;
struct get_window_property_request get_window_property;
struct get_window_properties_request get_window_properties;
};
#define SERVER_PROTOCOL_VERSION 58
#define SERVER_PROTOCOL_VERSION 59
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
......@@ -133,6 +133,14 @@ struct wake_up_reply
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 @@ enum message_type
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
......@@ -194,6 +194,10 @@ DECL_HANDLER(get_window_info);
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 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] =
(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 */
......
......@@ -271,6 +271,23 @@ static size_t dump_varargs_input_records( const void *req )
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 @@ static void dump_get_window_tree_reply( const struct get_window_tree_request *re
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 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = {
(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 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = {
(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 @@ static const char * const req_names[REQ_NB_REQUESTS] = {
"get_window_parents",
"get_window_children",
"get_window_tree",
"set_window_property",
"remove_window_property",
"get_window_property",
"get_window_properties",
};
/* ### make_requests end ### */
......
......@@ -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
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 @@ static void link_window( struct window *win, struct window *parent, struct windo
}
}
/* 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 @@ static void destroy_window( struct window *win )
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 @@ static struct window *create_window( struct window *parent, struct window *owner
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 @@ DECL_HANDLER(get_window_tree)
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) );
}
......@@ -26,7 +26,6 @@ C_SRCS = \
multimon.c \
nonclient.c \
painting.c \
property.c \
queue.c \
rect.c \
scroll.c \
......
......@@ -549,7 +549,6 @@ static void WIN_DestroyWindow( HWND hwnd )
/* free resources associated with the window */
TIMER_RemoveWindowTimers( hwnd );
PROPERTY_RemoveWindowProps( hwnd );
if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return;
wndPtr->hmemTaskQ = 0;
......@@ -646,7 +645,6 @@ BOOL WIN_CreateDesktopWindow(void)
pWndDesktop->dce = NULL;
pWndDesktop->pVScroll = NULL;
pWndDesktop->pHScroll = NULL;
pWndDesktop->pProp = NULL;
pWndDesktop->wIDmenu = 0;
pWndDesktop->helpContext = 0;
pWndDesktop->flags = 0;
......@@ -859,7 +857,6 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
wndPtr->flags = (type == WIN_PROC_16) ? 0 : WIN_ISWIN32;
wndPtr->pVScroll = NULL;
wndPtr->pHScroll = NULL;
wndPtr->pProp = NULL;
wndPtr->userdata = 0;
wndPtr->hSysMenu = (wndPtr->dwStyle & WS_SYSMENU)
? MENU_GetSysMenu( hwnd, 0 ) : 0;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment