diff --git a/dlls/ttydrv/wnd.c b/dlls/ttydrv/wnd.c index 13a01e9cfdcd53279a07aa561f0d0b7dcf429efc..2db3ec41bbf0342390d2f1715382b4948ee3832e 100644 --- a/dlls/ttydrv/wnd.c +++ b/dlls/ttydrv/wnd.c @@ -127,7 +127,7 @@ static BOOL DCE_GetVisRect( WND *wndPtr, BOOL clientArea, RECT *lprect ) INT xoffset = lprect->left; INT yoffset = lprect->top; - while ((wndPtr = WIN_LockWndPtr(wndPtr->parent))) + while ((wndPtr = WIN_FindWndPtr( GetAncestor(wndPtr->hwndSelf,GA_PARENT) ))) { if ( (wndPtr->dwStyle & (WS_ICONIC | WS_VISIBLE)) != WS_VISIBLE ) { @@ -175,27 +175,28 @@ fail: * adding to the clip region the intersection of the target rectangle * with an offset window rectangle. */ -static BOOL DCE_AddClipRects( WND *pWndStart, WND *pWndEnd, - HRGN hrgnClip, LPRECT lpRect, int x, int y ) +static BOOL DCE_AddClipRects( HWND start, HWND end, HRGN hrgnClip, LPRECT lpRect, int x, int y ) { RECT rect; + WND *pWnd; - for (WIN_LockWndPtr(pWndStart); (pWndStart && (pWndStart != pWndEnd)); WIN_UpdateWndPtr(&pWndStart,pWndStart->next)) + for (pWnd = WIN_FindWndPtr(start); (pWnd && (pWnd->hwndSelf != end)); WIN_UpdateWndPtr(&pWnd,pWnd->next)) { - if( !(pWndStart->dwStyle & WS_VISIBLE) ) continue; + if( !(pWnd->dwStyle & WS_VISIBLE) ) continue; - rect.left = pWndStart->rectWindow.left + x; - rect.top = pWndStart->rectWindow.top + y; - rect.right = pWndStart->rectWindow.right + x; - rect.bottom = pWndStart->rectWindow.bottom + y; + rect.left = pWnd->rectWindow.left + x; + rect.top = pWnd->rectWindow.top + y; + rect.right = pWnd->rectWindow.right + x; + rect.bottom = pWnd->rectWindow.bottom + y; if( IntersectRect( &rect, &rect, lpRect )) { if(!REGION_UnionRectWithRgn( hrgnClip, &rect )) break; } } - WIN_ReleaseWndPtr(pWndStart); - return (pWndStart == pWndEnd); + start = pWnd->hwndSelf; + WIN_ReleaseWndPtr(pWnd); + return (start == end); } @@ -242,7 +243,7 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags ) else xoffset = yoffset = 0; - DCE_AddClipRects( wndPtr->child, NULL, hrgnClip, &rect, xoffset, yoffset ); + DCE_AddClipRects( wndPtr->child->hwndSelf, 0, hrgnClip, &rect, xoffset, yoffset ); } /* We may need to clip children of child window, if a window with PARENTDC @@ -267,7 +268,7 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags ) xoffset += childWnd->rectClient.left; yoffset += childWnd->rectClient.top; - DCE_AddClipRects( childWnd->child, NULL, hrgnClip, + DCE_AddClipRects( childWnd->child->hwndSelf, 0, hrgnClip, &rect, xoffset, yoffset ); } @@ -286,8 +287,8 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags ) } if (flags & DCX_CLIPSIBLINGS && wndPtr->parent ) - DCE_AddClipRects( wndPtr->parent->child, - wndPtr, hrgnClip, &rect, xoffset, yoffset ); + DCE_AddClipRects( GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ), + wndPtr->hwndSelf, hrgnClip, &rect, xoffset, yoffset ); /* Clip siblings of all ancestors that have the * WS_CLIPSIBLINGS style @@ -295,13 +296,15 @@ static HRGN DCE_GetVisRgn( HWND hwnd, WORD flags, HWND hwndChild, WORD cflags ) while (wndPtr->parent) { - WIN_UpdateWndPtr(&wndPtr,wndPtr->parent); + WND *ptr = WIN_FindWndPtr( wndPtr->parent ); + WIN_ReleaseWndPtr( wndPtr ); + wndPtr = ptr; xoffset -= wndPtr->rectClient.left; yoffset -= wndPtr->rectClient.top; if(wndPtr->dwStyle & WS_CLIPSIBLINGS && wndPtr->parent) { - DCE_AddClipRects( wndPtr->parent->child, wndPtr, - hrgnClip, &rect, xoffset, yoffset ); + DCE_AddClipRects( GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ), + wndPtr->hwndSelf, hrgnClip, &rect, xoffset, yoffset ); } } @@ -364,7 +367,7 @@ BOOL TTYDRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags ) { if (flags & DCX_PARENTCLIP) { - WND *parentPtr = WIN_LockWndPtr(wndPtr->parent); + WND *parentPtr = WIN_FindWndPtr( wndPtr->parent ); if( wndPtr->dwStyle & WS_VISIBLE && !(parentPtr->dwStyle & WS_MINIMIZE) ) { @@ -534,7 +537,10 @@ BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos ) } if( winpos->hwndInsertAfter == HWND_TOP ) - winpos->flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0; + { + if (GetWindow( wndPtr->hwndSelf, GW_HWNDFIRST ) == wndPtr->hwndSelf) + winpos->flags |= SWP_NOZORDER; + } else if( winpos->hwndInsertAfter == HWND_BOTTOM ) winpos->flags |= ( wndPtr->next )? 0: SWP_NOZORDER; @@ -583,14 +589,11 @@ BOOL TTYDRV_SetWindowPos( WINDOWPOS *winpos ) if( !(winpos->flags & SWP_NOREDRAW) ) { - RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, + RedrawWindow( wndPtr->parent, NULL, 0, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN ); - if (wndPtr->parent->hwndSelf == GetDesktopWindow() || - wndPtr->parent->parent->hwndSelf == GetDesktopWindow()) - { - RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, + if (wndPtr->parent == GetDesktopWindow()) + RedrawWindow( wndPtr->parent, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN ); - } } if (!(winpos->flags & SWP_NOACTIVATE)) diff --git a/dlls/x11drv/window.c b/dlls/x11drv/window.c index 524ba99a0bbf3e8b28620bda2e0fdc33716c37ca..b1a59059b94908ae18f1b50ebe2cf6219c6bfd1e 100644 --- a/dlls/x11drv/window.c +++ b/dlls/x11drv/window.c @@ -76,8 +76,7 @@ inline static BOOL is_window_managed( WND *win ) */ inline static BOOL is_window_top_level( WND *win ) { - return (root_window == DefaultRootWindow(gdi_display) && - win->parent->hwndSelf == GetDesktopWindow()); + return (root_window == DefaultRootWindow(gdi_display) && win->parent == GetDesktopWindow()); } @@ -633,7 +632,7 @@ static Window create_whole_window( Display *display, WND *win ) if (!(cx = rect.right - rect.left)) cx = 1; if (!(cy = rect.bottom - rect.top)) cy = 1; - parent = get_client_window( win->parent ); + parent = X11DRV_get_client_window( win->parent ); wine_tsx11_lock(); @@ -887,9 +886,9 @@ BOOL X11DRV_CreateWindow( HWND hwnd, CREATESTRUCTA *cs, BOOL unicode ) (unsigned int)data->whole_window, (unsigned int)data->client_window ); if ((wndPtr->dwStyle & (WS_CHILD|WS_MAXIMIZE)) == WS_CHILD) - WIN_LinkWindow( hwnd, wndPtr->parent->hwndSelf, HWND_BOTTOM ); + WIN_LinkWindow( hwnd, wndPtr->parent, HWND_BOTTOM ); else - WIN_LinkWindow( hwnd, wndPtr->parent->hwndSelf, HWND_TOP ); + WIN_LinkWindow( hwnd, wndPtr->parent, HWND_TOP ); WIN_ReleaseWndPtr( wndPtr ); @@ -1009,7 +1008,7 @@ HWND X11DRV_SetParent( HWND hwnd, HWND parent ) * including the WM_SHOWWINDOW messages and all */ if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE ); - retvalue = wndPtr->parent->hwndSelf; /* old parent */ + retvalue = wndPtr->parent; /* old parent */ if (parent != retvalue) { struct x11drv_win_data *data = wndPtr->pDriverData; diff --git a/dlls/x11drv/winpos.c b/dlls/x11drv/winpos.c index 0d4c286f2652061451660be947e75b0e19ea14a0..218186ad54297d0f426f93750952b14204c83459 100644 --- a/dlls/x11drv/winpos.c +++ b/dlls/x11drv/winpos.c @@ -59,37 +59,48 @@ DEFAULT_DEBUG_CHANNEL(x11drv); * * Clip all children of a given window out of the visible region */ -static int clip_children( WND *win, WND *last, HRGN hrgn, int whole_window ) +static int clip_children( HWND parent, HWND last, HRGN hrgn, int whole_window ) { + HWND *list; WND *ptr; HRGN rectRgn; - int x, y, ret = SIMPLEREGION; + int i, x, y, ret = SIMPLEREGION; /* first check if we have anything to do */ - for (ptr = win->child; ptr && ptr != last; ptr = ptr->next) - if (ptr->dwStyle & WS_VISIBLE) break; - if (!ptr || ptr == last) return ret; /* no children to clip */ + if (!(list = WIN_ListChildren( parent ))) return ret; + for (i = 0; list[i] && list[i] != last; i++) + if (GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE) break; + if (!list[i] || list[i] == last) goto done; /* no children to clip */ if (whole_window) { + WND *win = WIN_FindWndPtr( parent ); x = win->rectWindow.left - win->rectClient.left; y = win->rectWindow.top - win->rectClient.top; + WIN_ReleaseWndPtr( win ); } else x = y = 0; rectRgn = CreateRectRgn( 0, 0, 0, 0 ); - while (ptr && ptr != last) + + for ( ; list[i] && list[i] != last; i++) { + if (!(ptr = WIN_FindWndPtr( list[i] ))) continue; if (ptr->dwStyle & WS_VISIBLE) { SetRectRgn( rectRgn, ptr->rectWindow.left + x, ptr->rectWindow.top + y, ptr->rectWindow.right + x, ptr->rectWindow.bottom + y ); if ((ret = CombineRgn( hrgn, hrgn, rectRgn, RGN_DIFF )) == NULLREGION) + { + WIN_ReleaseWndPtr( ptr ); break; /* no need to go on, region is empty */ + } } - ptr = ptr->next; + WIN_ReleaseWndPtr( ptr ); } DeleteObject( rectRgn ); + done: + HeapFree( GetProcessHeap(), 0, list ); return ret; } @@ -99,7 +110,7 @@ static int clip_children( WND *win, WND *last, HRGN hrgn, int whole_window ) * * Compute the visible region of a window */ -static HRGN get_visible_region( WND *win, WND *top, UINT flags, int mode ) +static HRGN get_visible_region( WND *win, HWND top, UINT flags, int mode ) { HRGN rgn; RECT rect; @@ -118,7 +129,7 @@ static HRGN get_visible_region( WND *win, WND *top, UINT flags, int mode ) } if (flags & DCX_PARENTCLIP) - GetClientRect( win->parent->hwndSelf, &rect ); + GetClientRect( win->parent, &rect ); else if (flags & DCX_WINDOW) rect = data->whole_rect; else @@ -132,12 +143,12 @@ static HRGN get_visible_region( WND *win, WND *top, UINT flags, int mode ) if ((flags & DCX_CLIPCHILDREN) && (mode != ClipByChildren)) { /* we need to clip children by hand */ - if (clip_children( win, NULL, rgn, (flags & DCX_WINDOW) ) == NULLREGION) return rgn; + if (clip_children( win->hwndSelf, 0, rgn, (flags & DCX_WINDOW) ) == NULLREGION) return rgn; } - if (top && top != win) /* need to clip siblings of ancestors */ + if (top && top != win->hwndSelf) /* need to clip siblings of ancestors */ { - WND *ptr = win; + WND *parent, *ptr = WIN_LockWndPtr( win ); HRGN tmp = 0; OffsetRgn( rgn, xoffset, yoffset ); @@ -145,10 +156,12 @@ static HRGN get_visible_region( WND *win, WND *top, UINT flags, int mode ) { if (ptr->dwStyle & WS_CLIPSIBLINGS) { - if (clip_children( ptr->parent, ptr, rgn, FALSE ) == NULLREGION) break; + if (clip_children( ptr->parent, ptr->hwndSelf, rgn, FALSE ) == NULLREGION) break; } - if (ptr == top) break; - ptr = ptr->parent; + if (ptr->hwndSelf == top) break; + if (!(parent = WIN_FindWndPtr( ptr->parent ))) break; + WIN_ReleaseWndPtr( ptr ); + ptr = parent; /* clip to parent client area */ if (tmp) SetRectRgn( tmp, 0, 0, ptr->rectClient.right - ptr->rectClient.left, ptr->rectClient.bottom - ptr->rectClient.top ); @@ -159,6 +172,7 @@ static HRGN get_visible_region( WND *win, WND *top, UINT flags, int mode ) xoffset += ptr->rectClient.left; yoffset += ptr->rectClient.top; } + WIN_ReleaseWndPtr( ptr ); /* make it relative to the target window again */ OffsetRgn( rgn, -xoffset, -yoffset ); if (tmp) DeleteObject( tmp ); @@ -180,7 +194,7 @@ static int get_covered_region( WND *win, HRGN rgn ) { HRGN tmp; int ret; - WND *ptr = win; + WND *parent, *ptr = WIN_LockWndPtr( win ); int xoffset = 0, yoffset = 0; tmp = CreateRectRgn( 0, 0, 0, 0 ); @@ -193,13 +207,16 @@ static int get_covered_region( WND *win, HRGN rgn ) { if (!(ptr->dwStyle & WS_CLIPSIBLINGS)) { - if (clip_children( ptr->parent, ptr, tmp, FALSE ) == NULLREGION) break; + if (clip_children( ptr->parent, ptr->hwndSelf, tmp, FALSE ) == NULLREGION) break; } - if (!(ptr = ptr->parent)) break; + if (!(parent = WIN_FindWndPtr( ptr->parent ))) break; + WIN_ReleaseWndPtr( ptr ); + ptr = parent; OffsetRgn( tmp, ptr->rectClient.left, ptr->rectClient.top ); xoffset += ptr->rectClient.left; yoffset += ptr->rectClient.top; } + WIN_ReleaseWndPtr( ptr ); /* make it relative to the target window again */ OffsetRgn( tmp, -xoffset, -yoffset ); @@ -215,44 +232,58 @@ static int get_covered_region( WND *win, HRGN rgn ) * * Expose a region of a given window. */ -static void expose_window( WND *win, RECT *rect, HRGN rgn, int flags ) +static void expose_window( HWND hwnd, RECT *rect, HRGN rgn, int flags ) { - WND *ptr, *top; - int xoffset = 0, yoffset = 0; + POINT offset; + HWND top = 0; + HWND *list; + int i; /* find the top most parent that doesn't clip children or siblings and * invalidate the area on its parent, including all children */ - top = NULL; - for (ptr = win; ptr && ptr->parent; ptr = ptr->parent) + if ((list = WIN_ListParents( hwnd ))) { - if (!(ptr->dwStyle & WS_CLIPSIBLINGS)) top = ptr; - if (!(ptr->parent->dwStyle & WS_CLIPCHILDREN)) top = ptr; - } + HWND current = hwnd; + LONG style = GetWindowLongW( hwnd, GWL_STYLE ); + for (i = 0; list[i] && list[i] != GetDesktopWindow(); i++) + { + if (!(style & WS_CLIPSIBLINGS)) top = current; + style = GetWindowLongW( list[i], GWL_STYLE ); + if (!(style & WS_CLIPCHILDREN)) top = current; + current = list[i]; + } - if (top) - { - if (top->parent && top->parent->hwndSelf != GetDesktopWindow()) top = top->parent; - flags &= ~RDW_FRAME; /* parent will invalidate children frame anyway */ - flags |= RDW_ALLCHILDREN; + if (top) + { + /* find the parent of the top window, reusing the parent list */ + if (top == hwnd) i = 0; + else + { + for (i = 0; list[i]; i++) if (list[i] == top) break; + if (list[i] && list[i+1]) i++; + } + if (list[i] != GetDesktopWindow()) top = list[i]; + flags &= ~RDW_FRAME; /* parent will invalidate children frame anyway */ + flags |= RDW_ALLCHILDREN; + } + HeapFree( GetProcessHeap(), 0, list ); } - else top = win; + + if (!top) top = hwnd; /* make coords relative to top */ - for (ptr = win; ptr != top; ptr = ptr->parent) - { - xoffset += ptr->rectClient.left; - yoffset += ptr->rectClient.top; - } + offset.x = offset.y = 0; + MapWindowPoints( hwnd, top, &offset, 1 ); if (rect) { - OffsetRect( rect, xoffset, yoffset ); - RedrawWindow( top->hwndSelf, rect, 0, flags ); + OffsetRect( rect, offset.x, offset.y ); + RedrawWindow( top, rect, 0, flags ); } else { - OffsetRgn( rgn, xoffset, yoffset ); - RedrawWindow( top->hwndSelf, NULL, rgn, flags ); + OffsetRgn( rgn, offset.x, offset.y ); + RedrawWindow( top, NULL, rgn, flags ); } } @@ -327,7 +358,7 @@ static void expose_covered_window_area( WND *win, const RECT *old_client_rect, B if (ret != NULLREGION) { if (get_covered_region( win, hrgn ) != NULLREGION) - expose_window( win, NULL, hrgn, + expose_window( win->hwndSelf, NULL, hrgn, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN ); } @@ -362,9 +393,9 @@ void X11DRV_Expose( HWND hwnd, XExposeEvent *event ) /* make position relative to client area instead of window */ OffsetRect( &rect, -data->client_rect.left, -data->client_rect.top ); } - - expose_window( win, &rect, 0, flags ); WIN_ReleaseWndPtr( win ); + + expose_window( hwnd, &rect, 0, flags ); } @@ -377,49 +408,53 @@ void X11DRV_Expose( HWND hwnd, XExposeEvent *event ) BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags ) { WND *win = WIN_FindWndPtr( hwnd ); - WND *ptr, *top; + HWND top = 0; X11DRV_WND_DATA *data = win->pDriverData; Drawable drawable; BOOL visible; - int org_x, org_y, mode = IncludeInferiors; + POINT org; + int mode = IncludeInferiors; /* don't clip siblings if using parent clip region */ if (flags & DCX_PARENTCLIP) flags &= ~DCX_CLIPSIBLINGS; /* find the top parent in the hierarchy that isn't clipping siblings */ - top = NULL; visible = (win->dwStyle & WS_VISIBLE) != 0; if (visible) { - for (ptr = win->parent; ptr && ptr->parent; ptr = ptr->parent) + HWND *list = WIN_ListParents( hwnd ); + if (list) { - if (!(ptr->dwStyle & WS_VISIBLE)) + int i; + for (i = 0; list[i] != GetDesktopWindow(); i++) { - visible = FALSE; - top = NULL; - break; + LONG style = GetWindowLongW( list[i], GWL_STYLE ); + if (!(style & WS_VISIBLE)) + { + visible = FALSE; + top = 0; + break; + } + if (!(style & WS_CLIPSIBLINGS)) top = list[i]; } - if (!(ptr->dwStyle & WS_CLIPSIBLINGS)) top = ptr; + HeapFree( GetProcessHeap(), 0, list ); } - if (!top && visible && !(flags & DCX_CLIPSIBLINGS)) top = win; + if (!top && visible && !(flags & DCX_CLIPSIBLINGS)) top = hwnd; } if (top) { - org_x = org_y = 0; + HWND parent = GetAncestor( top, GA_PARENT ); + org.x = org.y = 0; if (flags & DCX_WINDOW) { - org_x = win->rectWindow.left - win->rectClient.left; - org_y = win->rectWindow.top - win->rectClient.top; - } - for (ptr = win; ptr != top->parent; ptr = ptr->parent) - { - org_x += ptr->rectClient.left; - org_y += ptr->rectClient.top; + org.x = win->rectWindow.left - win->rectClient.left; + org.y = win->rectWindow.top - win->rectClient.top; } + MapWindowPoints( hwnd, parent, &org, 1 ); /* have to use the parent so that we include siblings */ - if (top->parent) drawable = get_client_window( top->parent ); + if (parent) drawable = X11DRV_get_client_window( parent ); else drawable = root_window; } else @@ -427,25 +462,25 @@ BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags ) if (IsIconic( hwnd )) { drawable = data->icon_window ? data->icon_window : data->whole_window; - org_x = 0; - org_y = 0; + org.x = 0; + org.y = 0; } else if (flags & DCX_WINDOW) { drawable = data->whole_window; - org_x = win->rectWindow.left - data->whole_rect.left; - org_y = win->rectWindow.top - data->whole_rect.top; + org.x = win->rectWindow.left - data->whole_rect.left; + org.y = win->rectWindow.top - data->whole_rect.top; } else { drawable = data->client_window; - org_x = 0; - org_y = 0; + org.x = 0; + org.y = 0; if (flags & DCX_CLIPCHILDREN) mode = ClipByChildren; /* can use X11 clipping */ } } - X11DRV_SetDrawable( hdc, drawable, mode, org_x, org_y ); + X11DRV_SetDrawable( hdc, drawable, mode, org.x, org.y ); if (flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN) || SetHookFlags16( hdc, DCHF_VALIDATEVISRGN )) /* DC was dirty */ @@ -462,7 +497,7 @@ BOOL X11DRV_GetDC( HWND hwnd, HDC hdc, HRGN hrgn, DWORD flags ) (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF ); /* make it relative to the drawable origin */ - OffsetRgn( visRgn, org_x, org_y ); + OffsetRgn( visRgn, org.x, org.y ); } else visRgn = CreateRectRgn( 0, 0, 0, 0 ); @@ -893,9 +928,10 @@ BOOL X11DRV_SetWindowPos( WINDOWPOS *winpos ) static POINT WINPOS_FindIconPos( WND* wndPtr, POINT pt ) { RECT rectParent; + HWND *list; short x, y, xspacing, yspacing; - GetClientRect( wndPtr->parent->hwndSelf, &rectParent ); + GetClientRect( wndPtr->parent, &rectParent ); if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) && (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom)) return pt; /* The icon already has a suitable position */ @@ -903,34 +939,48 @@ static POINT WINPOS_FindIconPos( WND* wndPtr, POINT pt ) xspacing = GetSystemMetrics(SM_CXICONSPACING); yspacing = GetSystemMetrics(SM_CYICONSPACING); + list = WIN_ListChildren( wndPtr->parent ); y = rectParent.bottom; for (;;) { x = rectParent.left; do { - /* Check if another icon already occupies this spot */ - WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child); - while (childPtr) + /* Check if another icon already occupies this spot */ + /* FIXME: this is completely inefficient */ + if (list) { - if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr)) + int i; + WND *childPtr; + + for (i = 0; list[i]; i++) { + if (list[i] == wndPtr->hwndSelf) continue; + if (!IsIconic( list[i] )) continue; + if (!(childPtr = WIN_FindWndPtr( list[i] ))) continue; if ((childPtr->rectWindow.left < x + xspacing) && (childPtr->rectWindow.right >= x) && (childPtr->rectWindow.top <= y) && (childPtr->rectWindow.bottom > y - yspacing)) + { + WIN_ReleaseWndPtr( childPtr ); break; /* There's a window in there */ + } + WIN_ReleaseWndPtr( childPtr ); + } + if (list[i]) + { + /* found something here, try next spot */ + x += xspacing; + continue; } - WIN_UpdateWndPtr(&childPtr,childPtr->next); - } - WIN_ReleaseWndPtr(childPtr); - if (!childPtr) /* No window was found, so it's OK for us */ - { - pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2; - pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2; - return pt; } - x += xspacing; + + /* No window was found, so it's OK for us */ + pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2; + pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2; + return pt; + } while(x <= rectParent.right-xspacing); y -= yspacing; } @@ -1990,35 +2040,42 @@ void X11DRV_SysCommandSizeMove( HWND hwnd, WPARAM wParam ) */ void X11DRV_ForceWindowRaise( HWND hwnd ) { + int i = 0; + HWND *list; XWindowChanges winChanges; Display *display = thread_display(); - WND *wndPrev, *wndPtr = WIN_FindWndPtr( hwnd ); + WND *wndPtr = WIN_FindWndPtr( hwnd ); if (!wndPtr) return; if ((wndPtr->dwExStyle & WS_EX_MANAGED) || - wndPtr->parent->hwndSelf != GetDesktopWindow() || + wndPtr->parent != GetDesktopWindow() || IsRectEmpty( &wndPtr->rectWindow ) || !get_whole_window(wndPtr)) { WIN_ReleaseWndPtr( wndPtr ); return; } + WIN_ReleaseWndPtr( wndPtr ); /* Raise all windows up to wndPtr according to their Z order. * (it would be easier with sibling-related Below but it doesn't * work very well with SGI mwm for instance) */ winChanges.stack_mode = Above; - while (wndPtr) + if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return; + while (list[i] && list[i] != hwnd) i++; + if (list[i]) { - if (!IsRectEmpty( &wndPtr->rectWindow ) && get_whole_window(wndPtr)) - TSXReconfigureWMWindow( display, get_whole_window(wndPtr), 0, - CWStackMode, &winChanges ); - wndPrev = wndPtr->parent->child; - if (wndPrev == wndPtr) break; - while (wndPrev && (wndPrev->next != wndPtr)) wndPrev = wndPrev->next; - WIN_UpdateWndPtr( &wndPtr, wndPrev ); + for ( ; i >= 0; i--) + { + WND *ptr = WIN_FindWndPtr( list[i] ); + if (!ptr) continue; + if (!IsRectEmpty( &ptr->rectWindow ) && get_whole_window(ptr)) + TSXReconfigureWMWindow( display, get_whole_window(ptr), 0, + CWStackMode, &winChanges ); + WIN_ReleaseWndPtr( ptr ); + } } - WIN_ReleaseWndPtr( wndPtr ); + HeapFree( GetProcessHeap(), 0, list ); } diff --git a/include/win.h b/include/win.h index 42577afb3be17222a8f149da70f9907dbdc8387e..829e075f657573369108a48a4d2711554da7a6f9 100644 --- a/include/win.h +++ b/include/win.h @@ -24,7 +24,7 @@ typedef struct tagWND { struct tagWND *next; /* Next sibling */ struct tagWND *child; /* First child */ - struct tagWND *parent; /* Window parent (from CreateWindow) */ + HWND parent; /* Window parent */ HWND owner; /* Window owner */ struct tagCLASS *class; /* Window class */ HWINDOWPROC winproc; /* Window procedure */ diff --git a/windows/win.c b/windows/win.c index 440bbdff292d9bf8e80035d1b4b5a675bdc98ca9..86fe6a51b299f5854ee51d707b22d81f13a28cd5 100644 --- a/windows/win.c +++ b/windows/win.c @@ -406,14 +406,16 @@ void WIN_LinkWindow( HWND hwnd, HWND parent, HWND hwndInsertAfter ) /* first unlink it if it is linked */ if (wndPtr->parent) { - ppWnd = &wndPtr->parent->child; + WND *ptr = WIN_FindWndPtr( wndPtr->parent ); + ppWnd = &ptr->child; while (*ppWnd && *ppWnd != wndPtr) ppWnd = &(*ppWnd)->next; if (*ppWnd) *ppWnd = wndPtr->next; + WIN_ReleaseWndPtr( ptr ); } if (parentPtr) { - wndPtr->parent = parentPtr; + wndPtr->parent = parentPtr->hwndSelf; if ((hwndInsertAfter == HWND_TOP) || (hwndInsertAfter == HWND_BOTTOM)) { ppWnd = &parentPtr->child; /* Point to first sibling hwnd */ @@ -622,7 +624,7 @@ BOOL WIN_CreateDesktopWindow(void) pWndDesktop->tid = 0; /* nobody owns the desktop */ pWndDesktop->next = NULL; pWndDesktop->child = NULL; - pWndDesktop->parent = NULL; + pWndDesktop->parent = 0; pWndDesktop->owner = 0; pWndDesktop->class = class; pWndDesktop->hInstance = 0; @@ -777,7 +779,16 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, WARN("Bad parent %04x\n", cs->hwndParent ); return 0; } - if (cs->style & WS_CHILD) parent = cs->hwndParent; + if (cs->style & WS_CHILD) + { + parent = WIN_GetFullHandle(cs->hwndParent); + if (!WIN_IsCurrentProcess(parent)) + { + FIXME( "creating child window of %x in other process not supported yet\n", + parent ); + return 0; + } + } else owner = GetAncestor( cs->hwndParent, GA_ROOT ); } else if ((cs->style & WS_CHILD) && !(cs->style & WS_POPUP)) @@ -831,9 +842,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, wndPtr->next = NULL; wndPtr->child = NULL; wndPtr->owner = owner; - wndPtr->parent = WIN_FindWndPtr( parent ); - WIN_ReleaseWndPtr(wndPtr->parent); - + wndPtr->parent = parent; wndPtr->class = classPtr; wndPtr->winproc = winproc; wndPtr->hInstance = cs->hInstance; @@ -964,7 +973,7 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, { /* Notify the parent window only */ - SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY, + SendMessageA( wndPtr->parent, WM_PARENTNOTIFY, MAKEWPARAM(WM_CREATE, wndPtr->wIDmenu), (LPARAM)hwnd ); if( !IsWindow(hwnd) ) { @@ -1262,8 +1271,8 @@ BOOL WINAPI DestroyWindow( HWND hwnd ) if( wndPtr->dwStyle & WS_CHILD && !(wndPtr->dwExStyle & WS_EX_NOPARENTNOTIFY) ) { /* Notify the parent window only */ - SendMessageA( wndPtr->parent->hwndSelf, WM_PARENTNOTIFY, - MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd ); + SendMessageA( wndPtr->parent, WM_PARENTNOTIFY, + MAKEWPARAM(WM_DESTROY, wndPtr->wIDmenu), (LPARAM)hwnd ); if( !IsWindow(hwnd) ) { retvalue = TRUE; @@ -1292,7 +1301,7 @@ BOOL WINAPI DestroyWindow( HWND hwnd ) for (;;) { int i, got_one = 0; - HWND *list = WIN_ListChildren( wndPtr->parent->hwndSelf ); + HWND *list = WIN_ListChildren( wndPtr->parent ); if (list) { for (i = 0; list[i]; i++) @@ -2092,7 +2101,7 @@ HWND WINAPI GetParent( HWND hwnd ) if ((wndPtr = WIN_FindWndPtr(hwnd))) { if (wndPtr->dwStyle & WS_CHILD) - retvalue = wndPtr->parent->hwndSelf; + retvalue = wndPtr->parent; else if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner; WIN_ReleaseWndPtr(wndPtr); @@ -2107,34 +2116,42 @@ HWND WINAPI GetParent( HWND hwnd ) HWND WINAPI GetAncestor( HWND hwnd, UINT type ) { HWND ret = 0; - WND *wndPtr; + size_t size = (type == GA_PARENT) ? sizeof(user_handle_t) : REQUEST_MAX_VAR_SIZE; - if (!(wndPtr = WIN_FindWndPtr(hwnd))) return 0; - if (wndPtr->hwndSelf == GetDesktopWindow()) goto done; - - switch(type) - { - case GA_PARENT: - WIN_UpdateWndPtr( &wndPtr, wndPtr->parent ); - break; - case GA_ROOT: - while (wndPtr->parent->hwndSelf != GetDesktopWindow()) - WIN_UpdateWndPtr( &wndPtr, wndPtr->parent ); - break; - case GA_ROOTOWNER: - while (wndPtr->parent->hwndSelf != GetDesktopWindow()) - WIN_UpdateWndPtr( &wndPtr, wndPtr->parent ); - while (wndPtr && wndPtr->owner) + SERVER_START_VAR_REQ( get_window_parents, size ) + { + req->handle = hwnd; + if (!SERVER_CALL()) { - WND *ptr = WIN_FindWndPtr( wndPtr->owner ); - WIN_ReleaseWndPtr( wndPtr ); - wndPtr = ptr; + user_handle_t *data = server_data_ptr(req); + int count = server_data_size(req) / sizeof(*data); + if (count) + { + switch(type) + { + case GA_PARENT: + ret = data[0]; + break; + case GA_ROOT: + case GA_ROOTOWNER: + if (count > 1) ret = data[count - 2]; /* get the one before the desktop */ + else ret = WIN_GetFullHandle( hwnd ); + break; + } + } + } + } + SERVER_END_VAR_REQ; + + if (ret && type == GA_ROOTOWNER) + { + for (;;) + { + HWND owner = GetWindow( ret, GW_OWNER ); + if (!owner) break; + ret = owner; } - break; } - ret = wndPtr ? wndPtr->hwndSelf : 0; - done: - WIN_ReleaseWndPtr( wndPtr ); return ret; } @@ -2169,7 +2186,7 @@ HWND WINAPI SetParent( HWND hwnd, HWND parent ) * including the WM_SHOWWINDOW messages and all */ if (dwStyle & WS_VISIBLE) ShowWindow( hwnd, SW_HIDE ); - retvalue = wndPtr->parent->hwndSelf; /* old parent */ + retvalue = wndPtr->parent; /* old parent */ if (parent != retvalue) { WIN_LinkWindow( hwnd, parent, HWND_TOP ); diff --git a/windows/winpos.c b/windows/winpos.c index 285f5b5308ad211a7e8881aaaa2b117377d5c286..34522236bbebaf54efb9b9b0efd8cbd6d0ccf769 100644 --- a/windows/winpos.c +++ b/windows/winpos.c @@ -309,7 +309,7 @@ HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest ) } if (wndScope->parent) - MapWindowPoints( GetDesktopWindow(), wndScope->parent->hwndSelf, &xy, 1 ); + MapWindowPoints( GetDesktopWindow(), wndScope->parent, &xy, 1 ); if (xy.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right || xy.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom || @@ -401,7 +401,7 @@ hittest: /* Restart the search from the next sibling */ WIN_UpdateWndPtr(&wndPtr,wndTmp->next); - hwnd_ret = wndTmp->parent ? wndTmp->parent->hwndSelf : 0; + hwnd_ret = wndTmp->parent; WIN_ReleaseWndPtr( wndTmp ); } @@ -477,6 +477,8 @@ static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset ) { WND * wndPtr = 0; + HWND *list; + int i; offset->x = offset->y = 0; if (hwndFrom == hwndTo ) return; @@ -489,11 +491,16 @@ static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, ERR("bad hwndFrom = %04x\n",hwndFrom); return; } - while (wndPtr->parent) + if ((list = WIN_ListParents( hwndFrom ))) { - offset->x += wndPtr->rectClient.left; - offset->y += wndPtr->rectClient.top; - WIN_UpdateWndPtr(&wndPtr,wndPtr->parent); + for (i = 0; list[i]; i++) + { + offset->x += wndPtr->rectClient.left; + offset->y += wndPtr->rectClient.top; + WIN_ReleaseWndPtr( wndPtr ); + if (!(wndPtr = WIN_FindWndPtr( list[i] ))) break; + } + HeapFree( GetProcessHeap(), 0, list ); } WIN_ReleaseWndPtr(wndPtr); } @@ -506,12 +513,17 @@ static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, ERR("bad hwndTo = %04x\n", hwndTo ); return; } - while (wndPtr->parent) + if ((list = WIN_ListParents( hwndTo ))) { - offset->x -= wndPtr->rectClient.left; - offset->y -= wndPtr->rectClient.top; - WIN_UpdateWndPtr(&wndPtr,wndPtr->parent); - } + for (i = 0; list[i]; i++) + { + offset->x -= wndPtr->rectClient.left; + offset->y -= wndPtr->rectClient.top; + WIN_ReleaseWndPtr( wndPtr ); + if (!(wndPtr = WIN_FindWndPtr( list[i] ))) break; + } + HeapFree( GetProcessHeap(), 0, list ); + } WIN_ReleaseWndPtr(wndPtr); } }