Added proper support for storing window parents in the server.
Added a few requests to query the window hierarchy.
diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h
index ebf2d3f..18ecc74 100644
--- a/include/wine/server_protocol.h
+++ b/include/wine/server_protocol.h
@@ -1563,17 +1563,11 @@
-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_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 @@
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 @@
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 a8523eb..d1daa24 100644
--- a/include/winuser.h
+++ b/include/winuser.h
@@ -3602,8 +3602,8 @@
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 c386dd9..a87287c 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -1395,17 +1395,12 @@
@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 @@
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 2cab814..4e0332b 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -833,7 +833,7 @@
{
/* 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 97bc21e..c4530b5 100644
--- a/server/request.h
+++ b/server/request.h
@@ -188,11 +188,13 @@
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 @@
(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 5dc05bc..93a4f36 100644
--- a/server/trace.c
+++ b/server/trace.c
@@ -119,6 +119,21 @@
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 @@
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 @@
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 @@
(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 @@
(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 @@
"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 88c7fd7..e31fb16 100644
--- a/server/user.c
+++ b/server/user.c
@@ -91,11 +91,7 @@
{
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 @@
{
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 1e33168..d53cc53 100644
--- a/server/user.h
+++ b/server/user.h
@@ -33,5 +33,6 @@
/* 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 f6e853c..8bc9155 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 @@
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 @@
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;
}
- 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;
+ }
}
@@ -123,19 +170,14 @@
{
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 @@
/* 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 @@
}
}
}
+
+
+/* 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 2ca2f77..a587cae 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -75,7 +75,7 @@
*
* 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 @@
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;
+ req->parent = parent;
+ req->owner = owner;
+ if ((res = !SERVER_CALL_ERR())) handle = req->handle;
}
- else
- {
- SERVER_START_REQ( create_window )
- {
- if ((res = !SERVER_CALL_ERR())) handle = req->handle;
- }
- SERVER_END_REQ;
- }
+ SERVER_END_REQ;
if (!res)
{
@@ -542,7 +533,7 @@
&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 @@
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 @@
/* Find the parent window */
+ parent = GetDesktopWindow();
+ owner = 0;
if (cs->hwndParent)
{
/* Make sure parent is valid */
@@ -702,7 +695,11 @@
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 @@
/* 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 @@
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 @@
/* 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 @@
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 @@
/* 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 @@
{
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 @@
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 @@
/*******************************************************************
* 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 *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_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;
}