2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
13 #include "wine/winuser16.h"
26 #include "nonclient.h"
27 #include "debugtools.h"
32 DEFAULT_DEBUG_CHANNEL(win
)
34 #define HAS_DLGFRAME(style,exStyle) \
35 (((exStyle) & WS_EX_DLGMODALFRAME) || \
36 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
38 #define HAS_THICKFRAME(style) \
39 (((style) & WS_THICKFRAME) && \
40 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
42 #define SWP_AGG_NOGEOMETRYCHANGE \
43 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
44 #define SWP_AGG_NOPOSCHANGE \
45 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
46 #define SWP_AGG_STATUSFLAGS \
47 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
49 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
51 #define PLACE_MIN 0x0001
52 #define PLACE_MAX 0x0002
53 #define PLACE_RECT 0x0004
55 #define SWP_EX_NOCOPY 0x0001
56 #define SWP_EX_PAINTSELF 0x0002
57 #define SWP_EX_NONCLIENT 0x0004
59 #define MINMAX_NOSWP 0x00010000
61 /* ----- internal variables ----- */
63 static HWND hwndPrevActive
= 0; /* Previously active window */
64 static HWND hGlobalShellWindow
=0; /*the shell*/
65 static HWND hGlobalTaskmanWindow
=0;
66 static HWND hGlobalProgmanWindow
=0;
68 static LPCSTR atomInternalPos
;
70 extern HQUEUE16 hActiveQueue
;
72 /***********************************************************************
73 * WINPOS_CreateInternalPosAtom
75 BOOL
WINPOS_CreateInternalPosAtom()
78 atomInternalPos
= (LPCSTR
)(DWORD
)GlobalAddAtomA(str
);
79 return (atomInternalPos
) ? TRUE
: FALSE
;
82 /***********************************************************************
83 * WINPOS_CheckInternalPos
85 * Called when a window is destroyed.
87 void WINPOS_CheckInternalPos( WND
* wndPtr
)
90 MESSAGEQUEUE
*pMsgQ
= 0;
91 HWND hwnd
= wndPtr
->hwndSelf
;
93 lpPos
= (LPINTERNALPOS
) GetPropA( hwnd
, atomInternalPos
);
95 /* Retrieve the message queue associated with this window */
96 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
99 WARN("\tMessage queue not found. Exiting!\n" );
103 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
105 if( hwnd
== PERQDATA_GetActiveWnd( pMsgQ
->pQData
) )
107 PERQDATA_SetActiveWnd( pMsgQ
->pQData
, 0 );
108 WARN("\tattempt to activate destroyed window!\n");
113 if( IsWindow(lpPos
->hwndIconTitle
) )
114 DestroyWindow( lpPos
->hwndIconTitle
);
115 HeapFree( SystemHeap
, 0, lpPos
);
118 QUEUE_Unlock( pMsgQ
);
122 /***********************************************************************
125 * Find a suitable place for an iconic window.
127 static POINT16
WINPOS_FindIconPos( WND
* wndPtr
, POINT16 pt
)
130 short x
, y
, xspacing
, yspacing
;
132 GetClientRect16( wndPtr
->parent
->hwndSelf
, &rectParent
);
133 if ((pt
.x
>= rectParent
.left
) && (pt
.x
+ GetSystemMetrics(SM_CXICON
) < rectParent
.right
) &&
134 (pt
.y
>= rectParent
.top
) && (pt
.y
+ GetSystemMetrics(SM_CYICON
) < rectParent
.bottom
))
135 return pt
; /* The icon already has a suitable position */
137 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
138 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
140 y
= rectParent
.bottom
;
146 /* Check if another icon already occupies this spot */
147 WND
*childPtr
= WIN_LockWndPtr(wndPtr
->parent
->child
);
150 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (childPtr
!= wndPtr
))
152 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
153 (childPtr
->rectWindow
.right
>= x
) &&
154 (childPtr
->rectWindow
.top
<= y
) &&
155 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
156 break; /* There's a window in there */
158 WIN_UpdateWndPtr(&childPtr
,childPtr
->next
);
160 WIN_ReleaseWndPtr(childPtr
);
161 if (!childPtr
) /* No window was found, so it's OK for us */
163 pt
.x
= x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2;
164 pt
.y
= y
- (yspacing
+ GetSystemMetrics(SM_CYICON
)) / 2;
168 } while(x
<= rectParent
.right
-xspacing
);
174 /***********************************************************************
175 * ArrangeIconicWindows16 (USER.170)
177 UINT16 WINAPI
ArrangeIconicWindows16( HWND16 parent
)
179 return ArrangeIconicWindows(parent
);
181 /***********************************************************************
182 * ArrangeIconicWindows (USER32.7)
184 UINT WINAPI
ArrangeIconicWindows( HWND parent
)
188 INT x
, y
, xspacing
, yspacing
;
190 GetClientRect( parent
, &rectParent
);
192 y
= rectParent
.bottom
;
193 xspacing
= GetSystemMetrics(SM_CXICONSPACING
);
194 yspacing
= GetSystemMetrics(SM_CYICONSPACING
);
196 hwndChild
= GetWindow( parent
, GW_CHILD
);
199 if( IsIconic( hwndChild
) )
201 WND
*wndPtr
= WIN_FindWndPtr(hwndChild
);
203 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
205 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- GetSystemMetrics(SM_CXICON
)) / 2,
206 y
- yspacing
- GetSystemMetrics(SM_CYICON
)/2, 0, 0,
207 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
208 if( IsWindow(hwndChild
) )
209 WINPOS_ShowIconTitle(wndPtr
, TRUE
);
210 WIN_ReleaseWndPtr(wndPtr
);
212 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
219 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
225 /***********************************************************************
226 * SwitchToThisWindow16 (USER.172)
228 void WINAPI
SwitchToThisWindow16( HWND16 hwnd
, BOOL16 restore
)
230 SwitchToThisWindow( hwnd
, restore
);
234 /***********************************************************************
235 * SwitchToThisWindow (USER32.539)
237 void WINAPI
SwitchToThisWindow( HWND hwnd
, BOOL restore
)
239 ShowWindow( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
243 /***********************************************************************
244 * GetWindowRect16 (USER.32)
246 void WINAPI
GetWindowRect16( HWND16 hwnd
, LPRECT16 rect
)
248 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
251 CONV_RECT32TO16( &wndPtr
->rectWindow
, rect
);
252 if (wndPtr
->dwStyle
& WS_CHILD
)
253 MapWindowPoints16( wndPtr
->parent
->hwndSelf
, 0, (POINT16
*)rect
, 2 );
254 WIN_ReleaseWndPtr(wndPtr
);
258 /***********************************************************************
259 * GetWindowRect (USER32.308)
261 BOOL WINAPI
GetWindowRect( HWND hwnd
, LPRECT rect
)
263 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
264 if (!wndPtr
) return FALSE
;
266 *rect
= wndPtr
->rectWindow
;
267 if (wndPtr
->dwStyle
& WS_CHILD
)
268 MapWindowPoints( wndPtr
->parent
->hwndSelf
, 0, (POINT
*)rect
, 2 );
269 WIN_ReleaseWndPtr(wndPtr
);
274 /***********************************************************************
275 * GetWindowRgn (USER32)
277 int WINAPI
GetWindowRgn ( HWND hwnd
, HRGN hrgn
)
280 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
283 if (wndPtr
->hrgnWnd
) nRet
= CombineRgn( hrgn
, wndPtr
->hrgnWnd
, 0, RGN_COPY
);
284 WIN_ReleaseWndPtr(wndPtr
);
289 /***********************************************************************
290 * SetWindowRgn (USER32)
292 int WINAPI
SetWindowRgn( HWND hwnd
, HRGN hrgn
, BOOL bRedraw
)
297 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
299 if (!wndPtr
) return FALSE
;
301 /* a region exists for this window */
302 if (hrgn
!= 0 && hrgn
== wndPtr
->hrgnWnd
)
304 /* can't replace actual region with same region
305 since we're now owner of that region
307 SetLastError(ERROR_INVALID_HANDLE
);
312 /* we'd like to set it back to 0 */
315 GetWindowRect(hwnd
, &tempRect
);
319 /* verify that region really exists */
320 if (GetRgnBox(hrgn
, &tempRect
) == ERROR
) goto done
;
324 /* Size the window to the rectangle of the new region
325 (if it isn't NULL) */
326 SetWindowPos( hwnd
, NULL
, tempRect
.left
, tempRect
.top
,
327 tempRect
.right
- tempRect
.left
, tempRect
.bottom
- tempRect
.top
,
328 SWP_NOSIZE
| SWP_FRAMECHANGED
| SWP_NOMOVE
|
329 SWP_NOZORDER
| (bRedraw
? 0 : SWP_NOREDRAW
) );
334 /* delete previous region */
335 DeleteObject(wndPtr
->hrgnWnd
);
338 else if (hrgn
== NULL
)
340 /* if there was no previous region (stored in wndPtr->hrgnWnd) and
341 the region to be set is also NULL, there is nothing more to do
347 /* valid region handle */
348 wndPtr
->hrgnWnd
= hrgn
;
349 wndPtr
->pDriver
->pSetWindowRgn(wndPtr
, hrgn
);
354 WIN_ReleaseWndPtr(wndPtr
);
358 /***********************************************************************
361 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
365 FIXME("SetWindowRgn16: stub\n");
370 /***********************************************************************
371 * GetClientRect16 (USER.33)
373 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
375 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
377 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
380 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
381 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
383 WIN_ReleaseWndPtr(wndPtr
);
387 /***********************************************************************
388 * GetClientRect (USER.220)
390 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
392 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
394 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
395 if (!wndPtr
) return FALSE
;
396 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
397 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
399 WIN_ReleaseWndPtr(wndPtr
);
404 /*******************************************************************
405 * ClientToScreen16 (USER.28)
407 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
409 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
413 /*******************************************************************
414 * ClientToScreen (USER32.52)
416 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
418 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
423 /*******************************************************************
424 * ScreenToClient16 (USER.29)
426 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
428 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
432 /*******************************************************************
433 * ScreenToClient (USER32.447)
435 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
437 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
442 /***********************************************************************
443 * WINPOS_WindowFromPoint
445 * Find the window and hittest for a given point.
447 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
450 INT16 hittest
= HTERROR
;
454 TRACE("scope %04x %d,%d\n", wndScope
->hwndSelf
, pt
.x
, pt
.y
);
456 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
458 if( wndScope
->dwStyle
& WS_DISABLED
)
464 if( wndScope
->dwExStyle
& WS_EX_MANAGED
)
466 /* In managed mode we have to check wndScope first as it is also
467 * a window which received the mouse event. */
469 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
470 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
473 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
479 /* If point is in window, and window is visible, and it */
480 /* is enabled (or it's a top-level window), then explore */
481 /* its children. Otherwise, go to the next window. */
483 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
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 * WindowFromPoint16 (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.582)
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 * ChildWindowFromPoint16 (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.49)
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 * ChildWindowFromPointEx16 (USER.50)
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.50)
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 * MapWindowPoints16 (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.386)
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 /***********************************************************************
790 * IsIconic16 (USER.31)
792 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
794 return IsIconic(hWnd
);
798 /***********************************************************************
799 * IsIconic (USER32.345)
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 (USER.352)
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.205)
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 * SetActiveWindow16 (USER.59)
880 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
882 return SetActiveWindow(hwnd
);
886 /*******************************************************************
887 * SetActiveWindow (USER32.463)
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 * GetForegroundWindow16 (USER.608)
944 HWND16 WINAPI
GetForegroundWindow16(void)
946 return (HWND16
)GetForegroundWindow();
950 /*******************************************************************
951 * SetForegroundWindow16 (USER.609)
953 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
955 return SetForegroundWindow( hwnd
);
959 /*******************************************************************
960 * GetForegroundWindow (USER32.241)
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.482)
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 * GetShellWindow16 (USER.600)
1013 HWND16 WINAPI
GetShellWindow16(void)
1015 return GetShellWindow();
1018 /*******************************************************************
1019 * SetShellWindow (USER32.504)
1021 HWND WINAPI
SetShellWindow(HWND hwndshell
)
1022 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
1024 hGlobalShellWindow
= hwndshell
;
1025 return hGlobalShellWindow
;
1029 /*******************************************************************
1030 * GetShellWindow (USER32.287)
1032 HWND WINAPI
GetShellWindow(void)
1033 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
1035 return hGlobalShellWindow
;
1039 /***********************************************************************
1040 * BringWindowToTop16 (USER.45)
1042 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
1044 return BringWindowToTop(hwnd
);
1048 /***********************************************************************
1049 * BringWindowToTop (USER32.11)
1051 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
1053 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
1057 /***********************************************************************
1058 * MoveWindow16 (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.399)
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( SystemHeap
, 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 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1309 swpFlags
|= MINMAX_NOSWP
;
1311 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1312 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1314 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1316 /* Restore to maximized position */
1317 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1318 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1319 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1320 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1321 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1326 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1327 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1329 /* Restore to normal position */
1331 *lpRect
= lpPos
->rectNormal
;
1332 lpRect
->right
-= lpRect
->left
;
1333 lpRect
->bottom
-= lpRect
->top
;
1337 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1341 /***********************************************************************
1342 * ShowWindowAsync (USER32.535)
1344 * doesn't wait; returns immediately.
1345 * used by threads to toggle windows in other (possibly hanging) threads
1347 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1349 /* FIXME: does ShowWindow() return immediately ? */
1350 return ShowWindow(hwnd
, cmd
);
1354 /***********************************************************************
1355 * ShowWindow16 (USER.42)
1357 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1359 return ShowWindow(hwnd
,cmd
);
1363 /***********************************************************************
1364 * ShowWindow (USER32.534)
1366 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1368 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1369 BOOL wasVisible
, showFlag
;
1370 RECT16 newPos
= {0, 0, 0, 0};
1373 if (!wndPtr
) return FALSE
;
1375 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1377 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1382 if (!wasVisible
) goto END
;;
1383 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1384 SWP_NOACTIVATE
| SWP_NOZORDER
;
1387 case SW_SHOWMINNOACTIVE
:
1388 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1390 case SW_SHOWMINIMIZED
:
1391 swp
|= SWP_SHOWWINDOW
;
1394 swp
|= SWP_FRAMECHANGED
;
1395 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1396 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1397 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1400 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1401 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1402 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1403 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1404 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1408 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1411 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1414 * ShowWindow has a little peculiar behavior that if the
1415 * window is already the topmost window, it will not
1418 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1419 swp
|= SWP_NOACTIVATE
;
1423 case SW_SHOWNOACTIVATE
:
1424 swp
|= SWP_NOZORDER
;
1425 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1427 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1428 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1430 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1432 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1433 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1434 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1438 showFlag
= (cmd
!= SW_HIDE
);
1439 if (showFlag
!= wasVisible
)
1441 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1442 if (!IsWindow( hwnd
)) goto END
;
1445 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1446 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1447 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1449 /* Don't call SetWindowPos() on invisible child windows */
1450 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1451 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1455 /* We can't activate a child window */
1456 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1457 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1458 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1459 if (!(swp
& MINMAX_NOSWP
))
1461 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1462 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1465 /* FIXME: This will cause the window to be activated irrespective
1466 * of whether it is owned by the same thread. Has to be done
1470 if (hwnd
== GetActiveWindow())
1471 WINPOS_ActivateOtherWindow(wndPtr
);
1473 /* Revert focus to parent */
1474 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1475 SetFocus( GetParent(hwnd
) );
1478 if (!IsWindow( hwnd
)) goto END
;
1479 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1482 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1484 /* should happen only in CreateWindowEx() */
1485 int wParam
= SIZE_RESTORED
;
1487 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1488 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1489 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1490 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1491 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1492 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1493 SendMessageA( hwnd
, WM_MOVE
, 0,
1494 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1498 WIN_ReleaseWndPtr(wndPtr
);
1503 /***********************************************************************
1504 * GetInternalWindowPos16 (USER.460)
1506 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1509 WINDOWPLACEMENT16 wndpl
;
1510 if (GetWindowPlacement16( hwnd
, &wndpl
))
1512 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1513 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1514 return wndpl
.showCmd
;
1520 /***********************************************************************
1521 * GetInternalWindowPos (USER32.245)
1523 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1526 WINDOWPLACEMENT wndpl
;
1527 if (GetWindowPlacement( hwnd
, &wndpl
))
1529 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1530 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1531 return wndpl
.showCmd
;
1536 /***********************************************************************
1537 * GetWindowPlacement16 (USER.370)
1539 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1541 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1542 LPINTERNALPOS lpPos
;
1544 if(!pWnd
) return FALSE
;
1546 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1547 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1548 wndpl
->length
= sizeof(*wndpl
);
1549 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1550 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1552 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1553 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1554 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1555 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1558 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1559 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1560 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1562 WIN_ReleaseWndPtr(pWnd
);
1567 /***********************************************************************
1568 * GetWindowPlacement (USER32.307)
1571 * Fails if wndpl->length of Win95 (!) apps is invalid.
1573 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1577 WINDOWPLACEMENT16 wpl
;
1578 wpl
.length
= sizeof(wpl
);
1579 if( GetWindowPlacement16( hwnd
, &wpl
) )
1581 pwpl32
->length
= sizeof(*pwpl32
);
1582 pwpl32
->flags
= wpl
.flags
;
1583 pwpl32
->showCmd
= wpl
.showCmd
;
1584 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1585 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1586 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1594 /***********************************************************************
1595 * WINPOS_SetPlacement
1597 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1600 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1603 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1604 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1606 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1607 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1608 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1610 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1612 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1613 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1614 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1615 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1617 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1619 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1620 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1621 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1623 else if( flags
& PLACE_RECT
)
1624 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1625 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1626 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1627 SWP_NOZORDER
| SWP_NOACTIVATE
);
1629 ShowWindow( hwnd
, wndpl
->showCmd
);
1630 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1632 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1634 /* SDK: ...valid only the next time... */
1635 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1637 WIN_ReleaseWndPtr(pWnd
);
1644 /***********************************************************************
1645 * SetWindowPlacement16 (USER.371)
1647 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1649 return WINPOS_SetPlacement( hwnd
, wndpl
,
1650 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1653 /***********************************************************************
1654 * SetWindowPlacement (USER32.519)
1657 * Fails if wndpl->length of Win95 (!) apps is invalid.
1659 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1663 WINDOWPLACEMENT16 wpl
;
1665 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1666 wpl
.flags
= pwpl32
->flags
;
1667 wpl
.showCmd
= pwpl32
->showCmd
;
1668 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1669 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1670 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1671 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1672 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1673 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1674 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1675 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1677 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1683 /***********************************************************************
1684 * SetInternalWindowPos16 (USER.461)
1686 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1687 LPRECT16 rect
, LPPOINT16 pt
)
1689 if( IsWindow16(hwnd
) )
1691 WINDOWPLACEMENT16 wndpl
;
1694 wndpl
.length
= sizeof(wndpl
);
1695 wndpl
.showCmd
= showCmd
;
1696 wndpl
.flags
= flags
= 0;
1701 wndpl
.flags
|= WPF_SETMINPOSITION
;
1702 wndpl
.ptMinPosition
= *pt
;
1706 flags
|= PLACE_RECT
;
1707 wndpl
.rcNormalPosition
= *rect
;
1709 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1714 /***********************************************************************
1715 * SetInternalWindowPos (USER32.483)
1717 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1718 LPRECT rect
, LPPOINT pt
)
1720 if( IsWindow(hwnd
) )
1722 WINDOWPLACEMENT16 wndpl
;
1725 wndpl
.length
= sizeof(wndpl
);
1726 wndpl
.showCmd
= showCmd
;
1727 wndpl
.flags
= flags
= 0;
1732 wndpl
.flags
|= WPF_SETMINPOSITION
;
1733 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1737 flags
|= PLACE_RECT
;
1738 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1740 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1744 /*******************************************************************
1745 * WINPOS_SetActiveWindow
1747 * SetActiveWindow() back-end. This is the only function that
1748 * can assign active status to a window. It must be called only
1749 * for the top level windows.
1751 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1753 CBTACTIVATESTRUCT16
* cbtStruct
;
1754 WND
* wndPtr
=0, *wndTemp
;
1755 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1756 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1758 HWND hwndActive
= 0;
1761 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1763 /* Get current active window from the active queue */
1766 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1767 if ( pOldActiveQueue
)
1768 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1771 /* paranoid checks */
1772 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1775 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1778 wndPtr
= WIN_FindWndPtr(hWnd
);
1779 hOldActiveQueue
= hActiveQueue
;
1781 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1783 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1784 WIN_ReleaseWndPtr(wndTemp
);
1787 TRACE("no current active window.\n");
1789 /* call CBT hook chain */
1790 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1792 cbtStruct
->fMouse
= fMouse
;
1793 cbtStruct
->hWndActive
= hwndActive
;
1794 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1795 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1796 SEGPTR_FREE(cbtStruct
);
1797 if (bRet
) goto CLEANUP_END
;
1800 /* set prev active wnd to current active wnd and send notification */
1801 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1803 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1805 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1807 if (GetSysModalWindow16() != hWnd
)
1809 /* disregard refusal if hWnd is sysmodal */
1812 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1813 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1816 /* check if something happened during message processing
1817 * (global active queue may have changed)
1819 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1820 if(!pTempActiveQueue
)
1823 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1824 QUEUE_Unlock( pTempActiveQueue
);
1825 if( hwndPrevActive
!= hwndActive
)
1829 /* Set new active window in the message queue */
1833 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1834 if ( pNewActiveQueue
)
1835 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1837 else /* have to do this or MDI frame activation goes to hell */
1838 if( pOldActiveQueue
)
1839 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1841 /* send palette messages */
1842 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1843 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1845 /* if prev wnd is minimized redraw icon title */
1846 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1848 /* managed windows will get ConfigureNotify event */
1849 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->dwExStyle
& WS_EX_MANAGED
))
1851 /* check Z-order and bring hWnd to the top */
1852 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1854 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1856 WIN_ReleaseDesktop();
1857 WIN_ReleaseWndPtr(wndTemp
);
1859 if( wndTemp
!= wndPtr
)
1860 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1861 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1862 if (!IsWindow(hWnd
))
1866 /* Get a handle to the new active queue */
1867 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1869 /* send WM_ACTIVATEAPP if necessary */
1870 if (hOldActiveQueue
!= hNewActiveQueue
)
1872 WND
**list
, **ppWnd
;
1873 WND
*pDesktop
= WIN_GetDesktop();
1875 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1877 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1879 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1881 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1882 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1883 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1885 WIN_ReleaseWinArray(list
);
1888 hActiveQueue
= hNewActiveQueue
;
1890 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1892 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1894 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1896 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1897 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1898 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1900 WIN_ReleaseWinArray(list
);
1902 WIN_ReleaseDesktop();
1904 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1909 /* walk up to the first unowned window */
1910 wndTemp
= WIN_LockWndPtr(wndPtr
);
1911 while (wndTemp
->owner
)
1913 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1915 /* and set last active owned popup */
1916 wndTemp
->hwndLastActive
= hWnd
;
1918 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1919 WIN_ReleaseWndPtr(wndTemp
);
1920 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1921 SendMessageA( hWnd
, WM_ACTIVATE
,
1922 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1923 (LPARAM
)hwndPrevActive
);
1924 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1927 /* change focus if possible */
1930 if ( pNewActiveQueue
)
1932 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1934 if ( hOldFocus
&& WIN_GetTopParent( hOldFocus
) != hwndActive
)
1935 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1936 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1940 if ( pOldActiveQueue
&&
1941 ( !pNewActiveQueue
||
1942 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1944 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1946 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1950 if( !hwndPrevActive
&& wndPtr
)
1951 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1953 /* if active wnd is minimized redraw icon title */
1954 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1956 bRet
= (hWnd
== hwndActive
); /* Success? */
1958 CLEANUP
: /* Unlock the message queues before returning */
1960 if ( pNewActiveQueue
)
1961 QUEUE_Unlock( pNewActiveQueue
);
1965 if ( pOldActiveQueue
)
1966 QUEUE_Unlock( pOldActiveQueue
);
1968 WIN_ReleaseWndPtr(wndPtr
);
1972 /*******************************************************************
1973 * WINPOS_ActivateOtherWindow
1975 * Activates window other than pWnd.
1977 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1981 HWND hwndActive
= 0;
1983 /* Get current active window from the active queue */
1986 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1989 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1990 QUEUE_Unlock( pActiveQueue
);
1994 if( pWnd
->hwndSelf
== hwndPrevActive
)
1997 if( hwndActive
!= pWnd
->hwndSelf
&&
1998 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
2001 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
2002 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
2004 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
2006 WIN_ReleaseWndPtr(pWndTo
);
2007 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
2009 while( !WINPOS_CanActivate(pWndTo
) )
2011 /* by now owned windows should've been taken care of */
2012 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
2013 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
2014 if( !pWndTo
) break;
2016 WIN_ReleaseWndPtr(pWndPtr
);
2019 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
2021 /* switch desktop queue to current active */
2024 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
2025 WIN_ReleaseWndPtr(pWndTo
);
2026 WIN_ReleaseDesktop();
2033 /*******************************************************************
2034 * WINPOS_ChangeActiveWindow
2037 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
2039 WND
*wndPtr
, *wndTemp
;
2041 HWND hwndActive
= 0;
2043 /* Get current active window from the active queue */
2046 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2049 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2050 QUEUE_Unlock( pActiveQueue
);
2055 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
2057 wndPtr
= WIN_FindWndPtr(hWnd
);
2058 if( !wndPtr
) return FALSE
;
2060 /* child windows get WM_CHILDACTIVATE message */
2061 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2063 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
2067 if( hWnd
== hwndActive
)
2073 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
2079 /* switch desktop queue to current active */
2080 wndTemp
= WIN_GetDesktop();
2081 if( wndPtr
->parent
== wndTemp
)
2082 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
2083 WIN_ReleaseDesktop();
2087 WIN_ReleaseWndPtr(wndPtr
);
2092 /***********************************************************************
2093 * WINPOS_SendNCCalcSize
2095 * Send a WM_NCCALCSIZE message to a window.
2096 * All parameters are read-only except newClientRect.
2097 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2098 * when calcValidRect is TRUE.
2100 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2101 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2102 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2103 RECT
*newClientRect
)
2105 NCCALCSIZE_PARAMS params
;
2106 WINDOWPOS winposCopy
;
2109 params
.rgrc
[0] = *newWindowRect
;
2112 winposCopy
= *winpos
;
2113 params
.rgrc
[1] = *oldWindowRect
;
2114 params
.rgrc
[2] = *oldClientRect
;
2115 params
.lppos
= &winposCopy
;
2117 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2119 TRACE("%d,%d-%d,%d\n",
2120 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2121 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2123 /* If the application send back garbage, ignore it */
2124 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2125 *newClientRect
= params
.rgrc
[0];
2131 /***********************************************************************
2132 * WINPOS_HandleWindowPosChanging16
2134 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2136 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2138 POINT maxSize
, minTrack
;
2139 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2140 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2141 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2143 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2144 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2145 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2146 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2148 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2149 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2156 /***********************************************************************
2157 * WINPOS_HandleWindowPosChanging
2159 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2161 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2164 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2165 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2166 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2168 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2169 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
2170 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
2175 /***********************************************************************
2178 * fix Z order taking into account owned popups -
2179 * basically we need to maintain them above the window that owns them
2181 * FIXME: hide/show owned popups when owner visibility changes.
2183 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2185 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2187 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2189 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2191 /* make sure this popup stays above the owner */
2193 HWND hwndLocalPrev
= HWND_TOP
;
2195 if( hwndInsertAfter
!= HWND_TOP
)
2197 while( w
!= wndPtr
->owner
)
2199 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2200 if( hwndLocalPrev
== hwndInsertAfter
) break;
2201 WIN_UpdateWndPtr(&w
,w
->next
);
2203 hwndInsertAfter
= hwndLocalPrev
;
2206 else if( wndPtr
->dwStyle
& WS_CHILD
)
2209 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2213 if( w
== wndPtr
) break;
2215 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2217 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2218 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2219 hwndInsertAfter
= w
->hwndSelf
;
2221 WIN_UpdateWndPtr(&w
, w
->next
);
2225 WIN_ReleaseWndPtr(w
);
2226 return hwndInsertAfter
;
2229 /***********************************************************************
2232 * Make window look nice without excessive repainting
2234 * visible and update regions are in window coordinates
2235 * client and window rectangles are in parent client coordinates
2237 * Returns: uFlags and a dirty region in *pVisRgn.
2239 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2240 LPRECT lpOldWndRect
,
2241 LPRECT lpOldClientRect
, UINT uFlags
)
2244 HRGN newVisRgn
, dirtyRgn
;
2245 INT my
= COMPLEXREGION
;
2247 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2248 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2249 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2250 lpOldWndRect
->left
, lpOldWndRect
->top
,
2251 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2252 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2253 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2254 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2255 lpOldClientRect
->left
, lpOldClientRect
->top
,
2256 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2258 if( Wnd
->hrgnUpdate
== 1 )
2259 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2261 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2262 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2264 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2265 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2267 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2271 TRACE("\twon't copy anything!\n");
2273 /* set dirtyRgn to the sum of old and new visible regions
2274 * in parent client coordinates */
2276 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2277 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2279 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2281 else /* copy valid bits to a new location */
2283 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2284 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2286 /* subtract already invalid region inside Wnd from the dst region */
2288 if( Wnd
->hrgnUpdate
)
2289 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2292 /* check if entire window can be copied */
2294 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2295 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2296 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2297 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2299 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2300 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2301 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2302 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2304 if( (ocw
!= ncw
) || (och
!= nch
) ||
2305 ( ow
!= nw
) || ( oh
!= nh
) ||
2306 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2307 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2308 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2309 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2311 if(uFlags
& SWP_EX_PAINTSELF
)
2313 /* movement relative to the window itself */
2314 dx
= (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
) -
2315 (lpOldClientRect
->left
- lpOldWndRect
->left
) ;
2316 dy
= (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
) -
2317 (lpOldClientRect
->top
- lpOldWndRect
->top
) ;
2321 /* movement relative to the parent's client area */
2322 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2323 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2326 /* restrict valid bits to the common client rect */
2328 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2329 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2330 r
.right
= r
.left
+ min( ocw
, ncw
);
2331 r
.bottom
= r
.top
+ min( och
, nch
);
2333 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2334 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2335 GetRgnBox( hrgnValid
, &r
);
2336 if( IsRectEmpty( &r
) )
2338 r
= *lpOldClientRect
;
2342 if(uFlags
& SWP_EX_PAINTSELF
) {
2344 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2345 * relative to itself, only the client area can change.
2346 * if the client rect didn't change, there's nothing to do.
2353 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2354 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2355 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2360 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2362 /* Move remaining regions to parent coordinates */
2363 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2364 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2367 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2369 TRACE("\tcomputing dirty region!\n");
2371 /* Compute combined dirty region (old + new - valid) */
2372 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2373 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2375 /* Blt valid bits, r is the rect to copy */
2382 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2383 from copying clipped areas */
2385 if( uFlags
& SWP_EX_PAINTSELF
)
2387 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2388 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2389 rClip
.right
= nw
; rClip
.bottom
= nh
;
2393 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2394 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2395 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2396 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2398 rClip
.left
= rClip
.top
= 0;
2400 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2401 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2403 if( IntersectRect( &r
, &r
, &rClip
) )
2405 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, hDC
, dx
, dy
, &r
, TRUE
);
2407 /* When you copy the bits without repainting, parent doesn't
2408 get validated appropriately. Therefore, we have to validate
2409 the parent with the windows' updated region when the
2410 parent's update region is not empty. */
2412 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2414 OffsetRect(&r
, dx
, dy
);
2415 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2418 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2419 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2423 /* *pVisRgn now points to the invalidated region */
2425 DeleteObject(newVisRgn
);
2426 DeleteObject(dirtyRgn
);
2430 /***********************************************************************
2431 * SWP_DoSimpleFrameChanged
2433 * NOTE: old and new client rect origins are identical, only
2434 * extents may have changed. Window extents are the same.
2436 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2442 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2444 /* Client rect changed its position/size, most likely a scrollar
2445 * was added/removed.
2447 * FIXME: WVR alignment flags
2450 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2454 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2455 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2456 if(!(uFlags
& SWP_EX_NOCOPY
))
2457 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2465 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2468 hrgn
= CreateRectRgnIndirect( &rect
);
2470 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2471 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2472 if(!(uFlags
& SWP_EX_NOCOPY
))
2473 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2477 REGION_UnionRectWithRgn( hrgn
, &rect
);
2480 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2482 rect
= wndPtr
->rectWindow
;
2483 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2484 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2492 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2493 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2497 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2501 DeleteObject( hrgn
);
2504 /***********************************************************************
2505 * SWP_DoWinPosChanging
2507 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2508 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2510 /* Send WM_WINDOWPOSCHANGING message */
2512 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2513 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2515 /* Calculate new position and size */
2517 *pNewWindowRect
= wndPtr
->rectWindow
;
2518 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2519 : wndPtr
->rectClient
;
2521 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2523 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2524 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2526 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2528 pNewWindowRect
->left
= pWinpos
->x
;
2529 pNewWindowRect
->top
= pWinpos
->y
;
2530 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2531 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2533 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2534 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2537 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2541 /***********************************************************************
2544 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2545 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2549 /* Send WM_NCCALCSIZE message to get new client area */
2550 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2552 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2553 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2554 pWinpos
, pNewClientRect
);
2556 /* FIXME: WVR_ALIGNxxx */
2558 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2559 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2560 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2562 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2563 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2564 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2565 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2566 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2569 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2570 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2571 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2575 /***********************************************************************
2576 * SetWindowPos (USER.2)
2578 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2579 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2581 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2584 /***********************************************************************
2585 * SetWindowPos (USER32.520)
2587 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2588 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2591 WND
* wndPtr
,*wndTemp
;
2592 RECT newWindowRect
, newClientRect
;
2593 RECT oldWindowRect
, oldClientRect
;
2595 UINT wvrFlags
= 0, uFlags
= 0;
2596 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2597 HWND hwndActive
= 0;
2599 /* Get current active window from the active queue */
2602 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2605 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2606 QUEUE_Unlock( pActiveQueue
);
2610 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2611 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2613 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2614 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2617 /* ------------------------------------------------------------------------ CHECKS */
2619 /* Check window handle */
2621 if (hwnd
== GetDesktopWindow()) return FALSE
;
2622 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2624 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2625 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2627 /* Fix redundant flags */
2629 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2630 flags
&= ~SWP_SHOWWINDOW
;
2633 if (!(flags
& SWP_SHOWWINDOW
))
2634 flags
|= SWP_NOREDRAW
;
2635 flags
&= ~SWP_HIDEWINDOW
;
2638 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2640 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2641 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2642 flags
|= SWP_NOSIZE
; /* Already the right size */
2644 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2645 flags
|= SWP_NOMOVE
; /* Already the right position */
2647 if (hwnd
== hwndActive
)
2648 flags
|= SWP_NOACTIVATE
; /* Already active */
2649 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2651 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2653 flags
&= ~SWP_NOZORDER
;
2654 hwndInsertAfter
= HWND_TOP
;
2659 /* Check hwndInsertAfter */
2661 /* FIXME: TOPMOST not supported yet */
2662 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2663 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2665 /* hwndInsertAfter must be a sibling of the window */
2666 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2668 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2671 if( wnd
->parent
!= wndPtr
->parent
)
2674 WIN_ReleaseWndPtr(wnd
);
2677 /* don't need to change the Zorder of hwnd if it's already inserted
2678 * after hwndInsertAfter or when inserting hwnd after itself.
2680 if(( wnd
->next
== wndPtr
) || (hwnd
== hwndInsertAfter
)) flags
|= SWP_NOZORDER
;
2682 WIN_ReleaseWndPtr(wnd
);
2685 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2687 /* Fill the WINDOWPOS structure */
2690 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2695 winpos
.flags
= flags
;
2697 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2699 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2701 if( wndPtr
->parent
== WIN_GetDesktop() )
2702 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2703 hwndInsertAfter
, winpos
.flags
);
2704 WIN_ReleaseDesktop();
2707 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2709 if( hwndInsertAfter
== HWND_TOP
)
2710 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2712 if( hwndInsertAfter
== HWND_BOTTOM
)
2713 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2715 if( !(winpos
.flags
& SWP_NOZORDER
) )
2716 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2717 winpos
.flags
|= SWP_NOZORDER
;
2719 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2720 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2721 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2723 /* get a previous visible region for SWP_CopyValidBits() */
2724 DWORD dflags
= DCX_WINDOW
;
2726 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2727 dflags
|= DCX_CLIPSIBLINGS
;
2729 visRgn
= DCE_GetVisRgn(hwnd
, dflags
, 0, 0);
2733 /* Common operations */
2735 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2737 if(!(winpos
.flags
& SWP_NOZORDER
) && winpos
.hwnd
!= hwndInsertAfter
)
2739 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2740 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2743 /* Reset active DCEs */
2745 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2746 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2747 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2751 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2752 DCE_InvalidateDCE(wndPtr
, &rect
);
2755 oldWindowRect
= wndPtr
->rectWindow
;
2756 oldClientRect
= wndPtr
->rectClient
;
2758 /* Find out if we have to redraw the whole client rect */
2760 if( oldClientRect
.bottom
- oldClientRect
.top
==
2761 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2763 if( oldClientRect
.right
- oldClientRect
.left
==
2764 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2766 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2767 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2769 uFlags
|= SWP_EX_NOCOPY
;
2772 * Use this later in CopyValidBits()
2775 uFlags |= SWP_EX_NONCLIENT;
2778 /* FIXME: actually do something with WVR_VALIDRECTS */
2780 wndPtr
->rectWindow
= newWindowRect
;
2781 wndPtr
->rectClient
= newClientRect
;
2783 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2785 BOOL bCallDriver
= TRUE
;
2786 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2788 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2790 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2792 /* This is the only place where we need to force repainting of the contents
2793 of windows created by the host window system, all other cases go through the
2794 expose event handling */
2796 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2798 cx
= newWindowRect
.right
- newWindowRect
.left
;
2799 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2801 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2802 winpos
.hwndInsertAfter
= tempInsertAfter
;
2803 bCallDriver
= FALSE
;
2805 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2806 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2809 /* client area moved but window extents remained the same, copy valid bits */
2811 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2812 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2813 uFlags
| SWP_EX_PAINTSELF
);
2820 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2822 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2823 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2824 !(uFlags
& SWP_EX_NOCOPY
) )
2826 /* The origin of the client rect didn't move so we can try to repaint
2827 * only the nonclient area by setting bit gravity hint for the host window system.
2830 if( !(wndPtr
->dwExStyle
& WS_EX_MANAGED
) )
2832 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2833 newWindowRect
.bottom
- newWindowRect
.top
);
2834 RECT rcn
= newClientRect
;
2835 RECT rco
= oldClientRect
;
2837 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2838 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2839 IntersectRect( &rcn
, &rcn
, &rco
);
2840 visRgn
= CreateRectRgnIndirect( &rcn
);
2841 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2842 DeleteObject( hrgn
);
2843 uFlags
= SWP_EX_PAINTSELF
;
2845 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2848 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2851 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2852 winpos
.hwndInsertAfter
= tempInsertAfter
;
2855 if( winpos
.flags
& SWP_SHOWWINDOW
)
2859 wndPtr
->dwStyle
|= WS_VISIBLE
;
2861 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) resync
= TRUE
;
2863 /* focus was set to unmapped window, reset host focus
2864 * since the window is now visible */
2866 focus
= curr
= GetFocus();
2871 WND
*pFocus
= WIN_FindWndPtr( focus
);
2873 pFocus
->pDriver
->pSetFocus(pFocus
);
2874 WIN_ReleaseWndPtr(pFocus
);
2877 curr
= GetParent(curr
);
2881 else /* -------------------------------------------- emulated window */
2883 if( winpos
.flags
& SWP_SHOWWINDOW
)
2885 wndPtr
->dwStyle
|= WS_VISIBLE
;
2886 uFlags
|= SWP_EX_PAINTSELF
;
2887 visRgn
= 1; /* redraw the whole window */
2889 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2891 if( winpos
.flags
& SWP_HIDEWINDOW
)
2893 if( visRgn
> 1 ) /* map to parent */
2894 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2900 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2902 /* if window was not resized and not moved try to repaint itself */
2903 if((winpos
.flags
& SWP_AGG_NOGEOMETRYCHANGE
) == SWP_AGG_NOGEOMETRYCHANGE
)
2904 uFlags
|= SWP_EX_PAINTSELF
;
2905 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2906 &oldClientRect
, uFlags
);
2910 /* nothing moved, redraw frame if needed */
2912 if( winpos
.flags
& SWP_FRAMECHANGED
)
2913 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2916 DeleteObject( visRgn
);
2924 if( winpos
.flags
& SWP_HIDEWINDOW
)
2926 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2929 if (hwnd
== CARET_GetHwnd())
2931 if( winpos
.flags
& SWP_HIDEWINDOW
)
2933 else if (winpos
.flags
& SWP_SHOWWINDOW
)
2937 /* ------------------------------------------------------------------------ FINAL */
2939 if (wndPtr
->flags
& WIN_NATIVE
)
2940 EVENT_Synchronize(); /* Synchronize with the host window system */
2942 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2944 /* Simulate a mouse event to set the cursor */
2945 int iWndsLocks
= WIN_SuspendWndsLock();
2947 hardware_event( WM_MOUSEMOVE
, GET_KEYSTATE(), 0,
2948 PosX
, PosY
, GetTickCount(), 0 );
2950 WIN_RestoreWndsLock(iWndsLocks
);
2953 wndTemp
= WIN_GetDesktop();
2955 /* repaint invalidated region (if any)
2957 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2958 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2963 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2966 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2967 its parent and sibling and so on, and then erase the parent window
2968 back ground if the parent is either a top-level window or its parent's parent
2969 is top-level window. Rely on the system to repaint other affected
2970 windows later on. */
2971 if( uFlags
& SWP_EX_PAINTSELF
)
2973 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2974 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2975 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2979 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2980 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2984 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2986 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2987 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2991 DeleteObject( visRgn
);
2994 WIN_ReleaseDesktop();
2996 if (!(flags
& SWP_NOACTIVATE
))
2997 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2999 /* And last, send the WM_WINDOWPOSCHANGED message */
3001 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
3004 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
3005 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
3007 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
3008 if (resync
) EVENT_Synchronize();
3013 WIN_ReleaseWndPtr(wndPtr
);
3018 /***********************************************************************
3019 * BeginDeferWindowPos16 (USER.259)
3021 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
3023 return BeginDeferWindowPos( count
);
3027 /***********************************************************************
3028 * BeginDeferWindowPos (USER32.9)
3030 HDWP WINAPI
BeginDeferWindowPos( INT count
)
3037 SetLastError(ERROR_INVALID_PARAMETER
);
3040 /* Windows allows zero count, in which case it allocates context for 8 moves */
3041 if (count
== 0) count
= 8;
3043 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
3044 if (!handle
) return 0;
3045 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
3046 pDWP
->actualCount
= 0;
3047 pDWP
->suggestedCount
= count
;
3049 pDWP
->wMagic
= DWP_MAGIC
;
3050 pDWP
->hwndParent
= 0;
3055 /***********************************************************************
3056 * DeferWindowPos16 (USER.260)
3058 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
3059 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
3062 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
3063 x
, y
, cx
, cy
, flags
);
3067 /***********************************************************************
3068 * DeferWindowPos (USER32.128)
3070 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
3071 INT x
, INT y
, INT cx
, INT cy
,
3076 HDWP newhdwp
= hdwp
,retvalue
;
3080 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3081 if (!pDWP
) return 0;
3082 if (hwnd
== GetDesktopWindow()) return 0;
3084 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
3085 USER_HEAP_FREE( hdwp
);
3089 /* Numega Bounds Checker Demo dislikes the following code.
3090 In fact, I've not been able to find any "same parent" requirement in any docu
3094 /* All the windows of a DeferWindowPos() must have the same parent */
3095 parent
= pWnd
->parent
->hwndSelf
;
3096 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
3097 else if (parent
!= pDWP
->hwndParent
)
3099 USER_HEAP_FREE( hdwp
);
3105 for (i
= 0; i
< pDWP
->actualCount
; i
++)
3107 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
3109 /* Merge with the other changes */
3110 if (!(flags
& SWP_NOZORDER
))
3112 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3114 if (!(flags
& SWP_NOMOVE
))
3116 pDWP
->winPos
[i
].x
= x
;
3117 pDWP
->winPos
[i
].y
= y
;
3119 if (!(flags
& SWP_NOSIZE
))
3121 pDWP
->winPos
[i
].cx
= cx
;
3122 pDWP
->winPos
[i
].cy
= cy
;
3124 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3125 SWP_NOZORDER
| SWP_NOREDRAW
|
3126 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3128 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3134 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3136 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3137 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3143 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3144 pDWP
->suggestedCount
++;
3146 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3147 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3148 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3149 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3150 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3151 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3152 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3153 pDWP
->actualCount
++;
3156 WIN_ReleaseWndPtr(pWnd
);
3161 /***********************************************************************
3162 * EndDeferWindowPos16 (USER.261)
3164 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3166 return EndDeferWindowPos( hdwp
);
3170 /***********************************************************************
3171 * EndDeferWindowPos (USER32.173)
3173 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3180 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3181 if (!pDWP
) return FALSE
;
3182 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3184 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3185 winpos
->x
, winpos
->y
, winpos
->cx
,
3186 winpos
->cy
, winpos
->flags
))) break;
3188 USER_HEAP_FREE( hdwp
);
3193 /***********************************************************************
3194 * TileChildWindows (USER.199)
3196 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3198 FIXME("(%04x, %d): stub\n", parent
, action
);
3201 /***********************************************************************
3202 * CascadeChildWindows (USER.198)
3204 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3206 FIXME("(%04x, %d): stub\n", parent
, action
);
3209 /***********************************************************************
3210 * SetProgmanWindow [USER32.522]
3212 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3214 hGlobalProgmanWindow
= hwnd
;
3215 return hGlobalProgmanWindow
;
3218 /***********************************************************************
3219 * GetProgmanWindow [USER32.289]
3221 HRESULT WINAPI
GetProgmanWindow ( )
3223 return hGlobalProgmanWindow
;
3226 /***********************************************************************
3227 * SetShellWindowEx [USER32.531]
3228 * hwndProgman = Progman[Program Manager]
3229 * |-> SHELLDLL_DefView
3230 * hwndListView = | |-> SysListView32
3231 * | | |-> tooltips_class32
3237 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3239 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3240 hGlobalShellWindow
= hwndProgman
;
3241 return hGlobalShellWindow
;
3245 /***********************************************************************
3246 * SetTaskmanWindow [USER32.537]
3248 * hwnd = MSTaskSwWClass
3249 * |-> SysTabControl32
3251 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3253 hGlobalTaskmanWindow
= hwnd
;
3254 return hGlobalTaskmanWindow
;
3257 /***********************************************************************
3258 * GetTaskmanWindow [USER32.304]
3260 HRESULT WINAPI
GetTaskmanWindow ( )
3262 return hGlobalTaskmanWindow
;