Release 950109
[wine.git] / windows / winpos.c
blob659211e63bac4c39e499db31dc7a1eee7e656397
1 /*
2 * Window position related functions.
4 * Copyright 1993, 1994 Alexandre Julliard
5 */
7 #include "sysmetrics.h"
8 #include "user.h"
9 #include "win.h"
10 #include "message.h"
11 #include "winpos.h"
12 #include "stddebug.h"
13 /* #define DEBUG_WIN */
14 /* #undef DEBUG_WIN */
15 #include "debug.h"
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 );
26 if (!wndPtr) return;
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;
42 if (wndPtr)
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 )
73 HWND hwndRet = 0;
74 HWND hwnd = GetDesktopWindow();
76 while(hwnd)
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))
91 hwndRet = hwnd;
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;
100 return hwndRet;
103 /*******************************************************************
104 * ChildWindowFromPoint (USER.191)
106 HWND ChildWindowFromPoint( HWND hwndParent, POINT pt )
108 RECT rect;
109 HWND hwnd;
111 GetWindowRect( hwndParent, &rect );
112 if (!PtInRect( &rect, pt )) return 0;
113 hwnd = GetTopWindow( hwndParent );
114 while (hwnd)
116 GetWindowRect( hwnd, &rect );
117 if (PtInRect( &rect, pt )) return hwnd;
118 hwnd = GetWindow( hwnd, GW_HWNDNEXT );
120 return hwndParent;
124 /*******************************************************************
125 * MapWindowPoints (USER.258)
127 void MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, WORD count )
129 WND * wndPtr;
130 POINT * curpt;
131 POINT origin = { 0, 0 };
132 WORD i;
134 /* Translate source window origin to screen coords */
135 while(hwndFrom)
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 */
144 while(hwndTo)
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 /***********************************************************************
162 * IsIconic (USER.31)
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()
188 return hwndActive;
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 );
200 return prev;
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 );
232 BOOL wasVisible;
233 BOOL wasIconic;
234 int swpflags = 0;
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;
246 switch(cmd)
248 case SW_HIDE:
250 * if the window wasn't visible to begin with -- just return
252 if (!wasVisible)
253 return FALSE; /* Nothing to do */
254 swpflags |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
255 SWP_NOACTIVATE | SWP_NOZORDER;
256 break;
259 case SW_SHOWMINNOACTIVE:
260 case SW_SHOWMINIMIZED:
261 case SW_MINIMIZE:
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 );
278 break;
280 case SW_SHOWNA:
281 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE: */
282 case SW_SHOW:
283 swpflags |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
284 break;
287 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
288 case SW_SHOWNOACTIVATE:
289 case SW_RESTORE:
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;
299 if (wasIconic) {
300 MoveWindow(hwnd, wndPtr->rectNormal.left,
301 wndPtr->rectNormal.top,
302 wndPtr->rectNormal.right - wndPtr->rectNormal.left,
303 wndPtr->rectNormal.bottom - wndPtr->rectNormal.top,
304 FALSE);
306 break;
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) );
326 return wasVisible;
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);
370 wndpl->flags = 0;
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;
376 return TRUE;
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 );
395 return TRUE;
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
404 * b) parent of hwnd
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 */
412 for (;;)
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 )
433 HANDLE minmaxHandle;
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) );
446 if (minmaxHandle)
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;
478 if (hwndActive)
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 */
486 hwndActive = hwnd;
487 if (hwndActive)
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 ) );
497 return 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;
514 HANDLE hparams;
515 LONG result;
517 if (!(hparams = USER_HEAP_ALLOC( GMEM_MOVEABLE, sizeof(*params) )))
518 return 0;
519 params = (NCCALCSIZE_PARAMS *) USER_HEAP_ADDR( hparams );
520 params->rgrc[0] = *newWindowRect;
521 if (calcValidRect)
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 );
530 return result;
534 /***********************************************************************
535 * WINPOS_HandleWindowPosChanging
537 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
539 LONG WINPOS_HandleWindowPosChanging( WINDOWPOS *winpos )
541 POINT maxSize;
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 );
551 return 0;
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 )
563 BOOL movingUp;
564 HWND hwndCur;
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)
576 movingUp = TRUE;
578 else if (hwndAfter == HWND_BOTTOM)
580 if (!wndPtr->hwndNext) return; /* Already at the bottom */
581 movingUp = FALSE;
583 else
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);
594 if (movingUp)
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 )
637 HWND hwndAfter;
638 WND *wndPtr;
639 RECT newWindowRect, newClientRect;
640 int flags, result;
641 int changeMask = 0;
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;
659 /* Check flags */
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;
716 else
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))
730 if (wndPtr->window)
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 */
757 if (wndPtr->window)
759 if (changeMask) XConfigureWindow( display, wndPtr->window,
760 changeMask, &winChanges );
761 wndPtr->rectWindow = newWindowRect;
762 wndPtr->rectClient = newClientRect;
764 else
766 RECT oldWindowRect = wndPtr->rectWindow;
768 wndPtr->rectWindow = newWindowRect;
769 wndPtr->rectClient = newClientRect;
771 if (changeMask)
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;
794 if (wndPtr->window)
796 XMapWindow( display, wndPtr->window );
797 MSG_Synchronize();
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;
805 if (wndPtr->window)
807 XUnmapWindow( display, wndPtr->window );
809 else
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 );
846 else
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 );
859 return TRUE;
863 /***********************************************************************
864 * BeginDeferWindowPos (USER.259)
866 HDWP BeginDeferWindowPos( INT count )
868 HDWP handle;
869 DWP *pDWP;
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;
878 pDWP->valid = TRUE;
879 pDWP->wMagic = DWP_MAGIC;
880 pDWP->hwndParent = 0;
881 return handle;
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 )
891 DWP *pDWP;
892 int i;
893 HDWP newhdwp = hdwp;
895 pDWP = (DWP *) USER_HEAP_ADDR( hdwp );
896 if (!pDWP) return 0;
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 );
904 return 0;
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 |
929 SWP_NOOWNERZORDER);
930 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
931 SWP_FRAMECHANGED);
932 return hdwp;
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;
950 pDWP->actualCount++;
951 return newhdwp;
955 /***********************************************************************
956 * EndDeferWindowPos (USER.261)
958 BOOL EndDeferWindowPos( HDWP hdwp )
960 DWP *pDWP;
961 BOOL res = TRUE;
962 int i;
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 );
971 return res;
975 /***********************************************************************
976 * SetWindowPos (USER.232)
978 BOOL SetWindowPos( HWND hwnd, HWND hwndInsertAfter, INT x, INT y,
979 INT cx, INT cy, WORD flags )
981 HDWP hdwp;
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);
1013 return 0;