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->hwndParent)
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 = firstWindow;
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->hwndParent;
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->hwndParent;
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 if (maxSize) *maxSize = pMinMax->ptMaxSize;
379 if (maxPos) *maxPos = pMinMax->ptMaxPosition;
380 if (minTrack) *minTrack = pMinMax->ptMinTrackSize;
381 if (maxTrack) *maxTrack = pMinMax->ptMaxTrackSize;
382 if (minmaxHandle) USER_HEAP_FREE( minmaxHandle );
386 /*******************************************************************
387 * WINPOS_ChangeActiveWindow
389 * Change the active window and send the corresponding messages.
391 HWND WINPOS_ChangeActiveWindow( HWND hwnd, BOOL mouseMsg )
393 HWND prevActive = hwndActive;
394 if (hwnd == hwndActive) return 0;
397 if (!SendMessage( hwndActive, WM_NCACTIVATE, FALSE, 0 )) return 0;
398 SendMessage( hwndActive, WM_ACTIVATE, WA_INACTIVE,
399 MAKELONG( IsIconic(hwndActive), hwnd ) );
400 /* Send WM_ACTIVATEAPP here */
406 /* Send WM_ACTIVATEAPP here */
407 SendMessage( hwnd, WM_NCACTIVATE, TRUE, 0 );
408 SendMessage( hwnd, WM_ACTIVATE, mouseMsg ? WA_CLICKACTIVE : WA_ACTIVE,
409 MAKELONG( IsIconic(hwnd), prevActive ) );
415 /***********************************************************************
416 * SetWindowPos (USER.232)
418 /* Unimplemented flags: SWP_NOREDRAW
420 /* Note: all this code should be in the DeferWindowPos() routines,
421 * and SetWindowPos() should simply call them. This will be implemented
424 BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, short x, short y,
425 short cx, short cy, WORD flags )
429 RECT newWindowRect, newClientRect;
431 int calcsize_result = 0;
432 XWindowChanges winChanges;
436 printf( "SetWindowPos: %d %d %d,%d %dx%d 0x%x\n",
437 hwnd, hwndInsertAfter, x, y, cx, cy, flags );
440 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
441 if (flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW))
442 flags |= SWP_NOMOVE | SWP_NOSIZE;
444 /* Send WM_WINDOWPOSCHANGING message */
446 if (!(hmem = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(WINDOWPOS) )))
448 winPos = (WINDOWPOS *)USER_HEAP_ADDR( hmem );
450 winPos->hwndInsertAfter = hwndInsertAfter;
455 winPos->flags = flags;
456 SendMessage( hwnd, WM_WINDOWPOSCHANGING, 0, (LONG)winPos );
458 /* Calculate new position and size */
460 newWindowRect = wndPtr->rectWindow;
461 newClientRect = wndPtr->rectClient;
463 if (!(winPos->flags & SWP_NOSIZE))
465 newWindowRect.right = newWindowRect.left + winPos->cx;
466 newWindowRect.bottom = newWindowRect.top + winPos->cy;
469 if (!(winPos->flags & SWP_NOMOVE))
471 newWindowRect.left = winPos->x;
472 newWindowRect.top = winPos->y;
473 newWindowRect.right += winPos->x - wndPtr->rectWindow.left;
474 newWindowRect.bottom += winPos->y - wndPtr->rectWindow.top;
477 /* Reposition window in Z order */
479 if (!(winPos->flags & SWP_NOZORDER))
481 hwndInsertAfter = winPos->hwndInsertAfter;
483 /* TOPMOST not supported yet */
484 if ((hwndInsertAfter == HWND_TOPMOST) ||
485 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
487 /* Make sure hwndInsertAfter is a sibling of hwnd */
488 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
489 if (wndPtr->hwndParent != GetParent(hwndInsertAfter)) goto Abort;
491 WIN_UnlinkWindow( hwnd );
492 WIN_LinkWindow( hwnd, hwndInsertAfter );
495 /* Recalculate client area position */
497 if (winPos->flags & SWP_FRAMECHANGED)
499 /* Send WM_NCCALCSIZE message */
500 NCCALCSIZE_PARAMS *params;
503 if (!(hparams = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(*params) )))
505 params = (NCCALCSIZE_PARAMS *) USER_HEAP_ADDR( hparams );
506 params->rgrc[0] = newWindowRect;
507 params->rgrc[1] = wndPtr->rectWindow;
508 params->rgrc[2] = wndPtr->rectClient;
509 params->lppos = winPos;
510 calcsize_result = SendMessage(hwnd, WM_NCCALCSIZE, TRUE, (LONG)params);
511 USER_HEAP_FREE( hparams );
512 newClientRect = params->rgrc[0];
513 /* Handle result here */
517 newClientRect.left = newWindowRect.left + wndPtr->rectClient.left
518 - wndPtr->rectWindow.left;
519 newClientRect.top = newWindowRect.top + wndPtr->rectClient.top
520 - wndPtr->rectWindow.top;
521 newClientRect.right = newWindowRect.right + wndPtr->rectClient.right
522 - wndPtr->rectWindow.right;
523 newClientRect.bottom = newWindowRect.bottom + wndPtr->rectClient.bottom
524 - wndPtr->rectWindow.bottom;
527 /* Perform the moving and resizing */
529 if (!(winPos->flags & SWP_NOMOVE))
532 winChanges.x = newWindowRect.left;
533 winChanges.y = newWindowRect.top;
534 if (wndPtr->hwndParent)
536 parentPtr = WIN_FindWndPtr(wndPtr->hwndParent);
537 winChanges.x += parentPtr->rectClient.left-parentPtr->rectWindow.left;
538 winChanges.y += parentPtr->rectClient.top-parentPtr->rectWindow.top;
540 changeMask |= CWX | CWY;
542 if (!(winPos->flags & SWP_NOSIZE))
544 winChanges.width = newWindowRect.right - newWindowRect.left;
545 winChanges.height = newWindowRect.bottom - newWindowRect.top;
546 changeMask |= CWWidth | CWHeight;
548 if (!(winPos->flags & SWP_NOZORDER))
550 if (hwndInsertAfter == HWND_TOP) winChanges.stack_mode = Above;
551 else winChanges.stack_mode = Below;
552 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
554 WND * insertPtr = WIN_FindWndPtr( hwndInsertAfter );
555 winChanges.sibling = insertPtr->window;
556 changeMask |= CWSibling;
558 changeMask |= CWStackMode;
560 if (changeMask) XConfigureWindow( display, wndPtr->window,
561 changeMask, &winChanges );
563 if (winPos->flags & SWP_SHOWWINDOW)
565 wndPtr->dwStyle |= WS_VISIBLE;
566 XMapWindow( display, wndPtr->window );
568 else if (winPos->flags & SWP_HIDEWINDOW)
570 wndPtr->dwStyle &= ~WS_VISIBLE;
571 XUnmapWindow( display, wndPtr->window );
574 if (!(winPos->flags & SWP_NOACTIVATE))
576 if (!(wndPtr->dwStyle & WS_CHILD))
577 WINPOS_ChangeActiveWindow( hwnd, FALSE );
580 /* Send WM_NCPAINT message if needed */
581 if ((winPos->flags & (SWP_FRAMECHANGED | SWP_SHOWWINDOW)) ||
582 (!(winPos->flags & SWP_NOSIZE)) ||
583 (!(winPos->flags & SWP_NOMOVE)) ||
584 (!(winPos->flags & SWP_NOACTIVATE)) ||
585 (!(winPos->flags & SWP_NOZORDER)))
586 SendMessage( hwnd, WM_NCPAINT, 1, 0L );
588 /* Finally send the WM_WINDOWPOSCHANGED message */
589 wndPtr->rectWindow = newWindowRect;
590 wndPtr->rectClient = newClientRect;
591 SendMessage( hwnd, WM_WINDOWPOSCHANGED, 0, (LONG)winPos );
592 USER_HEAP_FREE( hmem );
596 Abort: /* Fatal error encountered */
597 if (hmem) USER_HEAP_FREE( hmem );