2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
13 #include "wine/winuser16.h"
25 #include "nonclient.h"
26 #include "debugtools.h"
31 DEFAULT_DEBUG_CHANNEL(win
);
33 #define HAS_DLGFRAME(style,exStyle) \
34 (((exStyle) & WS_EX_DLGMODALFRAME) || \
35 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
37 #define HAS_THICKFRAME(style) \
38 (((style) & WS_THICKFRAME) && \
39 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
41 #define SWP_AGG_NOGEOMETRYCHANGE \
42 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
43 #define SWP_AGG_NOPOSCHANGE \
44 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
45 #define SWP_AGG_STATUSFLAGS \
46 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
48 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
50 #define PLACE_MIN 0x0001
51 #define PLACE_MAX 0x0002
52 #define PLACE_RECT 0x0004
54 #define SWP_EX_NOCOPY 0x0001
55 #define SWP_EX_PAINTSELF 0x0002
56 #define SWP_EX_NONCLIENT 0x0004
58 #define MINMAX_NOSWP 0x00010000
60 /* ----- internal variables ----- */
62 static HWND hwndPrevActive
= 0; /* Previously active window */
63 static HWND hGlobalShellWindow
=0; /*the shell*/
64 static HWND hGlobalTaskmanWindow
=0;
65 static HWND hGlobalProgmanWindow
=0;
67 static LPCSTR atomInternalPos
;
69 extern HQUEUE16 hActiveQueue
;
71 /***********************************************************************
72 * WINPOS_CreateInternalPosAtom
74 BOOL
WINPOS_CreateInternalPosAtom()
77 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
78 return (atomInternalPos
) ? TRUE
: FALSE
;
81 /***********************************************************************
82 * WINPOS_CheckInternalPos
84 * Called when a window is destroyed.
86 void WINPOS_CheckInternalPos( WND
* wndPtr
)
89 MESSAGEQUEUE
*pMsgQ
= 0;
90 HWND hwnd
= wndPtr
->hwndSelf
;
92 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
94 /* Retrieve the message queue associated with this window */
95 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
98 WARN("\tMessage queue not found. Exiting!\n" );
102 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
104 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
106 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
107 WARN("\tattempt to activate destroyed window!\n");
112 if( IsWindow(lpPos
->hwndIconTitle
) )
113 DestroyWindow( lpPos
->hwndIconTitle
);
114 HeapFree( SystemHeap
, 0, lpPos
);
117 QUEUE_Unlock( pMsgQ
);
121 /***********************************************************************
124 * Find a suitable place for an iconic window.
126 static POINT16
WINPOS_FindIconPos( WND
* wndPtr
, POINT16 pt
)
129 short x
, y
, xspacing
, yspacing
;
131 GetClientRect16( wndPtr
->parent
->hwndSelf
, &rectParent
);
132 if ((pt
.x
>= rectParent
.left
) && (pt
.x
+ GetSystemMetrics(SM_CXICON
) < rectParent
.right
) &&
133 (pt
.y
>= rectParent
.top
) && (pt
.y
+ GetSystemMetrics(SM_CYICON
) < rectParent
.bottom
))
134 return pt
; /* The icon already has a suitable position */
136 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
137 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
139 y
= rectParent
.bottom
;
145 /* Check if another icon already occupies this spot */
146 WND
*childPtr
= WIN_LockWndPtr(wndPtr
->parent
->child
);
149 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (childPtr
!= wndPtr
))
151 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
152 (childPtr
->rectWindow
.right
>= x
) &&
153 (childPtr
->rectWindow
.top
<= y
) &&
154 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
155 break; /* There's a window in there */
157 WIN_UpdateWndPtr(&childPtr
,childPtr
->next
);
159 WIN_ReleaseWndPtr(childPtr
);
160 if (!childPtr
) /* No window was found, so it's OK for us */
162 pt
.x
= x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2;
163 pt
.y
= y
- (yspacing
+ GetSystemMetrics(SM_CYICON
)) / 2;
167 } while(x
<= rectParent
.right
-xspacing
);
173 /***********************************************************************
174 * ArrangeIconicWindows16 (USER.170)
176 UINT16 WINAPI
ArrangeIconicWindows16( HWND16 parent
)
178 return ArrangeIconicWindows(parent
);
180 /***********************************************************************
181 * ArrangeIconicWindows (USER32.7)
183 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
187 INT x
, y
, xspacing
, yspacing
;
189 GetClientRect( parent
, &rectParent
);
191 y
= rectParent
.bottom
;
192 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
193 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
195 hwndChild
= GetWindow( parent
, GW_CHILD
);
198 if( IsIconic( hwndChild
) )
200 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
202 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
204 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2,
205 y
- yspacing
- GetSystemMetrics(SM_CYICON
)/2, 0, 0,
206 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
207 if( IsWindow(hwndChild
) )
208 WINPOS_ShowIconTitle(wndPtr
, TRUE
);
209 WIN_ReleaseWndPtr(wndPtr
);
211 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
218 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
224 /***********************************************************************
225 * SwitchToThisWindow16 (USER.172)
227 void WINAPI
SwitchToThisWindow16( HWND16 hwnd
, BOOL16 restore
)
229 SwitchToThisWindow( hwnd
, restore
);
233 /***********************************************************************
234 * SwitchToThisWindow (USER32.539)
236 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
238 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
242 /***********************************************************************
243 * GetWindowRect16 (USER.32)
245 void WINAPI
GetWindowRect16( HWND16 hwnd
, LPRECT16 rect
)
247 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
250 CONV_RECT32TO16( &wndPtr
->rectWindow
, rect
);
251 if (wndPtr
->dwStyle
& WS_CHILD
)
252 MapWindowPoints16( wndPtr
->parent
->hwndSelf
, 0, (POINT16
*)rect
, 2 );
253 WIN_ReleaseWndPtr(wndPtr
);
257 /***********************************************************************
258 * GetWindowRect (USER32.308)
260 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
262 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
263 if (!wndPtr
) return FALSE
;
265 *rect
= wndPtr
->rectWindow
;
266 if (wndPtr
->dwStyle
& WS_CHILD
)
267 MapWindowPoints( wndPtr
->parent
->hwndSelf
, 0, (POINT
*)rect
, 2 );
268 WIN_ReleaseWndPtr(wndPtr
);
273 /***********************************************************************
274 * GetWindowRgn (USER32)
276 int WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
279 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
282 if (wndPtr
->hrgnWnd
) nRet
= CombineRgn( hrgn
, wndPtr
->hrgnWnd
, 0, RGN_COPY
);
283 WIN_ReleaseWndPtr(wndPtr
);
288 /***********************************************************************
289 * SetWindowRgn (USER32)
291 int WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
, BOOL bRedraw
)
296 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
298 if (!wndPtr
) return FALSE
;
300 /* a region exists for this window */
301 if (hrgn
!= 0 && hrgn
== wndPtr
->hrgnWnd
)
303 /* can't replace actual region with same region
304 since we're now owner of that region
306 SetLastError(ERROR_INVALID_HANDLE
);
311 /* we'd like to set it back to 0 */
314 GetWindowRect(hwnd
, &tempRect
);
318 /* verify that region really exists */
319 if (GetRgnBox(hrgn
, &tempRect
) == ERROR
) goto done
;
323 /* Size the window to the rectangle of the new region
324 (if it isn't NULL) */
325 SetWindowPos( hwnd
, NULL
, tempRect
.left
, tempRect
.top
,
326 tempRect
.right
- tempRect
.left
, tempRect
.bottom
- tempRect
.top
,
327 SWP_NOSIZE
| SWP_FRAMECHANGED
| SWP_NOMOVE
|
328 SWP_NOZORDER
| (bRedraw
? 0 : SWP_NOREDRAW
) );
333 /* delete previous region */
334 DeleteObject(wndPtr
->hrgnWnd
);
337 else if (hrgn
== NULL
)
339 /* if there was no previous region (stored in wndPtr->hrgnWnd) and
340 the region to be set is also NULL, there is nothing more to do
346 /* valid region handle */
347 wndPtr
->hrgnWnd
= hrgn
;
348 wndPtr
->pDriver
->pSetWindowRgn(wndPtr
, hrgn
);
353 WIN_ReleaseWndPtr(wndPtr
);
357 /***********************************************************************
360 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
364 FIXME("SetWindowRgn16: stub\n");
369 /***********************************************************************
370 * GetClientRect16 (USER.33)
372 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
374 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
376 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
379 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
380 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
382 WIN_ReleaseWndPtr(wndPtr
);
386 /***********************************************************************
387 * GetClientRect (USER.220)
389 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
391 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
393 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
394 if (!wndPtr
) return FALSE
;
395 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
396 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
398 WIN_ReleaseWndPtr(wndPtr
);
403 /*******************************************************************
404 * ClientToScreen16 (USER.28)
406 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
408 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
412 /*******************************************************************
413 * ClientToScreen (USER32.52)
415 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
417 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
422 /*******************************************************************
423 * ScreenToClient16 (USER.29)
425 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
427 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
431 /*******************************************************************
432 * ScreenToClient (USER32.447)
434 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
436 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
441 /***********************************************************************
442 * WINPOS_WindowFromPoint
444 * Find the window and hittest for a given point.
446 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
449 INT16 hittest
= HTERROR
;
453 TRACE("scope %04x %d,%d\n", wndScope
->hwndSelf
, pt
.x
, pt
.y
);
455 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
457 if( wndScope
->dwStyle
& WS_DISABLED
)
463 if( wndScope
->dwExStyle
& WS_EX_MANAGED
)
465 /* In managed mode we have to check wndScope first as it is also
466 * a window which received the mouse event. */
468 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
469 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
472 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
478 /* If point is in window, and window is visible, and it */
479 /* is enabled (or it's a top-level window), then explore */
480 /* its children. Otherwise, go to the next window. */
482 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
483 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
484 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
486 PtInRegion(wndPtr
->hrgnWnd
, xy
.x
- wndPtr
->rectWindow
.left
,
487 xy
.y
- wndPtr
->rectWindow
.top
) :
488 ((xy
.x
>= wndPtr
->rectWindow
.left
) &&
489 (xy
.x
< wndPtr
->rectWindow
.right
) &&
490 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
491 (xy
.y
< wndPtr
->rectWindow
.bottom
))))
493 TRACE("%d,%d is inside %04x\n", xy
.x
, xy
.y
, wndPtr
->hwndSelf
);
494 *ppWnd
= wndPtr
; /* Got a suitable window */
496 /* If window is minimized or disabled, return at once */
497 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
499 retvalue
= HTCAPTION
;
502 if (wndPtr
->dwStyle
& WS_DISABLED
)
508 /* If point is not in client area, ignore the children */
509 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
510 (xy
.x
>= wndPtr
->rectClient
.right
) ||
511 (xy
.y
< wndPtr
->rectClient
.top
) ||
512 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
514 xy
.x
-= wndPtr
->rectClient
.left
;
515 xy
.y
-= wndPtr
->rectClient
.top
;
516 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
520 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
525 /* If nothing found, try the scope window */
526 if (!*ppWnd
) *ppWnd
= wndScope
;
528 /* Send the WM_NCHITTEST message (only if to the same task) */
529 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
531 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
532 0, MAKELONG( pt
.x
, pt
.y
) );
533 if (hittest
!= HTTRANSPARENT
)
535 retvalue
= hittest
; /* Found the window */
545 /* If no children found in last search, make point relative to parent */
548 xy
.x
+= (*ppWnd
)->rectClient
.left
;
549 xy
.y
+= (*ppWnd
)->rectClient
.top
;
552 /* Restart the search from the next sibling */
553 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
554 *ppWnd
= (*ppWnd
)->parent
;
558 WIN_ReleaseWndPtr(wndPtr
);
563 /*******************************************************************
564 * WindowFromPoint16 (USER.30)
566 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
569 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
570 WIN_ReleaseDesktop();
571 return pWnd
->hwndSelf
;
575 /*******************************************************************
576 * WindowFromPoint (USER32.582)
578 HWND WINAPI
WindowFromPoint( POINT pt
)
582 CONV_POINT32TO16( &pt
, &pt16
);
583 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
584 WIN_ReleaseDesktop();
585 return (HWND
)pWnd
->hwndSelf
;
589 /*******************************************************************
590 * ChildWindowFromPoint16 (USER.191)
592 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
595 CONV_POINT16TO32( &pt
, &pt32
);
596 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
600 /*******************************************************************
601 * ChildWindowFromPoint (USER32.49)
603 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
605 /* pt is in the client coordinates */
607 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
613 /* get client rect fast */
614 rect
.top
= rect
.left
= 0;
615 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
616 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
618 if (!PtInRect( &rect
, pt
))
623 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
626 if (PtInRect( &wnd
->rectWindow
, pt
))
628 retvalue
= wnd
->hwndSelf
;
631 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
633 retvalue
= hwndParent
;
635 WIN_ReleaseWndPtr(wnd
);
639 /*******************************************************************
640 * ChildWindowFromPointEx16 (USER.50)
642 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
645 CONV_POINT16TO32( &pt
, &pt32
);
646 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
650 /*******************************************************************
651 * ChildWindowFromPointEx (USER32.50)
653 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
656 /* pt is in the client coordinates */
658 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
664 /* get client rect fast */
665 rect
.top
= rect
.left
= 0;
666 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
667 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
669 if (!PtInRect( &rect
, pt
))
674 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
678 if (PtInRect( &wnd
->rectWindow
, pt
)) {
679 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
680 !(wnd
->dwStyle
& WS_VISIBLE
) );
681 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
682 (wnd
->dwStyle
& WS_DISABLED
) );
683 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
684 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
687 retvalue
= wnd
->hwndSelf
;
692 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
694 retvalue
= hwndParent
;
696 WIN_ReleaseWndPtr(wnd
);
701 /*******************************************************************
702 * WINPOS_GetWinOffset
704 * Calculate the offset between the origin of the two windows. Used
705 * to implement MapWindowPoints.
707 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
712 offset
->x
= offset
->y
= 0;
713 if (hwndFrom
== hwndTo
) return;
715 /* Translate source window origin to screen coords */
718 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
720 ERR("bad hwndFrom = %04x\n",hwndFrom
);
723 while (wndPtr
->parent
)
725 offset
->x
+= wndPtr
->rectClient
.left
;
726 offset
->y
+= wndPtr
->rectClient
.top
;
727 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
729 WIN_ReleaseWndPtr(wndPtr
);
732 /* Translate origin to destination window coords */
735 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
737 ERR("bad hwndTo = %04x\n", hwndTo
);
740 while (wndPtr
->parent
)
742 offset
->x
-= wndPtr
->rectClient
.left
;
743 offset
->y
-= wndPtr
->rectClient
.top
;
744 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
746 WIN_ReleaseWndPtr(wndPtr
);
751 /*******************************************************************
752 * MapWindowPoints16 (USER.258)
754 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
755 LPPOINT16 lppt
, UINT16 count
)
759 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
769 /*******************************************************************
770 * MapWindowPoints (USER32.386)
772 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
773 LPPOINT lppt
, UINT count
)
777 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
784 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
788 /***********************************************************************
789 * IsIconic16 (USER.31)
791 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
793 return IsIconic(hWnd
);
797 /***********************************************************************
798 * IsIconic (USER32.345)
800 BOOL WINAPI
IsIconic(HWND hWnd
)
803 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
804 if (wndPtr
== NULL
) return FALSE
;
805 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
806 WIN_ReleaseWndPtr(wndPtr
);
811 /***********************************************************************
812 * IsZoomed (USER.272)
814 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
816 return IsZoomed(hWnd
);
820 /***********************************************************************
821 * IsZoomed (USER.352)
823 BOOL WINAPI
IsZoomed(HWND hWnd
)
826 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
827 if (wndPtr
== NULL
) return FALSE
;
828 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
829 WIN_ReleaseWndPtr(wndPtr
);
834 /*******************************************************************
835 * GetActiveWindow (USER.60)
837 HWND16 WINAPI
GetActiveWindow16(void)
839 return (HWND16
)GetActiveWindow();
842 /*******************************************************************
843 * GetActiveWindow (USER32.205)
845 HWND WINAPI
GetActiveWindow(void)
847 MESSAGEQUEUE
*pCurMsgQ
= 0;
850 /* Get the messageQ for the current thread */
851 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
853 WARN("\tCurrent message queue not found. Exiting!\n" );
857 /* Return the current active window from the perQ data of the current message Q */
858 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
860 QUEUE_Unlock( pCurMsgQ
);
865 /*******************************************************************
868 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
870 if( pWnd
&& ( (pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
871 == WS_VISIBLE
) ) return TRUE
;
876 /*******************************************************************
877 * SetActiveWindow16 (USER.59)
879 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
881 return SetActiveWindow(hwnd
);
885 /*******************************************************************
886 * SetActiveWindow (USER32.463)
888 HWND WINAPI
SetActiveWindow( HWND hwnd
)
891 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
892 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
894 if (!wndPtr
|| (wndPtr
->dwStyle
& (WS_DISABLED
| WS_CHILD
)))
900 /* Get the messageQ for the current thread */
901 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
903 WARN("\tCurrent message queue not found. Exiting!\n" );
907 /* Retrieve the message queue associated with this window */
908 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
911 WARN("\tWindow message queue not found. Exiting!\n" );
915 /* Make sure that the window is associated with the calling threads
916 * message queue. It must share the same perQ data.
919 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
922 /* Save current active window */
923 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
925 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
928 /* Unlock the queues before returning */
930 QUEUE_Unlock( pMsgQ
);
932 QUEUE_Unlock( pCurMsgQ
);
935 WIN_ReleaseWndPtr(wndPtr
);
940 /*******************************************************************
941 * GetForegroundWindow16 (USER.608)
943 HWND16 WINAPI
GetForegroundWindow16(void)
945 return (HWND16
)GetForegroundWindow();
949 /*******************************************************************
950 * SetForegroundWindow16 (USER.609)
952 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
954 return SetForegroundWindow( hwnd
);
958 /*******************************************************************
959 * GetForegroundWindow (USER32.241)
961 HWND WINAPI
GetForegroundWindow(void)
965 /* Get the foreground window (active window of hActiveQueue) */
968 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
970 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
972 QUEUE_Unlock( pActiveQueue
);
978 /*******************************************************************
979 * SetForegroundWindow (USER32.482)
981 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
983 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
987 /*******************************************************************
988 * AllowSetForegroundWindow (USER32)
990 BOOL WINAPI
AllowSetForegroundWindow( DWORD procid
)
992 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
993 * implemented, then fix this function. */
998 /*******************************************************************
999 * LockSetForegroundWindow (USER32)
1001 BOOL WINAPI
LockSetForegroundWindow( UINT lockcode
)
1003 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
1004 * implemented, then fix this function. */
1009 /*******************************************************************
1010 * GetShellWindow16 (USER.600)
1012 HWND16 WINAPI
GetShellWindow16(void)
1014 return GetShellWindow();
1017 /*******************************************************************
1018 * SetShellWindow (USER32.504)
1020 HWND WINAPI
SetShellWindow(HWND hwndshell
)
1021 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
1023 hGlobalShellWindow
= hwndshell
;
1024 return hGlobalShellWindow
;
1028 /*******************************************************************
1029 * GetShellWindow (USER32.287)
1031 HWND WINAPI
GetShellWindow(void)
1032 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
1034 return hGlobalShellWindow
;
1038 /***********************************************************************
1039 * BringWindowToTop16 (USER.45)
1041 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
1043 return BringWindowToTop(hwnd
);
1047 /***********************************************************************
1048 * BringWindowToTop (USER32.11)
1050 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
1052 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
1056 /***********************************************************************
1057 * MoveWindow16 (USER.56)
1059 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
1062 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
1066 /***********************************************************************
1067 * MoveWindow (USER32.399)
1069 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
1072 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
1073 if (!repaint
) flags
|= SWP_NOREDRAW
;
1074 TRACE("%04x %d,%d %dx%d %d\n",
1075 hwnd
, x
, y
, cx
, cy
, repaint
);
1076 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1079 /***********************************************************************
1080 * WINPOS_InitInternalPos
1082 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1083 LPRECT restoreRect
)
1085 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1089 /* this happens when the window is minimized/maximized
1090 * for the first time (rectWindow is not adjusted yet) */
1092 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1093 if( !lpPos
) return NULL
;
1095 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1096 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1097 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1098 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1101 if( wnd
->dwStyle
& WS_MINIMIZE
)
1102 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1103 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1104 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1105 else if( restoreRect
)
1106 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1111 /***********************************************************************
1112 * WINPOS_RedrawIconTitle
1114 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1116 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1119 if( lpPos
->hwndIconTitle
)
1121 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1122 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1129 /***********************************************************************
1130 * WINPOS_ShowIconTitle
1132 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1134 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1136 if( lpPos
&& !(pWnd
->dwExStyle
& WS_EX_MANAGED
))
1138 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1140 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1143 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1146 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1148 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1150 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1151 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1152 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1154 WIN_ReleaseWndPtr(pWnd
);
1157 else ShowWindow( hWnd
, SW_HIDE
);
1162 /*******************************************************************
1163 * WINPOS_GetMinMaxInfo
1165 * Get the minimized and maximized information for a window.
1167 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1168 POINT
*minTrack
, POINT
*maxTrack
)
1170 LPINTERNALPOS lpPos
;
1174 /* Compute default values */
1176 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1177 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1178 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1179 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1180 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1181 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1183 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) xinc
= yinc
= 0;
1184 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1186 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1187 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1192 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1194 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1195 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1197 if (wndPtr
->dwStyle
& WS_BORDER
)
1199 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1200 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1203 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1204 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1206 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1207 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1208 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1211 MinMax
.ptMaxPosition
.x
= -xinc
;
1212 MinMax
.ptMaxPosition
.y
= -yinc
;
1215 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1217 /* Some sanity checks */
1219 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1220 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1221 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1222 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1223 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1224 MinMax
.ptMaxTrackSize
.x
= max( MinMax
.ptMaxTrackSize
.x
,
1225 MinMax
.ptMinTrackSize
.x
);
1226 MinMax
.ptMaxTrackSize
.y
= max( MinMax
.ptMaxTrackSize
.y
,
1227 MinMax
.ptMinTrackSize
.y
);
1229 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1230 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1231 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1232 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1235 /***********************************************************************
1236 * WINPOS_MinMaximize
1238 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1239 * This function assumes that 'cmd' is different from the current window
1242 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1246 LPINTERNALPOS lpPos
;
1248 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1250 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1251 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1253 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1255 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1257 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1258 return (SWP_NOSIZE
| SWP_NOMOVE
);
1259 swpFlags
|= SWP_NOCOPYBITS
;
1264 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1266 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1267 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1270 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1271 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1273 if( wndPtr
->flags
& WIN_NATIVE
)
1274 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1275 swpFlags
|= MINMAX_NOSWP
;
1277 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1279 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1280 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1281 swpFlags
|= SWP_NOCOPYBITS
;
1285 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1286 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1287 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1289 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1291 if( wndPtr
->flags
& WIN_NATIVE
)
1292 wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
);
1294 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1295 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1297 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1299 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1304 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1306 if( wndPtr
->flags
& WIN_NATIVE
)
1307 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1308 swpFlags
|= MINMAX_NOSWP
;
1310 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1311 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1313 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1315 /* Restore to maximized position */
1316 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1317 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1318 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1319 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1320 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1325 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1326 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1328 /* Restore to normal position */
1330 *lpRect
= lpPos
->rectNormal
;
1331 lpRect
->right
-= lpRect
->left
;
1332 lpRect
->bottom
-= lpRect
->top
;
1336 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1340 /***********************************************************************
1341 * ShowWindowAsync (USER32.535)
1343 * doesn't wait; returns immediately.
1344 * used by threads to toggle windows in other (possibly hanging) threads
1346 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1348 /* FIXME: does ShowWindow() return immediately ? */
1349 return ShowWindow(hwnd
, cmd
);
1353 /***********************************************************************
1354 * ShowWindow16 (USER.42)
1356 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1358 return ShowWindow(hwnd
,cmd
);
1362 /***********************************************************************
1363 * ShowWindow (USER32.534)
1365 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1367 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1368 BOOL wasVisible
, showFlag
;
1369 RECT16 newPos
= {0, 0, 0, 0};
1372 if (!wndPtr
) return FALSE
;
1374 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1376 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1381 if (!wasVisible
) goto END
;;
1382 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1383 SWP_NOACTIVATE
| SWP_NOZORDER
;
1386 case SW_SHOWMINNOACTIVE
:
1387 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1389 case SW_SHOWMINIMIZED
:
1390 swp
|= SWP_SHOWWINDOW
;
1393 swp
|= SWP_FRAMECHANGED
;
1394 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1395 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1396 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1399 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1400 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1401 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1402 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1403 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1407 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1410 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1413 * ShowWindow has a little peculiar behavior that if the
1414 * window is already the topmost window, it will not
1417 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1418 swp
|= SWP_NOACTIVATE
;
1422 case SW_SHOWNOACTIVATE
:
1423 swp
|= SWP_NOZORDER
;
1424 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1426 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1427 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1429 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1431 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1432 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1433 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1437 showFlag
= (cmd
!= SW_HIDE
);
1438 if (showFlag
!= wasVisible
)
1440 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1441 if (!IsWindow( hwnd
)) goto END
;
1444 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1445 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1446 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1448 /* Don't call SetWindowPos() on invisible child windows */
1449 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1450 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1454 /* We can't activate a child window */
1455 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1456 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1457 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1458 if (!(swp
& MINMAX_NOSWP
))
1460 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1461 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1464 /* FIXME: This will cause the window to be activated irrespective
1465 * of whether it is owned by the same thread. Has to be done
1469 if (hwnd
== GetActiveWindow())
1470 WINPOS_ActivateOtherWindow(wndPtr
);
1472 /* Revert focus to parent */
1473 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1474 SetFocus( GetParent(hwnd
) );
1477 if (!IsWindow( hwnd
)) goto END
;
1478 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1481 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1483 /* should happen only in CreateWindowEx() */
1484 int wParam
= SIZE_RESTORED
;
1486 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1487 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1488 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1489 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1490 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1491 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1492 SendMessageA( hwnd
, WM_MOVE
, 0,
1493 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1497 WIN_ReleaseWndPtr(wndPtr
);
1502 /***********************************************************************
1503 * GetInternalWindowPos16 (USER.460)
1505 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1508 WINDOWPLACEMENT16 wndpl
;
1509 if (GetWindowPlacement16( hwnd
, &wndpl
))
1511 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1512 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1513 return wndpl
.showCmd
;
1519 /***********************************************************************
1520 * GetInternalWindowPos (USER32.245)
1522 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1525 WINDOWPLACEMENT wndpl
;
1526 if (GetWindowPlacement( hwnd
, &wndpl
))
1528 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1529 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1530 return wndpl
.showCmd
;
1535 /***********************************************************************
1536 * GetWindowPlacement16 (USER.370)
1538 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1540 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1541 LPINTERNALPOS lpPos
;
1543 if(!pWnd
) return FALSE
;
1545 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1546 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1547 wndpl
->length
= sizeof(*wndpl
);
1548 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1549 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1551 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1552 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1553 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1554 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1557 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1558 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1559 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1561 WIN_ReleaseWndPtr(pWnd
);
1566 /***********************************************************************
1567 * GetWindowPlacement (USER32.307)
1570 * Fails if wndpl->length of Win95 (!) apps is invalid.
1572 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1576 WINDOWPLACEMENT16 wpl
;
1577 wpl
.length
= sizeof(wpl
);
1578 if( GetWindowPlacement16( hwnd
, &wpl
) )
1580 pwpl32
->length
= sizeof(*pwpl32
);
1581 pwpl32
->flags
= wpl
.flags
;
1582 pwpl32
->showCmd
= wpl
.showCmd
;
1583 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1584 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1585 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1593 /***********************************************************************
1594 * WINPOS_SetPlacement
1596 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1599 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1602 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1603 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1605 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1606 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1607 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1609 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1611 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1612 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1613 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1614 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1616 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1618 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1619 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1620 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1622 else if( flags
& PLACE_RECT
)
1623 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1624 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1625 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1626 SWP_NOZORDER
| SWP_NOACTIVATE
);
1628 ShowWindow( hwnd
, wndpl
->showCmd
);
1629 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1631 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1633 /* SDK: ...valid only the next time... */
1634 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1636 WIN_ReleaseWndPtr(pWnd
);
1643 /***********************************************************************
1644 * SetWindowPlacement16 (USER.371)
1646 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1648 return WINPOS_SetPlacement( hwnd
, wndpl
,
1649 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1652 /***********************************************************************
1653 * SetWindowPlacement (USER32.519)
1656 * Fails if wndpl->length of Win95 (!) apps is invalid.
1658 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1662 WINDOWPLACEMENT16 wpl
;
1664 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1665 wpl
.flags
= pwpl32
->flags
;
1666 wpl
.showCmd
= pwpl32
->showCmd
;
1667 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1668 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1669 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1670 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1671 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1672 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1673 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1674 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1676 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1682 /***********************************************************************
1683 * SetInternalWindowPos16 (USER.461)
1685 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1686 LPRECT16 rect
, LPPOINT16 pt
)
1688 if( IsWindow16(hwnd
) )
1690 WINDOWPLACEMENT16 wndpl
;
1693 wndpl
.length
= sizeof(wndpl
);
1694 wndpl
.showCmd
= showCmd
;
1695 wndpl
.flags
= flags
= 0;
1700 wndpl
.flags
|= WPF_SETMINPOSITION
;
1701 wndpl
.ptMinPosition
= *pt
;
1705 flags
|= PLACE_RECT
;
1706 wndpl
.rcNormalPosition
= *rect
;
1708 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1713 /***********************************************************************
1714 * SetInternalWindowPos (USER32.483)
1716 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1717 LPRECT rect
, LPPOINT pt
)
1719 if( IsWindow(hwnd
) )
1721 WINDOWPLACEMENT16 wndpl
;
1724 wndpl
.length
= sizeof(wndpl
);
1725 wndpl
.showCmd
= showCmd
;
1726 wndpl
.flags
= flags
= 0;
1731 wndpl
.flags
|= WPF_SETMINPOSITION
;
1732 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1736 flags
|= PLACE_RECT
;
1737 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1739 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1743 /*******************************************************************
1744 * WINPOS_SetActiveWindow
1746 * SetActiveWindow() back-end. This is the only function that
1747 * can assign active status to a window. It must be called only
1748 * for the top level windows.
1750 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1752 CBTACTIVATESTRUCT16
* cbtStruct
;
1753 WND
* wndPtr
=0, *wndTemp
;
1754 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1755 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1757 HWND hwndActive
= 0;
1760 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1762 /* Get current active window from the active queue */
1765 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1766 if ( pOldActiveQueue
)
1767 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1770 /* paranoid checks */
1771 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1774 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1777 wndPtr
= WIN_FindWndPtr(hWnd
);
1778 hOldActiveQueue
= hActiveQueue
;
1780 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1782 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1783 WIN_ReleaseWndPtr(wndTemp
);
1786 TRACE("no current active window.\n");
1788 /* call CBT hook chain */
1789 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1791 cbtStruct
->fMouse
= fMouse
;
1792 cbtStruct
->hWndActive
= hwndActive
;
1793 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1794 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1795 SEGPTR_FREE(cbtStruct
);
1796 if (bRet
) goto CLEANUP_END
;
1799 /* set prev active wnd to current active wnd and send notification */
1800 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1802 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1804 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1806 if (GetSysModalWindow16() != hWnd
)
1808 /* disregard refusal if hWnd is sysmodal */
1811 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1812 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1815 /* check if something happened during message processing
1816 * (global active queue may have changed)
1818 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1819 if(!pTempActiveQueue
)
1822 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1823 QUEUE_Unlock( pTempActiveQueue
);
1824 if( hwndPrevActive
!= hwndActive
)
1828 /* Set new active window in the message queue */
1832 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1833 if ( pNewActiveQueue
)
1834 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1836 else /* have to do this or MDI frame activation goes to hell */
1837 if( pOldActiveQueue
)
1838 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1840 /* send palette messages */
1841 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1842 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1844 /* if prev wnd is minimized redraw icon title */
1845 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1847 /* managed windows will get ConfigureNotify event */
1848 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->dwExStyle
& WS_EX_MANAGED
))
1850 /* check Z-order and bring hWnd to the top */
1851 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1853 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1855 WIN_ReleaseDesktop();
1856 WIN_ReleaseWndPtr(wndTemp
);
1858 if( wndTemp
!= wndPtr
)
1859 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1860 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1861 if (!IsWindow(hWnd
))
1865 /* Get a handle to the new active queue */
1866 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1868 /* send WM_ACTIVATEAPP if necessary */
1869 if (hOldActiveQueue
!= hNewActiveQueue
)
1871 WND
**list
, **ppWnd
;
1872 WND
*pDesktop
= WIN_GetDesktop();
1874 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1876 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1878 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1880 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1881 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1882 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1884 WIN_ReleaseWinArray(list
);
1887 hActiveQueue
= hNewActiveQueue
;
1889 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1891 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1893 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1895 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1896 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1897 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1899 WIN_ReleaseWinArray(list
);
1901 WIN_ReleaseDesktop();
1903 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1908 /* walk up to the first unowned window */
1909 wndTemp
= WIN_LockWndPtr(wndPtr
);
1910 while (wndTemp
->owner
)
1912 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1914 /* and set last active owned popup */
1915 wndTemp
->hwndLastActive
= hWnd
;
1917 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1918 WIN_ReleaseWndPtr(wndTemp
);
1919 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1920 SendMessageA( hWnd
, WM_ACTIVATE
,
1921 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1922 (LPARAM
)hwndPrevActive
);
1923 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1926 /* change focus if possible */
1929 if ( pNewActiveQueue
)
1931 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1933 if ( hOldFocus
&& WIN_GetTopParent( hOldFocus
) != hwndActive
)
1934 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1935 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1939 if ( pOldActiveQueue
&&
1940 ( !pNewActiveQueue
||
1941 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1943 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1945 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1949 if( !hwndPrevActive
&& wndPtr
)
1950 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1952 /* if active wnd is minimized redraw icon title */
1953 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1955 bRet
= (hWnd
== hwndActive
); /* Success? */
1957 CLEANUP
: /* Unlock the message queues before returning */
1959 if ( pNewActiveQueue
)
1960 QUEUE_Unlock( pNewActiveQueue
);
1964 if ( pOldActiveQueue
)
1965 QUEUE_Unlock( pOldActiveQueue
);
1967 WIN_ReleaseWndPtr(wndPtr
);
1971 /*******************************************************************
1972 * WINPOS_ActivateOtherWindow
1974 * Activates window other than pWnd.
1976 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1980 HWND hwndActive
= 0;
1982 /* Get current active window from the active queue */
1985 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1988 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1989 QUEUE_Unlock( pActiveQueue
);
1993 if( pWnd
->hwndSelf
== hwndPrevActive
)
1996 if( hwndActive
!= pWnd
->hwndSelf
&&
1997 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
2000 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
2001 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
2003 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
2005 WIN_ReleaseWndPtr(pWndTo
);
2006 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
2008 while( !WINPOS_CanActivate(pWndTo
) )
2010 /* by now owned windows should've been taken care of */
2011 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
2012 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
2013 if( !pWndTo
) break;
2015 WIN_ReleaseWndPtr(pWndPtr
);
2018 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
2020 /* switch desktop queue to current active */
2023 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
2024 WIN_ReleaseWndPtr(pWndTo
);
2025 WIN_ReleaseDesktop();
2032 /*******************************************************************
2033 * WINPOS_ChangeActiveWindow
2036 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
2038 WND
*wndPtr
, *wndTemp
;
2040 HWND hwndActive
= 0;
2042 /* Get current active window from the active queue */
2045 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2048 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2049 QUEUE_Unlock( pActiveQueue
);
2054 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
2056 wndPtr
= WIN_FindWndPtr(hWnd
);
2057 if( !wndPtr
) return FALSE
;
2059 /* child windows get WM_CHILDACTIVATE message */
2060 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2062 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
2066 if( hWnd
== hwndActive
)
2072 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
2078 /* switch desktop queue to current active */
2079 wndTemp
= WIN_GetDesktop();
2080 if( wndPtr
->parent
== wndTemp
)
2081 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
2082 WIN_ReleaseDesktop();
2086 WIN_ReleaseWndPtr(wndPtr
);
2091 /***********************************************************************
2092 * WINPOS_SendNCCalcSize
2094 * Send a WM_NCCALCSIZE message to a window.
2095 * All parameters are read-only except newClientRect.
2096 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2097 * when calcValidRect is TRUE.
2099 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2100 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2101 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2102 RECT
*newClientRect
)
2104 NCCALCSIZE_PARAMS params
;
2105 WINDOWPOS winposCopy
;
2108 params
.rgrc
[0] = *newWindowRect
;
2111 winposCopy
= *winpos
;
2112 params
.rgrc
[1] = *oldWindowRect
;
2113 params
.rgrc
[2] = *oldClientRect
;
2114 params
.lppos
= &winposCopy
;
2116 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2118 TRACE("%d,%d-%d,%d\n",
2119 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2120 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2122 /* If the application send back garbage, ignore it */
2123 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2124 *newClientRect
= params
.rgrc
[0];
2130 /***********************************************************************
2131 * WINPOS_HandleWindowPosChanging16
2133 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2135 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2137 POINT maxSize
, minTrack
;
2138 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2139 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2140 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2142 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2143 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2144 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2145 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2147 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2148 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2155 /***********************************************************************
2156 * WINPOS_HandleWindowPosChanging
2158 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2160 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2163 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2164 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2165 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2167 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2168 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
2169 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
2174 /***********************************************************************
2177 * fix Z order taking into account owned popups -
2178 * basically we need to maintain them above the window that owns them
2180 * FIXME: hide/show owned popups when owner visibility changes.
2182 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2184 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2186 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2188 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2190 /* make sure this popup stays above the owner */
2192 HWND hwndLocalPrev
= HWND_TOP
;
2194 if( hwndInsertAfter
!= HWND_TOP
)
2196 while( w
!= wndPtr
->owner
)
2198 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2199 if( hwndLocalPrev
== hwndInsertAfter
) break;
2200 WIN_UpdateWndPtr(&w
,w
->next
);
2202 hwndInsertAfter
= hwndLocalPrev
;
2205 else if( wndPtr
->dwStyle
& WS_CHILD
)
2208 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2212 if( w
== wndPtr
) break;
2214 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2216 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2217 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2218 hwndInsertAfter
= w
->hwndSelf
;
2220 WIN_UpdateWndPtr(&w
, w
->next
);
2224 WIN_ReleaseWndPtr(w
);
2225 return hwndInsertAfter
;
2228 /***********************************************************************
2231 * Make window look nice without excessive repainting
2233 * visible and update regions are in window coordinates
2234 * client and window rectangles are in parent client coordinates
2236 * Returns: uFlags and a dirty region in *pVisRgn.
2238 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2239 LPRECT lpOldWndRect
,
2240 LPRECT lpOldClientRect
, UINT uFlags
)
2243 HRGN newVisRgn
, dirtyRgn
;
2244 INT my
= COMPLEXREGION
;
2246 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2247 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2248 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2249 lpOldWndRect
->left
, lpOldWndRect
->top
,
2250 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2251 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2252 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2253 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2254 lpOldClientRect
->left
, lpOldClientRect
->top
,
2255 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2257 if( Wnd
->hrgnUpdate
== 1 )
2258 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2260 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2261 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2263 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2264 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2266 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2270 TRACE("\twon't copy anything!\n");
2272 /* set dirtyRgn to the sum of old and new visible regions
2273 * in parent client coordinates */
2275 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2276 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2278 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2280 else /* copy valid bits to a new location */
2282 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2283 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2285 /* subtract already invalid region inside Wnd from the dst region */
2287 if( Wnd
->hrgnUpdate
)
2288 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2291 /* check if entire window can be copied */
2293 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2294 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2295 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2296 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2298 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2299 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2300 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2301 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2303 if( (ocw
!= ncw
) || (och
!= nch
) ||
2304 ( ow
!= nw
) || ( oh
!= nh
) ||
2305 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2306 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2307 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2308 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2310 if(uFlags
& SWP_EX_PAINTSELF
)
2312 /* movement relative to the window itself */
2313 dx
= (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
) -
2314 (lpOldClientRect
->left
- lpOldWndRect
->left
) ;
2315 dy
= (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
) -
2316 (lpOldClientRect
->top
- lpOldWndRect
->top
) ;
2320 /* movement relative to the parent's client area */
2321 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2322 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2325 /* restrict valid bits to the common client rect */
2327 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2328 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2329 r
.right
= r
.left
+ min( ocw
, ncw
);
2330 r
.bottom
= r
.top
+ min( och
, nch
);
2332 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2333 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2334 GetRgnBox( hrgnValid
, &r
);
2335 if( IsRectEmpty( &r
) )
2337 r
= *lpOldClientRect
;
2341 if(uFlags
& SWP_EX_PAINTSELF
) {
2343 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2344 * relative to itself, only the client area can change.
2345 * if the client rect didn't change, there's nothing to do.
2352 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2353 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2354 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2359 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2361 /* Move remaining regions to parent coordinates */
2362 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2363 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2366 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2368 TRACE("\tcomputing dirty region!\n");
2370 /* Compute combined dirty region (old + new - valid) */
2371 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2372 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2374 /* Blt valid bits, r is the rect to copy */
2381 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2382 from copying clipped areas */
2384 if( uFlags
& SWP_EX_PAINTSELF
)
2386 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2387 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2388 rClip
.right
= nw
; rClip
.bottom
= nh
;
2392 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2393 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2394 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2395 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2397 rClip
.left
= rClip
.top
= 0;
2399 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2400 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2402 if( IntersectRect( &r
, &r
, &rClip
) )
2404 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, hDC
, dx
, dy
, &r
, TRUE
);
2406 /* When you copy the bits without repainting, parent doesn't
2407 get validated appropriately. Therefore, we have to validate
2408 the parent with the windows' updated region when the
2409 parent's update region is not empty. */
2411 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2413 OffsetRect(&r
, dx
, dy
);
2414 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2417 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2418 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2422 /* *pVisRgn now points to the invalidated region */
2424 DeleteObject(newVisRgn
);
2425 DeleteObject(dirtyRgn
);
2429 /***********************************************************************
2430 * SWP_DoSimpleFrameChanged
2432 * NOTE: old and new client rect origins are identical, only
2433 * extents may have changed. Window extents are the same.
2435 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2441 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2443 /* Client rect changed its position/size, most likely a scrollar
2444 * was added/removed.
2446 * FIXME: WVR alignment flags
2449 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2453 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2454 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2455 if(!(uFlags
& SWP_EX_NOCOPY
))
2456 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2464 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2467 hrgn
= CreateRectRgnIndirect( &rect
);
2469 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2470 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2471 if(!(uFlags
& SWP_EX_NOCOPY
))
2472 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2476 REGION_UnionRectWithRgn( hrgn
, &rect
);
2479 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2481 rect
= wndPtr
->rectWindow
;
2482 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2483 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2491 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2492 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2496 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2500 DeleteObject( hrgn
);
2503 /***********************************************************************
2504 * SWP_DoWinPosChanging
2506 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2507 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2509 /* Send WM_WINDOWPOSCHANGING message */
2511 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2512 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2514 /* Calculate new position and size */
2516 *pNewWindowRect
= wndPtr
->rectWindow
;
2517 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2518 : wndPtr
->rectClient
;
2520 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2522 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2523 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2525 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2527 pNewWindowRect
->left
= pWinpos
->x
;
2528 pNewWindowRect
->top
= pWinpos
->y
;
2529 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2530 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2532 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2533 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2536 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2540 /***********************************************************************
2543 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2544 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2548 /* Send WM_NCCALCSIZE message to get new client area */
2549 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2551 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2552 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2553 pWinpos
, pNewClientRect
);
2555 /* FIXME: WVR_ALIGNxxx */
2557 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2558 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2559 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2561 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2562 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2563 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2564 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2565 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2568 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2569 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2570 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2574 /***********************************************************************
2575 * SetWindowPos (USER.2)
2577 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2578 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2580 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2583 /***********************************************************************
2584 * SetWindowPos (USER32.520)
2586 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2587 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2590 WND
* wndPtr
,*wndTemp
;
2591 RECT newWindowRect
, newClientRect
;
2592 RECT oldWindowRect
, oldClientRect
;
2594 UINT wvrFlags
= 0, uFlags
= 0;
2595 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2596 HWND hwndActive
= 0;
2598 /* Get current active window from the active queue */
2601 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2604 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2605 QUEUE_Unlock( pActiveQueue
);
2609 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2610 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2612 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2613 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2616 /* ------------------------------------------------------------------------ CHECKS */
2618 /* Check window handle */
2620 if (hwnd
== GetDesktopWindow()) return FALSE
;
2621 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2623 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2624 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2626 /* Fix redundant flags */
2628 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2629 flags
&= ~SWP_SHOWWINDOW
;
2632 if (!(flags
& SWP_SHOWWINDOW
))
2633 flags
|= SWP_NOREDRAW
;
2634 flags
&= ~SWP_HIDEWINDOW
;
2637 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2639 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2640 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2641 flags
|= SWP_NOSIZE
; /* Already the right size */
2643 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2644 flags
|= SWP_NOMOVE
; /* Already the right position */
2646 if (hwnd
== hwndActive
)
2647 flags
|= SWP_NOACTIVATE
; /* Already active */
2648 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2650 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2652 flags
&= ~SWP_NOZORDER
;
2653 hwndInsertAfter
= HWND_TOP
;
2658 /* Check hwndInsertAfter */
2660 /* FIXME: TOPMOST not supported yet */
2661 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2662 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2664 /* hwndInsertAfter must be a sibling of the window */
2665 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2667 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2670 if( wnd
->parent
!= wndPtr
->parent
)
2673 WIN_ReleaseWndPtr(wnd
);
2676 /* don't need to change the Zorder of hwnd if it's already inserted
2677 * after hwndInsertAfter or when inserting hwnd after itself.
2679 if(( wnd
->next
== wndPtr
) || (hwnd
== hwndInsertAfter
)) flags
|= SWP_NOZORDER
;
2681 WIN_ReleaseWndPtr(wnd
);
2684 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2686 /* Fill the WINDOWPOS structure */
2689 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2694 winpos
.flags
= flags
;
2696 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2698 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2700 if( wndPtr
->parent
== WIN_GetDesktop() )
2701 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2702 hwndInsertAfter
, winpos
.flags
);
2703 WIN_ReleaseDesktop();
2706 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2708 if( hwndInsertAfter
== HWND_TOP
)
2709 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2711 if( hwndInsertAfter
== HWND_BOTTOM
)
2712 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2714 if( !(winpos
.flags
& SWP_NOZORDER
) )
2715 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2716 winpos
.flags
|= SWP_NOZORDER
;
2718 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2719 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2720 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2722 /* get a previous visible region for SWP_CopyValidBits() */
2723 DWORD dflags
= DCX_WINDOW
;
2725 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2726 dflags
|= DCX_CLIPSIBLINGS
;
2728 visRgn
= DCE_GetVisRgn(hwnd
, dflags
, 0, 0);
2732 /* Common operations */
2734 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2736 if(!(winpos
.flags
& SWP_NOZORDER
) && winpos
.hwnd
!= hwndInsertAfter
)
2738 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2739 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2742 /* Reset active DCEs */
2744 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2745 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2746 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2750 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2751 DCE_InvalidateDCE(wndPtr
, &rect
);
2754 oldWindowRect
= wndPtr
->rectWindow
;
2755 oldClientRect
= wndPtr
->rectClient
;
2757 /* Find out if we have to redraw the whole client rect */
2759 if( oldClientRect
.bottom
- oldClientRect
.top
==
2760 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2762 if( oldClientRect
.right
- oldClientRect
.left
==
2763 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2765 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2766 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2768 uFlags
|= SWP_EX_NOCOPY
;
2771 * Use this later in CopyValidBits()
2774 uFlags |= SWP_EX_NONCLIENT;
2777 /* FIXME: actually do something with WVR_VALIDRECTS */
2779 wndPtr
->rectWindow
= newWindowRect
;
2780 wndPtr
->rectClient
= newClientRect
;
2782 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2784 BOOL bCallDriver
= TRUE
;
2785 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2787 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2789 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2791 /* This is the only place where we need to force repainting of the contents
2792 of windows created by the host window system, all other cases go through the
2793 expose event handling */
2795 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2797 cx
= newWindowRect
.right
- newWindowRect
.left
;
2798 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2800 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2801 winpos
.hwndInsertAfter
= tempInsertAfter
;
2802 bCallDriver
= FALSE
;
2804 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2805 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2808 /* client area moved but window extents remained the same, copy valid bits */
2810 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2811 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2812 uFlags
| SWP_EX_PAINTSELF
);
2819 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2821 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2822 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2823 !(uFlags
& SWP_EX_NOCOPY
) )
2825 /* The origin of the client rect didn't move so we can try to repaint
2826 * only the nonclient area by setting bit gravity hint for the host window system.
2829 if( !(wndPtr
->dwExStyle
& WS_EX_MANAGED
) )
2831 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2832 newWindowRect
.bottom
- newWindowRect
.top
);
2833 RECT rcn
= newClientRect
;
2834 RECT rco
= oldClientRect
;
2836 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2837 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2838 IntersectRect( &rcn
, &rcn
, &rco
);
2839 visRgn
= CreateRectRgnIndirect( &rcn
);
2840 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2841 DeleteObject( hrgn
);
2842 uFlags
= SWP_EX_PAINTSELF
;
2844 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2847 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2850 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2851 winpos
.hwndInsertAfter
= tempInsertAfter
;
2854 if( winpos
.flags
& SWP_SHOWWINDOW
)
2858 wndPtr
->dwStyle
|= WS_VISIBLE
;
2860 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) resync
= TRUE
;
2862 /* focus was set to unmapped window, reset host focus
2863 * since the window is now visible */
2865 focus
= curr
= GetFocus();
2870 WND
*pFocus
= WIN_FindWndPtr( focus
);
2872 pFocus
->pDriver
->pSetFocus(pFocus
);
2873 WIN_ReleaseWndPtr(pFocus
);
2876 curr
= GetParent(curr
);
2880 else /* -------------------------------------------- emulated window */
2882 if( winpos
.flags
& SWP_SHOWWINDOW
)
2884 wndPtr
->dwStyle
|= WS_VISIBLE
;
2885 uFlags
|= SWP_EX_PAINTSELF
;
2886 visRgn
= 1; /* redraw the whole window */
2888 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2890 if( winpos
.flags
& SWP_HIDEWINDOW
)
2892 if( visRgn
> 1 ) /* map to parent */
2893 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2899 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2901 /* if window was not resized and not moved try to repaint itself */
2902 if((winpos
.flags
& SWP_AGG_NOGEOMETRYCHANGE
) == SWP_AGG_NOGEOMETRYCHANGE
)
2903 uFlags
|= SWP_EX_PAINTSELF
;
2904 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2905 &oldClientRect
, uFlags
);
2909 /* nothing moved, redraw frame if needed */
2911 if( winpos
.flags
& SWP_FRAMECHANGED
)
2912 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2915 DeleteObject( visRgn
);
2923 if( winpos
.flags
& SWP_HIDEWINDOW
)
2925 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2928 if (hwnd
== CARET_GetHwnd())
2930 if( winpos
.flags
& SWP_HIDEWINDOW
)
2932 else if (winpos
.flags
& SWP_SHOWWINDOW
)
2936 /* ------------------------------------------------------------------------ FINAL */
2938 if (wndPtr
->flags
& WIN_NATIVE
)
2939 EVENT_Synchronize(); /* Synchronize with the host window system */
2941 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2943 /* Simulate a mouse event to set the cursor */
2944 int iWndsLocks
= WIN_SuspendWndsLock();
2946 hardware_event( WM_MOUSEMOVE
, GET_KEYSTATE(), 0,
2947 PosX
, PosY
, GetTickCount(), 0 );
2949 WIN_RestoreWndsLock(iWndsLocks
);
2952 wndTemp
= WIN_GetDesktop();
2954 /* repaint invalidated region (if any)
2956 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2957 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2962 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2965 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2966 its parent and sibling and so on, and then erase the parent window
2967 back ground if the parent is either a top-level window or its parent's parent
2968 is top-level window. Rely on the system to repaint other affected
2969 windows later on. */
2970 if( uFlags
& SWP_EX_PAINTSELF
)
2972 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2973 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2974 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2978 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2979 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2983 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2985 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2986 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2990 DeleteObject( visRgn
);
2993 WIN_ReleaseDesktop();
2995 if (!(flags
& SWP_NOACTIVATE
))
2996 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2998 /* And last, send the WM_WINDOWPOSCHANGED message */
3000 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
3003 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
3004 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
3006 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
3007 if (resync
) EVENT_Synchronize();
3012 WIN_ReleaseWndPtr(wndPtr
);
3017 /***********************************************************************
3018 * BeginDeferWindowPos16 (USER.259)
3020 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
3022 return BeginDeferWindowPos( count
);
3026 /***********************************************************************
3027 * BeginDeferWindowPos (USER32.9)
3029 HDWP WINAPI
BeginDeferWindowPos( INT count
)
3036 SetLastError(ERROR_INVALID_PARAMETER
);
3039 /* Windows allows zero count, in which case it allocates context for 8 moves */
3040 if (count
== 0) count
= 8;
3042 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
3043 if (!handle
) return 0;
3044 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
3045 pDWP
->actualCount
= 0;
3046 pDWP
->suggestedCount
= count
;
3048 pDWP
->wMagic
= DWP_MAGIC
;
3049 pDWP
->hwndParent
= 0;
3054 /***********************************************************************
3055 * DeferWindowPos16 (USER.260)
3057 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
3058 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
3061 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
3062 x
, y
, cx
, cy
, flags
);
3066 /***********************************************************************
3067 * DeferWindowPos (USER32.128)
3069 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
3070 INT x
, INT y
, INT cx
, INT cy
,
3075 HDWP newhdwp
= hdwp
,retvalue
;
3079 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3080 if (!pDWP
) return 0;
3081 if (hwnd
== GetDesktopWindow()) return 0;
3083 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
3084 USER_HEAP_FREE( hdwp
);
3088 /* Numega Bounds Checker Demo dislikes the following code.
3089 In fact, I've not been able to find any "same parent" requirement in any docu
3093 /* All the windows of a DeferWindowPos() must have the same parent */
3094 parent
= pWnd
->parent
->hwndSelf
;
3095 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
3096 else if (parent
!= pDWP
->hwndParent
)
3098 USER_HEAP_FREE( hdwp
);
3104 for (i
= 0; i
< pDWP
->actualCount
; i
++)
3106 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
3108 /* Merge with the other changes */
3109 if (!(flags
& SWP_NOZORDER
))
3111 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3113 if (!(flags
& SWP_NOMOVE
))
3115 pDWP
->winPos
[i
].x
= x
;
3116 pDWP
->winPos
[i
].y
= y
;
3118 if (!(flags
& SWP_NOSIZE
))
3120 pDWP
->winPos
[i
].cx
= cx
;
3121 pDWP
->winPos
[i
].cy
= cy
;
3123 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3124 SWP_NOZORDER
| SWP_NOREDRAW
|
3125 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3127 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3133 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3135 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3136 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3142 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3143 pDWP
->suggestedCount
++;
3145 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3146 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3147 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3148 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3149 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3150 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3151 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3152 pDWP
->actualCount
++;
3155 WIN_ReleaseWndPtr(pWnd
);
3160 /***********************************************************************
3161 * EndDeferWindowPos16 (USER.261)
3163 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3165 return EndDeferWindowPos( hdwp
);
3169 /***********************************************************************
3170 * EndDeferWindowPos (USER32.173)
3172 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3179 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3180 if (!pDWP
) return FALSE
;
3181 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3183 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3184 winpos
->x
, winpos
->y
, winpos
->cx
,
3185 winpos
->cy
, winpos
->flags
))) break;
3187 USER_HEAP_FREE( hdwp
);
3192 /***********************************************************************
3193 * TileChildWindows (USER.199)
3195 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3197 FIXME("(%04x, %d): stub\n", parent
, action
);
3200 /***********************************************************************
3201 * CascadeChildWindows (USER.198)
3203 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3205 FIXME("(%04x, %d): stub\n", parent
, action
);
3208 /***********************************************************************
3209 * SetProgmanWindow [USER32.522]
3211 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3213 hGlobalProgmanWindow
= hwnd
;
3214 return hGlobalProgmanWindow
;
3217 /***********************************************************************
3218 * GetProgmanWindow [USER32.289]
3220 HRESULT WINAPI
GetProgmanWindow ( )
3222 return hGlobalProgmanWindow
;
3225 /***********************************************************************
3226 * SetShellWindowEx [USER32.531]
3227 * hwndProgman = Progman[Program Manager]
3228 * |-> SHELLDLL_DefView
3229 * hwndListView = | |-> SysListView32
3230 * | | |-> tooltips_class32
3236 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3238 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3239 hGlobalShellWindow
= hwndProgman
;
3240 return hGlobalShellWindow
;
3244 /***********************************************************************
3245 * SetTaskmanWindow [USER32.537]
3247 * hwnd = MSTaskSwWClass
3248 * |-> SysTabControl32
3250 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3252 hGlobalTaskmanWindow
= hwnd
;
3253 return hGlobalTaskmanWindow
;
3256 /***********************************************************************
3257 * GetTaskmanWindow [USER32.304]
3259 HRESULT WINAPI
GetTaskmanWindow ( )
3261 return hGlobalTaskmanWindow
;