2 * Window position related functions.
4 * Copyright 1993, 1994 Alexandre Julliard
7 #include "sysmetrics.h"
13 /* #define DEBUG_WIN */
14 /* #undef DEBUG_WIN */
17 static HWND hwndActive
= 0; /* Currently active window */
20 /***********************************************************************
21 * GetWindowRect (USER.32)
23 void GetWindowRect( HWND hwnd
, LPRECT rect
)
25 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
28 *rect
= wndPtr
->rectWindow
;
29 if (wndPtr
->dwStyle
& WS_CHILD
)
30 MapWindowPoints( wndPtr
->hwndParent
, 0, (POINT
*)rect
, 2 );
34 /***********************************************************************
35 * GetClientRect (USER.33)
37 void GetClientRect( HWND hwnd
, LPRECT rect
)
39 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
41 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
44 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
45 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
50 /*******************************************************************
51 * ClientToScreen (USER.28)
53 void ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
55 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
59 /*******************************************************************
60 * ScreenToClient (USER.29)
62 void ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
64 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
68 /*******************************************************************
69 * WindowFromPoint (USER.30)
71 HWND
WindowFromPoint( POINT pt
)
74 HWND hwnd
= GetDesktopWindow();
78 /* If point is in window, and window is visible, */
79 /* not disabled and not transparent, then explore */
80 /* its children. Otherwise, go to the next window. */
82 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
83 if ((pt
.x
>= wndPtr
->rectWindow
.left
) &&
84 (pt
.x
< wndPtr
->rectWindow
.right
) &&
85 (pt
.y
>= wndPtr
->rectWindow
.top
) &&
86 (pt
.y
< wndPtr
->rectWindow
.bottom
) &&
87 !(wndPtr
->dwStyle
& WS_DISABLED
) &&
88 (wndPtr
->dwStyle
& WS_VISIBLE
) &&
89 !(wndPtr
->dwExStyle
& WS_EX_TRANSPARENT
))
92 /* If window is minimized, ignore its children */
93 if (wndPtr
->dwStyle
& WS_MINIMIZE
) break;
94 pt
.x
-= wndPtr
->rectClient
.left
;
95 pt
.y
-= wndPtr
->rectClient
.top
;
96 hwnd
= wndPtr
->hwndChild
;
98 else hwnd
= wndPtr
->hwndNext
;
103 /*******************************************************************
104 * ChildWindowFromPoint (USER.191)
106 HWND
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
111 GetWindowRect( hwndParent
, &rect
);
112 if (!PtInRect( &rect
, pt
)) return 0;
113 hwnd
= GetTopWindow( hwndParent
);
116 GetWindowRect( hwnd
, &rect
);
117 if (PtInRect( &rect
, pt
)) return hwnd
;
118 hwnd
= GetWindow( hwnd
, GW_HWNDNEXT
);
124 /*******************************************************************
125 * MapWindowPoints (USER.258)
127 void MapWindowPoints( HWND hwndFrom
, HWND hwndTo
, LPPOINT lppt
, WORD count
)
131 POINT origin
= { 0, 0 };
134 /* Translate source window origin to screen coords */
137 wndPtr
= WIN_FindWndPtr( hwndFrom
);
138 origin
.x
+= wndPtr
->rectClient
.left
;
139 origin
.y
+= wndPtr
->rectClient
.top
;
140 hwndFrom
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->hwndParent
: 0;
143 /* Translate origin to destination window coords */
146 wndPtr
= WIN_FindWndPtr( hwndTo
);
147 origin
.x
-= wndPtr
->rectClient
.left
;
148 origin
.y
-= wndPtr
->rectClient
.top
;
149 hwndTo
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->hwndParent
: 0;
152 /* Translate points */
153 for (i
= 0, curpt
= lppt
; i
< count
; i
++, curpt
++)
155 curpt
->x
+= origin
.x
;
156 curpt
->y
+= origin
.y
;
161 /***********************************************************************
164 BOOL
IsIconic(HWND hWnd
)
166 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
167 if (wndPtr
== NULL
) return FALSE
;
168 return (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
172 /***********************************************************************
173 * IsZoomed (USER.272)
175 BOOL
IsZoomed(HWND hWnd
)
177 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
178 if (wndPtr
== NULL
) return FALSE
;
179 return (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
183 /*******************************************************************
184 * GetActiveWindow (USER.60)
186 HWND
GetActiveWindow()
191 /*******************************************************************
192 * SetActiveWindow (USER.59)
194 HWND
SetActiveWindow( HWND hwnd
)
196 HWND prev
= hwndActive
;
197 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
198 if (!wndPtr
|| (wndPtr
->dwStyle
& WS_CHILD
)) return 0;
199 SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
204 /***********************************************************************
205 * BringWindowToTop (USER.45)
207 BOOL
BringWindowToTop( HWND hwnd
)
209 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
213 /***********************************************************************
214 * MoveWindow (USER.56)
216 BOOL
MoveWindow( HWND hwnd
, short x
, short y
, short cx
, short cy
, BOOL repaint
)
218 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
219 if (!repaint
) flags
|= SWP_NOREDRAW
;
220 dprintf_win(stddeb
, "MoveWindow: %d %d,%d %dx%d %d\n",
221 hwnd
, x
, y
, cx
, cy
, repaint
);
222 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
226 /***********************************************************************
227 * ShowWindow (USER.42)
229 BOOL
ShowWindow( HWND hwnd
, int cmd
)
231 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
236 if (!wndPtr
) return FALSE
;
238 dprintf_win(stddeb
,"ShowWindow: hwnd=%04X, cmd=%d\n", hwnd
, cmd
);
241 * wasVisible is true if user has not made window invisible
242 * wasIconic is true if the window is not iconified
244 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
250 * if the window wasn't visible to begin with -- just return
253 return FALSE
; /* Nothing to do */
254 swpflags
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
255 SWP_NOACTIVATE
| SWP_NOZORDER
;
259 case SW_SHOWMINNOACTIVE
:
260 case SW_SHOWMINIMIZED
:
262 wndPtr
->dwStyle
|= WS_MINIMIZE
;
263 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
264 SWP_NOACTIVATE
| SWP_NOZORDER
;
266 /* store the size and position of the window, so we can
267 * deiconify it to the same size and position
269 wndPtr
->rectNormal
= wndPtr
->rectWindow
;
270 wndPtr
->ptIconPos
.x
= wndPtr
->rectWindow
.left
;
271 wndPtr
->ptIconPos
.y
= wndPtr
->rectWindow
.top
;
272 /* move the window to icon size and position and
273 * tell it that it is going to have to be painted
275 MoveWindow(hwnd
, wndPtr
->ptIconPos
.x
, wndPtr
->ptIconPos
.y
,
276 SYSMETRICS_CXICON
, SYSMETRICS_CYICON
, FALSE
);
277 RedrawWindow( hwnd
, NULL
, 0, RDW_FRAME
| RDW_ERASENOW
);
281 case SW_SHOWMAXIMIZED
: /* same as SW_MAXIMIZE: */
283 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
287 case SW_SHOWNORMAL
: /* same as SW_NORMAL: */
288 case SW_SHOWNOACTIVATE
:
290 wasIconic
= IsIconic(hwnd
);
291 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
292 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
293 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
294 if (cmd
== SW_SHOWNOACTIVATE
)
296 swpflags
|= SWP_NOZORDER
;
297 if (GetActiveWindow()) swpflags
|= SWP_NOACTIVATE
;
300 MoveWindow(hwnd
, wndPtr
->rectNormal
.left
,
301 wndPtr
->rectNormal
.top
,
302 wndPtr
->rectNormal
.right
- wndPtr
->rectNormal
.left
,
303 wndPtr
->rectNormal
.bottom
- wndPtr
->rectNormal
.top
,
309 SendMessage( hwnd
, WM_SHOWWINDOW
, (cmd
!= SW_HIDE
), 0 );
310 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, swpflags
);
312 /* Send WM_SIZE and WM_MOVE messages if not already done */
313 if (!(wndPtr
->flags
& WIN_GOT_SIZEMSG
))
315 int wParam
= SIZE_RESTORED
;
316 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
317 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
318 wndPtr
->flags
|= WIN_GOT_SIZEMSG
;
319 SendMessage( hwnd
, WM_SIZE
, wParam
,
320 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
321 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
322 SendMessage( hwnd
, WM_MOVE
, 0,
323 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
330 /***********************************************************************
331 * GetInternalWindowPos (USER.460)
333 WORD
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
, LPPOINT ptIcon
)
335 WINDOWPLACEMENT wndpl
;
336 if (!GetWindowPlacement( hwnd
, &wndpl
)) return 0;
337 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
338 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
339 return wndpl
.showCmd
;
343 /***********************************************************************
344 * SetInternalWindowPos (USER.461)
346 void SetInternalWindowPos( HWND hwnd
, WORD showCmd
, LPRECT rect
, LPPOINT pt
)
348 WINDOWPLACEMENT wndpl
;
349 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
351 wndpl
.length
= sizeof(wndpl
);
352 wndpl
.flags
= (pt
!= NULL
) ? WPF_SETMINPOSITION
: 0;
353 wndpl
.showCmd
= showCmd
;
354 if (pt
) wndpl
.ptMinPosition
= *pt
;
355 wndpl
.rcNormalPosition
= (rect
!= NULL
) ? *rect
: wndPtr
->rectNormal
;
356 wndpl
.ptMaxPosition
= wndPtr
->ptMaxPos
;
357 SetWindowPlacement( hwnd
, &wndpl
);
361 /***********************************************************************
362 * GetWindowPlacement (USER.370)
364 BOOL
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
366 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
367 if (!wndPtr
) return FALSE
;
369 wndpl
->length
= sizeof(*wndpl
);
371 wndpl
->showCmd
= IsZoomed(hwnd
) ? SW_SHOWMAXIMIZED
:
372 (IsIconic(hwnd
) ? SW_SHOWMINIMIZED
: SW_SHOWNORMAL
);
373 wndpl
->ptMinPosition
= wndPtr
->ptIconPos
;
374 wndpl
->ptMaxPosition
= wndPtr
->ptMaxPos
;
375 wndpl
->rcNormalPosition
= wndPtr
->rectNormal
;
380 /***********************************************************************
381 * SetWindowPlacement (USER.371)
383 BOOL
SetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
385 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
386 if (!wndPtr
) return FALSE
;
388 if (wndpl
->flags
& WPF_SETMINPOSITION
)
389 wndPtr
->ptIconPos
= wndpl
->ptMinPosition
;
390 if ((wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) &&
391 (wndpl
->showCmd
== SW_SHOWMINIMIZED
)) wndPtr
->flags
|= WIN_RESTORE_MAX
;
392 wndPtr
->ptMaxPos
= wndpl
->ptMaxPosition
;
393 wndPtr
->rectNormal
= wndpl
->rcNormalPosition
;
394 ShowWindow( hwnd
, wndpl
->showCmd
);
399 /*******************************************************************
400 * WINPOS_NextWindowFromPoint
402 * Looks for next enabled window that is
403 * a) sibling of hwnd, later in Z-order and encloses pt, or
406 HWND
WINPOS_NextWindowFromPoint( HWND hwnd
, POINT pt
)
408 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
410 if (!wndPtr
->hwndParent
) return hwnd
; /* desktop window */
411 ScreenToClient( wndPtr
->hwndParent
, &pt
); /* make pt relative to parent */
414 if (!wndPtr
->hwndNext
) break; /* No more children */
415 hwnd
= wndPtr
->hwndNext
;
416 wndPtr
= WIN_FindWndPtr( hwnd
);
417 if ((wndPtr
->dwStyle
& WS_VISIBLE
) &&
418 !(wndPtr
->dwStyle
& WS_DISABLED
) &&
419 PtInRect( &wndPtr
->rectWindow
, pt
)) return hwnd
;
421 return wndPtr
->hwndParent
;
425 /*******************************************************************
426 * WINPOS_GetMinMaxInfo
428 * Send a WM_GETMINMAXINFO to the window.
430 void WINPOS_GetMinMaxInfo( HWND hwnd
, POINT
*maxSize
, POINT
*maxPos
,
431 POINT
*minTrack
, POINT
*maxTrack
)
434 MINMAXINFO MinMax
, *pMinMax
;
435 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
437 MinMax
.ptMaxSize
.x
= SYSMETRICS_CXSCREEN
;
438 MinMax
.ptMaxSize
.y
= SYSMETRICS_CYSCREEN
;
439 MinMax
.ptMaxPosition
= wndPtr
->ptMaxPos
;
440 MinMax
.ptMinTrackSize
.x
= SYSMETRICS_CXMINTRACK
;
441 MinMax
.ptMinTrackSize
.y
= SYSMETRICS_CYMINTRACK
;
442 MinMax
.ptMaxTrackSize
.x
= SYSMETRICS_CXSCREEN
;
443 MinMax
.ptMaxTrackSize
.y
= SYSMETRICS_CYSCREEN
;
445 minmaxHandle
= USER_HEAP_ALLOC( LMEM_MOVEABLE
, sizeof(MINMAXINFO
) );
448 pMinMax
= (MINMAXINFO
*) USER_HEAP_ADDR( minmaxHandle
);
449 memcpy( pMinMax
, &MinMax
, sizeof(MinMax
) );
450 SendMessage( hwnd
, WM_GETMINMAXINFO
, 0, (LONG
)pMinMax
);
452 else pMinMax
= &MinMax
;
454 /* Some sanity checks */
456 pMinMax
->ptMaxTrackSize
.x
= max( pMinMax
->ptMaxTrackSize
.x
,
457 pMinMax
->ptMinTrackSize
.x
);
458 pMinMax
->ptMaxTrackSize
.y
= max( pMinMax
->ptMaxTrackSize
.y
,
459 pMinMax
->ptMinTrackSize
.y
);
461 if (maxSize
) *maxSize
= pMinMax
->ptMaxSize
;
462 if (maxPos
) *maxPos
= pMinMax
->ptMaxPosition
;
463 if (minTrack
) *minTrack
= pMinMax
->ptMinTrackSize
;
464 if (maxTrack
) *maxTrack
= pMinMax
->ptMaxTrackSize
;
465 if (minmaxHandle
) USER_HEAP_FREE( minmaxHandle
);
469 /*******************************************************************
470 * WINPOS_ChangeActiveWindow
472 * Change the active window and send the corresponding messages.
474 HWND
WINPOS_ChangeActiveWindow( HWND hwnd
, BOOL mouseMsg
)
476 HWND prevActive
= hwndActive
;
477 if (hwnd
== hwndActive
) return 0;
480 if (!SendMessage( hwndActive
, WM_NCACTIVATE
, FALSE
, 0 )) return 0;
481 SendMessage( hwndActive
, WM_ACTIVATE
, WA_INACTIVE
,
482 MAKELONG( IsIconic(hwndActive
), hwnd
) );
483 /* Send WM_ACTIVATEAPP here */
489 WND
*wndPtr
= WIN_FindWndPtr( hwndActive
);
490 wndPtr
->hwndPrevActive
= prevActive
;
492 /* Send WM_ACTIVATEAPP here */
493 SendMessage( hwnd
, WM_NCACTIVATE
, TRUE
, 0 );
494 SendMessage( hwnd
, WM_ACTIVATE
, mouseMsg
? WA_CLICKACTIVE
: WA_ACTIVE
,
495 MAKELONG( IsIconic(hwnd
), prevActive
) );
501 /***********************************************************************
502 * WINPOS_SendNCCalcSize
504 * Send a WM_NCCALCSIZE message to a window.
505 * All parameters are read-only except newClientRect.
506 * oldWindowRect, oldClientRect and winpos must be non-NULL only
507 * when calcValidRect is TRUE.
509 LONG
WINPOS_SendNCCalcSize( HWND hwnd
, BOOL calcValidRect
, RECT
*newWindowRect
,
510 RECT
*oldWindowRect
, RECT
*oldClientRect
,
511 WINDOWPOS
*winpos
, RECT
*newClientRect
)
513 NCCALCSIZE_PARAMS
*params
;
517 if (!(hparams
= USER_HEAP_ALLOC( GMEM_MOVEABLE
, sizeof(*params
) )))
519 params
= (NCCALCSIZE_PARAMS
*) USER_HEAP_ADDR( hparams
);
520 params
->rgrc
[0] = *newWindowRect
;
523 params
->rgrc
[1] = *oldWindowRect
;
524 params
->rgrc
[2] = *oldClientRect
;
525 params
->lppos
= winpos
;
527 result
= SendMessage( hwnd
, WM_NCCALCSIZE
, calcValidRect
, (LONG
)params
);
528 *newClientRect
= params
->rgrc
[0];
529 USER_HEAP_FREE( hparams
);
534 /***********************************************************************
535 * WINPOS_HandleWindowPosChanging
537 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
539 LONG
WINPOS_HandleWindowPosChanging( WINDOWPOS
*winpos
)
542 WND
*wndPtr
= WIN_FindWndPtr( winpos
->hwnd
);
543 if (!wndPtr
|| (winpos
->flags
& SWP_NOSIZE
)) return 0;
544 if ((wndPtr
->dwStyle
& WS_THICKFRAME
) ||
545 (wndPtr
->dwStyle
& (WS_POPUP
| WS_CHILD
) == 0))
547 WINPOS_GetMinMaxInfo( winpos
->hwnd
, &maxSize
, NULL
, NULL
, NULL
);
548 winpos
->cx
= min( winpos
->cx
, maxSize
.x
);
549 winpos
->cy
= min( winpos
->cy
, maxSize
.y
);
555 /***********************************************************************
556 * WINPOS_MoveWindowZOrder
558 * Move a window in Z order, invalidating everything that needs it.
559 * Only necessary for windows without associated X window.
561 static void WINPOS_MoveWindowZOrder( HWND hwnd
, HWND hwndAfter
, BOOL erase
)
565 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
567 /* We have two possible cases:
568 * - The window is moving up: we have to invalidate all areas
569 * of the window that were covered by other windows
570 * - The window is moving down: we have to invalidate areas
571 * of other windows covered by this one.
574 if (hwndAfter
== HWND_TOP
)
578 else if (hwndAfter
== HWND_BOTTOM
)
580 if (!wndPtr
->hwndNext
) return; /* Already at the bottom */
585 if (wndPtr
->hwndNext
== hwndAfter
) return; /* Already placed right */
587 /* Determine which window we encounter first in Z-order */
588 hwndCur
= GetWindow( wndPtr
->hwndParent
, GW_CHILD
);
589 while ((hwndCur
!= hwnd
) && (hwndCur
!= hwndAfter
))
590 hwndCur
= GetWindow( hwndCur
, GW_HWNDNEXT
);
591 movingUp
= (hwndCur
== hwndAfter
);
596 HWND hwndPrevAfter
= wndPtr
->hwndNext
;
597 WIN_UnlinkWindow( hwnd
);
598 WIN_LinkWindow( hwnd
, hwndAfter
);
599 hwndCur
= wndPtr
->hwndNext
;
600 while (hwndCur
!= hwndPrevAfter
)
602 WND
*curPtr
= WIN_FindWndPtr( hwndCur
);
603 RECT rect
= curPtr
->rectWindow
;
604 OffsetRect( &rect
, -wndPtr
->rectClient
.left
,
605 -wndPtr
->rectClient
.top
);
606 RedrawWindow( hwnd
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
|
607 RDW_FRAME
| (erase
? RDW_ERASENOW
: RDW_ERASE
) );
608 hwndCur
= curPtr
->hwndNext
;
611 else /* Moving down */
613 hwndCur
= wndPtr
->hwndNext
;
614 WIN_UnlinkWindow( hwnd
);
615 WIN_LinkWindow( hwnd
, hwndAfter
);
616 while (hwndCur
!= hwnd
)
618 WND
*curPtr
= WIN_FindWndPtr( hwndCur
);
619 RECT rect
= wndPtr
->rectWindow
;
620 OffsetRect( &rect
, -curPtr
->rectClient
.left
,
621 -curPtr
->rectClient
.top
);
622 RedrawWindow( hwndCur
, &rect
, 0, RDW_INVALIDATE
| RDW_ALLCHILDREN
|
623 RDW_FRAME
| (erase
? RDW_ERASENOW
: RDW_ERASE
) );
624 hwndCur
= curPtr
->hwndNext
;
630 /***********************************************************************
631 * WINPOS_InternalSetWindowPos
633 * Helper function for SetWindowPos.
635 static BOOL
WINPOS_InternalSetWindowPos( WINDOWPOS
*winpos
)
639 RECT newWindowRect
, newClientRect
;
642 XWindowChanges winChanges
;
644 /* Send WM_WINDOWPOSCHANGING message */
646 if (!(winpos
->flags
& SWP_NOSENDCHANGING
))
647 SendMessage( winpos
->hwnd
, WM_WINDOWPOSCHANGING
, 0, (LONG
)winpos
);
649 /* Check window handle */
651 if (winpos
->hwnd
== GetDesktopWindow()) return FALSE
;
652 if (!(wndPtr
= WIN_FindWndPtr( winpos
->hwnd
))) return FALSE
;
654 /* Check dimensions */
656 if (winpos
->cx
<= 0) winpos
->cx
= 1;
657 if (winpos
->cy
<= 0) winpos
->cy
= 1;
661 flags
= winpos
->flags
;
662 if (winpos
->hwnd
== hwndActive
) flags
|= SWP_NOACTIVATE
; /*Already active*/
664 /* Check hwndAfter */
666 hwndAfter
= winpos
->hwndInsertAfter
;
667 if (!(flags
& (SWP_NOZORDER
| SWP_NOACTIVATE
)))
669 /* Ignore TOPMOST flags when activating a window */
670 /* _and_ moving it in Z order. */
671 if ((hwndAfter
== HWND_TOPMOST
) || (hwndAfter
== HWND_NOTOPMOST
))
672 hwndAfter
= HWND_TOP
;
674 /* TOPMOST not supported yet */
675 if ((hwndAfter
== HWND_TOPMOST
) || (hwndAfter
== HWND_NOTOPMOST
))
676 hwndAfter
= HWND_TOP
;
677 /* hwndAfter must be a sibling of the window */
678 if ((hwndAfter
!= HWND_TOP
) && (hwndAfter
!= HWND_BOTTOM
) &&
679 (GetParent(winpos
->hwnd
) != GetParent(hwndAfter
))) return FALSE
;
681 /* Calculate new position and size */
683 newWindowRect
= wndPtr
->rectWindow
;
684 newClientRect
= wndPtr
->rectClient
;
686 if (!(flags
& SWP_NOSIZE
))
688 if ((newWindowRect
.right
!= newWindowRect
.left
+ winpos
->cx
) ||
689 (newWindowRect
.bottom
!= newWindowRect
.top
+ winpos
->cy
))
691 newWindowRect
.right
= newWindowRect
.left
+ winpos
->cx
;
692 newWindowRect
.bottom
= newWindowRect
.top
+ winpos
->cy
;
693 winChanges
.width
= winpos
->cx
;
694 winChanges
.height
= winpos
->cy
;
695 changeMask
|= CWWidth
| CWHeight
;
697 else flags
= winpos
->flags
|= SWP_NOSIZE
;
699 if (!(flags
& SWP_NOMOVE
))
701 if ((newWindowRect
.left
!= winpos
->x
) ||
702 (newWindowRect
.top
!= winpos
->y
))
704 newWindowRect
.left
= winpos
->x
;
705 newWindowRect
.top
= winpos
->y
;
706 newWindowRect
.right
+= winpos
->x
- wndPtr
->rectWindow
.left
;
707 newWindowRect
.bottom
+= winpos
->y
- wndPtr
->rectWindow
.top
;
708 if (wndPtr
->dwStyle
& WS_CHILD
)
710 WND
*parentPtr
= WIN_FindWndPtr(wndPtr
->hwndParent
);
711 winChanges
.x
= winpos
->x
+ parentPtr
->rectClient
.left
712 - parentPtr
->rectWindow
.left
;
713 winChanges
.y
= winpos
->y
+ parentPtr
->rectClient
.top
714 - parentPtr
->rectWindow
.top
;
718 winChanges
.x
= winpos
->x
;
719 winChanges
.y
= winpos
->y
;
721 changeMask
|= CWX
| CWY
;
723 else flags
= winpos
->flags
|= SWP_NOMOVE
;
726 /* Reposition window in Z order */
728 if (!(flags
& SWP_NOZORDER
))
732 WIN_UnlinkWindow( winpos
->hwnd
);
733 WIN_LinkWindow( winpos
->hwnd
, hwndAfter
);
734 if (hwndAfter
== HWND_TOP
) winChanges
.stack_mode
= Above
;
735 else winChanges
.stack_mode
= Below
;
736 if ((hwndAfter
!= HWND_TOP
) && (hwndAfter
!= HWND_BOTTOM
))
738 WND
* insertPtr
= WIN_FindWndPtr( hwndAfter
);
739 winChanges
.sibling
= insertPtr
->window
;
740 changeMask
|= CWSibling
;
742 changeMask
|= CWStackMode
;
744 else WINPOS_MoveWindowZOrder( winpos
->hwnd
, hwndAfter
,
745 !(flags
& SWP_DEFERERASE
) );
748 /* Send WM_NCCALCSIZE message to get new client area */
750 result
= WINPOS_SendNCCalcSize( winpos
->hwnd
, TRUE
, &newWindowRect
,
751 &wndPtr
->rectWindow
, &wndPtr
->rectClient
,
752 winpos
, &newClientRect
);
753 /* .... Should handle result here */
755 /* Perform the moving and resizing */
759 if (changeMask
) XConfigureWindow( display
, wndPtr
->window
,
760 changeMask
, &winChanges
);
761 wndPtr
->rectWindow
= newWindowRect
;
762 wndPtr
->rectClient
= newClientRect
;
766 RECT oldWindowRect
= wndPtr
->rectWindow
;
768 wndPtr
->rectWindow
= newWindowRect
;
769 wndPtr
->rectClient
= newClientRect
;
773 HRGN hrgn1
= CreateRectRgnIndirect( &oldWindowRect
);
774 HRGN hrgn2
= CreateRectRgnIndirect( &wndPtr
->rectWindow
);
775 HRGN hrgn3
= CreateRectRgn( 0, 0, 0, 0 );
776 CombineRgn( hrgn3
, hrgn1
, hrgn2
, RGN_DIFF
);
777 RedrawWindow( wndPtr
->hwndParent
, NULL
, hrgn3
,
778 RDW_INVALIDATE
| RDW_ALLCHILDREN
| RDW_ERASENOW
);
779 if ((oldWindowRect
.left
!= wndPtr
->rectWindow
.left
) ||
780 (oldWindowRect
.top
!= wndPtr
->rectWindow
.top
))
782 RedrawWindow( winpos
->hwnd
, NULL
, 0, RDW_INVALIDATE
|
783 RDW_FRAME
| RDW_ALLCHILDREN
| RDW_ERASENOW
);
785 DeleteObject( hrgn1
);
786 DeleteObject( hrgn2
);
787 DeleteObject( hrgn3
);
791 if (flags
& SWP_SHOWWINDOW
)
793 wndPtr
->dwStyle
|= WS_VISIBLE
;
796 XMapWindow( display
, wndPtr
->window
);
798 if (flags
& SWP_NOREDRAW
) /* Validate the whole window */
799 RedrawWindow( winpos
->hwnd
, NULL
, 0, RDW_VALIDATE
);
802 else if (flags
& SWP_HIDEWINDOW
)
804 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
807 XUnmapWindow( display
, wndPtr
->window
);
811 RedrawWindow( wndPtr
->hwndParent
, &wndPtr
->rectWindow
, 0,
812 RDW_INVALIDATE
| RDW_FRAME
|
813 RDW_ALLCHILDREN
| RDW_ERASENOW
);
815 if ((winpos
->hwnd
== GetFocus()) || IsChild(winpos
->hwnd
, GetFocus()))
816 SetFocus( GetParent(winpos
->hwnd
) ); /* Revert focus to parent */
817 if (winpos
->hwnd
== hwndActive
)
819 /* Activate previously active window if possible */
820 HWND newActive
= wndPtr
->hwndPrevActive
;
821 if (!IsWindow(newActive
) || (newActive
== winpos
->hwnd
))
823 newActive
= GetTopWindow(GetDesktopWindow());
824 if (newActive
== winpos
->hwnd
) newActive
= wndPtr
->hwndNext
;
826 WINPOS_ChangeActiveWindow( newActive
, FALSE
);
830 /* Activate the window */
832 if (!(flags
& SWP_NOACTIVATE
))
834 if (!(wndPtr
->dwStyle
& WS_CHILD
))
835 WINPOS_ChangeActiveWindow( winpos
->hwnd
, FALSE
);
838 /* Send WM_NCPAINT message if needed */
840 if (flags
& SWP_SHOWWINDOW
)
842 /* Repaint the window frame and background */
843 RedrawWindow( winpos
->hwnd
, NULL
, 0,
844 RDW_INVALIDATE
| RDW_FRAME
| RDW_ERASENOW
);
848 if ((flags
& SWP_FRAMECHANGED
) ||
849 (!(flags
& SWP_NOSIZE
)) ||
850 (!(flags
& SWP_NOMOVE
)) ||
851 (!(flags
& SWP_NOACTIVATE
)) ||
852 (!(flags
& SWP_NOZORDER
)))
853 SendMessage( winpos
->hwnd
, WM_NCPAINT
, 1, 0L );
856 /* And last, send the WM_WINDOWPOSCHANGED message */
858 SendMessage( winpos
->hwnd
, WM_WINDOWPOSCHANGED
, 0, (LONG
)winpos
);
863 /***********************************************************************
864 * BeginDeferWindowPos (USER.259)
866 HDWP
BeginDeferWindowPos( INT count
)
871 if (count
<= 0) return 0;
872 handle
= USER_HEAP_ALLOC( GMEM_MOVEABLE
,
873 sizeof(DWP
) + (count
-1)*sizeof(WINDOWPOS
) );
874 if (!handle
) return 0;
875 pDWP
= (DWP
*) USER_HEAP_ADDR( handle
);
876 pDWP
->actualCount
= 0;
877 pDWP
->suggestedCount
= count
;
879 pDWP
->wMagic
= DWP_MAGIC
;
880 pDWP
->hwndParent
= 0;
885 /***********************************************************************
886 * DeferWindowPos (USER.260)
888 HDWP
DeferWindowPos( HDWP hdwp
, HWND hwnd
, HWND hwndAfter
, INT x
, INT y
,
889 INT cx
, INT cy
, WORD flags
)
895 pDWP
= (DWP
*) USER_HEAP_ADDR( hdwp
);
898 /* All the windows of a DeferWindowPos() must have the same parent */
900 if (pDWP
->actualCount
== 0) pDWP
->hwndParent
= GetParent( hwnd
);
901 else if (GetParent( hwnd
) != pDWP
->hwndParent
)
903 USER_HEAP_FREE( hdwp
);
907 for (i
= 0; i
< pDWP
->actualCount
; i
++)
909 if (pDWP
->winPos
[i
].hwnd
== hwnd
)
911 /* Merge with the other changes */
912 if (!(flags
& SWP_NOZORDER
))
914 pDWP
->winPos
[i
].hwndInsertAfter
= hwndAfter
;
916 if (!(flags
& SWP_NOMOVE
))
918 pDWP
->winPos
[i
].x
= x
;
919 pDWP
->winPos
[i
].y
= y
;
921 if (!(flags
& SWP_NOSIZE
))
923 pDWP
->winPos
[i
].cx
= cx
;
924 pDWP
->winPos
[i
].cy
= cy
;
926 pDWP
->winPos
[i
].flags
&= flags
& (SWP_NOSIZE
| SWP_NOMOVE
|
927 SWP_NOZORDER
| SWP_NOREDRAW
|
928 SWP_NOACTIVATE
| SWP_NOCOPYBITS
|
930 pDWP
->winPos
[i
].flags
|= flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
|
935 if (pDWP
->actualCount
>= pDWP
->suggestedCount
)
937 newhdwp
= USER_HEAP_REALLOC( hdwp
,
938 sizeof(DWP
) + pDWP
->suggestedCount
*sizeof(WINDOWPOS
), 0);
939 if (!newhdwp
) return 0;
940 pDWP
= (DWP
*) USER_HEAP_ADDR( newhdwp
);
941 pDWP
->suggestedCount
++;
943 pDWP
->winPos
[pDWP
->actualCount
].hwnd
= hwnd
;
944 pDWP
->winPos
[pDWP
->actualCount
].hwndInsertAfter
= hwndAfter
;
945 pDWP
->winPos
[pDWP
->actualCount
].x
= x
;
946 pDWP
->winPos
[pDWP
->actualCount
].y
= y
;
947 pDWP
->winPos
[pDWP
->actualCount
].cx
= cx
;
948 pDWP
->winPos
[pDWP
->actualCount
].cy
= cy
;
949 pDWP
->winPos
[pDWP
->actualCount
].flags
= flags
;
955 /***********************************************************************
956 * EndDeferWindowPos (USER.261)
958 BOOL
EndDeferWindowPos( HDWP hdwp
)
964 pDWP
= (DWP
*) USER_HEAP_ADDR( hdwp
);
965 if (!pDWP
) return FALSE
;
966 for (i
= 0; i
< pDWP
->actualCount
; i
++)
968 if (!(res
= WINPOS_InternalSetWindowPos( &pDWP
->winPos
[i
] ))) break;
970 USER_HEAP_FREE( hdwp
);
975 /***********************************************************************
976 * SetWindowPos (USER.232)
978 BOOL
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
, INT x
, INT y
,
979 INT cx
, INT cy
, WORD flags
)
983 dprintf_win(stddeb
, "SetWindowPos: %04X %d %d,%d %dx%d 0x%x\n",
984 hwnd
, hwndInsertAfter
, x
, y
, cx
, cy
, flags
);
985 if (!(hdwp
= BeginDeferWindowPos( 1 ))) return FALSE
;
986 if (!(hdwp
= DeferWindowPos( hdwp
, hwnd
, hwndInsertAfter
,
987 x
, y
, cx
, cy
, flags
))) return FALSE
;
988 return EndDeferWindowPos( hdwp
);
991 /***********************************************************************
992 * TileChildWindows (USER.199)
994 void TileChildWindows( HWND parent
, WORD action
)
996 printf("STUB TileChildWindows(%04X, %d)\n", parent
, action
);
999 /***********************************************************************
1000 * CascageChildWindows (USER.198)
1002 void CascadeChildWindows( HWND parent
, WORD action
)
1004 printf("STUB CascadeChildWindows(%04X, %d)\n", parent
, action
);
1007 /***********************************************************************
1008 * ArrangeIconicWindows (USER.170)
1010 WORD
ArrangeIconicWindows( HWND parent
)
1012 printf("STUB ArrangeIconicWindows(%04X)\n", parent
);