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"
32 DEFAULT_DEBUG_CHANNEL(win)
34 #define HAS_DLGFRAME(style,exStyle) \
35 (((exStyle) & WS_EX_DLGMODALFRAME) || \
36 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
38 #define HAS_THICKFRAME(style) \
39 (((style) & WS_THICKFRAME) && \
40 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
42 #define SWP_AGG_NOGEOMETRYCHANGE \
43 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
44 #define SWP_AGG_NOPOSCHANGE \
45 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
46 #define SWP_AGG_STATUSFLAGS \
47 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
49 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
51 #define PLACE_MIN 0x0001
52 #define PLACE_MAX 0x0002
53 #define PLACE_RECT 0x0004
55 #define SWP_EX_NOCOPY 0x0001
56 #define SWP_EX_PAINTSELF 0x0002
57 #define SWP_EX_NONCLIENT 0x0004
59 #define MINMAX_NOSWP 0x00010000
61 /* ----- internal variables ----- */
63 static HWND hwndPrevActive = 0; /* Previously active window */
64 static HWND hGlobalShellWindow=0; /*the shell*/
65 static HWND hGlobalTaskmanWindow=0;
66 static HWND hGlobalProgmanWindow=0;
68 static LPCSTR atomInternalPos;
70 extern HQUEUE16 hActiveQueue;
72 /***********************************************************************
73 * WINPOS_CreateInternalPosAtom
75 BOOL WINPOS_CreateInternalPosAtom()
78 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
79 return (atomInternalPos) ? TRUE : FALSE;
82 /***********************************************************************
83 * WINPOS_CheckInternalPos
85 * Called when a window is destroyed.
87 void WINPOS_CheckInternalPos( WND* wndPtr )
90 MESSAGEQUEUE *pMsgQ = 0;
91 HWND hwnd = wndPtr->hwndSelf;
93 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
95 /* Retrieve the message queue associated with this window */
96 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
99 WARN("\tMessage queue not found. Exiting!\n" );
103 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
105 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
107 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
108 WARN("\tattempt to activate destroyed window!\n");
113 if( IsWindow(lpPos->hwndIconTitle) )
114 DestroyWindow( lpPos->hwndIconTitle );
115 HeapFree( SystemHeap, 0, lpPos );
118 QUEUE_Unlock( pMsgQ );
122 /***********************************************************************
125 * Find a suitable place for an iconic window.
127 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
130 short x, y, xspacing, yspacing;
132 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
133 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
134 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
135 return pt; /* The icon already has a suitable position */
137 xspacing = GetSystemMetrics(SM_CXICONSPACING);
138 yspacing = GetSystemMetrics(SM_CYICONSPACING);
140 y = rectParent.bottom;
146 /* Check if another icon already occupies this spot */
147 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
150 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
152 if ((childPtr->rectWindow.left < x + xspacing) &&
153 (childPtr->rectWindow.right >= x) &&
154 (childPtr->rectWindow.top <= y) &&
155 (childPtr->rectWindow.bottom > y - yspacing))
156 break; /* There's a window in there */
158 WIN_UpdateWndPtr(&childPtr,childPtr->next);
160 WIN_ReleaseWndPtr(childPtr);
161 if (!childPtr) /* No window was found, so it's OK for us */
163 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
164 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
168 } while(x <= rectParent.right-xspacing);
174 /***********************************************************************
175 * ArrangeIconicWindows16 (USER.170)
177 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
179 return ArrangeIconicWindows(parent);
181 /***********************************************************************
182 * ArrangeIconicWindows (USER32.7)
184 UINT WINAPI ArrangeIconicWindows( HWND parent )
188 INT x, y, xspacing, yspacing;
190 GetClientRect( parent, &rectParent );
192 y = rectParent.bottom;
193 xspacing = GetSystemMetrics(SM_CXICONSPACING);
194 yspacing = GetSystemMetrics(SM_CYICONSPACING);
196 hwndChild = GetWindow( parent, GW_CHILD );
199 if( IsIconic( hwndChild ) )
201 WND *wndPtr = WIN_FindWndPtr(hwndChild);
203 WINPOS_ShowIconTitle( wndPtr, FALSE );
205 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
206 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
207 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
208 if( IsWindow(hwndChild) )
209 WINPOS_ShowIconTitle(wndPtr , TRUE );
210 WIN_ReleaseWndPtr(wndPtr);
212 if (x <= rectParent.right - xspacing) x += xspacing;
219 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
225 /***********************************************************************
226 * SwitchToThisWindow16 (USER.172)
228 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
230 SwitchToThisWindow( hwnd, restore );
234 /***********************************************************************
235 * SwitchToThisWindow (USER32.539)
237 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
239 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
243 /***********************************************************************
244 * GetWindowRect16 (USER.32)
246 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
248 WND * wndPtr = WIN_FindWndPtr( hwnd );
251 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
252 if (wndPtr->dwStyle & WS_CHILD)
253 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
254 WIN_ReleaseWndPtr(wndPtr);
258 /***********************************************************************
259 * GetWindowRect (USER32.308)
261 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
263 WND * wndPtr = WIN_FindWndPtr( hwnd );
264 if (!wndPtr) return FALSE;
266 *rect = wndPtr->rectWindow;
267 if (wndPtr->dwStyle & WS_CHILD)
268 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
269 WIN_ReleaseWndPtr(wndPtr);
274 /***********************************************************************
275 * GetWindowRgn (USER32)
277 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
280 WND *wndPtr = WIN_FindWndPtr( hwnd );
283 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
284 WIN_ReleaseWndPtr(wndPtr);
289 /***********************************************************************
290 * SetWindowRgn (USER32)
292 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
297 WND *wndPtr = WIN_FindWndPtr(hwnd);
299 if (!wndPtr) return FALSE;
301 /* a region exists for this window */
302 if (hrgn != 0 && hrgn == wndPtr->hrgnWnd)
304 /* can't replace actual region with same region
305 since we're now owner of that region
307 SetLastError(ERROR_INVALID_HANDLE);
313 /* delete previous region */
314 DeleteObject(wndPtr->hrgnWnd);
318 /* we'd like to set it back to 0 */
321 GetWindowRect(hwnd, &tempRect);
325 /* verify that region really exists */
326 if (GetRgnBox(hrgn, &tempRect) == ERROR) goto done;
329 /* valid region handle */
330 wndPtr->hrgnWnd = hrgn;
331 SetWindowPos( hwnd, NULL, tempRect.left, tempRect.top,
332 tempRect.right - tempRect.left, tempRect.bottom - tempRect.top,
333 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE |
334 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
336 wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn);
341 WIN_ReleaseWndPtr(wndPtr);
345 /***********************************************************************
348 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
352 FIXME("SetWindowRgn16: stub\n");
357 /***********************************************************************
358 * GetClientRect16 (USER.33)
360 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
362 WND * wndPtr = WIN_FindWndPtr( hwnd );
364 rect->left = rect->top = rect->right = rect->bottom = 0;
367 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
368 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
370 WIN_ReleaseWndPtr(wndPtr);
374 /***********************************************************************
375 * GetClientRect (USER.220)
377 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
379 WND * wndPtr = WIN_FindWndPtr( hwnd );
381 rect->left = rect->top = rect->right = rect->bottom = 0;
382 if (!wndPtr) return FALSE;
383 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
384 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
386 WIN_ReleaseWndPtr(wndPtr);
391 /*******************************************************************
392 * ClientToScreen16 (USER.28)
394 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
396 MapWindowPoints16( hwnd, 0, lppnt, 1 );
400 /*******************************************************************
401 * ClientToScreen (USER32.52)
403 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
405 MapWindowPoints( hwnd, 0, lppnt, 1 );
410 /*******************************************************************
411 * ScreenToClient16 (USER.29)
413 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
415 MapWindowPoints16( 0, hwnd, lppnt, 1 );
419 /*******************************************************************
420 * ScreenToClient (USER32.447)
422 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
424 MapWindowPoints( 0, hwnd, lppnt, 1 );
429 /***********************************************************************
430 * WINPOS_WindowFromPoint
432 * Find the window and hittest for a given point.
434 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
437 INT16 hittest = HTERROR;
442 wndPtr = WIN_LockWndPtr(wndScope->child);
444 if( wndScope->dwStyle & WS_DISABLED )
450 if( wndScope->flags & WIN_MANAGED )
452 /* In managed mode we have to check wndScope first as it is also
453 * a window which received the mouse event. */
455 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
456 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
459 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
465 /* If point is in window, and window is visible, and it */
466 /* is enabled (or it's a top-level window), then explore */
467 /* its children. Otherwise, go to the next window. */
469 if ((wndPtr->dwStyle & WS_VISIBLE) &&
470 (!(wndPtr->dwStyle & WS_DISABLED) ||
471 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
472 (xy.x >= wndPtr->rectWindow.left) &&
473 (xy.x < wndPtr->rectWindow.right) &&
474 (xy.y >= wndPtr->rectWindow.top) &&
475 (xy.y < wndPtr->rectWindow.bottom))
477 *ppWnd = wndPtr; /* Got a suitable window */
479 /* If window is minimized or disabled, return at once */
480 if (wndPtr->dwStyle & WS_MINIMIZE)
482 retvalue = HTCAPTION;
485 if (wndPtr->dwStyle & WS_DISABLED)
491 /* If point is not in client area, ignore the children */
492 if ((xy.x < wndPtr->rectClient.left) ||
493 (xy.x >= wndPtr->rectClient.right) ||
494 (xy.y < wndPtr->rectClient.top) ||
495 (xy.y >= wndPtr->rectClient.bottom)) break;
497 xy.x -= wndPtr->rectClient.left;
498 xy.y -= wndPtr->rectClient.top;
499 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
503 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
508 /* If nothing found, try the scope window */
509 if (!*ppWnd) *ppWnd = wndScope;
511 /* Send the WM_NCHITTEST message (only if to the same task) */
512 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
514 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
515 0, MAKELONG( pt.x, pt.y ) );
516 if (hittest != HTTRANSPARENT)
518 retvalue = hittest; /* Found the window */
528 /* If no children found in last search, make point relative to parent */
531 xy.x += (*ppWnd)->rectClient.left;
532 xy.y += (*ppWnd)->rectClient.top;
535 /* Restart the search from the next sibling */
536 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
537 *ppWnd = (*ppWnd)->parent;
541 WIN_ReleaseWndPtr(wndPtr);
546 /*******************************************************************
547 * WindowFromPoint16 (USER.30)
549 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
552 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
553 WIN_ReleaseDesktop();
554 return pWnd->hwndSelf;
558 /*******************************************************************
559 * WindowFromPoint (USER32.582)
561 HWND WINAPI WindowFromPoint( POINT pt )
565 CONV_POINT32TO16( &pt, &pt16 );
566 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
567 WIN_ReleaseDesktop();
568 return (HWND)pWnd->hwndSelf;
572 /*******************************************************************
573 * ChildWindowFromPoint16 (USER.191)
575 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
578 CONV_POINT16TO32( &pt, &pt32 );
579 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
583 /*******************************************************************
584 * ChildWindowFromPoint (USER32.49)
586 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
588 /* pt is in the client coordinates */
590 WND* wnd = WIN_FindWndPtr(hwndParent);
596 /* get client rect fast */
597 rect.top = rect.left = 0;
598 rect.right = wnd->rectClient.right - wnd->rectClient.left;
599 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
601 if (!PtInRect( &rect, pt ))
606 WIN_UpdateWndPtr(&wnd,wnd->child);
609 if (PtInRect( &wnd->rectWindow, pt ))
611 retvalue = wnd->hwndSelf;
614 WIN_UpdateWndPtr(&wnd,wnd->next);
616 retvalue = hwndParent;
618 WIN_ReleaseWndPtr(wnd);
622 /*******************************************************************
623 * ChildWindowFromPointEx16 (USER.50)
625 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
628 CONV_POINT16TO32( &pt, &pt32 );
629 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
633 /*******************************************************************
634 * ChildWindowFromPointEx (USER32.50)
636 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
639 /* pt is in the client coordinates */
641 WND* wnd = WIN_FindWndPtr(hwndParent);
647 /* get client rect fast */
648 rect.top = rect.left = 0;
649 rect.right = wnd->rectClient.right - wnd->rectClient.left;
650 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
652 if (!PtInRect( &rect, pt ))
657 WIN_UpdateWndPtr(&wnd,wnd->child);
661 if (PtInRect( &wnd->rectWindow, pt )) {
662 if ( (uFlags & CWP_SKIPINVISIBLE) &&
663 !(wnd->dwStyle & WS_VISIBLE) );
664 else if ( (uFlags & CWP_SKIPDISABLED) &&
665 (wnd->dwStyle & WS_DISABLED) );
666 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
667 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
670 retvalue = wnd->hwndSelf;
675 WIN_UpdateWndPtr(&wnd,wnd->next);
677 retvalue = hwndParent;
679 WIN_ReleaseWndPtr(wnd);
684 /*******************************************************************
685 * WINPOS_GetWinOffset
687 * Calculate the offset between the origin of the two windows. Used
688 * to implement MapWindowPoints.
690 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
695 offset->x = offset->y = 0;
696 if (hwndFrom == hwndTo ) return;
698 /* Translate source window origin to screen coords */
701 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
703 ERR("bad hwndFrom = %04x\n",hwndFrom);
706 while (wndPtr->parent)
708 offset->x += wndPtr->rectClient.left;
709 offset->y += wndPtr->rectClient.top;
710 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
712 WIN_ReleaseWndPtr(wndPtr);
715 /* Translate origin to destination window coords */
718 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
720 ERR("bad hwndTo = %04x\n", hwndTo );
723 while (wndPtr->parent)
725 offset->x -= wndPtr->rectClient.left;
726 offset->y -= wndPtr->rectClient.top;
727 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
729 WIN_ReleaseWndPtr(wndPtr);
734 /*******************************************************************
735 * MapWindowPoints16 (USER.258)
737 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
738 LPPOINT16 lppt, UINT16 count )
742 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
752 /*******************************************************************
753 * MapWindowPoints (USER32.386)
755 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
756 LPPOINT lppt, UINT count )
760 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
767 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
771 /***********************************************************************
772 * IsIconic16 (USER.31)
774 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
776 return IsIconic(hWnd);
780 /***********************************************************************
781 * IsIconic (USER32.345)
783 BOOL WINAPI IsIconic(HWND hWnd)
786 WND * wndPtr = WIN_FindWndPtr(hWnd);
787 if (wndPtr == NULL) return FALSE;
788 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
789 WIN_ReleaseWndPtr(wndPtr);
794 /***********************************************************************
795 * IsZoomed (USER.272)
797 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
799 return IsZoomed(hWnd);
803 /***********************************************************************
804 * IsZoomed (USER.352)
806 BOOL WINAPI IsZoomed(HWND hWnd)
809 WND * wndPtr = WIN_FindWndPtr(hWnd);
810 if (wndPtr == NULL) return FALSE;
811 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
812 WIN_ReleaseWndPtr(wndPtr);
817 /*******************************************************************
818 * GetActiveWindow (USER.60)
820 HWND16 WINAPI GetActiveWindow16(void)
822 return (HWND16)GetActiveWindow();
825 /*******************************************************************
826 * GetActiveWindow (USER32.205)
828 HWND WINAPI GetActiveWindow(void)
830 MESSAGEQUEUE *pCurMsgQ = 0;
833 /* Get the messageQ for the current thread */
834 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
836 WARN("\tCurrent message queue not found. Exiting!\n" );
840 /* Return the current active window from the perQ data of the current message Q */
841 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
843 QUEUE_Unlock( pCurMsgQ );
848 /*******************************************************************
851 static BOOL WINPOS_CanActivate(WND* pWnd)
853 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
854 == WS_VISIBLE ) ) return TRUE;
859 /*******************************************************************
860 * SetActiveWindow16 (USER.59)
862 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
864 return SetActiveWindow(hwnd);
868 /*******************************************************************
869 * SetActiveWindow (USER32.463)
871 HWND WINAPI SetActiveWindow( HWND hwnd )
874 WND *wndPtr = WIN_FindWndPtr( hwnd );
875 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
877 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
883 /* Get the messageQ for the current thread */
884 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
886 WARN("\tCurrent message queue not found. Exiting!\n" );
890 /* Retrieve the message queue associated with this window */
891 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
894 WARN("\tWindow message queue not found. Exiting!\n" );
898 /* Make sure that the window is associated with the calling threads
899 * message queue. It must share the same perQ data.
902 if ( pCurMsgQ->pQData != pMsgQ->pQData )
905 /* Save current active window */
906 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
908 WINPOS_SetActiveWindow( hwnd, 0, 0 );
911 /* Unlock the queues before returning */
913 QUEUE_Unlock( pMsgQ );
915 QUEUE_Unlock( pCurMsgQ );
918 WIN_ReleaseWndPtr(wndPtr);
923 /*******************************************************************
924 * GetForegroundWindow16 (USER.608)
926 HWND16 WINAPI GetForegroundWindow16(void)
928 return (HWND16)GetForegroundWindow();
932 /*******************************************************************
933 * SetForegroundWindow16 (USER.609)
935 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
937 return SetForegroundWindow( hwnd );
941 /*******************************************************************
942 * GetForegroundWindow (USER32.241)
944 HWND WINAPI GetForegroundWindow(void)
948 /* Get the foreground window (active window of hActiveQueue) */
951 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
953 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
955 QUEUE_Unlock( pActiveQueue );
961 /*******************************************************************
962 * SetForegroundWindow (USER32.482)
964 BOOL WINAPI SetForegroundWindow( HWND hwnd )
966 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
970 /*******************************************************************
971 * GetShellWindow16 (USER.600)
973 HWND16 WINAPI GetShellWindow16(void)
975 return GetShellWindow();
978 /*******************************************************************
979 * SetShellWindow (USER32.504)
981 HWND WINAPI SetShellWindow(HWND hwndshell)
982 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
984 hGlobalShellWindow = hwndshell;
985 return hGlobalShellWindow;
989 /*******************************************************************
990 * GetShellWindow (USER32.287)
992 HWND WINAPI GetShellWindow(void)
993 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
995 return hGlobalShellWindow;
999 /***********************************************************************
1000 * BringWindowToTop16 (USER.45)
1002 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1004 return BringWindowToTop(hwnd);
1008 /***********************************************************************
1009 * BringWindowToTop (USER32.11)
1011 BOOL WINAPI BringWindowToTop( HWND hwnd )
1013 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1017 /***********************************************************************
1018 * MoveWindow16 (USER.56)
1020 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1023 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1027 /***********************************************************************
1028 * MoveWindow (USER32.399)
1030 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1033 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1034 if (!repaint) flags |= SWP_NOREDRAW;
1035 TRACE("%04x %d,%d %dx%d %d\n",
1036 hwnd, x, y, cx, cy, repaint );
1037 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1040 /***********************************************************************
1041 * WINPOS_InitInternalPos
1043 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1044 LPRECT restoreRect )
1046 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1050 /* this happens when the window is minimized/maximized
1051 * for the first time (rectWindow is not adjusted yet) */
1053 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1054 if( !lpPos ) return NULL;
1056 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1057 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1058 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1059 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1062 if( wnd->dwStyle & WS_MINIMIZE )
1063 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1064 else if( wnd->dwStyle & WS_MAXIMIZE )
1065 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1066 else if( restoreRect )
1067 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1072 /***********************************************************************
1073 * WINPOS_RedrawIconTitle
1075 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1077 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1080 if( lpPos->hwndIconTitle )
1082 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1083 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1090 /***********************************************************************
1091 * WINPOS_ShowIconTitle
1093 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1095 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1097 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1099 HWND16 hWnd = lpPos->hwndIconTitle;
1101 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1104 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1107 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1109 if( !(pWnd->dwStyle & WS_VISIBLE) )
1111 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1112 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1113 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1115 WIN_ReleaseWndPtr(pWnd);
1118 else ShowWindow( hWnd, SW_HIDE );
1123 /*******************************************************************
1124 * WINPOS_GetMinMaxInfo
1126 * Get the minimized and maximized information for a window.
1128 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1129 POINT *minTrack, POINT *maxTrack )
1131 LPINTERNALPOS lpPos;
1135 /* Compute default values */
1137 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1138 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1139 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1140 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1141 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1142 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1144 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1145 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1147 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1148 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1153 if (HAS_THICKFRAME(wndPtr->dwStyle))
1155 xinc += GetSystemMetrics(SM_CXFRAME);
1156 yinc += GetSystemMetrics(SM_CYFRAME);
1158 if (wndPtr->dwStyle & WS_BORDER)
1160 xinc += GetSystemMetrics(SM_CXBORDER);
1161 yinc += GetSystemMetrics(SM_CYBORDER);
1164 MinMax.ptMaxSize.x += 2 * xinc;
1165 MinMax.ptMaxSize.y += 2 * yinc;
1167 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1168 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1169 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1172 MinMax.ptMaxPosition.x = -xinc;
1173 MinMax.ptMaxPosition.y = -yinc;
1176 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1178 /* Some sanity checks */
1180 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1181 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1182 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1183 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1184 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1185 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1186 MinMax.ptMinTrackSize.x );
1187 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1188 MinMax.ptMinTrackSize.y );
1190 if (maxSize) *maxSize = MinMax.ptMaxSize;
1191 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1192 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1193 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1196 /***********************************************************************
1197 * WINPOS_MinMaximize
1199 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1200 * This function assumes that 'cmd' is different from the current window
1203 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1207 LPINTERNALPOS lpPos;
1209 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1211 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1212 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1214 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1216 if( wndPtr->dwStyle & WS_MINIMIZE )
1218 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1219 return (SWP_NOSIZE | SWP_NOMOVE);
1220 swpFlags |= SWP_NOCOPYBITS;
1225 if( wndPtr->dwStyle & WS_MAXIMIZE)
1227 wndPtr->flags |= WIN_RESTORE_MAX;
1228 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1231 wndPtr->flags &= ~WIN_RESTORE_MAX;
1232 wndPtr->dwStyle |= WS_MINIMIZE;
1234 if( wndPtr->flags & WIN_NATIVE )
1235 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1236 swpFlags |= MINMAX_NOSWP;
1238 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1240 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1241 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1242 swpFlags |= SWP_NOCOPYBITS;
1246 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1247 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1248 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1250 if( wndPtr->dwStyle & WS_MINIMIZE )
1252 if( wndPtr->flags & WIN_NATIVE )
1253 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1254 swpFlags |= MINMAX_NOSWP;
1256 WINPOS_ShowIconTitle( wndPtr, FALSE );
1257 wndPtr->dwStyle &= ~WS_MINIMIZE;
1259 wndPtr->dwStyle |= WS_MAXIMIZE;
1261 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1266 if( wndPtr->dwStyle & WS_MINIMIZE )
1268 if( wndPtr->flags & WIN_NATIVE )
1269 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1270 swpFlags |= MINMAX_NOSWP;
1272 wndPtr->dwStyle &= ~WS_MINIMIZE;
1273 WINPOS_ShowIconTitle( wndPtr, FALSE );
1275 if( wndPtr->flags & WIN_RESTORE_MAX)
1277 /* Restore to maximized position */
1278 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1279 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1280 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1281 wndPtr->dwStyle |= WS_MAXIMIZE;
1282 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1287 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1288 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1290 /* Restore to normal position */
1292 *lpRect = lpPos->rectNormal;
1293 lpRect->right -= lpRect->left;
1294 lpRect->bottom -= lpRect->top;
1298 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1302 /***********************************************************************
1303 * ShowWindowAsync (USER32.535)
1305 * doesn't wait; returns immediately.
1306 * used by threads to toggle windows in other (possibly hanging) threads
1308 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1310 /* FIXME: does ShowWindow() return immediately ? */
1311 return ShowWindow(hwnd, cmd);
1315 /***********************************************************************
1316 * ShowWindow16 (USER.42)
1318 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1320 return ShowWindow(hwnd,cmd);
1324 /***********************************************************************
1325 * ShowWindow (USER32.534)
1327 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1329 WND* wndPtr = WIN_FindWndPtr( hwnd );
1330 BOOL wasVisible, showFlag;
1331 RECT16 newPos = {0, 0, 0, 0};
1334 if (!wndPtr) return FALSE;
1336 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1338 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1343 if (!wasVisible) goto END;;
1344 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1345 SWP_NOACTIVATE | SWP_NOZORDER;
1348 case SW_SHOWMINNOACTIVE:
1349 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1351 case SW_SHOWMINIMIZED:
1352 swp |= SWP_SHOWWINDOW;
1355 swp |= SWP_FRAMECHANGED;
1356 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1357 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1358 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1361 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1362 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1363 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1364 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1365 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1369 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1372 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1375 * ShowWindow has a little peculiar behavior that if the
1376 * window is already the topmost window, it will not
1379 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1380 swp |= SWP_NOACTIVATE;
1384 case SW_SHOWNOACTIVATE:
1385 swp |= SWP_NOZORDER;
1386 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1388 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1389 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1391 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1393 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1394 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1395 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1399 showFlag = (cmd != SW_HIDE);
1400 if (showFlag != wasVisible)
1402 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1403 if (!IsWindow( hwnd )) goto END;
1406 if ((wndPtr->dwStyle & WS_CHILD) &&
1407 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1408 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1410 /* Don't call SetWindowPos() on invisible child windows */
1411 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1412 else wndPtr->dwStyle |= WS_VISIBLE;
1416 /* We can't activate a child window */
1417 if ((wndPtr->dwStyle & WS_CHILD) &&
1418 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1419 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1420 if (!(swp & MINMAX_NOSWP))
1422 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1423 newPos.right, newPos.bottom, LOWORD(swp) );
1426 /* FIXME: This will cause the window to be activated irrespective
1427 * of whether it is owned by the same thread. Has to be done
1431 if (hwnd == GetActiveWindow())
1432 WINPOS_ActivateOtherWindow(wndPtr);
1434 /* Revert focus to parent */
1435 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1436 SetFocus( GetParent(hwnd) );
1439 if (!IsWindow( hwnd )) goto END;
1440 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1443 if (wndPtr->flags & WIN_NEED_SIZE)
1445 /* should happen only in CreateWindowEx() */
1446 int wParam = SIZE_RESTORED;
1448 wndPtr->flags &= ~WIN_NEED_SIZE;
1449 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1450 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1451 SendMessageA( hwnd, WM_SIZE, wParam,
1452 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1453 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1454 SendMessageA( hwnd, WM_MOVE, 0,
1455 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1459 WIN_ReleaseWndPtr(wndPtr);
1464 /***********************************************************************
1465 * GetInternalWindowPos16 (USER.460)
1467 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1470 WINDOWPLACEMENT16 wndpl;
1471 if (GetWindowPlacement16( hwnd, &wndpl ))
1473 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1474 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1475 return wndpl.showCmd;
1481 /***********************************************************************
1482 * GetInternalWindowPos (USER32.245)
1484 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1487 WINDOWPLACEMENT wndpl;
1488 if (GetWindowPlacement( hwnd, &wndpl ))
1490 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1491 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1492 return wndpl.showCmd;
1497 /***********************************************************************
1498 * GetWindowPlacement16 (USER.370)
1500 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1502 WND *pWnd = WIN_FindWndPtr( hwnd );
1503 LPINTERNALPOS lpPos;
1505 if(!pWnd ) return FALSE;
1507 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1508 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1509 wndpl->length = sizeof(*wndpl);
1510 if( pWnd->dwStyle & WS_MINIMIZE )
1511 wndpl->showCmd = SW_SHOWMINIMIZED;
1513 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1514 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1515 if( pWnd->flags & WIN_RESTORE_MAX )
1516 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1519 wndpl->ptMinPosition = lpPos->ptIconPos;
1520 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1521 wndpl->rcNormalPosition = lpPos->rectNormal;
1523 WIN_ReleaseWndPtr(pWnd);
1528 /***********************************************************************
1529 * GetWindowPlacement (USER32.307)
1532 * Fails if wndpl->length of Win95 (!) apps is invalid.
1534 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1538 WINDOWPLACEMENT16 wpl;
1539 wpl.length = sizeof(wpl);
1540 if( GetWindowPlacement16( hwnd, &wpl ) )
1542 pwpl32->length = sizeof(*pwpl32);
1543 pwpl32->flags = wpl.flags;
1544 pwpl32->showCmd = wpl.showCmd;
1545 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1546 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1547 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1555 /***********************************************************************
1556 * WINPOS_SetPlacement
1558 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1561 WND *pWnd = WIN_FindWndPtr( hwnd );
1564 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1565 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1567 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1568 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1569 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1571 if( pWnd->dwStyle & WS_MINIMIZE )
1573 WINPOS_ShowIconTitle( pWnd, FALSE );
1574 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1575 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1576 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1578 else if( pWnd->dwStyle & WS_MAXIMIZE )
1580 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1581 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1582 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1584 else if( flags & PLACE_RECT )
1585 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1586 lpPos->rectNormal.right - lpPos->rectNormal.left,
1587 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1588 SWP_NOZORDER | SWP_NOACTIVATE );
1590 ShowWindow( hwnd, wndpl->showCmd );
1591 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1593 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1595 /* SDK: ...valid only the next time... */
1596 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1598 WIN_ReleaseWndPtr(pWnd);
1605 /***********************************************************************
1606 * SetWindowPlacement16 (USER.371)
1608 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1610 return WINPOS_SetPlacement( hwnd, wndpl,
1611 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1614 /***********************************************************************
1615 * SetWindowPlacement (USER32.519)
1618 * Fails if wndpl->length of Win95 (!) apps is invalid.
1620 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1624 WINDOWPLACEMENT16 wpl;
1626 wpl.length = sizeof(WINDOWPLACEMENT16);
1627 wpl.flags = pwpl32->flags;
1628 wpl.showCmd = pwpl32->showCmd;
1629 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1630 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1631 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1632 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1633 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1634 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1635 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1636 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1638 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1644 /***********************************************************************
1645 * SetInternalWindowPos16 (USER.461)
1647 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1648 LPRECT16 rect, LPPOINT16 pt )
1650 if( IsWindow16(hwnd) )
1652 WINDOWPLACEMENT16 wndpl;
1655 wndpl.length = sizeof(wndpl);
1656 wndpl.showCmd = showCmd;
1657 wndpl.flags = flags = 0;
1662 wndpl.flags |= WPF_SETMINPOSITION;
1663 wndpl.ptMinPosition = *pt;
1667 flags |= PLACE_RECT;
1668 wndpl.rcNormalPosition = *rect;
1670 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1675 /***********************************************************************
1676 * SetInternalWindowPos (USER32.483)
1678 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1679 LPRECT rect, LPPOINT pt )
1681 if( IsWindow(hwnd) )
1683 WINDOWPLACEMENT16 wndpl;
1686 wndpl.length = sizeof(wndpl);
1687 wndpl.showCmd = showCmd;
1688 wndpl.flags = flags = 0;
1693 wndpl.flags |= WPF_SETMINPOSITION;
1694 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1698 flags |= PLACE_RECT;
1699 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1701 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1705 /*******************************************************************
1706 * WINPOS_SetActiveWindow
1708 * SetActiveWindow() back-end. This is the only function that
1709 * can assign active status to a window. It must be called only
1710 * for the top level windows.
1712 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1714 CBTACTIVATESTRUCT16* cbtStruct;
1715 WND* wndPtr=0, *wndTemp;
1716 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1717 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1719 HWND hwndActive = 0;
1722 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1724 /* Get current active window from the active queue */
1727 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1728 if ( pOldActiveQueue )
1729 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1732 /* paranoid checks */
1733 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1736 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1739 wndPtr = WIN_FindWndPtr(hWnd);
1740 hOldActiveQueue = hActiveQueue;
1742 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1744 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1745 WIN_ReleaseWndPtr(wndTemp);
1748 TRACE("no current active window.\n");
1750 /* call CBT hook chain */
1751 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1753 cbtStruct->fMouse = fMouse;
1754 cbtStruct->hWndActive = hwndActive;
1755 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1756 (LPARAM)SEGPTR_GET(cbtStruct) );
1757 SEGPTR_FREE(cbtStruct);
1758 if (bRet) goto CLEANUP_END;
1761 /* set prev active wnd to current active wnd and send notification */
1762 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1764 MESSAGEQUEUE *pTempActiveQueue = 0;
1766 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1768 if (GetSysModalWindow16() != hWnd)
1770 /* disregard refusal if hWnd is sysmodal */
1773 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1774 MAKEWPARAM( WA_INACTIVE, wIconized ),
1777 /* check if something happened during message processing
1778 * (global active queue may have changed)
1780 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1781 if(!pTempActiveQueue)
1784 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1785 QUEUE_Unlock( pTempActiveQueue );
1786 if( hwndPrevActive != hwndActive )
1790 /* Set new active window in the message queue */
1794 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1795 if ( pNewActiveQueue )
1796 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1798 else /* have to do this or MDI frame activation goes to hell */
1799 if( pOldActiveQueue )
1800 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1802 /* send palette messages */
1803 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1804 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1806 /* if prev wnd is minimized redraw icon title */
1807 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1809 /* managed windows will get ConfigureNotify event */
1810 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1812 /* check Z-order and bring hWnd to the top */
1813 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1815 if (wndTemp->dwStyle & WS_VISIBLE) break;
1817 WIN_ReleaseDesktop();
1818 WIN_ReleaseWndPtr(wndTemp);
1820 if( wndTemp != wndPtr )
1821 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1822 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1823 if (!IsWindow(hWnd))
1827 /* Get a handle to the new active queue */
1828 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1830 /* send WM_ACTIVATEAPP if necessary */
1831 if (hOldActiveQueue != hNewActiveQueue)
1833 WND **list, **ppWnd;
1834 WND *pDesktop = WIN_GetDesktop();
1836 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1838 for (ppWnd = list; *ppWnd; ppWnd++)
1840 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1842 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1843 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1844 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1846 WIN_ReleaseWinArray(list);
1849 hActiveQueue = hNewActiveQueue;
1851 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1853 for (ppWnd = list; *ppWnd; ppWnd++)
1855 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1857 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1858 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1859 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1861 WIN_ReleaseWinArray(list);
1863 WIN_ReleaseDesktop();
1865 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1870 /* walk up to the first unowned window */
1871 wndTemp = WIN_LockWndPtr(wndPtr);
1872 while (wndTemp->owner)
1874 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1876 /* and set last active owned popup */
1877 wndTemp->hwndLastActive = hWnd;
1879 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1880 WIN_ReleaseWndPtr(wndTemp);
1881 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1882 SendMessageA( hWnd, WM_ACTIVATE,
1883 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1884 (LPARAM)hwndPrevActive );
1885 if( !IsWindow(hWnd) ) goto CLEANUP;
1888 /* change focus if possible */
1891 if ( pNewActiveQueue )
1893 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1895 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1896 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1897 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1901 if ( pOldActiveQueue &&
1902 ( !pNewActiveQueue ||
1903 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1905 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1907 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1911 if( !hwndPrevActive && wndPtr )
1912 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1914 /* if active wnd is minimized redraw icon title */
1915 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1917 bRet = (hWnd == hwndActive); /* Success? */
1919 CLEANUP: /* Unlock the message queues before returning */
1921 if ( pNewActiveQueue )
1922 QUEUE_Unlock( pNewActiveQueue );
1926 if ( pOldActiveQueue )
1927 QUEUE_Unlock( pOldActiveQueue );
1929 WIN_ReleaseWndPtr(wndPtr);
1933 /*******************************************************************
1934 * WINPOS_ActivateOtherWindow
1936 * Activates window other than pWnd.
1938 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1942 HWND hwndActive = 0;
1944 /* Get current active window from the active queue */
1947 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1950 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1951 QUEUE_Unlock( pActiveQueue );
1955 if( pWnd->hwndSelf == hwndPrevActive )
1958 if( hwndActive != pWnd->hwndSelf &&
1959 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1962 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1963 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1965 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1967 WIN_ReleaseWndPtr(pWndTo);
1968 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1970 while( !WINPOS_CanActivate(pWndTo) )
1972 /* by now owned windows should've been taken care of */
1973 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1974 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1975 if( !pWndTo ) break;
1977 WIN_ReleaseWndPtr(pWndPtr);
1980 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1982 /* switch desktop queue to current active */
1985 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1986 WIN_ReleaseWndPtr(pWndTo);
1987 WIN_ReleaseDesktop();
1994 /*******************************************************************
1995 * WINPOS_ChangeActiveWindow
1998 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2000 WND *wndPtr, *wndTemp;
2002 HWND hwndActive = 0;
2004 /* Get current active window from the active queue */
2007 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2010 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2011 QUEUE_Unlock( pActiveQueue );
2016 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2018 wndPtr = WIN_FindWndPtr(hWnd);
2019 if( !wndPtr ) return FALSE;
2021 /* child windows get WM_CHILDACTIVATE message */
2022 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2024 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2028 if( hWnd == hwndActive )
2034 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2040 /* switch desktop queue to current active */
2041 wndTemp = WIN_GetDesktop();
2042 if( wndPtr->parent == wndTemp)
2043 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2044 WIN_ReleaseDesktop();
2048 WIN_ReleaseWndPtr(wndPtr);
2053 /***********************************************************************
2054 * WINPOS_SendNCCalcSize
2056 * Send a WM_NCCALCSIZE message to a window.
2057 * All parameters are read-only except newClientRect.
2058 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2059 * when calcValidRect is TRUE.
2061 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2062 RECT *newWindowRect, RECT *oldWindowRect,
2063 RECT *oldClientRect, WINDOWPOS *winpos,
2064 RECT *newClientRect )
2066 NCCALCSIZE_PARAMS params;
2067 WINDOWPOS winposCopy;
2070 params.rgrc[0] = *newWindowRect;
2073 winposCopy = *winpos;
2074 params.rgrc[1] = *oldWindowRect;
2075 params.rgrc[2] = *oldClientRect;
2076 params.lppos = &winposCopy;
2078 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2080 TRACE("%d,%d-%d,%d\n",
2081 params.rgrc[0].left, params.rgrc[0].top,
2082 params.rgrc[0].right, params.rgrc[0].bottom );
2084 /* If the application send back garbage, ignore it */
2085 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2086 *newClientRect = params.rgrc[0];
2092 /***********************************************************************
2093 * WINPOS_HandleWindowPosChanging16
2095 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2097 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2099 POINT maxSize, minTrack;
2100 if (winpos->flags & SWP_NOSIZE) return 0;
2101 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2102 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2104 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2105 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2106 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2107 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2109 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2110 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2117 /***********************************************************************
2118 * WINPOS_HandleWindowPosChanging
2120 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2122 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2125 if (winpos->flags & SWP_NOSIZE) return 0;
2126 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2127 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2129 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2130 winpos->cx = min( winpos->cx, maxSize.x );
2131 winpos->cy = min( winpos->cy, maxSize.y );
2136 /***********************************************************************
2139 * fix Z order taking into account owned popups -
2140 * basically we need to maintain them above the window that owns them
2142 * FIXME: hide/show owned popups when owner visibility changes.
2144 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2146 WND* w = WIN_LockWndPtr(pDesktop->child);
2148 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2150 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2152 /* make sure this popup stays above the owner */
2154 HWND hwndLocalPrev = HWND_TOP;
2156 if( hwndInsertAfter != HWND_TOP )
2158 while( w != wndPtr->owner )
2160 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2161 if( hwndLocalPrev == hwndInsertAfter ) break;
2162 WIN_UpdateWndPtr(&w,w->next);
2164 hwndInsertAfter = hwndLocalPrev;
2167 else if( wndPtr->dwStyle & WS_CHILD )
2170 WIN_UpdateWndPtr(&w, pDesktop->child);
2174 if( w == wndPtr ) break;
2176 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2178 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2179 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2180 hwndInsertAfter = w->hwndSelf;
2182 WIN_UpdateWndPtr(&w, w->next);
2186 WIN_ReleaseWndPtr(w);
2187 return hwndInsertAfter;
2190 /***********************************************************************
2193 * Make window look nice without excessive repainting
2195 * visible and update regions are in window coordinates
2196 * client and window rectangles are in parent client coordinates
2198 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2199 * window rects have the same origin.
2201 * Returns: uFlags and a dirty region in *pVisRgn.
2203 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2204 LPRECT lpOldWndRect,
2205 LPRECT lpOldClientRect, UINT uFlags )
2208 HRGN newVisRgn, dirtyRgn;
2209 INT my = COMPLEXREGION;
2211 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2212 Wnd->rectWindow.left, Wnd->rectWindow.top,
2213 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2214 lpOldWndRect->left, lpOldWndRect->top,
2215 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2216 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2217 Wnd->rectClient.left, Wnd->rectClient.top,
2218 Wnd->rectClient.right, Wnd->rectClient.bottom,
2219 lpOldClientRect->left, lpOldClientRect->top,
2220 lpOldClientRect->right,lpOldClientRect->bottom );
2222 if( Wnd->hrgnUpdate == 1 )
2223 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2225 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2226 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2228 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2229 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2231 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2235 TRACE("\twon't copy anything!\n");
2237 /* set dirtyRgn to the sum of old and new visible regions
2238 * in parent client coordinates */
2240 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2241 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2243 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2245 else /* copy valid bits to a new location */
2247 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2248 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2250 /* subtract already invalid region inside Wnd from the dst region */
2252 if( Wnd->hrgnUpdate )
2253 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2256 /* check if entire window can be copied */
2258 ow = lpOldWndRect->right - lpOldWndRect->left;
2259 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2260 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2261 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2263 ocw = lpOldClientRect->right - lpOldClientRect->left;
2264 och = lpOldClientRect->bottom - lpOldClientRect->top;
2265 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2266 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2268 if( (ocw != ncw) || (och != nch) ||
2269 ( ow != nw) || ( oh != nh) ||
2270 ((lpOldClientRect->top - lpOldWndRect->top) !=
2271 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2272 ((lpOldClientRect->left - lpOldWndRect->left) !=
2273 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2275 dx = Wnd->rectClient.left - lpOldClientRect->left;
2276 dy = Wnd->rectClient.top - lpOldClientRect->top;
2278 /* restrict valid bits to the common client rect */
2280 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2281 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2282 r.right = r.left + min( ocw, ncw );
2283 r.bottom = r.top + min( och, nch );
2285 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2286 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2287 GetRgnBox( hrgnValid, &r );
2288 if( IsRectEmpty( &r ) )
2290 r = *lpOldClientRect;
2294 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2295 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2296 if( !(uFlags & SWP_EX_PAINTSELF) )
2297 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2301 if( !(uFlags & SWP_EX_PAINTSELF) )
2303 /* Move remaining regions to parent coordinates */
2304 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2305 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2308 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2310 TRACE("\tcomputing dirty region!\n");
2312 /* Compute combined dirty region (old + new - valid) */
2313 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2314 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2316 /* Blt valid bits, r is the rect to copy */
2323 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2324 from copying clipped areas */
2326 if( uFlags & SWP_EX_PAINTSELF )
2328 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2329 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2330 rClip.right = nw; rClip.bottom = nh;
2334 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2335 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2336 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2337 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2339 rClip.left = rClip.top = 0;
2341 if( oh > nh ) r.bottom = r.top + nh;
2342 if( ow < nw ) r.right = r.left + nw;
2344 if( IntersectRect( &r, &r, &rClip ) )
2346 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2348 /* When you copy the bits without repainting, parent doesn't
2349 get validated appropriately. Therefore, we have to validate
2350 the parent with the windows' updated region when the
2351 parent's update region is not empty. */
2353 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2355 OffsetRect(&r, dx, dy);
2356 ValidateRect(Wnd->parent->hwndSelf, &r);
2359 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2360 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2364 /* *pVisRgn now points to the invalidated region */
2366 DeleteObject(newVisRgn);
2367 DeleteObject(dirtyRgn);
2371 /***********************************************************************
2372 * SWP_DoSimpleFrameChanged
2374 * NOTE: old and new client rect origins are identical, only
2375 * extents may have changed. Window extents are the same.
2377 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2383 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2385 /* Client rect changed its position/size, most likely a scrollar
2386 * was added/removed.
2388 * FIXME: WVR alignment flags
2391 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2395 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2396 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2397 if(!(uFlags & SWP_EX_NOCOPY))
2398 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2406 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2409 hrgn = CreateRectRgnIndirect( &rect );
2411 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2412 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2413 if(!(uFlags & SWP_EX_NOCOPY))
2414 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2418 REGION_UnionRectWithRgn( hrgn, &rect );
2421 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2423 rect = wndPtr->rectWindow;
2424 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2425 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2433 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2434 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2438 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2442 DeleteObject( hrgn );
2445 /***********************************************************************
2446 * SWP_DoWinPosChanging
2448 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2449 RECT* pNewWindowRect, RECT* pNewClientRect )
2451 /* Send WM_WINDOWPOSCHANGING message */
2453 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2454 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2456 /* Calculate new position and size */
2458 *pNewWindowRect = wndPtr->rectWindow;
2459 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2460 : wndPtr->rectClient;
2462 if (!(pWinpos->flags & SWP_NOSIZE))
2464 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2465 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2467 if (!(pWinpos->flags & SWP_NOMOVE))
2469 pNewWindowRect->left = pWinpos->x;
2470 pNewWindowRect->top = pWinpos->y;
2471 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2472 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2474 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2475 pWinpos->y - wndPtr->rectWindow.top );
2478 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2482 /***********************************************************************
2485 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2486 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2490 /* Send WM_NCCALCSIZE message to get new client area */
2491 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2493 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2494 &wndPtr->rectWindow, &wndPtr->rectClient,
2495 pWinpos, pNewClientRect );
2497 /* FIXME: WVR_ALIGNxxx */
2499 if( pNewClientRect->left != wndPtr->rectClient.left ||
2500 pNewClientRect->top != wndPtr->rectClient.top )
2501 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2503 if( (pNewClientRect->right - pNewClientRect->left !=
2504 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2505 (pNewClientRect->bottom - pNewClientRect->top !=
2506 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2507 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2510 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2511 pNewClientRect->top != wndPtr->rectClient.top) )
2512 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2516 /***********************************************************************
2517 * SetWindowPos (USER.2)
2519 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2520 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2522 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2525 /***********************************************************************
2526 * SetWindowPos (USER32.520)
2528 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2529 INT x, INT y, INT cx, INT cy, UINT flags )
2532 WND * wndPtr,*wndTemp;
2533 RECT newWindowRect, newClientRect;
2534 RECT oldWindowRect, oldClientRect;
2536 UINT wvrFlags = 0, uFlags = 0;
2537 BOOL retvalue, resync = FALSE, bChangePos;
2538 HWND hwndActive = 0;
2540 /* Get current active window from the active queue */
2543 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2546 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2547 QUEUE_Unlock( pActiveQueue );
2551 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2552 hwnd, x, y, x+cx, y+cy, flags);
2554 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2555 flags &= ~SWP_WINE_NOHOSTMOVE;
2558 /* ------------------------------------------------------------------------ CHECKS */
2560 /* Check window handle */
2562 if (hwnd == GetDesktopWindow()) return FALSE;
2563 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2565 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2566 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2568 /* Fix redundant flags */
2570 if(wndPtr->dwStyle & WS_VISIBLE)
2571 flags &= ~SWP_SHOWWINDOW;
2574 if (!(flags & SWP_SHOWWINDOW))
2575 flags |= SWP_NOREDRAW;
2576 flags &= ~SWP_HIDEWINDOW;
2579 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2581 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2582 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2583 flags |= SWP_NOSIZE; /* Already the right size */
2585 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2586 flags |= SWP_NOMOVE; /* Already the right position */
2588 if (hwnd == hwndActive)
2589 flags |= SWP_NOACTIVATE; /* Already active */
2590 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2592 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2594 flags &= ~SWP_NOZORDER;
2595 hwndInsertAfter = HWND_TOP;
2600 /* Check hwndInsertAfter */
2602 /* FIXME: TOPMOST not supported yet */
2603 if ((hwndInsertAfter == HWND_TOPMOST) ||
2604 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2606 /* hwndInsertAfter must be a sibling of the window */
2607 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2609 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2612 if( wnd->parent != wndPtr->parent )
2615 WIN_ReleaseWndPtr(wnd);
2618 /* don't need to change the Zorder of hwnd if it's already inserted
2619 * after hwndInsertAfter or when inserting hwnd after itself.
2621 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2623 WIN_ReleaseWndPtr(wnd);
2626 Pos: /* ------------------------------------------------------------------------ MAIN part */
2628 /* Fill the WINDOWPOS structure */
2631 winpos.hwndInsertAfter = hwndInsertAfter;
2636 winpos.flags = flags;
2638 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2640 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2642 if( wndPtr->parent == WIN_GetDesktop() )
2643 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2644 hwndInsertAfter, winpos.flags );
2645 WIN_ReleaseDesktop();
2648 if(!(wndPtr->flags & WIN_NATIVE) )
2650 if( hwndInsertAfter == HWND_TOP )
2651 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2653 if( hwndInsertAfter == HWND_BOTTOM )
2654 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2656 if( !(winpos.flags & SWP_NOZORDER) )
2657 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2658 winpos.flags |= SWP_NOZORDER;
2660 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2661 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2662 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2664 /* get a previous visible region for SWP_CopyValidBits() */
2665 DWORD dflags = DCX_WINDOW;
2667 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2668 dflags |= DCX_CLIPSIBLINGS;
2670 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2674 /* Common operations */
2676 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2678 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2680 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2681 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2684 /* Reset active DCEs */
2686 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2687 wndPtr->dwStyle & WS_VISIBLE) ||
2688 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2692 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2693 DCE_InvalidateDCE(wndPtr, &rect);
2696 oldWindowRect = wndPtr->rectWindow;
2697 oldClientRect = wndPtr->rectClient;
2699 /* Find out if we have to redraw the whole client rect */
2701 if( oldClientRect.bottom - oldClientRect.top ==
2702 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2704 if( oldClientRect.right - oldClientRect.left ==
2705 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2707 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2708 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2710 uFlags |= SWP_EX_NOCOPY;
2713 * Use this later in CopyValidBits()
2716 uFlags |= SWP_EX_NONCLIENT;
2719 /* FIXME: actually do something with WVR_VALIDRECTS */
2721 wndPtr->rectWindow = newWindowRect;
2722 wndPtr->rectClient = newClientRect;
2724 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2726 BOOL bCallDriver = TRUE;
2727 HWND tempInsertAfter = winpos.hwndInsertAfter;
2729 winpos.hwndInsertAfter = hwndInsertAfter;
2731 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2733 /* This is the only place where we need to force repainting of the contents
2734 of windows created by the host window system, all other cases go through the
2735 expose event handling */
2737 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2739 cx = newWindowRect.right - newWindowRect.left;
2740 cy = newWindowRect.bottom - newWindowRect.top;
2742 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2743 winpos.hwndInsertAfter = tempInsertAfter;
2744 bCallDriver = FALSE;
2746 if( winpos.flags & SWP_NOCLIENTMOVE )
2747 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2750 /* client area moved but window extents remained the same, copy valid bits */
2752 visRgn = CreateRectRgn( 0, 0, cx, cy );
2753 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2754 uFlags | SWP_EX_PAINTSELF );
2761 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2763 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2764 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2765 !(uFlags & SWP_EX_NOCOPY) )
2767 /* The origin of the client rect didn't move so we can try to repaint
2768 * only the nonclient area by setting bit gravity hint for the host window system.
2771 if( !(wndPtr->flags & WIN_MANAGED) )
2773 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2774 newWindowRect.bottom - newWindowRect.top);
2775 RECT rcn = newClientRect;
2776 RECT rco = oldClientRect;
2778 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2779 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2780 IntersectRect( &rcn, &rcn, &rco );
2781 visRgn = CreateRectRgnIndirect( &rcn );
2782 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2783 DeleteObject( hrgn );
2784 uFlags = SWP_EX_PAINTSELF;
2786 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2789 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2792 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2793 winpos.hwndInsertAfter = tempInsertAfter;
2796 if( winpos.flags & SWP_SHOWWINDOW )
2800 wndPtr->dwStyle |= WS_VISIBLE;
2802 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2804 /* focus was set to unmapped window, reset host focus
2805 * since the window is now visible */
2807 focus = curr = GetFocus();
2812 WND *pFocus = WIN_FindWndPtr( focus );
2814 pFocus->pDriver->pSetFocus(pFocus);
2815 WIN_ReleaseWndPtr(pFocus);
2818 curr = GetParent(curr);
2822 else /* -------------------------------------------- emulated window */
2824 if( winpos.flags & SWP_SHOWWINDOW )
2826 wndPtr->dwStyle |= WS_VISIBLE;
2827 uFlags |= SWP_EX_PAINTSELF;
2828 visRgn = 1; /* redraw the whole window */
2830 else if( !(winpos.flags & SWP_NOREDRAW) )
2832 if( winpos.flags & SWP_HIDEWINDOW )
2834 if( visRgn > 1 ) /* map to parent */
2835 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2841 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2842 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2843 &oldClientRect, uFlags);
2846 /* nothing moved, redraw frame if needed */
2848 if( winpos.flags & SWP_FRAMECHANGED )
2849 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2852 DeleteObject( visRgn );
2860 if( winpos.flags & SWP_HIDEWINDOW )
2862 wndPtr->dwStyle &= ~WS_VISIBLE;
2865 if (hwnd == CARET_GetHwnd())
2867 if( winpos.flags & SWP_HIDEWINDOW )
2869 else if (winpos.flags & SWP_SHOWWINDOW)
2873 /* ------------------------------------------------------------------------ FINAL */
2875 if (wndPtr->flags & WIN_NATIVE)
2876 EVENT_Synchronize(); /* Synchronize with the host window system */
2878 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2880 /* Simulate a mouse event to set the cursor */
2881 int iWndsLocks = WIN_SuspendWndsLock();
2883 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2884 PosX, PosY, GetTickCount(), 0 );
2886 WIN_RestoreWndsLock(iWndsLocks);
2889 wndTemp = WIN_GetDesktop();
2891 /* repaint invalidated region (if any)
2893 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2894 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2899 if( !(winpos.flags & SWP_NOREDRAW) )
2902 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2903 its parent and sibling and so on, and then erase the parent window
2904 back ground if the parent is either a top-level window or its parent's parent
2905 is top-level window. Rely on the system to repaint other affected
2906 windows later on. */
2907 if( uFlags & SWP_EX_PAINTSELF )
2909 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2910 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2911 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2915 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2916 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2920 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2922 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2923 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2927 DeleteObject( visRgn );
2930 WIN_ReleaseDesktop();
2932 if (!(flags & SWP_NOACTIVATE))
2933 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2935 /* And last, send the WM_WINDOWPOSCHANGED message */
2937 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2940 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2941 !(winpos.flags & SWP_NOSENDCHANGING)) )
2943 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2944 if (resync) EVENT_Synchronize();
2949 WIN_ReleaseWndPtr(wndPtr);
2954 /***********************************************************************
2955 * BeginDeferWindowPos16 (USER.259)
2957 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2959 return BeginDeferWindowPos( count );
2963 /***********************************************************************
2964 * BeginDeferWindowPos (USER32.9)
2966 HDWP WINAPI BeginDeferWindowPos( INT count )
2973 SetLastError(ERROR_INVALID_PARAMETER);
2976 /* Windows allows zero count, in which case it allocates context for 8 moves */
2977 if (count == 0) count = 8;
2979 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2980 if (!handle) return 0;
2981 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2982 pDWP->actualCount = 0;
2983 pDWP->suggestedCount = count;
2985 pDWP->wMagic = DWP_MAGIC;
2986 pDWP->hwndParent = 0;
2991 /***********************************************************************
2992 * DeferWindowPos16 (USER.260)
2994 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2995 INT16 x, INT16 y, INT16 cx, INT16 cy,
2998 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2999 x, y, cx, cy, flags );
3003 /***********************************************************************
3004 * DeferWindowPos (USER32.128)
3006 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3007 INT x, INT y, INT cx, INT cy,
3012 HDWP newhdwp = hdwp,retvalue;
3016 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3017 if (!pDWP) return 0;
3018 if (hwnd == GetDesktopWindow()) return 0;
3020 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3021 USER_HEAP_FREE( hdwp );
3025 /* Numega Bounds Checker Demo dislikes the following code.
3026 In fact, I've not been able to find any "same parent" requirement in any docu
3030 /* All the windows of a DeferWindowPos() must have the same parent */
3031 parent = pWnd->parent->hwndSelf;
3032 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3033 else if (parent != pDWP->hwndParent)
3035 USER_HEAP_FREE( hdwp );
3041 for (i = 0; i < pDWP->actualCount; i++)
3043 if (pDWP->winPos[i].hwnd == hwnd)
3045 /* Merge with the other changes */
3046 if (!(flags & SWP_NOZORDER))
3048 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3050 if (!(flags & SWP_NOMOVE))
3052 pDWP->winPos[i].x = x;
3053 pDWP->winPos[i].y = y;
3055 if (!(flags & SWP_NOSIZE))
3057 pDWP->winPos[i].cx = cx;
3058 pDWP->winPos[i].cy = cy;
3060 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3061 SWP_NOZORDER | SWP_NOREDRAW |
3062 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3064 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3070 if (pDWP->actualCount >= pDWP->suggestedCount)
3072 newhdwp = USER_HEAP_REALLOC( hdwp,
3073 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3079 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3080 pDWP->suggestedCount++;
3082 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3083 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3084 pDWP->winPos[pDWP->actualCount].x = x;
3085 pDWP->winPos[pDWP->actualCount].y = y;
3086 pDWP->winPos[pDWP->actualCount].cx = cx;
3087 pDWP->winPos[pDWP->actualCount].cy = cy;
3088 pDWP->winPos[pDWP->actualCount].flags = flags;
3089 pDWP->actualCount++;
3092 WIN_ReleaseWndPtr(pWnd);
3097 /***********************************************************************
3098 * EndDeferWindowPos16 (USER.261)
3100 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3102 return EndDeferWindowPos( hdwp );
3106 /***********************************************************************
3107 * EndDeferWindowPos (USER32.173)
3109 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3116 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3117 if (!pDWP) return FALSE;
3118 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3120 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3121 winpos->x, winpos->y, winpos->cx,
3122 winpos->cy, winpos->flags ))) break;
3124 USER_HEAP_FREE( hdwp );
3129 /***********************************************************************
3130 * TileChildWindows (USER.199)
3132 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3134 FIXME("(%04x, %d): stub\n", parent, action);
3137 /***********************************************************************
3138 * CascadeChildWindows (USER.198)
3140 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3142 FIXME("(%04x, %d): stub\n", parent, action);
3145 /***********************************************************************
3146 * SetProgmanWindow [USER32.522]
3148 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3150 hGlobalProgmanWindow = hwnd;
3151 return hGlobalProgmanWindow;
3154 /***********************************************************************
3155 * GetProgmanWindow [USER32.289]
3157 HRESULT WINAPI GetProgmanWindow ( )
3159 return hGlobalProgmanWindow;
3162 /***********************************************************************
3163 * SetShellWindowEx [USER32.531]
3164 * hwndProgman = Progman[Program Manager]
3165 * |-> SHELLDLL_DefView
3166 * hwndListView = | |-> SysListView32
3167 * | | |-> tooltips_class32
3173 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3175 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3176 hGlobalShellWindow = hwndProgman;
3177 return hGlobalShellWindow;
3181 /***********************************************************************
3182 * SetTaskmanWindow [USER32.537]
3184 * hwnd = MSTaskSwWClass
3185 * |-> SysTabControl32
3187 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3189 hGlobalTaskmanWindow = hwnd;
3190 return hGlobalTaskmanWindow;
3193 /***********************************************************************
3194 * GetTaskmanWindow [USER32.304]
3196 HRESULT WINAPI GetTaskmanWindow ( )
3198 return hGlobalTaskmanWindow;