2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
9 #include "wine/winuser16.h"
22 #include "nonclient.h"
23 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(win)
29 #define HAS_DLGFRAME(style,exStyle) \
30 (((exStyle) & WS_EX_DLGMODALFRAME) || \
31 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
33 #define HAS_THICKFRAME(style) \
34 (((style) & WS_THICKFRAME) && \
35 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
37 #define SWP_AGG_NOGEOMETRYCHANGE \
38 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
39 #define SWP_AGG_NOPOSCHANGE \
40 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
41 #define SWP_AGG_STATUSFLAGS \
42 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
44 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
46 #define PLACE_MIN 0x0001
47 #define PLACE_MAX 0x0002
48 #define PLACE_RECT 0x0004
50 #define SWP_EX_NOCOPY 0x0001
51 #define SWP_EX_PAINTSELF 0x0002
52 #define SWP_EX_NONCLIENT 0x0004
54 #define MINMAX_NOSWP 0x00010000
56 /* ----- internal variables ----- */
58 static HWND hwndPrevActive = 0; /* Previously active window */
59 static HWND hGlobalShellWindow=0; /*the shell*/
60 static HWND hGlobalTaskmanWindow=0;
61 static HWND hGlobalProgmanWindow=0;
63 static LPCSTR atomInternalPos;
65 extern HQUEUE16 hActiveQueue;
67 /***********************************************************************
68 * WINPOS_CreateInternalPosAtom
70 BOOL WINPOS_CreateInternalPosAtom()
73 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
74 return (atomInternalPos) ? TRUE : FALSE;
77 /***********************************************************************
78 * WINPOS_CheckInternalPos
80 * Called when a window is destroyed.
82 void WINPOS_CheckInternalPos( WND* wndPtr )
85 MESSAGEQUEUE *pMsgQ = 0;
86 HWND hwnd = wndPtr->hwndSelf;
88 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
90 /* Retrieve the message queue associated with this window */
91 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
94 WARN("\tMessage queue not found. Exiting!\n" );
98 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
100 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
102 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
103 WARN("\tattempt to activate destroyed window!\n");
108 if( IsWindow(lpPos->hwndIconTitle) )
109 DestroyWindow( lpPos->hwndIconTitle );
110 HeapFree( SystemHeap, 0, lpPos );
113 QUEUE_Unlock( pMsgQ );
117 /***********************************************************************
120 * Find a suitable place for an iconic window.
122 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
125 short x, y, xspacing, yspacing;
127 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
128 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
129 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
130 return pt; /* The icon already has a suitable position */
132 xspacing = GetSystemMetrics(SM_CXICONSPACING);
133 yspacing = GetSystemMetrics(SM_CYICONSPACING);
135 y = rectParent.bottom;
138 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
140 /* Check if another icon already occupies this spot */
141 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
144 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
146 if ((childPtr->rectWindow.left < x + xspacing) &&
147 (childPtr->rectWindow.right >= x) &&
148 (childPtr->rectWindow.top <= y) &&
149 (childPtr->rectWindow.bottom > y - yspacing))
150 break; /* There's a window in there */
152 WIN_UpdateWndPtr(&childPtr,childPtr->next);
154 WIN_ReleaseWndPtr(childPtr);
155 if (!childPtr) /* No window was found, so it's OK for us */
157 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
158 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
167 /***********************************************************************
168 * ArrangeIconicWindows16 (USER.170)
170 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
172 return ArrangeIconicWindows(parent);
174 /***********************************************************************
175 * ArrangeIconicWindows (USER32.7)
177 UINT WINAPI ArrangeIconicWindows( HWND parent )
181 INT x, y, xspacing, yspacing;
183 GetClientRect( parent, &rectParent );
185 y = rectParent.bottom;
186 xspacing = GetSystemMetrics(SM_CXICONSPACING);
187 yspacing = GetSystemMetrics(SM_CYICONSPACING);
189 hwndChild = GetWindow( parent, GW_CHILD );
192 if( IsIconic( hwndChild ) )
194 WND *wndPtr = WIN_FindWndPtr(hwndChild);
196 WINPOS_ShowIconTitle( wndPtr, FALSE );
198 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
199 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
200 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
201 if( IsWindow(hwndChild) )
202 WINPOS_ShowIconTitle(wndPtr , TRUE );
203 WIN_ReleaseWndPtr(wndPtr);
205 if (x <= rectParent.right - xspacing) x += xspacing;
212 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
218 /***********************************************************************
219 * SwitchToThisWindow16 (USER.172)
221 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
223 SwitchToThisWindow( hwnd, restore );
227 /***********************************************************************
228 * SwitchToThisWindow (USER32.539)
230 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
232 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
236 /***********************************************************************
237 * GetWindowRect16 (USER.32)
239 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
241 WND * wndPtr = WIN_FindWndPtr( hwnd );
244 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
245 if (wndPtr->dwStyle & WS_CHILD)
246 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
247 WIN_ReleaseWndPtr(wndPtr);
251 /***********************************************************************
252 * GetWindowRect (USER32.308)
254 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
256 WND * wndPtr = WIN_FindWndPtr( hwnd );
257 if (!wndPtr) return FALSE;
259 *rect = wndPtr->rectWindow;
260 if (wndPtr->dwStyle & WS_CHILD)
261 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
262 WIN_ReleaseWndPtr(wndPtr);
267 /***********************************************************************
270 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
274 WND * wndPtr = WIN_FindWndPtr( hwnd );
275 if (!wndPtr) return (ERROR);
277 FIXME("GetWindowRgn: doesn't really do regions\n");
279 memset (&rect, 0, sizeof(rect));
281 GetWindowRect ( hwnd, &rect );
283 FIXME("Check whether a valid region here\n");
285 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
287 WIN_ReleaseWndPtr(wndPtr);
288 return (SIMPLEREGION);
291 /***********************************************************************
294 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
298 FIXME("SetWindowRgn: stub\n");
302 /***********************************************************************
305 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
309 FIXME("SetWindowRgn16: stub\n");
314 /***********************************************************************
315 * GetClientRect16 (USER.33)
317 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
319 WND * wndPtr = WIN_FindWndPtr( hwnd );
321 rect->left = rect->top = rect->right = rect->bottom = 0;
324 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
325 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
327 WIN_ReleaseWndPtr(wndPtr);
331 /***********************************************************************
332 * GetClientRect (USER.220)
334 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
336 WND * wndPtr = WIN_FindWndPtr( hwnd );
338 rect->left = rect->top = rect->right = rect->bottom = 0;
339 if (!wndPtr) return FALSE;
340 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
341 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
343 WIN_ReleaseWndPtr(wndPtr);
348 /*******************************************************************
349 * ClientToScreen16 (USER.28)
351 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
353 MapWindowPoints16( hwnd, 0, lppnt, 1 );
357 /*******************************************************************
358 * ClientToScreen (USER32.52)
360 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
362 MapWindowPoints( hwnd, 0, lppnt, 1 );
367 /*******************************************************************
368 * ScreenToClient16 (USER.29)
370 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
372 MapWindowPoints16( 0, hwnd, lppnt, 1 );
376 /*******************************************************************
377 * ScreenToClient (USER32.447)
379 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
381 MapWindowPoints( 0, hwnd, lppnt, 1 );
386 /***********************************************************************
387 * WINPOS_WindowFromPoint
389 * Find the window and hittest for a given point.
391 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
394 INT16 hittest = HTERROR;
399 wndPtr = WIN_LockWndPtr(wndScope->child);
401 if( wndScope->flags & WIN_MANAGED )
403 /* In managed mode we have to check wndScope first as it is also
404 * a window which received the mouse event. */
406 if( wndScope->dwStyle & WS_DISABLED )
411 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
412 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
415 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
421 /* If point is in window, and window is visible, and it */
422 /* is enabled (or it's a top-level window), then explore */
423 /* its children. Otherwise, go to the next window. */
425 if ((wndPtr->dwStyle & WS_VISIBLE) &&
426 (!(wndPtr->dwStyle & WS_DISABLED) ||
427 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
428 (xy.x >= wndPtr->rectWindow.left) &&
429 (xy.x < wndPtr->rectWindow.right) &&
430 (xy.y >= wndPtr->rectWindow.top) &&
431 (xy.y < wndPtr->rectWindow.bottom))
433 *ppWnd = wndPtr; /* Got a suitable window */
435 /* If window is minimized or disabled, return at once */
436 if (wndPtr->dwStyle & WS_MINIMIZE)
438 retvalue = HTCAPTION;
441 if (wndPtr->dwStyle & WS_DISABLED)
447 /* If point is not in client area, ignore the children */
448 if ((xy.x < wndPtr->rectClient.left) ||
449 (xy.x >= wndPtr->rectClient.right) ||
450 (xy.y < wndPtr->rectClient.top) ||
451 (xy.y >= wndPtr->rectClient.bottom)) break;
453 xy.x -= wndPtr->rectClient.left;
454 xy.y -= wndPtr->rectClient.top;
455 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
459 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
464 /* If nothing found, try the scope window */
465 if (!*ppWnd) *ppWnd = wndScope;
467 /* Send the WM_NCHITTEST message (only if to the same task) */
468 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
470 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
471 0, MAKELONG( pt.x, pt.y ) );
472 if (hittest != HTTRANSPARENT)
474 retvalue = hittest; /* Found the window */
484 /* If no children found in last search, make point relative to parent */
487 xy.x += (*ppWnd)->rectClient.left;
488 xy.y += (*ppWnd)->rectClient.top;
491 /* Restart the search from the next sibling */
492 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
493 *ppWnd = (*ppWnd)->parent;
497 WIN_ReleaseWndPtr(wndPtr);
502 /*******************************************************************
503 * WindowFromPoint16 (USER.30)
505 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
508 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
509 WIN_ReleaseDesktop();
510 return pWnd->hwndSelf;
514 /*******************************************************************
515 * WindowFromPoint (USER32.582)
517 HWND WINAPI WindowFromPoint( POINT pt )
521 CONV_POINT32TO16( &pt, &pt16 );
522 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
523 WIN_ReleaseDesktop();
524 return (HWND)pWnd->hwndSelf;
528 /*******************************************************************
529 * ChildWindowFromPoint16 (USER.191)
531 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
534 CONV_POINT16TO32( &pt, &pt32 );
535 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
539 /*******************************************************************
540 * ChildWindowFromPoint (USER32.49)
542 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
544 /* pt is in the client coordinates */
546 WND* wnd = WIN_FindWndPtr(hwndParent);
552 /* get client rect fast */
553 rect.top = rect.left = 0;
554 rect.right = wnd->rectClient.right - wnd->rectClient.left;
555 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
557 if (!PtInRect( &rect, pt ))
562 WIN_UpdateWndPtr(&wnd,wnd->child);
565 if (PtInRect( &wnd->rectWindow, pt ))
567 retvalue = wnd->hwndSelf;
570 WIN_UpdateWndPtr(&wnd,wnd->next);
572 retvalue = hwndParent;
574 WIN_ReleaseWndPtr(wnd);
578 /*******************************************************************
579 * ChildWindowFromPointEx16 (USER.50)
581 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
584 CONV_POINT16TO32( &pt, &pt32 );
585 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
589 /*******************************************************************
590 * ChildWindowFromPointEx32 (USER32.50)
592 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
595 /* pt is in the client coordinates */
597 WND* wnd = WIN_FindWndPtr(hwndParent);
603 /* get client rect fast */
604 rect.top = rect.left = 0;
605 rect.right = wnd->rectClient.right - wnd->rectClient.left;
606 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
608 if (!PtInRect( &rect, pt ))
613 WIN_UpdateWndPtr(&wnd,wnd->child);
617 if (PtInRect( &wnd->rectWindow, pt )) {
618 if ( (uFlags & CWP_SKIPINVISIBLE) &&
619 !(wnd->dwStyle & WS_VISIBLE) );
620 else if ( (uFlags & CWP_SKIPDISABLED) &&
621 (wnd->dwStyle & WS_DISABLED) );
622 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
623 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
626 retvalue = wnd->hwndSelf;
631 WIN_UpdateWndPtr(&wnd,wnd->next);
633 retvalue = hwndParent;
635 WIN_ReleaseWndPtr(wnd);
640 /*******************************************************************
641 * WINPOS_GetWinOffset
643 * Calculate the offset between the origin of the two windows. Used
644 * to implement MapWindowPoints.
646 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
651 offset->x = offset->y = 0;
652 if (hwndFrom == hwndTo ) return;
654 /* Translate source window origin to screen coords */
657 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
659 ERR("bad hwndFrom = %04x\n",hwndFrom);
662 while (wndPtr->parent)
664 offset->x += wndPtr->rectClient.left;
665 offset->y += wndPtr->rectClient.top;
666 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
668 WIN_ReleaseWndPtr(wndPtr);
671 /* Translate origin to destination window coords */
674 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
676 ERR("bad hwndTo = %04x\n", hwndTo );
679 while (wndPtr->parent)
681 offset->x -= wndPtr->rectClient.left;
682 offset->y -= wndPtr->rectClient.top;
683 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
685 WIN_ReleaseWndPtr(wndPtr);
690 /*******************************************************************
691 * MapWindowPoints16 (USER.258)
693 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
694 LPPOINT16 lppt, UINT16 count )
698 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
708 /*******************************************************************
709 * MapWindowPoints (USER32.386)
711 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
712 LPPOINT lppt, UINT count )
716 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
723 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
727 /***********************************************************************
728 * IsIconic16 (USER.31)
730 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
732 return IsIconic(hWnd);
736 /***********************************************************************
737 * IsIconic (USER32.345)
739 BOOL WINAPI IsIconic(HWND hWnd)
742 WND * wndPtr = WIN_FindWndPtr(hWnd);
743 if (wndPtr == NULL) return FALSE;
744 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
745 WIN_ReleaseWndPtr(wndPtr);
750 /***********************************************************************
751 * IsZoomed (USER.272)
753 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
755 return IsZoomed(hWnd);
759 /***********************************************************************
760 * IsZoomed (USER.352)
762 BOOL WINAPI IsZoomed(HWND hWnd)
765 WND * wndPtr = WIN_FindWndPtr(hWnd);
766 if (wndPtr == NULL) return FALSE;
767 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
768 WIN_ReleaseWndPtr(wndPtr);
773 /*******************************************************************
774 * GetActiveWindow (USER.60)
776 HWND16 WINAPI GetActiveWindow16(void)
778 return (HWND16)GetActiveWindow();
781 /*******************************************************************
782 * GetActiveWindow (USER32.205)
784 HWND WINAPI GetActiveWindow(void)
786 MESSAGEQUEUE *pCurMsgQ = 0;
789 /* Get the messageQ for the current thread */
790 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
792 WARN("\tCurrent message queue not found. Exiting!\n" );
796 /* Return the current active window from the perQ data of the current message Q */
797 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
799 QUEUE_Unlock( pCurMsgQ );
804 /*******************************************************************
807 static BOOL WINPOS_CanActivate(WND* pWnd)
809 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
810 == WS_VISIBLE) ) return TRUE;
815 /*******************************************************************
816 * SetActiveWindow16 (USER.59)
818 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
820 return SetActiveWindow(hwnd);
824 /*******************************************************************
825 * SetActiveWindow (USER32.463)
827 HWND WINAPI SetActiveWindow( HWND hwnd )
830 WND *wndPtr = WIN_FindWndPtr( hwnd );
831 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
833 if ( !WINPOS_CanActivate(wndPtr) )
839 /* Get the messageQ for the current thread */
840 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
842 WARN("\tCurrent message queue not found. Exiting!\n" );
846 /* Retrieve the message queue associated with this window */
847 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
850 WARN("\tWindow message queue not found. Exiting!\n" );
854 /* Make sure that the window is associated with the calling threads
855 * message queue. It must share the same perQ data.
858 if ( pCurMsgQ->pQData != pMsgQ->pQData )
861 /* Save current active window */
862 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
864 WINPOS_SetActiveWindow( hwnd, 0, 0 );
867 /* Unlock the queues before returning */
869 QUEUE_Unlock( pMsgQ );
871 QUEUE_Unlock( pCurMsgQ );
874 WIN_ReleaseWndPtr(wndPtr);
879 /*******************************************************************
880 * GetForegroundWindow16 (USER.608)
882 HWND16 WINAPI GetForegroundWindow16(void)
884 return (HWND16)GetForegroundWindow();
888 /*******************************************************************
889 * SetForegroundWindow16 (USER.609)
891 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
893 return SetForegroundWindow( hwnd );
897 /*******************************************************************
898 * GetForegroundWindow (USER32.241)
900 HWND WINAPI GetForegroundWindow(void)
904 /* Get the foreground window (active window of hActiveQueue) */
907 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
909 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
911 QUEUE_Unlock( pActiveQueue );
917 /*******************************************************************
918 * SetForegroundWindow (USER32.482)
920 BOOL WINAPI SetForegroundWindow( HWND hwnd )
922 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
926 /*******************************************************************
927 * GetShellWindow16 (USER.600)
929 HWND16 WINAPI GetShellWindow16(void)
931 return GetShellWindow();
934 /*******************************************************************
935 * SetShellWindow (USER32.504)
937 HWND WINAPI SetShellWindow(HWND hwndshell)
938 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
940 hGlobalShellWindow = hwndshell;
941 return hGlobalShellWindow;
945 /*******************************************************************
946 * GetShellWindow (USER32.287)
948 HWND WINAPI GetShellWindow(void)
949 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
951 return hGlobalShellWindow;
955 /***********************************************************************
956 * BringWindowToTop16 (USER.45)
958 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
960 return BringWindowToTop(hwnd);
964 /***********************************************************************
965 * BringWindowToTop (USER32.11)
967 BOOL WINAPI BringWindowToTop( HWND hwnd )
969 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
973 /***********************************************************************
974 * MoveWindow16 (USER.56)
976 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
979 return MoveWindow(hwnd,x,y,cx,cy,repaint);
983 /***********************************************************************
984 * MoveWindow (USER32.399)
986 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
989 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
990 if (!repaint) flags |= SWP_NOREDRAW;
991 TRACE("%04x %d,%d %dx%d %d\n",
992 hwnd, x, y, cx, cy, repaint );
993 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
996 /***********************************************************************
997 * WINPOS_InitInternalPos
999 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1000 LPRECT restoreRect )
1002 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1006 /* this happens when the window is minimized/maximized
1007 * for the first time (rectWindow is not adjusted yet) */
1009 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1010 if( !lpPos ) return NULL;
1012 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1013 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1014 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1015 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1018 if( wnd->dwStyle & WS_MINIMIZE )
1019 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1020 else if( wnd->dwStyle & WS_MAXIMIZE )
1021 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1022 else if( restoreRect )
1023 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1028 /***********************************************************************
1029 * WINPOS_RedrawIconTitle
1031 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1033 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1036 if( lpPos->hwndIconTitle )
1038 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1039 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1046 /***********************************************************************
1047 * WINPOS_ShowIconTitle
1049 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1051 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1053 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1055 HWND16 hWnd = lpPos->hwndIconTitle;
1057 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1060 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1063 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1065 if( !(pWnd->dwStyle & WS_VISIBLE) )
1067 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1068 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1069 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1071 WIN_ReleaseWndPtr(pWnd);
1074 else ShowWindow( hWnd, SW_HIDE );
1079 /*******************************************************************
1080 * WINPOS_GetMinMaxInfo
1082 * Get the minimized and maximized information for a window.
1084 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1085 POINT *minTrack, POINT *maxTrack )
1087 LPINTERNALPOS lpPos;
1091 /* Compute default values */
1093 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1094 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1095 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1096 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1097 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1098 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1100 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1101 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1103 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1104 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1109 if (HAS_THICKFRAME(wndPtr->dwStyle))
1111 xinc += GetSystemMetrics(SM_CXFRAME);
1112 yinc += GetSystemMetrics(SM_CYFRAME);
1114 if (wndPtr->dwStyle & WS_BORDER)
1116 xinc += GetSystemMetrics(SM_CXBORDER);
1117 yinc += GetSystemMetrics(SM_CYBORDER);
1120 MinMax.ptMaxSize.x += 2 * xinc;
1121 MinMax.ptMaxSize.y += 2 * yinc;
1123 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1124 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1125 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1128 MinMax.ptMaxPosition.x = -xinc;
1129 MinMax.ptMaxPosition.y = -yinc;
1132 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1134 /* Some sanity checks */
1136 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1137 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1138 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1139 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1140 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1141 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1142 MinMax.ptMinTrackSize.x );
1143 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1144 MinMax.ptMinTrackSize.y );
1146 if (maxSize) *maxSize = MinMax.ptMaxSize;
1147 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1148 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1149 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1152 /***********************************************************************
1153 * WINPOS_MinMaximize
1155 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1156 * This function assumes that 'cmd' is different from the current window
1159 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1163 LPINTERNALPOS lpPos;
1165 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1167 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1168 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1170 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1172 if( wndPtr->dwStyle & WS_MINIMIZE )
1174 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1175 return (SWP_NOSIZE | SWP_NOMOVE);
1176 swpFlags |= SWP_NOCOPYBITS;
1181 if( wndPtr->dwStyle & WS_MAXIMIZE)
1183 wndPtr->flags |= WIN_RESTORE_MAX;
1184 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1187 wndPtr->flags &= ~WIN_RESTORE_MAX;
1188 wndPtr->dwStyle |= WS_MINIMIZE;
1190 if( wndPtr->flags & WIN_NATIVE )
1191 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1192 swpFlags |= MINMAX_NOSWP;
1194 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1196 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1197 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1198 swpFlags |= SWP_NOCOPYBITS;
1202 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1203 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1204 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1206 if( wndPtr->dwStyle & WS_MINIMIZE )
1208 if( wndPtr->flags & WIN_NATIVE )
1209 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1210 swpFlags |= MINMAX_NOSWP;
1212 WINPOS_ShowIconTitle( wndPtr, FALSE );
1213 wndPtr->dwStyle &= ~WS_MINIMIZE;
1215 wndPtr->dwStyle |= WS_MAXIMIZE;
1217 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1222 if( wndPtr->dwStyle & WS_MINIMIZE )
1224 if( wndPtr->flags & WIN_NATIVE )
1225 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1226 swpFlags |= MINMAX_NOSWP;
1228 wndPtr->dwStyle &= ~WS_MINIMIZE;
1229 WINPOS_ShowIconTitle( wndPtr, FALSE );
1231 if( wndPtr->flags & WIN_RESTORE_MAX)
1233 /* Restore to maximized position */
1234 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1235 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1236 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1237 wndPtr->dwStyle |= WS_MAXIMIZE;
1238 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1243 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1244 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1246 /* Restore to normal position */
1248 *lpRect = lpPos->rectNormal;
1249 lpRect->right -= lpRect->left;
1250 lpRect->bottom -= lpRect->top;
1254 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1258 /***********************************************************************
1259 * ShowWindowAsync (USER32.535)
1261 * doesn't wait; returns immediately.
1262 * used by threads to toggle windows in other (possibly hanging) threads
1264 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1266 /* FIXME: does ShowWindow() return immediately ? */
1267 return ShowWindow(hwnd, cmd);
1271 /***********************************************************************
1272 * ShowWindow16 (USER.42)
1274 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1276 return ShowWindow(hwnd,cmd);
1280 /***********************************************************************
1281 * ShowWindow (USER32.534)
1283 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1285 WND* wndPtr = WIN_FindWndPtr( hwnd );
1286 BOOL wasVisible, showFlag;
1287 RECT16 newPos = {0, 0, 0, 0};
1290 if (!wndPtr) return FALSE;
1292 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1294 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1299 if (!wasVisible) goto END;;
1300 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1301 SWP_NOACTIVATE | SWP_NOZORDER;
1302 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
1304 /* Revert focus to parent */
1305 SetFocus( GetParent(hwnd) );
1309 case SW_SHOWMINNOACTIVE:
1310 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1312 case SW_SHOWMINIMIZED:
1313 swp |= SWP_SHOWWINDOW;
1316 swp |= SWP_FRAMECHANGED;
1317 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1318 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1319 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1322 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1323 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1324 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1325 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1326 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1330 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1333 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1336 * ShowWindow has a little peculiar behavior that if the
1337 * window is already the topmost window, it will not
1340 if (GetTopWindow((HWND)0)==hwnd)
1341 swp |= SWP_NOACTIVATE;
1345 case SW_SHOWNOACTIVATE:
1346 swp |= SWP_NOZORDER;
1347 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1349 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1350 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1352 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1354 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1355 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1356 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1360 showFlag = (cmd != SW_HIDE);
1361 if (showFlag != wasVisible)
1363 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1364 if (!IsWindow( hwnd )) goto END;
1367 if ((wndPtr->dwStyle & WS_CHILD) &&
1368 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1369 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1371 /* Don't call SetWindowPos() on invisible child windows */
1372 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1373 else wndPtr->dwStyle |= WS_VISIBLE;
1377 /* We can't activate a child window */
1378 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1379 if (!(swp & MINMAX_NOSWP))
1380 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1381 newPos.right, newPos.bottom, LOWORD(swp) );
1382 if (!IsWindow( hwnd )) goto END;
1383 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1386 if (wndPtr->flags & WIN_NEED_SIZE)
1388 /* should happen only in CreateWindowEx() */
1389 int wParam = SIZE_RESTORED;
1391 wndPtr->flags &= ~WIN_NEED_SIZE;
1392 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1393 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1394 SendMessageA( hwnd, WM_SIZE, wParam,
1395 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1396 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1397 SendMessageA( hwnd, WM_MOVE, 0,
1398 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1402 WIN_ReleaseWndPtr(wndPtr);
1407 /***********************************************************************
1408 * GetInternalWindowPos16 (USER.460)
1410 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1413 WINDOWPLACEMENT16 wndpl;
1414 if (GetWindowPlacement16( hwnd, &wndpl ))
1416 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1417 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1418 return wndpl.showCmd;
1424 /***********************************************************************
1425 * GetInternalWindowPos (USER32.245)
1427 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1430 WINDOWPLACEMENT wndpl;
1431 if (GetWindowPlacement( hwnd, &wndpl ))
1433 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1434 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1435 return wndpl.showCmd;
1440 /***********************************************************************
1441 * GetWindowPlacement16 (USER.370)
1443 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1445 WND *pWnd = WIN_FindWndPtr( hwnd );
1446 LPINTERNALPOS lpPos;
1448 if(!pWnd ) return FALSE;
1450 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1451 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1452 wndpl->length = sizeof(*wndpl);
1453 if( pWnd->dwStyle & WS_MINIMIZE )
1454 wndpl->showCmd = SW_SHOWMINIMIZED;
1456 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1457 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1458 if( pWnd->flags & WIN_RESTORE_MAX )
1459 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1462 wndpl->ptMinPosition = lpPos->ptIconPos;
1463 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1464 wndpl->rcNormalPosition = lpPos->rectNormal;
1466 WIN_ReleaseWndPtr(pWnd);
1471 /***********************************************************************
1472 * GetWindowPlacement (USER32.307)
1475 * Fails if wndpl->length of Win95 (!) apps is invalid.
1477 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1481 WINDOWPLACEMENT16 wpl;
1482 wpl.length = sizeof(wpl);
1483 if( GetWindowPlacement16( hwnd, &wpl ) )
1485 pwpl32->length = sizeof(*pwpl32);
1486 pwpl32->flags = wpl.flags;
1487 pwpl32->showCmd = wpl.showCmd;
1488 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1489 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1490 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1498 /***********************************************************************
1499 * WINPOS_SetPlacement
1501 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1504 WND *pWnd = WIN_FindWndPtr( hwnd );
1507 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1508 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1510 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1511 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1512 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1514 if( pWnd->dwStyle & WS_MINIMIZE )
1516 WINPOS_ShowIconTitle( pWnd, FALSE );
1517 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1518 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1519 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1521 else if( pWnd->dwStyle & WS_MAXIMIZE )
1523 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1524 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1525 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1527 else if( flags & PLACE_RECT )
1528 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1529 lpPos->rectNormal.right - lpPos->rectNormal.left,
1530 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1531 SWP_NOZORDER | SWP_NOACTIVATE );
1533 ShowWindow( hwnd, wndpl->showCmd );
1534 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1536 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1538 /* SDK: ...valid only the next time... */
1539 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1541 WIN_ReleaseWndPtr(pWnd);
1548 /***********************************************************************
1549 * SetWindowPlacement16 (USER.371)
1551 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1553 return WINPOS_SetPlacement( hwnd, wndpl,
1554 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1557 /***********************************************************************
1558 * SetWindowPlacement (USER32.519)
1561 * Fails if wndpl->length of Win95 (!) apps is invalid.
1563 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1567 WINDOWPLACEMENT16 wpl;
1569 wpl.length = sizeof(WINDOWPLACEMENT16);
1570 wpl.flags = pwpl32->flags;
1571 wpl.showCmd = pwpl32->showCmd;
1572 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1573 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1574 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1575 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1576 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1577 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1578 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1579 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1581 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1587 /***********************************************************************
1588 * SetInternalWindowPos16 (USER.461)
1590 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1591 LPRECT16 rect, LPPOINT16 pt )
1593 if( IsWindow16(hwnd) )
1595 WINDOWPLACEMENT16 wndpl;
1598 wndpl.length = sizeof(wndpl);
1599 wndpl.showCmd = showCmd;
1600 wndpl.flags = flags = 0;
1605 wndpl.flags |= WPF_SETMINPOSITION;
1606 wndpl.ptMinPosition = *pt;
1610 flags |= PLACE_RECT;
1611 wndpl.rcNormalPosition = *rect;
1613 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1618 /***********************************************************************
1619 * SetInternalWindowPos (USER32.483)
1621 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1622 LPRECT rect, LPPOINT pt )
1624 if( IsWindow(hwnd) )
1626 WINDOWPLACEMENT16 wndpl;
1629 wndpl.length = sizeof(wndpl);
1630 wndpl.showCmd = showCmd;
1631 wndpl.flags = flags = 0;
1636 wndpl.flags |= WPF_SETMINPOSITION;
1637 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1641 flags |= PLACE_RECT;
1642 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1644 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1648 /*******************************************************************
1649 * WINPOS_SetActiveWindow
1651 * SetActiveWindow() back-end. This is the only function that
1652 * can assign active status to a window. It must be called only
1653 * for the top level windows.
1655 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1657 CBTACTIVATESTRUCT16* cbtStruct;
1658 WND* wndPtr=0, *wndTemp;
1659 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1660 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1662 HWND hwndActive = 0;
1665 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1667 /* Get current active window from the active queue */
1670 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1671 if ( pOldActiveQueue )
1672 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1675 /* paranoid checks */
1676 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1679 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1682 wndPtr = WIN_FindWndPtr(hWnd);
1683 hOldActiveQueue = hActiveQueue;
1685 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1687 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1688 WIN_ReleaseWndPtr(wndTemp);
1691 TRACE("no current active window.\n");
1693 /* call CBT hook chain */
1694 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1696 cbtStruct->fMouse = fMouse;
1697 cbtStruct->hWndActive = hwndActive;
1698 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1699 (LPARAM)SEGPTR_GET(cbtStruct) );
1700 SEGPTR_FREE(cbtStruct);
1701 if (bRet) goto CLEANUP_END;
1704 /* set prev active wnd to current active wnd and send notification */
1705 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1707 MESSAGEQUEUE *pTempActiveQueue = 0;
1709 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1711 if (GetSysModalWindow16() != hWnd)
1713 /* disregard refusal if hWnd is sysmodal */
1716 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1717 MAKEWPARAM( WA_INACTIVE, wIconized ),
1720 /* check if something happened during message processing
1721 * (global active queue may have changed)
1723 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1724 if(!pTempActiveQueue)
1727 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1728 QUEUE_Unlock( pTempActiveQueue );
1729 if( hwndPrevActive != hwndActive )
1733 /* Set new active window in the message queue */
1737 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1738 if ( pNewActiveQueue )
1739 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1741 else /* have to do this or MDI frame activation goes to hell */
1742 if( pOldActiveQueue )
1743 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1745 /* send palette messages */
1746 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1747 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1749 /* if prev wnd is minimized redraw icon title */
1750 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1752 /* managed windows will get ConfigureNotify event */
1753 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1755 /* check Z-order and bring hWnd to the top */
1756 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1758 if (wndTemp->dwStyle & WS_VISIBLE) break;
1760 WIN_ReleaseDesktop();
1761 WIN_ReleaseWndPtr(wndTemp);
1763 if( wndTemp != wndPtr )
1764 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1765 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1766 if (!IsWindow(hWnd))
1770 /* Get a handle to the new active queue */
1771 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1773 /* send WM_ACTIVATEAPP if necessary */
1774 if (hOldActiveQueue != hNewActiveQueue)
1776 WND **list, **ppWnd;
1777 WND *pDesktop = WIN_GetDesktop();
1779 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1781 for (ppWnd = list; *ppWnd; ppWnd++)
1783 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1785 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1786 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1787 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1789 WIN_ReleaseWinArray(list);
1792 hActiveQueue = hNewActiveQueue;
1794 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1796 for (ppWnd = list; *ppWnd; ppWnd++)
1798 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1800 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1801 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1802 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1804 WIN_ReleaseWinArray(list);
1806 WIN_ReleaseDesktop();
1808 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1813 /* walk up to the first unowned window */
1814 wndTemp = WIN_LockWndPtr(wndPtr);
1815 while (wndTemp->owner)
1817 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1819 /* and set last active owned popup */
1820 wndTemp->hwndLastActive = hWnd;
1822 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1823 WIN_ReleaseWndPtr(wndTemp);
1824 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1825 SendMessageA( hWnd, WM_ACTIVATE,
1826 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1827 (LPARAM)hwndPrevActive );
1828 if( !IsWindow(hWnd) ) goto CLEANUP;
1831 /* change focus if possible */
1834 if ( pNewActiveQueue )
1836 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1838 if ( WIN_GetTopParent( hOldFocus ) != hwndActive )
1839 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1840 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1844 if ( pOldActiveQueue &&
1845 ( !pNewActiveQueue ||
1846 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1848 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1850 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1854 if( !hwndPrevActive && wndPtr )
1855 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1857 /* if active wnd is minimized redraw icon title */
1858 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1860 bRet = (hWnd == hwndActive); /* Success? */
1862 CLEANUP: /* Unlock the message queues before returning */
1864 if ( pNewActiveQueue )
1865 QUEUE_Unlock( pNewActiveQueue );
1869 if ( pOldActiveQueue )
1870 QUEUE_Unlock( pOldActiveQueue );
1872 WIN_ReleaseWndPtr(wndPtr);
1876 /*******************************************************************
1877 * WINPOS_ActivateOtherWindow
1879 * Activates window other than pWnd.
1881 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1885 HWND hwndActive = 0;
1887 /* Get current active window from the active queue */
1890 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1893 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1894 QUEUE_Unlock( pActiveQueue );
1898 if( pWnd->hwndSelf == hwndPrevActive )
1901 if( hwndActive != pWnd->hwndSelf &&
1902 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1905 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1906 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1908 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1910 WIN_ReleaseWndPtr(pWndTo);
1911 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1913 while( !WINPOS_CanActivate(pWndTo) )
1915 /* by now owned windows should've been taken care of */
1916 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1917 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1918 if( !pWndTo ) break;
1920 WIN_ReleaseWndPtr(pWndPtr);
1923 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1925 /* switch desktop queue to current active */
1928 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1929 WIN_ReleaseWndPtr(pWndTo);
1930 WIN_ReleaseDesktop();
1937 /*******************************************************************
1938 * WINPOS_ChangeActiveWindow
1941 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1943 WND *wndPtr, *wndTemp;
1945 HWND hwndActive = 0;
1947 /* Get current active window from the active queue */
1950 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1953 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1954 QUEUE_Unlock( pActiveQueue );
1959 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1961 wndPtr = WIN_FindWndPtr(hWnd);
1962 if( !wndPtr ) return FALSE;
1964 /* child windows get WM_CHILDACTIVATE message */
1965 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1967 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1971 if( hWnd == hwndActive )
1977 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1983 /* switch desktop queue to current active */
1984 wndTemp = WIN_GetDesktop();
1985 if( wndPtr->parent == wndTemp)
1986 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1987 WIN_ReleaseDesktop();
1991 WIN_ReleaseWndPtr(wndPtr);
1996 /***********************************************************************
1997 * WINPOS_SendNCCalcSize
1999 * Send a WM_NCCALCSIZE message to a window.
2000 * All parameters are read-only except newClientRect.
2001 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2002 * when calcValidRect is TRUE.
2004 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2005 RECT *newWindowRect, RECT *oldWindowRect,
2006 RECT *oldClientRect, WINDOWPOS *winpos,
2007 RECT *newClientRect )
2009 NCCALCSIZE_PARAMS params;
2010 WINDOWPOS winposCopy;
2013 params.rgrc[0] = *newWindowRect;
2016 winposCopy = *winpos;
2017 params.rgrc[1] = *oldWindowRect;
2018 params.rgrc[2] = *oldClientRect;
2019 params.lppos = &winposCopy;
2021 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2023 TRACE("%d,%d-%d,%d\n",
2024 params.rgrc[0].left, params.rgrc[0].top,
2025 params.rgrc[0].right, params.rgrc[0].bottom );
2026 *newClientRect = params.rgrc[0];
2031 /***********************************************************************
2032 * WINPOS_HandleWindowPosChanging16
2034 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2036 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2038 POINT maxSize, minTrack;
2039 if (winpos->flags & SWP_NOSIZE) return 0;
2040 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2041 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2043 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2044 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2045 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2046 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2048 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2049 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2056 /***********************************************************************
2057 * WINPOS_HandleWindowPosChanging
2059 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2061 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2064 if (winpos->flags & SWP_NOSIZE) return 0;
2065 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2066 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2068 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2069 winpos->cx = MIN( winpos->cx, maxSize.x );
2070 winpos->cy = MIN( winpos->cy, maxSize.y );
2075 /***********************************************************************
2078 * fix Z order taking into account owned popups -
2079 * basically we need to maintain them above the window that owns them
2081 * FIXME: hide/show owned popups when owner visibility changes.
2083 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2085 WND* w = WIN_LockWndPtr(pDesktop->child);
2087 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2089 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2091 /* make sure this popup stays above the owner */
2093 HWND hwndLocalPrev = HWND_TOP;
2095 if( hwndInsertAfter != HWND_TOP )
2097 while( w != wndPtr->owner )
2099 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2100 if( hwndLocalPrev == hwndInsertAfter ) break;
2101 WIN_UpdateWndPtr(&w,w->next);
2103 hwndInsertAfter = hwndLocalPrev;
2106 else if( wndPtr->dwStyle & WS_CHILD )
2109 WIN_UpdateWndPtr(&w, pDesktop->child);
2113 if( w == wndPtr ) break;
2115 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2117 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2118 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2119 hwndInsertAfter = w->hwndSelf;
2121 WIN_UpdateWndPtr(&w, w->next);
2125 WIN_ReleaseWndPtr(w);
2126 return hwndInsertAfter;
2129 /***********************************************************************
2132 * Make window look nice without excessive repainting
2134 * visible and update regions are in window coordinates
2135 * client and window rectangles are in parent client coordinates
2137 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2138 * window rects have the same origin.
2140 * Returns: uFlags and a dirty region in *pVisRgn.
2142 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2143 LPRECT lpOldWndRect,
2144 LPRECT lpOldClientRect, UINT uFlags )
2147 HRGN newVisRgn, dirtyRgn;
2148 INT my = COMPLEXREGION;
2150 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2151 Wnd->rectWindow.left, Wnd->rectWindow.top,
2152 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2153 lpOldWndRect->left, lpOldWndRect->top,
2154 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2155 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2156 Wnd->rectClient.left, Wnd->rectClient.top,
2157 Wnd->rectClient.right, Wnd->rectClient.bottom,
2158 lpOldClientRect->left, lpOldClientRect->top,
2159 lpOldClientRect->right,lpOldClientRect->bottom );
2161 if( Wnd->hrgnUpdate == 1 )
2162 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2164 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2165 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2167 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2168 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2170 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2174 TRACE("\twon't copy anything!\n");
2176 /* set dirtyRgn to the sum of old and new visible regions
2177 * in parent client coordinates */
2179 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2180 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2182 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2184 else /* copy valid bits to a new location */
2186 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2187 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2189 /* subtract already invalid region inside Wnd from the dst region */
2191 if( Wnd->hrgnUpdate )
2192 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2195 /* check if entire window can be copied */
2197 ow = lpOldWndRect->right - lpOldWndRect->left;
2198 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2199 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2200 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2202 ocw = lpOldClientRect->right - lpOldClientRect->left;
2203 och = lpOldClientRect->bottom - lpOldClientRect->top;
2204 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2205 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2207 if( (ocw != ncw) || (och != nch) ||
2208 ( ow != nw) || ( oh != nh) ||
2209 ((lpOldClientRect->top - lpOldWndRect->top) !=
2210 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2211 ((lpOldClientRect->left - lpOldWndRect->left) !=
2212 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2214 dx = Wnd->rectClient.left - lpOldClientRect->left;
2215 dy = Wnd->rectClient.top - lpOldClientRect->top;
2217 /* restrict valid bits to the common client rect */
2219 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2220 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2221 r.right = r.left + MIN( ocw, ncw );
2222 r.bottom = r.top + MIN( och, nch );
2224 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2225 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2226 GetRgnBox( hrgnValid, &r );
2227 if( IsRectEmpty( &r ) )
2229 r = *lpOldClientRect;
2233 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2234 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2235 if( !(uFlags & SWP_EX_PAINTSELF) )
2236 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2240 if( !(uFlags & SWP_EX_PAINTSELF) )
2242 /* Move remaining regions to parent coordinates */
2243 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2244 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2247 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2249 TRACE("\tcomputing dirty region!\n");
2251 /* Compute combined dirty region (old + new - valid) */
2252 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2253 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2255 /* Blt valid bits, r is the rect to copy */
2263 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2264 from copying clipped areas */
2266 if( uFlags & SWP_EX_PAINTSELF )
2268 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2269 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2270 rClip.right = nw; rClip.bottom = nh;
2274 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2275 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2276 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2277 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2279 rClip.left = rClip.top = 0;
2281 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2283 if( oh > nh ) r.bottom = r.top + nh;
2284 if( ow < nw ) r.right = r.left + nw;
2286 if( IntersectRect( &r, &r, &rClip ) )
2288 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2290 /* When you copy the bits without repainting, parent doesn't
2291 get validated appropriately. Therefore, we have to validate
2292 the parent with the windows' updated region when the
2293 parent's update region is not empty. */
2295 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2297 OffsetRect(&r, dx, dy);
2298 ValidateRect(Wnd->parent->hwndSelf, &r);
2302 GDI_HEAP_UNLOCK( hDC );
2304 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2305 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2309 /* *pVisRgn now points to the invalidated region */
2311 DeleteObject(newVisRgn);
2312 DeleteObject(dirtyRgn);
2316 /***********************************************************************
2317 * SWP_DoSimpleFrameChanged
2319 * NOTE: old and new client rect origins are identical, only
2320 * extents may have changed. Window extents are the same.
2322 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2328 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2330 /* Client rect changed its position/size, most likely a scrollar
2331 * was added/removed.
2333 * FIXME: WVR alignment flags
2336 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2340 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2341 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2342 if(!(uFlags & SWP_EX_NOCOPY))
2343 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2351 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2354 hrgn = CreateRectRgnIndirect( &rect );
2356 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2357 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2358 if(!(uFlags & SWP_EX_NOCOPY))
2359 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2363 REGION_UnionRectWithRgn( hrgn, &rect );
2366 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2368 rect = wndPtr->rectWindow;
2369 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2370 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2378 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2379 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2383 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2387 DeleteObject( hrgn );
2390 /***********************************************************************
2391 * SWP_DoWinPosChanging
2393 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2394 RECT* pNewWindowRect, RECT* pNewClientRect )
2396 /* Send WM_WINDOWPOSCHANGING message */
2398 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2399 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2401 /* Calculate new position and size */
2403 *pNewWindowRect = wndPtr->rectWindow;
2404 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2405 : wndPtr->rectClient;
2407 if (!(pWinpos->flags & SWP_NOSIZE))
2409 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2410 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2412 if (!(pWinpos->flags & SWP_NOMOVE))
2414 pNewWindowRect->left = pWinpos->x;
2415 pNewWindowRect->top = pWinpos->y;
2416 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2417 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2419 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2420 pWinpos->y - wndPtr->rectWindow.top );
2423 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2427 /***********************************************************************
2430 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2431 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2435 /* Send WM_NCCALCSIZE message to get new client area */
2436 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2438 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2439 &wndPtr->rectWindow, &wndPtr->rectClient,
2440 pWinpos, pNewClientRect );
2442 /* FIXME: WVR_ALIGNxxx */
2444 if( pNewClientRect->left != wndPtr->rectClient.left ||
2445 pNewClientRect->top != wndPtr->rectClient.top )
2446 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2448 if( (pNewClientRect->right - pNewClientRect->left !=
2449 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2450 (pNewClientRect->bottom - pNewClientRect->top !=
2451 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2452 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2455 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2456 pNewClientRect->top != wndPtr->rectClient.top) )
2457 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2461 /***********************************************************************
2462 * SetWindowPos (USER.2)
2464 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2465 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2467 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2470 /***********************************************************************
2471 * SetWindowPos (USER32.520)
2473 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2474 INT x, INT y, INT cx, INT cy, UINT flags )
2477 WND * wndPtr,*wndTemp;
2478 RECT newWindowRect, newClientRect;
2479 RECT oldWindowRect, oldClientRect;
2481 UINT wvrFlags = 0, uFlags = 0;
2482 BOOL retvalue, resync = FALSE, bChangePos;
2483 HWND hwndActive = 0;
2485 /* Get current active window from the active queue */
2488 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2491 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2492 QUEUE_Unlock( pActiveQueue );
2496 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2497 hwnd, x, y, x+cx, y+cy, flags);
2499 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2500 flags &= ~SWP_WINE_NOHOSTMOVE;
2503 /* ------------------------------------------------------------------------ CHECKS */
2505 /* Check window handle */
2507 if (hwnd == GetDesktopWindow()) return FALSE;
2508 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2510 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2511 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2513 /* Fix redundant flags */
2515 if(wndPtr->dwStyle & WS_VISIBLE)
2516 flags &= ~SWP_SHOWWINDOW;
2519 if (!(flags & SWP_SHOWWINDOW))
2520 flags |= SWP_NOREDRAW;
2521 flags &= ~SWP_HIDEWINDOW;
2524 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2526 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2527 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2528 flags |= SWP_NOSIZE; /* Already the right size */
2530 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2531 flags |= SWP_NOMOVE; /* Already the right position */
2533 if (hwnd == hwndActive)
2534 flags |= SWP_NOACTIVATE; /* Already active */
2535 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2537 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2539 flags &= ~SWP_NOZORDER;
2540 hwndInsertAfter = HWND_TOP;
2545 /* Check hwndInsertAfter */
2547 /* FIXME: TOPMOST not supported yet */
2548 if ((hwndInsertAfter == HWND_TOPMOST) ||
2549 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2551 /* hwndInsertAfter must be a sibling of the window */
2552 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2554 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2557 if( wnd->parent != wndPtr->parent )
2560 WIN_ReleaseWndPtr(wnd);
2563 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2565 WIN_ReleaseWndPtr(wnd);
2568 Pos: /* ------------------------------------------------------------------------ MAIN part */
2570 /* Fill the WINDOWPOS structure */
2573 winpos.hwndInsertAfter = hwndInsertAfter;
2578 winpos.flags = flags;
2580 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2582 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2584 if( wndPtr->parent == WIN_GetDesktop() )
2585 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2586 hwndInsertAfter, winpos.flags );
2587 WIN_ReleaseDesktop();
2590 if(!(wndPtr->flags & WIN_NATIVE) )
2592 if( hwndInsertAfter == HWND_TOP )
2593 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2595 if( hwndInsertAfter == HWND_BOTTOM )
2596 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2598 if( !(winpos.flags & SWP_NOZORDER) )
2599 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2600 winpos.flags |= SWP_NOZORDER;
2602 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2603 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2604 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2606 /* get a previous visible region for SWP_CopyValidBits() */
2607 DWORD flags = DCX_WINDOW;
2609 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2610 flags |= DCX_CLIPSIBLINGS;
2612 visRgn = DCE_GetVisRgn(hwnd, flags, 0, 0);
2616 /* Common operations */
2618 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2620 if(!(winpos.flags & SWP_NOZORDER))
2622 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2623 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2626 /* Reset active DCEs */
2628 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2629 wndPtr->dwStyle & WS_VISIBLE) ||
2630 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2634 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2635 DCE_InvalidateDCE(wndPtr, &rect);
2638 oldWindowRect = wndPtr->rectWindow;
2639 oldClientRect = wndPtr->rectClient;
2641 /* Find out if we have to redraw the whole client rect */
2643 if( oldClientRect.bottom - oldClientRect.top ==
2644 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2646 if( oldClientRect.right - oldClientRect.left ==
2647 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2649 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2650 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2652 uFlags |= SWP_EX_NOCOPY;
2655 * Use this later in CopyValidBits()
2658 uFlags |= SWP_EX_NONCLIENT;
2661 /* FIXME: actually do something with WVR_VALIDRECTS */
2663 wndPtr->rectWindow = newWindowRect;
2664 wndPtr->rectClient = newClientRect;
2666 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2668 BOOL bCallDriver = TRUE;
2669 HWND tempInsertAfter = winpos.hwndInsertAfter;
2671 winpos.hwndInsertAfter = hwndInsertAfter;
2673 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2675 /* This is the only place where we need to force repainting of the contents
2676 of windows created by the host window system, all other cases go through the
2677 expose event handling */
2679 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2681 cx = newWindowRect.right - newWindowRect.left;
2682 cy = newWindowRect.bottom - newWindowRect.top;
2684 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2685 winpos.hwndInsertAfter = tempInsertAfter;
2686 bCallDriver = FALSE;
2688 if( winpos.flags & SWP_NOCLIENTMOVE )
2689 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2692 /* client area moved but window extents remained the same, copy valid bits */
2694 visRgn = CreateRectRgn( 0, 0, cx, cy );
2695 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2696 uFlags | SWP_EX_PAINTSELF );
2703 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2705 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2706 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2707 !(uFlags & SWP_EX_NOCOPY) )
2709 /* The origin of the client rect didn't move so we can try to repaint
2710 * only the nonclient area by setting bit gravity hint for the host window system.
2713 if( !(wndPtr->flags & WIN_MANAGED) )
2715 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2716 newWindowRect.bottom - newWindowRect.top);
2717 RECT rcn = newClientRect;
2718 RECT rco = oldClientRect;
2720 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2721 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2722 IntersectRect( &rcn, &rcn, &rco );
2723 visRgn = CreateRectRgnIndirect( &rcn );
2724 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2725 DeleteObject( hrgn );
2726 uFlags = SWP_EX_PAINTSELF;
2728 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2731 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2734 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2735 winpos.hwndInsertAfter = tempInsertAfter;
2738 if( winpos.flags & SWP_SHOWWINDOW )
2742 wndPtr->dwStyle |= WS_VISIBLE;
2744 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2746 /* focus was set to unmapped window, reset host focus
2747 * since the window is now visible */
2749 focus = curr = GetFocus();
2754 WND *pFocus = WIN_FindWndPtr( focus );
2756 pFocus->pDriver->pSetFocus(pFocus);
2757 WIN_ReleaseWndPtr(pFocus);
2760 curr = GetParent(curr);
2764 else /* -------------------------------------------- emulated window */
2766 if( winpos.flags & SWP_SHOWWINDOW )
2768 wndPtr->dwStyle |= WS_VISIBLE;
2769 uFlags |= SWP_EX_PAINTSELF;
2770 visRgn = 1; /* redraw the whole window */
2772 else if( !(winpos.flags & SWP_NOREDRAW) )
2774 if( winpos.flags & SWP_HIDEWINDOW )
2776 if( visRgn > 1 ) /* map to parent */
2777 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2783 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2784 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2785 &oldClientRect, uFlags);
2788 /* nothing moved, redraw frame if needed */
2790 if( winpos.flags & SWP_FRAMECHANGED )
2791 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2794 DeleteObject( visRgn );
2802 if( winpos.flags & SWP_HIDEWINDOW )
2804 wndPtr->dwStyle &= ~WS_VISIBLE;
2806 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2808 /* FIXME: This will cause the window to be activated irrespective
2809 * of whether it is owned by the same thread. Has to be done
2813 if (winpos.hwnd == hwndActive)
2814 WINPOS_ActivateOtherWindow( wndPtr );
2817 /* ------------------------------------------------------------------------ FINAL */
2819 if (wndPtr->flags & WIN_NATIVE)
2820 EVENT_Synchronize(); /* Synchronize with the host window system */
2822 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2824 /* Simulate a mouse event to set the cursor */
2825 DWORD posX, posY, keyState;
2827 if ( EVENT_QueryPointer( &posX, &posY, &keyState ) )
2829 int iWndsLocks = WIN_SuspendWndsLock();
2831 hardware_event( WM_MOUSEMOVE, keyState, 0,
2832 posX, posY, GetTickCount(), 0 );
2834 WIN_RestoreWndsLock(iWndsLocks);
2838 wndTemp = WIN_GetDesktop();
2840 /* repaint invalidated region (if any)
2842 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2843 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2848 if( !(winpos.flags & SWP_NOREDRAW) )
2851 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2852 its parent and sibling and so on, and then erase the parent window
2853 back ground if the parent is either a top-level window or its parent's parent
2854 is top-level window. Rely on the system to repaint other affected
2855 windows later on. */
2856 if( uFlags & SWP_EX_PAINTSELF )
2858 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2859 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2860 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2864 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2865 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2869 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2871 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2872 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2876 DeleteObject( visRgn );
2879 WIN_ReleaseDesktop();
2881 if (!(flags & SWP_NOACTIVATE))
2882 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2884 /* And last, send the WM_WINDOWPOSCHANGED message */
2886 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2889 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2890 !(winpos.flags & SWP_NOSENDCHANGING)) )
2892 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2893 if (resync) EVENT_Synchronize();
2898 WIN_ReleaseWndPtr(wndPtr);
2903 /***********************************************************************
2904 * BeginDeferWindowPos16 (USER.259)
2906 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2908 return BeginDeferWindowPos( count );
2912 /***********************************************************************
2913 * BeginDeferWindowPos (USER32.9)
2915 HDWP WINAPI BeginDeferWindowPos( INT count )
2920 if (count <= 0) return 0;
2921 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2922 if (!handle) return 0;
2923 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2924 pDWP->actualCount = 0;
2925 pDWP->suggestedCount = count;
2927 pDWP->wMagic = DWP_MAGIC;
2928 pDWP->hwndParent = 0;
2933 /***********************************************************************
2934 * DeferWindowPos16 (USER.260)
2936 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2937 INT16 x, INT16 y, INT16 cx, INT16 cy,
2940 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2941 x, y, cx, cy, flags );
2945 /***********************************************************************
2946 * DeferWindowPos (USER32.128)
2948 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2949 INT x, INT y, INT cx, INT cy,
2954 HDWP newhdwp = hdwp,retvalue;
2958 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2959 if (!pDWP) return 0;
2960 if (hwnd == GetDesktopWindow()) return 0;
2962 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2963 USER_HEAP_FREE( hdwp );
2967 /* Numega Bounds Checker Demo dislikes the following code.
2968 In fact, I've not been able to find any "same parent" requirement in any docu
2972 /* All the windows of a DeferWindowPos() must have the same parent */
2973 parent = pWnd->parent->hwndSelf;
2974 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2975 else if (parent != pDWP->hwndParent)
2977 USER_HEAP_FREE( hdwp );
2983 for (i = 0; i < pDWP->actualCount; i++)
2985 if (pDWP->winPos[i].hwnd == hwnd)
2987 /* Merge with the other changes */
2988 if (!(flags & SWP_NOZORDER))
2990 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2992 if (!(flags & SWP_NOMOVE))
2994 pDWP->winPos[i].x = x;
2995 pDWP->winPos[i].y = y;
2997 if (!(flags & SWP_NOSIZE))
2999 pDWP->winPos[i].cx = cx;
3000 pDWP->winPos[i].cy = cy;
3002 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3003 SWP_NOZORDER | SWP_NOREDRAW |
3004 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3006 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3012 if (pDWP->actualCount >= pDWP->suggestedCount)
3014 newhdwp = USER_HEAP_REALLOC( hdwp,
3015 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3021 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3022 pDWP->suggestedCount++;
3024 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3025 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3026 pDWP->winPos[pDWP->actualCount].x = x;
3027 pDWP->winPos[pDWP->actualCount].y = y;
3028 pDWP->winPos[pDWP->actualCount].cx = cx;
3029 pDWP->winPos[pDWP->actualCount].cy = cy;
3030 pDWP->winPos[pDWP->actualCount].flags = flags;
3031 pDWP->actualCount++;
3034 WIN_ReleaseWndPtr(pWnd);
3039 /***********************************************************************
3040 * EndDeferWindowPos16 (USER.261)
3042 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3044 return EndDeferWindowPos( hdwp );
3048 /***********************************************************************
3049 * EndDeferWindowPos (USER32.173)
3051 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3058 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3059 if (!pDWP) return FALSE;
3060 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3062 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3063 winpos->x, winpos->y, winpos->cx,
3064 winpos->cy, winpos->flags ))) break;
3066 USER_HEAP_FREE( hdwp );
3071 /***********************************************************************
3072 * TileChildWindows (USER.199)
3074 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3076 FIXME("(%04x, %d): stub\n", parent, action);
3079 /***********************************************************************
3080 * CascageChildWindows (USER.198)
3082 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3084 FIXME("(%04x, %d): stub\n", parent, action);
3087 /***********************************************************************
3088 * SetProgmanWindow [USER32.522]
3090 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3092 hGlobalProgmanWindow = hwnd;
3093 return hGlobalProgmanWindow;
3096 /***********************************************************************
3097 * GetProgmanWindow [USER32.289]
3099 HRESULT WINAPI GetProgmanWindow ( )
3101 return hGlobalProgmanWindow;
3104 /***********************************************************************
3105 * SetShellWindowEx [USER32.531]
3106 * hwndProgman = Progman[Program Manager]
3107 * |-> SHELLDLL_DefView
3108 * hwndListView = | |-> SysListView32
3109 * | | |-> tooltips_class32
3115 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3117 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3118 hGlobalShellWindow = hwndProgman;
3119 return hGlobalShellWindow;
3123 /***********************************************************************
3124 * SetTaskmanWindow [USER32.537]
3126 * hwnd = MSTaskSwWClass
3127 * |-> SysTabControl32
3129 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3131 hGlobalTaskmanWindow = hwnd;
3132 return hGlobalTaskmanWindow;
3135 /***********************************************************************
3136 * GetTaskmanWindow [USER32.304]
3138 HRESULT WINAPI GetTaskmanWindow ( )
3140 return hGlobalTaskmanWindow;