2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
9 #include "sysmetrics.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
53 #define MINMAX_NOSWP 0x00010000
55 /* ----- internal variables ----- */
57 static HWND hwndPrevActive = 0; /* Previously active window */
58 static HWND hGlobalShellWindow=0; /*the shell*/
59 static HWND hGlobalTaskmanWindow=0;
60 static HWND hGlobalProgmanWindow=0;
62 static LPCSTR atomInternalPos;
64 extern HQUEUE16 hActiveQueue;
66 /***********************************************************************
67 * WINPOS_CreateInternalPosAtom
69 BOOL WINPOS_CreateInternalPosAtom()
72 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
73 return (atomInternalPos) ? TRUE : FALSE;
76 /***********************************************************************
77 * WINPOS_CheckInternalPos
79 * Called when a window is destroyed.
81 void WINPOS_CheckInternalPos( WND* wndPtr )
84 MESSAGEQUEUE *pMsgQ = 0;
85 HWND hwnd = wndPtr->hwndSelf;
87 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
89 /* Retrieve the message queue associated with this window */
90 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
93 WARN( win, "\tMessage queue not found. Exiting!\n" );
97 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
99 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
101 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
102 WARN(win, "\tattempt to activate destroyed window!\n");
107 if( IsWindow(lpPos->hwndIconTitle) )
108 DestroyWindow( lpPos->hwndIconTitle );
109 HeapFree( SystemHeap, 0, lpPos );
112 QUEUE_Unlock( pMsgQ );
116 /***********************************************************************
119 * Find a suitable place for an iconic window.
121 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
124 short x, y, xspacing, yspacing;
126 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
127 if ((pt.x >= rectParent.left) && (pt.x + SYSMETRICS_CXICON < rectParent.right) &&
128 (pt.y >= rectParent.top) && (pt.y + SYSMETRICS_CYICON < rectParent.bottom))
129 return pt; /* The icon already has a suitable position */
131 xspacing = SYSMETRICS_CXICONSPACING;
132 yspacing = SYSMETRICS_CYICONSPACING;
134 y = rectParent.bottom;
137 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
139 /* Check if another icon already occupies this spot */
140 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
143 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
145 if ((childPtr->rectWindow.left < x + xspacing) &&
146 (childPtr->rectWindow.right >= x) &&
147 (childPtr->rectWindow.top <= y) &&
148 (childPtr->rectWindow.bottom > y - yspacing))
149 break; /* There's a window in there */
151 WIN_UpdateWndPtr(&childPtr,childPtr->next);
153 WIN_ReleaseWndPtr(childPtr);
154 if (!childPtr) /* No window was found, so it's OK for us */
156 pt.x = x + (xspacing - SYSMETRICS_CXICON) / 2;
157 pt.y = y - (yspacing + SYSMETRICS_CYICON) / 2;
166 /***********************************************************************
167 * ArrangeIconicWindows16 (USER.170)
169 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
171 return ArrangeIconicWindows(parent);
173 /***********************************************************************
174 * ArrangeIconicWindows (USER32.7)
176 UINT WINAPI ArrangeIconicWindows( HWND parent )
180 INT x, y, xspacing, yspacing;
182 GetClientRect( parent, &rectParent );
184 y = rectParent.bottom;
185 xspacing = SYSMETRICS_CXICONSPACING;
186 yspacing = SYSMETRICS_CYICONSPACING;
188 hwndChild = GetWindow( parent, GW_CHILD );
191 if( IsIconic( hwndChild ) )
193 WND *wndPtr = WIN_FindWndPtr(hwndChild);
195 WINPOS_ShowIconTitle( wndPtr, FALSE );
197 SetWindowPos( hwndChild, 0, x + (xspacing - SYSMETRICS_CXICON) / 2,
198 y - yspacing - SYSMETRICS_CYICON/2, 0, 0,
199 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
200 if( IsWindow(hwndChild) )
201 WINPOS_ShowIconTitle(wndPtr , TRUE );
202 WIN_ReleaseWndPtr(wndPtr);
204 if (x <= rectParent.right - xspacing) x += xspacing;
211 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
217 /***********************************************************************
218 * SwitchToThisWindow16 (USER.172)
220 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
222 SwitchToThisWindow( hwnd, restore );
226 /***********************************************************************
227 * SwitchToThisWindow (USER32.539)
229 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
231 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
235 /***********************************************************************
236 * GetWindowRect16 (USER.32)
238 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
240 WND * wndPtr = WIN_FindWndPtr( hwnd );
243 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
244 if (wndPtr->dwStyle & WS_CHILD)
245 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
246 WIN_ReleaseWndPtr(wndPtr);
250 /***********************************************************************
251 * GetWindowRect (USER32.308)
253 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
255 WND * wndPtr = WIN_FindWndPtr( hwnd );
256 if (!wndPtr) return FALSE;
258 *rect = wndPtr->rectWindow;
259 if (wndPtr->dwStyle & WS_CHILD)
260 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
261 WIN_ReleaseWndPtr(wndPtr);
266 /***********************************************************************
269 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
273 WND * wndPtr = WIN_FindWndPtr( hwnd );
274 if (!wndPtr) return (ERROR);
276 FIXME (win, "GetWindowRgn: doesn't really do regions\n");
278 memset (&rect, 0, sizeof(rect));
280 GetWindowRect ( hwnd, &rect );
282 FIXME (win, "Check whether a valid region here\n");
284 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
286 WIN_ReleaseWndPtr(wndPtr);
287 return (SIMPLEREGION);
290 /***********************************************************************
293 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
297 FIXME (win, "SetWindowRgn: stub\n");
301 /***********************************************************************
304 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
308 FIXME (win, "SetWindowRgn16: stub\n");
313 /***********************************************************************
314 * GetClientRect16 (USER.33)
316 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
318 WND * wndPtr = WIN_FindWndPtr( hwnd );
320 rect->left = rect->top = rect->right = rect->bottom = 0;
323 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
324 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
326 WIN_ReleaseWndPtr(wndPtr);
330 /***********************************************************************
331 * GetClientRect (USER.220)
333 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
335 WND * wndPtr = WIN_FindWndPtr( hwnd );
337 rect->left = rect->top = rect->right = rect->bottom = 0;
338 if (!wndPtr) return FALSE;
339 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
340 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
342 WIN_ReleaseWndPtr(wndPtr);
347 /*******************************************************************
348 * ClientToScreen16 (USER.28)
350 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
352 MapWindowPoints16( hwnd, 0, lppnt, 1 );
356 /*******************************************************************
357 * ClientToScreen (USER32.52)
359 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
361 MapWindowPoints( hwnd, 0, lppnt, 1 );
366 /*******************************************************************
367 * ScreenToClient16 (USER.29)
369 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
371 MapWindowPoints16( 0, hwnd, lppnt, 1 );
375 /*******************************************************************
376 * ScreenToClient (USER32.447)
378 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
380 MapWindowPoints( 0, hwnd, lppnt, 1 );
385 /***********************************************************************
386 * WINPOS_WindowFromPoint
388 * Find the window and hittest for a given point.
390 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
393 INT16 hittest = HTERROR;
398 wndPtr = WIN_LockWndPtr(wndScope->child);
400 if( wndScope->flags & WIN_MANAGED )
402 /* In managed mode we have to check wndScope first as it is also
403 * a window which received the mouse event. */
405 if( wndScope->dwStyle & WS_DISABLED )
410 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
411 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
414 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
420 /* If point is in window, and window is visible, and it */
421 /* is enabled (or it's a top-level window), then explore */
422 /* its children. Otherwise, go to the next window. */
424 if ((wndPtr->dwStyle & WS_VISIBLE) &&
425 (!(wndPtr->dwStyle & WS_DISABLED) ||
426 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
427 (xy.x >= wndPtr->rectWindow.left) &&
428 (xy.x < wndPtr->rectWindow.right) &&
429 (xy.y >= wndPtr->rectWindow.top) &&
430 (xy.y < wndPtr->rectWindow.bottom))
432 *ppWnd = wndPtr; /* Got a suitable window */
434 /* If window is minimized or disabled, return at once */
435 if (wndPtr->dwStyle & WS_MINIMIZE)
437 retvalue = HTCAPTION;
440 if (wndPtr->dwStyle & WS_DISABLED)
446 /* If point is not in client area, ignore the children */
447 if ((xy.x < wndPtr->rectClient.left) ||
448 (xy.x >= wndPtr->rectClient.right) ||
449 (xy.y < wndPtr->rectClient.top) ||
450 (xy.y >= wndPtr->rectClient.bottom)) break;
452 xy.x -= wndPtr->rectClient.left;
453 xy.y -= wndPtr->rectClient.top;
454 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
458 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
463 /* If nothing found, try the scope window */
464 if (!*ppWnd) *ppWnd = wndScope;
466 /* Send the WM_NCHITTEST message (only if to the same task) */
467 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
469 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
470 0, MAKELONG( pt.x, pt.y ) );
471 if (hittest != HTTRANSPARENT)
473 retvalue = hittest; /* Found the window */
483 /* If no children found in last search, make point relative to parent */
486 xy.x += (*ppWnd)->rectClient.left;
487 xy.y += (*ppWnd)->rectClient.top;
490 /* Restart the search from the next sibling */
491 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
492 *ppWnd = (*ppWnd)->parent;
496 WIN_ReleaseWndPtr(wndPtr);
501 /*******************************************************************
502 * WindowFromPoint16 (USER.30)
504 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
507 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
508 WIN_ReleaseDesktop();
509 return pWnd->hwndSelf;
513 /*******************************************************************
514 * WindowFromPoint (USER32.582)
516 HWND WINAPI WindowFromPoint( POINT pt )
520 CONV_POINT32TO16( &pt, &pt16 );
521 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
522 WIN_ReleaseDesktop();
523 return (HWND)pWnd->hwndSelf;
527 /*******************************************************************
528 * ChildWindowFromPoint16 (USER.191)
530 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
533 CONV_POINT16TO32( &pt, &pt32 );
534 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
538 /*******************************************************************
539 * ChildWindowFromPoint (USER32.49)
541 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
543 /* pt is in the client coordinates */
545 WND* wnd = WIN_FindWndPtr(hwndParent);
551 /* get client rect fast */
552 rect.top = rect.left = 0;
553 rect.right = wnd->rectClient.right - wnd->rectClient.left;
554 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
556 if (!PtInRect( &rect, pt ))
561 WIN_UpdateWndPtr(&wnd,wnd->child);
564 if (PtInRect( &wnd->rectWindow, pt ))
566 retvalue = wnd->hwndSelf;
569 WIN_UpdateWndPtr(&wnd,wnd->next);
571 retvalue = hwndParent;
573 WIN_ReleaseWndPtr(wnd);
577 /*******************************************************************
578 * ChildWindowFromPointEx16 (USER.50)
580 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
583 CONV_POINT16TO32( &pt, &pt32 );
584 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
588 /*******************************************************************
589 * ChildWindowFromPointEx32 (USER32.50)
591 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
594 /* pt is in the client coordinates */
596 WND* wnd = WIN_FindWndPtr(hwndParent);
602 /* get client rect fast */
603 rect.top = rect.left = 0;
604 rect.right = wnd->rectClient.right - wnd->rectClient.left;
605 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
607 if (!PtInRect( &rect, pt ))
612 WIN_UpdateWndPtr(&wnd,wnd->child);
616 if (PtInRect( &wnd->rectWindow, pt )) {
617 if ( (uFlags & CWP_SKIPINVISIBLE) &&
618 !(wnd->dwStyle & WS_VISIBLE) );
619 else if ( (uFlags & CWP_SKIPDISABLED) &&
620 (wnd->dwStyle & WS_DISABLED) );
621 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
622 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
625 retvalue = wnd->hwndSelf;
628 WIN_UpdateWndPtr(&wnd,wnd->next);
632 retvalue = hwndParent;
634 WIN_ReleaseWndPtr(wnd);
639 /*******************************************************************
640 * WINPOS_GetWinOffset
642 * Calculate the offset between the origin of the two windows. Used
643 * to implement MapWindowPoints.
645 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
650 offset->x = offset->y = 0;
651 if (hwndFrom == hwndTo ) return;
653 /* Translate source window origin to screen coords */
656 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
658 ERR(win,"bad hwndFrom = %04x\n",hwndFrom);
661 while (wndPtr->parent)
663 offset->x += wndPtr->rectClient.left;
664 offset->y += wndPtr->rectClient.top;
665 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
667 WIN_ReleaseWndPtr(wndPtr);
670 /* Translate origin to destination window coords */
673 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
675 ERR(win,"bad hwndTo = %04x\n", hwndTo );
678 while (wndPtr->parent)
680 offset->x -= wndPtr->rectClient.left;
681 offset->y -= wndPtr->rectClient.top;
682 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
684 WIN_ReleaseWndPtr(wndPtr);
689 /*******************************************************************
690 * MapWindowPoints16 (USER.258)
692 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
693 LPPOINT16 lppt, UINT16 count )
697 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
707 /*******************************************************************
708 * MapWindowPoints (USER32.386)
710 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
711 LPPOINT lppt, UINT count )
715 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
722 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
726 /***********************************************************************
727 * IsIconic16 (USER.31)
729 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
731 return IsIconic(hWnd);
735 /***********************************************************************
736 * IsIconic (USER32.345)
738 BOOL WINAPI IsIconic(HWND hWnd)
741 WND * wndPtr = WIN_FindWndPtr(hWnd);
742 if (wndPtr == NULL) return FALSE;
743 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
744 WIN_ReleaseWndPtr(wndPtr);
749 /***********************************************************************
750 * IsZoomed (USER.272)
752 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
754 return IsZoomed(hWnd);
758 /***********************************************************************
759 * IsZoomed (USER.352)
761 BOOL WINAPI IsZoomed(HWND hWnd)
764 WND * wndPtr = WIN_FindWndPtr(hWnd);
765 if (wndPtr == NULL) return FALSE;
766 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
767 WIN_ReleaseWndPtr(wndPtr);
772 /*******************************************************************
773 * GetActiveWindow (USER.60)
775 HWND16 WINAPI GetActiveWindow16(void)
777 return (HWND16)GetActiveWindow();
780 /*******************************************************************
781 * GetActiveWindow (USER32.205)
783 HWND WINAPI GetActiveWindow(void)
785 MESSAGEQUEUE *pCurMsgQ = 0;
788 /* Get the messageQ for the current thread */
789 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
791 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
795 /* Return the current active window from the perQ data of the current message Q */
796 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
798 QUEUE_Unlock( pCurMsgQ );
803 /*******************************************************************
806 static BOOL WINPOS_CanActivate(WND* pWnd)
808 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
809 == WS_VISIBLE) ) return TRUE;
814 /*******************************************************************
815 * SetActiveWindow16 (USER.59)
817 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
819 return SetActiveWindow(hwnd);
823 /*******************************************************************
824 * SetActiveWindow (USER32.463)
826 HWND WINAPI SetActiveWindow( HWND hwnd )
829 WND *wndPtr = WIN_FindWndPtr( hwnd );
830 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
832 if ( !WINPOS_CanActivate(wndPtr) )
838 /* Get the messageQ for the current thread */
839 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
841 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
845 /* Retrieve the message queue associated with this window */
846 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
849 WARN( win, "\tWindow message queue not found. Exiting!\n" );
853 /* Make sure that the window is associated with the calling threads
854 * message queue. It must share the same perQ data.
857 if ( pCurMsgQ->pQData != pMsgQ->pQData )
860 /* Save current active window */
861 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
863 WINPOS_SetActiveWindow( hwnd, 0, 0 );
866 /* Unlock the queues before returning */
868 QUEUE_Unlock( pMsgQ );
870 QUEUE_Unlock( pCurMsgQ );
873 WIN_ReleaseWndPtr(wndPtr);
878 /*******************************************************************
879 * GetForegroundWindow16 (USER.608)
881 HWND16 WINAPI GetForegroundWindow16(void)
883 return (HWND16)GetForegroundWindow();
887 /*******************************************************************
888 * SetForegroundWindow16 (USER.609)
890 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
892 return SetForegroundWindow( hwnd );
896 /*******************************************************************
897 * GetForegroundWindow (USER32.241)
899 HWND WINAPI GetForegroundWindow(void)
901 return GetActiveWindow();
905 /*******************************************************************
906 * SetForegroundWindow (USER32.482)
908 BOOL WINAPI SetForegroundWindow( HWND hwnd )
910 SetActiveWindow( hwnd );
915 /*******************************************************************
916 * GetShellWindow16 (USER.600)
918 HWND16 WINAPI GetShellWindow16(void)
920 return GetShellWindow();
923 /*******************************************************************
924 * SetShellWindow (USER32.504)
926 HWND WINAPI SetShellWindow(HWND hwndshell)
927 { WARN(win, "(hWnd=%08x) semi stub\n",hwndshell );
929 hGlobalShellWindow = hwndshell;
930 return hGlobalShellWindow;
934 /*******************************************************************
935 * GetShellWindow (USER32.287)
937 HWND WINAPI GetShellWindow(void)
938 { WARN(win, "(hWnd=%x) semi stub\n",hGlobalShellWindow );
940 return hGlobalShellWindow;
944 /***********************************************************************
945 * BringWindowToTop16 (USER.45)
947 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
949 return BringWindowToTop(hwnd);
953 /***********************************************************************
954 * BringWindowToTop (USER32.11)
956 BOOL WINAPI BringWindowToTop( HWND hwnd )
958 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
962 /***********************************************************************
963 * MoveWindow16 (USER.56)
965 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
968 return MoveWindow(hwnd,x,y,cx,cy,repaint);
972 /***********************************************************************
973 * MoveWindow (USER32.399)
975 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
978 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
979 if (!repaint) flags |= SWP_NOREDRAW;
980 TRACE(win, "%04x %d,%d %dx%d %d\n",
981 hwnd, x, y, cx, cy, repaint );
982 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
985 /***********************************************************************
986 * WINPOS_InitInternalPos
988 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
991 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
995 /* this happens when the window is minimized/maximized
996 * for the first time (rectWindow is not adjusted yet) */
998 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
999 if( !lpPos ) return NULL;
1001 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1002 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1003 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1004 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1007 if( wnd->dwStyle & WS_MINIMIZE )
1008 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1009 else if( wnd->dwStyle & WS_MAXIMIZE )
1010 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1011 else if( restoreRect )
1012 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1017 /***********************************************************************
1018 * WINPOS_RedrawIconTitle
1020 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1022 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1025 if( lpPos->hwndIconTitle )
1027 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1028 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1035 /***********************************************************************
1036 * WINPOS_ShowIconTitle
1038 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1040 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1042 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1044 HWND16 hWnd = lpPos->hwndIconTitle;
1046 TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1049 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1052 pWnd = WIN_FindWndPtr(hWnd);
1054 if( !(pWnd->dwStyle & WS_VISIBLE) )
1056 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1057 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1058 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1060 WIN_ReleaseWndPtr(pWnd);
1062 else ShowWindow( hWnd, SW_HIDE );
1067 /*******************************************************************
1068 * WINPOS_GetMinMaxInfo
1070 * Get the minimized and maximized information for a window.
1072 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1073 POINT *minTrack, POINT *maxTrack )
1075 LPINTERNALPOS lpPos;
1079 /* Compute default values */
1081 MinMax.ptMaxSize.x = SYSMETRICS_CXSCREEN;
1082 MinMax.ptMaxSize.y = SYSMETRICS_CYSCREEN;
1083 MinMax.ptMinTrackSize.x = SYSMETRICS_CXMINTRACK;
1084 MinMax.ptMinTrackSize.y = SYSMETRICS_CYMINTRACK;
1085 MinMax.ptMaxTrackSize.x = SYSMETRICS_CXSCREEN;
1086 MinMax.ptMaxTrackSize.y = SYSMETRICS_CYSCREEN;
1088 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1089 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1091 xinc = SYSMETRICS_CXDLGFRAME;
1092 yinc = SYSMETRICS_CYDLGFRAME;
1097 if (HAS_THICKFRAME(wndPtr->dwStyle))
1099 xinc += SYSMETRICS_CXFRAME;
1100 yinc += SYSMETRICS_CYFRAME;
1102 if (wndPtr->dwStyle & WS_BORDER)
1104 xinc += SYSMETRICS_CXBORDER;
1105 yinc += SYSMETRICS_CYBORDER;
1108 MinMax.ptMaxSize.x += 2 * xinc;
1109 MinMax.ptMaxSize.y += 2 * yinc;
1111 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1112 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1113 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1116 MinMax.ptMaxPosition.x = -xinc;
1117 MinMax.ptMaxPosition.y = -yinc;
1120 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1122 /* Some sanity checks */
1124 TRACE(win,"%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1125 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1126 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1127 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1128 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1129 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1130 MinMax.ptMinTrackSize.x );
1131 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1132 MinMax.ptMinTrackSize.y );
1134 if (maxSize) *maxSize = MinMax.ptMaxSize;
1135 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1136 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1137 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1140 /***********************************************************************
1141 * WINPOS_MinMaximize
1143 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1144 * This function assumes that 'cmd' is different from the current window
1147 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;
1157 size.y = wndPtr->rectWindow.top;
1159 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1161 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1163 if( wndPtr->dwStyle & WS_MINIMIZE )
1165 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1166 return (SWP_NOSIZE | SWP_NOMOVE);
1167 swpFlags |= SWP_NOCOPYBITS;
1172 if( wndPtr->dwStyle & WS_MAXIMIZE)
1174 wndPtr->flags |= WIN_RESTORE_MAX;
1175 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1178 wndPtr->flags &= ~WIN_RESTORE_MAX;
1179 wndPtr->dwStyle |= WS_MINIMIZE;
1181 if( wndPtr->flags & WIN_NATIVE )
1182 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1183 swpFlags |= MINMAX_NOSWP;
1185 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1187 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1188 SYSMETRICS_CXICON, SYSMETRICS_CYICON );
1189 swpFlags |= SWP_NOCOPYBITS;
1193 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1194 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1195 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1197 if( wndPtr->dwStyle & WS_MINIMIZE )
1199 if( wndPtr->flags & WIN_NATIVE )
1200 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1201 swpFlags |= MINMAX_NOSWP;
1203 WINPOS_ShowIconTitle( wndPtr, FALSE );
1204 wndPtr->dwStyle &= ~WS_MINIMIZE;
1206 wndPtr->dwStyle |= WS_MAXIMIZE;
1208 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1213 if( wndPtr->dwStyle & WS_MINIMIZE )
1215 if( wndPtr->flags & WIN_NATIVE )
1216 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1217 swpFlags |= MINMAX_NOSWP;
1219 wndPtr->dwStyle &= ~WS_MINIMIZE;
1220 WINPOS_ShowIconTitle( wndPtr, FALSE );
1222 if( wndPtr->flags & WIN_RESTORE_MAX)
1224 /* Restore to maximized position */
1225 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1226 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1227 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1228 wndPtr->dwStyle |= WS_MAXIMIZE;
1229 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1234 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1235 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1237 /* Restore to normal position */
1239 *lpRect = lpPos->rectNormal;
1240 lpRect->right -= lpRect->left;
1241 lpRect->bottom -= lpRect->top;
1245 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1249 /***********************************************************************
1250 * ShowWindowAsync (USER32.535)
1252 * doesn't wait; returns immediately.
1253 * used by threads to toggle windows in other (possibly hanging) threads
1255 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1257 /* FIXME: does ShowWindow() return immediately ? */
1258 return ShowWindow(hwnd, cmd);
1262 /***********************************************************************
1263 * ShowWindow16 (USER.42)
1265 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1267 return ShowWindow(hwnd,cmd);
1271 /***********************************************************************
1272 * ShowWindow (USER32.534)
1274 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1276 WND* wndPtr = WIN_FindWndPtr( hwnd );
1277 BOOL wasVisible, showFlag;
1278 RECT16 newPos = {0, 0, 0, 0};
1281 if (!wndPtr) return FALSE;
1283 TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1285 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1290 if (!wasVisible) goto END;;
1291 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1292 SWP_NOACTIVATE | SWP_NOZORDER;
1293 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
1295 /* Revert focus to parent */
1296 SetFocus( GetParent(hwnd) );
1300 case SW_SHOWMINNOACTIVE:
1301 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1303 case SW_SHOWMINIMIZED:
1304 swp |= SWP_SHOWWINDOW;
1307 swp |= SWP_FRAMECHANGED;
1308 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1309 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1310 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1313 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1314 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1315 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1316 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1317 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1321 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1324 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1327 case SW_SHOWNOACTIVATE:
1328 swp |= SWP_NOZORDER;
1329 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1331 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1332 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1334 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1336 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1337 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1338 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1342 showFlag = (cmd != SW_HIDE);
1343 if (showFlag != wasVisible)
1345 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1346 if (!IsWindow( hwnd )) goto END;
1349 if ((wndPtr->dwStyle & WS_CHILD) &&
1350 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1351 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1353 /* Don't call SetWindowPos() on invisible child windows */
1354 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1355 else wndPtr->dwStyle |= WS_VISIBLE;
1359 /* We can't activate a child window */
1360 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1361 if (!(swp & MINMAX_NOSWP))
1362 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1363 newPos.right, newPos.bottom, LOWORD(swp) );
1364 if (!IsWindow( hwnd )) goto END;
1365 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1368 if (wndPtr->flags & WIN_NEED_SIZE)
1370 /* should happen only in CreateWindowEx() */
1371 int wParam = SIZE_RESTORED;
1373 wndPtr->flags &= ~WIN_NEED_SIZE;
1374 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1375 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1376 SendMessageA( hwnd, WM_SIZE, wParam,
1377 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1378 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1379 SendMessageA( hwnd, WM_MOVE, 0,
1380 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1384 WIN_ReleaseWndPtr(wndPtr);
1389 /***********************************************************************
1390 * GetInternalWindowPos16 (USER.460)
1392 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1395 WINDOWPLACEMENT16 wndpl;
1396 if (GetWindowPlacement16( hwnd, &wndpl ))
1398 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1399 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1400 return wndpl.showCmd;
1406 /***********************************************************************
1407 * GetInternalWindowPos (USER32.245)
1409 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1412 WINDOWPLACEMENT wndpl;
1413 if (GetWindowPlacement( hwnd, &wndpl ))
1415 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1416 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1417 return wndpl.showCmd;
1422 /***********************************************************************
1423 * GetWindowPlacement16 (USER.370)
1425 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1427 WND *pWnd = WIN_FindWndPtr( hwnd );
1428 LPINTERNALPOS lpPos;
1430 if(!pWnd ) return FALSE;
1432 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1433 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1434 wndpl->length = sizeof(*wndpl);
1435 if( pWnd->dwStyle & WS_MINIMIZE )
1436 wndpl->showCmd = SW_SHOWMINIMIZED;
1438 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1439 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1440 if( pWnd->flags & WIN_RESTORE_MAX )
1441 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1444 wndpl->ptMinPosition = lpPos->ptIconPos;
1445 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1446 wndpl->rcNormalPosition = lpPos->rectNormal;
1448 WIN_ReleaseWndPtr(pWnd);
1453 /***********************************************************************
1454 * GetWindowPlacement (USER32.307)
1457 * Fails if wndpl->length of Win95 (!) apps is invalid.
1459 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1463 WINDOWPLACEMENT16 wpl;
1464 wpl.length = sizeof(wpl);
1465 if( GetWindowPlacement16( hwnd, &wpl ) )
1467 pwpl32->length = sizeof(*pwpl32);
1468 pwpl32->flags = wpl.flags;
1469 pwpl32->showCmd = wpl.showCmd;
1470 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1471 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1472 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1480 /***********************************************************************
1481 * WINPOS_SetPlacement
1483 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1486 WND *pWnd = WIN_FindWndPtr( hwnd );
1489 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1490 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1492 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1493 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1494 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1496 if( pWnd->dwStyle & WS_MINIMIZE )
1498 WINPOS_ShowIconTitle( pWnd, FALSE );
1499 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1500 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1501 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1503 else if( pWnd->dwStyle & WS_MAXIMIZE )
1505 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1506 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1507 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1509 else if( flags & PLACE_RECT )
1510 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1511 lpPos->rectNormal.right - lpPos->rectNormal.left,
1512 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1513 SWP_NOZORDER | SWP_NOACTIVATE );
1515 ShowWindow( hwnd, wndpl->showCmd );
1516 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1518 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1520 /* SDK: ...valid only the next time... */
1521 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1523 WIN_ReleaseWndPtr(pWnd);
1530 /***********************************************************************
1531 * SetWindowPlacement16 (USER.371)
1533 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1535 return WINPOS_SetPlacement( hwnd, wndpl,
1536 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1539 /***********************************************************************
1540 * SetWindowPlacement (USER32.519)
1543 * Fails if wndpl->length of Win95 (!) apps is invalid.
1545 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1549 WINDOWPLACEMENT16 wpl;
1551 wpl.length = sizeof(WINDOWPLACEMENT16);
1552 wpl.flags = pwpl32->flags;
1553 wpl.showCmd = pwpl32->showCmd;
1554 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1555 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1556 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1557 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1558 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1559 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1560 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1561 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1563 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1569 /***********************************************************************
1570 * SetInternalWindowPos16 (USER.461)
1572 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1573 LPRECT16 rect, LPPOINT16 pt )
1575 if( IsWindow16(hwnd) )
1577 WINDOWPLACEMENT16 wndpl;
1580 wndpl.length = sizeof(wndpl);
1581 wndpl.showCmd = showCmd;
1582 wndpl.flags = flags = 0;
1587 wndpl.flags |= WPF_SETMINPOSITION;
1588 wndpl.ptMinPosition = *pt;
1592 flags |= PLACE_RECT;
1593 wndpl.rcNormalPosition = *rect;
1595 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1600 /***********************************************************************
1601 * SetInternalWindowPos (USER32.483)
1603 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1604 LPRECT rect, LPPOINT pt )
1606 if( IsWindow(hwnd) )
1608 WINDOWPLACEMENT16 wndpl;
1611 wndpl.length = sizeof(wndpl);
1612 wndpl.showCmd = showCmd;
1613 wndpl.flags = flags = 0;
1618 wndpl.flags |= WPF_SETMINPOSITION;
1619 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1623 flags |= PLACE_RECT;
1624 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1626 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1630 /*******************************************************************
1631 * WINPOS_SetActiveWindow
1633 * SetActiveWindow() back-end. This is the only function that
1634 * can assign active status to a window. It must be called only
1635 * for the top level windows.
1637 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1639 CBTACTIVATESTRUCT16* cbtStruct;
1640 WND* wndPtr=0, *wndTemp;
1641 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1642 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1644 HWND hwndActive = 0;
1647 /* Get current active window from the active queue */
1650 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1651 if ( pOldActiveQueue )
1652 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1655 /* paranoid checks */
1656 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1659 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1662 wndPtr = WIN_FindWndPtr(hWnd);
1663 hOldActiveQueue = hActiveQueue;
1665 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1667 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1668 WIN_ReleaseWndPtr(wndTemp);
1671 TRACE(win,"no current active window.\n");
1673 /* call CBT hook chain */
1674 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1676 cbtStruct->fMouse = fMouse;
1677 cbtStruct->hWndActive = hwndActive;
1678 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1679 (LPARAM)SEGPTR_GET(cbtStruct) );
1680 SEGPTR_FREE(cbtStruct);
1681 if (bRet) goto CLEANUP_END;
1684 /* set prev active wnd to current active wnd and send notification */
1685 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1687 MESSAGEQUEUE *pTempActiveQueue = 0;
1689 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1691 if (GetSysModalWindow16() != hWnd)
1693 /* disregard refusal if hWnd is sysmodal */
1696 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1697 MAKEWPARAM( WA_INACTIVE, wIconized ),
1700 /* check if something happened during message processing
1701 * (global active queue may have changed)
1703 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1704 if(!pTempActiveQueue)
1707 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1708 QUEUE_Unlock( pTempActiveQueue );
1709 if( hwndPrevActive != hwndActive )
1713 /* Set new active window in the message queue */
1717 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1718 if ( pNewActiveQueue )
1719 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1721 else /* have to do this or MDI frame activation goes to hell */
1722 if( pOldActiveQueue )
1723 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1725 /* send palette messages */
1726 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1727 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1729 /* if prev wnd is minimized redraw icon title */
1730 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1732 /* managed windows will get ConfigureNotify event */
1733 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1735 /* check Z-order and bring hWnd to the top */
1736 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1738 if (wndTemp->dwStyle & WS_VISIBLE) break;
1740 WIN_ReleaseDesktop();
1741 WIN_ReleaseWndPtr(wndTemp);
1743 if( wndTemp != wndPtr )
1744 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1745 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1746 if (!IsWindow(hWnd))
1750 /* Get a handle to the new active queue */
1751 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1753 /* send WM_ACTIVATEAPP if necessary */
1754 if (hOldActiveQueue != hNewActiveQueue)
1756 WND **list, **ppWnd;
1757 WND *pDesktop = WIN_GetDesktop();
1759 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1761 for (ppWnd = list; *ppWnd; ppWnd++)
1763 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1765 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1766 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1767 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1769 WIN_ReleaseWinArray(list);
1772 hActiveQueue = hNewActiveQueue;
1774 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1776 for (ppWnd = list; *ppWnd; ppWnd++)
1778 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1780 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1781 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1782 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1784 WIN_ReleaseWinArray(list);
1786 WIN_ReleaseDesktop();
1788 if (!IsWindow(hWnd)) goto CLEANUP;
1793 /* walk up to the first unowned window */
1794 wndTemp = WIN_LockWndPtr(wndPtr);
1795 while (wndTemp->owner)
1797 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1799 /* and set last active owned popup */
1800 wndTemp->hwndLastActive = hWnd;
1802 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1803 WIN_ReleaseWndPtr(wndTemp);
1804 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1805 SendMessageA( hWnd, WM_ACTIVATE,
1806 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1807 (LPARAM)hwndPrevActive );
1808 if( !IsWindow(hWnd) ) goto CLEANUP;
1811 /* change focus if possible */
1812 if( fChangeFocus && GetFocus() )
1813 if( WIN_GetTopParent(GetFocus()) != hwndActive )
1814 FOCUS_SwitchFocus( pNewActiveQueue, GetFocus(),
1815 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1820 if( !hwndPrevActive && wndPtr )
1821 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1823 /* if active wnd is minimized redraw icon title */
1824 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1826 bRet = (hWnd == hwndActive); /* Success? */
1828 CLEANUP: /* Unlock the message queues before returning */
1830 if ( pNewActiveQueue )
1831 QUEUE_Unlock( pNewActiveQueue );
1835 if ( pOldActiveQueue )
1836 QUEUE_Unlock( pOldActiveQueue );
1838 WIN_ReleaseWndPtr(wndPtr);
1842 /*******************************************************************
1843 * WINPOS_ActivateOtherWindow
1845 * Activates window other than pWnd.
1847 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1851 HWND hwndActive = 0;
1853 /* Get current active window from the active queue */
1856 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1859 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1860 QUEUE_Unlock( pActiveQueue );
1864 if( pWnd->hwndSelf == hwndPrevActive )
1867 if( hwndActive != pWnd->hwndSelf &&
1868 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1871 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1872 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1874 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1876 WIN_ReleaseWndPtr(pWndTo);
1877 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1879 while( !WINPOS_CanActivate(pWndTo) )
1881 /* by now owned windows should've been taken care of */
1882 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1883 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1884 if( !pWndTo ) break;
1886 WIN_ReleaseWndPtr(pWndPtr);
1889 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1891 /* switch desktop queue to current active */
1894 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1895 WIN_ReleaseWndPtr(pWndTo);
1896 WIN_ReleaseDesktop();
1903 /*******************************************************************
1904 * WINPOS_ChangeActiveWindow
1907 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1909 WND *wndPtr, *wndTemp;
1911 HWND hwndActive = 0;
1913 /* Get current active window from the active queue */
1916 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1919 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1920 QUEUE_Unlock( pActiveQueue );
1925 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1927 wndPtr = WIN_FindWndPtr(hWnd);
1928 if( !wndPtr ) return FALSE;
1930 /* child windows get WM_CHILDACTIVATE message */
1931 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1933 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1937 if( hWnd == hwndActive )
1943 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1949 /* switch desktop queue to current active */
1950 wndTemp = WIN_GetDesktop();
1951 if( wndPtr->parent == wndTemp)
1952 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1953 WIN_ReleaseDesktop();
1957 WIN_ReleaseWndPtr(wndPtr);
1962 /***********************************************************************
1963 * WINPOS_SendNCCalcSize
1965 * Send a WM_NCCALCSIZE message to a window.
1966 * All parameters are read-only except newClientRect.
1967 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1968 * when calcValidRect is TRUE.
1970 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1971 RECT *newWindowRect, RECT *oldWindowRect,
1972 RECT *oldClientRect, WINDOWPOS *winpos,
1973 RECT *newClientRect )
1975 NCCALCSIZE_PARAMS params;
1976 WINDOWPOS winposCopy;
1979 params.rgrc[0] = *newWindowRect;
1982 winposCopy = *winpos;
1983 params.rgrc[1] = *oldWindowRect;
1984 params.rgrc[2] = *oldClientRect;
1985 params.lppos = &winposCopy;
1987 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
1989 TRACE(win, "%d,%d-%d,%d\n",
1990 params.rgrc[0].left, params.rgrc[0].top,
1991 params.rgrc[0].right, params.rgrc[0].bottom );
1992 *newClientRect = params.rgrc[0];
1997 /***********************************************************************
1998 * WINPOS_HandleWindowPosChanging16
2000 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2002 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2004 POINT maxSize, minTrack;
2005 if (winpos->flags & SWP_NOSIZE) return 0;
2006 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2007 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2009 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2010 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2011 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2012 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2014 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2015 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2022 /***********************************************************************
2023 * WINPOS_HandleWindowPosChanging
2025 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2027 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2030 if (winpos->flags & SWP_NOSIZE) return 0;
2031 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2032 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2034 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2035 winpos->cx = MIN( winpos->cx, maxSize.x );
2036 winpos->cy = MIN( winpos->cy, maxSize.y );
2041 /***********************************************************************
2044 * fix Z order taking into account owned popups -
2045 * basically we need to maintain them above the window that owns them
2047 * FIXME: hide/show owned popups when owner visibility changes.
2049 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2051 WND* w = WIN_LockWndPtr(pDesktop->child);
2053 WARN(win, "(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2055 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2057 /* make sure this popup stays above the owner */
2059 HWND hwndLocalPrev = HWND_TOP;
2061 if( hwndInsertAfter != HWND_TOP )
2063 while( w != wndPtr->owner )
2065 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2066 if( hwndLocalPrev == hwndInsertAfter ) break;
2067 WIN_UpdateWndPtr(&w,w->next);
2069 hwndInsertAfter = hwndLocalPrev;
2072 else if( wndPtr->dwStyle & WS_CHILD )
2075 WIN_UpdateWndPtr(&w, pDesktop->child);
2079 if( w == wndPtr ) break;
2081 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2083 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2084 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2085 hwndInsertAfter = w->hwndSelf;
2087 WIN_UpdateWndPtr(&w, w->next);
2091 WIN_ReleaseWndPtr(w);
2092 return hwndInsertAfter;
2095 /***********************************************************************
2098 * Make window look nice without excessive repainting
2100 * visible and update regions are in window coordinates
2101 * client and window rectangles are in parent client coordinates
2103 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2104 * window rects have the same origin.
2106 * Returns: uFlags and a dirty region in *pVisRgn.
2108 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2109 LPRECT lpOldWndRect,
2110 LPRECT lpOldClientRect, UINT uFlags )
2113 HRGN newVisRgn, dirtyRgn;
2114 INT my = COMPLEXREGION;
2116 TRACE(win,"\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2117 Wnd->rectWindow.left, Wnd->rectWindow.top,
2118 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2119 lpOldWndRect->left, lpOldWndRect->top,
2120 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2121 TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2122 Wnd->rectClient.left, Wnd->rectClient.top,
2123 Wnd->rectClient.right, Wnd->rectClient.bottom,
2124 lpOldClientRect->left, lpOldClientRect->top,
2125 lpOldClientRect->right,lpOldClientRect->bottom );
2127 if( Wnd->hrgnUpdate == 1 )
2128 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2130 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2131 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2133 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2134 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2136 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2140 TRACE(win,"\twon't copy anything!\n");
2142 /* set dirtyRgn to the sum of old and new visible regions
2143 * in parent client coordinates */
2145 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2146 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2148 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2150 else /* copy valid bits to a new location */
2152 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2153 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2155 /* subtract already invalid region inside Wnd from the dst region */
2157 if( Wnd->hrgnUpdate )
2158 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2161 /* check if entire window can be copied */
2163 ow = lpOldWndRect->right - lpOldWndRect->left;
2164 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2165 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2166 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2168 ocw = lpOldClientRect->right - lpOldClientRect->left;
2169 och = lpOldClientRect->bottom - lpOldClientRect->top;
2170 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2171 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2173 if( (ocw != ncw) || (och != nch) ||
2174 ( ow != nw) || ( oh != nw) ||
2175 ((lpOldClientRect->top - lpOldWndRect->top) !=
2176 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2177 ((lpOldClientRect->left - lpOldWndRect->left) !=
2178 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2180 dx = Wnd->rectClient.left - lpOldClientRect->left;
2181 dy = Wnd->rectClient.top - lpOldClientRect->top;
2183 /* restrict valid bits to the common client rect */
2185 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2186 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2187 r.right = r.left + MIN( ocw, ncw );
2188 r.bottom = r.top + MIN( och, nch );
2190 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2191 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2192 GetRgnBox( hrgnValid, &r );
2193 if( IsRectEmpty( &r ) )
2195 r = *lpOldClientRect;
2199 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2200 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2201 if( !(uFlags & SWP_EX_PAINTSELF) )
2202 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2206 if( !(uFlags & SWP_EX_PAINTSELF) )
2208 /* Move remaining regions to parent coordinates */
2209 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2210 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2213 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2215 TRACE(win,"\tcomputing dirty region!\n");
2217 /* Compute combined dirty region (old + new - valid) */
2218 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2219 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2221 /* Blt valid bits, r is the rect to copy */
2226 HDC hDC = ( uFlags & SWP_EX_PAINTSELF)
2227 ? GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2228 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS )
2229 : GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2230 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2231 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2233 if( oh > nh ) r.bottom = r.top + nh;
2234 if( ow < nw ) r.right = r.left + nw;
2236 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2238 GDI_HEAP_UNLOCK( hDC );
2240 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2241 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2245 /* *pVisRgn now points to the invalidated region */
2247 DeleteObject(newVisRgn);
2248 DeleteObject(dirtyRgn);
2252 /***********************************************************************
2253 * SWP_DoSimpleFrameChanged
2255 * NOTE: old and new client rect origins are identical, only
2256 * extents may have changed. Window extents are the same.
2258 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2264 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2266 /* FIXME: WVR alignment flags */
2268 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2272 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2273 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2274 if(!(uFlags & SWP_EX_NOCOPY))
2275 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2283 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2286 hrgn = CreateRectRgnIndirect( &rect );
2288 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2289 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2290 if(!(uFlags & SWP_EX_NOCOPY))
2291 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2295 REGION_UnionRectWithRgn( hrgn, &rect );
2298 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2300 rect = wndPtr->rectWindow;
2301 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2302 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2310 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2311 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2314 hrgn = WIN_UpdateNCRgn(wndPtr, TRUE, TRUE);
2317 DeleteObject( hrgn );
2320 /***********************************************************************
2321 * SWP_DoWinPosChanging
2323 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2324 RECT* pNewWindowRect, RECT* pNewClientRect )
2326 /* Send WM_WINDOWPOSCHANGING message */
2328 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2329 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2331 /* Calculate new position and size */
2333 *pNewWindowRect = wndPtr->rectWindow;
2334 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2335 : wndPtr->rectClient;
2337 if (!(pWinpos->flags & SWP_NOSIZE))
2339 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2340 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2342 if (!(pWinpos->flags & SWP_NOMOVE))
2344 pNewWindowRect->left = pWinpos->x;
2345 pNewWindowRect->top = pWinpos->y;
2346 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2347 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2349 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2350 pWinpos->y - wndPtr->rectWindow.top );
2353 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2357 /***********************************************************************
2360 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2361 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2365 /* Send WM_NCCALCSIZE message to get new client area */
2366 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2368 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2369 &wndPtr->rectWindow, &wndPtr->rectClient,
2370 pWinpos, pNewClientRect );
2372 /* FIXME: WVR_ALIGNxxx */
2374 if( pNewClientRect->left != wndPtr->rectClient.left ||
2375 pNewClientRect->top != wndPtr->rectClient.top )
2376 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2378 if( (pNewClientRect->right - pNewClientRect->left !=
2379 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2380 (pNewClientRect->bottom - pNewClientRect->top !=
2381 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2382 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2385 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2386 pNewClientRect->top != wndPtr->rectClient.top) )
2387 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2391 /***********************************************************************
2392 * SetWindowPos (USER.2)
2394 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2395 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2397 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2400 /***********************************************************************
2401 * SetWindowPos (USER32.520)
2403 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2404 INT x, INT y, INT cx, INT cy, WORD flags)
2407 WND * wndPtr,*wndTemp;
2408 RECT newWindowRect, newClientRect;
2409 RECT oldWindowRect, oldClientRect;
2411 UINT wvrFlags = 0, uFlags = 0;
2412 BOOL retvalue, resync = FALSE;
2413 HWND hwndActive = 0;
2415 /* Get current active window from the active queue */
2418 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2421 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2422 QUEUE_Unlock( pActiveQueue );
2426 TRACE(win,"hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2427 hwnd, x, y, x+cx, y+cy, flags);
2429 /* ------------------------------------------------------------------------ CHECKS */
2431 /* Check window handle */
2433 if (hwnd == GetDesktopWindow()) return FALSE;
2434 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2436 TRACE(win,"\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2437 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2439 /* Fix redundant flags */
2441 if(wndPtr->dwStyle & WS_VISIBLE)
2442 flags &= ~SWP_SHOWWINDOW;
2445 if (!(flags & SWP_SHOWWINDOW))
2446 flags |= SWP_NOREDRAW;
2447 flags &= ~SWP_HIDEWINDOW;
2450 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2452 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2453 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2454 flags |= SWP_NOSIZE; /* Already the right size */
2456 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2457 flags |= SWP_NOMOVE; /* Already the right position */
2459 if (hwnd == hwndActive)
2460 flags |= SWP_NOACTIVATE; /* Already active */
2463 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2465 flags &= ~SWP_NOZORDER;
2466 hwndInsertAfter = HWND_TOP;
2471 /* Check hwndInsertAfter */
2473 /* FIXME: TOPMOST not supported yet */
2474 if ((hwndInsertAfter == HWND_TOPMOST) ||
2475 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2477 /* hwndInsertAfter must be a sibling of the window */
2478 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2480 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2483 if( wnd->parent != wndPtr->parent )
2486 WIN_ReleaseWndPtr(wnd);
2489 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2491 WIN_ReleaseWndPtr(wnd);
2494 Pos: /* ------------------------------------------------------------------------ MAIN part */
2496 /* Fill the WINDOWPOS structure */
2499 winpos.hwndInsertAfter = hwndInsertAfter;
2504 winpos.flags = flags;
2506 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2508 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2510 if( wndPtr->parent == WIN_GetDesktop() )
2511 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2512 hwndInsertAfter, winpos.flags );
2513 WIN_ReleaseDesktop();
2516 if(!(wndPtr->flags & WIN_NATIVE) )
2518 if( hwndInsertAfter == HWND_TOP )
2519 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2521 if( hwndInsertAfter == HWND_BOTTOM )
2522 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2524 if( !(winpos.flags & SWP_NOZORDER) )
2525 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2526 winpos.flags |= SWP_NOZORDER;
2528 if( !(winpos.flags & SWP_NOREDRAW) &&
2529 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2530 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2532 /* get a previous visible region for SWP_CopyValidBits() */
2534 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2538 /* Common operations */
2540 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2542 if(!(winpos.flags & SWP_NOZORDER))
2544 /* upon window creation (while processing WM_NCCREATE), wndPtr->parent is set correctly
2545 * but wndPtr is not yet in wndPtr->parent->child list
2546 * in those cases (SetWindowPos called while processing WM_NCCREATE),
2547 * do not unlink/link winPtr in parent->child
2549 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2550 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2553 /* Reset active DCEs */
2555 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2556 wndPtr->dwStyle & WS_VISIBLE) ||
2557 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2561 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2562 DCE_InvalidateDCE(wndPtr, &rect);
2565 oldWindowRect = wndPtr->rectWindow;
2566 oldClientRect = wndPtr->rectClient;
2568 /* Find out if we have to redraw the whole client rect */
2570 if( oldClientRect.bottom - oldClientRect.top ==
2571 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2573 if( oldClientRect.right - oldClientRect.left ==
2574 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2576 uFlags |= ((winpos.flags & SWP_NOCOPYBITS) ||
2577 (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2578 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS))) ? SWP_EX_NOCOPY : 0;
2580 /* FIXME: actually do something with WVR_VALIDRECTS */
2582 wndPtr->rectWindow = newWindowRect;
2583 wndPtr->rectClient = newClientRect;
2585 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2587 BOOL bCallDriver = TRUE;
2588 HWND tempInsertAfter = winpos.hwndInsertAfter;
2590 winpos.hwndInsertAfter = hwndInsertAfter;
2592 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2594 /* This is the only place where we need to force repainting of the contents
2595 of windows created by the host window system, all other cases go through the
2596 expose event handling */
2598 if( (winpos.flags & SWP_FRAMECHANGED) )
2602 if( (x = (newWindowRect.right - newWindowRect.left)) == (oldWindowRect.right - oldWindowRect.left) &&
2603 (y = (newWindowRect.bottom - newWindowRect.top)) == (oldWindowRect.bottom - oldWindowRect.top) )
2606 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2607 winpos.hwndInsertAfter = tempInsertAfter;
2608 bCallDriver = FALSE;
2610 if( winpos.flags & SWP_NOCLIENTMOVE )
2611 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2614 /* client area moved but window extents remained the same, copy valid bits */
2616 visRgn = CreateRectRgn( 0, 0, x, y );
2617 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2618 uFlags | SWP_EX_PAINTSELF );
2626 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2628 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2629 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2630 !(uFlags & SWP_EX_NOCOPY) )
2632 /* The origin of the client rect didn't move so we can try to repaint
2633 * only the nonclient area by setting bit gravity hint for the host window system.
2636 if( !(wndPtr->flags & WIN_MANAGED) )
2638 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2639 newWindowRect.bottom - newWindowRect.top);
2640 RECT rcn = newClientRect;
2641 RECT rco = oldClientRect;
2643 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2644 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2645 IntersectRect( &rcn, &rcn, &rco );
2646 visRgn = CreateRectRgnIndirect( &rcn );
2647 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2648 DeleteObject( hrgn );
2649 uFlags = SWP_EX_PAINTSELF;
2651 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2654 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2656 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2657 winpos.hwndInsertAfter = tempInsertAfter;
2660 if( winpos.flags & SWP_SHOWWINDOW )
2664 wndPtr->dwStyle |= WS_VISIBLE;
2666 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2668 /* focus was set to unmapped window, reset host focus
2669 * since the window is now visible */
2671 focus = curr = GetFocus();
2676 WND *pFocus = WIN_FindWndPtr( focus );
2678 pFocus->pDriver->pSetFocus(pFocus);
2679 WIN_ReleaseWndPtr(pFocus);
2682 curr = GetParent(curr);
2686 else /* -------------------------------------------- emulated window */
2688 if( winpos.flags & SWP_SHOWWINDOW )
2690 wndPtr->dwStyle |= WS_VISIBLE;
2691 uFlags |= SWP_EX_PAINTSELF;
2692 visRgn = 1; /* redraw the whole window */
2694 else if( !(winpos.flags & SWP_NOREDRAW) )
2696 if( winpos.flags & SWP_HIDEWINDOW )
2698 if( visRgn > 1 ) /* map to parent */
2699 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2705 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2706 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2707 &oldClientRect, uFlags);
2710 /* nothing moved, redraw frame if needed */
2712 if( winpos.flags & SWP_FRAMECHANGED )
2713 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2716 DeleteObject( visRgn );
2724 if( winpos.flags & SWP_HIDEWINDOW )
2726 wndPtr->dwStyle &= ~WS_VISIBLE;
2728 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2730 /* FIXME: This will cause the window to be activated irrespective
2731 * of whether it is owned by the same thread. Has to be done
2735 if (winpos.hwnd == hwndActive)
2736 WINPOS_ActivateOtherWindow( wndPtr );
2739 /* ------------------------------------------------------------------------ FINAL */
2741 if (wndPtr->flags & WIN_NATIVE)
2742 EVENT_Synchronize(); /* Synchronize with the host window system */
2744 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2745 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2747 wndTemp = WIN_GetDesktop();
2749 /* repaint invalidated region (if any)
2751 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2752 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2757 if( !(winpos.flags & SWP_NOREDRAW) )
2759 if( uFlags & SWP_EX_PAINTSELF )
2761 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE | RDW_FRAME |
2762 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2763 RDW_ALLCHILDREN, RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2767 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE |
2768 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2769 RDW_ALLCHILDREN, RDW_EX_USEHRGN );
2773 DeleteObject( visRgn );
2776 WIN_ReleaseDesktop();
2778 if (!(flags & SWP_NOACTIVATE))
2779 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2781 /* And last, send the WM_WINDOWPOSCHANGED message */
2783 TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2786 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2787 !(winpos.flags & SWP_NOSENDCHANGING)) )
2789 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2790 if (resync) EVENT_Synchronize ();
2795 WIN_ReleaseWndPtr(wndPtr);
2800 /***********************************************************************
2801 * BeginDeferWindowPos16 (USER.259)
2803 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2805 return BeginDeferWindowPos( count );
2809 /***********************************************************************
2810 * BeginDeferWindowPos (USER32.9)
2812 HDWP WINAPI BeginDeferWindowPos( INT count )
2817 if (count <= 0) return 0;
2818 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2819 if (!handle) return 0;
2820 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2821 pDWP->actualCount = 0;
2822 pDWP->suggestedCount = count;
2824 pDWP->wMagic = DWP_MAGIC;
2825 pDWP->hwndParent = 0;
2830 /***********************************************************************
2831 * DeferWindowPos16 (USER.260)
2833 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2834 INT16 x, INT16 y, INT16 cx, INT16 cy,
2837 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2838 x, y, cx, cy, flags );
2842 /***********************************************************************
2843 * DeferWindowPos (USER32.128)
2845 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2846 INT x, INT y, INT cx, INT cy,
2851 HDWP newhdwp = hdwp,retvalue;
2855 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2856 if (!pDWP) return 0;
2857 if (hwnd == GetDesktopWindow()) return 0;
2859 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2860 USER_HEAP_FREE( hdwp );
2864 /* Numega Bounds Checker Demo dislikes the following code.
2865 In fact, I've not been able to find any "same parent" requirement in any docu
2869 /* All the windows of a DeferWindowPos() must have the same parent */
2870 parent = pWnd->parent->hwndSelf;
2871 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2872 else if (parent != pDWP->hwndParent)
2874 USER_HEAP_FREE( hdwp );
2880 for (i = 0; i < pDWP->actualCount; i++)
2882 if (pDWP->winPos[i].hwnd == hwnd)
2884 /* Merge with the other changes */
2885 if (!(flags & SWP_NOZORDER))
2887 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2889 if (!(flags & SWP_NOMOVE))
2891 pDWP->winPos[i].x = x;
2892 pDWP->winPos[i].y = y;
2894 if (!(flags & SWP_NOSIZE))
2896 pDWP->winPos[i].cx = cx;
2897 pDWP->winPos[i].cy = cy;
2899 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2900 SWP_NOZORDER | SWP_NOREDRAW |
2901 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2903 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2909 if (pDWP->actualCount >= pDWP->suggestedCount)
2911 newhdwp = USER_HEAP_REALLOC( hdwp,
2912 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
2918 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2919 pDWP->suggestedCount++;
2921 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2922 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2923 pDWP->winPos[pDWP->actualCount].x = x;
2924 pDWP->winPos[pDWP->actualCount].y = y;
2925 pDWP->winPos[pDWP->actualCount].cx = cx;
2926 pDWP->winPos[pDWP->actualCount].cy = cy;
2927 pDWP->winPos[pDWP->actualCount].flags = flags;
2928 pDWP->actualCount++;
2931 WIN_ReleaseWndPtr(pWnd);
2936 /***********************************************************************
2937 * EndDeferWindowPos16 (USER.261)
2939 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
2941 return EndDeferWindowPos( hdwp );
2945 /***********************************************************************
2946 * EndDeferWindowPos (USER32.173)
2948 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
2955 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2956 if (!pDWP) return FALSE;
2957 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
2959 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
2960 winpos->x, winpos->y, winpos->cx,
2961 winpos->cy, winpos->flags ))) break;
2963 USER_HEAP_FREE( hdwp );
2968 /***********************************************************************
2969 * TileChildWindows (USER.199)
2971 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
2973 FIXME(win, "(%04x, %d): stub\n", parent, action);
2976 /***********************************************************************
2977 * CascageChildWindows (USER.198)
2979 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
2981 FIXME(win, "(%04x, %d): stub\n", parent, action);
2984 /***********************************************************************
2985 * SetProgmanWindow [USER32.522]
2987 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
2989 hGlobalProgmanWindow = hwnd;
2990 return hGlobalProgmanWindow;
2993 /***********************************************************************
2994 * GetProgmanWindow [USER32.289]
2996 HRESULT WINAPI GetProgmanWindow ( )
2998 return hGlobalProgmanWindow;
3001 /***********************************************************************
3002 * SetShellWindowEx [USER32.531]
3003 * hwndProgman = Progman[Program Manager]
3004 * |-> SHELLDLL_DefView
3005 * hwndListView = | |-> SysListView32
3006 * | | |-> tooltips_class32
3012 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3014 FIXME(win,"0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3015 hGlobalShellWindow = hwndProgman;
3016 return hGlobalShellWindow;
3020 /***********************************************************************
3021 * SetTaskmanWindow [USER32.537]
3023 * hwnd = MSTaskSwWClass
3024 * |-> SysTabControl32
3026 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3028 hGlobalTaskmanWindow = hwnd;
3029 return hGlobalTaskmanWindow;
3032 /***********************************************************************
3033 * GetTaskmanWindow [USER32.304]
3035 HRESULT WINAPI GetTaskmanWindow ( )
3037 return hGlobalTaskmanWindow;