Moved some macros like NULL, FALSE to winnt.h
[wine.git] / windows / winpos.c
bloba59e5ea197ae2d6c4795ac76086d36aad8e75292
1 /*
2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
6 */
8 #include <string.h>
9 #include "winerror.h"
10 #include "windef.h"
11 #include "wingdi.h"
12 #include "winerror.h"
13 #include "wine/winuser16.h"
14 #include "controls.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "region.h"
18 #include "win.h"
19 #include "hook.h"
20 #include "message.h"
21 #include "queue.h"
22 #include "options.h"
23 #include "task.h"
24 #include "winpos.h"
25 #include "dce.h"
26 #include "nonclient.h"
27 #include "debugtools.h"
28 #include "input.h"
30 DEFAULT_DEBUG_CHANNEL(win);
32 #define HAS_DLGFRAME(style,exStyle) \
33 (((exStyle) & WS_EX_DLGMODALFRAME) || \
34 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
36 #define HAS_THICKFRAME(style) \
37 (((style) & WS_THICKFRAME) && \
38 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
40 #define SWP_AGG_NOGEOMETRYCHANGE \
41 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
42 #define SWP_AGG_NOPOSCHANGE \
43 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
44 #define SWP_AGG_STATUSFLAGS \
45 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
47 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
49 #define PLACE_MIN 0x0001
50 #define PLACE_MAX 0x0002
51 #define PLACE_RECT 0x0004
53 #define SWP_EX_NOCOPY 0x0001
54 #define SWP_EX_PAINTSELF 0x0002
55 #define SWP_EX_NONCLIENT 0x0004
57 #define MINMAX_NOSWP 0x00010000
59 /* ----- internal variables ----- */
61 static HWND hwndPrevActive = 0; /* Previously active window */
62 static HWND hGlobalShellWindow=0; /*the shell*/
63 static HWND hGlobalTaskmanWindow=0;
64 static HWND hGlobalProgmanWindow=0;
66 static LPCSTR atomInternalPos;
68 extern HQUEUE16 hActiveQueue;
70 /***********************************************************************
71 * WINPOS_CreateInternalPosAtom
73 BOOL WINPOS_CreateInternalPosAtom()
75 LPSTR str = "SysIP";
76 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
77 return (atomInternalPos) ? TRUE : FALSE;
80 /***********************************************************************
81 * WINPOS_CheckInternalPos
83 * Called when a window is destroyed.
85 void WINPOS_CheckInternalPos( WND* wndPtr )
87 LPINTERNALPOS lpPos;
88 MESSAGEQUEUE *pMsgQ = 0;
89 HWND hwnd = wndPtr->hwndSelf;
91 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
93 /* Retrieve the message queue associated with this window */
94 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
95 if ( !pMsgQ )
97 WARN("\tMessage queue not found. Exiting!\n" );
98 return;
101 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
103 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
105 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
106 WARN("\tattempt to activate destroyed window!\n");
109 if( lpPos )
111 if( IsWindow(lpPos->hwndIconTitle) )
112 DestroyWindow( lpPos->hwndIconTitle );
113 HeapFree( SystemHeap, 0, lpPos );
116 QUEUE_Unlock( pMsgQ );
117 return;
120 /***********************************************************************
121 * WINPOS_FindIconPos
123 * Find a suitable place for an iconic window.
125 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
127 RECT16 rectParent;
128 short x, y, xspacing, yspacing;
130 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
131 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
132 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
133 return pt; /* The icon already has a suitable position */
135 xspacing = GetSystemMetrics(SM_CXICONSPACING);
136 yspacing = GetSystemMetrics(SM_CYICONSPACING);
138 y = rectParent.bottom;
139 for (;;)
141 x = rectParent.left;
144 /* Check if another icon already occupies this spot */
145 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
146 while (childPtr)
148 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
150 if ((childPtr->rectWindow.left < x + xspacing) &&
151 (childPtr->rectWindow.right >= x) &&
152 (childPtr->rectWindow.top <= y) &&
153 (childPtr->rectWindow.bottom > y - yspacing))
154 break; /* There's a window in there */
156 WIN_UpdateWndPtr(&childPtr,childPtr->next);
158 WIN_ReleaseWndPtr(childPtr);
159 if (!childPtr) /* No window was found, so it's OK for us */
161 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
162 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
163 return pt;
165 x += xspacing;
166 } while(x <= rectParent.right-xspacing);
167 y -= yspacing;
172 /***********************************************************************
173 * ArrangeIconicWindows16 (USER.170)
175 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
177 return ArrangeIconicWindows(parent);
179 /***********************************************************************
180 * ArrangeIconicWindows (USER32.7)
182 UINT WINAPI ArrangeIconicWindows( HWND parent )
184 RECT rectParent;
185 HWND hwndChild;
186 INT x, y, xspacing, yspacing;
188 GetClientRect( parent, &rectParent );
189 x = rectParent.left;
190 y = rectParent.bottom;
191 xspacing = GetSystemMetrics(SM_CXICONSPACING);
192 yspacing = GetSystemMetrics(SM_CYICONSPACING);
194 hwndChild = GetWindow( parent, GW_CHILD );
195 while (hwndChild)
197 if( IsIconic( hwndChild ) )
199 WND *wndPtr = WIN_FindWndPtr(hwndChild);
201 WINPOS_ShowIconTitle( wndPtr, FALSE );
203 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
204 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
205 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
206 if( IsWindow(hwndChild) )
207 WINPOS_ShowIconTitle(wndPtr , TRUE );
208 WIN_ReleaseWndPtr(wndPtr);
210 if (x <= rectParent.right - xspacing) x += xspacing;
211 else
213 x = rectParent.left;
214 y -= yspacing;
217 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
219 return yspacing;
223 /***********************************************************************
224 * SwitchToThisWindow16 (USER.172)
226 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
228 SwitchToThisWindow( hwnd, restore );
232 /***********************************************************************
233 * SwitchToThisWindow (USER32.539)
235 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
237 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
241 /***********************************************************************
242 * GetWindowRect16 (USER.32)
244 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
246 WND * wndPtr = WIN_FindWndPtr( hwnd );
247 if (!wndPtr) return;
249 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
250 if (wndPtr->dwStyle & WS_CHILD)
251 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
252 WIN_ReleaseWndPtr(wndPtr);
256 /***********************************************************************
257 * GetWindowRect (USER32.308)
259 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
261 WND * wndPtr = WIN_FindWndPtr( hwnd );
262 if (!wndPtr) return FALSE;
264 *rect = wndPtr->rectWindow;
265 if (wndPtr->dwStyle & WS_CHILD)
266 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
267 WIN_ReleaseWndPtr(wndPtr);
268 return TRUE;
272 /***********************************************************************
273 * GetWindowRgn (USER32)
275 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
277 int nRet = ERROR;
278 WND *wndPtr = WIN_FindWndPtr( hwnd );
279 if (wndPtr)
281 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
282 WIN_ReleaseWndPtr(wndPtr);
284 return nRet;
287 /***********************************************************************
288 * SetWindowRgn (USER32)
290 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
292 int ret = FALSE;
293 RECT tempRect;
295 WND *wndPtr = WIN_FindWndPtr(hwnd);
297 if (!wndPtr) return FALSE;
299 /* a region exists for this window */
300 if (hrgn != 0 && hrgn == wndPtr->hrgnWnd)
302 /* can't replace actual region with same region
303 since we're now owner of that region
305 SetLastError(ERROR_INVALID_HANDLE);
306 goto done;
310 /* we'd like to set it back to 0 */
311 if (hrgn == 0)
313 GetWindowRect(hwnd, &tempRect);
315 else
317 /* verify that region really exists */
318 if (GetRgnBox(hrgn, &tempRect) == ERROR) goto done;
322 /* Size the window to the rectangle of the new region
323 (if it isn't NULL) */
324 SetWindowPos( hwnd, 0, tempRect.left, tempRect.top,
325 tempRect.right - tempRect.left, tempRect.bottom - tempRect.top,
326 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE |
327 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
330 if (wndPtr->hrgnWnd)
332 /* delete previous region */
333 DeleteObject(wndPtr->hrgnWnd);
334 wndPtr->hrgnWnd = 0;
336 else if (!hrgn)
338 /* if there was no previous region (stored in wndPtr->hrgnWnd) and
339 the region to be set is also NULL, there is nothing more to do
341 ret = TRUE;
342 goto done;
345 /* valid region handle */
346 wndPtr->hrgnWnd = hrgn;
347 wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn);
349 ret = TRUE;
351 done:
352 WIN_ReleaseWndPtr(wndPtr);
353 return ret;
356 /***********************************************************************
357 * SetWindowRgn16
359 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
363 FIXME("SetWindowRgn16: stub\n");
364 return TRUE;
368 /***********************************************************************
369 * GetClientRect16 (USER.33)
371 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
373 WND * wndPtr = WIN_FindWndPtr( hwnd );
375 rect->left = rect->top = rect->right = rect->bottom = 0;
376 if (wndPtr)
378 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
379 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
381 WIN_ReleaseWndPtr(wndPtr);
385 /***********************************************************************
386 * GetClientRect (USER.220)
388 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
390 WND * wndPtr = WIN_FindWndPtr( hwnd );
392 rect->left = rect->top = rect->right = rect->bottom = 0;
393 if (!wndPtr) return FALSE;
394 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
395 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
397 WIN_ReleaseWndPtr(wndPtr);
398 return TRUE;
402 /*******************************************************************
403 * ClientToScreen16 (USER.28)
405 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
407 MapWindowPoints16( hwnd, 0, lppnt, 1 );
411 /*******************************************************************
412 * ClientToScreen (USER32.52)
414 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
416 MapWindowPoints( hwnd, 0, lppnt, 1 );
417 return TRUE;
421 /*******************************************************************
422 * ScreenToClient16 (USER.29)
424 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
426 MapWindowPoints16( 0, hwnd, lppnt, 1 );
430 /*******************************************************************
431 * ScreenToClient (USER32.447)
433 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
435 MapWindowPoints( 0, hwnd, lppnt, 1 );
436 return TRUE;
440 /***********************************************************************
441 * WINPOS_WindowFromPoint
443 * Find the window and hittest for a given point.
445 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
447 WND *wndPtr;
448 INT16 hittest = HTERROR;
449 INT16 retvalue;
450 POINT16 xy = pt;
452 TRACE("scope %04x %d,%d\n", wndScope->hwndSelf, pt.x, pt.y);
453 *ppWnd = NULL;
454 wndPtr = WIN_LockWndPtr(wndScope->child);
456 if( wndScope->dwStyle & WS_DISABLED )
458 retvalue = HTERROR;
459 goto end;
462 if( wndScope->dwExStyle & WS_EX_MANAGED)
464 /* In managed mode we have to check wndScope first as it is also
465 * a window which received the mouse event. */
467 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
468 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
469 goto hittest;
471 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
473 for (;;)
475 while (wndPtr)
477 /* If point is in window, and window is visible, and it */
478 /* is enabled (or it's a top-level window), then explore */
479 /* its children. Otherwise, go to the next window. */
481 if ((wndPtr->dwStyle & WS_VISIBLE) &&
482 (!(wndPtr->dwStyle & WS_DISABLED) ||
483 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
484 (wndPtr->hrgnWnd ?
485 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
486 xy.y - wndPtr->rectWindow.top) :
487 ((xy.x >= wndPtr->rectWindow.left) &&
488 (xy.x < wndPtr->rectWindow.right) &&
489 (xy.y >= wndPtr->rectWindow.top) &&
490 (xy.y < wndPtr->rectWindow.bottom))))
492 TRACE("%d,%d is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
493 *ppWnd = wndPtr; /* Got a suitable window */
495 /* If window is minimized or disabled, return at once */
496 if (wndPtr->dwStyle & WS_MINIMIZE)
498 retvalue = HTCAPTION;
499 goto end;
501 if (wndPtr->dwStyle & WS_DISABLED)
503 retvalue = HTERROR;
504 goto end;
507 /* If point is not in client area, ignore the children */
508 if ((xy.x < wndPtr->rectClient.left) ||
509 (xy.x >= wndPtr->rectClient.right) ||
510 (xy.y < wndPtr->rectClient.top) ||
511 (xy.y >= wndPtr->rectClient.bottom)) break;
513 xy.x -= wndPtr->rectClient.left;
514 xy.y -= wndPtr->rectClient.top;
515 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
517 else
519 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
523 hittest:
524 /* If nothing found, try the scope window */
525 if (!*ppWnd) *ppWnd = wndScope;
527 /* Send the WM_NCHITTEST message (only if to the same task) */
528 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
530 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
531 0, MAKELONG( pt.x, pt.y ) );
532 if (hittest != HTTRANSPARENT)
534 retvalue = hittest; /* Found the window */
535 goto end;
538 else
540 retvalue = HTCLIENT;
541 goto end;
544 /* If no children found in last search, make point relative to parent */
545 if (!wndPtr)
547 xy.x += (*ppWnd)->rectClient.left;
548 xy.y += (*ppWnd)->rectClient.top;
551 /* Restart the search from the next sibling */
552 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
553 *ppWnd = (*ppWnd)->parent;
556 end:
557 WIN_ReleaseWndPtr(wndPtr);
558 return retvalue;
562 /*******************************************************************
563 * WindowFromPoint16 (USER.30)
565 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
567 WND *pWnd;
568 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
569 WIN_ReleaseDesktop();
570 return pWnd->hwndSelf;
574 /*******************************************************************
575 * WindowFromPoint (USER32.582)
577 HWND WINAPI WindowFromPoint( POINT pt )
579 WND *pWnd;
580 POINT16 pt16;
581 CONV_POINT32TO16( &pt, &pt16 );
582 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
583 WIN_ReleaseDesktop();
584 return (HWND)pWnd->hwndSelf;
588 /*******************************************************************
589 * ChildWindowFromPoint16 (USER.191)
591 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
593 POINT pt32;
594 CONV_POINT16TO32( &pt, &pt32 );
595 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
599 /*******************************************************************
600 * ChildWindowFromPoint (USER32.49)
602 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
604 /* pt is in the client coordinates */
606 WND* wnd = WIN_FindWndPtr(hwndParent);
607 RECT rect;
608 HWND retvalue;
610 if( !wnd ) return 0;
612 /* get client rect fast */
613 rect.top = rect.left = 0;
614 rect.right = wnd->rectClient.right - wnd->rectClient.left;
615 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
617 if (!PtInRect( &rect, pt ))
619 retvalue = 0;
620 goto end;
622 WIN_UpdateWndPtr(&wnd,wnd->child);
623 while ( wnd )
625 if (PtInRect( &wnd->rectWindow, pt ))
627 retvalue = wnd->hwndSelf;
628 goto end;
630 WIN_UpdateWndPtr(&wnd,wnd->next);
632 retvalue = hwndParent;
633 end:
634 WIN_ReleaseWndPtr(wnd);
635 return retvalue;
638 /*******************************************************************
639 * ChildWindowFromPointEx16 (USER.50)
641 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
643 POINT pt32;
644 CONV_POINT16TO32( &pt, &pt32 );
645 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
649 /*******************************************************************
650 * ChildWindowFromPointEx (USER32.50)
652 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
653 UINT uFlags)
655 /* pt is in the client coordinates */
657 WND* wnd = WIN_FindWndPtr(hwndParent);
658 RECT rect;
659 HWND retvalue;
661 if( !wnd ) return 0;
663 /* get client rect fast */
664 rect.top = rect.left = 0;
665 rect.right = wnd->rectClient.right - wnd->rectClient.left;
666 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
668 if (!PtInRect( &rect, pt ))
670 retvalue = 0;
671 goto end;
673 WIN_UpdateWndPtr(&wnd,wnd->child);
675 while ( wnd )
677 if (PtInRect( &wnd->rectWindow, pt )) {
678 if ( (uFlags & CWP_SKIPINVISIBLE) &&
679 !(wnd->dwStyle & WS_VISIBLE) );
680 else if ( (uFlags & CWP_SKIPDISABLED) &&
681 (wnd->dwStyle & WS_DISABLED) );
682 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
683 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
684 else
686 retvalue = wnd->hwndSelf;
687 goto end;
691 WIN_UpdateWndPtr(&wnd,wnd->next);
693 retvalue = hwndParent;
694 end:
695 WIN_ReleaseWndPtr(wnd);
696 return retvalue;
700 /*******************************************************************
701 * WINPOS_GetWinOffset
703 * Calculate the offset between the origin of the two windows. Used
704 * to implement MapWindowPoints.
706 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
707 POINT *offset )
709 WND * wndPtr = 0;
711 offset->x = offset->y = 0;
712 if (hwndFrom == hwndTo ) return;
714 /* Translate source window origin to screen coords */
715 if (hwndFrom)
717 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
719 ERR("bad hwndFrom = %04x\n",hwndFrom);
720 return;
722 while (wndPtr->parent)
724 offset->x += wndPtr->rectClient.left;
725 offset->y += wndPtr->rectClient.top;
726 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
728 WIN_ReleaseWndPtr(wndPtr);
731 /* Translate origin to destination window coords */
732 if (hwndTo)
734 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
736 ERR("bad hwndTo = %04x\n", hwndTo );
737 return;
739 while (wndPtr->parent)
741 offset->x -= wndPtr->rectClient.left;
742 offset->y -= wndPtr->rectClient.top;
743 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
745 WIN_ReleaseWndPtr(wndPtr);
750 /*******************************************************************
751 * MapWindowPoints16 (USER.258)
753 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
754 LPPOINT16 lppt, UINT16 count )
756 POINT offset;
758 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
759 while (count--)
761 lppt->x += offset.x;
762 lppt->y += offset.y;
763 lppt++;
768 /*******************************************************************
769 * MapWindowPoints (USER32.386)
771 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
772 LPPOINT lppt, UINT count )
774 POINT offset;
776 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
777 while (count--)
779 lppt->x += offset.x;
780 lppt->y += offset.y;
781 lppt++;
783 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
787 /***********************************************************************
788 * IsIconic16 (USER.31)
790 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
792 return IsIconic(hWnd);
796 /***********************************************************************
797 * IsIconic (USER32.345)
799 BOOL WINAPI IsIconic(HWND hWnd)
801 BOOL retvalue;
802 WND * wndPtr = WIN_FindWndPtr(hWnd);
803 if (wndPtr == NULL) return FALSE;
804 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
805 WIN_ReleaseWndPtr(wndPtr);
806 return retvalue;
810 /***********************************************************************
811 * IsZoomed (USER.272)
813 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
815 return IsZoomed(hWnd);
819 /***********************************************************************
820 * IsZoomed (USER.352)
822 BOOL WINAPI IsZoomed(HWND hWnd)
824 BOOL retvalue;
825 WND * wndPtr = WIN_FindWndPtr(hWnd);
826 if (wndPtr == NULL) return FALSE;
827 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
828 WIN_ReleaseWndPtr(wndPtr);
829 return retvalue;
833 /*******************************************************************
834 * GetActiveWindow (USER.60)
836 HWND16 WINAPI GetActiveWindow16(void)
838 return (HWND16)GetActiveWindow();
841 /*******************************************************************
842 * GetActiveWindow (USER32.205)
844 HWND WINAPI GetActiveWindow(void)
846 MESSAGEQUEUE *pCurMsgQ = 0;
847 HWND hwndActive = 0;
849 /* Get the messageQ for the current thread */
850 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
852 WARN("\tCurrent message queue not found. Exiting!\n" );
853 return 0;
856 /* Return the current active window from the perQ data of the current message Q */
857 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
859 QUEUE_Unlock( pCurMsgQ );
860 return hwndActive;
864 /*******************************************************************
865 * WINPOS_CanActivate
867 static BOOL WINPOS_CanActivate(WND* pWnd)
869 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
870 == WS_VISIBLE ) ) return TRUE;
871 return FALSE;
875 /*******************************************************************
876 * SetActiveWindow16 (USER.59)
878 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
880 return SetActiveWindow(hwnd);
884 /*******************************************************************
885 * SetActiveWindow (USER32.463)
887 HWND WINAPI SetActiveWindow( HWND hwnd )
889 HWND prev = 0;
890 WND *wndPtr = WIN_FindWndPtr( hwnd );
891 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
893 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
895 prev = 0;
896 goto end;
899 /* Get the messageQ for the current thread */
900 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
902 WARN("\tCurrent message queue not found. Exiting!\n" );
903 goto CLEANUP;
906 /* Retrieve the message queue associated with this window */
907 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
908 if ( !pMsgQ )
910 WARN("\tWindow message queue not found. Exiting!\n" );
911 goto CLEANUP;
914 /* Make sure that the window is associated with the calling threads
915 * message queue. It must share the same perQ data.
918 if ( pCurMsgQ->pQData != pMsgQ->pQData )
919 goto CLEANUP;
921 /* Save current active window */
922 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
924 WINPOS_SetActiveWindow( hwnd, 0, 0 );
926 CLEANUP:
927 /* Unlock the queues before returning */
928 if ( pMsgQ )
929 QUEUE_Unlock( pMsgQ );
930 if ( pCurMsgQ )
931 QUEUE_Unlock( pCurMsgQ );
933 end:
934 WIN_ReleaseWndPtr(wndPtr);
935 return prev;
939 /*******************************************************************
940 * GetForegroundWindow16 (USER.608)
942 HWND16 WINAPI GetForegroundWindow16(void)
944 return (HWND16)GetForegroundWindow();
948 /*******************************************************************
949 * SetForegroundWindow16 (USER.609)
951 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
953 return SetForegroundWindow( hwnd );
957 /*******************************************************************
958 * GetForegroundWindow (USER32.241)
960 HWND WINAPI GetForegroundWindow(void)
962 HWND hwndActive = 0;
964 /* Get the foreground window (active window of hActiveQueue) */
965 if ( hActiveQueue )
967 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
968 if ( pActiveQueue )
969 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
971 QUEUE_Unlock( pActiveQueue );
974 return hwndActive;
977 /*******************************************************************
978 * SetForegroundWindow (USER32.482)
980 BOOL WINAPI SetForegroundWindow( HWND hwnd )
982 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
986 /*******************************************************************
987 * AllowSetForegroundWindow (USER32)
989 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
991 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
992 * implemented, then fix this function. */
993 return TRUE;
997 /*******************************************************************
998 * LockSetForegroundWindow (USER32)
1000 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
1002 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
1003 * implemented, then fix this function. */
1004 return TRUE;
1008 /*******************************************************************
1009 * GetShellWindow16 (USER.600)
1011 HWND16 WINAPI GetShellWindow16(void)
1013 return GetShellWindow();
1016 /*******************************************************************
1017 * SetShellWindow (USER32.504)
1019 HWND WINAPI SetShellWindow(HWND hwndshell)
1020 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
1022 hGlobalShellWindow = hwndshell;
1023 return hGlobalShellWindow;
1027 /*******************************************************************
1028 * GetShellWindow (USER32.287)
1030 HWND WINAPI GetShellWindow(void)
1031 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
1033 return hGlobalShellWindow;
1037 /***********************************************************************
1038 * BringWindowToTop16 (USER.45)
1040 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1042 return BringWindowToTop(hwnd);
1046 /***********************************************************************
1047 * BringWindowToTop (USER32.11)
1049 BOOL WINAPI BringWindowToTop( HWND hwnd )
1051 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1055 /***********************************************************************
1056 * MoveWindow16 (USER.56)
1058 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1059 BOOL16 repaint )
1061 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1065 /***********************************************************************
1066 * MoveWindow (USER32.399)
1068 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1069 BOOL repaint )
1071 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1072 if (!repaint) flags |= SWP_NOREDRAW;
1073 TRACE("%04x %d,%d %dx%d %d\n",
1074 hwnd, x, y, cx, cy, repaint );
1075 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1078 /***********************************************************************
1079 * WINPOS_InitInternalPos
1081 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1082 LPRECT restoreRect )
1084 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1085 atomInternalPos );
1086 if( !lpPos )
1088 /* this happens when the window is minimized/maximized
1089 * for the first time (rectWindow is not adjusted yet) */
1091 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1092 if( !lpPos ) return NULL;
1094 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1095 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1096 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1097 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1100 if( wnd->dwStyle & WS_MINIMIZE )
1101 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1102 else if( wnd->dwStyle & WS_MAXIMIZE )
1103 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1104 else if( restoreRect )
1105 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1107 return lpPos;
1110 /***********************************************************************
1111 * WINPOS_RedrawIconTitle
1113 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1115 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1116 if( lpPos )
1118 if( lpPos->hwndIconTitle )
1120 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1121 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1122 return TRUE;
1125 return FALSE;
1128 /***********************************************************************
1129 * WINPOS_ShowIconTitle
1131 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1133 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1135 if( lpPos && !(pWnd->dwExStyle & WS_EX_MANAGED))
1137 HWND16 hWnd = lpPos->hwndIconTitle;
1139 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1141 if( !hWnd )
1142 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1143 if( bShow )
1145 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1147 if( !(pWnd->dwStyle & WS_VISIBLE) )
1149 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1150 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1151 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1153 WIN_ReleaseWndPtr(pWnd);
1156 else ShowWindow( hWnd, SW_HIDE );
1158 return FALSE;
1161 /*******************************************************************
1162 * WINPOS_GetMinMaxInfo
1164 * Get the minimized and maximized information for a window.
1166 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1167 POINT *minTrack, POINT *maxTrack )
1169 LPINTERNALPOS lpPos;
1170 MINMAXINFO MinMax;
1171 INT xinc, yinc;
1173 /* Compute default values */
1175 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1176 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1177 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1178 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1179 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1180 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1182 if (wndPtr->dwExStyle & WS_EX_MANAGED) xinc = yinc = 0;
1183 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1185 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1186 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1188 else
1190 xinc = yinc = 0;
1191 if (HAS_THICKFRAME(wndPtr->dwStyle))
1193 xinc += GetSystemMetrics(SM_CXFRAME);
1194 yinc += GetSystemMetrics(SM_CYFRAME);
1196 if (wndPtr->dwStyle & WS_BORDER)
1198 xinc += GetSystemMetrics(SM_CXBORDER);
1199 yinc += GetSystemMetrics(SM_CYBORDER);
1202 MinMax.ptMaxSize.x += 2 * xinc;
1203 MinMax.ptMaxSize.y += 2 * yinc;
1205 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1206 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1207 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1208 else
1210 MinMax.ptMaxPosition.x = -xinc;
1211 MinMax.ptMaxPosition.y = -yinc;
1214 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1216 /* Some sanity checks */
1218 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1219 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1220 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1221 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1222 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1223 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1224 MinMax.ptMinTrackSize.x );
1225 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1226 MinMax.ptMinTrackSize.y );
1228 if (maxSize) *maxSize = MinMax.ptMaxSize;
1229 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1230 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1231 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1234 /***********************************************************************
1235 * WINPOS_MinMaximize
1237 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1238 * This function assumes that 'cmd' is different from the current window
1239 * state.
1241 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1243 UINT swpFlags = 0;
1244 POINT pt, size;
1245 LPINTERNALPOS lpPos;
1247 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1249 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1250 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1252 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1254 if( wndPtr->dwStyle & WS_MINIMIZE )
1256 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1257 return (SWP_NOSIZE | SWP_NOMOVE);
1258 swpFlags |= SWP_NOCOPYBITS;
1260 switch( cmd )
1262 case SW_MINIMIZE:
1263 if( wndPtr->dwStyle & WS_MAXIMIZE)
1265 wndPtr->flags |= WIN_RESTORE_MAX;
1266 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1268 else
1269 wndPtr->flags &= ~WIN_RESTORE_MAX;
1270 wndPtr->dwStyle |= WS_MINIMIZE;
1272 if( wndPtr->flags & WIN_NATIVE )
1273 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1274 swpFlags |= MINMAX_NOSWP;
1276 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1278 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1279 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1280 swpFlags |= SWP_NOCOPYBITS;
1281 break;
1283 case SW_MAXIMIZE:
1284 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1285 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1286 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1288 if( wndPtr->dwStyle & WS_MINIMIZE )
1290 if( wndPtr->flags & WIN_NATIVE )
1291 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1293 WINPOS_ShowIconTitle( wndPtr, FALSE );
1294 wndPtr->dwStyle &= ~WS_MINIMIZE;
1296 wndPtr->dwStyle |= WS_MAXIMIZE;
1298 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1299 size.x, size.y );
1300 break;
1302 case SW_RESTORE:
1303 if( wndPtr->dwStyle & WS_MINIMIZE )
1305 if( wndPtr->flags & WIN_NATIVE )
1306 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1307 swpFlags |= MINMAX_NOSWP;
1309 wndPtr->dwStyle &= ~WS_MINIMIZE;
1310 WINPOS_ShowIconTitle( wndPtr, FALSE );
1312 if( wndPtr->flags & WIN_RESTORE_MAX)
1314 /* Restore to maximized position */
1315 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1316 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1317 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1318 wndPtr->dwStyle |= WS_MAXIMIZE;
1319 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1320 break;
1323 else
1324 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1325 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1327 /* Restore to normal position */
1329 *lpRect = lpPos->rectNormal;
1330 lpRect->right -= lpRect->left;
1331 lpRect->bottom -= lpRect->top;
1333 break;
1335 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1336 return swpFlags;
1339 /***********************************************************************
1340 * ShowWindowAsync (USER32.535)
1342 * doesn't wait; returns immediately.
1343 * used by threads to toggle windows in other (possibly hanging) threads
1345 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1347 /* FIXME: does ShowWindow() return immediately ? */
1348 return ShowWindow(hwnd, cmd);
1352 /***********************************************************************
1353 * ShowWindow16 (USER.42)
1355 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1357 return ShowWindow(hwnd,cmd);
1361 /***********************************************************************
1362 * ShowWindow (USER32.534)
1364 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1366 WND* wndPtr = WIN_FindWndPtr( hwnd );
1367 BOOL wasVisible, showFlag;
1368 RECT16 newPos = {0, 0, 0, 0};
1369 UINT swp = 0;
1371 if (!wndPtr) return FALSE;
1373 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1375 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1377 switch(cmd)
1379 case SW_HIDE:
1380 if (!wasVisible) goto END;;
1381 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1382 SWP_NOACTIVATE | SWP_NOZORDER;
1383 break;
1385 case SW_SHOWMINNOACTIVE:
1386 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1387 /* fall through */
1388 case SW_SHOWMINIMIZED:
1389 swp |= SWP_SHOWWINDOW;
1390 /* fall through */
1391 case SW_MINIMIZE:
1392 swp |= SWP_FRAMECHANGED;
1393 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1394 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1395 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1396 break;
1398 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1399 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1400 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1401 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1402 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1403 break;
1405 case SW_SHOWNA:
1406 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1407 /* fall through */
1408 case SW_SHOW:
1409 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1412 * ShowWindow has a little peculiar behavior that if the
1413 * window is already the topmost window, it will not
1414 * activate it.
1416 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1417 swp |= SWP_NOACTIVATE;
1419 break;
1421 case SW_SHOWNOACTIVATE:
1422 swp |= SWP_NOZORDER;
1423 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1424 /* fall through */
1425 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1426 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1427 case SW_RESTORE:
1428 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1430 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1431 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1432 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1433 break;
1436 showFlag = (cmd != SW_HIDE);
1437 if (showFlag != wasVisible)
1439 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1440 if (!IsWindow( hwnd )) goto END;
1443 if ((wndPtr->dwStyle & WS_CHILD) &&
1444 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1445 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1447 /* Don't call SetWindowPos() on invisible child windows */
1448 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1449 else wndPtr->dwStyle |= WS_VISIBLE;
1451 else
1453 /* We can't activate a child window */
1454 if ((wndPtr->dwStyle & WS_CHILD) &&
1455 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1456 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1457 if (!(swp & MINMAX_NOSWP))
1459 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1460 newPos.right, newPos.bottom, LOWORD(swp) );
1461 if (cmd == SW_HIDE)
1463 /* FIXME: This will cause the window to be activated irrespective
1464 * of whether it is owned by the same thread. Has to be done
1465 * asynchronously.
1468 if (hwnd == GetActiveWindow())
1469 WINPOS_ActivateOtherWindow(wndPtr);
1471 /* Revert focus to parent */
1472 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1473 SetFocus( GetParent(hwnd) );
1476 if (!IsWindow( hwnd )) goto END;
1477 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1480 if (wndPtr->flags & WIN_NEED_SIZE)
1482 /* should happen only in CreateWindowEx() */
1483 int wParam = SIZE_RESTORED;
1485 wndPtr->flags &= ~WIN_NEED_SIZE;
1486 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1487 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1488 SendMessageA( hwnd, WM_SIZE, wParam,
1489 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1490 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1491 SendMessageA( hwnd, WM_MOVE, 0,
1492 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1495 END:
1496 WIN_ReleaseWndPtr(wndPtr);
1497 return wasVisible;
1501 /***********************************************************************
1502 * GetInternalWindowPos16 (USER.460)
1504 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1505 LPPOINT16 ptIcon )
1507 WINDOWPLACEMENT16 wndpl;
1508 if (GetWindowPlacement16( hwnd, &wndpl ))
1510 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1511 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1512 return wndpl.showCmd;
1514 return 0;
1518 /***********************************************************************
1519 * GetInternalWindowPos (USER32.245)
1521 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1522 LPPOINT ptIcon )
1524 WINDOWPLACEMENT wndpl;
1525 if (GetWindowPlacement( hwnd, &wndpl ))
1527 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1528 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1529 return wndpl.showCmd;
1531 return 0;
1534 /***********************************************************************
1535 * GetWindowPlacement16 (USER.370)
1537 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1539 WND *pWnd = WIN_FindWndPtr( hwnd );
1540 LPINTERNALPOS lpPos;
1542 if(!pWnd ) return FALSE;
1544 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1545 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1546 wndpl->length = sizeof(*wndpl);
1547 if( pWnd->dwStyle & WS_MINIMIZE )
1548 wndpl->showCmd = SW_SHOWMINIMIZED;
1549 else
1550 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1551 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1552 if( pWnd->flags & WIN_RESTORE_MAX )
1553 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1554 else
1555 wndpl->flags = 0;
1556 wndpl->ptMinPosition = lpPos->ptIconPos;
1557 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1558 wndpl->rcNormalPosition = lpPos->rectNormal;
1560 WIN_ReleaseWndPtr(pWnd);
1561 return TRUE;
1565 /***********************************************************************
1566 * GetWindowPlacement (USER32.307)
1568 * Win95:
1569 * Fails if wndpl->length of Win95 (!) apps is invalid.
1571 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1573 if( pwpl32 )
1575 WINDOWPLACEMENT16 wpl;
1576 wpl.length = sizeof(wpl);
1577 if( GetWindowPlacement16( hwnd, &wpl ) )
1579 pwpl32->length = sizeof(*pwpl32);
1580 pwpl32->flags = wpl.flags;
1581 pwpl32->showCmd = wpl.showCmd;
1582 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1583 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1584 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1585 return TRUE;
1588 return FALSE;
1592 /***********************************************************************
1593 * WINPOS_SetPlacement
1595 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1596 UINT flags )
1598 WND *pWnd = WIN_FindWndPtr( hwnd );
1599 if( pWnd )
1601 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1602 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1604 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1605 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1606 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1608 if( pWnd->dwStyle & WS_MINIMIZE )
1610 WINPOS_ShowIconTitle( pWnd, FALSE );
1611 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1612 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1613 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1615 else if( pWnd->dwStyle & WS_MAXIMIZE )
1617 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1618 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1619 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1621 else if( flags & PLACE_RECT )
1622 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1623 lpPos->rectNormal.right - lpPos->rectNormal.left,
1624 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1625 SWP_NOZORDER | SWP_NOACTIVATE );
1627 ShowWindow( hwnd, wndpl->showCmd );
1628 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1630 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1632 /* SDK: ...valid only the next time... */
1633 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1635 WIN_ReleaseWndPtr(pWnd);
1636 return TRUE;
1638 return FALSE;
1642 /***********************************************************************
1643 * SetWindowPlacement16 (USER.371)
1645 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1647 return WINPOS_SetPlacement( hwnd, wndpl,
1648 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1651 /***********************************************************************
1652 * SetWindowPlacement (USER32.519)
1654 * Win95:
1655 * Fails if wndpl->length of Win95 (!) apps is invalid.
1657 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1659 if( pwpl32 )
1661 WINDOWPLACEMENT16 wpl;
1663 wpl.length = sizeof(WINDOWPLACEMENT16);
1664 wpl.flags = pwpl32->flags;
1665 wpl.showCmd = pwpl32->showCmd;
1666 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1667 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1668 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1669 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1670 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1671 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1672 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1673 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1675 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1677 return FALSE;
1681 /***********************************************************************
1682 * SetInternalWindowPos16 (USER.461)
1684 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1685 LPRECT16 rect, LPPOINT16 pt )
1687 if( IsWindow16(hwnd) )
1689 WINDOWPLACEMENT16 wndpl;
1690 UINT flags;
1692 wndpl.length = sizeof(wndpl);
1693 wndpl.showCmd = showCmd;
1694 wndpl.flags = flags = 0;
1696 if( pt )
1698 flags |= PLACE_MIN;
1699 wndpl.flags |= WPF_SETMINPOSITION;
1700 wndpl.ptMinPosition = *pt;
1702 if( rect )
1704 flags |= PLACE_RECT;
1705 wndpl.rcNormalPosition = *rect;
1707 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1712 /***********************************************************************
1713 * SetInternalWindowPos (USER32.483)
1715 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1716 LPRECT rect, LPPOINT pt )
1718 if( IsWindow(hwnd) )
1720 WINDOWPLACEMENT16 wndpl;
1721 UINT flags;
1723 wndpl.length = sizeof(wndpl);
1724 wndpl.showCmd = showCmd;
1725 wndpl.flags = flags = 0;
1727 if( pt )
1729 flags |= PLACE_MIN;
1730 wndpl.flags |= WPF_SETMINPOSITION;
1731 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1733 if( rect )
1735 flags |= PLACE_RECT;
1736 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1738 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1742 /*******************************************************************
1743 * WINPOS_SetActiveWindow
1745 * SetActiveWindow() back-end. This is the only function that
1746 * can assign active status to a window. It must be called only
1747 * for the top level windows.
1749 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1751 CBTACTIVATESTRUCT16* cbtStruct;
1752 WND* wndPtr=0, *wndTemp;
1753 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1754 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1755 WORD wIconized = 0;
1756 HWND hwndActive = 0;
1757 BOOL bRet = 0;
1759 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1761 /* Get current active window from the active queue */
1762 if ( hActiveQueue )
1764 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1765 if ( pOldActiveQueue )
1766 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1769 /* paranoid checks */
1770 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1771 goto CLEANUP_END;
1773 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1774 * return 0;
1776 wndPtr = WIN_FindWndPtr(hWnd);
1777 hOldActiveQueue = hActiveQueue;
1779 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1781 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1782 WIN_ReleaseWndPtr(wndTemp);
1784 else
1785 TRACE("no current active window.\n");
1787 /* call CBT hook chain */
1788 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1790 cbtStruct->fMouse = fMouse;
1791 cbtStruct->hWndActive = hwndActive;
1792 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1793 (LPARAM)SEGPTR_GET(cbtStruct) );
1794 SEGPTR_FREE(cbtStruct);
1795 if (bRet) goto CLEANUP_END;
1798 /* set prev active wnd to current active wnd and send notification */
1799 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1801 MESSAGEQUEUE *pTempActiveQueue = 0;
1803 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1805 if (GetSysModalWindow16() != hWnd)
1806 goto CLEANUP_END;
1807 /* disregard refusal if hWnd is sysmodal */
1810 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1811 MAKEWPARAM( WA_INACTIVE, wIconized ),
1812 (LPARAM)hWnd );
1814 /* check if something happened during message processing
1815 * (global active queue may have changed)
1817 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1818 if(!pTempActiveQueue)
1819 goto CLEANUP_END;
1821 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1822 QUEUE_Unlock( pTempActiveQueue );
1823 if( hwndPrevActive != hwndActive )
1824 goto CLEANUP_END;
1827 /* Set new active window in the message queue */
1828 hwndActive = hWnd;
1829 if ( wndPtr )
1831 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1832 if ( pNewActiveQueue )
1833 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1835 else /* have to do this or MDI frame activation goes to hell */
1836 if( pOldActiveQueue )
1837 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1839 /* send palette messages */
1840 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1841 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1843 /* if prev wnd is minimized redraw icon title */
1844 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1846 /* managed windows will get ConfigureNotify event */
1847 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1849 /* check Z-order and bring hWnd to the top */
1850 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1852 if (wndTemp->dwStyle & WS_VISIBLE) break;
1854 WIN_ReleaseDesktop();
1855 WIN_ReleaseWndPtr(wndTemp);
1857 if( wndTemp != wndPtr )
1858 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1859 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1860 if (!IsWindow(hWnd))
1861 goto CLEANUP;
1864 /* Get a handle to the new active queue */
1865 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1867 /* send WM_ACTIVATEAPP if necessary */
1868 if (hOldActiveQueue != hNewActiveQueue)
1870 WND **list, **ppWnd;
1871 WND *pDesktop = WIN_GetDesktop();
1873 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1875 for (ppWnd = list; *ppWnd; ppWnd++)
1877 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1879 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1880 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1881 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1883 WIN_ReleaseWinArray(list);
1886 hActiveQueue = hNewActiveQueue;
1888 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1890 for (ppWnd = list; *ppWnd; ppWnd++)
1892 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1894 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1895 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1896 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1898 WIN_ReleaseWinArray(list);
1900 WIN_ReleaseDesktop();
1902 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1905 if (hWnd)
1907 /* walk up to the first unowned window */
1908 wndTemp = WIN_LockWndPtr(wndPtr);
1909 while (wndTemp->owner)
1911 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1913 /* and set last active owned popup */
1914 wndTemp->hwndLastActive = hWnd;
1916 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1917 WIN_ReleaseWndPtr(wndTemp);
1918 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1919 SendMessageA( hWnd, WM_ACTIVATE,
1920 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1921 (LPARAM)hwndPrevActive );
1922 if( !IsWindow(hWnd) ) goto CLEANUP;
1925 /* change focus if possible */
1926 if ( fChangeFocus )
1928 if ( pNewActiveQueue )
1930 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1932 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1933 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1934 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1935 0 : hwndActive );
1938 if ( pOldActiveQueue &&
1939 ( !pNewActiveQueue ||
1940 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1942 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1943 if ( hOldFocus )
1944 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1948 if( !hwndPrevActive && wndPtr )
1949 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1951 /* if active wnd is minimized redraw icon title */
1952 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1954 bRet = (hWnd == hwndActive); /* Success? */
1956 CLEANUP: /* Unlock the message queues before returning */
1958 if ( pNewActiveQueue )
1959 QUEUE_Unlock( pNewActiveQueue );
1961 CLEANUP_END:
1963 if ( pOldActiveQueue )
1964 QUEUE_Unlock( pOldActiveQueue );
1966 WIN_ReleaseWndPtr(wndPtr);
1967 return bRet;
1970 /*******************************************************************
1971 * WINPOS_ActivateOtherWindow
1973 * Activates window other than pWnd.
1975 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1977 BOOL bRet = 0;
1978 WND* pWndTo = NULL;
1979 HWND hwndActive = 0;
1981 /* Get current active window from the active queue */
1982 if ( hActiveQueue )
1984 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1985 if ( pActiveQueue )
1987 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1988 QUEUE_Unlock( pActiveQueue );
1992 if( pWnd->hwndSelf == hwndPrevActive )
1993 hwndPrevActive = 0;
1995 if( hwndActive != pWnd->hwndSelf &&
1996 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1997 return 0;
1999 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
2000 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
2002 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
2004 WIN_ReleaseWndPtr(pWndTo);
2005 pWndTo = WIN_FindWndPtr(hwndPrevActive);
2007 while( !WINPOS_CanActivate(pWndTo) )
2009 /* by now owned windows should've been taken care of */
2010 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
2011 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
2012 if( !pWndTo ) break;
2014 WIN_ReleaseWndPtr(pWndPtr);
2017 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
2019 /* switch desktop queue to current active */
2020 if( pWndTo )
2022 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
2023 WIN_ReleaseWndPtr(pWndTo);
2024 WIN_ReleaseDesktop();
2027 hwndPrevActive = 0;
2028 return bRet;
2031 /*******************************************************************
2032 * WINPOS_ChangeActiveWindow
2035 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2037 WND *wndPtr, *wndTemp;
2038 BOOL retvalue;
2039 HWND hwndActive = 0;
2041 /* Get current active window from the active queue */
2042 if ( hActiveQueue )
2044 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2045 if ( pActiveQueue )
2047 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2048 QUEUE_Unlock( pActiveQueue );
2052 if (!hWnd)
2053 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2055 wndPtr = WIN_FindWndPtr(hWnd);
2056 if( !wndPtr ) return FALSE;
2058 /* child windows get WM_CHILDACTIVATE message */
2059 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2061 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2062 goto end;
2065 if( hWnd == hwndActive )
2067 retvalue = FALSE;
2068 goto end;
2071 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2073 retvalue = FALSE;
2074 goto end;
2077 /* switch desktop queue to current active */
2078 wndTemp = WIN_GetDesktop();
2079 if( wndPtr->parent == wndTemp)
2080 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2081 WIN_ReleaseDesktop();
2083 retvalue = TRUE;
2084 end:
2085 WIN_ReleaseWndPtr(wndPtr);
2086 return retvalue;
2090 /***********************************************************************
2091 * WINPOS_SendNCCalcSize
2093 * Send a WM_NCCALCSIZE message to a window.
2094 * All parameters are read-only except newClientRect.
2095 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2096 * when calcValidRect is TRUE.
2098 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2099 RECT *newWindowRect, RECT *oldWindowRect,
2100 RECT *oldClientRect, WINDOWPOS *winpos,
2101 RECT *newClientRect )
2103 NCCALCSIZE_PARAMS params;
2104 WINDOWPOS winposCopy;
2105 LONG result;
2107 params.rgrc[0] = *newWindowRect;
2108 if (calcValidRect)
2110 winposCopy = *winpos;
2111 params.rgrc[1] = *oldWindowRect;
2112 params.rgrc[2] = *oldClientRect;
2113 params.lppos = &winposCopy;
2115 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2116 (LPARAM)&params );
2117 TRACE("%d,%d-%d,%d\n",
2118 params.rgrc[0].left, params.rgrc[0].top,
2119 params.rgrc[0].right, params.rgrc[0].bottom );
2121 /* If the application send back garbage, ignore it */
2122 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2123 *newClientRect = params.rgrc[0];
2125 return result;
2129 /***********************************************************************
2130 * WINPOS_HandleWindowPosChanging16
2132 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2134 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2136 POINT maxSize, minTrack;
2137 if (winpos->flags & SWP_NOSIZE) return 0;
2138 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2139 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2141 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2142 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2143 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2144 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2146 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2147 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2150 return 0;
2154 /***********************************************************************
2155 * WINPOS_HandleWindowPosChanging
2157 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2159 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2161 POINT maxSize;
2162 if (winpos->flags & SWP_NOSIZE) return 0;
2163 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2164 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2166 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2167 winpos->cx = min( winpos->cx, maxSize.x );
2168 winpos->cy = min( winpos->cy, maxSize.y );
2170 return 0;
2173 /***********************************************************************
2174 * SWP_DoOwnedPopups
2176 * fix Z order taking into account owned popups -
2177 * basically we need to maintain them above the window that owns them
2179 * FIXME: hide/show owned popups when owner visibility changes.
2181 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2183 WND* w = WIN_LockWndPtr(pDesktop->child);
2185 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2187 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2189 /* make sure this popup stays above the owner */
2191 HWND hwndLocalPrev = HWND_TOP;
2193 if( hwndInsertAfter != HWND_TOP )
2195 while( w != wndPtr->owner )
2197 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2198 if( hwndLocalPrev == hwndInsertAfter ) break;
2199 WIN_UpdateWndPtr(&w,w->next);
2201 hwndInsertAfter = hwndLocalPrev;
2204 else if( wndPtr->dwStyle & WS_CHILD )
2205 goto END;
2207 WIN_UpdateWndPtr(&w, pDesktop->child);
2209 while( w )
2211 if( w == wndPtr ) break;
2213 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2215 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2216 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2217 hwndInsertAfter = w->hwndSelf;
2219 WIN_UpdateWndPtr(&w, w->next);
2222 END:
2223 WIN_ReleaseWndPtr(w);
2224 return hwndInsertAfter;
2227 /***********************************************************************
2228 * SWP_CopyValidBits
2230 * Make window look nice without excessive repainting
2232 * visible and update regions are in window coordinates
2233 * client and window rectangles are in parent client coordinates
2235 * Returns: uFlags and a dirty region in *pVisRgn.
2237 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2238 LPRECT lpOldWndRect,
2239 LPRECT lpOldClientRect, UINT uFlags )
2241 RECT r;
2242 HRGN newVisRgn, dirtyRgn;
2243 INT my = COMPLEXREGION;
2245 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2246 Wnd->rectWindow.left, Wnd->rectWindow.top,
2247 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2248 lpOldWndRect->left, lpOldWndRect->top,
2249 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2250 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2251 Wnd->rectClient.left, Wnd->rectClient.top,
2252 Wnd->rectClient.right, Wnd->rectClient.bottom,
2253 lpOldClientRect->left, lpOldClientRect->top,
2254 lpOldClientRect->right,lpOldClientRect->bottom );
2256 if( Wnd->hrgnUpdate == 1 )
2257 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2259 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2260 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2262 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2263 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2265 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2267 nocopy:
2269 TRACE("\twon't copy anything!\n");
2271 /* set dirtyRgn to the sum of old and new visible regions
2272 * in parent client coordinates */
2274 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2275 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2277 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2279 else /* copy valid bits to a new location */
2281 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2282 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2284 /* subtract already invalid region inside Wnd from the dst region */
2286 if( Wnd->hrgnUpdate )
2287 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2288 goto nocopy;
2290 /* check if entire window can be copied */
2292 ow = lpOldWndRect->right - lpOldWndRect->left;
2293 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2294 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2295 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2297 ocw = lpOldClientRect->right - lpOldClientRect->left;
2298 och = lpOldClientRect->bottom - lpOldClientRect->top;
2299 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2300 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2302 if( (ocw != ncw) || (och != nch) ||
2303 ( ow != nw) || ( oh != nh) ||
2304 ((lpOldClientRect->top - lpOldWndRect->top) !=
2305 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2306 ((lpOldClientRect->left - lpOldWndRect->left) !=
2307 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2309 if(uFlags & SWP_EX_PAINTSELF)
2311 /* movement relative to the window itself */
2312 dx = (Wnd->rectClient.left - Wnd->rectWindow.left) -
2313 (lpOldClientRect->left - lpOldWndRect->left) ;
2314 dy = (Wnd->rectClient.top - Wnd->rectWindow.top) -
2315 (lpOldClientRect->top - lpOldWndRect->top) ;
2317 else
2319 /* movement relative to the parent's client area */
2320 dx = Wnd->rectClient.left - lpOldClientRect->left;
2321 dy = Wnd->rectClient.top - lpOldClientRect->top;
2324 /* restrict valid bits to the common client rect */
2326 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2327 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2328 r.right = r.left + min( ocw, ncw );
2329 r.bottom = r.top + min( och, nch );
2331 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2332 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2333 GetRgnBox( hrgnValid, &r );
2334 if( IsRectEmpty( &r ) )
2335 goto nocopy;
2336 r = *lpOldClientRect;
2338 else
2340 if(uFlags & SWP_EX_PAINTSELF) {
2342 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2343 * relative to itself, only the client area can change.
2344 * if the client rect didn't change, there's nothing to do.
2346 dx = 0;
2347 dy = 0;
2349 else
2351 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2352 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2353 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2355 r = *lpOldWndRect;
2358 if( !(uFlags & SWP_EX_PAINTSELF) )
2360 /* Move remaining regions to parent coordinates */
2361 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2362 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2364 else
2365 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2367 TRACE("\tcomputing dirty region!\n");
2369 /* Compute combined dirty region (old + new - valid) */
2370 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2371 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2373 /* Blt valid bits, r is the rect to copy */
2375 if( dx || dy )
2377 RECT rClip;
2378 HDC hDC;
2380 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2381 from copying clipped areas */
2383 if( uFlags & SWP_EX_PAINTSELF )
2385 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2386 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2387 rClip.right = nw; rClip.bottom = nh;
2389 else
2391 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2392 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2393 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2394 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2396 rClip.left = rClip.top = 0;
2398 if( oh > nh ) r.bottom = r.top + nh;
2399 if( ow < nw ) r.right = r.left + nw;
2401 if( IntersectRect( &r, &r, &rClip ) )
2403 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2405 /* When you copy the bits without repainting, parent doesn't
2406 get validated appropriately. Therefore, we have to validate
2407 the parent with the windows' updated region when the
2408 parent's update region is not empty. */
2410 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2412 OffsetRect(&r, dx, dy);
2413 ValidateRect(Wnd->parent->hwndSelf, &r);
2416 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2417 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2421 /* *pVisRgn now points to the invalidated region */
2423 DeleteObject(newVisRgn);
2424 DeleteObject(dirtyRgn);
2425 return uFlags;
2428 /***********************************************************************
2429 * SWP_DoSimpleFrameChanged
2431 * NOTE: old and new client rect origins are identical, only
2432 * extents may have changed. Window extents are the same.
2434 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2436 INT i = 0;
2437 RECT rect;
2438 HRGN hrgn = 0;
2440 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2442 /* Client rect changed its position/size, most likely a scrollar
2443 * was added/removed.
2445 * FIXME: WVR alignment flags
2448 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2450 i++;
2451 rect.top = 0;
2452 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2453 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2454 if(!(uFlags & SWP_EX_NOCOPY))
2455 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2456 else
2458 rect.left = 0;
2459 goto redraw;
2463 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2465 if( i )
2466 hrgn = CreateRectRgnIndirect( &rect );
2467 rect.left = 0;
2468 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2469 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2470 if(!(uFlags & SWP_EX_NOCOPY))
2471 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2472 else
2473 rect.top = 0;
2474 if( i++ )
2475 REGION_UnionRectWithRgn( hrgn, &rect );
2478 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2480 rect = wndPtr->rectWindow;
2481 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2482 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2483 i++;
2487 if( i )
2489 redraw:
2490 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2491 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2493 else
2495 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2498 if( hrgn > 1 )
2499 DeleteObject( hrgn );
2502 /***********************************************************************
2503 * SWP_DoWinPosChanging
2505 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2506 RECT* pNewWindowRect, RECT* pNewClientRect )
2508 /* Send WM_WINDOWPOSCHANGING message */
2510 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2511 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2513 /* Calculate new position and size */
2515 *pNewWindowRect = wndPtr->rectWindow;
2516 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2517 : wndPtr->rectClient;
2519 if (!(pWinpos->flags & SWP_NOSIZE))
2521 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2522 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2524 if (!(pWinpos->flags & SWP_NOMOVE))
2526 pNewWindowRect->left = pWinpos->x;
2527 pNewWindowRect->top = pWinpos->y;
2528 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2529 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2531 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2532 pWinpos->y - wndPtr->rectWindow.top );
2535 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2536 return TRUE;
2539 /***********************************************************************
2540 * SWP_DoNCCalcSize
2542 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2543 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2545 UINT wvrFlags = 0;
2547 /* Send WM_NCCALCSIZE message to get new client area */
2548 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2550 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2551 &wndPtr->rectWindow, &wndPtr->rectClient,
2552 pWinpos, pNewClientRect );
2554 /* FIXME: WVR_ALIGNxxx */
2556 if( pNewClientRect->left != wndPtr->rectClient.left ||
2557 pNewClientRect->top != wndPtr->rectClient.top )
2558 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2560 if( (pNewClientRect->right - pNewClientRect->left !=
2561 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2562 (pNewClientRect->bottom - pNewClientRect->top !=
2563 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2564 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2566 else
2567 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2568 pNewClientRect->top != wndPtr->rectClient.top) )
2569 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2570 return wvrFlags;
2573 /***********************************************************************
2574 * SetWindowPos (USER.2)
2576 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2577 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2579 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2582 /***********************************************************************
2583 * SetWindowPos (USER32.520)
2585 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2586 INT x, INT y, INT cx, INT cy, UINT flags )
2588 WINDOWPOS winpos;
2589 WND * wndPtr,*wndTemp;
2590 RECT newWindowRect, newClientRect;
2591 RECT oldWindowRect, oldClientRect;
2592 HRGN visRgn = 0;
2593 UINT wvrFlags = 0, uFlags = 0;
2594 BOOL retvalue, resync = FALSE, bChangePos;
2595 HWND hwndActive = 0;
2597 /* Get current active window from the active queue */
2598 if ( hActiveQueue )
2600 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2601 if ( pActiveQueue )
2603 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2604 QUEUE_Unlock( pActiveQueue );
2608 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2609 hwnd, x, y, x+cx, y+cy, flags);
2611 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2612 flags &= ~SWP_WINE_NOHOSTMOVE;
2615 /* ------------------------------------------------------------------------ CHECKS */
2617 /* Check window handle */
2619 if (hwnd == GetDesktopWindow()) return FALSE;
2620 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2622 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2623 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2625 /* Fix redundant flags */
2627 if(wndPtr->dwStyle & WS_VISIBLE)
2628 flags &= ~SWP_SHOWWINDOW;
2629 else
2631 if (!(flags & SWP_SHOWWINDOW))
2632 flags |= SWP_NOREDRAW;
2633 flags &= ~SWP_HIDEWINDOW;
2636 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2638 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2639 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2640 flags |= SWP_NOSIZE; /* Already the right size */
2642 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2643 flags |= SWP_NOMOVE; /* Already the right position */
2645 if (hwnd == hwndActive)
2646 flags |= SWP_NOACTIVATE; /* Already active */
2647 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2649 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2651 flags &= ~SWP_NOZORDER;
2652 hwndInsertAfter = HWND_TOP;
2653 goto Pos;
2657 /* Check hwndInsertAfter */
2659 /* FIXME: TOPMOST not supported yet */
2660 if ((hwndInsertAfter == HWND_TOPMOST) ||
2661 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2663 /* hwndInsertAfter must be a sibling of the window */
2664 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2666 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2668 if( wnd ) {
2669 if( wnd->parent != wndPtr->parent )
2671 retvalue = FALSE;
2672 WIN_ReleaseWndPtr(wnd);
2673 goto END;
2675 /* don't need to change the Zorder of hwnd if it's already inserted
2676 * after hwndInsertAfter or when inserting hwnd after itself.
2678 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2680 WIN_ReleaseWndPtr(wnd);
2683 Pos: /* ------------------------------------------------------------------------ MAIN part */
2685 /* Fill the WINDOWPOS structure */
2687 winpos.hwnd = hwnd;
2688 winpos.hwndInsertAfter = hwndInsertAfter;
2689 winpos.x = x;
2690 winpos.y = y;
2691 winpos.cx = cx;
2692 winpos.cy = cy;
2693 winpos.flags = flags;
2695 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2697 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2699 if( wndPtr->parent == WIN_GetDesktop() )
2700 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2701 hwndInsertAfter, winpos.flags );
2702 WIN_ReleaseDesktop();
2705 if(!(wndPtr->flags & WIN_NATIVE) )
2707 if( hwndInsertAfter == HWND_TOP )
2708 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2709 else
2710 if( hwndInsertAfter == HWND_BOTTOM )
2711 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2712 else
2713 if( !(winpos.flags & SWP_NOZORDER) )
2714 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2715 winpos.flags |= SWP_NOZORDER;
2717 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2718 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2719 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2721 /* get a previous visible region for SWP_CopyValidBits() */
2722 DWORD dflags = DCX_WINDOW;
2724 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2725 dflags |= DCX_CLIPSIBLINGS;
2727 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2731 /* Common operations */
2733 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2735 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2737 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2738 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2741 /* Reset active DCEs */
2743 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2744 wndPtr->dwStyle & WS_VISIBLE) ||
2745 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2747 RECT rect;
2749 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2750 DCE_InvalidateDCE(wndPtr, &rect);
2753 oldWindowRect = wndPtr->rectWindow;
2754 oldClientRect = wndPtr->rectClient;
2756 /* Find out if we have to redraw the whole client rect */
2758 if( oldClientRect.bottom - oldClientRect.top ==
2759 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2761 if( oldClientRect.right - oldClientRect.left ==
2762 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2764 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2765 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2767 uFlags |= SWP_EX_NOCOPY;
2770 * Use this later in CopyValidBits()
2772 else if( 0 )
2773 uFlags |= SWP_EX_NONCLIENT;
2776 /* FIXME: actually do something with WVR_VALIDRECTS */
2778 wndPtr->rectWindow = newWindowRect;
2779 wndPtr->rectClient = newClientRect;
2781 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2783 BOOL bCallDriver = TRUE;
2784 HWND tempInsertAfter = winpos.hwndInsertAfter;
2786 winpos.hwndInsertAfter = hwndInsertAfter;
2788 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2790 /* This is the only place where we need to force repainting of the contents
2791 of windows created by the host window system, all other cases go through the
2792 expose event handling */
2794 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2796 cx = newWindowRect.right - newWindowRect.left;
2797 cy = newWindowRect.bottom - newWindowRect.top;
2799 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2800 winpos.hwndInsertAfter = tempInsertAfter;
2801 bCallDriver = FALSE;
2803 if( winpos.flags & SWP_NOCLIENTMOVE )
2804 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2805 else
2807 /* client area moved but window extents remained the same, copy valid bits */
2809 visRgn = CreateRectRgn( 0, 0, cx, cy );
2810 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2811 uFlags | SWP_EX_PAINTSELF );
2816 if( bCallDriver )
2818 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2820 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2821 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2822 !(uFlags & SWP_EX_NOCOPY) )
2824 /* The origin of the client rect didn't move so we can try to repaint
2825 * only the nonclient area by setting bit gravity hint for the host window system.
2828 if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
2830 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2831 newWindowRect.bottom - newWindowRect.top);
2832 RECT rcn = newClientRect;
2833 RECT rco = oldClientRect;
2835 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2836 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2837 IntersectRect( &rcn, &rcn, &rco );
2838 visRgn = CreateRectRgnIndirect( &rcn );
2839 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2840 DeleteObject( hrgn );
2841 uFlags = SWP_EX_PAINTSELF;
2843 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2845 else
2846 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2849 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2850 winpos.hwndInsertAfter = tempInsertAfter;
2853 if( winpos.flags & SWP_SHOWWINDOW )
2855 HWND focus, curr;
2857 wndPtr->dwStyle |= WS_VISIBLE;
2859 if (wndPtr->dwExStyle & WS_EX_MANAGED) resync = TRUE;
2861 /* focus was set to unmapped window, reset host focus
2862 * since the window is now visible */
2864 focus = curr = GetFocus();
2865 while (curr)
2867 if (curr == hwnd)
2869 WND *pFocus = WIN_FindWndPtr( focus );
2870 if (pFocus)
2871 pFocus->pDriver->pSetFocus(pFocus);
2872 WIN_ReleaseWndPtr(pFocus);
2873 break;
2875 curr = GetParent(curr);
2879 else /* -------------------------------------------- emulated window */
2881 if( winpos.flags & SWP_SHOWWINDOW )
2883 wndPtr->dwStyle |= WS_VISIBLE;
2884 uFlags |= SWP_EX_PAINTSELF;
2885 visRgn = 1; /* redraw the whole window */
2887 else if( !(winpos.flags & SWP_NOREDRAW) )
2889 if( winpos.flags & SWP_HIDEWINDOW )
2891 if( visRgn > 1 ) /* map to parent */
2892 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2893 else
2894 visRgn = 0;
2896 else
2898 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2900 /* if window was not resized and not moved try to repaint itself */
2901 if((winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) == SWP_AGG_NOGEOMETRYCHANGE)
2902 uFlags |= SWP_EX_PAINTSELF;
2903 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2904 &oldClientRect, uFlags);
2906 else
2908 /* nothing moved, redraw frame if needed */
2910 if( winpos.flags & SWP_FRAMECHANGED )
2911 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2912 if( visRgn )
2914 DeleteObject( visRgn );
2915 visRgn = 0;
2922 if( winpos.flags & SWP_HIDEWINDOW )
2924 wndPtr->dwStyle &= ~WS_VISIBLE;
2927 if (hwnd == CARET_GetHwnd())
2929 if( winpos.flags & SWP_HIDEWINDOW )
2930 HideCaret(hwnd);
2931 else if (winpos.flags & SWP_SHOWWINDOW)
2932 ShowCaret(hwnd);
2935 /* ------------------------------------------------------------------------ FINAL */
2937 if (wndPtr->flags & WIN_NATIVE)
2938 EVENT_Synchronize(); /* Synchronize with the host window system */
2940 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2942 /* Simulate a mouse event to set the cursor */
2943 int iWndsLocks = WIN_SuspendWndsLock();
2945 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2946 PosX, PosY, GetTickCount(), 0 );
2948 WIN_RestoreWndsLock(iWndsLocks);
2951 wndTemp = WIN_GetDesktop();
2953 /* repaint invalidated region (if any)
2955 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2956 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2959 if( visRgn )
2961 if( !(winpos.flags & SWP_NOREDRAW) )
2964 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2965 its parent and sibling and so on, and then erase the parent window
2966 back ground if the parent is either a top-level window or its parent's parent
2967 is top-level window. Rely on the system to repaint other affected
2968 windows later on. */
2969 if( uFlags & SWP_EX_PAINTSELF )
2971 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2972 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2973 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2975 else
2977 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2978 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2979 RDW_EX_USEHRGN );
2982 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2984 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2985 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2988 if( visRgn != 1 )
2989 DeleteObject( visRgn );
2992 WIN_ReleaseDesktop();
2994 if (!(flags & SWP_NOACTIVATE))
2995 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2997 /* And last, send the WM_WINDOWPOSCHANGED message */
2999 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
3001 if ( resync ||
3002 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
3003 !(winpos.flags & SWP_NOSENDCHANGING)) )
3005 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
3006 if (resync) EVENT_Synchronize();
3009 retvalue = TRUE;
3010 END:
3011 WIN_ReleaseWndPtr(wndPtr);
3012 return retvalue;
3016 /***********************************************************************
3017 * BeginDeferWindowPos16 (USER.259)
3019 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
3021 return BeginDeferWindowPos( count );
3025 /***********************************************************************
3026 * BeginDeferWindowPos (USER32.9)
3028 HDWP WINAPI BeginDeferWindowPos( INT count )
3030 HDWP handle;
3031 DWP *pDWP;
3033 if (count < 0)
3035 SetLastError(ERROR_INVALID_PARAMETER);
3036 return 0;
3038 /* Windows allows zero count, in which case it allocates context for 8 moves */
3039 if (count == 0) count = 8;
3041 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
3042 if (!handle) return 0;
3043 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
3044 pDWP->actualCount = 0;
3045 pDWP->suggestedCount = count;
3046 pDWP->valid = TRUE;
3047 pDWP->wMagic = DWP_MAGIC;
3048 pDWP->hwndParent = 0;
3049 return handle;
3053 /***********************************************************************
3054 * DeferWindowPos16 (USER.260)
3056 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
3057 INT16 x, INT16 y, INT16 cx, INT16 cy,
3058 UINT16 flags )
3060 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3061 x, y, cx, cy, flags );
3065 /***********************************************************************
3066 * DeferWindowPos (USER32.128)
3068 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3069 INT x, INT y, INT cx, INT cy,
3070 UINT flags )
3072 DWP *pDWP;
3073 int i;
3074 HDWP newhdwp = hdwp,retvalue;
3075 /* HWND parent; */
3076 WND *pWnd;
3078 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3079 if (!pDWP) return 0;
3080 if (hwnd == GetDesktopWindow()) return 0;
3082 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3083 USER_HEAP_FREE( hdwp );
3084 return 0;
3087 /* Numega Bounds Checker Demo dislikes the following code.
3088 In fact, I've not been able to find any "same parent" requirement in any docu
3089 [AM 980509]
3091 #if 0
3092 /* All the windows of a DeferWindowPos() must have the same parent */
3093 parent = pWnd->parent->hwndSelf;
3094 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3095 else if (parent != pDWP->hwndParent)
3097 USER_HEAP_FREE( hdwp );
3098 retvalue = 0;
3099 goto END;
3101 #endif
3103 for (i = 0; i < pDWP->actualCount; i++)
3105 if (pDWP->winPos[i].hwnd == hwnd)
3107 /* Merge with the other changes */
3108 if (!(flags & SWP_NOZORDER))
3110 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3112 if (!(flags & SWP_NOMOVE))
3114 pDWP->winPos[i].x = x;
3115 pDWP->winPos[i].y = y;
3117 if (!(flags & SWP_NOSIZE))
3119 pDWP->winPos[i].cx = cx;
3120 pDWP->winPos[i].cy = cy;
3122 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3123 SWP_NOZORDER | SWP_NOREDRAW |
3124 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3125 SWP_NOOWNERZORDER);
3126 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3127 SWP_FRAMECHANGED);
3128 retvalue = hdwp;
3129 goto END;
3132 if (pDWP->actualCount >= pDWP->suggestedCount)
3134 newhdwp = USER_HEAP_REALLOC( hdwp,
3135 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3136 if (!newhdwp)
3138 retvalue = 0;
3139 goto END;
3141 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3142 pDWP->suggestedCount++;
3144 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3145 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3146 pDWP->winPos[pDWP->actualCount].x = x;
3147 pDWP->winPos[pDWP->actualCount].y = y;
3148 pDWP->winPos[pDWP->actualCount].cx = cx;
3149 pDWP->winPos[pDWP->actualCount].cy = cy;
3150 pDWP->winPos[pDWP->actualCount].flags = flags;
3151 pDWP->actualCount++;
3152 retvalue = newhdwp;
3153 END:
3154 WIN_ReleaseWndPtr(pWnd);
3155 return retvalue;
3159 /***********************************************************************
3160 * EndDeferWindowPos16 (USER.261)
3162 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3164 return EndDeferWindowPos( hdwp );
3168 /***********************************************************************
3169 * EndDeferWindowPos (USER32.173)
3171 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3173 DWP *pDWP;
3174 WINDOWPOS *winpos;
3175 BOOL res = TRUE;
3176 int i;
3178 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3179 if (!pDWP) return FALSE;
3180 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3182 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3183 winpos->x, winpos->y, winpos->cx,
3184 winpos->cy, winpos->flags ))) break;
3186 USER_HEAP_FREE( hdwp );
3187 return res;
3191 /***********************************************************************
3192 * TileChildWindows (USER.199)
3194 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3196 FIXME("(%04x, %d): stub\n", parent, action);
3199 /***********************************************************************
3200 * CascadeChildWindows (USER.198)
3202 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3204 FIXME("(%04x, %d): stub\n", parent, action);
3207 /***********************************************************************
3208 * SetProgmanWindow [USER32.522]
3210 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3212 hGlobalProgmanWindow = hwnd;
3213 return hGlobalProgmanWindow;
3216 /***********************************************************************
3217 * GetProgmanWindow [USER32.289]
3219 HRESULT WINAPI GetProgmanWindow ( )
3221 return hGlobalProgmanWindow;
3224 /***********************************************************************
3225 * SetShellWindowEx [USER32.531]
3226 * hwndProgman = Progman[Program Manager]
3227 * |-> SHELLDLL_DefView
3228 * hwndListView = | |-> SysListView32
3229 * | | |-> tooltips_class32
3230 * | |
3231 * | |-> SysHeader32
3232 * |
3233 * |-> ProxyTarget
3235 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3237 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3238 hGlobalShellWindow = hwndProgman;
3239 return hGlobalShellWindow;
3243 /***********************************************************************
3244 * SetTaskmanWindow [USER32.537]
3245 * NOTES
3246 * hwnd = MSTaskSwWClass
3247 * |-> SysTabControl32
3249 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3251 hGlobalTaskmanWindow = hwnd;
3252 return hGlobalTaskmanWindow;
3255 /***********************************************************************
3256 * GetTaskmanWindow [USER32.304]
3258 HRESULT WINAPI GetTaskmanWindow ( )
3260 return hGlobalTaskmanWindow;