2 * Window position related functions.
4 * Copyright 1993 Alexandre Julliard
7 static char Copyright
[] = "Copyright Alexandre Julliard, 1993";
9 #include "sysmetrics.h"
13 extern Display
* display
;
15 static HWND hwndActive
= 0; /* Currently active window */
18 /***********************************************************************
19 * GetWindowRect (USER.32)
21 void GetWindowRect( HWND hwnd
, LPRECT rect
)
23 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
26 *rect
= wndPtr
->rectWindow
;
27 if (wndPtr
->dwStyle
& WS_CHILD
)
28 MapWindowPoints( wndPtr
->hwndParent
, 0, (POINT
*)rect
, 2 );
32 /***********************************************************************
33 * GetClientRect (USER.33)
35 void GetClientRect( HWND hwnd
, LPRECT rect
)
37 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
39 rect
->left
= rect
->top
= rect
->right
= rect
->bottom
= 0;
42 rect
->right
= wndPtr
->rectClient
.right
- wndPtr
->rectClient
.left
;
43 rect
->bottom
= wndPtr
->rectClient
.bottom
- wndPtr
->rectClient
.top
;
48 /*******************************************************************
49 * ClientToScreen (USER.28)
51 void ClientToScreen( HWND hwnd
, LPPOINT lppnt
)
53 MapWindowPoints( hwnd
, 0, lppnt
, 1 );
57 /*******************************************************************
58 * ScreenToClient (USER.29)
60 void ScreenToClient( HWND hwnd
, LPPOINT lppnt
)
62 MapWindowPoints( 0, hwnd
, lppnt
, 1 );
66 /*******************************************************************
67 * WindowFromPoint (USER.30)
69 HWND
WindowFromPoint( POINT pt
)
72 HWND hwnd
= GetTopWindow( GetDesktopWindow() );
75 GetWindowRect( hwnd
, &rect
);
76 if (PtInRect( &rect
, pt
)) return hwnd
;
77 hwnd
= GetWindow( hwnd
, GW_HWNDNEXT
);
83 /*******************************************************************
84 * ChildWindowFromPoint (USER.191)
86 HWND
ChildWindowFromPoint( HWND hwndParent
, POINT pt
)
91 GetWindowRect( hwndParent
, &rect
);
92 if (!PtInRect( &rect
, pt
)) return 0;
93 hwnd
= GetTopWindow( hwndParent
);
96 GetWindowRect( hwnd
, &rect
);
97 if (PtInRect( &rect
, pt
)) return hwnd
;
98 hwnd
= GetWindow( hwnd
, GW_HWNDNEXT
);
104 /*******************************************************************
105 * MapWindowPoints (USER.258)
107 void MapWindowPoints( HWND hwndFrom
, HWND hwndTo
, LPPOINT lppt
, WORD count
)
111 POINT origin
= { 0, 0 };
114 /* Translate source window origin to screen coords */
117 wndPtr
= WIN_FindWndPtr( hwndFrom
);
118 origin
.x
+= wndPtr
->rectClient
.left
;
119 origin
.y
+= wndPtr
->rectClient
.top
;
120 hwndFrom
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->hwndParent
: 0;
123 /* Translate origin to destination window coords */
126 wndPtr
= WIN_FindWndPtr( hwndTo
);
127 origin
.x
-= wndPtr
->rectClient
.left
;
128 origin
.y
-= wndPtr
->rectClient
.top
;
129 hwndTo
= (wndPtr
->dwStyle
& WS_CHILD
) ? wndPtr
->hwndParent
: 0;
132 /* Translate points */
133 for (i
= 0, curpt
= lppt
; i
< count
; i
++, curpt
++)
135 curpt
->x
+= origin
.x
;
136 curpt
->y
+= origin
.y
;
141 /***********************************************************************
144 BOOL
IsIconic(HWND hWnd
)
146 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
147 if (wndPtr
== NULL
) return FALSE
;
148 return (wndPtr
->dwStyle
& WS_MINIMIZE
) != 0;
152 /***********************************************************************
153 * IsZoomed (USER.272)
155 BOOL
IsZoomed(HWND hWnd
)
157 WND
* wndPtr
= WIN_FindWndPtr(hWnd
);
158 if (wndPtr
== NULL
) return FALSE
;
159 return (wndPtr
->dwStyle
& WS_MAXIMIZE
) != 0;
163 /*******************************************************************
164 * GetActiveWindow (USER.60)
166 HWND
GetActiveWindow()
172 /*******************************************************************
173 * SetActiveWindow (USER.59)
175 HWND
SetActiveWindow( HWND hwnd
)
177 HWND prev
= hwndActive
;
178 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
179 if (!wndPtr
|| (wndPtr
->dwStyle
& WS_CHILD
)) return 0;
180 SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
185 /***********************************************************************
186 * BringWindowToTop (USER.45)
188 BOOL
BringWindowToTop( HWND hwnd
)
190 return SetWindowPos( hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
194 /***********************************************************************
195 * MoveWindow (USER.56)
197 BOOL
MoveWindow( HWND hwnd
, short x
, short y
, short cx
, short cy
, BOOL repaint
)
199 int flags
= SWP_NOZORDER
| SWP_NOACTIVATE
;
200 if (!repaint
) flags
|= SWP_NOREDRAW
;
202 printf( "MoveWindow: %d %d,%d %dx%d %d\n", hwnd
, x
, y
, cx
, cy
, repaint
);
204 return SetWindowPos( hwnd
, 0, x
, y
, cx
, cy
, flags
);
208 /***********************************************************************
209 * ShowWindow (USER.42)
211 BOOL
ShowWindow( HWND hwnd
, int cmd
)
213 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
218 printf("ShowWindow: hwnd=%d, cmd=%d\n", hwnd
, cmd
);
221 if (!wndPtr
) return FALSE
;
222 wasVisible
= (wndPtr
->dwStyle
& WS_VISIBLE
) != 0;
226 if (!wasVisible
) return FALSE
; /* Nothing to do */
227 swpflags
|= SWP_HIDEWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
228 SWP_NOACTIVATE
| SWP_NOZORDER
;
231 case SW_SHOWMINNOACTIVE
:
232 case SW_SHOWMINIMIZED
:
233 case SW_SHOWMAXIMIZED
:
235 wndPtr
->dwStyle
|= WS_MINIMIZE
;
236 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
|
237 SWP_NOACTIVATE
| SWP_NOZORDER
;
243 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
248 case SW_SHOWNOACTIVATE
:
250 wndPtr
->dwStyle
&= ~WS_MINIMIZE
;
251 wndPtr
->dwStyle
&= ~WS_MAXIMIZE
;
252 swpflags
|= SWP_SHOWWINDOW
| SWP_NOSIZE
| SWP_NOMOVE
;
253 if (cmd
== SW_SHOWNOACTIVATE
)
255 swpflags
|= SWP_NOZORDER
;
256 if (GetActiveWindow()) swpflags
|= SWP_NOACTIVATE
;
260 SendMessage( hwnd
, WM_SHOWWINDOW
, (cmd
!= SW_HIDE
), 0 );
261 SetWindowPos( hwnd
, 0, 0, 0, 0, 0, swpflags
);
263 /* Send WM_SIZE and WM_MOVE messages if not already done */
264 if (!(wndPtr
->flags
& WIN_GOT_SIZEMSG
))
266 int wParam
= SIZE_RESTORED
;
267 if (wndPtr
->dwStyle
& WS_MAXIMIZE
) wParam
= SIZE_MAXIMIZED
;
268 else if (wndPtr
->dwStyle
& WS_MINIMIZE
) wParam
= SIZE_MINIMIZED
;
269 wndPtr
->flags
|= WIN_GOT_SIZEMSG
;
270 SendMessage( hwnd
, WM_SIZE
, wParam
,
271 MAKELONG(wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
272 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
));
273 SendMessage( hwnd
, WM_MOVE
, 0,
274 MAKELONG(wndPtr
->rectClient
.left
, wndPtr
->rectClient
.top
) );
280 /***********************************************************************
281 * GetInternalWindowPos (USER.460)
283 WORD
GetInternalWindowPos( HWND hwnd
, LPRECT rectWnd
, LPPOINT ptIcon
)
285 WINDOWPLACEMENT wndpl
;
286 if (!GetWindowPlacement( hwnd
, &wndpl
)) return 0;
287 if (rectWnd
) *rectWnd
= wndpl
.rcNormalPosition
;
288 if (ptIcon
) *ptIcon
= wndpl
.ptMinPosition
;
289 return wndpl
.showCmd
;
293 /***********************************************************************
294 * SetInternalWindowPos (USER.461)
296 void SetInternalWindowPos( HWND hwnd
, WORD showCmd
, LPRECT rect
, LPPOINT pt
)
298 WINDOWPLACEMENT wndpl
;
299 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
301 wndpl
.length
= sizeof(wndpl
);
302 wndpl
.flags
= (pt
!= NULL
) ? WPF_SETMINPOSITION
: 0;
303 wndpl
.showCmd
= showCmd
;
304 if (pt
) wndpl
.ptMinPosition
= *pt
;
305 wndpl
.rcNormalPosition
= (rect
!= NULL
) ? *rect
: wndPtr
->rectNormal
;
306 wndpl
.ptMaxPosition
= wndPtr
->ptMaxPos
;
307 SetWindowPlacement( hwnd
, &wndpl
);
311 /***********************************************************************
312 * GetWindowPlacement (USER.370)
314 BOOL
GetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
316 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
317 if (!wndPtr
) return FALSE
;
319 wndpl
->length
= sizeof(*wndpl
);
321 wndpl
->showCmd
= IsZoomed(hwnd
) ? SW_SHOWMAXIMIZED
:
322 (IsIconic(hwnd
) ? SW_SHOWMINIMIZED
: SW_SHOWNORMAL
);
323 wndpl
->ptMinPosition
= wndPtr
->ptIconPos
;
324 wndpl
->ptMaxPosition
= wndPtr
->ptMaxPos
;
325 wndpl
->rcNormalPosition
= wndPtr
->rectNormal
;
330 /***********************************************************************
331 * SetWindowPlacement (USER.371)
333 BOOL
SetWindowPlacement( HWND hwnd
, WINDOWPLACEMENT
*wndpl
)
335 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
336 if (!wndPtr
) return FALSE
;
338 if (wndpl
->flags
& WPF_SETMINPOSITION
)
339 wndPtr
->ptIconPos
= wndpl
->ptMinPosition
;
340 if ((wndpl
->flags
& WPF_RESTORETOMAXIMIZED
) &&
341 (wndpl
->showCmd
== SW_SHOWMINIMIZED
)) wndPtr
->flags
|= WIN_RESTORE_MAX
;
342 wndPtr
->ptMaxPos
= wndpl
->ptMaxPosition
;
343 wndPtr
->rectNormal
= wndpl
->rcNormalPosition
;
344 ShowWindow( hwnd
, wndpl
->showCmd
);
349 /*******************************************************************
350 * WINPOS_GetMinMaxInfo
352 * Send a WM_GETMINMAXINFO to the window.
354 void WINPOS_GetMinMaxInfo( HWND hwnd
, POINT
*maxSize
, POINT
*maxPos
,
355 POINT
*minTrack
, POINT
*maxTrack
)
358 MINMAXINFO MinMax
, *pMinMax
;
359 WND
*wndPtr
= WIN_FindWndPtr( hwnd
);
361 MinMax
.ptMaxSize
.x
= SYSMETRICS_CXSCREEN
;
362 MinMax
.ptMaxSize
.y
= SYSMETRICS_CYSCREEN
;
363 MinMax
.ptMaxPosition
= wndPtr
->ptMaxPos
;
364 MinMax
.ptMinTrackSize
.x
= SYSMETRICS_CXMINTRACK
;
365 MinMax
.ptMinTrackSize
.y
= SYSMETRICS_CYMINTRACK
;
366 MinMax
.ptMaxTrackSize
.x
= SYSMETRICS_CXSCREEN
;
367 MinMax
.ptMaxTrackSize
.y
= SYSMETRICS_CYSCREEN
;
369 minmaxHandle
= USER_HEAP_ALLOC( LMEM_MOVEABLE
, sizeof(MINMAXINFO
) );
372 pMinMax
= (MINMAXINFO
*) USER_HEAP_ADDR( minmaxHandle
);
373 memcpy( pMinMax
, &MinMax
, sizeof(MinMax
) );
374 SendMessage( hwnd
, WM_GETMINMAXINFO
, 0, (LONG
)pMinMax
);
376 else pMinMax
= &MinMax
;
378 /* Some sanity checks */
380 pMinMax
->ptMaxTrackSize
.x
= max( pMinMax
->ptMaxTrackSize
.x
,
381 pMinMax
->ptMinTrackSize
.x
);
382 pMinMax
->ptMaxTrackSize
.y
= max( pMinMax
->ptMaxTrackSize
.y
,
383 pMinMax
->ptMinTrackSize
.y
);
385 if (maxSize
) *maxSize
= pMinMax
->ptMaxSize
;
386 if (maxPos
) *maxPos
= pMinMax
->ptMaxPosition
;
387 if (minTrack
) *minTrack
= pMinMax
->ptMinTrackSize
;
388 if (maxTrack
) *maxTrack
= pMinMax
->ptMaxTrackSize
;
389 if (minmaxHandle
) USER_HEAP_FREE( minmaxHandle
);
393 /*******************************************************************
394 * WINPOS_ChangeActiveWindow
396 * Change the active window and send the corresponding messages.
398 HWND
WINPOS_ChangeActiveWindow( HWND hwnd
, BOOL mouseMsg
)
400 HWND prevActive
= hwndActive
;
401 if (hwnd
== hwndActive
) return 0;
404 if (!SendMessage( hwndActive
, WM_NCACTIVATE
, FALSE
, 0 )) return 0;
405 SendMessage( hwndActive
, WM_ACTIVATE
, WA_INACTIVE
,
406 MAKELONG( IsIconic(hwndActive
), hwnd
) );
407 /* Send WM_ACTIVATEAPP here */
413 /* Send WM_ACTIVATEAPP here */
414 SendMessage( hwnd
, WM_NCACTIVATE
, TRUE
, 0 );
415 SendMessage( hwnd
, WM_ACTIVATE
, mouseMsg
? WA_CLICKACTIVE
: WA_ACTIVE
,
416 MAKELONG( IsIconic(hwnd
), prevActive
) );
422 /***********************************************************************
423 * SetWindowPos (USER.232)
425 /* Unimplemented flags: SWP_NOREDRAW
427 /* Note: all this code should be in the DeferWindowPos() routines,
428 * and SetWindowPos() should simply call them. This will be implemented
431 BOOL
SetWindowPos( HWND hwnd
, HWND hwndInsertAfter
, short x
, short y
,
432 short cx
, short cy
, WORD flags
)
436 RECT newWindowRect
, newClientRect
;
438 int calcsize_result
= 0;
439 XWindowChanges winChanges
;
443 printf( "SetWindowPos: %d %d %d,%d %dx%d 0x%x\n",
444 hwnd
, hwndInsertAfter
, x
, y
, cx
, cy
, flags
);
447 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
448 if (flags
& (SWP_SHOWWINDOW
| SWP_HIDEWINDOW
))
449 flags
|= SWP_NOMOVE
| SWP_NOSIZE
;
451 /* Send WM_WINDOWPOSCHANGING message */
453 if (!(hmem
= USER_HEAP_ALLOC( GMEM_MOVEABLE
, sizeof(WINDOWPOS
) )))
455 winPos
= (WINDOWPOS
*)USER_HEAP_ADDR( hmem
);
457 winPos
->hwndInsertAfter
= hwndInsertAfter
;
462 winPos
->flags
= flags
;
463 SendMessage( hwnd
, WM_WINDOWPOSCHANGING
, 0, (LONG
)winPos
);
465 /* Calculate new position and size */
467 newWindowRect
= wndPtr
->rectWindow
;
468 newClientRect
= wndPtr
->rectClient
;
470 if (!(winPos
->flags
& SWP_NOSIZE
))
472 newWindowRect
.right
= newWindowRect
.left
+ winPos
->cx
;
473 newWindowRect
.bottom
= newWindowRect
.top
+ winPos
->cy
;
476 if (!(winPos
->flags
& SWP_NOMOVE
))
478 newWindowRect
.left
= winPos
->x
;
479 newWindowRect
.top
= winPos
->y
;
480 newWindowRect
.right
+= winPos
->x
- wndPtr
->rectWindow
.left
;
481 newWindowRect
.bottom
+= winPos
->y
- wndPtr
->rectWindow
.top
;
484 /* Reposition window in Z order */
486 if (!(winPos
->flags
& SWP_NOZORDER
))
488 hwndInsertAfter
= winPos
->hwndInsertAfter
;
490 /* TOPMOST not supported yet */
491 if ((hwndInsertAfter
== HWND_TOPMOST
) ||
492 (hwndInsertAfter
== HWND_NOTOPMOST
)) hwndInsertAfter
= HWND_TOP
;
494 /* Make sure hwndInsertAfter is a sibling of hwnd */
495 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
496 if (GetParent(hwnd
) != GetParent(hwndInsertAfter
)) goto Abort
;
498 WIN_UnlinkWindow( hwnd
);
499 WIN_LinkWindow( hwnd
, hwndInsertAfter
);
502 /* Recalculate client area position */
504 if (winPos
->flags
& SWP_FRAMECHANGED
)
506 /* Send WM_NCCALCSIZE message */
507 NCCALCSIZE_PARAMS
*params
;
510 if (!(hparams
= USER_HEAP_ALLOC( GMEM_MOVEABLE
, sizeof(*params
) )))
512 params
= (NCCALCSIZE_PARAMS
*) USER_HEAP_ADDR( hparams
);
513 params
->rgrc
[0] = newWindowRect
;
514 params
->rgrc
[1] = wndPtr
->rectWindow
;
515 params
->rgrc
[2] = wndPtr
->rectClient
;
516 params
->lppos
= winPos
;
517 calcsize_result
= SendMessage(hwnd
, WM_NCCALCSIZE
, TRUE
, (LONG
)params
);
518 USER_HEAP_FREE( hparams
);
519 newClientRect
= params
->rgrc
[0];
520 /* Handle result here */
524 newClientRect
.left
= newWindowRect
.left
+ wndPtr
->rectClient
.left
525 - wndPtr
->rectWindow
.left
;
526 newClientRect
.top
= newWindowRect
.top
+ wndPtr
->rectClient
.top
527 - wndPtr
->rectWindow
.top
;
528 newClientRect
.right
= newWindowRect
.right
+ wndPtr
->rectClient
.right
529 - wndPtr
->rectWindow
.right
;
530 newClientRect
.bottom
= newWindowRect
.bottom
+ wndPtr
->rectClient
.bottom
531 - wndPtr
->rectWindow
.bottom
;
534 /* Perform the moving and resizing */
536 if (!(winPos
->flags
& SWP_NOMOVE
))
539 winChanges
.x
= newWindowRect
.left
;
540 winChanges
.y
= newWindowRect
.top
;
541 if (wndPtr
->dwStyle
& WS_CHILD
)
543 parentPtr
= WIN_FindWndPtr(wndPtr
->hwndParent
);
544 winChanges
.x
+= parentPtr
->rectClient
.left
-parentPtr
->rectWindow
.left
;
545 winChanges
.y
+= parentPtr
->rectClient
.top
-parentPtr
->rectWindow
.top
;
547 changeMask
|= CWX
| CWY
;
549 if (!(winPos
->flags
& SWP_NOSIZE
))
551 winChanges
.width
= newWindowRect
.right
- newWindowRect
.left
;
552 winChanges
.height
= newWindowRect
.bottom
- newWindowRect
.top
;
553 changeMask
|= CWWidth
| CWHeight
;
555 if (!(winPos
->flags
& SWP_NOZORDER
))
557 if (hwndInsertAfter
== HWND_TOP
) winChanges
.stack_mode
= Above
;
558 else winChanges
.stack_mode
= Below
;
559 if ((hwndInsertAfter
!= HWND_TOP
) && (hwndInsertAfter
!= HWND_BOTTOM
))
561 WND
* insertPtr
= WIN_FindWndPtr( hwndInsertAfter
);
562 winChanges
.sibling
= insertPtr
->window
;
563 changeMask
|= CWSibling
;
565 changeMask
|= CWStackMode
;
567 if (changeMask
) XConfigureWindow( display
, wndPtr
->window
,
568 changeMask
, &winChanges
);
570 if (winPos
->flags
& SWP_SHOWWINDOW
)
572 wndPtr
->dwStyle
|= WS_VISIBLE
;
573 XMapWindow( display
, wndPtr
->window
);
575 else if (winPos
->flags
& SWP_HIDEWINDOW
)
577 wndPtr
->dwStyle
&= ~WS_VISIBLE
;
578 XUnmapWindow( display
, wndPtr
->window
);
581 if (!(winPos
->flags
& SWP_NOACTIVATE
))
583 if (!(wndPtr
->dwStyle
& WS_CHILD
))
584 WINPOS_ChangeActiveWindow( hwnd
, FALSE
);
587 /* Send WM_NCPAINT message if needed */
588 if ((winPos
->flags
& (SWP_FRAMECHANGED
| SWP_SHOWWINDOW
)) ||
589 (!(winPos
->flags
& SWP_NOSIZE
)) ||
590 (!(winPos
->flags
& SWP_NOMOVE
)) ||
591 (!(winPos
->flags
& SWP_NOACTIVATE
)) ||
592 (!(winPos
->flags
& SWP_NOZORDER
)))
593 SendMessage( hwnd
, WM_NCPAINT
, 1, 0L );
595 /* Finally send the WM_WINDOWPOSCHANGED message */
596 wndPtr
->rectWindow
= newWindowRect
;
597 wndPtr
->rectClient
= newClientRect
;
598 SendMessage( hwnd
, WM_WINDOWPOSCHANGED
, 0, (LONG
)winPos
);
599 USER_HEAP_FREE( hmem
);
603 Abort
: /* Fatal error encountered */
604 if (hmem
) USER_HEAP_FREE( hmem
);