2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996 Alex Korobka
11 #include "sysmetrics.h"
23 #include "nonclient.h"
28 #define HAS_DLGFRAME(style,exStyle) \
29 (((exStyle) & WS_EX_DLGMODALFRAME) || \
30 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
32 #define HAS_THICKFRAME(style) \
33 (((style) & WS_THICKFRAME) && \
34 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
36 #define SWP_AGG_NOGEOMETRYCHANGE \
37 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
38 #define SWP_AGG_NOPOSCHANGE \
39 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
40 #define SWP_AGG_STATUSFLAGS \
41 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
43 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
45 #define PLACE_MIN 0x0001
46 #define PLACE_MAX 0x0002
47 #define PLACE_RECT 0x0004
49 #define SMC_NOCOPY 0x0001
50 #define SMC_NOPARENTERASE 0x0002
51 #define SMC_DRAWFRAME 0x0004
52 #define SMC_SETXPOS 0x0008
54 /* ----- internal variables ----- */
56 static HWND hwndPrevActive = 0; /* Previously active window */
57 static HWND hGlobalShellWindow=0; /*the shell*/
59 static LPCSTR atomInternalPos;
61 extern HQUEUE16 hActiveQueue;
63 /***********************************************************************
64 * WINPOS_CreateInternalPosAtom
66 BOOL WINPOS_CreateInternalPosAtom()
69 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
70 return (atomInternalPos) ? TRUE : FALSE;
73 /***********************************************************************
74 * WINPOS_CheckInternalPos
76 * Called when a window is destroyed.
78 void WINPOS_CheckInternalPos( WND* wndPtr )
81 MESSAGEQUEUE *pMsgQ = 0;
82 HWND hwnd = wndPtr->hwndSelf;
84 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
86 /* Retrieve the message queue associated with this window */
87 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
90 WARN( win, "\tMessage queue not found. Exiting!\n" );
94 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
96 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
98 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
99 WARN(win, "\tattempt to activate destroyed window!\n");
104 if( IsWindow(lpPos->hwndIconTitle) )
105 DestroyWindow( lpPos->hwndIconTitle );
106 HeapFree( SystemHeap, 0, lpPos );
109 QUEUE_Unlock( pMsgQ );
113 /***********************************************************************
116 * Find a suitable place for an iconic window.
118 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
121 short x, y, xspacing, yspacing;
123 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
124 if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
125 (pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
126 return pt; /* The icon already has a suitable position */
128 xspacing = SYSMETRICS_CXICONSPACING;
129 yspacing = SYSMETRICS_CYICONSPACING;
131 y = rectParent.bottom;
134 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
136 /* Check if another icon already occupies this spot */
137 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
140 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
142 if ((childPtr->rectWindow.left < x + xspacing) &&
143 (childPtr->rectWindow.right >= x) &&
144 (childPtr->rectWindow.top <= y) &&
145 (childPtr->rectWindow.bottom > y - yspacing))
146 break; /* There's a window in there */
148 WIN_UpdateWndPtr(&childPtr,childPtr->next);
150 WIN_ReleaseWndPtr(childPtr);
151 if (!childPtr) /* No window was found, so it's OK for us */
153 pt.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
154 pt.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
163 /***********************************************************************
164 * ArrangeIconicWindows16 (USER.170)
166 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
168 return ArrangeIconicWindows(parent);
170 /***********************************************************************
171 * ArrangeIconicWindows (USER32.7)
173 UINT WINAPI ArrangeIconicWindows( HWND parent )
177 INT x, y, xspacing, yspacing;
179 GetClientRect( parent, &rectParent );
181 y = rectParent.bottom;
182 xspacing = SYSMETRICS_CXICONSPACING;
183 yspacing = SYSMETRICS_CYICONSPACING;
185 hwndChild = GetWindow( parent, GW_CHILD );
188 if( IsIconic( hwndChild ) )
190 WND *wndPtr = WIN_FindWndPtr(hwndChild);
192 WINPOS_ShowIconTitle( wndPtr, FALSE );
194 SetWindowPos( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
195 y - yspacing - SYSMETRICS_CYICON/2, 0, 0,
196 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
197 if( IsWindow(hwndChild) )
198 WINPOS_ShowIconTitle(wndPtr , TRUE );
199 WIN_ReleaseWndPtr(wndPtr);
201 if (x <= rectParent.right - xspacing) x += xspacing;
208 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
214 /***********************************************************************
215 * SwitchToThisWindow16 (USER.172)
217 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
219 SwitchToThisWindow( hwnd, restore );
223 /***********************************************************************
224 * SwitchToThisWindow (USER32.539)
226 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
228 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
232 /***********************************************************************
233 * GetWindowRect16 (USER.32)
235 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
237 WND * wndPtr = WIN_FindWndPtr( hwnd );
240 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
241 if (wndPtr->dwStyle & WS_CHILD)
242 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
243 WIN_ReleaseWndPtr(wndPtr);
247 /***********************************************************************
248 * GetWindowRect (USER32.308)
250 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
252 WND * wndPtr = WIN_FindWndPtr( hwnd );
253 if (!wndPtr) return FALSE;
255 *rect = wndPtr->rectWindow;
256 if (wndPtr->dwStyle & WS_CHILD)
257 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
258 WIN_ReleaseWndPtr(wndPtr);
263 /***********************************************************************
266 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
270 WND * wndPtr = WIN_FindWndPtr( hwnd );
271 if (!wndPtr) return (ERROR);
273 FIXME (win, "GetWindowRgn: doesn't really do regions\n");
275 memset (&rect, 0, sizeof(rect));
277 GetWindowRect ( hwnd, &rect );
279 FIXME (win, "Check whether a valid region here\n");
281 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
283 WIN_ReleaseWndPtr(wndPtr);
284 return (SIMPLEREGION);
287 /***********************************************************************
290 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
294 FIXME (win, "SetWindowRgn: stub\n");
298 /***********************************************************************
301 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
305 FIXME (win, "SetWindowRgn16: stub\n");
310 /***********************************************************************
311 * GetClientRect16 (USER.33)
313 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
315 WND * wndPtr = WIN_FindWndPtr( hwnd );
317 rect->left = rect->top = rect->right = rect->bottom = 0;
320 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
321 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
323 WIN_ReleaseWndPtr(wndPtr);
327 /***********************************************************************
328 * GetClientRect (USER.220)
330 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
332 WND * wndPtr = WIN_FindWndPtr( hwnd );
334 rect->left = rect->top = rect->right = rect->bottom = 0;
335 if (!wndPtr) return FALSE;
336 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
337 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
339 WIN_ReleaseWndPtr(wndPtr);
344 /*******************************************************************
345 * ClientToScreen16 (USER.28)
347 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
349 MapWindowPoints16( hwnd, 0, lppnt, 1 );
353 /*******************************************************************
354 * ClientToScreen (USER32.52)
356 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
358 MapWindowPoints( hwnd, 0, lppnt, 1 );
363 /*******************************************************************
364 * ScreenToClient16 (USER.29)
366 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
368 MapWindowPoints16( 0, hwnd, lppnt, 1 );
372 /*******************************************************************
373 * ScreenToClient (USER32.447)
375 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
377 MapWindowPoints( 0, hwnd, lppnt, 1 );
382 /***********************************************************************
383 * WINPOS_WindowFromPoint
385 * Find the window and hittest for a given point.
387 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
390 INT16 hittest = HTERROR;
395 wndPtr = WIN_LockWndPtr(wndScope->child);
397 if( wndScope->flags & WIN_MANAGED )
399 /* this prevents mouse clicks from going "through" scrollbars in managed mode */
400 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
401 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
404 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
410 /* If point is in window, and window is visible, and it */
411 /* is enabled (or it's a top-level window), then explore */
412 /* its children. Otherwise, go to the next window. */
414 if ((wndPtr->dwStyle & WS_VISIBLE) &&
415 (!(wndPtr->dwStyle & WS_DISABLED) ||
416 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
417 (xy.x >= wndPtr->rectWindow.left) &&
418 (xy.x < wndPtr->rectWindow.right) &&
419 (xy.y >= wndPtr->rectWindow.top) &&
420 (xy.y < wndPtr->rectWindow.bottom))
422 *ppWnd = wndPtr; /* Got a suitable window */
424 /* If window is minimized or disabled, return at once */
425 if (wndPtr->dwStyle & WS_MINIMIZE)
427 retvalue = HTCAPTION;
430 if (wndPtr->dwStyle & WS_DISABLED)
436 /* If point is not in client area, ignore the children */
437 if ((xy.x < wndPtr->rectClient.left) ||
438 (xy.x >= wndPtr->rectClient.right) ||
439 (xy.y < wndPtr->rectClient.top) ||
440 (xy.y >= wndPtr->rectClient.bottom)) break;
442 xy.x -= wndPtr->rectClient.left;
443 xy.y -= wndPtr->rectClient.top;
444 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
448 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
453 /* If nothing found, try the scope window */
454 if (!*ppWnd) *ppWnd = wndScope;
456 /* Send the WM_NCHITTEST message (only if to the same task) */
457 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
459 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
460 0, MAKELONG( pt.x, pt.y ) );
461 if (hittest != HTTRANSPARENT)
463 retvalue = hittest; /* Found the window */
473 /* If no children found in last search, make point relative to parent */
476 xy.x += (*ppWnd)->rectClient.left;
477 xy.y += (*ppWnd)->rectClient.top;
480 /* Restart the search from the next sibling */
481 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
482 *ppWnd = (*ppWnd)->parent;
486 WIN_ReleaseWndPtr(wndPtr);
491 /*******************************************************************
492 * WindowFromPoint16 (USER.30)
494 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
497 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
498 WIN_ReleaseDesktop();
499 return pWnd->hwndSelf;
503 /*******************************************************************
504 * WindowFromPoint (USER32.582)
506 HWND WINAPI WindowFromPoint( POINT pt )
510 CONV_POINT32TO16( &pt, &pt16 );
511 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
512 WIN_ReleaseDesktop();
513 return (HWND)pWnd->hwndSelf;
517 /*******************************************************************
518 * ChildWindowFromPoint16 (USER.191)
520 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
523 CONV_POINT16TO32( &pt, &pt32 );
524 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
528 /*******************************************************************
529 * ChildWindowFromPoint (USER32.49)
531 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
533 /* pt is in the client coordinates */
535 WND* wnd = WIN_FindWndPtr(hwndParent);
541 /* get client rect fast */
542 rect.top = rect.left = 0;
543 rect.right = wnd->rectClient.right - wnd->rectClient.left;
544 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
546 if (!PtInRect( &rect, pt ))
551 WIN_UpdateWndPtr(&wnd,wnd->child);
554 if (PtInRect( &wnd->rectWindow, pt ))
556 retvalue = wnd->hwndSelf;
559 WIN_UpdateWndPtr(&wnd,wnd->next);
561 retvalue = hwndParent;
563 WIN_ReleaseWndPtr(wnd);
567 /*******************************************************************
568 * ChildWindowFromPointEx16 (USER.50)
570 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
573 CONV_POINT16TO32( &pt, &pt32 );
574 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
578 /*******************************************************************
579 * ChildWindowFromPointEx32 (USER32.50)
581 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
584 /* pt is in the client coordinates */
586 WND* wnd = WIN_FindWndPtr(hwndParent);
592 /* get client rect fast */
593 rect.top = rect.left = 0;
594 rect.right = wnd->rectClient.right - wnd->rectClient.left;
595 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
597 if (!PtInRect( &rect, pt ))
602 WIN_UpdateWndPtr(&wnd,wnd->child);
606 if (PtInRect( &wnd->rectWindow, pt )) {
607 if ( (uFlags & CWP_SKIPINVISIBLE) &&
608 !(wnd->dwStyle & WS_VISIBLE) );
609 else if ( (uFlags & CWP_SKIPDISABLED) &&
610 (wnd->dwStyle & WS_DISABLED) );
611 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
612 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
615 retvalue = wnd->hwndSelf;
618 WIN_UpdateWndPtr(&wnd,wnd->next);
622 retvalue = hwndParent;
624 WIN_ReleaseWndPtr(wnd);
629 /*******************************************************************
630 * WINPOS_GetWinOffset
632 * Calculate the offset between the origin of the two windows. Used
633 * to implement MapWindowPoints.
635 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
640 offset->x = offset->y = 0;
641 if (hwndFrom == hwndTo ) return;
643 /* Translate source window origin to screen coords */
646 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
648 ERR(win,"bad hwndFrom = %04x\n",hwndFrom);
651 while (wndPtr->parent)
653 offset->x += wndPtr->rectClient.left;
654 offset->y += wndPtr->rectClient.top;
655 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
659 /* Translate origin to destination window coords */
662 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
664 ERR(win,"bad hwndTo = %04x\n", hwndTo );
667 while (wndPtr->parent)
669 offset->x -= wndPtr->rectClient.left;
670 offset->y -= wndPtr->rectClient.top;
671 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
674 WIN_ReleaseWndPtr(wndPtr);
678 /*******************************************************************
679 * MapWindowPoints16 (USER.258)
681 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
682 LPPOINT16 lppt, UINT16 count )
686 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
696 /*******************************************************************
697 * MapWindowPoints (USER32.386)
699 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
700 LPPOINT lppt, UINT count )
704 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
711 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
715 /***********************************************************************
716 * IsIconic16 (USER.31)
718 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
720 return IsIconic(hWnd);
724 /***********************************************************************
725 * IsIconic (USER32.345)
727 BOOL WINAPI IsIconic(HWND hWnd)
730 WND * wndPtr = WIN_FindWndPtr(hWnd);
731 if (wndPtr == NULL) return FALSE;
732 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
733 WIN_ReleaseWndPtr(wndPtr);
738 /***********************************************************************
739 * IsZoomed (USER.272)
741 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
743 return IsZoomed(hWnd);
747 /***********************************************************************
748 * IsZoomed (USER.352)
750 BOOL WINAPI IsZoomed(HWND hWnd)
753 WND * wndPtr = WIN_FindWndPtr(hWnd);
754 if (wndPtr == NULL) return FALSE;
755 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
756 WIN_ReleaseWndPtr(wndPtr);
761 /*******************************************************************
762 * GetActiveWindow (USER.60)
764 HWND16 WINAPI GetActiveWindow16(void)
766 return (HWND16)GetActiveWindow();
769 /*******************************************************************
770 * GetActiveWindow (USER32.205)
772 HWND WINAPI GetActiveWindow(void)
774 MESSAGEQUEUE *pCurMsgQ = 0;
777 /* Get the messageQ for the current thread */
778 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
780 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
784 /* Return the current active window from the perQ data of the current message Q */
785 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
787 QUEUE_Unlock( pCurMsgQ );
792 /*******************************************************************
795 static BOOL WINPOS_CanActivate(WND* pWnd)
797 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
798 == WS_VISIBLE) ) return TRUE;
803 /*******************************************************************
804 * SetActiveWindow16 (USER.59)
806 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
808 return SetActiveWindow(hwnd);
812 /*******************************************************************
813 * SetActiveWindow (USER32.463)
815 HWND WINAPI SetActiveWindow( HWND hwnd )
818 WND *wndPtr = WIN_FindWndPtr( hwnd );
819 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
821 if ( !WINPOS_CanActivate(wndPtr) )
827 /* Get the messageQ for the current thread */
828 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
830 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
834 /* Retrieve the message queue associated with this window */
835 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
838 WARN( win, "\tWindow message queue not found. Exiting!\n" );
842 /* Make sure that the window is associated with the calling threads
843 * message queue. It must share the same perQ data.
846 if ( pCurMsgQ->pQData != pMsgQ->pQData )
849 /* Save current active window */
850 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
852 WINPOS_SetActiveWindow( hwnd, 0, 0 );
855 /* Unlock the queues before returning */
857 QUEUE_Unlock( pMsgQ );
859 QUEUE_Unlock( pCurMsgQ );
862 WIN_ReleaseWndPtr(wndPtr);
867 /*******************************************************************
868 * GetForegroundWindow16 (USER.608)
870 HWND16 WINAPI GetForegroundWindow16(void)
872 return (HWND16)GetForegroundWindow();
876 /*******************************************************************
877 * SetForegroundWindow16 (USER.609)
879 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
881 return SetForegroundWindow( hwnd );
885 /*******************************************************************
886 * GetForegroundWindow (USER32.241)
888 HWND WINAPI GetForegroundWindow(void)
890 return GetActiveWindow();
894 /*******************************************************************
895 * SetForegroundWindow (USER32.482)
897 BOOL WINAPI SetForegroundWindow( HWND hwnd )
899 SetActiveWindow( hwnd );
904 /*******************************************************************
905 * GetShellWindow16 (USER.600)
907 HWND16 WINAPI GetShellWindow16(void)
909 return GetShellWindow();
912 /*******************************************************************
913 * SetShellWindow (USER32.504)
915 HWND WINAPI SetShellWindow(HWND hwndshell)
916 { WARN(win, "(hWnd=%08x) semi stub\n",hwndshell );
918 hGlobalShellWindow = hwndshell;
919 return hGlobalShellWindow;
923 /*******************************************************************
924 * GetShellWindow (USER32.287)
926 HWND WINAPI GetShellWindow(void)
927 { WARN(win, "(hWnd=%x) semi stub\n",hGlobalShellWindow );
929 return hGlobalShellWindow;
933 /***********************************************************************
934 * BringWindowToTop16 (USER.45)
936 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
938 return BringWindowToTop(hwnd);
942 /***********************************************************************
943 * BringWindowToTop (USER32.11)
945 BOOL WINAPI BringWindowToTop( HWND hwnd )
947 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
951 /***********************************************************************
952 * MoveWindow16 (USER.56)
954 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
957 return MoveWindow(hwnd,x,y,cx,cy,repaint);
961 /***********************************************************************
962 * MoveWindow (USER32.399)
964 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
967 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
968 if (!repaint) flags |= SWP_NOREDRAW;
969 TRACE(win, "%04x %d,%d %dx%d %d\n",
970 hwnd, x, y, cx, cy, repaint );
971 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
974 /***********************************************************************
975 * WINPOS_InitInternalPos
977 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
980 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
984 /* this happens when the window is minimized/maximized
985 * for the first time (rectWindow is not adjusted yet) */
987 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
988 if( !lpPos ) return NULL;
990 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
991 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
992 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
993 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
996 if( wnd->dwStyle & WS_MINIMIZE )
997 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
998 else if( wnd->dwStyle & WS_MAXIMIZE )
999 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1000 else if( restoreRect )
1001 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1006 /***********************************************************************
1007 * WINPOS_RedrawIconTitle
1009 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1011 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1014 if( lpPos->hwndIconTitle )
1016 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1017 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1024 /***********************************************************************
1025 * WINPOS_ShowIconTitle
1027 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1029 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1031 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1033 HWND16 hWnd = lpPos->hwndIconTitle;
1035 TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1038 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1041 pWnd = WIN_FindWndPtr(hWnd);
1043 if( !(pWnd->dwStyle & WS_VISIBLE) )
1045 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1046 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1047 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1049 WIN_ReleaseWndPtr(pWnd);
1051 else ShowWindow( hWnd, SW_HIDE );
1056 /*******************************************************************
1057 * WINPOS_GetMinMaxInfo
1059 * Get the minimized and maximized information for a window.
1061 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1062 POINT *minTrack, POINT *maxTrack )
1064 LPINTERNALPOS lpPos;
1068 /* Compute default values */
1070 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
1071 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
1072 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
1073 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
1074 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
1075 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
1077 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1078 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1080 xinc = SYSMETRICS_CXDLGFRAME;
1081 yinc = SYSMETRICS_CYDLGFRAME;
1086 if (HAS_THICKFRAME(wndPtr->dwStyle))
1088 xinc += SYSMETRICS_CXFRAME;
1089 yinc += SYSMETRICS_CYFRAME;
1091 if (wndPtr->dwStyle & WS_BORDER)
1093 xinc += SYSMETRICS_CXBORDER;
1094 yinc += SYSMETRICS_CYBORDER;
1097 MinMax.ptMaxSize.x += 2 * xinc;
1098 MinMax.ptMaxSize.y += 2 * yinc;
1100 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1101 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1102 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1105 MinMax.ptMaxPosition.x = -xinc;
1106 MinMax.ptMaxPosition.y = -yinc;
1109 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1111 /* Some sanity checks */
1113 TRACE(win,"%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1114 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1115 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1116 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1117 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1118 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1119 MinMax.ptMinTrackSize.x );
1120 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1121 MinMax.ptMinTrackSize.y );
1123 if (maxSize) *maxSize = MinMax.ptMaxSize;
1124 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1125 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1126 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1129 /***********************************************************************
1130 * WINPOS_MinMaximize
1132 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1133 * This function assumes that 'cmd' is different from the current window
1136 UINT16 WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1138 UINT16 swpFlags = 0;
1140 POINT size = { wndPtr->rectWindow.left, wndPtr->rectWindow.top };
1141 LPINTERNALPOS lpPos = WINPOS_InitInternalPos( wndPtr, size,
1142 &wndPtr->rectWindow );
1144 TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
1146 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1148 if( wndPtr->dwStyle & WS_MINIMIZE )
1150 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1151 return (SWP_NOSIZE | SWP_NOMOVE);
1152 swpFlags |= SWP_NOCOPYBITS;
1157 if( wndPtr->dwStyle & WS_MAXIMIZE)
1159 wndPtr->flags |= WIN_RESTORE_MAX;
1160 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1163 wndPtr->flags &= ~WIN_RESTORE_MAX;
1164 wndPtr->dwStyle |= WS_MINIMIZE;
1166 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1168 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1169 SYSMETRICS_CXICON, SYSMETRICS_CYICON );
1170 swpFlags |= SWP_NOCOPYBITS;
1174 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1175 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1176 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1178 if( wndPtr->dwStyle & WS_MINIMIZE )
1180 WINPOS_ShowIconTitle( wndPtr, FALSE );
1181 wndPtr->dwStyle &= ~WS_MINIMIZE;
1183 wndPtr->dwStyle |= WS_MAXIMIZE;
1185 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1190 if( wndPtr->dwStyle & WS_MINIMIZE )
1192 wndPtr->dwStyle &= ~WS_MINIMIZE;
1193 WINPOS_ShowIconTitle( wndPtr, FALSE );
1194 if( wndPtr->flags & WIN_RESTORE_MAX)
1196 /* Restore to maximized position */
1197 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1198 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1199 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1200 wndPtr->dwStyle |= WS_MAXIMIZE;
1201 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1206 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1207 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1209 /* Restore to normal position */
1211 *lpRect = lpPos->rectNormal;
1212 lpRect->right -= lpRect->left;
1213 lpRect->bottom -= lpRect->top;
1217 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1221 /***********************************************************************
1222 * ShowWindowAsync (USER32.535)
1224 * doesn't wait; returns immediately.
1225 * used by threads to toggle windows in other (possibly hanging) threads
1227 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1229 /* FIXME: does ShowWindow() return immediately ? */
1230 return ShowWindow(hwnd, cmd);
1234 /***********************************************************************
1235 * ShowWindow16 (USER.42)
1237 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1239 return ShowWindow(hwnd,cmd);
1243 /***********************************************************************
1244 * ShowWindow (USER32.534)
1246 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1248 WND* wndPtr = WIN_FindWndPtr( hwnd );
1249 BOOL wasVisible, showFlag;
1250 RECT16 newPos = {0, 0, 0, 0};
1253 if (!wndPtr) return FALSE;
1255 TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1257 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1262 if (!wasVisible) goto END;;
1263 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1264 SWP_NOACTIVATE | SWP_NOZORDER;
1265 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
1267 /* Revert focus to parent */
1268 SetFocus( GetParent(hwnd) );
1272 case SW_SHOWMINNOACTIVE:
1273 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1275 case SW_SHOWMINIMIZED:
1276 swp |= SWP_SHOWWINDOW;
1279 swp |= SWP_FRAMECHANGED;
1280 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1281 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1282 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1285 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1286 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1287 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1288 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1289 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1293 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1296 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1299 case SW_SHOWNOACTIVATE:
1300 swp |= SWP_NOZORDER;
1301 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1303 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1304 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1306 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1308 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1309 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1310 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1314 showFlag = (cmd != SW_HIDE);
1315 if (showFlag != wasVisible)
1317 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1318 if (!IsWindow( hwnd )) goto END;
1321 if ((wndPtr->dwStyle & WS_CHILD) &&
1322 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1323 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1325 /* Don't call SetWindowPos() on invisible child windows */
1326 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1327 else wndPtr->dwStyle |= WS_VISIBLE;
1331 /* We can't activate a child window */
1332 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1333 SetWindowPos( hwnd, HWND_TOP,
1334 newPos.left, newPos.top, newPos.right, newPos.bottom, swp );
1335 if (!IsWindow( hwnd )) goto END;
1336 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1339 if (wndPtr->flags & WIN_NEED_SIZE)
1341 /* should happen only in CreateWindowEx() */
1342 int wParam = SIZE_RESTORED;
1344 wndPtr->flags &= ~WIN_NEED_SIZE;
1345 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1346 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1347 SendMessageA( hwnd, WM_SIZE, wParam,
1348 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1349 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1350 SendMessageA( hwnd, WM_MOVE, 0,
1351 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1355 WIN_ReleaseWndPtr(wndPtr);
1360 /***********************************************************************
1361 * GetInternalWindowPos16 (USER.460)
1363 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1366 WINDOWPLACEMENT16 wndpl;
1367 if (GetWindowPlacement16( hwnd, &wndpl ))
1369 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1370 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1371 return wndpl.showCmd;
1377 /***********************************************************************
1378 * GetInternalWindowPos (USER32.245)
1380 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1383 WINDOWPLACEMENT wndpl;
1384 if (GetWindowPlacement( hwnd, &wndpl ))
1386 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1387 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1388 return wndpl.showCmd;
1393 /***********************************************************************
1394 * GetWindowPlacement16 (USER.370)
1396 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1398 WND *pWnd = WIN_FindWndPtr( hwnd );
1399 LPINTERNALPOS lpPos;
1401 if(!pWnd ) return FALSE;
1403 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1404 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1405 wndpl->length = sizeof(*wndpl);
1406 if( pWnd->dwStyle & WS_MINIMIZE )
1407 wndpl->showCmd = SW_SHOWMINIMIZED;
1409 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1410 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1411 if( pWnd->flags & WIN_RESTORE_MAX )
1412 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1415 wndpl->ptMinPosition = lpPos->ptIconPos;
1416 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1417 wndpl->rcNormalPosition = lpPos->rectNormal;
1419 WIN_ReleaseWndPtr(pWnd);
1424 /***********************************************************************
1425 * GetWindowPlacement (USER32.307)
1428 * Fails if wndpl->length of Win95 (!) apps is invalid.
1430 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1434 WINDOWPLACEMENT16 wpl;
1435 wpl.length = sizeof(wpl);
1436 if( GetWindowPlacement16( hwnd, &wpl ) )
1438 pwpl32->length = sizeof(*pwpl32);
1439 pwpl32->flags = wpl.flags;
1440 pwpl32->showCmd = wpl.showCmd;
1441 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1442 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1443 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1451 /***********************************************************************
1452 * WINPOS_SetPlacement
1454 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1457 WND *pWnd = WIN_FindWndPtr( hwnd );
1460 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1461 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1463 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1464 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1465 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1467 if( pWnd->dwStyle & WS_MINIMIZE )
1469 WINPOS_ShowIconTitle( pWnd, FALSE );
1470 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1471 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1472 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1474 else if( pWnd->dwStyle & WS_MAXIMIZE )
1476 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1477 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1478 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1480 else if( flags & PLACE_RECT )
1481 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1482 lpPos->rectNormal.right - lpPos->rectNormal.left,
1483 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1484 SWP_NOZORDER | SWP_NOACTIVATE );
1486 ShowWindow( hwnd, wndpl->showCmd );
1487 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1489 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1491 /* SDK: ...valid only the next time... */
1492 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1494 WIN_ReleaseWndPtr(pWnd);
1501 /***********************************************************************
1502 * SetWindowPlacement16 (USER.371)
1504 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1506 return WINPOS_SetPlacement( hwnd, wndpl,
1507 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1510 /***********************************************************************
1511 * SetWindowPlacement (USER32.519)
1514 * Fails if wndpl->length of Win95 (!) apps is invalid.
1516 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1520 WINDOWPLACEMENT16 wpl = { sizeof(WINDOWPLACEMENT16),
1521 pwpl32->flags, pwpl32->showCmd, { pwpl32->ptMinPosition.x,
1522 pwpl32->ptMinPosition.y }, { pwpl32->ptMaxPosition.x,
1523 pwpl32->ptMaxPosition.y }, { pwpl32->rcNormalPosition.left,
1524 pwpl32->rcNormalPosition.top, pwpl32->rcNormalPosition.right,
1525 pwpl32->rcNormalPosition.bottom } };
1527 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1533 /***********************************************************************
1534 * SetInternalWindowPos16 (USER.461)
1536 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1537 LPRECT16 rect, LPPOINT16 pt )
1539 if( IsWindow16(hwnd) )
1541 WINDOWPLACEMENT16 wndpl;
1544 wndpl.length = sizeof(wndpl);
1545 wndpl.showCmd = showCmd;
1546 wndpl.flags = flags = 0;
1551 wndpl.flags |= WPF_SETMINPOSITION;
1552 wndpl.ptMinPosition = *pt;
1556 flags |= PLACE_RECT;
1557 wndpl.rcNormalPosition = *rect;
1559 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1564 /***********************************************************************
1565 * SetInternalWindowPos (USER32.483)
1567 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1568 LPRECT rect, LPPOINT pt )
1570 if( IsWindow(hwnd) )
1572 WINDOWPLACEMENT16 wndpl;
1575 wndpl.length = sizeof(wndpl);
1576 wndpl.showCmd = showCmd;
1577 wndpl.flags = flags = 0;
1582 wndpl.flags |= WPF_SETMINPOSITION;
1583 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1587 flags |= PLACE_RECT;
1588 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1590 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1594 /*******************************************************************
1595 * WINPOS_SetActiveWindow
1597 * SetActiveWindow() back-end. This is the only function that
1598 * can assign active status to a window. It must be called only
1599 * for the top level windows.
1601 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1603 CBTACTIVATESTRUCT16* cbtStruct;
1604 WND* wndPtr=0, *wndTemp;
1605 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1606 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1608 HWND hwndActive = 0;
1611 /* Get current active window from the active queue */
1614 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1615 if ( pOldActiveQueue )
1616 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1619 /* paranoid checks */
1620 if( hWnd == GetDesktopWindow() || hWnd == hwndActive ) goto CLEANUP;
1622 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1625 wndPtr = WIN_FindWndPtr(hWnd);
1626 hOldActiveQueue = hActiveQueue;
1628 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1629 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1631 TRACE(win,"no current active window.\n");
1632 WIN_ReleaseWndPtr(wndTemp);
1633 /* call CBT hook chain */
1634 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1637 cbtStruct->fMouse = fMouse;
1638 cbtStruct->hWndActive = hwndActive;
1639 wRet = HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1640 (LPARAM)SEGPTR_GET(cbtStruct) );
1641 SEGPTR_FREE(cbtStruct);
1644 /* Unlock the active queue before returning */
1645 if ( pOldActiveQueue )
1646 QUEUE_Unlock( pOldActiveQueue );
1651 /* set prev active wnd to current active wnd and send notification */
1652 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1654 MESSAGEQUEUE *pTempActiveQueue = 0;
1656 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1658 if (GetSysModalWindow16() != hWnd) goto CLEANUP;
1659 /* disregard refusal if hWnd is sysmodal */
1663 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1664 MAKEWPARAM( WA_INACTIVE, wIconized ),
1667 /* FIXME: must be SendMessage16() because A doesn't do
1668 * intertask at this time */
1669 SendMessage16( hwndPrevActive, WM_ACTIVATE, WA_INACTIVE,
1670 MAKELPARAM( (HWND16)hWnd, wIconized ) );
1673 /* check if something happened during message processing
1674 * (global active queue may have changed)
1676 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1677 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1678 QUEUE_Unlock( pTempActiveQueue );
1679 if( hwndPrevActive != hwndActive )
1683 /* Set new active window in the message queue */
1687 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1688 if ( pNewActiveQueue )
1689 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1692 /* send palette messages */
1693 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1694 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1696 /* if prev wnd is minimized redraw icon title */
1697 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1699 /* managed windows will get ConfigureNotify event */
1700 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1702 /* check Z-order and bring hWnd to the top */
1703 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1705 if (wndTemp->dwStyle & WS_VISIBLE) break;
1707 WIN_ReleaseDesktop();
1708 WIN_ReleaseWndPtr(wndTemp);
1710 if( wndTemp != wndPtr )
1711 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1712 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1713 if (!IsWindow(hWnd)) goto CLEANUP;
1716 /* Get a handle to the new active queue */
1717 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1719 /* send WM_ACTIVATEAPP if necessary */
1720 if (hOldActiveQueue != hNewActiveQueue)
1722 WND **list, **ppWnd;
1723 WND *pDesktop = WIN_GetDesktop();
1725 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1727 for (ppWnd = list; *ppWnd; ppWnd++)
1729 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1731 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1732 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1733 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1735 WIN_ReleaseWinArray(list);
1738 hActiveQueue = hNewActiveQueue;
1740 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1742 for (ppWnd = list; *ppWnd; ppWnd++)
1744 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1746 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1747 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1748 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1750 WIN_ReleaseWinArray(list);
1752 WIN_ReleaseDesktop();
1754 if (!IsWindow(hWnd)) goto CLEANUP;
1759 /* walk up to the first unowned window */
1760 wndTemp = WIN_LockWndPtr(wndPtr);
1761 while (wndTemp->owner)
1763 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1765 /* and set last active owned popup */
1766 wndTemp->hwndLastActive = hWnd;
1768 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1769 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1771 SendMessageA( hWnd, WM_ACTIVATE,
1772 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1773 (LPARAM)hwndPrevActive );
1775 SendMessage16(hWnd, WM_ACTIVATE, (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE,
1776 MAKELPARAM( (HWND16)hwndPrevActive, wIconized) );
1779 if( !IsWindow(hWnd) ) goto CLEANUP;
1782 /* change focus if possible */
1783 if( fChangeFocus && GetFocus() )
1784 if( WIN_GetTopParent(GetFocus()) != hwndActive )
1785 FOCUS_SwitchFocus( pNewActiveQueue, GetFocus(),
1786 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1791 if( !hwndPrevActive && wndPtr )
1792 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1794 /* if active wnd is minimized redraw icon title */
1795 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1797 bRet = 1; // Success
1801 /* Unlock the message queues before returning */
1802 if ( pOldActiveQueue )
1803 QUEUE_Unlock( pOldActiveQueue );
1804 if ( pNewActiveQueue )
1805 QUEUE_Unlock( pNewActiveQueue );
1806 WIN_ReleaseWndPtr(wndPtr);
1807 return bRet ? (hWnd == hwndActive) : 0;
1810 /*******************************************************************
1811 * WINPOS_ActivateOtherWindow
1813 * Activates window other than pWnd.
1815 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1819 HWND hwndActive = 0;
1821 /* Get current active window from the active queue */
1824 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1827 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1828 QUEUE_Unlock( pActiveQueue );
1832 if( pWnd->hwndSelf == hwndPrevActive )
1835 if( hwndActive != pWnd->hwndSelf &&
1836 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1839 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1840 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1842 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1844 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1846 while( !WINPOS_CanActivate(pWndTo) )
1848 /* by now owned windows should've been taken care of */
1849 WIN_ReleaseWndPtr(pWndTo);
1850 pWndTo = WIN_LockWndPtr(pWndPtr->next);
1851 WIN_ReleaseWndPtr(pWndPtr);
1852 pWndPtr = WIN_LockWndPtr(pWndTo);
1853 if( !pWndTo ) break;
1855 WIN_ReleaseWndPtr(pWndPtr);
1858 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1860 /* switch desktop queue to current active */
1863 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1864 WIN_ReleaseWndPtr(pWndTo);
1865 WIN_ReleaseDesktop();
1872 /*******************************************************************
1873 * WINPOS_ChangeActiveWindow
1876 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1878 WND *wndPtr = WIN_FindWndPtr(hWnd);
1881 HWND hwndActive = 0;
1883 if( !wndPtr ) return FALSE;
1885 /* Get current active window from the active queue */
1888 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1891 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1892 QUEUE_Unlock( pActiveQueue );
1898 retvalue = WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1903 /* child windows get WM_CHILDACTIVATE message */
1904 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1906 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1910 /* owned popups imply owner activation - not sure */
1911 if ((wndPtr->dwStyle & WS_POPUP) && wndPtr->owner &&
1912 (wndPtr->owner->dwStyle & WS_VISIBLE ) &&
1913 !(wndPtr->owner->dwStyle & WS_DISABLED ))
1915 WIN_UpdateWndPtr(&wndPtr,wndPtr->owner);
1921 hWnd = wndPtr->hwndSelf;
1924 if( hWnd == hwndActive )
1930 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1936 /* switch desktop queue to current active */
1937 wndTemp = WIN_GetDesktop();
1938 if( wndPtr->parent == wndTemp)
1939 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1940 WIN_ReleaseDesktop();
1944 WIN_ReleaseWndPtr(wndPtr);
1949 /***********************************************************************
1950 * WINPOS_SendNCCalcSize
1952 * Send a WM_NCCALCSIZE message to a window.
1953 * All parameters are read-only except newClientRect.
1954 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1955 * when calcValidRect is TRUE.
1957 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1958 RECT *newWindowRect, RECT *oldWindowRect,
1959 RECT *oldClientRect, WINDOWPOS *winpos,
1960 RECT *newClientRect )
1962 NCCALCSIZE_PARAMS params;
1963 WINDOWPOS winposCopy;
1966 params.rgrc[0] = *newWindowRect;
1969 winposCopy = *winpos;
1970 params.rgrc[1] = *oldWindowRect;
1971 params.rgrc[2] = *oldClientRect;
1972 params.lppos = &winposCopy;
1974 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
1976 TRACE(win, "%d,%d-%d,%d\n",
1977 params.rgrc[0].left, params.rgrc[0].top,
1978 params.rgrc[0].right, params.rgrc[0].bottom );
1979 *newClientRect = params.rgrc[0];
1984 /***********************************************************************
1985 * WINPOS_HandleWindowPosChanging16
1987 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1989 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
1991 POINT maxSize, minTrack;
1992 if (winpos->flags & SWP_NOSIZE) return 0;
1993 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
1994 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
1996 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
1997 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1998 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1999 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2001 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2002 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2009 /***********************************************************************
2010 * WINPOS_HandleWindowPosChanging
2012 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2014 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2017 if (winpos->flags & SWP_NOSIZE) return 0;
2018 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2019 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2021 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2022 winpos->cx = MIN( winpos->cx, maxSize.x );
2023 winpos->cy = MIN( winpos->cy, maxSize.y );
2029 /***********************************************************************
2030 * WINPOS_MoveWindowZOrder
2032 * Move a window in Z order, invalidating everything that needs it.
2033 * Only necessary for windows without associated X window.
2035 static void WINPOS_MoveWindowZOrder( HWND hwnd, HWND hwndAfter )
2038 WND *pWndAfter, *pWndCur, *wndPtr = WIN_FindWndPtr( hwnd );
2040 /* We have two possible cases:
2041 * - The window is moving up: we have to invalidate all areas
2042 * of the window that were covered by other windows
2043 * - The window is moving down: we have to invalidate areas
2044 * of other windows covered by this one.
2047 if (hwndAfter == HWND_TOP)
2051 else if (hwndAfter == HWND_BOTTOM)
2053 if (!wndPtr->next) goto END; /* Already at the bottom */
2058 if (!(pWndAfter = WIN_FindWndPtr( hwndAfter ))) goto END;
2059 if (wndPtr->next == pWndAfter)
2061 WIN_ReleaseWndPtr(pWndAfter);
2062 goto END; /* Already placed right */
2065 /* Determine which window we encounter first in Z-order */
2066 pWndCur = WIN_LockWndPtr(wndPtr->parent->child);
2067 while ((pWndCur != wndPtr) && (pWndCur != pWndAfter))
2069 WIN_UpdateWndPtr(&pWndCur,pWndCur->next);
2071 movingUp = (pWndCur == pWndAfter);
2072 WIN_ReleaseWndPtr(pWndCur);
2073 WIN_ReleaseWndPtr(pWndAfter);
2078 WND *pWndPrevAfter = WIN_LockWndPtr(wndPtr->next);
2079 WIN_UnlinkWindow( hwnd );
2080 WIN_LinkWindow( hwnd, hwndAfter );
2081 pWndCur = WIN_LockWndPtr(wndPtr->next);
2082 while (pWndCur != pWndPrevAfter)
2084 RECT rect = { pWndCur->rectWindow.left,
2085 pWndCur->rectWindow.top,
2086 pWndCur->rectWindow.right,
2087 pWndCur->rectWindow.bottom };
2088 OffsetRect( &rect, -wndPtr->rectClient.left,
2089 -wndPtr->rectClient.top );
2090 PAINT_RedrawWindow( hwnd, &rect, 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
2091 RDW_FRAME | RDW_ERASE, 0 );
2092 WIN_UpdateWndPtr(&pWndCur,pWndCur->next);
2094 WIN_ReleaseWndPtr(pWndPrevAfter);
2096 else /* Moving down */
2098 pWndCur = WIN_LockWndPtr(wndPtr->next);
2099 WIN_UnlinkWindow( hwnd );
2100 WIN_LinkWindow( hwnd, hwndAfter );
2101 while (pWndCur != wndPtr)
2103 RECT rect = { pWndCur->rectWindow.left,
2104 pWndCur->rectWindow.top,
2105 pWndCur->rectWindow.right,
2106 pWndCur->rectWindow.bottom };
2107 OffsetRect( &rect, -pWndCur->rectClient.left,
2108 -pWndCur->rectClient.top );
2109 PAINT_RedrawWindow( pWndCur->hwndSelf, &rect, 0, RDW_INVALIDATE |
2110 RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
2111 WIN_UpdateWndPtr(&pWndCur,pWndCur->next);
2115 WIN_ReleaseWndPtr(wndPtr);
2118 /***********************************************************************
2119 * WINPOS_ReorderOwnedPopups
2121 * fix Z order taking into account owned popups -
2122 * basically we need to maintain them above the window that owns them
2124 HWND WINPOS_ReorderOwnedPopups(HWND hwndInsertAfter,WND* wndPtr,WORD flags)
2126 WND* pDesktop = WIN_GetDesktop();
2127 WND* w = WIN_LockWndPtr(pDesktop->child);
2129 if( wndPtr->dwStyle & WS_POPUP && wndPtr->owner )
2131 /* implement "local z-order" between the top and owner window */
2133 HWND hwndLocalPrev = HWND_TOP;
2135 if( hwndInsertAfter != HWND_TOP )
2137 while( w != wndPtr->owner )
2139 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2140 if( hwndLocalPrev == hwndInsertAfter ) break;
2141 WIN_UpdateWndPtr(&w,w->next);
2143 hwndInsertAfter = hwndLocalPrev;
2147 else if( wndPtr->dwStyle & WS_CHILD )
2150 WIN_UpdateWndPtr(&w,pDesktop->child);
2154 if( w == wndPtr ) break;
2156 if( w->dwStyle & WS_POPUP && w->owner == wndPtr )
2158 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
2159 SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2160 hwndInsertAfter = w->hwndSelf;
2162 WIN_UpdateWndPtr(&w,w->next);
2166 WIN_ReleaseWndPtr(w);
2167 WIN_ReleaseDesktop();
2168 return hwndInsertAfter;
2171 /***********************************************************************
2172 * WINPOS_SizeMoveClean
2174 * Make window look nice without excessive repainting
2178 * visible regions are in window coordinates
2179 * update regions are in window client coordinates
2180 * client and window rectangles are in parent client coordinates
2182 * FIXME: Move visible and update regions to the same coordinate system
2183 * (either parent client or window). This is a lot of work though.
2185 static UINT WINPOS_SizeMoveClean( WND* Wnd, HRGN oldVisRgn,
2186 LPRECT lpOldWndRect,
2187 LPRECT lpOldClientRect, UINT uFlags )
2189 HRGN newVisRgn = DCE_GetVisRgn(Wnd->hwndSelf,DCX_WINDOW | DCX_CLIPSIBLINGS,0,0);
2190 HRGN dirtyRgn = CreateRectRgn(0,0,0,0);
2193 TRACE(win,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n",
2194 Wnd->rectWindow.left, Wnd->rectWindow.top,
2195 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2196 lpOldWndRect->left, lpOldWndRect->top,
2197 lpOldWndRect->right, lpOldWndRect->bottom);
2198 TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2199 Wnd->rectClient.left, Wnd->rectClient.top,
2200 Wnd->rectClient.right, Wnd->rectClient.bottom,
2201 lpOldClientRect->left, lpOldClientRect->top,
2202 lpOldClientRect->right,lpOldClientRect->bottom );
2204 if( (lpOldWndRect->right - lpOldWndRect->left) != (Wnd->rectWindow.right - Wnd->rectWindow.left) ||
2205 (lpOldWndRect->bottom - lpOldWndRect->top) != (Wnd->rectWindow.bottom - Wnd->rectWindow.top) )
2206 uFlags |= SMC_DRAWFRAME;
2208 CombineRgn( dirtyRgn, newVisRgn, 0, RGN_COPY);
2210 if( !(uFlags & SMC_NOCOPY) )
2211 CombineRgn( newVisRgn, newVisRgn, oldVisRgn, RGN_AND );
2213 /* map regions to the parent client area */
2215 OffsetRgn( dirtyRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2216 OffsetRgn( oldVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2218 /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
2220 other = CombineRgn(dirtyRgn, oldVisRgn, dirtyRgn, RGN_DIFF);
2222 /* map visible region to the Wnd client area */
2224 OffsetRgn( newVisRgn, Wnd->rectWindow.left - Wnd->rectClient.left,
2225 Wnd->rectWindow.top - Wnd->rectClient.top );
2227 /* substract previously invalidated region from the Wnd visible region */
2229 my = (Wnd->hrgnUpdate > 1) ? CombineRgn( newVisRgn, newVisRgn,
2230 Wnd->hrgnUpdate, RGN_DIFF)
2233 if( uFlags & SMC_NOCOPY ) /* invalidate Wnd visible region */
2235 if (my != NULLREGION)
2236 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, newVisRgn, RDW_INVALIDATE |
2237 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2238 else if(uFlags & SMC_DRAWFRAME)
2239 Wnd->flags |= WIN_NEEDS_NCPAINT;
2241 else /* bitblt old client area */
2246 int xfrom,yfrom,xto,yto,width,height;
2248 if( uFlags & SMC_DRAWFRAME )
2250 /* copy only client area, frame will be redrawn anyway */
2252 xfrom = lpOldClientRect->left; yfrom = lpOldClientRect->top;
2253 xto = Wnd->rectClient.left; yto = Wnd->rectClient.top;
2254 width = lpOldClientRect->right - xfrom; height = lpOldClientRect->bottom - yfrom;
2255 updateRgn = CreateRectRgn( 0, 0, width, height );
2256 CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
2257 SetRectRgn( updateRgn, 0, 0, Wnd->rectClient.right - xto,
2258 Wnd->rectClient.bottom - yto );
2262 xfrom = lpOldWndRect->left; yfrom = lpOldWndRect->top;
2263 xto = Wnd->rectWindow.left; yto = Wnd->rectWindow.top;
2264 width = lpOldWndRect->right - xfrom; height = lpOldWndRect->bottom - yfrom;
2265 updateRgn = CreateRectRgn( xto - Wnd->rectClient.left,
2266 yto - Wnd->rectClient.top,
2267 Wnd->rectWindow.right - Wnd->rectClient.left,
2268 Wnd->rectWindow.bottom - Wnd->rectClient.top );
2271 CombineRgn( newVisRgn, newVisRgn, updateRgn, RGN_AND );
2273 /* substract new visRgn from target rect to get a region that won't be copied */
2275 update = CombineRgn( updateRgn, updateRgn, newVisRgn, RGN_DIFF );
2277 /* Blt valid bits using parent window DC */
2279 if( my != NULLREGION && (xfrom != xto || yfrom != yto) )
2282 /* compute clipping region in parent client coordinates */
2284 OffsetRgn( newVisRgn, Wnd->rectClient.left, Wnd->rectClient.top );
2285 CombineRgn( oldVisRgn, oldVisRgn, newVisRgn, RGN_OR );
2287 hDC = GetDCEx( Wnd->parent->hwndSelf, oldVisRgn,
2288 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN |
2289 DCX_CACHE | DCX_CLIPSIBLINGS);
2291 BitBlt( hDC, xto, yto, width, height, hDC, xfrom, yfrom, SRCCOPY );
2292 ReleaseDC( Wnd->parent->hwndSelf, hDC);
2295 if( update != NULLREGION )
2296 PAINT_RedrawWindow( Wnd->hwndSelf, NULL, updateRgn, RDW_INVALIDATE |
2297 RDW_FRAME | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2298 else if( uFlags & SMC_DRAWFRAME ) Wnd->flags |= WIN_NEEDS_NCPAINT;
2299 DeleteObject( updateRgn );
2302 /* erase uncovered areas */
2304 if( !(uFlags & SMC_NOPARENTERASE) && (other != NULLREGION ) )
2305 PAINT_RedrawWindow( Wnd->parent->hwndSelf, NULL, dirtyRgn,
2306 RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASE, RDW_C_USEHRGN );
2307 DeleteObject(dirtyRgn);
2308 DeleteObject(newVisRgn);
2312 /***********************************************************************
2313 * SetWindowPos (USER.2)
2315 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2316 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2318 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2321 /***********************************************************************
2322 * SetWindowPos (USER32.520)
2324 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2325 INT x, INT y, INT cx, INT cy, WORD flags)
2328 WND * wndPtr,*wndTemp;
2329 RECT newWindowRect, newClientRect, oldWindowRect;
2331 HWND tempInsertAfter= 0;
2334 BOOL resync = FALSE,retvalue;
2335 HWND hwndActive = 0;
2337 /* Get current active window from the active queue */
2340 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2343 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2344 QUEUE_Unlock( pActiveQueue );
2348 TRACE(win,"hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n",
2349 hwnd, x, y, x+cx, y+cy, flags);
2350 /* Check window handle */
2352 if (hwnd == GetDesktopWindow()) return FALSE;
2353 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2355 if(wndPtr->dwStyle & WS_VISIBLE)
2356 flags &= ~SWP_SHOWWINDOW;
2359 uFlags |= SMC_NOPARENTERASE;
2360 flags &= ~SWP_HIDEWINDOW;
2361 if (!(flags & SWP_SHOWWINDOW)) flags |= SWP_NOREDRAW;
2364 /* Check for windows that may not be resized
2365 FIXME: this should be done only for Windows 3.0 programs
2366 if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
2367 flags |= SWP_NOSIZE | SWP_NOMOVE;
2369 /* Check dimensions */
2371 if (cx <= 0) cx = 1;
2372 if (cy <= 0) cy = 1;
2376 if (hwnd == hwndActive) flags |= SWP_NOACTIVATE; /* Already active */
2377 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2378 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2379 flags |= SWP_NOSIZE; /* Already the right size */
2380 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2381 flags |= SWP_NOMOVE; /* Already the right position */
2383 /* Check hwndInsertAfter */
2385 if (!(flags & (SWP_NOZORDER | SWP_NOACTIVATE)))
2387 /* Ignore TOPMOST flags when activating a window */
2388 /* _and_ moving it in Z order. */
2389 if ((hwndInsertAfter == HWND_TOPMOST) ||
2390 (hwndInsertAfter == HWND_NOTOPMOST))
2391 hwndInsertAfter = HWND_TOP;
2393 /* TOPMOST not supported yet */
2394 if ((hwndInsertAfter == HWND_TOPMOST) ||
2395 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2397 /* hwndInsertAfter must be a sibling of the window */
2398 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2400 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2403 if( wnd->parent != wndPtr->parent )
2406 WIN_ReleaseWndPtr(wnd);
2409 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2411 WIN_ReleaseWndPtr(wnd);
2413 else if (!X11DRV_WND_GetXWindow(wndPtr))
2415 /* FIXME: the following optimization is no good for "X-ed" windows */
2416 if (hwndInsertAfter == HWND_TOP)
2417 flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2418 else /* HWND_BOTTOM */
2419 flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2422 /* Fill the WINDOWPOS structure */
2425 winpos.hwndInsertAfter = hwndInsertAfter;
2430 winpos.flags = flags;
2432 /* Send WM_WINDOWPOSCHANGING message */
2434 if (!(winpos.flags & SWP_NOSENDCHANGING))
2435 SendMessageA( hwnd, WM_WINDOWPOSCHANGING, 0, (LPARAM)&winpos );
2437 /* Calculate new position and size */
2439 newWindowRect = wndPtr->rectWindow;
2440 newClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2441 : wndPtr->rectClient;
2443 if (!(winpos.flags & SWP_NOSIZE))
2445 newWindowRect.right = newWindowRect.left + winpos.cx;
2446 newWindowRect.bottom = newWindowRect.top + winpos.cy;
2448 if (!(winpos.flags & SWP_NOMOVE))
2450 newWindowRect.left = winpos.x;
2451 newWindowRect.top = winpos.y;
2452 newWindowRect.right += winpos.x - wndPtr->rectWindow.left;
2453 newWindowRect.bottom += winpos.y - wndPtr->rectWindow.top;
2455 OffsetRect( &newClientRect, winpos.x - wndPtr->rectWindow.left,
2456 winpos.y - wndPtr->rectWindow.top );
2459 winpos.flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2461 /* Reposition window in Z order */
2463 if (!(winpos.flags & SWP_NOZORDER))
2465 /* reorder owned popups if hwnd is top-level window
2467 if( wndPtr->parent == WIN_GetDesktop() )
2469 hwndInsertAfter = WINPOS_ReorderOwnedPopups( hwndInsertAfter,
2470 wndPtr, winpos.flags );
2472 WIN_ReleaseDesktop();
2474 if (X11DRV_WND_GetXWindow(wndPtr))
2477 WIN_UnlinkWindow( winpos.hwnd );
2478 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2481 WINPOS_MoveWindowZOrder( winpos.hwnd, hwndInsertAfter );
2484 if ( !X11DRV_WND_GetXWindow(wndPtr) && !(winpos.flags & SWP_NOREDRAW) &&
2485 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED))
2486 != (SWP_NOMOVE | SWP_NOSIZE)) )
2487 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2489 /* Send WM_NCCALCSIZE message to get new client area */
2490 if( (winpos.flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2492 result = WINPOS_SendNCCalcSize( winpos.hwnd, TRUE, &newWindowRect,
2493 &wndPtr->rectWindow, &wndPtr->rectClient,
2494 &winpos, &newClientRect );
2496 /* FIXME: WVR_ALIGNxxx */
2498 if( newClientRect.left != wndPtr->rectClient.left ||
2499 newClientRect.top != wndPtr->rectClient.top )
2500 winpos.flags &= ~SWP_NOCLIENTMOVE;
2502 if( (newClientRect.right - newClientRect.left !=
2503 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2504 (newClientRect.bottom - newClientRect.top !=
2505 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2506 winpos.flags &= ~SWP_NOCLIENTSIZE;
2509 if( !(flags & SWP_NOMOVE) && (newClientRect.left != wndPtr->rectClient.left ||
2510 newClientRect.top != wndPtr->rectClient.top) )
2511 winpos.flags &= ~SWP_NOCLIENTMOVE;
2513 /* Update active DCEs
2514 * TODO: Optimize conditions that trigger DCE update.
2517 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2518 wndPtr->dwStyle & WS_VISIBLE) ||
2519 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2523 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2524 DCE_InvalidateDCE(wndPtr, &rect);
2527 /* change geometry */
2529 oldWindowRect = wndPtr->rectWindow;
2531 if (X11DRV_WND_GetXWindow(wndPtr))
2533 RECT oldClientRect = wndPtr->rectClient;
2535 tempInsertAfter = winpos.hwndInsertAfter;
2537 winpos.hwndInsertAfter = hwndInsertAfter;
2539 /* postpone geometry change */
2541 if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2543 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2544 winpos.hwndInsertAfter = tempInsertAfter;
2546 else uFlags |= SMC_SETXPOS;
2548 wndPtr->rectWindow = newWindowRect;
2549 wndPtr->rectClient = newClientRect;
2551 if( !(flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW)) )
2553 if( (oldClientRect.left - oldWindowRect.left !=
2554 newClientRect.left - newWindowRect.left) ||
2555 (oldClientRect.top - oldWindowRect.top !=
2556 newClientRect.top - newWindowRect.top) ||
2557 (winpos.flags & SWP_NOCOPYBITS) )
2559 /* if the client area moved as a result of WM_NCCALCSIZE returning
2560 * obscure WVR_ALIGNxxx flags then we simply redraw the whole thing
2562 * TODO: use WINPOS_SizeMoveClean() if there is no SWP_NOCOPYBITS
2565 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, RDW_INVALIDATE |
2566 RDW_ALLCHILDREN | RDW_FRAME | RDW_ERASE, 0 );
2569 if( winpos.flags & SWP_FRAMECHANGED )
2574 if( newClientRect.right > oldClientRect.right ) /* redraw exposed client area on the right */
2576 rect.top = 0; rect.bottom = newClientRect.bottom - newClientRect.top;
2577 rect.left = oldClientRect.right - newClientRect.left;
2578 rect.right = newClientRect.right - newClientRect.left;
2580 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2581 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
2583 if( newClientRect.bottom > oldClientRect.bottom ) /* redraw exposed client area on the bottom */
2585 rect.left = 0; rect.right = ((wErase)?oldClientRect.right:newClientRect.right) - newClientRect.left;
2586 rect.top = oldClientRect.bottom - newClientRect.top;
2587 rect.bottom = newClientRect.bottom - newClientRect.top;
2589 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, 0,
2590 RDW_INVALIDATE | RDW_FRAME | RDW_ERASE | RDW_ERASENOW | RDW_ALLCHILDREN, 0 );
2592 if( !wErase ) /* just update the nonclient area */
2593 // the previous command (wndPtr->flags |= WIN_NEEDS_NCPAINT)
2594 // was not enough. Absolutly need a non client update at this point
2595 // Cannot wait for the next WM_PAINT message, particularly in the menu-bar redrawing
2596 WIN_UpdateNCArea(wndPtr,TRUE);
2599 uFlags |= SMC_NOPARENTERASE; /* X windows do not have eraseable parents */
2601 else /* not an X window */
2603 RECT oldClientRect = wndPtr->rectClient;
2605 wndPtr->rectWindow = newWindowRect;
2606 wndPtr->rectClient = newClientRect;
2608 if( oldClientRect.bottom - oldClientRect.top ==
2609 newClientRect.bottom - newClientRect.top ) result &= ~WVR_VREDRAW;
2611 if( oldClientRect.right - oldClientRect.left ==
2612 newClientRect.right - newClientRect.left ) result &= ~WVR_HREDRAW;
2614 if( !(flags & (SWP_NOREDRAW | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2616 uFlags |= ((winpos.flags & SWP_NOCOPYBITS) ||
2617 (result >= WVR_HREDRAW && result < WVR_VALIDRECTS)) ? SMC_NOCOPY : 0;
2618 uFlags |= (winpos.flags & SWP_FRAMECHANGED) ? SMC_DRAWFRAME : 0;
2620 if( (winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) != SWP_AGG_NOGEOMETRYCHANGE )
2621 uFlags = WINPOS_SizeMoveClean(wndPtr, visRgn, &oldWindowRect,
2622 &oldClientRect, uFlags);
2625 /* adjust the frame and do not erase the parent */
2627 if( winpos.flags & SWP_FRAMECHANGED ) wndPtr->flags |= WIN_NEEDS_NCPAINT;
2628 if( winpos.flags & SWP_NOZORDER ) uFlags |= SMC_NOPARENTERASE;
2631 DeleteObject(visRgn);
2634 if (flags & SWP_SHOWWINDOW)
2636 wndPtr->dwStyle |= WS_VISIBLE;
2637 if (X11DRV_WND_GetXWindow(wndPtr))
2641 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
2642 if( uFlags & SMC_SETXPOS )
2644 winpos.hwndInsertAfter = tempInsertAfter;
2647 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2649 /* If focus was set to an unmapped window, reset X focus now */
2650 focus = curr = GetFocus();
2653 WND *pFocus = WIN_FindWndPtr( focus );
2655 pFocus->pDriver->pSetFocus(pFocus);
2656 WIN_ReleaseWndPtr(pFocus);
2659 curr = GetParent(curr);
2664 if (!(flags & SWP_NOREDRAW))
2665 PAINT_RedrawWindow( winpos.hwnd, NULL, 0,
2666 RDW_INVALIDATE | RDW_ALLCHILDREN |
2667 RDW_FRAME | RDW_ERASENOW | RDW_ERASE, 0 );
2670 else if (flags & SWP_HIDEWINDOW)
2672 wndPtr->dwStyle &= ~WS_VISIBLE;
2673 if (X11DRV_WND_GetXWindow(wndPtr))
2675 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, uFlags & SMC_SETXPOS );
2676 if( uFlags & SMC_SETXPOS )
2678 winpos.hwndInsertAfter = tempInsertAfter;
2683 if (!(flags & SWP_NOREDRAW))
2684 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, &oldWindowRect,
2685 0, RDW_INVALIDATE | RDW_ALLCHILDREN |
2686 RDW_ERASE | RDW_ERASENOW, 0 );
2687 uFlags |= SMC_NOPARENTERASE;
2690 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2692 /* FIXME: This will cause the window to be activated irrespective
2693 * of whether it is owned by the same thread.
2694 * Should this behaviour be allowed in SetWindowPos?
2696 if (winpos.hwnd == hwndActive)
2697 WINPOS_ActivateOtherWindow( wndPtr );
2700 /* Activate the window */
2702 if (!(flags & SWP_NOACTIVATE))
2703 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2705 /* Repaint the window */
2707 if (X11DRV_WND_GetXWindow(wndPtr))
2708 EVENT_Synchronize(); /* Wait for all expose events */
2710 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2711 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2713 wndTemp = WIN_GetDesktop();
2714 if (!(flags & SWP_DEFERERASE) && !(uFlags & SMC_NOPARENTERASE) )
2715 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_ALLCHILDREN | RDW_ERASENOW, 0 );
2716 else if( wndPtr->parent == wndTemp && wndPtr->parent->flags & WIN_NEEDS_ERASEBKGND )
2718 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0, RDW_NOCHILDREN | RDW_ERASENOW, 0 );
2720 WIN_ReleaseDesktop();
2722 /* And last, send the WM_WINDOWPOSCHANGED message */
2724 TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2727 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2728 !(winpos.flags & SWP_NOSENDCHANGING)) )
2730 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2731 if (resync) EVENT_Synchronize ();
2736 WIN_ReleaseWndPtr(wndPtr);
2741 /***********************************************************************
2742 * BeginDeferWindowPos16 (USER.259)
2744 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2746 return BeginDeferWindowPos( count );
2750 /***********************************************************************
2751 * BeginDeferWindowPos (USER32.9)
2753 HDWP WINAPI BeginDeferWindowPos( INT count )
2758 if (count <= 0) return 0;
2759 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2760 if (!handle) return 0;
2761 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2762 pDWP->actualCount = 0;
2763 pDWP->suggestedCount = count;
2765 pDWP->wMagic = DWP_MAGIC;
2766 pDWP->hwndParent = 0;
2771 /***********************************************************************
2772 * DeferWindowPos16 (USER.260)
2774 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2775 INT16 x, INT16 y, INT16 cx, INT16 cy,
2778 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2779 x, y, cx, cy, flags );
2783 /***********************************************************************
2784 * DeferWindowPos (USER32.128)
2786 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2787 INT x, INT y, INT cx, INT cy,
2792 HDWP newhdwp = hdwp,retvalue;
2796 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2797 if (!pDWP) return 0;
2798 if (hwnd == GetDesktopWindow()) return 0;
2800 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2801 USER_HEAP_FREE( hdwp );
2805 /* Numega Bounds Checker Demo dislikes the following code.
2806 In fact, I've not been able to find any "same parent" requirement in any docu
2810 /* All the windows of a DeferWindowPos() must have the same parent */
2811 parent = pWnd->parent->hwndSelf;
2812 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2813 else if (parent != pDWP->hwndParent)
2815 USER_HEAP_FREE( hdwp );
2821 for (i = 0; i < pDWP->actualCount; i++)
2823 if (pDWP->winPos[i].hwnd == hwnd)
2825 /* Merge with the other changes */
2826 if (!(flags & SWP_NOZORDER))
2828 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2830 if (!(flags & SWP_NOMOVE))
2832 pDWP->winPos[i].x = x;
2833 pDWP->winPos[i].y = y;
2835 if (!(flags & SWP_NOSIZE))
2837 pDWP->winPos[i].cx = cx;
2838 pDWP->winPos[i].cy = cy;
2840 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2841 SWP_NOZORDER | SWP_NOREDRAW |
2842 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2844 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2850 if (pDWP->actualCount >= pDWP->suggestedCount)
2852 newhdwp = USER_HEAP_REALLOC( hdwp,
2853 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
2859 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2860 pDWP->suggestedCount++;
2862 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2863 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2864 pDWP->winPos[pDWP->actualCount].x = x;
2865 pDWP->winPos[pDWP->actualCount].y = y;
2866 pDWP->winPos[pDWP->actualCount].cx = cx;
2867 pDWP->winPos[pDWP->actualCount].cy = cy;
2868 pDWP->winPos[pDWP->actualCount].flags = flags;
2869 pDWP->actualCount++;
2872 WIN_ReleaseWndPtr(pWnd);
2877 /***********************************************************************
2878 * EndDeferWindowPos16 (USER.261)
2880 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2882 return EndDeferWindowPos( hdwp );
2886 /***********************************************************************
2887 * EndDeferWindowPos (USER32.173)
2889 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
2896 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2897 if (!pDWP) return FALSE;
2898 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2900 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
2901 winpos->x, winpos->y, winpos->cx,
2902 winpos->cy, winpos->flags ))) break;
2904 USER_HEAP_FREE( hdwp );
2909 /***********************************************************************
2910 * TileChildWindows (USER.199)
2912 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
2914 FIXME(win, "(%04x, %d): stub\n", parent, action);
2917 /***********************************************************************
2918 * CascageChildWindows (USER.198)
2920 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
2922 FIXME(win, "(%04x, %d): stub\n", parent, action);
2924 /***********************************************************************
2925 * GetProgmanWindow [USER32.289]
2927 HRESULT WINAPI GetProgmanWindow ( )
2928 { FIXME(win,"stub\n");
2931 /***********************************************************************
2932 * GetTaskmanWindow [USER32.304]
2934 HRESULT WINAPI GetTaskmanWindow ( )
2935 { FIXME(win,"stub\n");
2938 /***********************************************************************
2939 * SetProgmanWindow [USER32.522]
2941 HRESULT WINAPI SetProgmanWindow ( DWORD x )
2942 { FIXME(win,"0x%08lx stub\n",x);
2945 /***********************************************************************
2946 * SetShellWindowEx [USER32.531]
2948 HRESULT WINAPI SetShellWindowEx ( DWORD x, DWORD y )
2949 { FIXME(win,"0x%08lx 0x%08lx stub\n",x,y);
2952 /***********************************************************************
2953 * SetTaskmanWindow [USER32.537]
2955 HRESULT WINAPI SetTaskmanWindow ( DWORD x )
2956 { FIXME(win,"0x%08lx stub\n",x);