Use libwine and libwine_unicode directly from their build directory
[wine/multimedia.git] / windows / winpos.c
blobc080c326074d1748d02dc8bfff443f7242b9c67f
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 "heap.h"
15 #include "user.h"
16 #include "region.h"
17 #include "win.h"
18 #include "hook.h"
19 #include "message.h"
20 #include "queue.h"
21 #include "options.h"
22 #include "task.h"
23 #include "winpos.h"
24 #include "dce.h"
25 #include "nonclient.h"
26 #include "debugtools.h"
27 #include "local.h"
28 #include "ldt.h"
29 #include "input.h"
31 DEFAULT_DEBUG_CHANNEL(win);
33 #define HAS_DLGFRAME(style,exStyle) \
34 (((exStyle) & WS_EX_DLGMODALFRAME) || \
35 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
37 #define HAS_THICKFRAME(style) \
38 (((style) & WS_THICKFRAME) && \
39 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
41 #define SWP_AGG_NOGEOMETRYCHANGE \
42 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
43 #define SWP_AGG_NOPOSCHANGE \
44 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
45 #define SWP_AGG_STATUSFLAGS \
46 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
48 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
50 #define PLACE_MIN 0x0001
51 #define PLACE_MAX 0x0002
52 #define PLACE_RECT 0x0004
54 #define SWP_EX_NOCOPY 0x0001
55 #define SWP_EX_PAINTSELF 0x0002
56 #define SWP_EX_NONCLIENT 0x0004
58 #define MINMAX_NOSWP 0x00010000
60 /* ----- internal variables ----- */
62 static HWND hwndPrevActive = 0; /* Previously active window */
63 static HWND hGlobalShellWindow=0; /*the shell*/
64 static HWND hGlobalTaskmanWindow=0;
65 static HWND hGlobalProgmanWindow=0;
67 static LPCSTR atomInternalPos;
69 extern HQUEUE16 hActiveQueue;
71 /***********************************************************************
72 * WINPOS_CreateInternalPosAtom
74 BOOL WINPOS_CreateInternalPosAtom()
76 LPSTR str = "SysIP";
77 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
78 return (atomInternalPos) ? TRUE : FALSE;
81 /***********************************************************************
82 * WINPOS_CheckInternalPos
84 * Called when a window is destroyed.
86 void WINPOS_CheckInternalPos( WND* wndPtr )
88 LPINTERNALPOS lpPos;
89 MESSAGEQUEUE *pMsgQ = 0;
90 HWND hwnd = wndPtr->hwndSelf;
92 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
94 /* Retrieve the message queue associated with this window */
95 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
96 if ( !pMsgQ )
98 WARN("\tMessage queue not found. Exiting!\n" );
99 return;
102 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
104 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
106 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
107 WARN("\tattempt to activate destroyed window!\n");
110 if( lpPos )
112 if( IsWindow(lpPos->hwndIconTitle) )
113 DestroyWindow( lpPos->hwndIconTitle );
114 HeapFree( SystemHeap, 0, lpPos );
117 QUEUE_Unlock( pMsgQ );
118 return;
121 /***********************************************************************
122 * WINPOS_FindIconPos
124 * Find a suitable place for an iconic window.
126 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
128 RECT16 rectParent;
129 short x, y, xspacing, yspacing;
131 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
132 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
133 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
134 return pt; /* The icon already has a suitable position */
136 xspacing = GetSystemMetrics(SM_CXICONSPACING);
137 yspacing = GetSystemMetrics(SM_CYICONSPACING);
139 y = rectParent.bottom;
140 for (;;)
142 x = rectParent.left;
145 /* Check if another icon already occupies this spot */
146 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
147 while (childPtr)
149 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
151 if ((childPtr->rectWindow.left < x + xspacing) &&
152 (childPtr->rectWindow.right >= x) &&
153 (childPtr->rectWindow.top <= y) &&
154 (childPtr->rectWindow.bottom > y - yspacing))
155 break; /* There's a window in there */
157 WIN_UpdateWndPtr(&childPtr,childPtr->next);
159 WIN_ReleaseWndPtr(childPtr);
160 if (!childPtr) /* No window was found, so it's OK for us */
162 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
163 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
164 return pt;
166 x += xspacing;
167 } while(x <= rectParent.right-xspacing);
168 y -= yspacing;
173 /***********************************************************************
174 * ArrangeIconicWindows16 (USER.170)
176 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
178 return ArrangeIconicWindows(parent);
180 /***********************************************************************
181 * ArrangeIconicWindows (USER32.7)
183 UINT WINAPI ArrangeIconicWindows( HWND parent )
185 RECT rectParent;
186 HWND hwndChild;
187 INT x, y, xspacing, yspacing;
189 GetClientRect( parent, &rectParent );
190 x = rectParent.left;
191 y = rectParent.bottom;
192 xspacing = GetSystemMetrics(SM_CXICONSPACING);
193 yspacing = GetSystemMetrics(SM_CYICONSPACING);
195 hwndChild = GetWindow( parent, GW_CHILD );
196 while (hwndChild)
198 if( IsIconic( hwndChild ) )
200 WND *wndPtr = WIN_FindWndPtr(hwndChild);
202 WINPOS_ShowIconTitle( wndPtr, FALSE );
204 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
205 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
206 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
207 if( IsWindow(hwndChild) )
208 WINPOS_ShowIconTitle(wndPtr , TRUE );
209 WIN_ReleaseWndPtr(wndPtr);
211 if (x <= rectParent.right - xspacing) x += xspacing;
212 else
214 x = rectParent.left;
215 y -= yspacing;
218 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
220 return yspacing;
224 /***********************************************************************
225 * SwitchToThisWindow16 (USER.172)
227 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
229 SwitchToThisWindow( hwnd, restore );
233 /***********************************************************************
234 * SwitchToThisWindow (USER32.539)
236 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
238 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
242 /***********************************************************************
243 * GetWindowRect16 (USER.32)
245 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
247 WND * wndPtr = WIN_FindWndPtr( hwnd );
248 if (!wndPtr) return;
250 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
251 if (wndPtr->dwStyle & WS_CHILD)
252 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
253 WIN_ReleaseWndPtr(wndPtr);
257 /***********************************************************************
258 * GetWindowRect (USER32.308)
260 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
262 WND * wndPtr = WIN_FindWndPtr( hwnd );
263 if (!wndPtr) return FALSE;
265 *rect = wndPtr->rectWindow;
266 if (wndPtr->dwStyle & WS_CHILD)
267 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
268 WIN_ReleaseWndPtr(wndPtr);
269 return TRUE;
273 /***********************************************************************
274 * GetWindowRgn (USER32)
276 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
278 int nRet = ERROR;
279 WND *wndPtr = WIN_FindWndPtr( hwnd );
280 if (wndPtr)
282 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
283 WIN_ReleaseWndPtr(wndPtr);
285 return nRet;
288 /***********************************************************************
289 * SetWindowRgn (USER32)
291 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
293 int ret = FALSE;
294 RECT tempRect;
296 WND *wndPtr = WIN_FindWndPtr(hwnd);
298 if (!wndPtr) return FALSE;
300 /* a region exists for this window */
301 if (hrgn != 0 && hrgn == wndPtr->hrgnWnd)
303 /* can't replace actual region with same region
304 since we're now owner of that region
306 SetLastError(ERROR_INVALID_HANDLE);
307 goto done;
311 /* we'd like to set it back to 0 */
312 if (hrgn == 0)
314 GetWindowRect(hwnd, &tempRect);
316 else
318 /* verify that region really exists */
319 if (GetRgnBox(hrgn, &tempRect) == ERROR) goto done;
323 /* Size the window to the rectangle of the new region
324 (if it isn't NULL) */
325 SetWindowPos( hwnd, NULL, tempRect.left, tempRect.top,
326 tempRect.right - tempRect.left, tempRect.bottom - tempRect.top,
327 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE |
328 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
331 if (wndPtr->hrgnWnd)
333 /* delete previous region */
334 DeleteObject(wndPtr->hrgnWnd);
335 wndPtr->hrgnWnd = 0;
337 else if (hrgn == NULL)
339 /* if there was no previous region (stored in wndPtr->hrgnWnd) and
340 the region to be set is also NULL, there is nothing more to do
342 ret = TRUE;
343 goto done;
346 /* valid region handle */
347 wndPtr->hrgnWnd = hrgn;
348 wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn);
350 ret = TRUE;
352 done:
353 WIN_ReleaseWndPtr(wndPtr);
354 return ret;
357 /***********************************************************************
358 * SetWindowRgn16
360 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
364 FIXME("SetWindowRgn16: stub\n");
365 return TRUE;
369 /***********************************************************************
370 * GetClientRect16 (USER.33)
372 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
374 WND * wndPtr = WIN_FindWndPtr( hwnd );
376 rect->left = rect->top = rect->right = rect->bottom = 0;
377 if (wndPtr)
379 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
380 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
382 WIN_ReleaseWndPtr(wndPtr);
386 /***********************************************************************
387 * GetClientRect (USER.220)
389 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
391 WND * wndPtr = WIN_FindWndPtr( hwnd );
393 rect->left = rect->top = rect->right = rect->bottom = 0;
394 if (!wndPtr) return FALSE;
395 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
396 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
398 WIN_ReleaseWndPtr(wndPtr);
399 return TRUE;
403 /*******************************************************************
404 * ClientToScreen16 (USER.28)
406 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
408 MapWindowPoints16( hwnd, 0, lppnt, 1 );
412 /*******************************************************************
413 * ClientToScreen (USER32.52)
415 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
417 MapWindowPoints( hwnd, 0, lppnt, 1 );
418 return TRUE;
422 /*******************************************************************
423 * ScreenToClient16 (USER.29)
425 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
427 MapWindowPoints16( 0, hwnd, lppnt, 1 );
431 /*******************************************************************
432 * ScreenToClient (USER32.447)
434 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
436 MapWindowPoints( 0, hwnd, lppnt, 1 );
437 return TRUE;
441 /***********************************************************************
442 * WINPOS_WindowFromPoint
444 * Find the window and hittest for a given point.
446 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
448 WND *wndPtr;
449 INT16 hittest = HTERROR;
450 INT16 retvalue;
451 POINT16 xy = pt;
453 TRACE("scope %04x %d,%d\n", wndScope->hwndSelf, pt.x, pt.y);
454 *ppWnd = NULL;
455 wndPtr = WIN_LockWndPtr(wndScope->child);
457 if( wndScope->dwStyle & WS_DISABLED )
459 retvalue = HTERROR;
460 goto end;
463 if( wndScope->dwExStyle & WS_EX_MANAGED)
465 /* In managed mode we have to check wndScope first as it is also
466 * a window which received the mouse event. */
468 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
469 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
470 goto hittest;
472 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
474 for (;;)
476 while (wndPtr)
478 /* If point is in window, and window is visible, and it */
479 /* is enabled (or it's a top-level window), then explore */
480 /* its children. Otherwise, go to the next window. */
482 if ((wndPtr->dwStyle & WS_VISIBLE) &&
483 (!(wndPtr->dwStyle & WS_DISABLED) ||
484 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
485 (wndPtr->hrgnWnd ?
486 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
487 xy.y - wndPtr->rectWindow.top) :
488 ((xy.x >= wndPtr->rectWindow.left) &&
489 (xy.x < wndPtr->rectWindow.right) &&
490 (xy.y >= wndPtr->rectWindow.top) &&
491 (xy.y < wndPtr->rectWindow.bottom))))
493 TRACE("%d,%d is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
494 *ppWnd = wndPtr; /* Got a suitable window */
496 /* If window is minimized or disabled, return at once */
497 if (wndPtr->dwStyle & WS_MINIMIZE)
499 retvalue = HTCAPTION;
500 goto end;
502 if (wndPtr->dwStyle & WS_DISABLED)
504 retvalue = HTERROR;
505 goto end;
508 /* If point is not in client area, ignore the children */
509 if ((xy.x < wndPtr->rectClient.left) ||
510 (xy.x >= wndPtr->rectClient.right) ||
511 (xy.y < wndPtr->rectClient.top) ||
512 (xy.y >= wndPtr->rectClient.bottom)) break;
514 xy.x -= wndPtr->rectClient.left;
515 xy.y -= wndPtr->rectClient.top;
516 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
518 else
520 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
524 hittest:
525 /* If nothing found, try the scope window */
526 if (!*ppWnd) *ppWnd = wndScope;
528 /* Send the WM_NCHITTEST message (only if to the same task) */
529 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
531 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
532 0, MAKELONG( pt.x, pt.y ) );
533 if (hittest != HTTRANSPARENT)
535 retvalue = hittest; /* Found the window */
536 goto end;
539 else
541 retvalue = HTCLIENT;
542 goto end;
545 /* If no children found in last search, make point relative to parent */
546 if (!wndPtr)
548 xy.x += (*ppWnd)->rectClient.left;
549 xy.y += (*ppWnd)->rectClient.top;
552 /* Restart the search from the next sibling */
553 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
554 *ppWnd = (*ppWnd)->parent;
557 end:
558 WIN_ReleaseWndPtr(wndPtr);
559 return retvalue;
563 /*******************************************************************
564 * WindowFromPoint16 (USER.30)
566 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
568 WND *pWnd;
569 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
570 WIN_ReleaseDesktop();
571 return pWnd->hwndSelf;
575 /*******************************************************************
576 * WindowFromPoint (USER32.582)
578 HWND WINAPI WindowFromPoint( POINT pt )
580 WND *pWnd;
581 POINT16 pt16;
582 CONV_POINT32TO16( &pt, &pt16 );
583 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
584 WIN_ReleaseDesktop();
585 return (HWND)pWnd->hwndSelf;
589 /*******************************************************************
590 * ChildWindowFromPoint16 (USER.191)
592 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
594 POINT pt32;
595 CONV_POINT16TO32( &pt, &pt32 );
596 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
600 /*******************************************************************
601 * ChildWindowFromPoint (USER32.49)
603 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
605 /* pt is in the client coordinates */
607 WND* wnd = WIN_FindWndPtr(hwndParent);
608 RECT rect;
609 HWND retvalue;
611 if( !wnd ) return 0;
613 /* get client rect fast */
614 rect.top = rect.left = 0;
615 rect.right = wnd->rectClient.right - wnd->rectClient.left;
616 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
618 if (!PtInRect( &rect, pt ))
620 retvalue = 0;
621 goto end;
623 WIN_UpdateWndPtr(&wnd,wnd->child);
624 while ( wnd )
626 if (PtInRect( &wnd->rectWindow, pt ))
628 retvalue = wnd->hwndSelf;
629 goto end;
631 WIN_UpdateWndPtr(&wnd,wnd->next);
633 retvalue = hwndParent;
634 end:
635 WIN_ReleaseWndPtr(wnd);
636 return retvalue;
639 /*******************************************************************
640 * ChildWindowFromPointEx16 (USER.50)
642 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
644 POINT pt32;
645 CONV_POINT16TO32( &pt, &pt32 );
646 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
650 /*******************************************************************
651 * ChildWindowFromPointEx (USER32.50)
653 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
654 UINT uFlags)
656 /* pt is in the client coordinates */
658 WND* wnd = WIN_FindWndPtr(hwndParent);
659 RECT rect;
660 HWND retvalue;
662 if( !wnd ) return 0;
664 /* get client rect fast */
665 rect.top = rect.left = 0;
666 rect.right = wnd->rectClient.right - wnd->rectClient.left;
667 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
669 if (!PtInRect( &rect, pt ))
671 retvalue = 0;
672 goto end;
674 WIN_UpdateWndPtr(&wnd,wnd->child);
676 while ( wnd )
678 if (PtInRect( &wnd->rectWindow, pt )) {
679 if ( (uFlags & CWP_SKIPINVISIBLE) &&
680 !(wnd->dwStyle & WS_VISIBLE) );
681 else if ( (uFlags & CWP_SKIPDISABLED) &&
682 (wnd->dwStyle & WS_DISABLED) );
683 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
684 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
685 else
687 retvalue = wnd->hwndSelf;
688 goto end;
692 WIN_UpdateWndPtr(&wnd,wnd->next);
694 retvalue = hwndParent;
695 end:
696 WIN_ReleaseWndPtr(wnd);
697 return retvalue;
701 /*******************************************************************
702 * WINPOS_GetWinOffset
704 * Calculate the offset between the origin of the two windows. Used
705 * to implement MapWindowPoints.
707 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
708 POINT *offset )
710 WND * wndPtr = 0;
712 offset->x = offset->y = 0;
713 if (hwndFrom == hwndTo ) return;
715 /* Translate source window origin to screen coords */
716 if (hwndFrom)
718 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
720 ERR("bad hwndFrom = %04x\n",hwndFrom);
721 return;
723 while (wndPtr->parent)
725 offset->x += wndPtr->rectClient.left;
726 offset->y += wndPtr->rectClient.top;
727 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
729 WIN_ReleaseWndPtr(wndPtr);
732 /* Translate origin to destination window coords */
733 if (hwndTo)
735 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
737 ERR("bad hwndTo = %04x\n", hwndTo );
738 return;
740 while (wndPtr->parent)
742 offset->x -= wndPtr->rectClient.left;
743 offset->y -= wndPtr->rectClient.top;
744 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
746 WIN_ReleaseWndPtr(wndPtr);
751 /*******************************************************************
752 * MapWindowPoints16 (USER.258)
754 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
755 LPPOINT16 lppt, UINT16 count )
757 POINT offset;
759 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
760 while (count--)
762 lppt->x += offset.x;
763 lppt->y += offset.y;
764 lppt++;
769 /*******************************************************************
770 * MapWindowPoints (USER32.386)
772 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
773 LPPOINT lppt, UINT count )
775 POINT offset;
777 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
778 while (count--)
780 lppt->x += offset.x;
781 lppt->y += offset.y;
782 lppt++;
784 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
788 /***********************************************************************
789 * IsIconic16 (USER.31)
791 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
793 return IsIconic(hWnd);
797 /***********************************************************************
798 * IsIconic (USER32.345)
800 BOOL WINAPI IsIconic(HWND hWnd)
802 BOOL retvalue;
803 WND * wndPtr = WIN_FindWndPtr(hWnd);
804 if (wndPtr == NULL) return FALSE;
805 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
806 WIN_ReleaseWndPtr(wndPtr);
807 return retvalue;
811 /***********************************************************************
812 * IsZoomed (USER.272)
814 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
816 return IsZoomed(hWnd);
820 /***********************************************************************
821 * IsZoomed (USER.352)
823 BOOL WINAPI IsZoomed(HWND hWnd)
825 BOOL retvalue;
826 WND * wndPtr = WIN_FindWndPtr(hWnd);
827 if (wndPtr == NULL) return FALSE;
828 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
829 WIN_ReleaseWndPtr(wndPtr);
830 return retvalue;
834 /*******************************************************************
835 * GetActiveWindow (USER.60)
837 HWND16 WINAPI GetActiveWindow16(void)
839 return (HWND16)GetActiveWindow();
842 /*******************************************************************
843 * GetActiveWindow (USER32.205)
845 HWND WINAPI GetActiveWindow(void)
847 MESSAGEQUEUE *pCurMsgQ = 0;
848 HWND hwndActive = 0;
850 /* Get the messageQ for the current thread */
851 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
853 WARN("\tCurrent message queue not found. Exiting!\n" );
854 return 0;
857 /* Return the current active window from the perQ data of the current message Q */
858 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
860 QUEUE_Unlock( pCurMsgQ );
861 return hwndActive;
865 /*******************************************************************
866 * WINPOS_CanActivate
868 static BOOL WINPOS_CanActivate(WND* pWnd)
870 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
871 == WS_VISIBLE ) ) return TRUE;
872 return FALSE;
876 /*******************************************************************
877 * SetActiveWindow16 (USER.59)
879 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
881 return SetActiveWindow(hwnd);
885 /*******************************************************************
886 * SetActiveWindow (USER32.463)
888 HWND WINAPI SetActiveWindow( HWND hwnd )
890 HWND prev = 0;
891 WND *wndPtr = WIN_FindWndPtr( hwnd );
892 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
894 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
896 prev = 0;
897 goto end;
900 /* Get the messageQ for the current thread */
901 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
903 WARN("\tCurrent message queue not found. Exiting!\n" );
904 goto CLEANUP;
907 /* Retrieve the message queue associated with this window */
908 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
909 if ( !pMsgQ )
911 WARN("\tWindow message queue not found. Exiting!\n" );
912 goto CLEANUP;
915 /* Make sure that the window is associated with the calling threads
916 * message queue. It must share the same perQ data.
919 if ( pCurMsgQ->pQData != pMsgQ->pQData )
920 goto CLEANUP;
922 /* Save current active window */
923 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
925 WINPOS_SetActiveWindow( hwnd, 0, 0 );
927 CLEANUP:
928 /* Unlock the queues before returning */
929 if ( pMsgQ )
930 QUEUE_Unlock( pMsgQ );
931 if ( pCurMsgQ )
932 QUEUE_Unlock( pCurMsgQ );
934 end:
935 WIN_ReleaseWndPtr(wndPtr);
936 return prev;
940 /*******************************************************************
941 * GetForegroundWindow16 (USER.608)
943 HWND16 WINAPI GetForegroundWindow16(void)
945 return (HWND16)GetForegroundWindow();
949 /*******************************************************************
950 * SetForegroundWindow16 (USER.609)
952 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
954 return SetForegroundWindow( hwnd );
958 /*******************************************************************
959 * GetForegroundWindow (USER32.241)
961 HWND WINAPI GetForegroundWindow(void)
963 HWND hwndActive = 0;
965 /* Get the foreground window (active window of hActiveQueue) */
966 if ( hActiveQueue )
968 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
969 if ( pActiveQueue )
970 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
972 QUEUE_Unlock( pActiveQueue );
975 return hwndActive;
978 /*******************************************************************
979 * SetForegroundWindow (USER32.482)
981 BOOL WINAPI SetForegroundWindow( HWND hwnd )
983 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
987 /*******************************************************************
988 * AllowSetForegroundWindow (USER32)
990 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
992 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
993 * implemented, then fix this function. */
994 return TRUE;
998 /*******************************************************************
999 * LockSetForegroundWindow (USER32)
1001 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
1003 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
1004 * implemented, then fix this function. */
1005 return TRUE;
1009 /*******************************************************************
1010 * GetShellWindow16 (USER.600)
1012 HWND16 WINAPI GetShellWindow16(void)
1014 return GetShellWindow();
1017 /*******************************************************************
1018 * SetShellWindow (USER32.504)
1020 HWND WINAPI SetShellWindow(HWND hwndshell)
1021 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
1023 hGlobalShellWindow = hwndshell;
1024 return hGlobalShellWindow;
1028 /*******************************************************************
1029 * GetShellWindow (USER32.287)
1031 HWND WINAPI GetShellWindow(void)
1032 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
1034 return hGlobalShellWindow;
1038 /***********************************************************************
1039 * BringWindowToTop16 (USER.45)
1041 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1043 return BringWindowToTop(hwnd);
1047 /***********************************************************************
1048 * BringWindowToTop (USER32.11)
1050 BOOL WINAPI BringWindowToTop( HWND hwnd )
1052 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1056 /***********************************************************************
1057 * MoveWindow16 (USER.56)
1059 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1060 BOOL16 repaint )
1062 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1066 /***********************************************************************
1067 * MoveWindow (USER32.399)
1069 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1070 BOOL repaint )
1072 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1073 if (!repaint) flags |= SWP_NOREDRAW;
1074 TRACE("%04x %d,%d %dx%d %d\n",
1075 hwnd, x, y, cx, cy, repaint );
1076 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1079 /***********************************************************************
1080 * WINPOS_InitInternalPos
1082 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1083 LPRECT restoreRect )
1085 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1086 atomInternalPos );
1087 if( !lpPos )
1089 /* this happens when the window is minimized/maximized
1090 * for the first time (rectWindow is not adjusted yet) */
1092 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1093 if( !lpPos ) return NULL;
1095 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1096 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1097 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1098 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1101 if( wnd->dwStyle & WS_MINIMIZE )
1102 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1103 else if( wnd->dwStyle & WS_MAXIMIZE )
1104 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1105 else if( restoreRect )
1106 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1108 return lpPos;
1111 /***********************************************************************
1112 * WINPOS_RedrawIconTitle
1114 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1116 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1117 if( lpPos )
1119 if( lpPos->hwndIconTitle )
1121 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1122 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1123 return TRUE;
1126 return FALSE;
1129 /***********************************************************************
1130 * WINPOS_ShowIconTitle
1132 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1134 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1136 if( lpPos && !(pWnd->dwExStyle & WS_EX_MANAGED))
1138 HWND16 hWnd = lpPos->hwndIconTitle;
1140 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1142 if( !hWnd )
1143 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1144 if( bShow )
1146 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1148 if( !(pWnd->dwStyle & WS_VISIBLE) )
1150 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1151 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1152 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1154 WIN_ReleaseWndPtr(pWnd);
1157 else ShowWindow( hWnd, SW_HIDE );
1159 return FALSE;
1162 /*******************************************************************
1163 * WINPOS_GetMinMaxInfo
1165 * Get the minimized and maximized information for a window.
1167 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1168 POINT *minTrack, POINT *maxTrack )
1170 LPINTERNALPOS lpPos;
1171 MINMAXINFO MinMax;
1172 INT xinc, yinc;
1174 /* Compute default values */
1176 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1177 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1178 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1179 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1180 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1181 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1183 if (wndPtr->dwExStyle & WS_EX_MANAGED) xinc = yinc = 0;
1184 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1186 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1187 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1189 else
1191 xinc = yinc = 0;
1192 if (HAS_THICKFRAME(wndPtr->dwStyle))
1194 xinc += GetSystemMetrics(SM_CXFRAME);
1195 yinc += GetSystemMetrics(SM_CYFRAME);
1197 if (wndPtr->dwStyle & WS_BORDER)
1199 xinc += GetSystemMetrics(SM_CXBORDER);
1200 yinc += GetSystemMetrics(SM_CYBORDER);
1203 MinMax.ptMaxSize.x += 2 * xinc;
1204 MinMax.ptMaxSize.y += 2 * yinc;
1206 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1207 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1208 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1209 else
1211 MinMax.ptMaxPosition.x = -xinc;
1212 MinMax.ptMaxPosition.y = -yinc;
1215 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1217 /* Some sanity checks */
1219 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1220 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1221 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1222 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1223 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1224 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1225 MinMax.ptMinTrackSize.x );
1226 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1227 MinMax.ptMinTrackSize.y );
1229 if (maxSize) *maxSize = MinMax.ptMaxSize;
1230 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1231 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1232 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1235 /***********************************************************************
1236 * WINPOS_MinMaximize
1238 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1239 * This function assumes that 'cmd' is different from the current window
1240 * state.
1242 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1244 UINT swpFlags = 0;
1245 POINT pt, size;
1246 LPINTERNALPOS lpPos;
1248 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1250 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1251 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1253 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1255 if( wndPtr->dwStyle & WS_MINIMIZE )
1257 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1258 return (SWP_NOSIZE | SWP_NOMOVE);
1259 swpFlags |= SWP_NOCOPYBITS;
1261 switch( cmd )
1263 case SW_MINIMIZE:
1264 if( wndPtr->dwStyle & WS_MAXIMIZE)
1266 wndPtr->flags |= WIN_RESTORE_MAX;
1267 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1269 else
1270 wndPtr->flags &= ~WIN_RESTORE_MAX;
1271 wndPtr->dwStyle |= WS_MINIMIZE;
1273 if( wndPtr->flags & WIN_NATIVE )
1274 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1275 swpFlags |= MINMAX_NOSWP;
1277 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1279 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1280 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1281 swpFlags |= SWP_NOCOPYBITS;
1282 break;
1284 case SW_MAXIMIZE:
1285 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1286 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1287 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1289 if( wndPtr->dwStyle & WS_MINIMIZE )
1291 if( wndPtr->flags & WIN_NATIVE )
1292 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1294 WINPOS_ShowIconTitle( wndPtr, FALSE );
1295 wndPtr->dwStyle &= ~WS_MINIMIZE;
1297 wndPtr->dwStyle |= WS_MAXIMIZE;
1299 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1300 size.x, size.y );
1301 break;
1303 case SW_RESTORE:
1304 if( wndPtr->dwStyle & WS_MINIMIZE )
1306 if( wndPtr->flags & WIN_NATIVE )
1307 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1308 swpFlags |= MINMAX_NOSWP;
1310 wndPtr->dwStyle &= ~WS_MINIMIZE;
1311 WINPOS_ShowIconTitle( wndPtr, FALSE );
1313 if( wndPtr->flags & WIN_RESTORE_MAX)
1315 /* Restore to maximized position */
1316 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1317 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1318 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1319 wndPtr->dwStyle |= WS_MAXIMIZE;
1320 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1321 break;
1324 else
1325 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1326 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1328 /* Restore to normal position */
1330 *lpRect = lpPos->rectNormal;
1331 lpRect->right -= lpRect->left;
1332 lpRect->bottom -= lpRect->top;
1334 break;
1336 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1337 return swpFlags;
1340 /***********************************************************************
1341 * ShowWindowAsync (USER32.535)
1343 * doesn't wait; returns immediately.
1344 * used by threads to toggle windows in other (possibly hanging) threads
1346 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1348 /* FIXME: does ShowWindow() return immediately ? */
1349 return ShowWindow(hwnd, cmd);
1353 /***********************************************************************
1354 * ShowWindow16 (USER.42)
1356 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1358 return ShowWindow(hwnd,cmd);
1362 /***********************************************************************
1363 * ShowWindow (USER32.534)
1365 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1367 WND* wndPtr = WIN_FindWndPtr( hwnd );
1368 BOOL wasVisible, showFlag;
1369 RECT16 newPos = {0, 0, 0, 0};
1370 UINT swp = 0;
1372 if (!wndPtr) return FALSE;
1374 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1376 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1378 switch(cmd)
1380 case SW_HIDE:
1381 if (!wasVisible) goto END;;
1382 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1383 SWP_NOACTIVATE | SWP_NOZORDER;
1384 break;
1386 case SW_SHOWMINNOACTIVE:
1387 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1388 /* fall through */
1389 case SW_SHOWMINIMIZED:
1390 swp |= SWP_SHOWWINDOW;
1391 /* fall through */
1392 case SW_MINIMIZE:
1393 swp |= SWP_FRAMECHANGED;
1394 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1395 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1396 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1397 break;
1399 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1400 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1401 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1402 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1403 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1404 break;
1406 case SW_SHOWNA:
1407 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1408 /* fall through */
1409 case SW_SHOW:
1410 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1413 * ShowWindow has a little peculiar behavior that if the
1414 * window is already the topmost window, it will not
1415 * activate it.
1417 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1418 swp |= SWP_NOACTIVATE;
1420 break;
1422 case SW_SHOWNOACTIVATE:
1423 swp |= SWP_NOZORDER;
1424 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1425 /* fall through */
1426 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1427 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1428 case SW_RESTORE:
1429 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1431 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1432 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1433 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1434 break;
1437 showFlag = (cmd != SW_HIDE);
1438 if (showFlag != wasVisible)
1440 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1441 if (!IsWindow( hwnd )) goto END;
1444 if ((wndPtr->dwStyle & WS_CHILD) &&
1445 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1446 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1448 /* Don't call SetWindowPos() on invisible child windows */
1449 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1450 else wndPtr->dwStyle |= WS_VISIBLE;
1452 else
1454 /* We can't activate a child window */
1455 if ((wndPtr->dwStyle & WS_CHILD) &&
1456 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1457 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1458 if (!(swp & MINMAX_NOSWP))
1460 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1461 newPos.right, newPos.bottom, LOWORD(swp) );
1462 if (cmd == SW_HIDE)
1464 /* FIXME: This will cause the window to be activated irrespective
1465 * of whether it is owned by the same thread. Has to be done
1466 * asynchronously.
1469 if (hwnd == GetActiveWindow())
1470 WINPOS_ActivateOtherWindow(wndPtr);
1472 /* Revert focus to parent */
1473 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1474 SetFocus( GetParent(hwnd) );
1477 if (!IsWindow( hwnd )) goto END;
1478 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1481 if (wndPtr->flags & WIN_NEED_SIZE)
1483 /* should happen only in CreateWindowEx() */
1484 int wParam = SIZE_RESTORED;
1486 wndPtr->flags &= ~WIN_NEED_SIZE;
1487 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1488 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1489 SendMessageA( hwnd, WM_SIZE, wParam,
1490 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1491 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1492 SendMessageA( hwnd, WM_MOVE, 0,
1493 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1496 END:
1497 WIN_ReleaseWndPtr(wndPtr);
1498 return wasVisible;
1502 /***********************************************************************
1503 * GetInternalWindowPos16 (USER.460)
1505 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1506 LPPOINT16 ptIcon )
1508 WINDOWPLACEMENT16 wndpl;
1509 if (GetWindowPlacement16( hwnd, &wndpl ))
1511 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1512 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1513 return wndpl.showCmd;
1515 return 0;
1519 /***********************************************************************
1520 * GetInternalWindowPos (USER32.245)
1522 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1523 LPPOINT ptIcon )
1525 WINDOWPLACEMENT wndpl;
1526 if (GetWindowPlacement( hwnd, &wndpl ))
1528 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1529 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1530 return wndpl.showCmd;
1532 return 0;
1535 /***********************************************************************
1536 * GetWindowPlacement16 (USER.370)
1538 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1540 WND *pWnd = WIN_FindWndPtr( hwnd );
1541 LPINTERNALPOS lpPos;
1543 if(!pWnd ) return FALSE;
1545 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1546 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1547 wndpl->length = sizeof(*wndpl);
1548 if( pWnd->dwStyle & WS_MINIMIZE )
1549 wndpl->showCmd = SW_SHOWMINIMIZED;
1550 else
1551 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1552 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1553 if( pWnd->flags & WIN_RESTORE_MAX )
1554 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1555 else
1556 wndpl->flags = 0;
1557 wndpl->ptMinPosition = lpPos->ptIconPos;
1558 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1559 wndpl->rcNormalPosition = lpPos->rectNormal;
1561 WIN_ReleaseWndPtr(pWnd);
1562 return TRUE;
1566 /***********************************************************************
1567 * GetWindowPlacement (USER32.307)
1569 * Win95:
1570 * Fails if wndpl->length of Win95 (!) apps is invalid.
1572 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1574 if( pwpl32 )
1576 WINDOWPLACEMENT16 wpl;
1577 wpl.length = sizeof(wpl);
1578 if( GetWindowPlacement16( hwnd, &wpl ) )
1580 pwpl32->length = sizeof(*pwpl32);
1581 pwpl32->flags = wpl.flags;
1582 pwpl32->showCmd = wpl.showCmd;
1583 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1584 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1585 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1586 return TRUE;
1589 return FALSE;
1593 /***********************************************************************
1594 * WINPOS_SetPlacement
1596 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1597 UINT flags )
1599 WND *pWnd = WIN_FindWndPtr( hwnd );
1600 if( pWnd )
1602 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1603 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1605 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1606 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1607 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1609 if( pWnd->dwStyle & WS_MINIMIZE )
1611 WINPOS_ShowIconTitle( pWnd, FALSE );
1612 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1613 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1614 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1616 else if( pWnd->dwStyle & WS_MAXIMIZE )
1618 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1619 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1620 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1622 else if( flags & PLACE_RECT )
1623 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1624 lpPos->rectNormal.right - lpPos->rectNormal.left,
1625 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1626 SWP_NOZORDER | SWP_NOACTIVATE );
1628 ShowWindow( hwnd, wndpl->showCmd );
1629 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1631 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1633 /* SDK: ...valid only the next time... */
1634 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1636 WIN_ReleaseWndPtr(pWnd);
1637 return TRUE;
1639 return FALSE;
1643 /***********************************************************************
1644 * SetWindowPlacement16 (USER.371)
1646 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1648 return WINPOS_SetPlacement( hwnd, wndpl,
1649 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1652 /***********************************************************************
1653 * SetWindowPlacement (USER32.519)
1655 * Win95:
1656 * Fails if wndpl->length of Win95 (!) apps is invalid.
1658 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1660 if( pwpl32 )
1662 WINDOWPLACEMENT16 wpl;
1664 wpl.length = sizeof(WINDOWPLACEMENT16);
1665 wpl.flags = pwpl32->flags;
1666 wpl.showCmd = pwpl32->showCmd;
1667 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1668 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1669 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1670 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1671 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1672 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1673 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1674 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1676 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1678 return FALSE;
1682 /***********************************************************************
1683 * SetInternalWindowPos16 (USER.461)
1685 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1686 LPRECT16 rect, LPPOINT16 pt )
1688 if( IsWindow16(hwnd) )
1690 WINDOWPLACEMENT16 wndpl;
1691 UINT flags;
1693 wndpl.length = sizeof(wndpl);
1694 wndpl.showCmd = showCmd;
1695 wndpl.flags = flags = 0;
1697 if( pt )
1699 flags |= PLACE_MIN;
1700 wndpl.flags |= WPF_SETMINPOSITION;
1701 wndpl.ptMinPosition = *pt;
1703 if( rect )
1705 flags |= PLACE_RECT;
1706 wndpl.rcNormalPosition = *rect;
1708 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1713 /***********************************************************************
1714 * SetInternalWindowPos (USER32.483)
1716 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1717 LPRECT rect, LPPOINT pt )
1719 if( IsWindow(hwnd) )
1721 WINDOWPLACEMENT16 wndpl;
1722 UINT flags;
1724 wndpl.length = sizeof(wndpl);
1725 wndpl.showCmd = showCmd;
1726 wndpl.flags = flags = 0;
1728 if( pt )
1730 flags |= PLACE_MIN;
1731 wndpl.flags |= WPF_SETMINPOSITION;
1732 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1734 if( rect )
1736 flags |= PLACE_RECT;
1737 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1739 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1743 /*******************************************************************
1744 * WINPOS_SetActiveWindow
1746 * SetActiveWindow() back-end. This is the only function that
1747 * can assign active status to a window. It must be called only
1748 * for the top level windows.
1750 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1752 CBTACTIVATESTRUCT16* cbtStruct;
1753 WND* wndPtr=0, *wndTemp;
1754 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1755 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1756 WORD wIconized = 0;
1757 HWND hwndActive = 0;
1758 BOOL bRet = 0;
1760 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1762 /* Get current active window from the active queue */
1763 if ( hActiveQueue )
1765 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1766 if ( pOldActiveQueue )
1767 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1770 /* paranoid checks */
1771 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1772 goto CLEANUP_END;
1774 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1775 * return 0;
1777 wndPtr = WIN_FindWndPtr(hWnd);
1778 hOldActiveQueue = hActiveQueue;
1780 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1782 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1783 WIN_ReleaseWndPtr(wndTemp);
1785 else
1786 TRACE("no current active window.\n");
1788 /* call CBT hook chain */
1789 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1791 cbtStruct->fMouse = fMouse;
1792 cbtStruct->hWndActive = hwndActive;
1793 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1794 (LPARAM)SEGPTR_GET(cbtStruct) );
1795 SEGPTR_FREE(cbtStruct);
1796 if (bRet) goto CLEANUP_END;
1799 /* set prev active wnd to current active wnd and send notification */
1800 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1802 MESSAGEQUEUE *pTempActiveQueue = 0;
1804 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1806 if (GetSysModalWindow16() != hWnd)
1807 goto CLEANUP_END;
1808 /* disregard refusal if hWnd is sysmodal */
1811 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1812 MAKEWPARAM( WA_INACTIVE, wIconized ),
1813 (LPARAM)hWnd );
1815 /* check if something happened during message processing
1816 * (global active queue may have changed)
1818 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1819 if(!pTempActiveQueue)
1820 goto CLEANUP_END;
1822 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1823 QUEUE_Unlock( pTempActiveQueue );
1824 if( hwndPrevActive != hwndActive )
1825 goto CLEANUP_END;
1828 /* Set new active window in the message queue */
1829 hwndActive = hWnd;
1830 if ( wndPtr )
1832 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1833 if ( pNewActiveQueue )
1834 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1836 else /* have to do this or MDI frame activation goes to hell */
1837 if( pOldActiveQueue )
1838 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1840 /* send palette messages */
1841 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1842 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1844 /* if prev wnd is minimized redraw icon title */
1845 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1847 /* managed windows will get ConfigureNotify event */
1848 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1850 /* check Z-order and bring hWnd to the top */
1851 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1853 if (wndTemp->dwStyle & WS_VISIBLE) break;
1855 WIN_ReleaseDesktop();
1856 WIN_ReleaseWndPtr(wndTemp);
1858 if( wndTemp != wndPtr )
1859 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1860 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1861 if (!IsWindow(hWnd))
1862 goto CLEANUP;
1865 /* Get a handle to the new active queue */
1866 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1868 /* send WM_ACTIVATEAPP if necessary */
1869 if (hOldActiveQueue != hNewActiveQueue)
1871 WND **list, **ppWnd;
1872 WND *pDesktop = WIN_GetDesktop();
1874 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1876 for (ppWnd = list; *ppWnd; ppWnd++)
1878 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1880 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1881 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1882 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1884 WIN_ReleaseWinArray(list);
1887 hActiveQueue = hNewActiveQueue;
1889 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1891 for (ppWnd = list; *ppWnd; ppWnd++)
1893 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1895 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1896 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1897 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1899 WIN_ReleaseWinArray(list);
1901 WIN_ReleaseDesktop();
1903 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1906 if (hWnd)
1908 /* walk up to the first unowned window */
1909 wndTemp = WIN_LockWndPtr(wndPtr);
1910 while (wndTemp->owner)
1912 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1914 /* and set last active owned popup */
1915 wndTemp->hwndLastActive = hWnd;
1917 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1918 WIN_ReleaseWndPtr(wndTemp);
1919 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1920 SendMessageA( hWnd, WM_ACTIVATE,
1921 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1922 (LPARAM)hwndPrevActive );
1923 if( !IsWindow(hWnd) ) goto CLEANUP;
1926 /* change focus if possible */
1927 if ( fChangeFocus )
1929 if ( pNewActiveQueue )
1931 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1933 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1934 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1935 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1936 0 : hwndActive );
1939 if ( pOldActiveQueue &&
1940 ( !pNewActiveQueue ||
1941 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1943 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1944 if ( hOldFocus )
1945 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1949 if( !hwndPrevActive && wndPtr )
1950 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1952 /* if active wnd is minimized redraw icon title */
1953 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1955 bRet = (hWnd == hwndActive); /* Success? */
1957 CLEANUP: /* Unlock the message queues before returning */
1959 if ( pNewActiveQueue )
1960 QUEUE_Unlock( pNewActiveQueue );
1962 CLEANUP_END:
1964 if ( pOldActiveQueue )
1965 QUEUE_Unlock( pOldActiveQueue );
1967 WIN_ReleaseWndPtr(wndPtr);
1968 return bRet;
1971 /*******************************************************************
1972 * WINPOS_ActivateOtherWindow
1974 * Activates window other than pWnd.
1976 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1978 BOOL bRet = 0;
1979 WND* pWndTo = NULL;
1980 HWND hwndActive = 0;
1982 /* Get current active window from the active queue */
1983 if ( hActiveQueue )
1985 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1986 if ( pActiveQueue )
1988 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1989 QUEUE_Unlock( pActiveQueue );
1993 if( pWnd->hwndSelf == hwndPrevActive )
1994 hwndPrevActive = 0;
1996 if( hwndActive != pWnd->hwndSelf &&
1997 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1998 return 0;
2000 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
2001 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
2003 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
2005 WIN_ReleaseWndPtr(pWndTo);
2006 pWndTo = WIN_FindWndPtr(hwndPrevActive);
2008 while( !WINPOS_CanActivate(pWndTo) )
2010 /* by now owned windows should've been taken care of */
2011 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
2012 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
2013 if( !pWndTo ) break;
2015 WIN_ReleaseWndPtr(pWndPtr);
2018 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
2020 /* switch desktop queue to current active */
2021 if( pWndTo )
2023 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
2024 WIN_ReleaseWndPtr(pWndTo);
2025 WIN_ReleaseDesktop();
2028 hwndPrevActive = 0;
2029 return bRet;
2032 /*******************************************************************
2033 * WINPOS_ChangeActiveWindow
2036 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2038 WND *wndPtr, *wndTemp;
2039 BOOL retvalue;
2040 HWND hwndActive = 0;
2042 /* Get current active window from the active queue */
2043 if ( hActiveQueue )
2045 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2046 if ( pActiveQueue )
2048 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2049 QUEUE_Unlock( pActiveQueue );
2053 if (!hWnd)
2054 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2056 wndPtr = WIN_FindWndPtr(hWnd);
2057 if( !wndPtr ) return FALSE;
2059 /* child windows get WM_CHILDACTIVATE message */
2060 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2062 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2063 goto end;
2066 if( hWnd == hwndActive )
2068 retvalue = FALSE;
2069 goto end;
2072 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2074 retvalue = FALSE;
2075 goto end;
2078 /* switch desktop queue to current active */
2079 wndTemp = WIN_GetDesktop();
2080 if( wndPtr->parent == wndTemp)
2081 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2082 WIN_ReleaseDesktop();
2084 retvalue = TRUE;
2085 end:
2086 WIN_ReleaseWndPtr(wndPtr);
2087 return retvalue;
2091 /***********************************************************************
2092 * WINPOS_SendNCCalcSize
2094 * Send a WM_NCCALCSIZE message to a window.
2095 * All parameters are read-only except newClientRect.
2096 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2097 * when calcValidRect is TRUE.
2099 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2100 RECT *newWindowRect, RECT *oldWindowRect,
2101 RECT *oldClientRect, WINDOWPOS *winpos,
2102 RECT *newClientRect )
2104 NCCALCSIZE_PARAMS params;
2105 WINDOWPOS winposCopy;
2106 LONG result;
2108 params.rgrc[0] = *newWindowRect;
2109 if (calcValidRect)
2111 winposCopy = *winpos;
2112 params.rgrc[1] = *oldWindowRect;
2113 params.rgrc[2] = *oldClientRect;
2114 params.lppos = &winposCopy;
2116 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2117 (LPARAM)&params );
2118 TRACE("%d,%d-%d,%d\n",
2119 params.rgrc[0].left, params.rgrc[0].top,
2120 params.rgrc[0].right, params.rgrc[0].bottom );
2122 /* If the application send back garbage, ignore it */
2123 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2124 *newClientRect = params.rgrc[0];
2126 return result;
2130 /***********************************************************************
2131 * WINPOS_HandleWindowPosChanging16
2133 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2135 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2137 POINT maxSize, minTrack;
2138 if (winpos->flags & SWP_NOSIZE) return 0;
2139 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2140 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2142 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2143 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2144 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2145 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2147 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2148 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2151 return 0;
2155 /***********************************************************************
2156 * WINPOS_HandleWindowPosChanging
2158 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2160 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2162 POINT maxSize;
2163 if (winpos->flags & SWP_NOSIZE) return 0;
2164 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2165 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2167 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2168 winpos->cx = min( winpos->cx, maxSize.x );
2169 winpos->cy = min( winpos->cy, maxSize.y );
2171 return 0;
2174 /***********************************************************************
2175 * SWP_DoOwnedPopups
2177 * fix Z order taking into account owned popups -
2178 * basically we need to maintain them above the window that owns them
2180 * FIXME: hide/show owned popups when owner visibility changes.
2182 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2184 WND* w = WIN_LockWndPtr(pDesktop->child);
2186 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2188 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2190 /* make sure this popup stays above the owner */
2192 HWND hwndLocalPrev = HWND_TOP;
2194 if( hwndInsertAfter != HWND_TOP )
2196 while( w != wndPtr->owner )
2198 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2199 if( hwndLocalPrev == hwndInsertAfter ) break;
2200 WIN_UpdateWndPtr(&w,w->next);
2202 hwndInsertAfter = hwndLocalPrev;
2205 else if( wndPtr->dwStyle & WS_CHILD )
2206 goto END;
2208 WIN_UpdateWndPtr(&w, pDesktop->child);
2210 while( w )
2212 if( w == wndPtr ) break;
2214 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2216 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2217 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2218 hwndInsertAfter = w->hwndSelf;
2220 WIN_UpdateWndPtr(&w, w->next);
2223 END:
2224 WIN_ReleaseWndPtr(w);
2225 return hwndInsertAfter;
2228 /***********************************************************************
2229 * SWP_CopyValidBits
2231 * Make window look nice without excessive repainting
2233 * visible and update regions are in window coordinates
2234 * client and window rectangles are in parent client coordinates
2236 * Returns: uFlags and a dirty region in *pVisRgn.
2238 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2239 LPRECT lpOldWndRect,
2240 LPRECT lpOldClientRect, UINT uFlags )
2242 RECT r;
2243 HRGN newVisRgn, dirtyRgn;
2244 INT my = COMPLEXREGION;
2246 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2247 Wnd->rectWindow.left, Wnd->rectWindow.top,
2248 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2249 lpOldWndRect->left, lpOldWndRect->top,
2250 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2251 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2252 Wnd->rectClient.left, Wnd->rectClient.top,
2253 Wnd->rectClient.right, Wnd->rectClient.bottom,
2254 lpOldClientRect->left, lpOldClientRect->top,
2255 lpOldClientRect->right,lpOldClientRect->bottom );
2257 if( Wnd->hrgnUpdate == 1 )
2258 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2260 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2261 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2263 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2264 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2266 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2268 nocopy:
2270 TRACE("\twon't copy anything!\n");
2272 /* set dirtyRgn to the sum of old and new visible regions
2273 * in parent client coordinates */
2275 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2276 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2278 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2280 else /* copy valid bits to a new location */
2282 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2283 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2285 /* subtract already invalid region inside Wnd from the dst region */
2287 if( Wnd->hrgnUpdate )
2288 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2289 goto nocopy;
2291 /* check if entire window can be copied */
2293 ow = lpOldWndRect->right - lpOldWndRect->left;
2294 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2295 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2296 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2298 ocw = lpOldClientRect->right - lpOldClientRect->left;
2299 och = lpOldClientRect->bottom - lpOldClientRect->top;
2300 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2301 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2303 if( (ocw != ncw) || (och != nch) ||
2304 ( ow != nw) || ( oh != nh) ||
2305 ((lpOldClientRect->top - lpOldWndRect->top) !=
2306 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2307 ((lpOldClientRect->left - lpOldWndRect->left) !=
2308 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2310 if(uFlags & SWP_EX_PAINTSELF)
2312 /* movement relative to the window itself */
2313 dx = (Wnd->rectClient.left - Wnd->rectWindow.left) -
2314 (lpOldClientRect->left - lpOldWndRect->left) ;
2315 dy = (Wnd->rectClient.top - Wnd->rectWindow.top) -
2316 (lpOldClientRect->top - lpOldWndRect->top) ;
2318 else
2320 /* movement relative to the parent's client area */
2321 dx = Wnd->rectClient.left - lpOldClientRect->left;
2322 dy = Wnd->rectClient.top - lpOldClientRect->top;
2325 /* restrict valid bits to the common client rect */
2327 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2328 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2329 r.right = r.left + min( ocw, ncw );
2330 r.bottom = r.top + min( och, nch );
2332 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2333 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2334 GetRgnBox( hrgnValid, &r );
2335 if( IsRectEmpty( &r ) )
2336 goto nocopy;
2337 r = *lpOldClientRect;
2339 else
2341 if(uFlags & SWP_EX_PAINTSELF) {
2343 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2344 * relative to itself, only the client area can change.
2345 * if the client rect didn't change, there's nothing to do.
2347 dx = 0;
2348 dy = 0;
2350 else
2352 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2353 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2354 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2356 r = *lpOldWndRect;
2359 if( !(uFlags & SWP_EX_PAINTSELF) )
2361 /* Move remaining regions to parent coordinates */
2362 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2363 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2365 else
2366 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2368 TRACE("\tcomputing dirty region!\n");
2370 /* Compute combined dirty region (old + new - valid) */
2371 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2372 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2374 /* Blt valid bits, r is the rect to copy */
2376 if( dx || dy )
2378 RECT rClip;
2379 HDC hDC;
2381 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2382 from copying clipped areas */
2384 if( uFlags & SWP_EX_PAINTSELF )
2386 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2387 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2388 rClip.right = nw; rClip.bottom = nh;
2390 else
2392 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2393 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2394 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2395 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2397 rClip.left = rClip.top = 0;
2399 if( oh > nh ) r.bottom = r.top + nh;
2400 if( ow < nw ) r.right = r.left + nw;
2402 if( IntersectRect( &r, &r, &rClip ) )
2404 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2406 /* When you copy the bits without repainting, parent doesn't
2407 get validated appropriately. Therefore, we have to validate
2408 the parent with the windows' updated region when the
2409 parent's update region is not empty. */
2411 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2413 OffsetRect(&r, dx, dy);
2414 ValidateRect(Wnd->parent->hwndSelf, &r);
2417 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2418 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2422 /* *pVisRgn now points to the invalidated region */
2424 DeleteObject(newVisRgn);
2425 DeleteObject(dirtyRgn);
2426 return uFlags;
2429 /***********************************************************************
2430 * SWP_DoSimpleFrameChanged
2432 * NOTE: old and new client rect origins are identical, only
2433 * extents may have changed. Window extents are the same.
2435 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2437 INT i = 0;
2438 RECT rect;
2439 HRGN hrgn = 0;
2441 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2443 /* Client rect changed its position/size, most likely a scrollar
2444 * was added/removed.
2446 * FIXME: WVR alignment flags
2449 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2451 i++;
2452 rect.top = 0;
2453 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2454 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2455 if(!(uFlags & SWP_EX_NOCOPY))
2456 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2457 else
2459 rect.left = 0;
2460 goto redraw;
2464 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2466 if( i )
2467 hrgn = CreateRectRgnIndirect( &rect );
2468 rect.left = 0;
2469 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2470 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2471 if(!(uFlags & SWP_EX_NOCOPY))
2472 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2473 else
2474 rect.top = 0;
2475 if( i++ )
2476 REGION_UnionRectWithRgn( hrgn, &rect );
2479 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2481 rect = wndPtr->rectWindow;
2482 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2483 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2484 i++;
2488 if( i )
2490 redraw:
2491 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2492 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2494 else
2496 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2499 if( hrgn > 1 )
2500 DeleteObject( hrgn );
2503 /***********************************************************************
2504 * SWP_DoWinPosChanging
2506 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2507 RECT* pNewWindowRect, RECT* pNewClientRect )
2509 /* Send WM_WINDOWPOSCHANGING message */
2511 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2512 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2514 /* Calculate new position and size */
2516 *pNewWindowRect = wndPtr->rectWindow;
2517 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2518 : wndPtr->rectClient;
2520 if (!(pWinpos->flags & SWP_NOSIZE))
2522 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2523 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2525 if (!(pWinpos->flags & SWP_NOMOVE))
2527 pNewWindowRect->left = pWinpos->x;
2528 pNewWindowRect->top = pWinpos->y;
2529 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2530 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2532 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2533 pWinpos->y - wndPtr->rectWindow.top );
2536 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2537 return TRUE;
2540 /***********************************************************************
2541 * SWP_DoNCCalcSize
2543 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2544 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2546 UINT wvrFlags = 0;
2548 /* Send WM_NCCALCSIZE message to get new client area */
2549 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2551 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2552 &wndPtr->rectWindow, &wndPtr->rectClient,
2553 pWinpos, pNewClientRect );
2555 /* FIXME: WVR_ALIGNxxx */
2557 if( pNewClientRect->left != wndPtr->rectClient.left ||
2558 pNewClientRect->top != wndPtr->rectClient.top )
2559 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2561 if( (pNewClientRect->right - pNewClientRect->left !=
2562 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2563 (pNewClientRect->bottom - pNewClientRect->top !=
2564 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2565 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2567 else
2568 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2569 pNewClientRect->top != wndPtr->rectClient.top) )
2570 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2571 return wvrFlags;
2574 /***********************************************************************
2575 * SetWindowPos (USER.2)
2577 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2578 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2580 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2583 /***********************************************************************
2584 * SetWindowPos (USER32.520)
2586 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2587 INT x, INT y, INT cx, INT cy, UINT flags )
2589 WINDOWPOS winpos;
2590 WND * wndPtr,*wndTemp;
2591 RECT newWindowRect, newClientRect;
2592 RECT oldWindowRect, oldClientRect;
2593 HRGN visRgn = 0;
2594 UINT wvrFlags = 0, uFlags = 0;
2595 BOOL retvalue, resync = FALSE, bChangePos;
2596 HWND hwndActive = 0;
2598 /* Get current active window from the active queue */
2599 if ( hActiveQueue )
2601 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2602 if ( pActiveQueue )
2604 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2605 QUEUE_Unlock( pActiveQueue );
2609 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2610 hwnd, x, y, x+cx, y+cy, flags);
2612 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2613 flags &= ~SWP_WINE_NOHOSTMOVE;
2616 /* ------------------------------------------------------------------------ CHECKS */
2618 /* Check window handle */
2620 if (hwnd == GetDesktopWindow()) return FALSE;
2621 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2623 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2624 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2626 /* Fix redundant flags */
2628 if(wndPtr->dwStyle & WS_VISIBLE)
2629 flags &= ~SWP_SHOWWINDOW;
2630 else
2632 if (!(flags & SWP_SHOWWINDOW))
2633 flags |= SWP_NOREDRAW;
2634 flags &= ~SWP_HIDEWINDOW;
2637 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2639 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2640 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2641 flags |= SWP_NOSIZE; /* Already the right size */
2643 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2644 flags |= SWP_NOMOVE; /* Already the right position */
2646 if (hwnd == hwndActive)
2647 flags |= SWP_NOACTIVATE; /* Already active */
2648 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2650 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2652 flags &= ~SWP_NOZORDER;
2653 hwndInsertAfter = HWND_TOP;
2654 goto Pos;
2658 /* Check hwndInsertAfter */
2660 /* FIXME: TOPMOST not supported yet */
2661 if ((hwndInsertAfter == HWND_TOPMOST) ||
2662 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2664 /* hwndInsertAfter must be a sibling of the window */
2665 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2667 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2669 if( wnd ) {
2670 if( wnd->parent != wndPtr->parent )
2672 retvalue = FALSE;
2673 WIN_ReleaseWndPtr(wnd);
2674 goto END;
2676 /* don't need to change the Zorder of hwnd if it's already inserted
2677 * after hwndInsertAfter or when inserting hwnd after itself.
2679 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2681 WIN_ReleaseWndPtr(wnd);
2684 Pos: /* ------------------------------------------------------------------------ MAIN part */
2686 /* Fill the WINDOWPOS structure */
2688 winpos.hwnd = hwnd;
2689 winpos.hwndInsertAfter = hwndInsertAfter;
2690 winpos.x = x;
2691 winpos.y = y;
2692 winpos.cx = cx;
2693 winpos.cy = cy;
2694 winpos.flags = flags;
2696 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2698 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2700 if( wndPtr->parent == WIN_GetDesktop() )
2701 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2702 hwndInsertAfter, winpos.flags );
2703 WIN_ReleaseDesktop();
2706 if(!(wndPtr->flags & WIN_NATIVE) )
2708 if( hwndInsertAfter == HWND_TOP )
2709 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2710 else
2711 if( hwndInsertAfter == HWND_BOTTOM )
2712 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2713 else
2714 if( !(winpos.flags & SWP_NOZORDER) )
2715 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2716 winpos.flags |= SWP_NOZORDER;
2718 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2719 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2720 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2722 /* get a previous visible region for SWP_CopyValidBits() */
2723 DWORD dflags = DCX_WINDOW;
2725 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2726 dflags |= DCX_CLIPSIBLINGS;
2728 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2732 /* Common operations */
2734 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2736 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2738 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2739 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2742 /* Reset active DCEs */
2744 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2745 wndPtr->dwStyle & WS_VISIBLE) ||
2746 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2748 RECT rect;
2750 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2751 DCE_InvalidateDCE(wndPtr, &rect);
2754 oldWindowRect = wndPtr->rectWindow;
2755 oldClientRect = wndPtr->rectClient;
2757 /* Find out if we have to redraw the whole client rect */
2759 if( oldClientRect.bottom - oldClientRect.top ==
2760 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2762 if( oldClientRect.right - oldClientRect.left ==
2763 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2765 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2766 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2768 uFlags |= SWP_EX_NOCOPY;
2771 * Use this later in CopyValidBits()
2773 else if( 0 )
2774 uFlags |= SWP_EX_NONCLIENT;
2777 /* FIXME: actually do something with WVR_VALIDRECTS */
2779 wndPtr->rectWindow = newWindowRect;
2780 wndPtr->rectClient = newClientRect;
2782 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2784 BOOL bCallDriver = TRUE;
2785 HWND tempInsertAfter = winpos.hwndInsertAfter;
2787 winpos.hwndInsertAfter = hwndInsertAfter;
2789 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2791 /* This is the only place where we need to force repainting of the contents
2792 of windows created by the host window system, all other cases go through the
2793 expose event handling */
2795 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2797 cx = newWindowRect.right - newWindowRect.left;
2798 cy = newWindowRect.bottom - newWindowRect.top;
2800 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2801 winpos.hwndInsertAfter = tempInsertAfter;
2802 bCallDriver = FALSE;
2804 if( winpos.flags & SWP_NOCLIENTMOVE )
2805 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2806 else
2808 /* client area moved but window extents remained the same, copy valid bits */
2810 visRgn = CreateRectRgn( 0, 0, cx, cy );
2811 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2812 uFlags | SWP_EX_PAINTSELF );
2817 if( bCallDriver )
2819 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2821 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2822 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2823 !(uFlags & SWP_EX_NOCOPY) )
2825 /* The origin of the client rect didn't move so we can try to repaint
2826 * only the nonclient area by setting bit gravity hint for the host window system.
2829 if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
2831 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2832 newWindowRect.bottom - newWindowRect.top);
2833 RECT rcn = newClientRect;
2834 RECT rco = oldClientRect;
2836 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2837 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2838 IntersectRect( &rcn, &rcn, &rco );
2839 visRgn = CreateRectRgnIndirect( &rcn );
2840 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2841 DeleteObject( hrgn );
2842 uFlags = SWP_EX_PAINTSELF;
2844 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2846 else
2847 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2850 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2851 winpos.hwndInsertAfter = tempInsertAfter;
2854 if( winpos.flags & SWP_SHOWWINDOW )
2856 HWND focus, curr;
2858 wndPtr->dwStyle |= WS_VISIBLE;
2860 if (wndPtr->dwExStyle & WS_EX_MANAGED) resync = TRUE;
2862 /* focus was set to unmapped window, reset host focus
2863 * since the window is now visible */
2865 focus = curr = GetFocus();
2866 while (curr)
2868 if (curr == hwnd)
2870 WND *pFocus = WIN_FindWndPtr( focus );
2871 if (pFocus)
2872 pFocus->pDriver->pSetFocus(pFocus);
2873 WIN_ReleaseWndPtr(pFocus);
2874 break;
2876 curr = GetParent(curr);
2880 else /* -------------------------------------------- emulated window */
2882 if( winpos.flags & SWP_SHOWWINDOW )
2884 wndPtr->dwStyle |= WS_VISIBLE;
2885 uFlags |= SWP_EX_PAINTSELF;
2886 visRgn = 1; /* redraw the whole window */
2888 else if( !(winpos.flags & SWP_NOREDRAW) )
2890 if( winpos.flags & SWP_HIDEWINDOW )
2892 if( visRgn > 1 ) /* map to parent */
2893 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2894 else
2895 visRgn = 0;
2897 else
2899 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2901 /* if window was not resized and not moved try to repaint itself */
2902 if((winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) == SWP_AGG_NOGEOMETRYCHANGE)
2903 uFlags |= SWP_EX_PAINTSELF;
2904 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2905 &oldClientRect, uFlags);
2907 else
2909 /* nothing moved, redraw frame if needed */
2911 if( winpos.flags & SWP_FRAMECHANGED )
2912 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2913 if( visRgn )
2915 DeleteObject( visRgn );
2916 visRgn = 0;
2923 if( winpos.flags & SWP_HIDEWINDOW )
2925 wndPtr->dwStyle &= ~WS_VISIBLE;
2928 if (hwnd == CARET_GetHwnd())
2930 if( winpos.flags & SWP_HIDEWINDOW )
2931 HideCaret(hwnd);
2932 else if (winpos.flags & SWP_SHOWWINDOW)
2933 ShowCaret(hwnd);
2936 /* ------------------------------------------------------------------------ FINAL */
2938 if (wndPtr->flags & WIN_NATIVE)
2939 EVENT_Synchronize(); /* Synchronize with the host window system */
2941 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2943 /* Simulate a mouse event to set the cursor */
2944 int iWndsLocks = WIN_SuspendWndsLock();
2946 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2947 PosX, PosY, GetTickCount(), 0 );
2949 WIN_RestoreWndsLock(iWndsLocks);
2952 wndTemp = WIN_GetDesktop();
2954 /* repaint invalidated region (if any)
2956 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2957 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2960 if( visRgn )
2962 if( !(winpos.flags & SWP_NOREDRAW) )
2965 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2966 its parent and sibling and so on, and then erase the parent window
2967 back ground if the parent is either a top-level window or its parent's parent
2968 is top-level window. Rely on the system to repaint other affected
2969 windows later on. */
2970 if( uFlags & SWP_EX_PAINTSELF )
2972 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2973 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2974 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2976 else
2978 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2979 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2980 RDW_EX_USEHRGN );
2983 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2985 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2986 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2989 if( visRgn != 1 )
2990 DeleteObject( visRgn );
2993 WIN_ReleaseDesktop();
2995 if (!(flags & SWP_NOACTIVATE))
2996 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2998 /* And last, send the WM_WINDOWPOSCHANGED message */
3000 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
3002 if ( resync ||
3003 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
3004 !(winpos.flags & SWP_NOSENDCHANGING)) )
3006 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
3007 if (resync) EVENT_Synchronize();
3010 retvalue = TRUE;
3011 END:
3012 WIN_ReleaseWndPtr(wndPtr);
3013 return retvalue;
3017 /***********************************************************************
3018 * BeginDeferWindowPos16 (USER.259)
3020 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
3022 return BeginDeferWindowPos( count );
3026 /***********************************************************************
3027 * BeginDeferWindowPos (USER32.9)
3029 HDWP WINAPI BeginDeferWindowPos( INT count )
3031 HDWP handle;
3032 DWP *pDWP;
3034 if (count < 0)
3036 SetLastError(ERROR_INVALID_PARAMETER);
3037 return 0;
3039 /* Windows allows zero count, in which case it allocates context for 8 moves */
3040 if (count == 0) count = 8;
3042 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
3043 if (!handle) return 0;
3044 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
3045 pDWP->actualCount = 0;
3046 pDWP->suggestedCount = count;
3047 pDWP->valid = TRUE;
3048 pDWP->wMagic = DWP_MAGIC;
3049 pDWP->hwndParent = 0;
3050 return handle;
3054 /***********************************************************************
3055 * DeferWindowPos16 (USER.260)
3057 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
3058 INT16 x, INT16 y, INT16 cx, INT16 cy,
3059 UINT16 flags )
3061 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3062 x, y, cx, cy, flags );
3066 /***********************************************************************
3067 * DeferWindowPos (USER32.128)
3069 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3070 INT x, INT y, INT cx, INT cy,
3071 UINT flags )
3073 DWP *pDWP;
3074 int i;
3075 HDWP newhdwp = hdwp,retvalue;
3076 /* HWND parent; */
3077 WND *pWnd;
3079 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3080 if (!pDWP) return 0;
3081 if (hwnd == GetDesktopWindow()) return 0;
3083 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3084 USER_HEAP_FREE( hdwp );
3085 return 0;
3088 /* Numega Bounds Checker Demo dislikes the following code.
3089 In fact, I've not been able to find any "same parent" requirement in any docu
3090 [AM 980509]
3092 #if 0
3093 /* All the windows of a DeferWindowPos() must have the same parent */
3094 parent = pWnd->parent->hwndSelf;
3095 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3096 else if (parent != pDWP->hwndParent)
3098 USER_HEAP_FREE( hdwp );
3099 retvalue = 0;
3100 goto END;
3102 #endif
3104 for (i = 0; i < pDWP->actualCount; i++)
3106 if (pDWP->winPos[i].hwnd == hwnd)
3108 /* Merge with the other changes */
3109 if (!(flags & SWP_NOZORDER))
3111 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3113 if (!(flags & SWP_NOMOVE))
3115 pDWP->winPos[i].x = x;
3116 pDWP->winPos[i].y = y;
3118 if (!(flags & SWP_NOSIZE))
3120 pDWP->winPos[i].cx = cx;
3121 pDWP->winPos[i].cy = cy;
3123 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3124 SWP_NOZORDER | SWP_NOREDRAW |
3125 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3126 SWP_NOOWNERZORDER);
3127 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3128 SWP_FRAMECHANGED);
3129 retvalue = hdwp;
3130 goto END;
3133 if (pDWP->actualCount >= pDWP->suggestedCount)
3135 newhdwp = USER_HEAP_REALLOC( hdwp,
3136 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3137 if (!newhdwp)
3139 retvalue = 0;
3140 goto END;
3142 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3143 pDWP->suggestedCount++;
3145 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3146 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3147 pDWP->winPos[pDWP->actualCount].x = x;
3148 pDWP->winPos[pDWP->actualCount].y = y;
3149 pDWP->winPos[pDWP->actualCount].cx = cx;
3150 pDWP->winPos[pDWP->actualCount].cy = cy;
3151 pDWP->winPos[pDWP->actualCount].flags = flags;
3152 pDWP->actualCount++;
3153 retvalue = newhdwp;
3154 END:
3155 WIN_ReleaseWndPtr(pWnd);
3156 return retvalue;
3160 /***********************************************************************
3161 * EndDeferWindowPos16 (USER.261)
3163 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3165 return EndDeferWindowPos( hdwp );
3169 /***********************************************************************
3170 * EndDeferWindowPos (USER32.173)
3172 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3174 DWP *pDWP;
3175 WINDOWPOS *winpos;
3176 BOOL res = TRUE;
3177 int i;
3179 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3180 if (!pDWP) return FALSE;
3181 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3183 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3184 winpos->x, winpos->y, winpos->cx,
3185 winpos->cy, winpos->flags ))) break;
3187 USER_HEAP_FREE( hdwp );
3188 return res;
3192 /***********************************************************************
3193 * TileChildWindows (USER.199)
3195 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3197 FIXME("(%04x, %d): stub\n", parent, action);
3200 /***********************************************************************
3201 * CascadeChildWindows (USER.198)
3203 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3205 FIXME("(%04x, %d): stub\n", parent, action);
3208 /***********************************************************************
3209 * SetProgmanWindow [USER32.522]
3211 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3213 hGlobalProgmanWindow = hwnd;
3214 return hGlobalProgmanWindow;
3217 /***********************************************************************
3218 * GetProgmanWindow [USER32.289]
3220 HRESULT WINAPI GetProgmanWindow ( )
3222 return hGlobalProgmanWindow;
3225 /***********************************************************************
3226 * SetShellWindowEx [USER32.531]
3227 * hwndProgman = Progman[Program Manager]
3228 * |-> SHELLDLL_DefView
3229 * hwndListView = | |-> SysListView32
3230 * | | |-> tooltips_class32
3231 * | |
3232 * | |-> SysHeader32
3233 * |
3234 * |-> ProxyTarget
3236 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3238 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3239 hGlobalShellWindow = hwndProgman;
3240 return hGlobalShellWindow;
3244 /***********************************************************************
3245 * SetTaskmanWindow [USER32.537]
3246 * NOTES
3247 * hwnd = MSTaskSwWClass
3248 * |-> SysTabControl32
3250 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3252 hGlobalTaskmanWindow = hwnd;
3253 return hGlobalTaskmanWindow;
3256 /***********************************************************************
3257 * GetTaskmanWindow [USER32.304]
3259 HRESULT WINAPI GetTaskmanWindow ( )
3261 return hGlobalTaskmanWindow;