2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
13 #include "wine/winuser16.h"
26 #include "nonclient.h"
27 #include "debugtools.h"
30 DEFAULT_DEBUG_CHANNEL(win);
32 #define HAS_DLGFRAME(style,exStyle) \
33 (((exStyle) & WS_EX_DLGMODALFRAME) || \
34 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
36 #define HAS_THICKFRAME(style) \
37 (((style) & WS_THICKFRAME) && \
38 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
40 #define SWP_AGG_NOGEOMETRYCHANGE \
41 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
42 #define SWP_AGG_NOPOSCHANGE \
43 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
44 #define SWP_AGG_STATUSFLAGS \
45 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
47 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
49 #define PLACE_MIN 0x0001
50 #define PLACE_MAX 0x0002
51 #define PLACE_RECT 0x0004
53 #define SWP_EX_NOCOPY 0x0001
54 #define SWP_EX_PAINTSELF 0x0002
55 #define SWP_EX_NONCLIENT 0x0004
57 #define MINMAX_NOSWP 0x00010000
59 /* ----- internal variables ----- */
61 static HWND hwndPrevActive = 0; /* Previously active window */
62 static HWND hGlobalShellWindow=0; /*the shell*/
63 static HWND hGlobalTaskmanWindow=0;
64 static HWND hGlobalProgmanWindow=0;
66 static LPCSTR atomInternalPos;
68 extern HQUEUE16 hActiveQueue;
70 /***********************************************************************
71 * WINPOS_CreateInternalPosAtom
73 BOOL WINPOS_CreateInternalPosAtom()
76 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
77 return (atomInternalPos) ? TRUE : FALSE;
80 /***********************************************************************
81 * WINPOS_CheckInternalPos
83 * Called when a window is destroyed.
85 void WINPOS_CheckInternalPos( WND* wndPtr )
88 MESSAGEQUEUE *pMsgQ = 0;
89 HWND hwnd = wndPtr->hwndSelf;
91 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
93 /* Retrieve the message queue associated with this window */
94 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
97 WARN("\tMessage queue not found. Exiting!\n" );
101 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
103 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
105 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
106 WARN("\tattempt to activate destroyed window!\n");
111 if( IsWindow(lpPos->hwndIconTitle) )
112 DestroyWindow( lpPos->hwndIconTitle );
113 HeapFree( SystemHeap, 0, lpPos );
116 QUEUE_Unlock( pMsgQ );
120 /***********************************************************************
123 * Find a suitable place for an iconic window.
125 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
128 short x, y, xspacing, yspacing;
130 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
131 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
132 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
133 return pt; /* The icon already has a suitable position */
135 xspacing = GetSystemMetrics(SM_CXICONSPACING);
136 yspacing = GetSystemMetrics(SM_CYICONSPACING);
138 y = rectParent.bottom;
144 /* Check if another icon already occupies this spot */
145 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
148 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
150 if ((childPtr->rectWindow.left < x + xspacing) &&
151 (childPtr->rectWindow.right >= x) &&
152 (childPtr->rectWindow.top <= y) &&
153 (childPtr->rectWindow.bottom > y - yspacing))
154 break; /* There's a window in there */
156 WIN_UpdateWndPtr(&childPtr,childPtr->next);
158 WIN_ReleaseWndPtr(childPtr);
159 if (!childPtr) /* No window was found, so it's OK for us */
161 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
162 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
166 } while(x <= rectParent.right-xspacing);
172 /***********************************************************************
173 * ArrangeIconicWindows16 (USER.170)
175 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
177 return ArrangeIconicWindows(parent);
179 /***********************************************************************
180 * ArrangeIconicWindows (USER32.7)
182 UINT WINAPI ArrangeIconicWindows( HWND parent )
186 INT x, y, xspacing, yspacing;
188 GetClientRect( parent, &rectParent );
190 y = rectParent.bottom;
191 xspacing = GetSystemMetrics(SM_CXICONSPACING);
192 yspacing = GetSystemMetrics(SM_CYICONSPACING);
194 hwndChild = GetWindow( parent, GW_CHILD );
197 if( IsIconic( hwndChild ) )
199 WND *wndPtr = WIN_FindWndPtr(hwndChild);
201 WINPOS_ShowIconTitle( wndPtr, FALSE );
203 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
204 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
205 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
206 if( IsWindow(hwndChild) )
207 WINPOS_ShowIconTitle(wndPtr , TRUE );
208 WIN_ReleaseWndPtr(wndPtr);
210 if (x <= rectParent.right - xspacing) x += xspacing;
217 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
223 /***********************************************************************
224 * SwitchToThisWindow16 (USER.172)
226 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
228 SwitchToThisWindow( hwnd, restore );
232 /***********************************************************************
233 * SwitchToThisWindow (USER32.539)
235 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
237 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
241 /***********************************************************************
242 * GetWindowRect16 (USER.32)
244 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
246 WND * wndPtr = WIN_FindWndPtr( hwnd );
249 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
250 if (wndPtr->dwStyle & WS_CHILD)
251 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
252 WIN_ReleaseWndPtr(wndPtr);
256 /***********************************************************************
257 * GetWindowRect (USER32.308)
259 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
261 WND * wndPtr = WIN_FindWndPtr( hwnd );
262 if (!wndPtr) return FALSE;
264 *rect = wndPtr->rectWindow;
265 if (wndPtr->dwStyle & WS_CHILD)
266 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
267 WIN_ReleaseWndPtr(wndPtr);
272 /***********************************************************************
273 * GetWindowRgn (USER32)
275 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
278 WND *wndPtr = WIN_FindWndPtr( hwnd );
281 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
282 WIN_ReleaseWndPtr(wndPtr);
287 /***********************************************************************
288 * SetWindowRgn (USER32)
290 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
295 WND *wndPtr = WIN_FindWndPtr(hwnd);
297 if (!wndPtr) return FALSE;
299 /* a region exists for this window */
300 if (hrgn != 0 && hrgn == wndPtr->hrgnWnd)
302 /* can't replace actual region with same region
303 since we're now owner of that region
305 SetLastError(ERROR_INVALID_HANDLE);
310 /* we'd like to set it back to 0 */
313 GetWindowRect(hwnd, &tempRect);
317 /* verify that region really exists */
318 if (GetRgnBox(hrgn, &tempRect) == ERROR) goto done;
322 /* Size the window to the rectangle of the new region
323 (if it isn't NULL) */
324 SetWindowPos( hwnd, 0, tempRect.left, tempRect.top,
325 tempRect.right - tempRect.left, tempRect.bottom - tempRect.top,
326 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE |
327 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
332 /* delete previous region */
333 DeleteObject(wndPtr->hrgnWnd);
338 /* if there was no previous region (stored in wndPtr->hrgnWnd) and
339 the region to be set is also NULL, there is nothing more to do
345 /* valid region handle */
346 wndPtr->hrgnWnd = hrgn;
347 wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn);
352 WIN_ReleaseWndPtr(wndPtr);
356 /***********************************************************************
359 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
363 FIXME("SetWindowRgn16: stub\n");
368 /***********************************************************************
369 * GetClientRect16 (USER.33)
371 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
373 WND * wndPtr = WIN_FindWndPtr( hwnd );
375 rect->left = rect->top = rect->right = rect->bottom = 0;
378 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
379 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
381 WIN_ReleaseWndPtr(wndPtr);
385 /***********************************************************************
386 * GetClientRect (USER.220)
388 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
390 WND * wndPtr = WIN_FindWndPtr( hwnd );
392 rect->left = rect->top = rect->right = rect->bottom = 0;
393 if (!wndPtr) return FALSE;
394 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
395 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
397 WIN_ReleaseWndPtr(wndPtr);
402 /*******************************************************************
403 * ClientToScreen16 (USER.28)
405 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
407 MapWindowPoints16( hwnd, 0, lppnt, 1 );
411 /*******************************************************************
412 * ClientToScreen (USER32.52)
414 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
416 MapWindowPoints( hwnd, 0, lppnt, 1 );
421 /*******************************************************************
422 * ScreenToClient16 (USER.29)
424 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
426 MapWindowPoints16( 0, hwnd, lppnt, 1 );
430 /*******************************************************************
431 * ScreenToClient (USER32.447)
433 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
435 MapWindowPoints( 0, hwnd, lppnt, 1 );
440 /***********************************************************************
441 * WINPOS_WindowFromPoint
443 * Find the window and hittest for a given point.
445 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
448 INT16 hittest = HTERROR;
452 TRACE("scope %04x %d,%d\n", wndScope->hwndSelf, pt.x, pt.y);
454 wndPtr = WIN_LockWndPtr(wndScope->child);
456 if( wndScope->dwStyle & WS_DISABLED )
462 if( wndScope->dwExStyle & WS_EX_MANAGED)
464 /* In managed mode we have to check wndScope first as it is also
465 * a window which received the mouse event. */
467 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
468 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
471 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
477 /* If point is in window, and window is visible, and it */
478 /* is enabled (or it's a top-level window), then explore */
479 /* its children. Otherwise, go to the next window. */
481 if ((wndPtr->dwStyle & WS_VISIBLE) &&
482 (!(wndPtr->dwStyle & WS_DISABLED) ||
483 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
485 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
486 xy.y - wndPtr->rectWindow.top) :
487 ((xy.x >= wndPtr->rectWindow.left) &&
488 (xy.x < wndPtr->rectWindow.right) &&
489 (xy.y >= wndPtr->rectWindow.top) &&
490 (xy.y < wndPtr->rectWindow.bottom))))
492 TRACE("%d,%d is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
493 *ppWnd = wndPtr; /* Got a suitable window */
495 /* If window is minimized or disabled, return at once */
496 if (wndPtr->dwStyle & WS_MINIMIZE)
498 retvalue = HTCAPTION;
501 if (wndPtr->dwStyle & WS_DISABLED)
507 /* If point is not in client area, ignore the children */
508 if ((xy.x < wndPtr->rectClient.left) ||
509 (xy.x >= wndPtr->rectClient.right) ||
510 (xy.y < wndPtr->rectClient.top) ||
511 (xy.y >= wndPtr->rectClient.bottom)) break;
513 xy.x -= wndPtr->rectClient.left;
514 xy.y -= wndPtr->rectClient.top;
515 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
519 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
524 /* If nothing found, try the scope window */
525 if (!*ppWnd) *ppWnd = wndScope;
527 /* Send the WM_NCHITTEST message (only if to the same task) */
528 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
530 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
531 0, MAKELONG( pt.x, pt.y ) );
532 if (hittest != HTTRANSPARENT)
534 retvalue = hittest; /* Found the window */
544 /* If no children found in last search, make point relative to parent */
547 xy.x += (*ppWnd)->rectClient.left;
548 xy.y += (*ppWnd)->rectClient.top;
551 /* Restart the search from the next sibling */
552 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
553 *ppWnd = (*ppWnd)->parent;
557 WIN_ReleaseWndPtr(wndPtr);
562 /*******************************************************************
563 * WindowFromPoint16 (USER.30)
565 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
568 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
569 WIN_ReleaseDesktop();
570 return pWnd->hwndSelf;
574 /*******************************************************************
575 * WindowFromPoint (USER32.582)
577 HWND WINAPI WindowFromPoint( POINT pt )
581 CONV_POINT32TO16( &pt, &pt16 );
582 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
583 WIN_ReleaseDesktop();
584 return (HWND)pWnd->hwndSelf;
588 /*******************************************************************
589 * ChildWindowFromPoint16 (USER.191)
591 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
594 CONV_POINT16TO32( &pt, &pt32 );
595 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
599 /*******************************************************************
600 * ChildWindowFromPoint (USER32.49)
602 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
604 /* pt is in the client coordinates */
606 WND* wnd = WIN_FindWndPtr(hwndParent);
612 /* get client rect fast */
613 rect.top = rect.left = 0;
614 rect.right = wnd->rectClient.right - wnd->rectClient.left;
615 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
617 if (!PtInRect( &rect, pt ))
622 WIN_UpdateWndPtr(&wnd,wnd->child);
625 if (PtInRect( &wnd->rectWindow, pt ))
627 retvalue = wnd->hwndSelf;
630 WIN_UpdateWndPtr(&wnd,wnd->next);
632 retvalue = hwndParent;
634 WIN_ReleaseWndPtr(wnd);
638 /*******************************************************************
639 * ChildWindowFromPointEx16 (USER.50)
641 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
644 CONV_POINT16TO32( &pt, &pt32 );
645 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
649 /*******************************************************************
650 * ChildWindowFromPointEx (USER32.50)
652 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
655 /* pt is in the client coordinates */
657 WND* wnd = WIN_FindWndPtr(hwndParent);
663 /* get client rect fast */
664 rect.top = rect.left = 0;
665 rect.right = wnd->rectClient.right - wnd->rectClient.left;
666 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
668 if (!PtInRect( &rect, pt ))
673 WIN_UpdateWndPtr(&wnd,wnd->child);
677 if (PtInRect( &wnd->rectWindow, pt )) {
678 if ( (uFlags & CWP_SKIPINVISIBLE) &&
679 !(wnd->dwStyle & WS_VISIBLE) );
680 else if ( (uFlags & CWP_SKIPDISABLED) &&
681 (wnd->dwStyle & WS_DISABLED) );
682 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
683 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
686 retvalue = wnd->hwndSelf;
691 WIN_UpdateWndPtr(&wnd,wnd->next);
693 retvalue = hwndParent;
695 WIN_ReleaseWndPtr(wnd);
700 /*******************************************************************
701 * WINPOS_GetWinOffset
703 * Calculate the offset between the origin of the two windows. Used
704 * to implement MapWindowPoints.
706 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
711 offset->x = offset->y = 0;
712 if (hwndFrom == hwndTo ) return;
714 /* Translate source window origin to screen coords */
717 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
719 ERR("bad hwndFrom = %04x\n",hwndFrom);
722 while (wndPtr->parent)
724 offset->x += wndPtr->rectClient.left;
725 offset->y += wndPtr->rectClient.top;
726 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
728 WIN_ReleaseWndPtr(wndPtr);
731 /* Translate origin to destination window coords */
734 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
736 ERR("bad hwndTo = %04x\n", hwndTo );
739 while (wndPtr->parent)
741 offset->x -= wndPtr->rectClient.left;
742 offset->y -= wndPtr->rectClient.top;
743 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
745 WIN_ReleaseWndPtr(wndPtr);
750 /*******************************************************************
751 * MapWindowPoints16 (USER.258)
753 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
754 LPPOINT16 lppt, UINT16 count )
758 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
768 /*******************************************************************
769 * MapWindowPoints (USER32.386)
771 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
772 LPPOINT lppt, UINT count )
776 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
783 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
787 /***********************************************************************
788 * IsIconic16 (USER.31)
790 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
792 return IsIconic(hWnd);
796 /***********************************************************************
797 * IsIconic (USER32.345)
799 BOOL WINAPI IsIconic(HWND hWnd)
802 WND * wndPtr = WIN_FindWndPtr(hWnd);
803 if (wndPtr == NULL) return FALSE;
804 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
805 WIN_ReleaseWndPtr(wndPtr);
810 /***********************************************************************
811 * IsZoomed (USER.272)
813 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
815 return IsZoomed(hWnd);
819 /***********************************************************************
820 * IsZoomed (USER.352)
822 BOOL WINAPI IsZoomed(HWND hWnd)
825 WND * wndPtr = WIN_FindWndPtr(hWnd);
826 if (wndPtr == NULL) return FALSE;
827 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
828 WIN_ReleaseWndPtr(wndPtr);
833 /*******************************************************************
834 * GetActiveWindow (USER.60)
836 HWND16 WINAPI GetActiveWindow16(void)
838 return (HWND16)GetActiveWindow();
841 /*******************************************************************
842 * GetActiveWindow (USER32.205)
844 HWND WINAPI GetActiveWindow(void)
846 MESSAGEQUEUE *pCurMsgQ = 0;
849 /* Get the messageQ for the current thread */
850 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
852 WARN("\tCurrent message queue not found. Exiting!\n" );
856 /* Return the current active window from the perQ data of the current message Q */
857 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
859 QUEUE_Unlock( pCurMsgQ );
864 /*******************************************************************
867 static BOOL WINPOS_CanActivate(WND* pWnd)
869 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
870 == WS_VISIBLE ) ) return TRUE;
875 /*******************************************************************
876 * SetActiveWindow16 (USER.59)
878 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
880 return SetActiveWindow(hwnd);
884 /*******************************************************************
885 * SetActiveWindow (USER32.463)
887 HWND WINAPI SetActiveWindow( HWND hwnd )
890 WND *wndPtr = WIN_FindWndPtr( hwnd );
891 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
893 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
899 /* Get the messageQ for the current thread */
900 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
902 WARN("\tCurrent message queue not found. Exiting!\n" );
906 /* Retrieve the message queue associated with this window */
907 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
910 WARN("\tWindow message queue not found. Exiting!\n" );
914 /* Make sure that the window is associated with the calling threads
915 * message queue. It must share the same perQ data.
918 if ( pCurMsgQ->pQData != pMsgQ->pQData )
921 /* Save current active window */
922 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
924 WINPOS_SetActiveWindow( hwnd, 0, 0 );
927 /* Unlock the queues before returning */
929 QUEUE_Unlock( pMsgQ );
931 QUEUE_Unlock( pCurMsgQ );
934 WIN_ReleaseWndPtr(wndPtr);
939 /*******************************************************************
940 * GetForegroundWindow16 (USER.608)
942 HWND16 WINAPI GetForegroundWindow16(void)
944 return (HWND16)GetForegroundWindow();
948 /*******************************************************************
949 * SetForegroundWindow16 (USER.609)
951 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
953 return SetForegroundWindow( hwnd );
957 /*******************************************************************
958 * GetForegroundWindow (USER32.241)
960 HWND WINAPI GetForegroundWindow(void)
964 /* Get the foreground window (active window of hActiveQueue) */
967 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
969 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
971 QUEUE_Unlock( pActiveQueue );
977 /*******************************************************************
978 * SetForegroundWindow (USER32.482)
980 BOOL WINAPI SetForegroundWindow( HWND hwnd )
982 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
986 /*******************************************************************
987 * AllowSetForegroundWindow (USER32)
989 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
991 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
992 * implemented, then fix this function. */
997 /*******************************************************************
998 * LockSetForegroundWindow (USER32)
1000 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
1002 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
1003 * implemented, then fix this function. */
1008 /*******************************************************************
1009 * GetShellWindow16 (USER.600)
1011 HWND16 WINAPI GetShellWindow16(void)
1013 return GetShellWindow();
1016 /*******************************************************************
1017 * SetShellWindow (USER32.504)
1019 HWND WINAPI SetShellWindow(HWND hwndshell)
1020 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
1022 hGlobalShellWindow = hwndshell;
1023 return hGlobalShellWindow;
1027 /*******************************************************************
1028 * GetShellWindow (USER32.287)
1030 HWND WINAPI GetShellWindow(void)
1031 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
1033 return hGlobalShellWindow;
1037 /***********************************************************************
1038 * BringWindowToTop16 (USER.45)
1040 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1042 return BringWindowToTop(hwnd);
1046 /***********************************************************************
1047 * BringWindowToTop (USER32.11)
1049 BOOL WINAPI BringWindowToTop( HWND hwnd )
1051 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1055 /***********************************************************************
1056 * MoveWindow16 (USER.56)
1058 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1061 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1065 /***********************************************************************
1066 * MoveWindow (USER32.399)
1068 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1071 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1072 if (!repaint) flags |= SWP_NOREDRAW;
1073 TRACE("%04x %d,%d %dx%d %d\n",
1074 hwnd, x, y, cx, cy, repaint );
1075 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1078 /***********************************************************************
1079 * WINPOS_InitInternalPos
1081 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1082 LPRECT restoreRect )
1084 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1088 /* this happens when the window is minimized/maximized
1089 * for the first time (rectWindow is not adjusted yet) */
1091 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1092 if( !lpPos ) return NULL;
1094 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1095 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1096 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1097 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1100 if( wnd->dwStyle & WS_MINIMIZE )
1101 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1102 else if( wnd->dwStyle & WS_MAXIMIZE )
1103 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1104 else if( restoreRect )
1105 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1110 /***********************************************************************
1111 * WINPOS_RedrawIconTitle
1113 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1115 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1118 if( lpPos->hwndIconTitle )
1120 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1121 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1128 /***********************************************************************
1129 * WINPOS_ShowIconTitle
1131 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1133 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1135 if( lpPos && !(pWnd->dwExStyle & WS_EX_MANAGED))
1137 HWND16 hWnd = lpPos->hwndIconTitle;
1139 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1142 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1145 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1147 if( !(pWnd->dwStyle & WS_VISIBLE) )
1149 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1150 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1151 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1153 WIN_ReleaseWndPtr(pWnd);
1156 else ShowWindow( hWnd, SW_HIDE );
1161 /*******************************************************************
1162 * WINPOS_GetMinMaxInfo
1164 * Get the minimized and maximized information for a window.
1166 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1167 POINT *minTrack, POINT *maxTrack )
1169 LPINTERNALPOS lpPos;
1173 /* Compute default values */
1175 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1176 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1177 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1178 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1179 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1180 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1182 if (wndPtr->dwExStyle & WS_EX_MANAGED) xinc = yinc = 0;
1183 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1185 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1186 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1191 if (HAS_THICKFRAME(wndPtr->dwStyle))
1193 xinc += GetSystemMetrics(SM_CXFRAME);
1194 yinc += GetSystemMetrics(SM_CYFRAME);
1196 if (wndPtr->dwStyle & WS_BORDER)
1198 xinc += GetSystemMetrics(SM_CXBORDER);
1199 yinc += GetSystemMetrics(SM_CYBORDER);
1202 MinMax.ptMaxSize.x += 2 * xinc;
1203 MinMax.ptMaxSize.y += 2 * yinc;
1205 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1206 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1207 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1210 MinMax.ptMaxPosition.x = -xinc;
1211 MinMax.ptMaxPosition.y = -yinc;
1214 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1216 /* Some sanity checks */
1218 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1219 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1220 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1221 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1222 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1223 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1224 MinMax.ptMinTrackSize.x );
1225 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1226 MinMax.ptMinTrackSize.y );
1228 if (maxSize) *maxSize = MinMax.ptMaxSize;
1229 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1230 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1231 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1234 /***********************************************************************
1235 * WINPOS_MinMaximize
1237 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1238 * This function assumes that 'cmd' is different from the current window
1241 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1245 LPINTERNALPOS lpPos;
1247 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1249 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1250 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1252 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1254 if( wndPtr->dwStyle & WS_MINIMIZE )
1256 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1257 return (SWP_NOSIZE | SWP_NOMOVE);
1258 swpFlags |= SWP_NOCOPYBITS;
1263 if( wndPtr->dwStyle & WS_MAXIMIZE)
1265 wndPtr->flags |= WIN_RESTORE_MAX;
1266 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1269 wndPtr->flags &= ~WIN_RESTORE_MAX;
1270 wndPtr->dwStyle |= WS_MINIMIZE;
1272 if( wndPtr->flags & WIN_NATIVE )
1273 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1274 swpFlags |= MINMAX_NOSWP;
1276 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1278 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1279 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1280 swpFlags |= SWP_NOCOPYBITS;
1284 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1285 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1286 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1288 if( wndPtr->dwStyle & WS_MINIMIZE )
1290 if( wndPtr->flags & WIN_NATIVE )
1291 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1293 WINPOS_ShowIconTitle( wndPtr, FALSE );
1294 wndPtr->dwStyle &= ~WS_MINIMIZE;
1296 wndPtr->dwStyle |= WS_MAXIMIZE;
1298 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1303 if( wndPtr->dwStyle & WS_MINIMIZE )
1305 if( wndPtr->flags & WIN_NATIVE )
1306 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1307 swpFlags |= MINMAX_NOSWP;
1309 wndPtr->dwStyle &= ~WS_MINIMIZE;
1310 WINPOS_ShowIconTitle( wndPtr, FALSE );
1312 if( wndPtr->flags & WIN_RESTORE_MAX)
1314 /* Restore to maximized position */
1315 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1316 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1317 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1318 wndPtr->dwStyle |= WS_MAXIMIZE;
1319 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1324 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1325 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1327 /* Restore to normal position */
1329 *lpRect = lpPos->rectNormal;
1330 lpRect->right -= lpRect->left;
1331 lpRect->bottom -= lpRect->top;
1335 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1339 /***********************************************************************
1340 * ShowWindowAsync (USER32.535)
1342 * doesn't wait; returns immediately.
1343 * used by threads to toggle windows in other (possibly hanging) threads
1345 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1347 /* FIXME: does ShowWindow() return immediately ? */
1348 return ShowWindow(hwnd, cmd);
1352 /***********************************************************************
1353 * ShowWindow16 (USER.42)
1355 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1357 return ShowWindow(hwnd,cmd);
1361 /***********************************************************************
1362 * ShowWindow (USER32.534)
1364 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1366 WND* wndPtr = WIN_FindWndPtr( hwnd );
1367 BOOL wasVisible, showFlag;
1368 RECT16 newPos = {0, 0, 0, 0};
1371 if (!wndPtr) return FALSE;
1373 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1375 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1380 if (!wasVisible) goto END;;
1381 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1382 SWP_NOACTIVATE | SWP_NOZORDER;
1385 case SW_SHOWMINNOACTIVE:
1386 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1388 case SW_SHOWMINIMIZED:
1389 swp |= SWP_SHOWWINDOW;
1392 swp |= SWP_FRAMECHANGED;
1393 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1394 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1395 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1398 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1399 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1400 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1401 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1402 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1406 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1409 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1412 * ShowWindow has a little peculiar behavior that if the
1413 * window is already the topmost window, it will not
1416 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1417 swp |= SWP_NOACTIVATE;
1421 case SW_SHOWNOACTIVATE:
1422 swp |= SWP_NOZORDER;
1423 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1425 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1426 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1428 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1430 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1431 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1432 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1436 showFlag = (cmd != SW_HIDE);
1437 if (showFlag != wasVisible)
1439 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1440 if (!IsWindow( hwnd )) goto END;
1443 if ((wndPtr->dwStyle & WS_CHILD) &&
1444 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1445 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1447 /* Don't call SetWindowPos() on invisible child windows */
1448 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1449 else wndPtr->dwStyle |= WS_VISIBLE;
1453 /* We can't activate a child window */
1454 if ((wndPtr->dwStyle & WS_CHILD) &&
1455 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1456 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1457 if (!(swp & MINMAX_NOSWP))
1459 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1460 newPos.right, newPos.bottom, LOWORD(swp) );
1463 /* FIXME: This will cause the window to be activated irrespective
1464 * of whether it is owned by the same thread. Has to be done
1468 if (hwnd == GetActiveWindow())
1469 WINPOS_ActivateOtherWindow(wndPtr);
1471 /* Revert focus to parent */
1472 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1473 SetFocus( GetParent(hwnd) );
1476 if (!IsWindow( hwnd )) goto END;
1477 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1480 if (wndPtr->flags & WIN_NEED_SIZE)
1482 /* should happen only in CreateWindowEx() */
1483 int wParam = SIZE_RESTORED;
1485 wndPtr->flags &= ~WIN_NEED_SIZE;
1486 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1487 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1488 SendMessageA( hwnd, WM_SIZE, wParam,
1489 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1490 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1491 SendMessageA( hwnd, WM_MOVE, 0,
1492 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1496 WIN_ReleaseWndPtr(wndPtr);
1501 /***********************************************************************
1502 * GetInternalWindowPos16 (USER.460)
1504 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1507 WINDOWPLACEMENT16 wndpl;
1508 if (GetWindowPlacement16( hwnd, &wndpl ))
1510 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1511 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1512 return wndpl.showCmd;
1518 /***********************************************************************
1519 * GetInternalWindowPos (USER32.245)
1521 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1524 WINDOWPLACEMENT wndpl;
1525 if (GetWindowPlacement( hwnd, &wndpl ))
1527 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1528 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1529 return wndpl.showCmd;
1534 /***********************************************************************
1535 * GetWindowPlacement16 (USER.370)
1537 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1539 WND *pWnd = WIN_FindWndPtr( hwnd );
1540 LPINTERNALPOS lpPos;
1542 if(!pWnd ) return FALSE;
1544 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1545 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1546 wndpl->length = sizeof(*wndpl);
1547 if( pWnd->dwStyle & WS_MINIMIZE )
1548 wndpl->showCmd = SW_SHOWMINIMIZED;
1550 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1551 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1552 if( pWnd->flags & WIN_RESTORE_MAX )
1553 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1556 wndpl->ptMinPosition = lpPos->ptIconPos;
1557 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1558 wndpl->rcNormalPosition = lpPos->rectNormal;
1560 WIN_ReleaseWndPtr(pWnd);
1565 /***********************************************************************
1566 * GetWindowPlacement (USER32.307)
1569 * Fails if wndpl->length of Win95 (!) apps is invalid.
1571 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1575 WINDOWPLACEMENT16 wpl;
1576 wpl.length = sizeof(wpl);
1577 if( GetWindowPlacement16( hwnd, &wpl ) )
1579 pwpl32->length = sizeof(*pwpl32);
1580 pwpl32->flags = wpl.flags;
1581 pwpl32->showCmd = wpl.showCmd;
1582 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1583 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1584 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1592 /***********************************************************************
1593 * WINPOS_SetPlacement
1595 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1598 WND *pWnd = WIN_FindWndPtr( hwnd );
1601 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1602 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1604 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1605 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1606 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1608 if( pWnd->dwStyle & WS_MINIMIZE )
1610 WINPOS_ShowIconTitle( pWnd, FALSE );
1611 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1612 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1613 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1615 else if( pWnd->dwStyle & WS_MAXIMIZE )
1617 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1618 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1619 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1621 else if( flags & PLACE_RECT )
1622 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1623 lpPos->rectNormal.right - lpPos->rectNormal.left,
1624 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1625 SWP_NOZORDER | SWP_NOACTIVATE );
1627 ShowWindow( hwnd, wndpl->showCmd );
1628 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1630 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1632 /* SDK: ...valid only the next time... */
1633 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1635 WIN_ReleaseWndPtr(pWnd);
1642 /***********************************************************************
1643 * SetWindowPlacement16 (USER.371)
1645 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1647 return WINPOS_SetPlacement( hwnd, wndpl,
1648 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1651 /***********************************************************************
1652 * SetWindowPlacement (USER32.519)
1655 * Fails if wndpl->length of Win95 (!) apps is invalid.
1657 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1661 WINDOWPLACEMENT16 wpl;
1663 wpl.length = sizeof(WINDOWPLACEMENT16);
1664 wpl.flags = pwpl32->flags;
1665 wpl.showCmd = pwpl32->showCmd;
1666 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1667 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1668 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1669 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1670 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1671 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1672 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1673 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1675 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1681 /***********************************************************************
1682 * SetInternalWindowPos16 (USER.461)
1684 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1685 LPRECT16 rect, LPPOINT16 pt )
1687 if( IsWindow16(hwnd) )
1689 WINDOWPLACEMENT16 wndpl;
1692 wndpl.length = sizeof(wndpl);
1693 wndpl.showCmd = showCmd;
1694 wndpl.flags = flags = 0;
1699 wndpl.flags |= WPF_SETMINPOSITION;
1700 wndpl.ptMinPosition = *pt;
1704 flags |= PLACE_RECT;
1705 wndpl.rcNormalPosition = *rect;
1707 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1712 /***********************************************************************
1713 * SetInternalWindowPos (USER32.483)
1715 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1716 LPRECT rect, LPPOINT pt )
1718 if( IsWindow(hwnd) )
1720 WINDOWPLACEMENT16 wndpl;
1723 wndpl.length = sizeof(wndpl);
1724 wndpl.showCmd = showCmd;
1725 wndpl.flags = flags = 0;
1730 wndpl.flags |= WPF_SETMINPOSITION;
1731 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1735 flags |= PLACE_RECT;
1736 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1738 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1742 /*******************************************************************
1743 * WINPOS_SetActiveWindow
1745 * SetActiveWindow() back-end. This is the only function that
1746 * can assign active status to a window. It must be called only
1747 * for the top level windows.
1749 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1751 CBTACTIVATESTRUCT16* cbtStruct;
1752 WND* wndPtr=0, *wndTemp;
1753 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1754 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1756 HWND hwndActive = 0;
1759 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1761 /* Get current active window from the active queue */
1764 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1765 if ( pOldActiveQueue )
1766 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1769 /* paranoid checks */
1770 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1773 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1776 wndPtr = WIN_FindWndPtr(hWnd);
1777 hOldActiveQueue = hActiveQueue;
1779 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1781 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1782 WIN_ReleaseWndPtr(wndTemp);
1785 TRACE("no current active window.\n");
1787 /* call CBT hook chain */
1788 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1790 cbtStruct->fMouse = fMouse;
1791 cbtStruct->hWndActive = hwndActive;
1792 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1793 (LPARAM)SEGPTR_GET(cbtStruct) );
1794 SEGPTR_FREE(cbtStruct);
1795 if (bRet) goto CLEANUP_END;
1798 /* set prev active wnd to current active wnd and send notification */
1799 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1801 MESSAGEQUEUE *pTempActiveQueue = 0;
1803 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1805 if (GetSysModalWindow16() != hWnd)
1807 /* disregard refusal if hWnd is sysmodal */
1810 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1811 MAKEWPARAM( WA_INACTIVE, wIconized ),
1814 /* check if something happened during message processing
1815 * (global active queue may have changed)
1817 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1818 if(!pTempActiveQueue)
1821 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1822 QUEUE_Unlock( pTempActiveQueue );
1823 if( hwndPrevActive != hwndActive )
1827 /* Set new active window in the message queue */
1831 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1832 if ( pNewActiveQueue )
1833 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1835 else /* have to do this or MDI frame activation goes to hell */
1836 if( pOldActiveQueue )
1837 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1839 /* send palette messages */
1840 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1841 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1843 /* if prev wnd is minimized redraw icon title */
1844 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1846 /* managed windows will get ConfigureNotify event */
1847 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1849 /* check Z-order and bring hWnd to the top */
1850 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1852 if (wndTemp->dwStyle & WS_VISIBLE) break;
1854 WIN_ReleaseDesktop();
1855 WIN_ReleaseWndPtr(wndTemp);
1857 if( wndTemp != wndPtr )
1858 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1859 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1860 if (!IsWindow(hWnd))
1864 /* Get a handle to the new active queue */
1865 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1867 /* send WM_ACTIVATEAPP if necessary */
1868 if (hOldActiveQueue != hNewActiveQueue)
1870 WND **list, **ppWnd;
1871 WND *pDesktop = WIN_GetDesktop();
1873 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1875 for (ppWnd = list; *ppWnd; ppWnd++)
1877 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1879 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1880 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1881 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1883 WIN_ReleaseWinArray(list);
1886 hActiveQueue = hNewActiveQueue;
1888 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1890 for (ppWnd = list; *ppWnd; ppWnd++)
1892 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1894 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1895 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1896 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1898 WIN_ReleaseWinArray(list);
1900 WIN_ReleaseDesktop();
1902 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1907 /* walk up to the first unowned window */
1908 wndTemp = WIN_LockWndPtr(wndPtr);
1909 while (wndTemp->owner)
1911 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1913 /* and set last active owned popup */
1914 wndTemp->hwndLastActive = hWnd;
1916 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1917 WIN_ReleaseWndPtr(wndTemp);
1918 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1919 SendMessageA( hWnd, WM_ACTIVATE,
1920 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1921 (LPARAM)hwndPrevActive );
1922 if( !IsWindow(hWnd) ) goto CLEANUP;
1925 /* change focus if possible */
1928 if ( pNewActiveQueue )
1930 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1932 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1933 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1934 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1938 if ( pOldActiveQueue &&
1939 ( !pNewActiveQueue ||
1940 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1942 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1944 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1948 if( !hwndPrevActive && wndPtr )
1949 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1951 /* if active wnd is minimized redraw icon title */
1952 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1954 bRet = (hWnd == hwndActive); /* Success? */
1956 CLEANUP: /* Unlock the message queues before returning */
1958 if ( pNewActiveQueue )
1959 QUEUE_Unlock( pNewActiveQueue );
1963 if ( pOldActiveQueue )
1964 QUEUE_Unlock( pOldActiveQueue );
1966 WIN_ReleaseWndPtr(wndPtr);
1970 /*******************************************************************
1971 * WINPOS_ActivateOtherWindow
1973 * Activates window other than pWnd.
1975 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1979 HWND hwndActive = 0;
1981 /* Get current active window from the active queue */
1984 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1987 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1988 QUEUE_Unlock( pActiveQueue );
1992 if( pWnd->hwndSelf == hwndPrevActive )
1995 if( hwndActive != pWnd->hwndSelf &&
1996 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1999 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
2000 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
2002 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
2004 WIN_ReleaseWndPtr(pWndTo);
2005 pWndTo = WIN_FindWndPtr(hwndPrevActive);
2007 while( !WINPOS_CanActivate(pWndTo) )
2009 /* by now owned windows should've been taken care of */
2010 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
2011 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
2012 if( !pWndTo ) break;
2014 WIN_ReleaseWndPtr(pWndPtr);
2017 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
2019 /* switch desktop queue to current active */
2022 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
2023 WIN_ReleaseWndPtr(pWndTo);
2024 WIN_ReleaseDesktop();
2031 /*******************************************************************
2032 * WINPOS_ChangeActiveWindow
2035 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2037 WND *wndPtr, *wndTemp;
2039 HWND hwndActive = 0;
2041 /* Get current active window from the active queue */
2044 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2047 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2048 QUEUE_Unlock( pActiveQueue );
2053 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2055 wndPtr = WIN_FindWndPtr(hWnd);
2056 if( !wndPtr ) return FALSE;
2058 /* child windows get WM_CHILDACTIVATE message */
2059 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2061 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2065 if( hWnd == hwndActive )
2071 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2077 /* switch desktop queue to current active */
2078 wndTemp = WIN_GetDesktop();
2079 if( wndPtr->parent == wndTemp)
2080 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2081 WIN_ReleaseDesktop();
2085 WIN_ReleaseWndPtr(wndPtr);
2090 /***********************************************************************
2091 * WINPOS_SendNCCalcSize
2093 * Send a WM_NCCALCSIZE message to a window.
2094 * All parameters are read-only except newClientRect.
2095 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2096 * when calcValidRect is TRUE.
2098 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2099 RECT *newWindowRect, RECT *oldWindowRect,
2100 RECT *oldClientRect, WINDOWPOS *winpos,
2101 RECT *newClientRect )
2103 NCCALCSIZE_PARAMS params;
2104 WINDOWPOS winposCopy;
2107 params.rgrc[0] = *newWindowRect;
2110 winposCopy = *winpos;
2111 params.rgrc[1] = *oldWindowRect;
2112 params.rgrc[2] = *oldClientRect;
2113 params.lppos = &winposCopy;
2115 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2117 TRACE("%d,%d-%d,%d\n",
2118 params.rgrc[0].left, params.rgrc[0].top,
2119 params.rgrc[0].right, params.rgrc[0].bottom );
2121 /* If the application send back garbage, ignore it */
2122 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2123 *newClientRect = params.rgrc[0];
2129 /***********************************************************************
2130 * WINPOS_HandleWindowPosChanging16
2132 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2134 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2136 POINT maxSize, minTrack;
2137 if (winpos->flags & SWP_NOSIZE) return 0;
2138 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2139 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2141 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2142 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2143 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2144 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2146 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2147 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2154 /***********************************************************************
2155 * WINPOS_HandleWindowPosChanging
2157 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2159 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2161 POINT maxSize, minTrack;
2162 if (winpos->flags & SWP_NOSIZE) return 0;
2163 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2164 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2166 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2167 winpos->cx = min( winpos->cx, maxSize.x );
2168 winpos->cy = min( winpos->cy, maxSize.y );
2169 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2171 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2172 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2178 /***********************************************************************
2181 * fix Z order taking into account owned popups -
2182 * basically we need to maintain them above the window that owns them
2184 * FIXME: hide/show owned popups when owner visibility changes.
2186 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2188 WND* w = WIN_LockWndPtr(pDesktop->child);
2190 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2192 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2194 /* make sure this popup stays above the owner */
2196 HWND hwndLocalPrev = HWND_TOP;
2198 if( hwndInsertAfter != HWND_TOP )
2200 while( w != wndPtr->owner )
2202 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2203 if( hwndLocalPrev == hwndInsertAfter ) break;
2204 WIN_UpdateWndPtr(&w,w->next);
2206 hwndInsertAfter = hwndLocalPrev;
2209 else if( wndPtr->dwStyle & WS_CHILD )
2212 WIN_UpdateWndPtr(&w, pDesktop->child);
2216 if( w == wndPtr ) break;
2218 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2220 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2221 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2222 hwndInsertAfter = w->hwndSelf;
2224 WIN_UpdateWndPtr(&w, w->next);
2228 WIN_ReleaseWndPtr(w);
2229 return hwndInsertAfter;
2232 /***********************************************************************
2235 * Make window look nice without excessive repainting
2237 * visible and update regions are in window coordinates
2238 * client and window rectangles are in parent client coordinates
2240 * Returns: uFlags and a dirty region in *pVisRgn.
2242 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2243 LPRECT lpOldWndRect,
2244 LPRECT lpOldClientRect, UINT uFlags )
2247 HRGN newVisRgn, dirtyRgn;
2248 INT my = COMPLEXREGION;
2250 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2251 Wnd->rectWindow.left, Wnd->rectWindow.top,
2252 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2253 lpOldWndRect->left, lpOldWndRect->top,
2254 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2255 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2256 Wnd->rectClient.left, Wnd->rectClient.top,
2257 Wnd->rectClient.right, Wnd->rectClient.bottom,
2258 lpOldClientRect->left, lpOldClientRect->top,
2259 lpOldClientRect->right,lpOldClientRect->bottom );
2261 if( Wnd->hrgnUpdate == 1 )
2262 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2264 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2265 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2267 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2268 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2270 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2274 TRACE("\twon't copy anything!\n");
2276 /* set dirtyRgn to the sum of old and new visible regions
2277 * in parent client coordinates */
2279 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2280 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2282 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2284 else /* copy valid bits to a new location */
2286 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2287 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2289 /* subtract already invalid region inside Wnd from the dst region */
2291 if( Wnd->hrgnUpdate )
2292 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2295 /* check if entire window can be copied */
2297 ow = lpOldWndRect->right - lpOldWndRect->left;
2298 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2299 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2300 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2302 ocw = lpOldClientRect->right - lpOldClientRect->left;
2303 och = lpOldClientRect->bottom - lpOldClientRect->top;
2304 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2305 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2307 if( (ocw != ncw) || (och != nch) ||
2308 ( ow != nw) || ( oh != nh) ||
2309 ((lpOldClientRect->top - lpOldWndRect->top) !=
2310 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2311 ((lpOldClientRect->left - lpOldWndRect->left) !=
2312 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2314 if(uFlags & SWP_EX_PAINTSELF)
2316 /* movement relative to the window itself */
2317 dx = (Wnd->rectClient.left - Wnd->rectWindow.left) -
2318 (lpOldClientRect->left - lpOldWndRect->left) ;
2319 dy = (Wnd->rectClient.top - Wnd->rectWindow.top) -
2320 (lpOldClientRect->top - lpOldWndRect->top) ;
2324 /* movement relative to the parent's client area */
2325 dx = Wnd->rectClient.left - lpOldClientRect->left;
2326 dy = Wnd->rectClient.top - lpOldClientRect->top;
2329 /* restrict valid bits to the common client rect */
2331 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2332 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2333 r.right = r.left + min( ocw, ncw );
2334 r.bottom = r.top + min( och, nch );
2336 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2337 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2338 GetRgnBox( hrgnValid, &r );
2339 if( IsRectEmpty( &r ) )
2341 r = *lpOldClientRect;
2345 if(uFlags & SWP_EX_PAINTSELF) {
2347 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2348 * relative to itself, only the client area can change.
2349 * if the client rect didn't change, there's nothing to do.
2356 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2357 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2358 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2363 if( !(uFlags & SWP_EX_PAINTSELF) )
2365 /* Move remaining regions to parent coordinates */
2366 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2367 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2370 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2372 TRACE("\tcomputing dirty region!\n");
2374 /* Compute combined dirty region (old + new - valid) */
2375 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2376 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2378 /* Blt valid bits, r is the rect to copy */
2385 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2386 from copying clipped areas */
2388 if( uFlags & SWP_EX_PAINTSELF )
2390 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2391 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2392 rClip.right = nw; rClip.bottom = nh;
2396 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2397 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2398 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2399 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2401 rClip.left = rClip.top = 0;
2403 if( oh > nh ) r.bottom = r.top + nh;
2404 if( ow < nw ) r.right = r.left + nw;
2406 if( IntersectRect( &r, &r, &rClip ) )
2408 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2410 /* When you copy the bits without repainting, parent doesn't
2411 get validated appropriately. Therefore, we have to validate
2412 the parent with the windows' updated region when the
2413 parent's update region is not empty. */
2415 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2417 OffsetRect(&r, dx, dy);
2418 ValidateRect(Wnd->parent->hwndSelf, &r);
2421 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2422 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2426 /* *pVisRgn now points to the invalidated region */
2428 DeleteObject(newVisRgn);
2429 DeleteObject(dirtyRgn);
2433 /***********************************************************************
2434 * SWP_DoSimpleFrameChanged
2436 * NOTE: old and new client rect origins are identical, only
2437 * extents may have changed. Window extents are the same.
2439 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2445 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2447 /* Client rect changed its position/size, most likely a scrollar
2448 * was added/removed.
2450 * FIXME: WVR alignment flags
2453 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2457 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2458 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2459 if(!(uFlags & SWP_EX_NOCOPY))
2460 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2468 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2471 hrgn = CreateRectRgnIndirect( &rect );
2473 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2474 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2475 if(!(uFlags & SWP_EX_NOCOPY))
2476 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2480 REGION_UnionRectWithRgn( hrgn, &rect );
2483 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2485 rect = wndPtr->rectWindow;
2486 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2487 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2495 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2496 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2500 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2504 DeleteObject( hrgn );
2507 /***********************************************************************
2508 * SWP_DoWinPosChanging
2510 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2511 RECT* pNewWindowRect, RECT* pNewClientRect )
2513 /* Send WM_WINDOWPOSCHANGING message */
2515 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2516 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2518 /* Calculate new position and size */
2520 *pNewWindowRect = wndPtr->rectWindow;
2521 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2522 : wndPtr->rectClient;
2524 if (!(pWinpos->flags & SWP_NOSIZE))
2526 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2527 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2529 if (!(pWinpos->flags & SWP_NOMOVE))
2531 pNewWindowRect->left = pWinpos->x;
2532 pNewWindowRect->top = pWinpos->y;
2533 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2534 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2536 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2537 pWinpos->y - wndPtr->rectWindow.top );
2540 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2544 /***********************************************************************
2547 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2548 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2552 /* Send WM_NCCALCSIZE message to get new client area */
2553 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2555 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2556 &wndPtr->rectWindow, &wndPtr->rectClient,
2557 pWinpos, pNewClientRect );
2559 /* FIXME: WVR_ALIGNxxx */
2561 if( pNewClientRect->left != wndPtr->rectClient.left ||
2562 pNewClientRect->top != wndPtr->rectClient.top )
2563 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2565 if( (pNewClientRect->right - pNewClientRect->left !=
2566 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2567 (pNewClientRect->bottom - pNewClientRect->top !=
2568 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2569 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2572 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2573 pNewClientRect->top != wndPtr->rectClient.top) )
2574 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2578 /***********************************************************************
2579 * SetWindowPos (USER.2)
2581 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2582 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2584 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2587 /***********************************************************************
2588 * SetWindowPos (USER32.520)
2590 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2591 INT x, INT y, INT cx, INT cy, UINT flags )
2594 WND * wndPtr,*wndTemp;
2595 RECT newWindowRect, newClientRect;
2596 RECT oldWindowRect, oldClientRect;
2598 UINT wvrFlags = 0, uFlags = 0;
2599 BOOL retvalue, resync = FALSE, bChangePos;
2600 HWND hwndActive = 0;
2602 /* Get current active window from the active queue */
2605 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2608 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2609 QUEUE_Unlock( pActiveQueue );
2613 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2614 hwnd, x, y, x+cx, y+cy, flags);
2616 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2617 flags &= ~SWP_WINE_NOHOSTMOVE;
2620 /* ------------------------------------------------------------------------ CHECKS */
2622 /* Check window handle */
2624 if (hwnd == GetDesktopWindow()) return FALSE;
2625 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2627 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2628 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2630 /* Fix redundant flags */
2632 if(wndPtr->dwStyle & WS_VISIBLE)
2633 flags &= ~SWP_SHOWWINDOW;
2636 if (!(flags & SWP_SHOWWINDOW))
2637 flags |= SWP_NOREDRAW;
2638 flags &= ~SWP_HIDEWINDOW;
2641 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2643 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2644 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2645 flags |= SWP_NOSIZE; /* Already the right size */
2647 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2648 flags |= SWP_NOMOVE; /* Already the right position */
2650 if (hwnd == hwndActive)
2651 flags |= SWP_NOACTIVATE; /* Already active */
2652 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2654 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2656 flags &= ~SWP_NOZORDER;
2657 hwndInsertAfter = HWND_TOP;
2662 /* Check hwndInsertAfter */
2664 /* FIXME: TOPMOST not supported yet */
2665 if ((hwndInsertAfter == HWND_TOPMOST) ||
2666 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2668 /* hwndInsertAfter must be a sibling of the window */
2669 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2671 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2674 if( wnd->parent != wndPtr->parent )
2677 WIN_ReleaseWndPtr(wnd);
2680 /* don't need to change the Zorder of hwnd if it's already inserted
2681 * after hwndInsertAfter or when inserting hwnd after itself.
2683 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2685 WIN_ReleaseWndPtr(wnd);
2688 Pos: /* ------------------------------------------------------------------------ MAIN part */
2690 /* Fill the WINDOWPOS structure */
2693 winpos.hwndInsertAfter = hwndInsertAfter;
2698 winpos.flags = flags;
2700 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2702 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2704 if( wndPtr->parent == WIN_GetDesktop() )
2705 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2706 hwndInsertAfter, winpos.flags );
2707 WIN_ReleaseDesktop();
2710 if(!(wndPtr->flags & WIN_NATIVE) )
2712 if( hwndInsertAfter == HWND_TOP )
2713 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2715 if( hwndInsertAfter == HWND_BOTTOM )
2716 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2718 if( !(winpos.flags & SWP_NOZORDER) )
2719 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2720 winpos.flags |= SWP_NOZORDER;
2722 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2723 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2724 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2726 /* get a previous visible region for SWP_CopyValidBits() */
2727 DWORD dflags = DCX_WINDOW;
2729 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2730 dflags |= DCX_CLIPSIBLINGS;
2732 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2736 /* Common operations */
2738 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2740 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2742 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2743 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2746 /* Reset active DCEs */
2748 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2749 wndPtr->dwStyle & WS_VISIBLE) ||
2750 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2754 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2755 DCE_InvalidateDCE(wndPtr, &rect);
2758 oldWindowRect = wndPtr->rectWindow;
2759 oldClientRect = wndPtr->rectClient;
2761 /* Find out if we have to redraw the whole client rect */
2763 if( oldClientRect.bottom - oldClientRect.top ==
2764 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2766 if( oldClientRect.right - oldClientRect.left ==
2767 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2769 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2770 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2772 uFlags |= SWP_EX_NOCOPY;
2775 * Use this later in CopyValidBits()
2778 uFlags |= SWP_EX_NONCLIENT;
2781 /* FIXME: actually do something with WVR_VALIDRECTS */
2783 wndPtr->rectWindow = newWindowRect;
2784 wndPtr->rectClient = newClientRect;
2786 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2788 BOOL bCallDriver = TRUE;
2789 HWND tempInsertAfter = winpos.hwndInsertAfter;
2791 winpos.hwndInsertAfter = hwndInsertAfter;
2793 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2795 /* This is the only place where we need to force repainting of the contents
2796 of windows created by the host window system, all other cases go through the
2797 expose event handling */
2799 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2801 cx = newWindowRect.right - newWindowRect.left;
2802 cy = newWindowRect.bottom - newWindowRect.top;
2804 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2805 winpos.hwndInsertAfter = tempInsertAfter;
2806 bCallDriver = FALSE;
2808 if( winpos.flags & SWP_NOCLIENTMOVE )
2809 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2812 /* client area moved but window extents remained the same, copy valid bits */
2814 visRgn = CreateRectRgn( 0, 0, cx, cy );
2815 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2816 uFlags | SWP_EX_PAINTSELF );
2823 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2825 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2826 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2827 !(uFlags & SWP_EX_NOCOPY) )
2829 /* The origin of the client rect didn't move so we can try to repaint
2830 * only the nonclient area by setting bit gravity hint for the host window system.
2833 if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
2835 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2836 newWindowRect.bottom - newWindowRect.top);
2837 RECT rcn = newClientRect;
2838 RECT rco = oldClientRect;
2840 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2841 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2842 IntersectRect( &rcn, &rcn, &rco );
2843 visRgn = CreateRectRgnIndirect( &rcn );
2844 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2845 DeleteObject( hrgn );
2846 uFlags = SWP_EX_PAINTSELF;
2848 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2851 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2854 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2855 winpos.hwndInsertAfter = tempInsertAfter;
2858 if( winpos.flags & SWP_SHOWWINDOW )
2862 wndPtr->dwStyle |= WS_VISIBLE;
2864 if (wndPtr->dwExStyle & WS_EX_MANAGED) resync = TRUE;
2866 /* focus was set to unmapped window, reset host focus
2867 * since the window is now visible */
2869 focus = curr = GetFocus();
2874 WND *pFocus = WIN_FindWndPtr( focus );
2876 pFocus->pDriver->pSetFocus(pFocus);
2877 WIN_ReleaseWndPtr(pFocus);
2880 curr = GetParent(curr);
2884 else /* -------------------------------------------- emulated window */
2886 if( winpos.flags & SWP_SHOWWINDOW )
2888 wndPtr->dwStyle |= WS_VISIBLE;
2889 uFlags |= SWP_EX_PAINTSELF;
2890 visRgn = 1; /* redraw the whole window */
2892 else if( !(winpos.flags & SWP_NOREDRAW) )
2894 if( winpos.flags & SWP_HIDEWINDOW )
2896 if( visRgn > 1 ) /* map to parent */
2897 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2903 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2905 /* if window was not resized and not moved try to repaint itself */
2906 if((winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) == SWP_AGG_NOGEOMETRYCHANGE)
2907 uFlags |= SWP_EX_PAINTSELF;
2908 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2909 &oldClientRect, uFlags);
2913 /* nothing moved, redraw frame if needed */
2915 if( winpos.flags & SWP_FRAMECHANGED )
2916 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2919 DeleteObject( visRgn );
2927 if( winpos.flags & SWP_HIDEWINDOW )
2929 wndPtr->dwStyle &= ~WS_VISIBLE;
2932 if (hwnd == CARET_GetHwnd())
2934 if( winpos.flags & SWP_HIDEWINDOW )
2936 else if (winpos.flags & SWP_SHOWWINDOW)
2940 /* ------------------------------------------------------------------------ FINAL */
2942 if (wndPtr->flags & WIN_NATIVE)
2943 EVENT_Synchronize(); /* Synchronize with the host window system */
2945 wndTemp = WIN_GetDesktop();
2947 /* repaint invalidated region (if any)
2949 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2950 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2955 if( !(winpos.flags & SWP_NOREDRAW) )
2958 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2959 its parent and sibling and so on, and then erase the parent window
2960 back ground if the parent is either a top-level window or its parent's parent
2961 is top-level window. Rely on the system to repaint other affected
2962 windows later on. */
2963 if( uFlags & SWP_EX_PAINTSELF )
2965 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2966 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2967 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2971 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2972 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2976 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2978 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2979 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2983 DeleteObject( visRgn );
2986 WIN_ReleaseDesktop();
2988 if (!(flags & SWP_NOACTIVATE))
2989 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2991 /* And last, send the WM_WINDOWPOSCHANGED message */
2993 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2996 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2997 !(winpos.flags & SWP_NOSENDCHANGING)) )
2999 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
3000 if (resync) EVENT_Synchronize();
3005 WIN_ReleaseWndPtr(wndPtr);
3010 /***********************************************************************
3011 * BeginDeferWindowPos16 (USER.259)
3013 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
3015 return BeginDeferWindowPos( count );
3019 /***********************************************************************
3020 * BeginDeferWindowPos (USER32.9)
3022 HDWP WINAPI BeginDeferWindowPos( INT count )
3029 SetLastError(ERROR_INVALID_PARAMETER);
3032 /* Windows allows zero count, in which case it allocates context for 8 moves */
3033 if (count == 0) count = 8;
3035 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
3036 if (!handle) return 0;
3037 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
3038 pDWP->actualCount = 0;
3039 pDWP->suggestedCount = count;
3041 pDWP->wMagic = DWP_MAGIC;
3042 pDWP->hwndParent = 0;
3047 /***********************************************************************
3048 * DeferWindowPos16 (USER.260)
3050 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
3051 INT16 x, INT16 y, INT16 cx, INT16 cy,
3054 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3055 x, y, cx, cy, flags );
3059 /***********************************************************************
3060 * DeferWindowPos (USER32.128)
3062 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3063 INT x, INT y, INT cx, INT cy,
3068 HDWP newhdwp = hdwp,retvalue;
3072 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3073 if (!pDWP) return 0;
3074 if (hwnd == GetDesktopWindow()) return 0;
3076 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3077 USER_HEAP_FREE( hdwp );
3081 /* Numega Bounds Checker Demo dislikes the following code.
3082 In fact, I've not been able to find any "same parent" requirement in any docu
3086 /* All the windows of a DeferWindowPos() must have the same parent */
3087 parent = pWnd->parent->hwndSelf;
3088 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3089 else if (parent != pDWP->hwndParent)
3091 USER_HEAP_FREE( hdwp );
3097 for (i = 0; i < pDWP->actualCount; i++)
3099 if (pDWP->winPos[i].hwnd == hwnd)
3101 /* Merge with the other changes */
3102 if (!(flags & SWP_NOZORDER))
3104 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3106 if (!(flags & SWP_NOMOVE))
3108 pDWP->winPos[i].x = x;
3109 pDWP->winPos[i].y = y;
3111 if (!(flags & SWP_NOSIZE))
3113 pDWP->winPos[i].cx = cx;
3114 pDWP->winPos[i].cy = cy;
3116 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3117 SWP_NOZORDER | SWP_NOREDRAW |
3118 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3120 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3126 if (pDWP->actualCount >= pDWP->suggestedCount)
3128 newhdwp = USER_HEAP_REALLOC( hdwp,
3129 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3135 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3136 pDWP->suggestedCount++;
3138 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3139 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3140 pDWP->winPos[pDWP->actualCount].x = x;
3141 pDWP->winPos[pDWP->actualCount].y = y;
3142 pDWP->winPos[pDWP->actualCount].cx = cx;
3143 pDWP->winPos[pDWP->actualCount].cy = cy;
3144 pDWP->winPos[pDWP->actualCount].flags = flags;
3145 pDWP->actualCount++;
3148 WIN_ReleaseWndPtr(pWnd);
3153 /***********************************************************************
3154 * EndDeferWindowPos16 (USER.261)
3156 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3158 return EndDeferWindowPos( hdwp );
3162 /***********************************************************************
3163 * EndDeferWindowPos (USER32.173)
3165 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3172 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3173 if (!pDWP) return FALSE;
3174 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3176 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3177 winpos->x, winpos->y, winpos->cx,
3178 winpos->cy, winpos->flags ))) break;
3180 USER_HEAP_FREE( hdwp );
3185 /***********************************************************************
3186 * TileChildWindows (USER.199)
3188 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3190 FIXME("(%04x, %d): stub\n", parent, action);
3193 /***********************************************************************
3194 * CascadeChildWindows (USER.198)
3196 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3198 FIXME("(%04x, %d): stub\n", parent, action);
3201 /***********************************************************************
3202 * SetProgmanWindow [USER32.522]
3204 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3206 hGlobalProgmanWindow = hwnd;
3207 return hGlobalProgmanWindow;
3210 /***********************************************************************
3211 * GetProgmanWindow [USER32.289]
3213 HRESULT WINAPI GetProgmanWindow ( )
3215 return hGlobalProgmanWindow;
3218 /***********************************************************************
3219 * SetShellWindowEx [USER32.531]
3220 * hwndProgman = Progman[Program Manager]
3221 * |-> SHELLDLL_DefView
3222 * hwndListView = | |-> SysListView32
3223 * | | |-> tooltips_class32
3229 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3231 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3232 hGlobalShellWindow = hwndProgman;
3233 return hGlobalShellWindow;
3237 /***********************************************************************
3238 * SetTaskmanWindow [USER32.537]
3240 * hwnd = MSTaskSwWClass
3241 * |-> SysTabControl32
3243 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3245 hGlobalTaskmanWindow = hwnd;
3246 return hGlobalTaskmanWindow;
3249 /***********************************************************************
3250 * GetTaskmanWindow [USER32.304]
3252 HRESULT WINAPI GetTaskmanWindow ( )
3254 return hGlobalTaskmanWindow;