Better implementation of [GS]etForegroundWindow.
[wine/hacks.git] / windows / winpos.c
blob5954f180ac6468dc050be3035ad5292ba8e022d7
1 /*
2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
6 */
8 #include <string.h>
9 #include "wine/winuser16.h"
10 #include "heap.h"
11 #include "module.h"
12 #include "user.h"
13 #include "region.h"
14 #include "win.h"
15 #include "hook.h"
16 #include "message.h"
17 #include "queue.h"
18 #include "options.h"
19 #include "task.h"
20 #include "winpos.h"
21 #include "dce.h"
22 #include "nonclient.h"
23 #include "debug.h"
24 #include "local.h"
25 #include "ldt.h"
27 DEFAULT_DEBUG_CHANNEL(win)
29 #define HAS_DLGFRAME(style,exStyle) \
30 (((exStyle) & WS_EX_DLGMODALFRAME) || \
31 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
33 #define HAS_THICKFRAME(style) \
34 (((style) & WS_THICKFRAME) && \
35 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
37 #define SWP_AGG_NOGEOMETRYCHANGE \
38 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
39 #define SWP_AGG_NOPOSCHANGE \
40 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
41 #define SWP_AGG_STATUSFLAGS \
42 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
44 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
46 #define PLACE_MIN 0x0001
47 #define PLACE_MAX 0x0002
48 #define PLACE_RECT 0x0004
50 #define SWP_EX_NOCOPY 0x0001
51 #define SWP_EX_PAINTSELF 0x0002
52 #define SWP_EX_NONCLIENT 0x0004
54 #define MINMAX_NOSWP 0x00010000
56 /* ----- internal variables ----- */
58 static HWND hwndPrevActive = 0; /* Previously active window */
59 static HWND hGlobalShellWindow=0; /*the shell*/
60 static HWND hGlobalTaskmanWindow=0;
61 static HWND hGlobalProgmanWindow=0;
63 static LPCSTR atomInternalPos;
65 extern HQUEUE16 hActiveQueue;
67 /***********************************************************************
68 * WINPOS_CreateInternalPosAtom
70 BOOL WINPOS_CreateInternalPosAtom()
72 LPSTR str = "SysIP";
73 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
74 return (atomInternalPos) ? TRUE : FALSE;
77 /***********************************************************************
78 * WINPOS_CheckInternalPos
80 * Called when a window is destroyed.
82 void WINPOS_CheckInternalPos( WND* wndPtr )
84 LPINTERNALPOS lpPos;
85 MESSAGEQUEUE *pMsgQ = 0;
86 HWND hwnd = wndPtr->hwndSelf;
88 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
90 /* Retrieve the message queue associated with this window */
91 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
92 if ( !pMsgQ )
94 WARN( win, "\tMessage queue not found. Exiting!\n" );
95 return;
98 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
100 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
102 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
103 WARN(win, "\tattempt to activate destroyed window!\n");
106 if( lpPos )
108 if( IsWindow(lpPos->hwndIconTitle) )
109 DestroyWindow( lpPos->hwndIconTitle );
110 HeapFree( SystemHeap, 0, lpPos );
113 QUEUE_Unlock( pMsgQ );
114 return;
117 /***********************************************************************
118 * WINPOS_FindIconPos
120 * Find a suitable place for an iconic window.
122 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
124 RECT16 rectParent;
125 short x, y, xspacing, yspacing;
127 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
128 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
129 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
130 return pt; /* The icon already has a suitable position */
132 xspacing = GetSystemMetrics(SM_CXICONSPACING);
133 yspacing = GetSystemMetrics(SM_CYICONSPACING);
135 y = rectParent.bottom;
136 for (;;)
138 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
140 /* Check if another icon already occupies this spot */
141 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
142 while (childPtr)
144 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
146 if ((childPtr->rectWindow.left < x + xspacing) &&
147 (childPtr->rectWindow.right >= x) &&
148 (childPtr->rectWindow.top <= y) &&
149 (childPtr->rectWindow.bottom > y - yspacing))
150 break; /* There's a window in there */
152 WIN_UpdateWndPtr(&childPtr,childPtr->next);
154 WIN_ReleaseWndPtr(childPtr);
155 if (!childPtr) /* No window was found, so it's OK for us */
157 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
158 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
159 return pt;
162 y -= yspacing;
167 /***********************************************************************
168 * ArrangeIconicWindows16 (USER.170)
170 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
172 return ArrangeIconicWindows(parent);
174 /***********************************************************************
175 * ArrangeIconicWindows (USER32.7)
177 UINT WINAPI ArrangeIconicWindows( HWND parent )
179 RECT rectParent;
180 HWND hwndChild;
181 INT x, y, xspacing, yspacing;
183 GetClientRect( parent, &rectParent );
184 x = rectParent.left;
185 y = rectParent.bottom;
186 xspacing = GetSystemMetrics(SM_CXICONSPACING);
187 yspacing = GetSystemMetrics(SM_CYICONSPACING);
189 hwndChild = GetWindow( parent, GW_CHILD );
190 while (hwndChild)
192 if( IsIconic( hwndChild ) )
194 WND *wndPtr = WIN_FindWndPtr(hwndChild);
196 WINPOS_ShowIconTitle( wndPtr, FALSE );
198 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
199 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
200 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
201 if( IsWindow(hwndChild) )
202 WINPOS_ShowIconTitle(wndPtr , TRUE );
203 WIN_ReleaseWndPtr(wndPtr);
205 if (x <= rectParent.right - xspacing) x += xspacing;
206 else
208 x = rectParent.left;
209 y -= yspacing;
212 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
214 return yspacing;
218 /***********************************************************************
219 * SwitchToThisWindow16 (USER.172)
221 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
223 SwitchToThisWindow( hwnd, restore );
227 /***********************************************************************
228 * SwitchToThisWindow (USER32.539)
230 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
232 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
236 /***********************************************************************
237 * GetWindowRect16 (USER.32)
239 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
241 WND * wndPtr = WIN_FindWndPtr( hwnd );
242 if (!wndPtr) return;
244 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
245 if (wndPtr->dwStyle & WS_CHILD)
246 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
247 WIN_ReleaseWndPtr(wndPtr);
251 /***********************************************************************
252 * GetWindowRect (USER32.308)
254 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
256 WND * wndPtr = WIN_FindWndPtr( hwnd );
257 if (!wndPtr) return FALSE;
259 *rect = wndPtr->rectWindow;
260 if (wndPtr->dwStyle & WS_CHILD)
261 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
262 WIN_ReleaseWndPtr(wndPtr);
263 return TRUE;
267 /***********************************************************************
268 * GetWindowRgn
270 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
273 RECT rect;
274 WND * wndPtr = WIN_FindWndPtr( hwnd );
275 if (!wndPtr) return (ERROR);
277 FIXME (win, "GetWindowRgn: doesn't really do regions\n");
279 memset (&rect, 0, sizeof(rect));
281 GetWindowRect ( hwnd, &rect );
283 FIXME (win, "Check whether a valid region here\n");
285 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
287 WIN_ReleaseWndPtr(wndPtr);
288 return (SIMPLEREGION);
291 /***********************************************************************
292 * SetWindowRgn
294 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
298 FIXME (win, "SetWindowRgn: stub\n");
299 return TRUE;
302 /***********************************************************************
303 * SetWindowRgn16
305 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
309 FIXME (win, "SetWindowRgn16: stub\n");
310 return TRUE;
314 /***********************************************************************
315 * GetClientRect16 (USER.33)
317 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
319 WND * wndPtr = WIN_FindWndPtr( hwnd );
321 rect->left = rect->top = rect->right = rect->bottom = 0;
322 if (wndPtr)
324 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
325 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
327 WIN_ReleaseWndPtr(wndPtr);
331 /***********************************************************************
332 * GetClientRect (USER.220)
334 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
336 WND * wndPtr = WIN_FindWndPtr( hwnd );
338 rect->left = rect->top = rect->right = rect->bottom = 0;
339 if (!wndPtr) return FALSE;
340 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
341 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
343 WIN_ReleaseWndPtr(wndPtr);
344 return TRUE;
348 /*******************************************************************
349 * ClientToScreen16 (USER.28)
351 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
353 MapWindowPoints16( hwnd, 0, lppnt, 1 );
357 /*******************************************************************
358 * ClientToScreen (USER32.52)
360 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
362 MapWindowPoints( hwnd, 0, lppnt, 1 );
363 return TRUE;
367 /*******************************************************************
368 * ScreenToClient16 (USER.29)
370 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
372 MapWindowPoints16( 0, hwnd, lppnt, 1 );
376 /*******************************************************************
377 * ScreenToClient (USER32.447)
379 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
381 MapWindowPoints( 0, hwnd, lppnt, 1 );
382 return TRUE;
386 /***********************************************************************
387 * WINPOS_WindowFromPoint
389 * Find the window and hittest for a given point.
391 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
393 WND *wndPtr;
394 INT16 hittest = HTERROR;
395 INT16 retvalue;
396 POINT16 xy = pt;
398 *ppWnd = NULL;
399 wndPtr = WIN_LockWndPtr(wndScope->child);
401 if( wndScope->flags & WIN_MANAGED )
403 /* In managed mode we have to check wndScope first as it is also
404 * a window which received the mouse event. */
406 if( wndScope->dwStyle & WS_DISABLED )
408 retvalue = HTERROR;
409 goto end;
411 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
412 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
413 goto hittest;
415 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
417 for (;;)
419 while (wndPtr)
421 /* If point is in window, and window is visible, and it */
422 /* is enabled (or it's a top-level window), then explore */
423 /* its children. Otherwise, go to the next window. */
425 if ((wndPtr->dwStyle & WS_VISIBLE) &&
426 (!(wndPtr->dwStyle & WS_DISABLED) ||
427 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
428 (xy.x >= wndPtr->rectWindow.left) &&
429 (xy.x < wndPtr->rectWindow.right) &&
430 (xy.y >= wndPtr->rectWindow.top) &&
431 (xy.y < wndPtr->rectWindow.bottom))
433 *ppWnd = wndPtr; /* Got a suitable window */
435 /* If window is minimized or disabled, return at once */
436 if (wndPtr->dwStyle & WS_MINIMIZE)
438 retvalue = HTCAPTION;
439 goto end;
441 if (wndPtr->dwStyle & WS_DISABLED)
443 retvalue = HTERROR;
444 goto end;
447 /* If point is not in client area, ignore the children */
448 if ((xy.x < wndPtr->rectClient.left) ||
449 (xy.x >= wndPtr->rectClient.right) ||
450 (xy.y < wndPtr->rectClient.top) ||
451 (xy.y >= wndPtr->rectClient.bottom)) break;
453 xy.x -= wndPtr->rectClient.left;
454 xy.y -= wndPtr->rectClient.top;
455 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
457 else
459 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
463 hittest:
464 /* If nothing found, try the scope window */
465 if (!*ppWnd) *ppWnd = wndScope;
467 /* Send the WM_NCHITTEST message (only if to the same task) */
468 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
470 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
471 0, MAKELONG( pt.x, pt.y ) );
472 if (hittest != HTTRANSPARENT)
474 retvalue = hittest; /* Found the window */
475 goto end;
478 else
480 retvalue = HTCLIENT;
481 goto end;
484 /* If no children found in last search, make point relative to parent */
485 if (!wndPtr)
487 xy.x += (*ppWnd)->rectClient.left;
488 xy.y += (*ppWnd)->rectClient.top;
491 /* Restart the search from the next sibling */
492 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
493 *ppWnd = (*ppWnd)->parent;
496 end:
497 WIN_ReleaseWndPtr(wndPtr);
498 return retvalue;
502 /*******************************************************************
503 * WindowFromPoint16 (USER.30)
505 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
507 WND *pWnd;
508 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
509 WIN_ReleaseDesktop();
510 return pWnd->hwndSelf;
514 /*******************************************************************
515 * WindowFromPoint (USER32.582)
517 HWND WINAPI WindowFromPoint( POINT pt )
519 WND *pWnd;
520 POINT16 pt16;
521 CONV_POINT32TO16( &pt, &pt16 );
522 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
523 WIN_ReleaseDesktop();
524 return (HWND)pWnd->hwndSelf;
528 /*******************************************************************
529 * ChildWindowFromPoint16 (USER.191)
531 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
533 POINT pt32;
534 CONV_POINT16TO32( &pt, &pt32 );
535 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
539 /*******************************************************************
540 * ChildWindowFromPoint (USER32.49)
542 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
544 /* pt is in the client coordinates */
546 WND* wnd = WIN_FindWndPtr(hwndParent);
547 RECT rect;
548 HWND retvalue;
550 if( !wnd ) return 0;
552 /* get client rect fast */
553 rect.top = rect.left = 0;
554 rect.right = wnd->rectClient.right - wnd->rectClient.left;
555 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
557 if (!PtInRect( &rect, pt ))
559 retvalue = 0;
560 goto end;
562 WIN_UpdateWndPtr(&wnd,wnd->child);
563 while ( wnd )
565 if (PtInRect( &wnd->rectWindow, pt ))
567 retvalue = wnd->hwndSelf;
568 goto end;
570 WIN_UpdateWndPtr(&wnd,wnd->next);
572 retvalue = hwndParent;
573 end:
574 WIN_ReleaseWndPtr(wnd);
575 return retvalue;
578 /*******************************************************************
579 * ChildWindowFromPointEx16 (USER.50)
581 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
583 POINT pt32;
584 CONV_POINT16TO32( &pt, &pt32 );
585 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
589 /*******************************************************************
590 * ChildWindowFromPointEx32 (USER32.50)
592 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
593 UINT uFlags)
595 /* pt is in the client coordinates */
597 WND* wnd = WIN_FindWndPtr(hwndParent);
598 RECT rect;
599 HWND retvalue;
601 if( !wnd ) return 0;
603 /* get client rect fast */
604 rect.top = rect.left = 0;
605 rect.right = wnd->rectClient.right - wnd->rectClient.left;
606 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
608 if (!PtInRect( &rect, pt ))
610 retvalue = 0;
611 goto end;
613 WIN_UpdateWndPtr(&wnd,wnd->child);
615 while ( wnd )
617 if (PtInRect( &wnd->rectWindow, pt )) {
618 if ( (uFlags & CWP_SKIPINVISIBLE) &&
619 !(wnd->dwStyle & WS_VISIBLE) );
620 else if ( (uFlags & CWP_SKIPDISABLED) &&
621 (wnd->dwStyle & WS_DISABLED) );
622 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
623 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
624 else
626 retvalue = wnd->hwndSelf;
627 goto end;
631 WIN_UpdateWndPtr(&wnd,wnd->next);
633 retvalue = hwndParent;
634 end:
635 WIN_ReleaseWndPtr(wnd);
636 return retvalue;
640 /*******************************************************************
641 * WINPOS_GetWinOffset
643 * Calculate the offset between the origin of the two windows. Used
644 * to implement MapWindowPoints.
646 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
647 POINT *offset )
649 WND * wndPtr = 0;
651 offset->x = offset->y = 0;
652 if (hwndFrom == hwndTo ) return;
654 /* Translate source window origin to screen coords */
655 if (hwndFrom)
657 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
659 ERR(win,"bad hwndFrom = %04x\n",hwndFrom);
660 return;
662 while (wndPtr->parent)
664 offset->x += wndPtr->rectClient.left;
665 offset->y += wndPtr->rectClient.top;
666 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
668 WIN_ReleaseWndPtr(wndPtr);
671 /* Translate origin to destination window coords */
672 if (hwndTo)
674 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
676 ERR(win,"bad hwndTo = %04x\n", hwndTo );
677 return;
679 while (wndPtr->parent)
681 offset->x -= wndPtr->rectClient.left;
682 offset->y -= wndPtr->rectClient.top;
683 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
685 WIN_ReleaseWndPtr(wndPtr);
690 /*******************************************************************
691 * MapWindowPoints16 (USER.258)
693 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
694 LPPOINT16 lppt, UINT16 count )
696 POINT offset;
698 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
699 while (count--)
701 lppt->x += offset.x;
702 lppt->y += offset.y;
703 lppt++;
708 /*******************************************************************
709 * MapWindowPoints (USER32.386)
711 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
712 LPPOINT lppt, UINT count )
714 POINT offset;
716 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
717 while (count--)
719 lppt->x += offset.x;
720 lppt->y += offset.y;
721 lppt++;
723 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
727 /***********************************************************************
728 * IsIconic16 (USER.31)
730 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
732 return IsIconic(hWnd);
736 /***********************************************************************
737 * IsIconic (USER32.345)
739 BOOL WINAPI IsIconic(HWND hWnd)
741 BOOL retvalue;
742 WND * wndPtr = WIN_FindWndPtr(hWnd);
743 if (wndPtr == NULL) return FALSE;
744 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
745 WIN_ReleaseWndPtr(wndPtr);
746 return retvalue;
750 /***********************************************************************
751 * IsZoomed (USER.272)
753 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
755 return IsZoomed(hWnd);
759 /***********************************************************************
760 * IsZoomed (USER.352)
762 BOOL WINAPI IsZoomed(HWND hWnd)
764 BOOL retvalue;
765 WND * wndPtr = WIN_FindWndPtr(hWnd);
766 if (wndPtr == NULL) return FALSE;
767 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
768 WIN_ReleaseWndPtr(wndPtr);
769 return retvalue;
773 /*******************************************************************
774 * GetActiveWindow (USER.60)
776 HWND16 WINAPI GetActiveWindow16(void)
778 return (HWND16)GetActiveWindow();
781 /*******************************************************************
782 * GetActiveWindow (USER32.205)
784 HWND WINAPI GetActiveWindow(void)
786 MESSAGEQUEUE *pCurMsgQ = 0;
787 HWND hwndActive = 0;
789 /* Get the messageQ for the current thread */
790 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
792 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
793 return 0;
796 /* Return the current active window from the perQ data of the current message Q */
797 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
799 QUEUE_Unlock( pCurMsgQ );
800 return hwndActive;
804 /*******************************************************************
805 * WINPOS_CanActivate
807 static BOOL WINPOS_CanActivate(WND* pWnd)
809 if( pWnd && ((pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
810 == WS_VISIBLE) ) return TRUE;
811 return FALSE;
815 /*******************************************************************
816 * SetActiveWindow16 (USER.59)
818 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
820 return SetActiveWindow(hwnd);
824 /*******************************************************************
825 * SetActiveWindow (USER32.463)
827 HWND WINAPI SetActiveWindow( HWND hwnd )
829 HWND prev = 0;
830 WND *wndPtr = WIN_FindWndPtr( hwnd );
831 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
833 if ( !WINPOS_CanActivate(wndPtr) )
835 prev = 0;
836 goto end;
839 /* Get the messageQ for the current thread */
840 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
842 WARN( win, "\tCurrent message queue not found. Exiting!\n" );
843 goto CLEANUP;
846 /* Retrieve the message queue associated with this window */
847 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
848 if ( !pMsgQ )
850 WARN( win, "\tWindow message queue not found. Exiting!\n" );
851 goto CLEANUP;
854 /* Make sure that the window is associated with the calling threads
855 * message queue. It must share the same perQ data.
858 if ( pCurMsgQ->pQData != pMsgQ->pQData )
859 goto CLEANUP;
861 /* Save current active window */
862 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
864 WINPOS_SetActiveWindow( hwnd, 0, 0 );
866 CLEANUP:
867 /* Unlock the queues before returning */
868 if ( pMsgQ )
869 QUEUE_Unlock( pMsgQ );
870 if ( pCurMsgQ )
871 QUEUE_Unlock( pCurMsgQ );
873 end:
874 WIN_ReleaseWndPtr(wndPtr);
875 return prev;
879 /*******************************************************************
880 * GetForegroundWindow16 (USER.608)
882 HWND16 WINAPI GetForegroundWindow16(void)
884 return (HWND16)GetForegroundWindow();
888 /*******************************************************************
889 * SetForegroundWindow16 (USER.609)
891 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
893 return SetForegroundWindow( hwnd );
897 /*******************************************************************
898 * GetForegroundWindow (USER32.241)
900 HWND WINAPI GetForegroundWindow(void)
902 HWND hwndActive = 0;
904 /* Get the foreground window (active window of hActiveQueue) */
905 if ( hActiveQueue )
907 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
908 if ( pActiveQueue )
909 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
911 QUEUE_Unlock( pActiveQueue );
914 return hwndActive;
917 /*******************************************************************
918 * SetForegroundWindow (USER32.482)
920 BOOL WINAPI SetForegroundWindow( HWND hwnd )
922 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
926 /*******************************************************************
927 * GetShellWindow16 (USER.600)
929 HWND16 WINAPI GetShellWindow16(void)
931 return GetShellWindow();
934 /*******************************************************************
935 * SetShellWindow (USER32.504)
937 HWND WINAPI SetShellWindow(HWND hwndshell)
938 { WARN(win, "(hWnd=%08x) semi stub\n",hwndshell );
940 hGlobalShellWindow = hwndshell;
941 return hGlobalShellWindow;
945 /*******************************************************************
946 * GetShellWindow (USER32.287)
948 HWND WINAPI GetShellWindow(void)
949 { WARN(win, "(hWnd=%x) semi stub\n",hGlobalShellWindow );
951 return hGlobalShellWindow;
955 /***********************************************************************
956 * BringWindowToTop16 (USER.45)
958 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
960 return BringWindowToTop(hwnd);
964 /***********************************************************************
965 * BringWindowToTop (USER32.11)
967 BOOL WINAPI BringWindowToTop( HWND hwnd )
969 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
973 /***********************************************************************
974 * MoveWindow16 (USER.56)
976 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
977 BOOL16 repaint )
979 return MoveWindow(hwnd,x,y,cx,cy,repaint);
983 /***********************************************************************
984 * MoveWindow (USER32.399)
986 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
987 BOOL repaint )
989 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
990 if (!repaint) flags |= SWP_NOREDRAW;
991 TRACE(win, "%04x %d,%d %dx%d %d\n",
992 hwnd, x, y, cx, cy, repaint );
993 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
996 /***********************************************************************
997 * WINPOS_InitInternalPos
999 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1000 LPRECT restoreRect )
1002 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1003 atomInternalPos );
1004 if( !lpPos )
1006 /* this happens when the window is minimized/maximized
1007 * for the first time (rectWindow is not adjusted yet) */
1009 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1010 if( !lpPos ) return NULL;
1012 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1013 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1014 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1015 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1018 if( wnd->dwStyle & WS_MINIMIZE )
1019 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1020 else if( wnd->dwStyle & WS_MAXIMIZE )
1021 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1022 else if( restoreRect )
1023 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1025 return lpPos;
1028 /***********************************************************************
1029 * WINPOS_RedrawIconTitle
1031 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1033 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1034 if( lpPos )
1036 if( lpPos->hwndIconTitle )
1038 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1039 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1040 return TRUE;
1043 return FALSE;
1046 /***********************************************************************
1047 * WINPOS_ShowIconTitle
1049 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1051 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1053 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1055 HWND16 hWnd = lpPos->hwndIconTitle;
1057 TRACE(win,"0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1059 if( !hWnd )
1060 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1061 if( bShow )
1063 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1065 if( !(pWnd->dwStyle & WS_VISIBLE) )
1067 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1068 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1069 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1071 WIN_ReleaseWndPtr(pWnd);
1074 else ShowWindow( hWnd, SW_HIDE );
1076 return FALSE;
1079 /*******************************************************************
1080 * WINPOS_GetMinMaxInfo
1082 * Get the minimized and maximized information for a window.
1084 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1085 POINT *minTrack, POINT *maxTrack )
1087 LPINTERNALPOS lpPos;
1088 MINMAXINFO MinMax;
1089 INT xinc, yinc;
1091 /* Compute default values */
1093 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1094 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1095 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1096 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1097 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1098 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1100 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1101 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1103 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1104 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1106 else
1108 xinc = yinc = 0;
1109 if (HAS_THICKFRAME(wndPtr->dwStyle))
1111 xinc += GetSystemMetrics(SM_CXFRAME);
1112 yinc += GetSystemMetrics(SM_CYFRAME);
1114 if (wndPtr->dwStyle & WS_BORDER)
1116 xinc += GetSystemMetrics(SM_CXBORDER);
1117 yinc += GetSystemMetrics(SM_CYBORDER);
1120 MinMax.ptMaxSize.x += 2 * xinc;
1121 MinMax.ptMaxSize.y += 2 * yinc;
1123 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1124 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1125 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1126 else
1128 MinMax.ptMaxPosition.x = -xinc;
1129 MinMax.ptMaxPosition.y = -yinc;
1132 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1134 /* Some sanity checks */
1136 TRACE(win,"%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1137 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1138 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1139 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1140 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1141 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1142 MinMax.ptMinTrackSize.x );
1143 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1144 MinMax.ptMinTrackSize.y );
1146 if (maxSize) *maxSize = MinMax.ptMaxSize;
1147 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1148 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1149 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1152 /***********************************************************************
1153 * WINPOS_MinMaximize
1155 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1156 * This function assumes that 'cmd' is different from the current window
1157 * state.
1159 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1161 UINT swpFlags = 0;
1162 POINT pt, size;
1163 LPINTERNALPOS lpPos;
1165 TRACE(win,"0x%04x %u\n", wndPtr->hwndSelf, cmd );
1167 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1168 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1170 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1172 if( wndPtr->dwStyle & WS_MINIMIZE )
1174 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1175 return (SWP_NOSIZE | SWP_NOMOVE);
1176 swpFlags |= SWP_NOCOPYBITS;
1178 switch( cmd )
1180 case SW_MINIMIZE:
1181 if( wndPtr->dwStyle & WS_MAXIMIZE)
1183 wndPtr->flags |= WIN_RESTORE_MAX;
1184 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1186 else
1187 wndPtr->flags &= ~WIN_RESTORE_MAX;
1188 wndPtr->dwStyle |= WS_MINIMIZE;
1190 if( wndPtr->flags & WIN_NATIVE )
1191 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1192 swpFlags |= MINMAX_NOSWP;
1194 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1196 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1197 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1198 swpFlags |= SWP_NOCOPYBITS;
1199 break;
1201 case SW_MAXIMIZE:
1202 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1203 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1204 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1206 if( wndPtr->dwStyle & WS_MINIMIZE )
1208 if( wndPtr->flags & WIN_NATIVE )
1209 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1210 swpFlags |= MINMAX_NOSWP;
1212 WINPOS_ShowIconTitle( wndPtr, FALSE );
1213 wndPtr->dwStyle &= ~WS_MINIMIZE;
1215 wndPtr->dwStyle |= WS_MAXIMIZE;
1217 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1218 size.x, size.y );
1219 break;
1221 case SW_RESTORE:
1222 if( wndPtr->dwStyle & WS_MINIMIZE )
1224 if( wndPtr->flags & WIN_NATIVE )
1225 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1226 swpFlags |= MINMAX_NOSWP;
1228 wndPtr->dwStyle &= ~WS_MINIMIZE;
1229 WINPOS_ShowIconTitle( wndPtr, FALSE );
1231 if( wndPtr->flags & WIN_RESTORE_MAX)
1233 /* Restore to maximized position */
1234 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1235 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1236 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1237 wndPtr->dwStyle |= WS_MAXIMIZE;
1238 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1239 break;
1242 else
1243 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1244 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1246 /* Restore to normal position */
1248 *lpRect = lpPos->rectNormal;
1249 lpRect->right -= lpRect->left;
1250 lpRect->bottom -= lpRect->top;
1252 break;
1254 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1255 return swpFlags;
1258 /***********************************************************************
1259 * ShowWindowAsync (USER32.535)
1261 * doesn't wait; returns immediately.
1262 * used by threads to toggle windows in other (possibly hanging) threads
1264 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1266 /* FIXME: does ShowWindow() return immediately ? */
1267 return ShowWindow(hwnd, cmd);
1271 /***********************************************************************
1272 * ShowWindow16 (USER.42)
1274 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1276 return ShowWindow(hwnd,cmd);
1280 /***********************************************************************
1281 * ShowWindow (USER32.534)
1283 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1285 WND* wndPtr = WIN_FindWndPtr( hwnd );
1286 BOOL wasVisible, showFlag;
1287 RECT16 newPos = {0, 0, 0, 0};
1288 UINT swp = 0;
1290 if (!wndPtr) return FALSE;
1292 TRACE(win,"hwnd=%04x, cmd=%d\n", hwnd, cmd);
1294 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1296 switch(cmd)
1298 case SW_HIDE:
1299 if (!wasVisible) goto END;;
1300 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1301 SWP_NOACTIVATE | SWP_NOZORDER;
1302 if ((hwnd == GetFocus()) || IsChild( hwnd, GetFocus()))
1304 /* Revert focus to parent */
1305 SetFocus( GetParent(hwnd) );
1307 break;
1309 case SW_SHOWMINNOACTIVE:
1310 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1311 /* fall through */
1312 case SW_SHOWMINIMIZED:
1313 swp |= SWP_SHOWWINDOW;
1314 /* fall through */
1315 case SW_MINIMIZE:
1316 swp |= SWP_FRAMECHANGED;
1317 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1318 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1319 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1320 break;
1322 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1323 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1324 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1325 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1326 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1327 break;
1329 case SW_SHOWNA:
1330 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1331 /* fall through */
1332 case SW_SHOW:
1333 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1334 break;
1336 case SW_SHOWNOACTIVATE:
1337 swp |= SWP_NOZORDER;
1338 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1339 /* fall through */
1340 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1341 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1342 case SW_RESTORE:
1343 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1345 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1346 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1347 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1348 break;
1351 showFlag = (cmd != SW_HIDE);
1352 if (showFlag != wasVisible)
1354 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1355 if (!IsWindow( hwnd )) goto END;
1358 if ((wndPtr->dwStyle & WS_CHILD) &&
1359 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1360 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1362 /* Don't call SetWindowPos() on invisible child windows */
1363 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1364 else wndPtr->dwStyle |= WS_VISIBLE;
1366 else
1368 /* We can't activate a child window */
1369 if (wndPtr->dwStyle & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1370 if (!(swp & MINMAX_NOSWP))
1371 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1372 newPos.right, newPos.bottom, LOWORD(swp) );
1373 if (!IsWindow( hwnd )) goto END;
1374 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1377 if (wndPtr->flags & WIN_NEED_SIZE)
1379 /* should happen only in CreateWindowEx() */
1380 int wParam = SIZE_RESTORED;
1382 wndPtr->flags &= ~WIN_NEED_SIZE;
1383 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1384 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1385 SendMessageA( hwnd, WM_SIZE, wParam,
1386 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1387 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1388 SendMessageA( hwnd, WM_MOVE, 0,
1389 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1392 END:
1393 WIN_ReleaseWndPtr(wndPtr);
1394 return wasVisible;
1398 /***********************************************************************
1399 * GetInternalWindowPos16 (USER.460)
1401 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1402 LPPOINT16 ptIcon )
1404 WINDOWPLACEMENT16 wndpl;
1405 if (GetWindowPlacement16( hwnd, &wndpl ))
1407 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1408 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1409 return wndpl.showCmd;
1411 return 0;
1415 /***********************************************************************
1416 * GetInternalWindowPos (USER32.245)
1418 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1419 LPPOINT ptIcon )
1421 WINDOWPLACEMENT wndpl;
1422 if (GetWindowPlacement( hwnd, &wndpl ))
1424 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1425 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1426 return wndpl.showCmd;
1428 return 0;
1431 /***********************************************************************
1432 * GetWindowPlacement16 (USER.370)
1434 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1436 WND *pWnd = WIN_FindWndPtr( hwnd );
1437 LPINTERNALPOS lpPos;
1439 if(!pWnd ) return FALSE;
1441 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1442 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1443 wndpl->length = sizeof(*wndpl);
1444 if( pWnd->dwStyle & WS_MINIMIZE )
1445 wndpl->showCmd = SW_SHOWMINIMIZED;
1446 else
1447 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1448 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1449 if( pWnd->flags & WIN_RESTORE_MAX )
1450 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1451 else
1452 wndpl->flags = 0;
1453 wndpl->ptMinPosition = lpPos->ptIconPos;
1454 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1455 wndpl->rcNormalPosition = lpPos->rectNormal;
1457 WIN_ReleaseWndPtr(pWnd);
1458 return TRUE;
1462 /***********************************************************************
1463 * GetWindowPlacement (USER32.307)
1465 * Win95:
1466 * Fails if wndpl->length of Win95 (!) apps is invalid.
1468 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1470 if( pwpl32 )
1472 WINDOWPLACEMENT16 wpl;
1473 wpl.length = sizeof(wpl);
1474 if( GetWindowPlacement16( hwnd, &wpl ) )
1476 pwpl32->length = sizeof(*pwpl32);
1477 pwpl32->flags = wpl.flags;
1478 pwpl32->showCmd = wpl.showCmd;
1479 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1480 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1481 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1482 return TRUE;
1485 return FALSE;
1489 /***********************************************************************
1490 * WINPOS_SetPlacement
1492 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1493 UINT flags )
1495 WND *pWnd = WIN_FindWndPtr( hwnd );
1496 if( pWnd )
1498 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1499 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1501 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1502 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1503 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1505 if( pWnd->dwStyle & WS_MINIMIZE )
1507 WINPOS_ShowIconTitle( pWnd, FALSE );
1508 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1509 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1510 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1512 else if( pWnd->dwStyle & WS_MAXIMIZE )
1514 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1515 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1516 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1518 else if( flags & PLACE_RECT )
1519 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1520 lpPos->rectNormal.right - lpPos->rectNormal.left,
1521 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1522 SWP_NOZORDER | SWP_NOACTIVATE );
1524 ShowWindow( hwnd, wndpl->showCmd );
1525 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1527 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1529 /* SDK: ...valid only the next time... */
1530 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1532 WIN_ReleaseWndPtr(pWnd);
1533 return TRUE;
1535 return FALSE;
1539 /***********************************************************************
1540 * SetWindowPlacement16 (USER.371)
1542 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1544 return WINPOS_SetPlacement( hwnd, wndpl,
1545 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1548 /***********************************************************************
1549 * SetWindowPlacement (USER32.519)
1551 * Win95:
1552 * Fails if wndpl->length of Win95 (!) apps is invalid.
1554 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1556 if( pwpl32 )
1558 WINDOWPLACEMENT16 wpl;
1560 wpl.length = sizeof(WINDOWPLACEMENT16);
1561 wpl.flags = pwpl32->flags;
1562 wpl.showCmd = pwpl32->showCmd;
1563 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1564 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1565 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1566 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1567 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1568 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1569 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1570 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1572 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1574 return FALSE;
1578 /***********************************************************************
1579 * SetInternalWindowPos16 (USER.461)
1581 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1582 LPRECT16 rect, LPPOINT16 pt )
1584 if( IsWindow16(hwnd) )
1586 WINDOWPLACEMENT16 wndpl;
1587 UINT flags;
1589 wndpl.length = sizeof(wndpl);
1590 wndpl.showCmd = showCmd;
1591 wndpl.flags = flags = 0;
1593 if( pt )
1595 flags |= PLACE_MIN;
1596 wndpl.flags |= WPF_SETMINPOSITION;
1597 wndpl.ptMinPosition = *pt;
1599 if( rect )
1601 flags |= PLACE_RECT;
1602 wndpl.rcNormalPosition = *rect;
1604 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1609 /***********************************************************************
1610 * SetInternalWindowPos (USER32.483)
1612 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1613 LPRECT rect, LPPOINT pt )
1615 if( IsWindow(hwnd) )
1617 WINDOWPLACEMENT16 wndpl;
1618 UINT flags;
1620 wndpl.length = sizeof(wndpl);
1621 wndpl.showCmd = showCmd;
1622 wndpl.flags = flags = 0;
1624 if( pt )
1626 flags |= PLACE_MIN;
1627 wndpl.flags |= WPF_SETMINPOSITION;
1628 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1630 if( rect )
1632 flags |= PLACE_RECT;
1633 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1635 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1639 /*******************************************************************
1640 * WINPOS_SetActiveWindow
1642 * SetActiveWindow() back-end. This is the only function that
1643 * can assign active status to a window. It must be called only
1644 * for the top level windows.
1646 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1648 CBTACTIVATESTRUCT16* cbtStruct;
1649 WND* wndPtr=0, *wndTemp;
1650 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1651 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1652 WORD wIconized = 0;
1653 HWND hwndActive = 0;
1654 BOOL bRet = 0;
1656 TRACE( win, "(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1658 /* Get current active window from the active queue */
1659 if ( hActiveQueue )
1661 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1662 if ( pOldActiveQueue )
1663 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1666 /* paranoid checks */
1667 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1668 goto CLEANUP_END;
1670 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1671 * return 0;
1673 wndPtr = WIN_FindWndPtr(hWnd);
1674 hOldActiveQueue = hActiveQueue;
1676 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1678 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1679 WIN_ReleaseWndPtr(wndTemp);
1681 else
1682 TRACE(win,"no current active window.\n");
1684 /* call CBT hook chain */
1685 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1687 cbtStruct->fMouse = fMouse;
1688 cbtStruct->hWndActive = hwndActive;
1689 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1690 (LPARAM)SEGPTR_GET(cbtStruct) );
1691 SEGPTR_FREE(cbtStruct);
1692 if (bRet) goto CLEANUP_END;
1695 /* set prev active wnd to current active wnd and send notification */
1696 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1698 MESSAGEQUEUE *pTempActiveQueue = 0;
1700 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1702 if (GetSysModalWindow16() != hWnd)
1703 goto CLEANUP_END;
1704 /* disregard refusal if hWnd is sysmodal */
1707 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1708 MAKEWPARAM( WA_INACTIVE, wIconized ),
1709 (LPARAM)hWnd );
1711 /* check if something happened during message processing
1712 * (global active queue may have changed)
1714 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1715 if(!pTempActiveQueue)
1716 goto CLEANUP_END;
1718 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1719 QUEUE_Unlock( pTempActiveQueue );
1720 if( hwndPrevActive != hwndActive )
1721 goto CLEANUP_END;
1724 /* Set new active window in the message queue */
1725 hwndActive = hWnd;
1726 if ( wndPtr )
1728 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1729 if ( pNewActiveQueue )
1730 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1732 else /* have to do this or MDI frame activation goes to hell */
1733 if( pOldActiveQueue )
1734 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1736 /* send palette messages */
1737 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1738 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1740 /* if prev wnd is minimized redraw icon title */
1741 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1743 /* managed windows will get ConfigureNotify event */
1744 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1746 /* check Z-order and bring hWnd to the top */
1747 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1749 if (wndTemp->dwStyle & WS_VISIBLE) break;
1751 WIN_ReleaseDesktop();
1752 WIN_ReleaseWndPtr(wndTemp);
1754 if( wndTemp != wndPtr )
1755 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1756 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1757 if (!IsWindow(hWnd))
1758 goto CLEANUP;
1761 /* Get a handle to the new active queue */
1762 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1764 /* send WM_ACTIVATEAPP if necessary */
1765 if (hOldActiveQueue != hNewActiveQueue)
1767 WND **list, **ppWnd;
1768 WND *pDesktop = WIN_GetDesktop();
1770 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1772 for (ppWnd = list; *ppWnd; ppWnd++)
1774 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1776 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1777 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1778 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1780 WIN_ReleaseWinArray(list);
1783 hActiveQueue = hNewActiveQueue;
1785 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1787 for (ppWnd = list; *ppWnd; ppWnd++)
1789 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1791 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1792 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1793 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1795 WIN_ReleaseWinArray(list);
1797 WIN_ReleaseDesktop();
1799 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1802 if (hWnd)
1804 /* walk up to the first unowned window */
1805 wndTemp = WIN_LockWndPtr(wndPtr);
1806 while (wndTemp->owner)
1808 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1810 /* and set last active owned popup */
1811 wndTemp->hwndLastActive = hWnd;
1813 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1814 WIN_ReleaseWndPtr(wndTemp);
1815 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1816 SendMessageA( hWnd, WM_ACTIVATE,
1817 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1818 (LPARAM)hwndPrevActive );
1819 if( !IsWindow(hWnd) ) goto CLEANUP;
1822 /* change focus if possible */
1823 if ( fChangeFocus )
1825 if ( pNewActiveQueue )
1827 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1829 if ( WIN_GetTopParent( hOldFocus ) != hwndActive )
1830 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1831 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1832 0 : hwndActive );
1835 if ( pOldActiveQueue &&
1836 ( !pNewActiveQueue ||
1837 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1839 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1840 if ( hOldFocus )
1841 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1845 if( !hwndPrevActive && wndPtr )
1846 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1848 /* if active wnd is minimized redraw icon title */
1849 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1851 bRet = (hWnd == hwndActive); /* Success? */
1853 CLEANUP: /* Unlock the message queues before returning */
1855 if ( pNewActiveQueue )
1856 QUEUE_Unlock( pNewActiveQueue );
1858 CLEANUP_END:
1860 if ( pOldActiveQueue )
1861 QUEUE_Unlock( pOldActiveQueue );
1863 WIN_ReleaseWndPtr(wndPtr);
1864 return bRet;
1867 /*******************************************************************
1868 * WINPOS_ActivateOtherWindow
1870 * Activates window other than pWnd.
1872 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1874 BOOL bRet = 0;
1875 WND* pWndTo = NULL;
1876 HWND hwndActive = 0;
1878 /* Get current active window from the active queue */
1879 if ( hActiveQueue )
1881 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1882 if ( pActiveQueue )
1884 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1885 QUEUE_Unlock( pActiveQueue );
1889 if( pWnd->hwndSelf == hwndPrevActive )
1890 hwndPrevActive = 0;
1892 if( hwndActive != pWnd->hwndSelf &&
1893 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1894 return 0;
1896 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1897 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1899 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1901 WIN_ReleaseWndPtr(pWndTo);
1902 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1904 while( !WINPOS_CanActivate(pWndTo) )
1906 /* by now owned windows should've been taken care of */
1907 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1908 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1909 if( !pWndTo ) break;
1911 WIN_ReleaseWndPtr(pWndPtr);
1914 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1916 /* switch desktop queue to current active */
1917 if( pWndTo )
1919 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1920 WIN_ReleaseWndPtr(pWndTo);
1921 WIN_ReleaseDesktop();
1924 hwndPrevActive = 0;
1925 return bRet;
1928 /*******************************************************************
1929 * WINPOS_ChangeActiveWindow
1932 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1934 WND *wndPtr, *wndTemp;
1935 BOOL retvalue;
1936 HWND hwndActive = 0;
1938 /* Get current active window from the active queue */
1939 if ( hActiveQueue )
1941 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1942 if ( pActiveQueue )
1944 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1945 QUEUE_Unlock( pActiveQueue );
1949 if (!hWnd)
1950 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1952 wndPtr = WIN_FindWndPtr(hWnd);
1953 if( !wndPtr ) return FALSE;
1955 /* child windows get WM_CHILDACTIVATE message */
1956 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1958 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1959 goto end;
1962 if( hWnd == hwndActive )
1964 retvalue = FALSE;
1965 goto end;
1968 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1970 retvalue = FALSE;
1971 goto end;
1974 /* switch desktop queue to current active */
1975 wndTemp = WIN_GetDesktop();
1976 if( wndPtr->parent == wndTemp)
1977 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1978 WIN_ReleaseDesktop();
1980 retvalue = TRUE;
1981 end:
1982 WIN_ReleaseWndPtr(wndPtr);
1983 return retvalue;
1987 /***********************************************************************
1988 * WINPOS_SendNCCalcSize
1990 * Send a WM_NCCALCSIZE message to a window.
1991 * All parameters are read-only except newClientRect.
1992 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1993 * when calcValidRect is TRUE.
1995 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
1996 RECT *newWindowRect, RECT *oldWindowRect,
1997 RECT *oldClientRect, WINDOWPOS *winpos,
1998 RECT *newClientRect )
2000 NCCALCSIZE_PARAMS params;
2001 WINDOWPOS winposCopy;
2002 LONG result;
2004 params.rgrc[0] = *newWindowRect;
2005 if (calcValidRect)
2007 winposCopy = *winpos;
2008 params.rgrc[1] = *oldWindowRect;
2009 params.rgrc[2] = *oldClientRect;
2010 params.lppos = &winposCopy;
2012 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2013 (LPARAM)&params );
2014 TRACE(win, "%d,%d-%d,%d\n",
2015 params.rgrc[0].left, params.rgrc[0].top,
2016 params.rgrc[0].right, params.rgrc[0].bottom );
2017 *newClientRect = params.rgrc[0];
2018 return result;
2022 /***********************************************************************
2023 * WINPOS_HandleWindowPosChanging16
2025 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2027 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2029 POINT maxSize, minTrack;
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, &minTrack, NULL );
2035 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2036 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2037 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2039 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2040 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2043 return 0;
2047 /***********************************************************************
2048 * WINPOS_HandleWindowPosChanging
2050 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2052 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2054 POINT maxSize;
2055 if (winpos->flags & SWP_NOSIZE) return 0;
2056 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2057 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2059 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2060 winpos->cx = MIN( winpos->cx, maxSize.x );
2061 winpos->cy = MIN( winpos->cy, maxSize.y );
2063 return 0;
2066 /***********************************************************************
2067 * SWP_DoOwnedPopups
2069 * fix Z order taking into account owned popups -
2070 * basically we need to maintain them above the window that owns them
2072 * FIXME: hide/show owned popups when owner visibility changes.
2074 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2076 WND* w = WIN_LockWndPtr(pDesktop->child);
2078 WARN(win, "(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2080 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2082 /* make sure this popup stays above the owner */
2084 HWND hwndLocalPrev = HWND_TOP;
2086 if( hwndInsertAfter != HWND_TOP )
2088 while( w != wndPtr->owner )
2090 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2091 if( hwndLocalPrev == hwndInsertAfter ) break;
2092 WIN_UpdateWndPtr(&w,w->next);
2094 hwndInsertAfter = hwndLocalPrev;
2097 else if( wndPtr->dwStyle & WS_CHILD )
2098 goto END;
2100 WIN_UpdateWndPtr(&w, pDesktop->child);
2102 while( w )
2104 if( w == wndPtr ) break;
2106 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2108 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2109 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2110 hwndInsertAfter = w->hwndSelf;
2112 WIN_UpdateWndPtr(&w, w->next);
2115 END:
2116 WIN_ReleaseWndPtr(w);
2117 return hwndInsertAfter;
2120 /***********************************************************************
2121 * SWP_CopyValidBits
2123 * Make window look nice without excessive repainting
2125 * visible and update regions are in window coordinates
2126 * client and window rectangles are in parent client coordinates
2128 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2129 * window rects have the same origin.
2131 * Returns: uFlags and a dirty region in *pVisRgn.
2133 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2134 LPRECT lpOldWndRect,
2135 LPRECT lpOldClientRect, UINT uFlags )
2137 RECT r;
2138 HRGN newVisRgn, dirtyRgn;
2139 INT my = COMPLEXREGION;
2141 TRACE(win,"\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2142 Wnd->rectWindow.left, Wnd->rectWindow.top,
2143 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2144 lpOldWndRect->left, lpOldWndRect->top,
2145 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2146 TRACE(win,"\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2147 Wnd->rectClient.left, Wnd->rectClient.top,
2148 Wnd->rectClient.right, Wnd->rectClient.bottom,
2149 lpOldClientRect->left, lpOldClientRect->top,
2150 lpOldClientRect->right,lpOldClientRect->bottom );
2152 if( Wnd->hrgnUpdate == 1 )
2153 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2155 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2156 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2158 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2159 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2161 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2163 nocopy:
2165 TRACE(win,"\twon't copy anything!\n");
2167 /* set dirtyRgn to the sum of old and new visible regions
2168 * in parent client coordinates */
2170 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2171 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2173 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2175 else /* copy valid bits to a new location */
2177 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2178 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2180 /* subtract already invalid region inside Wnd from the dst region */
2182 if( Wnd->hrgnUpdate )
2183 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2184 goto nocopy;
2186 /* check if entire window can be copied */
2188 ow = lpOldWndRect->right - lpOldWndRect->left;
2189 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2190 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2191 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2193 ocw = lpOldClientRect->right - lpOldClientRect->left;
2194 och = lpOldClientRect->bottom - lpOldClientRect->top;
2195 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2196 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2198 if( (ocw != ncw) || (och != nch) ||
2199 ( ow != nw) || ( oh != nh) ||
2200 ((lpOldClientRect->top - lpOldWndRect->top) !=
2201 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2202 ((lpOldClientRect->left - lpOldWndRect->left) !=
2203 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2205 dx = Wnd->rectClient.left - lpOldClientRect->left;
2206 dy = Wnd->rectClient.top - lpOldClientRect->top;
2208 /* restrict valid bits to the common client rect */
2210 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2211 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2212 r.right = r.left + MIN( ocw, ncw );
2213 r.bottom = r.top + MIN( och, nch );
2215 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2216 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2217 GetRgnBox( hrgnValid, &r );
2218 if( IsRectEmpty( &r ) )
2219 goto nocopy;
2220 r = *lpOldClientRect;
2222 else
2224 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2225 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2226 if( !(uFlags & SWP_EX_PAINTSELF) )
2227 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2228 r = *lpOldWndRect;
2231 if( !(uFlags & SWP_EX_PAINTSELF) )
2233 /* Move remaining regions to parent coordinates */
2234 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2235 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2237 else
2238 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2240 TRACE(win,"\tcomputing dirty region!\n");
2242 /* Compute combined dirty region (old + new - valid) */
2243 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2244 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2246 /* Blt valid bits, r is the rect to copy */
2248 if( dx || dy )
2250 RECT rClip;
2251 HDC hDC;
2252 DC* dc;
2254 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2255 from copying clipped areas */
2257 if( uFlags & SWP_EX_PAINTSELF )
2259 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2260 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2261 rClip.right = nw; rClip.bottom = nh;
2263 else
2265 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2266 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2267 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2268 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2270 rClip.left = rClip.top = 0;
2272 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2274 if( oh > nh ) r.bottom = r.top + nh;
2275 if( ow < nw ) r.right = r.left + nw;
2277 if( IntersectRect( &r, &r, &rClip ) )
2278 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2280 GDI_HEAP_UNLOCK( hDC );
2282 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2283 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2287 /* *pVisRgn now points to the invalidated region */
2289 DeleteObject(newVisRgn);
2290 DeleteObject(dirtyRgn);
2291 return uFlags;
2294 /***********************************************************************
2295 * SWP_DoSimpleFrameChanged
2297 * NOTE: old and new client rect origins are identical, only
2298 * extents may have changed. Window extents are the same.
2300 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2302 INT i = 0;
2303 RECT rect;
2304 HRGN hrgn = 0;
2306 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2308 /* Client rect changed its position/size, most likely a scrollar
2309 * was added/removed.
2311 * FIXME: WVR alignment flags
2314 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2316 i++;
2317 rect.top = 0;
2318 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2319 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2320 if(!(uFlags & SWP_EX_NOCOPY))
2321 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2322 else
2324 rect.left = 0;
2325 goto redraw;
2329 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2331 if( i )
2332 hrgn = CreateRectRgnIndirect( &rect );
2333 rect.left = 0;
2334 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2335 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2336 if(!(uFlags & SWP_EX_NOCOPY))
2337 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2338 else
2339 rect.top = 0;
2340 if( i++ )
2341 REGION_UnionRectWithRgn( hrgn, &rect );
2344 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2346 rect = wndPtr->rectWindow;
2347 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2348 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2349 i++;
2353 if( i )
2355 redraw:
2356 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2357 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2359 else
2361 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2364 if( hrgn > 1 )
2365 DeleteObject( hrgn );
2368 /***********************************************************************
2369 * SWP_DoWinPosChanging
2371 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2372 RECT* pNewWindowRect, RECT* pNewClientRect )
2374 /* Send WM_WINDOWPOSCHANGING message */
2376 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2377 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2379 /* Calculate new position and size */
2381 *pNewWindowRect = wndPtr->rectWindow;
2382 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2383 : wndPtr->rectClient;
2385 if (!(pWinpos->flags & SWP_NOSIZE))
2387 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2388 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2390 if (!(pWinpos->flags & SWP_NOMOVE))
2392 pNewWindowRect->left = pWinpos->x;
2393 pNewWindowRect->top = pWinpos->y;
2394 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2395 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2397 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2398 pWinpos->y - wndPtr->rectWindow.top );
2401 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2402 return TRUE;
2405 /***********************************************************************
2406 * SWP_DoNCCalcSize
2408 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2409 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2411 UINT wvrFlags = 0;
2413 /* Send WM_NCCALCSIZE message to get new client area */
2414 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2416 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2417 &wndPtr->rectWindow, &wndPtr->rectClient,
2418 pWinpos, pNewClientRect );
2420 /* FIXME: WVR_ALIGNxxx */
2422 if( pNewClientRect->left != wndPtr->rectClient.left ||
2423 pNewClientRect->top != wndPtr->rectClient.top )
2424 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2426 if( (pNewClientRect->right - pNewClientRect->left !=
2427 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2428 (pNewClientRect->bottom - pNewClientRect->top !=
2429 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2430 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2432 else
2433 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2434 pNewClientRect->top != wndPtr->rectClient.top) )
2435 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2436 return wvrFlags;
2439 /***********************************************************************
2440 * SetWindowPos (USER.2)
2442 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2443 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2445 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2448 /***********************************************************************
2449 * SetWindowPos (USER32.520)
2451 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2452 INT x, INT y, INT cx, INT cy, WORD flags)
2454 WINDOWPOS winpos;
2455 WND * wndPtr,*wndTemp;
2456 RECT newWindowRect, newClientRect;
2457 RECT oldWindowRect, oldClientRect;
2458 HRGN visRgn = 0;
2459 UINT wvrFlags = 0, uFlags = 0;
2460 BOOL retvalue, resync = FALSE;
2461 HWND hwndActive = 0;
2463 /* Get current active window from the active queue */
2464 if ( hActiveQueue )
2466 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2467 if ( pActiveQueue )
2469 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2470 QUEUE_Unlock( pActiveQueue );
2474 TRACE(win,"hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2475 hwnd, x, y, x+cx, y+cy, flags);
2477 /* ------------------------------------------------------------------------ CHECKS */
2479 /* Check window handle */
2481 if (hwnd == GetDesktopWindow()) return FALSE;
2482 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2484 TRACE(win,"\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2485 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2487 /* Fix redundant flags */
2489 if(wndPtr->dwStyle & WS_VISIBLE)
2490 flags &= ~SWP_SHOWWINDOW;
2491 else
2493 if (!(flags & SWP_SHOWWINDOW))
2494 flags |= SWP_NOREDRAW;
2495 flags &= ~SWP_HIDEWINDOW;
2498 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2500 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2501 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2502 flags |= SWP_NOSIZE; /* Already the right size */
2504 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2505 flags |= SWP_NOMOVE; /* Already the right position */
2507 if (hwnd == hwndActive)
2508 flags |= SWP_NOACTIVATE; /* Already active */
2509 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2511 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2513 flags &= ~SWP_NOZORDER;
2514 hwndInsertAfter = HWND_TOP;
2515 goto Pos;
2519 /* Check hwndInsertAfter */
2521 /* FIXME: TOPMOST not supported yet */
2522 if ((hwndInsertAfter == HWND_TOPMOST) ||
2523 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2525 /* hwndInsertAfter must be a sibling of the window */
2526 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2528 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2530 if( wnd ) {
2531 if( wnd->parent != wndPtr->parent )
2533 retvalue = FALSE;
2534 WIN_ReleaseWndPtr(wnd);
2535 goto END;
2537 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2539 WIN_ReleaseWndPtr(wnd);
2542 Pos: /* ------------------------------------------------------------------------ MAIN part */
2544 /* Fill the WINDOWPOS structure */
2546 winpos.hwnd = hwnd;
2547 winpos.hwndInsertAfter = hwndInsertAfter;
2548 winpos.x = x;
2549 winpos.y = y;
2550 winpos.cx = cx;
2551 winpos.cy = cy;
2552 winpos.flags = flags;
2554 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2556 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2558 if( wndPtr->parent == WIN_GetDesktop() )
2559 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2560 hwndInsertAfter, winpos.flags );
2561 WIN_ReleaseDesktop();
2564 if(!(wndPtr->flags & WIN_NATIVE) )
2566 if( hwndInsertAfter == HWND_TOP )
2567 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2568 else
2569 if( hwndInsertAfter == HWND_BOTTOM )
2570 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2571 else
2572 if( !(winpos.flags & SWP_NOZORDER) )
2573 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2574 winpos.flags |= SWP_NOZORDER;
2576 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2577 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2578 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2580 /* get a previous visible region for SWP_CopyValidBits() */
2582 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2586 /* Common operations */
2588 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2590 if(!(winpos.flags & SWP_NOZORDER))
2592 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2593 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2596 /* Reset active DCEs */
2598 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2599 wndPtr->dwStyle & WS_VISIBLE) ||
2600 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2602 RECT rect;
2604 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2605 DCE_InvalidateDCE(wndPtr, &rect);
2608 oldWindowRect = wndPtr->rectWindow;
2609 oldClientRect = wndPtr->rectClient;
2611 /* Find out if we have to redraw the whole client rect */
2613 if( oldClientRect.bottom - oldClientRect.top ==
2614 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2616 if( oldClientRect.right - oldClientRect.left ==
2617 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2619 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2620 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2622 uFlags |= SWP_EX_NOCOPY;
2625 * Use this later in CopyValidBits()
2627 else if( 0 )
2628 uFlags |= SWP_EX_NONCLIENT;
2631 /* FIXME: actually do something with WVR_VALIDRECTS */
2633 wndPtr->rectWindow = newWindowRect;
2634 wndPtr->rectClient = newClientRect;
2636 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2638 BOOL bCallDriver = TRUE;
2639 HWND tempInsertAfter = winpos.hwndInsertAfter;
2641 winpos.hwndInsertAfter = hwndInsertAfter;
2643 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2645 /* This is the only place where we need to force repainting of the contents
2646 of windows created by the host window system, all other cases go through the
2647 expose event handling */
2649 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2651 cx = newWindowRect.right - newWindowRect.left;
2652 cy = newWindowRect.bottom - newWindowRect.top;
2654 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2655 winpos.hwndInsertAfter = tempInsertAfter;
2656 bCallDriver = FALSE;
2658 if( winpos.flags & SWP_NOCLIENTMOVE )
2659 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2660 else
2662 /* client area moved but window extents remained the same, copy valid bits */
2664 visRgn = CreateRectRgn( 0, 0, cx, cy );
2665 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2666 uFlags | SWP_EX_PAINTSELF );
2671 if( bCallDriver )
2673 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2675 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2676 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2677 !(uFlags & SWP_EX_NOCOPY) )
2679 /* The origin of the client rect didn't move so we can try to repaint
2680 * only the nonclient area by setting bit gravity hint for the host window system.
2683 if( !(wndPtr->flags & WIN_MANAGED) )
2685 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2686 newWindowRect.bottom - newWindowRect.top);
2687 RECT rcn = newClientRect;
2688 RECT rco = oldClientRect;
2690 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2691 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2692 IntersectRect( &rcn, &rcn, &rco );
2693 visRgn = CreateRectRgnIndirect( &rcn );
2694 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2695 DeleteObject( hrgn );
2696 uFlags = SWP_EX_PAINTSELF;
2698 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2700 else
2701 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2704 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, TRUE);
2705 winpos.hwndInsertAfter = tempInsertAfter;
2708 if( winpos.flags & SWP_SHOWWINDOW )
2710 HWND focus, curr;
2712 wndPtr->dwStyle |= WS_VISIBLE;
2714 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2716 /* focus was set to unmapped window, reset host focus
2717 * since the window is now visible */
2719 focus = curr = GetFocus();
2720 while (curr)
2722 if (curr == hwnd)
2724 WND *pFocus = WIN_FindWndPtr( focus );
2725 if (pFocus)
2726 pFocus->pDriver->pSetFocus(pFocus);
2727 WIN_ReleaseWndPtr(pFocus);
2728 break;
2730 curr = GetParent(curr);
2734 else /* -------------------------------------------- emulated window */
2736 if( winpos.flags & SWP_SHOWWINDOW )
2738 wndPtr->dwStyle |= WS_VISIBLE;
2739 uFlags |= SWP_EX_PAINTSELF;
2740 visRgn = 1; /* redraw the whole window */
2742 else if( !(winpos.flags & SWP_NOREDRAW) )
2744 if( winpos.flags & SWP_HIDEWINDOW )
2746 if( visRgn > 1 ) /* map to parent */
2747 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2748 else
2749 visRgn = 0;
2751 else
2753 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2754 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2755 &oldClientRect, uFlags);
2756 else
2758 /* nothing moved, redraw frame if needed */
2760 if( winpos.flags & SWP_FRAMECHANGED )
2761 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2762 if( visRgn )
2764 DeleteObject( visRgn );
2765 visRgn = 0;
2772 if( winpos.flags & SWP_HIDEWINDOW )
2774 wndPtr->dwStyle &= ~WS_VISIBLE;
2776 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2778 /* FIXME: This will cause the window to be activated irrespective
2779 * of whether it is owned by the same thread. Has to be done
2780 * asynchronously.
2783 if (winpos.hwnd == hwndActive)
2784 WINPOS_ActivateOtherWindow( wndPtr );
2787 /* ------------------------------------------------------------------------ FINAL */
2789 if (wndPtr->flags & WIN_NATIVE)
2790 EVENT_Synchronize( TRUE ); /* Synchronize with the host window system */
2792 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2794 /* Simulate a mouse event to set the cursor */
2795 DWORD posX, posY, keyState;
2797 if ( EVENT_QueryPointer( &posX, &posY, &keyState ) )
2799 int iWndsLocks = WIN_SuspendWndsLock();
2801 hardware_event( WM_MOUSEMOVE, keyState, 0,
2802 posX, posY, GetTickCount(), 0 );
2804 WIN_RestoreWndsLock(iWndsLocks);
2808 wndTemp = WIN_GetDesktop();
2810 /* repaint invalidated region (if any)
2812 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2813 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2816 if( visRgn )
2818 if( !(winpos.flags & SWP_NOREDRAW) )
2820 if( uFlags & SWP_EX_PAINTSELF )
2822 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE | RDW_FRAME |
2823 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2824 RDW_ALLCHILDREN, RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2826 else
2828 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE |
2829 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2830 RDW_ALLCHILDREN, RDW_EX_USEHRGN );
2833 if( visRgn != 1 )
2834 DeleteObject( visRgn );
2837 WIN_ReleaseDesktop();
2839 if (!(flags & SWP_NOACTIVATE))
2840 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2842 /* And last, send the WM_WINDOWPOSCHANGED message */
2844 TRACE(win,"\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2846 if ( resync ||
2847 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2848 !(winpos.flags & SWP_NOSENDCHANGING)) )
2850 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2851 if (resync) EVENT_Synchronize ( TRUE );
2854 retvalue = TRUE;
2855 END:
2856 WIN_ReleaseWndPtr(wndPtr);
2857 return retvalue;
2861 /***********************************************************************
2862 * BeginDeferWindowPos16 (USER.259)
2864 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2866 return BeginDeferWindowPos( count );
2870 /***********************************************************************
2871 * BeginDeferWindowPos (USER32.9)
2873 HDWP WINAPI BeginDeferWindowPos( INT count )
2875 HDWP handle;
2876 DWP *pDWP;
2878 if (count <= 0) return 0;
2879 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2880 if (!handle) return 0;
2881 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2882 pDWP->actualCount = 0;
2883 pDWP->suggestedCount = count;
2884 pDWP->valid = TRUE;
2885 pDWP->wMagic = DWP_MAGIC;
2886 pDWP->hwndParent = 0;
2887 return handle;
2891 /***********************************************************************
2892 * DeferWindowPos16 (USER.260)
2894 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2895 INT16 x, INT16 y, INT16 cx, INT16 cy,
2896 UINT16 flags )
2898 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2899 x, y, cx, cy, flags );
2903 /***********************************************************************
2904 * DeferWindowPos (USER32.128)
2906 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2907 INT x, INT y, INT cx, INT cy,
2908 UINT flags )
2910 DWP *pDWP;
2911 int i;
2912 HDWP newhdwp = hdwp,retvalue;
2913 /* HWND parent; */
2914 WND *pWnd;
2916 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2917 if (!pDWP) return 0;
2918 if (hwnd == GetDesktopWindow()) return 0;
2920 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2921 USER_HEAP_FREE( hdwp );
2922 return 0;
2925 /* Numega Bounds Checker Demo dislikes the following code.
2926 In fact, I've not been able to find any "same parent" requirement in any docu
2927 [AM 980509]
2929 #if 0
2930 /* All the windows of a DeferWindowPos() must have the same parent */
2931 parent = pWnd->parent->hwndSelf;
2932 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2933 else if (parent != pDWP->hwndParent)
2935 USER_HEAP_FREE( hdwp );
2936 retvalue = 0;
2937 goto END;
2939 #endif
2941 for (i = 0; i < pDWP->actualCount; i++)
2943 if (pDWP->winPos[i].hwnd == hwnd)
2945 /* Merge with the other changes */
2946 if (!(flags & SWP_NOZORDER))
2948 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2950 if (!(flags & SWP_NOMOVE))
2952 pDWP->winPos[i].x = x;
2953 pDWP->winPos[i].y = y;
2955 if (!(flags & SWP_NOSIZE))
2957 pDWP->winPos[i].cx = cx;
2958 pDWP->winPos[i].cy = cy;
2960 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2961 SWP_NOZORDER | SWP_NOREDRAW |
2962 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2963 SWP_NOOWNERZORDER);
2964 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2965 SWP_FRAMECHANGED);
2966 retvalue = hdwp;
2967 goto END;
2970 if (pDWP->actualCount >= pDWP->suggestedCount)
2972 newhdwp = USER_HEAP_REALLOC( hdwp,
2973 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
2974 if (!newhdwp)
2976 retvalue = 0;
2977 goto END;
2979 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
2980 pDWP->suggestedCount++;
2982 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
2983 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
2984 pDWP->winPos[pDWP->actualCount].x = x;
2985 pDWP->winPos[pDWP->actualCount].y = y;
2986 pDWP->winPos[pDWP->actualCount].cx = cx;
2987 pDWP->winPos[pDWP->actualCount].cy = cy;
2988 pDWP->winPos[pDWP->actualCount].flags = flags;
2989 pDWP->actualCount++;
2990 retvalue = newhdwp;
2991 END:
2992 WIN_ReleaseWndPtr(pWnd);
2993 return retvalue;
2997 /***********************************************************************
2998 * EndDeferWindowPos16 (USER.261)
3000 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3002 return EndDeferWindowPos( hdwp );
3006 /***********************************************************************
3007 * EndDeferWindowPos (USER32.173)
3009 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3011 DWP *pDWP;
3012 WINDOWPOS *winpos;
3013 BOOL res = TRUE;
3014 int i;
3016 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3017 if (!pDWP) return FALSE;
3018 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3020 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3021 winpos->x, winpos->y, winpos->cx,
3022 winpos->cy, winpos->flags ))) break;
3024 USER_HEAP_FREE( hdwp );
3025 return res;
3029 /***********************************************************************
3030 * TileChildWindows (USER.199)
3032 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3034 FIXME(win, "(%04x, %d): stub\n", parent, action);
3037 /***********************************************************************
3038 * CascageChildWindows (USER.198)
3040 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3042 FIXME(win, "(%04x, %d): stub\n", parent, action);
3045 /***********************************************************************
3046 * SetProgmanWindow [USER32.522]
3048 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3050 hGlobalProgmanWindow = hwnd;
3051 return hGlobalProgmanWindow;
3054 /***********************************************************************
3055 * GetProgmanWindow [USER32.289]
3057 HRESULT WINAPI GetProgmanWindow ( )
3059 return hGlobalProgmanWindow;
3062 /***********************************************************************
3063 * SetShellWindowEx [USER32.531]
3064 * hwndProgman = Progman[Program Manager]
3065 * |-> SHELLDLL_DefView
3066 * hwndListView = | |-> SysListView32
3067 * | | |-> tooltips_class32
3068 * | |
3069 * | |-> SysHeader32
3070 * |
3071 * |-> ProxyTarget
3073 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3075 FIXME(win,"0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3076 hGlobalShellWindow = hwndProgman;
3077 return hGlobalShellWindow;
3081 /***********************************************************************
3082 * SetTaskmanWindow [USER32.537]
3083 * NOTES
3084 * hwnd = MSTaskSwWClass
3085 * |-> SysTabControl32
3087 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3089 hGlobalTaskmanWindow = hwnd;
3090 return hGlobalTaskmanWindow;
3093 /***********************************************************************
3094 * GetTaskmanWindow [USER32.304]
3096 HRESULT WINAPI GetTaskmanWindow ( )
3098 return hGlobalTaskmanWindow;