2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995,1996 Alex Korobka
10 #include <X11/Xatom.h>
11 #include "sysmetrics.h"
22 #include "nonclient.h"
24 /* #define DEBUG_WIN */
27 #define SWP_AGG_NOGEOMETRYCHANGE \
28 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
29 #define SWP_AGG_NOPOSCHANGE \
30 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
31 #define SWP_AGG_STATUSFLAGS \
32 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
34 #define SMC_NOCOPY 0x0001
35 #define SMC_NOPARENTERASE 0x0002
36 #define SMC_DRAWFRAME 0x0004
37 #define SMC_SETXPOS 0x0008
39 /* ----- external functions ----- */
41 extern void FOCUS_SwitchFocus( HWND32
, HWND32
);
42 extern HRGN32
DCE_GetVisRgn( HWND32
, WORD
);
43 extern HWND32
CARET_GetHwnd();
44 extern BOOL32
DCE_InvalidateDCE(WND
*, RECT16
* );
46 /* ----- internal variables ----- */
48 static HWND32 hwndActive
= 0; /* Currently active window */
49 static HWND32 hwndPrevActive
= 0; /* Previously active window */
51 extern MESSAGEQUEUE
* pActiveQueue
;
53 /***********************************************************************
56 void WINPOS_CheckActive( HWND32 hwnd
)
58 if( hwnd
== hwndPrevActive
) hwndPrevActive
= 0;
59 if( hwnd
== hwndActive
)
62 dprintf_win(stddeb
,"\tattempt to activate destroyed window!\n");
66 /***********************************************************************
69 * Find a suitable place for an iconic window.
70 * The new position is stored into wndPtr->ptIconPos.
72 void WINPOS_FindIconPos( HWND32 hwnd
)
75 short x
, y
, xspacing
, yspacing
;
76 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
78 if (!wndPtr
|| !wndPtr
->parent
) return;
79 GetClientRect16( wndPtr
->parent
->hwndSelf
, &rectParent
);
80 if ((wndPtr
->ptIconPos
.x
>= rectParent
.left
) &&
81 (wndPtr
->ptIconPos
.x
+ SYSMETRICS_CXICON
< rectParent
.right
) &&
82 (wndPtr
->ptIconPos
.y
>= rectParent
.top
) &&
83 (wndPtr
->ptIconPos
.y
+ SYSMETRICS_CYICON
< rectParent
.bottom
))
84 return; /* The icon already has a suitable position */
86 xspacing
= yspacing
= 70; /* FIXME: This should come from WIN.INI */
87 y
= rectParent
.bottom
;
90 for (x
= rectParent
.left
; x
<=rectParent
.right
-xspacing
; x
+= xspacing
)
92 /* Check if another icon already occupies this spot */
93 WND
*childPtr
= wndPtr
->parent
->child
;
96 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (childPtr
!= wndPtr
))
98 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
99 (childPtr
->rectWindow
.right
>= x
) &&
100 (childPtr
->rectWindow
.top
<= y
) &&
101 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
102 break; /* There's a window in there */
104 childPtr
= childPtr
->next
;
108 /* No window was found, so it's OK for us */
109 wndPtr
->ptIconPos
.x
= x
+ (xspacing
- SYSMETRICS_CXICON
) / 2;
110 wndPtr
->ptIconPos
.y
= y
- (yspacing
+ SYSMETRICS_CYICON
) / 2;
119 /***********************************************************************
120 * ArrangeIconicWindows (USER32.6)
122 UINT16
ArrangeIconicWindows16( HWND16 parent
) {
123 return ArrangeIconicWindows32(parent
);
125 /***********************************************************************
126 * ArrangeIconicWindows (USER.170)
128 UINT32
ArrangeIconicWindows32( HWND32 parent
)
132 INT32 x
, y
, xspacing
, yspacing
;
134 GetClientRect32( parent
, &rectParent
);
136 y
= rectParent
.bottom
;
137 xspacing
= yspacing
= 70; /* FIXME: This should come from WIN.INI */
138 hwndChild
= GetWindow32( parent
, GW_CHILD
);
141 if (IsIconic32( hwndChild
))
143 SetWindowPos32( hwndChild
, 0, x
+ (xspacing
- SYSMETRICS_CXICON
) / 2,
144 y
- (yspacing
+ SYSMETRICS_CYICON
) / 2, 0, 0,
145 SWP_NOSIZE
|SWP_NOZORDER
|SWP_NOACTIVATE
);
146 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
153 hwndChild
= GetWindow32( hwndChild
, GW_HWNDNEXT
);
159 /***********************************************************************
160 * SwitchToThisWindow16 (USER.172)
162 void SwitchToThisWindow16( HWND16 hwnd
, BOOL16 restore
)
164 SwitchToThisWindow32( hwnd
, restore
);
168 /***********************************************************************
169 * SwitchToThisWindow32 (USER32.538)
171 void SwitchToThisWindow32( HWND32 hwnd
, BOOL32 restore
)
173 ShowWindow32( hwnd
, restore
? SW_RESTORE
: SW_SHOWMINIMIZED
);
177 /***********************************************************************
178 * GetWindowRect16 (USER.32)
180 void GetWindowRect16( HWND16 hwnd
, LPRECT16 rect
)
182 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
185 *rect
= wndPtr
->rectWindow
;
186 if (wndPtr
->dwStyle
& WS_CHILD
)
187 MapWindowPoints16( wndPtr
->parent
->hwndSelf
, 0, (POINT16
*)rect
, 2 );
191 /***********************************************************************
192 * GetWindowRect32 (USER.32)
194 void GetWindowRect32( HWND32 hwnd
, LPRECT32 rect
)
196 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
199 CONV_RECT16TO32( &wndPtr
->rectWindow
, rect
);
200 if (wndPtr
->dwStyle
& WS_CHILD
)
201 MapWindowPoints32( wndPtr
->parent
->hwndSelf
, 0, (POINT32
*)rect
, 2 );
205 /***********************************************************************
206 * GetClientRect16 (USER.33)
208 void GetClientRect16( HWND16 hwnd
, LPRECT16 rect
)
210 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
212 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
215 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
216 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
221 /***********************************************************************
222 * GetClientRect32 (USER32.219)
224 void GetClientRect32( HWND32 hwnd
, LPRECT32 rect
)
226 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
228 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
231 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
232 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
237 /*******************************************************************
238 * ClientToScreen16 (USER.28)
240 BOOL16
ClientToScreen16( HWND16 hwnd
, LPPOINT16 lppnt
)
242 MapWindowPoints16( hwnd
, 0, lppnt
, 1 );
247 /*******************************************************************
248 * ClientToScreen32 (USER32.51)
250 BOOL32
ClientToScreen32( HWND32 hwnd
, LPPOINT32 lppnt
)
252 MapWindowPoints32( hwnd
, 0, lppnt
, 1 );
257 /*******************************************************************
258 * ScreenToClient16 (USER.29)
260 void ScreenToClient16( HWND16 hwnd
, LPPOINT16 lppnt
)
262 MapWindowPoints16( 0, hwnd
, lppnt
, 1 );
266 /*******************************************************************
267 * ScreenToClient32 (USER32.446)
269 void ScreenToClient32( HWND32 hwnd
, LPPOINT32 lppnt
)
271 MapWindowPoints32( 0, hwnd
, lppnt
, 1 );
275 /***********************************************************************
276 * WINPOS_WindowFromPoint
278 * Find the window and hittest for a given point.
280 INT16
WINPOS_WindowFromPoint( WND
* wndScope
, POINT16 pt
, WND
**ppWnd
)
283 INT16 hittest
= HTERROR
;
287 wndPtr
= wndScope
->child
;
288 MapWindowPoints16( GetDesktopWindow16(), wndScope
->hwndSelf
, &xy
, 1 );
294 /* If point is in window, and window is visible, and it */
295 /* is enabled (or it's a top-level window), then explore */
296 /* its children. Otherwise, go to the next window. */
298 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
299 (!(wndPtr
->dwStyle
& WS_DISABLED
) ||
300 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) != WS_CHILD
)) &&
301 (xy
.x
>= wndPtr
->rectWindow
.left
) &&
302 (xy
.x
< wndPtr
->rectWindow
.right
) &&
303 (xy
.y
>= wndPtr
->rectWindow
.top
) &&
304 (xy
.y
< wndPtr
->rectWindow
.bottom
))
306 *ppWnd
= wndPtr
; /* Got a suitable window */
308 /* If window is minimized or disabled, return at once */
309 if (wndPtr
->dwStyle
& WS_MINIMIZE
) return HTCAPTION
;
310 if (wndPtr
->dwStyle
& WS_DISABLED
) return HTERROR
;
312 /* If point is not in client area, ignore the children */
313 if ((xy
.x
< wndPtr
->rectClient
.left
) ||
314 (xy
.x
>= wndPtr
->rectClient
.right
) ||
315 (xy
.y
< wndPtr
->rectClient
.top
) ||
316 (xy
.y
>= wndPtr
->rectClient
.bottom
)) break;
318 xy
.x
-= wndPtr
->rectClient
.left
;
319 xy
.y
-= wndPtr
->rectClient
.top
;
320 wndPtr
= wndPtr
->child
;
322 else wndPtr
= wndPtr
->next
;
325 /* If nothing found, try the scope window */
326 if (!*ppWnd
) *ppWnd
= wndScope
;
328 /* Send the WM_NCHITTEST message (only if to the same task) */
329 if ((*ppWnd
)->hmemTaskQ
== GetTaskQueue(0))
331 hittest
= (INT16
)SendMessage16( (*ppWnd
)->hwndSelf
, WM_NCHITTEST
,
332 0, MAKELONG( pt
.x
, pt
.y
) );
333 if (hittest
!= HTTRANSPARENT
) return hittest
; /* Found the window */
335 else return HTCLIENT
;
337 /* If no children found in last search, make point relative to parent */
340 xy
.x
+= (*ppWnd
)->rectClient
.left
;
341 xy
.y
+= (*ppWnd
)->rectClient
.top
;
344 /* Restart the search from the next sibling */
345 wndPtr
= (*ppWnd
)->next
;
346 *ppWnd
= (*ppWnd
)->parent
;
351 /*******************************************************************
352 * WindowFromPoint16 (USER.30)
354 HWND16
WindowFromPoint16( POINT16 pt
)
357 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt
, &pWnd
);
358 return pWnd
->hwndSelf
;
362 /*******************************************************************
363 * WindowFromPoint32 (USER32.581)
365 HWND32
WindowFromPoint32( POINT32 pt
)
369 CONV_POINT32TO16( &pt
, &pt16
);
370 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16
, &pWnd
);
371 return (HWND32
)pWnd
->hwndSelf
;
375 /*******************************************************************
376 * ChildWindowFromPoint16 (USER.191)
378 HWND16
ChildWindowFromPoint16( HWND16 hwndParent
, POINT16 pt
)
380 /* pt is in the client coordinates */
382 WND
* wnd
= WIN_FindWndPtr(hwndParent
);
387 /* get client rect fast */
388 rect
.top
= rect
.left
= 0;
389 rect
.right
= wnd
->rectClient
.right
- wnd
->rectClient
.left
;
390 rect
.bottom
= wnd
->rectClient
.bottom
- wnd
->rectClient
.top
;
392 if (!PtInRect16( &rect
, pt
)) return 0;
397 if (PtInRect16( &wnd
->rectWindow
, pt
)) return wnd
->hwndSelf
;
404 /*******************************************************************
405 * ChildWindowFromPoint32 (USER32.)
407 HWND32
ChildWindowFromPoint32( HWND32 hwndParent
, POINT32 pt
)
410 CONV_POINT32TO16( &pt
, &pt16
);
411 return (HWND32
)ChildWindowFromPoint16( hwndParent
, pt16
);
415 /*******************************************************************
416 * WINPOS_GetWinOffset
418 * Calculate the offset between the origin of the two windows. Used
419 * to implement MapWindowPoints.
421 static void WINPOS_GetWinOffset( HWND32 hwndFrom
, HWND32 hwndTo
,
426 offset
->x
= offset
->y
= 0;
427 if (hwndFrom
== hwndTo
) return;
429 /* Translate source window origin to screen coords */
432 if (!(wndPtr
= WIN_FindWndPtr( hwndFrom
)))
434 fprintf(stderr
,"MapWindowPoints: bad hwndFrom = %04x\n",hwndFrom
);
437 while (wndPtr
->parent
)
439 offset
->x
+= wndPtr
->rectClient
.left
;
440 offset
->y
+= wndPtr
->rectClient
.top
;
441 wndPtr
= wndPtr
->parent
;
445 /* Translate origin to destination window coords */
448 if (!(wndPtr
= WIN_FindWndPtr( hwndTo
)))
450 fprintf(stderr
,"MapWindowPoints: bad hwndTo = %04x\n", hwndTo
);
453 while (wndPtr
->parent
)
455 offset
->x
-= wndPtr
->rectClient
.left
;
456 offset
->y
-= wndPtr
->rectClient
.top
;
457 wndPtr
= wndPtr
->parent
;
463 /*******************************************************************
464 * MapWindowPoints16 (USER.258)
466 void MapWindowPoints16( HWND16 hwndFrom
, HWND16 hwndTo
,
467 LPPOINT16 lppt
, UINT16 count
)
471 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
481 /*******************************************************************
482 * MapWindowPoints32 (USER32.385)
484 void MapWindowPoints32( HWND32 hwndFrom
, HWND32 hwndTo
,
485 LPPOINT32 lppt
, UINT32 count
)
489 WINPOS_GetWinOffset( hwndFrom
, hwndTo
, &offset
);
499 /***********************************************************************
502 BOOL16
IsIconic16(HWND16 hWnd
)
504 return IsIconic32(hWnd
);
506 /***********************************************************************
507 * IsIconic (USER32.344)
509 BOOL32
IsIconic32(HWND32 hWnd
)
511 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
512 if (wndPtr
== NULL
) return FALSE
;
513 return (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
517 /***********************************************************************
518 * IsZoomed (USER.272)
520 BOOL16
IsZoomed16(HWND16 hWnd
)
522 return IsZoomed32(hWnd
);
524 /***********************************************************************
525 * IsZoomed (USER32.351)
527 BOOL32
IsZoomed32(HWND32 hWnd
)
529 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
530 if (wndPtr
== NULL
) return FALSE
;
531 return (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
535 /*******************************************************************
536 * GetActiveWindow (USER.60)
538 HWND16
GetActiveWindow16(void)
540 return GetActiveWindow32();
542 /*******************************************************************
543 * GetActiveWindow (USER32.204)
545 HWND32
GetActiveWindow32(void)
551 /*******************************************************************
552 * WINPOS_IsGoodEnough
554 static BOOL32
WINPOS_IsGoodEnough(WND
* pWnd
)
556 return (pWnd
) ? ((!(pWnd
->dwStyle
& WS_DISABLED
) &&
557 pWnd
->dwStyle
& WS_VISIBLE
) ? TRUE
: FALSE
) : FALSE
;
561 /*******************************************************************
562 * SetActiveWindow (USER.59)
564 HWND16
SetActiveWindow16( HWND16 hwnd
)
566 return SetActiveWindow32(hwnd
);
568 /*******************************************************************
569 * SetActiveWindow (USER.59)
571 HWND32
SetActiveWindow32( HWND32 hwnd
)
573 HWND32 prev
= hwndActive
;
574 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
576 if ( !WINPOS_IsGoodEnough(wndPtr
) ) return 0;
578 WINPOS_SetActiveWindow( hwnd
, 0, 0 );
583 /***********************************************************************
584 * BringWindowToTop (USER.45)
586 BOOL16
BringWindowToTop16( HWND16 hwnd
)
588 return BringWindowToTop32(hwnd
);
590 /***********************************************************************
591 * BringWindowToTop (USER32.10)
593 BOOL32
BringWindowToTop32( HWND32 hwnd
)
595 return SetWindowPos32( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
|SWP_NOSIZE
);
599 /***********************************************************************
600 * MoveWindow (USER.56)
603 HWND16 hwnd
, INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, BOOL16 repaint
605 return MoveWindow32(hwnd
,x
,y
,cx
,cy
,repaint
);
607 /***********************************************************************
608 * MoveWindow (USER32.398)
611 HWND32 hwnd
, INT32 x
, INT32 y
, INT32 cx
, INT32 cy
, BOOL32 repaint
613 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
614 if (!repaint
) flags
|= SWP_NOREDRAW
;
615 dprintf_win(stddeb
, "MoveWindow: %04x %d,%d %dx%d %d\n",
616 hwnd
, x
, y
, cx
, cy
, repaint
);
617 return SetWindowPos32( hwnd
, 0, x
, y
, cx
, cy
, flags
);
620 /***********************************************************************
621 * ShowWindow (USER.42)
623 BOOL16
ShowWindow16( HWND16 hwnd
, INT16 cmd
)
625 return ShowWindow32(hwnd
,cmd
);
627 /***********************************************************************
628 * ShowWindow (USER.42)
630 BOOL32
ShowWindow32( HWND32 hwnd
, INT32 cmd
)
632 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
633 BOOL32 wasVisible
, showFlag
;
636 short x
= 0, y
= 0, cx
= 0, cy
= 0;
638 if (!wndPtr
) return FALSE
;
640 dprintf_win(stddeb
,"ShowWindow: hwnd=%04x, cmd=%d\n", hwnd
, cmd
);
642 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
647 if (!wasVisible
) return FALSE
;
648 swpflags
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
649 SWP_NOACTIVATE
| SWP_NOZORDER
;
652 case SW_SHOWMINNOACTIVE
:
653 swpflags
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
655 case SW_SHOWMINIMIZED
:
656 swpflags
|= SWP_SHOWWINDOW
;
659 swpflags
|= SWP_FRAMECHANGED
;
660 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
662 if( HOOK_CallHooks16( WH_CBT
, HCBT_MINMAX
, hwnd
, cmd
) )
665 if (wndPtr
->dwStyle
& WS_MAXIMIZE
)
667 wndPtr
->flags
|= WIN_RESTORE_MAX
;
668 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
672 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
673 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
675 wndPtr
->dwStyle
|= WS_MINIMIZE
;
676 WINPOS_FindIconPos( hwnd
);
677 x
= wndPtr
->ptIconPos
.x
;
678 y
= wndPtr
->ptIconPos
.y
;
679 cx
= SYSMETRICS_CXICON
;
680 cy
= SYSMETRICS_CYICON
;
681 swpflags
|= SWP_NOCOPYBITS
;
683 else swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
686 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE: */
687 swpflags
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
688 if (!(wndPtr
->dwStyle
& WS_MAXIMIZE
))
690 if( HOOK_CallHooks16( WH_CBT
, HCBT_MINMAX
, hwnd
, cmd
) )
693 /* Store the current position and find the maximized size */
694 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
695 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
697 NC_GetMinMaxInfo( wndPtr
, &maxSize
,
698 &wndPtr
->ptMaxPos
, NULL
, NULL
);
699 x
= wndPtr
->ptMaxPos
.x
;
700 y
= wndPtr
->ptMaxPos
.y
;
702 if( wndPtr
->dwStyle
& WS_MINIMIZE
)
703 if( !SendMessage32A( hwnd
, WM_QUERYOPEN
, 0, 0L ) )
705 swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
708 else swpflags
|= SWP_NOCOPYBITS
;
712 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
713 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
715 else swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
719 swpflags
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
722 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
725 case SW_SHOWNOACTIVATE
:
726 swpflags
|= SWP_NOZORDER
;
727 if (GetActiveWindow32()) swpflags
|= SWP_NOACTIVATE
;
729 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
730 case SW_SHOWDEFAULT
: /* FIXME: should have its own handler */
732 swpflags
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
734 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
736 if( HOOK_CallHooks16( WH_CBT
, HCBT_MINMAX
, hwnd
, cmd
) )
739 if( !SendMessage16( hwnd
, WM_QUERYOPEN
, 0, 0L) )
741 swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
744 wndPtr
->ptIconPos
.x
= wndPtr
->rectWindow
.left
;
745 wndPtr
->ptIconPos
.y
= wndPtr
->rectWindow
.top
;
746 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
747 if (wndPtr
->flags
& WIN_RESTORE_MAX
)
749 /* Restore to maximized position */
750 NC_GetMinMaxInfo( wndPtr
, &maxSize
, &wndPtr
->ptMaxPos
,
752 x
= wndPtr
->ptMaxPos
.x
;
753 y
= wndPtr
->ptMaxPos
.y
;
756 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
758 else /* Restore to normal position */
760 x
= wndPtr
->rectNormal
.left
;
761 y
= wndPtr
->rectNormal
.top
;
762 cx
= wndPtr
->rectNormal
.right
- wndPtr
->rectNormal
.left
;
763 cy
= wndPtr
->rectNormal
.bottom
- wndPtr
->rectNormal
.top
;
765 swpflags
|= SWP_NOCOPYBITS
;
767 else if (wndPtr
->dwStyle
& WS_MAXIMIZE
)
769 if( HOOK_CallHooks16( WH_CBT
, HCBT_MINMAX
, hwnd
, cmd
) )
772 wndPtr
->ptMaxPos
.x
= wndPtr
->rectWindow
.left
;
773 wndPtr
->ptMaxPos
.y
= wndPtr
->rectWindow
.top
;
774 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
775 x
= wndPtr
->rectNormal
.left
;
776 y
= wndPtr
->rectNormal
.top
;
777 cx
= wndPtr
->rectNormal
.right
- wndPtr
->rectNormal
.left
;
778 cy
= wndPtr
->rectNormal
.bottom
- wndPtr
->rectNormal
.top
;
780 else swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
784 showFlag
= (cmd
!= SW_HIDE
);
785 if (showFlag
!= wasVisible
)
787 SendMessage16( hwnd
, WM_SHOWWINDOW
, showFlag
, 0 );
788 if (!IsWindow32( hwnd
)) return wasVisible
;
791 if ((wndPtr
->dwStyle
& WS_CHILD
) &&
792 !IsWindowVisible32( wndPtr
->parent
->hwndSelf
) &&
793 (swpflags
& SWP_NOSIZE
) && (swpflags
& SWP_NOMOVE
))
795 /* Don't call SetWindowPos32() on invisible child windows */
796 if (cmd
== SW_HIDE
) wndPtr
->dwStyle
&= ~WS_VISIBLE
;
797 else wndPtr
->dwStyle
|= WS_VISIBLE
;
801 /* We can't activate a child window */
802 if (wndPtr
->dwStyle
& WS_CHILD
)
803 swpflags
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
804 SetWindowPos32( hwnd
, HWND_TOP
, x
, y
, cx
, cy
, swpflags
);
805 if (!IsWindow32( hwnd
)) return wasVisible
;
808 if (wndPtr
->flags
& WIN_NEED_SIZE
)
810 /* should happen only in CreateWindowEx() */
811 int wParam
= SIZE_RESTORED
;
813 wndPtr
->flags
&= ~WIN_NEED_SIZE
;
814 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
815 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
816 SendMessage16( hwnd
, WM_SIZE
, wParam
,
817 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
818 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
819 SendMessage16( hwnd
, WM_MOVE
, 0,
820 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
827 /***********************************************************************
828 * GetInternalWindowPos16 (USER.460)
830 UINT16
GetInternalWindowPos16( HWND16 hwnd
, LPRECT16 rectWnd
, LPPOINT16 ptIcon
)
832 WINDOWPLACEMENT16 wndpl
;
833 if (!GetWindowPlacement16( hwnd
, &wndpl
)) return 0;
834 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
835 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
836 return wndpl
.showCmd
;
840 /***********************************************************************
841 * GetInternalWindowPos32 (USER32.244)
843 UINT32
GetInternalWindowPos32( HWND32 hwnd
, LPRECT32 rectWnd
, LPPOINT32 ptIcon
)
845 WINDOWPLACEMENT32 wndpl
;
846 if (!GetWindowPlacement32( hwnd
, &wndpl
)) return 0;
847 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
848 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
849 return wndpl
.showCmd
;
853 /***********************************************************************
854 * SetInternalWindowPos16 (USER.461)
856 void SetInternalWindowPos16( HWND16 hwnd
, UINT16 showCmd
,
857 LPRECT16 rect
, LPPOINT16 pt
)
859 WINDOWPLACEMENT16 wndpl
;
860 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
862 wndpl
.length
= sizeof(wndpl
);
863 wndpl
.flags
= (pt
!= NULL
) ? WPF_SETMINPOSITION
: 0;
864 wndpl
.showCmd
= showCmd
;
865 if (pt
) wndpl
.ptMinPosition
= *pt
;
866 wndpl
.rcNormalPosition
= (rect
!= NULL
) ? *rect
: wndPtr
->rectNormal
;
867 wndpl
.ptMaxPosition
= wndPtr
->ptMaxPos
;
868 SetWindowPlacement16( hwnd
, &wndpl
);
872 /***********************************************************************
873 * SetInternalWindowPos32 (USER32.482)
875 void SetInternalWindowPos32( HWND32 hwnd
, UINT32 showCmd
,
876 LPRECT32 rect
, LPPOINT32 pt
)
878 WINDOWPLACEMENT32 wndpl
;
879 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
881 wndpl
.length
= sizeof(wndpl
);
882 wndpl
.flags
= (pt
!= NULL
) ? WPF_SETMINPOSITION
: 0;
883 wndpl
.showCmd
= showCmd
;
884 if (pt
) wndpl
.ptMinPosition
= *pt
;
885 if (rect
) wndpl
.rcNormalPosition
= *rect
;
886 else CONV_RECT16TO32( &wndPtr
->rectNormal
, &wndpl
.rcNormalPosition
);
887 CONV_POINT16TO32( &wndPtr
->ptMaxPos
, &wndpl
.ptMaxPosition
);
888 SetWindowPlacement32( hwnd
, &wndpl
);
892 /***********************************************************************
893 * GetWindowPlacement16 (USER.370)
895 BOOL16
GetWindowPlacement16( HWND16 hwnd
, WINDOWPLACEMENT16
*wndpl
)
897 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
898 if (!wndPtr
) return FALSE
;
900 wndpl
->length
= sizeof(*wndpl
);
902 wndpl
->showCmd
= IsZoomed16(hwnd
) ? SW_SHOWMAXIMIZED
:
903 (IsIconic16(hwnd
) ? SW_SHOWMINIMIZED
: SW_SHOWNORMAL
);
904 wndpl
->ptMinPosition
= wndPtr
->ptIconPos
;
905 wndpl
->ptMaxPosition
= wndPtr
->ptMaxPos
;
906 wndpl
->rcNormalPosition
= wndPtr
->rectNormal
;
911 /***********************************************************************
912 * GetWindowPlacement32 (USER32.306)
914 BOOL32
GetWindowPlacement32( HWND32 hwnd
, WINDOWPLACEMENT32
*wndpl
)
916 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
917 if (!wndPtr
) return FALSE
;
919 wndpl
->length
= sizeof(*wndpl
);
921 wndpl
->showCmd
= IsZoomed32(hwnd
) ? SW_SHOWMAXIMIZED
:
922 (IsIconic32(hwnd
) ? SW_SHOWMINIMIZED
: SW_SHOWNORMAL
);
923 CONV_POINT16TO32( &wndPtr
->ptIconPos
, &wndpl
->ptMinPosition
);
924 CONV_POINT16TO32( &wndPtr
->ptMaxPos
, &wndpl
->ptMaxPosition
);
925 CONV_RECT16TO32( &wndPtr
->rectNormal
, &wndpl
->rcNormalPosition
);
930 /***********************************************************************
931 * SetWindowPlacement16 (USER.371)
933 BOOL16
SetWindowPlacement16( HWND16 hwnd
, const WINDOWPLACEMENT16
*wndpl
)
935 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
936 if (!wndPtr
) return FALSE
;
938 if (wndpl
->flags
& WPF_SETMINPOSITION
)
939 wndPtr
->ptIconPos
= wndpl
->ptMinPosition
;
940 if ((wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) &&
941 (wndpl
->showCmd
== SW_SHOWMINIMIZED
)) wndPtr
->flags
|= WIN_RESTORE_MAX
;
942 wndPtr
->ptMaxPos
= wndpl
->ptMaxPosition
;
943 wndPtr
->rectNormal
= wndpl
->rcNormalPosition
;
944 ShowWindow16( hwnd
, wndpl
->showCmd
);
949 /***********************************************************************
950 * SetWindowPlacement32 (USER32.518)
952 BOOL32
SetWindowPlacement32( HWND32 hwnd
, const WINDOWPLACEMENT32
*wndpl
)
954 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
955 if (!wndPtr
) return FALSE
;
957 if (wndpl
->flags
& WPF_SETMINPOSITION
)
958 CONV_POINT32TO16( &wndpl
->ptMinPosition
, &wndPtr
->ptIconPos
);
959 if ((wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) &&
960 (wndpl
->showCmd
== SW_SHOWMINIMIZED
)) wndPtr
->flags
|= WIN_RESTORE_MAX
;
961 CONV_POINT32TO16( &wndpl
->ptMaxPosition
, &wndPtr
->ptMaxPos
);
962 CONV_RECT32TO16( &wndpl
->rcNormalPosition
, &wndPtr
->rectNormal
);
963 ShowWindow32( hwnd
, wndpl
->showCmd
);
968 /***********************************************************************
969 * WINPOS_ForceXWindowRaise
971 * Raise a window on top of the X stacking order, while preserving
972 * the correct Windows Z order.
974 static void WINPOS_ForceXWindowRaise( WND
* pWnd
)
976 XWindowChanges winChanges
;
979 /* Raise all windows up to pWnd according to their Z order.
980 * (it would be easier with sibling-related Below but it doesn't
981 * work very well with SGI mwm for instance)
983 winChanges
.stack_mode
= Above
;
986 if (pWnd
->window
) XReconfigureWMWindow( display
, pWnd
->window
, 0,
987 CWStackMode
, &winChanges
);
988 wndPrev
= WIN_GetDesktop()->child
;
989 if (wndPrev
== pWnd
) break;
990 while (wndPrev
&& (wndPrev
->next
!= pWnd
)) wndPrev
= wndPrev
->next
;
996 /*******************************************************************
997 * WINPOS_SetActiveWindow
999 * back-end to SetActiveWindow
1001 BOOL32
WINPOS_SetActiveWindow( HWND32 hWnd
, BOOL32 fMouse
, BOOL32 fChangeFocus
)
1003 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
1004 WND
*wndTemp
= WIN_FindWndPtr(hwndActive
);
1005 CBTACTIVATESTRUCT16
*cbtStruct
;
1007 HQUEUE16 hOldActiveQueue
= (pActiveQueue
)?pActiveQueue
->self
:0;
1008 HQUEUE16 hNewActiveQueue
;
1010 /* paranoid checks */
1011 if( hWnd
== GetDesktopWindow32() || hWnd
== hwndActive
)
1014 /* if (wndPtr && (GetTaskQueue(0) != wndPtr->hmemTaskQ))
1019 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1021 dprintf_win(stddeb
,"WINPOS_ActivateWindow: no current active window.\n");
1023 /* call CBT hook chain */
1024 if ((cbtStruct
= SEGPTR_NEW(CBTACTIVATESTRUCT16
)))
1027 cbtStruct
->fMouse
= fMouse
;
1028 cbtStruct
->hWndActive
= hwndActive
;
1029 wRet
= HOOK_CallHooks16( WH_CBT
, HCBT_ACTIVATE
, (WPARAM16
)hWnd
,
1030 (LPARAM
)SEGPTR_GET(cbtStruct
) );
1031 SEGPTR_FREE(cbtStruct
);
1032 if (wRet
) return wRet
;
1035 /* set prev active wnd to current active wnd and send notification */
1036 if ((hwndPrevActive
= hwndActive
) && IsWindow32(hwndPrevActive
))
1038 if (!SendMessage16( hwndPrevActive
, WM_NCACTIVATE
, FALSE
, 0 ))
1040 if (GetSysModalWindow16() != hWnd
) return 0;
1041 /* disregard refusal if hWnd is sysmodal */
1045 SendMessage32A( hwndPrevActive
, WM_ACTIVATE
,
1046 MAKEWPARAM( WA_INACTIVE
, wIconized
),
1049 /* FIXME: must be SendMessage16() because 32A doesn't do
1050 * intertask at this time */
1051 SendMessage16( hwndPrevActive
, WM_ACTIVATE
, WA_INACTIVE
,
1052 MAKELPARAM( (HWND16
)hWnd
, wIconized
) );
1055 /* check if something happened during message processing */
1056 if( hwndPrevActive
!= hwndActive
) return 0;
1059 /* set active wnd */
1062 /* send palette messages */
1063 if (hWnd
&& SendMessage16( hWnd
, WM_QUERYNEWPALETTE
, 0, 0L))
1064 SendMessage16((HWND16
)-1, WM_PALETTEISCHANGING
, (WPARAM16
)hWnd
, 0L );
1066 /* if prev wnd is minimized redraw icon title
1067 if( hwndPrevActive )
1069 wndTemp = WIN_FindWndPtr( WIN_GetTopParent( hwndPrevActive ) );
1071 if(wndTemp->dwStyle & WS_MINIMIZE)
1072 RedrawIconTitle(hwndPrevActive);
1076 /* managed windows will get ConfigureNotify event */
1077 if (wndPtr
&& !(wndPtr
->dwStyle
& WS_CHILD
) && !(wndPtr
->flags
& WIN_MANAGED
))
1079 /* check Z-order and bring hWnd to the top */
1080 for (wndTemp
= WIN_GetDesktop()->child
; wndTemp
; wndTemp
= wndTemp
->next
)
1081 if (wndTemp
->dwStyle
& WS_VISIBLE
) break;
1083 if( wndTemp
!= wndPtr
)
1084 SetWindowPos32(hWnd
, HWND_TOP
, 0,0,0,0,
1085 SWP_NOSIZE
| SWP_NOMOVE
| SWP_NOACTIVATE
);
1086 if (!IsWindow32(hWnd
)) return 0;
1089 hNewActiveQueue
= wndPtr
? wndPtr
->hmemTaskQ
: 0;
1091 /* send WM_ACTIVATEAPP if necessary */
1092 if (hOldActiveQueue
!= hNewActiveQueue
)
1094 WND
**list
, **ppWnd
;
1096 if ((list
= WIN_BuildWinArray( WIN_GetDesktop() )))
1098 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1100 if (!IsWindow32( (*ppWnd
)->hwndSelf
)) continue;
1102 if ((*ppWnd
)->hmemTaskQ
== hOldActiveQueue
)
1103 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1104 0, QUEUE_GetQueueTask(hNewActiveQueue
) );
1106 HeapFree( SystemHeap
, 0, list
);
1109 pActiveQueue
= (hNewActiveQueue
)
1110 ? (MESSAGEQUEUE
*) GlobalLock16(hNewActiveQueue
) : NULL
;
1112 if ((list
= WIN_BuildWinArray( WIN_GetDesktop() )))
1114 for (ppWnd
= list
; *ppWnd
; ppWnd
++)
1116 if (!IsWindow32( (*ppWnd
)->hwndSelf
)) continue;
1118 if ((*ppWnd
)->hmemTaskQ
== hNewActiveQueue
)
1119 SendMessage16( (*ppWnd
)->hwndSelf
, WM_ACTIVATEAPP
,
1120 1, QUEUE_GetQueueTask( hOldActiveQueue
) );
1122 HeapFree( SystemHeap
, 0, list
);
1124 if (!IsWindow32(hWnd
)) return 0;
1129 /* walk up to the first unowned window */
1131 while (wndTemp
->owner
) wndTemp
= wndTemp
->owner
;
1132 /* and set last active owned popup */
1133 wndTemp
->hwndLastActive
= hWnd
;
1135 wIconized
= HIWORD(wndTemp
->dwStyle
& WS_MINIMIZE
);
1136 SendMessage16( hWnd
, WM_NCACTIVATE
, TRUE
, 0 );
1138 SendMessage32A( hWnd
, WM_ACTIVATE
,
1139 MAKEWPARAM( (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
, wIconized
),
1140 (LPARAM
)hwndPrevActive
);
1142 SendMessage16(hWnd
, WM_ACTIVATE
, (fMouse
) ? WA_CLICKACTIVE
: WA_ACTIVE
,
1143 MAKELPARAM( (HWND16
)hwndPrevActive
, wIconized
) );
1146 if( !IsWindow32(hWnd
) ) return 0;
1149 /* change focus if possible */
1150 if( fChangeFocus
&& GetFocus32() )
1151 if( WIN_GetTopParent(GetFocus32()) != hwndActive
)
1152 FOCUS_SwitchFocus( GetFocus32(),
1153 (wndPtr
->dwStyle
& WS_MINIMIZE
)? 0: hwndActive
);
1155 if( !hwndPrevActive
&& wndPtr
&&
1156 wndPtr
->window
&& !(wndPtr
->flags
& WIN_MANAGED
) )
1157 WINPOS_ForceXWindowRaise(wndPtr
);
1159 /* if active wnd is minimized redraw icon title
1162 wndPtr = WIN_FindWndPtr(hwndActive);
1163 if(wndPtr->dwStyle & WS_MINIMIZE)
1164 RedrawIconTitle(hwndActive);
1167 return (hWnd
== hwndActive
);
1170 /*******************************************************************
1171 * WINPOS_ActivateOtherWindow
1173 * DestroyWindow() helper. pWnd must be a top-level window.
1175 BOOL32
WINPOS_ActivateOtherWindow(WND
* pWnd
)
1180 if( pWnd
->hwndSelf
== hwndPrevActive
)
1183 if( hwndActive
!= pWnd
->hwndSelf
&&
1184 ( hwndActive
|| QUEUE_IsDoomedQueue(pWnd
->hmemTaskQ
)) )
1187 if( pWnd
->dwStyle
& WS_POPUP
&&
1188 WINPOS_IsGoodEnough( pWnd
->owner
) ) pWndTo
= pWnd
->owner
;
1191 WND
* pWndPtr
= pWnd
;
1193 pWndTo
= WIN_FindWndPtr(hwndPrevActive
);
1195 while( !WINPOS_IsGoodEnough(pWndTo
) )
1197 /* by now owned windows should've been taken care of */
1199 pWndTo
= pWndPtr
->next
;
1201 if( !pWndTo
) return 0;
1205 bRet
= WINPOS_SetActiveWindow( pWndTo
->hwndSelf
, FALSE
, TRUE
);
1207 /* switch desktop queue to current active */
1208 if( pWndTo
->parent
== WIN_GetDesktop())
1209 WIN_GetDesktop()->hmemTaskQ
= pWndTo
->hmemTaskQ
;
1215 /*******************************************************************
1216 * WINPOS_ChangeActiveWindow
1219 BOOL32
WINPOS_ChangeActiveWindow( HWND32 hWnd
, BOOL32 mouseMsg
)
1221 WND
*wndPtr
= WIN_FindWndPtr(hWnd
);
1223 if (!hWnd
) return WINPOS_SetActiveWindow( 0, mouseMsg
, TRUE
);
1225 if( !wndPtr
) return FALSE
;
1227 /* child windows get WM_CHILDACTIVATE message */
1228 if( (wndPtr
->dwStyle
& (WS_CHILD
| WS_POPUP
)) == WS_CHILD
)
1229 return SendMessage16(hWnd
, WM_CHILDACTIVATE
, 0, 0L);
1231 /* owned popups imply owner activation - not sure */
1232 if ((wndPtr
->dwStyle
& WS_POPUP
) && wndPtr
->owner
&&
1233 !(wndPtr
->owner
->dwStyle
& WS_DISABLED
))
1235 if (!(wndPtr
= wndPtr
->owner
)) return FALSE
;
1236 hWnd
= wndPtr
->hwndSelf
;
1239 if( hWnd
== hwndActive
) return FALSE
;
1241 if( !WINPOS_SetActiveWindow(hWnd
,mouseMsg
,TRUE
) )
1244 /* switch desktop queue to current active */
1245 if( wndPtr
->parent
== WIN_GetDesktop())
1246 WIN_GetDesktop()->hmemTaskQ
= wndPtr
->hmemTaskQ
;
1252 /***********************************************************************
1253 * WINPOS_SendNCCalcSize
1255 * Send a WM_NCCALCSIZE message to a window.
1256 * All parameters are read-only except newClientRect.
1257 * oldWindowRect, oldClientRect and winpos must be non-NULL only
1258 * when calcValidRect is TRUE.
1260 LONG
WINPOS_SendNCCalcSize( HWND32 hwnd
, BOOL32 calcValidRect
,
1261 RECT16
*newWindowRect
, RECT16
*oldWindowRect
,
1262 RECT16
*oldClientRect
, SEGPTR winpos
,
1263 RECT16
*newClientRect
)
1265 NCCALCSIZE_PARAMS16
*params
;
1268 if (!(params
= SEGPTR_NEW(NCCALCSIZE_PARAMS16
))) return 0;
1269 params
->rgrc
[0] = *newWindowRect
;
1272 params
->rgrc
[1] = *oldWindowRect
;
1273 params
->rgrc
[2] = *oldClientRect
;
1274 params
->lppos
= winpos
;
1276 result
= SendMessage16( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
1277 (LPARAM
)SEGPTR_GET( params
) );
1278 dprintf_win( stddeb
, "WINPOS_SendNCCalcSize: %d,%d-%d,%d\n",
1279 params
->rgrc
[0].left
, params
->rgrc
[0].top
,
1280 params
->rgrc
[0].right
, params
->rgrc
[0].bottom
);
1281 *newClientRect
= params
->rgrc
[0];
1282 SEGPTR_FREE(params
);
1287 /***********************************************************************
1288 * WINPOS_HandleWindowPosChanging16
1290 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1292 LONG
WINPOS_HandleWindowPosChanging16( WND
*wndPtr
, WINDOWPOS16
*winpos
)
1295 if (winpos
->flags
& SWP_NOSIZE
) return 0;
1296 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
1297 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
1299 NC_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
1300 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
1301 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
1307 /***********************************************************************
1308 * WINPOS_HandleWindowPosChanging32
1310 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1312 LONG
WINPOS_HandleWindowPosChanging32( WND
*wndPtr
, WINDOWPOS32
*winpos
)
1315 if (winpos
->flags
& SWP_NOSIZE
) return 0;
1316 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
1317 ((wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
)) == 0))
1319 NC_GetMinMaxInfo( wndPtr
, &maxSize
, NULL
, NULL
, NULL
);
1320 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
1321 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
1327 /***********************************************************************
1328 * WINPOS_MoveWindowZOrder
1330 * Move a window in Z order, invalidating everything that needs it.
1331 * Only necessary for windows without associated X window.
1333 static void WINPOS_MoveWindowZOrder( HWND32 hwnd
, HWND32 hwndAfter
)
1336 WND
*pWndAfter
, *pWndCur
, *wndPtr
= WIN_FindWndPtr( hwnd
);
1338 /* We have two possible cases:
1339 * - The window is moving up: we have to invalidate all areas
1340 * of the window that were covered by other windows
1341 * - The window is moving down: we have to invalidate areas
1342 * of other windows covered by this one.
1345 if (hwndAfter
== HWND_TOP
)
1349 else if (hwndAfter
== HWND_BOTTOM
)
1351 if (!wndPtr
->next
) return; /* Already at the bottom */
1356 if (!(pWndAfter
= WIN_FindWndPtr( hwndAfter
))) return;
1357 if (wndPtr
->next
== pWndAfter
) return; /* Already placed right */
1359 /* Determine which window we encounter first in Z-order */
1360 pWndCur
= wndPtr
->parent
->child
;
1361 while ((pWndCur
!= wndPtr
) && (pWndCur
!= pWndAfter
))
1362 pWndCur
= pWndCur
->next
;
1363 movingUp
= (pWndCur
== pWndAfter
);
1368 WND
*pWndPrevAfter
= wndPtr
->next
;
1369 WIN_UnlinkWindow( hwnd
);
1370 WIN_LinkWindow( hwnd
, hwndAfter
);
1371 pWndCur
= wndPtr
->next
;
1372 while (pWndCur
!= pWndPrevAfter
)
1374 RECT32 rect
= { pWndCur
->rectWindow
.left
,
1375 pWndCur
->rectWindow
.top
,
1376 pWndCur
->rectWindow
.right
,
1377 pWndCur
->rectWindow
.bottom
};
1378 OffsetRect32( &rect
, -wndPtr
->rectClient
.left
,
1379 -wndPtr
->rectClient
.top
);
1380 PAINT_RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
|
1381 RDW_FRAME
| RDW_ERASE
, 0 );
1382 pWndCur
= pWndCur
->next
;
1385 else /* Moving down */
1387 pWndCur
= wndPtr
->next
;
1388 WIN_UnlinkWindow( hwnd
);
1389 WIN_LinkWindow( hwnd
, hwndAfter
);
1390 while (pWndCur
!= wndPtr
)
1392 RECT32 rect
= { pWndCur
->rectWindow
.left
,
1393 pWndCur
->rectWindow
.top
,
1394 pWndCur
->rectWindow
.right
,
1395 pWndCur
->rectWindow
.bottom
};
1396 OffsetRect32( &rect
, -pWndCur
->rectClient
.left
,
1397 -pWndCur
->rectClient
.top
);
1398 PAINT_RedrawWindow( pWndCur
->hwndSelf
, &rect
, 0, RDW_INVALIDATE
|
1399 RDW_ALLCHILDREN
| RDW_FRAME
| RDW_ERASE
, 0 );
1400 pWndCur
= pWndCur
->next
;
1405 /***********************************************************************
1406 * WINPOS_ReorderOwnedPopups
1408 * fix Z order taking into account owned popups -
1409 * basically we need to maintain them above owner window
1411 HWND32
WINPOS_ReorderOwnedPopups(HWND32 hwndInsertAfter
,WND
* wndPtr
,WORD flags
)
1413 WND
* w
= WIN_GetDesktop()->child
;
1415 if( wndPtr
->dwStyle
& WS_POPUP
&& wndPtr
->owner
)
1417 /* implement "local z-order" between the top and owner window */
1419 HWND32 hwndLocalPrev
= HWND_TOP
;
1421 if( hwndInsertAfter
!= HWND_TOP
)
1423 while( w
!= wndPtr
->owner
)
1425 if (w
!= wndPtr
) hwndLocalPrev
= w
->hwndSelf
;
1426 if( hwndLocalPrev
== hwndInsertAfter
) break;
1429 hwndInsertAfter
= hwndLocalPrev
;
1433 else if( wndPtr
->dwStyle
& WS_CHILD
) return hwndInsertAfter
;
1435 w
= WIN_GetDesktop()->child
;
1438 if( w
== wndPtr
) break;
1440 if( w
->dwStyle
& WS_POPUP
&& w
->owner
== wndPtr
)
1442 SetWindowPos32(w
->hwndSelf
, hwndInsertAfter
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
|
1443 SWP_NOACTIVATE
| SWP_NOSENDCHANGING
| SWP_DEFERERASE
);
1444 hwndInsertAfter
= w
->hwndSelf
;
1449 return hwndInsertAfter
;
1452 /***********************************************************************
1453 * WINPOS_SizeMoveClean
1455 * Make window look nice without excessive repainting
1459 * visible regions are in window coordinates
1460 * update regions are in window client coordinates
1461 * client and window rectangles are in parent client coordinates
1463 static UINT32
WINPOS_SizeMoveClean(WND
* Wnd
, HRGN32 oldVisRgn
, LPRECT16 lpOldWndRect
, LPRECT16 lpOldClientRect
, UINT32 uFlags
)
1465 HRGN32 newVisRgn
= DCE_GetVisRgn(Wnd
->hwndSelf
,DCX_WINDOW
| DCX_CLIPSIBLINGS
);
1466 HRGN32 dirtyRgn
= CreateRectRgn32(0,0,0,0);
1469 dprintf_win(stddeb
,"cleaning up...new wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i)\n\
1470 \t\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
1471 Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
, Wnd
->rectWindow
.right
, Wnd
->rectWindow
.bottom
,
1472 lpOldWndRect
->left
, lpOldWndRect
->top
, lpOldWndRect
->right
, lpOldWndRect
->bottom
,
1473 Wnd
->rectClient
.left
,Wnd
->rectClient
.top
,Wnd
->rectClient
.right
,Wnd
->rectClient
.bottom
,
1474 lpOldClientRect
->left
,lpOldClientRect
->top
,lpOldClientRect
->right
,lpOldClientRect
->bottom
);
1476 if( (lpOldWndRect
->right
- lpOldWndRect
->left
) != (Wnd
->rectWindow
.right
- Wnd
->rectWindow
.left
) ||
1477 (lpOldWndRect
->bottom
- lpOldWndRect
->top
) != (Wnd
->rectWindow
.bottom
- Wnd
->rectWindow
.top
) )
1478 uFlags
|= SMC_DRAWFRAME
;
1480 CombineRgn32( dirtyRgn
, newVisRgn
, 0, RGN_COPY
);
1482 if( !(uFlags
& SMC_NOCOPY
) )
1483 CombineRgn32( newVisRgn
, newVisRgn
, oldVisRgn
, RGN_AND
);
1485 /* map regions to the parent client area */
1487 OffsetRgn32( dirtyRgn
, Wnd
->rectWindow
.left
, Wnd
->rectWindow
.top
);
1488 OffsetRgn32( oldVisRgn
, lpOldWndRect
->left
, lpOldWndRect
->top
);
1490 /* compute invalidated region outside Wnd - (in client coordinates of the parent window) */
1492 other
= CombineRgn32(dirtyRgn
, oldVisRgn
, dirtyRgn
, RGN_DIFF
);
1494 /* map visible region to the Wnd client area */
1496 OffsetRgn32( newVisRgn
, Wnd
->rectWindow
.left
- Wnd
->rectClient
.left
,
1497 Wnd
->rectWindow
.top
- Wnd
->rectClient
.top
);
1499 /* substract previously invalidated region from the Wnd visible region */
1501 my
= (Wnd
->hrgnUpdate
> 1) ? CombineRgn32( newVisRgn
, newVisRgn
,
1502 Wnd
->hrgnUpdate
, RGN_DIFF
)
1505 if( uFlags
& SMC_NOCOPY
) /* invalidate Wnd visible region */
1507 if (my
!= NULLREGION
)
1508 PAINT_RedrawWindow( Wnd
->hwndSelf
, NULL
, newVisRgn
, RDW_INVALIDATE
|
1509 RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
, RDW_C_USEHRGN
);
1510 else if(uFlags
& SMC_DRAWFRAME
)
1511 Wnd
->flags
|= WIN_NEEDS_NCPAINT
;
1513 else /* bitblt old client area */
1518 int xfrom
,yfrom
,xto
,yto
,width
,height
;
1520 if( uFlags
& SMC_DRAWFRAME
)
1522 /* copy only client area, frame will be redrawn anyway */
1524 xfrom
= lpOldClientRect
->left
; yfrom
= lpOldClientRect
->top
;
1525 xto
= Wnd
->rectClient
.left
; yto
= Wnd
->rectClient
.top
;
1526 width
= lpOldClientRect
->right
- xfrom
; height
= lpOldClientRect
->bottom
- yfrom
;
1527 updateRgn
= CreateRectRgn32( 0, 0, width
, height
);
1528 CombineRgn32( newVisRgn
, newVisRgn
, updateRgn
, RGN_AND
);
1529 SetRectRgn32( updateRgn
, 0, 0, Wnd
->rectClient
.right
- xto
,
1530 Wnd
->rectClient
.bottom
- yto
);
1534 xfrom
= lpOldWndRect
->left
; yfrom
= lpOldWndRect
->top
;
1535 xto
= Wnd
->rectWindow
.left
; yto
= Wnd
->rectWindow
.top
;
1536 width
= lpOldWndRect
->right
- xfrom
; height
= lpOldWndRect
->bottom
- yfrom
;
1537 updateRgn
= CreateRectRgn32( xto
- Wnd
->rectClient
.left
,
1538 yto
- Wnd
->rectClient
.top
,
1539 Wnd
->rectWindow
.right
- Wnd
->rectClient
.left
,
1540 Wnd
->rectWindow
.bottom
- Wnd
->rectClient
.top
);
1543 CombineRgn32( newVisRgn
, newVisRgn
, updateRgn
, RGN_AND
);
1545 /* substract new visRgn from target rect to get a region that won't be copied */
1547 update
= CombineRgn32( updateRgn
, updateRgn
, newVisRgn
, RGN_DIFF
);
1549 /* Blt valid bits using parent window DC */
1551 if( my
!= NULLREGION
&& (xfrom
!= xto
|| yfrom
!= yto
) )
1554 /* compute clipping region in parent client coordinates */
1556 OffsetRgn32( newVisRgn
, Wnd
->rectClient
.left
, Wnd
->rectClient
.top
);
1557 CombineRgn32( oldVisRgn
, oldVisRgn
, newVisRgn
, RGN_OR
);
1559 hDC
= GetDCEx32( Wnd
->parent
->hwndSelf
, oldVisRgn
,
1560 DCX_KEEPCLIPRGN
| DCX_INTERSECTRGN
|
1561 DCX_CACHE
| DCX_CLIPSIBLINGS
);
1563 BitBlt32( hDC
, xto
, yto
, width
, height
, hDC
, xfrom
, yfrom
, SRCCOPY
);
1564 ReleaseDC32( Wnd
->parent
->hwndSelf
, hDC
);
1567 if( update
!= NULLREGION
)
1568 PAINT_RedrawWindow( Wnd
->hwndSelf
, NULL
, updateRgn
, RDW_INVALIDATE
|
1569 RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
, RDW_C_USEHRGN
);
1570 else if( uFlags
& SMC_DRAWFRAME
) Wnd
->flags
|= WIN_NEEDS_NCPAINT
;
1571 DeleteObject32( updateRgn
);
1574 /* erase uncovered areas */
1576 if( !(uFlags
& SMC_NOPARENTERASE
) && (other
!= NULLREGION
) )
1577 PAINT_RedrawWindow( Wnd
->parent
->hwndSelf
, NULL
, dirtyRgn
,
1578 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
, RDW_C_USEHRGN
);
1579 DeleteObject32(dirtyRgn
);
1580 DeleteObject32(newVisRgn
);
1585 /***********************************************************************
1586 * WINPOS_FindDeskTopXWindow
1588 * Find the actual X window which needs be restacked.
1589 * Used by WINPOS_SetXWindowPos().
1591 static Window
WINPOS_FindDeskTopXWindow( WND
*wndPtr
)
1593 if (!(wndPtr
->flags
& WIN_MANAGED
))
1594 return wndPtr
->window
;
1597 Window window
, root
, parent
, *children
;
1599 window
= wndPtr
->window
;
1602 XQueryTree( display
, window
, &root
, &parent
,
1603 &children
, &nchildren
);
1612 /***********************************************************************
1613 * WINPOS_SetXWindowPos
1615 * SetWindowPos() for an X window. Used by the real SetWindowPos().
1617 static void WINPOS_SetXWindowPos( WINDOWPOS16
*winpos
)
1619 XWindowChanges winChanges
;
1621 WND
*wndPtr
= WIN_FindWndPtr( winpos
->hwnd
);
1623 if (!(winpos
->flags
& SWP_NOSIZE
))
1625 winChanges
.width
= winpos
->cx
;
1626 winChanges
.height
= winpos
->cy
;
1627 changeMask
|= CWWidth
| CWHeight
;
1629 /* Tweak dialog window size hints */
1631 if ((wndPtr
->flags
& WIN_MANAGED
) &&
1632 (wndPtr
->dwExStyle
& WS_EX_DLGMODALFRAME
))
1634 XSizeHints
*size_hints
= XAllocSizeHints();
1638 long supplied_return
;
1640 XGetWMSizeHints( display
, wndPtr
->window
, size_hints
,
1641 &supplied_return
, XA_WM_NORMAL_HINTS
);
1642 size_hints
->min_width
= size_hints
->max_width
= winpos
->cx
;
1643 size_hints
->min_height
= size_hints
->max_height
= winpos
->cy
;
1644 XSetWMSizeHints( display
, wndPtr
->window
, size_hints
,
1645 XA_WM_NORMAL_HINTS
);
1650 if (!(winpos
->flags
& SWP_NOMOVE
))
1652 winChanges
.x
= winpos
->x
;
1653 winChanges
.y
= winpos
->y
;
1654 changeMask
|= CWX
| CWY
;
1656 if (!(winpos
->flags
& SWP_NOZORDER
))
1658 winChanges
.stack_mode
= Below
;
1659 changeMask
|= CWStackMode
;
1661 if (winpos
->hwndInsertAfter
== HWND_TOP
) winChanges
.stack_mode
= Above
;
1662 else if (winpos
->hwndInsertAfter
!= HWND_BOTTOM
)
1664 WND
* insertPtr
= WIN_FindWndPtr( winpos
->hwndInsertAfter
);
1667 stack
[0] = WINPOS_FindDeskTopXWindow( insertPtr
);
1668 stack
[1] = WINPOS_FindDeskTopXWindow( wndPtr
);
1670 /* for stupid window managers (i.e. all of them) */
1672 XRestackWindows(display
, stack
, 2);
1673 changeMask
&= ~CWStackMode
;
1676 if (!changeMask
) return;
1678 XReconfigureWMWindow( display
, wndPtr
->window
, 0, changeMask
, &winChanges
);
1682 /***********************************************************************
1683 * SetWindowPos (USER.232)
1685 BOOL16
SetWindowPos16( HWND16 hwnd
, HWND16 hwndInsertAfter
, INT16 x
, INT16 y
,
1686 INT16 cx
, INT16 cy
, WORD flags
)
1688 return SetWindowPos32(hwnd
,(INT32
)(INT16
)hwndInsertAfter
,x
,y
,cx
,cy
,flags
);
1691 /***********************************************************************
1692 * SetWindowPos (USER32.519)
1694 BOOL32
SetWindowPos32( HWND32 hwnd
, HWND32 hwndInsertAfter
, INT32 x
, INT32 y
,
1695 INT32 cx
, INT32 cy
, WORD flags
)
1697 WINDOWPOS16
*winpos
;
1699 RECT16 newWindowRect
, newClientRect
, oldWindowRect
;
1701 HWND32 tempInsertAfter
= 0;
1705 dprintf_win(stddeb
,"SetWindowPos: hwnd %04x, (%i,%i)-(%i,%i) flags %08x\n",
1706 hwnd
, x
, y
, x
+cx
, y
+cy
, flags
);
1707 /* Check window handle */
1709 if (hwnd
== GetDesktopWindow32()) return FALSE
;
1710 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
1712 if (wndPtr
->dwStyle
& WS_VISIBLE
) flags
&= ~SWP_SHOWWINDOW
;
1715 uFlags
|= SMC_NOPARENTERASE
;
1716 flags
&= ~SWP_HIDEWINDOW
;
1717 if (!(flags
& SWP_SHOWWINDOW
)) flags
|= SWP_NOREDRAW
;
1720 /* Check for windows that may not be resized
1721 FIXME: this should be done only for Windows 3.0 programs
1722 if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW ) )
1723 flags |= SWP_NOSIZE | SWP_NOMOVE;
1725 /* Check dimensions */
1727 if (cx
<= 0) cx
= 1;
1728 if (cy
<= 0) cy
= 1;
1732 if (hwnd
== hwndActive
) flags
|= SWP_NOACTIVATE
; /* Already active */
1733 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
1734 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
1735 flags
|= SWP_NOSIZE
; /* Already the right size */
1736 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
1737 flags
|= SWP_NOMOVE
; /* Already the right position */
1739 /* Check hwndInsertAfter */
1741 if (!(flags
& (SWP_NOZORDER
| SWP_NOACTIVATE
)))
1743 /* Ignore TOPMOST flags when activating a window */
1744 /* _and_ moving it in Z order. */
1745 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
1746 (hwndInsertAfter
== HWND_NOTOPMOST
))
1747 hwndInsertAfter
= HWND_TOP
;
1749 /* TOPMOST not supported yet */
1750 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
1751 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
1753 /* hwndInsertAfter must be a sibling of the window */
1754 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
1756 WND
* wnd
= WIN_FindWndPtr(hwndInsertAfter
);
1757 if( wnd
->parent
!= wndPtr
->parent
) return FALSE
;
1758 if( wnd
->next
== wndPtr
) flags
|= SWP_NOZORDER
;
1760 else if (!(wndPtr
->window
))
1761 /* FIXME: the following optimization is no good for "X-ed" windows */
1762 if (hwndInsertAfter
== HWND_TOP
)
1763 flags
|= ( wndPtr
->parent
->child
== wndPtr
)? SWP_NOZORDER
: 0;
1764 else /* HWND_BOTTOM */
1765 flags
|= ( wndPtr
->next
)? 0: SWP_NOZORDER
;
1767 /* Fill the WINDOWPOS structure */
1769 if (!(winpos
= SEGPTR_NEW(WINDOWPOS16
))) return FALSE
;
1770 winpos
->hwnd
= hwnd
;
1771 winpos
->hwndInsertAfter
= hwndInsertAfter
;
1776 winpos
->flags
= flags
;
1778 /* Send WM_WINDOWPOSCHANGING message */
1780 if (!(flags
& SWP_NOSENDCHANGING
))
1781 SendMessage16( hwnd
, WM_WINDOWPOSCHANGING
, 0,
1782 (LPARAM
)SEGPTR_GET(winpos
) );
1784 /* Calculate new position and size */
1786 newWindowRect
= wndPtr
->rectWindow
;
1787 newClientRect
= (wndPtr
->dwStyle
& WS_MINIMIZE
) ? wndPtr
->rectWindow
1788 : wndPtr
->rectClient
;
1790 if (!(winpos
->flags
& SWP_NOSIZE
))
1792 newWindowRect
.right
= newWindowRect
.left
+ winpos
->cx
;
1793 newWindowRect
.bottom
= newWindowRect
.top
+ winpos
->cy
;
1795 if (!(winpos
->flags
& SWP_NOMOVE
))
1797 newWindowRect
.left
= winpos
->x
;
1798 newWindowRect
.top
= winpos
->y
;
1799 newWindowRect
.right
+= winpos
->x
- wndPtr
->rectWindow
.left
;
1800 newWindowRect
.bottom
+= winpos
->y
- wndPtr
->rectWindow
.top
;
1802 OffsetRect16( &newClientRect
, winpos
->x
- wndPtr
->rectWindow
.left
,
1803 winpos
->y
- wndPtr
->rectWindow
.top
);
1806 winpos
->flags
|= SWP_NOCLIENTMOVE
| SWP_NOCLIENTSIZE
;
1808 /* Reposition window in Z order */
1810 if (!(winpos
->flags
& SWP_NOZORDER
))
1812 /* reorder owned popups if hwnd is top-level window
1814 if( wndPtr
->parent
== WIN_GetDesktop() )
1815 hwndInsertAfter
= WINPOS_ReorderOwnedPopups( hwndInsertAfter
,
1820 WIN_UnlinkWindow( winpos
->hwnd
);
1821 WIN_LinkWindow( winpos
->hwnd
, hwndInsertAfter
);
1823 else WINPOS_MoveWindowZOrder( winpos
->hwnd
, hwndInsertAfter
);
1826 if ( !wndPtr
->window
&& !(flags
& SWP_NOREDRAW
) &&
1827 (!(flags
& SWP_NOMOVE
) || !(flags
& SWP_NOSIZE
) || (flags
& SWP_FRAMECHANGED
)) )
1828 visRgn
= DCE_GetVisRgn(hwnd
, DCX_WINDOW
| DCX_CLIPSIBLINGS
);
1831 /* Send WM_NCCALCSIZE message to get new client area */
1832 if( (flags
& (SWP_FRAMECHANGED
| SWP_NOSIZE
)) != SWP_NOSIZE
)
1834 result
= WINPOS_SendNCCalcSize( winpos
->hwnd
, TRUE
, &newWindowRect
,
1835 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
1836 SEGPTR_GET(winpos
), &newClientRect
);
1838 /* FIXME: WVR_ALIGNxxx */
1840 if( newClientRect
.left
!= wndPtr
->rectClient
.left
||
1841 newClientRect
.top
!= wndPtr
->rectClient
.top
)
1842 winpos
->flags
&= ~SWP_NOCLIENTMOVE
;
1844 if( (newClientRect
.right
- newClientRect
.left
!=
1845 wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
) ||
1846 (newClientRect
.bottom
- newClientRect
.top
!=
1847 wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
) )
1848 winpos
->flags
&= ~SWP_NOCLIENTSIZE
;
1851 if( !(flags
& SWP_NOMOVE
) && (newClientRect
.left
!= wndPtr
->rectClient
.left
||
1852 newClientRect
.top
!= wndPtr
->rectClient
.top
) )
1853 winpos
->flags
&= ~SWP_NOCLIENTMOVE
;
1855 /* Update active DCEs */
1857 if( !(flags
& SWP_NOZORDER
) || (flags
& SWP_HIDEWINDOW
) || (flags
& SWP_SHOWWINDOW
)
1858 || (memcmp(&newWindowRect
,&wndPtr
->rectWindow
,sizeof(RECT16
))
1859 && wndPtr
->dwStyle
& WS_VISIBLE
) )
1863 UnionRect16(&rect
,&newWindowRect
,&wndPtr
->rectWindow
);
1864 DCE_InvalidateDCE(wndPtr
->parent
, &rect
);
1867 /* change geometry */
1869 oldWindowRect
= wndPtr
->rectWindow
;
1873 RECT16 oldClientRect
= wndPtr
->rectClient
;
1875 tempInsertAfter
= winpos
->hwndInsertAfter
;
1877 winpos
->hwndInsertAfter
= hwndInsertAfter
;
1879 /* postpone geometry change */
1881 if( !(flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
)) )
1883 WINPOS_SetXWindowPos( winpos
);
1884 winpos
->hwndInsertAfter
= tempInsertAfter
;
1886 else uFlags
|= SMC_SETXPOS
;
1888 wndPtr
->rectWindow
= newWindowRect
;
1889 wndPtr
->rectClient
= newClientRect
;
1891 if( !(flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
)) )
1892 if( (oldClientRect
.left
- oldWindowRect
.left
!=
1893 newClientRect
.left
- newWindowRect
.left
) ||
1894 (oldClientRect
.top
- oldWindowRect
.top
!=
1895 newClientRect
.top
- newWindowRect
.top
) || winpos
->flags
& SWP_NOCOPYBITS
)
1897 PAINT_RedrawWindow( wndPtr
->hwndSelf
, NULL
, 0, RDW_INVALIDATE
|
1898 RDW_ALLCHILDREN
| RDW_FRAME
| RDW_ERASE
, 0 );
1900 if( winpos
->flags
& SWP_FRAMECHANGED
)
1905 if( oldClientRect
.right
> newClientRect
.right
)
1907 rect
.left
= newClientRect
.right
; rect
.top
= newClientRect
.top
;
1908 rect
.right
= oldClientRect
.right
; rect
.bottom
= newClientRect
.bottom
;
1910 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, 0,
1911 RDW_INVALIDATE
| RDW_FRAME
| RDW_ALLCHILDREN
, 0 );
1913 if( oldClientRect
.bottom
> newClientRect
.bottom
)
1915 rect
.left
= newClientRect
.left
; rect
.top
= newClientRect
.bottom
;
1916 rect
.right
= (wErase
)?oldClientRect
.right
:newClientRect
.right
;
1917 rect
.bottom
= oldClientRect
.bottom
;
1919 PAINT_RedrawWindow( wndPtr
->hwndSelf
, &rect
, 0,
1920 RDW_INVALIDATE
| RDW_FRAME
| RDW_ALLCHILDREN
, 0 );
1922 if( !wErase
) wndPtr
->flags
|= WIN_NEEDS_NCPAINT
;
1927 RECT16 oldClientRect
= wndPtr
->rectClient
;
1929 wndPtr
->rectWindow
= newWindowRect
;
1930 wndPtr
->rectClient
= newClientRect
;
1932 if( oldClientRect
.bottom
- oldClientRect
.top
==
1933 newClientRect
.bottom
- newClientRect
.top
) result
&= ~WVR_VREDRAW
;
1935 if( oldClientRect
.right
- oldClientRect
.left
==
1936 newClientRect
.right
- newClientRect
.left
) result
&= ~WVR_HREDRAW
;
1938 if( !(flags
& (SWP_NOREDRAW
| SWP_HIDEWINDOW
| SWP_SHOWWINDOW
)) )
1940 uFlags
|= ((winpos
->flags
& SWP_NOCOPYBITS
) ||
1941 (result
>= WVR_HREDRAW
&& result
< WVR_VALIDRECTS
)) ? SMC_NOCOPY
: 0;
1942 uFlags
|= (winpos
->flags
& SWP_FRAMECHANGED
) ? SMC_DRAWFRAME
: 0;
1944 if( (winpos
->flags
& SWP_AGG_NOGEOMETRYCHANGE
) != SWP_AGG_NOGEOMETRYCHANGE
)
1945 uFlags
= WINPOS_SizeMoveClean(wndPtr
, visRgn
, &oldWindowRect
,
1946 &oldClientRect
, uFlags
);
1949 /* adjust frame and do not erase parent */
1951 if( winpos
->flags
& SWP_FRAMECHANGED
) wndPtr
->flags
|= WIN_NEEDS_NCPAINT
;
1952 if( winpos
->flags
& SWP_NOZORDER
) uFlags
|= SMC_NOPARENTERASE
;
1955 DeleteObject32(visRgn
);
1958 if (flags
& SWP_SHOWWINDOW
)
1960 wndPtr
->dwStyle
|= WS_VISIBLE
;
1963 if( uFlags
& SMC_SETXPOS
)
1965 WINPOS_SetXWindowPos( winpos
);
1966 winpos
->hwndInsertAfter
= tempInsertAfter
;
1968 XMapWindow( display
, wndPtr
->window
);
1972 if (!(flags
& SWP_NOREDRAW
))
1973 PAINT_RedrawWindow( winpos
->hwnd
, NULL
, 0,
1974 RDW_INVALIDATE
| RDW_ALLCHILDREN
|
1975 RDW_FRAME
| RDW_ERASENOW
| RDW_ERASE
, 0 );
1978 else if (flags
& SWP_HIDEWINDOW
)
1980 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
1983 XUnmapWindow( display
, wndPtr
->window
);
1984 if( uFlags
& SMC_SETXPOS
)
1986 WINPOS_SetXWindowPos( winpos
);
1987 winpos
->hwndInsertAfter
= tempInsertAfter
;
1992 if (!(flags
& SWP_NOREDRAW
))
1994 RECT32 rect
= { oldWindowRect
.left
, oldWindowRect
.top
,
1995 oldWindowRect
.right
, oldWindowRect
.bottom
};
1996 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, &rect
, 0,
1997 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
| RDW_ERASENOW
, 0);
1999 uFlags
|= SMC_NOPARENTERASE
;
2002 if ((winpos
->hwnd
== GetFocus32()) ||
2003 IsChild32( winpos
->hwnd
, GetFocus32()))
2005 /* Revert focus to parent */
2006 SetFocus32( GetParent32(winpos
->hwnd
) );
2008 if (hwnd
== CARET_GetHwnd()) DestroyCaret32();
2010 if (winpos
->hwnd
== hwndActive
)
2012 /* Activate previously active window if possible */
2013 HWND32 newActive
= hwndPrevActive
;
2014 if (!IsWindow32(newActive
) || (newActive
== winpos
->hwnd
))
2016 newActive
= GetTopWindow32( GetDesktopWindow32() );
2017 if (newActive
== winpos
->hwnd
)
2018 newActive
= wndPtr
->next
? wndPtr
->next
->hwndSelf
: 0;
2020 WINPOS_ChangeActiveWindow( newActive
, FALSE
);
2024 /* Activate the window */
2026 if (!(flags
& SWP_NOACTIVATE
))
2027 WINPOS_ChangeActiveWindow( winpos
->hwnd
, FALSE
);
2029 /* Repaint the window */
2031 if (wndPtr
->window
) EVENT_Synchronize(); /* Wait for all expose events */
2033 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
2035 if (!(flags
& SWP_DEFERERASE
) && !(uFlags
& SMC_NOPARENTERASE
) )
2038 CONV_RECT16TO32( &oldWindowRect
, &rect
);
2039 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, (wndPtr
->flags
& WIN_SAVEUNDER_OVERRIDE
)
2040 ? &rect
: NULL
, 0, RDW_ALLCHILDREN
| RDW_ERASENOW
|
2041 ((wndPtr
->flags
& WIN_SAVEUNDER_OVERRIDE
) ? RDW_INVALIDATE
: 0), 0 );
2042 wndPtr
->flags
&= ~WIN_SAVEUNDER_OVERRIDE
;
2044 else if( wndPtr
->parent
== WIN_GetDesktop() && wndPtr
->parent
->flags
& WIN_NEEDS_ERASEBKGND
)
2045 PAINT_RedrawWindow( wndPtr
->parent
->hwndSelf
, NULL
, 0, RDW_NOCHILDREN
| RDW_ERASENOW
, 0 );
2047 /* And last, send the WM_WINDOWPOSCHANGED message */
2049 dprintf_win(stddeb
,"\tstatus flags = %04x\n", winpos
->flags
& SWP_AGG_STATUSFLAGS
);
2051 if ( ((winpos
->flags
& SWP_AGG_STATUSFLAGS
) != SWP_AGG_NOPOSCHANGE
) &&
2052 !(winpos
->flags
& SWP_NOSENDCHANGING
))
2053 SendMessage16( winpos
->hwnd
, WM_WINDOWPOSCHANGED
,
2054 0, (LPARAM
)SEGPTR_GET(winpos
) );
2056 SEGPTR_FREE(winpos
);
2061 /***********************************************************************
2062 * BeginDeferWindowPos16 (USER.259)
2064 HDWP16
BeginDeferWindowPos16( INT16 count
)
2066 return BeginDeferWindowPos32( count
);
2070 /***********************************************************************
2071 * BeginDeferWindowPos32 (USER32.8)
2073 HDWP32
BeginDeferWindowPos32( INT32 count
)
2078 if (count
<= 0) return 0;
2079 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS32
) );
2080 if (!handle
) return 0;
2081 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
2082 pDWP
->actualCount
= 0;
2083 pDWP
->suggestedCount
= count
;
2085 pDWP
->wMagic
= DWP_MAGIC
;
2086 pDWP
->hwndParent
= 0;
2091 /***********************************************************************
2092 * DeferWindowPos16 (USER.260)
2094 HDWP16
DeferWindowPos16( HDWP16 hdwp
, HWND16 hwnd
, HWND16 hwndAfter
,
2095 INT16 x
, INT16 y
, INT16 cx
, INT16 cy
, UINT16 flags
)
2097 return DeferWindowPos32( hdwp
, hwnd
, (INT32
)(INT16
)hwndAfter
,
2098 x
, y
, cx
, cy
, flags
);
2102 /***********************************************************************
2103 * DeferWindowPos32 (USER32.127)
2105 HDWP32
DeferWindowPos32( HDWP32 hdwp
, HWND32 hwnd
, HWND32 hwndAfter
,
2106 INT32 x
, INT32 y
, INT32 cx
, INT32 cy
, UINT32 flags
)
2110 HDWP32 newhdwp
= hdwp
;
2113 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2114 if (!pDWP
) return 0;
2115 if (hwnd
== GetDesktopWindow32()) return 0;
2117 /* All the windows of a DeferWindowPos() must have the same parent */
2119 parent
= WIN_FindWndPtr( hwnd
)->parent
->hwndSelf
;
2120 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
2121 else if (parent
!= pDWP
->hwndParent
)
2123 USER_HEAP_FREE( hdwp
);
2127 for (i
= 0; i
< pDWP
->actualCount
; i
++)
2129 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
2131 /* Merge with the other changes */
2132 if (!(flags
& SWP_NOZORDER
))
2134 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
2136 if (!(flags
& SWP_NOMOVE
))
2138 pDWP
->winPos
[i
].x
= x
;
2139 pDWP
->winPos
[i
].y
= y
;
2141 if (!(flags
& SWP_NOSIZE
))
2143 pDWP
->winPos
[i
].cx
= cx
;
2144 pDWP
->winPos
[i
].cy
= cy
;
2146 pDWP
->winPos
[i
].flags
&= flags
& (SWP_NOSIZE
| SWP_NOMOVE
|
2147 SWP_NOZORDER
| SWP_NOREDRAW
|
2148 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
2150 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
2155 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
2157 newhdwp
= USER_HEAP_REALLOC( hdwp
,
2158 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS32
) );
2159 if (!newhdwp
) return 0;
2160 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
2161 pDWP
->suggestedCount
++;
2163 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
2164 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
2165 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
2166 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
2167 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
2168 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
2169 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
2170 pDWP
->actualCount
++;
2175 /***********************************************************************
2176 * EndDeferWindowPos16 (USER.261)
2178 BOOL16
EndDeferWindowPos16( HDWP16 hdwp
)
2180 return EndDeferWindowPos32( hdwp
);
2184 /***********************************************************************
2185 * EndDeferWindowPos32 (USER32.172)
2187 BOOL32
EndDeferWindowPos32( HDWP32 hdwp
)
2190 WINDOWPOS32
*winpos
;
2194 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
2195 if (!pDWP
) return FALSE
;
2196 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
2198 if (!(res
= SetWindowPos32( winpos
->hwnd
, winpos
->hwndInsertAfter
,
2199 winpos
->x
, winpos
->y
, winpos
->cx
,
2200 winpos
->cy
, winpos
->flags
))) break;
2202 USER_HEAP_FREE( hdwp
);
2207 /***********************************************************************
2208 * TileChildWindows (USER.199)
2210 void TileChildWindows( HWND16 parent
, WORD action
)
2212 printf("STUB TileChildWindows(%04x, %d)\n", parent
, action
);
2215 /***********************************************************************
2216 * CascageChildWindows (USER.198)
2218 void CascadeChildWindows( HWND16 parent
, WORD action
)
2220 printf("STUB CascadeChildWindows(%04x, %d)\n", parent
, action
);