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
);
313 /* delete previous region */
314 DeleteObject(wndPtr
->hrgnWnd
);
318 /* we'd like to set it back to 0 */
321 GetWindowRect(hwnd
, &tempRect
);
325 /* verify that region really exists */
326 if (GetRgnBox(hrgn
, &tempRect
) == ERROR
) goto done
;
329 /* valid region handle */
330 wndPtr
->hrgnWnd
= hrgn
;
331 SetWindowPos( hwnd
, NULL
, tempRect
.left
, tempRect
.top
,
332 tempRect
.right
- tempRect
.left
, tempRect
.bottom
- tempRect
.top
,
333 SWP_NOSIZE
| SWP_FRAMECHANGED
| SWP_NOMOVE
|
334 SWP_NOZORDER
| (bRedraw
? 0 : SWP_NOREDRAW
) );
336 wndPtr
->pDriver
->pSetWindowRgn(wndPtr
, hrgn
);
341 WIN_ReleaseWndPtr(wndPtr
);
345 /***********************************************************************
348 INT16 WINAPI
SetWindowRgn16( HWND16 hwnd
, HRGN16 hrgn
,BOOL16 bRedraw
)
352 FIXME("SetWindowRgn16: stub\n");
357 /***********************************************************************
358 * GetClientRect16 (USER.33)
360 void WINAPI
GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
362 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
364 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
367 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
368 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
370 WIN_ReleaseWndPtr(wndPtr
);
374 /***********************************************************************
375 * GetClientRect (USER.220)
377 BOOL WINAPI
GetClientRect( HWND hwnd
, LPRECT rect
)
379 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
381 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
382 if (!wndPtr
) return FALSE
;
383 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
384 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
386 WIN_ReleaseWndPtr(wndPtr
);
391 /*******************************************************************
392 * ClientToScreen16 (USER.28)
394 void WINAPI
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
396 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
400 /*******************************************************************
401 * ClientToScreen (USER32.52)
403 BOOL WINAPI
ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
405 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
410 /*******************************************************************
411 * ScreenToClient16 (USER.29)
413 void WINAPI
ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
415 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
419 /*******************************************************************
420 * ScreenToClient (USER32.447)
422 BOOL WINAPI
ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
424 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
429 /***********************************************************************
430 * WINPOS_WindowFromPoint
432 * Find the window and hittest for a given point.
434 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
437 INT16 hittest
= HTERROR
;
441 TRACE("scope %04x %d,%d\n", wndScope
->hwndSelf
, pt
.x
, pt
.y
);
443 wndPtr
= WIN_LockWndPtr(wndScope
->child
);
445 if( wndScope
->dwStyle
& WS_DISABLED
)
451 if( wndScope
->flags
& WIN_MANAGED
)
453 /* In managed mode we have to check wndScope first as it is also
454 * a window which received the mouse event. */
456 if( pt
.x
< wndScope
->rectClient
.left
|| pt
.x
>= wndScope
->rectClient
.right
||
457 pt
.y
< wndScope
->rectClient
.top
|| pt
.y
>= wndScope
->rectClient
.bottom
)
460 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
466 /* If point is in window, and window is visible, and it */
467 /* is enabled (or it's a top-level window), then explore */
468 /* its children. Otherwise, go to the next window. */
470 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
471 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
472 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
474 PtInRegion(wndPtr
->hrgnWnd
, xy
.x
- wndPtr
->rectWindow
.left
,
475 xy
.y
- wndPtr
->rectWindow
.top
) :
476 ((xy
.x
>= wndPtr
->rectWindow
.left
) &&
477 (xy
.x
< wndPtr
->rectWindow
.right
) &&
478 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
479 (xy
.y
< wndPtr
->rectWindow
.bottom
))))
481 TRACE("%d,%d is inside %04x\n", xy
.x
, xy
.y
, wndPtr
->hwndSelf
);
482 *ppWnd
= wndPtr
; /* Got a suitable window */
484 /* If window is minimized or disabled, return at once */
485 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
487 retvalue
= HTCAPTION
;
490 if (wndPtr
->dwStyle
& WS_DISABLED
)
496 /* If point is not in client area, ignore the children */
497 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
498 (xy
.x
>= wndPtr
->rectClient
.right
) ||
499 (xy
.y
< wndPtr
->rectClient
.top
) ||
500 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
502 xy
.x
-= wndPtr
->rectClient
.left
;
503 xy
.y
-= wndPtr
->rectClient
.top
;
504 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->child
);
508 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->next
);
513 /* If nothing found, try the scope window */
514 if (!*ppWnd
) *ppWnd
= wndScope
;
516 /* Send the WM_NCHITTEST message (only if to the same task) */
517 if ((*ppWnd
)->hmemTaskQ
== GetFastQueue16())
519 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
520 0, MAKELONG( pt
.x
, pt
.y
) );
521 if (hittest
!= HTTRANSPARENT
)
523 retvalue
= hittest
; /* Found the window */
533 /* If no children found in last search, make point relative to parent */
536 xy
.x
+= (*ppWnd
)->rectClient
.left
;
537 xy
.y
+= (*ppWnd
)->rectClient
.top
;
540 /* Restart the search from the next sibling */
541 WIN_UpdateWndPtr(&wndPtr
,(*ppWnd
)->next
);
542 *ppWnd
= (*ppWnd
)->parent
;
546 WIN_ReleaseWndPtr(wndPtr
);
551 /*******************************************************************
552 * WindowFromPoint16 (USER.30)
554 HWND16 WINAPI
WindowFromPoint16( POINT16 pt
)
557 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
558 WIN_ReleaseDesktop();
559 return pWnd
->hwndSelf
;
563 /*******************************************************************
564 * WindowFromPoint (USER32.582)
566 HWND WINAPI
WindowFromPoint( POINT pt
)
570 CONV_POINT32TO16( &pt
, &pt16
);
571 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
572 WIN_ReleaseDesktop();
573 return (HWND
)pWnd
->hwndSelf
;
577 /*******************************************************************
578 * ChildWindowFromPoint16 (USER.191)
580 HWND16 WINAPI
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
583 CONV_POINT16TO32( &pt
, &pt32
);
584 return (HWND16
)ChildWindowFromPoint( hwndParent
, pt32
);
588 /*******************************************************************
589 * ChildWindowFromPoint (USER32.49)
591 HWND WINAPI
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
593 /* pt is in the client coordinates */
595 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
601 /* get client rect fast */
602 rect
.top
= rect
.left
= 0;
603 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
604 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
606 if (!PtInRect( &rect
, pt
))
611 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
614 if (PtInRect( &wnd
->rectWindow
, pt
))
616 retvalue
= wnd
->hwndSelf
;
619 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
621 retvalue
= hwndParent
;
623 WIN_ReleaseWndPtr(wnd
);
627 /*******************************************************************
628 * ChildWindowFromPointEx16 (USER.50)
630 HWND16 WINAPI
ChildWindowFromPointEx16( HWND16 hwndParent
, POINT16 pt
, UINT16 uFlags
)
633 CONV_POINT16TO32( &pt
, &pt32
);
634 return (HWND16
)ChildWindowFromPointEx( hwndParent
, pt32
, uFlags
);
638 /*******************************************************************
639 * ChildWindowFromPointEx (USER32.50)
641 HWND WINAPI
ChildWindowFromPointEx( HWND hwndParent
, POINT pt
,
644 /* pt is in the client coordinates */
646 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
652 /* get client rect fast */
653 rect
.top
= rect
.left
= 0;
654 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
655 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
657 if (!PtInRect( &rect
, pt
))
662 WIN_UpdateWndPtr(&wnd
,wnd
->child
);
666 if (PtInRect( &wnd
->rectWindow
, pt
)) {
667 if ( (uFlags
& CWP_SKIPINVISIBLE
) &&
668 !(wnd
->dwStyle
& WS_VISIBLE
) );
669 else if ( (uFlags
& CWP_SKIPDISABLED
) &&
670 (wnd
->dwStyle
& WS_DISABLED
) );
671 else if ( (uFlags
& CWP_SKIPTRANSPARENT
) &&
672 (wnd
->dwExStyle
& WS_EX_TRANSPARENT
) );
675 retvalue
= wnd
->hwndSelf
;
680 WIN_UpdateWndPtr(&wnd
,wnd
->next
);
682 retvalue
= hwndParent
;
684 WIN_ReleaseWndPtr(wnd
);
689 /*******************************************************************
690 * WINPOS_GetWinOffset
692 * Calculate the offset between the origin of the two windows. Used
693 * to implement MapWindowPoints.
695 static void WINPOS_GetWinOffset( HWND hwndFrom
, HWND hwndTo
,
700 offset
->x
= offset
->y
= 0;
701 if (hwndFrom
== hwndTo
) return;
703 /* Translate source window origin to screen coords */
706 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
708 ERR("bad hwndFrom = %04x\n",hwndFrom
);
711 while (wndPtr
->parent
)
713 offset
->x
+= wndPtr
->rectClient
.left
;
714 offset
->y
+= wndPtr
->rectClient
.top
;
715 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
717 WIN_ReleaseWndPtr(wndPtr
);
720 /* Translate origin to destination window coords */
723 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
725 ERR("bad hwndTo = %04x\n", hwndTo
);
728 while (wndPtr
->parent
)
730 offset
->x
-= wndPtr
->rectClient
.left
;
731 offset
->y
-= wndPtr
->rectClient
.top
;
732 WIN_UpdateWndPtr(&wndPtr
,wndPtr
->parent
);
734 WIN_ReleaseWndPtr(wndPtr
);
739 /*******************************************************************
740 * MapWindowPoints16 (USER.258)
742 void WINAPI
MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
743 LPPOINT16 lppt
, UINT16 count
)
747 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
757 /*******************************************************************
758 * MapWindowPoints (USER32.386)
760 INT WINAPI
MapWindowPoints( HWND hwndFrom
, HWND hwndTo
,
761 LPPOINT lppt
, UINT count
)
765 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
772 return MAKELONG( LOWORD(offset
.x
), LOWORD(offset
.y
) );
776 /***********************************************************************
777 * IsIconic16 (USER.31)
779 BOOL16 WINAPI
IsIconic16(HWND16 hWnd
)
781 return IsIconic(hWnd
);
785 /***********************************************************************
786 * IsIconic (USER32.345)
788 BOOL WINAPI
IsIconic(HWND hWnd
)
791 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
792 if (wndPtr
== NULL
) return FALSE
;
793 retvalue
= (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
794 WIN_ReleaseWndPtr(wndPtr
);
799 /***********************************************************************
800 * IsZoomed (USER.272)
802 BOOL16 WINAPI
IsZoomed16(HWND16 hWnd
)
804 return IsZoomed(hWnd
);
808 /***********************************************************************
809 * IsZoomed (USER.352)
811 BOOL WINAPI
IsZoomed(HWND hWnd
)
814 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
815 if (wndPtr
== NULL
) return FALSE
;
816 retvalue
= (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
817 WIN_ReleaseWndPtr(wndPtr
);
822 /*******************************************************************
823 * GetActiveWindow (USER.60)
825 HWND16 WINAPI
GetActiveWindow16(void)
827 return (HWND16
)GetActiveWindow();
830 /*******************************************************************
831 * GetActiveWindow (USER32.205)
833 HWND WINAPI
GetActiveWindow(void)
835 MESSAGEQUEUE
*pCurMsgQ
= 0;
838 /* Get the messageQ for the current thread */
839 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
841 WARN("\tCurrent message queue not found. Exiting!\n" );
845 /* Return the current active window from the perQ data of the current message Q */
846 hwndActive
= PERQDATA_GetActiveWnd( pCurMsgQ
->pQData
);
848 QUEUE_Unlock( pCurMsgQ
);
853 /*******************************************************************
856 static BOOL
WINPOS_CanActivate(WND
* pWnd
)
858 if( pWnd
&& ( (pWnd
->dwStyle
& (WS_DISABLED
| WS_VISIBLE
| WS_CHILD
))
859 == WS_VISIBLE
) ) return TRUE
;
864 /*******************************************************************
865 * SetActiveWindow16 (USER.59)
867 HWND16 WINAPI
SetActiveWindow16( HWND16 hwnd
)
869 return SetActiveWindow(hwnd
);
873 /*******************************************************************
874 * SetActiveWindow (USER32.463)
876 HWND WINAPI
SetActiveWindow( HWND hwnd
)
879 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
880 MESSAGEQUEUE
*pMsgQ
= 0, *pCurMsgQ
= 0;
882 if (!wndPtr
|| (wndPtr
->dwStyle
& (WS_DISABLED
| WS_CHILD
)))
888 /* Get the messageQ for the current thread */
889 if (!(pCurMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( GetFastQueue16() )))
891 WARN("\tCurrent message queue not found. Exiting!\n" );
895 /* Retrieve the message queue associated with this window */
896 pMsgQ
= (MESSAGEQUEUE
*)QUEUE_Lock( wndPtr
->hmemTaskQ
);
899 WARN("\tWindow message queue not found. Exiting!\n" );
903 /* Make sure that the window is associated with the calling threads
904 * message queue. It must share the same perQ data.
907 if ( pCurMsgQ
->pQData
!= pMsgQ
->pQData
)
910 /* Save current active window */
911 prev
= PERQDATA_GetActiveWnd( pMsgQ
->pQData
);
913 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
916 /* Unlock the queues before returning */
918 QUEUE_Unlock( pMsgQ
);
920 QUEUE_Unlock( pCurMsgQ
);
923 WIN_ReleaseWndPtr(wndPtr
);
928 /*******************************************************************
929 * GetForegroundWindow16 (USER.608)
931 HWND16 WINAPI
GetForegroundWindow16(void)
933 return (HWND16
)GetForegroundWindow();
937 /*******************************************************************
938 * SetForegroundWindow16 (USER.609)
940 BOOL16 WINAPI
SetForegroundWindow16( HWND16 hwnd
)
942 return SetForegroundWindow( hwnd
);
946 /*******************************************************************
947 * GetForegroundWindow (USER32.241)
949 HWND WINAPI
GetForegroundWindow(void)
953 /* Get the foreground window (active window of hActiveQueue) */
956 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
958 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
960 QUEUE_Unlock( pActiveQueue
);
966 /*******************************************************************
967 * SetForegroundWindow (USER32.482)
969 BOOL WINAPI
SetForegroundWindow( HWND hwnd
)
971 return WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
975 /*******************************************************************
976 * GetShellWindow16 (USER.600)
978 HWND16 WINAPI
GetShellWindow16(void)
980 return GetShellWindow();
983 /*******************************************************************
984 * SetShellWindow (USER32.504)
986 HWND WINAPI
SetShellWindow(HWND hwndshell
)
987 { WARN("(hWnd=%08x) semi stub\n",hwndshell
);
989 hGlobalShellWindow
= hwndshell
;
990 return hGlobalShellWindow
;
994 /*******************************************************************
995 * GetShellWindow (USER32.287)
997 HWND WINAPI
GetShellWindow(void)
998 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow
);
1000 return hGlobalShellWindow
;
1004 /***********************************************************************
1005 * BringWindowToTop16 (USER.45)
1007 BOOL16 WINAPI
BringWindowToTop16( HWND16 hwnd
)
1009 return BringWindowToTop(hwnd
);
1013 /***********************************************************************
1014 * BringWindowToTop (USER32.11)
1016 BOOL WINAPI
BringWindowToTop( HWND hwnd
)
1018 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
1022 /***********************************************************************
1023 * MoveWindow16 (USER.56)
1025 BOOL16 WINAPI
MoveWindow16( HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
1028 return MoveWindow(hwnd
,x
,y
,cx
,cy
,repaint
);
1032 /***********************************************************************
1033 * MoveWindow (USER32.399)
1035 BOOL WINAPI
MoveWindow( HWND hwnd
, INT x
, INT y
, INT cx
, INT cy
,
1038 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
1039 if (!repaint
) flags
|= SWP_NOREDRAW
;
1040 TRACE("%04x %d,%d %dx%d %d\n",
1041 hwnd
, x
, y
, cx
, cy
, repaint
);
1042 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
1045 /***********************************************************************
1046 * WINPOS_InitInternalPos
1048 static LPINTERNALPOS
WINPOS_InitInternalPos( WND
* wnd
, POINT pt
,
1049 LPRECT restoreRect
)
1051 LPINTERNALPOS lpPos
= (LPINTERNALPOS
) GetPropA( wnd
->hwndSelf
,
1055 /* this happens when the window is minimized/maximized
1056 * for the first time (rectWindow is not adjusted yet) */
1058 lpPos
= HeapAlloc( SystemHeap
, 0, sizeof(INTERNALPOS
) );
1059 if( !lpPos
) return NULL
;
1061 SetPropA( wnd
->hwndSelf
, atomInternalPos
, (HANDLE
)lpPos
);
1062 lpPos
->hwndIconTitle
= 0; /* defer until needs to be shown */
1063 CONV_RECT32TO16( &wnd
->rectWindow
, &lpPos
->rectNormal
);
1064 *(UINT
*)&lpPos
->ptIconPos
= *(UINT
*)&lpPos
->ptMaxPos
= 0xFFFFFFFF;
1067 if( wnd
->dwStyle
& WS_MINIMIZE
)
1068 CONV_POINT32TO16( &pt
, &lpPos
->ptIconPos
);
1069 else if( wnd
->dwStyle
& WS_MAXIMIZE
)
1070 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1071 else if( restoreRect
)
1072 CONV_RECT32TO16( restoreRect
, &lpPos
->rectNormal
);
1077 /***********************************************************************
1078 * WINPOS_RedrawIconTitle
1080 BOOL
WINPOS_RedrawIconTitle( HWND hWnd
)
1082 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( hWnd
, atomInternalPos
);
1085 if( lpPos
->hwndIconTitle
)
1087 SendMessageA( lpPos
->hwndIconTitle
, WM_SHOWWINDOW
, TRUE
, 0);
1088 InvalidateRect( lpPos
->hwndIconTitle
, NULL
, TRUE
);
1095 /***********************************************************************
1096 * WINPOS_ShowIconTitle
1098 BOOL
WINPOS_ShowIconTitle( WND
* pWnd
, BOOL bShow
)
1100 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)GetPropA( pWnd
->hwndSelf
, atomInternalPos
);
1102 if( lpPos
&& !(pWnd
->flags
& WIN_MANAGED
))
1104 HWND16 hWnd
= lpPos
->hwndIconTitle
;
1106 TRACE("0x%04x %i\n", pWnd
->hwndSelf
, (bShow
!= 0) );
1109 lpPos
->hwndIconTitle
= hWnd
= ICONTITLE_Create( pWnd
);
1112 if( ( pWnd
= WIN_FindWndPtr(hWnd
) ) != NULL
)
1114 if( !(pWnd
->dwStyle
& WS_VISIBLE
) )
1116 SendMessageA( hWnd
, WM_SHOWWINDOW
, TRUE
, 0 );
1117 SetWindowPos( hWnd
, 0, 0, 0, 0, 0, SWP_NOSIZE
| SWP_NOMOVE
|
1118 SWP_NOACTIVATE
| SWP_NOZORDER
| SWP_SHOWWINDOW
);
1120 WIN_ReleaseWndPtr(pWnd
);
1123 else ShowWindow( hWnd
, SW_HIDE
);
1128 /*******************************************************************
1129 * WINPOS_GetMinMaxInfo
1131 * Get the minimized and maximized information for a window.
1133 void WINPOS_GetMinMaxInfo( WND
*wndPtr
, POINT
*maxSize
, POINT
*maxPos
,
1134 POINT
*minTrack
, POINT
*maxTrack
)
1136 LPINTERNALPOS lpPos
;
1140 /* Compute default values */
1142 MinMax
.ptMaxSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1143 MinMax
.ptMaxSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1144 MinMax
.ptMinTrackSize
.x
= GetSystemMetrics(SM_CXMINTRACK
);
1145 MinMax
.ptMinTrackSize
.y
= GetSystemMetrics(SM_CYMINTRACK
);
1146 MinMax
.ptMaxTrackSize
.x
= GetSystemMetrics(SM_CXSCREEN
);
1147 MinMax
.ptMaxTrackSize
.y
= GetSystemMetrics(SM_CYSCREEN
);
1149 if (wndPtr
->flags
& WIN_MANAGED
) xinc
= yinc
= 0;
1150 else if (HAS_DLGFRAME( wndPtr
->dwStyle
, wndPtr
->dwExStyle
))
1152 xinc
= GetSystemMetrics(SM_CXDLGFRAME
);
1153 yinc
= GetSystemMetrics(SM_CYDLGFRAME
);
1158 if (HAS_THICKFRAME(wndPtr
->dwStyle
))
1160 xinc
+= GetSystemMetrics(SM_CXFRAME
);
1161 yinc
+= GetSystemMetrics(SM_CYFRAME
);
1163 if (wndPtr
->dwStyle
& WS_BORDER
)
1165 xinc
+= GetSystemMetrics(SM_CXBORDER
);
1166 yinc
+= GetSystemMetrics(SM_CYBORDER
);
1169 MinMax
.ptMaxSize
.x
+= 2 * xinc
;
1170 MinMax
.ptMaxSize
.y
+= 2 * yinc
;
1172 lpPos
= (LPINTERNALPOS
)GetPropA( wndPtr
->hwndSelf
, atomInternalPos
);
1173 if( lpPos
&& !EMPTYPOINT(lpPos
->ptMaxPos
) )
1174 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &MinMax
.ptMaxPosition
);
1177 MinMax
.ptMaxPosition
.x
= -xinc
;
1178 MinMax
.ptMaxPosition
.y
= -yinc
;
1181 SendMessageA( wndPtr
->hwndSelf
, WM_GETMINMAXINFO
, 0, (LPARAM
)&MinMax
);
1183 /* Some sanity checks */
1185 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1186 MinMax
.ptMaxSize
.x
, MinMax
.ptMaxSize
.y
,
1187 MinMax
.ptMaxPosition
.x
, MinMax
.ptMaxPosition
.y
,
1188 MinMax
.ptMaxTrackSize
.x
, MinMax
.ptMaxTrackSize
.y
,
1189 MinMax
.ptMinTrackSize
.x
, MinMax
.ptMinTrackSize
.y
);
1190 MinMax
.ptMaxTrackSize
.x
= max( MinMax
.ptMaxTrackSize
.x
,
1191 MinMax
.ptMinTrackSize
.x
);
1192 MinMax
.ptMaxTrackSize
.y
= max( MinMax
.ptMaxTrackSize
.y
,
1193 MinMax
.ptMinTrackSize
.y
);
1195 if (maxSize
) *maxSize
= MinMax
.ptMaxSize
;
1196 if (maxPos
) *maxPos
= MinMax
.ptMaxPosition
;
1197 if (minTrack
) *minTrack
= MinMax
.ptMinTrackSize
;
1198 if (maxTrack
) *maxTrack
= MinMax
.ptMaxTrackSize
;
1201 /***********************************************************************
1202 * WINPOS_MinMaximize
1204 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1205 * This function assumes that 'cmd' is different from the current window
1208 UINT
WINPOS_MinMaximize( WND
* wndPtr
, UINT16 cmd
, LPRECT16 lpRect
)
1212 LPINTERNALPOS lpPos
;
1214 TRACE("0x%04x %u\n", wndPtr
->hwndSelf
, cmd
);
1216 size
.x
= wndPtr
->rectWindow
.left
; size
.y
= wndPtr
->rectWindow
.top
;
1217 lpPos
= WINPOS_InitInternalPos( wndPtr
, size
, &wndPtr
->rectWindow
);
1219 if (lpPos
&& !HOOK_CallHooks16(WH_CBT
, HCBT_MINMAX
, wndPtr
->hwndSelf
, cmd
))
1221 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1223 if( !SendMessageA( wndPtr
->hwndSelf
, WM_QUERYOPEN
, 0, 0L ) )
1224 return (SWP_NOSIZE
| SWP_NOMOVE
);
1225 swpFlags
|= SWP_NOCOPYBITS
;
1230 if( wndPtr
->dwStyle
& WS_MAXIMIZE
)
1232 wndPtr
->flags
|= WIN_RESTORE_MAX
;
1233 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1236 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
1237 wndPtr
->dwStyle
|= WS_MINIMIZE
;
1239 if( wndPtr
->flags
& WIN_NATIVE
)
1240 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, TRUE
) )
1241 swpFlags
|= MINMAX_NOSWP
;
1243 lpPos
->ptIconPos
= WINPOS_FindIconPos( wndPtr
, lpPos
->ptIconPos
);
1245 SetRect16( lpRect
, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1246 GetSystemMetrics(SM_CXICON
), GetSystemMetrics(SM_CYICON
) );
1247 swpFlags
|= SWP_NOCOPYBITS
;
1251 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1252 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1253 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1255 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1257 if( wndPtr
->flags
& WIN_NATIVE
)
1258 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1259 swpFlags
|= MINMAX_NOSWP
;
1261 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1262 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1264 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1266 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1271 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
1273 if( wndPtr
->flags
& WIN_NATIVE
)
1274 if( wndPtr
->pDriver
->pSetHostAttr( wndPtr
, HAK_ICONICSTATE
, FALSE
) )
1275 swpFlags
|= MINMAX_NOSWP
;
1277 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
1278 WINPOS_ShowIconTitle( wndPtr
, FALSE
);
1280 if( wndPtr
->flags
& WIN_RESTORE_MAX
)
1282 /* Restore to maximized position */
1283 CONV_POINT16TO32( &lpPos
->ptMaxPos
, &pt
);
1284 WINPOS_GetMinMaxInfo( wndPtr
, &size
, &pt
, NULL
, NULL
);
1285 CONV_POINT32TO16( &pt
, &lpPos
->ptMaxPos
);
1286 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
1287 SetRect16( lpRect
, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
, size
.x
, size
.y
);
1292 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) ) return (UINT16
)(-1);
1293 else wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
1295 /* Restore to normal position */
1297 *lpRect
= lpPos
->rectNormal
;
1298 lpRect
->right
-= lpRect
->left
;
1299 lpRect
->bottom
-= lpRect
->top
;
1303 } else swpFlags
|= SWP_NOSIZE
| SWP_NOMOVE
;
1307 /***********************************************************************
1308 * ShowWindowAsync (USER32.535)
1310 * doesn't wait; returns immediately.
1311 * used by threads to toggle windows in other (possibly hanging) threads
1313 BOOL WINAPI
ShowWindowAsync( HWND hwnd
, INT cmd
)
1315 /* FIXME: does ShowWindow() return immediately ? */
1316 return ShowWindow(hwnd
, cmd
);
1320 /***********************************************************************
1321 * ShowWindow16 (USER.42)
1323 BOOL16 WINAPI
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
1325 return ShowWindow(hwnd
,cmd
);
1329 /***********************************************************************
1330 * ShowWindow (USER32.534)
1332 BOOL WINAPI
ShowWindow( HWND hwnd
, INT cmd
)
1334 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
1335 BOOL wasVisible
, showFlag
;
1336 RECT16 newPos
= {0, 0, 0, 0};
1339 if (!wndPtr
) return FALSE
;
1341 TRACE("hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
1343 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
1348 if (!wasVisible
) goto END
;;
1349 swp
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
1350 SWP_NOACTIVATE
| SWP_NOZORDER
;
1353 case SW_SHOWMINNOACTIVE
:
1354 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1356 case SW_SHOWMINIMIZED
:
1357 swp
|= SWP_SHOWWINDOW
;
1360 swp
|= SWP_FRAMECHANGED
;
1361 if( !(wndPtr
->dwStyle
& WS_MINIMIZE
) )
1362 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MINIMIZE
, &newPos
);
1363 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1366 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE */
1367 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1368 if( !(wndPtr
->dwStyle
& WS_MAXIMIZE
) )
1369 swp
|= WINPOS_MinMaximize( wndPtr
, SW_MAXIMIZE
, &newPos
);
1370 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1374 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1377 swp
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
1380 * ShowWindow has a little peculiar behavior that if the
1381 * window is already the topmost window, it will not
1384 if (GetTopWindow((HWND
)0)==hwnd
&& (wasVisible
|| GetActiveWindow() == hwnd
))
1385 swp
|= SWP_NOACTIVATE
;
1389 case SW_SHOWNOACTIVATE
:
1390 swp
|= SWP_NOZORDER
;
1391 if (GetActiveWindow()) swp
|= SWP_NOACTIVATE
;
1393 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
1394 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
1396 swp
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
1398 if( wndPtr
->dwStyle
& (WS_MINIMIZE
| WS_MAXIMIZE
) )
1399 swp
|= WINPOS_MinMaximize( wndPtr
, SW_RESTORE
, &newPos
);
1400 else swp
|= SWP_NOSIZE
| SWP_NOMOVE
;
1404 showFlag
= (cmd
!= SW_HIDE
);
1405 if (showFlag
!= wasVisible
)
1407 SendMessageA( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
1408 if (!IsWindow( hwnd
)) goto END
;
1411 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1412 !IsWindowVisible( wndPtr
->parent
->hwndSelf
) &&
1413 (swp
& (SWP_NOSIZE
| SWP_NOMOVE
)) == (SWP_NOSIZE
| SWP_NOMOVE
) )
1415 /* Don't call SetWindowPos() on invisible child windows */
1416 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1417 else wndPtr
->dwStyle
|= WS_VISIBLE
;
1421 /* We can't activate a child window */
1422 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
1423 !(wndPtr
->dwExStyle
& WS_EX_MDICHILD
))
1424 swp
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
1425 if (!(swp
& MINMAX_NOSWP
))
1427 SetWindowPos( hwnd
, HWND_TOP
, newPos
.left
, newPos
.top
,
1428 newPos
.right
, newPos
.bottom
, LOWORD(swp
) );
1431 /* FIXME: This will cause the window to be activated irrespective
1432 * of whether it is owned by the same thread. Has to be done
1436 if (hwnd
== GetActiveWindow())
1437 WINPOS_ActivateOtherWindow(wndPtr
);
1439 /* Revert focus to parent */
1440 if (hwnd
== GetFocus() || IsChild(hwnd
, GetFocus()))
1441 SetFocus( GetParent(hwnd
) );
1444 if (!IsWindow( hwnd
)) goto END
;
1445 else if( wndPtr
->dwStyle
& WS_MINIMIZE
) WINPOS_ShowIconTitle( wndPtr
, TRUE
);
1448 if (wndPtr
->flags
& WIN_NEED_SIZE
)
1450 /* should happen only in CreateWindowEx() */
1451 int wParam
= SIZE_RESTORED
;
1453 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
1454 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
1455 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
1456 SendMessageA( hwnd
, WM_SIZE
, wParam
,
1457 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
1458 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
1459 SendMessageA( hwnd
, WM_MOVE
, 0,
1460 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
1464 WIN_ReleaseWndPtr(wndPtr
);
1469 /***********************************************************************
1470 * GetInternalWindowPos16 (USER.460)
1472 UINT16 WINAPI
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
,
1475 WINDOWPLACEMENT16 wndpl
;
1476 if (GetWindowPlacement16( hwnd
, &wndpl
))
1478 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1479 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1480 return wndpl
.showCmd
;
1486 /***********************************************************************
1487 * GetInternalWindowPos (USER32.245)
1489 UINT WINAPI
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
,
1492 WINDOWPLACEMENT wndpl
;
1493 if (GetWindowPlacement( hwnd
, &wndpl
))
1495 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
1496 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
1497 return wndpl
.showCmd
;
1502 /***********************************************************************
1503 * GetWindowPlacement16 (USER.370)
1505 BOOL16 WINAPI
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
1507 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1508 LPINTERNALPOS lpPos
;
1510 if(!pWnd
) return FALSE
;
1512 lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1513 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1514 wndpl
->length
= sizeof(*wndpl
);
1515 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1516 wndpl
->showCmd
= SW_SHOWMINIMIZED
;
1518 wndpl
->showCmd
= ( pWnd
->dwStyle
& WS_MAXIMIZE
)
1519 ? SW_SHOWMAXIMIZED
: SW_SHOWNORMAL
;
1520 if( pWnd
->flags
& WIN_RESTORE_MAX
)
1521 wndpl
->flags
= WPF_RESTORETOMAXIMIZED
;
1524 wndpl
->ptMinPosition
= lpPos
->ptIconPos
;
1525 wndpl
->ptMaxPosition
= lpPos
->ptMaxPos
;
1526 wndpl
->rcNormalPosition
= lpPos
->rectNormal
;
1528 WIN_ReleaseWndPtr(pWnd
);
1533 /***********************************************************************
1534 * GetWindowPlacement (USER32.307)
1537 * Fails if wndpl->length of Win95 (!) apps is invalid.
1539 BOOL WINAPI
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*pwpl32
)
1543 WINDOWPLACEMENT16 wpl
;
1544 wpl
.length
= sizeof(wpl
);
1545 if( GetWindowPlacement16( hwnd
, &wpl
) )
1547 pwpl32
->length
= sizeof(*pwpl32
);
1548 pwpl32
->flags
= wpl
.flags
;
1549 pwpl32
->showCmd
= wpl
.showCmd
;
1550 CONV_POINT16TO32( &wpl
.ptMinPosition
, &pwpl32
->ptMinPosition
);
1551 CONV_POINT16TO32( &wpl
.ptMaxPosition
, &pwpl32
->ptMaxPosition
);
1552 CONV_RECT16TO32( &wpl
.rcNormalPosition
, &pwpl32
->rcNormalPosition
);
1560 /***********************************************************************
1561 * WINPOS_SetPlacement
1563 static BOOL
WINPOS_SetPlacement( HWND hwnd
, const WINDOWPLACEMENT16
*wndpl
,
1566 WND
*pWnd
= WIN_FindWndPtr( hwnd
);
1569 LPINTERNALPOS lpPos
= (LPINTERNALPOS
)WINPOS_InitInternalPos( pWnd
,
1570 *(LPPOINT
)&pWnd
->rectWindow
.left
, &pWnd
->rectWindow
);
1572 if( flags
& PLACE_MIN
) lpPos
->ptIconPos
= wndpl
->ptMinPosition
;
1573 if( flags
& PLACE_MAX
) lpPos
->ptMaxPos
= wndpl
->ptMaxPosition
;
1574 if( flags
& PLACE_RECT
) lpPos
->rectNormal
= wndpl
->rcNormalPosition
;
1576 if( pWnd
->dwStyle
& WS_MINIMIZE
)
1578 WINPOS_ShowIconTitle( pWnd
, FALSE
);
1579 if( wndpl
->flags
& WPF_SETMINPOSITION
&& !EMPTYPOINT(lpPos
->ptIconPos
))
1580 SetWindowPos( hwnd
, 0, lpPos
->ptIconPos
.x
, lpPos
->ptIconPos
.y
,
1581 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1583 else if( pWnd
->dwStyle
& WS_MAXIMIZE
)
1585 if( !EMPTYPOINT(lpPos
->ptMaxPos
) )
1586 SetWindowPos( hwnd
, 0, lpPos
->ptMaxPos
.x
, lpPos
->ptMaxPos
.y
,
1587 0, 0, SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
1589 else if( flags
& PLACE_RECT
)
1590 SetWindowPos( hwnd
, 0, lpPos
->rectNormal
.left
, lpPos
->rectNormal
.top
,
1591 lpPos
->rectNormal
.right
- lpPos
->rectNormal
.left
,
1592 lpPos
->rectNormal
.bottom
- lpPos
->rectNormal
.top
,
1593 SWP_NOZORDER
| SWP_NOACTIVATE
);
1595 ShowWindow( hwnd
, wndpl
->showCmd
);
1596 if( IsWindow(hwnd
) && pWnd
->dwStyle
& WS_MINIMIZE
)
1598 if( pWnd
->dwStyle
& WS_VISIBLE
) WINPOS_ShowIconTitle( pWnd
, TRUE
);
1600 /* SDK: ...valid only the next time... */
1601 if( wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) pWnd
->flags
|= WIN_RESTORE_MAX
;
1603 WIN_ReleaseWndPtr(pWnd
);
1610 /***********************************************************************
1611 * SetWindowPlacement16 (USER.371)
1613 BOOL16 WINAPI
SetWindowPlacement16(HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
1615 return WINPOS_SetPlacement( hwnd
, wndpl
,
1616 PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1619 /***********************************************************************
1620 * SetWindowPlacement (USER32.519)
1623 * Fails if wndpl->length of Win95 (!) apps is invalid.
1625 BOOL WINAPI
SetWindowPlacement( HWND hwnd
, const WINDOWPLACEMENT
*pwpl32
)
1629 WINDOWPLACEMENT16 wpl
;
1631 wpl
.length
= sizeof(WINDOWPLACEMENT16
);
1632 wpl
.flags
= pwpl32
->flags
;
1633 wpl
.showCmd
= pwpl32
->showCmd
;
1634 wpl
.ptMinPosition
.x
= pwpl32
->ptMinPosition
.x
;
1635 wpl
.ptMinPosition
.y
= pwpl32
->ptMinPosition
.y
;
1636 wpl
.ptMaxPosition
.x
= pwpl32
->ptMaxPosition
.x
;
1637 wpl
.ptMaxPosition
.y
= pwpl32
->ptMaxPosition
.y
;
1638 wpl
.rcNormalPosition
.left
= pwpl32
->rcNormalPosition
.left
;
1639 wpl
.rcNormalPosition
.top
= pwpl32
->rcNormalPosition
.top
;
1640 wpl
.rcNormalPosition
.right
= pwpl32
->rcNormalPosition
.right
;
1641 wpl
.rcNormalPosition
.bottom
= pwpl32
->rcNormalPosition
.bottom
;
1643 return WINPOS_SetPlacement( hwnd
, &wpl
, PLACE_MIN
| PLACE_MAX
| PLACE_RECT
);
1649 /***********************************************************************
1650 * SetInternalWindowPos16 (USER.461)
1652 void WINAPI
SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
1653 LPRECT16 rect
, LPPOINT16 pt
)
1655 if( IsWindow16(hwnd
) )
1657 WINDOWPLACEMENT16 wndpl
;
1660 wndpl
.length
= sizeof(wndpl
);
1661 wndpl
.showCmd
= showCmd
;
1662 wndpl
.flags
= flags
= 0;
1667 wndpl
.flags
|= WPF_SETMINPOSITION
;
1668 wndpl
.ptMinPosition
= *pt
;
1672 flags
|= PLACE_RECT
;
1673 wndpl
.rcNormalPosition
= *rect
;
1675 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1680 /***********************************************************************
1681 * SetInternalWindowPos (USER32.483)
1683 void WINAPI
SetInternalWindowPos( HWND hwnd
, UINT showCmd
,
1684 LPRECT rect
, LPPOINT pt
)
1686 if( IsWindow(hwnd
) )
1688 WINDOWPLACEMENT16 wndpl
;
1691 wndpl
.length
= sizeof(wndpl
);
1692 wndpl
.showCmd
= showCmd
;
1693 wndpl
.flags
= flags
= 0;
1698 wndpl
.flags
|= WPF_SETMINPOSITION
;
1699 CONV_POINT32TO16( pt
, &wndpl
.ptMinPosition
);
1703 flags
|= PLACE_RECT
;
1704 CONV_RECT32TO16( rect
, &wndpl
.rcNormalPosition
);
1706 WINPOS_SetPlacement( hwnd
, &wndpl
, flags
);
1710 /*******************************************************************
1711 * WINPOS_SetActiveWindow
1713 * SetActiveWindow() back-end. This is the only function that
1714 * can assign active status to a window. It must be called only
1715 * for the top level windows.
1717 BOOL
WINPOS_SetActiveWindow( HWND hWnd
, BOOL fMouse
, BOOL fChangeFocus
)
1719 CBTACTIVATESTRUCT16
* cbtStruct
;
1720 WND
* wndPtr
=0, *wndTemp
;
1721 HQUEUE16 hOldActiveQueue
, hNewActiveQueue
;
1722 MESSAGEQUEUE
*pOldActiveQueue
= 0, *pNewActiveQueue
= 0;
1724 HWND hwndActive
= 0;
1727 TRACE("(%04x, %d, %d)\n", hWnd
, fMouse
, fChangeFocus
);
1729 /* Get current active window from the active queue */
1732 pOldActiveQueue
= QUEUE_Lock( hActiveQueue
);
1733 if ( pOldActiveQueue
)
1734 hwndActive
= PERQDATA_GetActiveWnd( pOldActiveQueue
->pQData
);
1737 /* paranoid checks */
1738 if( hWnd
== GetDesktopWindow() || (bRet
= (hWnd
== hwndActive
)) )
1741 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1744 wndPtr
= WIN_FindWndPtr(hWnd
);
1745 hOldActiveQueue
= hActiveQueue
;
1747 if( (wndTemp
= WIN_FindWndPtr(hwndActive
)) )
1749 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1750 WIN_ReleaseWndPtr(wndTemp
);
1753 TRACE("no current active window.\n");
1755 /* call CBT hook chain */
1756 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1758 cbtStruct
->fMouse
= fMouse
;
1759 cbtStruct
->hWndActive
= hwndActive
;
1760 bRet
= (BOOL
)HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1761 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1762 SEGPTR_FREE(cbtStruct
);
1763 if (bRet
) goto CLEANUP_END
;
1766 /* set prev active wnd to current active wnd and send notification */
1767 if ((hwndPrevActive
= hwndActive
) && IsWindow(hwndPrevActive
))
1769 MESSAGEQUEUE
*pTempActiveQueue
= 0;
1771 if (!SendMessageA( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1773 if (GetSysModalWindow16() != hWnd
)
1775 /* disregard refusal if hWnd is sysmodal */
1778 SendMessageA( hwndPrevActive
, WM_ACTIVATE
,
1779 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1782 /* check if something happened during message processing
1783 * (global active queue may have changed)
1785 pTempActiveQueue
= QUEUE_Lock( hActiveQueue
);
1786 if(!pTempActiveQueue
)
1789 hwndActive
= PERQDATA_GetActiveWnd( pTempActiveQueue
->pQData
);
1790 QUEUE_Unlock( pTempActiveQueue
);
1791 if( hwndPrevActive
!= hwndActive
)
1795 /* Set new active window in the message queue */
1799 pNewActiveQueue
= QUEUE_Lock( wndPtr
->hmemTaskQ
);
1800 if ( pNewActiveQueue
)
1801 PERQDATA_SetActiveWnd( pNewActiveQueue
->pQData
, hwndActive
);
1803 else /* have to do this or MDI frame activation goes to hell */
1804 if( pOldActiveQueue
)
1805 PERQDATA_SetActiveWnd( pOldActiveQueue
->pQData
, 0 );
1807 /* send palette messages */
1808 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1809 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1811 /* if prev wnd is minimized redraw icon title */
1812 if( IsIconic( hwndPrevActive
) ) WINPOS_RedrawIconTitle(hwndPrevActive
);
1814 /* managed windows will get ConfigureNotify event */
1815 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1817 /* check Z-order and bring hWnd to the top */
1818 for (wndTemp
= WIN_LockWndPtr(WIN_GetDesktop()->child
); wndTemp
; WIN_UpdateWndPtr(&wndTemp
,wndTemp
->next
))
1820 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1822 WIN_ReleaseDesktop();
1823 WIN_ReleaseWndPtr(wndTemp
);
1825 if( wndTemp
!= wndPtr
)
1826 SetWindowPos(hWnd
, HWND_TOP
, 0,0,0,0,
1827 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1828 if (!IsWindow(hWnd
))
1832 /* Get a handle to the new active queue */
1833 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1835 /* send WM_ACTIVATEAPP if necessary */
1836 if (hOldActiveQueue
!= hNewActiveQueue
)
1838 WND
**list
, **ppWnd
;
1839 WND
*pDesktop
= WIN_GetDesktop();
1841 if ((list
= WIN_BuildWinArray( pDesktop
, 0, NULL
)))
1843 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1845 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1847 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1848 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1849 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1851 WIN_ReleaseWinArray(list
);
1854 hActiveQueue
= hNewActiveQueue
;
1856 if ((list
= WIN_BuildWinArray(pDesktop
, 0, NULL
)))
1858 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1860 if (!IsWindow( (*ppWnd
)->hwndSelf
)) continue;
1862 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1863 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1864 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1866 WIN_ReleaseWinArray(list
);
1868 WIN_ReleaseDesktop();
1870 if (hWnd
&& !IsWindow(hWnd
)) goto CLEANUP
;
1875 /* walk up to the first unowned window */
1876 wndTemp
= WIN_LockWndPtr(wndPtr
);
1877 while (wndTemp
->owner
)
1879 WIN_UpdateWndPtr(&wndTemp
,wndTemp
->owner
);
1881 /* and set last active owned popup */
1882 wndTemp
->hwndLastActive
= hWnd
;
1884 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1885 WIN_ReleaseWndPtr(wndTemp
);
1886 SendMessageA( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1887 SendMessageA( hWnd
, WM_ACTIVATE
,
1888 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1889 (LPARAM
)hwndPrevActive
);
1890 if( !IsWindow(hWnd
) ) goto CLEANUP
;
1893 /* change focus if possible */
1896 if ( pNewActiveQueue
)
1898 HWND hOldFocus
= PERQDATA_GetFocusWnd( pNewActiveQueue
->pQData
);
1900 if ( hOldFocus
&& WIN_GetTopParent( hOldFocus
) != hwndActive
)
1901 FOCUS_SwitchFocus( pNewActiveQueue
, hOldFocus
,
1902 (wndPtr
&& (wndPtr
->dwStyle
& WS_MINIMIZE
))?
1906 if ( pOldActiveQueue
&&
1907 ( !pNewActiveQueue
||
1908 pNewActiveQueue
->pQData
!= pOldActiveQueue
->pQData
) )
1910 HWND hOldFocus
= PERQDATA_GetFocusWnd( pOldActiveQueue
->pQData
);
1912 FOCUS_SwitchFocus( pOldActiveQueue
, hOldFocus
, 0 );
1916 if( !hwndPrevActive
&& wndPtr
)
1917 (*wndPtr
->pDriver
->pForceWindowRaise
)(wndPtr
);
1919 /* if active wnd is minimized redraw icon title */
1920 if( IsIconic(hwndActive
) ) WINPOS_RedrawIconTitle(hwndActive
);
1922 bRet
= (hWnd
== hwndActive
); /* Success? */
1924 CLEANUP
: /* Unlock the message queues before returning */
1926 if ( pNewActiveQueue
)
1927 QUEUE_Unlock( pNewActiveQueue
);
1931 if ( pOldActiveQueue
)
1932 QUEUE_Unlock( pOldActiveQueue
);
1934 WIN_ReleaseWndPtr(wndPtr
);
1938 /*******************************************************************
1939 * WINPOS_ActivateOtherWindow
1941 * Activates window other than pWnd.
1943 BOOL
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1947 HWND hwndActive
= 0;
1949 /* Get current active window from the active queue */
1952 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
1955 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
1956 QUEUE_Unlock( pActiveQueue
);
1960 if( pWnd
->hwndSelf
== hwndPrevActive
)
1963 if( hwndActive
!= pWnd
->hwndSelf
&&
1964 ( hwndActive
|| QUEUE_IsExitingQueue(pWnd
->hmemTaskQ
)) )
1967 if( !(pWnd
->dwStyle
& WS_POPUP
) || !(pWnd
->owner
) ||
1968 !WINPOS_CanActivate((pWndTo
= WIN_GetTopParentPtr(pWnd
->owner
))) )
1970 WND
* pWndPtr
= WIN_GetTopParentPtr(pWnd
);
1972 WIN_ReleaseWndPtr(pWndTo
);
1973 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1975 while( !WINPOS_CanActivate(pWndTo
) )
1977 /* by now owned windows should've been taken care of */
1978 WIN_UpdateWndPtr(&pWndTo
,pWndPtr
->next
);
1979 WIN_UpdateWndPtr(&pWndPtr
,pWndTo
);
1980 if( !pWndTo
) break;
1982 WIN_ReleaseWndPtr(pWndPtr
);
1985 bRet
= WINPOS_SetActiveWindow( pWndTo
? pWndTo
->hwndSelf
: 0, FALSE
, TRUE
);
1987 /* switch desktop queue to current active */
1990 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1991 WIN_ReleaseWndPtr(pWndTo
);
1992 WIN_ReleaseDesktop();
1999 /*******************************************************************
2000 * WINPOS_ChangeActiveWindow
2003 BOOL
WINPOS_ChangeActiveWindow( HWND hWnd
, BOOL mouseMsg
)
2005 WND
*wndPtr
, *wndTemp
;
2007 HWND hwndActive
= 0;
2009 /* Get current active window from the active queue */
2012 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2015 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2016 QUEUE_Unlock( pActiveQueue
);
2021 return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
2023 wndPtr
= WIN_FindWndPtr(hWnd
);
2024 if( !wndPtr
) return FALSE
;
2026 /* child windows get WM_CHILDACTIVATE message */
2027 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
2029 retvalue
= SendMessageA(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
2033 if( hWnd
== hwndActive
)
2039 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
2045 /* switch desktop queue to current active */
2046 wndTemp
= WIN_GetDesktop();
2047 if( wndPtr
->parent
== wndTemp
)
2048 wndTemp
->hmemTaskQ
= wndPtr
->hmemTaskQ
;
2049 WIN_ReleaseDesktop();
2053 WIN_ReleaseWndPtr(wndPtr
);
2058 /***********************************************************************
2059 * WINPOS_SendNCCalcSize
2061 * Send a WM_NCCALCSIZE message to a window.
2062 * All parameters are read-only except newClientRect.
2063 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2064 * when calcValidRect is TRUE.
2066 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
,
2067 RECT
*newWindowRect
, RECT
*oldWindowRect
,
2068 RECT
*oldClientRect
, WINDOWPOS
*winpos
,
2069 RECT
*newClientRect
)
2071 NCCALCSIZE_PARAMS params
;
2072 WINDOWPOS winposCopy
;
2075 params
.rgrc
[0] = *newWindowRect
;
2078 winposCopy
= *winpos
;
2079 params
.rgrc
[1] = *oldWindowRect
;
2080 params
.rgrc
[2] = *oldClientRect
;
2081 params
.lppos
= &winposCopy
;
2083 result
= SendMessageA( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
2085 TRACE("%d,%d-%d,%d\n",
2086 params
.rgrc
[0].left
, params
.rgrc
[0].top
,
2087 params
.rgrc
[0].right
, params
.rgrc
[0].bottom
);
2089 /* If the application send back garbage, ignore it */
2090 if (params
.rgrc
[0].left
<= params
.rgrc
[0].right
&& params
.rgrc
[0].top
<= params
.rgrc
[0].bottom
)
2091 *newClientRect
= params
.rgrc
[0];
2097 /***********************************************************************
2098 * WINPOS_HandleWindowPosChanging16
2100 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2102 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
2104 POINT maxSize
, minTrack
;
2105 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2106 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2107 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2109 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, &minTrack
, NULL
);
2110 if (maxSize
.x
< winpos
->cx
) winpos
->cx
= maxSize
.x
;
2111 if (maxSize
.y
< winpos
->cy
) winpos
->cy
= maxSize
.y
;
2112 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
2114 if (winpos
->cx
< minTrack
.x
) winpos
->cx
= minTrack
.x
;
2115 if (winpos
->cy
< minTrack
.y
) winpos
->cy
= minTrack
.y
;
2122 /***********************************************************************
2123 * WINPOS_HandleWindowPosChanging
2125 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2127 LONG
WINPOS_HandleWindowPosChanging( WND
*wndPtr
, WINDOWPOS
*winpos
)
2130 if (winpos
->flags
& SWP_NOSIZE
) return 0;
2131 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
2132 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
2134 WINPOS_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
2135 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
2136 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
2141 /***********************************************************************
2144 * fix Z order taking into account owned popups -
2145 * basically we need to maintain them above the window that owns them
2147 * FIXME: hide/show owned popups when owner visibility changes.
2149 static HWND
SWP_DoOwnedPopups(WND
* pDesktop
, WND
* wndPtr
, HWND hwndInsertAfter
, WORD flags
)
2151 WND
* w
= WIN_LockWndPtr(pDesktop
->child
);
2153 WARN("(%04x) hInsertAfter = %04x\n", wndPtr
->hwndSelf
, hwndInsertAfter
);
2155 if( (wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
)
2157 /* make sure this popup stays above the owner */
2159 HWND hwndLocalPrev
= HWND_TOP
;
2161 if( hwndInsertAfter
!= HWND_TOP
)
2163 while( w
!= wndPtr
->owner
)
2165 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
2166 if( hwndLocalPrev
== hwndInsertAfter
) break;
2167 WIN_UpdateWndPtr(&w
,w
->next
);
2169 hwndInsertAfter
= hwndLocalPrev
;
2172 else if( wndPtr
->dwStyle
& WS_CHILD
)
2175 WIN_UpdateWndPtr(&w
, pDesktop
->child
);
2179 if( w
== wndPtr
) break;
2181 if( (w
->dwStyle
& WS_POPUP
) && w
->owner
== wndPtr
)
2183 SetWindowPos(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0,
2184 SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
2185 hwndInsertAfter
= w
->hwndSelf
;
2187 WIN_UpdateWndPtr(&w
, w
->next
);
2191 WIN_ReleaseWndPtr(w
);
2192 return hwndInsertAfter
;
2195 /***********************************************************************
2198 * Make window look nice without excessive repainting
2200 * visible and update regions are in window coordinates
2201 * client and window rectangles are in parent client coordinates
2203 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2204 * window rects have the same origin.
2206 * Returns: uFlags and a dirty region in *pVisRgn.
2208 static UINT
SWP_CopyValidBits( WND
* Wnd
, HRGN
* pVisRgn
,
2209 LPRECT lpOldWndRect
,
2210 LPRECT lpOldClientRect
, UINT uFlags
)
2213 HRGN newVisRgn
, dirtyRgn
;
2214 INT my
= COMPLEXREGION
;
2216 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2217 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
,
2218 Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
2219 lpOldWndRect
->left
, lpOldWndRect
->top
,
2220 lpOldWndRect
->right
, lpOldWndRect
->bottom
, *pVisRgn
);
2221 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2222 Wnd
->rectClient
.left
, Wnd
->rectClient
.top
,
2223 Wnd
->rectClient
.right
, Wnd
->rectClient
.bottom
,
2224 lpOldClientRect
->left
, lpOldClientRect
->top
,
2225 lpOldClientRect
->right
,lpOldClientRect
->bottom
);
2227 if( Wnd
->hrgnUpdate
== 1 )
2228 uFlags
|= SWP_EX_NOCOPY
; /* whole window is invalid, nothing to copy */
2230 newVisRgn
= DCE_GetVisRgn( Wnd
->hwndSelf
, DCX_WINDOW
| DCX_CLIPSIBLINGS
, 0, 0);
2231 dirtyRgn
= CreateRectRgn( 0, 0, 0, 0 );
2233 if( !(uFlags
& SWP_EX_NOCOPY
) ) /* make sure dst region covers only valid bits */
2234 my
= CombineRgn( dirtyRgn
, newVisRgn
, *pVisRgn
, RGN_AND
);
2236 if( (my
== NULLREGION
) || (uFlags
& SWP_EX_NOCOPY
) )
2240 TRACE("\twon't copy anything!\n");
2242 /* set dirtyRgn to the sum of old and new visible regions
2243 * in parent client coordinates */
2245 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2246 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2248 CombineRgn(*pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2250 else /* copy valid bits to a new location */
2252 INT dx
, dy
, ow
, oh
, nw
, nh
, ocw
, ncw
, och
, nch
;
2253 HRGN hrgnValid
= dirtyRgn
; /* non-empty intersection of old and new visible rgns */
2255 /* subtract already invalid region inside Wnd from the dst region */
2257 if( Wnd
->hrgnUpdate
)
2258 if( CombineRgn( hrgnValid
, hrgnValid
, Wnd
->hrgnUpdate
, RGN_DIFF
) == NULLREGION
)
2261 /* check if entire window can be copied */
2263 ow
= lpOldWndRect
->right
- lpOldWndRect
->left
;
2264 oh
= lpOldWndRect
->bottom
- lpOldWndRect
->top
;
2265 nw
= Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
;
2266 nh
= Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
;
2268 ocw
= lpOldClientRect
->right
- lpOldClientRect
->left
;
2269 och
= lpOldClientRect
->bottom
- lpOldClientRect
->top
;
2270 ncw
= Wnd
->rectClient
.right
- Wnd
->rectClient
.left
;
2271 nch
= Wnd
->rectClient
.bottom
- Wnd
->rectClient
.top
;
2273 if( (ocw
!= ncw
) || (och
!= nch
) ||
2274 ( ow
!= nw
) || ( oh
!= nh
) ||
2275 ((lpOldClientRect
->top
- lpOldWndRect
->top
) !=
2276 (Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
)) ||
2277 ((lpOldClientRect
->left
- lpOldWndRect
->left
) !=
2278 (Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
)) )
2280 dx
= Wnd
->rectClient
.left
- lpOldClientRect
->left
;
2281 dy
= Wnd
->rectClient
.top
- lpOldClientRect
->top
;
2283 /* restrict valid bits to the common client rect */
2285 r
.left
= Wnd
->rectClient
.left
- Wnd
->rectWindow
.left
;
2286 r
.top
= Wnd
->rectClient
.top
- Wnd
->rectWindow
.top
;
2287 r
.right
= r
.left
+ min( ocw
, ncw
);
2288 r
.bottom
= r
.top
+ min( och
, nch
);
2290 REGION_CropRgn( hrgnValid
, hrgnValid
, &r
,
2291 (uFlags
& SWP_EX_PAINTSELF
) ? NULL
: (POINT
*)&(Wnd
->rectWindow
));
2292 GetRgnBox( hrgnValid
, &r
);
2293 if( IsRectEmpty( &r
) )
2295 r
= *lpOldClientRect
;
2299 dx
= Wnd
->rectWindow
.left
- lpOldWndRect
->left
;
2300 dy
= Wnd
->rectWindow
.top
- lpOldWndRect
->top
;
2301 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2302 OffsetRgn( hrgnValid
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2306 if( !(uFlags
& SWP_EX_PAINTSELF
) )
2308 /* Move remaining regions to parent coordinates */
2309 OffsetRgn( newVisRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
2310 OffsetRgn( *pVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
2313 OffsetRect( &r
, -lpOldWndRect
->left
, -lpOldWndRect
->top
);
2315 TRACE("\tcomputing dirty region!\n");
2317 /* Compute combined dirty region (old + new - valid) */
2318 CombineRgn( *pVisRgn
, *pVisRgn
, newVisRgn
, RGN_OR
);
2319 CombineRgn( *pVisRgn
, *pVisRgn
, hrgnValid
, RGN_DIFF
);
2321 /* Blt valid bits, r is the rect to copy */
2328 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2329 from copying clipped areas */
2331 if( uFlags
& SWP_EX_PAINTSELF
)
2333 hDC
= GetDCEx( Wnd
->hwndSelf
, hrgnValid
, DCX_WINDOW
| DCX_CACHE
|
2334 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2335 rClip
.right
= nw
; rClip
.bottom
= nh
;
2339 hDC
= GetDCEx( Wnd
->parent
->hwndSelf
, hrgnValid
, DCX_CACHE
|
2340 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
| DCX_CLIPSIBLINGS
);
2341 rClip
.right
= Wnd
->parent
->rectClient
.right
- Wnd
->parent
->rectClient
.left
;
2342 rClip
.bottom
= Wnd
->parent
->rectClient
.bottom
- Wnd
->parent
->rectClient
.top
;
2344 rClip
.left
= rClip
.top
= 0;
2346 if( oh
> nh
) r
.bottom
= r
.top
+ nh
;
2347 if( ow
< nw
) r
.right
= r
.left
+ nw
;
2349 if( IntersectRect( &r
, &r
, &rClip
) )
2351 Wnd
->pDriver
->pSurfaceCopy( Wnd
->parent
, hDC
, dx
, dy
, &r
, TRUE
);
2353 /* When you copy the bits without repainting, parent doesn't
2354 get validated appropriately. Therefore, we have to validate
2355 the parent with the windows' updated region when the
2356 parent's update region is not empty. */
2358 if (Wnd
->parent
->hrgnUpdate
!= 0 && !(Wnd
->parent
->dwStyle
& WS_CLIPCHILDREN
))
2360 OffsetRect(&r
, dx
, dy
);
2361 ValidateRect(Wnd
->parent
->hwndSelf
, &r
);
2364 ReleaseDC( (uFlags
& SWP_EX_PAINTSELF
) ?
2365 Wnd
->hwndSelf
: Wnd
->parent
->hwndSelf
, hDC
);
2369 /* *pVisRgn now points to the invalidated region */
2371 DeleteObject(newVisRgn
);
2372 DeleteObject(dirtyRgn
);
2376 /***********************************************************************
2377 * SWP_DoSimpleFrameChanged
2379 * NOTE: old and new client rect origins are identical, only
2380 * extents may have changed. Window extents are the same.
2382 static void SWP_DoSimpleFrameChanged( WND
* wndPtr
, RECT
* pOldClientRect
, WORD swpFlags
, UINT uFlags
)
2388 if( !(swpFlags
& SWP_NOCLIENTSIZE
) )
2390 /* Client rect changed its position/size, most likely a scrollar
2391 * was added/removed.
2393 * FIXME: WVR alignment flags
2396 if( wndPtr
->rectClient
.right
> pOldClientRect
->right
) /* right edge */
2400 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2401 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2402 if(!(uFlags
& SWP_EX_NOCOPY
))
2403 rect
.left
= pOldClientRect
->right
- wndPtr
->rectClient
.left
;
2411 if( wndPtr
->rectClient
.bottom
> pOldClientRect
->bottom
) /* bottom edge */
2414 hrgn
= CreateRectRgnIndirect( &rect
);
2416 rect
.right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
2417 rect
.bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
2418 if(!(uFlags
& SWP_EX_NOCOPY
))
2419 rect
.top
= pOldClientRect
->bottom
- wndPtr
->rectClient
.top
;
2423 REGION_UnionRectWithRgn( hrgn
, &rect
);
2426 if( i
== 0 && (uFlags
& SWP_EX_NOCOPY
) ) /* force redraw anyway */
2428 rect
= wndPtr
->rectWindow
;
2429 OffsetRect( &rect
, wndPtr
->rectWindow
.left
- wndPtr
->rectClient
.left
,
2430 wndPtr
->rectWindow
.top
- wndPtr
->rectClient
.top
);
2438 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, hrgn
, RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
|
2439 RDW_ERASENOW
| RDW_ALLCHILDREN
, RDW_EX_TOPFRAME
| RDW_EX_USEHRGN
);
2443 WIN_UpdateNCRgn(wndPtr
, 0, UNC_UPDATE
| UNC_ENTIRE
);
2447 DeleteObject( hrgn
);
2450 /***********************************************************************
2451 * SWP_DoWinPosChanging
2453 static BOOL
SWP_DoWinPosChanging( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2454 RECT
* pNewWindowRect
, RECT
* pNewClientRect
)
2456 /* Send WM_WINDOWPOSCHANGING message */
2458 if (!(pWinpos
->flags
& SWP_NOSENDCHANGING
))
2459 SendMessageA( wndPtr
->hwndSelf
, WM_WINDOWPOSCHANGING
, 0, (LPARAM
)pWinpos
);
2461 /* Calculate new position and size */
2463 *pNewWindowRect
= wndPtr
->rectWindow
;
2464 *pNewClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
2465 : wndPtr
->rectClient
;
2467 if (!(pWinpos
->flags
& SWP_NOSIZE
))
2469 pNewWindowRect
->right
= pNewWindowRect
->left
+ pWinpos
->cx
;
2470 pNewWindowRect
->bottom
= pNewWindowRect
->top
+ pWinpos
->cy
;
2472 if (!(pWinpos
->flags
& SWP_NOMOVE
))
2474 pNewWindowRect
->left
= pWinpos
->x
;
2475 pNewWindowRect
->top
= pWinpos
->y
;
2476 pNewWindowRect
->right
+= pWinpos
->x
- wndPtr
->rectWindow
.left
;
2477 pNewWindowRect
->bottom
+= pWinpos
->y
- wndPtr
->rectWindow
.top
;
2479 OffsetRect( pNewClientRect
, pWinpos
->x
- wndPtr
->rectWindow
.left
,
2480 pWinpos
->y
- wndPtr
->rectWindow
.top
);
2483 pWinpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
2487 /***********************************************************************
2490 static UINT
SWP_DoNCCalcSize( WND
* wndPtr
, WINDOWPOS
* pWinpos
,
2491 RECT
* pNewWindowRect
, RECT
* pNewClientRect
, WORD f
)
2495 /* Send WM_NCCALCSIZE message to get new client area */
2496 if( (pWinpos
->flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
2498 wvrFlags
= WINPOS_SendNCCalcSize( pWinpos
->hwnd
, TRUE
, pNewWindowRect
,
2499 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
2500 pWinpos
, pNewClientRect
);
2502 /* FIXME: WVR_ALIGNxxx */
2504 if( pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2505 pNewClientRect
->top
!= wndPtr
->rectClient
.top
)
2506 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2508 if( (pNewClientRect
->right
- pNewClientRect
->left
!=
2509 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
2510 (pNewClientRect
->bottom
- pNewClientRect
->top
!=
2511 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
2512 pWinpos
->flags
&= ~SWP_NOCLIENTSIZE
;
2515 if( !(f
& SWP_NOMOVE
) && (pNewClientRect
->left
!= wndPtr
->rectClient
.left
||
2516 pNewClientRect
->top
!= wndPtr
->rectClient
.top
) )
2517 pWinpos
->flags
&= ~SWP_NOCLIENTMOVE
;
2521 /***********************************************************************
2522 * SetWindowPos (USER.2)
2524 BOOL16 WINAPI
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
,
2525 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, WORD flags
)
2527 return SetWindowPos(hwnd
,(INT
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
2530 /***********************************************************************
2531 * SetWindowPos (USER32.520)
2533 BOOL WINAPI
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
,
2534 INT x
, INT y
, INT cx
, INT cy
, UINT flags
)
2537 WND
* wndPtr
,*wndTemp
;
2538 RECT newWindowRect
, newClientRect
;
2539 RECT oldWindowRect
, oldClientRect
;
2541 UINT wvrFlags
= 0, uFlags
= 0;
2542 BOOL retvalue
, resync
= FALSE
, bChangePos
;
2543 HWND hwndActive
= 0;
2545 /* Get current active window from the active queue */
2548 MESSAGEQUEUE
*pActiveQueue
= QUEUE_Lock( hActiveQueue
);
2551 hwndActive
= PERQDATA_GetActiveWnd( pActiveQueue
->pQData
);
2552 QUEUE_Unlock( pActiveQueue
);
2556 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2557 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
2559 bChangePos
= !(flags
& SWP_WINE_NOHOSTMOVE
);
2560 flags
&= ~SWP_WINE_NOHOSTMOVE
;
2563 /* ------------------------------------------------------------------------ CHECKS */
2565 /* Check window handle */
2567 if (hwnd
== GetDesktopWindow()) return FALSE
;
2568 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
2570 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr
->rectWindow
.left
, wndPtr
->rectWindow
.top
,
2571 wndPtr
->rectWindow
.right
, wndPtr
->rectWindow
.bottom
, (unsigned)wndPtr
->dwStyle
);
2573 /* Fix redundant flags */
2575 if(wndPtr
->dwStyle
& WS_VISIBLE
)
2576 flags
&= ~SWP_SHOWWINDOW
;
2579 if (!(flags
& SWP_SHOWWINDOW
))
2580 flags
|= SWP_NOREDRAW
;
2581 flags
&= ~SWP_HIDEWINDOW
;
2584 if ( cx
< 0 ) cx
= 0; if( cy
< 0 ) cy
= 0;
2586 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
2587 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
2588 flags
|= SWP_NOSIZE
; /* Already the right size */
2590 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
2591 flags
|= SWP_NOMOVE
; /* Already the right position */
2593 if (hwnd
== hwndActive
)
2594 flags
|= SWP_NOACTIVATE
; /* Already active */
2595 else if ( (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)
2597 if(!(flags
& SWP_NOACTIVATE
)) /* Bring to the top when activating */
2599 flags
&= ~SWP_NOZORDER
;
2600 hwndInsertAfter
= HWND_TOP
;
2605 /* Check hwndInsertAfter */
2607 /* FIXME: TOPMOST not supported yet */
2608 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
2609 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
2611 /* hwndInsertAfter must be a sibling of the window */
2612 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
2614 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
2617 if( wnd
->parent
!= wndPtr
->parent
)
2620 WIN_ReleaseWndPtr(wnd
);
2623 /* don't need to change the Zorder of hwnd if it's already inserted
2624 * after hwndInsertAfter or when inserting hwnd after itself.
2626 if(( wnd
->next
== wndPtr
) || (hwnd
== hwndInsertAfter
)) flags
|= SWP_NOZORDER
;
2628 WIN_ReleaseWndPtr(wnd
);
2631 Pos
: /* ------------------------------------------------------------------------ MAIN part */
2633 /* Fill the WINDOWPOS structure */
2636 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2641 winpos
.flags
= flags
;
2643 SWP_DoWinPosChanging( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
);
2645 if((winpos
.flags
& (SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) != SWP_NOZORDER
)
2647 if( wndPtr
->parent
== WIN_GetDesktop() )
2648 hwndInsertAfter
= SWP_DoOwnedPopups( wndPtr
->parent
, wndPtr
,
2649 hwndInsertAfter
, winpos
.flags
);
2650 WIN_ReleaseDesktop();
2653 if(!(wndPtr
->flags
& WIN_NATIVE
) )
2655 if( hwndInsertAfter
== HWND_TOP
)
2656 winpos
.flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
2658 if( hwndInsertAfter
== HWND_BOTTOM
)
2659 winpos
.flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
2661 if( !(winpos
.flags
& SWP_NOZORDER
) )
2662 if( GetWindow(hwndInsertAfter
, GW_HWNDNEXT
) == wndPtr
->hwndSelf
)
2663 winpos
.flags
|= SWP_NOZORDER
;
2665 if( !(winpos
.flags
& (SWP_NOREDRAW
| SWP_SHOWWINDOW
)) &&
2666 ((winpos
.flags
& (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
| SWP_HIDEWINDOW
| SWP_FRAMECHANGED
))
2667 != (SWP_NOMOVE
| SWP_NOSIZE
| SWP_NOZORDER
)) )
2669 /* get a previous visible region for SWP_CopyValidBits() */
2670 DWORD dflags
= DCX_WINDOW
;
2672 if (wndPtr
->dwStyle
& WS_CLIPSIBLINGS
)
2673 dflags
|= DCX_CLIPSIBLINGS
;
2675 visRgn
= DCE_GetVisRgn(hwnd
, dflags
, 0, 0);
2679 /* Common operations */
2681 wvrFlags
= SWP_DoNCCalcSize( wndPtr
, &winpos
, &newWindowRect
, &newClientRect
, flags
);
2683 if(!(winpos
.flags
& SWP_NOZORDER
) && winpos
.hwnd
!= hwndInsertAfter
)
2685 if ( WIN_UnlinkWindow( winpos
.hwnd
) )
2686 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
2689 /* Reset active DCEs */
2691 if( (((winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
) &&
2692 wndPtr
->dwStyle
& WS_VISIBLE
) ||
2693 (flags
& (SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
2697 UnionRect(&rect
, &newWindowRect
, &wndPtr
->rectWindow
);
2698 DCE_InvalidateDCE(wndPtr
, &rect
);
2701 oldWindowRect
= wndPtr
->rectWindow
;
2702 oldClientRect
= wndPtr
->rectClient
;
2704 /* Find out if we have to redraw the whole client rect */
2706 if( oldClientRect
.bottom
- oldClientRect
.top
==
2707 newClientRect
.bottom
- newClientRect
.top
) wvrFlags
&= ~WVR_VREDRAW
;
2709 if( oldClientRect
.right
- oldClientRect
.left
==
2710 newClientRect
.right
- newClientRect
.left
) wvrFlags
&= ~WVR_HREDRAW
;
2712 if( (winpos
.flags
& SWP_NOCOPYBITS
) || (!(winpos
.flags
& SWP_NOCLIENTSIZE
) &&
2713 (wvrFlags
>= WVR_HREDRAW
) && (wvrFlags
< WVR_VALIDRECTS
)) )
2715 uFlags
|= SWP_EX_NOCOPY
;
2718 * Use this later in CopyValidBits()
2721 uFlags |= SWP_EX_NONCLIENT;
2724 /* FIXME: actually do something with WVR_VALIDRECTS */
2726 wndPtr
->rectWindow
= newWindowRect
;
2727 wndPtr
->rectClient
= newClientRect
;
2729 if (wndPtr
->flags
& WIN_NATIVE
) /* -------------------------------------------- hosted window */
2731 BOOL bCallDriver
= TRUE
;
2732 HWND tempInsertAfter
= winpos
.hwndInsertAfter
;
2734 winpos
.hwndInsertAfter
= hwndInsertAfter
;
2736 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2738 /* This is the only place where we need to force repainting of the contents
2739 of windows created by the host window system, all other cases go through the
2740 expose event handling */
2742 if( (winpos
.flags
& (SWP_NOSIZE
| SWP_FRAMECHANGED
)) == (SWP_NOSIZE
| SWP_FRAMECHANGED
) )
2744 cx
= newWindowRect
.right
- newWindowRect
.left
;
2745 cy
= newWindowRect
.bottom
- newWindowRect
.top
;
2747 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2748 winpos
.hwndInsertAfter
= tempInsertAfter
;
2749 bCallDriver
= FALSE
;
2751 if( winpos
.flags
& SWP_NOCLIENTMOVE
)
2752 SWP_DoSimpleFrameChanged(wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2755 /* client area moved but window extents remained the same, copy valid bits */
2757 visRgn
= CreateRectRgn( 0, 0, cx
, cy
);
2758 uFlags
= SWP_CopyValidBits( wndPtr
, &visRgn
, &oldWindowRect
, &oldClientRect
,
2759 uFlags
| SWP_EX_PAINTSELF
);
2766 if( !(winpos
.flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
| SWP_NOREDRAW
)) )
2768 if( (oldClientRect
.left
- oldWindowRect
.left
== newClientRect
.left
- newWindowRect
.left
) &&
2769 (oldClientRect
.top
- oldWindowRect
.top
== newClientRect
.top
- newWindowRect
.top
) &&
2770 !(uFlags
& SWP_EX_NOCOPY
) )
2772 /* The origin of the client rect didn't move so we can try to repaint
2773 * only the nonclient area by setting bit gravity hint for the host window system.
2776 if( !(wndPtr
->flags
& WIN_MANAGED
) )
2778 HRGN hrgn
= CreateRectRgn( 0, 0, newWindowRect
.right
- newWindowRect
.left
,
2779 newWindowRect
.bottom
- newWindowRect
.top
);
2780 RECT rcn
= newClientRect
;
2781 RECT rco
= oldClientRect
;
2783 OffsetRect( &rcn
, -newWindowRect
.left
, -newWindowRect
.top
);
2784 OffsetRect( &rco
, -oldWindowRect
.left
, -oldWindowRect
.top
);
2785 IntersectRect( &rcn
, &rcn
, &rco
);
2786 visRgn
= CreateRectRgnIndirect( &rcn
);
2787 CombineRgn( visRgn
, hrgn
, visRgn
, RGN_DIFF
);
2788 DeleteObject( hrgn
);
2789 uFlags
= SWP_EX_PAINTSELF
;
2791 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGNorthWest
);
2794 wndPtr
->pDriver
->pSetHostAttr(wndPtr
, HAK_BITGRAVITY
, BGForget
);
2797 wndPtr
->pDriver
->pSetWindowPos(wndPtr
, &winpos
, bChangePos
);
2798 winpos
.hwndInsertAfter
= tempInsertAfter
;
2801 if( winpos
.flags
& SWP_SHOWWINDOW
)
2805 wndPtr
->dwStyle
|= WS_VISIBLE
;
2807 if (wndPtr
->flags
& WIN_MANAGED
) resync
= TRUE
;
2809 /* focus was set to unmapped window, reset host focus
2810 * since the window is now visible */
2812 focus
= curr
= GetFocus();
2817 WND
*pFocus
= WIN_FindWndPtr( focus
);
2819 pFocus
->pDriver
->pSetFocus(pFocus
);
2820 WIN_ReleaseWndPtr(pFocus
);
2823 curr
= GetParent(curr
);
2827 else /* -------------------------------------------- emulated window */
2829 if( winpos
.flags
& SWP_SHOWWINDOW
)
2831 wndPtr
->dwStyle
|= WS_VISIBLE
;
2832 uFlags
|= SWP_EX_PAINTSELF
;
2833 visRgn
= 1; /* redraw the whole window */
2835 else if( !(winpos
.flags
& SWP_NOREDRAW
) )
2837 if( winpos
.flags
& SWP_HIDEWINDOW
)
2839 if( visRgn
> 1 ) /* map to parent */
2840 OffsetRgn( visRgn
, oldWindowRect
.left
, oldWindowRect
.top
);
2846 if( (winpos
.flags
& SWP_AGG_NOPOSCHANGE
) != SWP_AGG_NOPOSCHANGE
)
2847 uFlags
= SWP_CopyValidBits(wndPtr
, &visRgn
, &oldWindowRect
,
2848 &oldClientRect
, uFlags
);
2851 /* nothing moved, redraw frame if needed */
2853 if( winpos
.flags
& SWP_FRAMECHANGED
)
2854 SWP_DoSimpleFrameChanged( wndPtr
, &oldClientRect
, winpos
.flags
, uFlags
);
2857 DeleteObject( visRgn
);
2865 if( winpos
.flags
& SWP_HIDEWINDOW
)
2867 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
2870 if (hwnd
== CARET_GetHwnd())
2872 if( winpos
.flags
& SWP_HIDEWINDOW
)
2874 else if (winpos
.flags
& SWP_SHOWWINDOW
)
2878 /* ------------------------------------------------------------------------ FINAL */
2880 if (wndPtr
->flags
& WIN_NATIVE
)
2881 EVENT_Synchronize(); /* Synchronize with the host window system */
2883 if (!GetCapture() && ((wndPtr
->dwStyle
& WS_VISIBLE
) || (flags
& SWP_HIDEWINDOW
)))
2885 /* Simulate a mouse event to set the cursor */
2886 int iWndsLocks
= WIN_SuspendWndsLock();
2888 hardware_event( WM_MOUSEMOVE
, GET_KEYSTATE(), 0,
2889 PosX
, PosY
, GetTickCount(), 0 );
2891 WIN_RestoreWndsLock(iWndsLocks
);
2894 wndTemp
= WIN_GetDesktop();
2896 /* repaint invalidated region (if any)
2898 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2899 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2904 if( !(winpos
.flags
& SWP_NOREDRAW
) )
2907 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2908 its parent and sibling and so on, and then erase the parent window
2909 back ground if the parent is either a top-level window or its parent's parent
2910 is top-level window. Rely on the system to repaint other affected
2911 windows later on. */
2912 if( uFlags
& SWP_EX_PAINTSELF
)
2914 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2915 RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2916 RDW_EX_XYWINDOW
| RDW_EX_USEHRGN
);
2920 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, (visRgn
== 1) ? 0 : visRgn
,
2921 RDW_ERASE
| RDW_INVALIDATE
| RDW_ALLCHILDREN
,
2925 if(wndPtr
-> parent
== wndTemp
|| wndPtr
->parent
->parent
== wndTemp
)
2927 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0,
2928 RDW_ERASENOW
| RDW_NOCHILDREN
, 0 );
2932 DeleteObject( visRgn
);
2935 WIN_ReleaseDesktop();
2937 if (!(flags
& SWP_NOACTIVATE
))
2938 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
2940 /* And last, send the WM_WINDOWPOSCHANGED message */
2942 TRACE("\tstatus flags = %04x\n", winpos
.flags
& SWP_AGG_STATUSFLAGS
);
2945 (((winpos
.flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2946 !(winpos
.flags
& SWP_NOSENDCHANGING
)) )
2948 SendMessageA( winpos
.hwnd
, WM_WINDOWPOSCHANGED
, 0, (LPARAM
)&winpos
);
2949 if (resync
) EVENT_Synchronize();
2954 WIN_ReleaseWndPtr(wndPtr
);
2959 /***********************************************************************
2960 * BeginDeferWindowPos16 (USER.259)
2962 HDWP16 WINAPI
BeginDeferWindowPos16( INT16 count
)
2964 return BeginDeferWindowPos( count
);
2968 /***********************************************************************
2969 * BeginDeferWindowPos (USER32.9)
2971 HDWP WINAPI
BeginDeferWindowPos( INT count
)
2978 SetLastError(ERROR_INVALID_PARAMETER
);
2981 /* Windows allows zero count, in which case it allocates context for 8 moves */
2982 if (count
== 0) count
= 8;
2984 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
2985 if (!handle
) return 0;
2986 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2987 pDWP
->actualCount
= 0;
2988 pDWP
->suggestedCount
= count
;
2990 pDWP
->wMagic
= DWP_MAGIC
;
2991 pDWP
->hwndParent
= 0;
2996 /***********************************************************************
2997 * DeferWindowPos16 (USER.260)
2999 HDWP16 WINAPI
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
3000 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
,
3003 return DeferWindowPos( hdwp
, hwnd
, (INT
)(INT16
)hwndAfter
,
3004 x
, y
, cx
, cy
, flags
);
3008 /***********************************************************************
3009 * DeferWindowPos (USER32.128)
3011 HDWP WINAPI
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
,
3012 INT x
, INT y
, INT cx
, INT cy
,
3017 HDWP newhdwp
= hdwp
,retvalue
;
3021 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3022 if (!pDWP
) return 0;
3023 if (hwnd
== GetDesktopWindow()) return 0;
3025 if (!(pWnd
=WIN_FindWndPtr( hwnd
))) {
3026 USER_HEAP_FREE( hdwp
);
3030 /* Numega Bounds Checker Demo dislikes the following code.
3031 In fact, I've not been able to find any "same parent" requirement in any docu
3035 /* All the windows of a DeferWindowPos() must have the same parent */
3036 parent
= pWnd
->parent
->hwndSelf
;
3037 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
3038 else if (parent
!= pDWP
->hwndParent
)
3040 USER_HEAP_FREE( hdwp
);
3046 for (i
= 0; i
< pDWP
->actualCount
; i
++)
3048 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
3050 /* Merge with the other changes */
3051 if (!(flags
& SWP_NOZORDER
))
3053 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
3055 if (!(flags
& SWP_NOMOVE
))
3057 pDWP
->winPos
[i
].x
= x
;
3058 pDWP
->winPos
[i
].y
= y
;
3060 if (!(flags
& SWP_NOSIZE
))
3062 pDWP
->winPos
[i
].cx
= cx
;
3063 pDWP
->winPos
[i
].cy
= cy
;
3065 pDWP
->winPos
[i
].flags
&= flags
| ~(SWP_NOSIZE
| SWP_NOMOVE
|
3066 SWP_NOZORDER
| SWP_NOREDRAW
|
3067 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
3069 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
3075 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
3077 newhdwp
= USER_HEAP_REALLOC( hdwp
,
3078 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
3084 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
3085 pDWP
->suggestedCount
++;
3087 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
3088 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
3089 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
3090 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
3091 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
3092 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
3093 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
3094 pDWP
->actualCount
++;
3097 WIN_ReleaseWndPtr(pWnd
);
3102 /***********************************************************************
3103 * EndDeferWindowPos16 (USER.261)
3105 BOOL16 WINAPI
EndDeferWindowPos16( HDWP16 hdwp
)
3107 return EndDeferWindowPos( hdwp
);
3111 /***********************************************************************
3112 * EndDeferWindowPos (USER32.173)
3114 BOOL WINAPI
EndDeferWindowPos( HDWP hdwp
)
3121 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
3122 if (!pDWP
) return FALSE
;
3123 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
3125 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
3126 winpos
->x
, winpos
->y
, winpos
->cx
,
3127 winpos
->cy
, winpos
->flags
))) break;
3129 USER_HEAP_FREE( hdwp
);
3134 /***********************************************************************
3135 * TileChildWindows (USER.199)
3137 void WINAPI
TileChildWindows16( HWND16 parent
, WORD action
)
3139 FIXME("(%04x, %d): stub\n", parent
, action
);
3142 /***********************************************************************
3143 * CascadeChildWindows (USER.198)
3145 void WINAPI
CascadeChildWindows16( HWND16 parent
, WORD action
)
3147 FIXME("(%04x, %d): stub\n", parent
, action
);
3150 /***********************************************************************
3151 * SetProgmanWindow [USER32.522]
3153 HRESULT WINAPI
SetProgmanWindow ( HWND hwnd
)
3155 hGlobalProgmanWindow
= hwnd
;
3156 return hGlobalProgmanWindow
;
3159 /***********************************************************************
3160 * GetProgmanWindow [USER32.289]
3162 HRESULT WINAPI
GetProgmanWindow ( )
3164 return hGlobalProgmanWindow
;
3167 /***********************************************************************
3168 * SetShellWindowEx [USER32.531]
3169 * hwndProgman = Progman[Program Manager]
3170 * |-> SHELLDLL_DefView
3171 * hwndListView = | |-> SysListView32
3172 * | | |-> tooltips_class32
3178 HRESULT WINAPI
SetShellWindowEx ( HWND hwndProgman
, HWND hwndListView
)
3180 FIXME("0x%08x 0x%08x stub\n",hwndProgman
,hwndListView
);
3181 hGlobalShellWindow
= hwndProgman
;
3182 return hGlobalShellWindow
;
3186 /***********************************************************************
3187 * SetTaskmanWindow [USER32.537]
3189 * hwnd = MSTaskSwWClass
3190 * |-> SysTabControl32
3192 HRESULT WINAPI
SetTaskmanWindow ( HWND hwnd
)
3194 hGlobalTaskmanWindow
= hwnd
;
3195 return hGlobalTaskmanWindow
;
3198 /***********************************************************************
3199 * GetTaskmanWindow [USER32.304]
3201 HRESULT WINAPI
GetTaskmanWindow ( )
3203 return hGlobalTaskmanWindow
;