2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
7 #include "sysmetrics.h"
12 #include "stackframe.h"
14 #include "nonclient.h"
16 /* #define DEBUG_WIN */
19 static HWND hwndActive
= 0; /* Currently active window */
22 /***********************************************************************
25 * Find a suitable place for an iconic window.
26 * The new position is stored into wndPtr->ptIconPos.
28 void WINPOS_FindIconPos( HWND hwnd
)
31 short x
, y
, xspacing
, yspacing
;
32 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
35 GetClientRect( wndPtr
->hwndParent
, &rectParent
);
36 if ((wndPtr
->ptIconPos
.x
>= rectParent
.left
) &&
37 (wndPtr
->ptIconPos
.x
+ SYSMETRICS_CXICON
< rectParent
.right
) &&
38 (wndPtr
->ptIconPos
.y
>= rectParent
.top
) &&
39 (wndPtr
->ptIconPos
.y
+ SYSMETRICS_CYICON
< rectParent
.bottom
))
40 return; /* The icon already has a suitable position */
42 xspacing
= yspacing
= 70; /* FIXME: This should come from WIN.INI */
43 y
= rectParent
.bottom
;
46 for (x
= rectParent
.left
; x
<=rectParent
.right
-xspacing
; x
+= xspacing
)
48 /* Check if another icon already occupies this spot */
49 HWND hwndChild
= GetWindow( wndPtr
->hwndParent
, GW_CHILD
);
52 WND
*childPtr
= WIN_FindWndPtr( hwndChild
);
53 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (hwndChild
!= hwnd
))
55 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
56 (childPtr
->rectWindow
.right
>= x
) &&
57 (childPtr
->rectWindow
.top
<= y
) &&
58 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
59 break; /* There's a window in there */
62 hwndChild
= childPtr
->hwndNext
;
66 /* No window was found, so it's OK for us */
67 wndPtr
->ptIconPos
.x
= x
+ (xspacing
- SYSMETRICS_CXICON
) / 2;
68 wndPtr
->ptIconPos
.y
= y
- (yspacing
+ SYSMETRICS_CYICON
) / 2;
77 /***********************************************************************
78 * ArrangeIconicWindows (USER.170)
80 WORD
ArrangeIconicWindows( HWND parent
)
84 short x
, y
, xspacing
, yspacing
;
86 GetClientRect( parent
, &rectParent
);
88 y
= rectParent
.bottom
;
89 xspacing
= yspacing
= 70; /* FIXME: This should come from WIN.INI */
90 hwndChild
= GetWindow( parent
, GW_CHILD
);
93 if (IsIconic( hwndChild
))
95 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- SYSMETRICS_CXICON
) / 2,
96 y
- (yspacing
+ SYSMETRICS_CYICON
) / 2, 0, 0,
97 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
98 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
105 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
111 /***********************************************************************
112 * GetWindowRect (USER.32)
114 void GetWindowRect( HWND hwnd
, LPRECT rect
)
116 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
119 *rect
= wndPtr
->rectWindow
;
120 if (wndPtr
->dwStyle
& WS_CHILD
)
121 MapWindowPoints( wndPtr
->hwndParent
, 0, (POINT
*)rect
, 2 );
125 /***********************************************************************
126 * GetClientRect (USER.33)
128 void GetClientRect( HWND hwnd
, LPRECT rect
)
130 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
132 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
135 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
136 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
141 /*******************************************************************
142 * ClientToScreen (USER.28)
144 void ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
146 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
150 /*******************************************************************
151 * ScreenToClient (USER.29)
153 void ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
155 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
159 /*******************************************************************
160 * WindowFromPoint (USER.30)
162 HWND
WindowFromPoint( POINT pt
)
165 HWND hwnd
= GetDesktopWindow();
169 /* If point is in window, and window is visible, */
170 /* not disabled and not transparent, then explore */
171 /* its children. Otherwise, go to the next window. */
173 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
174 if ((pt
.x
>= wndPtr
->rectWindow
.left
) &&
175 (pt
.x
< wndPtr
->rectWindow
.right
) &&
176 (pt
.y
>= wndPtr
->rectWindow
.top
) &&
177 (pt
.y
< wndPtr
->rectWindow
.bottom
) &&
178 !(wndPtr
->dwStyle
& WS_DISABLED
) &&
179 (wndPtr
->dwStyle
& WS_VISIBLE
) &&
180 !(wndPtr
->dwExStyle
& WS_EX_TRANSPARENT
))
183 /* If window is minimized, ignore its children */
184 if (wndPtr
->dwStyle
& WS_MINIMIZE
) break;
185 pt
.x
-= wndPtr
->rectClient
.left
;
186 pt
.y
-= wndPtr
->rectClient
.top
;
187 hwnd
= wndPtr
->hwndChild
;
189 else hwnd
= wndPtr
->hwndNext
;
195 /*******************************************************************
196 * ChildWindowFromPoint (USER.191)
198 HWND
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
203 GetWindowRect( hwndParent
, &rect
);
204 if (!PtInRect( &rect
, pt
)) return 0;
205 hwnd
= GetTopWindow( hwndParent
);
208 GetWindowRect( hwnd
, &rect
);
209 if (PtInRect( &rect
, pt
)) return hwnd
;
210 hwnd
= GetWindow( hwnd
, GW_HWNDNEXT
);
216 /*******************************************************************
217 * MapWindowPoints (USER.258)
219 void MapWindowPoints( HWND hwndFrom
, HWND hwndTo
, LPPOINT lppt
, WORD count
)
223 POINT origin
= { 0, 0 };
226 /* Translate source window origin to screen coords */
229 wndPtr
= WIN_FindWndPtr( hwndFrom
);
230 origin
.x
+= wndPtr
->rectClient
.left
;
231 origin
.y
+= wndPtr
->rectClient
.top
;
232 hwndFrom
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->hwndParent
: 0;
235 /* Translate origin to destination window coords */
238 wndPtr
= WIN_FindWndPtr( hwndTo
);
239 origin
.x
-= wndPtr
->rectClient
.left
;
240 origin
.y
-= wndPtr
->rectClient
.top
;
241 hwndTo
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->hwndParent
: 0;
244 /* Translate points */
245 for (i
= 0, curpt
= lppt
; i
< count
; i
++, curpt
++)
247 curpt
->x
+= origin
.x
;
248 curpt
->y
+= origin
.y
;
253 /***********************************************************************
256 BOOL
IsIconic(HWND hWnd
)
258 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
259 if (wndPtr
== NULL
) return FALSE
;
260 return (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
264 /***********************************************************************
265 * IsZoomed (USER.272)
267 BOOL
IsZoomed(HWND hWnd
)
269 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
270 if (wndPtr
== NULL
) return FALSE
;
271 return (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
275 /*******************************************************************
276 * GetActiveWindow (USER.60)
278 HWND
GetActiveWindow()
284 /*******************************************************************
285 * SetActiveWindow (USER.59)
287 HWND
SetActiveWindow( HWND hwnd
)
289 HWND prev
= hwndActive
;
290 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
291 if (!wndPtr
|| (wndPtr
->dwStyle
& WS_CHILD
)) return 0;
292 SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
297 /***********************************************************************
298 * BringWindowToTop (USER.45)
300 BOOL
BringWindowToTop( HWND hwnd
)
302 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
306 /***********************************************************************
307 * MoveWindow (USER.56)
309 BOOL
MoveWindow( HWND hwnd
, short x
, short y
, short cx
, short cy
, BOOL repaint
)
311 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
312 if (!repaint
) flags
|= SWP_NOREDRAW
;
313 dprintf_win(stddeb
, "MoveWindow: "NPFMT
" %d,%d %dx%d %d\n",
314 hwnd
, x
, y
, cx
, cy
, repaint
);
315 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
319 /***********************************************************************
320 * ShowWindow (USER.42)
322 BOOL
ShowWindow( HWND hwnd
, int cmd
)
324 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
328 short x
= 0, y
= 0, cx
= 0, cy
= 0;
330 if (!wndPtr
) return FALSE
;
332 dprintf_win(stddeb
,"ShowWindow: hwnd="NPFMT
", cmd=%d\n", hwnd
, cmd
);
334 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
339 swpflags
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
340 SWP_NOACTIVATE
| SWP_NOZORDER
;
343 case SW_SHOWMINNOACTIVE
:
344 swpflags
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
346 case SW_SHOWMINIMIZED
:
347 swpflags
|= SWP_SHOWWINDOW
;
350 swpflags
|= SWP_FRAMECHANGED
;
351 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
353 if (wndPtr
->dwStyle
& WS_MAXIMIZE
)
355 wndPtr
->flags
|= WIN_RESTORE_MAX
;
356 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
360 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
361 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
363 wndPtr
->dwStyle
|= WS_MINIMIZE
;
364 WINPOS_FindIconPos( hwnd
);
365 x
= wndPtr
->ptIconPos
.x
;
366 y
= wndPtr
->ptIconPos
.y
;
367 cx
= SYSMETRICS_CXICON
;
368 cy
= SYSMETRICS_CYICON
;
370 else swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
373 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE: */
374 swpflags
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
375 if (!(wndPtr
->dwStyle
& WS_MAXIMIZE
))
377 /* Store the current position and find the maximized size */
378 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
379 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
380 NC_GetMinMaxInfo( hwnd
, &maxSize
,
381 &wndPtr
->ptMaxPos
, NULL
, NULL
);
382 x
= wndPtr
->ptMaxPos
.x
;
383 y
= wndPtr
->ptMaxPos
.y
;
386 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
387 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
389 else swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
393 swpflags
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
396 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
399 case SW_SHOWNOACTIVATE
:
400 swpflags
|= SWP_NOZORDER
;
401 if (GetActiveWindow()) swpflags
|= SWP_NOACTIVATE
;
403 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
405 swpflags
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
406 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
408 wndPtr
->ptIconPos
.x
= wndPtr
->rectWindow
.left
;
409 wndPtr
->ptIconPos
.y
= wndPtr
->rectWindow
.top
;
410 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
411 if (wndPtr
->flags
& WIN_RESTORE_MAX
)
413 /* Restore to maximized position */
414 NC_GetMinMaxInfo( hwnd
, &maxSize
, &wndPtr
->ptMaxPos
,
416 x
= wndPtr
->ptMaxPos
.x
;
417 y
= wndPtr
->ptMaxPos
.y
;
420 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
422 else /* Restore to normal position */
424 x
= wndPtr
->rectNormal
.left
;
425 y
= wndPtr
->rectNormal
.top
;
426 cx
= wndPtr
->rectNormal
.right
- wndPtr
->rectNormal
.left
;
427 cy
= wndPtr
->rectNormal
.bottom
- wndPtr
->rectNormal
.top
;
430 else if (wndPtr
->dwStyle
& WS_MAXIMIZE
)
432 wndPtr
->ptMaxPos
.x
= wndPtr
->rectWindow
.left
;
433 wndPtr
->ptMaxPos
.y
= wndPtr
->rectWindow
.top
;
434 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
435 x
= wndPtr
->rectNormal
.left
;
436 y
= wndPtr
->rectNormal
.top
;
437 cx
= wndPtr
->rectNormal
.right
- wndPtr
->rectNormal
.left
;
438 cy
= wndPtr
->rectNormal
.bottom
- wndPtr
->rectNormal
.top
;
440 else swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
444 SendMessage( hwnd
, WM_SHOWWINDOW
, (cmd
!= SW_HIDE
), 0 );
445 SetWindowPos( hwnd
, HWND_TOP
, x
, y
, cx
, cy
, swpflags
);
447 /* Send WM_SIZE and WM_MOVE messages if not already done */
448 if (!(wndPtr
->flags
& WIN_GOT_SIZEMSG
))
450 int wParam
= SIZE_RESTORED
;
451 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
452 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
453 wndPtr
->flags
|= WIN_GOT_SIZEMSG
;
454 SendMessage( hwnd
, WM_SIZE
, wParam
,
455 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
456 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
457 SendMessage( hwnd
, WM_MOVE
, 0,
458 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
465 /***********************************************************************
466 * GetInternalWindowPos (USER.460)
468 WORD
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
, LPPOINT ptIcon
)
470 WINDOWPLACEMENT wndpl
;
471 if (!GetWindowPlacement( hwnd
, &wndpl
)) return 0;
472 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
473 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
474 return wndpl
.showCmd
;
478 /***********************************************************************
479 * SetInternalWindowPos (USER.461)
481 void SetInternalWindowPos( HWND hwnd
, WORD showCmd
, LPRECT rect
, LPPOINT pt
)
483 WINDOWPLACEMENT wndpl
;
484 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
486 wndpl
.length
= sizeof(wndpl
);
487 wndpl
.flags
= (pt
!= NULL
) ? WPF_SETMINPOSITION
: 0;
488 wndpl
.showCmd
= showCmd
;
489 if (pt
) wndpl
.ptMinPosition
= *pt
;
490 wndpl
.rcNormalPosition
= (rect
!= NULL
) ? *rect
: wndPtr
->rectNormal
;
491 wndpl
.ptMaxPosition
= wndPtr
->ptMaxPos
;
492 SetWindowPlacement( hwnd
, &wndpl
);
496 /***********************************************************************
497 * GetWindowPlacement (USER.370)
499 BOOL
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
501 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
502 if (!wndPtr
) return FALSE
;
504 wndpl
->length
= sizeof(*wndpl
);
506 wndpl
->showCmd
= IsZoomed(hwnd
) ? SW_SHOWMAXIMIZED
:
507 (IsIconic(hwnd
) ? SW_SHOWMINIMIZED
: SW_SHOWNORMAL
);
508 wndpl
->ptMinPosition
= wndPtr
->ptIconPos
;
509 wndpl
->ptMaxPosition
= wndPtr
->ptMaxPos
;
510 wndpl
->rcNormalPosition
= wndPtr
->rectNormal
;
515 /***********************************************************************
516 * SetWindowPlacement (USER.371)
518 BOOL
SetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
520 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
521 if (!wndPtr
) return FALSE
;
523 if (wndpl
->flags
& WPF_SETMINPOSITION
)
524 wndPtr
->ptIconPos
= wndpl
->ptMinPosition
;
525 if ((wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) &&
526 (wndpl
->showCmd
== SW_SHOWMINIMIZED
)) wndPtr
->flags
|= WIN_RESTORE_MAX
;
527 wndPtr
->ptMaxPos
= wndpl
->ptMaxPosition
;
528 wndPtr
->rectNormal
= wndpl
->rcNormalPosition
;
529 ShowWindow( hwnd
, wndpl
->showCmd
);
534 /*******************************************************************
535 * WINPOS_ChangeActiveWindow
537 * Change the active window and send the corresponding messages.
539 HWND
WINPOS_ChangeActiveWindow( HWND hwnd
, BOOL mouseMsg
)
541 HWND prevActive
= hwndActive
;
542 if (hwnd
== hwndActive
) return 0;
545 if (!SendMessage( hwndActive
, WM_NCACTIVATE
, FALSE
, 0 )) return 0;
547 SendMessage( hwndActive
, WM_ACTIVATE
,
548 MAKEWPARAM( WA_INACTIVE
, IsIconic(hwndActive
) ),
551 SendMessage( hwndActive
, WM_ACTIVATE
, WA_INACTIVE
,
552 MAKELONG( IsIconic(hwndActive
), hwnd
) );
554 /* Send WM_ACTIVATEAPP here */
560 WND
*wndPtr
= WIN_FindWndPtr( hwndActive
);
561 wndPtr
->hwndPrevActive
= prevActive
;
563 /* Send WM_ACTIVATEAPP here */
564 SendMessage( hwnd
, WM_NCACTIVATE
, TRUE
, 0 );
566 SendMessage( hwnd
, WM_ACTIVATE
,
567 MAKEWPARAM( mouseMsg
? WA_CLICKACTIVE
: WA_ACTIVE
,
569 , (LPARAM
)prevActive
);
571 SendMessage( hwnd
, WM_ACTIVATE
, mouseMsg
? WA_CLICKACTIVE
: WA_ACTIVE
,
572 MAKELONG( IsIconic(hwnd
), prevActive
) );
579 /***********************************************************************
580 * WINPOS_SendNCCalcSize
582 * Send a WM_NCCALCSIZE message to a window.
583 * All parameters are read-only except newClientRect.
584 * oldWindowRect, oldClientRect and winpos must be non-NULL only
585 * when calcValidRect is TRUE.
587 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
, RECT
*newWindowRect
,
588 RECT
*oldWindowRect
, RECT
*oldClientRect
,
589 WINDOWPOS
*winpos
, RECT
*newClientRect
)
591 NCCALCSIZE_PARAMS params
;
594 params
.rgrc
[0] = *newWindowRect
;
597 params
.rgrc
[1] = *oldWindowRect
;
598 params
.rgrc
[2] = *oldClientRect
;
599 params
.lppos
= winpos
;
601 result
= SendMessage( hwnd
, WM_NCCALCSIZE
, calcValidRect
,
602 MAKE_SEGPTR( ¶ms
) );
603 *newClientRect
= params
.rgrc
[0];
608 /***********************************************************************
609 * WINPOS_HandleWindowPosChanging
611 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
613 LONG
WINPOS_HandleWindowPosChanging( WINDOWPOS
*winpos
)
616 WND
*wndPtr
= WIN_FindWndPtr( winpos
->hwnd
);
617 if (!wndPtr
|| (winpos
->flags
& SWP_NOSIZE
)) return 0;
618 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
619 (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
) == 0))
621 NC_GetMinMaxInfo( winpos
->hwnd
, &maxSize
, NULL
, NULL
, NULL
);
622 winpos
->cx
= MIN( winpos
->cx
, maxSize
.x
);
623 winpos
->cy
= MIN( winpos
->cy
, maxSize
.y
);
629 /***********************************************************************
630 * WINPOS_MoveWindowZOrder
632 * Move a window in Z order, invalidating everything that needs it.
633 * Only necessary for windows without associated X window.
635 static void WINPOS_MoveWindowZOrder( HWND hwnd
, HWND hwndAfter
)
639 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
641 /* We have two possible cases:
642 * - The window is moving up: we have to invalidate all areas
643 * of the window that were covered by other windows
644 * - The window is moving down: we have to invalidate areas
645 * of other windows covered by this one.
648 if (hwndAfter
== HWND_TOP
)
652 else if (hwndAfter
== HWND_BOTTOM
)
654 if (!wndPtr
->hwndNext
) return; /* Already at the bottom */
659 if (wndPtr
->hwndNext
== hwndAfter
) return; /* Already placed right */
661 /* Determine which window we encounter first in Z-order */
662 hwndCur
= GetWindow( wndPtr
->hwndParent
, GW_CHILD
);
663 while ((hwndCur
!= hwnd
) && (hwndCur
!= hwndAfter
))
664 hwndCur
= GetWindow( hwndCur
, GW_HWNDNEXT
);
665 movingUp
= (hwndCur
== hwndAfter
);
670 HWND hwndPrevAfter
= wndPtr
->hwndNext
;
671 WIN_UnlinkWindow( hwnd
);
672 WIN_LinkWindow( hwnd
, hwndAfter
);
673 hwndCur
= wndPtr
->hwndNext
;
674 while (hwndCur
!= hwndPrevAfter
)
676 WND
*curPtr
= WIN_FindWndPtr( hwndCur
);
677 RECT rect
= curPtr
->rectWindow
;
678 OffsetRect( &rect
, -wndPtr
->rectClient
.left
,
679 -wndPtr
->rectClient
.top
);
680 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
|
681 RDW_FRAME
| RDW_ERASE
);
682 hwndCur
= curPtr
->hwndNext
;
685 else /* Moving down */
687 hwndCur
= wndPtr
->hwndNext
;
688 WIN_UnlinkWindow( hwnd
);
689 WIN_LinkWindow( hwnd
, hwndAfter
);
690 while (hwndCur
!= hwnd
)
692 WND
*curPtr
= WIN_FindWndPtr( hwndCur
);
693 RECT rect
= wndPtr
->rectWindow
;
694 OffsetRect( &rect
, -curPtr
->rectClient
.left
,
695 -curPtr
->rectClient
.top
);
696 RedrawWindow( hwndCur
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
|
697 RDW_FRAME
| RDW_ERASE
);
698 hwndCur
= curPtr
->hwndNext
;
704 /***********************************************************************
705 * WINPOS_SetXWindowPos
707 * SetWindowPos() for an X window. Used by the real SetWindowPos().
709 static void WINPOS_SetXWindowPos( WINDOWPOS
*winpos
)
711 XWindowChanges winChanges
;
713 WND
*wndPtr
= WIN_FindWndPtr( winpos
->hwnd
);
715 if (!(winpos
->flags
& SWP_NOSIZE
))
717 winChanges
.width
= winpos
->cx
;
718 winChanges
.height
= winpos
->cy
;
719 changeMask
|= CWWidth
| CWHeight
;
721 if (!(winpos
->flags
& SWP_NOMOVE
))
723 winChanges
.x
= winpos
->x
;
724 winChanges
.y
= winpos
->y
;
725 changeMask
|= CWX
| CWY
;
727 if (!(winpos
->flags
& SWP_NOZORDER
))
729 if (winpos
->hwndInsertAfter
== HWND_TOP
) winChanges
.stack_mode
= Above
;
730 else winChanges
.stack_mode
= Below
;
731 if ((winpos
->hwndInsertAfter
!= HWND_TOP
) &&
732 (winpos
->hwndInsertAfter
!= HWND_BOTTOM
))
734 WND
* insertPtr
= WIN_FindWndPtr( winpos
->hwndInsertAfter
);
735 winChanges
.sibling
= insertPtr
->window
;
736 changeMask
|= CWSibling
;
738 changeMask
|= CWStackMode
;
741 XConfigureWindow( display
, wndPtr
->window
, changeMask
, &winChanges
);
745 /***********************************************************************
746 * SetWindowPos (USER.232)
748 BOOL
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
, INT x
, INT y
,
749 INT cx
, INT cy
, WORD flags
)
753 RECT newWindowRect
, newClientRect
;
756 /* Check window handle */
758 if (hwnd
== GetDesktopWindow()) return FALSE
;
759 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
761 /* Check dimensions */
768 if (hwnd
== hwndActive
) flags
|= SWP_NOACTIVATE
; /* Already active */
769 if ((wndPtr
->rectWindow
.right
- wndPtr
->rectWindow
.left
== cx
) &&
770 (wndPtr
->rectWindow
.bottom
- wndPtr
->rectWindow
.top
== cy
))
771 flags
|= SWP_NOSIZE
; /* Already the right size */
772 if ((wndPtr
->rectWindow
.left
== x
) && (wndPtr
->rectWindow
.top
== y
))
773 flags
|= SWP_NOMOVE
; /* Already the right position */
775 /* Check hwndInsertAfter */
777 if (!(flags
& (SWP_NOZORDER
| SWP_NOACTIVATE
)))
779 /* Ignore TOPMOST flags when activating a window */
780 /* _and_ moving it in Z order. */
781 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
782 (hwndInsertAfter
== HWND_NOTOPMOST
))
783 hwndInsertAfter
= HWND_TOP
;
785 /* TOPMOST not supported yet */
786 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
787 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
788 /* hwndInsertAfter must be a sibling of the window */
789 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
) &&
790 (wndPtr
->hwndParent
!= WIN_FindWndPtr(hwndInsertAfter
)->hwndParent
))
793 /* Fill the WINDOWPOS structure */
796 winpos
.hwndInsertAfter
= hwndInsertAfter
;
801 winpos
.flags
= flags
;
803 /* Send WM_WINDOWPOSCHANGING message */
805 if (!(flags
& SWP_NOSENDCHANGING
))
806 SendMessage( hwnd
, WM_WINDOWPOSCHANGING
, 0, MAKE_SEGPTR(&winpos
) );
808 /* Calculate new position and size */
810 newWindowRect
= wndPtr
->rectWindow
;
811 newClientRect
= wndPtr
->rectClient
;
813 if (!(winpos
.flags
& SWP_NOSIZE
))
815 newWindowRect
.right
= newWindowRect
.left
+ winpos
.cx
;
816 newWindowRect
.bottom
= newWindowRect
.top
+ winpos
.cy
;
818 if (!(winpos
.flags
& SWP_NOMOVE
))
820 newWindowRect
.left
= winpos
.x
;
821 newWindowRect
.top
= winpos
.y
;
822 newWindowRect
.right
+= winpos
.x
- wndPtr
->rectWindow
.left
;
823 newWindowRect
.bottom
+= winpos
.y
- wndPtr
->rectWindow
.top
;
826 /* Reposition window in Z order */
828 if (!(winpos
.flags
& SWP_NOZORDER
))
832 WIN_UnlinkWindow( winpos
.hwnd
);
833 WIN_LinkWindow( winpos
.hwnd
, hwndInsertAfter
);
835 else WINPOS_MoveWindowZOrder( winpos
.hwnd
, hwndInsertAfter
);
838 /* Send WM_NCCALCSIZE message to get new client area */
840 result
= WINPOS_SendNCCalcSize( winpos
.hwnd
, TRUE
, &newWindowRect
,
841 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
842 &winpos
, &newClientRect
);
843 /* .... Should handle result here */
845 /* Perform the moving and resizing */
849 WINPOS_SetXWindowPos( &winpos
);
850 wndPtr
->rectWindow
= newWindowRect
;
851 wndPtr
->rectClient
= newClientRect
;
855 RECT oldWindowRect
= wndPtr
->rectWindow
;
857 wndPtr
->rectWindow
= newWindowRect
;
858 wndPtr
->rectClient
= newClientRect
;
860 if (!(flags
& SWP_NOREDRAW
) &&
861 (!(flags
& SWP_NOSIZE
) || !(flags
& SWP_NOMOVE
) ||
862 !(flags
& SWP_NOZORDER
)))
864 HRGN hrgn1
= CreateRectRgnIndirect( &oldWindowRect
);
865 HRGN hrgn2
= CreateRectRgnIndirect( &wndPtr
->rectWindow
);
866 HRGN hrgn3
= CreateRectRgn( 0, 0, 0, 0 );
867 CombineRgn( hrgn3
, hrgn1
, hrgn2
, RGN_DIFF
);
868 RedrawWindow( wndPtr
->hwndParent
, NULL
, hrgn3
,
869 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
);
870 if ((oldWindowRect
.left
!= wndPtr
->rectWindow
.left
) ||
871 (oldWindowRect
.top
!= wndPtr
->rectWindow
.top
))
873 RedrawWindow( winpos
.hwnd
, NULL
, 0, RDW_INVALIDATE
|
874 RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
);
876 DeleteObject( hrgn1
);
877 DeleteObject( hrgn2
);
878 DeleteObject( hrgn3
);
882 if (flags
& SWP_SHOWWINDOW
)
884 wndPtr
->dwStyle
|= WS_VISIBLE
;
887 XMapWindow( display
, wndPtr
->window
);
891 if (!(flags
& SWP_NOREDRAW
))
892 RedrawWindow( winpos
.hwnd
, NULL
, 0,
893 RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
896 else if (flags
& SWP_HIDEWINDOW
)
898 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
901 XUnmapWindow( display
, wndPtr
->window
);
905 if (!(flags
& SWP_NOREDRAW
))
906 RedrawWindow( wndPtr
->hwndParent
, &wndPtr
->rectWindow
, 0,
907 RDW_INVALIDATE
| RDW_FRAME
|
908 RDW_ALLCHILDREN
| RDW_ERASE
);
910 if ((winpos
.hwnd
== GetFocus()) || IsChild(winpos
.hwnd
, GetFocus()))
911 SetFocus( GetParent(winpos
.hwnd
) ); /* Revert focus to parent */
912 if (winpos
.hwnd
== hwndActive
)
914 /* Activate previously active window if possible */
915 HWND newActive
= wndPtr
->hwndPrevActive
;
916 if (!IsWindow(newActive
) || (newActive
== winpos
.hwnd
))
918 newActive
= GetTopWindow(GetDesktopWindow());
919 if (newActive
== winpos
.hwnd
) newActive
= wndPtr
->hwndNext
;
921 WINPOS_ChangeActiveWindow( newActive
, FALSE
);
925 /* Activate the window */
927 if (!(flags
& SWP_NOACTIVATE
))
929 if (!(wndPtr
->dwStyle
& WS_CHILD
))
930 WINPOS_ChangeActiveWindow( winpos
.hwnd
, FALSE
);
933 /* Repaint the window */
935 if (wndPtr
->window
) MSG_Synchronize(); /* Wait for all expose events */
936 EVENT_DummyMotionNotify(); /* Simulate a mouse event to set the cursor */
937 if ((flags
& SWP_FRAMECHANGED
) && !(flags
& SWP_NOREDRAW
))
938 RedrawWindow( winpos
.hwnd
, NULL
, 0,
939 RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
940 if (!(flags
& SWP_DEFERERASE
))
941 RedrawWindow( wndPtr
->hwndParent
, NULL
, 0,
942 RDW_ALLCHILDREN
| RDW_ERASENOW
);
944 /* And last, send the WM_WINDOWPOSCHANGED message */
946 winpos
.flags
|= SWP_NOMOVE
; /* prevent looping.. window is already moved ??? (FIXME)*/
948 if (!(winpos
.flags
& SWP_NOSENDCHANGING
))
949 SendMessage( winpos
.hwnd
, WM_WINDOWPOSCHANGED
,
950 0, MAKE_SEGPTR(&winpos
) );
956 /***********************************************************************
957 * BeginDeferWindowPos (USER.259)
959 HDWP
BeginDeferWindowPos( INT count
)
964 if (count
<= 0) return 0;
965 handle
= USER_HEAP_ALLOC( sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
966 if (!handle
) return 0;
967 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( handle
);
968 pDWP
->actualCount
= 0;
969 pDWP
->suggestedCount
= count
;
971 pDWP
->wMagic
= DWP_MAGIC
;
972 pDWP
->hwndParent
= 0;
977 /***********************************************************************
978 * DeferWindowPos (USER.260)
980 HDWP
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
, INT x
, INT y
,
981 INT cx
, INT cy
, WORD flags
)
988 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
991 /* All the windows of a DeferWindowPos() must have the same parent */
993 parent
= WIN_FindWndPtr( hwnd
)->hwndParent
;
994 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= parent
;
995 else if (parent
!= pDWP
->hwndParent
)
997 USER_HEAP_FREE( hdwp
);
1001 for (i
= 0; i
< pDWP
->actualCount
; i
++)
1003 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
1005 /* Merge with the other changes */
1006 if (!(flags
& SWP_NOZORDER
))
1008 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
1010 if (!(flags
& SWP_NOMOVE
))
1012 pDWP
->winPos
[i
].x
= x
;
1013 pDWP
->winPos
[i
].y
= y
;
1015 if (!(flags
& SWP_NOSIZE
))
1017 pDWP
->winPos
[i
].cx
= cx
;
1018 pDWP
->winPos
[i
].cy
= cy
;
1020 pDWP
->winPos
[i
].flags
&= flags
& (SWP_NOSIZE
| SWP_NOMOVE
|
1021 SWP_NOZORDER
| SWP_NOREDRAW
|
1022 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
1024 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
1029 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
1031 newhdwp
= USER_HEAP_REALLOC( hdwp
,
1032 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
) );
1033 if (!newhdwp
) return 0;
1034 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( newhdwp
);
1035 pDWP
->suggestedCount
++;
1037 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
1038 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
1039 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
1040 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
1041 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
1042 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
1043 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
1044 pDWP
->actualCount
++;
1049 /***********************************************************************
1050 * EndDeferWindowPos (USER.261)
1052 BOOL
EndDeferWindowPos( HDWP hdwp
)
1059 pDWP
= (DWP
*) USER_HEAP_LIN_ADDR( hdwp
);
1060 if (!pDWP
) return FALSE
;
1061 for (i
= 0, winpos
= pDWP
->winPos
; i
< pDWP
->actualCount
; i
++, winpos
++)
1063 if (!(res
= SetWindowPos( winpos
->hwnd
, winpos
->hwndInsertAfter
,
1064 winpos
->x
, winpos
->y
, winpos
->cx
, winpos
->cy
,
1065 winpos
->flags
))) break;
1067 USER_HEAP_FREE( hdwp
);
1072 /***********************************************************************
1073 * TileChildWindows (USER.199)
1075 void TileChildWindows( HWND parent
, WORD action
)
1077 printf("STUB TileChildWindows("NPFMT
", %d)\n", parent
, action
);
1080 /***********************************************************************
1081 * CascageChildWindows (USER.198)
1083 void CascadeChildWindows( HWND parent
, WORD action
)
1085 printf("STUB CascadeChildWindows("NPFMT
", %d)\n", parent
, action
);