Release 940301
[wine/gsoc-2012-control.git] / windows / winpos.c
blobee37ecb2850d692923ed4fcb8ca0edab56477b5e
1 /*
2 * Window position related functions.
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include "sysmetrics.h"
10 #include "user.h"
11 #include "win.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 );
24 if (!wndPtr) return;
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;
40 if (wndPtr)
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 )
71 RECT rect;
72 HWND hwnd = GetTopWindow( GetDesktopWindow() );
73 while (hwnd)
75 GetWindowRect( hwnd, &rect );
76 if (PtInRect( &rect, pt )) return hwnd;
77 hwnd = GetWindow( hwnd, GW_HWNDNEXT );
79 return 0;
83 /*******************************************************************
84 * ChildWindowFromPoint (USER.191)
86 HWND ChildWindowFromPoint( HWND hwndParent, POINT pt )
88 RECT rect;
89 HWND hwnd;
91 GetWindowRect( hwndParent, &rect );
92 if (!PtInRect( &rect, pt )) return 0;
93 hwnd = GetTopWindow( hwndParent );
94 while (hwnd)
96 GetWindowRect( hwnd, &rect );
97 if (PtInRect( &rect, pt )) return hwnd;
98 hwnd = GetWindow( hwnd, GW_HWNDNEXT );
100 return 0;
104 /*******************************************************************
105 * MapWindowPoints (USER.258)
107 void MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, WORD count )
109 WND * wndPtr;
110 POINT * curpt;
111 POINT origin = { 0, 0 };
112 WORD i;
114 /* Translate source window origin to screen coords */
115 while(hwndFrom)
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 */
124 while(hwndTo)
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 /***********************************************************************
142 * IsIconic (USER.31)
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()
168 return hwndActive;
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 );
181 return prev;
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;
201 #ifdef DEBUG_WIN
202 printf( "MoveWindow: %d %d,%d %dx%d %d\n", hwnd, x, y, cx, cy, repaint );
203 #endif
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 );
214 BOOL wasVisible;
215 int swpflags = 0;
217 #ifdef DEBUG_WIN
218 printf("ShowWindow: hwnd=%d, cmd=%d\n", hwnd, cmd);
219 #endif
221 if (!wndPtr) return FALSE;
222 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
223 switch(cmd)
225 case SW_HIDE:
226 if (!wasVisible) return FALSE; /* Nothing to do */
227 swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
228 SWP_NOACTIVATE | SWP_NOZORDER;
229 break;
231 case SW_SHOWMINNOACTIVE:
232 case SW_SHOWMINIMIZED:
233 case SW_SHOWMAXIMIZED:
234 case SW_MINIMIZE:
235 wndPtr->dwStyle |= WS_MINIMIZE;
236 swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE |
237 SWP_NOACTIVATE | SWP_NOZORDER;
238 break;
240 case SW_SHOWNA:
241 case SW_MAXIMIZE:
242 case SW_SHOW:
243 swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
244 break;
246 case SW_NORMAL:
247 case SW_SHOWNORMAL:
248 case SW_SHOWNOACTIVATE:
249 case SW_RESTORE:
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;
258 break;
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) );
276 return wasVisible;
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);
320 wndpl->flags = 0;
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;
326 return TRUE;
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 );
345 return TRUE;
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 )
357 HANDLE minmaxHandle;
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) );
370 if (minmaxHandle)
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;
402 if (hwndActive)
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 */
410 hwndActive = hwnd;
411 if (hwndActive)
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 ) );
418 return 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
429 * some day...
431 BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, short x, short y,
432 short cx, short cy, WORD flags )
434 WINDOWPOS *winPos;
435 HANDLE hmem = 0;
436 RECT newWindowRect, newClientRect;
437 WND *wndPtr;
438 int calcsize_result = 0;
439 XWindowChanges winChanges;
440 int changeMask = 0;
442 #ifdef DEBUG_WIN
443 printf( "SetWindowPos: %d %d %d,%d %dx%d 0x%x\n",
444 hwnd, hwndInsertAfter, x, y, cx, cy, flags );
445 #endif
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) )))
454 return FALSE;
455 winPos = (WINDOWPOS *)USER_HEAP_ADDR( hmem );
456 winPos->hwnd = hwnd;
457 winPos->hwndInsertAfter = hwndInsertAfter;
458 winPos->x = x;
459 winPos->y = y;
460 winPos->cx = cx;
461 winPos->cy = cy;
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;
508 HANDLE hparams;
510 if (!(hparams = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(*params) )))
511 goto Abort;
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 */
522 else
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))
538 WND * parentPtr;
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 );
601 return TRUE;
603 Abort: /* Fatal error encountered */
604 if (hmem) USER_HEAP_FREE( hmem );
605 return FALSE;