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
);
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
;
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 /* James: Added SWP_NOACTIVATE because SetWindowRgn in Windows doesn't activate the
324 window (and this was REALLY screwing up my app) */
325 SetWindowPos( hwnd
, 0, tempRect
.left
, tempRect
.top
,
326 tempRect
.right
- tempRect
.left
, tempRect
.bottom
- tempRect
.top
,
327 SWP_NOSIZE
| SWP_FRAMECHANGED
| SWP_NOMOVE
| SWP_NOACTIVATE
|
328 SWP_NOZORDER
| (bRedraw
? 0 : SWP_NOREDRAW
) );
333 /* delete previous region */
334 DeleteObject(wndPtr
->hrgnWnd
);
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 /***********************************************************************
358 * SetWindowRgn (USER.668)
360 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
364 FIXME("SetWindowRgn16: stub\n");
369 /***********************************************************************
370 * GetClientRect (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 (USER32.@)
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 * ClientToScreen (USER.28)
406 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
408 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
412 /*******************************************************************
413 * ClientToScreen (USER32.@)
415 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
417 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
422 /*******************************************************************
423 * ScreenToClient (USER.29)
425 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
427 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
431 /*******************************************************************
432 * ScreenToClient (USER32.@)
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
->dwExStyle
& (WS_EX_LAYERED
| WS_EX_TRANSPARENT
)) != (WS_EX_LAYERED
| WS_EX_TRANSPARENT
)) &&
484 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
485 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
487 PtInRegion(wndPtr
->hrgnWnd
, xy
.x
- wndPtr
->rectWindow
.left
,
488 xy
.y
- wndPtr
->rectWindow
.top
) :
489 ((xy
.x
>= wndPtr
->rectWindow
.left
) &&
490 (xy
.x
< wndPtr
->rectWindow
.right
) &&
491 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
492 (xy
.y
< wndPtr
->rectWindow
.bottom
))))
494 TRACE("%d,%d is inside %04x\n", xy
.x
, xy
.y
, wndPtr
->hwndSelf
);
495 *ppWnd
= wndPtr
; /* Got a suitable window */
497 /* If window is minimized or disabled, return at once */
498 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
500 retvalue
= HTCAPTION
;
503 if (wndPtr
->dwStyle
& WS_DISABLED
)
509 /* If point is not in client area, ignore the children */
510 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
511 (xy
.x
>= wndPtr
->rectClient
.right
) ||
512 (xy
.y
< wndPtr
->rectClient
.top
) ||
513 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
515 xy
.x
-= wndPtr
->rectClient
.left
;
516 xy
.y
-= wndPtr
->rectClient
.top
;
517 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
521 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
526 /* If nothing found, try the scope window */
527 if (!*ppWnd
) *ppWnd
= wndScope
;
529 /* Send the WM_NCHITTEST message (only if to the same task) */
530 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
532 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
533 0, MAKELONG( pt
.x
, pt
.y
) );
534 if (hittest
!= HTTRANSPARENT
)
536 retvalue
= hittest
; /* Found the window */
546 /* If no children found in last search, make point relative to parent */
549 xy
.x
+= (*ppWnd
)->rectClient
.left
;
550 xy
.y
+= (*ppWnd
)->rectClient
.top
;
553 /* Restart the search from the next sibling */
554 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
555 *ppWnd
= (*ppWnd
)->parent
;
559 WIN_ReleaseWndPtr(wndPtr
);
564 /*******************************************************************
565 * WindowFromPoint (USER.30)
567 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
570 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
571 WIN_ReleaseDesktop();
572 return pWnd
->hwndSelf
;
576 /*******************************************************************
577 * WindowFromPoint (USER32.@)
579 HWND WINAPI
WindowFromPoint( POINT pt
)
583 CONV_POINT32TO16( &pt
, &pt16
);
584 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
585 WIN_ReleaseDesktop();
586 return (HWND
)pWnd
->hwndSelf
;
590 /*******************************************************************
591 * ChildWindowFromPoint (USER.191)
593 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
596 CONV_POINT16TO32( &pt
, &pt32
);
597 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
601 /*******************************************************************
602 * ChildWindowFromPoint (USER32.@)
604 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
606 /* pt is in the client coordinates */
608 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
614 /* get client rect fast */
615 rect
.top
= rect
.left
= 0;
616 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
617 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
619 if (!PtInRect( &rect
, pt
))
624 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
627 if (PtInRect( &wnd
->rectWindow
, pt
))
629 retvalue
= wnd
->hwndSelf
;
632 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
634 retvalue
= hwndParent
;
636 WIN_ReleaseWndPtr(wnd
);
640 /*******************************************************************
641 * ChildWindowFromPointEx (USER.399)
643 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
646 CONV_POINT16TO32( &pt
, &pt32
);
647 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
651 /*******************************************************************
652 * ChildWindowFromPointEx (USER32.@)
654 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
657 /* pt is in the client coordinates */
659 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
665 /* get client rect fast */
666 rect
.top
= rect
.left
= 0;
667 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
668 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
670 if (!PtInRect( &rect
, pt
))
675 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
679 if (PtInRect( &wnd
->rectWindow
, pt
)) {
680 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
681 !(wnd
->dwStyle
& WS_VISIBLE
) );
682 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
683 (wnd
->dwStyle
& WS_DISABLED
) );
684 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
685 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
688 retvalue
= wnd
->hwndSelf
;
693 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
695 retvalue
= hwndParent
;
697 WIN_ReleaseWndPtr(wnd
);
702 /*******************************************************************
703 * WINPOS_GetWinOffset
705 * Calculate the offset between the origin of the two windows. Used
706 * to implement MapWindowPoints.
708 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
713 offset
->x
= offset
->y
= 0;
714 if (hwndFrom
== hwndTo
) return;
716 /* Translate source window origin to screen coords */
719 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
721 ERR("bad hwndFrom = %04x\n",hwndFrom
);
724 while (wndPtr
->parent
)
726 offset
->x
+= wndPtr
->rectClient
.left
;
727 offset
->y
+= wndPtr
->rectClient
.top
;
728 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
730 WIN_ReleaseWndPtr(wndPtr
);
733 /* Translate origin to destination window coords */
736 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
738 ERR("bad hwndTo = %04x\n", hwndTo
);
741 while (wndPtr
->parent
)
743 offset
->x
-= wndPtr
->rectClient
.left
;
744 offset
->y
-= wndPtr
->rectClient
.top
;
745 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
747 WIN_ReleaseWndPtr(wndPtr
);
752 /*******************************************************************
753 * MapWindowPoints (USER.258)
755 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
756 LPPOINT16 lppt
, UINT16 count
)
760 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
770 /*******************************************************************
771 * MapWindowPoints (USER32.@)
773 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
774 LPPOINT lppt
, UINT count
)
778 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
785 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
789 /***********************************************************************
792 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
794 return IsIconic(hWnd
);
798 /***********************************************************************
799 * IsIconic (USER32.@)
801 BOOL WINAPI
IsIconic(HWND hWnd
)
804 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
805 if (wndPtr
== NULL
) return FALSE
;
806 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
807 WIN_ReleaseWndPtr(wndPtr
);
812 /***********************************************************************
813 * IsZoomed (USER.272)
815 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
817 return IsZoomed(hWnd
);
821 /***********************************************************************
822 * IsZoomed (USER32.@)
824 BOOL WINAPI
IsZoomed(HWND hWnd
)
827 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
828 if (wndPtr
== NULL
) return FALSE
;
829 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
830 WIN_ReleaseWndPtr(wndPtr
);
835 /*******************************************************************
836 * GetActiveWindow (USER.60)
838 HWND16 WINAPI
GetActiveWindow16(void)
840 return (HWND16
)GetActiveWindow();
843 /*******************************************************************
844 * GetActiveWindow (USER32.@)
846 HWND WINAPI
GetActiveWindow(void)
848 MESSAGEQUEUE
*pCurMsgQ
= 0;
851 /* Get the messageQ for the current thread */
852 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
854 WARN("\tCurrent message queue not found. Exiting!\n" );
858 /* Return the current active window from the perQ data of the current message Q */
859 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
861 QUEUE_Unlock( pCurMsgQ
);
866 /*******************************************************************
869 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
871 if( pWnd
&& ( (pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
872 == WS_VISIBLE
) ) return TRUE
;
877 /*******************************************************************
878 * SetActiveWindow (USER.59)
880 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
882 return SetActiveWindow(hwnd
);
886 /*******************************************************************
887 * SetActiveWindow (USER32.@)
889 HWND WINAPI
SetActiveWindow( HWND hwnd
)
892 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
893 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
895 if (!wndPtr
|| (wndPtr
->dwStyle
& (WS_DISABLED
| WS_CHILD
)))
901 /* Get the messageQ for the current thread */
902 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
904 WARN("\tCurrent message queue not found. Exiting!\n" );
908 /* Retrieve the message queue associated with this window */
909 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
912 WARN("\tWindow message queue not found. Exiting!\n" );
916 /* Make sure that the window is associated with the calling threads
917 * message queue. It must share the same perQ data.
920 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
923 /* Save current active window */
924 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
926 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
929 /* Unlock the queues before returning */
931 QUEUE_Unlock( pMsgQ
);
933 QUEUE_Unlock( pCurMsgQ
);
936 WIN_ReleaseWndPtr(wndPtr
);
941 /*******************************************************************
942 * GetForegroundWindow (USER.608)
944 HWND16 WINAPI
GetForegroundWindow16(void)
946 return (HWND16
)GetForegroundWindow();
950 /*******************************************************************
951 * SetForegroundWindow (USER.609)
953 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
955 return SetForegroundWindow( hwnd
);
959 /*******************************************************************
960 * GetForegroundWindow (USER32.@)
962 HWND WINAPI
GetForegroundWindow(void)
966 /* Get the foreground window (active window of hActiveQueue) */
969 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
971 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
973 QUEUE_Unlock( pActiveQueue
);
979 /*******************************************************************
980 * SetForegroundWindow (USER32.@)
982 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
984 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
988 /*******************************************************************
989 * AllowSetForegroundWindow (USER32.@)
991 BOOL WINAPI
AllowSetForegroundWindow( DWORD procid
)
993 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
994 * implemented, then fix this function. */
999 /*******************************************************************
1000 * LockSetForegroundWindow (USER32.@)
1002 BOOL WINAPI
LockSetForegroundWindow( UINT lockcode
)
1004 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
1005 * implemented, then fix this function. */
1010 /*******************************************************************
1011 * GetShellWindow (USER.600)
1013 HWND16 WINAPI
GetShellWindow16(void)
1015 return GetShellWindow();
1018 /*******************************************************************
1019 * SetShellWindow (USER32.@)
1021 HWND WINAPI
SetShellWindow(HWND hwndshell
)
1022 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
1024 hGlobalShellWindow
= hwndshell
;
1025 return hGlobalShellWindow
;
1029 /*******************************************************************
1030 * GetShellWindow (USER32.@)
1032 HWND WINAPI
GetShellWindow(void)
1033 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
1035 return hGlobalShellWindow
;
1039 /***********************************************************************
1040 * BringWindowToTop (USER.45)
1042 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
1044 return BringWindowToTop(hwnd
);
1048 /***********************************************************************
1049 * BringWindowToTop (USER32.@)
1051 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
1053 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
1057 /***********************************************************************
1058 * MoveWindow (USER.56)
1060 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
1063 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
1067 /***********************************************************************
1068 * MoveWindow (USER32.@)
1070 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
1073 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
1074 if (!repaint
) flags
|= SWP_NOREDRAW
;
1075 TRACE("%04x %d,%d %dx%d %d\n",
1076 hwnd
, x
, y
, cx
, cy
, repaint
);
1077 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1080 /***********************************************************************
1081 * WINPOS_InitInternalPos
1083 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1084 LPRECT restoreRect
)
1086 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1090 /* this happens when the window is minimized/maximized
1091 * for the first time (rectWindow is not adjusted yet) */
1093 lpPos
= HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS
) );
1094 if( !lpPos
) return NULL
;
1096 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1097 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1098 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1099 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1102 if( wnd
->dwStyle
& WS_MINIMIZE
)
1103 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1104 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1105 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1106 else if( restoreRect
)
1107 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1112 /***********************************************************************
1113 * WINPOS_RedrawIconTitle
1115 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1117 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1120 if( lpPos
->hwndIconTitle
)
1122 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1123 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1130 /***********************************************************************
1131 * WINPOS_ShowIconTitle
1133 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1135 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1137 if( lpPos
&& !(pWnd
->dwExStyle
& WS_EX_MANAGED
))
1139 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1141 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1144 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1147 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1149 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1151 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1152 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1153 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1155 WIN_ReleaseWndPtr(pWnd
);
1158 else ShowWindow( hWnd
, SW_HIDE
);
1163 /*******************************************************************
1164 * WINPOS_GetMinMaxInfo
1166 * Get the minimized and maximized information for a window.
1168 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1169 POINT
*minTrack
, POINT
*maxTrack
)
1171 LPINTERNALPOS lpPos
;
1175 /* Compute default values */
1177 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1178 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1179 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1180 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1181 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1182 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1184 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) xinc
= yinc
= 0;
1185 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1187 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1188 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1193 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1195 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1196 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1198 if (wndPtr
->dwStyle
& WS_BORDER
)
1200 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1201 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1204 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1205 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1207 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1208 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1209 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1212 MinMax
.ptMaxPosition
.x
= -xinc
;
1213 MinMax
.ptMaxPosition
.y
= -yinc
;
1216 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1218 /* Some sanity checks */
1220 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1221 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1222 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1223 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1224 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1225 MinMax
.ptMaxTrackSize
.x
= max( MinMax
.ptMaxTrackSize
.x
,
1226 MinMax
.ptMinTrackSize
.x
);
1227 MinMax
.ptMaxTrackSize
.y
= max( MinMax
.ptMaxTrackSize
.y
,
1228 MinMax
.ptMinTrackSize
.y
);
1230 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1231 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1232 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1233 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1236 /***********************************************************************
1237 * WINPOS_MinMaximize
1239 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1240 * This function assumes that 'cmd' is different from the current window
1243 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1247 LPINTERNALPOS lpPos
;
1249 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1251 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1252 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1254 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1256 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1258 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1259 return (SWP_NOSIZE
| SWP_NOMOVE
);
1260 swpFlags
|= SWP_NOCOPYBITS
;
1265 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1267 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1268 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1271 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1272 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1274 if( wndPtr
->flags
& WIN_NATIVE
)
1275 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1276 swpFlags
|= MINMAX_NOSWP
;
1278 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1280 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1281 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1282 swpFlags
|= SWP_NOCOPYBITS
;
1286 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1287 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1288 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1290 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1292 if( wndPtr
->flags
& WIN_NATIVE
)
1293 wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
);
1295 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1296 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1298 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1300 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1305 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1307 if( wndPtr
->flags
& WIN_NATIVE
)
1308 wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
);
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.@)
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 * ShowWindow (USER.42)
1356 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1358 return ShowWindow(hwnd
,cmd
);
1362 /***********************************************************************
1363 * ShowWindow (USER32.@)
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 * GetInternalWindowPos (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.@)
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 * GetWindowPlacement (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.@)
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 * SetWindowPlacement (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.@)
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 * SetInternalWindowPos (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.@)
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
)
2162 POINT maxSize
, minTrack
;
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
, &minTrack
, NULL
);
2168 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
2169 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
2170 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2172 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2173 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2179 /***********************************************************************
2182 * fix Z order taking into account owned popups -
2183 * basically we need to maintain them above the window that owns them
2185 * FIXME: hide/show owned popups when owner visibility changes.
2187 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2189 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2191 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2193 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2195 /* make sure this popup stays above the owner */
2197 HWND hwndLocalPrev
= HWND_TOP
;
2199 if( hwndInsertAfter
!= HWND_TOP
)
2201 while( w
&& w
!= wndPtr
->owner
)
2203 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2204 if( hwndLocalPrev
== hwndInsertAfter
) break;
2205 WIN_UpdateWndPtr(&w
,w
->next
);
2207 hwndInsertAfter
= hwndLocalPrev
;
2210 else if( wndPtr
->dwStyle
& WS_CHILD
)
2213 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2217 if( w
== wndPtr
) break;
2219 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2221 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2222 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2223 hwndInsertAfter
= w
->hwndSelf
;
2225 WIN_UpdateWndPtr(&w
, w
->next
);
2229 WIN_ReleaseWndPtr(w
);
2230 return hwndInsertAfter
;
2233 /***********************************************************************
2236 * Make window look nice without excessive repainting
2238 * visible and update regions are in window coordinates
2239 * client and window rectangles are in parent client coordinates
2241 * Returns: uFlags and a dirty region in *pVisRgn.
2243 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2244 LPRECT lpOldWndRect
,
2245 LPRECT lpOldClientRect
, UINT uFlags
)
2248 HRGN newVisRgn
, dirtyRgn
;
2249 INT my
= COMPLEXREGION
;
2252 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2253 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2254 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2255 lpOldWndRect
->left
, lpOldWndRect
->top
,
2256 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2257 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2258 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2259 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2260 lpOldClientRect
->left
, lpOldClientRect
->top
,
2261 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2263 if( Wnd
->hrgnUpdate
== 1 )
2264 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2266 dflags
= DCX_WINDOW
;
2267 if(Wnd
->dwStyle
& WS_CLIPSIBLINGS
)
2268 dflags
|= DCX_CLIPSIBLINGS
;
2269 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, dflags
, 0, 0);
2271 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2273 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2274 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2276 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2280 TRACE("\twon't copy anything!\n");
2282 /* set dirtyRgn to the sum of old and new visible regions
2283 * in parent client coordinates */
2285 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2286 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2288 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2290 else /* copy valid bits to a new location */
2292 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2293 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2295 /* subtract already invalid region inside Wnd from the dst region */
2297 if( Wnd
->hrgnUpdate
)
2298 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2301 /* check if entire window can be copied */
2303 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2304 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2305 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2306 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2308 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2309 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2310 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2311 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2313 if( (ocw
!= ncw
) || (och
!= nch
) ||
2314 ( ow
!= nw
) || ( oh
!= nh
) ||
2315 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2316 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2317 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2318 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2320 if(uFlags
& SWP_EX_PAINTSELF
)
2322 /* movement relative to the window itself */
2323 dx
= (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
) -
2324 (lpOldClientRect
->left
- lpOldWndRect
->left
) ;
2325 dy
= (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
) -
2326 (lpOldClientRect
->top
- lpOldWndRect
->top
) ;
2330 /* movement relative to the parent's client area */
2331 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2332 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2335 /* restrict valid bits to the common client rect */
2337 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2338 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2339 r
.right
= r
.left
+ min( ocw
, ncw
);
2340 r
.bottom
= r
.top
+ min( och
, nch
);
2342 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2343 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2344 GetRgnBox( hrgnValid
, &r
);
2345 if( IsRectEmpty( &r
) )
2347 r
= *lpOldClientRect
;
2351 if(uFlags
& SWP_EX_PAINTSELF
) {
2353 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2354 * relative to itself, only the client area can change.
2355 * if the client rect didn't change, there's nothing to do.
2362 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2363 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2364 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2369 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2371 /* Move remaining regions to parent coordinates */
2372 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2373 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2376 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2378 TRACE("\tcomputing dirty region!\n");
2380 /* Compute combined dirty region (old + new - valid) */
2381 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2382 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2384 /* Blt valid bits, r is the rect to copy */
2391 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2392 from copying clipped areas */
2394 if( uFlags
& SWP_EX_PAINTSELF
)
2396 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2397 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2398 rClip
.right
= nw
; rClip
.bottom
= nh
;
2402 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2403 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2404 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2405 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2407 rClip
.left
= rClip
.top
= 0;
2409 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2410 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2412 if( IntersectRect( &r
, &r
, &rClip
) )
2414 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, hDC
, dx
, dy
, &r
, TRUE
);
2416 /* When you copy the bits without repainting, parent doesn't
2417 get validated appropriately. Therefore, we have to validate
2418 the parent with the windows' updated region when the
2419 parent's update region is not empty. */
2421 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2423 OffsetRect(&r
, dx
, dy
);
2424 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2427 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2428 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2432 /* *pVisRgn now points to the invalidated region */
2434 DeleteObject(newVisRgn
);
2435 DeleteObject(dirtyRgn
);
2439 /***********************************************************************
2440 * SWP_DoSimpleFrameChanged
2442 * NOTE: old and new client rect origins are identical, only
2443 * extents may have changed. Window extents are the same.
2445 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2451 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2453 /* Client rect changed its position/size, most likely a scrollar
2454 * was added/removed.
2456 * FIXME: WVR alignment flags
2459 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2463 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2464 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2465 if(!(uFlags
& SWP_EX_NOCOPY
))
2466 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2474 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2477 hrgn
= CreateRectRgnIndirect( &rect
);
2479 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2480 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2481 if(!(uFlags
& SWP_EX_NOCOPY
))
2482 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2486 REGION_UnionRectWithRgn( hrgn
, &rect
);
2489 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2491 rect
= wndPtr
->rectWindow
;
2492 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2493 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2501 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2502 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2506 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2510 DeleteObject( hrgn
);
2513 /***********************************************************************
2514 * SWP_DoWinPosChanging
2516 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2517 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2519 /* Send WM_WINDOWPOSCHANGING message */
2521 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2522 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2524 /* Calculate new position and size */
2526 *pNewWindowRect
= wndPtr
->rectWindow
;
2527 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2528 : wndPtr
->rectClient
;
2530 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2532 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2533 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2535 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2537 pNewWindowRect
->left
= pWinpos
->x
;
2538 pNewWindowRect
->top
= pWinpos
->y
;
2539 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2540 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2542 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2543 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2546 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2550 /***********************************************************************
2553 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2554 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2558 /* Send WM_NCCALCSIZE message to get new client area */
2559 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2561 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2562 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2563 pWinpos
, pNewClientRect
);
2565 /* FIXME: WVR_ALIGNxxx */
2567 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2568 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2569 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2571 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2572 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2573 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2574 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2575 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2578 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2579 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2580 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2584 /***********************************************************************
2585 * SetWindowPos (USER.232)
2587 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2588 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2590 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2593 /***********************************************************************
2594 * SetWindowPos (USER32.@)
2596 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2597 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2600 WND
* wndPtr
,*wndTemp
;
2601 RECT newWindowRect
, newClientRect
;
2602 RECT oldWindowRect
, oldClientRect
;
2604 UINT wvrFlags
= 0, uFlags
= 0;
2605 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2606 HWND hwndActive
= 0;
2608 /* Get current active window from the active queue */
2611 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2614 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2615 QUEUE_Unlock( pActiveQueue
);
2619 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2620 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2622 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2623 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2626 /* ------------------------------------------------------------------------ CHECKS */
2628 /* Check window handle */
2630 if (hwnd
== GetDesktopWindow()) return FALSE
;
2631 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2633 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2634 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2636 /* Fix redundant flags */
2638 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2639 flags
&= ~SWP_SHOWWINDOW
;
2642 if (!(flags
& SWP_SHOWWINDOW
))
2643 flags
|= SWP_NOREDRAW
;
2644 flags
&= ~SWP_HIDEWINDOW
;
2647 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2649 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2650 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2651 flags
|= SWP_NOSIZE
; /* Already the right size */
2653 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2654 flags
|= SWP_NOMOVE
; /* Already the right position */
2656 if (hwnd
== hwndActive
)
2657 flags
|= SWP_NOACTIVATE
; /* Already active */
2658 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2660 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2662 flags
&= ~SWP_NOZORDER
;
2663 hwndInsertAfter
= HWND_TOP
;
2668 /* Check hwndInsertAfter */
2670 /* FIXME: TOPMOST not supported yet */
2671 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2672 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2674 /* hwndInsertAfter must be a sibling of the window */
2675 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2677 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2680 if( wnd
->parent
!= wndPtr
->parent
)
2683 WIN_ReleaseWndPtr(wnd
);
2686 /* don't need to change the Zorder of hwnd if it's already inserted
2687 * after hwndInsertAfter or when inserting hwnd after itself.
2689 if(( wnd
->next
== wndPtr
) || (hwnd
== hwndInsertAfter
)) flags
|= SWP_NOZORDER
;
2691 WIN_ReleaseWndPtr(wnd
);
2694 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2696 /* Fill the WINDOWPOS structure */
2699 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2704 winpos
.flags
= flags
;
2706 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2708 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2710 if( wndPtr
->parent
== WIN_GetDesktop() )
2711 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2712 hwndInsertAfter
, winpos
.flags
);
2713 WIN_ReleaseDesktop();
2716 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2718 if( hwndInsertAfter
== HWND_TOP
)
2719 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2721 if( hwndInsertAfter
== HWND_BOTTOM
)
2722 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2724 if( !(winpos
.flags
& SWP_NOZORDER
) )
2725 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2726 winpos
.flags
|= SWP_NOZORDER
;
2728 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2729 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2730 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2732 /* get a previous visible region for SWP_CopyValidBits() */
2733 DWORD dflags
= DCX_WINDOW
;
2735 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2736 dflags
|= DCX_CLIPSIBLINGS
;
2738 visRgn
= DCE_GetVisRgn(hwnd
, dflags
, 0, 0);
2742 /* Common operations */
2744 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2746 if(!(winpos
.flags
& SWP_NOZORDER
) && winpos
.hwnd
!= hwndInsertAfter
)
2748 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2749 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2752 /* Reset active DCEs */
2754 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2755 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2756 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2760 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2761 DCE_InvalidateDCE(wndPtr
, &rect
);
2764 oldWindowRect
= wndPtr
->rectWindow
;
2765 oldClientRect
= wndPtr
->rectClient
;
2767 /* Find out if we have to redraw the whole client rect */
2769 if( oldClientRect
.bottom
- oldClientRect
.top
==
2770 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2772 if( oldClientRect
.right
- oldClientRect
.left
==
2773 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2775 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2776 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2778 uFlags
|= SWP_EX_NOCOPY
;
2781 * Use this later in CopyValidBits()
2784 uFlags |= SWP_EX_NONCLIENT;
2787 /* FIXME: actually do something with WVR_VALIDRECTS */
2789 wndPtr
->rectWindow
= newWindowRect
;
2790 wndPtr
->rectClient
= newClientRect
;
2792 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2794 BOOL bCallDriver
= TRUE
;
2795 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2797 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2799 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2801 /* This is the only place where we need to force repainting of the contents
2802 of windows created by the host window system, all other cases go through the
2803 expose event handling */
2805 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2807 cx
= newWindowRect
.right
- newWindowRect
.left
;
2808 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2810 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2811 winpos
.hwndInsertAfter
= tempInsertAfter
;
2812 bCallDriver
= FALSE
;
2814 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2815 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2818 /* client area moved but window extents remained the same, copy valid bits */
2820 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2821 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2822 uFlags
| SWP_EX_PAINTSELF
);
2829 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2831 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2832 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2833 !(uFlags
& SWP_EX_NOCOPY
) )
2835 /* The origin of the client rect didn't move so we can try to repaint
2836 * only the nonclient area by setting bit gravity hint for the host window system.
2839 if( !(wndPtr
->dwExStyle
& WS_EX_MANAGED
) )
2841 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2842 newWindowRect
.bottom
- newWindowRect
.top
);
2843 RECT rcn
= newClientRect
;
2844 RECT rco
= oldClientRect
;
2846 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2847 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2848 IntersectRect( &rcn
, &rcn
, &rco
);
2849 visRgn
= CreateRectRgnIndirect( &rcn
);
2850 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2851 DeleteObject( hrgn
);
2852 uFlags
= SWP_EX_PAINTSELF
;
2854 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2858 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2859 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2860 winpos
.hwndInsertAfter
= tempInsertAfter
;
2863 if( winpos
.flags
& SWP_SHOWWINDOW
)
2867 wndPtr
->dwStyle
|= WS_VISIBLE
;
2869 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) resync
= TRUE
;
2871 /* focus was set to unmapped window, reset host focus
2872 * since the window is now visible */
2874 focus
= curr
= GetFocus();
2879 WND
*pFocus
= WIN_FindWndPtr( focus
);
2881 pFocus
->pDriver
->pSetFocus(pFocus
);
2882 WIN_ReleaseWndPtr(pFocus
);
2885 curr
= GetParent(curr
);
2889 else /* -------------------------------------------- emulated window */
2891 if( winpos
.flags
& SWP_SHOWWINDOW
)
2893 wndPtr
->dwStyle
|= WS_VISIBLE
;
2894 uFlags
|= SWP_EX_PAINTSELF
;
2895 visRgn
= 1; /* redraw the whole window */
2897 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2899 if( winpos
.flags
& SWP_HIDEWINDOW
)
2901 if( visRgn
> 1 ) /* map to parent */
2902 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2908 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2909 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2910 &oldClientRect
, uFlags
);
2913 /* nothing moved, redraw frame if needed */
2915 if( winpos
.flags
& SWP_FRAMECHANGED
)
2916 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2919 DeleteObject( visRgn
);
2927 if( winpos
.flags
& SWP_HIDEWINDOW
)
2929 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2932 if (hwnd
== CARET_GetHwnd())
2934 if( winpos
.flags
& SWP_HIDEWINDOW
)
2936 else if (winpos
.flags
& SWP_SHOWWINDOW
)
2940 /* ------------------------------------------------------------------------ FINAL */
2942 if (wndPtr
->flags
& WIN_NATIVE
)
2943 EVENT_Synchronize(); /* Synchronize with the host window system */
2945 wndTemp
= WIN_GetDesktop();
2947 /* repaint invalidated region (if any)
2949 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2950 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2955 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2958 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2959 its parent and sibling and so on, and then erase the parent window
2960 background if the parent is either a top-level window or its parent's parent
2961 is top-level window. Rely on the system to repaint other affected
2962 windows later on. */
2963 if( uFlags
& SWP_EX_PAINTSELF
)
2965 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2966 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2967 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2971 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2972 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2976 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2978 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2979 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2983 DeleteObject( visRgn
);
2986 WIN_ReleaseDesktop();
2988 if (!(flags
& SWP_NOACTIVATE
))
2989 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2991 /* And last, send the WM_WINDOWPOSCHANGED message */
2993 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2996 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2997 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2999 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
3000 if (resync
) EVENT_Synchronize();
3005 WIN_ReleaseWndPtr(wndPtr
);
3010 /***********************************************************************
3011 * BeginDeferWindowPos (USER.259)
3013 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
3015 return BeginDeferWindowPos( count
);
3019 /***********************************************************************
3020 * BeginDeferWindowPos (USER32.@)
3022 HDWP WINAPI
BeginDeferWindowPos( INT count
)
3029 SetLastError(ERROR_INVALID_PARAMETER
);
3032 /* Windows allows zero count, in which case it allocates context for 8 moves */
3033 if (count
== 0) count
= 8;
3035 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
3036 if (!handle
) return 0;
3037 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
3038 pDWP
->actualCount
= 0;
3039 pDWP
->suggestedCount
= count
;
3041 pDWP
->wMagic
= DWP_MAGIC
;
3042 pDWP
->hwndParent
= 0;
3047 /***********************************************************************
3048 * DeferWindowPos (USER.260)
3050 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
3051 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
3054 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
3055 x
, y
, cx
, cy
, flags
);
3059 /***********************************************************************
3060 * DeferWindowPos (USER32.@)
3062 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
3063 INT x
, INT y
, INT cx
, INT cy
,
3068 HDWP newhdwp
= hdwp
,retvalue
;
3072 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3073 if (!pDWP
) return 0;
3074 if (hwnd
== GetDesktopWindow()) return 0;
3076 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
3077 USER_HEAP_FREE( hdwp
);
3081 /* Numega Bounds Checker Demo dislikes the following code.
3082 In fact, I've not been able to find any "same parent" requirement in any docu
3086 /* All the windows of a DeferWindowPos() must have the same parent */
3087 parent
= pWnd
->parent
->hwndSelf
;
3088 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
3089 else if (parent
!= pDWP
->hwndParent
)
3091 USER_HEAP_FREE( hdwp
);
3097 for (i
= 0; i
< pDWP
->actualCount
; i
++)
3099 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
3101 /* Merge with the other changes */
3102 if (!(flags
& SWP_NOZORDER
))
3104 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3106 if (!(flags
& SWP_NOMOVE
))
3108 pDWP
->winPos
[i
].x
= x
;
3109 pDWP
->winPos
[i
].y
= y
;
3111 if (!(flags
& SWP_NOSIZE
))
3113 pDWP
->winPos
[i
].cx
= cx
;
3114 pDWP
->winPos
[i
].cy
= cy
;
3116 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3117 SWP_NOZORDER
| SWP_NOREDRAW
|
3118 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3120 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3126 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3128 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3129 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3135 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3136 pDWP
->suggestedCount
++;
3138 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3139 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3140 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3141 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3142 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3143 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3144 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3145 pDWP
->actualCount
++;
3148 WIN_ReleaseWndPtr(pWnd
);
3153 /***********************************************************************
3154 * EndDeferWindowPos (USER.261)
3156 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3158 return EndDeferWindowPos( hdwp
);
3162 /***********************************************************************
3163 * EndDeferWindowPos (USER32.@)
3165 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3172 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3173 if (!pDWP
) return FALSE
;
3174 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3176 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3177 winpos
->x
, winpos
->y
, winpos
->cx
,
3178 winpos
->cy
, winpos
->flags
))) break;
3180 USER_HEAP_FREE( hdwp
);
3185 /***********************************************************************
3186 * TileChildWindows (USER.199)
3188 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3190 FIXME("(%04x, %d): stub\n", parent
, action
);
3193 /***********************************************************************
3194 * CascadeChildWindows (USER.198)
3196 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3198 FIXME("(%04x, %d): stub\n", parent
, action
);
3201 /***********************************************************************
3202 * SetProgmanWindow (USER32.@)
3204 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3206 hGlobalProgmanWindow
= hwnd
;
3207 return hGlobalProgmanWindow
;
3210 /***********************************************************************
3211 * GetProgmanWindow (USER32.@)
3213 HRESULT WINAPI
GetProgmanWindow ( )
3215 return hGlobalProgmanWindow
;
3218 /***********************************************************************
3219 * SetShellWindowEx (USER32.@)
3220 * hwndProgman = Progman[Program Manager]
3221 * |-> SHELLDLL_DefView
3222 * hwndListView = | |-> SysListView32
3223 * | | |-> tooltips_class32
3229 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3231 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3232 hGlobalShellWindow
= hwndProgman
;
3233 return hGlobalShellWindow
;
3237 /***********************************************************************
3238 * SetTaskmanWindow (USER32.@)
3240 * hwnd = MSTaskSwWClass
3241 * |-> SysTabControl32
3243 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3245 hGlobalTaskmanWindow
= hwnd
;
3246 return hGlobalTaskmanWindow
;
3249 /***********************************************************************
3250 * GetTaskmanWindow (USER32.@)
3252 HRESULT WINAPI
GetTaskmanWindow ( )
3254 return hGlobalTaskmanWindow
;