Added proper support for storing window parents in the server.
Added a few requests to query the window hierarchy.
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;
}