2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
7 #include "sysmetrics.h"
12 #include "nonclient.h"
14 /* #define DEBUG_WIN */
17 static HWND hwndActive
= 0; /* Currently active window */
20 /***********************************************************************
23 * Find a suitable place for an iconic window.
24 * The new position is stored into wndPtr->ptIconPos.
26 static void WINPOS_FindIconPos( HWND hwnd
)
29 short x
, y
, xspacing
, yspacing
;
30 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
33 GetClientRect( wndPtr
->hwndParent
, &rectParent
);
34 if ((wndPtr
->ptIconPos
.x
>= rectParent
.left
) &&
35 (wndPtr
->ptIconPos
.x
+ SYSMETRICS_CXICON
< rectParent
.right
) &&
36 (wndPtr
->ptIconPos
.y
>= rectParent
.top
) &&
37 (wndPtr
->ptIconPos
.y
+ SYSMETRICS_CYICON
< rectParent
.bottom
))
38 return; /* The icon already has a suitable position */
40 xspacing
= yspacing
= 70; /* FIXME: This should come from WIN.INI */
41 y
= rectParent
.bottom
;
44 for (x
= rectParent
.left
; x
<=rectParent
.right
-xspacing
; x
+= xspacing
)
46 /* Check if another icon already occupies this spot */
47 HWND hwndChild
= GetWindow( wndPtr
->hwndParent
, GW_CHILD
);
50 WND
*childPtr
= WIN_FindWndPtr( hwndChild
);
51 if ((childPtr
->dwStyle
& WS_MINIMIZE
) && (hwndChild
!= hwnd
))
53 if ((childPtr
->rectWindow
.left
< x
+ xspacing
) &&
54 (childPtr
->rectWindow
.right
>= x
) &&
55 (childPtr
->rectWindow
.top
<= y
) &&
56 (childPtr
->rectWindow
.bottom
> y
- yspacing
))
57 break; /* There's a window in there */
60 hwndChild
= childPtr
->hwndNext
;
64 /* No window was found, so it's OK for us */
65 wndPtr
->ptIconPos
.x
= x
+ (xspacing
- SYSMETRICS_CXICON
) / 2;
66 wndPtr
->ptIconPos
.y
= y
- (yspacing
+ SYSMETRICS_CYICON
) / 2;
75 /***********************************************************************
76 * ArrangeIconicWindows (USER.170)
78 WORD
ArrangeIconicWindows( HWND parent
)
82 short x
, y
, xspacing
, yspacing
;
84 GetClientRect( parent
, &rectParent
);
86 y
= rectParent
.bottom
;
87 xspacing
= yspacing
= 70; /* FIXME: This should come from WIN.INI */
88 hwndChild
= GetWindow( parent
, GW_CHILD
);
91 if (IsIconic( hwndChild
))
93 SetWindowPos( hwndChild
, 0, x
+ (xspacing
- SYSMETRICS_CXICON
) / 2,
94 y
- (yspacing
+ SYSMETRICS_CYICON
) / 2, 0, 0,
95 SWP_NOSIZE
| SWP_NOZORDER
| SWP_NOACTIVATE
);
96 if (x
<= rectParent
.right
- xspacing
) x
+= xspacing
;
103 hwndChild
= GetWindow( hwndChild
, GW_HWNDNEXT
);
109 /***********************************************************************
110 * GetWindowRect (USER.32)
112 void GetWindowRect( HWND hwnd
, LPRECT rect
)
114 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
117 *rect
= wndPtr
->rectWindow
;
118 if (wndPtr
->dwStyle
& WS_CHILD
)
119 MapWindowPoints( wndPtr
->hwndParent
, 0, (POINT
*)rect
, 2 );
123 /***********************************************************************
124 * GetClientRect (USER.33)
126 void GetClientRect( HWND hwnd
, LPRECT rect
)
128 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
130 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
133 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
134 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
139 /*******************************************************************
140 * ClientToScreen (USER.28)
142 void ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
144 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
148 /*******************************************************************
149 * ScreenToClient (USER.29)
151 void ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
153 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
157 /*******************************************************************
158 * WindowFromPoint (USER.30)
160 HWND
WindowFromPoint( POINT pt
)
163 HWND hwnd
= GetDesktopWindow();
167 /* If point is in window, and window is visible, */
168 /* not disabled and not transparent, then explore */
169 /* its children. Otherwise, go to the next window. */
171 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
172 if ((pt
.x
>= wndPtr
->rectWindow
.left
) &&
173 (pt
.x
< wndPtr
->rectWindow
.right
) &&
174 (pt
.y
>= wndPtr
->rectWindow
.top
) &&
175 (pt
.y
< wndPtr
->rectWindow
.bottom
) &&
176 !(wndPtr
->dwStyle
& WS_DISABLED
) &&
177 (wndPtr
->dwStyle
& WS_VISIBLE
) &&
178 !(wndPtr
->dwExStyle
& WS_EX_TRANSPARENT
))
181 /* If window is minimized, ignore its children */
182 if (wndPtr
->dwStyle
& WS_MINIMIZE
) break;
183 pt
.x
-= wndPtr
->rectClient
.left
;
184 pt
.y
-= wndPtr
->rectClient
.top
;
185 hwnd
= wndPtr
->hwndChild
;
187 else hwnd
= wndPtr
->hwndNext
;
193 /*******************************************************************
194 * ChildWindowFromPoint (USER.191)
196 HWND
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
201 GetWindowRect( hwndParent
, &rect
);
202 if (!PtInRect( &rect
, pt
)) return 0;
203 hwnd
= GetTopWindow( hwndParent
);
206 GetWindowRect( hwnd
, &rect
);
207 if (PtInRect( &rect
, pt
)) return hwnd
;
208 hwnd
= GetWindow( hwnd
, GW_HWNDNEXT
);
214 /*******************************************************************
215 * MapWindowPoints (USER.258)
217 void MapWindowPoints( HWND hwndFrom
, HWND hwndTo
, LPPOINT lppt
, WORD count
)
221 POINT origin
= { 0, 0 };
224 /* Translate source window origin to screen coords */
227 wndPtr
= WIN_FindWndPtr( hwndFrom
);
228 origin
.x
+= wndPtr
->rectClient
.left
;
229 origin
.y
+= wndPtr
->rectClient
.top
;
230 hwndFrom
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->hwndParent
: 0;
233 /* Translate origin to destination window coords */
236 wndPtr
= WIN_FindWndPtr( hwndTo
);
237 origin
.x
-= wndPtr
->rectClient
.left
;
238 origin
.y
-= wndPtr
->rectClient
.top
;
239 hwndTo
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->hwndParent
: 0;
242 /* Translate points */
243 for (i
= 0, curpt
= lppt
; i
< count
; i
++, curpt
++)
245 curpt
->x
+= origin
.x
;
246 curpt
->y
+= origin
.y
;
251 /***********************************************************************
254 BOOL
IsIconic(HWND hWnd
)
256 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
257 if (wndPtr
== NULL
) return FALSE
;
258 return (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
262 /***********************************************************************
263 * IsZoomed (USER.272)
265 BOOL
IsZoomed(HWND hWnd
)
267 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
268 if (wndPtr
== NULL
) return FALSE
;
269 return (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
273 /*******************************************************************
274 * GetActiveWindow (USER.60)
276 HWND
GetActiveWindow()
282 /*******************************************************************
283 * SetActiveWindow (USER.59)
285 HWND
SetActiveWindow( HWND hwnd
)
287 HWND prev
= hwndActive
;
288 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
289 if (!wndPtr
|| (wndPtr
->dwStyle
& WS_CHILD
)) return 0;
290 SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
295 /***********************************************************************
296 * BringWindowToTop (USER.45)
298 BOOL
BringWindowToTop( HWND hwnd
)
300 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
304 /***********************************************************************
305 * MoveWindow (USER.56)
307 BOOL
MoveWindow( HWND hwnd
, short x
, short y
, short cx
, short cy
, BOOL repaint
)
309 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
310 if (!repaint
) flags
|= SWP_NOREDRAW
;
311 dprintf_win(stddeb
, "MoveWindow: %d %d,%d %dx%d %d\n",
312 hwnd
, x
, y
, cx
, cy
, repaint
);
313 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
317 /***********************************************************************
318 * ShowWindow (USER.42)
320 BOOL
ShowWindow( HWND hwnd
, int cmd
)
322 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
326 short x
= 0, y
= 0, cx
= 0, cy
= 0;
328 if (!wndPtr
) return FALSE
;
330 dprintf_win(stddeb
,"ShowWindow: hwnd=%04X, cmd=%d\n", hwnd
, cmd
);
332 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
337 swpflags
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
338 SWP_NOACTIVATE
| SWP_NOZORDER
;
341 case SW_SHOWMINNOACTIVE
:
342 swpflags
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
344 case SW_SHOWMINIMIZED
:
345 swpflags
|= SWP_SHOWWINDOW
;
348 swpflags
|= SWP_FRAMECHANGED
;
349 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
351 if (wndPtr
->dwStyle
& WS_MAXIMIZE
)
353 wndPtr
->flags
|= WIN_RESTORE_MAX
;
354 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
358 wndPtr
->flags
&= ~WIN_RESTORE_MAX
;
359 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
361 wndPtr
->dwStyle
|= WS_MINIMIZE
;
362 WINPOS_FindIconPos( hwnd
);
363 x
= wndPtr
->ptIconPos
.x
;
364 y
= wndPtr
->ptIconPos
.y
;
365 cx
= SYSMETRICS_CXICON
;
366 cy
= SYSMETRICS_CYICON
;
368 else swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
371 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE: */
372 swpflags
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
373 if (!(wndPtr
->dwStyle
& WS_MAXIMIZE
))
375 /* Store the current position and find the maximized size */
376 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
))
377 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
378 NC_GetMinMaxInfo( hwnd
, &maxSize
,
379 &wndPtr
->ptMaxPos
, NULL
, NULL
);
380 x
= wndPtr
->ptMaxPos
.x
;
381 y
= wndPtr
->ptMaxPos
.y
;
384 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
385 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
387 else swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
391 swpflags
|= SWP_NOACTIVATE
| SWP_NOZORDER
;
394 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
397 case SW_SHOWNOACTIVATE
:
398 swpflags
|= SWP_NOZORDER
;
399 if (GetActiveWindow()) swpflags
|= SWP_NOACTIVATE
;
401 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
403 swpflags
|= SWP_SHOWWINDOW
| SWP_FRAMECHANGED
;
404 if (wndPtr
->dwStyle
& WS_MINIMIZE
)
406 wndPtr
->ptIconPos
.x
= wndPtr
->rectWindow
.left
;
407 wndPtr
->ptIconPos
.y
= wndPtr
->rectWindow
.top
;
408 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
409 if (wndPtr
->flags
& WIN_RESTORE_MAX
)
411 /* Restore to maximized position */
412 NC_GetMinMaxInfo( hwnd
, &maxSize
, &wndPtr
->ptMaxPos
,
414 x
= wndPtr
->ptMaxPos
.x
;
415 y
= wndPtr
->ptMaxPos
.y
;
418 wndPtr
->dwStyle
|= WS_MAXIMIZE
;
420 else /* Restore to normal position */
422 x
= wndPtr
->rectNormal
.left
;
423 y
= wndPtr
->rectNormal
.top
;
424 cx
= wndPtr
->rectNormal
.right
- wndPtr
->rectNormal
.left
;
425 cy
= wndPtr
->rectNormal
.bottom
- wndPtr
->rectNormal
.top
;
428 else if (wndPtr
->dwStyle
& WS_MAXIMIZE
)
430 wndPtr
->ptMaxPos
.x
= wndPtr
->rectWindow
.left
;
431 wndPtr
->ptMaxPos
.y
= wndPtr
->rectWindow
.top
;
432 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
433 x
= wndPtr
->rectNormal
.left
;
434 y
= wndPtr
->rectNormal
.top
;
435 cx
= wndPtr
->rectNormal
.right
- wndPtr
->rectNormal
.left
;
436 cy
= wndPtr
->rectNormal
.bottom
- wndPtr
->rectNormal
.top
;
438 else swpflags
|= SWP_NOSIZE
| SWP_NOMOVE
;
442 SendMessage( hwnd
, WM_SHOWWINDOW
, (cmd
!= SW_HIDE
), 0 );
443 SetWindowPos( hwnd
, HWND_TOP
, x
, y
, cx
, cy
, swpflags
);
445 /* Send WM_SIZE and WM_MOVE messages if not already done */
446 if (!(wndPtr
->flags
& WIN_GOT_SIZEMSG
))
448 int wParam
= SIZE_RESTORED
;
449 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
450 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
451 wndPtr
->flags
|= WIN_GOT_SIZEMSG
;
452 SendMessage( hwnd
, WM_SIZE
, wParam
,
453 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
454 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
455 SendMessage( hwnd
, WM_MOVE
, 0,
456 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
463 /***********************************************************************
464 * GetInternalWindowPos (USER.460)
466 WORD
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
, LPPOINT ptIcon
)
468 WINDOWPLACEMENT wndpl
;
469 if (!GetWindowPlacement( hwnd
, &wndpl
)) return 0;
470 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
471 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
472 return wndpl
.showCmd
;
476 /***********************************************************************
477 * SetInternalWindowPos (USER.461)
479 void SetInternalWindowPos( HWND hwnd
, WORD showCmd
, LPRECT rect
, LPPOINT pt
)
481 WINDOWPLACEMENT wndpl
;
482 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
484 wndpl
.length
= sizeof(wndpl
);
485 wndpl
.flags
= (pt
!= NULL
) ? WPF_SETMINPOSITION
: 0;
486 wndpl
.showCmd
= showCmd
;
487 if (pt
) wndpl
.ptMinPosition
= *pt
;
488 wndpl
.rcNormalPosition
= (rect
!= NULL
) ? *rect
: wndPtr
->rectNormal
;
489 wndpl
.ptMaxPosition
= wndPtr
->ptMaxPos
;
490 SetWindowPlacement( hwnd
, &wndpl
);
494 /***********************************************************************
495 * GetWindowPlacement (USER.370)
497 BOOL
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
499 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
500 if (!wndPtr
) return FALSE
;
502 wndpl
->length
= sizeof(*wndpl
);
504 wndpl
->showCmd
= IsZoomed(hwnd
) ? SW_SHOWMAXIMIZED
:
505 (IsIconic(hwnd
) ? SW_SHOWMINIMIZED
: SW_SHOWNORMAL
);
506 wndpl
->ptMinPosition
= wndPtr
->ptIconPos
;
507 wndpl
->ptMaxPosition
= wndPtr
->ptMaxPos
;
508 wndpl
->rcNormalPosition
= wndPtr
->rectNormal
;
513 /***********************************************************************
514 * SetWindowPlacement (USER.371)
516 BOOL
SetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
518 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
519 if (!wndPtr
) return FALSE
;
521 if (wndpl
->flags
& WPF_SETMINPOSITION
)
522 wndPtr
->ptIconPos
= wndpl
->ptMinPosition
;
523 if ((wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) &&
524 (wndpl
->showCmd
== SW_SHOWMINIMIZED
)) wndPtr
->flags
|= WIN_RESTORE_MAX
;
525 wndPtr
->ptMaxPos
= wndpl
->ptMaxPosition
;
526 wndPtr
->rectNormal
= wndpl
->rcNormalPosition
;
527 ShowWindow( hwnd
, wndpl
->showCmd
);
532 /*******************************************************************
533 * WINPOS_NextWindowFromPoint
535 * Looks for next enabled window that is
536 * a) sibling of hwnd, later in Z-order and encloses pt, or
539 HWND
WINPOS_NextWindowFromPoint( HWND hwnd
, POINT pt
)
541 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
543 if (!wndPtr
->hwndParent
) return hwnd
; /* desktop window */
544 ScreenToClient( wndPtr
->hwndParent
, &pt
); /* make pt relative to parent */
547 if (!wndPtr
->hwndNext
) break; /* No more children */
548 hwnd
= wndPtr
->hwndNext
;
549 wndPtr
= WIN_FindWndPtr( hwnd
);
550 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
551 !(wndPtr
->dwStyle
& WS_DISABLED
) &&
552 PtInRect( &wndPtr
->rectWindow
, pt
)) return hwnd
;
554 return wndPtr
->hwndParent
;
558 /*******************************************************************
559 * WINPOS_ChangeActiveWindow
561 * Change the active window and send the corresponding messages.
563 HWND
WINPOS_ChangeActiveWindow( HWND hwnd
, BOOL mouseMsg
)
565 HWND prevActive
= hwndActive
;
566 if (hwnd
== hwndActive
) return 0;
569 if (!SendMessage( hwndActive
, WM_NCACTIVATE
, FALSE
, 0 )) return 0;
570 SendMessage( hwndActive
, WM_ACTIVATE
, WA_INACTIVE
,
571 MAKELONG( IsIconic(hwndActive
), hwnd
) );
572 /* Send WM_ACTIVATEAPP here */
578 WND
*wndPtr
= WIN_FindWndPtr( hwndActive
);
579 wndPtr
->hwndPrevActive
= prevActive
;
581 /* Send WM_ACTIVATEAPP here */
582 SendMessage( hwnd
, WM_NCACTIVATE
, TRUE
, 0 );
583 SendMessage( hwnd
, WM_ACTIVATE
, mouseMsg
? WA_CLICKACTIVE
: WA_ACTIVE
,
584 MAKELONG( IsIconic(hwnd
), prevActive
) );
590 /***********************************************************************
591 * WINPOS_SendNCCalcSize
593 * Send a WM_NCCALCSIZE message to a window.
594 * All parameters are read-only except newClientRect.
595 * oldWindowRect, oldClientRect and winpos must be non-NULL only
596 * when calcValidRect is TRUE.
598 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
, RECT
*newWindowRect
,
599 RECT
*oldWindowRect
, RECT
*oldClientRect
,
600 WINDOWPOS
*winpos
, RECT
*newClientRect
)
602 NCCALCSIZE_PARAMS
*params
;
606 if (!(hparams
= USER_HEAP_ALLOC( GMEM_MOVEABLE
, sizeof(*params
) )))
608 params
= (NCCALCSIZE_PARAMS
*) USER_HEAP_ADDR( hparams
);
609 params
->rgrc
[0] = *newWindowRect
;
612 params
->rgrc
[1] = *oldWindowRect
;
613 params
->rgrc
[2] = *oldClientRect
;
614 params
->lppos
= winpos
;
616 result
= SendMessage( hwnd
, WM_NCCALCSIZE
, calcValidRect
, (LONG
)params
);
617 *newClientRect
= params
->rgrc
[0];
618 USER_HEAP_FREE( hparams
);
623 /***********************************************************************
624 * WINPOS_HandleWindowPosChanging
626 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
628 LONG
WINPOS_HandleWindowPosChanging( WINDOWPOS
*winpos
)
631 WND
*wndPtr
= WIN_FindWndPtr( winpos
->hwnd
);
632 if (!wndPtr
|| (winpos
->flags
& SWP_NOSIZE
)) return 0;
633 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
634 (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
) == 0))
636 NC_GetMinMaxInfo( winpos
->hwnd
, &maxSize
, NULL
, NULL
, NULL
);
637 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
638 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
644 /***********************************************************************
645 * WINPOS_MoveWindowZOrder
647 * Move a window in Z order, invalidating everything that needs it.
648 * Only necessary for windows without associated X window.
650 static void WINPOS_MoveWindowZOrder( HWND hwnd
, HWND hwndAfter
)
654 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
656 /* We have two possible cases:
657 * - The window is moving up: we have to invalidate all areas
658 * of the window that were covered by other windows
659 * - The window is moving down: we have to invalidate areas
660 * of other windows covered by this one.
663 if (hwndAfter
== HWND_TOP
)
667 else if (hwndAfter
== HWND_BOTTOM
)
669 if (!wndPtr
->hwndNext
) return; /* Already at the bottom */
674 if (wndPtr
->hwndNext
== hwndAfter
) return; /* Already placed right */
676 /* Determine which window we encounter first in Z-order */
677 hwndCur
= GetWindow( wndPtr
->hwndParent
, GW_CHILD
);
678 while ((hwndCur
!= hwnd
) && (hwndCur
!= hwndAfter
))
679 hwndCur
= GetWindow( hwndCur
, GW_HWNDNEXT
);
680 movingUp
= (hwndCur
== hwndAfter
);
685 HWND hwndPrevAfter
= wndPtr
->hwndNext
;
686 WIN_UnlinkWindow( hwnd
);
687 WIN_LinkWindow( hwnd
, hwndAfter
);
688 hwndCur
= wndPtr
->hwndNext
;
689 while (hwndCur
!= hwndPrevAfter
)
691 WND
*curPtr
= WIN_FindWndPtr( hwndCur
);
692 RECT rect
= curPtr
->rectWindow
;
693 OffsetRect( &rect
, -wndPtr
->rectClient
.left
,
694 -wndPtr
->rectClient
.top
);
695 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
|
696 RDW_FRAME
| RDW_ERASE
);
697 hwndCur
= curPtr
->hwndNext
;
700 else /* Moving down */
702 hwndCur
= wndPtr
->hwndNext
;
703 WIN_UnlinkWindow( hwnd
);
704 WIN_LinkWindow( hwnd
, hwndAfter
);
705 while (hwndCur
!= hwnd
)
707 WND
*curPtr
= WIN_FindWndPtr( hwndCur
);
708 RECT rect
= wndPtr
->rectWindow
;
709 OffsetRect( &rect
, -curPtr
->rectClient
.left
,
710 -curPtr
->rectClient
.top
);
711 RedrawWindow( hwndCur
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
|
712 RDW_FRAME
| RDW_ERASE
);
713 hwndCur
= curPtr
->hwndNext
;
719 /***********************************************************************
720 * WINPOS_SetXWindosPos
722 * SetWindowPos() for an X window. Used by the real SetWindowPos().
724 static void WINPOS_SetXWindowPos( WINDOWPOS
*winpos
)
726 XWindowChanges winChanges
;
728 WND
*wndPtr
= WIN_FindWndPtr( winpos
->hwnd
);
730 if (!(winpos
->flags
& SWP_NOSIZE
))
732 winChanges
.width
= winpos
->cx
;
733 winChanges
.height
= winpos
->cy
;
734 changeMask
|= CWWidth
| CWHeight
;
736 if (!(winpos
->flags
& SWP_NOMOVE
))
738 winChanges
.x
= winpos
->x
;
739 winChanges
.y
= winpos
->y
;
740 changeMask
|= CWX
| CWY
;
742 if (!(winpos
->flags
& SWP_NOZORDER
))
744 if (winpos
->hwndInsertAfter
== HWND_TOP
) winChanges
.stack_mode
= Above
;
745 else winChanges
.stack_mode
= Below
;
746 if ((winpos
->hwndInsertAfter
!= HWND_TOP
) &&
747 (winpos
->hwndInsertAfter
!= HWND_BOTTOM
))
749 WND
* insertPtr
= WIN_FindWndPtr( winpos
->hwndInsertAfter
);
750 winChanges
.sibling
= insertPtr
->window
;
751 changeMask
|= CWSibling
;
753 changeMask
|= CWStackMode
;
756 XConfigureWindow( display
, wndPtr
->window
, changeMask
, &winChanges
);
760 /***********************************************************************
761 * WINPOS_InternalSetWindowPos
763 * Helper function for SetWindowPos.
765 static BOOL
WINPOS_InternalSetWindowPos( WINDOWPOS
*winpos
)
769 RECT newWindowRect
, newClientRect
;
772 /* Send WM_WINDOWPOSCHANGING message */
774 if (!(winpos
->flags
& SWP_NOSENDCHANGING
))
775 SendMessage( winpos
->hwnd
, WM_WINDOWPOSCHANGING
, 0, (LONG
)winpos
);
777 /* Check window handle */
779 if (winpos
->hwnd
== GetDesktopWindow()) return FALSE
;
780 if (!(wndPtr
= WIN_FindWndPtr( winpos
->hwnd
))) return FALSE
;
782 /* Check dimensions */
784 if (winpos
->cx
<= 0) winpos
->cx
= 1;
785 if (winpos
->cy
<= 0) winpos
->cy
= 1;
789 if (winpos
->hwnd
== hwndActive
)
790 winpos
->flags
|= SWP_NOACTIVATE
; /* Already active */
791 if ((wndPtr
->rectWindow
.right
-wndPtr
->rectWindow
.left
== winpos
->cx
) &&
792 (wndPtr
->rectWindow
.bottom
-wndPtr
->rectWindow
.top
== winpos
->cy
))
793 winpos
->flags
|= SWP_NOSIZE
; /* Already the right size */
794 if ((wndPtr
->rectWindow
.left
== winpos
->x
) &&
795 (wndPtr
->rectWindow
.top
== winpos
->y
))
796 winpos
->flags
|= SWP_NOMOVE
; /* Already the right position */
797 flags
= winpos
->flags
;
799 /* Check hwndAfter */
801 hwndAfter
= winpos
->hwndInsertAfter
;
802 if (!(winpos
->flags
& (SWP_NOZORDER
| SWP_NOACTIVATE
)))
804 /* Ignore TOPMOST flags when activating a window */
805 /* _and_ moving it in Z order. */
806 if ((hwndAfter
== HWND_TOPMOST
) || (hwndAfter
== HWND_NOTOPMOST
))
807 hwndAfter
= HWND_TOP
;
809 /* TOPMOST not supported yet */
810 if ((hwndAfter
== HWND_TOPMOST
) || (hwndAfter
== HWND_NOTOPMOST
))
811 hwndAfter
= HWND_TOP
;
812 /* hwndAfter must be a sibling of the window */
813 if ((hwndAfter
!= HWND_TOP
) && (hwndAfter
!= HWND_BOTTOM
) &&
814 (GetParent(winpos
->hwnd
) != GetParent(hwndAfter
))) return FALSE
;
815 winpos
->hwndInsertAfter
= hwndAfter
;
817 /* Calculate new position and size */
819 newWindowRect
= wndPtr
->rectWindow
;
820 newClientRect
= wndPtr
->rectClient
;
822 if (!(winpos
->flags
& SWP_NOSIZE
))
824 newWindowRect
.right
= newWindowRect
.left
+ winpos
->cx
;
825 newWindowRect
.bottom
= newWindowRect
.top
+ winpos
->cy
;
827 if (!(winpos
->flags
& SWP_NOMOVE
))
829 newWindowRect
.left
= winpos
->x
;
830 newWindowRect
.top
= winpos
->y
;
831 newWindowRect
.right
+= winpos
->x
- wndPtr
->rectWindow
.left
;
832 newWindowRect
.bottom
+= winpos
->y
- wndPtr
->rectWindow
.top
;
835 /* Reposition window in Z order */
837 if (!(winpos
->flags
& SWP_NOZORDER
))
841 WIN_UnlinkWindow( winpos
->hwnd
);
842 WIN_LinkWindow( winpos
->hwnd
, hwndAfter
);
844 else WINPOS_MoveWindowZOrder( winpos
->hwnd
, hwndAfter
);
847 /* Send WM_NCCALCSIZE message to get new client area */
849 result
= WINPOS_SendNCCalcSize( winpos
->hwnd
, TRUE
, &newWindowRect
,
850 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
851 winpos
, &newClientRect
);
852 /* .... Should handle result here */
854 /* Perform the moving and resizing */
858 WINPOS_SetXWindowPos( winpos
);
859 wndPtr
->rectWindow
= newWindowRect
;
860 wndPtr
->rectClient
= newClientRect
;
864 RECT oldWindowRect
= wndPtr
->rectWindow
;
866 wndPtr
->rectWindow
= newWindowRect
;
867 wndPtr
->rectClient
= newClientRect
;
869 if (!(flags
& SWP_NOREDRAW
) &&
870 (!(flags
& SWP_NOSIZE
) || !(flags
& SWP_NOMOVE
) ||
871 !(flags
& SWP_NOZORDER
)))
873 HRGN hrgn1
= CreateRectRgnIndirect( &oldWindowRect
);
874 HRGN hrgn2
= CreateRectRgnIndirect( &wndPtr
->rectWindow
);
875 HRGN hrgn3
= CreateRectRgn( 0, 0, 0, 0 );
876 CombineRgn( hrgn3
, hrgn1
, hrgn2
, RGN_DIFF
);
877 RedrawWindow( wndPtr
->hwndParent
, NULL
, hrgn3
,
878 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASE
);
879 if ((oldWindowRect
.left
!= wndPtr
->rectWindow
.left
) ||
880 (oldWindowRect
.top
!= wndPtr
->rectWindow
.top
))
882 RedrawWindow( winpos
->hwnd
, NULL
, 0, RDW_INVALIDATE
|
883 RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASE
);
885 DeleteObject( hrgn1
);
886 DeleteObject( hrgn2
);
887 DeleteObject( hrgn3
);
891 if (flags
& SWP_SHOWWINDOW
)
893 wndPtr
->dwStyle
|= WS_VISIBLE
;
896 XMapWindow( display
, wndPtr
->window
);
900 if (!(flags
& SWP_NOREDRAW
))
901 RedrawWindow( winpos
->hwnd
, NULL
, 0,
902 RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
905 else if (flags
& SWP_HIDEWINDOW
)
907 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
910 XUnmapWindow( display
, wndPtr
->window
);
914 if (!(flags
& SWP_NOREDRAW
))
915 RedrawWindow( wndPtr
->hwndParent
, &wndPtr
->rectWindow
, 0,
916 RDW_INVALIDATE
| RDW_FRAME
|
917 RDW_ALLCHILDREN
| RDW_ERASE
);
919 if ((winpos
->hwnd
== GetFocus()) || IsChild(winpos
->hwnd
, GetFocus()))
920 SetFocus( GetParent(winpos
->hwnd
) ); /* Revert focus to parent */
921 if (winpos
->hwnd
== hwndActive
)
923 /* Activate previously active window if possible */
924 HWND newActive
= wndPtr
->hwndPrevActive
;
925 if (!IsWindow(newActive
) || (newActive
== winpos
->hwnd
))
927 newActive
= GetTopWindow(GetDesktopWindow());
928 if (newActive
== winpos
->hwnd
) newActive
= wndPtr
->hwndNext
;
930 WINPOS_ChangeActiveWindow( newActive
, FALSE
);
934 /* Activate the window */
936 if (!(flags
& SWP_NOACTIVATE
))
938 if (!(wndPtr
->dwStyle
& WS_CHILD
))
939 WINPOS_ChangeActiveWindow( winpos
->hwnd
, FALSE
);
942 /* Repaint the window */
944 if (wndPtr
->window
) MSG_Synchronize(); /* Wait for all expose events */
945 if ((flags
& SWP_FRAMECHANGED
) && !(flags
& SWP_NOREDRAW
))
946 RedrawWindow( winpos
->hwnd
, NULL
, 0,
947 RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASE
);
948 if (!(flags
& SWP_DEFERERASE
))
949 RedrawWindow( wndPtr
->hwndParent
, NULL
, 0,
950 RDW_ALLCHILDREN
| RDW_ERASENOW
);
952 /* And last, send the WM_WINDOWPOSCHANGED message */
954 if (!(winpos
->flags
& SWP_NOSENDCHANGING
))
955 SendMessage( winpos
->hwnd
, WM_WINDOWPOSCHANGED
, 0, (LONG
)winpos
);
960 /***********************************************************************
961 * BeginDeferWindowPos (USER.259)
963 HDWP
BeginDeferWindowPos( INT count
)
968 if (count
<= 0) return 0;
969 handle
= USER_HEAP_ALLOC( GMEM_MOVEABLE
,
970 sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
971 if (!handle
) return 0;
972 pDWP
= (DWP
*) USER_HEAP_ADDR( handle
);
973 pDWP
->actualCount
= 0;
974 pDWP
->suggestedCount
= count
;
976 pDWP
->wMagic
= DWP_MAGIC
;
977 pDWP
->hwndParent
= 0;
982 /***********************************************************************
983 * DeferWindowPos (USER.260)
985 HDWP
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
, INT x
, INT y
,
986 INT cx
, INT cy
, WORD flags
)
992 pDWP
= (DWP
*) USER_HEAP_ADDR( hdwp
);
995 /* All the windows of a DeferWindowPos() must have the same parent */
997 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= GetParent( hwnd
);
998 else if (GetParent( hwnd
) != pDWP
->hwndParent
)
1000 USER_HEAP_FREE( hdwp
);
1004 for (i
= 0; i
< pDWP
->actualCount
; i
++)
1006 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
1008 /* Merge with the other changes */
1009 if (!(flags
& SWP_NOZORDER
))
1011 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
1013 if (!(flags
& SWP_NOMOVE
))
1015 pDWP
->winPos
[i
].x
= x
;
1016 pDWP
->winPos
[i
].y
= y
;
1018 if (!(flags
& SWP_NOSIZE
))
1020 pDWP
->winPos
[i
].cx
= cx
;
1021 pDWP
->winPos
[i
].cy
= cy
;
1023 pDWP
->winPos
[i
].flags
&= flags
& (SWP_NOSIZE
| SWP_NOMOVE
|
1024 SWP_NOZORDER
| SWP_NOREDRAW
|
1025 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
1027 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
1032 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
1034 newhdwp
= USER_HEAP_REALLOC( hdwp
,
1035 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
), 0);
1036 if (!newhdwp
) return 0;
1037 pDWP
= (DWP
*) USER_HEAP_ADDR( newhdwp
);
1038 pDWP
->suggestedCount
++;
1040 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
1041 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
1042 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
1043 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
1044 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
1045 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
1046 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
1047 pDWP
->actualCount
++;
1052 /***********************************************************************
1053 * EndDeferWindowPos (USER.261)
1055 BOOL
EndDeferWindowPos( HDWP hdwp
)
1061 pDWP
= (DWP
*) USER_HEAP_ADDR( hdwp
);
1062 if (!pDWP
) return FALSE
;
1063 for (i
= 0; i
< pDWP
->actualCount
; i
++)
1065 if (!(res
= WINPOS_InternalSetWindowPos( &pDWP
->winPos
[i
] ))) break;
1067 USER_HEAP_FREE( hdwp
);
1072 /***********************************************************************
1073 * SetWindowPos (USER.232)
1075 BOOL
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
, INT x
, INT y
,
1076 INT cx
, INT cy
, WORD flags
)
1080 dprintf_win(stddeb
, "SetWindowPos: %04X %d %d,%d %dx%d 0x%x\n",
1081 hwnd
, hwndInsertAfter
, x
, y
, cx
, cy
, flags
);
1082 if (!(hdwp
= BeginDeferWindowPos( 1 ))) return FALSE
;
1083 if (!(hdwp
= DeferWindowPos( hdwp
, hwnd
, hwndInsertAfter
,
1084 x
, y
, cx
, cy
, flags
))) return FALSE
;
1085 return EndDeferWindowPos( hdwp
);
1088 /***********************************************************************
1089 * TileChildWindows (USER.199)
1091 void TileChildWindows( HWND parent
, WORD action
)
1093 printf("STUB TileChildWindows(%04X, %d)\n", parent
, action
);
1096 /***********************************************************************
1097 * CascageChildWindows (USER.198)
1099 void CascadeChildWindows( HWND parent
, WORD action
)
1101 printf("STUB CascadeChildWindows(%04X, %d)\n", parent
, action
);