From a09da0cbbddab2af0801fbf922fd0bc9eea91bd9 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Fri, 21 Sep 2001 21:08:40 +0000 Subject: [PATCH] Added proper support for storing window parents in the server. Added a few requests to query the window hierarchy. --- include/wine/server_protocol.h | 56 +++++-- include/winuser.h | 4 +- server/protocol.def | 44 +++++- server/queue.c | 2 +- server/request.h | 8 +- server/trace.c | 79 ++++++++-- server/user.c | 12 +- server/user.h | 1 + server/window.c | 223 ++++++++++++++++++++------- windows/win.c | 274 ++++++++++++--------------------- 10 files changed, 430 insertions(+), 273 deletions(-) diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index ebf2d3fd583..18ecc74b8e4 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -1563,17 +1563,11 @@ struct get_named_pipe_info_request -struct create_desktop_window_request -{ - struct request_header __header; - user_handle_t handle; -}; - - - struct create_window_request { struct request_header __header; + user_handle_t parent; + user_handle_t owner; user_handle_t handle; }; @@ -1607,6 +1601,42 @@ struct get_window_info_request }; + +struct get_window_parents_request +{ + struct request_header __header; + user_handle_t handle; + int count; + /* VARARG(parents,user_handles); */ +}; + + + +struct get_window_children_request +{ + struct request_header __header; + user_handle_t parent; + int count; + /* VARARG(parents,user_handles); */ +}; + + + +struct get_window_tree_request +{ + struct request_header __header; + user_handle_t handle; + user_handle_t parent; + user_handle_t owner; + user_handle_t next_sibling; + user_handle_t prev_sibling; + user_handle_t first_sibling; + user_handle_t last_sibling; + user_handle_t first_child; + user_handle_t last_child; +}; + + enum request { REQ_new_process, @@ -1732,11 +1762,13 @@ enum request REQ_wait_named_pipe, REQ_disconnect_named_pipe, REQ_get_named_pipe_info, - REQ_create_desktop_window, REQ_create_window, REQ_link_window, REQ_destroy_window, REQ_get_window_info, + REQ_get_window_parents, + REQ_get_window_children, + REQ_get_window_tree, REQ_NB_REQUESTS }; @@ -1867,13 +1899,15 @@ union generic_request struct wait_named_pipe_request wait_named_pipe; struct disconnect_named_pipe_request disconnect_named_pipe; struct get_named_pipe_info_request get_named_pipe_info; - struct create_desktop_window_request create_desktop_window; struct create_window_request create_window; struct link_window_request link_window; struct destroy_window_request destroy_window; struct get_window_info_request get_window_info; + struct get_window_parents_request get_window_parents; + struct get_window_children_request get_window_children; + struct get_window_tree_request get_window_tree; }; -#define SERVER_PROTOCOL_VERSION 52 +#define SERVER_PROTOCOL_VERSION 53 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/include/winuser.h b/include/winuser.h index a8523eb4ca8..d1daa2485c6 100644 --- a/include/winuser.h +++ b/include/winuser.h @@ -3602,8 +3602,8 @@ INT WINAPI GetUpdateRgn(HWND,HRGN,BOOL); BOOL WINAPI GetUserObjectInformationA(HANDLE,INT,LPVOID,DWORD,LPDWORD); BOOL WINAPI GetUserObjectInformationW(HANDLE,INT,LPVOID,DWORD,LPDWORD); #define GetUserObjectInformation WINELIB_NAME_AW(GetUserObjectInformation) -HWND WINAPI GetWindow(HWND,WORD); -HDC WINAPI GetWindowDC(HWND); +HWND WINAPI GetWindow(HWND,UINT); +HDC WINAPI GetWindowDC(HWND); LONG WINAPI GetWindowLongA(HWND,INT); LONG WINAPI GetWindowLongW(HWND,INT); #define GetWindowLong WINELIB_NAME_AW(GetWindowLong) diff --git a/server/protocol.def b/server/protocol.def index c386dd93b0f..a87287c8a12 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -1395,17 +1395,12 @@ enum message_type @END -/* Create the desktop window */ -@REQ(create_desktop_window) -@REPLY - user_handle_t handle; /* handle to the window */ -@END - - /* Create a window */ @REQ(create_window) + user_handle_t parent; /* parent window */ + user_handle_t owner; /* owner window */ @REPLY - user_handle_t handle; /* handle to the window */ + user_handle_t handle; /* created window */ @END @@ -1432,3 +1427,36 @@ enum message_type void* pid; /* process owning the window */ void* tid; /* thread owning the window */ @END + + +/* Get a list of the window parents, up to the root of the tree */ +@REQ(get_window_parents) + user_handle_t handle; /* handle to the window */ +@REPLY + int count; /* total count of parents */ + VARARG(parents,user_handles); /* parent handles */ +@END + + +/* Get a list of the window children */ +@REQ(get_window_children) + user_handle_t parent; /* parent window */ +@REPLY + int count; /* total count of children */ + VARARG(parents,user_handles); /* children handles */ +@END + + +/* Get window tree information from a window handle */ +@REQ(get_window_tree) + user_handle_t handle; /* handle to the window */ +@REPLY + user_handle_t parent; /* parent window */ + user_handle_t owner; /* owner window */ + user_handle_t next_sibling; /* next sibling in Z-order */ + user_handle_t prev_sibling; /* prev sibling in Z-order */ + user_handle_t first_sibling; /* first sibling in Z-order */ + user_handle_t last_sibling; /* last sibling in Z-order */ + user_handle_t first_child; /* first child */ + user_handle_t last_child; /* last child */ +@END diff --git a/server/queue.c b/server/queue.c index 2cab8148307..4e0332b6aa6 100644 --- a/server/queue.c +++ b/server/queue.c @@ -833,7 +833,7 @@ inline static struct message *find_matching_message( const struct message_list * { /* check against the filters */ if (msg->msg == WM_QUIT) break; /* WM_QUIT is never filtered */ - if (win && msg->win && msg->win != win) continue; + if (win && msg->win && msg->win != win && !is_child_window( win, msg->win )) continue; if (msg->msg < first) continue; if (msg->msg > last) continue; break; /* found one */ diff --git a/server/request.h b/server/request.h index 97bc21e57b2..c4530b539f8 100644 --- a/server/request.h +++ b/server/request.h @@ -188,11 +188,13 @@ DECL_HANDLER(connect_named_pipe); DECL_HANDLER(wait_named_pipe); DECL_HANDLER(disconnect_named_pipe); DECL_HANDLER(get_named_pipe_info); -DECL_HANDLER(create_desktop_window); DECL_HANDLER(create_window); DECL_HANDLER(link_window); DECL_HANDLER(destroy_window); DECL_HANDLER(get_window_info); +DECL_HANDLER(get_window_parents); +DECL_HANDLER(get_window_children); +DECL_HANDLER(get_window_tree); #ifdef WANT_REQUEST_HANDLERS @@ -322,11 +324,13 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_wait_named_pipe, (req_handler)req_disconnect_named_pipe, (req_handler)req_get_named_pipe_info, - (req_handler)req_create_desktop_window, (req_handler)req_create_window, (req_handler)req_link_window, (req_handler)req_destroy_window, (req_handler)req_get_window_info, + (req_handler)req_get_window_parents, + (req_handler)req_get_window_children, + (req_handler)req_get_window_tree, }; #endif /* WANT_REQUEST_HANDLERS */ diff --git a/server/trace.c b/server/trace.c index 5dc05bce231..93a4f367977 100644 --- a/server/trace.c +++ b/server/trace.c @@ -119,6 +119,21 @@ static size_t dump_varargs_ptrs( const void *req ) return get_size(req); } +static size_t dump_varargs_user_handles( const void *req ) +{ + const user_handle_t *data = get_data(req); + size_t len = get_size(req) / sizeof(*data); + + fputc( '{', stderr ); + while (len > 0) + { + fprintf( stderr, "%08x", *data++ ); + if (--len) fputc( ',', stderr ); + } + fputc( '}', stderr ); + return get_size(req); +} + static size_t dump_varargs_bytes( const void *req ) { const unsigned char *data = get_data(req); @@ -1652,17 +1667,10 @@ static void dump_get_named_pipe_info_reply( const struct get_named_pipe_info_req fprintf( stderr, " insize=%08x", req->insize ); } -static void dump_create_desktop_window_request( const struct create_desktop_window_request *req ) -{ -} - -static void dump_create_desktop_window_reply( const struct create_desktop_window_request *req ) -{ - fprintf( stderr, " handle=%08x", req->handle ); -} - static void dump_create_window_request( const struct create_window_request *req ) { + fprintf( stderr, " parent=%08x,", req->parent ); + fprintf( stderr, " owner=%08x", req->owner ); } static void dump_create_window_reply( const struct create_window_request *req ) @@ -1694,6 +1702,47 @@ static void dump_get_window_info_reply( const struct get_window_info_request *re fprintf( stderr, " tid=%p", req->tid ); } +static void dump_get_window_parents_request( const struct get_window_parents_request *req ) +{ + fprintf( stderr, " handle=%08x", req->handle ); +} + +static void dump_get_window_parents_reply( const struct get_window_parents_request *req ) +{ + fprintf( stderr, " count=%d,", req->count ); + fprintf( stderr, " parents=" ); + cur_pos += dump_varargs_user_handles( req ); +} + +static void dump_get_window_children_request( const struct get_window_children_request *req ) +{ + fprintf( stderr, " parent=%08x", req->parent ); +} + +static void dump_get_window_children_reply( const struct get_window_children_request *req ) +{ + fprintf( stderr, " count=%d,", req->count ); + fprintf( stderr, " parents=" ); + cur_pos += dump_varargs_user_handles( req ); +} + +static void dump_get_window_tree_request( const struct get_window_tree_request *req ) +{ + fprintf( stderr, " handle=%08x", req->handle ); +} + +static void dump_get_window_tree_reply( const struct get_window_tree_request *req ) +{ + fprintf( stderr, " parent=%08x,", req->parent ); + fprintf( stderr, " owner=%08x,", req->owner ); + fprintf( stderr, " next_sibling=%08x,", req->next_sibling ); + fprintf( stderr, " prev_sibling=%08x,", req->prev_sibling ); + fprintf( stderr, " first_sibling=%08x,", req->first_sibling ); + fprintf( stderr, " last_sibling=%08x,", req->last_sibling ); + fprintf( stderr, " first_child=%08x,", req->first_child ); + fprintf( stderr, " last_child=%08x", req->last_child ); +} + static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_new_process_request, (dump_func)dump_get_new_process_info_request, @@ -1818,11 +1867,13 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_wait_named_pipe_request, (dump_func)dump_disconnect_named_pipe_request, (dump_func)dump_get_named_pipe_info_request, - (dump_func)dump_create_desktop_window_request, (dump_func)dump_create_window_request, (dump_func)dump_link_window_request, (dump_func)dump_destroy_window_request, (dump_func)dump_get_window_info_request, + (dump_func)dump_get_window_parents_request, + (dump_func)dump_get_window_children_request, + (dump_func)dump_get_window_tree_request, }; static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { @@ -1949,11 +2000,13 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { (dump_func)0, (dump_func)0, (dump_func)dump_get_named_pipe_info_reply, - (dump_func)dump_create_desktop_window_reply, (dump_func)dump_create_window_reply, (dump_func)0, (dump_func)0, (dump_func)dump_get_window_info_reply, + (dump_func)dump_get_window_parents_reply, + (dump_func)dump_get_window_children_reply, + (dump_func)dump_get_window_tree_reply, }; static const char * const req_names[REQ_NB_REQUESTS] = { @@ -2080,11 +2133,13 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "wait_named_pipe", "disconnect_named_pipe", "get_named_pipe_info", - "create_desktop_window", "create_window", "link_window", "destroy_window", "get_window_info", + "get_window_parents", + "get_window_children", + "get_window_tree", }; /* ### make_requests end ### */ diff --git a/server/user.c b/server/user.c index 88c7fd71d58..e31fb162320 100644 --- a/server/user.c +++ b/server/user.c @@ -91,11 +91,7 @@ void *get_user_object( user_handle_t handle, enum user_object type ) { struct user_handle *entry; - if (!(entry = handle_to_entry( handle )) || entry->type != type) - { - set_error( STATUS_INVALID_HANDLE ); - return NULL; - } + if (!(entry = handle_to_entry( handle )) || entry->type != type) return NULL; return entry->ptr; } @@ -114,11 +110,7 @@ void *get_user_object_handle( user_handle_t *handle, enum user_object type ) { struct user_handle *entry; - if (!(entry = handle_to_entry( *handle )) || entry->type != type) - { - set_error( STATUS_INVALID_HANDLE ); - return NULL; - } + if (!(entry = handle_to_entry( *handle )) || entry->type != type) return NULL; *handle = entry_to_handle( entry ); return entry->ptr; } diff --git a/server/user.h b/server/user.h index 1e331686a62..d53cc53db33 100644 --- a/server/user.h +++ b/server/user.h @@ -33,5 +33,6 @@ extern void queue_cleanup_window( struct thread *thread, user_handle_t win ); /* window functions */ extern void destroy_thread_windows( struct thread *thread ); +extern int is_child_window( user_handle_t parent, user_handle_t child ); #endif /* __WINE_SERVER_USER_H */ diff --git a/server/window.c b/server/window.c index f6e853c7a87..8bc91554c61 100644 --- a/server/window.c +++ b/server/window.c @@ -14,57 +14,85 @@ struct window { - struct window *parent; /* parent window */ - struct window *child; /* first child window */ - struct window *next; /* next window in Z-order */ - struct window *prev; /* prev window in Z-order */ - user_handle_t handle; /* full handle for this window */ - struct thread *thread; /* thread owning the window */ + struct window *parent; /* parent window */ + struct window *owner; /* owner of this window */ + struct window *first_child; /* first child window */ + struct window *last_child; /* last child window */ + struct window *next; /* next window in Z-order */ + struct window *prev; /* prev window in Z-order */ + user_handle_t handle; /* full handle for this window */ + struct thread *thread; /* thread owning the window */ }; static struct window *top_window; /* top-level (desktop) window */ + +/* retrieve a pointer to a window from its handle */ +inline static struct window *get_window( user_handle_t handle ) +{ + struct window *ret = get_user_object( handle, USER_WINDOW ); + if (!ret) set_error( STATUS_INVALID_HANDLE ); + return ret; +} + /* link a window into the tree (or unlink it if the new parent is NULL) */ static void link_window( struct window *win, struct window *parent, struct window *previous ) { if (win->parent) /* unlink it from the previous location */ { if (win->next) win->next->prev = win->prev; + else if (win->parent->last_child == win) win->parent->last_child = win->prev; if (win->prev) win->prev->next = win->next; - else win->parent->child = win->next; + else if (win->parent->first_child == win) win->parent->first_child = win->next; } - if ((win->parent = parent)) + if (parent) { + win->parent = parent; if ((win->prev = previous)) { if ((win->next = previous->next)) win->next->prev = win; + else if (win->parent->last_child == previous) win->parent->last_child = win; win->prev->next = win; } else { - if ((win->next = parent->child)) win->next->prev = win; - parent->child = win; + if ((win->next = parent->first_child)) win->next->prev = win; + else win->parent->last_child = win; + parent->first_child = win; } } - else win->next = win->prev = NULL; - + else + { + /* don't touch parent; an unlinked window still has a valid parent pointer */ + win->next = win->prev = NULL; + } } -/* free a window structure */ -static void free_window( struct window *win ) +/* destroy a window */ +static void destroy_window( struct window *win ) { assert( win != top_window ); - while (win->child) free_window( win->child ); + /* destroy all children */ + while (win->first_child) destroy_window( win->first_child ); + + /* reset siblings owner */ + if (win->parent) + { + struct window *ptr; + for (ptr = win->parent->first_child; ptr; ptr = ptr->next) + if (ptr->owner == win) ptr->owner = NULL; + } + if (win->thread->queue) queue_cleanup_window( win->thread, win->handle ); free_user_handle( win->handle ); - if (win->parent) link_window( win, NULL, NULL ); + link_window( win, NULL, NULL ); memset( win, 0x55, sizeof(*win) ); free( win ); } -/* create a new window structure */ -static struct window *create_window(void) +/* 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 ) { struct window *win = mem_alloc( sizeof(*win) ); if (!win) return NULL; @@ -74,11 +102,13 @@ static struct window *create_window(void) free( win ); return NULL; } - win->parent = NULL; - win->child = NULL; - win->next = NULL; - win->prev = NULL; - win->thread = current; + win->parent = parent; + win->owner = owner; + win->first_child = NULL; + win->last_child = NULL; + win->next = NULL; + win->prev = NULL; + win->thread = current; return win; } @@ -91,30 +121,47 @@ void destroy_thread_windows( struct thread *thread ) while ((win = next_user_handle( &handle, USER_WINDOW ))) { if (win->thread != thread) continue; - free_window( win ); + destroy_window( win ); } } +/* check whether child is a descendant of parent */ +int is_child_window( user_handle_t parent, user_handle_t child ) +{ + struct window *child_ptr = get_user_object( child, USER_WINDOW ); + struct window *parent_ptr = get_user_object( parent, USER_WINDOW ); + + if (!child_ptr || !parent_ptr) return 0; + while (child_ptr->parent) + { + if (child_ptr->parent == parent_ptr) return 1; + child_ptr = child_ptr->parent; + } + return 0; +} + /* create a window */ DECL_HANDLER(create_window) { - struct window *win; - req->handle = 0; - if ((win = create_window())) req->handle = win->handle; -} - - -/* create the desktop window */ -DECL_HANDLER(create_desktop_window) -{ - req->handle = 0; - if (!top_window) + if (!req->parent) /* return desktop window */ { - if (!(top_window = create_window())) return; - top_window->thread = NULL; /* no thread owns the desktop */ + if (!top_window) + { + if (!(top_window = create_window( NULL, NULL ))) return; + top_window->thread = NULL; /* no thread owns the desktop */ + } + req->handle = top_window->handle; + } + else + { + struct window *win, *parent, *owner = NULL; + + if (!(parent = get_window( req->parent ))) return; + if (req->owner && !(owner = get_window( req->owner ))) return; + if (!(win = create_window( parent, owner ))) return; + req->handle = win->handle; } - req->handle = top_window->handle; } @@ -123,19 +170,14 @@ DECL_HANDLER(link_window) { struct window *win, *parent = NULL, *previous = NULL; - if (!(win = get_user_object( req->handle, USER_WINDOW ))) return; - if (req->parent && !(parent = get_user_object( req->parent, USER_WINDOW ))) return; + if (!(win = get_window( req->handle ))) return; + if (req->parent && !(parent = get_window( req->parent ))) return; if (parent && req->previous) { if (req->previous == 1) /* special case: HWND_BOTTOM */ - { - if ((previous = parent->child)) - { - /* make it the last of the list */ - while (previous->next) previous = previous->next; - } - } - else if (!(previous = get_user_object( req->previous, USER_WINDOW ))) return; + previous = parent->last_child; + else + if (!(previous = get_window( req->previous ))) return; if (previous && previous->parent != parent) /* previous must be a child of parent */ { @@ -150,26 +192,25 @@ DECL_HANDLER(link_window) /* destroy a window */ DECL_HANDLER(destroy_window) { - struct window *win = get_user_object( req->handle, USER_WINDOW ); + struct window *win = get_window( req->handle ); if (win) { - if (win != top_window) free_window( win ); + if (win != top_window) destroy_window( win ); else set_error( STATUS_ACCESS_DENIED ); } } -/* Get information from a window handle */ +/* get information from a window handle */ DECL_HANDLER(get_window_info) { - user_handle_t handle = req->handle; - struct window *win = get_user_object_handle( &handle, USER_WINDOW ); + struct window *win = get_window( req->handle ); req->full_handle = 0; req->tid = req->pid = 0; if (win) { - req->full_handle = handle; + req->full_handle = win->handle; if (win->thread) { req->tid = get_thread_id( win->thread ); @@ -177,3 +218,77 @@ DECL_HANDLER(get_window_info) } } } + + +/* get a list of the window parents, up to the root of the tree */ +DECL_HANDLER(get_window_parents) +{ + struct window *ptr, *win = get_window( req->handle ); + int total = 0; + size_t len; + + if (win) for (ptr = win->parent; ptr; ptr = ptr->parent) total++; + + req->count = total; + len = min( get_req_data_size(req), total * sizeof(user_handle_t) ); + set_req_data_size( req, len ); + if (len) + { + user_handle_t *data = get_req_data(req); + for (ptr = win->parent; ptr && len; ptr = ptr->parent, len -= sizeof(*data)) + *data++ = ptr->handle; + } +} + + +/* get a list of the window children */ +DECL_HANDLER(get_window_children) +{ + struct window *ptr, *parent = get_window( req->parent ); + int total = 0; + size_t len; + + if (parent) + for (ptr = parent->first_child, total = 0; ptr; ptr = ptr->next) total++; + + req->count = total; + len = min( get_req_data_size(req), total * sizeof(user_handle_t) ); + set_req_data_size( req, len ); + if (len) + { + user_handle_t *data = get_req_data(req); + for (ptr = parent->first_child; ptr && len; ptr = ptr->next, len -= sizeof(*data)) + *data++ = ptr->handle; + } +} + + +/* get window tree information from a window handle */ +DECL_HANDLER(get_window_tree) +{ + struct window *win = get_window( req->handle ); + + if (!win) return; + + if (win->parent) + { + struct window *parent = win->parent; + req->parent = parent->handle; + req->owner = win->owner ? win->owner->handle : 0; + req->next_sibling = win->next ? win->next->handle : 0; + req->prev_sibling = win->prev ? win->prev->handle : 0; + req->first_sibling = parent->first_child ? parent->first_child->handle : 0; + req->last_sibling = parent->last_child ? parent->last_child->handle : 0; + } + else + { + req->parent = 0; + req->owner = 0; + req->next_sibling = 0; + req->prev_sibling = 0; + req->first_sibling = 0; + req->last_sibling = 0; + } + req->first_child = win->first_child ? win->first_child->handle : 0; + req->last_child = win->last_child ? win->last_child->handle : 0; +} diff --git a/windows/win.c b/windows/win.c index 2ca2f7728d4..a587caebf99 100644 --- a/windows/win.c +++ b/windows/win.c @@ -75,7 +75,7 @@ void WIN_RestoreWndsLock( int ipreviousLocks ) * * Create a window handle with the server. */ -static WND *create_window_handle( BOOL desktop, INT size ) +static WND *create_window_handle( HWND parent, HWND owner, INT size ) { BOOL res; user_handle_t handle = 0; @@ -85,22 +85,13 @@ static WND *create_window_handle( BOOL desktop, INT size ) USER_Lock(); - if (desktop) + SERVER_START_REQ( create_window ) { - SERVER_START_REQ( create_desktop_window ) - { - if ((res = !SERVER_CALL_ERR())) handle = req->handle; - } - SERVER_END_REQ; - } - else - { - SERVER_START_REQ( create_window ) - { - if ((res = !SERVER_CALL_ERR())) handle = req->handle; - } - SERVER_END_REQ; + req->parent = parent; + req->owner = owner; + if ((res = !SERVER_CALL_ERR())) handle = req->handle; } + SERVER_END_REQ; if (!res) { @@ -542,7 +533,7 @@ BOOL WIN_CreateDesktopWindow(void) &wndExtra, &winproc, &clsStyle, &dce ))) return FALSE; - pWndDesktop = create_window_handle( TRUE, sizeof(WND) + wndExtra ); + pWndDesktop = create_window_handle( 0, 0, sizeof(WND) + wndExtra ); if (!pWndDesktop) return FALSE; hwndDesktop = pWndDesktop->hwndSelf; @@ -675,7 +666,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, INT sw = SW_SHOW; struct tagCLASS *classPtr; WND *wndPtr; - HWND hwnd, hwndLinkAfter; + HWND hwnd, hwndLinkAfter, parent, owner; POINT maxSize, maxPos, minTrack, maxTrack; INT wndExtra; DWORD clsStyle; @@ -694,6 +685,8 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, /* Find the parent window */ + parent = GetDesktopWindow(); + owner = 0; if (cs->hwndParent) { /* Make sure parent is valid */ @@ -702,7 +695,11 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, WARN("Bad parent %04x\n", cs->hwndParent ); return 0; } - } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) { + if (cs->style & WS_CHILD) parent = cs->hwndParent; + else owner = GetAncestor( cs->hwndParent, GA_ROOT ); + } + else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) + { WARN("No parent for child window\n" ); return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */ } @@ -738,7 +735,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, /* Create the window structure */ - if (!(wndPtr = create_window_handle( FALSE, + if (!(wndPtr = create_window_handle( parent, owner, sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) ))) { TRACE("out of memory\n" ); @@ -751,22 +748,9 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, wndPtr->tid = GetCurrentThreadId(); wndPtr->next = NULL; wndPtr->child = NULL; - - if ((cs->style & WS_CHILD) && cs->hwndParent) - { - wndPtr->parent = WIN_FindWndPtr( cs->hwndParent ); - wndPtr->owner = 0; - WIN_ReleaseWndPtr(wndPtr->parent); - } - else - { - wndPtr->parent = pWndDesktop; - if (!cs->hwndParent || (cs->hwndParent == pWndDesktop->hwndSelf)) - wndPtr->owner = 0; - else - wndPtr->owner = GetAncestor( cs->hwndParent, GA_ROOT ); - } - + wndPtr->owner = owner; + wndPtr->parent = WIN_FindWndPtr( parent ); + WIN_ReleaseWndPtr(wndPtr->parent); wndPtr->class = classPtr; wndPtr->winproc = winproc; @@ -916,7 +900,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, /* Call WH_SHELL hook */ - if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner) + if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER )) HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0 ); TRACE("created window %04x\n", hwnd); @@ -1186,7 +1170,7 @@ BOOL WINAPI DestroyWindow( HWND hwnd ) if( HOOK_CallHooksA( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0L) ) return FALSE; if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE; - if (!(wndPtr->dwStyle & WS_CHILD) && !wndPtr->owner) + if (!(wndPtr->dwStyle & WS_CHILD) && !GetWindow( hwnd, GW_OWNER )) { HOOK_CallHooksA( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L ); /* FIXME: clean up palette - see "Internals" p.352 */ @@ -1210,20 +1194,19 @@ BOOL WINAPI DestroyWindow( HWND hwnd ) /* Hide the window */ - if (wndPtr->dwStyle & WS_VISIBLE) + ShowWindow( hwnd, SW_HIDE ); + if (!IsWindow(hwnd)) { - ShowWindow( hwnd, SW_HIDE ); - if (!IsWindow(hwnd)) - { - retvalue = TRUE; - goto end; - } + retvalue = TRUE; + goto end; } /* Recursively destroy owned windows */ if( !(wndPtr->dwStyle & WS_CHILD) ) { + HWND owner; + for (;;) { int i, got_one = 0; @@ -1232,19 +1215,17 @@ BOOL WINAPI DestroyWindow( HWND hwnd ) { for (i = 0; list[i]; i++) { - WND *siblingPtr = WIN_FindWndPtr( list[i] ); - if (!siblingPtr) continue; - if (siblingPtr->owner == hwnd) + WND *siblingPtr; + if (GetWindow( list[i], GW_OWNER ) != hwnd) continue; + if (!(siblingPtr = WIN_FindWndPtr( list[i] ))) continue; + if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ) { - if (siblingPtr->hmemTaskQ == wndPtr->hmemTaskQ) - { - WIN_ReleaseWndPtr( siblingPtr ); - DestroyWindow( list[i] ); - got_one = 1; - continue; - } - else siblingPtr->owner = 0; + WIN_ReleaseWndPtr( siblingPtr ); + DestroyWindow( list[i] ); + got_one = 1; + continue; } + else siblingPtr->owner = 0; WIN_ReleaseWndPtr( siblingPtr ); } HeapFree( GetProcessHeap(), 0, list ); @@ -1252,13 +1233,16 @@ BOOL WINAPI DestroyWindow( HWND hwnd ) if (!got_one) break; } - WINPOS_ActivateOtherWindow(wndPtr->hwndSelf); + WINPOS_ActivateOtherWindow( hwnd ); - if (wndPtr->owner) + if ((owner = GetWindow( hwnd, GW_OWNER ))) { - WND *owner = WIN_FindWndPtr( wndPtr->owner ); - if (owner->hwndLastActive == hwnd) owner->hwndLastActive = wndPtr->owner; - WIN_ReleaseWndPtr( owner ); + WND *ptr = WIN_FindWndPtr( owner ); + if (ptr) + { + if (ptr->hwndLastActive == hwnd) ptr->hwndLastActive = owner; + WIN_ReleaseWndPtr( ptr ); + } } } @@ -2219,72 +2203,45 @@ HWND WINAPI GetTopWindow( HWND hwnd ) /******************************************************************* * GetWindow (USER32.@) */ -HWND WINAPI GetWindow( HWND hwnd, WORD rel ) +HWND WINAPI GetWindow( HWND hwnd, UINT rel ) { - HWND retval; + HWND retval = 0; - WND * wndPtr = WIN_FindWndPtr( hwnd ); - if (!wndPtr) return 0; - hwnd = wndPtr->hwndSelf; /* make it a full handle */ - - switch(rel) + if (rel == GW_OWNER) /* special case: not fully supported in the server yet */ { - case GW_HWNDFIRST: - retval = wndPtr->parent ? wndPtr->parent->child->hwndSelf : 0; - goto end; - - case GW_HWNDLAST: - if (!wndPtr->parent) - { - retval = 0; /* Desktop window */ - goto end; - } - while (wndPtr->next) - { - WIN_UpdateWndPtr(&wndPtr,wndPtr->next); - } - retval = wndPtr->hwndSelf; - goto end; - - case GW_HWNDNEXT: - retval = wndPtr->next ? wndPtr->next->hwndSelf : 0; - goto end; - - case GW_HWNDPREV: - if (!wndPtr->parent) - { - retval = 0; /* Desktop window */ - goto end; - } - WIN_UpdateWndPtr(&wndPtr,wndPtr->parent->child); /* First sibling */ - if (wndPtr->hwndSelf == hwnd) - { - retval = 0; /* First in list */ - goto end; - } - while (wndPtr->next) - { - if (wndPtr->next->hwndSelf == hwnd) - { - retval = wndPtr->hwndSelf; - goto end; - } - WIN_UpdateWndPtr(&wndPtr,wndPtr->next); - } - retval = 0; - goto end; - - case GW_OWNER: + WND *wndPtr = WIN_FindWndPtr( hwnd ); + if (!wndPtr) return 0; retval = wndPtr->owner; - goto end; - - case GW_CHILD: - retval = wndPtr->child ? wndPtr->child->hwndSelf : 0; - goto end; + WIN_ReleaseWndPtr( wndPtr ); + return retval; } - retval = 0; -end: - WIN_ReleaseWndPtr(wndPtr); + + SERVER_START_REQ( get_window_tree ) + { + req->handle = hwnd; + if (!SERVER_CALL_ERR()) + { + switch(rel) + { + case GW_HWNDFIRST: + retval = req->first_sibling; + break; + case GW_HWNDLAST: + retval = req->last_sibling; + break; + case GW_HWNDNEXT: + retval = req->next_sibling; + break; + case GW_HWNDPREV: + retval = req->prev_sibling; + break; + case GW_CHILD: + retval = req->first_child; + break; + } + } + } + SERVER_END_REQ; return retval; } @@ -2428,36 +2385,23 @@ HWND WINAPI GetLastActivePopup( HWND hwnd ) */ HWND *WIN_ListParents( HWND hwnd ) { - WND *parent, *wndPtr = WIN_FindWndPtr( hwnd ); HWND *list = NULL; - UINT i, count = 0; - /* First count the windows */ - - if (!wndPtr) return NULL; - - parent = wndPtr->parent; - while (parent && parent->hwndSelf != GetDesktopWindow()) + SERVER_START_VAR_REQ( get_window_parents, REQUEST_MAX_VAR_SIZE ) { - count++; - parent = parent->parent; - } - - if (count) - { - if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1) ))) + req->handle = hwnd; + if (!SERVER_CALL()) { - parent = wndPtr->parent; - for (i = 0; i < count; i++) + user_handle_t *data = server_data_ptr(req); + int i, count = server_data_size(req) / sizeof(*data); + if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) )))) { - list[i] = parent->hwndSelf; - parent = parent->parent; + for (i = 0; i < count; i++) list[i] = data[i]; + list[i] = 0; } - list[i] = 0; } } - - WIN_ReleaseWndPtr( wndPtr ); + SERVER_END_VAR_REQ; return list; } @@ -2470,39 +2414,23 @@ HWND *WIN_ListParents( HWND hwnd ) */ HWND *WIN_ListChildren( HWND hwnd ) { - WND *pWnd, *wndPtr = WIN_FindWndPtr( hwnd ); - HWND *list, *phwnd; - UINT count = 0; + HWND *list = NULL; - /* First count the windows */ - - if (!wndPtr) return NULL; - - pWnd = WIN_LockWndPtr(wndPtr->child); - while (pWnd) + SERVER_START_VAR_REQ( get_window_children, REQUEST_MAX_VAR_SIZE ) { - count++; - WIN_UpdateWndPtr(&pWnd,pWnd->next); + req->parent = hwnd; + if (!SERVER_CALL()) + { + user_handle_t *data = server_data_ptr(req); + int i, count = server_data_size(req) / sizeof(*data); + if (count && ((list = HeapAlloc( GetProcessHeap(), 0, (count + 1) * sizeof(HWND) )))) + { + for (i = 0; i < count; i++) list[i] = data[i]; + list[i] = 0; + } + } } - - if( count ) - { - /* Now build the list of all windows */ - - if ((list = HeapAlloc( GetProcessHeap(), 0, sizeof(HWND) * (count + 1)))) - { - for (pWnd = WIN_LockWndPtr(wndPtr->child), phwnd = list, count = 0; pWnd; WIN_UpdateWndPtr(&pWnd,pWnd->next)) - { - *phwnd++ = pWnd->hwndSelf; - count++; - } - WIN_ReleaseWndPtr(pWnd); - *phwnd = 0; - } - else count = 0; - } else list = NULL; - - WIN_ReleaseWndPtr( wndPtr ); + SERVER_END_VAR_REQ; return list; }