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"
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( win, "\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(win, "\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 (win, "GetWindowRgn: doesn't really do regions\n");
279 memset (&rect, 0, sizeof(rect));
281 GetWindowRect ( hwnd, &rect );
283 FIXME (win, "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 (win, "SetWindowRgn: stub\n");
302 /***********************************************************************
305 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
309 FIXME (win, "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(win,"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(win,"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( win, "\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( win, "\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( win, "\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)
902 return GetActiveWindow();
906 /*******************************************************************
907 * SetForegroundWindow (USER32.482)
909 BOOL WINAPI SetForegroundWindow( HWND hwnd )
911 SetActiveWindow( hwnd );
916 /*******************************************************************
917 * GetShellWindow16 (USER.600)
919 HWND16 WINAPI GetShellWindow16(void)
921 return GetShellWindow();
924 /*******************************************************************
925 * SetShellWindow (USER32.504)
927 HWND WINAPI SetShellWindow(HWND hwndshell)
928 { WARN(win, "(hWnd=%08x) semi stub\n",hwndshell );
930 hGlobalShellWindow = hwndshell;
931 return hGlobalShellWindow;
935 /*******************************************************************
936 * GetShellWindow (USER32.287)
938 HWND WINAPI GetShellWindow(void)
939 { WARN(win, "(hWnd=%x) semi stub\n",hGlobalShellWindow );
941 return hGlobalShellWindow;
945 /***********************************************************************
946 * BringWindowToTop16 (USER.45)
948 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
950 return BringWindowToTop(hwnd);
954 /***********************************************************************
955 * BringWindowToTop (USER32.11)
957 BOOL WINAPI BringWindowToTop( HWND hwnd )
959 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
963 /***********************************************************************
964 * MoveWindow16 (USER.56)
966 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
969 return MoveWindow(hwnd,x,y,cx,cy,repaint);
973 /***********************************************************************
974 * MoveWindow (USER32.399)
976 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
979 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
980 if (!repaint) flags |= SWP_NOREDRAW;
981 TRACE(win, "%04x %d,%d %dx%d %d\n",
982 hwnd, x, y, cx, cy, repaint );
983 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
986 /***********************************************************************
987 * WINPOS_InitInternalPos
989 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
992 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
996 /* this happens when the window is minimized/maximized
997 * for the first time (rectWindow is not adjusted yet) */
999 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1000 if( !lpPos ) return NULL;
1002 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1003 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1004 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1005 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1008 if( wnd->dwStyle & WS_MINIMIZE )
1009 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1010 else if( wnd->dwStyle & WS_MAXIMIZE )
1011 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1012 else if( restoreRect )
1013 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1018 /***********************************************************************
1019 * WINPOS_RedrawIconTitle
1021 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1023 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1026 if( lpPos->hwndIconTitle )
1028 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1029 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1036 /***********************************************************************
1037 * WINPOS_ShowIconTitle
1039 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1041 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1043 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1045 HWND16 hWnd = lpPos->hwndIconTitle;
1047 TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1050 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1053 pWnd = WIN_FindWndPtr(hWnd);
1055 if( !(pWnd->dwStyle & WS_VISIBLE) )
1057 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1058 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1059 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1061 WIN_ReleaseWndPtr(pWnd);
1063 else ShowWindow( hWnd, SW_HIDE );
1068 /*******************************************************************
1069 * WINPOS_GetMinMaxInfo
1071 * Get the minimized and maximized information for a window.
1073 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1074 POINT *minTrack, POINT *maxTrack )
1076 LPINTERNALPOS lpPos;
1080 /* Compute default values */
1082 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1083 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1084 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1085 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1086 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1087 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1089 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1090 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1092 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1093 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1098 if (HAS_THICKFRAME(wndPtr->dwStyle))
1100 xinc += GetSystemMetrics(SM_CXFRAME);
1101 yinc += GetSystemMetrics(SM_CYFRAME);
1103 if (wndPtr->dwStyle & WS_BORDER)
1105 xinc += GetSystemMetrics(SM_CXBORDER);
1106 yinc += GetSystemMetrics(SM_CYBORDER);
1109 MinMax.ptMaxSize.x += 2 * xinc;
1110 MinMax.ptMaxSize.y += 2 * yinc;
1112 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1113 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1114 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1117 MinMax.ptMaxPosition.x = -xinc;
1118 MinMax.ptMaxPosition.y = -yinc;
1121 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1123 /* Some sanity checks */
1125 TRACE(win,"%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1126 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1127 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1128 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1129 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1130 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1131 MinMax.ptMinTrackSize.x );
1132 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1133 MinMax.ptMinTrackSize.y );
1135 if (maxSize) *maxSize = MinMax.ptMaxSize;
1136 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1137 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1138 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1141 /***********************************************************************
1142 * WINPOS_MinMaximize
1144 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1145 * This function assumes that 'cmd' is different from the current window
1148 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1152 LPINTERNALPOS lpPos;
1154 TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
1156 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1157 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1159 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1161 if( wndPtr->dwStyle & WS_MINIMIZE )
1163 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1164 return (SWP_NOSIZE | SWP_NOMOVE);
1165 swpFlags |= SWP_NOCOPYBITS;
1170 if( wndPtr->dwStyle & WS_MAXIMIZE)
1172 wndPtr->flags |= WIN_RESTORE_MAX;
1173 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1176 wndPtr->flags &= ~WIN_RESTORE_MAX;
1177 wndPtr->dwStyle |= WS_MINIMIZE;
1179 if( wndPtr->flags & WIN_NATIVE )
1180 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1181 swpFlags |= MINMAX_NOSWP;
1183 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1185 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1186 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1187 swpFlags |= SWP_NOCOPYBITS;
1191 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1192 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1193 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1195 if( wndPtr->dwStyle & WS_MINIMIZE )
1197 if( wndPtr->flags & WIN_NATIVE )
1198 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1199 swpFlags |= MINMAX_NOSWP;
1201 WINPOS_ShowIconTitle( wndPtr, FALSE );
1202 wndPtr->dwStyle &= ~WS_MINIMIZE;
1204 wndPtr->dwStyle |= WS_MAXIMIZE;
1206 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1211 if( wndPtr->dwStyle & WS_MINIMIZE )
1213 if( wndPtr->flags & WIN_NATIVE )
1214 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1215 swpFlags |= MINMAX_NOSWP;
1217 wndPtr->dwStyle &= ~WS_MINIMIZE;
1218 WINPOS_ShowIconTitle( wndPtr, FALSE );
1220 if( wndPtr->flags & WIN_RESTORE_MAX)
1222 /* Restore to maximized position */
1223 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1224 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1225 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1226 wndPtr->dwStyle |= WS_MAXIMIZE;
1227 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1232 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1233 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1235 /* Restore to normal position */
1237 *lpRect = lpPos->rectNormal;
1238 lpRect->right -= lpRect->left;
1239 lpRect->bottom -= lpRect->top;
1243 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1247 /***********************************************************************
1248 * ShowWindowAsync (USER32.535)
1250 * doesn't wait; returns immediately.
1251 * used by threads to toggle windows in other (possibly hanging) threads
1253 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1255 /* FIXME: does ShowWindow() return immediately ? */
1256 return ShowWindow(hwnd, cmd);
1260 /***********************************************************************
1261 * ShowWindow16 (USER.42)
1263 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1265 return ShowWindow(hwnd,cmd);
1269 /***********************************************************************
1270 * ShowWindow (USER32.534)
1272 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1274 WND* wndPtr = WIN_FindWndPtr( hwnd );
1275 BOOL wasVisible, showFlag;
1276 RECT16 newPos = {0, 0, 0, 0};
1279 if (!wndPtr) return FALSE;
1281 TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1283 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1288 if (!wasVisible) goto END;;
1289 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1290 SWP_NOACTIVATE | SWP_NOZORDER;
1291 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
1293 /* Revert focus to parent */
1294 SetFocus( GetParent(hwnd) );
1298 case SW_SHOWMINNOACTIVE:
1299 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1301 case SW_SHOWMINIMIZED:
1302 swp |= SWP_SHOWWINDOW;
1305 swp |= SWP_FRAMECHANGED;
1306 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1307 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1308 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1311 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1312 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1313 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1314 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1315 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1319 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1322 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1325 case SW_SHOWNOACTIVATE:
1326 swp |= SWP_NOZORDER;
1327 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1329 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1330 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1332 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1334 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1335 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1336 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1340 showFlag = (cmd != SW_HIDE);
1341 if (showFlag != wasVisible)
1343 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1344 if (!IsWindow( hwnd )) goto END;
1347 if ((wndPtr->dwStyle & WS_CHILD) &&
1348 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1349 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1351 /* Don't call SetWindowPos() on invisible child windows */
1352 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1353 else wndPtr->dwStyle |= WS_VISIBLE;
1357 /* We can't activate a child window */
1358 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1359 if (!(swp & MINMAX_NOSWP))
1360 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1361 newPos.right, newPos.bottom, LOWORD(swp) );
1362 if (!IsWindow( hwnd )) goto END;
1363 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1366 if (wndPtr->flags & WIN_NEED_SIZE)
1368 /* should happen only in CreateWindowEx() */
1369 int wParam = SIZE_RESTORED;
1371 wndPtr->flags &= ~WIN_NEED_SIZE;
1372 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1373 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1374 SendMessageA( hwnd, WM_SIZE, wParam,
1375 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1376 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1377 SendMessageA( hwnd, WM_MOVE, 0,
1378 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1382 WIN_ReleaseWndPtr(wndPtr);
1387 /***********************************************************************
1388 * GetInternalWindowPos16 (USER.460)
1390 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1393 WINDOWPLACEMENT16 wndpl;
1394 if (GetWindowPlacement16( hwnd, &wndpl ))
1396 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1397 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1398 return wndpl.showCmd;
1404 /***********************************************************************
1405 * GetInternalWindowPos (USER32.245)
1407 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1410 WINDOWPLACEMENT wndpl;
1411 if (GetWindowPlacement( hwnd, &wndpl ))
1413 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1414 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1415 return wndpl.showCmd;
1420 /***********************************************************************
1421 * GetWindowPlacement16 (USER.370)
1423 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1425 WND *pWnd = WIN_FindWndPtr( hwnd );
1426 LPINTERNALPOS lpPos;
1428 if(!pWnd ) return FALSE;
1430 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1431 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1432 wndpl->length = sizeof(*wndpl);
1433 if( pWnd->dwStyle & WS_MINIMIZE )
1434 wndpl->showCmd = SW_SHOWMINIMIZED;
1436 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1437 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1438 if( pWnd->flags & WIN_RESTORE_MAX )
1439 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1442 wndpl->ptMinPosition = lpPos->ptIconPos;
1443 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1444 wndpl->rcNormalPosition = lpPos->rectNormal;
1446 WIN_ReleaseWndPtr(pWnd);
1451 /***********************************************************************
1452 * GetWindowPlacement (USER32.307)
1455 * Fails if wndpl->length of Win95 (!) apps is invalid.
1457 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1461 WINDOWPLACEMENT16 wpl;
1462 wpl.length = sizeof(wpl);
1463 if( GetWindowPlacement16( hwnd, &wpl ) )
1465 pwpl32->length = sizeof(*pwpl32);
1466 pwpl32->flags = wpl.flags;
1467 pwpl32->showCmd = wpl.showCmd;
1468 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1469 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1470 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1478 /***********************************************************************
1479 * WINPOS_SetPlacement
1481 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1484 WND *pWnd = WIN_FindWndPtr( hwnd );
1487 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1488 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1490 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1491 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1492 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1494 if( pWnd->dwStyle & WS_MINIMIZE )
1496 WINPOS_ShowIconTitle( pWnd, FALSE );
1497 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1498 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1499 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1501 else if( pWnd->dwStyle & WS_MAXIMIZE )
1503 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1504 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1505 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1507 else if( flags & PLACE_RECT )
1508 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1509 lpPos->rectNormal.right - lpPos->rectNormal.left,
1510 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1511 SWP_NOZORDER | SWP_NOACTIVATE );
1513 ShowWindow( hwnd, wndpl->showCmd );
1514 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1516 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1518 /* SDK: ...valid only the next time... */
1519 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1521 WIN_ReleaseWndPtr(pWnd);
1528 /***********************************************************************
1529 * SetWindowPlacement16 (USER.371)
1531 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1533 return WINPOS_SetPlacement( hwnd, wndpl,
1534 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1537 /***********************************************************************
1538 * SetWindowPlacement (USER32.519)
1541 * Fails if wndpl->length of Win95 (!) apps is invalid.
1543 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1547 WINDOWPLACEMENT16 wpl;
1549 wpl.length = sizeof(WINDOWPLACEMENT16);
1550 wpl.flags = pwpl32->flags;
1551 wpl.showCmd = pwpl32->showCmd;
1552 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1553 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1554 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1555 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1556 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1557 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1558 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1559 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1561 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1567 /***********************************************************************
1568 * SetInternalWindowPos16 (USER.461)
1570 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1571 LPRECT16 rect, LPPOINT16 pt )
1573 if( IsWindow16(hwnd) )
1575 WINDOWPLACEMENT16 wndpl;
1578 wndpl.length = sizeof(wndpl);
1579 wndpl.showCmd = showCmd;
1580 wndpl.flags = flags = 0;
1585 wndpl.flags |= WPF_SETMINPOSITION;
1586 wndpl.ptMinPosition = *pt;
1590 flags |= PLACE_RECT;
1591 wndpl.rcNormalPosition = *rect;
1593 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1598 /***********************************************************************
1599 * SetInternalWindowPos (USER32.483)
1601 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1602 LPRECT rect, LPPOINT pt )
1604 if( IsWindow(hwnd) )
1606 WINDOWPLACEMENT16 wndpl;
1609 wndpl.length = sizeof(wndpl);
1610 wndpl.showCmd = showCmd;
1611 wndpl.flags = flags = 0;
1616 wndpl.flags |= WPF_SETMINPOSITION;
1617 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1621 flags |= PLACE_RECT;
1622 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1624 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1628 /*******************************************************************
1629 * WINPOS_SetActiveWindow
1631 * SetActiveWindow() back-end. This is the only function that
1632 * can assign active status to a window. It must be called only
1633 * for the top level windows.
1635 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1637 CBTACTIVATESTRUCT16* cbtStruct;
1638 WND* wndPtr=0, *wndTemp;
1639 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1640 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1642 HWND hwndActive = 0;
1645 /* Get current active window from the active queue */
1648 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1649 if ( pOldActiveQueue )
1650 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1653 /* paranoid checks */
1654 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1657 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1660 wndPtr = WIN_FindWndPtr(hWnd);
1661 hOldActiveQueue = hActiveQueue;
1663 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1665 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1666 WIN_ReleaseWndPtr(wndTemp);
1669 TRACE(win,"no current active window.\n");
1671 /* call CBT hook chain */
1672 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1674 cbtStruct->fMouse = fMouse;
1675 cbtStruct->hWndActive = hwndActive;
1676 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1677 (LPARAM)SEGPTR_GET(cbtStruct) );
1678 SEGPTR_FREE(cbtStruct);
1679 if (bRet) goto CLEANUP_END;
1682 /* set prev active wnd to current active wnd and send notification */
1683 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1685 MESSAGEQUEUE *pTempActiveQueue = 0;
1687 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1689 if (GetSysModalWindow16() != hWnd)
1691 /* disregard refusal if hWnd is sysmodal */
1694 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1695 MAKEWPARAM( WA_INACTIVE, wIconized ),
1698 /* check if something happened during message processing
1699 * (global active queue may have changed)
1701 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1702 if(!pTempActiveQueue)
1705 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1706 QUEUE_Unlock( pTempActiveQueue );
1707 if( hwndPrevActive != hwndActive )
1711 /* Set new active window in the message queue */
1715 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1716 if ( pNewActiveQueue )
1717 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1719 else /* have to do this or MDI frame activation goes to hell */
1720 if( pOldActiveQueue )
1721 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1723 /* send palette messages */
1724 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1725 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1727 /* if prev wnd is minimized redraw icon title */
1728 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1730 /* managed windows will get ConfigureNotify event */
1731 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1733 /* check Z-order and bring hWnd to the top */
1734 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1736 if (wndTemp->dwStyle & WS_VISIBLE) break;
1738 WIN_ReleaseDesktop();
1739 WIN_ReleaseWndPtr(wndTemp);
1741 if( wndTemp != wndPtr )
1742 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1743 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1744 if (!IsWindow(hWnd))
1748 /* Get a handle to the new active queue */
1749 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1751 /* send WM_ACTIVATEAPP if necessary */
1752 if (hOldActiveQueue != hNewActiveQueue)
1754 WND **list, **ppWnd;
1755 WND *pDesktop = WIN_GetDesktop();
1757 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1759 for (ppWnd = list; *ppWnd; ppWnd++)
1761 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1763 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1764 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1765 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1767 WIN_ReleaseWinArray(list);
1770 hActiveQueue = hNewActiveQueue;
1772 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1774 for (ppWnd = list; *ppWnd; ppWnd++)
1776 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1778 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1779 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1780 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1782 WIN_ReleaseWinArray(list);
1784 WIN_ReleaseDesktop();
1786 if (!IsWindow(hWnd)) goto CLEANUP;
1791 /* walk up to the first unowned window */
1792 wndTemp = WIN_LockWndPtr(wndPtr);
1793 while (wndTemp->owner)
1795 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1797 /* and set last active owned popup */
1798 wndTemp->hwndLastActive = hWnd;
1800 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1801 WIN_ReleaseWndPtr(wndTemp);
1802 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1803 SendMessageA( hWnd, WM_ACTIVATE,
1804 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1805 (LPARAM)hwndPrevActive );
1806 if( !IsWindow(hWnd) ) goto CLEANUP;
1809 /* change focus if possible */
1810 if( fChangeFocus && GetFocus() )
1811 if( WIN_GetTopParent(GetFocus()) != hwndActive )
1812 FOCUS_SwitchFocus( pNewActiveQueue, GetFocus(),
1813 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1818 if( !hwndPrevActive && wndPtr )
1819 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1821 /* if active wnd is minimized redraw icon title */
1822 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1824 bRet = (hWnd == hwndActive); /* Success? */
1826 CLEANUP: /* Unlock the message queues before returning */
1828 if ( pNewActiveQueue )
1829 QUEUE_Unlock( pNewActiveQueue );
1833 if ( pOldActiveQueue )
1834 QUEUE_Unlock( pOldActiveQueue );
1836 WIN_ReleaseWndPtr(wndPtr);
1840 /*******************************************************************
1841 * WINPOS_ActivateOtherWindow
1843 * Activates window other than pWnd.
1845 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1849 HWND hwndActive = 0;
1851 /* Get current active window from the active queue */
1854 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1857 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1858 QUEUE_Unlock( pActiveQueue );
1862 if( pWnd->hwndSelf == hwndPrevActive )
1865 if( hwndActive != pWnd->hwndSelf &&
1866 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1869 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1870 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1872 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1874 WIN_ReleaseWndPtr(pWndTo);
1875 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1877 while( !WINPOS_CanActivate(pWndTo) )
1879 /* by now owned windows should've been taken care of */
1880 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1881 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1882 if( !pWndTo ) break;
1884 WIN_ReleaseWndPtr(pWndPtr);
1887 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1889 /* switch desktop queue to current active */
1892 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1893 WIN_ReleaseWndPtr(pWndTo);
1894 WIN_ReleaseDesktop();
1901 /*******************************************************************
1902 * WINPOS_ChangeActiveWindow
1905 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1907 WND *wndPtr, *wndTemp;
1909 HWND hwndActive = 0;
1911 /* Get current active window from the active queue */
1914 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1917 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1918 QUEUE_Unlock( pActiveQueue );
1923 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1925 wndPtr = WIN_FindWndPtr(hWnd);
1926 if( !wndPtr ) return FALSE;
1928 /* child windows get WM_CHILDACTIVATE message */
1929 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1931 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1935 if( hWnd == hwndActive )
1941 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1947 /* switch desktop queue to current active */
1948 wndTemp = WIN_GetDesktop();
1949 if( wndPtr->parent == wndTemp)
1950 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1951 WIN_ReleaseDesktop();
1955 WIN_ReleaseWndPtr(wndPtr);
1960 /***********************************************************************
1961 * WINPOS_SendNCCalcSize
1963 * Send a WM_NCCALCSIZE message to a window.
1964 * All parameters are read-only except newClientRect.
1965 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1966 * when calcValidRect is TRUE.
1968 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1969 RECT *newWindowRect, RECT *oldWindowRect,
1970 RECT *oldClientRect, WINDOWPOS *winpos,
1971 RECT *newClientRect )
1973 NCCALCSIZE_PARAMS params;
1974 WINDOWPOS winposCopy;
1977 params.rgrc[0] = *newWindowRect;
1980 winposCopy = *winpos;
1981 params.rgrc[1] = *oldWindowRect;
1982 params.rgrc[2] = *oldClientRect;
1983 params.lppos = &winposCopy;
1985 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
1987 TRACE(win, "%d,%d-%d,%d\n",
1988 params.rgrc[0].left, params.rgrc[0].top,
1989 params.rgrc[0].right, params.rgrc[0].bottom );
1990 *newClientRect = params.rgrc[0];
1995 /***********************************************************************
1996 * WINPOS_HandleWindowPosChanging16
1998 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2000 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2002 POINT maxSize, minTrack;
2003 if (winpos->flags & SWP_NOSIZE) return 0;
2004 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2005 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2007 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2008 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2009 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2010 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2012 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2013 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2020 /***********************************************************************
2021 * WINPOS_HandleWindowPosChanging
2023 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2025 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2028 if (winpos->flags & SWP_NOSIZE) return 0;
2029 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2030 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2032 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2033 winpos->cx = MIN( winpos->cx, maxSize.x );
2034 winpos->cy = MIN( winpos->cy, maxSize.y );
2039 /***********************************************************************
2042 * fix Z order taking into account owned popups -
2043 * basically we need to maintain them above the window that owns them
2045 * FIXME: hide/show owned popups when owner visibility changes.
2047 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2049 WND* w = WIN_LockWndPtr(pDesktop->child);
2051 WARN(win, "(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2053 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2055 /* make sure this popup stays above the owner */
2057 HWND hwndLocalPrev = HWND_TOP;
2059 if( hwndInsertAfter != HWND_TOP )
2061 while( w != wndPtr->owner )
2063 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2064 if( hwndLocalPrev == hwndInsertAfter ) break;
2065 WIN_UpdateWndPtr(&w,w->next);
2067 hwndInsertAfter = hwndLocalPrev;
2070 else if( wndPtr->dwStyle & WS_CHILD )
2073 WIN_UpdateWndPtr(&w, pDesktop->child);
2077 if( w == wndPtr ) break;
2079 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2081 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2082 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2083 hwndInsertAfter = w->hwndSelf;
2085 WIN_UpdateWndPtr(&w, w->next);
2089 WIN_ReleaseWndPtr(w);
2090 return hwndInsertAfter;
2093 /***********************************************************************
2096 * Make window look nice without excessive repainting
2098 * visible and update regions are in window coordinates
2099 * client and window rectangles are in parent client coordinates
2101 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2102 * window rects have the same origin.
2104 * Returns: uFlags and a dirty region in *pVisRgn.
2106 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2107 LPRECT lpOldWndRect,
2108 LPRECT lpOldClientRect, UINT uFlags )
2111 HRGN newVisRgn, dirtyRgn;
2112 INT my = COMPLEXREGION;
2114 TRACE(win,"\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2115 Wnd->rectWindow.left, Wnd->rectWindow.top,
2116 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2117 lpOldWndRect->left, lpOldWndRect->top,
2118 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2119 TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2120 Wnd->rectClient.left, Wnd->rectClient.top,
2121 Wnd->rectClient.right, Wnd->rectClient.bottom,
2122 lpOldClientRect->left, lpOldClientRect->top,
2123 lpOldClientRect->right,lpOldClientRect->bottom );
2125 if( Wnd->hrgnUpdate == 1 )
2126 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2128 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2129 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2131 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2132 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2134 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2138 TRACE(win,"\twon't copy anything!\n");
2140 /* set dirtyRgn to the sum of old and new visible regions
2141 * in parent client coordinates */
2143 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2144 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2146 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2148 else /* copy valid bits to a new location */
2150 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2151 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2153 /* subtract already invalid region inside Wnd from the dst region */
2155 if( Wnd->hrgnUpdate )
2156 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2159 /* check if entire window can be copied */
2161 ow = lpOldWndRect->right - lpOldWndRect->left;
2162 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2163 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2164 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2166 ocw = lpOldClientRect->right - lpOldClientRect->left;
2167 och = lpOldClientRect->bottom - lpOldClientRect->top;
2168 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2169 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2171 if( (ocw != ncw) || (och != nch) ||
2172 ( ow != nw) || ( oh != nh) ||
2173 ((lpOldClientRect->top - lpOldWndRect->top) !=
2174 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2175 ((lpOldClientRect->left - lpOldWndRect->left) !=
2176 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2178 dx = Wnd->rectClient.left - lpOldClientRect->left;
2179 dy = Wnd->rectClient.top - lpOldClientRect->top;
2181 /* restrict valid bits to the common client rect */
2183 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2184 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2185 r.right = r.left + MIN( ocw, ncw );
2186 r.bottom = r.top + MIN( och, nch );
2188 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2189 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2190 GetRgnBox( hrgnValid, &r );
2191 if( IsRectEmpty( &r ) )
2193 r = *lpOldClientRect;
2197 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2198 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2199 if( !(uFlags & SWP_EX_PAINTSELF) )
2200 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2204 if( !(uFlags & SWP_EX_PAINTSELF) )
2206 /* Move remaining regions to parent coordinates */
2207 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2208 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2211 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2213 TRACE(win,"\tcomputing dirty region!\n");
2215 /* Compute combined dirty region (old + new - valid) */
2216 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2217 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2219 /* Blt valid bits, r is the rect to copy */
2227 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2228 from copying clipped areas */
2230 if( uFlags & SWP_EX_PAINTSELF )
2232 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2233 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2234 rClip.right = nw; rClip.bottom = nh;
2238 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2239 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2240 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2241 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2243 rClip.left = rClip.top = 0;
2245 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2247 if( oh > nh ) r.bottom = r.top + nh;
2248 if( ow < nw ) r.right = r.left + nw;
2250 if( IntersectRect( &r, &r, &rClip ) )
2251 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2253 GDI_HEAP_UNLOCK( hDC );
2255 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2256 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2260 /* *pVisRgn now points to the invalidated region */
2262 DeleteObject(newVisRgn);
2263 DeleteObject(dirtyRgn);
2267 /***********************************************************************
2268 * SWP_DoSimpleFrameChanged
2270 * NOTE: old and new client rect origins are identical, only
2271 * extents may have changed. Window extents are the same.
2273 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2279 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2281 /* Client rect changed its position/size, most likely a scrollar
2282 * was added/removed.
2284 * FIXME: WVR alignment flags
2287 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2291 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2292 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2293 if(!(uFlags & SWP_EX_NOCOPY))
2294 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2302 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2305 hrgn = CreateRectRgnIndirect( &rect );
2307 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2308 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2309 if(!(uFlags & SWP_EX_NOCOPY))
2310 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2314 REGION_UnionRectWithRgn( hrgn, &rect );
2317 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2319 rect = wndPtr->rectWindow;
2320 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2321 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2329 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2330 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2334 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2338 DeleteObject( hrgn );
2341 /***********************************************************************
2342 * SWP_DoWinPosChanging
2344 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2345 RECT* pNewWindowRect, RECT* pNewClientRect )
2347 /* Send WM_WINDOWPOSCHANGING message */
2349 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2350 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2352 /* Calculate new position and size */
2354 *pNewWindowRect = wndPtr->rectWindow;
2355 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2356 : wndPtr->rectClient;
2358 if (!(pWinpos->flags & SWP_NOSIZE))
2360 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2361 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2363 if (!(pWinpos->flags & SWP_NOMOVE))
2365 pNewWindowRect->left = pWinpos->x;
2366 pNewWindowRect->top = pWinpos->y;
2367 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2368 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2370 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2371 pWinpos->y - wndPtr->rectWindow.top );
2374 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2378 /***********************************************************************
2381 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2382 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2386 /* Send WM_NCCALCSIZE message to get new client area */
2387 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2389 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2390 &wndPtr->rectWindow, &wndPtr->rectClient,
2391 pWinpos, pNewClientRect );
2393 /* FIXME: WVR_ALIGNxxx */
2395 if( pNewClientRect->left != wndPtr->rectClient.left ||
2396 pNewClientRect->top != wndPtr->rectClient.top )
2397 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2399 if( (pNewClientRect->right - pNewClientRect->left !=
2400 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2401 (pNewClientRect->bottom - pNewClientRect->top !=
2402 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2403 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2406 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2407 pNewClientRect->top != wndPtr->rectClient.top) )
2408 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2412 /***********************************************************************
2413 * SetWindowPos (USER.2)
2415 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2416 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2418 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2421 /***********************************************************************
2422 * SetWindowPos (USER32.520)
2424 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2425 INT x, INT y, INT cx, INT cy, WORD flags)
2428 WND * wndPtr,*wndTemp;
2429 RECT newWindowRect, newClientRect;
2430 RECT oldWindowRect, oldClientRect;
2432 UINT wvrFlags = 0, uFlags = 0;
2433 BOOL retvalue, resync = FALSE;
2434 HWND hwndActive = 0;
2436 /* Get current active window from the active queue */
2439 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2442 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2443 QUEUE_Unlock( pActiveQueue );
2447 TRACE(win,"hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2448 hwnd, x, y, x+cx, y+cy, flags);
2450 /* ------------------------------------------------------------------------ CHECKS */
2452 /* Check window handle */
2454 if (hwnd == GetDesktopWindow()) return FALSE;
2455 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2457 TRACE(win,"\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2458 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2460 /* Fix redundant flags */
2462 if(wndPtr->dwStyle & WS_VISIBLE)
2463 flags &= ~SWP_SHOWWINDOW;
2466 if (!(flags & SWP_SHOWWINDOW))
2467 flags |= SWP_NOREDRAW;
2468 flags &= ~SWP_HIDEWINDOW;
2471 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2473 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2474 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2475 flags |= SWP_NOSIZE; /* Already the right size */
2477 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2478 flags |= SWP_NOMOVE; /* Already the right position */
2480 if (hwnd == hwndActive)
2481 flags |= SWP_NOACTIVATE; /* Already active */
2482 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2484 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2486 flags &= ~SWP_NOZORDER;
2487 hwndInsertAfter = HWND_TOP;
2492 /* Check hwndInsertAfter */
2494 /* FIXME: TOPMOST not supported yet */
2495 if ((hwndInsertAfter == HWND_TOPMOST) ||
2496 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2498 /* hwndInsertAfter must be a sibling of the window */
2499 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2501 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2504 if( wnd->parent != wndPtr->parent )
2507 WIN_ReleaseWndPtr(wnd);
2510 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2512 WIN_ReleaseWndPtr(wnd);
2515 Pos: /* ------------------------------------------------------------------------ MAIN part */
2517 /* Fill the WINDOWPOS structure */
2520 winpos.hwndInsertAfter = hwndInsertAfter;
2525 winpos.flags = flags;
2527 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2529 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2531 if( wndPtr->parent == WIN_GetDesktop() )
2532 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2533 hwndInsertAfter, winpos.flags );
2534 WIN_ReleaseDesktop();
2537 if(!(wndPtr->flags & WIN_NATIVE) )
2539 if( hwndInsertAfter == HWND_TOP )
2540 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2542 if( hwndInsertAfter == HWND_BOTTOM )
2543 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2545 if( !(winpos.flags & SWP_NOZORDER) )
2546 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2547 winpos.flags |= SWP_NOZORDER;
2549 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2550 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2551 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2553 /* get a previous visible region for SWP_CopyValidBits() */
2555 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2559 /* Common operations */
2561 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2563 if(!(winpos.flags & SWP_NOZORDER))
2565 WIN_UnlinkWindow( winpos.hwnd );
2566 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2569 /* Reset active DCEs */
2571 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2572 wndPtr->dwStyle & WS_VISIBLE) ||
2573 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2577 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2578 DCE_InvalidateDCE(wndPtr, &rect);
2581 oldWindowRect = wndPtr->rectWindow;
2582 oldClientRect = wndPtr->rectClient;
2584 /* Find out if we have to redraw the whole client rect */
2586 if( oldClientRect.bottom - oldClientRect.top ==
2587 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2589 if( oldClientRect.right - oldClientRect.left ==
2590 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2592 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2593 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2595 uFlags |= SWP_EX_NOCOPY;
2598 * Use this later in CopyValidBits()
2601 uFlags |= SWP_EX_NONCLIENT;
2604 /* FIXME: actually do something with WVR_VALIDRECTS */
2606 wndPtr->rectWindow = newWindowRect;
2607 wndPtr->rectClient = newClientRect;
2609 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2611 BOOL bCallDriver = TRUE;
2612 HWND tempInsertAfter = winpos.hwndInsertAfter;
2614 winpos.hwndInsertAfter = hwndInsertAfter;
2616 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2618 /* This is the only place where we need to force repainting of the contents
2619 of windows created by the host window system, all other cases go through the
2620 expose event handling */
2622 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2624 cx = newWindowRect.right - newWindowRect.left;
2625 cy = newWindowRect.bottom - newWindowRect.top;
2627 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2628 winpos.hwndInsertAfter = tempInsertAfter;
2629 bCallDriver = FALSE;
2631 if( winpos.flags & SWP_NOCLIENTMOVE )
2632 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2635 /* client area moved but window extents remained the same, copy valid bits */
2637 visRgn = CreateRectRgn( 0, 0, cx, cy );
2638 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2639 uFlags | SWP_EX_PAINTSELF );
2646 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2648 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2649 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2650 !(uFlags & SWP_EX_NOCOPY) )
2652 /* The origin of the client rect didn't move so we can try to repaint
2653 * only the nonclient area by setting bit gravity hint for the host window system.
2656 if( !(wndPtr->flags & WIN_MANAGED) )
2658 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2659 newWindowRect.bottom - newWindowRect.top);
2660 RECT rcn = newClientRect;
2661 RECT rco = oldClientRect;
2663 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2664 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2665 IntersectRect( &rcn, &rcn, &rco );
2666 visRgn = CreateRectRgnIndirect( &rcn );
2667 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2668 DeleteObject( hrgn );
2669 uFlags = SWP_EX_PAINTSELF;
2671 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2674 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2677 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2678 winpos.hwndInsertAfter = tempInsertAfter;
2681 if( winpos.flags & SWP_SHOWWINDOW )
2685 wndPtr->dwStyle |= WS_VISIBLE;
2687 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2689 /* focus was set to unmapped window, reset host focus
2690 * since the window is now visible */
2692 focus = curr = GetFocus();
2697 WND *pFocus = WIN_FindWndPtr( focus );
2699 pFocus->pDriver->pSetFocus(pFocus);
2700 WIN_ReleaseWndPtr(pFocus);
2703 curr = GetParent(curr);
2707 else /* -------------------------------------------- emulated window */
2709 if( winpos.flags & SWP_SHOWWINDOW )
2711 wndPtr->dwStyle |= WS_VISIBLE;
2712 uFlags |= SWP_EX_PAINTSELF;
2713 visRgn = 1; /* redraw the whole window */
2715 else if( !(winpos.flags & SWP_NOREDRAW) )
2717 if( winpos.flags & SWP_HIDEWINDOW )
2719 if( visRgn > 1 ) /* map to parent */
2720 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2726 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2727 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2728 &oldClientRect, uFlags);
2731 /* nothing moved, redraw frame if needed */
2733 if( winpos.flags & SWP_FRAMECHANGED )
2734 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2737 DeleteObject( visRgn );
2745 if( winpos.flags & SWP_HIDEWINDOW )
2747 wndPtr->dwStyle &= ~WS_VISIBLE;
2749 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2751 /* FIXME: This will cause the window to be activated irrespective
2752 * of whether it is owned by the same thread. Has to be done
2756 if (winpos.hwnd == hwndActive)
2757 WINPOS_ActivateOtherWindow( wndPtr );
2760 /* ------------------------------------------------------------------------ FINAL */
2762 if (wndPtr->flags & WIN_NATIVE)
2763 EVENT_Synchronize( TRUE ); /* Synchronize with the host window system */
2765 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2766 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2768 wndTemp = WIN_GetDesktop();
2770 /* repaint invalidated region (if any)
2772 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2773 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2778 if( !(winpos.flags & SWP_NOREDRAW) )
2780 if( uFlags & SWP_EX_PAINTSELF )
2782 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE | RDW_FRAME |
2783 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2784 RDW_ALLCHILDREN, RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2788 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE |
2789 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2790 RDW_ALLCHILDREN, RDW_EX_USEHRGN );
2794 DeleteObject( visRgn );
2797 WIN_ReleaseDesktop();
2799 if (!(flags & SWP_NOACTIVATE))
2800 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2802 /* And last, send the WM_WINDOWPOSCHANGED message */
2804 TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2807 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2808 !(winpos.flags & SWP_NOSENDCHANGING)) )
2810 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2811 if (resync) EVENT_Synchronize ( TRUE );
2816 WIN_ReleaseWndPtr(wndPtr);
2821 /***********************************************************************
2822 * BeginDeferWindowPos16 (USER.259)
2824 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2826 return BeginDeferWindowPos( count );
2830 /***********************************************************************
2831 * BeginDeferWindowPos (USER32.9)
2833 HDWP WINAPI BeginDeferWindowPos( INT count )
2838 if (count <= 0) return 0;
2839 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2840 if (!handle) return 0;
2841 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2842 pDWP->actualCount = 0;
2843 pDWP->suggestedCount = count;
2845 pDWP->wMagic = DWP_MAGIC;
2846 pDWP->hwndParent = 0;
2851 /***********************************************************************
2852 * DeferWindowPos16 (USER.260)
2854 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2855 INT16 x, INT16 y, INT16 cx, INT16 cy,
2858 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2859 x, y, cx, cy, flags );
2863 /***********************************************************************
2864 * DeferWindowPos (USER32.128)
2866 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2867 INT x, INT y, INT cx, INT cy,
2872 HDWP newhdwp = hdwp,retvalue;
2876 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2877 if (!pDWP) return 0;
2878 if (hwnd == GetDesktopWindow()) return 0;
2880 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2881 USER_HEAP_FREE( hdwp );
2885 /* Numega Bounds Checker Demo dislikes the following code.
2886 In fact, I've not been able to find any "same parent" requirement in any docu
2890 /* All the windows of a DeferWindowPos() must have the same parent */
2891 parent = pWnd->parent->hwndSelf;
2892 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2893 else if (parent != pDWP->hwndParent)
2895 USER_HEAP_FREE( hdwp );
2901 for (i = 0; i < pDWP->actualCount; i++)
2903 if (pDWP->winPos[i].hwnd == hwnd)
2905 /* Merge with the other changes */
2906 if (!(flags & SWP_NOZORDER))
2908 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2910 if (!(flags & SWP_NOMOVE))
2912 pDWP->winPos[i].x = x;
2913 pDWP->winPos[i].y = y;
2915 if (!(flags & SWP_NOSIZE))
2917 pDWP->winPos[i].cx = cx;
2918 pDWP->winPos[i].cy = cy;
2920 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2921 SWP_NOZORDER | SWP_NOREDRAW |
2922 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2924 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2930 if (pDWP->actualCount >= pDWP->suggestedCount)
2932 newhdwp = USER_HEAP_REALLOC( hdwp,
2933 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
2939 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2940 pDWP->suggestedCount++;
2942 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2943 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2944 pDWP->winPos[pDWP->actualCount].x = x;
2945 pDWP->winPos[pDWP->actualCount].y = y;
2946 pDWP->winPos[pDWP->actualCount].cx = cx;
2947 pDWP->winPos[pDWP->actualCount].cy = cy;
2948 pDWP->winPos[pDWP->actualCount].flags = flags;
2949 pDWP->actualCount++;
2952 WIN_ReleaseWndPtr(pWnd);
2957 /***********************************************************************
2958 * EndDeferWindowPos16 (USER.261)
2960 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2962 return EndDeferWindowPos( hdwp );
2966 /***********************************************************************
2967 * EndDeferWindowPos (USER32.173)
2969 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
2976 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2977 if (!pDWP) return FALSE;
2978 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2980 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
2981 winpos->x, winpos->y, winpos->cx,
2982 winpos->cy, winpos->flags ))) break;
2984 USER_HEAP_FREE( hdwp );
2989 /***********************************************************************
2990 * TileChildWindows (USER.199)
2992 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
2994 FIXME(win, "(%04x, %d): stub\n", parent, action);
2997 /***********************************************************************
2998 * CascageChildWindows (USER.198)
3000 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3002 FIXME(win, "(%04x, %d): stub\n", parent, action);
3005 /***********************************************************************
3006 * SetProgmanWindow [USER32.522]
3008 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3010 hGlobalProgmanWindow = hwnd;
3011 return hGlobalProgmanWindow;
3014 /***********************************************************************
3015 * GetProgmanWindow [USER32.289]
3017 HRESULT WINAPI GetProgmanWindow ( )
3019 return hGlobalProgmanWindow;
3022 /***********************************************************************
3023 * SetShellWindowEx [USER32.531]
3024 * hwndProgman = Progman[Program Manager]
3025 * |-> SHELLDLL_DefView
3026 * hwndListView = | |-> SysListView32
3027 * | | |-> tooltips_class32
3033 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3035 FIXME(win,"0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3036 hGlobalShellWindow = hwndProgman;
3037 return hGlobalShellWindow;
3041 /***********************************************************************
3042 * SetTaskmanWindow [USER32.537]
3044 * hwnd = MSTaskSwWClass
3045 * |-> SysTabControl32
3047 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3049 hGlobalTaskmanWindow = hwnd;
3050 return hGlobalTaskmanWindow;
3053 /***********************************************************************
3054 * GetTaskmanWindow [USER32.304]
3056 HRESULT WINAPI GetTaskmanWindow ( )
3058 return hGlobalTaskmanWindow;