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"
29 DEFAULT_DEBUG_CHANNEL(win
);
31 #define HAS_DLGFRAME(style,exStyle) \
32 (((exStyle) & WS_EX_DLGMODALFRAME) || \
33 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
35 #define HAS_THICKFRAME(style) \
36 (((style) & WS_THICKFRAME) && \
37 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
39 #define SWP_AGG_NOGEOMETRYCHANGE \
40 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
41 #define SWP_AGG_NOPOSCHANGE \
42 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
43 #define SWP_AGG_STATUSFLAGS \
44 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
46 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
48 #define PLACE_MIN 0x0001
49 #define PLACE_MAX 0x0002
50 #define PLACE_RECT 0x0004
52 #define SWP_EX_NOCOPY 0x0001
53 #define SWP_EX_PAINTSELF 0x0002
54 #define SWP_EX_NONCLIENT 0x0004
56 #define MINMAX_NOSWP 0x00010000
58 /* ----- internal variables ----- */
60 static HWND hwndPrevActive
= 0; /* Previously active window */
61 static HWND hGlobalShellWindow
=0; /*the shell*/
62 static HWND hGlobalTaskmanWindow
=0;
63 static HWND hGlobalProgmanWindow
=0;
65 static LPCSTR atomInternalPos
;
67 extern HQUEUE16 hActiveQueue
;
69 /***********************************************************************
70 * WINPOS_CreateInternalPosAtom
72 BOOL
WINPOS_CreateInternalPosAtom()
75 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
76 return (atomInternalPos
) ? TRUE
: FALSE
;
79 /***********************************************************************
80 * WINPOS_CheckInternalPos
82 * Called when a window is destroyed.
84 void WINPOS_CheckInternalPos( WND
* wndPtr
)
87 MESSAGEQUEUE
*pMsgQ
= 0;
88 HWND hwnd
= wndPtr
->hwndSelf
;
90 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
92 /* Retrieve the message queue associated with this window */
93 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
96 WARN("\tMessage queue not found. Exiting!\n" );
100 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
102 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
104 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
105 WARN("\tattempt to activate destroyed window!\n");
110 if( IsWindow(lpPos
->hwndIconTitle
) )
111 DestroyWindow( lpPos
->hwndIconTitle
);
112 HeapFree( GetProcessHeap(), 0, lpPos
);
115 QUEUE_Unlock( pMsgQ
);
119 /***********************************************************************
122 * Find a suitable place for an iconic window.
124 static POINT16
WINPOS_FindIconPos( WND
* wndPtr
, POINT16 pt
)
127 short x
, y
, xspacing
, yspacing
;
129 GetClientRect16( wndPtr
->parent
->hwndSelf
, &rectParent
);
130 if ((pt
.x
>= rectParent
.left
) && (pt
.x
+ GetSystemMetrics(SM_CXICON
) < rectParent
.right
) &&
131 (pt
.y
>= rectParent
.top
) && (pt
.y
+ GetSystemMetrics(SM_CYICON
) < rectParent
.bottom
))
132 return pt
; /* The icon already has a suitable position */
134 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
135 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
137 y
= rectParent
.bottom
;
143 /* Check if another icon already occupies this spot */
144 WND
*childPtr
= WIN_LockWndPtr(wndPtr
->parent
->child
);
147 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (childPtr
!= wndPtr
))
149 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
150 (childPtr
->rectWindow
.right
>= x
) &&
151 (childPtr
->rectWindow
.top
<= y
) &&
152 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
153 break; /* There's a window in there */
155 WIN_UpdateWndPtr(&childPtr
,childPtr
->next
);
157 WIN_ReleaseWndPtr(childPtr
);
158 if (!childPtr
) /* No window was found, so it's OK for us */
160 pt
.x
= x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2;
161 pt
.y
= y
- (yspacing
+ GetSystemMetrics(SM_CYICON
)) / 2;
165 } while(x
<= rectParent
.right
-xspacing
);
171 /***********************************************************************
172 * ArrangeIconicWindows (USER.170)
174 UINT16 WINAPI
ArrangeIconicWindows16( HWND16 parent
)
176 return ArrangeIconicWindows(parent
);
178 /***********************************************************************
179 * ArrangeIconicWindows (USER32.@)
181 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
185 INT x
, y
, xspacing
, yspacing
;
187 GetClientRect( parent
, &rectParent
);
189 y
= rectParent
.bottom
;
190 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
191 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
193 hwndChild
= GetWindow( parent
, GW_CHILD
);
196 if( IsIconic( hwndChild
) )
198 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
200 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
202 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2,
203 y
- yspacing
- GetSystemMetrics(SM_CYICON
)/2, 0, 0,
204 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
205 if( IsWindow(hwndChild
) )
206 WINPOS_ShowIconTitle(wndPtr
, TRUE
);
207 WIN_ReleaseWndPtr(wndPtr
);
209 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
216 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
222 /***********************************************************************
223 * SwitchToThisWindow (USER.172)
225 void WINAPI
SwitchToThisWindow16( HWND16 hwnd
, BOOL16 restore
)
227 SwitchToThisWindow( hwnd
, restore
);
231 /***********************************************************************
232 * SwitchToThisWindow (USER32.@)
234 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
236 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
240 /***********************************************************************
241 * GetWindowRect (USER.32)
243 void WINAPI
GetWindowRect16( HWND16 hwnd
, LPRECT16 rect
)
245 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
248 CONV_RECT32TO16( &wndPtr
->rectWindow
, rect
);
249 if (wndPtr
->dwStyle
& WS_CHILD
)
250 MapWindowPoints16( wndPtr
->parent
->hwndSelf
, 0, (POINT16
*)rect
, 2 );
251 WIN_ReleaseWndPtr(wndPtr
);
255 /***********************************************************************
256 * GetWindowRect (USER32.@)
258 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
260 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
261 if (!wndPtr
) return FALSE
;
263 *rect
= wndPtr
->rectWindow
;
264 if (wndPtr
->dwStyle
& WS_CHILD
)
265 MapWindowPoints( wndPtr
->parent
->hwndSelf
, 0, (POINT
*)rect
, 2 );
266 WIN_ReleaseWndPtr(wndPtr
);
271 /***********************************************************************
272 * GetWindowRgn (USER32.@)
274 int WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
277 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
280 if (wndPtr
->hrgnWnd
) nRet
= CombineRgn( hrgn
, wndPtr
->hrgnWnd
, 0, RGN_COPY
);
281 WIN_ReleaseWndPtr(wndPtr
);
286 /***********************************************************************
287 * SetWindowRgn (USER32.@)
289 int WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
, BOOL bRedraw
)
294 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
296 if (!wndPtr
) return FALSE
;
298 /* a region exists for this window */
299 if (hrgn
!= 0 && hrgn
== wndPtr
->hrgnWnd
)
301 /* can't replace actual region with same region
302 since we're now owner of that region
304 SetLastError(ERROR_INVALID_HANDLE
);
309 /* we'd like to set it back to 0 */
312 GetWindowRect(hwnd
, &tempRect
);
316 /* verify that region really exists */
317 if (GetRgnBox(hrgn
, &tempRect
) == ERROR
) goto done
;
321 /* Size the window to the rectangle of the new region
322 (if it isn't NULL) */
323 SetWindowPos( hwnd
, 0, tempRect
.left
, tempRect
.top
,
324 tempRect
.right
- tempRect
.left
, tempRect
.bottom
- tempRect
.top
,
325 SWP_NOSIZE
| SWP_FRAMECHANGED
| SWP_NOMOVE
|
326 SWP_NOZORDER
| (bRedraw
? 0 : SWP_NOREDRAW
) );
331 /* delete previous region */
332 DeleteObject(wndPtr
->hrgnWnd
);
337 /* if there was no previous region (stored in wndPtr->hrgnWnd) and
338 the region to be set is also NULL, there is nothing more to do
344 /* valid region handle */
345 wndPtr
->hrgnWnd
= hrgn
;
346 wndPtr
->pDriver
->pSetWindowRgn(wndPtr
, hrgn
);
351 WIN_ReleaseWndPtr(wndPtr
);
355 /***********************************************************************
356 * SetWindowRgn (USER.668)
358 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
362 FIXME("SetWindowRgn16: stub\n");
367 /***********************************************************************
368 * GetClientRect (USER.33)
370 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
372 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
374 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
377 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
378 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
380 WIN_ReleaseWndPtr(wndPtr
);
384 /***********************************************************************
385 * GetClientRect (USER32.@)
387 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
389 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
391 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
392 if (!wndPtr
) return FALSE
;
393 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
394 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
396 WIN_ReleaseWndPtr(wndPtr
);
401 /*******************************************************************
402 * ClientToScreen (USER.28)
404 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
406 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
410 /*******************************************************************
411 * ClientToScreen (USER32.@)
413 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
415 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
420 /*******************************************************************
421 * ScreenToClient (USER.29)
423 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
425 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
429 /*******************************************************************
430 * ScreenToClient (USER32.@)
432 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
434 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
439 /***********************************************************************
440 * WINPOS_WindowFromPoint
442 * Find the window and hittest for a given point.
444 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
447 INT16 hittest
= HTERROR
;
451 TRACE("scope %04x %d,%d\n", wndScope
->hwndSelf
, pt
.x
, pt
.y
);
453 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
455 if( wndScope
->dwStyle
& WS_DISABLED
)
461 if( wndScope
->dwExStyle
& WS_EX_MANAGED
)
463 /* In managed mode we have to check wndScope first as it is also
464 * a window which received the mouse event. */
466 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
467 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
470 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
476 /* If point is in window, and window is visible, and it */
477 /* is enabled (or it's a top-level window), then explore */
478 /* its children. Otherwise, go to the next window. */
480 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
481 ((wndPtr
->dwExStyle
& (WS_EX_LAYERED
| WS_EX_TRANSPARENT
)) != (WS_EX_LAYERED
| WS_EX_TRANSPARENT
)) &&
482 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
483 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
485 PtInRegion(wndPtr
->hrgnWnd
, xy
.x
- wndPtr
->rectWindow
.left
,
486 xy
.y
- wndPtr
->rectWindow
.top
) :
487 ((xy
.x
>= wndPtr
->rectWindow
.left
) &&
488 (xy
.x
< wndPtr
->rectWindow
.right
) &&
489 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
490 (xy
.y
< wndPtr
->rectWindow
.bottom
))))
492 TRACE("%d,%d is inside %04x\n", xy
.x
, xy
.y
, wndPtr
->hwndSelf
);
493 *ppWnd
= wndPtr
; /* Got a suitable window */
495 /* If window is minimized or disabled, return at once */
496 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
498 retvalue
= HTCAPTION
;
501 if (wndPtr
->dwStyle
& WS_DISABLED
)
507 /* If point is not in client area, ignore the children */
508 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
509 (xy
.x
>= wndPtr
->rectClient
.right
) ||
510 (xy
.y
< wndPtr
->rectClient
.top
) ||
511 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
513 xy
.x
-= wndPtr
->rectClient
.left
;
514 xy
.y
-= wndPtr
->rectClient
.top
;
515 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
519 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
524 /* If nothing found, try the scope window */
525 if (!*ppWnd
) *ppWnd
= wndScope
;
527 /* Send the WM_NCHITTEST message (only if to the same task) */
528 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
530 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
531 0, MAKELONG( pt
.x
, pt
.y
) );
532 if (hittest
!= HTTRANSPARENT
)
534 retvalue
= hittest
; /* Found the window */
544 /* If no children found in last search, make point relative to parent */
547 xy
.x
+= (*ppWnd
)->rectClient
.left
;
548 xy
.y
+= (*ppWnd
)->rectClient
.top
;
551 /* Restart the search from the next sibling */
552 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
553 *ppWnd
= (*ppWnd
)->parent
;
557 WIN_ReleaseWndPtr(wndPtr
);
562 /*******************************************************************
563 * WindowFromPoint (USER.30)
565 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
568 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
569 WIN_ReleaseDesktop();
570 return pWnd
->hwndSelf
;
574 /*******************************************************************
575 * WindowFromPoint (USER32.@)
577 HWND WINAPI
WindowFromPoint( POINT pt
)
581 CONV_POINT32TO16( &pt
, &pt16
);
582 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
583 WIN_ReleaseDesktop();
584 return (HWND
)pWnd
->hwndSelf
;
588 /*******************************************************************
589 * ChildWindowFromPoint (USER.191)
591 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
594 CONV_POINT16TO32( &pt
, &pt32
);
595 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
599 /*******************************************************************
600 * ChildWindowFromPoint (USER32.@)
602 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
604 /* pt is in the client coordinates */
606 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
612 /* get client rect fast */
613 rect
.top
= rect
.left
= 0;
614 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
615 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
617 if (!PtInRect( &rect
, pt
))
622 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
625 if (PtInRect( &wnd
->rectWindow
, pt
))
627 retvalue
= wnd
->hwndSelf
;
630 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
632 retvalue
= hwndParent
;
634 WIN_ReleaseWndPtr(wnd
);
638 /*******************************************************************
639 * ChildWindowFromPointEx (USER.399)
641 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
644 CONV_POINT16TO32( &pt
, &pt32
);
645 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
649 /*******************************************************************
650 * ChildWindowFromPointEx (USER32.@)
652 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
655 /* pt is in the client coordinates */
657 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
663 /* get client rect fast */
664 rect
.top
= rect
.left
= 0;
665 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
666 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
668 if (!PtInRect( &rect
, pt
))
673 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
677 if (PtInRect( &wnd
->rectWindow
, pt
)) {
678 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
679 !(wnd
->dwStyle
& WS_VISIBLE
) );
680 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
681 (wnd
->dwStyle
& WS_DISABLED
) );
682 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
683 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
686 retvalue
= wnd
->hwndSelf
;
691 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
693 retvalue
= hwndParent
;
695 WIN_ReleaseWndPtr(wnd
);
700 /*******************************************************************
701 * WINPOS_GetWinOffset
703 * Calculate the offset between the origin of the two windows. Used
704 * to implement MapWindowPoints.
706 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
711 offset
->x
= offset
->y
= 0;
712 if (hwndFrom
== hwndTo
) return;
714 /* Translate source window origin to screen coords */
717 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
719 ERR("bad hwndFrom = %04x\n",hwndFrom
);
722 while (wndPtr
->parent
)
724 offset
->x
+= wndPtr
->rectClient
.left
;
725 offset
->y
+= wndPtr
->rectClient
.top
;
726 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
728 WIN_ReleaseWndPtr(wndPtr
);
731 /* Translate origin to destination window coords */
734 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
736 ERR("bad hwndTo = %04x\n", hwndTo
);
739 while (wndPtr
->parent
)
741 offset
->x
-= wndPtr
->rectClient
.left
;
742 offset
->y
-= wndPtr
->rectClient
.top
;
743 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
745 WIN_ReleaseWndPtr(wndPtr
);
750 /*******************************************************************
751 * MapWindowPoints (USER.258)
753 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
754 LPPOINT16 lppt
, UINT16 count
)
758 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
768 /*******************************************************************
769 * MapWindowPoints (USER32.@)
771 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
772 LPPOINT lppt
, UINT count
)
776 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
783 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
787 /***********************************************************************
790 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
792 return IsIconic(hWnd
);
796 /***********************************************************************
797 * IsIconic (USER32.@)
799 BOOL WINAPI
IsIconic(HWND hWnd
)
802 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
803 if (wndPtr
== NULL
) return FALSE
;
804 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
805 WIN_ReleaseWndPtr(wndPtr
);
810 /***********************************************************************
811 * IsZoomed (USER.272)
813 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
815 return IsZoomed(hWnd
);
819 /***********************************************************************
820 * IsZoomed (USER32.@)
822 BOOL WINAPI
IsZoomed(HWND hWnd
)
825 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
826 if (wndPtr
== NULL
) return FALSE
;
827 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
828 WIN_ReleaseWndPtr(wndPtr
);
833 /*******************************************************************
834 * GetActiveWindow (USER.60)
836 HWND16 WINAPI
GetActiveWindow16(void)
838 return (HWND16
)GetActiveWindow();
841 /*******************************************************************
842 * GetActiveWindow (USER32.@)
844 HWND WINAPI
GetActiveWindow(void)
846 MESSAGEQUEUE
*pCurMsgQ
= 0;
849 /* Get the messageQ for the current thread */
850 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
852 WARN("\tCurrent message queue not found. Exiting!\n" );
856 /* Return the current active window from the perQ data of the current message Q */
857 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
859 QUEUE_Unlock( pCurMsgQ
);
864 /*******************************************************************
867 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
869 if( pWnd
&& ( (pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
870 == WS_VISIBLE
) ) return TRUE
;
875 /*******************************************************************
876 * SetActiveWindow (USER.59)
878 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
880 return SetActiveWindow(hwnd
);
884 /*******************************************************************
885 * SetActiveWindow (USER32.@)
887 HWND WINAPI
SetActiveWindow( HWND hwnd
)
890 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
891 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
893 if (!wndPtr
|| (wndPtr
->dwStyle
& (WS_DISABLED
| WS_CHILD
)))
899 /* Get the messageQ for the current thread */
900 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
902 WARN("\tCurrent message queue not found. Exiting!\n" );
906 /* Retrieve the message queue associated with this window */
907 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
910 WARN("\tWindow message queue not found. Exiting!\n" );
914 /* Make sure that the window is associated with the calling threads
915 * message queue. It must share the same perQ data.
918 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
921 /* Save current active window */
922 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
924 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
927 /* Unlock the queues before returning */
929 QUEUE_Unlock( pMsgQ
);
931 QUEUE_Unlock( pCurMsgQ
);
934 WIN_ReleaseWndPtr(wndPtr
);
939 /*******************************************************************
940 * GetForegroundWindow (USER.608)
942 HWND16 WINAPI
GetForegroundWindow16(void)
944 return (HWND16
)GetForegroundWindow();
948 /*******************************************************************
949 * SetForegroundWindow (USER.609)
951 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
953 return SetForegroundWindow( hwnd
);
957 /*******************************************************************
958 * GetForegroundWindow (USER32.@)
960 HWND WINAPI
GetForegroundWindow(void)
964 /* Get the foreground window (active window of hActiveQueue) */
967 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
969 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
971 QUEUE_Unlock( pActiveQueue
);
977 /*******************************************************************
978 * SetForegroundWindow (USER32.@)
980 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
982 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
986 /*******************************************************************
987 * AllowSetForegroundWindow (USER32.@)
989 BOOL WINAPI
AllowSetForegroundWindow( DWORD procid
)
991 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
992 * implemented, then fix this function. */
997 /*******************************************************************
998 * LockSetForegroundWindow (USER32.@)
1000 BOOL WINAPI
LockSetForegroundWindow( UINT lockcode
)
1002 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
1003 * implemented, then fix this function. */
1008 /*******************************************************************
1009 * GetShellWindow (USER.600)
1011 HWND16 WINAPI
GetShellWindow16(void)
1013 return GetShellWindow();
1016 /*******************************************************************
1017 * SetShellWindow (USER32.@)
1019 HWND WINAPI
SetShellWindow(HWND hwndshell
)
1020 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
1022 hGlobalShellWindow
= hwndshell
;
1023 return hGlobalShellWindow
;
1027 /*******************************************************************
1028 * GetShellWindow (USER32.@)
1030 HWND WINAPI
GetShellWindow(void)
1031 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
1033 return hGlobalShellWindow
;
1037 /***********************************************************************
1038 * BringWindowToTop (USER.45)
1040 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
1042 return BringWindowToTop(hwnd
);
1046 /***********************************************************************
1047 * BringWindowToTop (USER32.@)
1049 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
1051 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
1055 /***********************************************************************
1056 * MoveWindow (USER.56)
1058 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
1061 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
1065 /***********************************************************************
1066 * MoveWindow (USER32.@)
1068 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
1071 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
1072 if (!repaint
) flags
|= SWP_NOREDRAW
;
1073 TRACE("%04x %d,%d %dx%d %d\n",
1074 hwnd
, x
, y
, cx
, cy
, repaint
);
1075 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1078 /***********************************************************************
1079 * WINPOS_InitInternalPos
1081 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1082 LPRECT restoreRect
)
1084 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1088 /* this happens when the window is minimized/maximized
1089 * for the first time (rectWindow is not adjusted yet) */
1091 lpPos
= HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS
) );
1092 if( !lpPos
) return NULL
;
1094 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1095 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1096 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1097 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1100 if( wnd
->dwStyle
& WS_MINIMIZE
)
1101 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1102 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1103 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1104 else if( restoreRect
)
1105 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1110 /***********************************************************************
1111 * WINPOS_RedrawIconTitle
1113 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1115 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1118 if( lpPos
->hwndIconTitle
)
1120 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1121 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1128 /***********************************************************************
1129 * WINPOS_ShowIconTitle
1131 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1133 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1135 if( lpPos
&& !(pWnd
->dwExStyle
& WS_EX_MANAGED
))
1137 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1139 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1142 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1145 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1147 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1149 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1150 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1151 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1153 WIN_ReleaseWndPtr(pWnd
);
1156 else ShowWindow( hWnd
, SW_HIDE
);
1161 /*******************************************************************
1162 * WINPOS_GetMinMaxInfo
1164 * Get the minimized and maximized information for a window.
1166 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1167 POINT
*minTrack
, POINT
*maxTrack
)
1169 LPINTERNALPOS lpPos
;
1173 /* Compute default values */
1175 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1176 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1177 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1178 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1179 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1180 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1182 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) xinc
= yinc
= 0;
1183 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1185 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1186 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1191 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1193 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1194 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1196 if (wndPtr
->dwStyle
& WS_BORDER
)
1198 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1199 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1202 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1203 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1205 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1206 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1207 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1210 MinMax
.ptMaxPosition
.x
= -xinc
;
1211 MinMax
.ptMaxPosition
.y
= -yinc
;
1214 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1216 /* Some sanity checks */
1218 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1219 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1220 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1221 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1222 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1223 MinMax
.ptMaxTrackSize
.x
= max( MinMax
.ptMaxTrackSize
.x
,
1224 MinMax
.ptMinTrackSize
.x
);
1225 MinMax
.ptMaxTrackSize
.y
= max( MinMax
.ptMaxTrackSize
.y
,
1226 MinMax
.ptMinTrackSize
.y
);
1228 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1229 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1230 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1231 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1234 /***********************************************************************
1235 * WINPOS_MinMaximize
1237 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1238 * This function assumes that 'cmd' is different from the current window
1241 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1245 LPINTERNALPOS lpPos
;
1247 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1249 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1250 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1252 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1254 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1256 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1257 return (SWP_NOSIZE
| SWP_NOMOVE
);
1258 swpFlags
|= SWP_NOCOPYBITS
;
1263 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1265 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1266 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1269 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1270 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1272 if( wndPtr
->flags
& WIN_NATIVE
)
1273 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1274 swpFlags
|= MINMAX_NOSWP
;
1276 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1278 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1279 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1280 swpFlags
|= SWP_NOCOPYBITS
;
1284 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1285 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1286 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1288 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1290 if( wndPtr
->flags
& WIN_NATIVE
)
1291 wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
);
1293 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1294 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1296 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1298 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1303 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1305 if( wndPtr
->flags
& WIN_NATIVE
)
1306 wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
);
1308 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1309 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1311 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1313 /* Restore to maximized position */
1314 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1315 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1316 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1317 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1318 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1323 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1324 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1326 /* Restore to normal position */
1328 *lpRect
= lpPos
->rectNormal
;
1329 lpRect
->right
-= lpRect
->left
;
1330 lpRect
->bottom
-= lpRect
->top
;
1334 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1338 /***********************************************************************
1339 * ShowWindowAsync (USER32.@)
1341 * doesn't wait; returns immediately.
1342 * used by threads to toggle windows in other (possibly hanging) threads
1344 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1346 /* FIXME: does ShowWindow() return immediately ? */
1347 return ShowWindow(hwnd
, cmd
);
1351 /***********************************************************************
1352 * ShowWindow (USER.42)
1354 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1356 return ShowWindow(hwnd
,cmd
);
1360 /***********************************************************************
1361 * ShowWindow (USER32.@)
1363 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1365 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1366 BOOL wasVisible
, showFlag
;
1367 RECT16 newPos
= {0, 0, 0, 0};
1370 if (!wndPtr
) return FALSE
;
1372 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1374 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1379 if (!wasVisible
) goto END
;;
1380 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1381 SWP_NOACTIVATE
| SWP_NOZORDER
;
1384 case SW_SHOWMINNOACTIVE
:
1385 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1387 case SW_SHOWMINIMIZED
:
1388 swp
|= SWP_SHOWWINDOW
;
1391 swp
|= SWP_FRAMECHANGED
;
1392 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1393 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1394 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1397 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1398 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1399 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1400 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1401 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1405 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1408 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1411 * ShowWindow has a little peculiar behavior that if the
1412 * window is already the topmost window, it will not
1415 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1416 swp
|= SWP_NOACTIVATE
;
1420 case SW_SHOWNOACTIVATE
:
1421 swp
|= SWP_NOZORDER
;
1422 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1424 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1425 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1427 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1429 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1430 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1431 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1435 showFlag
= (cmd
!= SW_HIDE
);
1436 if (showFlag
!= wasVisible
)
1438 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1439 if (!IsWindow( hwnd
)) goto END
;
1442 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1443 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1444 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1446 /* Don't call SetWindowPos() on invisible child windows */
1447 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1448 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1452 /* We can't activate a child window */
1453 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1454 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1455 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1456 if (!(swp
& MINMAX_NOSWP
))
1458 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1459 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1462 /* FIXME: This will cause the window to be activated irrespective
1463 * of whether it is owned by the same thread. Has to be done
1467 if (hwnd
== GetActiveWindow())
1468 WINPOS_ActivateOtherWindow(wndPtr
);
1470 /* Revert focus to parent */
1471 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1472 SetFocus( GetParent(hwnd
) );
1475 if (!IsWindow( hwnd
)) goto END
;
1476 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1479 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1481 /* should happen only in CreateWindowEx() */
1482 int wParam
= SIZE_RESTORED
;
1484 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1485 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1486 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1487 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1488 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1489 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1490 SendMessageA( hwnd
, WM_MOVE
, 0,
1491 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1495 WIN_ReleaseWndPtr(wndPtr
);
1500 /***********************************************************************
1501 * GetInternalWindowPos (USER.460)
1503 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1506 WINDOWPLACEMENT16 wndpl
;
1507 if (GetWindowPlacement16( hwnd
, &wndpl
))
1509 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1510 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1511 return wndpl
.showCmd
;
1517 /***********************************************************************
1518 * GetInternalWindowPos (USER32.@)
1520 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1523 WINDOWPLACEMENT wndpl
;
1524 if (GetWindowPlacement( hwnd
, &wndpl
))
1526 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1527 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1528 return wndpl
.showCmd
;
1533 /***********************************************************************
1534 * GetWindowPlacement (USER.370)
1536 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1538 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1539 LPINTERNALPOS lpPos
;
1541 if(!pWnd
) return FALSE
;
1543 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1544 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1545 wndpl
->length
= sizeof(*wndpl
);
1546 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1547 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1549 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1550 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1551 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1552 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1555 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1556 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1557 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1559 WIN_ReleaseWndPtr(pWnd
);
1564 /***********************************************************************
1565 * GetWindowPlacement (USER32.@)
1568 * Fails if wndpl->length of Win95 (!) apps is invalid.
1570 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1574 WINDOWPLACEMENT16 wpl
;
1575 wpl
.length
= sizeof(wpl
);
1576 if( GetWindowPlacement16( hwnd
, &wpl
) )
1578 pwpl32
->length
= sizeof(*pwpl32
);
1579 pwpl32
->flags
= wpl
.flags
;
1580 pwpl32
->showCmd
= wpl
.showCmd
;
1581 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1582 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1583 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1591 /***********************************************************************
1592 * WINPOS_SetPlacement
1594 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1597 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1600 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1601 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1603 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1604 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1605 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1607 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1609 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1610 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1611 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1612 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1614 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1616 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1617 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1618 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1620 else if( flags
& PLACE_RECT
)
1621 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1622 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1623 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1624 SWP_NOZORDER
| SWP_NOACTIVATE
);
1626 ShowWindow( hwnd
, wndpl
->showCmd
);
1627 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1629 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1631 /* SDK: ...valid only the next time... */
1632 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1634 WIN_ReleaseWndPtr(pWnd
);
1641 /***********************************************************************
1642 * SetWindowPlacement (USER.371)
1644 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1646 return WINPOS_SetPlacement( hwnd
, wndpl
,
1647 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1650 /***********************************************************************
1651 * SetWindowPlacement (USER32.@)
1654 * Fails if wndpl->length of Win95 (!) apps is invalid.
1656 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1660 WINDOWPLACEMENT16 wpl
;
1662 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1663 wpl
.flags
= pwpl32
->flags
;
1664 wpl
.showCmd
= pwpl32
->showCmd
;
1665 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1666 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1667 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1668 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1669 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1670 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1671 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1672 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1674 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1680 /***********************************************************************
1681 * SetInternalWindowPos (USER.461)
1683 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1684 LPRECT16 rect
, LPPOINT16 pt
)
1686 if( IsWindow16(hwnd
) )
1688 WINDOWPLACEMENT16 wndpl
;
1691 wndpl
.length
= sizeof(wndpl
);
1692 wndpl
.showCmd
= showCmd
;
1693 wndpl
.flags
= flags
= 0;
1698 wndpl
.flags
|= WPF_SETMINPOSITION
;
1699 wndpl
.ptMinPosition
= *pt
;
1703 flags
|= PLACE_RECT
;
1704 wndpl
.rcNormalPosition
= *rect
;
1706 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1711 /***********************************************************************
1712 * SetInternalWindowPos (USER32.@)
1714 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1715 LPRECT rect
, LPPOINT pt
)
1717 if( IsWindow(hwnd
) )
1719 WINDOWPLACEMENT16 wndpl
;
1722 wndpl
.length
= sizeof(wndpl
);
1723 wndpl
.showCmd
= showCmd
;
1724 wndpl
.flags
= flags
= 0;
1729 wndpl
.flags
|= WPF_SETMINPOSITION
;
1730 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1734 flags
|= PLACE_RECT
;
1735 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1737 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1741 /*******************************************************************
1742 * WINPOS_SetActiveWindow
1744 * SetActiveWindow() back-end. This is the only function that
1745 * can assign active status to a window. It must be called only
1746 * for the top level windows.
1748 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1750 CBTACTIVATESTRUCT16
* cbtStruct
;
1751 WND
* wndPtr
=0, *wndTemp
;
1752 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1753 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1755 HWND hwndActive
= 0;
1758 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1760 /* Get current active window from the active queue */
1763 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1764 if ( pOldActiveQueue
)
1765 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1768 /* paranoid checks */
1769 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1772 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1775 wndPtr
= WIN_FindWndPtr(hWnd
);
1776 hOldActiveQueue
= hActiveQueue
;
1778 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1780 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1781 WIN_ReleaseWndPtr(wndTemp
);
1784 TRACE("no current active window.\n");
1786 /* call CBT hook chain */
1787 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1789 cbtStruct
->fMouse
= fMouse
;
1790 cbtStruct
->hWndActive
= hwndActive
;
1791 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1792 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1793 SEGPTR_FREE(cbtStruct
);
1794 if (bRet
) goto CLEANUP_END
;
1797 /* set prev active wnd to current active wnd and send notification */
1798 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1800 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1802 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1804 if (GetSysModalWindow16() != hWnd
)
1806 /* disregard refusal if hWnd is sysmodal */
1809 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1810 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1813 /* check if something happened during message processing
1814 * (global active queue may have changed)
1816 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1817 if(!pTempActiveQueue
)
1820 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1821 QUEUE_Unlock( pTempActiveQueue
);
1822 if( hwndPrevActive
!= hwndActive
)
1826 /* Set new active window in the message queue */
1830 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1831 if ( pNewActiveQueue
)
1832 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1834 else /* have to do this or MDI frame activation goes to hell */
1835 if( pOldActiveQueue
)
1836 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1838 /* send palette messages */
1839 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1840 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1842 /* if prev wnd is minimized redraw icon title */
1843 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1845 /* managed windows will get ConfigureNotify event */
1846 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->dwExStyle
& WS_EX_MANAGED
))
1848 /* check Z-order and bring hWnd to the top */
1849 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1851 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1853 WIN_ReleaseDesktop();
1854 WIN_ReleaseWndPtr(wndTemp
);
1856 if( wndTemp
!= wndPtr
)
1857 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1858 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1859 if (!IsWindow(hWnd
))
1863 /* Get a handle to the new active queue */
1864 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1866 /* send WM_ACTIVATEAPP if necessary */
1867 if (hOldActiveQueue
!= hNewActiveQueue
)
1869 WND
**list
, **ppWnd
;
1870 WND
*pDesktop
= WIN_GetDesktop();
1872 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1874 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1876 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1878 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1879 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1880 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1882 WIN_ReleaseWinArray(list
);
1885 hActiveQueue
= hNewActiveQueue
;
1887 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1889 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1891 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1893 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1894 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1895 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1897 WIN_ReleaseWinArray(list
);
1899 WIN_ReleaseDesktop();
1901 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1906 /* walk up to the first unowned window */
1907 wndTemp
= WIN_LockWndPtr(wndPtr
);
1908 while (wndTemp
->owner
)
1910 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1912 /* and set last active owned popup */
1913 wndTemp
->hwndLastActive
= hWnd
;
1915 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1916 WIN_ReleaseWndPtr(wndTemp
);
1917 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1918 SendMessageA( hWnd
, WM_ACTIVATE
,
1919 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1920 (LPARAM
)hwndPrevActive
);
1921 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1924 /* change focus if possible */
1927 if ( pNewActiveQueue
)
1929 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1931 if ( hOldFocus
&& WIN_GetTopParent( hOldFocus
) != hwndActive
)
1932 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1933 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1937 if ( pOldActiveQueue
&&
1938 ( !pNewActiveQueue
||
1939 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1941 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1943 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1947 if( !hwndPrevActive
&& wndPtr
)
1948 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1950 /* if active wnd is minimized redraw icon title */
1951 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1953 bRet
= (hWnd
== hwndActive
); /* Success? */
1955 CLEANUP
: /* Unlock the message queues before returning */
1957 if ( pNewActiveQueue
)
1958 QUEUE_Unlock( pNewActiveQueue
);
1962 if ( pOldActiveQueue
)
1963 QUEUE_Unlock( pOldActiveQueue
);
1965 WIN_ReleaseWndPtr(wndPtr
);
1969 /*******************************************************************
1970 * WINPOS_ActivateOtherWindow
1972 * Activates window other than pWnd.
1974 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1978 HWND hwndActive
= 0;
1980 /* Get current active window from the active queue */
1983 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1986 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1987 QUEUE_Unlock( pActiveQueue
);
1991 if( pWnd
->hwndSelf
== hwndPrevActive
)
1994 if( hwndActive
!= pWnd
->hwndSelf
&&
1995 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1998 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1999 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
2001 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
2003 WIN_ReleaseWndPtr(pWndTo
);
2004 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
2006 while( !WINPOS_CanActivate(pWndTo
) )
2008 /* by now owned windows should've been taken care of */
2009 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
2010 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
2011 if( !pWndTo
) break;
2013 WIN_ReleaseWndPtr(pWndPtr
);
2016 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
2018 /* switch desktop queue to current active */
2021 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
2022 WIN_ReleaseWndPtr(pWndTo
);
2023 WIN_ReleaseDesktop();
2030 /*******************************************************************
2031 * WINPOS_ChangeActiveWindow
2034 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
2036 WND
*wndPtr
, *wndTemp
;
2038 HWND hwndActive
= 0;
2040 /* Get current active window from the active queue */
2043 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2046 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2047 QUEUE_Unlock( pActiveQueue
);
2052 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
2054 wndPtr
= WIN_FindWndPtr(hWnd
);
2055 if( !wndPtr
) return FALSE
;
2057 /* child windows get WM_CHILDACTIVATE message */
2058 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2060 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
2064 if( hWnd
== hwndActive
)
2070 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
2076 /* switch desktop queue to current active */
2077 wndTemp
= WIN_GetDesktop();
2078 if( wndPtr
->parent
== wndTemp
)
2079 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
2080 WIN_ReleaseDesktop();
2084 WIN_ReleaseWndPtr(wndPtr
);
2089 /***********************************************************************
2090 * WINPOS_SendNCCalcSize
2092 * Send a WM_NCCALCSIZE message to a window.
2093 * All parameters are read-only except newClientRect.
2094 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2095 * when calcValidRect is TRUE.
2097 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2098 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2099 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2100 RECT
*newClientRect
)
2102 NCCALCSIZE_PARAMS params
;
2103 WINDOWPOS winposCopy
;
2106 params
.rgrc
[0] = *newWindowRect
;
2109 winposCopy
= *winpos
;
2110 params
.rgrc
[1] = *oldWindowRect
;
2111 params
.rgrc
[2] = *oldClientRect
;
2112 params
.lppos
= &winposCopy
;
2114 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2116 TRACE("%d,%d-%d,%d\n",
2117 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2118 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2120 /* If the application send back garbage, ignore it */
2121 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2122 *newClientRect
= params
.rgrc
[0];
2128 /***********************************************************************
2129 * WINPOS_HandleWindowPosChanging16
2131 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2133 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2135 POINT maxSize
, minTrack
;
2136 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2137 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2138 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2140 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2141 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2142 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2143 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2145 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2146 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2153 /***********************************************************************
2154 * WINPOS_HandleWindowPosChanging
2156 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2158 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2160 POINT maxSize
, minTrack
;
2161 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2162 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2163 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2165 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2166 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
2167 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
2168 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2170 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2171 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2177 /***********************************************************************
2180 * fix Z order taking into account owned popups -
2181 * basically we need to maintain them above the window that owns them
2183 * FIXME: hide/show owned popups when owner visibility changes.
2185 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2187 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2189 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2191 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2193 /* make sure this popup stays above the owner */
2195 HWND hwndLocalPrev
= HWND_TOP
;
2197 if( hwndInsertAfter
!= HWND_TOP
)
2199 while( w
&& w
!= wndPtr
->owner
)
2201 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2202 if( hwndLocalPrev
== hwndInsertAfter
) break;
2203 WIN_UpdateWndPtr(&w
,w
->next
);
2205 hwndInsertAfter
= hwndLocalPrev
;
2208 else if( wndPtr
->dwStyle
& WS_CHILD
)
2211 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2215 if( w
== wndPtr
) break;
2217 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2219 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2220 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2221 hwndInsertAfter
= w
->hwndSelf
;
2223 WIN_UpdateWndPtr(&w
, w
->next
);
2227 WIN_ReleaseWndPtr(w
);
2228 return hwndInsertAfter
;
2231 /***********************************************************************
2234 * Make window look nice without excessive repainting
2236 * visible and update regions are in window coordinates
2237 * client and window rectangles are in parent client coordinates
2239 * Returns: uFlags and a dirty region in *pVisRgn.
2241 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2242 LPRECT lpOldWndRect
,
2243 LPRECT lpOldClientRect
, UINT uFlags
)
2246 HRGN newVisRgn
, dirtyRgn
;
2247 INT my
= COMPLEXREGION
;
2250 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2251 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2252 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2253 lpOldWndRect
->left
, lpOldWndRect
->top
,
2254 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2255 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2256 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2257 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2258 lpOldClientRect
->left
, lpOldClientRect
->top
,
2259 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2261 if( Wnd
->hrgnUpdate
== 1 )
2262 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2264 dflags
= DCX_WINDOW
;
2265 if(Wnd
->dwStyle
& WS_CLIPSIBLINGS
)
2266 dflags
|= DCX_CLIPSIBLINGS
;
2267 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, dflags
, 0, 0);
2269 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2271 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2272 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2274 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2278 TRACE("\twon't copy anything!\n");
2280 /* set dirtyRgn to the sum of old and new visible regions
2281 * in parent client coordinates */
2283 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2284 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2286 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2288 else /* copy valid bits to a new location */
2290 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2291 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2293 /* subtract already invalid region inside Wnd from the dst region */
2295 if( Wnd
->hrgnUpdate
)
2296 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2299 /* check if entire window can be copied */
2301 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2302 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2303 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2304 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2306 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2307 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2308 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2309 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2311 if( (ocw
!= ncw
) || (och
!= nch
) ||
2312 ( ow
!= nw
) || ( oh
!= nh
) ||
2313 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2314 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2315 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2316 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2318 if(uFlags
& SWP_EX_PAINTSELF
)
2320 /* movement relative to the window itself */
2321 dx
= (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
) -
2322 (lpOldClientRect
->left
- lpOldWndRect
->left
) ;
2323 dy
= (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
) -
2324 (lpOldClientRect
->top
- lpOldWndRect
->top
) ;
2328 /* movement relative to the parent's client area */
2329 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2330 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2333 /* restrict valid bits to the common client rect */
2335 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2336 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2337 r
.right
= r
.left
+ min( ocw
, ncw
);
2338 r
.bottom
= r
.top
+ min( och
, nch
);
2340 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2341 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2342 GetRgnBox( hrgnValid
, &r
);
2343 if( IsRectEmpty( &r
) )
2345 r
= *lpOldClientRect
;
2349 if(uFlags
& SWP_EX_PAINTSELF
) {
2351 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2352 * relative to itself, only the client area can change.
2353 * if the client rect didn't change, there's nothing to do.
2360 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2361 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2362 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2367 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2369 /* Move remaining regions to parent coordinates */
2370 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2371 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2374 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2376 TRACE("\tcomputing dirty region!\n");
2378 /* Compute combined dirty region (old + new - valid) */
2379 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2380 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2382 /* Blt valid bits, r is the rect to copy */
2389 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2390 from copying clipped areas */
2392 if( uFlags
& SWP_EX_PAINTSELF
)
2394 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2395 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2396 rClip
.right
= nw
; rClip
.bottom
= nh
;
2400 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2401 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2402 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2403 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2405 rClip
.left
= rClip
.top
= 0;
2407 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2408 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2410 if( IntersectRect( &r
, &r
, &rClip
) )
2412 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, hDC
, dx
, dy
, &r
, TRUE
);
2414 /* When you copy the bits without repainting, parent doesn't
2415 get validated appropriately. Therefore, we have to validate
2416 the parent with the windows' updated region when the
2417 parent's update region is not empty. */
2419 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2421 OffsetRect(&r
, dx
, dy
);
2422 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2425 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2426 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2430 /* *pVisRgn now points to the invalidated region */
2432 DeleteObject(newVisRgn
);
2433 DeleteObject(dirtyRgn
);
2437 /***********************************************************************
2438 * SWP_DoSimpleFrameChanged
2440 * NOTE: old and new client rect origins are identical, only
2441 * extents may have changed. Window extents are the same.
2443 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2449 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2451 /* Client rect changed its position/size, most likely a scrollar
2452 * was added/removed.
2454 * FIXME: WVR alignment flags
2457 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2461 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2462 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2463 if(!(uFlags
& SWP_EX_NOCOPY
))
2464 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2472 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2475 hrgn
= CreateRectRgnIndirect( &rect
);
2477 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2478 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2479 if(!(uFlags
& SWP_EX_NOCOPY
))
2480 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2484 REGION_UnionRectWithRgn( hrgn
, &rect
);
2487 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2489 rect
= wndPtr
->rectWindow
;
2490 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2491 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2499 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2500 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2504 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2508 DeleteObject( hrgn
);
2511 /***********************************************************************
2512 * SWP_DoWinPosChanging
2514 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2515 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2517 /* Send WM_WINDOWPOSCHANGING message */
2519 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2520 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2522 /* Calculate new position and size */
2524 *pNewWindowRect
= wndPtr
->rectWindow
;
2525 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2526 : wndPtr
->rectClient
;
2528 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2530 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2531 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2533 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2535 pNewWindowRect
->left
= pWinpos
->x
;
2536 pNewWindowRect
->top
= pWinpos
->y
;
2537 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2538 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2540 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2541 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2544 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2548 /***********************************************************************
2551 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2552 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2556 /* Send WM_NCCALCSIZE message to get new client area */
2557 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2559 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2560 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2561 pWinpos
, pNewClientRect
);
2563 /* FIXME: WVR_ALIGNxxx */
2565 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2566 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2567 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2569 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2570 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2571 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2572 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2573 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2576 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2577 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2578 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2582 /***********************************************************************
2583 * SetWindowPos (USER.232)
2585 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2586 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2588 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2591 /***********************************************************************
2592 * SetWindowPos (USER32.@)
2594 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2595 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2598 WND
* wndPtr
,*wndTemp
;
2599 RECT newWindowRect
, newClientRect
;
2600 RECT oldWindowRect
, oldClientRect
;
2602 UINT wvrFlags
= 0, uFlags
= 0;
2603 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2604 HWND hwndActive
= 0;
2606 /* Get current active window from the active queue */
2609 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2612 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2613 QUEUE_Unlock( pActiveQueue
);
2617 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2618 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2620 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2621 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2624 /* ------------------------------------------------------------------------ CHECKS */
2626 /* Check window handle */
2628 if (hwnd
== GetDesktopWindow()) return FALSE
;
2629 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2631 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2632 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2634 /* Fix redundant flags */
2636 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2637 flags
&= ~SWP_SHOWWINDOW
;
2640 if (!(flags
& SWP_SHOWWINDOW
))
2641 flags
|= SWP_NOREDRAW
;
2642 flags
&= ~SWP_HIDEWINDOW
;
2645 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2647 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2648 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2649 flags
|= SWP_NOSIZE
; /* Already the right size */
2651 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2652 flags
|= SWP_NOMOVE
; /* Already the right position */
2654 if (hwnd
== hwndActive
)
2655 flags
|= SWP_NOACTIVATE
; /* Already active */
2656 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2658 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2660 flags
&= ~SWP_NOZORDER
;
2661 hwndInsertAfter
= HWND_TOP
;
2666 /* Check hwndInsertAfter */
2668 /* FIXME: TOPMOST not supported yet */
2669 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2670 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2672 /* hwndInsertAfter must be a sibling of the window */
2673 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2675 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2678 if( wnd
->parent
!= wndPtr
->parent
)
2681 WIN_ReleaseWndPtr(wnd
);
2684 /* don't need to change the Zorder of hwnd if it's already inserted
2685 * after hwndInsertAfter or when inserting hwnd after itself.
2687 if(( wnd
->next
== wndPtr
) || (hwnd
== hwndInsertAfter
)) flags
|= SWP_NOZORDER
;
2689 WIN_ReleaseWndPtr(wnd
);
2692 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2694 /* Fill the WINDOWPOS structure */
2697 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2702 winpos
.flags
= flags
;
2704 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2706 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2708 if( wndPtr
->parent
== WIN_GetDesktop() )
2709 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2710 hwndInsertAfter
, winpos
.flags
);
2711 WIN_ReleaseDesktop();
2714 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2716 if( hwndInsertAfter
== HWND_TOP
)
2717 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2719 if( hwndInsertAfter
== HWND_BOTTOM
)
2720 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2722 if( !(winpos
.flags
& SWP_NOZORDER
) )
2723 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2724 winpos
.flags
|= SWP_NOZORDER
;
2726 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2727 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2728 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2730 /* get a previous visible region for SWP_CopyValidBits() */
2731 DWORD dflags
= DCX_WINDOW
;
2733 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2734 dflags
|= DCX_CLIPSIBLINGS
;
2736 visRgn
= DCE_GetVisRgn(hwnd
, dflags
, 0, 0);
2740 /* Common operations */
2742 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2744 if(!(winpos
.flags
& SWP_NOZORDER
) && winpos
.hwnd
!= hwndInsertAfter
)
2746 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2747 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2750 /* Reset active DCEs */
2752 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2753 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2754 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2758 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2759 DCE_InvalidateDCE(wndPtr
, &rect
);
2762 oldWindowRect
= wndPtr
->rectWindow
;
2763 oldClientRect
= wndPtr
->rectClient
;
2765 /* Find out if we have to redraw the whole client rect */
2767 if( oldClientRect
.bottom
- oldClientRect
.top
==
2768 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2770 if( oldClientRect
.right
- oldClientRect
.left
==
2771 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2773 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2774 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2776 uFlags
|= SWP_EX_NOCOPY
;
2779 * Use this later in CopyValidBits()
2782 uFlags |= SWP_EX_NONCLIENT;
2785 /* FIXME: actually do something with WVR_VALIDRECTS */
2787 wndPtr
->rectWindow
= newWindowRect
;
2788 wndPtr
->rectClient
= newClientRect
;
2790 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2792 BOOL bCallDriver
= TRUE
;
2793 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2795 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2797 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2799 /* This is the only place where we need to force repainting of the contents
2800 of windows created by the host window system, all other cases go through the
2801 expose event handling */
2803 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2805 cx
= newWindowRect
.right
- newWindowRect
.left
;
2806 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2808 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2809 winpos
.hwndInsertAfter
= tempInsertAfter
;
2810 bCallDriver
= FALSE
;
2812 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2813 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2816 /* client area moved but window extents remained the same, copy valid bits */
2818 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2819 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2820 uFlags
| SWP_EX_PAINTSELF
);
2827 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2829 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2830 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2831 !(uFlags
& SWP_EX_NOCOPY
) )
2833 /* The origin of the client rect didn't move so we can try to repaint
2834 * only the nonclient area by setting bit gravity hint for the host window system.
2837 if( !(wndPtr
->dwExStyle
& WS_EX_MANAGED
) )
2839 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2840 newWindowRect
.bottom
- newWindowRect
.top
);
2841 RECT rcn
= newClientRect
;
2842 RECT rco
= oldClientRect
;
2844 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2845 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2846 IntersectRect( &rcn
, &rcn
, &rco
);
2847 visRgn
= CreateRectRgnIndirect( &rcn
);
2848 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2849 DeleteObject( hrgn
);
2850 uFlags
= SWP_EX_PAINTSELF
;
2852 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2856 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2857 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2858 winpos
.hwndInsertAfter
= tempInsertAfter
;
2861 if( winpos
.flags
& SWP_SHOWWINDOW
)
2865 wndPtr
->dwStyle
|= WS_VISIBLE
;
2867 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) resync
= TRUE
;
2869 /* focus was set to unmapped window, reset host focus
2870 * since the window is now visible */
2872 focus
= curr
= GetFocus();
2877 WND
*pFocus
= WIN_FindWndPtr( focus
);
2879 pFocus
->pDriver
->pSetFocus(pFocus
);
2880 WIN_ReleaseWndPtr(pFocus
);
2883 curr
= GetParent(curr
);
2887 else /* -------------------------------------------- emulated window */
2889 if( winpos
.flags
& SWP_SHOWWINDOW
)
2891 wndPtr
->dwStyle
|= WS_VISIBLE
;
2892 uFlags
|= SWP_EX_PAINTSELF
;
2893 visRgn
= 1; /* redraw the whole window */
2895 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2897 if( winpos
.flags
& SWP_HIDEWINDOW
)
2899 if( visRgn
> 1 ) /* map to parent */
2900 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2906 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2907 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2908 &oldClientRect
, uFlags
);
2911 /* nothing moved, redraw frame if needed */
2913 if( winpos
.flags
& SWP_FRAMECHANGED
)
2914 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2917 DeleteObject( visRgn
);
2925 if( winpos
.flags
& SWP_HIDEWINDOW
)
2927 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2930 if (hwnd
== CARET_GetHwnd())
2932 if( winpos
.flags
& SWP_HIDEWINDOW
)
2934 else if (winpos
.flags
& SWP_SHOWWINDOW
)
2938 /* ------------------------------------------------------------------------ FINAL */
2940 if (wndPtr
->flags
& WIN_NATIVE
)
2941 EVENT_Synchronize(); /* Synchronize with the host window system */
2943 wndTemp
= WIN_GetDesktop();
2945 /* repaint invalidated region (if any)
2947 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2948 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2953 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2956 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2957 its parent and sibling and so on, and then erase the parent window
2958 background if the parent is either a top-level window or its parent's parent
2959 is top-level window. Rely on the system to repaint other affected
2960 windows later on. */
2961 if( uFlags
& SWP_EX_PAINTSELF
)
2963 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2964 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2965 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2969 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2970 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2974 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2976 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2977 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2981 DeleteObject( visRgn
);
2984 WIN_ReleaseDesktop();
2986 if (!(flags
& SWP_NOACTIVATE
))
2987 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2989 /* And last, send the WM_WINDOWPOSCHANGED message */
2991 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2994 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2995 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2997 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2998 if (resync
) EVENT_Synchronize();
3003 WIN_ReleaseWndPtr(wndPtr
);
3008 /***********************************************************************
3009 * BeginDeferWindowPos (USER.259)
3011 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
3013 return BeginDeferWindowPos( count
);
3017 /***********************************************************************
3018 * BeginDeferWindowPos (USER32.@)
3020 HDWP WINAPI
BeginDeferWindowPos( INT count
)
3027 SetLastError(ERROR_INVALID_PARAMETER
);
3030 /* Windows allows zero count, in which case it allocates context for 8 moves */
3031 if (count
== 0) count
= 8;
3033 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
3034 if (!handle
) return 0;
3035 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
3036 pDWP
->actualCount
= 0;
3037 pDWP
->suggestedCount
= count
;
3039 pDWP
->wMagic
= DWP_MAGIC
;
3040 pDWP
->hwndParent
= 0;
3045 /***********************************************************************
3046 * DeferWindowPos (USER.260)
3048 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
3049 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
3052 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
3053 x
, y
, cx
, cy
, flags
);
3057 /***********************************************************************
3058 * DeferWindowPos (USER32.@)
3060 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
3061 INT x
, INT y
, INT cx
, INT cy
,
3066 HDWP newhdwp
= hdwp
,retvalue
;
3070 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3071 if (!pDWP
) return 0;
3072 if (hwnd
== GetDesktopWindow()) return 0;
3074 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
3075 USER_HEAP_FREE( hdwp
);
3079 /* Numega Bounds Checker Demo dislikes the following code.
3080 In fact, I've not been able to find any "same parent" requirement in any docu
3084 /* All the windows of a DeferWindowPos() must have the same parent */
3085 parent
= pWnd
->parent
->hwndSelf
;
3086 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
3087 else if (parent
!= pDWP
->hwndParent
)
3089 USER_HEAP_FREE( hdwp
);
3095 for (i
= 0; i
< pDWP
->actualCount
; i
++)
3097 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
3099 /* Merge with the other changes */
3100 if (!(flags
& SWP_NOZORDER
))
3102 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3104 if (!(flags
& SWP_NOMOVE
))
3106 pDWP
->winPos
[i
].x
= x
;
3107 pDWP
->winPos
[i
].y
= y
;
3109 if (!(flags
& SWP_NOSIZE
))
3111 pDWP
->winPos
[i
].cx
= cx
;
3112 pDWP
->winPos
[i
].cy
= cy
;
3114 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3115 SWP_NOZORDER
| SWP_NOREDRAW
|
3116 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3118 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3124 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3126 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3127 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3133 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3134 pDWP
->suggestedCount
++;
3136 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3137 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3138 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3139 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3140 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3141 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3142 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3143 pDWP
->actualCount
++;
3146 WIN_ReleaseWndPtr(pWnd
);
3151 /***********************************************************************
3152 * EndDeferWindowPos (USER.261)
3154 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3156 return EndDeferWindowPos( hdwp
);
3160 /***********************************************************************
3161 * EndDeferWindowPos (USER32.@)
3163 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3170 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3171 if (!pDWP
) return FALSE
;
3172 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3174 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3175 winpos
->x
, winpos
->y
, winpos
->cx
,
3176 winpos
->cy
, winpos
->flags
))) break;
3178 USER_HEAP_FREE( hdwp
);
3183 /***********************************************************************
3184 * TileChildWindows (USER.199)
3186 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3188 FIXME("(%04x, %d): stub\n", parent
, action
);
3191 /***********************************************************************
3192 * CascadeChildWindows (USER.198)
3194 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3196 FIXME("(%04x, %d): stub\n", parent
, action
);
3199 /***********************************************************************
3200 * SetProgmanWindow (USER32.@)
3202 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3204 hGlobalProgmanWindow
= hwnd
;
3205 return hGlobalProgmanWindow
;
3208 /***********************************************************************
3209 * GetProgmanWindow (USER32.@)
3211 HRESULT WINAPI
GetProgmanWindow ( )
3213 return hGlobalProgmanWindow
;
3216 /***********************************************************************
3217 * SetShellWindowEx (USER32.@)
3218 * hwndProgman = Progman[Program Manager]
3219 * |-> SHELLDLL_DefView
3220 * hwndListView = | |-> SysListView32
3221 * | | |-> tooltips_class32
3227 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3229 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3230 hGlobalShellWindow
= hwndProgman
;
3231 return hGlobalShellWindow
;
3235 /***********************************************************************
3236 * SetTaskmanWindow (USER32.@)
3238 * hwnd = MSTaskSwWClass
3239 * |-> SysTabControl32
3241 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3243 hGlobalTaskmanWindow
= hwnd
;
3244 return hGlobalTaskmanWindow
;
3247 /***********************************************************************
3248 * GetTaskmanWindow (USER32.@)
3250 HRESULT WINAPI
GetTaskmanWindow ( )
3252 return hGlobalTaskmanWindow
;