Reset disabled style for the dialog boxes set on property pages.
[wine.git] / windows / winpos.c
blobfc517145ff83813dc592c71535f991a80017ef80
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 "debugtools.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("\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("\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("GetWindowRgn: doesn't really do regions\n");
279 memset (&rect, 0, sizeof(rect));
281 GetWindowRect ( hwnd, &rect );
283 FIXME("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("SetWindowRgn: stub\n");
299 return TRUE;
302 /***********************************************************************
303 * SetWindowRgn16
305 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
309 FIXME("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("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("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("\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("\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("\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("(hWnd=%08x) semi stub\n",hwndshell );
940 hGlobalShellWindow = hwndshell;
941 return hGlobalShellWindow;
945 /*******************************************************************
946 * GetShellWindow (USER32.287)
948 HWND WINAPI GetShellWindow(void)
949 { WARN("(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("%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("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("%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("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("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("(%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("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("%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("(%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("\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("\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("\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("\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 ) )
2279 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2281 /* When you copy the bits without repainting, parent doesn't
2282 get validated appropriately. Therefore, we have to validate
2283 the parent with the windows' updated region when the
2284 parent's update region is not empty. */
2286 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2288 OffsetRect(&r, dx, dy);
2289 ValidateRect(Wnd->parent->hwndSelf, &r);
2293 GDI_HEAP_UNLOCK( hDC );
2295 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2296 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2300 /* *pVisRgn now points to the invalidated region */
2302 DeleteObject(newVisRgn);
2303 DeleteObject(dirtyRgn);
2304 return uFlags;
2307 /***********************************************************************
2308 * SWP_DoSimpleFrameChanged
2310 * NOTE: old and new client rect origins are identical, only
2311 * extents may have changed. Window extents are the same.
2313 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2315 INT i = 0;
2316 RECT rect;
2317 HRGN hrgn = 0;
2319 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2321 /* Client rect changed its position/size, most likely a scrollar
2322 * was added/removed.
2324 * FIXME: WVR alignment flags
2327 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2329 i++;
2330 rect.top = 0;
2331 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2332 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2333 if(!(uFlags & SWP_EX_NOCOPY))
2334 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2335 else
2337 rect.left = 0;
2338 goto redraw;
2342 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2344 if( i )
2345 hrgn = CreateRectRgnIndirect( &rect );
2346 rect.left = 0;
2347 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2348 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2349 if(!(uFlags & SWP_EX_NOCOPY))
2350 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2351 else
2352 rect.top = 0;
2353 if( i++ )
2354 REGION_UnionRectWithRgn( hrgn, &rect );
2357 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2359 rect = wndPtr->rectWindow;
2360 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2361 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2362 i++;
2366 if( i )
2368 redraw:
2369 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2370 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2372 else
2374 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2377 if( hrgn > 1 )
2378 DeleteObject( hrgn );
2381 /***********************************************************************
2382 * SWP_DoWinPosChanging
2384 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2385 RECT* pNewWindowRect, RECT* pNewClientRect )
2387 /* Send WM_WINDOWPOSCHANGING message */
2389 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2390 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2392 /* Calculate new position and size */
2394 *pNewWindowRect = wndPtr->rectWindow;
2395 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2396 : wndPtr->rectClient;
2398 if (!(pWinpos->flags & SWP_NOSIZE))
2400 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2401 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2403 if (!(pWinpos->flags & SWP_NOMOVE))
2405 pNewWindowRect->left = pWinpos->x;
2406 pNewWindowRect->top = pWinpos->y;
2407 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2408 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2410 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2411 pWinpos->y - wndPtr->rectWindow.top );
2414 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2415 return TRUE;
2418 /***********************************************************************
2419 * SWP_DoNCCalcSize
2421 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2422 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2424 UINT wvrFlags = 0;
2426 /* Send WM_NCCALCSIZE message to get new client area */
2427 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2429 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2430 &wndPtr->rectWindow, &wndPtr->rectClient,
2431 pWinpos, pNewClientRect );
2433 /* FIXME: WVR_ALIGNxxx */
2435 if( pNewClientRect->left != wndPtr->rectClient.left ||
2436 pNewClientRect->top != wndPtr->rectClient.top )
2437 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2439 if( (pNewClientRect->right - pNewClientRect->left !=
2440 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2441 (pNewClientRect->bottom - pNewClientRect->top !=
2442 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2443 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2445 else
2446 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2447 pNewClientRect->top != wndPtr->rectClient.top) )
2448 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2449 return wvrFlags;
2452 /***********************************************************************
2453 * SetWindowPos (USER.2)
2455 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2456 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2458 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2461 /***********************************************************************
2462 * SetWindowPos (USER32.520)
2464 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2465 INT x, INT y, INT cx, INT cy, UINT flags )
2467 WINDOWPOS winpos;
2468 WND * wndPtr,*wndTemp;
2469 RECT newWindowRect, newClientRect;
2470 RECT oldWindowRect, oldClientRect;
2471 HRGN visRgn = 0;
2472 UINT wvrFlags = 0, uFlags = 0;
2473 BOOL retvalue, resync = FALSE, bChangePos;
2474 HWND hwndActive = 0;
2476 /* Get current active window from the active queue */
2477 if ( hActiveQueue )
2479 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2480 if ( pActiveQueue )
2482 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2483 QUEUE_Unlock( pActiveQueue );
2487 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2488 hwnd, x, y, x+cx, y+cy, flags);
2490 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2491 flags &= ~SWP_WINE_NOHOSTMOVE;
2494 /* ------------------------------------------------------------------------ CHECKS */
2496 /* Check window handle */
2498 if (hwnd == GetDesktopWindow()) return FALSE;
2499 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2501 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2502 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2504 /* Fix redundant flags */
2506 if(wndPtr->dwStyle & WS_VISIBLE)
2507 flags &= ~SWP_SHOWWINDOW;
2508 else
2510 if (!(flags & SWP_SHOWWINDOW))
2511 flags |= SWP_NOREDRAW;
2512 flags &= ~SWP_HIDEWINDOW;
2515 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2517 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2518 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2519 flags |= SWP_NOSIZE; /* Already the right size */
2521 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2522 flags |= SWP_NOMOVE; /* Already the right position */
2524 if (hwnd == hwndActive)
2525 flags |= SWP_NOACTIVATE; /* Already active */
2526 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2528 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2530 flags &= ~SWP_NOZORDER;
2531 hwndInsertAfter = HWND_TOP;
2532 goto Pos;
2536 /* Check hwndInsertAfter */
2538 /* FIXME: TOPMOST not supported yet */
2539 if ((hwndInsertAfter == HWND_TOPMOST) ||
2540 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2542 /* hwndInsertAfter must be a sibling of the window */
2543 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2545 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2547 if( wnd ) {
2548 if( wnd->parent != wndPtr->parent )
2550 retvalue = FALSE;
2551 WIN_ReleaseWndPtr(wnd);
2552 goto END;
2554 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2556 WIN_ReleaseWndPtr(wnd);
2559 Pos: /* ------------------------------------------------------------------------ MAIN part */
2561 /* Fill the WINDOWPOS structure */
2563 winpos.hwnd = hwnd;
2564 winpos.hwndInsertAfter = hwndInsertAfter;
2565 winpos.x = x;
2566 winpos.y = y;
2567 winpos.cx = cx;
2568 winpos.cy = cy;
2569 winpos.flags = flags;
2571 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2573 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2575 if( wndPtr->parent == WIN_GetDesktop() )
2576 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2577 hwndInsertAfter, winpos.flags );
2578 WIN_ReleaseDesktop();
2581 if(!(wndPtr->flags & WIN_NATIVE) )
2583 if( hwndInsertAfter == HWND_TOP )
2584 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2585 else
2586 if( hwndInsertAfter == HWND_BOTTOM )
2587 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2588 else
2589 if( !(winpos.flags & SWP_NOZORDER) )
2590 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2591 winpos.flags |= SWP_NOZORDER;
2593 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2594 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2595 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2597 /* get a previous visible region for SWP_CopyValidBits() */
2599 visRgn = DCE_GetVisRgn(hwnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2603 /* Common operations */
2605 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2607 if(!(winpos.flags & SWP_NOZORDER))
2609 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2610 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2613 /* Reset active DCEs */
2615 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2616 wndPtr->dwStyle & WS_VISIBLE) ||
2617 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2619 RECT rect;
2621 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2622 DCE_InvalidateDCE(wndPtr, &rect);
2625 oldWindowRect = wndPtr->rectWindow;
2626 oldClientRect = wndPtr->rectClient;
2628 /* Find out if we have to redraw the whole client rect */
2630 if( oldClientRect.bottom - oldClientRect.top ==
2631 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2633 if( oldClientRect.right - oldClientRect.left ==
2634 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2636 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2637 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2639 uFlags |= SWP_EX_NOCOPY;
2642 * Use this later in CopyValidBits()
2644 else if( 0 )
2645 uFlags |= SWP_EX_NONCLIENT;
2648 /* FIXME: actually do something with WVR_VALIDRECTS */
2650 wndPtr->rectWindow = newWindowRect;
2651 wndPtr->rectClient = newClientRect;
2653 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2655 BOOL bCallDriver = TRUE;
2656 HWND tempInsertAfter = winpos.hwndInsertAfter;
2658 winpos.hwndInsertAfter = hwndInsertAfter;
2660 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2662 /* This is the only place where we need to force repainting of the contents
2663 of windows created by the host window system, all other cases go through the
2664 expose event handling */
2666 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2668 cx = newWindowRect.right - newWindowRect.left;
2669 cy = newWindowRect.bottom - newWindowRect.top;
2671 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2672 winpos.hwndInsertAfter = tempInsertAfter;
2673 bCallDriver = FALSE;
2675 if( winpos.flags & SWP_NOCLIENTMOVE )
2676 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2677 else
2679 /* client area moved but window extents remained the same, copy valid bits */
2681 visRgn = CreateRectRgn( 0, 0, cx, cy );
2682 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2683 uFlags | SWP_EX_PAINTSELF );
2688 if( bCallDriver )
2690 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2692 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2693 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2694 !(uFlags & SWP_EX_NOCOPY) )
2696 /* The origin of the client rect didn't move so we can try to repaint
2697 * only the nonclient area by setting bit gravity hint for the host window system.
2700 if( !(wndPtr->flags & WIN_MANAGED) )
2702 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2703 newWindowRect.bottom - newWindowRect.top);
2704 RECT rcn = newClientRect;
2705 RECT rco = oldClientRect;
2707 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2708 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2709 IntersectRect( &rcn, &rcn, &rco );
2710 visRgn = CreateRectRgnIndirect( &rcn );
2711 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2712 DeleteObject( hrgn );
2713 uFlags = SWP_EX_PAINTSELF;
2715 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2717 else
2718 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2721 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2722 winpos.hwndInsertAfter = tempInsertAfter;
2725 if( winpos.flags & SWP_SHOWWINDOW )
2727 HWND focus, curr;
2729 wndPtr->dwStyle |= WS_VISIBLE;
2731 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2733 /* focus was set to unmapped window, reset host focus
2734 * since the window is now visible */
2736 focus = curr = GetFocus();
2737 while (curr)
2739 if (curr == hwnd)
2741 WND *pFocus = WIN_FindWndPtr( focus );
2742 if (pFocus)
2743 pFocus->pDriver->pSetFocus(pFocus);
2744 WIN_ReleaseWndPtr(pFocus);
2745 break;
2747 curr = GetParent(curr);
2751 else /* -------------------------------------------- emulated window */
2753 if( winpos.flags & SWP_SHOWWINDOW )
2755 wndPtr->dwStyle |= WS_VISIBLE;
2756 uFlags |= SWP_EX_PAINTSELF;
2757 visRgn = 1; /* redraw the whole window */
2759 else if( !(winpos.flags & SWP_NOREDRAW) )
2761 if( winpos.flags & SWP_HIDEWINDOW )
2763 if( visRgn > 1 ) /* map to parent */
2764 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2765 else
2766 visRgn = 0;
2768 else
2770 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2771 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2772 &oldClientRect, uFlags);
2773 else
2775 /* nothing moved, redraw frame if needed */
2777 if( winpos.flags & SWP_FRAMECHANGED )
2778 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2779 if( visRgn )
2781 DeleteObject( visRgn );
2782 visRgn = 0;
2789 if( winpos.flags & SWP_HIDEWINDOW )
2791 wndPtr->dwStyle &= ~WS_VISIBLE;
2793 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2795 /* FIXME: This will cause the window to be activated irrespective
2796 * of whether it is owned by the same thread. Has to be done
2797 * asynchronously.
2800 if (winpos.hwnd == hwndActive)
2801 WINPOS_ActivateOtherWindow( wndPtr );
2804 /* ------------------------------------------------------------------------ FINAL */
2806 if (wndPtr->flags & WIN_NATIVE)
2807 EVENT_Synchronize(); /* Synchronize with the host window system */
2809 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2811 /* Simulate a mouse event to set the cursor */
2812 DWORD posX, posY, keyState;
2814 if ( EVENT_QueryPointer( &posX, &posY, &keyState ) )
2816 int iWndsLocks = WIN_SuspendWndsLock();
2818 hardware_event( WM_MOUSEMOVE, keyState, 0,
2819 posX, posY, GetTickCount(), 0 );
2821 WIN_RestoreWndsLock(iWndsLocks);
2825 wndTemp = WIN_GetDesktop();
2827 /* repaint invalidated region (if any)
2829 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2830 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2833 if( visRgn )
2835 if( !(winpos.flags & SWP_NOREDRAW) )
2837 if (wndPtr->parent == wndTemp)
2839 /* Desktop does not receive wm_paint message so we use RDW_ERASENOW to erase the
2840 the desktop window */
2842 if( uFlags & SWP_EX_PAINTSELF )
2844 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE | RDW_FRAME |
2845 ((winpos.flags & SWP_DEFERERASE) ? 0 : RDW_ERASENOW) | RDW_INVALIDATE |
2846 RDW_ALLCHILDREN, RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2848 else
2850 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2851 RDW_ERASE | RDW_ERASENOW | RDW_INVALIDATE | RDW_ALLCHILDREN, RDW_EX_USEHRGN );
2854 else
2856 if( uFlags & SWP_EX_PAINTSELF )
2858 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2859 its parent and sibling and so on, and then update the parent window,
2860 the non-top-level window. Rely on the system to repaint other affected
2861 windows later on. */
2863 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn, RDW_ERASE |
2864 RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN, RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2866 else
2868 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2869 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN, RDW_EX_USEHRGN );
2871 UpdateWindow( wndPtr->parent->hwndSelf);
2875 if( visRgn != 1 )
2876 DeleteObject( visRgn );
2879 WIN_ReleaseDesktop();
2881 if (!(flags & SWP_NOACTIVATE))
2882 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2884 /* And last, send the WM_WINDOWPOSCHANGED message */
2886 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2888 if ( resync ||
2889 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2890 !(winpos.flags & SWP_NOSENDCHANGING)) )
2892 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2893 if (resync) EVENT_Synchronize();
2896 retvalue = TRUE;
2897 END:
2898 WIN_ReleaseWndPtr(wndPtr);
2899 return retvalue;
2903 /***********************************************************************
2904 * BeginDeferWindowPos16 (USER.259)
2906 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2908 return BeginDeferWindowPos( count );
2912 /***********************************************************************
2913 * BeginDeferWindowPos (USER32.9)
2915 HDWP WINAPI BeginDeferWindowPos( INT count )
2917 HDWP handle;
2918 DWP *pDWP;
2920 if (count <= 0) return 0;
2921 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2922 if (!handle) return 0;
2923 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2924 pDWP->actualCount = 0;
2925 pDWP->suggestedCount = count;
2926 pDWP->valid = TRUE;
2927 pDWP->wMagic = DWP_MAGIC;
2928 pDWP->hwndParent = 0;
2929 return handle;
2933 /***********************************************************************
2934 * DeferWindowPos16 (USER.260)
2936 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2937 INT16 x, INT16 y, INT16 cx, INT16 cy,
2938 UINT16 flags )
2940 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2941 x, y, cx, cy, flags );
2945 /***********************************************************************
2946 * DeferWindowPos (USER32.128)
2948 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2949 INT x, INT y, INT cx, INT cy,
2950 UINT flags )
2952 DWP *pDWP;
2953 int i;
2954 HDWP newhdwp = hdwp,retvalue;
2955 /* HWND parent; */
2956 WND *pWnd;
2958 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2959 if (!pDWP) return 0;
2960 if (hwnd == GetDesktopWindow()) return 0;
2962 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2963 USER_HEAP_FREE( hdwp );
2964 return 0;
2967 /* Numega Bounds Checker Demo dislikes the following code.
2968 In fact, I've not been able to find any "same parent" requirement in any docu
2969 [AM 980509]
2971 #if 0
2972 /* All the windows of a DeferWindowPos() must have the same parent */
2973 parent = pWnd->parent->hwndSelf;
2974 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2975 else if (parent != pDWP->hwndParent)
2977 USER_HEAP_FREE( hdwp );
2978 retvalue = 0;
2979 goto END;
2981 #endif
2983 for (i = 0; i < pDWP->actualCount; i++)
2985 if (pDWP->winPos[i].hwnd == hwnd)
2987 /* Merge with the other changes */
2988 if (!(flags & SWP_NOZORDER))
2990 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2992 if (!(flags & SWP_NOMOVE))
2994 pDWP->winPos[i].x = x;
2995 pDWP->winPos[i].y = y;
2997 if (!(flags & SWP_NOSIZE))
2999 pDWP->winPos[i].cx = cx;
3000 pDWP->winPos[i].cy = cy;
3002 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3003 SWP_NOZORDER | SWP_NOREDRAW |
3004 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3005 SWP_NOOWNERZORDER);
3006 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3007 SWP_FRAMECHANGED);
3008 retvalue = hdwp;
3009 goto END;
3012 if (pDWP->actualCount >= pDWP->suggestedCount)
3014 newhdwp = USER_HEAP_REALLOC( hdwp,
3015 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3016 if (!newhdwp)
3018 retvalue = 0;
3019 goto END;
3021 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3022 pDWP->suggestedCount++;
3024 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3025 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3026 pDWP->winPos[pDWP->actualCount].x = x;
3027 pDWP->winPos[pDWP->actualCount].y = y;
3028 pDWP->winPos[pDWP->actualCount].cx = cx;
3029 pDWP->winPos[pDWP->actualCount].cy = cy;
3030 pDWP->winPos[pDWP->actualCount].flags = flags;
3031 pDWP->actualCount++;
3032 retvalue = newhdwp;
3033 END:
3034 WIN_ReleaseWndPtr(pWnd);
3035 return retvalue;
3039 /***********************************************************************
3040 * EndDeferWindowPos16 (USER.261)
3042 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3044 return EndDeferWindowPos( hdwp );
3048 /***********************************************************************
3049 * EndDeferWindowPos (USER32.173)
3051 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3053 DWP *pDWP;
3054 WINDOWPOS *winpos;
3055 BOOL res = TRUE;
3056 int i;
3058 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3059 if (!pDWP) return FALSE;
3060 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3062 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3063 winpos->x, winpos->y, winpos->cx,
3064 winpos->cy, winpos->flags ))) break;
3066 USER_HEAP_FREE( hdwp );
3067 return res;
3071 /***********************************************************************
3072 * TileChildWindows (USER.199)
3074 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3076 FIXME("(%04x, %d): stub\n", parent, action);
3079 /***********************************************************************
3080 * CascageChildWindows (USER.198)
3082 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3084 FIXME("(%04x, %d): stub\n", parent, action);
3087 /***********************************************************************
3088 * SetProgmanWindow [USER32.522]
3090 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3092 hGlobalProgmanWindow = hwnd;
3093 return hGlobalProgmanWindow;
3096 /***********************************************************************
3097 * GetProgmanWindow [USER32.289]
3099 HRESULT WINAPI GetProgmanWindow ( )
3101 return hGlobalProgmanWindow;
3104 /***********************************************************************
3105 * SetShellWindowEx [USER32.531]
3106 * hwndProgman = Progman[Program Manager]
3107 * |-> SHELLDLL_DefView
3108 * hwndListView = | |-> SysListView32
3109 * | | |-> tooltips_class32
3110 * | |
3111 * | |-> SysHeader32
3112 * |
3113 * |-> ProxyTarget
3115 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3117 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3118 hGlobalShellWindow = hwndProgman;
3119 return hGlobalShellWindow;
3123 /***********************************************************************
3124 * SetTaskmanWindow [USER32.537]
3125 * NOTES
3126 * hwnd = MSTaskSwWClass
3127 * |-> SysTabControl32
3129 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3131 hGlobalTaskmanWindow = hwnd;
3132 return hGlobalTaskmanWindow;
3135 /***********************************************************************
3136 * GetTaskmanWindow [USER32.304]
3138 HRESULT WINAPI GetTaskmanWindow ( )
3140 return hGlobalTaskmanWindow;