2 * Window position related functions.
4 * Copyright 1993 Alexandre Julliard
7 static char Copyright
[] = "Copyright Alexandre Julliard, 1993";
9 #include "sysmetrics.h"
15 /* #define DEBUG_WIN /* */
16 /* #undef DEBUG_WIN /* */
19 static HWND hwndActive
= 0; /* Currently active window */
22 /***********************************************************************
23 * GetWindowRect (USER.32)
25 void GetWindowRect( HWND hwnd
, LPRECT rect
)
27 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
30 *rect
= wndPtr
->rectWindow
;
31 if (wndPtr
->dwStyle
& WS_CHILD
)
32 MapWindowPoints( wndPtr
->hwndParent
, 0, (POINT
*)rect
, 2 );
36 /***********************************************************************
37 * GetClientRect (USER.33)
39 void GetClientRect( HWND hwnd
, LPRECT rect
)
41 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
43 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
46 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
47 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
52 /*******************************************************************
53 * ClientToScreen (USER.28)
55 void ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
57 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
61 /*******************************************************************
62 * ScreenToClient (USER.29)
64 void ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
66 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
70 /*******************************************************************
71 * WindowFromPoint (USER.30)
73 HWND
WindowFromPoint( POINT pt
)
76 HWND hwnd
= GetDesktopWindow();
80 /* If point is in window, and window is visible, */
81 /* not disabled and not transparent, then explore */
82 /* its children. Otherwise, go to the next window. */
84 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
85 if ((pt
.x
>= wndPtr
->rectWindow
.left
) &&
86 (pt
.x
< wndPtr
->rectWindow
.right
) &&
87 (pt
.y
>= wndPtr
->rectWindow
.top
) &&
88 (pt
.y
< wndPtr
->rectWindow
.bottom
) &&
89 !(wndPtr
->dwStyle
& WS_DISABLED
) &&
90 (wndPtr
->dwStyle
& WS_VISIBLE
) &&
91 !(wndPtr
->dwExStyle
& WS_EX_TRANSPARENT
))
93 pt
.x
-= wndPtr
->rectClient
.left
;
94 pt
.y
-= wndPtr
->rectClient
.top
;
96 hwnd
= wndPtr
->hwndChild
;
98 else hwnd
= wndPtr
->hwndNext
;
104 /*******************************************************************
105 * ChildWindowFromPoint (USER.191)
107 HWND
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
112 GetWindowRect( hwndParent
, &rect
);
113 if (!PtInRect( &rect
, pt
)) return 0;
114 hwnd
= GetTopWindow( hwndParent
);
117 GetWindowRect( hwnd
, &rect
);
118 if (PtInRect( &rect
, pt
)) return hwnd
;
119 hwnd
= GetWindow( hwnd
, GW_HWNDNEXT
);
125 /*******************************************************************
126 * MapWindowPoints (USER.258)
128 void MapWindowPoints( HWND hwndFrom
, HWND hwndTo
, LPPOINT lppt
, WORD count
)
132 POINT origin
= { 0, 0 };
135 /* Translate source window origin to screen coords */
138 wndPtr
= WIN_FindWndPtr( hwndFrom
);
139 origin
.x
+= wndPtr
->rectClient
.left
;
140 origin
.y
+= wndPtr
->rectClient
.top
;
141 hwndFrom
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->hwndParent
: 0;
144 /* Translate origin to destination window coords */
147 wndPtr
= WIN_FindWndPtr( hwndTo
);
148 origin
.x
-= wndPtr
->rectClient
.left
;
149 origin
.y
-= wndPtr
->rectClient
.top
;
150 hwndTo
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->hwndParent
: 0;
153 /* Translate points */
154 for (i
= 0, curpt
= lppt
; i
< count
; i
++, curpt
++)
156 curpt
->x
+= origin
.x
;
157 curpt
->y
+= origin
.y
;
162 /***********************************************************************
165 BOOL
IsIconic(HWND hWnd
)
167 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
168 if (wndPtr
== NULL
) return FALSE
;
169 return (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
173 /***********************************************************************
174 * IsZoomed (USER.272)
176 BOOL
IsZoomed(HWND hWnd
)
178 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
179 if (wndPtr
== NULL
) return FALSE
;
180 return (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
184 /*******************************************************************
185 * GetActiveWindow (USER.60)
187 HWND
GetActiveWindow()
192 /*******************************************************************
193 * SetActiveWindow (USER.59)
195 HWND
SetActiveWindow( HWND hwnd
)
197 HWND prev
= hwndActive
;
198 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
199 if (!wndPtr
|| (wndPtr
->dwStyle
& WS_CHILD
)) return 0;
200 SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
205 /***********************************************************************
206 * BringWindowToTop (USER.45)
208 BOOL
BringWindowToTop( HWND hwnd
)
210 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
214 /***********************************************************************
215 * MoveWindow (USER.56)
217 BOOL
MoveWindow( HWND hwnd
, short x
, short y
, short cx
, short cy
, BOOL repaint
)
219 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
220 if (!repaint
) flags
|= SWP_NOREDRAW
;
221 dprintf_win(stddeb
, "MoveWindow: %d %d,%d %dx%d %d\n",
222 hwnd
, x
, y
, cx
, cy
, repaint
);
223 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
229 * hwnd is the handle to the first child window to hide
231 static void WINPOS_hideChildren(HWND hwnd
)
236 ShowWindow(hwnd
, SW_HIDE
);
237 wndPtr
= WIN_FindWndPtr(hwnd
);
239 WINPOS_hideChildren(wndPtr
->hwndChild
);
240 hwnd
= wndPtr
->hwndNext
;
245 static void WINPOS_ChildrenComeOutToPlay(HWND hwnd
)
251 * we shouldn't really be calling SW_SHOWNOACTIVATE
252 * here because we wake up all windows, even the ones
253 * the user has decided to iconify or hide
255 * have to use SHOWNOACTIVATE instead of SHOWNORMAL
256 * since we are traversing the window tree and don't
257 * want windows linked/unlined under us
259 ShowWindow(hwnd
, SW_SHOWNOACTIVATE
);
260 wndPtr
= WIN_FindWndPtr(hwnd
);
262 WINPOS_ChildrenComeOutToPlay(wndPtr
->hwndChild
);
263 hwnd
= wndPtr
->hwndNext
;
268 /***********************************************************************
269 * ShowWindow (USER.42)
271 BOOL
ShowWindow( HWND hwnd
, int cmd
)
273 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
278 if (!wndPtr
) return FALSE
;
280 dprintf_win(stddeb
,"ShowWindow: hwnd=%04X, cmd=%d\n", hwnd
, cmd
);
283 * wasVisible is true if user has not made window invisible
284 * wasIconic is true if the window is not iconified
286 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
292 * if the window wasn't visible to begin with -- just return
295 return FALSE
; /* Nothing to do */
296 swpflags
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
297 SWP_NOACTIVATE
| SWP_NOZORDER
;
301 case SW_SHOWMINNOACTIVE
:
302 case SW_SHOWMINIMIZED
:
304 wndPtr
->dwStyle
|= WS_MINIMIZE
;
305 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
306 SWP_NOACTIVATE
| SWP_NOZORDER
;
310 * tell children that they are getting hidden
312 WINPOS_hideChildren(wndPtr
->hwndChild
);
315 /* store the size and position of the window, so we can
316 * deiconify it to the same size and position
318 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
319 wndPtr
->ptIconPos
.x
= wndPtr
->rectWindow
.left
;
320 wndPtr
->ptIconPos
.y
= wndPtr
->rectWindow
.top
;
321 /* move the window to icon size and position and
322 * tell it that it is going to have to be painted
324 MoveWindow(hwnd
, wndPtr
->ptIconPos
.x
, wndPtr
->ptIconPos
.y
,
325 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
, FALSE
);
326 SendMessage(hwnd
, WM_PAINTICON
, 0, 0);
331 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE: */
333 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
337 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
338 case SW_SHOWNOACTIVATE
:
340 wasIconic
= IsIconic(hwnd
);
341 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
342 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
343 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
344 if (cmd
== SW_SHOWNOACTIVATE
)
346 swpflags
|= SWP_NOZORDER
;
347 if (GetActiveWindow()) swpflags
|= SWP_NOACTIVATE
;
350 MoveWindow(hwnd
, wndPtr
->rectNormal
.left
,
351 wndPtr
->rectNormal
.top
,
352 wndPtr
->rectNormal
.right
- wndPtr
->rectNormal
.left
,
353 wndPtr
->rectNormal
.bottom
- wndPtr
->rectNormal
.top
,
357 WINPOS_ChildrenComeOutToPlay(wndPtr
->hwndChild
);
362 SendMessage( hwnd
, WM_SHOWWINDOW
, (cmd
!= SW_HIDE
), 0 );
363 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, swpflags
);
365 /* Send WM_SIZE and WM_MOVE messages if not already done */
366 if (!(wndPtr
->flags
& WIN_GOT_SIZEMSG
))
368 int wParam
= SIZE_RESTORED
;
369 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
370 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
371 wndPtr
->flags
|= WIN_GOT_SIZEMSG
;
372 SendMessage( hwnd
, WM_SIZE
, wParam
,
373 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
374 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
375 SendMessage( hwnd
, WM_MOVE
, 0,
376 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
383 /***********************************************************************
384 * GetInternalWindowPos (USER.460)
386 WORD
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
, LPPOINT ptIcon
)
388 WINDOWPLACEMENT wndpl
;
389 if (!GetWindowPlacement( hwnd
, &wndpl
)) return 0;
390 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
391 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
392 return wndpl
.showCmd
;
396 /***********************************************************************
397 * SetInternalWindowPos (USER.461)
399 void SetInternalWindowPos( HWND hwnd
, WORD showCmd
, LPRECT rect
, LPPOINT pt
)
401 WINDOWPLACEMENT wndpl
;
402 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
404 wndpl
.length
= sizeof(wndpl
);
405 wndpl
.flags
= (pt
!= NULL
) ? WPF_SETMINPOSITION
: 0;
406 wndpl
.showCmd
= showCmd
;
407 if (pt
) wndpl
.ptMinPosition
= *pt
;
408 wndpl
.rcNormalPosition
= (rect
!= NULL
) ? *rect
: wndPtr
->rectNormal
;
409 wndpl
.ptMaxPosition
= wndPtr
->ptMaxPos
;
410 SetWindowPlacement( hwnd
, &wndpl
);
414 /***********************************************************************
415 * GetWindowPlacement (USER.370)
417 BOOL
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
419 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
420 if (!wndPtr
) return FALSE
;
422 wndpl
->length
= sizeof(*wndpl
);
424 wndpl
->showCmd
= IsZoomed(hwnd
) ? SW_SHOWMAXIMIZED
:
425 (IsIconic(hwnd
) ? SW_SHOWMINIMIZED
: SW_SHOWNORMAL
);
426 wndpl
->ptMinPosition
= wndPtr
->ptIconPos
;
427 wndpl
->ptMaxPosition
= wndPtr
->ptMaxPos
;
428 wndpl
->rcNormalPosition
= wndPtr
->rectNormal
;
433 /***********************************************************************
434 * SetWindowPlacement (USER.371)
436 BOOL
SetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
438 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
439 if (!wndPtr
) return FALSE
;
441 if (wndpl
->flags
& WPF_SETMINPOSITION
)
442 wndPtr
->ptIconPos
= wndpl
->ptMinPosition
;
443 if ((wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) &&
444 (wndpl
->showCmd
== SW_SHOWMINIMIZED
)) wndPtr
->flags
|= WIN_RESTORE_MAX
;
445 wndPtr
->ptMaxPos
= wndpl
->ptMaxPosition
;
446 wndPtr
->rectNormal
= wndpl
->rcNormalPosition
;
447 ShowWindow( hwnd
, wndpl
->showCmd
);
452 /*******************************************************************
453 * WINPOS_GetMinMaxInfo
455 * Send a WM_GETMINMAXINFO to the window.
457 void WINPOS_GetMinMaxInfo( HWND hwnd
, POINT
*maxSize
, POINT
*maxPos
,
458 POINT
*minTrack
, POINT
*maxTrack
)
461 MINMAXINFO MinMax
, *pMinMax
;
462 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
464 MinMax
.ptMaxSize
.x
= SYSMETRICS_CXSCREEN
;
465 MinMax
.ptMaxSize
.y
= SYSMETRICS_CYSCREEN
;
466 MinMax
.ptMaxPosition
= wndPtr
->ptMaxPos
;
467 MinMax
.ptMinTrackSize
.x
= SYSMETRICS_CXMINTRACK
;
468 MinMax
.ptMinTrackSize
.y
= SYSMETRICS_CYMINTRACK
;
469 MinMax
.ptMaxTrackSize
.x
= SYSMETRICS_CXSCREEN
;
470 MinMax
.ptMaxTrackSize
.y
= SYSMETRICS_CYSCREEN
;
472 minmaxHandle
= USER_HEAP_ALLOC( LMEM_MOVEABLE
, sizeof(MINMAXINFO
) );
475 pMinMax
= (MINMAXINFO
*) USER_HEAP_ADDR( minmaxHandle
);
476 memcpy( pMinMax
, &MinMax
, sizeof(MinMax
) );
477 SendMessage( hwnd
, WM_GETMINMAXINFO
, 0, (LONG
)pMinMax
);
479 else pMinMax
= &MinMax
;
481 /* Some sanity checks */
483 pMinMax
->ptMaxTrackSize
.x
= max( pMinMax
->ptMaxTrackSize
.x
,
484 pMinMax
->ptMinTrackSize
.x
);
485 pMinMax
->ptMaxTrackSize
.y
= max( pMinMax
->ptMaxTrackSize
.y
,
486 pMinMax
->ptMinTrackSize
.y
);
488 if (maxSize
) *maxSize
= pMinMax
->ptMaxSize
;
489 if (maxPos
) *maxPos
= pMinMax
->ptMaxPosition
;
490 if (minTrack
) *minTrack
= pMinMax
->ptMinTrackSize
;
491 if (maxTrack
) *maxTrack
= pMinMax
->ptMaxTrackSize
;
492 if (minmaxHandle
) USER_HEAP_FREE( minmaxHandle
);
496 /*******************************************************************
497 * WINPOS_ChangeActiveWindow
499 * Change the active window and send the corresponding messages.
501 HWND
WINPOS_ChangeActiveWindow( HWND hwnd
, BOOL mouseMsg
)
503 HWND prevActive
= hwndActive
;
504 if (hwnd
== hwndActive
) return 0;
507 if (!SendMessage( hwndActive
, WM_NCACTIVATE
, FALSE
, 0 )) return 0;
508 SendMessage( hwndActive
, WM_ACTIVATE
, WA_INACTIVE
,
509 MAKELONG( IsIconic(hwndActive
), hwnd
) );
510 /* Send WM_ACTIVATEAPP here */
516 WND
*wndPtr
= WIN_FindWndPtr( hwndActive
);
517 wndPtr
->hwndPrevActive
= prevActive
;
519 /* Send WM_ACTIVATEAPP here */
520 SendMessage( hwnd
, WM_NCACTIVATE
, TRUE
, 0 );
521 SendMessage( hwnd
, WM_ACTIVATE
, mouseMsg
? WA_CLICKACTIVE
: WA_ACTIVE
,
522 MAKELONG( IsIconic(hwnd
), prevActive
) );
528 /***********************************************************************
529 * WINPOS_SendNCCalcSize
531 * Send a WM_NCCALCSIZE message to a window.
532 * All parameters are read-only except newClientRect.
533 * oldWindowRect, oldClientRect and winpos must be non-NULL only
534 * when calcValidRect is TRUE.
536 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
, RECT
*newWindowRect
,
537 RECT
*oldWindowRect
, RECT
*oldClientRect
,
538 WINDOWPOS
*winpos
, RECT
*newClientRect
)
540 NCCALCSIZE_PARAMS
*params
;
544 if (!(hparams
= USER_HEAP_ALLOC( GMEM_MOVEABLE
, sizeof(*params
) )))
546 params
= (NCCALCSIZE_PARAMS
*) USER_HEAP_ADDR( hparams
);
547 params
->rgrc
[0] = *newWindowRect
;
550 params
->rgrc
[1] = *oldWindowRect
;
551 params
->rgrc
[2] = *oldClientRect
;
552 params
->lppos
= winpos
;
554 result
= SendMessage( hwnd
, WM_NCCALCSIZE
, calcValidRect
, (LONG
)params
);
555 *newClientRect
= params
->rgrc
[0];
556 USER_HEAP_FREE( hparams
);
561 /***********************************************************************
562 * WINPOS_HandleWindowPosChanging
564 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
566 LONG
WINPOS_HandleWindowPosChanging( WINDOWPOS
*winpos
)
569 WND
*wndPtr
= WIN_FindWndPtr( winpos
->hwnd
);
570 if (!wndPtr
|| (winpos
->flags
& SWP_NOSIZE
)) return 0;
571 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
572 (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
) == 0))
574 WINPOS_GetMinMaxInfo( winpos
->hwnd
, &maxSize
, NULL
, NULL
, NULL
);
575 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
576 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
582 /***********************************************************************
583 * WINPOS_MoveWindowZOrder
585 * Move a window in Z order, invalidating everything that needs it.
586 * Only necessary for windows without associated X window.
588 static void WINPOS_MoveWindowZOrder( HWND hwnd
, HWND hwndAfter
, BOOL erase
)
592 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
594 /* We have two possible cases:
595 * - The window is moving up: we have to invalidate all areas
596 * of the window that were covered by other windows
597 * - The window is moving down: we have to invalidate areas
598 * of other windows covered by this one.
601 if (hwndAfter
== HWND_TOP
)
605 else if (hwndAfter
== HWND_BOTTOM
)
607 if (!wndPtr
->hwndNext
) return; /* Already at the bottom */
612 if (wndPtr
->hwndNext
== hwndAfter
) return; /* Already placed right */
614 /* Determine which window we encounter first in Z-order */
615 hwndCur
= GetWindow( wndPtr
->hwndParent
, GW_CHILD
);
616 while ((hwndCur
!= hwnd
) && (hwndCur
!= hwndAfter
))
617 hwndCur
= GetWindow( hwndCur
, GW_HWNDNEXT
);
618 movingUp
= (hwndCur
== hwndAfter
);
623 HWND hwndPrevAfter
= wndPtr
->hwndNext
;
624 WIN_UnlinkWindow( hwnd
);
625 WIN_LinkWindow( hwnd
, hwndAfter
);
626 hwndCur
= wndPtr
->hwndNext
;
627 while (hwndCur
!= hwndPrevAfter
)
629 WND
*curPtr
= WIN_FindWndPtr( hwndCur
);
630 RECT rect
= curPtr
->rectWindow
;
631 OffsetRect( &rect
, -wndPtr
->rectClient
.left
,
632 -wndPtr
->rectClient
.top
);
633 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
|
634 RDW_FRAME
| (erase
? RDW_ERASENOW
: RDW_ERASE
) );
635 hwndCur
= curPtr
->hwndNext
;
638 else /* Moving down */
640 hwndCur
= wndPtr
->hwndNext
;
641 WIN_UnlinkWindow( hwnd
);
642 WIN_LinkWindow( hwnd
, hwndAfter
);
643 while (hwndCur
!= hwnd
)
645 WND
*curPtr
= WIN_FindWndPtr( hwndCur
);
646 RECT rect
= wndPtr
->rectWindow
;
647 OffsetRect( &rect
, -curPtr
->rectClient
.left
,
648 -curPtr
->rectClient
.top
);
649 RedrawWindow( hwndCur
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
|
650 RDW_FRAME
| (erase
? RDW_ERASENOW
: RDW_ERASE
) );
651 hwndCur
= curPtr
->hwndNext
;
657 /***********************************************************************
658 * WINPOS_InternalSetWindowPos
660 * Helper function for SetWindowPos.
662 static BOOL
WINPOS_InternalSetWindowPos( WINDOWPOS
*winpos
)
666 RECT newWindowRect
, newClientRect
;
669 XWindowChanges winChanges
;
671 /* Send WM_WINDOWPOSCHANGING message */
673 if (!(winpos
->flags
& SWP_NOSENDCHANGING
))
674 SendMessage( winpos
->hwnd
, WM_WINDOWPOSCHANGING
, 0, (LONG
)winpos
);
676 /* Check window handle */
678 if (winpos
->hwnd
== GetDesktopWindow()) return FALSE
;
679 if (!(wndPtr
= WIN_FindWndPtr( winpos
->hwnd
))) return FALSE
;
681 /* Check dimensions */
683 if (winpos
->cx
<= 0) winpos
->cx
= 1;
684 if (winpos
->cy
<= 0) winpos
->cy
= 1;
688 flags
= winpos
->flags
;
689 if (winpos
->hwnd
== hwndActive
) flags
|= SWP_NOACTIVATE
; /*Already active*/
691 /* Check hwndAfter */
693 hwndAfter
= winpos
->hwndInsertAfter
;
694 if (!(flags
& (SWP_NOZORDER
| SWP_NOACTIVATE
)))
696 /* Ignore TOPMOST flags when activating a window */
697 /* _and_ moving it in Z order. */
698 if ((hwndAfter
== HWND_TOPMOST
) || (hwndAfter
== HWND_NOTOPMOST
))
699 hwndAfter
= HWND_TOP
;
701 /* TOPMOST not supported yet */
702 if ((hwndAfter
== HWND_TOPMOST
) || (hwndAfter
== HWND_NOTOPMOST
))
703 hwndAfter
= HWND_TOP
;
704 /* hwndAfter must be a sibling of the window */
705 if ((hwndAfter
!= HWND_TOP
) && (hwndAfter
!= HWND_BOTTOM
) &&
706 (GetParent(winpos
->hwnd
) != GetParent(hwndAfter
))) return FALSE
;
708 /* Calculate new position and size */
710 newWindowRect
= wndPtr
->rectWindow
;
711 newClientRect
= wndPtr
->rectClient
;
713 if (!(flags
& SWP_NOSIZE
))
715 newWindowRect
.right
= newWindowRect
.left
+ winpos
->cx
;
716 newWindowRect
.bottom
= newWindowRect
.top
+ winpos
->cy
;
717 winChanges
.width
= winpos
->cx
;
718 winChanges
.height
= winpos
->cy
;
719 changeMask
|= CWWidth
| CWHeight
;
721 if (!(flags
& SWP_NOMOVE
))
723 newWindowRect
.left
= winpos
->x
;
724 newWindowRect
.top
= winpos
->y
;
725 newWindowRect
.right
+= winpos
->x
- wndPtr
->rectWindow
.left
;
726 newWindowRect
.bottom
+= winpos
->y
- wndPtr
->rectWindow
.top
;
727 if (wndPtr
->dwStyle
& WS_CHILD
)
729 WND
*parentPtr
= WIN_FindWndPtr(wndPtr
->hwndParent
);
730 winChanges
.x
= winpos
->x
+ parentPtr
->rectClient
.left
731 - parentPtr
->rectWindow
.left
;
732 winChanges
.y
= winpos
->y
+ parentPtr
->rectClient
.top
733 - parentPtr
->rectWindow
.top
;
737 winChanges
.x
= winpos
->x
;
738 winChanges
.y
= winpos
->y
;
740 changeMask
|= CWX
| CWY
;
743 /* Reposition window in Z order */
745 if (!(flags
& SWP_NOZORDER
))
749 WIN_UnlinkWindow( winpos
->hwnd
);
750 WIN_LinkWindow( winpos
->hwnd
, hwndAfter
);
751 if (hwndAfter
== HWND_TOP
) winChanges
.stack_mode
= Above
;
752 else winChanges
.stack_mode
= Below
;
753 if ((hwndAfter
!= HWND_TOP
) && (hwndAfter
!= HWND_BOTTOM
))
755 WND
* insertPtr
= WIN_FindWndPtr( hwndAfter
);
756 winChanges
.sibling
= insertPtr
->window
;
757 changeMask
|= CWSibling
;
759 changeMask
|= CWStackMode
;
761 else WINPOS_MoveWindowZOrder( winpos
->hwnd
, hwndAfter
,
762 !(flags
& SWP_DEFERERASE
) );
765 /* Send WM_NCCALCSIZE message to get new client area */
767 result
= WINPOS_SendNCCalcSize( winpos
->hwnd
, TRUE
, &newWindowRect
,
768 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
769 winpos
, &newClientRect
);
770 /* .... Should handle result here */
772 /* Perform the moving and resizing */
776 if (changeMask
) XConfigureWindow( display
, wndPtr
->window
,
777 changeMask
, &winChanges
);
778 wndPtr
->rectWindow
= newWindowRect
;
779 wndPtr
->rectClient
= newClientRect
;
783 RECT oldWindowRect
= wndPtr
->rectWindow
;
785 wndPtr
->rectWindow
= newWindowRect
;
786 wndPtr
->rectClient
= newClientRect
;
790 HRGN hrgn1
= CreateRectRgnIndirect( &oldWindowRect
);
791 HRGN hrgn2
= CreateRectRgnIndirect( &wndPtr
->rectWindow
);
792 HRGN hrgn3
= CreateRectRgn( 0, 0, 0, 0 );
793 CombineRgn( hrgn3
, hrgn1
, hrgn2
, RGN_DIFF
);
794 RedrawWindow( wndPtr
->hwndParent
, NULL
, hrgn3
,
795 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASENOW
);
796 if ((oldWindowRect
.left
!= wndPtr
->rectWindow
.left
) ||
797 (oldWindowRect
.top
!= wndPtr
->rectWindow
.top
))
799 RedrawWindow( winpos
->hwnd
, NULL
, 0, RDW_INVALIDATE
|
800 RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASENOW
);
802 DeleteObject( hrgn1
);
803 DeleteObject( hrgn2
);
804 DeleteObject( hrgn3
);
808 if (flags
& SWP_SHOWWINDOW
)
810 wndPtr
->dwStyle
|= WS_VISIBLE
;
813 XMapWindow( display
, wndPtr
->window
);
815 if (flags
& SWP_NOREDRAW
) /* Validate the whole window */
816 RedrawWindow( winpos
->hwnd
, NULL
, 0, RDW_VALIDATE
);
819 else if (flags
& SWP_HIDEWINDOW
)
821 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
824 XUnmapWindow( display
, wndPtr
->window
);
828 RedrawWindow( wndPtr
->hwndParent
, &wndPtr
->rectWindow
, 0,
829 RDW_INVALIDATE
| RDW_FRAME
|
830 RDW_ALLCHILDREN
| RDW_ERASENOW
);
832 if ((winpos
->hwnd
== GetFocus()) || IsChild(winpos
->hwnd
, GetFocus()))
833 SetFocus( GetParent(winpos
->hwnd
) ); /* Revert focus to parent */
834 if (winpos
->hwnd
== hwndActive
)
836 /* Activate previously active window if possible */
837 HWND newActive
= wndPtr
->hwndPrevActive
;
838 if (!IsWindow(newActive
) || (newActive
== winpos
->hwnd
))
840 newActive
= GetTopWindow(GetDesktopWindow());
841 if (newActive
== winpos
->hwnd
) newActive
= wndPtr
->hwndNext
;
843 WINPOS_ChangeActiveWindow( newActive
, FALSE
);
847 /* Activate the window */
849 if (!(flags
& SWP_NOACTIVATE
))
851 if (!(wndPtr
->dwStyle
& WS_CHILD
))
852 WINPOS_ChangeActiveWindow( winpos
->hwnd
, FALSE
);
855 /* Send WM_NCPAINT message if needed */
857 if (flags
& SWP_SHOWWINDOW
)
859 /* Repaint the window frame and background */
860 RedrawWindow( winpos
->hwnd
, NULL
, 0,
861 RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
865 if ((flags
& SWP_FRAMECHANGED
) ||
866 (!(flags
& SWP_NOSIZE
)) ||
867 (!(flags
& SWP_NOMOVE
)) ||
868 (!(flags
& SWP_NOACTIVATE
)) ||
869 (!(flags
& SWP_NOZORDER
)))
870 SendMessage( winpos
->hwnd
, WM_NCPAINT
, 1, 0L );
873 /* And last, send the WM_WINDOWPOSCHANGED message */
875 SendMessage( winpos
->hwnd
, WM_WINDOWPOSCHANGED
, 0, (LONG
)winpos
);
880 /***********************************************************************
881 * BeginDeferWindowPos (USER.259)
883 HDWP
BeginDeferWindowPos( INT count
)
888 if (count
<= 0) return 0;
889 handle
= USER_HEAP_ALLOC( GMEM_MOVEABLE
,
890 sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
891 if (!handle
) return 0;
892 pDWP
= (DWP
*) USER_HEAP_ADDR( handle
);
893 pDWP
->actualCount
= 0;
894 pDWP
->suggestedCount
= count
;
896 pDWP
->wMagic
= DWP_MAGIC
;
901 /***********************************************************************
902 * DeferWindowPos (USER.260)
904 HDWP
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
, INT x
, INT y
,
905 INT cx
, INT cy
, WORD flags
)
911 pDWP
= (DWP
*) USER_HEAP_ADDR( hdwp
);
913 for (i
= 0; i
< pDWP
->actualCount
; i
++)
915 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
917 /* Merge with the other changes */
918 if (!(flags
& SWP_NOZORDER
))
920 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
922 if (!(flags
& SWP_NOMOVE
))
924 pDWP
->winPos
[i
].x
= x
;
925 pDWP
->winPos
[i
].y
= y
;
927 if (!(flags
& SWP_NOSIZE
))
929 pDWP
->winPos
[i
].cx
= cx
;
930 pDWP
->winPos
[i
].cy
= cy
;
932 pDWP
->winPos
[i
].flags
&= flags
& (SWP_NOSIZE
| SWP_NOMOVE
|
933 SWP_NOZORDER
| SWP_NOREDRAW
|
934 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
936 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
941 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
943 newhdwp
= USER_HEAP_REALLOC( hdwp
,
944 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
), 0);
945 if (!newhdwp
) return 0;
946 pDWP
= (DWP
*) USER_HEAP_ADDR( newhdwp
);
947 pDWP
->suggestedCount
++;
949 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
950 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
951 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
952 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
953 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
954 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
955 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
961 /***********************************************************************
962 * EndDeferWindowPos (USER.261)
964 BOOL
EndDeferWindowPos( HDWP hdwp
)
970 pDWP
= (DWP
*) USER_HEAP_ADDR( hdwp
);
971 if (!pDWP
) return FALSE
;
972 for (i
= 0; i
< pDWP
->actualCount
; i
++)
974 if (!(res
= WINPOS_InternalSetWindowPos( &pDWP
->winPos
[i
] ))) break;
976 USER_HEAP_FREE( hdwp
);
981 /***********************************************************************
982 * SetWindowPos (USER.232)
984 BOOL
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
, INT x
, INT y
,
985 INT cx
, INT cy
, WORD flags
)
990 printf( "SetWindowPos: %04X %d %d,%d %dx%d 0x%x\n",
991 hwnd
, hwndInsertAfter
, x
, y
, cx
, cy
, flags
);
993 if (!(hdwp
= BeginDeferWindowPos( 1 ))) return FALSE
;
994 if (!(hdwp
= DeferWindowPos( hdwp
, hwnd
, hwndInsertAfter
,
995 x
, y
, cx
, cy
, flags
))) return FALSE
;
996 return EndDeferWindowPos( hdwp
);