Added proper support for storing window parents in the server.

Added a few requests to query the window hierarchy.
This commit is contained in:
Alexandre Julliard 2001-09-21 21:08:40 +00:00
parent 9c89290e89
commit a09da0cbbd
10 changed files with 430 additions and 273 deletions

View File

@ -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 */

View File

@ -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)

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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 ### */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}