2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996 Alex Korobka
9 #include "sysmetrics.h"
21 #include "nonclient.h"
25 #define HAS_DLGFRAME(style,exStyle) \
26 (((exStyle) & WS_EX_DLGMODALFRAME) || \
27 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
29 #define HAS_THICKFRAME(style) \
30 (((style) & WS_THICKFRAME) && \
31 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
33 #define SWP_AGG_NOGEOMETRYCHANGE \
34 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
35 #define SWP_AGG_NOPOSCHANGE \
36 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
37 #define SWP_AGG_STATUSFLAGS \
38 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
40 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
42 #define PLACE_MIN 0x0001
43 #define PLACE_MAX 0x0002
44 #define PLACE_RECT 0x0004
46 #define SMC_NOCOPY 0x0001
47 #define SMC_NOPARENTERASE 0x0002
48 #define SMC_DRAWFRAME 0x0004
49 #define SMC_SETXPOS 0x0008
51 /* ----- internal variables ----- */
53 static HWND32 hwndActive = 0; /* Currently active window */
54 static HWND32 hwndPrevActive = 0; /* Previously active window */
55 static HWND32 hGlobalShellWindow=0; /*the shell*/
57 static LPCSTR atomInternalPos;
59 extern MESSAGEQUEUE* pActiveQueue;
61 /***********************************************************************
62 * WINPOS_CreateInternalPosAtom
64 BOOL32 WINPOS_CreateInternalPosAtom()
67 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtom32A(str);
68 return (atomInternalPos) ? TRUE : FALSE;
71 /***********************************************************************
72 * WINPOS_CheckInternalPos
74 * Called when a window is destroyed.
76 void WINPOS_CheckInternalPos( HWND32 hwnd )
78 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetProp32A( hwnd, atomInternalPos );
80 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
81 if( hwnd == hwndActive )
84 WARN(win, "\tattempt to activate destroyed window!\n");
89 if( IsWindow32(lpPos->hwndIconTitle) )
90 DestroyWindow32( lpPos->hwndIconTitle );
91 HeapFree( SystemHeap, 0, lpPos );
95 /***********************************************************************
98 * Find a suitable place for an iconic window.
100 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
103 short x, y, xspacing, yspacing;
105 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
106 if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
107 (pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
108 return pt; /* The icon already has a suitable position */
110 xspacing = SYSMETRICS_CXICONSPACING;
111 yspacing = SYSMETRICS_CYICONSPACING;
113 y = rectParent.bottom;
116 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
118 /* Check if another icon already occupies this spot */
119 WND *childPtr = wndPtr->parent->child;
122 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
124 if ((childPtr->rectWindow.left < x + xspacing) &&
125 (childPtr->rectWindow.right >= x) &&
126 (childPtr->rectWindow.top <= y) &&
127 (childPtr->rectWindow.bottom > y - yspacing))
128 break; /* There's a window in there */
130 childPtr = childPtr->next;
132 if (!childPtr) /* No window was found, so it's OK for us */
134 pt.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
135 pt.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
144 /***********************************************************************
145 * ArrangeIconicWindows16 (USER.170)
147 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
149 return ArrangeIconicWindows32(parent);
151 /***********************************************************************
152 * ArrangeIconicWindows32 (USER32.7)
154 UINT32 WINAPI ArrangeIconicWindows32( HWND32 parent )
158 INT32 x, y, xspacing, yspacing;
160 GetClientRect32( parent, &rectParent );
162 y = rectParent.bottom;
163 xspacing = SYSMETRICS_CXICONSPACING;
164 yspacing = SYSMETRICS_CYICONSPACING;
166 hwndChild = GetWindow32( parent, GW_CHILD );
169 if( IsIconic32( hwndChild ) )
171 WINPOS_ShowIconTitle( WIN_FindWndPtr(hwndChild), FALSE );
172 SetWindowPos32( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
173 y - yspacing - SYSMETRICS_CYICON/2, 0, 0,
174 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
175 if( IsWindow32(hwndChild) )
176 WINPOS_ShowIconTitle( WIN_FindWndPtr(hwndChild), TRUE );
177 if (x <= rectParent.right - xspacing) x += xspacing;
184 hwndChild = GetWindow32( hwndChild, GW_HWNDNEXT );
190 /***********************************************************************
191 * SwitchToThisWindow16 (USER.172)
193 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
195 SwitchToThisWindow32( hwnd, restore );
199 /***********************************************************************
200 * SwitchToThisWindow32 (USER32.539)
202 void WINAPI SwitchToThisWindow32( HWND32 hwnd, BOOL32 restore )
204 ShowWindow32( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
208 /***********************************************************************
209 * GetWindowRect16 (USER.32)
211 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
213 WND * wndPtr = WIN_FindWndPtr( hwnd );
216 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
217 if (wndPtr->dwStyle & WS_CHILD)
218 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
222 /***********************************************************************
223 * GetWindowRect32 (USER32.308)
225 BOOL32 WINAPI GetWindowRect32( HWND32 hwnd, LPRECT32 rect )
227 WND * wndPtr = WIN_FindWndPtr( hwnd );
228 if (!wndPtr) return FALSE;
230 *rect = wndPtr->rectWindow;
231 if (wndPtr->dwStyle & WS_CHILD)
232 MapWindowPoints32( wndPtr->parent->hwndSelf, 0, (POINT32 *)rect, 2 );
237 /***********************************************************************
240 BOOL32 WINAPI GetWindowRgn32 ( HWND32 hwnd, HRGN32 hrgn )
244 WND * wndPtr = WIN_FindWndPtr( hwnd );
245 if (!wndPtr) return (ERROR);
247 FIXME (win, "GetWindowRgn32: doesn't really do regions\n");
249 memset (&rect, 0, sizeof(rect));
251 GetWindowRect32 ( hwnd, &rect );
253 FIXME (win, "Check whether a valid region here\n");
255 SetRectRgn32 ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
257 return (SIMPLEREGION);
260 /***********************************************************************
263 INT32 WINAPI SetWindowRgn32( HWND32 hwnd, HRGN32 hrgn,BOOL32 bRedraw)
267 FIXME (win, "SetWindowRgn32: stub\n");
271 /***********************************************************************
274 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
278 FIXME (win, "SetWindowRgn16: stub\n");
283 /***********************************************************************
284 * GetClientRect16 (USER.33)
286 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
288 WND * wndPtr = WIN_FindWndPtr( hwnd );
290 rect->left = rect->top = rect->right = rect->bottom = 0;
293 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
294 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
299 /***********************************************************************
300 * GetClientRect32 (USER32.220)
302 void WINAPI GetClientRect32( HWND32 hwnd, LPRECT32 rect )
304 WND * wndPtr = WIN_FindWndPtr( hwnd );
306 rect->left = rect->top = rect->right = rect->bottom = 0;
309 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
310 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
315 /*******************************************************************
316 * ClientToScreen16 (USER.28)
318 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
320 MapWindowPoints16( hwnd, 0, lppnt, 1 );
324 /*******************************************************************
325 * ClientToScreen32 (USER32.52)
327 BOOL32 WINAPI ClientToScreen32( HWND32 hwnd, LPPOINT32 lppnt )
329 MapWindowPoints32( hwnd, 0, lppnt, 1 );
334 /*******************************************************************
335 * ScreenToClient16 (USER.29)
337 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
339 MapWindowPoints16( 0, hwnd, lppnt, 1 );
343 /*******************************************************************
344 * ScreenToClient32 (USER32.447)
346 void WINAPI ScreenToClient32( HWND32 hwnd, LPPOINT32 lppnt )
348 MapWindowPoints32( 0, hwnd, lppnt, 1 );
352 /***********************************************************************
353 * WINPOS_WindowFromPoint
355 * Find the window and hittest for a given point.
357 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
360 INT16 hittest = HTERROR;
364 wndPtr = wndScope->child;
365 if( wndScope->flags & WIN_MANAGED )
367 /* this prevents mouse clicks from going "through" scrollbars in managed mode */
368 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
369 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
372 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
378 /* If point is in window, and window is visible, and it */
379 /* is enabled (or it's a top-level window), then explore */
380 /* its children. Otherwise, go to the next window. */
382 if ((wndPtr->dwStyle & WS_VISIBLE) &&
383 (!(wndPtr->dwStyle & WS_DISABLED) ||
384 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
385 (xy.x >= wndPtr->rectWindow.left) &&
386 (xy.x < wndPtr->rectWindow.right) &&
387 (xy.y >= wndPtr->rectWindow.top) &&
388 (xy.y < wndPtr->rectWindow.bottom))
390 *ppWnd = wndPtr; /* Got a suitable window */
392 /* If window is minimized or disabled, return at once */
393 if (wndPtr->dwStyle & WS_MINIMIZE) return HTCAPTION;
394 if (wndPtr->dwStyle & WS_DISABLED) return HTERROR;
396 /* If point is not in client area, ignore the children */
397 if ((xy.x < wndPtr->rectClient.left) ||
398 (xy.x >= wndPtr->rectClient.right) ||
399 (xy.y < wndPtr->rectClient.top) ||
400 (xy.y >= wndPtr->rectClient.bottom)) break;
402 xy.x -= wndPtr->rectClient.left;
403 xy.y -= wndPtr->rectClient.top;
404 wndPtr = wndPtr->child;
406 else wndPtr = wndPtr->next;
410 /* If nothing found, try the scope window */
411 if (!*ppWnd) *ppWnd = wndScope;
413 /* Send the WM_NCHITTEST message (only if to the same task) */
414 if ((*ppWnd)->hmemTaskQ == GetFastQueue())
416 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
417 0, MAKELONG( pt.x, pt.y ) );
418 if (hittest != HTTRANSPARENT) return hittest; /* Found the window */
420 else return HTCLIENT;
422 /* If no children found in last search, make point relative to parent */
425 xy.x += (*ppWnd)->rectClient.left;
426 xy.y += (*ppWnd)->rectClient.top;
429 /* Restart the search from the next sibling */
430 wndPtr = (*ppWnd)->next;
431 *ppWnd = (*ppWnd)->parent;
436 /*******************************************************************
437 * WindowFromPoint16 (USER.30)
439 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
442 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
443 return pWnd->hwndSelf;
447 /*******************************************************************
448 * WindowFromPoint32 (USER32.582)
450 HWND32 WINAPI WindowFromPoint32( POINT32 pt )
454 CONV_POINT32TO16( &pt, &pt16 );
455 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
456 return (HWND32)pWnd->hwndSelf;
460 /*******************************************************************
461 * ChildWindowFromPoint16 (USER.191)
463 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
466 CONV_POINT16TO32( &pt, &pt32 );
467 return (HWND16)ChildWindowFromPoint32( hwndParent, pt32 );
471 /*******************************************************************
472 * ChildWindowFromPoint32 (USER32.49)
474 HWND32 WINAPI ChildWindowFromPoint32( HWND32 hwndParent, POINT32 pt )
476 /* pt is in the client coordinates */
478 WND* wnd = WIN_FindWndPtr(hwndParent);
483 /* get client rect fast */
484 rect.top = rect.left = 0;
485 rect.right = wnd->rectClient.right - wnd->rectClient.left;
486 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
488 if (!PtInRect32( &rect, pt )) return 0;
493 if (PtInRect32( &wnd->rectWindow, pt )) return wnd->hwndSelf;
499 /*******************************************************************
500 * ChildWindowFromPointEx16 (USER.50)
502 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
505 CONV_POINT16TO32( &pt, &pt32 );
506 return (HWND16)ChildWindowFromPointEx32( hwndParent, pt32, uFlags );
510 /*******************************************************************
511 * ChildWindowFromPointEx32 (USER32.50)
513 HWND32 WINAPI ChildWindowFromPointEx32( HWND32 hwndParent, POINT32 pt,
516 /* pt is in the client coordinates */
518 WND* wnd = WIN_FindWndPtr(hwndParent);
523 /* get client rect fast */
524 rect.top = rect.left = 0;
525 rect.right = wnd->rectClient.right - wnd->rectClient.left;
526 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
528 if (!PtInRect32( &rect, pt )) return 0;
533 if (PtInRect32( &wnd->rectWindow, pt )) {
534 if ( (uFlags & CWP_SKIPINVISIBLE) &&
535 !(wnd->dwStyle & WS_VISIBLE) )
537 else if ( (uFlags & CWP_SKIPDISABLED) &&
538 (wnd->dwStyle & WS_DISABLED) )
540 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
541 (wnd->dwExStyle & WS_EX_TRANSPARENT) )
544 return wnd->hwndSelf;
551 /*******************************************************************
552 * WINPOS_GetWinOffset
554 * Calculate the offset between the origin of the two windows. Used
555 * to implement MapWindowPoints.
557 static void WINPOS_GetWinOffset( HWND32 hwndFrom, HWND32 hwndTo,
562 offset->x = offset->y = 0;
563 if (hwndFrom == hwndTo ) return;
565 /* Translate source window origin to screen coords */
568 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
570 ERR(win,"bad hwndFrom = %04x\n",hwndFrom);
573 while (wndPtr->parent)
575 offset->x += wndPtr->rectClient.left;
576 offset->y += wndPtr->rectClient.top;
577 wndPtr = wndPtr->parent;
581 /* Translate origin to destination window coords */
584 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
586 ERR(win,"bad hwndTo = %04x\n", hwndTo );
589 while (wndPtr->parent)
591 offset->x -= wndPtr->rectClient.left;
592 offset->y -= wndPtr->rectClient.top;
593 wndPtr = wndPtr->parent;
599 /*******************************************************************
600 * MapWindowPoints16 (USER.258)
602 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
603 LPPOINT16 lppt, UINT16 count )
607 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
617 /*******************************************************************
618 * MapWindowPoints32 (USER32.386)
620 void WINAPI MapWindowPoints32( HWND32 hwndFrom, HWND32 hwndTo,
621 LPPOINT32 lppt, UINT32 count )
625 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
635 /***********************************************************************
636 * IsIconic16 (USER.31)
638 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
640 return IsIconic32(hWnd);
644 /***********************************************************************
645 * IsIconic32 (USER32.345)
647 BOOL32 WINAPI IsIconic32(HWND32 hWnd)
649 WND * wndPtr = WIN_FindWndPtr(hWnd);
650 if (wndPtr == NULL) return FALSE;
651 return (wndPtr->dwStyle & WS_MINIMIZE) != 0;
655 /***********************************************************************
656 * IsZoomed (USER.272)
658 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
660 return IsZoomed32(hWnd);
664 /***********************************************************************
665 * IsZoomed (USER32.352)
667 BOOL32 WINAPI IsZoomed32(HWND32 hWnd)
669 WND * wndPtr = WIN_FindWndPtr(hWnd);
670 if (wndPtr == NULL) return FALSE;
671 return (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
675 /*******************************************************************
676 * GetActiveWindow (USER.60)
678 HWND16 WINAPI GetActiveWindow16(void)
680 return (HWND16)hwndActive;
683 /*******************************************************************
684 * GetActiveWindow (USER32.205)
686 HWND32 WINAPI GetActiveWindow32(void)
688 return (HWND32)hwndActive;
692 /*******************************************************************
695 static BOOL32 WINPOS_CanActivate(WND* pWnd)
697 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
698 == WS_VISIBLE) ) return TRUE;
703 /*******************************************************************
704 * SetActiveWindow16 (USER.59)
706 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
708 return SetActiveWindow32(hwnd);
712 /*******************************************************************
713 * SetActiveWindow32 (USER32.463)
715 HWND32 WINAPI SetActiveWindow32( HWND32 hwnd )
717 HWND32 prev = hwndActive;
718 WND *wndPtr = WIN_FindWndPtr( hwnd );
720 if ( !WINPOS_CanActivate(wndPtr) ) return 0;
722 WINPOS_SetActiveWindow( hwnd, 0, 0 );
727 /*******************************************************************
728 * GetForegroundWindow16 (USER.608)
730 HWND16 WINAPI GetForegroundWindow16(void)
732 return (HWND16)GetForegroundWindow32();
736 /*******************************************************************
737 * SetForegroundWindow16 (USER.609)
739 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
741 return SetForegroundWindow32( hwnd );
745 /*******************************************************************
746 * GetForegroundWindow32 (USER32.241)
748 HWND32 WINAPI GetForegroundWindow32(void)
750 return GetActiveWindow32();
754 /*******************************************************************
755 * SetForegroundWindow32 (USER32.482)
757 BOOL32 WINAPI SetForegroundWindow32( HWND32 hwnd )
759 SetActiveWindow32( hwnd );
764 /*******************************************************************
765 * GetShellWindow16 (USER.600)
767 HWND16 WINAPI GetShellWindow16(void)
769 return GetShellWindow32();
772 /*******************************************************************
773 * SetShellWindow32 (USER32.504)
775 HWND32 WINAPI SetShellWindow32(HWND32 hwndshell)
776 { WARN(win, "(hWnd=%08x) semi stub\n",hwndshell );
778 hGlobalShellWindow = hwndshell;
779 return hGlobalShellWindow;
783 /*******************************************************************
784 * GetShellWindow32 (USER32.287)
786 HWND32 WINAPI GetShellWindow32(void)
787 { WARN(win, "(hWnd=%x) semi stub\n",hGlobalShellWindow );
789 return hGlobalShellWindow;
793 /***********************************************************************
794 * BringWindowToTop16 (USER.45)
796 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
798 return BringWindowToTop32(hwnd);
802 /***********************************************************************
803 * BringWindowToTop32 (USER32.11)
805 BOOL32 WINAPI BringWindowToTop32( HWND32 hwnd )
807 return SetWindowPos32( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
811 /***********************************************************************
812 * MoveWindow16 (USER.56)
814 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
817 return MoveWindow32(hwnd,x,y,cx,cy,repaint);
821 /***********************************************************************
822 * MoveWindow32 (USER32.399)
824 BOOL32 WINAPI MoveWindow32( HWND32 hwnd, INT32 x, INT32 y, INT32 cx, INT32 cy,
827 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
828 if (!repaint) flags |= SWP_NOREDRAW;
829 TRACE(win, "%04x %d,%d %dx%d %d\n",
830 hwnd, x, y, cx, cy, repaint );
831 return SetWindowPos32( hwnd, 0, x, y, cx, cy, flags );
834 /***********************************************************************
835 * WINPOS_InitInternalPos
837 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT32 pt,
838 LPRECT32 restoreRect )
840 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetProp32A( wnd->hwndSelf,
844 /* this happens when the window is minimized/maximized
845 * for the first time (rectWindow is not adjusted yet) */
847 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
848 if( !lpPos ) return NULL;
850 SetProp32A( wnd->hwndSelf, atomInternalPos, (HANDLE32)lpPos );
851 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
852 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
853 *(UINT32*)&lpPos->ptIconPos = *(UINT32*)&lpPos->ptMaxPos = 0xFFFFFFFF;
856 if( wnd->dwStyle & WS_MINIMIZE )
857 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
858 else if( wnd->dwStyle & WS_MAXIMIZE )
859 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
860 else if( restoreRect )
861 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
866 /***********************************************************************
867 * WINPOS_RedrawIconTitle
869 BOOL32 WINPOS_RedrawIconTitle( HWND32 hWnd )
871 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetProp32A( hWnd, atomInternalPos );
874 if( lpPos->hwndIconTitle )
876 SendMessage32A( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
877 InvalidateRect32( lpPos->hwndIconTitle, NULL, TRUE );
884 /***********************************************************************
885 * WINPOS_ShowIconTitle
887 BOOL32 WINPOS_ShowIconTitle( WND* pWnd, BOOL32 bShow )
889 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetProp32A( pWnd->hwndSelf, atomInternalPos );
891 if( lpPos && !(pWnd->flags & WIN_MANAGED))
893 HWND16 hWnd = lpPos->hwndIconTitle;
895 TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
898 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
901 pWnd = WIN_FindWndPtr(hWnd);
903 if( !(pWnd->dwStyle & WS_VISIBLE) )
905 SendMessage32A( hWnd, WM_SHOWWINDOW, TRUE, 0 );
906 SetWindowPos32( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
907 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
910 else ShowWindow32( hWnd, SW_HIDE );
915 /*******************************************************************
916 * WINPOS_GetMinMaxInfo
918 * Get the minimized and maximized information for a window.
920 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT32 *maxSize, POINT32 *maxPos,
921 POINT32 *minTrack, POINT32 *maxTrack )
927 /* Compute default values */
929 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
930 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
931 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
932 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
933 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
934 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
936 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
937 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
939 xinc = SYSMETRICS_CXDLGFRAME;
940 yinc = SYSMETRICS_CYDLGFRAME;
945 if (HAS_THICKFRAME(wndPtr->dwStyle))
947 xinc += SYSMETRICS_CXFRAME;
948 yinc += SYSMETRICS_CYFRAME;
950 if (wndPtr->dwStyle & WS_BORDER)
952 xinc += SYSMETRICS_CXBORDER;
953 yinc += SYSMETRICS_CYBORDER;
956 MinMax.ptMaxSize.x += 2 * xinc;
957 MinMax.ptMaxSize.y += 2 * yinc;
959 lpPos = (LPINTERNALPOS)GetProp32A( wndPtr->hwndSelf, atomInternalPos );
960 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
961 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
964 MinMax.ptMaxPosition.x = -xinc;
965 MinMax.ptMaxPosition.y = -yinc;
968 SendMessage32A( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
970 /* Some sanity checks */
972 TRACE(win,"%d %d / %d %d / %d %d / %d %d\n",
973 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
974 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
975 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
976 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
977 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
978 MinMax.ptMinTrackSize.x );
979 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
980 MinMax.ptMinTrackSize.y );
982 if (maxSize) *maxSize = MinMax.ptMaxSize;
983 if (maxPos) *maxPos = MinMax.ptMaxPosition;
984 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
985 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
988 /***********************************************************************
991 * Fill in lpRect and return additional flags to be used with SetWindowPos().
992 * This function assumes that 'cmd' is different from the current window
995 UINT16 WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
999 POINT32 size = { wndPtr->rectWindow.left, wndPtr->rectWindow.top };
1000 LPINTERNALPOS lpPos = WINPOS_InitInternalPos( wndPtr, size,
1001 &wndPtr->rectWindow );
1003 TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
1005 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1007 if( wndPtr->dwStyle & WS_MINIMIZE )
1009 if( !SendMessage32A( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1010 return (SWP_NOSIZE | SWP_NOMOVE);
1011 swpFlags |= SWP_NOCOPYBITS;
1016 if( wndPtr->dwStyle & WS_MAXIMIZE)
1018 wndPtr->flags |= WIN_RESTORE_MAX;
1019 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1022 wndPtr->flags &= ~WIN_RESTORE_MAX;
1023 wndPtr->dwStyle |= WS_MINIMIZE;
1025 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1027 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1028 SYSMETRICS_CXICON, SYSMETRICS_CYICON );
1029 swpFlags |= SWP_NOCOPYBITS;
1033 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1034 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1035 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1037 if( wndPtr->dwStyle & WS_MINIMIZE )
1039 WINPOS_ShowIconTitle( wndPtr, FALSE );
1040 wndPtr->dwStyle &= ~WS_MINIMIZE;
1042 wndPtr->dwStyle |= WS_MAXIMIZE;
1044 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1049 if( wndPtr->dwStyle & WS_MINIMIZE )
1051 wndPtr->dwStyle &= ~WS_MINIMIZE;
1052 WINPOS_ShowIconTitle( wndPtr, FALSE );
1053 if( wndPtr->flags & WIN_RESTORE_MAX)
1055 /* Restore to maximized position */
1056 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1057 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1058 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1059 wndPtr->dwStyle |= WS_MAXIMIZE;
1060 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1065 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1066 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1068 /* Restore to normal position */
1070 *lpRect = lpPos->rectNormal;
1071 lpRect->right -= lpRect->left;
1072 lpRect->bottom -= lpRect->top;
1076 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1080 /***********************************************************************
1081 * ShowWindowAsync32 (USER32.535)
1083 * doesn't wait; returns immediately.
1084 * used by threads to toggle windows in other (possibly hanging) threads
1086 BOOL32 WINAPI ShowWindowAsync32( HWND32 hwnd, INT32 cmd )
1088 /* FIXME: does ShowWindow32() return immediately ? */
1089 return ShowWindow32(hwnd, cmd);
1093 /***********************************************************************
1094 * ShowWindow16 (USER.42)
1096 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1098 return ShowWindow32(hwnd,cmd);
1102 /***********************************************************************
1103 * ShowWindow32 (USER32.534)
1105 BOOL32 WINAPI ShowWindow32( HWND32 hwnd, INT32 cmd )
1107 WND* wndPtr = WIN_FindWndPtr( hwnd );
1108 BOOL32 wasVisible, showFlag;
1109 RECT16 newPos = {0, 0, 0, 0};
1112 if (!wndPtr) return FALSE;
1114 TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1116 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1121 if (!wasVisible) return FALSE;
1122 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1123 SWP_NOACTIVATE | SWP_NOZORDER;
1126 case SW_SHOWMINNOACTIVE:
1127 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1129 case SW_SHOWMINIMIZED:
1130 swp |= SWP_SHOWWINDOW;
1133 swp |= SWP_FRAMECHANGED;
1134 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1135 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1136 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1139 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1140 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1141 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1142 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1143 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1147 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1150 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1153 case SW_SHOWNOACTIVATE:
1154 swp |= SWP_NOZORDER;
1155 if (GetActiveWindow32()) swp |= SWP_NOACTIVATE;
1157 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1158 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1160 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1162 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1163 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1164 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1168 showFlag = (cmd != SW_HIDE);
1169 if (showFlag != wasVisible)
1171 SendMessage32A( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1172 if (!IsWindow32( hwnd )) return wasVisible;
1175 if ((wndPtr->dwStyle & WS_CHILD) &&
1176 !IsWindowVisible32( wndPtr->parent->hwndSelf ) &&
1177 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1179 /* Don't call SetWindowPos32() on invisible child windows */
1180 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1181 else wndPtr->dwStyle |= WS_VISIBLE;
1185 /* We can't activate a child window */
1186 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1187 SetWindowPos32( hwnd, HWND_TOP,
1188 newPos.left, newPos.top, newPos.right, newPos.bottom, swp );
1189 if (!IsWindow32( hwnd )) return wasVisible;
1190 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1193 if (wndPtr->flags & WIN_NEED_SIZE)
1195 /* should happen only in CreateWindowEx() */
1196 int wParam = SIZE_RESTORED;
1198 wndPtr->flags &= ~WIN_NEED_SIZE;
1199 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1200 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1201 SendMessage32A( hwnd, WM_SIZE, wParam,
1202 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1203 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1204 SendMessage32A( hwnd, WM_MOVE, 0,
1205 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1212 /***********************************************************************
1213 * GetInternalWindowPos16 (USER.460)
1215 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1218 WINDOWPLACEMENT16 wndpl;
1219 if (GetWindowPlacement16( hwnd, &wndpl ))
1221 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1222 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1223 return wndpl.showCmd;
1229 /***********************************************************************
1230 * GetInternalWindowPos32 (USER32.245)
1232 UINT32 WINAPI GetInternalWindowPos32( HWND32 hwnd, LPRECT32 rectWnd,
1235 WINDOWPLACEMENT32 wndpl;
1236 if (GetWindowPlacement32( hwnd, &wndpl ))
1238 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1239 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1240 return wndpl.showCmd;
1245 /***********************************************************************
1246 * GetWindowPlacement16 (USER.370)
1248 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1250 WND *pWnd = WIN_FindWndPtr( hwnd );
1253 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1254 *(LPPOINT32)&pWnd->rectWindow.left, &pWnd->rectWindow );
1255 wndpl->length = sizeof(*wndpl);
1256 if( pWnd->dwStyle & WS_MINIMIZE )
1257 wndpl->showCmd = SW_SHOWMINIMIZED;
1259 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1260 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1261 if( pWnd->flags & WIN_RESTORE_MAX )
1262 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1265 wndpl->ptMinPosition = lpPos->ptIconPos;
1266 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1267 wndpl->rcNormalPosition = lpPos->rectNormal;
1274 /***********************************************************************
1275 * GetWindowPlacement32 (USER32.307)
1278 * Fails if wndpl->length of Win95 (!) apps is invalid.
1280 BOOL32 WINAPI GetWindowPlacement32( HWND32 hwnd, WINDOWPLACEMENT32 *pwpl32 )
1284 WINDOWPLACEMENT16 wpl;
1285 wpl.length = sizeof(wpl);
1286 if( GetWindowPlacement16( hwnd, &wpl ) )
1288 pwpl32->length = sizeof(*pwpl32);
1289 pwpl32->flags = wpl.flags;
1290 pwpl32->showCmd = wpl.showCmd;
1291 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1292 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1293 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1301 /***********************************************************************
1302 * WINPOS_SetPlacement
1304 static BOOL32 WINPOS_SetPlacement( HWND32 hwnd, const WINDOWPLACEMENT16 *wndpl,
1307 WND *pWnd = WIN_FindWndPtr( hwnd );
1310 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1311 *(LPPOINT32)&pWnd->rectWindow.left, &pWnd->rectWindow );
1313 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1314 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1315 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1317 if( pWnd->dwStyle & WS_MINIMIZE )
1319 WINPOS_ShowIconTitle( pWnd, FALSE );
1320 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1321 SetWindowPos32( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1322 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1324 else if( pWnd->dwStyle & WS_MAXIMIZE )
1326 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1327 SetWindowPos32( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1328 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1330 else if( flags & PLACE_RECT )
1331 SetWindowPos32( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1332 lpPos->rectNormal.right - lpPos->rectNormal.left,
1333 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1334 SWP_NOZORDER | SWP_NOACTIVATE );
1336 ShowWindow32( hwnd, wndpl->showCmd );
1337 if( IsWindow32(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1339 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1341 /* SDK: ...valid only the next time... */
1342 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1350 /***********************************************************************
1351 * SetWindowPlacement16 (USER.371)
1353 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1355 return WINPOS_SetPlacement( hwnd, wndpl,
1356 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1359 /***********************************************************************
1360 * SetWindowPlacement32 (USER32.519)
1363 * Fails if wndpl->length of Win95 (!) apps is invalid.
1365 BOOL32 WINAPI SetWindowPlacement32( HWND32 hwnd, const WINDOWPLACEMENT32 *pwpl32 )
1369 WINDOWPLACEMENT16 wpl = { sizeof(WINDOWPLACEMENT16),
1370 pwpl32->flags, pwpl32->showCmd, { pwpl32->ptMinPosition.x,
1371 pwpl32->ptMinPosition.y }, { pwpl32->ptMaxPosition.x,
1372 pwpl32->ptMaxPosition.y }, { pwpl32->rcNormalPosition.left,
1373 pwpl32->rcNormalPosition.top, pwpl32->rcNormalPosition.right,
1374 pwpl32->rcNormalPosition.bottom } };
1376 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1382 /***********************************************************************
1383 * SetInternalWindowPos16 (USER.461)
1385 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1386 LPRECT16 rect, LPPOINT16 pt )
1388 if( IsWindow16(hwnd) )
1390 WINDOWPLACEMENT16 wndpl;
1393 wndpl.length = sizeof(wndpl);
1394 wndpl.showCmd = showCmd;
1395 wndpl.flags = flags = 0;
1400 wndpl.flags |= WPF_SETMINPOSITION;
1401 wndpl.ptMinPosition = *pt;
1405 flags |= PLACE_RECT;
1406 wndpl.rcNormalPosition = *rect;
1408 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1413 /***********************************************************************
1414 * SetInternalWindowPos32 (USER32.483)
1416 void WINAPI SetInternalWindowPos32( HWND32 hwnd, UINT32 showCmd,
1417 LPRECT32 rect, LPPOINT32 pt )
1419 if( IsWindow32(hwnd) )
1421 WINDOWPLACEMENT16 wndpl;
1424 wndpl.length = sizeof(wndpl);
1425 wndpl.showCmd = showCmd;
1426 wndpl.flags = flags = 0;
1431 wndpl.flags |= WPF_SETMINPOSITION;
1432 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1436 flags |= PLACE_RECT;
1437 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1439 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1443 /*******************************************************************
1444 * WINPOS_SetActiveWindow
1446 * SetActiveWindow() back-end. This is the only function that
1447 * can assign active status to a window. It must be called only
1448 * for the top level windows.
1450 BOOL32 WINPOS_SetActiveWindow( HWND32 hWnd, BOOL32 fMouse, BOOL32 fChangeFocus)
1452 CBTACTIVATESTRUCT16* cbtStruct;
1453 WND* wndPtr, *wndTemp;
1454 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1457 /* paranoid checks */
1458 if( hWnd == GetDesktopWindow32() || hWnd == hwndActive ) return 0;
1460 /* if (wndPtr && (GetFastQueue() != wndPtr->hmemTaskQ))
1463 wndPtr = WIN_FindWndPtr(hWnd);
1464 hOldActiveQueue = (pActiveQueue)?pActiveQueue->self : 0;
1466 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1467 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1469 TRACE(win,"no current active window.\n");
1471 /* call CBT hook chain */
1472 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1475 cbtStruct->fMouse = fMouse;
1476 cbtStruct->hWndActive = hwndActive;
1477 wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1478 (LPARAM)SEGPTR_GET(cbtStruct) );
1479 SEGPTR_FREE(cbtStruct);
1480 if (wRet) return wRet;
1483 /* set prev active wnd to current active wnd and send notification */
1484 if ((hwndPrevActive = hwndActive) && IsWindow32(hwndPrevActive))
1486 if (!SendMessage32A( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1488 if (GetSysModalWindow16() != hWnd) return 0;
1489 /* disregard refusal if hWnd is sysmodal */
1493 SendMessage32A( hwndPrevActive, WM_ACTIVATE,
1494 MAKEWPARAM( WA_INACTIVE, wIconized ),
1497 /* FIXME: must be SendMessage16() because 32A doesn't do
1498 * intertask at this time */
1499 SendMessage16( hwndPrevActive, WM_ACTIVATE, WA_INACTIVE,
1500 MAKELPARAM( (HWND16)hWnd, wIconized ) );
1503 /* check if something happened during message processing */
1504 if( hwndPrevActive != hwndActive ) return 0;
1507 /* set active wnd */
1510 /* send palette messages */
1511 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1512 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1514 /* if prev wnd is minimized redraw icon title */
1515 if( IsIconic32( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1517 /* managed windows will get ConfigureNotify event */
1518 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1520 /* check Z-order and bring hWnd to the top */
1521 for (wndTemp = WIN_GetDesktop()->child; wndTemp; wndTemp = wndTemp->next)
1522 if (wndTemp->dwStyle & WS_VISIBLE) break;
1524 if( wndTemp != wndPtr )
1525 SetWindowPos32(hWnd, HWND_TOP, 0,0,0,0,
1526 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1527 if (!IsWindow32(hWnd)) return 0;
1530 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1532 /* send WM_ACTIVATEAPP if necessary */
1533 if (hOldActiveQueue != hNewActiveQueue)
1535 WND **list, **ppWnd;
1537 if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1539 for (ppWnd = list; *ppWnd; ppWnd++)
1541 if (!IsWindow32( (*ppWnd)->hwndSelf )) continue;
1543 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1544 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1545 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1547 HeapFree( SystemHeap, 0, list );
1550 pActiveQueue = (hNewActiveQueue)
1551 ? (MESSAGEQUEUE*) GlobalLock16(hNewActiveQueue) : NULL;
1553 if ((list = WIN_BuildWinArray( WIN_GetDesktop(), 0, NULL )))
1555 for (ppWnd = list; *ppWnd; ppWnd++)
1557 if (!IsWindow32( (*ppWnd)->hwndSelf )) continue;
1559 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1560 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1561 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1563 HeapFree( SystemHeap, 0, list );
1565 if (!IsWindow32(hWnd)) return 0;
1570 /* walk up to the first unowned window */
1572 while (wndTemp->owner) wndTemp = wndTemp->owner;
1573 /* and set last active owned popup */
1574 wndTemp->hwndLastActive = hWnd;
1576 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1577 SendMessage32A( hWnd, WM_NCACTIVATE, TRUE, 0 );
1579 SendMessage32A( hWnd, WM_ACTIVATE,
1580 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1581 (LPARAM)hwndPrevActive );
1583 SendMessage16(hWnd, WM_ACTIVATE, (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE,
1584 MAKELPARAM( (HWND16)hwndPrevActive, wIconized) );
1587 if( !IsWindow32(hWnd) ) return 0;
1590 /* change focus if possible */
1591 if( fChangeFocus && GetFocus32() )
1592 if( WIN_GetTopParent(GetFocus32()) != hwndActive )
1593 FOCUS_SwitchFocus( GetFocus32(),
1594 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1599 if( !hwndPrevActive && wndPtr )
1600 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1602 /* if active wnd is minimized redraw icon title */
1603 if( IsIconic32(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1605 return (hWnd == hwndActive);
1608 /*******************************************************************
1609 * WINPOS_ActivateOtherWindow
1611 * Activates window other than pWnd.
1613 BOOL32 WINPOS_ActivateOtherWindow(WND* pWnd)
1618 if( pWnd->hwndSelf == hwndPrevActive )
1621 if( hwndActive != pWnd->hwndSelf &&
1622 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1625 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1626 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1628 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1630 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1632 while( !WINPOS_CanActivate(pWndTo) )
1634 /* by now owned windows should've been taken care of */
1636 pWndTo = pWndPtr->next;
1638 if( !pWndTo ) break;
1642 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1644 /* switch desktop queue to current active */
1645 if( pWndTo ) WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1651 /*******************************************************************
1652 * WINPOS_ChangeActiveWindow
1655 BOOL32 WINPOS_ChangeActiveWindow( HWND32 hWnd, BOOL32 mouseMsg )
1657 WND *wndPtr = WIN_FindWndPtr(hWnd);
1659 if (!hWnd) return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1661 if( !wndPtr ) return FALSE;
1663 /* child windows get WM_CHILDACTIVATE message */
1664 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1665 return SendMessage32A(hWnd, WM_CHILDACTIVATE, 0, 0L);
1667 /* owned popups imply owner activation - not sure */
1668 if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
1669 (wndPtr->owner->dwStyle & WS_VISIBLE ) &&
1670 !(wndPtr->owner->dwStyle & WS_DISABLED ))
1672 if (!(wndPtr = wndPtr->owner)) return FALSE;
1673 hWnd = wndPtr->hwndSelf;
1676 if( hWnd == hwndActive ) return FALSE;
1678 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1681 /* switch desktop queue to current active */
1682 if( wndPtr->parent == WIN_GetDesktop())
1683 WIN_GetDesktop()->hmemTaskQ = wndPtr->hmemTaskQ;
1689 /***********************************************************************
1690 * WINPOS_SendNCCalcSize
1692 * Send a WM_NCCALCSIZE message to a window.
1693 * All parameters are read-only except newClientRect.
1694 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1695 * when calcValidRect is TRUE.
1697 LONG WINPOS_SendNCCalcSize( HWND32 hwnd, BOOL32 calcValidRect,
1698 RECT32 *newWindowRect, RECT32 *oldWindowRect,
1699 RECT32 *oldClientRect, WINDOWPOS32 *winpos,
1700 RECT32 *newClientRect )
1702 NCCALCSIZE_PARAMS32 params;
1703 WINDOWPOS32 winposCopy;
1706 params.rgrc[0] = *newWindowRect;
1709 winposCopy = *winpos;
1710 params.rgrc[1] = *oldWindowRect;
1711 params.rgrc[2] = *oldClientRect;
1712 params.lppos = &winposCopy;
1714 result = SendMessage32A( hwnd, WM_NCCALCSIZE, calcValidRect,
1716 TRACE(win, "%d,%d-%d,%d\n",
1717 params.rgrc[0].left, params.rgrc[0].top,
1718 params.rgrc[0].right, params.rgrc[0].bottom );
1719 *newClientRect = params.rgrc[0];
1724 /***********************************************************************
1725 * WINPOS_HandleWindowPosChanging16
1727 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1729 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
1731 POINT32 maxSize, minTrack;
1732 if (winpos->flags & SWP_NOSIZE) return 0;
1733 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1734 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1736 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
1737 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1738 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1739 if (!(wndPtr->dwStyle & WS_MINIMIZE))
1741 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1742 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1749 /***********************************************************************
1750 * WINPOS_HandleWindowPosChanging32
1752 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1754 LONG WINPOS_HandleWindowPosChanging32( WND *wndPtr, WINDOWPOS32 *winpos )
1757 if (winpos->flags & SWP_NOSIZE) return 0;
1758 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1759 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1761 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
1762 winpos->cx = MIN( winpos->cx, maxSize.x );
1763 winpos->cy = MIN( winpos->cy, maxSize.y );
1769 /***********************************************************************
1770 * WINPOS_MoveWindowZOrder
1772 * Move a window in Z order, invalidating everything that needs it.
1773 * Only necessary for windows without associated X window.
1775 static void WINPOS_MoveWindowZOrder( HWND32 hwnd, HWND32 hwndAfter )
1778 WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
1780 /* We have two possible cases:
1781 * - The window is moving up: we have to invalidate all areas
1782 * of the window that were covered by other windows
1783 * - The window is moving down: we have to invalidate areas
1784 * of other windows covered by this one.
1787 if (hwndAfter == HWND_TOP)
1791 else if (hwndAfter == HWND_BOTTOM)
1793 if (!wndPtr->next) return; /* Already at the bottom */
1798 if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) return;
1799 if (wndPtr->next == pWndAfter) return; /* Already placed right */
1801 /* Determine which window we encounter first in Z-order */
1802 pWndCur = wndPtr->parent->child;
1803 while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
1804 pWndCur = pWndCur->next;
1805 movingUp = (pWndCur == pWndAfter);
1810 WND *pWndPrevAfter = wndPtr->next;
1811 WIN_UnlinkWindow( hwnd );
1812 WIN_LinkWindow( hwnd, hwndAfter );
1813 pWndCur = wndPtr->next;
1814 while (pWndCur != pWndPrevAfter)
1816 RECT32 rect = { pWndCur->rectWindow.left,
1817 pWndCur->rectWindow.top,
1818 pWndCur->rectWindow.right,
1819 pWndCur->rectWindow.bottom };
1820 OffsetRect32( &rect, -wndPtr->rectClient.left,
1821 -wndPtr->rectClient.top );
1822 PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
1823 RDW_FRAME | RDW_ERASE, 0 );
1824 pWndCur = pWndCur->next;
1827 else /* Moving down */
1829 pWndCur = wndPtr->next;
1830 WIN_UnlinkWindow( hwnd );
1831 WIN_LinkWindow( hwnd, hwndAfter );
1832 while (pWndCur != wndPtr)
1834 RECT32 rect = { pWndCur->rectWindow.left,
1835 pWndCur->rectWindow.top,
1836 pWndCur->rectWindow.right,
1837 pWndCur->rectWindow.bottom };
1838 OffsetRect32( &rect, -pWndCur->rectClient.left,
1839 -pWndCur->rectClient.top );
1840 PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
1841 RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
1842 pWndCur = pWndCur->next;
1847 /***********************************************************************
1848 * WINPOS_ReorderOwnedPopups
1850 * fix Z order taking into account owned popups -
1851 * basically we need to maintain them above the window that owns them
1853 HWND32 WINPOS_ReorderOwnedPopups(HWND32 hwndInsertAfter,WND* wndPtr,WORD flags)
1855 WND* w = WIN_GetDesktop()->child;
1857 if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
1859 /* implement "local z-order" between the top and owner window */
1861 HWND32 hwndLocalPrev = HWND_TOP;
1863 if( hwndInsertAfter != HWND_TOP )
1865 while( w != wndPtr->owner )
1867 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
1868 if( hwndLocalPrev == hwndInsertAfter ) break;
1871 hwndInsertAfter = hwndLocalPrev;
1875 else if( wndPtr->dwStyle & WS_CHILD ) return hwndInsertAfter;
1877 w = WIN_GetDesktop()->child;
1880 if( w == wndPtr ) break;
1882 if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
1884 SetWindowPos32(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1885 SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
1886 hwndInsertAfter = w->hwndSelf;
1891 return hwndInsertAfter;
1894 /***********************************************************************
1895 * WINPOS_SizeMoveClean
1897 * Make window look nice without excessive repainting
1901 * visible regions are in window coordinates
1902 * update regions are in window client coordinates
1903 * client and window rectangles are in parent client coordinates
1905 * FIXME: Move visible and update regions to the same coordinate system
1906 * (either parent client or window). This is a lot of work though.
1908 static UINT32 WINPOS_SizeMoveClean( WND* Wnd, HRGN32 oldVisRgn,
1909 LPRECT32 lpOldWndRect,
1910 LPRECT32 lpOldClientRect, UINT32 uFlags )
1912 HRGN32 newVisRgn = DCE_GetVisRgn(Wnd->hwndSelf,DCX_WINDOW | DCX_CLIPSIBLINGS);
1913 HRGN32 dirtyRgn = CreateRectRgn32(0,0,0,0);
1916 TRACE(win,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n",
1917 Wnd->rectWindow.left, Wnd->rectWindow.top,
1918 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
1919 lpOldWndRect->left, lpOldWndRect->top,
1920 lpOldWndRect->right, lpOldWndRect->bottom);
1921 TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
1922 Wnd->rectClient.left, Wnd->rectClient.top,
1923 Wnd->rectClient.right, Wnd->rectClient.bottom,
1924 lpOldClientRect->left, lpOldClientRect->top,
1925 lpOldClientRect->right,lpOldClientRect->bottom );
1927 if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
1928 (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
1929 uFlags |= SMC_DRAWFRAME;
1931 CombineRgn32( dirtyRgn, newVisRgn, 0, RGN_COPY);
1933 if( !(uFlags & SMC_NOCOPY) )
1934 CombineRgn32( newVisRgn, newVisRgn, oldVisRgn, RGN_AND );
1936 /* map regions to the parent client area */
1938 OffsetRgn32( dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
1939 OffsetRgn32( oldVisRgn, lpOldWndRect->left, lpOldWndRect->top );
1941 /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
1943 other = CombineRgn32(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
1945 /* map visible region to the Wnd client area */
1947 OffsetRgn32( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
1948 Wnd->rectWindow.top - Wnd->rectClient.top );
1950 /* substract previously invalidated region from the Wnd visible region */
1952 my = (Wnd->hrgnUpdate > 1) ? CombineRgn32( newVisRgn, newVisRgn,
1953 Wnd->hrgnUpdate, RGN_DIFF)
1956 if( uFlags & SMC_NOCOPY ) /* invalidate Wnd visible region */
1958 if (my != NULLREGION)
1959 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
1960 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
1961 else if(uFlags & SMC_DRAWFRAME)
1962 Wnd->flags |= WIN_NEEDS_NCPAINT;
1964 else /* bitblt old client area */
1969 int xfrom,yfrom,xto,yto,width,height;
1971 if( uFlags & SMC_DRAWFRAME )
1973 /* copy only client area, frame will be redrawn anyway */
1975 xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
1976 xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
1977 width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
1978 updateRgn = CreateRectRgn32( 0, 0, width, height );
1979 CombineRgn32( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1980 SetRectRgn32( updateRgn, 0, 0, Wnd->rectClient.right - xto,
1981 Wnd->rectClient.bottom - yto );
1985 xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
1986 xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
1987 width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
1988 updateRgn = CreateRectRgn32( xto - Wnd->rectClient.left,
1989 yto - Wnd->rectClient.top,
1990 Wnd->rectWindow.right - Wnd->rectClient.left,
1991 Wnd->rectWindow.bottom - Wnd->rectClient.top );
1994 CombineRgn32( newVisRgn, newVisRgn, updateRgn, RGN_AND );
1996 /* substract new visRgn from target rect to get a region that won't be copied */
1998 update = CombineRgn32( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
2000 /* Blt valid bits using parent window DC */
2002 if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
2005 /* compute clipping region in parent client coordinates */
2007 OffsetRgn32( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top );
2008 CombineRgn32( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
2010 hDC = GetDCEx32( Wnd->parent->hwndSelf, oldVisRgn,
2011 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
2012 DCX_CACHE | DCX_CLIPSIBLINGS);
2014 BitBlt32( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
2015 ReleaseDC32( Wnd->parent->hwndSelf, hDC);
2018 if( update != NULLREGION )
2019 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
2020 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2021 else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
2022 DeleteObject32( updateRgn );
2025 /* erase uncovered areas */
2027 if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
2028 PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
2029 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2030 DeleteObject32(dirtyRgn);
2031 DeleteObject32(newVisRgn);
2035 /***********************************************************************
2036 * SetWindowPos (USER.232)
2038 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2039 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2041 return SetWindowPos32(hwnd,(INT32)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2044 /***********************************************************************
2045 * SetWindowPos (USER32.520)
2047 BOOL32 WINAPI SetWindowPos32( HWND32 hwnd, HWND32 hwndInsertAfter,
2048 INT32 x, INT32 y, INT32 cx, INT32 cy, WORD flags)
2052 RECT32 newWindowRect, newClientRect, oldWindowRect;
2054 HWND32 tempInsertAfter= 0;
2057 BOOL32 resync = FALSE;
2059 TRACE(win,"hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n",
2060 hwnd, x, y, x+cx, y+cy, flags);
2061 /* Check window handle */
2063 if (hwnd == GetDesktopWindow32()) return FALSE;
2064 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2066 if(wndPtr->dwStyle & WS_VISIBLE)
2067 flags &= ~SWP_SHOWWINDOW;
2070 uFlags |= SMC_NOPARENTERASE;
2071 flags &= ~SWP_HIDEWINDOW;
2072 if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
2075 /* Check for windows that may not be resized
2076 FIXME: this should be done only for Windows 3.0 programs
2077 if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
2078 flags |= SWP_NOSIZE | SWP_NOMOVE;
2080 /* Check dimensions */
2082 if (cx <= 0) cx = 1;
2083 if (cy <= 0) cy = 1;
2087 if (hwnd == hwndActive) flags |= SWP_NOACTIVATE; /* Already active */
2088 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2089 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2090 flags |= SWP_NOSIZE; /* Already the right size */
2091 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2092 flags |= SWP_NOMOVE; /* Already the right position */
2094 /* Check hwndInsertAfter */
2096 if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
2098 /* Ignore TOPMOST flags when activating a window */
2099 /* _and_ moving it in Z order. */
2100 if ((hwndInsertAfter == HWND_TOPMOST) ||
2101 (hwndInsertAfter == HWND_NOTOPMOST))
2102 hwndInsertAfter = HWND_TOP;
2104 /* TOPMOST not supported yet */
2105 if ((hwndInsertAfter == HWND_TOPMOST) ||
2106 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2108 /* hwndInsertAfter must be a sibling of the window */
2109 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2111 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2114 if( wnd->parent != wndPtr->parent ) return FALSE;
2115 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2118 else if (!((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
2120 /* FIXME: the following optimization is no good for "X-ed" windows */
2121 if (hwndInsertAfter == HWND_TOP)
2122 flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2123 else /* HWND_BOTTOM */
2124 flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2127 /* Fill the WINDOWPOS structure */
2130 winpos.hwndInsertAfter = hwndInsertAfter;
2135 winpos.flags = flags;
2137 /* Send WM_WINDOWPOSCHANGING message */
2139 if (!(winpos.flags & SWP_NOSENDCHANGING))
2140 SendMessage32A( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
2142 /* Calculate new position and size */
2144 newWindowRect = wndPtr->rectWindow;
2145 newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2146 : wndPtr->rectClient;
2148 if (!(winpos.flags & SWP_NOSIZE))
2150 newWindowRect.right = newWindowRect.left + winpos.cx;
2151 newWindowRect.bottom = newWindowRect.top + winpos.cy;
2153 if (!(winpos.flags & SWP_NOMOVE))
2155 newWindowRect.left = winpos.x;
2156 newWindowRect.top = winpos.y;
2157 newWindowRect.right += winpos.x - wndPtr->rectWindow.left;
2158 newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
2160 OffsetRect32( &newClientRect, winpos.x - wndPtr->rectWindow.left,
2161 winpos.y - wndPtr->rectWindow.top );
2164 winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2166 /* Reposition window in Z order */
2168 if (!(winpos.flags & SWP_NOZORDER))
2170 /* reorder owned popups if hwnd is top-level window
2172 if( wndPtr->parent == WIN_GetDesktop() )
2173 hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
2174 wndPtr, winpos.flags );
2176 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
2178 WIN_UnlinkWindow( winpos.hwnd );
2179 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2181 else WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
2184 if ( !((X11DRV_WND_DATA *) wndPtr->pDriverData)->window && !(winpos.flags & SWP_NOREDRAW) &&
2185 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED))
2186 != (SWP_NOMOVE | SWP_NOSIZE)) )
2187 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS);
2190 /* Send WM_NCCALCSIZE message to get new client area */
2191 if( (winpos.flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2193 result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
2194 &wndPtr->rectWindow, &wndPtr->rectClient,
2195 &winpos, &newClientRect );
2197 /* FIXME: WVR_ALIGNxxx */
2199 if( newClientRect.left != wndPtr->rectClient.left ||
2200 newClientRect.top != wndPtr->rectClient.top )
2201 winpos.flags &= ~SWP_NOCLIENTMOVE;
2203 if( (newClientRect.right - newClientRect.left !=
2204 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2205 (newClientRect.bottom - newClientRect.top !=
2206 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2207 winpos.flags &= ~SWP_NOCLIENTSIZE;
2210 if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
2211 newClientRect.top != wndPtr->rectClient.top) )
2212 winpos.flags &= ~SWP_NOCLIENTMOVE;
2214 /* Update active DCEs
2215 * TODO: Optimize conditions that trigger DCE update.
2218 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2219 wndPtr->dwStyle & WS_VISIBLE) ||
2220 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2224 UnionRect32(&rect, &newWindowRect, &wndPtr->rectWindow);
2225 DCE_InvalidateDCE(wndPtr, &rect);
2228 /* change geometry */
2230 oldWindowRect = wndPtr->rectWindow;
2232 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
2234 RECT32 oldClientRect = wndPtr->rectClient;
2236 tempInsertAfter = winpos.hwndInsertAfter;
2238 winpos.hwndInsertAfter = hwndInsertAfter;
2240 /* postpone geometry change */
2242 if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2244 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2245 winpos.hwndInsertAfter = tempInsertAfter;
2247 else uFlags |= SMC_SETXPOS;
2249 wndPtr->rectWindow = newWindowRect;
2250 wndPtr->rectClient = newClientRect;
2252 if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2254 if( (oldClientRect.left - oldWindowRect.left !=
2255 newClientRect.left - newWindowRect.left) ||
2256 (oldClientRect.top - oldWindowRect.top !=
2257 newClientRect.top - newWindowRect.top) ||
2258 (winpos.flags & SWP_NOCOPYBITS) )
2260 /* if the client area moved as a result of WM_NCCALCSIZE returning
2261 * obscure WVR_ALIGNxxx flags then we simply redraw the whole thing
2263 * TODO: use WINPOS_SizeMoveClean() if there is no SWP_NOCOPYBITS
2266 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
2267 RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
2270 if( winpos.flags & SWP_FRAMECHANGED )
2275 if( newClientRect.right > oldClientRect.right ) /* redraw exposed client area on the right */
2277 rect.top = 0; rect.bottom = newClientRect.bottom - newClientRect.top;
2278 rect.left = oldClientRect.right - newClientRect.left;
2279 rect.right = newClientRect.right - newClientRect.left;
2281 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2282 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
2284 if( newClientRect.bottom > oldClientRect.bottom ) /* redraw exposed client area on the bottom */
2286 rect.left = 0; rect.right = ((wErase)?oldClientRect.right:newClientRect.right) - newClientRect.left;
2287 rect.top = oldClientRect.bottom - newClientRect.top;
2288 rect.bottom = newClientRect.bottom - newClientRect.top;
2290 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2291 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
2293 if( !wErase ) /* just update the nonclient area */
2294 wndPtr->flags |= WIN_NEEDS_NCPAINT;
2297 uFlags |= SMC_NOPARENTERASE; /* X windows do not have eraseable parents */
2299 else /* not an X window */
2301 RECT32 oldClientRect = wndPtr->rectClient;
2303 wndPtr->rectWindow = newWindowRect;
2304 wndPtr->rectClient = newClientRect;
2306 if( oldClientRect.bottom - oldClientRect.top ==
2307 newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
2309 if( oldClientRect.right - oldClientRect.left ==
2310 newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
2312 if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2314 uFlags |= ((winpos.flags & SWP_NOCOPYBITS) ||
2315 (result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
2316 uFlags |= (winpos.flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
2318 if( (winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
2319 uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect,
2320 &oldClientRect, uFlags);
2323 /* adjust the frame and do not erase the parent */
2325 if( winpos.flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
2326 if( winpos.flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
2329 DeleteObject32(visRgn);
2332 if (flags & SWP_SHOWWINDOW)
2334 wndPtr->dwStyle |= WS_VISIBLE;
2335 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
2339 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
2340 if( uFlags & SMC_SETXPOS )
2342 winpos.hwndInsertAfter = tempInsertAfter;
2345 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2347 /* If focus was set to an unmapped window, reset X focus now */
2348 focus = curr = GetFocus32();
2352 SetFocus32( focus );
2355 curr = GetParent32(curr);
2360 if (!(flags & SWP_NOREDRAW))
2361 PAINT_RedrawWindow( winpos.hwnd, NULL, 0,
2362 RDW_INVALIDATE | RDW_ALLCHILDREN |
2363 RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
2366 else if (flags & SWP_HIDEWINDOW)
2368 wndPtr->dwStyle &= ~WS_VISIBLE;
2370 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
2372 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
2373 if( uFlags & SMC_SETXPOS )
2375 winpos.hwndInsertAfter = tempInsertAfter;
2380 if (!(flags & SWP_NOREDRAW))
2381 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect,
2382 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
2383 RDW_ERASE | RDW_ERASENOW, 0 );
2384 uFlags |= SMC_NOPARENTERASE;
2387 if ((winpos.hwnd == GetFocus32()) ||
2388 IsChild32( winpos.hwnd, GetFocus32()))
2390 /* Revert focus to parent */
2391 SetFocus32( GetParent32(winpos.hwnd) );
2393 if (hwnd == CARET_GetHwnd()) DestroyCaret32();
2395 if (winpos.hwnd == hwndActive)
2396 WINPOS_ActivateOtherWindow( wndPtr );
2399 /* Activate the window */
2401 if (!(flags & SWP_NOACTIVATE))
2402 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2404 /* Repaint the window */
2406 if (((X11DRV_WND_DATA *) wndPtr->pDriverData)->window)
2407 EVENT_Synchronize(); /* Wait for all expose events */
2409 if (!GetCapture32())
2410 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2412 if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
2413 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW, 0 );
2414 else if( wndPtr->parent == WIN_GetDesktop() && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
2415 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
2417 /* And last, send the WM_WINDOWPOSCHANGED message */
2419 TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2422 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2423 !(winpos.flags & SWP_NOSENDCHANGING)) )
2425 SendMessage32A( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2426 if (resync) EVENT_Synchronize ();
2433 /***********************************************************************
2434 * BeginDeferWindowPos16 (USER.259)
2436 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2438 return BeginDeferWindowPos32( count );
2442 /***********************************************************************
2443 * BeginDeferWindowPos32 (USER32.9)
2445 HDWP32 WINAPI BeginDeferWindowPos32( INT32 count )
2450 if (count <= 0) return 0;
2451 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS32) );
2452 if (!handle) return 0;
2453 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2454 pDWP->actualCount = 0;
2455 pDWP->suggestedCount = count;
2457 pDWP->wMagic = DWP_MAGIC;
2458 pDWP->hwndParent = 0;
2463 /***********************************************************************
2464 * DeferWindowPos16 (USER.260)
2466 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2467 INT16 x, INT16 y, INT16 cx, INT16 cy,
2470 return DeferWindowPos32( hdwp, hwnd, (INT32)(INT16)hwndAfter,
2471 x, y, cx, cy, flags );
2475 /***********************************************************************
2476 * DeferWindowPos32 (USER32.128)
2478 HDWP32 WINAPI DeferWindowPos32( HDWP32 hdwp, HWND32 hwnd, HWND32 hwndAfter,
2479 INT32 x, INT32 y, INT32 cx, INT32 cy,
2484 HDWP32 newhdwp = hdwp;
2485 /* HWND32 parent; */
2488 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2489 if (!pDWP) return 0;
2490 if (hwnd == GetDesktopWindow32()) return 0;
2492 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2493 USER_HEAP_FREE( hdwp );
2497 /* Numega Bounds Checker Demo dislikes the following code.
2498 In fact, I've not been able to find any "same parent" requirement in any docu
2502 /* All the windows of a DeferWindowPos() must have the same parent */
2503 parent = pWnd->parent->hwndSelf;
2504 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2505 else if (parent != pDWP->hwndParent)
2507 USER_HEAP_FREE( hdwp );
2512 for (i = 0; i < pDWP->actualCount; i++)
2514 if (pDWP->winPos[i].hwnd == hwnd)
2516 /* Merge with the other changes */
2517 if (!(flags & SWP_NOZORDER))
2519 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2521 if (!(flags & SWP_NOMOVE))
2523 pDWP->winPos[i].x = x;
2524 pDWP->winPos[i].y = y;
2526 if (!(flags & SWP_NOSIZE))
2528 pDWP->winPos[i].cx = cx;
2529 pDWP->winPos[i].cy = cy;
2531 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2532 SWP_NOZORDER | SWP_NOREDRAW |
2533 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2535 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2540 if (pDWP->actualCount >= pDWP->suggestedCount)
2542 newhdwp = USER_HEAP_REALLOC( hdwp,
2543 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS32) );
2544 if (!newhdwp) return 0;
2545 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2546 pDWP->suggestedCount++;
2548 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2549 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2550 pDWP->winPos[pDWP->actualCount].x = x;
2551 pDWP->winPos[pDWP->actualCount].y = y;
2552 pDWP->winPos[pDWP->actualCount].cx = cx;
2553 pDWP->winPos[pDWP->actualCount].cy = cy;
2554 pDWP->winPos[pDWP->actualCount].flags = flags;
2555 pDWP->actualCount++;
2560 /***********************************************************************
2561 * EndDeferWindowPos16 (USER.261)
2563 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2565 return EndDeferWindowPos32( hdwp );
2569 /***********************************************************************
2570 * EndDeferWindowPos32 (USER32.173)
2572 BOOL32 WINAPI EndDeferWindowPos32( HDWP32 hdwp )
2575 WINDOWPOS32 *winpos;
2579 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2580 if (!pDWP) return FALSE;
2581 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2583 if (!(res = SetWindowPos32( winpos->hwnd, winpos->hwndInsertAfter,
2584 winpos->x, winpos->y, winpos->cx,
2585 winpos->cy, winpos->flags ))) break;
2587 USER_HEAP_FREE( hdwp );
2592 /***********************************************************************
2593 * TileChildWindows (USER.199)
2595 void WINAPI TileChildWindows( HWND16 parent, WORD action )
2597 FIXME(win, "(%04x, %d): stub\n", parent, action);
2600 /***********************************************************************
2601 * CascageChildWindows (USER.198)
2603 void WINAPI CascadeChildWindows( HWND16 parent, WORD action )
2605 FIXME(win, "(%04x, %d): stub\n", parent, action);
2607 /***********************************************************************
2608 * GetProgmanWindow [USER32.289]
2610 HRESULT WINAPI GetProgmanWindow ( )
2611 { FIXME(win,"stub\n");
2614 /***********************************************************************
2615 * GetTaskmanWindow [USER32.304]
2617 HRESULT WINAPI GetTaskmanWindow ( )
2618 { FIXME(win,"stub\n");
2621 /***********************************************************************
2622 * SetProgmanWindow [USER32.522]
2624 HRESULT WINAPI SetProgmanWindow ( DWORD x )
2625 { FIXME(win,"0x%08lx stub\n",x);
2628 /***********************************************************************
2629 * SetShellWindowEx [USER32.531]
2631 HRESULT WINAPI SetShellWindowEx ( DWORD x, DWORD y )
2632 { FIXME(win,"0x%08lx 0x%08lx stub\n",x,y);
2635 /***********************************************************************
2636 * SetTaskmanWindow [USER32.537]
2638 HRESULT WINAPI SetTaskmanWindow ( DWORD x )
2639 { FIXME(win,"0x%08lx stub\n",x);