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 * GetShellWindow16 (USER.600)
991 HWND16 WINAPI
GetShellWindow16(void)
993 return GetShellWindow();
996 /*******************************************************************
997 * SetShellWindow (USER32.504)
999 HWND WINAPI
SetShellWindow(HWND hwndshell
)
1000 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
1002 hGlobalShellWindow
= hwndshell
;
1003 return hGlobalShellWindow
;
1007 /*******************************************************************
1008 * GetShellWindow (USER32.287)
1010 HWND WINAPI
GetShellWindow(void)
1011 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
1013 return hGlobalShellWindow
;
1017 /***********************************************************************
1018 * BringWindowToTop16 (USER.45)
1020 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
1022 return BringWindowToTop(hwnd
);
1026 /***********************************************************************
1027 * BringWindowToTop (USER32.11)
1029 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
1031 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
1035 /***********************************************************************
1036 * MoveWindow16 (USER.56)
1038 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
1041 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
1045 /***********************************************************************
1046 * MoveWindow (USER32.399)
1048 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
1051 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
1052 if (!repaint
) flags
|= SWP_NOREDRAW
;
1053 TRACE("%04x %d,%d %dx%d %d\n",
1054 hwnd
, x
, y
, cx
, cy
, repaint
);
1055 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1058 /***********************************************************************
1059 * WINPOS_InitInternalPos
1061 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1062 LPRECT restoreRect
)
1064 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1068 /* this happens when the window is minimized/maximized
1069 * for the first time (rectWindow is not adjusted yet) */
1071 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1072 if( !lpPos
) return NULL
;
1074 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1075 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1076 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1077 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1080 if( wnd
->dwStyle
& WS_MINIMIZE
)
1081 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1082 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1083 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1084 else if( restoreRect
)
1085 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1090 /***********************************************************************
1091 * WINPOS_RedrawIconTitle
1093 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1095 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1098 if( lpPos
->hwndIconTitle
)
1100 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1101 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1108 /***********************************************************************
1109 * WINPOS_ShowIconTitle
1111 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1113 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1115 if( lpPos
&& !(pWnd
->dwExStyle
& WS_EX_MANAGED
))
1117 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1119 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1122 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1125 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1127 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1129 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1130 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1131 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1133 WIN_ReleaseWndPtr(pWnd
);
1136 else ShowWindow( hWnd
, SW_HIDE
);
1141 /*******************************************************************
1142 * WINPOS_GetMinMaxInfo
1144 * Get the minimized and maximized information for a window.
1146 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1147 POINT
*minTrack
, POINT
*maxTrack
)
1149 LPINTERNALPOS lpPos
;
1153 /* Compute default values */
1155 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1156 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1157 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1158 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1159 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1160 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1162 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) xinc
= yinc
= 0;
1163 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1165 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1166 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1171 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1173 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1174 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1176 if (wndPtr
->dwStyle
& WS_BORDER
)
1178 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1179 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1182 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1183 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1185 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1186 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1187 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1190 MinMax
.ptMaxPosition
.x
= -xinc
;
1191 MinMax
.ptMaxPosition
.y
= -yinc
;
1194 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1196 /* Some sanity checks */
1198 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1199 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1200 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1201 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1202 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1203 MinMax
.ptMaxTrackSize
.x
= max( MinMax
.ptMaxTrackSize
.x
,
1204 MinMax
.ptMinTrackSize
.x
);
1205 MinMax
.ptMaxTrackSize
.y
= max( MinMax
.ptMaxTrackSize
.y
,
1206 MinMax
.ptMinTrackSize
.y
);
1208 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1209 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1210 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1211 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1214 /***********************************************************************
1215 * WINPOS_MinMaximize
1217 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1218 * This function assumes that 'cmd' is different from the current window
1221 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1225 LPINTERNALPOS lpPos
;
1227 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1229 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1230 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1232 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1234 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1236 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1237 return (SWP_NOSIZE
| SWP_NOMOVE
);
1238 swpFlags
|= SWP_NOCOPYBITS
;
1243 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1245 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1246 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1249 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1250 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1252 if( wndPtr
->flags
& WIN_NATIVE
)
1253 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1254 swpFlags
|= MINMAX_NOSWP
;
1256 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1258 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1259 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1260 swpFlags
|= SWP_NOCOPYBITS
;
1264 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1265 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1266 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1268 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1270 if( wndPtr
->flags
& WIN_NATIVE
)
1271 wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
);
1273 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1274 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1276 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1278 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1283 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1285 if( wndPtr
->flags
& WIN_NATIVE
)
1286 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1287 swpFlags
|= MINMAX_NOSWP
;
1289 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1290 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1292 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1294 /* Restore to maximized position */
1295 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1296 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1297 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1298 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1299 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1304 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1305 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1307 /* Restore to normal position */
1309 *lpRect
= lpPos
->rectNormal
;
1310 lpRect
->right
-= lpRect
->left
;
1311 lpRect
->bottom
-= lpRect
->top
;
1315 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1319 /***********************************************************************
1320 * ShowWindowAsync (USER32.535)
1322 * doesn't wait; returns immediately.
1323 * used by threads to toggle windows in other (possibly hanging) threads
1325 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1327 /* FIXME: does ShowWindow() return immediately ? */
1328 return ShowWindow(hwnd
, cmd
);
1332 /***********************************************************************
1333 * ShowWindow16 (USER.42)
1335 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1337 return ShowWindow(hwnd
,cmd
);
1341 /***********************************************************************
1342 * ShowWindow (USER32.534)
1344 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1346 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1347 BOOL wasVisible
, showFlag
;
1348 RECT16 newPos
= {0, 0, 0, 0};
1351 if (!wndPtr
) return FALSE
;
1353 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1355 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1360 if (!wasVisible
) goto END
;;
1361 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1362 SWP_NOACTIVATE
| SWP_NOZORDER
;
1365 case SW_SHOWMINNOACTIVE
:
1366 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1368 case SW_SHOWMINIMIZED
:
1369 swp
|= SWP_SHOWWINDOW
;
1372 swp
|= SWP_FRAMECHANGED
;
1373 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1374 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1375 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1378 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1379 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1380 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1381 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1382 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1386 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1389 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1392 * ShowWindow has a little peculiar behavior that if the
1393 * window is already the topmost window, it will not
1396 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1397 swp
|= SWP_NOACTIVATE
;
1401 case SW_SHOWNOACTIVATE
:
1402 swp
|= SWP_NOZORDER
;
1403 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1405 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1406 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1408 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1410 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1411 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1412 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1416 showFlag
= (cmd
!= SW_HIDE
);
1417 if (showFlag
!= wasVisible
)
1419 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1420 if (!IsWindow( hwnd
)) goto END
;
1423 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1424 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1425 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1427 /* Don't call SetWindowPos() on invisible child windows */
1428 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1429 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1433 /* We can't activate a child window */
1434 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1435 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1436 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1437 if (!(swp
& MINMAX_NOSWP
))
1439 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1440 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1443 /* FIXME: This will cause the window to be activated irrespective
1444 * of whether it is owned by the same thread. Has to be done
1448 if (hwnd
== GetActiveWindow())
1449 WINPOS_ActivateOtherWindow(wndPtr
);
1451 /* Revert focus to parent */
1452 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1453 SetFocus( GetParent(hwnd
) );
1456 if (!IsWindow( hwnd
)) goto END
;
1457 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1460 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1462 /* should happen only in CreateWindowEx() */
1463 int wParam
= SIZE_RESTORED
;
1465 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1466 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1467 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1468 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1469 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1470 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1471 SendMessageA( hwnd
, WM_MOVE
, 0,
1472 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1476 WIN_ReleaseWndPtr(wndPtr
);
1481 /***********************************************************************
1482 * GetInternalWindowPos16 (USER.460)
1484 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1487 WINDOWPLACEMENT16 wndpl
;
1488 if (GetWindowPlacement16( hwnd
, &wndpl
))
1490 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1491 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1492 return wndpl
.showCmd
;
1498 /***********************************************************************
1499 * GetInternalWindowPos (USER32.245)
1501 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1504 WINDOWPLACEMENT wndpl
;
1505 if (GetWindowPlacement( hwnd
, &wndpl
))
1507 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1508 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1509 return wndpl
.showCmd
;
1514 /***********************************************************************
1515 * GetWindowPlacement16 (USER.370)
1517 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1519 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1520 LPINTERNALPOS lpPos
;
1522 if(!pWnd
) return FALSE
;
1524 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1525 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1526 wndpl
->length
= sizeof(*wndpl
);
1527 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1528 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1530 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1531 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1532 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1533 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1536 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1537 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1538 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1540 WIN_ReleaseWndPtr(pWnd
);
1545 /***********************************************************************
1546 * GetWindowPlacement (USER32.307)
1549 * Fails if wndpl->length of Win95 (!) apps is invalid.
1551 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1555 WINDOWPLACEMENT16 wpl
;
1556 wpl
.length
= sizeof(wpl
);
1557 if( GetWindowPlacement16( hwnd
, &wpl
) )
1559 pwpl32
->length
= sizeof(*pwpl32
);
1560 pwpl32
->flags
= wpl
.flags
;
1561 pwpl32
->showCmd
= wpl
.showCmd
;
1562 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1563 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1564 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1572 /***********************************************************************
1573 * WINPOS_SetPlacement
1575 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1578 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1581 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1582 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1584 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1585 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1586 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1588 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1590 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1591 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1592 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1593 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1595 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1597 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1598 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1599 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1601 else if( flags
& PLACE_RECT
)
1602 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1603 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1604 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1605 SWP_NOZORDER
| SWP_NOACTIVATE
);
1607 ShowWindow( hwnd
, wndpl
->showCmd
);
1608 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1610 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1612 /* SDK: ...valid only the next time... */
1613 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1615 WIN_ReleaseWndPtr(pWnd
);
1622 /***********************************************************************
1623 * SetWindowPlacement16 (USER.371)
1625 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1627 return WINPOS_SetPlacement( hwnd
, wndpl
,
1628 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1631 /***********************************************************************
1632 * SetWindowPlacement (USER32.519)
1635 * Fails if wndpl->length of Win95 (!) apps is invalid.
1637 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1641 WINDOWPLACEMENT16 wpl
;
1643 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1644 wpl
.flags
= pwpl32
->flags
;
1645 wpl
.showCmd
= pwpl32
->showCmd
;
1646 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1647 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1648 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1649 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1650 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1651 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1652 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1653 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1655 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1661 /***********************************************************************
1662 * SetInternalWindowPos16 (USER.461)
1664 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1665 LPRECT16 rect
, LPPOINT16 pt
)
1667 if( IsWindow16(hwnd
) )
1669 WINDOWPLACEMENT16 wndpl
;
1672 wndpl
.length
= sizeof(wndpl
);
1673 wndpl
.showCmd
= showCmd
;
1674 wndpl
.flags
= flags
= 0;
1679 wndpl
.flags
|= WPF_SETMINPOSITION
;
1680 wndpl
.ptMinPosition
= *pt
;
1684 flags
|= PLACE_RECT
;
1685 wndpl
.rcNormalPosition
= *rect
;
1687 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1692 /***********************************************************************
1693 * SetInternalWindowPos (USER32.483)
1695 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1696 LPRECT rect
, LPPOINT pt
)
1698 if( IsWindow(hwnd
) )
1700 WINDOWPLACEMENT16 wndpl
;
1703 wndpl
.length
= sizeof(wndpl
);
1704 wndpl
.showCmd
= showCmd
;
1705 wndpl
.flags
= flags
= 0;
1710 wndpl
.flags
|= WPF_SETMINPOSITION
;
1711 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1715 flags
|= PLACE_RECT
;
1716 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1718 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1722 /*******************************************************************
1723 * WINPOS_SetActiveWindow
1725 * SetActiveWindow() back-end. This is the only function that
1726 * can assign active status to a window. It must be called only
1727 * for the top level windows.
1729 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1731 CBTACTIVATESTRUCT16
* cbtStruct
;
1732 WND
* wndPtr
=0, *wndTemp
;
1733 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1734 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1736 HWND hwndActive
= 0;
1739 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1741 /* Get current active window from the active queue */
1744 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1745 if ( pOldActiveQueue
)
1746 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1749 /* paranoid checks */
1750 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1753 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1756 wndPtr
= WIN_FindWndPtr(hWnd
);
1757 hOldActiveQueue
= hActiveQueue
;
1759 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1761 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1762 WIN_ReleaseWndPtr(wndTemp
);
1765 TRACE("no current active window.\n");
1767 /* call CBT hook chain */
1768 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1770 cbtStruct
->fMouse
= fMouse
;
1771 cbtStruct
->hWndActive
= hwndActive
;
1772 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1773 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1774 SEGPTR_FREE(cbtStruct
);
1775 if (bRet
) goto CLEANUP_END
;
1778 /* set prev active wnd to current active wnd and send notification */
1779 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1781 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1783 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1785 if (GetSysModalWindow16() != hWnd
)
1787 /* disregard refusal if hWnd is sysmodal */
1790 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1791 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1794 /* check if something happened during message processing
1795 * (global active queue may have changed)
1797 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1798 if(!pTempActiveQueue
)
1801 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1802 QUEUE_Unlock( pTempActiveQueue
);
1803 if( hwndPrevActive
!= hwndActive
)
1807 /* Set new active window in the message queue */
1811 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1812 if ( pNewActiveQueue
)
1813 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1815 else /* have to do this or MDI frame activation goes to hell */
1816 if( pOldActiveQueue
)
1817 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1819 /* send palette messages */
1820 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1821 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1823 /* if prev wnd is minimized redraw icon title */
1824 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1826 /* managed windows will get ConfigureNotify event */
1827 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->dwExStyle
& WS_EX_MANAGED
))
1829 /* check Z-order and bring hWnd to the top */
1830 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1832 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1834 WIN_ReleaseDesktop();
1835 WIN_ReleaseWndPtr(wndTemp
);
1837 if( wndTemp
!= wndPtr
)
1838 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1839 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1840 if (!IsWindow(hWnd
))
1844 /* Get a handle to the new active queue */
1845 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1847 /* send WM_ACTIVATEAPP if necessary */
1848 if (hOldActiveQueue
!= hNewActiveQueue
)
1850 WND
**list
, **ppWnd
;
1851 WND
*pDesktop
= WIN_GetDesktop();
1853 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1855 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1857 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1859 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1860 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1861 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1863 WIN_ReleaseWinArray(list
);
1866 hActiveQueue
= hNewActiveQueue
;
1868 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1870 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1872 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1874 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1875 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1876 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1878 WIN_ReleaseWinArray(list
);
1880 WIN_ReleaseDesktop();
1882 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1887 /* walk up to the first unowned window */
1888 wndTemp
= WIN_LockWndPtr(wndPtr
);
1889 while (wndTemp
->owner
)
1891 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1893 /* and set last active owned popup */
1894 wndTemp
->hwndLastActive
= hWnd
;
1896 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1897 WIN_ReleaseWndPtr(wndTemp
);
1898 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1899 SendMessageA( hWnd
, WM_ACTIVATE
,
1900 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1901 (LPARAM
)hwndPrevActive
);
1902 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1905 /* change focus if possible */
1908 if ( pNewActiveQueue
)
1910 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1912 if ( hOldFocus
&& WIN_GetTopParent( hOldFocus
) != hwndActive
)
1913 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1914 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1918 if ( pOldActiveQueue
&&
1919 ( !pNewActiveQueue
||
1920 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1922 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1924 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1928 if( !hwndPrevActive
&& wndPtr
)
1929 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1931 /* if active wnd is minimized redraw icon title */
1932 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1934 bRet
= (hWnd
== hwndActive
); /* Success? */
1936 CLEANUP
: /* Unlock the message queues before returning */
1938 if ( pNewActiveQueue
)
1939 QUEUE_Unlock( pNewActiveQueue
);
1943 if ( pOldActiveQueue
)
1944 QUEUE_Unlock( pOldActiveQueue
);
1946 WIN_ReleaseWndPtr(wndPtr
);
1950 /*******************************************************************
1951 * WINPOS_ActivateOtherWindow
1953 * Activates window other than pWnd.
1955 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1959 HWND hwndActive
= 0;
1961 /* Get current active window from the active queue */
1964 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1967 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1968 QUEUE_Unlock( pActiveQueue
);
1972 if( pWnd
->hwndSelf
== hwndPrevActive
)
1975 if( hwndActive
!= pWnd
->hwndSelf
&&
1976 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1979 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1980 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1982 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1984 WIN_ReleaseWndPtr(pWndTo
);
1985 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1987 while( !WINPOS_CanActivate(pWndTo
) )
1989 /* by now owned windows should've been taken care of */
1990 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1991 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1992 if( !pWndTo
) break;
1994 WIN_ReleaseWndPtr(pWndPtr
);
1997 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1999 /* switch desktop queue to current active */
2002 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
2003 WIN_ReleaseWndPtr(pWndTo
);
2004 WIN_ReleaseDesktop();
2011 /*******************************************************************
2012 * WINPOS_ChangeActiveWindow
2015 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
2017 WND
*wndPtr
, *wndTemp
;
2019 HWND hwndActive
= 0;
2021 /* Get current active window from the active queue */
2024 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2027 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2028 QUEUE_Unlock( pActiveQueue
);
2033 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
2035 wndPtr
= WIN_FindWndPtr(hWnd
);
2036 if( !wndPtr
) return FALSE
;
2038 /* child windows get WM_CHILDACTIVATE message */
2039 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2041 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
2045 if( hWnd
== hwndActive
)
2051 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
2057 /* switch desktop queue to current active */
2058 wndTemp
= WIN_GetDesktop();
2059 if( wndPtr
->parent
== wndTemp
)
2060 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
2061 WIN_ReleaseDesktop();
2065 WIN_ReleaseWndPtr(wndPtr
);
2070 /***********************************************************************
2071 * WINPOS_SendNCCalcSize
2073 * Send a WM_NCCALCSIZE message to a window.
2074 * All parameters are read-only except newClientRect.
2075 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2076 * when calcValidRect is TRUE.
2078 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2079 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2080 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2081 RECT
*newClientRect
)
2083 NCCALCSIZE_PARAMS params
;
2084 WINDOWPOS winposCopy
;
2087 params
.rgrc
[0] = *newWindowRect
;
2090 winposCopy
= *winpos
;
2091 params
.rgrc
[1] = *oldWindowRect
;
2092 params
.rgrc
[2] = *oldClientRect
;
2093 params
.lppos
= &winposCopy
;
2095 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2097 TRACE("%d,%d-%d,%d\n",
2098 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2099 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2101 /* If the application send back garbage, ignore it */
2102 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2103 *newClientRect
= params
.rgrc
[0];
2109 /***********************************************************************
2110 * WINPOS_HandleWindowPosChanging16
2112 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2114 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2116 POINT maxSize
, minTrack
;
2117 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2118 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2119 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2121 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2122 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2123 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2124 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2126 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2127 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2134 /***********************************************************************
2135 * WINPOS_HandleWindowPosChanging
2137 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2139 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2142 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2143 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2144 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2146 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2147 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
2148 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
2153 /***********************************************************************
2156 * fix Z order taking into account owned popups -
2157 * basically we need to maintain them above the window that owns them
2159 * FIXME: hide/show owned popups when owner visibility changes.
2161 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2163 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2165 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2167 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2169 /* make sure this popup stays above the owner */
2171 HWND hwndLocalPrev
= HWND_TOP
;
2173 if( hwndInsertAfter
!= HWND_TOP
)
2175 while( w
!= wndPtr
->owner
)
2177 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2178 if( hwndLocalPrev
== hwndInsertAfter
) break;
2179 WIN_UpdateWndPtr(&w
,w
->next
);
2181 hwndInsertAfter
= hwndLocalPrev
;
2184 else if( wndPtr
->dwStyle
& WS_CHILD
)
2187 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2191 if( w
== wndPtr
) break;
2193 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2195 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2196 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2197 hwndInsertAfter
= w
->hwndSelf
;
2199 WIN_UpdateWndPtr(&w
, w
->next
);
2203 WIN_ReleaseWndPtr(w
);
2204 return hwndInsertAfter
;
2207 /***********************************************************************
2210 * Make window look nice without excessive repainting
2212 * visible and update regions are in window coordinates
2213 * client and window rectangles are in parent client coordinates
2215 * Returns: uFlags and a dirty region in *pVisRgn.
2217 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2218 LPRECT lpOldWndRect
,
2219 LPRECT lpOldClientRect
, UINT uFlags
)
2222 HRGN newVisRgn
, dirtyRgn
;
2223 INT my
= COMPLEXREGION
;
2225 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2226 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2227 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2228 lpOldWndRect
->left
, lpOldWndRect
->top
,
2229 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2230 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2231 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2232 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2233 lpOldClientRect
->left
, lpOldClientRect
->top
,
2234 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2236 if( Wnd
->hrgnUpdate
== 1 )
2237 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2239 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2240 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2242 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2243 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2245 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2249 TRACE("\twon't copy anything!\n");
2251 /* set dirtyRgn to the sum of old and new visible regions
2252 * in parent client coordinates */
2254 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2255 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2257 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2259 else /* copy valid bits to a new location */
2261 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2262 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2264 /* subtract already invalid region inside Wnd from the dst region */
2266 if( Wnd
->hrgnUpdate
)
2267 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2270 /* check if entire window can be copied */
2272 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2273 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2274 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2275 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2277 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2278 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2279 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2280 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2282 if( (ocw
!= ncw
) || (och
!= nch
) ||
2283 ( ow
!= nw
) || ( oh
!= nh
) ||
2284 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2285 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2286 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2287 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2289 if(uFlags
& SWP_EX_PAINTSELF
)
2291 /* movement relative to the window itself */
2292 dx
= (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
) -
2293 (lpOldClientRect
->left
- lpOldWndRect
->left
) ;
2294 dy
= (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
) -
2295 (lpOldClientRect
->top
- lpOldWndRect
->top
) ;
2299 /* movement relative to the parent's client area */
2300 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2301 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2304 /* restrict valid bits to the common client rect */
2306 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2307 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2308 r
.right
= r
.left
+ min( ocw
, ncw
);
2309 r
.bottom
= r
.top
+ min( och
, nch
);
2311 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2312 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2313 GetRgnBox( hrgnValid
, &r
);
2314 if( IsRectEmpty( &r
) )
2316 r
= *lpOldClientRect
;
2320 if(uFlags
& SWP_EX_PAINTSELF
) {
2322 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2323 * relative to itself, only the client area can change.
2324 * if the client rect didn't change, there's nothing to do.
2331 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2332 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2333 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2338 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2340 /* Move remaining regions to parent coordinates */
2341 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2342 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2345 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2347 TRACE("\tcomputing dirty region!\n");
2349 /* Compute combined dirty region (old + new - valid) */
2350 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2351 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2353 /* Blt valid bits, r is the rect to copy */
2360 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2361 from copying clipped areas */
2363 if( uFlags
& SWP_EX_PAINTSELF
)
2365 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2366 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2367 rClip
.right
= nw
; rClip
.bottom
= nh
;
2371 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2372 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2373 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2374 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2376 rClip
.left
= rClip
.top
= 0;
2378 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2379 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2381 if( IntersectRect( &r
, &r
, &rClip
) )
2383 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, hDC
, dx
, dy
, &r
, TRUE
);
2385 /* When you copy the bits without repainting, parent doesn't
2386 get validated appropriately. Therefore, we have to validate
2387 the parent with the windows' updated region when the
2388 parent's update region is not empty. */
2390 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2392 OffsetRect(&r
, dx
, dy
);
2393 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2396 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2397 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2401 /* *pVisRgn now points to the invalidated region */
2403 DeleteObject(newVisRgn
);
2404 DeleteObject(dirtyRgn
);
2408 /***********************************************************************
2409 * SWP_DoSimpleFrameChanged
2411 * NOTE: old and new client rect origins are identical, only
2412 * extents may have changed. Window extents are the same.
2414 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2420 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2422 /* Client rect changed its position/size, most likely a scrollar
2423 * was added/removed.
2425 * FIXME: WVR alignment flags
2428 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2432 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2433 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2434 if(!(uFlags
& SWP_EX_NOCOPY
))
2435 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2443 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2446 hrgn
= CreateRectRgnIndirect( &rect
);
2448 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2449 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2450 if(!(uFlags
& SWP_EX_NOCOPY
))
2451 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2455 REGION_UnionRectWithRgn( hrgn
, &rect
);
2458 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2460 rect
= wndPtr
->rectWindow
;
2461 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2462 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2470 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2471 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2475 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2479 DeleteObject( hrgn
);
2482 /***********************************************************************
2483 * SWP_DoWinPosChanging
2485 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2486 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2488 /* Send WM_WINDOWPOSCHANGING message */
2490 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2491 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2493 /* Calculate new position and size */
2495 *pNewWindowRect
= wndPtr
->rectWindow
;
2496 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2497 : wndPtr
->rectClient
;
2499 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2501 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2502 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2504 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2506 pNewWindowRect
->left
= pWinpos
->x
;
2507 pNewWindowRect
->top
= pWinpos
->y
;
2508 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2509 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2511 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2512 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2515 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2519 /***********************************************************************
2522 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2523 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2527 /* Send WM_NCCALCSIZE message to get new client area */
2528 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2530 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2531 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2532 pWinpos
, pNewClientRect
);
2534 /* FIXME: WVR_ALIGNxxx */
2536 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2537 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2538 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2540 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2541 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2542 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2543 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2544 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2547 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2548 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2549 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2553 /***********************************************************************
2554 * SetWindowPos (USER.2)
2556 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2557 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2559 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2562 /***********************************************************************
2563 * SetWindowPos (USER32.520)
2565 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2566 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2569 WND
* wndPtr
,*wndTemp
;
2570 RECT newWindowRect
, newClientRect
;
2571 RECT oldWindowRect
, oldClientRect
;
2573 UINT wvrFlags
= 0, uFlags
= 0;
2574 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2575 HWND hwndActive
= 0;
2577 /* Get current active window from the active queue */
2580 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2583 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2584 QUEUE_Unlock( pActiveQueue
);
2588 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2589 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2591 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2592 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2595 /* ------------------------------------------------------------------------ CHECKS */
2597 /* Check window handle */
2599 if (hwnd
== GetDesktopWindow()) return FALSE
;
2600 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2602 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2603 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2605 /* Fix redundant flags */
2607 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2608 flags
&= ~SWP_SHOWWINDOW
;
2611 if (!(flags
& SWP_SHOWWINDOW
))
2612 flags
|= SWP_NOREDRAW
;
2613 flags
&= ~SWP_HIDEWINDOW
;
2616 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2618 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2619 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2620 flags
|= SWP_NOSIZE
; /* Already the right size */
2622 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2623 flags
|= SWP_NOMOVE
; /* Already the right position */
2625 if (hwnd
== hwndActive
)
2626 flags
|= SWP_NOACTIVATE
; /* Already active */
2627 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2629 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2631 flags
&= ~SWP_NOZORDER
;
2632 hwndInsertAfter
= HWND_TOP
;
2637 /* Check hwndInsertAfter */
2639 /* FIXME: TOPMOST not supported yet */
2640 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2641 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2643 /* hwndInsertAfter must be a sibling of the window */
2644 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2646 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2649 if( wnd
->parent
!= wndPtr
->parent
)
2652 WIN_ReleaseWndPtr(wnd
);
2655 /* don't need to change the Zorder of hwnd if it's already inserted
2656 * after hwndInsertAfter or when inserting hwnd after itself.
2658 if(( wnd
->next
== wndPtr
) || (hwnd
== hwndInsertAfter
)) flags
|= SWP_NOZORDER
;
2660 WIN_ReleaseWndPtr(wnd
);
2663 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2665 /* Fill the WINDOWPOS structure */
2668 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2673 winpos
.flags
= flags
;
2675 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2677 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2679 if( wndPtr
->parent
== WIN_GetDesktop() )
2680 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2681 hwndInsertAfter
, winpos
.flags
);
2682 WIN_ReleaseDesktop();
2685 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2687 if( hwndInsertAfter
== HWND_TOP
)
2688 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2690 if( hwndInsertAfter
== HWND_BOTTOM
)
2691 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2693 if( !(winpos
.flags
& SWP_NOZORDER
) )
2694 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2695 winpos
.flags
|= SWP_NOZORDER
;
2697 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2698 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2699 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2701 /* get a previous visible region for SWP_CopyValidBits() */
2702 DWORD dflags
= DCX_WINDOW
;
2704 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2705 dflags
|= DCX_CLIPSIBLINGS
;
2707 visRgn
= DCE_GetVisRgn(hwnd
, dflags
, 0, 0);
2711 /* Common operations */
2713 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2715 if(!(winpos
.flags
& SWP_NOZORDER
) && winpos
.hwnd
!= hwndInsertAfter
)
2717 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2718 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2721 /* Reset active DCEs */
2723 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2724 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2725 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2729 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2730 DCE_InvalidateDCE(wndPtr
, &rect
);
2733 oldWindowRect
= wndPtr
->rectWindow
;
2734 oldClientRect
= wndPtr
->rectClient
;
2736 /* Find out if we have to redraw the whole client rect */
2738 if( oldClientRect
.bottom
- oldClientRect
.top
==
2739 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2741 if( oldClientRect
.right
- oldClientRect
.left
==
2742 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2744 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2745 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2747 uFlags
|= SWP_EX_NOCOPY
;
2750 * Use this later in CopyValidBits()
2753 uFlags |= SWP_EX_NONCLIENT;
2756 /* FIXME: actually do something with WVR_VALIDRECTS */
2758 wndPtr
->rectWindow
= newWindowRect
;
2759 wndPtr
->rectClient
= newClientRect
;
2761 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2763 BOOL bCallDriver
= TRUE
;
2764 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2766 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2768 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2770 /* This is the only place where we need to force repainting of the contents
2771 of windows created by the host window system, all other cases go through the
2772 expose event handling */
2774 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2776 cx
= newWindowRect
.right
- newWindowRect
.left
;
2777 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2779 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2780 winpos
.hwndInsertAfter
= tempInsertAfter
;
2781 bCallDriver
= FALSE
;
2783 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2784 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2787 /* client area moved but window extents remained the same, copy valid bits */
2789 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2790 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2791 uFlags
| SWP_EX_PAINTSELF
);
2798 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2800 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2801 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2802 !(uFlags
& SWP_EX_NOCOPY
) )
2804 /* The origin of the client rect didn't move so we can try to repaint
2805 * only the nonclient area by setting bit gravity hint for the host window system.
2808 if( !(wndPtr
->dwExStyle
& WS_EX_MANAGED
) )
2810 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2811 newWindowRect
.bottom
- newWindowRect
.top
);
2812 RECT rcn
= newClientRect
;
2813 RECT rco
= oldClientRect
;
2815 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2816 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2817 IntersectRect( &rcn
, &rcn
, &rco
);
2818 visRgn
= CreateRectRgnIndirect( &rcn
);
2819 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2820 DeleteObject( hrgn
);
2821 uFlags
= SWP_EX_PAINTSELF
;
2823 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2826 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2829 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2830 winpos
.hwndInsertAfter
= tempInsertAfter
;
2833 if( winpos
.flags
& SWP_SHOWWINDOW
)
2837 wndPtr
->dwStyle
|= WS_VISIBLE
;
2839 if (wndPtr
->dwExStyle
& WS_EX_MANAGED
) resync
= TRUE
;
2841 /* focus was set to unmapped window, reset host focus
2842 * since the window is now visible */
2844 focus
= curr
= GetFocus();
2849 WND
*pFocus
= WIN_FindWndPtr( focus
);
2851 pFocus
->pDriver
->pSetFocus(pFocus
);
2852 WIN_ReleaseWndPtr(pFocus
);
2855 curr
= GetParent(curr
);
2859 else /* -------------------------------------------- emulated window */
2861 if( winpos
.flags
& SWP_SHOWWINDOW
)
2863 wndPtr
->dwStyle
|= WS_VISIBLE
;
2864 uFlags
|= SWP_EX_PAINTSELF
;
2865 visRgn
= 1; /* redraw the whole window */
2867 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2869 if( winpos
.flags
& SWP_HIDEWINDOW
)
2871 if( visRgn
> 1 ) /* map to parent */
2872 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2878 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2880 /* if window was not resized and not moved try to repaint itself */
2881 if((winpos
.flags
& SWP_AGG_NOGEOMETRYCHANGE
) == SWP_AGG_NOGEOMETRYCHANGE
)
2882 uFlags
|= SWP_EX_PAINTSELF
;
2883 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2884 &oldClientRect
, uFlags
);
2888 /* nothing moved, redraw frame if needed */
2890 if( winpos
.flags
& SWP_FRAMECHANGED
)
2891 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2894 DeleteObject( visRgn
);
2902 if( winpos
.flags
& SWP_HIDEWINDOW
)
2904 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2907 if (hwnd
== CARET_GetHwnd())
2909 if( winpos
.flags
& SWP_HIDEWINDOW
)
2911 else if (winpos
.flags
& SWP_SHOWWINDOW
)
2915 /* ------------------------------------------------------------------------ FINAL */
2917 if (wndPtr
->flags
& WIN_NATIVE
)
2918 EVENT_Synchronize(); /* Synchronize with the host window system */
2920 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2922 /* Simulate a mouse event to set the cursor */
2923 int iWndsLocks
= WIN_SuspendWndsLock();
2925 hardware_event( WM_MOUSEMOVE
, GET_KEYSTATE(), 0,
2926 PosX
, PosY
, GetTickCount(), 0 );
2928 WIN_RestoreWndsLock(iWndsLocks
);
2931 wndTemp
= WIN_GetDesktop();
2933 /* repaint invalidated region (if any)
2935 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2936 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2941 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2944 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2945 its parent and sibling and so on, and then erase the parent window
2946 back ground if the parent is either a top-level window or its parent's parent
2947 is top-level window. Rely on the system to repaint other affected
2948 windows later on. */
2949 if( uFlags
& SWP_EX_PAINTSELF
)
2951 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2952 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2953 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2957 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2958 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2962 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2964 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2965 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2969 DeleteObject( visRgn
);
2972 WIN_ReleaseDesktop();
2974 if (!(flags
& SWP_NOACTIVATE
))
2975 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2977 /* And last, send the WM_WINDOWPOSCHANGED message */
2979 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2982 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2983 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2985 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2986 if (resync
) EVENT_Synchronize();
2991 WIN_ReleaseWndPtr(wndPtr
);
2996 /***********************************************************************
2997 * BeginDeferWindowPos16 (USER.259)
2999 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
3001 return BeginDeferWindowPos( count
);
3005 /***********************************************************************
3006 * BeginDeferWindowPos (USER32.9)
3008 HDWP WINAPI
BeginDeferWindowPos( INT count
)
3015 SetLastError(ERROR_INVALID_PARAMETER
);
3018 /* Windows allows zero count, in which case it allocates context for 8 moves */
3019 if (count
== 0) count
= 8;
3021 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
3022 if (!handle
) return 0;
3023 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
3024 pDWP
->actualCount
= 0;
3025 pDWP
->suggestedCount
= count
;
3027 pDWP
->wMagic
= DWP_MAGIC
;
3028 pDWP
->hwndParent
= 0;
3033 /***********************************************************************
3034 * DeferWindowPos16 (USER.260)
3036 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
3037 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
3040 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
3041 x
, y
, cx
, cy
, flags
);
3045 /***********************************************************************
3046 * DeferWindowPos (USER32.128)
3048 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
3049 INT x
, INT y
, INT cx
, INT cy
,
3054 HDWP newhdwp
= hdwp
,retvalue
;
3058 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3059 if (!pDWP
) return 0;
3060 if (hwnd
== GetDesktopWindow()) return 0;
3062 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
3063 USER_HEAP_FREE( hdwp
);
3067 /* Numega Bounds Checker Demo dislikes the following code.
3068 In fact, I've not been able to find any "same parent" requirement in any docu
3072 /* All the windows of a DeferWindowPos() must have the same parent */
3073 parent
= pWnd
->parent
->hwndSelf
;
3074 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
3075 else if (parent
!= pDWP
->hwndParent
)
3077 USER_HEAP_FREE( hdwp
);
3083 for (i
= 0; i
< pDWP
->actualCount
; i
++)
3085 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
3087 /* Merge with the other changes */
3088 if (!(flags
& SWP_NOZORDER
))
3090 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3092 if (!(flags
& SWP_NOMOVE
))
3094 pDWP
->winPos
[i
].x
= x
;
3095 pDWP
->winPos
[i
].y
= y
;
3097 if (!(flags
& SWP_NOSIZE
))
3099 pDWP
->winPos
[i
].cx
= cx
;
3100 pDWP
->winPos
[i
].cy
= cy
;
3102 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3103 SWP_NOZORDER
| SWP_NOREDRAW
|
3104 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3106 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3112 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3114 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3115 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3121 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3122 pDWP
->suggestedCount
++;
3124 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3125 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3126 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3127 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3128 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3129 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3130 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3131 pDWP
->actualCount
++;
3134 WIN_ReleaseWndPtr(pWnd
);
3139 /***********************************************************************
3140 * EndDeferWindowPos16 (USER.261)
3142 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3144 return EndDeferWindowPos( hdwp
);
3148 /***********************************************************************
3149 * EndDeferWindowPos (USER32.173)
3151 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3158 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3159 if (!pDWP
) return FALSE
;
3160 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3162 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3163 winpos
->x
, winpos
->y
, winpos
->cx
,
3164 winpos
->cy
, winpos
->flags
))) break;
3166 USER_HEAP_FREE( hdwp
);
3171 /***********************************************************************
3172 * TileChildWindows (USER.199)
3174 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3176 FIXME("(%04x, %d): stub\n", parent
, action
);
3179 /***********************************************************************
3180 * CascadeChildWindows (USER.198)
3182 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3184 FIXME("(%04x, %d): stub\n", parent
, action
);
3187 /***********************************************************************
3188 * SetProgmanWindow [USER32.522]
3190 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3192 hGlobalProgmanWindow
= hwnd
;
3193 return hGlobalProgmanWindow
;
3196 /***********************************************************************
3197 * GetProgmanWindow [USER32.289]
3199 HRESULT WINAPI
GetProgmanWindow ( )
3201 return hGlobalProgmanWindow
;
3204 /***********************************************************************
3205 * SetShellWindowEx [USER32.531]
3206 * hwndProgman = Progman[Program Manager]
3207 * |-> SHELLDLL_DefView
3208 * hwndListView = | |-> SysListView32
3209 * | | |-> tooltips_class32
3215 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3217 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3218 hGlobalShellWindow
= hwndProgman
;
3219 return hGlobalShellWindow
;
3223 /***********************************************************************
3224 * SetTaskmanWindow [USER32.537]
3226 * hwnd = MSTaskSwWClass
3227 * |-> SysTabControl32
3229 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3231 hGlobalTaskmanWindow
= hwnd
;
3232 return hGlobalTaskmanWindow
;
3235 /***********************************************************************
3236 * GetTaskmanWindow [USER32.304]
3238 HRESULT WINAPI
GetTaskmanWindow ( )
3240 return hGlobalTaskmanWindow
;