Added proper support for storing window parents in the server.
Added a few requests to query the window hierarchy.
This commit is contained in:
parent
9c89290e89
commit
a09da0cbbd
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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 ### */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
223
server/window.c
223
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;
|
||||
}
|
||||
|
|
274
windows/win.c
274
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue