Store window class atom in the server.
Keep unlinked windows on a separate list. Implemented inter-process FindWindow().
This commit is contained in:
parent
5bcd11631f
commit
844ceb98ba
|
@ -79,6 +79,7 @@ typedef struct
|
|||
#define WIN_NEEDS_INTERNALSOP 0x1000 /* Window was hidden by WIN_InternalShowOwnedPopups */
|
||||
|
||||
/* Window functions */
|
||||
extern WND *WIN_GetWndPtr( HWND hwnd );
|
||||
extern int WIN_SuspendWndsLock( void );
|
||||
extern void WIN_RestoreWndsLock(int ipreviousLock);
|
||||
extern WND* WIN_FindWndPtr( HWND hwnd );
|
||||
|
@ -115,6 +116,8 @@ inline static WND *WIN_FindWndPtr16( HWND16 hwnd )
|
|||
return WIN_FindWndPtr( (HWND)(ULONG_PTR)hwnd );
|
||||
}
|
||||
|
||||
#define BAD_WND_PTR ((WND *)1) /* returned by WIN_GetWndPtr on bad window handles */
|
||||
|
||||
extern HWND CARET_GetHwnd(void);
|
||||
extern void CARET_GetRect(LPRECT lprc); /* windows/caret.c */
|
||||
|
||||
|
|
|
@ -1579,6 +1579,7 @@ struct create_window_request
|
|||
struct request_header __header;
|
||||
user_handle_t parent;
|
||||
user_handle_t owner;
|
||||
unsigned int atom;
|
||||
user_handle_t handle;
|
||||
};
|
||||
|
||||
|
@ -1627,6 +1628,8 @@ struct get_window_children_request
|
|||
{
|
||||
struct request_header __header;
|
||||
user_handle_t parent;
|
||||
unsigned int atom;
|
||||
void* tid;
|
||||
int count;
|
||||
/* VARARG(children,user_handles); */
|
||||
};
|
||||
|
@ -1919,6 +1922,6 @@ union generic_request
|
|||
struct get_window_tree_request get_window_tree;
|
||||
};
|
||||
|
||||
#define SERVER_PROTOCOL_VERSION 55
|
||||
#define SERVER_PROTOCOL_VERSION 56
|
||||
|
||||
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */
|
||||
|
|
|
@ -1410,6 +1410,7 @@ enum message_type
|
|||
@REQ(create_window)
|
||||
user_handle_t parent; /* parent window */
|
||||
user_handle_t owner; /* owner window */
|
||||
unsigned int atom; /* class atom */
|
||||
@REPLY
|
||||
user_handle_t handle; /* created window */
|
||||
@END
|
||||
|
@ -1452,6 +1453,8 @@ enum message_type
|
|||
/* Get a list of the window children */
|
||||
@REQ(get_window_children)
|
||||
user_handle_t parent; /* parent window */
|
||||
unsigned int atom; /* class atom for the listed children */
|
||||
void* tid; /* thread owning the listed children */
|
||||
@REPLY
|
||||
int count; /* total count of children */
|
||||
VARARG(children,user_handles); /* children handles */
|
||||
|
|
|
@ -1672,7 +1672,8 @@ static void dump_get_named_pipe_info_reply( const struct get_named_pipe_info_req
|
|||
static void dump_create_window_request( const struct create_window_request *req )
|
||||
{
|
||||
fprintf( stderr, " parent=%08x,", req->parent );
|
||||
fprintf( stderr, " owner=%08x", req->owner );
|
||||
fprintf( stderr, " owner=%08x,", req->owner );
|
||||
fprintf( stderr, " atom=%08x", req->atom );
|
||||
}
|
||||
|
||||
static void dump_create_window_reply( const struct create_window_request *req )
|
||||
|
@ -1718,7 +1719,9 @@ static void dump_get_window_parents_reply( const struct get_window_parents_reque
|
|||
|
||||
static void dump_get_window_children_request( const struct get_window_children_request *req )
|
||||
{
|
||||
fprintf( stderr, " parent=%08x", req->parent );
|
||||
fprintf( stderr, " parent=%08x,", req->parent );
|
||||
fprintf( stderr, " atom=%08x,", req->atom );
|
||||
fprintf( stderr, " tid=%p", req->tid );
|
||||
}
|
||||
|
||||
static void dump_get_window_children_reply( const struct get_window_children_request *req )
|
||||
|
|
|
@ -16,12 +16,14 @@ struct 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 *first_child; /* first child in Z-order */
|
||||
struct window *last_child; /* last child in Z-order */
|
||||
struct window *first_unlinked; /* first child not linked in the Z-order list */
|
||||
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 */
|
||||
unsigned int atom; /* class atom */
|
||||
};
|
||||
|
||||
static struct window *top_window; /* top-level (desktop) window */
|
||||
|
@ -35,16 +37,27 @@ inline static struct window *get_window( user_handle_t handle )
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* unlink a window from the tree */
|
||||
static void unlink_window( struct window *win )
|
||||
{
|
||||
struct window *parent = win->parent;
|
||||
|
||||
assert( parent );
|
||||
|
||||
if (win->next) win->next->prev = win->prev;
|
||||
else if (parent->last_child == win) parent->last_child = win->prev;
|
||||
|
||||
if (win->prev) win->prev->next = win->next;
|
||||
else if (parent->first_child == win) parent->first_child = win->next;
|
||||
else if (parent->first_unlinked == win) parent->first_unlinked = win->next;
|
||||
}
|
||||
|
||||
|
||||
/* 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 if (win->parent->first_child == win) win->parent->first_child = win->next;
|
||||
}
|
||||
unlink_window( win ); /* unlink it from the previous location */
|
||||
|
||||
if (parent)
|
||||
{
|
||||
win->parent = parent;
|
||||
|
@ -61,10 +74,12 @@ static void link_window( struct window *win, struct window *parent, struct windo
|
|||
parent->first_child = win;
|
||||
}
|
||||
}
|
||||
else
|
||||
else /* move it to parent unlinked list */
|
||||
{
|
||||
/* don't touch parent; an unlinked window still has a valid parent pointer */
|
||||
win->next = win->prev = NULL;
|
||||
parent = win->parent;
|
||||
if ((win->next = parent->first_unlinked)) win->next->prev = win;
|
||||
win->prev = NULL;
|
||||
parent->first_unlinked = win;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,6 +90,7 @@ static void destroy_window( struct window *win )
|
|||
|
||||
/* destroy all children */
|
||||
while (win->first_child) destroy_window( win->first_child );
|
||||
while (win->first_unlinked) destroy_window( win->first_unlinked );
|
||||
|
||||
/* reset siblings owner */
|
||||
if (win->parent)
|
||||
|
@ -82,17 +98,20 @@ static void destroy_window( struct window *win )
|
|||
struct window *ptr;
|
||||
for (ptr = win->parent->first_child; ptr; ptr = ptr->next)
|
||||
if (ptr->owner == win) ptr->owner = NULL;
|
||||
for (ptr = win->parent->first_unlinked; 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 );
|
||||
link_window( win, NULL, NULL );
|
||||
unlink_window( win );
|
||||
memset( win, 0x55, sizeof(*win) );
|
||||
free( win );
|
||||
}
|
||||
|
||||
/* create a new window structure (note: the window is not linked in the window tree) */
|
||||
static struct window *create_window( struct window *parent, struct window *owner )
|
||||
static struct window *create_window( struct window *parent, struct window *owner,
|
||||
unsigned int atom )
|
||||
{
|
||||
struct window *win = mem_alloc( sizeof(*win) );
|
||||
if (!win) return NULL;
|
||||
|
@ -106,9 +125,18 @@ static struct window *create_window( struct window *parent, struct window *owner
|
|||
win->owner = owner;
|
||||
win->first_child = NULL;
|
||||
win->last_child = NULL;
|
||||
win->next = NULL;
|
||||
win->prev = NULL;
|
||||
win->first_unlinked = NULL;
|
||||
win->thread = current;
|
||||
win->atom = atom;
|
||||
|
||||
if (parent) /* put it on parent unlinked list */
|
||||
{
|
||||
if ((win->next = parent->first_unlinked)) win->next->prev = win;
|
||||
win->prev = NULL;
|
||||
parent->first_unlinked = win;
|
||||
}
|
||||
else win->next = win->prev = NULL;
|
||||
|
||||
return win;
|
||||
}
|
||||
|
||||
|
@ -148,7 +176,7 @@ DECL_HANDLER(create_window)
|
|||
{
|
||||
if (!top_window)
|
||||
{
|
||||
if (!(top_window = create_window( NULL, NULL ))) return;
|
||||
if (!(top_window = create_window( NULL, NULL, req->atom ))) return;
|
||||
top_window->thread = NULL; /* no thread owns the desktop */
|
||||
}
|
||||
req->handle = top_window->handle;
|
||||
|
@ -159,7 +187,7 @@ DECL_HANDLER(create_window)
|
|||
|
||||
if (!(parent = get_window( req->parent ))) return;
|
||||
if (req->owner && !(owner = get_window( req->owner ))) return;
|
||||
if (!(win = create_window( parent, owner ))) return;
|
||||
if (!(win = create_window( parent, owner, req->atom ))) return;
|
||||
req->handle = win->handle;
|
||||
}
|
||||
}
|
||||
|
@ -172,6 +200,12 @@ DECL_HANDLER(link_window)
|
|||
|
||||
if (!(win = get_window( req->handle ))) return;
|
||||
if (req->parent && !(parent = get_window( req->parent ))) return;
|
||||
|
||||
if (win == top_window)
|
||||
{
|
||||
set_error( STATUS_INVALID_PARAMETER );
|
||||
return;
|
||||
}
|
||||
if (parent && req->previous)
|
||||
{
|
||||
if (req->previous == (user_handle_t)1) /* special case: HWND_BOTTOM */
|
||||
|
@ -254,7 +288,12 @@ DECL_HANDLER(get_window_children)
|
|||
size_t len;
|
||||
|
||||
if (parent)
|
||||
for (ptr = parent->first_child, total = 0; ptr; ptr = ptr->next) total++;
|
||||
for (ptr = parent->first_child, total = 0; ptr; ptr = ptr->next)
|
||||
{
|
||||
if (req->atom && ptr->atom != req->atom) continue;
|
||||
if (req->tid && get_thread_id(ptr->thread) != req->tid) continue;
|
||||
total++;
|
||||
}
|
||||
|
||||
req->count = total;
|
||||
len = min( get_req_data_size(req), total * sizeof(user_handle_t) );
|
||||
|
@ -263,8 +302,12 @@ DECL_HANDLER(get_window_children)
|
|||
{
|
||||
user_handle_t *data = get_req_data(req);
|
||||
for (ptr = parent->first_child; ptr && len; ptr = ptr->next, len -= sizeof(*data))
|
||||
{
|
||||
if (req->atom && ptr->atom != req->atom) continue;
|
||||
if (req->tid && get_thread_id(ptr->thread) != req->tid) continue;
|
||||
*data++ = ptr->handle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
113
windows/win.c
113
windows/win.c
|
@ -30,7 +30,6 @@
|
|||
DEFAULT_DEBUG_CHANNEL(win);
|
||||
DECLARE_DEBUG_CHANNEL(msg);
|
||||
|
||||
#define BAD_WND_PTR ((WND *)1) /* returned by get_wnd_ptr on bad window handles */
|
||||
#define NB_USER_HANDLES (LAST_USER_HANDLE - FIRST_USER_HANDLE + 1)
|
||||
|
||||
/**********************************************************************/
|
||||
|
@ -79,7 +78,7 @@ void WIN_RestoreWndsLock( int ipreviousLocks )
|
|||
*
|
||||
* Create a window handle with the server.
|
||||
*/
|
||||
static WND *create_window_handle( HWND parent, HWND owner, INT size )
|
||||
static WND *create_window_handle( HWND parent, HWND owner, ATOM atom, INT size )
|
||||
{
|
||||
BOOL res;
|
||||
user_handle_t handle = 0;
|
||||
|
@ -94,6 +93,7 @@ static WND *create_window_handle( HWND parent, HWND owner, INT size )
|
|||
{
|
||||
req->parent = parent;
|
||||
req->owner = owner;
|
||||
req->atom = atom;
|
||||
if ((res = !SERVER_CALL_ERR())) handle = req->handle;
|
||||
}
|
||||
SERVER_END_REQ;
|
||||
|
@ -144,14 +144,45 @@ static WND *free_window_handle( HWND hwnd )
|
|||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
* list_window_children
|
||||
*
|
||||
* Build an array of the children of a given window. The array must be
|
||||
* freed with HeapFree. Returns NULL when no windows are found.
|
||||
*/
|
||||
static HWND *list_window_children( HWND hwnd, ATOM atom, DWORD tid )
|
||||
{
|
||||
HWND *list = NULL;
|
||||
|
||||
SERVER_START_VAR_REQ( get_window_children, REQUEST_MAX_VAR_SIZE )
|
||||
{
|
||||
req->parent = hwnd;
|
||||
req->atom = atom;
|
||||
req->tid = (void *)tid;
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* get_wnd_ptr
|
||||
* WIN_GetWndPtr
|
||||
*
|
||||
* Return a pointer to the WND structure if local to the process,
|
||||
* or BAD_WND_PTR is handle is local but not valid.
|
||||
* If ret value is a valid pointer, the user lock is held.
|
||||
*/
|
||||
static WND *get_wnd_ptr( HWND hwnd )
|
||||
WND *WIN_GetWndPtr( HWND hwnd )
|
||||
{
|
||||
WND * ptr;
|
||||
WORD index = LOWORD(hwnd) - FIRST_USER_HANDLE;
|
||||
|
@ -179,7 +210,7 @@ BOOL WIN_IsCurrentProcess( HWND hwnd )
|
|||
{
|
||||
WND *ptr;
|
||||
|
||||
if (!(ptr = get_wnd_ptr( hwnd )) || ptr == BAD_WND_PTR) return FALSE;
|
||||
if (!(ptr = WIN_GetWndPtr( hwnd )) || ptr == BAD_WND_PTR) return FALSE;
|
||||
USER_Unlock();
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -195,7 +226,7 @@ BOOL WIN_IsCurrentThread( HWND hwnd )
|
|||
WND *ptr;
|
||||
BOOL ret = FALSE;
|
||||
|
||||
if ((ptr = get_wnd_ptr( hwnd )) && ptr != BAD_WND_PTR)
|
||||
if ((ptr = WIN_GetWndPtr( hwnd )) && ptr != BAD_WND_PTR)
|
||||
{
|
||||
ret = (ptr->tid == GetCurrentThreadId());
|
||||
USER_Unlock();
|
||||
|
@ -218,7 +249,7 @@ HWND WIN_Handle32( HWND16 hwnd16 )
|
|||
/* do sign extension for -2 and -3 */
|
||||
if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
|
||||
|
||||
if ((ptr = get_wnd_ptr( hwnd )))
|
||||
if ((ptr = WIN_GetWndPtr( hwnd )))
|
||||
{
|
||||
if (ptr != BAD_WND_PTR)
|
||||
{
|
||||
|
@ -250,7 +281,7 @@ WND * WIN_FindWndPtr( HWND hwnd )
|
|||
|
||||
if (!hwnd) return NULL;
|
||||
|
||||
if ((ptr = get_wnd_ptr( hwnd )))
|
||||
if ((ptr = WIN_GetWndPtr( hwnd )))
|
||||
{
|
||||
if (ptr != BAD_WND_PTR)
|
||||
{
|
||||
|
@ -583,7 +614,8 @@ BOOL WIN_CreateDesktopWindow(void)
|
|||
&wndExtra, &winproc, &clsStyle, &dce )))
|
||||
return FALSE;
|
||||
|
||||
pWndDesktop = create_window_handle( 0, 0, sizeof(WND) + wndExtra );
|
||||
pWndDesktop = create_window_handle( 0, 0, LOWORD(DESKTOP_CLASS_ATOM),
|
||||
sizeof(WND) + wndExtra - sizeof(pWndDesktop->wExtra) );
|
||||
if (!pWndDesktop) return FALSE;
|
||||
hwndDesktop = pWndDesktop->hwndSelf;
|
||||
|
||||
|
@ -785,7 +817,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
|
|||
|
||||
/* Create the window structure */
|
||||
|
||||
if (!(wndPtr = create_window_handle( parent, owner,
|
||||
if (!(wndPtr = create_window_handle( parent, owner, classAtom,
|
||||
sizeof(*wndPtr) + wndExtra - sizeof(wndPtr->wExtra) )))
|
||||
{
|
||||
TRACE("out of memory\n" );
|
||||
|
@ -1359,8 +1391,8 @@ BOOL WINAPI OpenIcon( HWND hwnd )
|
|||
*/
|
||||
static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR title )
|
||||
{
|
||||
HWND *list;
|
||||
HWND retvalue;
|
||||
HWND *list = NULL;
|
||||
HWND retvalue = 0;
|
||||
int i = 0, len = 0;
|
||||
WCHAR *buffer = NULL;
|
||||
|
||||
|
@ -1371,37 +1403,29 @@ static HWND WIN_FindWindow( HWND parent, HWND child, ATOM className, LPCWSTR tit
|
|||
if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
|
||||
}
|
||||
|
||||
if (!(list = WIN_ListChildren( parent )))
|
||||
{
|
||||
if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
|
||||
return 0;
|
||||
}
|
||||
if (!(list = list_window_children( parent, className, 0 ))) goto done;
|
||||
|
||||
if (child)
|
||||
{
|
||||
child = WIN_GetFullHandle( child );
|
||||
while (list[i] && list[i] != child) i++;
|
||||
if (!list[i]) return 0;
|
||||
if (!list[i]) goto done;
|
||||
i++; /* start from next window */
|
||||
}
|
||||
|
||||
for ( ; list[i]; i++)
|
||||
if (title)
|
||||
{
|
||||
while (list[i])
|
||||
{
|
||||
if (className && (GetClassWord(list[i], GCW_ATOM) != className))
|
||||
continue; /* Not the right class */
|
||||
|
||||
/* Now check the title */
|
||||
if (!title) break;
|
||||
if (GetWindowTextW( list[i], buffer, len ) && !strcmpiW( buffer, title )) break;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
retvalue = list[i];
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
|
||||
|
||||
/* In this case we need to check whether other processes
|
||||
own a window with the given paramters on the Desktop,
|
||||
but we don't, so let's at least warn about it */
|
||||
if (!retvalue) FIXME("Returning 0 without checking other processes\n");
|
||||
done:
|
||||
if (list) HeapFree( GetProcessHeap(), 0, list );
|
||||
if (buffer) HeapFree( GetProcessHeap(), 0, buffer );
|
||||
return retvalue;
|
||||
}
|
||||
|
||||
|
@ -2003,7 +2027,7 @@ BOOL WINAPI IsWindow( HWND hwnd )
|
|||
WND *ptr;
|
||||
BOOL ret;
|
||||
|
||||
if ((ptr = get_wnd_ptr( hwnd )))
|
||||
if ((ptr = WIN_GetWndPtr( hwnd )))
|
||||
{
|
||||
if (ptr == BAD_WND_PTR) return FALSE;
|
||||
USER_Unlock();
|
||||
|
@ -2029,7 +2053,7 @@ DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
|
|||
WND *ptr;
|
||||
DWORD tid = 0;
|
||||
|
||||
if ((ptr = get_wnd_ptr( hwnd )))
|
||||
if ((ptr = WIN_GetWndPtr( hwnd )))
|
||||
{
|
||||
if (ptr != BAD_WND_PTR)
|
||||
{
|
||||
|
@ -2462,24 +2486,7 @@ HWND *WIN_ListParents( HWND hwnd )
|
|||
*/
|
||||
HWND *WIN_ListChildren( HWND hwnd )
|
||||
{
|
||||
HWND *list = NULL;
|
||||
|
||||
SERVER_START_VAR_REQ( get_window_children, REQUEST_MAX_VAR_SIZE )
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
SERVER_END_VAR_REQ;
|
||||
return list;
|
||||
return list_window_children( hwnd, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
|
@ -2533,16 +2540,14 @@ BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
|
|||
HWND *list;
|
||||
int i, iWndsLocks;
|
||||
|
||||
if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return FALSE;
|
||||
if (!(list = list_window_children( GetDesktopWindow(), 0, GetCurrentThreadId() )))
|
||||
return FALSE;
|
||||
|
||||
/* Now call the callback function for every window */
|
||||
|
||||
iWndsLocks = WIN_SuspendWndsLock();
|
||||
for (i = 0; list[i]; i++)
|
||||
{
|
||||
if (GetWindowThreadProcessId( list[i], NULL ) != id) continue;
|
||||
if (!func( list[i], lParam )) break;
|
||||
}
|
||||
WIN_RestoreWndsLock(iWndsLocks);
|
||||
HeapFree( GetProcessHeap(), 0, list );
|
||||
return TRUE;
|
||||
|
|
Loading…
Reference in New Issue