2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
13 #include "wine/winuser16.h"
26 #include "nonclient.h"
27 #include "debugtools.h"
32 DEFAULT_DEBUG_CHANNEL(win)
34 #define HAS_DLGFRAME(style,exStyle) \
35 (((exStyle) & WS_EX_DLGMODALFRAME) || \
36 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
38 #define HAS_THICKFRAME(style) \
39 (((style) & WS_THICKFRAME) && \
40 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
42 #define SWP_AGG_NOGEOMETRYCHANGE \
43 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
44 #define SWP_AGG_NOPOSCHANGE \
45 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
46 #define SWP_AGG_STATUSFLAGS \
47 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
49 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
51 #define PLACE_MIN 0x0001
52 #define PLACE_MAX 0x0002
53 #define PLACE_RECT 0x0004
55 #define SWP_EX_NOCOPY 0x0001
56 #define SWP_EX_PAINTSELF 0x0002
57 #define SWP_EX_NONCLIENT 0x0004
59 #define MINMAX_NOSWP 0x00010000
61 /* ----- internal variables ----- */
63 static HWND hwndPrevActive = 0; /* Previously active window */
64 static HWND hGlobalShellWindow=0; /*the shell*/
65 static HWND hGlobalTaskmanWindow=0;
66 static HWND hGlobalProgmanWindow=0;
68 static LPCSTR atomInternalPos;
70 extern HQUEUE16 hActiveQueue;
72 /***********************************************************************
73 * WINPOS_CreateInternalPosAtom
75 BOOL WINPOS_CreateInternalPosAtom()
78 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
79 return (atomInternalPos) ? TRUE : FALSE;
82 /***********************************************************************
83 * WINPOS_CheckInternalPos
85 * Called when a window is destroyed.
87 void WINPOS_CheckInternalPos( WND* wndPtr )
90 MESSAGEQUEUE *pMsgQ = 0;
91 HWND hwnd = wndPtr->hwndSelf;
93 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
95 /* Retrieve the message queue associated with this window */
96 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
99 WARN("\tMessage queue not found. Exiting!\n" );
103 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
105 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
107 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
108 WARN("\tattempt to activate destroyed window!\n");
113 if( IsWindow(lpPos->hwndIconTitle) )
114 DestroyWindow( lpPos->hwndIconTitle );
115 HeapFree( SystemHeap, 0, lpPos );
118 QUEUE_Unlock( pMsgQ );
122 /***********************************************************************
125 * Find a suitable place for an iconic window.
127 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
130 short x, y, xspacing, yspacing;
132 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
133 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
134 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
135 return pt; /* The icon already has a suitable position */
137 xspacing = GetSystemMetrics(SM_CXICONSPACING);
138 yspacing = GetSystemMetrics(SM_CYICONSPACING);
140 y = rectParent.bottom;
146 /* Check if another icon already occupies this spot */
147 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
150 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
152 if ((childPtr->rectWindow.left < x + xspacing) &&
153 (childPtr->rectWindow.right >= x) &&
154 (childPtr->rectWindow.top <= y) &&
155 (childPtr->rectWindow.bottom > y - yspacing))
156 break; /* There's a window in there */
158 WIN_UpdateWndPtr(&childPtr,childPtr->next);
160 WIN_ReleaseWndPtr(childPtr);
161 if (!childPtr) /* No window was found, so it's OK for us */
163 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
164 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
168 } while(x <= rectParent.right-xspacing);
174 /***********************************************************************
175 * ArrangeIconicWindows16 (USER.170)
177 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
179 return ArrangeIconicWindows(parent);
181 /***********************************************************************
182 * ArrangeIconicWindows (USER32.7)
184 UINT WINAPI ArrangeIconicWindows( HWND parent )
188 INT x, y, xspacing, yspacing;
190 GetClientRect( parent, &rectParent );
192 y = rectParent.bottom;
193 xspacing = GetSystemMetrics(SM_CXICONSPACING);
194 yspacing = GetSystemMetrics(SM_CYICONSPACING);
196 hwndChild = GetWindow( parent, GW_CHILD );
199 if( IsIconic( hwndChild ) )
201 WND *wndPtr = WIN_FindWndPtr(hwndChild);
203 WINPOS_ShowIconTitle( wndPtr, FALSE );
205 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
206 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
207 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
208 if( IsWindow(hwndChild) )
209 WINPOS_ShowIconTitle(wndPtr , TRUE );
210 WIN_ReleaseWndPtr(wndPtr);
212 if (x <= rectParent.right - xspacing) x += xspacing;
219 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
225 /***********************************************************************
226 * SwitchToThisWindow16 (USER.172)
228 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
230 SwitchToThisWindow( hwnd, restore );
234 /***********************************************************************
235 * SwitchToThisWindow (USER32.539)
237 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
239 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
243 /***********************************************************************
244 * GetWindowRect16 (USER.32)
246 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
248 WND * wndPtr = WIN_FindWndPtr( hwnd );
251 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
252 if (wndPtr->dwStyle & WS_CHILD)
253 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
254 WIN_ReleaseWndPtr(wndPtr);
258 /***********************************************************************
259 * GetWindowRect (USER32.308)
261 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
263 WND * wndPtr = WIN_FindWndPtr( hwnd );
264 if (!wndPtr) return FALSE;
266 *rect = wndPtr->rectWindow;
267 if (wndPtr->dwStyle & WS_CHILD)
268 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
269 WIN_ReleaseWndPtr(wndPtr);
274 /***********************************************************************
275 * GetWindowRgn (USER32)
277 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
280 WND *wndPtr = WIN_FindWndPtr( hwnd );
283 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
284 WIN_ReleaseWndPtr(wndPtr);
289 /***********************************************************************
290 * SetWindowRgn (USER32)
292 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
297 WND *wndPtr = WIN_FindWndPtr(hwnd);
299 if (!wndPtr) return FALSE;
301 /* a region exists for this window */
302 if (hrgn != 0 && hrgn == wndPtr->hrgnWnd)
304 /* can't replace actual region with same region
305 since we're now owner of that region
307 SetLastError(ERROR_INVALID_HANDLE);
313 /* delete previous region */
314 DeleteObject(wndPtr->hrgnWnd);
318 /* we'd like to set it back to 0 */
321 GetWindowRect(hwnd, &tempRect);
325 /* verify that region really exists */
326 if (GetRgnBox(hrgn, &tempRect) == ERROR) goto done;
329 /* valid region handle */
330 wndPtr->hrgnWnd = hrgn;
331 SetWindowPos( hwnd, NULL, tempRect.left, tempRect.top,
332 tempRect.right - tempRect.left, tempRect.bottom - tempRect.top,
333 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE |
334 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
336 wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn);
341 WIN_ReleaseWndPtr(wndPtr);
345 /***********************************************************************
348 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
352 FIXME("SetWindowRgn16: stub\n");
357 /***********************************************************************
358 * GetClientRect16 (USER.33)
360 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
362 WND * wndPtr = WIN_FindWndPtr( hwnd );
364 rect->left = rect->top = rect->right = rect->bottom = 0;
367 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
368 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
370 WIN_ReleaseWndPtr(wndPtr);
374 /***********************************************************************
375 * GetClientRect (USER.220)
377 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
379 WND * wndPtr = WIN_FindWndPtr( hwnd );
381 rect->left = rect->top = rect->right = rect->bottom = 0;
382 if (!wndPtr) return FALSE;
383 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
384 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
386 WIN_ReleaseWndPtr(wndPtr);
391 /*******************************************************************
392 * ClientToScreen16 (USER.28)
394 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
396 MapWindowPoints16( hwnd, 0, lppnt, 1 );
400 /*******************************************************************
401 * ClientToScreen (USER32.52)
403 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
405 MapWindowPoints( hwnd, 0, lppnt, 1 );
410 /*******************************************************************
411 * ScreenToClient16 (USER.29)
413 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
415 MapWindowPoints16( 0, hwnd, lppnt, 1 );
419 /*******************************************************************
420 * ScreenToClient (USER32.447)
422 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
424 MapWindowPoints( 0, hwnd, lppnt, 1 );
429 /***********************************************************************
430 * WINPOS_WindowFromPoint
432 * Find the window and hittest for a given point.
434 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
437 INT16 hittest = HTERROR;
441 TRACE("scope %04x %d,%d\n", wndScope->hwndSelf, pt.x, pt.y);
443 wndPtr = WIN_LockWndPtr(wndScope->child);
445 if( wndScope->dwStyle & WS_DISABLED )
451 if( wndScope->flags & WIN_MANAGED )
453 /* In managed mode we have to check wndScope first as it is also
454 * a window which received the mouse event. */
456 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
457 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
460 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
466 /* If point is in window, and window is visible, and it */
467 /* is enabled (or it's a top-level window), then explore */
468 /* its children. Otherwise, go to the next window. */
470 if ((wndPtr->dwStyle & WS_VISIBLE) &&
471 (!(wndPtr->dwStyle & WS_DISABLED) ||
472 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
474 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
475 xy.y - wndPtr->rectWindow.top) :
476 ((xy.x >= wndPtr->rectWindow.left) &&
477 (xy.x < wndPtr->rectWindow.right) &&
478 (xy.y >= wndPtr->rectWindow.top) &&
479 (xy.y < wndPtr->rectWindow.bottom))))
481 TRACE("%d,%d is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
482 *ppWnd = wndPtr; /* Got a suitable window */
484 /* If window is minimized or disabled, return at once */
485 if (wndPtr->dwStyle & WS_MINIMIZE)
487 retvalue = HTCAPTION;
490 if (wndPtr->dwStyle & WS_DISABLED)
496 /* If point is not in client area, ignore the children */
497 if ((xy.x < wndPtr->rectClient.left) ||
498 (xy.x >= wndPtr->rectClient.right) ||
499 (xy.y < wndPtr->rectClient.top) ||
500 (xy.y >= wndPtr->rectClient.bottom)) break;
502 xy.x -= wndPtr->rectClient.left;
503 xy.y -= wndPtr->rectClient.top;
504 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
508 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
513 /* If nothing found, try the scope window */
514 if (!*ppWnd) *ppWnd = wndScope;
516 /* Send the WM_NCHITTEST message (only if to the same task) */
517 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
519 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
520 0, MAKELONG( pt.x, pt.y ) );
521 if (hittest != HTTRANSPARENT)
523 retvalue = hittest; /* Found the window */
533 /* If no children found in last search, make point relative to parent */
536 xy.x += (*ppWnd)->rectClient.left;
537 xy.y += (*ppWnd)->rectClient.top;
540 /* Restart the search from the next sibling */
541 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
542 *ppWnd = (*ppWnd)->parent;
546 WIN_ReleaseWndPtr(wndPtr);
551 /*******************************************************************
552 * WindowFromPoint16 (USER.30)
554 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
557 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
558 WIN_ReleaseDesktop();
559 return pWnd->hwndSelf;
563 /*******************************************************************
564 * WindowFromPoint (USER32.582)
566 HWND WINAPI WindowFromPoint( POINT pt )
570 CONV_POINT32TO16( &pt, &pt16 );
571 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
572 WIN_ReleaseDesktop();
573 return (HWND)pWnd->hwndSelf;
577 /*******************************************************************
578 * ChildWindowFromPoint16 (USER.191)
580 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
583 CONV_POINT16TO32( &pt, &pt32 );
584 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
588 /*******************************************************************
589 * ChildWindowFromPoint (USER32.49)
591 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
593 /* pt is in the client coordinates */
595 WND* wnd = WIN_FindWndPtr(hwndParent);
601 /* get client rect fast */
602 rect.top = rect.left = 0;
603 rect.right = wnd->rectClient.right - wnd->rectClient.left;
604 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
606 if (!PtInRect( &rect, pt ))
611 WIN_UpdateWndPtr(&wnd,wnd->child);
614 if (PtInRect( &wnd->rectWindow, pt ))
616 retvalue = wnd->hwndSelf;
619 WIN_UpdateWndPtr(&wnd,wnd->next);
621 retvalue = hwndParent;
623 WIN_ReleaseWndPtr(wnd);
627 /*******************************************************************
628 * ChildWindowFromPointEx16 (USER.50)
630 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
633 CONV_POINT16TO32( &pt, &pt32 );
634 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
638 /*******************************************************************
639 * ChildWindowFromPointEx (USER32.50)
641 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
644 /* pt is in the client coordinates */
646 WND* wnd = WIN_FindWndPtr(hwndParent);
652 /* get client rect fast */
653 rect.top = rect.left = 0;
654 rect.right = wnd->rectClient.right - wnd->rectClient.left;
655 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
657 if (!PtInRect( &rect, pt ))
662 WIN_UpdateWndPtr(&wnd,wnd->child);
666 if (PtInRect( &wnd->rectWindow, pt )) {
667 if ( (uFlags & CWP_SKIPINVISIBLE) &&
668 !(wnd->dwStyle & WS_VISIBLE) );
669 else if ( (uFlags & CWP_SKIPDISABLED) &&
670 (wnd->dwStyle & WS_DISABLED) );
671 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
672 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
675 retvalue = wnd->hwndSelf;
680 WIN_UpdateWndPtr(&wnd,wnd->next);
682 retvalue = hwndParent;
684 WIN_ReleaseWndPtr(wnd);
689 /*******************************************************************
690 * WINPOS_GetWinOffset
692 * Calculate the offset between the origin of the two windows. Used
693 * to implement MapWindowPoints.
695 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
700 offset->x = offset->y = 0;
701 if (hwndFrom == hwndTo ) return;
703 /* Translate source window origin to screen coords */
706 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
708 ERR("bad hwndFrom = %04x\n",hwndFrom);
711 while (wndPtr->parent)
713 offset->x += wndPtr->rectClient.left;
714 offset->y += wndPtr->rectClient.top;
715 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
717 WIN_ReleaseWndPtr(wndPtr);
720 /* Translate origin to destination window coords */
723 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
725 ERR("bad hwndTo = %04x\n", hwndTo );
728 while (wndPtr->parent)
730 offset->x -= wndPtr->rectClient.left;
731 offset->y -= wndPtr->rectClient.top;
732 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
734 WIN_ReleaseWndPtr(wndPtr);
739 /*******************************************************************
740 * MapWindowPoints16 (USER.258)
742 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
743 LPPOINT16 lppt, UINT16 count )
747 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
757 /*******************************************************************
758 * MapWindowPoints (USER32.386)
760 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
761 LPPOINT lppt, UINT count )
765 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
772 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
776 /***********************************************************************
777 * IsIconic16 (USER.31)
779 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
781 return IsIconic(hWnd);
785 /***********************************************************************
786 * IsIconic (USER32.345)
788 BOOL WINAPI IsIconic(HWND hWnd)
791 WND * wndPtr = WIN_FindWndPtr(hWnd);
792 if (wndPtr == NULL) return FALSE;
793 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
794 WIN_ReleaseWndPtr(wndPtr);
799 /***********************************************************************
800 * IsZoomed (USER.272)
802 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
804 return IsZoomed(hWnd);
808 /***********************************************************************
809 * IsZoomed (USER.352)
811 BOOL WINAPI IsZoomed(HWND hWnd)
814 WND * wndPtr = WIN_FindWndPtr(hWnd);
815 if (wndPtr == NULL) return FALSE;
816 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
817 WIN_ReleaseWndPtr(wndPtr);
822 /*******************************************************************
823 * GetActiveWindow (USER.60)
825 HWND16 WINAPI GetActiveWindow16(void)
827 return (HWND16)GetActiveWindow();
830 /*******************************************************************
831 * GetActiveWindow (USER32.205)
833 HWND WINAPI GetActiveWindow(void)
835 MESSAGEQUEUE *pCurMsgQ = 0;
838 /* Get the messageQ for the current thread */
839 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
841 WARN("\tCurrent message queue not found. Exiting!\n" );
845 /* Return the current active window from the perQ data of the current message Q */
846 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
848 QUEUE_Unlock( pCurMsgQ );
853 /*******************************************************************
856 static BOOL WINPOS_CanActivate(WND* pWnd)
858 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
859 == WS_VISIBLE ) ) return TRUE;
864 /*******************************************************************
865 * SetActiveWindow16 (USER.59)
867 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
869 return SetActiveWindow(hwnd);
873 /*******************************************************************
874 * SetActiveWindow (USER32.463)
876 HWND WINAPI SetActiveWindow( HWND hwnd )
879 WND *wndPtr = WIN_FindWndPtr( hwnd );
880 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
882 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
888 /* Get the messageQ for the current thread */
889 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
891 WARN("\tCurrent message queue not found. Exiting!\n" );
895 /* Retrieve the message queue associated with this window */
896 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
899 WARN("\tWindow message queue not found. Exiting!\n" );
903 /* Make sure that the window is associated with the calling threads
904 * message queue. It must share the same perQ data.
907 if ( pCurMsgQ->pQData != pMsgQ->pQData )
910 /* Save current active window */
911 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
913 WINPOS_SetActiveWindow( hwnd, 0, 0 );
916 /* Unlock the queues before returning */
918 QUEUE_Unlock( pMsgQ );
920 QUEUE_Unlock( pCurMsgQ );
923 WIN_ReleaseWndPtr(wndPtr);
928 /*******************************************************************
929 * GetForegroundWindow16 (USER.608)
931 HWND16 WINAPI GetForegroundWindow16(void)
933 return (HWND16)GetForegroundWindow();
937 /*******************************************************************
938 * SetForegroundWindow16 (USER.609)
940 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
942 return SetForegroundWindow( hwnd );
946 /*******************************************************************
947 * GetForegroundWindow (USER32.241)
949 HWND WINAPI GetForegroundWindow(void)
953 /* Get the foreground window (active window of hActiveQueue) */
956 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
958 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
960 QUEUE_Unlock( pActiveQueue );
966 /*******************************************************************
967 * SetForegroundWindow (USER32.482)
969 BOOL WINAPI SetForegroundWindow( HWND hwnd )
971 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
975 /*******************************************************************
976 * GetShellWindow16 (USER.600)
978 HWND16 WINAPI GetShellWindow16(void)
980 return GetShellWindow();
983 /*******************************************************************
984 * SetShellWindow (USER32.504)
986 HWND WINAPI SetShellWindow(HWND hwndshell)
987 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
989 hGlobalShellWindow = hwndshell;
990 return hGlobalShellWindow;
994 /*******************************************************************
995 * GetShellWindow (USER32.287)
997 HWND WINAPI GetShellWindow(void)
998 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
1000 return hGlobalShellWindow;
1004 /***********************************************************************
1005 * BringWindowToTop16 (USER.45)
1007 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1009 return BringWindowToTop(hwnd);
1013 /***********************************************************************
1014 * BringWindowToTop (USER32.11)
1016 BOOL WINAPI BringWindowToTop( HWND hwnd )
1018 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1022 /***********************************************************************
1023 * MoveWindow16 (USER.56)
1025 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1028 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1032 /***********************************************************************
1033 * MoveWindow (USER32.399)
1035 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1038 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1039 if (!repaint) flags |= SWP_NOREDRAW;
1040 TRACE("%04x %d,%d %dx%d %d\n",
1041 hwnd, x, y, cx, cy, repaint );
1042 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1045 /***********************************************************************
1046 * WINPOS_InitInternalPos
1048 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1049 LPRECT restoreRect )
1051 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1055 /* this happens when the window is minimized/maximized
1056 * for the first time (rectWindow is not adjusted yet) */
1058 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1059 if( !lpPos ) return NULL;
1061 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1062 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1063 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1064 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1067 if( wnd->dwStyle & WS_MINIMIZE )
1068 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1069 else if( wnd->dwStyle & WS_MAXIMIZE )
1070 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1071 else if( restoreRect )
1072 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1077 /***********************************************************************
1078 * WINPOS_RedrawIconTitle
1080 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1082 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1085 if( lpPos->hwndIconTitle )
1087 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1088 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1095 /***********************************************************************
1096 * WINPOS_ShowIconTitle
1098 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1100 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1102 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1104 HWND16 hWnd = lpPos->hwndIconTitle;
1106 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1109 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1112 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1114 if( !(pWnd->dwStyle & WS_VISIBLE) )
1116 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1117 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1118 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1120 WIN_ReleaseWndPtr(pWnd);
1123 else ShowWindow( hWnd, SW_HIDE );
1128 /*******************************************************************
1129 * WINPOS_GetMinMaxInfo
1131 * Get the minimized and maximized information for a window.
1133 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1134 POINT *minTrack, POINT *maxTrack )
1136 LPINTERNALPOS lpPos;
1140 /* Compute default values */
1142 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1143 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1144 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1145 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1146 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1147 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1149 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1150 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1152 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1153 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1158 if (HAS_THICKFRAME(wndPtr->dwStyle))
1160 xinc += GetSystemMetrics(SM_CXFRAME);
1161 yinc += GetSystemMetrics(SM_CYFRAME);
1163 if (wndPtr->dwStyle & WS_BORDER)
1165 xinc += GetSystemMetrics(SM_CXBORDER);
1166 yinc += GetSystemMetrics(SM_CYBORDER);
1169 MinMax.ptMaxSize.x += 2 * xinc;
1170 MinMax.ptMaxSize.y += 2 * yinc;
1172 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1173 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1174 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1177 MinMax.ptMaxPosition.x = -xinc;
1178 MinMax.ptMaxPosition.y = -yinc;
1181 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1183 /* Some sanity checks */
1185 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1186 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1187 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1188 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1189 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1190 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1191 MinMax.ptMinTrackSize.x );
1192 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1193 MinMax.ptMinTrackSize.y );
1195 if (maxSize) *maxSize = MinMax.ptMaxSize;
1196 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1197 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1198 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1201 /***********************************************************************
1202 * WINPOS_MinMaximize
1204 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1205 * This function assumes that 'cmd' is different from the current window
1208 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1212 LPINTERNALPOS lpPos;
1214 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1216 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1217 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1219 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1221 if( wndPtr->dwStyle & WS_MINIMIZE )
1223 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1224 return (SWP_NOSIZE | SWP_NOMOVE);
1225 swpFlags |= SWP_NOCOPYBITS;
1230 if( wndPtr->dwStyle & WS_MAXIMIZE)
1232 wndPtr->flags |= WIN_RESTORE_MAX;
1233 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1236 wndPtr->flags &= ~WIN_RESTORE_MAX;
1237 wndPtr->dwStyle |= WS_MINIMIZE;
1239 if( wndPtr->flags & WIN_NATIVE )
1240 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1241 swpFlags |= MINMAX_NOSWP;
1243 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1245 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1246 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1247 swpFlags |= SWP_NOCOPYBITS;
1251 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1252 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1253 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1255 if( wndPtr->dwStyle & WS_MINIMIZE )
1257 if( wndPtr->flags & WIN_NATIVE )
1258 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1260 WINPOS_ShowIconTitle( wndPtr, FALSE );
1261 wndPtr->dwStyle &= ~WS_MINIMIZE;
1263 wndPtr->dwStyle |= WS_MAXIMIZE;
1265 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1270 if( wndPtr->dwStyle & WS_MINIMIZE )
1272 if( wndPtr->flags & WIN_NATIVE )
1273 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1274 swpFlags |= MINMAX_NOSWP;
1276 wndPtr->dwStyle &= ~WS_MINIMIZE;
1277 WINPOS_ShowIconTitle( wndPtr, FALSE );
1279 if( wndPtr->flags & WIN_RESTORE_MAX)
1281 /* Restore to maximized position */
1282 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1283 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1284 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1285 wndPtr->dwStyle |= WS_MAXIMIZE;
1286 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1291 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1292 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1294 /* Restore to normal position */
1296 *lpRect = lpPos->rectNormal;
1297 lpRect->right -= lpRect->left;
1298 lpRect->bottom -= lpRect->top;
1302 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1306 /***********************************************************************
1307 * ShowWindowAsync (USER32.535)
1309 * doesn't wait; returns immediately.
1310 * used by threads to toggle windows in other (possibly hanging) threads
1312 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1314 /* FIXME: does ShowWindow() return immediately ? */
1315 return ShowWindow(hwnd, cmd);
1319 /***********************************************************************
1320 * ShowWindow16 (USER.42)
1322 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1324 return ShowWindow(hwnd,cmd);
1328 /***********************************************************************
1329 * ShowWindow (USER32.534)
1331 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1333 WND* wndPtr = WIN_FindWndPtr( hwnd );
1334 BOOL wasVisible, showFlag;
1335 RECT16 newPos = {0, 0, 0, 0};
1338 if (!wndPtr) return FALSE;
1340 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1342 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1347 if (!wasVisible) goto END;;
1348 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1349 SWP_NOACTIVATE | SWP_NOZORDER;
1352 case SW_SHOWMINNOACTIVE:
1353 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1355 case SW_SHOWMINIMIZED:
1356 swp |= SWP_SHOWWINDOW;
1359 swp |= SWP_FRAMECHANGED;
1360 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1361 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1362 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1365 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1366 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1367 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1368 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1369 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1373 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1376 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1379 * ShowWindow has a little peculiar behavior that if the
1380 * window is already the topmost window, it will not
1383 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1384 swp |= SWP_NOACTIVATE;
1388 case SW_SHOWNOACTIVATE:
1389 swp |= SWP_NOZORDER;
1390 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1392 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1393 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1395 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1397 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1398 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1399 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1403 showFlag = (cmd != SW_HIDE);
1404 if (showFlag != wasVisible)
1406 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1407 if (!IsWindow( hwnd )) goto END;
1410 if ((wndPtr->dwStyle & WS_CHILD) &&
1411 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1412 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1414 /* Don't call SetWindowPos() on invisible child windows */
1415 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1416 else wndPtr->dwStyle |= WS_VISIBLE;
1420 /* We can't activate a child window */
1421 if ((wndPtr->dwStyle & WS_CHILD) &&
1422 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1423 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1424 if (!(swp & MINMAX_NOSWP))
1426 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1427 newPos.right, newPos.bottom, LOWORD(swp) );
1430 /* FIXME: This will cause the window to be activated irrespective
1431 * of whether it is owned by the same thread. Has to be done
1435 if (hwnd == GetActiveWindow())
1436 WINPOS_ActivateOtherWindow(wndPtr);
1438 /* Revert focus to parent */
1439 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1440 SetFocus( GetParent(hwnd) );
1443 if (!IsWindow( hwnd )) goto END;
1444 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1447 if (wndPtr->flags & WIN_NEED_SIZE)
1449 /* should happen only in CreateWindowEx() */
1450 int wParam = SIZE_RESTORED;
1452 wndPtr->flags &= ~WIN_NEED_SIZE;
1453 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1454 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1455 SendMessageA( hwnd, WM_SIZE, wParam,
1456 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1457 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1458 SendMessageA( hwnd, WM_MOVE, 0,
1459 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1463 WIN_ReleaseWndPtr(wndPtr);
1468 /***********************************************************************
1469 * GetInternalWindowPos16 (USER.460)
1471 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1474 WINDOWPLACEMENT16 wndpl;
1475 if (GetWindowPlacement16( hwnd, &wndpl ))
1477 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1478 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1479 return wndpl.showCmd;
1485 /***********************************************************************
1486 * GetInternalWindowPos (USER32.245)
1488 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1491 WINDOWPLACEMENT wndpl;
1492 if (GetWindowPlacement( hwnd, &wndpl ))
1494 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1495 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1496 return wndpl.showCmd;
1501 /***********************************************************************
1502 * GetWindowPlacement16 (USER.370)
1504 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1506 WND *pWnd = WIN_FindWndPtr( hwnd );
1507 LPINTERNALPOS lpPos;
1509 if(!pWnd ) return FALSE;
1511 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1512 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1513 wndpl->length = sizeof(*wndpl);
1514 if( pWnd->dwStyle & WS_MINIMIZE )
1515 wndpl->showCmd = SW_SHOWMINIMIZED;
1517 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1518 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1519 if( pWnd->flags & WIN_RESTORE_MAX )
1520 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1523 wndpl->ptMinPosition = lpPos->ptIconPos;
1524 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1525 wndpl->rcNormalPosition = lpPos->rectNormal;
1527 WIN_ReleaseWndPtr(pWnd);
1532 /***********************************************************************
1533 * GetWindowPlacement (USER32.307)
1536 * Fails if wndpl->length of Win95 (!) apps is invalid.
1538 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1542 WINDOWPLACEMENT16 wpl;
1543 wpl.length = sizeof(wpl);
1544 if( GetWindowPlacement16( hwnd, &wpl ) )
1546 pwpl32->length = sizeof(*pwpl32);
1547 pwpl32->flags = wpl.flags;
1548 pwpl32->showCmd = wpl.showCmd;
1549 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1550 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1551 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1559 /***********************************************************************
1560 * WINPOS_SetPlacement
1562 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1565 WND *pWnd = WIN_FindWndPtr( hwnd );
1568 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1569 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1571 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1572 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1573 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1575 if( pWnd->dwStyle & WS_MINIMIZE )
1577 WINPOS_ShowIconTitle( pWnd, FALSE );
1578 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1579 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1580 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1582 else if( pWnd->dwStyle & WS_MAXIMIZE )
1584 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1585 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1586 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1588 else if( flags & PLACE_RECT )
1589 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1590 lpPos->rectNormal.right - lpPos->rectNormal.left,
1591 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1592 SWP_NOZORDER | SWP_NOACTIVATE );
1594 ShowWindow( hwnd, wndpl->showCmd );
1595 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1597 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1599 /* SDK: ...valid only the next time... */
1600 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1602 WIN_ReleaseWndPtr(pWnd);
1609 /***********************************************************************
1610 * SetWindowPlacement16 (USER.371)
1612 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1614 return WINPOS_SetPlacement( hwnd, wndpl,
1615 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1618 /***********************************************************************
1619 * SetWindowPlacement (USER32.519)
1622 * Fails if wndpl->length of Win95 (!) apps is invalid.
1624 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1628 WINDOWPLACEMENT16 wpl;
1630 wpl.length = sizeof(WINDOWPLACEMENT16);
1631 wpl.flags = pwpl32->flags;
1632 wpl.showCmd = pwpl32->showCmd;
1633 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1634 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1635 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1636 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1637 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1638 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1639 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1640 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1642 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1648 /***********************************************************************
1649 * SetInternalWindowPos16 (USER.461)
1651 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1652 LPRECT16 rect, LPPOINT16 pt )
1654 if( IsWindow16(hwnd) )
1656 WINDOWPLACEMENT16 wndpl;
1659 wndpl.length = sizeof(wndpl);
1660 wndpl.showCmd = showCmd;
1661 wndpl.flags = flags = 0;
1666 wndpl.flags |= WPF_SETMINPOSITION;
1667 wndpl.ptMinPosition = *pt;
1671 flags |= PLACE_RECT;
1672 wndpl.rcNormalPosition = *rect;
1674 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1679 /***********************************************************************
1680 * SetInternalWindowPos (USER32.483)
1682 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1683 LPRECT rect, LPPOINT pt )
1685 if( IsWindow(hwnd) )
1687 WINDOWPLACEMENT16 wndpl;
1690 wndpl.length = sizeof(wndpl);
1691 wndpl.showCmd = showCmd;
1692 wndpl.flags = flags = 0;
1697 wndpl.flags |= WPF_SETMINPOSITION;
1698 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1702 flags |= PLACE_RECT;
1703 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1705 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1709 /*******************************************************************
1710 * WINPOS_SetActiveWindow
1712 * SetActiveWindow() back-end. This is the only function that
1713 * can assign active status to a window. It must be called only
1714 * for the top level windows.
1716 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1718 CBTACTIVATESTRUCT16* cbtStruct;
1719 WND* wndPtr=0, *wndTemp;
1720 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1721 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1723 HWND hwndActive = 0;
1726 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1728 /* Get current active window from the active queue */
1731 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1732 if ( pOldActiveQueue )
1733 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1736 /* paranoid checks */
1737 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1740 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1743 wndPtr = WIN_FindWndPtr(hWnd);
1744 hOldActiveQueue = hActiveQueue;
1746 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1748 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1749 WIN_ReleaseWndPtr(wndTemp);
1752 TRACE("no current active window.\n");
1754 /* call CBT hook chain */
1755 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1757 cbtStruct->fMouse = fMouse;
1758 cbtStruct->hWndActive = hwndActive;
1759 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1760 (LPARAM)SEGPTR_GET(cbtStruct) );
1761 SEGPTR_FREE(cbtStruct);
1762 if (bRet) goto CLEANUP_END;
1765 /* set prev active wnd to current active wnd and send notification */
1766 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1768 MESSAGEQUEUE *pTempActiveQueue = 0;
1770 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1772 if (GetSysModalWindow16() != hWnd)
1774 /* disregard refusal if hWnd is sysmodal */
1777 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1778 MAKEWPARAM( WA_INACTIVE, wIconized ),
1781 /* check if something happened during message processing
1782 * (global active queue may have changed)
1784 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1785 if(!pTempActiveQueue)
1788 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1789 QUEUE_Unlock( pTempActiveQueue );
1790 if( hwndPrevActive != hwndActive )
1794 /* Set new active window in the message queue */
1798 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1799 if ( pNewActiveQueue )
1800 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1802 else /* have to do this or MDI frame activation goes to hell */
1803 if( pOldActiveQueue )
1804 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1806 /* send palette messages */
1807 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1808 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1810 /* if prev wnd is minimized redraw icon title */
1811 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1813 /* managed windows will get ConfigureNotify event */
1814 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1816 /* check Z-order and bring hWnd to the top */
1817 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1819 if (wndTemp->dwStyle & WS_VISIBLE) break;
1821 WIN_ReleaseDesktop();
1822 WIN_ReleaseWndPtr(wndTemp);
1824 if( wndTemp != wndPtr )
1825 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1826 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1827 if (!IsWindow(hWnd))
1831 /* Get a handle to the new active queue */
1832 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1834 /* send WM_ACTIVATEAPP if necessary */
1835 if (hOldActiveQueue != hNewActiveQueue)
1837 WND **list, **ppWnd;
1838 WND *pDesktop = WIN_GetDesktop();
1840 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1842 for (ppWnd = list; *ppWnd; ppWnd++)
1844 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1846 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1847 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1848 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1850 WIN_ReleaseWinArray(list);
1853 hActiveQueue = hNewActiveQueue;
1855 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1857 for (ppWnd = list; *ppWnd; ppWnd++)
1859 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1861 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1862 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1863 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1865 WIN_ReleaseWinArray(list);
1867 WIN_ReleaseDesktop();
1869 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1874 /* walk up to the first unowned window */
1875 wndTemp = WIN_LockWndPtr(wndPtr);
1876 while (wndTemp->owner)
1878 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1880 /* and set last active owned popup */
1881 wndTemp->hwndLastActive = hWnd;
1883 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1884 WIN_ReleaseWndPtr(wndTemp);
1885 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1886 SendMessageA( hWnd, WM_ACTIVATE,
1887 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1888 (LPARAM)hwndPrevActive );
1889 if( !IsWindow(hWnd) ) goto CLEANUP;
1892 /* change focus if possible */
1895 if ( pNewActiveQueue )
1897 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1899 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1900 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1901 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1905 if ( pOldActiveQueue &&
1906 ( !pNewActiveQueue ||
1907 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1909 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1911 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1915 if( !hwndPrevActive && wndPtr )
1916 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1918 /* if active wnd is minimized redraw icon title */
1919 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1921 bRet = (hWnd == hwndActive); /* Success? */
1923 CLEANUP: /* Unlock the message queues before returning */
1925 if ( pNewActiveQueue )
1926 QUEUE_Unlock( pNewActiveQueue );
1930 if ( pOldActiveQueue )
1931 QUEUE_Unlock( pOldActiveQueue );
1933 WIN_ReleaseWndPtr(wndPtr);
1937 /*******************************************************************
1938 * WINPOS_ActivateOtherWindow
1940 * Activates window other than pWnd.
1942 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1946 HWND hwndActive = 0;
1948 /* Get current active window from the active queue */
1951 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1954 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1955 QUEUE_Unlock( pActiveQueue );
1959 if( pWnd->hwndSelf == hwndPrevActive )
1962 if( hwndActive != pWnd->hwndSelf &&
1963 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1966 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1967 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1969 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1971 WIN_ReleaseWndPtr(pWndTo);
1972 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1974 while( !WINPOS_CanActivate(pWndTo) )
1976 /* by now owned windows should've been taken care of */
1977 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1978 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1979 if( !pWndTo ) break;
1981 WIN_ReleaseWndPtr(pWndPtr);
1984 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1986 /* switch desktop queue to current active */
1989 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1990 WIN_ReleaseWndPtr(pWndTo);
1991 WIN_ReleaseDesktop();
1998 /*******************************************************************
1999 * WINPOS_ChangeActiveWindow
2002 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2004 WND *wndPtr, *wndTemp;
2006 HWND hwndActive = 0;
2008 /* Get current active window from the active queue */
2011 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2014 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2015 QUEUE_Unlock( pActiveQueue );
2020 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2022 wndPtr = WIN_FindWndPtr(hWnd);
2023 if( !wndPtr ) return FALSE;
2025 /* child windows get WM_CHILDACTIVATE message */
2026 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2028 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2032 if( hWnd == hwndActive )
2038 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2044 /* switch desktop queue to current active */
2045 wndTemp = WIN_GetDesktop();
2046 if( wndPtr->parent == wndTemp)
2047 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2048 WIN_ReleaseDesktop();
2052 WIN_ReleaseWndPtr(wndPtr);
2057 /***********************************************************************
2058 * WINPOS_SendNCCalcSize
2060 * Send a WM_NCCALCSIZE message to a window.
2061 * All parameters are read-only except newClientRect.
2062 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2063 * when calcValidRect is TRUE.
2065 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2066 RECT *newWindowRect, RECT *oldWindowRect,
2067 RECT *oldClientRect, WINDOWPOS *winpos,
2068 RECT *newClientRect )
2070 NCCALCSIZE_PARAMS params;
2071 WINDOWPOS winposCopy;
2074 params.rgrc[0] = *newWindowRect;
2077 winposCopy = *winpos;
2078 params.rgrc[1] = *oldWindowRect;
2079 params.rgrc[2] = *oldClientRect;
2080 params.lppos = &winposCopy;
2082 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2084 TRACE("%d,%d-%d,%d\n",
2085 params.rgrc[0].left, params.rgrc[0].top,
2086 params.rgrc[0].right, params.rgrc[0].bottom );
2088 /* If the application send back garbage, ignore it */
2089 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2090 *newClientRect = params.rgrc[0];
2096 /***********************************************************************
2097 * WINPOS_HandleWindowPosChanging16
2099 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2101 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2103 POINT maxSize, minTrack;
2104 if (winpos->flags & SWP_NOSIZE) return 0;
2105 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2106 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2108 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2109 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2110 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2111 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2113 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2114 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2121 /***********************************************************************
2122 * WINPOS_HandleWindowPosChanging
2124 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2126 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2129 if (winpos->flags & SWP_NOSIZE) return 0;
2130 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2131 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2133 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2134 winpos->cx = min( winpos->cx, maxSize.x );
2135 winpos->cy = min( winpos->cy, maxSize.y );
2140 /***********************************************************************
2143 * fix Z order taking into account owned popups -
2144 * basically we need to maintain them above the window that owns them
2146 * FIXME: hide/show owned popups when owner visibility changes.
2148 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2150 WND* w = WIN_LockWndPtr(pDesktop->child);
2152 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2154 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2156 /* make sure this popup stays above the owner */
2158 HWND hwndLocalPrev = HWND_TOP;
2160 if( hwndInsertAfter != HWND_TOP )
2162 while( w != wndPtr->owner )
2164 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2165 if( hwndLocalPrev == hwndInsertAfter ) break;
2166 WIN_UpdateWndPtr(&w,w->next);
2168 hwndInsertAfter = hwndLocalPrev;
2171 else if( wndPtr->dwStyle & WS_CHILD )
2174 WIN_UpdateWndPtr(&w, pDesktop->child);
2178 if( w == wndPtr ) break;
2180 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2182 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2183 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2184 hwndInsertAfter = w->hwndSelf;
2186 WIN_UpdateWndPtr(&w, w->next);
2190 WIN_ReleaseWndPtr(w);
2191 return hwndInsertAfter;
2194 /***********************************************************************
2197 * Make window look nice without excessive repainting
2199 * visible and update regions are in window coordinates
2200 * client and window rectangles are in parent client coordinates
2202 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2203 * window rects have the same origin.
2205 * Returns: uFlags and a dirty region in *pVisRgn.
2207 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2208 LPRECT lpOldWndRect,
2209 LPRECT lpOldClientRect, UINT uFlags )
2212 HRGN newVisRgn, dirtyRgn;
2213 INT my = COMPLEXREGION;
2215 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2216 Wnd->rectWindow.left, Wnd->rectWindow.top,
2217 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2218 lpOldWndRect->left, lpOldWndRect->top,
2219 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2220 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2221 Wnd->rectClient.left, Wnd->rectClient.top,
2222 Wnd->rectClient.right, Wnd->rectClient.bottom,
2223 lpOldClientRect->left, lpOldClientRect->top,
2224 lpOldClientRect->right,lpOldClientRect->bottom );
2226 if( Wnd->hrgnUpdate == 1 )
2227 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2229 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2230 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2232 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2233 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2235 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2239 TRACE("\twon't copy anything!\n");
2241 /* set dirtyRgn to the sum of old and new visible regions
2242 * in parent client coordinates */
2244 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2245 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2247 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2249 else /* copy valid bits to a new location */
2251 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2252 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2254 /* subtract already invalid region inside Wnd from the dst region */
2256 if( Wnd->hrgnUpdate )
2257 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2260 /* check if entire window can be copied */
2262 ow = lpOldWndRect->right - lpOldWndRect->left;
2263 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2264 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2265 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2267 ocw = lpOldClientRect->right - lpOldClientRect->left;
2268 och = lpOldClientRect->bottom - lpOldClientRect->top;
2269 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2270 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2272 if( (ocw != ncw) || (och != nch) ||
2273 ( ow != nw) || ( oh != nh) ||
2274 ((lpOldClientRect->top - lpOldWndRect->top) !=
2275 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2276 ((lpOldClientRect->left - lpOldWndRect->left) !=
2277 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2279 dx = Wnd->rectClient.left - lpOldClientRect->left;
2280 dy = Wnd->rectClient.top - lpOldClientRect->top;
2282 /* restrict valid bits to the common client rect */
2284 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2285 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2286 r.right = r.left + min( ocw, ncw );
2287 r.bottom = r.top + min( och, nch );
2289 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2290 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2291 GetRgnBox( hrgnValid, &r );
2292 if( IsRectEmpty( &r ) )
2294 r = *lpOldClientRect;
2298 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2299 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2300 if( !(uFlags & SWP_EX_PAINTSELF) )
2301 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2305 if( !(uFlags & SWP_EX_PAINTSELF) )
2307 /* Move remaining regions to parent coordinates */
2308 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2309 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2312 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2314 TRACE("\tcomputing dirty region!\n");
2316 /* Compute combined dirty region (old + new - valid) */
2317 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2318 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2320 /* Blt valid bits, r is the rect to copy */
2327 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2328 from copying clipped areas */
2330 if( uFlags & SWP_EX_PAINTSELF )
2332 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2333 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2334 rClip.right = nw; rClip.bottom = nh;
2338 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2339 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2340 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2341 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2343 rClip.left = rClip.top = 0;
2345 if( oh > nh ) r.bottom = r.top + nh;
2346 if( ow < nw ) r.right = r.left + nw;
2348 if( IntersectRect( &r, &r, &rClip ) )
2350 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2352 /* When you copy the bits without repainting, parent doesn't
2353 get validated appropriately. Therefore, we have to validate
2354 the parent with the windows' updated region when the
2355 parent's update region is not empty. */
2357 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2359 OffsetRect(&r, dx, dy);
2360 ValidateRect(Wnd->parent->hwndSelf, &r);
2363 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2364 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2368 /* *pVisRgn now points to the invalidated region */
2370 DeleteObject(newVisRgn);
2371 DeleteObject(dirtyRgn);
2375 /***********************************************************************
2376 * SWP_DoSimpleFrameChanged
2378 * NOTE: old and new client rect origins are identical, only
2379 * extents may have changed. Window extents are the same.
2381 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2387 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2389 /* Client rect changed its position/size, most likely a scrollar
2390 * was added/removed.
2392 * FIXME: WVR alignment flags
2395 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2399 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2400 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2401 if(!(uFlags & SWP_EX_NOCOPY))
2402 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2410 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2413 hrgn = CreateRectRgnIndirect( &rect );
2415 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2416 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2417 if(!(uFlags & SWP_EX_NOCOPY))
2418 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2422 REGION_UnionRectWithRgn( hrgn, &rect );
2425 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2427 rect = wndPtr->rectWindow;
2428 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2429 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2437 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2438 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2442 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2446 DeleteObject( hrgn );
2449 /***********************************************************************
2450 * SWP_DoWinPosChanging
2452 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2453 RECT* pNewWindowRect, RECT* pNewClientRect )
2455 /* Send WM_WINDOWPOSCHANGING message */
2457 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2458 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2460 /* Calculate new position and size */
2462 *pNewWindowRect = wndPtr->rectWindow;
2463 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2464 : wndPtr->rectClient;
2466 if (!(pWinpos->flags & SWP_NOSIZE))
2468 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2469 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2471 if (!(pWinpos->flags & SWP_NOMOVE))
2473 pNewWindowRect->left = pWinpos->x;
2474 pNewWindowRect->top = pWinpos->y;
2475 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2476 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2478 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2479 pWinpos->y - wndPtr->rectWindow.top );
2482 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2486 /***********************************************************************
2489 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2490 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2494 /* Send WM_NCCALCSIZE message to get new client area */
2495 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2497 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2498 &wndPtr->rectWindow, &wndPtr->rectClient,
2499 pWinpos, pNewClientRect );
2501 /* FIXME: WVR_ALIGNxxx */
2503 if( pNewClientRect->left != wndPtr->rectClient.left ||
2504 pNewClientRect->top != wndPtr->rectClient.top )
2505 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2507 if( (pNewClientRect->right - pNewClientRect->left !=
2508 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2509 (pNewClientRect->bottom - pNewClientRect->top !=
2510 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2511 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2514 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2515 pNewClientRect->top != wndPtr->rectClient.top) )
2516 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2520 /***********************************************************************
2521 * SetWindowPos (USER.2)
2523 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2524 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2526 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2529 /***********************************************************************
2530 * SetWindowPos (USER32.520)
2532 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2533 INT x, INT y, INT cx, INT cy, UINT flags )
2536 WND * wndPtr,*wndTemp;
2537 RECT newWindowRect, newClientRect;
2538 RECT oldWindowRect, oldClientRect;
2540 UINT wvrFlags = 0, uFlags = 0;
2541 BOOL retvalue, resync = FALSE, bChangePos;
2542 HWND hwndActive = 0;
2544 /* Get current active window from the active queue */
2547 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2550 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2551 QUEUE_Unlock( pActiveQueue );
2555 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2556 hwnd, x, y, x+cx, y+cy, flags);
2558 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2559 flags &= ~SWP_WINE_NOHOSTMOVE;
2562 /* ------------------------------------------------------------------------ CHECKS */
2564 /* Check window handle */
2566 if (hwnd == GetDesktopWindow()) return FALSE;
2567 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2569 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2570 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2572 /* Fix redundant flags */
2574 if(wndPtr->dwStyle & WS_VISIBLE)
2575 flags &= ~SWP_SHOWWINDOW;
2578 if (!(flags & SWP_SHOWWINDOW))
2579 flags |= SWP_NOREDRAW;
2580 flags &= ~SWP_HIDEWINDOW;
2583 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2585 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2586 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2587 flags |= SWP_NOSIZE; /* Already the right size */
2589 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2590 flags |= SWP_NOMOVE; /* Already the right position */
2592 if (hwnd == hwndActive)
2593 flags |= SWP_NOACTIVATE; /* Already active */
2594 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2596 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2598 flags &= ~SWP_NOZORDER;
2599 hwndInsertAfter = HWND_TOP;
2604 /* Check hwndInsertAfter */
2606 /* FIXME: TOPMOST not supported yet */
2607 if ((hwndInsertAfter == HWND_TOPMOST) ||
2608 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2610 /* hwndInsertAfter must be a sibling of the window */
2611 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2613 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2616 if( wnd->parent != wndPtr->parent )
2619 WIN_ReleaseWndPtr(wnd);
2622 /* don't need to change the Zorder of hwnd if it's already inserted
2623 * after hwndInsertAfter or when inserting hwnd after itself.
2625 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2627 WIN_ReleaseWndPtr(wnd);
2630 Pos: /* ------------------------------------------------------------------------ MAIN part */
2632 /* Fill the WINDOWPOS structure */
2635 winpos.hwndInsertAfter = hwndInsertAfter;
2640 winpos.flags = flags;
2642 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2644 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2646 if( wndPtr->parent == WIN_GetDesktop() )
2647 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2648 hwndInsertAfter, winpos.flags );
2649 WIN_ReleaseDesktop();
2652 if(!(wndPtr->flags & WIN_NATIVE) )
2654 if( hwndInsertAfter == HWND_TOP )
2655 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2657 if( hwndInsertAfter == HWND_BOTTOM )
2658 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2660 if( !(winpos.flags & SWP_NOZORDER) )
2661 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2662 winpos.flags |= SWP_NOZORDER;
2664 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2665 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2666 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2668 /* get a previous visible region for SWP_CopyValidBits() */
2669 DWORD dflags = DCX_WINDOW;
2671 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2672 dflags |= DCX_CLIPSIBLINGS;
2674 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2678 /* Common operations */
2680 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2682 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2684 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2685 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2688 /* Reset active DCEs */
2690 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2691 wndPtr->dwStyle & WS_VISIBLE) ||
2692 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2696 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2697 DCE_InvalidateDCE(wndPtr, &rect);
2700 oldWindowRect = wndPtr->rectWindow;
2701 oldClientRect = wndPtr->rectClient;
2703 /* Find out if we have to redraw the whole client rect */
2705 if( oldClientRect.bottom - oldClientRect.top ==
2706 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2708 if( oldClientRect.right - oldClientRect.left ==
2709 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2711 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2712 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2714 uFlags |= SWP_EX_NOCOPY;
2717 * Use this later in CopyValidBits()
2720 uFlags |= SWP_EX_NONCLIENT;
2723 /* FIXME: actually do something with WVR_VALIDRECTS */
2725 wndPtr->rectWindow = newWindowRect;
2726 wndPtr->rectClient = newClientRect;
2728 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2730 BOOL bCallDriver = TRUE;
2731 HWND tempInsertAfter = winpos.hwndInsertAfter;
2733 winpos.hwndInsertAfter = hwndInsertAfter;
2735 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2737 /* This is the only place where we need to force repainting of the contents
2738 of windows created by the host window system, all other cases go through the
2739 expose event handling */
2741 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2743 cx = newWindowRect.right - newWindowRect.left;
2744 cy = newWindowRect.bottom - newWindowRect.top;
2746 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2747 winpos.hwndInsertAfter = tempInsertAfter;
2748 bCallDriver = FALSE;
2750 if( winpos.flags & SWP_NOCLIENTMOVE )
2751 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2754 /* client area moved but window extents remained the same, copy valid bits */
2756 visRgn = CreateRectRgn( 0, 0, cx, cy );
2757 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2758 uFlags | SWP_EX_PAINTSELF );
2765 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2767 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2768 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2769 !(uFlags & SWP_EX_NOCOPY) )
2771 /* The origin of the client rect didn't move so we can try to repaint
2772 * only the nonclient area by setting bit gravity hint for the host window system.
2775 if( !(wndPtr->flags & WIN_MANAGED) )
2777 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2778 newWindowRect.bottom - newWindowRect.top);
2779 RECT rcn = newClientRect;
2780 RECT rco = oldClientRect;
2782 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2783 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2784 IntersectRect( &rcn, &rcn, &rco );
2785 visRgn = CreateRectRgnIndirect( &rcn );
2786 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2787 DeleteObject( hrgn );
2788 uFlags = SWP_EX_PAINTSELF;
2790 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2793 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2796 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2797 winpos.hwndInsertAfter = tempInsertAfter;
2800 if( winpos.flags & SWP_SHOWWINDOW )
2804 wndPtr->dwStyle |= WS_VISIBLE;
2806 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2808 /* focus was set to unmapped window, reset host focus
2809 * since the window is now visible */
2811 focus = curr = GetFocus();
2816 WND *pFocus = WIN_FindWndPtr( focus );
2818 pFocus->pDriver->pSetFocus(pFocus);
2819 WIN_ReleaseWndPtr(pFocus);
2822 curr = GetParent(curr);
2826 else /* -------------------------------------------- emulated window */
2828 if( winpos.flags & SWP_SHOWWINDOW )
2830 wndPtr->dwStyle |= WS_VISIBLE;
2831 uFlags |= SWP_EX_PAINTSELF;
2832 visRgn = 1; /* redraw the whole window */
2834 else if( !(winpos.flags & SWP_NOREDRAW) )
2836 if( winpos.flags & SWP_HIDEWINDOW )
2838 if( visRgn > 1 ) /* map to parent */
2839 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2845 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2846 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2847 &oldClientRect, uFlags);
2850 /* nothing moved, redraw frame if needed */
2852 if( winpos.flags & SWP_FRAMECHANGED )
2853 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2856 DeleteObject( visRgn );
2864 if( winpos.flags & SWP_HIDEWINDOW )
2866 wndPtr->dwStyle &= ~WS_VISIBLE;
2869 if (hwnd == CARET_GetHwnd())
2871 if( winpos.flags & SWP_HIDEWINDOW )
2873 else if (winpos.flags & SWP_SHOWWINDOW)
2877 /* ------------------------------------------------------------------------ FINAL */
2879 if (wndPtr->flags & WIN_NATIVE)
2880 EVENT_Synchronize(); /* Synchronize with the host window system */
2882 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2884 /* Simulate a mouse event to set the cursor */
2885 int iWndsLocks = WIN_SuspendWndsLock();
2887 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2888 PosX, PosY, GetTickCount(), 0 );
2890 WIN_RestoreWndsLock(iWndsLocks);
2893 wndTemp = WIN_GetDesktop();
2895 /* repaint invalidated region (if any)
2897 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2898 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2903 if( !(winpos.flags & SWP_NOREDRAW) )
2906 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2907 its parent and sibling and so on, and then erase the parent window
2908 back ground if the parent is either a top-level window or its parent's parent
2909 is top-level window. Rely on the system to repaint other affected
2910 windows later on. */
2911 if( uFlags & SWP_EX_PAINTSELF )
2913 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2914 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2915 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2919 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2920 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2924 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2926 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2927 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2931 DeleteObject( visRgn );
2934 WIN_ReleaseDesktop();
2936 if (!(flags & SWP_NOACTIVATE))
2937 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2939 /* And last, send the WM_WINDOWPOSCHANGED message */
2941 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2944 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2945 !(winpos.flags & SWP_NOSENDCHANGING)) )
2947 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2948 if (resync) EVENT_Synchronize();
2953 WIN_ReleaseWndPtr(wndPtr);
2958 /***********************************************************************
2959 * BeginDeferWindowPos16 (USER.259)
2961 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2963 return BeginDeferWindowPos( count );
2967 /***********************************************************************
2968 * BeginDeferWindowPos (USER32.9)
2970 HDWP WINAPI BeginDeferWindowPos( INT count )
2977 SetLastError(ERROR_INVALID_PARAMETER);
2980 /* Windows allows zero count, in which case it allocates context for 8 moves */
2981 if (count == 0) count = 8;
2983 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2984 if (!handle) return 0;
2985 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2986 pDWP->actualCount = 0;
2987 pDWP->suggestedCount = count;
2989 pDWP->wMagic = DWP_MAGIC;
2990 pDWP->hwndParent = 0;
2995 /***********************************************************************
2996 * DeferWindowPos16 (USER.260)
2998 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2999 INT16 x, INT16 y, INT16 cx, INT16 cy,
3002 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3003 x, y, cx, cy, flags );
3007 /***********************************************************************
3008 * DeferWindowPos (USER32.128)
3010 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3011 INT x, INT y, INT cx, INT cy,
3016 HDWP newhdwp = hdwp,retvalue;
3020 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3021 if (!pDWP) return 0;
3022 if (hwnd == GetDesktopWindow()) return 0;
3024 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3025 USER_HEAP_FREE( hdwp );
3029 /* Numega Bounds Checker Demo dislikes the following code.
3030 In fact, I've not been able to find any "same parent" requirement in any docu
3034 /* All the windows of a DeferWindowPos() must have the same parent */
3035 parent = pWnd->parent->hwndSelf;
3036 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3037 else if (parent != pDWP->hwndParent)
3039 USER_HEAP_FREE( hdwp );
3045 for (i = 0; i < pDWP->actualCount; i++)
3047 if (pDWP->winPos[i].hwnd == hwnd)
3049 /* Merge with the other changes */
3050 if (!(flags & SWP_NOZORDER))
3052 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3054 if (!(flags & SWP_NOMOVE))
3056 pDWP->winPos[i].x = x;
3057 pDWP->winPos[i].y = y;
3059 if (!(flags & SWP_NOSIZE))
3061 pDWP->winPos[i].cx = cx;
3062 pDWP->winPos[i].cy = cy;
3064 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3065 SWP_NOZORDER | SWP_NOREDRAW |
3066 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3068 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3074 if (pDWP->actualCount >= pDWP->suggestedCount)
3076 newhdwp = USER_HEAP_REALLOC( hdwp,
3077 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3083 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3084 pDWP->suggestedCount++;
3086 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3087 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3088 pDWP->winPos[pDWP->actualCount].x = x;
3089 pDWP->winPos[pDWP->actualCount].y = y;
3090 pDWP->winPos[pDWP->actualCount].cx = cx;
3091 pDWP->winPos[pDWP->actualCount].cy = cy;
3092 pDWP->winPos[pDWP->actualCount].flags = flags;
3093 pDWP->actualCount++;
3096 WIN_ReleaseWndPtr(pWnd);
3101 /***********************************************************************
3102 * EndDeferWindowPos16 (USER.261)
3104 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3106 return EndDeferWindowPos( hdwp );
3110 /***********************************************************************
3111 * EndDeferWindowPos (USER32.173)
3113 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3120 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3121 if (!pDWP) return FALSE;
3122 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3124 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3125 winpos->x, winpos->y, winpos->cx,
3126 winpos->cy, winpos->flags ))) break;
3128 USER_HEAP_FREE( hdwp );
3133 /***********************************************************************
3134 * TileChildWindows (USER.199)
3136 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3138 FIXME("(%04x, %d): stub\n", parent, action);
3141 /***********************************************************************
3142 * CascadeChildWindows (USER.198)
3144 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3146 FIXME("(%04x, %d): stub\n", parent, action);
3149 /***********************************************************************
3150 * SetProgmanWindow [USER32.522]
3152 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3154 hGlobalProgmanWindow = hwnd;
3155 return hGlobalProgmanWindow;
3158 /***********************************************************************
3159 * GetProgmanWindow [USER32.289]
3161 HRESULT WINAPI GetProgmanWindow ( )
3163 return hGlobalProgmanWindow;
3166 /***********************************************************************
3167 * SetShellWindowEx [USER32.531]
3168 * hwndProgman = Progman[Program Manager]
3169 * |-> SHELLDLL_DefView
3170 * hwndListView = | |-> SysListView32
3171 * | | |-> tooltips_class32
3177 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3179 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3180 hGlobalShellWindow = hwndProgman;
3181 return hGlobalShellWindow;
3185 /***********************************************************************
3186 * SetTaskmanWindow [USER32.537]
3188 * hwnd = MSTaskSwWClass
3189 * |-> SysTabControl32
3191 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3193 hGlobalTaskmanWindow = hwnd;
3194 return hGlobalTaskmanWindow;
3197 /***********************************************************************
3198 * GetTaskmanWindow [USER32.304]
3200 HRESULT WINAPI GetTaskmanWindow ( )
3202 return hGlobalTaskmanWindow;