Some applications call GlobalMemoryStatus() very often. Cache the
[wine/dcerpc.git] / windows / winpos.c
blobba42028bac46e1dd3c544599e325e25e4605f2aa
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 "windef.h"
10 #include "wingdi.h"
11 #include "wine/winuser16.h"
12 #include "heap.h"
13 #include "module.h"
14 #include "user.h"
15 #include "region.h"
16 #include "win.h"
17 #include "hook.h"
18 #include "message.h"
19 #include "queue.h"
20 #include "options.h"
21 #include "task.h"
22 #include "winpos.h"
23 #include "dce.h"
24 #include "nonclient.h"
25 #include "debugtools.h"
26 #include "local.h"
27 #include "ldt.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
275 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
278 RECT rect;
279 WND * wndPtr = WIN_FindWndPtr( hwnd );
280 if (!wndPtr) return (ERROR);
282 FIXME("GetWindowRgn: doesn't really do regions\n");
284 memset (&rect, 0, sizeof(rect));
286 GetWindowRect ( hwnd, &rect );
288 FIXME("Check whether a valid region here\n");
290 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
292 WIN_ReleaseWndPtr(wndPtr);
293 return (SIMPLEREGION);
296 /***********************************************************************
297 * SetWindowRgn
299 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
303 FIXME("SetWindowRgn: stub\n");
304 return TRUE;
307 /***********************************************************************
308 * SetWindowRgn16
310 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
314 FIXME("SetWindowRgn16: stub\n");
315 return TRUE;
319 /***********************************************************************
320 * GetClientRect16 (USER.33)
322 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
324 WND * wndPtr = WIN_FindWndPtr( hwnd );
326 rect->left = rect->top = rect->right = rect->bottom = 0;
327 if (wndPtr)
329 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
330 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
332 WIN_ReleaseWndPtr(wndPtr);
336 /***********************************************************************
337 * GetClientRect (USER.220)
339 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
341 WND * wndPtr = WIN_FindWndPtr( hwnd );
343 rect->left = rect->top = rect->right = rect->bottom = 0;
344 if (!wndPtr) return FALSE;
345 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
346 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
348 WIN_ReleaseWndPtr(wndPtr);
349 return TRUE;
353 /*******************************************************************
354 * ClientToScreen16 (USER.28)
356 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
358 MapWindowPoints16( hwnd, 0, lppnt, 1 );
362 /*******************************************************************
363 * ClientToScreen (USER32.52)
365 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
367 MapWindowPoints( hwnd, 0, lppnt, 1 );
368 return TRUE;
372 /*******************************************************************
373 * ScreenToClient16 (USER.29)
375 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
377 MapWindowPoints16( 0, hwnd, lppnt, 1 );
381 /*******************************************************************
382 * ScreenToClient (USER32.447)
384 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
386 MapWindowPoints( 0, hwnd, lppnt, 1 );
387 return TRUE;
391 /***********************************************************************
392 * WINPOS_WindowFromPoint
394 * Find the window and hittest for a given point.
396 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
398 WND *wndPtr;
399 INT16 hittest = HTERROR;
400 INT16 retvalue;
401 POINT16 xy = pt;
403 *ppWnd = NULL;
404 wndPtr = WIN_LockWndPtr(wndScope->child);
406 if( wndScope->flags & WIN_MANAGED )
408 /* In managed mode we have to check wndScope first as it is also
409 * a window which received the mouse event. */
411 if( wndScope->dwStyle & WS_DISABLED )
413 retvalue = HTERROR;
414 goto end;
416 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
417 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
418 goto hittest;
420 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
422 for (;;)
424 while (wndPtr)
426 /* If point is in window, and window is visible, and it */
427 /* is enabled (or it's a top-level window), then explore */
428 /* its children. Otherwise, go to the next window. */
430 if ((wndPtr->dwStyle & WS_VISIBLE) &&
431 (!(wndPtr->dwStyle & WS_DISABLED) ||
432 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
433 (xy.x >= wndPtr->rectWindow.left) &&
434 (xy.x < wndPtr->rectWindow.right) &&
435 (xy.y >= wndPtr->rectWindow.top) &&
436 (xy.y < wndPtr->rectWindow.bottom))
438 *ppWnd = wndPtr; /* Got a suitable window */
440 /* If window is minimized or disabled, return at once */
441 if (wndPtr->dwStyle & WS_MINIMIZE)
443 retvalue = HTCAPTION;
444 goto end;
446 if (wndPtr->dwStyle & WS_DISABLED)
448 retvalue = HTERROR;
449 goto end;
452 /* If point is not in client area, ignore the children */
453 if ((xy.x < wndPtr->rectClient.left) ||
454 (xy.x >= wndPtr->rectClient.right) ||
455 (xy.y < wndPtr->rectClient.top) ||
456 (xy.y >= wndPtr->rectClient.bottom)) break;
458 xy.x -= wndPtr->rectClient.left;
459 xy.y -= wndPtr->rectClient.top;
460 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
462 else
464 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
468 hittest:
469 /* If nothing found, try the scope window */
470 if (!*ppWnd) *ppWnd = wndScope;
472 /* Send the WM_NCHITTEST message (only if to the same task) */
473 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
475 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
476 0, MAKELONG( pt.x, pt.y ) );
477 if (hittest != HTTRANSPARENT)
479 retvalue = hittest; /* Found the window */
480 goto end;
483 else
485 retvalue = HTCLIENT;
486 goto end;
489 /* If no children found in last search, make point relative to parent */
490 if (!wndPtr)
492 xy.x += (*ppWnd)->rectClient.left;
493 xy.y += (*ppWnd)->rectClient.top;
496 /* Restart the search from the next sibling */
497 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
498 *ppWnd = (*ppWnd)->parent;
501 end:
502 WIN_ReleaseWndPtr(wndPtr);
503 return retvalue;
507 /*******************************************************************
508 * WindowFromPoint16 (USER.30)
510 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
512 WND *pWnd;
513 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
514 WIN_ReleaseDesktop();
515 return pWnd->hwndSelf;
519 /*******************************************************************
520 * WindowFromPoint (USER32.582)
522 HWND WINAPI WindowFromPoint( POINT pt )
524 WND *pWnd;
525 POINT16 pt16;
526 CONV_POINT32TO16( &pt, &pt16 );
527 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
528 WIN_ReleaseDesktop();
529 return (HWND)pWnd->hwndSelf;
533 /*******************************************************************
534 * ChildWindowFromPoint16 (USER.191)
536 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
538 POINT pt32;
539 CONV_POINT16TO32( &pt, &pt32 );
540 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
544 /*******************************************************************
545 * ChildWindowFromPoint (USER32.49)
547 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
549 /* pt is in the client coordinates */
551 WND* wnd = WIN_FindWndPtr(hwndParent);
552 RECT rect;
553 HWND retvalue;
555 if( !wnd ) return 0;
557 /* get client rect fast */
558 rect.top = rect.left = 0;
559 rect.right = wnd->rectClient.right - wnd->rectClient.left;
560 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
562 if (!PtInRect( &rect, pt ))
564 retvalue = 0;
565 goto end;
567 WIN_UpdateWndPtr(&wnd,wnd->child);
568 while ( wnd )
570 if (PtInRect( &wnd->rectWindow, pt ))
572 retvalue = wnd->hwndSelf;
573 goto end;
575 WIN_UpdateWndPtr(&wnd,wnd->next);
577 retvalue = hwndParent;
578 end:
579 WIN_ReleaseWndPtr(wnd);
580 return retvalue;
583 /*******************************************************************
584 * ChildWindowFromPointEx16 (USER.50)
586 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
588 POINT pt32;
589 CONV_POINT16TO32( &pt, &pt32 );
590 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
594 /*******************************************************************
595 * ChildWindowFromPointEx32 (USER32.50)
597 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
598 UINT uFlags)
600 /* pt is in the client coordinates */
602 WND* wnd = WIN_FindWndPtr(hwndParent);
603 RECT rect;
604 HWND retvalue;
606 if( !wnd ) return 0;
608 /* get client rect fast */
609 rect.top = rect.left = 0;
610 rect.right = wnd->rectClient.right - wnd->rectClient.left;
611 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
613 if (!PtInRect( &rect, pt ))
615 retvalue = 0;
616 goto end;
618 WIN_UpdateWndPtr(&wnd,wnd->child);
620 while ( wnd )
622 if (PtInRect( &wnd->rectWindow, pt )) {
623 if ( (uFlags & CWP_SKIPINVISIBLE) &&
624 !(wnd->dwStyle & WS_VISIBLE) );
625 else if ( (uFlags & CWP_SKIPDISABLED) &&
626 (wnd->dwStyle & WS_DISABLED) );
627 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
628 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
629 else
631 retvalue = wnd->hwndSelf;
632 goto end;
636 WIN_UpdateWndPtr(&wnd,wnd->next);
638 retvalue = hwndParent;
639 end:
640 WIN_ReleaseWndPtr(wnd);
641 return retvalue;
645 /*******************************************************************
646 * WINPOS_GetWinOffset
648 * Calculate the offset between the origin of the two windows. Used
649 * to implement MapWindowPoints.
651 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
652 POINT *offset )
654 WND * wndPtr = 0;
656 offset->x = offset->y = 0;
657 if (hwndFrom == hwndTo ) return;
659 /* Translate source window origin to screen coords */
660 if (hwndFrom)
662 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
664 ERR("bad hwndFrom = %04x\n",hwndFrom);
665 return;
667 while (wndPtr->parent)
669 offset->x += wndPtr->rectClient.left;
670 offset->y += wndPtr->rectClient.top;
671 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
673 WIN_ReleaseWndPtr(wndPtr);
676 /* Translate origin to destination window coords */
677 if (hwndTo)
679 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
681 ERR("bad hwndTo = %04x\n", hwndTo );
682 return;
684 while (wndPtr->parent)
686 offset->x -= wndPtr->rectClient.left;
687 offset->y -= wndPtr->rectClient.top;
688 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
690 WIN_ReleaseWndPtr(wndPtr);
695 /*******************************************************************
696 * MapWindowPoints16 (USER.258)
698 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
699 LPPOINT16 lppt, UINT16 count )
701 POINT offset;
703 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
704 while (count--)
706 lppt->x += offset.x;
707 lppt->y += offset.y;
708 lppt++;
713 /*******************************************************************
714 * MapWindowPoints (USER32.386)
716 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
717 LPPOINT lppt, UINT count )
719 POINT offset;
721 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
722 while (count--)
724 lppt->x += offset.x;
725 lppt->y += offset.y;
726 lppt++;
728 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
732 /***********************************************************************
733 * IsIconic16 (USER.31)
735 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
737 return IsIconic(hWnd);
741 /***********************************************************************
742 * IsIconic (USER32.345)
744 BOOL WINAPI IsIconic(HWND hWnd)
746 BOOL retvalue;
747 WND * wndPtr = WIN_FindWndPtr(hWnd);
748 if (wndPtr == NULL) return FALSE;
749 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
750 WIN_ReleaseWndPtr(wndPtr);
751 return retvalue;
755 /***********************************************************************
756 * IsZoomed (USER.272)
758 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
760 return IsZoomed(hWnd);
764 /***********************************************************************
765 * IsZoomed (USER.352)
767 BOOL WINAPI IsZoomed(HWND hWnd)
769 BOOL retvalue;
770 WND * wndPtr = WIN_FindWndPtr(hWnd);
771 if (wndPtr == NULL) return FALSE;
772 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
773 WIN_ReleaseWndPtr(wndPtr);
774 return retvalue;
778 /*******************************************************************
779 * GetActiveWindow (USER.60)
781 HWND16 WINAPI GetActiveWindow16(void)
783 return (HWND16)GetActiveWindow();
786 /*******************************************************************
787 * GetActiveWindow (USER32.205)
789 HWND WINAPI GetActiveWindow(void)
791 MESSAGEQUEUE *pCurMsgQ = 0;
792 HWND hwndActive = 0;
794 /* Get the messageQ for the current thread */
795 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
797 WARN("\tCurrent message queue not found. Exiting!\n" );
798 return 0;
801 /* Return the current active window from the perQ data of the current message Q */
802 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
804 QUEUE_Unlock( pCurMsgQ );
805 return hwndActive;
809 /*******************************************************************
810 * WINPOS_CanActivate
812 static BOOL WINPOS_CanActivate(WND* pWnd)
814 if( pWnd && !(pWnd->dwStyle & (WS_DISABLED | WS_CHILD)) ) return TRUE;
815 return FALSE;
819 /*******************************************************************
820 * SetActiveWindow16 (USER.59)
822 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
824 return SetActiveWindow(hwnd);
828 /*******************************************************************
829 * SetActiveWindow (USER32.463)
831 HWND WINAPI SetActiveWindow( HWND hwnd )
833 HWND prev = 0;
834 WND *wndPtr = WIN_FindWndPtr( hwnd );
835 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
837 if ( !WINPOS_CanActivate(wndPtr) )
839 prev = 0;
840 goto end;
843 /* Get the messageQ for the current thread */
844 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
846 WARN("\tCurrent message queue not found. Exiting!\n" );
847 goto CLEANUP;
850 /* Retrieve the message queue associated with this window */
851 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
852 if ( !pMsgQ )
854 WARN("\tWindow message queue not found. Exiting!\n" );
855 goto CLEANUP;
858 /* Make sure that the window is associated with the calling threads
859 * message queue. It must share the same perQ data.
862 if ( pCurMsgQ->pQData != pMsgQ->pQData )
863 goto CLEANUP;
865 /* Save current active window */
866 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
868 WINPOS_SetActiveWindow( hwnd, 0, 0 );
870 CLEANUP:
871 /* Unlock the queues before returning */
872 if ( pMsgQ )
873 QUEUE_Unlock( pMsgQ );
874 if ( pCurMsgQ )
875 QUEUE_Unlock( pCurMsgQ );
877 end:
878 WIN_ReleaseWndPtr(wndPtr);
879 return prev;
883 /*******************************************************************
884 * GetForegroundWindow16 (USER.608)
886 HWND16 WINAPI GetForegroundWindow16(void)
888 return (HWND16)GetForegroundWindow();
892 /*******************************************************************
893 * SetForegroundWindow16 (USER.609)
895 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
897 return SetForegroundWindow( hwnd );
901 /*******************************************************************
902 * GetForegroundWindow (USER32.241)
904 HWND WINAPI GetForegroundWindow(void)
906 HWND hwndActive = 0;
908 /* Get the foreground window (active window of hActiveQueue) */
909 if ( hActiveQueue )
911 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
912 if ( pActiveQueue )
913 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
915 QUEUE_Unlock( pActiveQueue );
918 return hwndActive;
921 /*******************************************************************
922 * SetForegroundWindow (USER32.482)
924 BOOL WINAPI SetForegroundWindow( HWND hwnd )
926 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
930 /*******************************************************************
931 * GetShellWindow16 (USER.600)
933 HWND16 WINAPI GetShellWindow16(void)
935 return GetShellWindow();
938 /*******************************************************************
939 * SetShellWindow (USER32.504)
941 HWND WINAPI SetShellWindow(HWND hwndshell)
942 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
944 hGlobalShellWindow = hwndshell;
945 return hGlobalShellWindow;
949 /*******************************************************************
950 * GetShellWindow (USER32.287)
952 HWND WINAPI GetShellWindow(void)
953 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
955 return hGlobalShellWindow;
959 /***********************************************************************
960 * BringWindowToTop16 (USER.45)
962 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
964 return BringWindowToTop(hwnd);
968 /***********************************************************************
969 * BringWindowToTop (USER32.11)
971 BOOL WINAPI BringWindowToTop( HWND hwnd )
973 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
977 /***********************************************************************
978 * MoveWindow16 (USER.56)
980 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
981 BOOL16 repaint )
983 return MoveWindow(hwnd,x,y,cx,cy,repaint);
987 /***********************************************************************
988 * MoveWindow (USER32.399)
990 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
991 BOOL repaint )
993 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
994 if (!repaint) flags |= SWP_NOREDRAW;
995 TRACE("%04x %d,%d %dx%d %d\n",
996 hwnd, x, y, cx, cy, repaint );
997 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1000 /***********************************************************************
1001 * WINPOS_InitInternalPos
1003 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1004 LPRECT restoreRect )
1006 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1007 atomInternalPos );
1008 if( !lpPos )
1010 /* this happens when the window is minimized/maximized
1011 * for the first time (rectWindow is not adjusted yet) */
1013 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1014 if( !lpPos ) return NULL;
1016 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1017 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1018 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1019 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1022 if( wnd->dwStyle & WS_MINIMIZE )
1023 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1024 else if( wnd->dwStyle & WS_MAXIMIZE )
1025 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1026 else if( restoreRect )
1027 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1029 return lpPos;
1032 /***********************************************************************
1033 * WINPOS_RedrawIconTitle
1035 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1037 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1038 if( lpPos )
1040 if( lpPos->hwndIconTitle )
1042 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1043 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1044 return TRUE;
1047 return FALSE;
1050 /***********************************************************************
1051 * WINPOS_ShowIconTitle
1053 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1055 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1057 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1059 HWND16 hWnd = lpPos->hwndIconTitle;
1061 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1063 if( !hWnd )
1064 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1065 if( bShow )
1067 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1069 if( !(pWnd->dwStyle & WS_VISIBLE) )
1071 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1072 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1073 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1075 WIN_ReleaseWndPtr(pWnd);
1078 else ShowWindow( hWnd, SW_HIDE );
1080 return FALSE;
1083 /*******************************************************************
1084 * WINPOS_GetMinMaxInfo
1086 * Get the minimized and maximized information for a window.
1088 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1089 POINT *minTrack, POINT *maxTrack )
1091 LPINTERNALPOS lpPos;
1092 MINMAXINFO MinMax;
1093 INT xinc, yinc;
1095 /* Compute default values */
1097 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1098 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1099 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1100 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1101 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1102 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1104 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1105 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1107 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1108 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1110 else
1112 xinc = yinc = 0;
1113 if (HAS_THICKFRAME(wndPtr->dwStyle))
1115 xinc += GetSystemMetrics(SM_CXFRAME);
1116 yinc += GetSystemMetrics(SM_CYFRAME);
1118 if (wndPtr->dwStyle & WS_BORDER)
1120 xinc += GetSystemMetrics(SM_CXBORDER);
1121 yinc += GetSystemMetrics(SM_CYBORDER);
1124 MinMax.ptMaxSize.x += 2 * xinc;
1125 MinMax.ptMaxSize.y += 2 * yinc;
1127 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1128 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1129 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1130 else
1132 MinMax.ptMaxPosition.x = -xinc;
1133 MinMax.ptMaxPosition.y = -yinc;
1136 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1138 /* Some sanity checks */
1140 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1141 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1142 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1143 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1144 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1145 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1146 MinMax.ptMinTrackSize.x );
1147 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1148 MinMax.ptMinTrackSize.y );
1150 if (maxSize) *maxSize = MinMax.ptMaxSize;
1151 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1152 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1153 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1156 /***********************************************************************
1157 * WINPOS_MinMaximize
1159 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1160 * This function assumes that 'cmd' is different from the current window
1161 * state.
1163 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1165 UINT swpFlags = 0;
1166 POINT pt, size;
1167 LPINTERNALPOS lpPos;
1169 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1171 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1172 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1174 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1176 if( wndPtr->dwStyle & WS_MINIMIZE )
1178 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1179 return (SWP_NOSIZE | SWP_NOMOVE);
1180 swpFlags |= SWP_NOCOPYBITS;
1182 switch( cmd )
1184 case SW_MINIMIZE:
1185 if( wndPtr->dwStyle & WS_MAXIMIZE)
1187 wndPtr->flags |= WIN_RESTORE_MAX;
1188 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1190 else
1191 wndPtr->flags &= ~WIN_RESTORE_MAX;
1192 wndPtr->dwStyle |= WS_MINIMIZE;
1194 if( wndPtr->flags & WIN_NATIVE )
1195 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1196 swpFlags |= MINMAX_NOSWP;
1198 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1200 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1201 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1202 swpFlags |= SWP_NOCOPYBITS;
1203 break;
1205 case SW_MAXIMIZE:
1206 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1207 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1208 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1210 if( wndPtr->dwStyle & WS_MINIMIZE )
1212 if( wndPtr->flags & WIN_NATIVE )
1213 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1214 swpFlags |= MINMAX_NOSWP;
1216 WINPOS_ShowIconTitle( wndPtr, FALSE );
1217 wndPtr->dwStyle &= ~WS_MINIMIZE;
1219 wndPtr->dwStyle |= WS_MAXIMIZE;
1221 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1222 size.x, size.y );
1223 break;
1225 case SW_RESTORE:
1226 if( wndPtr->dwStyle & WS_MINIMIZE )
1228 if( wndPtr->flags & WIN_NATIVE )
1229 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1230 swpFlags |= MINMAX_NOSWP;
1232 wndPtr->dwStyle &= ~WS_MINIMIZE;
1233 WINPOS_ShowIconTitle( wndPtr, FALSE );
1235 if( wndPtr->flags & WIN_RESTORE_MAX)
1237 /* Restore to maximized position */
1238 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1239 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1240 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1241 wndPtr->dwStyle |= WS_MAXIMIZE;
1242 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1243 break;
1246 else
1247 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1248 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1250 /* Restore to normal position */
1252 *lpRect = lpPos->rectNormal;
1253 lpRect->right -= lpRect->left;
1254 lpRect->bottom -= lpRect->top;
1256 break;
1258 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1259 return swpFlags;
1262 /***********************************************************************
1263 * ShowWindowAsync (USER32.535)
1265 * doesn't wait; returns immediately.
1266 * used by threads to toggle windows in other (possibly hanging) threads
1268 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1270 /* FIXME: does ShowWindow() return immediately ? */
1271 return ShowWindow(hwnd, cmd);
1275 /***********************************************************************
1276 * ShowWindow16 (USER.42)
1278 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1280 return ShowWindow(hwnd,cmd);
1284 /***********************************************************************
1285 * ShowWindow (USER32.534)
1287 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1289 WND* wndPtr = WIN_FindWndPtr( hwnd );
1290 BOOL wasVisible, showFlag;
1291 RECT16 newPos = {0, 0, 0, 0};
1292 UINT swp = 0;
1294 if (!wndPtr) return FALSE;
1296 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1298 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1300 switch(cmd)
1302 case SW_HIDE:
1303 if (!wasVisible) goto END;;
1304 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1305 SWP_NOACTIVATE | SWP_NOZORDER;
1306 break;
1308 case SW_SHOWMINNOACTIVE:
1309 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1310 /* fall through */
1311 case SW_SHOWMINIMIZED:
1312 swp |= SWP_SHOWWINDOW;
1313 /* fall through */
1314 case SW_MINIMIZE:
1315 swp |= SWP_FRAMECHANGED;
1316 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1317 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1318 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1319 break;
1321 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1322 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1323 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1324 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1325 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1326 break;
1328 case SW_SHOWNA:
1329 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1330 /* fall through */
1331 case SW_SHOW:
1332 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1335 * ShowWindow has a little peculiar behavior that if the
1336 * window is already the topmost window, it will not
1337 * activate it.
1339 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1340 swp |= SWP_NOACTIVATE;
1342 break;
1344 case SW_SHOWNOACTIVATE:
1345 swp |= SWP_NOZORDER;
1346 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1347 /* fall through */
1348 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1349 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1350 case SW_RESTORE:
1351 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1353 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1354 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1355 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1356 break;
1359 showFlag = (cmd != SW_HIDE);
1360 if (showFlag != wasVisible)
1362 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1363 if (!IsWindow( hwnd )) goto END;
1366 if ((wndPtr->dwStyle & WS_CHILD) &&
1367 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1368 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1370 /* Don't call SetWindowPos() on invisible child windows */
1371 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1372 else wndPtr->dwStyle |= WS_VISIBLE;
1374 else
1376 /* We can't activate a child window */
1377 if ((wndPtr->dwStyle & WS_CHILD) &&
1378 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1379 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1380 if (!(swp & MINMAX_NOSWP))
1382 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1383 newPos.right, newPos.bottom, LOWORD(swp) );
1384 if (cmd == SW_HIDE)
1386 /* FIXME: This will cause the window to be activated irrespective
1387 * of whether it is owned by the same thread. Has to be done
1388 * asynchronously.
1391 if (hwnd == GetActiveWindow())
1392 WINPOS_ActivateOtherWindow(wndPtr);
1394 /* Revert focus to parent */
1395 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1396 SetFocus( GetParent(hwnd) );
1399 if (!IsWindow( hwnd )) goto END;
1400 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1403 if (wndPtr->flags & WIN_NEED_SIZE)
1405 /* should happen only in CreateWindowEx() */
1406 int wParam = SIZE_RESTORED;
1408 wndPtr->flags &= ~WIN_NEED_SIZE;
1409 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1410 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1411 SendMessageA( hwnd, WM_SIZE, wParam,
1412 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1413 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1414 SendMessageA( hwnd, WM_MOVE, 0,
1415 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1418 END:
1419 WIN_ReleaseWndPtr(wndPtr);
1420 return wasVisible;
1424 /***********************************************************************
1425 * GetInternalWindowPos16 (USER.460)
1427 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1428 LPPOINT16 ptIcon )
1430 WINDOWPLACEMENT16 wndpl;
1431 if (GetWindowPlacement16( hwnd, &wndpl ))
1433 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1434 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1435 return wndpl.showCmd;
1437 return 0;
1441 /***********************************************************************
1442 * GetInternalWindowPos (USER32.245)
1444 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1445 LPPOINT ptIcon )
1447 WINDOWPLACEMENT wndpl;
1448 if (GetWindowPlacement( hwnd, &wndpl ))
1450 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1451 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1452 return wndpl.showCmd;
1454 return 0;
1457 /***********************************************************************
1458 * GetWindowPlacement16 (USER.370)
1460 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1462 WND *pWnd = WIN_FindWndPtr( hwnd );
1463 LPINTERNALPOS lpPos;
1465 if(!pWnd ) return FALSE;
1467 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1468 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1469 wndpl->length = sizeof(*wndpl);
1470 if( pWnd->dwStyle & WS_MINIMIZE )
1471 wndpl->showCmd = SW_SHOWMINIMIZED;
1472 else
1473 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1474 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1475 if( pWnd->flags & WIN_RESTORE_MAX )
1476 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1477 else
1478 wndpl->flags = 0;
1479 wndpl->ptMinPosition = lpPos->ptIconPos;
1480 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1481 wndpl->rcNormalPosition = lpPos->rectNormal;
1483 WIN_ReleaseWndPtr(pWnd);
1484 return TRUE;
1488 /***********************************************************************
1489 * GetWindowPlacement (USER32.307)
1491 * Win95:
1492 * Fails if wndpl->length of Win95 (!) apps is invalid.
1494 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1496 if( pwpl32 )
1498 WINDOWPLACEMENT16 wpl;
1499 wpl.length = sizeof(wpl);
1500 if( GetWindowPlacement16( hwnd, &wpl ) )
1502 pwpl32->length = sizeof(*pwpl32);
1503 pwpl32->flags = wpl.flags;
1504 pwpl32->showCmd = wpl.showCmd;
1505 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1506 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1507 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1508 return TRUE;
1511 return FALSE;
1515 /***********************************************************************
1516 * WINPOS_SetPlacement
1518 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1519 UINT flags )
1521 WND *pWnd = WIN_FindWndPtr( hwnd );
1522 if( pWnd )
1524 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1525 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1527 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1528 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1529 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1531 if( pWnd->dwStyle & WS_MINIMIZE )
1533 WINPOS_ShowIconTitle( pWnd, FALSE );
1534 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1535 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1536 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1538 else if( pWnd->dwStyle & WS_MAXIMIZE )
1540 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1541 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1542 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1544 else if( flags & PLACE_RECT )
1545 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1546 lpPos->rectNormal.right - lpPos->rectNormal.left,
1547 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1548 SWP_NOZORDER | SWP_NOACTIVATE );
1550 ShowWindow( hwnd, wndpl->showCmd );
1551 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1553 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1555 /* SDK: ...valid only the next time... */
1556 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1558 WIN_ReleaseWndPtr(pWnd);
1559 return TRUE;
1561 return FALSE;
1565 /***********************************************************************
1566 * SetWindowPlacement16 (USER.371)
1568 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1570 return WINPOS_SetPlacement( hwnd, wndpl,
1571 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1574 /***********************************************************************
1575 * SetWindowPlacement (USER32.519)
1577 * Win95:
1578 * Fails if wndpl->length of Win95 (!) apps is invalid.
1580 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1582 if( pwpl32 )
1584 WINDOWPLACEMENT16 wpl;
1586 wpl.length = sizeof(WINDOWPLACEMENT16);
1587 wpl.flags = pwpl32->flags;
1588 wpl.showCmd = pwpl32->showCmd;
1589 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1590 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1591 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1592 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1593 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1594 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1595 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1596 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1598 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1600 return FALSE;
1604 /***********************************************************************
1605 * SetInternalWindowPos16 (USER.461)
1607 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1608 LPRECT16 rect, LPPOINT16 pt )
1610 if( IsWindow16(hwnd) )
1612 WINDOWPLACEMENT16 wndpl;
1613 UINT flags;
1615 wndpl.length = sizeof(wndpl);
1616 wndpl.showCmd = showCmd;
1617 wndpl.flags = flags = 0;
1619 if( pt )
1621 flags |= PLACE_MIN;
1622 wndpl.flags |= WPF_SETMINPOSITION;
1623 wndpl.ptMinPosition = *pt;
1625 if( rect )
1627 flags |= PLACE_RECT;
1628 wndpl.rcNormalPosition = *rect;
1630 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1635 /***********************************************************************
1636 * SetInternalWindowPos (USER32.483)
1638 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1639 LPRECT rect, LPPOINT pt )
1641 if( IsWindow(hwnd) )
1643 WINDOWPLACEMENT16 wndpl;
1644 UINT flags;
1646 wndpl.length = sizeof(wndpl);
1647 wndpl.showCmd = showCmd;
1648 wndpl.flags = flags = 0;
1650 if( pt )
1652 flags |= PLACE_MIN;
1653 wndpl.flags |= WPF_SETMINPOSITION;
1654 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1656 if( rect )
1658 flags |= PLACE_RECT;
1659 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1661 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1665 /*******************************************************************
1666 * WINPOS_SetActiveWindow
1668 * SetActiveWindow() back-end. This is the only function that
1669 * can assign active status to a window. It must be called only
1670 * for the top level windows.
1672 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1674 CBTACTIVATESTRUCT16* cbtStruct;
1675 WND* wndPtr=0, *wndTemp;
1676 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1677 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1678 WORD wIconized = 0;
1679 HWND hwndActive = 0;
1680 BOOL bRet = 0;
1682 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1684 /* Get current active window from the active queue */
1685 if ( hActiveQueue )
1687 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1688 if ( pOldActiveQueue )
1689 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1692 /* paranoid checks */
1693 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1694 goto CLEANUP_END;
1696 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1697 * return 0;
1699 wndPtr = WIN_FindWndPtr(hWnd);
1700 hOldActiveQueue = hActiveQueue;
1702 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1704 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1705 WIN_ReleaseWndPtr(wndTemp);
1707 else
1708 TRACE("no current active window.\n");
1710 /* call CBT hook chain */
1711 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1713 cbtStruct->fMouse = fMouse;
1714 cbtStruct->hWndActive = hwndActive;
1715 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1716 (LPARAM)SEGPTR_GET(cbtStruct) );
1717 SEGPTR_FREE(cbtStruct);
1718 if (bRet) goto CLEANUP_END;
1721 /* set prev active wnd to current active wnd and send notification */
1722 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1724 MESSAGEQUEUE *pTempActiveQueue = 0;
1726 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1728 if (GetSysModalWindow16() != hWnd)
1729 goto CLEANUP_END;
1730 /* disregard refusal if hWnd is sysmodal */
1733 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1734 MAKEWPARAM( WA_INACTIVE, wIconized ),
1735 (LPARAM)hWnd );
1737 /* check if something happened during message processing
1738 * (global active queue may have changed)
1740 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1741 if(!pTempActiveQueue)
1742 goto CLEANUP_END;
1744 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1745 QUEUE_Unlock( pTempActiveQueue );
1746 if( hwndPrevActive != hwndActive )
1747 goto CLEANUP_END;
1750 /* Set new active window in the message queue */
1751 hwndActive = hWnd;
1752 if ( wndPtr )
1754 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1755 if ( pNewActiveQueue )
1756 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1758 else /* have to do this or MDI frame activation goes to hell */
1759 if( pOldActiveQueue )
1760 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1762 /* send palette messages */
1763 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1764 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1766 /* if prev wnd is minimized redraw icon title */
1767 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1769 /* managed windows will get ConfigureNotify event */
1770 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1772 /* check Z-order and bring hWnd to the top */
1773 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1775 if (wndTemp->dwStyle & WS_VISIBLE) break;
1777 WIN_ReleaseDesktop();
1778 WIN_ReleaseWndPtr(wndTemp);
1780 if( wndTemp != wndPtr )
1781 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1782 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1783 if (!IsWindow(hWnd))
1784 goto CLEANUP;
1787 /* Get a handle to the new active queue */
1788 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1790 /* send WM_ACTIVATEAPP if necessary */
1791 if (hOldActiveQueue != hNewActiveQueue)
1793 WND **list, **ppWnd;
1794 WND *pDesktop = WIN_GetDesktop();
1796 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1798 for (ppWnd = list; *ppWnd; ppWnd++)
1800 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1802 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1803 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1804 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1806 WIN_ReleaseWinArray(list);
1809 hActiveQueue = hNewActiveQueue;
1811 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1813 for (ppWnd = list; *ppWnd; ppWnd++)
1815 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1817 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1818 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1819 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1821 WIN_ReleaseWinArray(list);
1823 WIN_ReleaseDesktop();
1825 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1828 if (hWnd)
1830 /* walk up to the first unowned window */
1831 wndTemp = WIN_LockWndPtr(wndPtr);
1832 while (wndTemp->owner)
1834 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1836 /* and set last active owned popup */
1837 wndTemp->hwndLastActive = hWnd;
1839 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1840 WIN_ReleaseWndPtr(wndTemp);
1841 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1842 SendMessageA( hWnd, WM_ACTIVATE,
1843 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1844 (LPARAM)hwndPrevActive );
1845 if( !IsWindow(hWnd) ) goto CLEANUP;
1848 /* change focus if possible */
1849 if ( fChangeFocus )
1851 if ( pNewActiveQueue )
1853 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1855 if ( WIN_GetTopParent( hOldFocus ) != hwndActive )
1856 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1857 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1858 0 : hwndActive );
1861 if ( pOldActiveQueue &&
1862 ( !pNewActiveQueue ||
1863 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1865 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1866 if ( hOldFocus )
1867 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1871 if( !hwndPrevActive && wndPtr )
1872 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1874 /* if active wnd is minimized redraw icon title */
1875 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1877 bRet = (hWnd == hwndActive); /* Success? */
1879 CLEANUP: /* Unlock the message queues before returning */
1881 if ( pNewActiveQueue )
1882 QUEUE_Unlock( pNewActiveQueue );
1884 CLEANUP_END:
1886 if ( pOldActiveQueue )
1887 QUEUE_Unlock( pOldActiveQueue );
1889 WIN_ReleaseWndPtr(wndPtr);
1890 return bRet;
1893 /*******************************************************************
1894 * WINPOS_ActivateOtherWindow
1896 * Activates window other than pWnd.
1898 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1900 BOOL bRet = 0;
1901 WND* pWndTo = NULL;
1902 HWND hwndActive = 0;
1904 /* Get current active window from the active queue */
1905 if ( hActiveQueue )
1907 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1908 if ( pActiveQueue )
1910 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1911 QUEUE_Unlock( pActiveQueue );
1915 if( pWnd->hwndSelf == hwndPrevActive )
1916 hwndPrevActive = 0;
1918 if( hwndActive != pWnd->hwndSelf &&
1919 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1920 return 0;
1922 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1923 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1925 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1927 WIN_ReleaseWndPtr(pWndTo);
1928 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1930 while( !WINPOS_CanActivate(pWndTo) )
1932 /* by now owned windows should've been taken care of */
1933 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1934 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1935 if( !pWndTo ) break;
1937 WIN_ReleaseWndPtr(pWndPtr);
1940 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1942 /* switch desktop queue to current active */
1943 if( pWndTo )
1945 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1946 WIN_ReleaseWndPtr(pWndTo);
1947 WIN_ReleaseDesktop();
1950 hwndPrevActive = 0;
1951 return bRet;
1954 /*******************************************************************
1955 * WINPOS_ChangeActiveWindow
1958 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1960 WND *wndPtr, *wndTemp;
1961 BOOL retvalue;
1962 HWND hwndActive = 0;
1964 /* Get current active window from the active queue */
1965 if ( hActiveQueue )
1967 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1968 if ( pActiveQueue )
1970 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1971 QUEUE_Unlock( pActiveQueue );
1975 if (!hWnd)
1976 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1978 wndPtr = WIN_FindWndPtr(hWnd);
1979 if( !wndPtr ) return FALSE;
1981 /* child windows get WM_CHILDACTIVATE message */
1982 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1984 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1985 goto end;
1988 if( hWnd == hwndActive )
1990 retvalue = FALSE;
1991 goto end;
1994 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1996 retvalue = FALSE;
1997 goto end;
2000 /* switch desktop queue to current active */
2001 wndTemp = WIN_GetDesktop();
2002 if( wndPtr->parent == wndTemp)
2003 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2004 WIN_ReleaseDesktop();
2006 retvalue = TRUE;
2007 end:
2008 WIN_ReleaseWndPtr(wndPtr);
2009 return retvalue;
2013 /***********************************************************************
2014 * WINPOS_SendNCCalcSize
2016 * Send a WM_NCCALCSIZE message to a window.
2017 * All parameters are read-only except newClientRect.
2018 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2019 * when calcValidRect is TRUE.
2021 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2022 RECT *newWindowRect, RECT *oldWindowRect,
2023 RECT *oldClientRect, WINDOWPOS *winpos,
2024 RECT *newClientRect )
2026 NCCALCSIZE_PARAMS params;
2027 WINDOWPOS winposCopy;
2028 LONG result;
2030 params.rgrc[0] = *newWindowRect;
2031 if (calcValidRect)
2033 winposCopy = *winpos;
2034 params.rgrc[1] = *oldWindowRect;
2035 params.rgrc[2] = *oldClientRect;
2036 params.lppos = &winposCopy;
2038 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2039 (LPARAM)&params );
2040 TRACE("%d,%d-%d,%d\n",
2041 params.rgrc[0].left, params.rgrc[0].top,
2042 params.rgrc[0].right, params.rgrc[0].bottom );
2044 /* If the application send back garbage, ignore it */
2045 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2046 *newClientRect = params.rgrc[0];
2048 return result;
2052 /***********************************************************************
2053 * WINPOS_HandleWindowPosChanging16
2055 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2057 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2059 POINT maxSize, minTrack;
2060 if (winpos->flags & SWP_NOSIZE) return 0;
2061 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2062 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2064 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2065 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2066 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2067 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2069 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2070 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2073 return 0;
2077 /***********************************************************************
2078 * WINPOS_HandleWindowPosChanging
2080 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2082 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2084 POINT maxSize;
2085 if (winpos->flags & SWP_NOSIZE) return 0;
2086 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2087 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2089 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2090 winpos->cx = MIN( winpos->cx, maxSize.x );
2091 winpos->cy = MIN( winpos->cy, maxSize.y );
2093 return 0;
2096 /***********************************************************************
2097 * SWP_DoOwnedPopups
2099 * fix Z order taking into account owned popups -
2100 * basically we need to maintain them above the window that owns them
2102 * FIXME: hide/show owned popups when owner visibility changes.
2104 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2106 WND* w = WIN_LockWndPtr(pDesktop->child);
2108 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2110 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2112 /* make sure this popup stays above the owner */
2114 HWND hwndLocalPrev = HWND_TOP;
2116 if( hwndInsertAfter != HWND_TOP )
2118 while( w != wndPtr->owner )
2120 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2121 if( hwndLocalPrev == hwndInsertAfter ) break;
2122 WIN_UpdateWndPtr(&w,w->next);
2124 hwndInsertAfter = hwndLocalPrev;
2127 else if( wndPtr->dwStyle & WS_CHILD )
2128 goto END;
2130 WIN_UpdateWndPtr(&w, pDesktop->child);
2132 while( w )
2134 if( w == wndPtr ) break;
2136 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2138 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2139 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2140 hwndInsertAfter = w->hwndSelf;
2142 WIN_UpdateWndPtr(&w, w->next);
2145 END:
2146 WIN_ReleaseWndPtr(w);
2147 return hwndInsertAfter;
2150 /***********************************************************************
2151 * SWP_CopyValidBits
2153 * Make window look nice without excessive repainting
2155 * visible and update regions are in window coordinates
2156 * client and window rectangles are in parent client coordinates
2158 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2159 * window rects have the same origin.
2161 * Returns: uFlags and a dirty region in *pVisRgn.
2163 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2164 LPRECT lpOldWndRect,
2165 LPRECT lpOldClientRect, UINT uFlags )
2167 RECT r;
2168 HRGN newVisRgn, dirtyRgn;
2169 INT my = COMPLEXREGION;
2171 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2172 Wnd->rectWindow.left, Wnd->rectWindow.top,
2173 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2174 lpOldWndRect->left, lpOldWndRect->top,
2175 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2176 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2177 Wnd->rectClient.left, Wnd->rectClient.top,
2178 Wnd->rectClient.right, Wnd->rectClient.bottom,
2179 lpOldClientRect->left, lpOldClientRect->top,
2180 lpOldClientRect->right,lpOldClientRect->bottom );
2182 if( Wnd->hrgnUpdate == 1 )
2183 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2185 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2186 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2188 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2189 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2191 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2193 nocopy:
2195 TRACE("\twon't copy anything!\n");
2197 /* set dirtyRgn to the sum of old and new visible regions
2198 * in parent client coordinates */
2200 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2201 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2203 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2205 else /* copy valid bits to a new location */
2207 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2208 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2210 /* subtract already invalid region inside Wnd from the dst region */
2212 if( Wnd->hrgnUpdate )
2213 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2214 goto nocopy;
2216 /* check if entire window can be copied */
2218 ow = lpOldWndRect->right - lpOldWndRect->left;
2219 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2220 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2221 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2223 ocw = lpOldClientRect->right - lpOldClientRect->left;
2224 och = lpOldClientRect->bottom - lpOldClientRect->top;
2225 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2226 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2228 if( (ocw != ncw) || (och != nch) ||
2229 ( ow != nw) || ( oh != nh) ||
2230 ((lpOldClientRect->top - lpOldWndRect->top) !=
2231 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2232 ((lpOldClientRect->left - lpOldWndRect->left) !=
2233 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2235 dx = Wnd->rectClient.left - lpOldClientRect->left;
2236 dy = Wnd->rectClient.top - lpOldClientRect->top;
2238 /* restrict valid bits to the common client rect */
2240 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2241 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2242 r.right = r.left + MIN( ocw, ncw );
2243 r.bottom = r.top + MIN( och, nch );
2245 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2246 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2247 GetRgnBox( hrgnValid, &r );
2248 if( IsRectEmpty( &r ) )
2249 goto nocopy;
2250 r = *lpOldClientRect;
2252 else
2254 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2255 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2256 if( !(uFlags & SWP_EX_PAINTSELF) )
2257 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2258 r = *lpOldWndRect;
2261 if( !(uFlags & SWP_EX_PAINTSELF) )
2263 /* Move remaining regions to parent coordinates */
2264 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2265 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2267 else
2268 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2270 TRACE("\tcomputing dirty region!\n");
2272 /* Compute combined dirty region (old + new - valid) */
2273 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2274 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2276 /* Blt valid bits, r is the rect to copy */
2278 if( dx || dy )
2280 RECT rClip;
2281 HDC hDC;
2282 DC* dc;
2284 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2285 from copying clipped areas */
2287 if( uFlags & SWP_EX_PAINTSELF )
2289 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2290 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2291 rClip.right = nw; rClip.bottom = nh;
2293 else
2295 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2296 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2297 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2298 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2300 rClip.left = rClip.top = 0;
2302 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2304 if( oh > nh ) r.bottom = r.top + nh;
2305 if( ow < nw ) r.right = r.left + nw;
2307 if( IntersectRect( &r, &r, &rClip ) )
2309 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2311 /* When you copy the bits without repainting, parent doesn't
2312 get validated appropriately. Therefore, we have to validate
2313 the parent with the windows' updated region when the
2314 parent's update region is not empty. */
2316 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2318 OffsetRect(&r, dx, dy);
2319 ValidateRect(Wnd->parent->hwndSelf, &r);
2323 GDI_HEAP_UNLOCK( hDC );
2325 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2326 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2330 /* *pVisRgn now points to the invalidated region */
2332 DeleteObject(newVisRgn);
2333 DeleteObject(dirtyRgn);
2334 return uFlags;
2337 /***********************************************************************
2338 * SWP_DoSimpleFrameChanged
2340 * NOTE: old and new client rect origins are identical, only
2341 * extents may have changed. Window extents are the same.
2343 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2345 INT i = 0;
2346 RECT rect;
2347 HRGN hrgn = 0;
2349 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2351 /* Client rect changed its position/size, most likely a scrollar
2352 * was added/removed.
2354 * FIXME: WVR alignment flags
2357 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2359 i++;
2360 rect.top = 0;
2361 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2362 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2363 if(!(uFlags & SWP_EX_NOCOPY))
2364 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2365 else
2367 rect.left = 0;
2368 goto redraw;
2372 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2374 if( i )
2375 hrgn = CreateRectRgnIndirect( &rect );
2376 rect.left = 0;
2377 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2378 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2379 if(!(uFlags & SWP_EX_NOCOPY))
2380 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2381 else
2382 rect.top = 0;
2383 if( i++ )
2384 REGION_UnionRectWithRgn( hrgn, &rect );
2387 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2389 rect = wndPtr->rectWindow;
2390 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2391 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2392 i++;
2396 if( i )
2398 redraw:
2399 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2400 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2402 else
2404 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2407 if( hrgn > 1 )
2408 DeleteObject( hrgn );
2411 /***********************************************************************
2412 * SWP_DoWinPosChanging
2414 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2415 RECT* pNewWindowRect, RECT* pNewClientRect )
2417 /* Send WM_WINDOWPOSCHANGING message */
2419 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2420 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2422 /* Calculate new position and size */
2424 *pNewWindowRect = wndPtr->rectWindow;
2425 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2426 : wndPtr->rectClient;
2428 if (!(pWinpos->flags & SWP_NOSIZE))
2430 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2431 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2433 if (!(pWinpos->flags & SWP_NOMOVE))
2435 pNewWindowRect->left = pWinpos->x;
2436 pNewWindowRect->top = pWinpos->y;
2437 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2438 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2440 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2441 pWinpos->y - wndPtr->rectWindow.top );
2444 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2445 return TRUE;
2448 /***********************************************************************
2449 * SWP_DoNCCalcSize
2451 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2452 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2454 UINT wvrFlags = 0;
2456 /* Send WM_NCCALCSIZE message to get new client area */
2457 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2459 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2460 &wndPtr->rectWindow, &wndPtr->rectClient,
2461 pWinpos, pNewClientRect );
2463 /* FIXME: WVR_ALIGNxxx */
2465 if( pNewClientRect->left != wndPtr->rectClient.left ||
2466 pNewClientRect->top != wndPtr->rectClient.top )
2467 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2469 if( (pNewClientRect->right - pNewClientRect->left !=
2470 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2471 (pNewClientRect->bottom - pNewClientRect->top !=
2472 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2473 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2475 else
2476 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2477 pNewClientRect->top != wndPtr->rectClient.top) )
2478 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2479 return wvrFlags;
2482 /***********************************************************************
2483 * SetWindowPos (USER.2)
2485 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2486 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2488 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2491 /***********************************************************************
2492 * SetWindowPos (USER32.520)
2494 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2495 INT x, INT y, INT cx, INT cy, UINT flags )
2497 WINDOWPOS winpos;
2498 WND * wndPtr,*wndTemp;
2499 RECT newWindowRect, newClientRect;
2500 RECT oldWindowRect, oldClientRect;
2501 HRGN visRgn = 0;
2502 UINT wvrFlags = 0, uFlags = 0;
2503 BOOL retvalue, resync = FALSE, bChangePos;
2504 HWND hwndActive = 0;
2506 /* Get current active window from the active queue */
2507 if ( hActiveQueue )
2509 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2510 if ( pActiveQueue )
2512 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2513 QUEUE_Unlock( pActiveQueue );
2517 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2518 hwnd, x, y, x+cx, y+cy, flags);
2520 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2521 flags &= ~SWP_WINE_NOHOSTMOVE;
2524 /* ------------------------------------------------------------------------ CHECKS */
2526 /* Check window handle */
2528 if (hwnd == GetDesktopWindow()) return FALSE;
2529 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2531 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2532 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2534 /* Fix redundant flags */
2536 if(wndPtr->dwStyle & WS_VISIBLE)
2537 flags &= ~SWP_SHOWWINDOW;
2538 else
2540 if (!(flags & SWP_SHOWWINDOW))
2541 flags |= SWP_NOREDRAW;
2542 flags &= ~SWP_HIDEWINDOW;
2545 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2547 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2548 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2549 flags |= SWP_NOSIZE; /* Already the right size */
2551 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2552 flags |= SWP_NOMOVE; /* Already the right position */
2554 if (hwnd == hwndActive)
2555 flags |= SWP_NOACTIVATE; /* Already active */
2556 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2558 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2560 flags &= ~SWP_NOZORDER;
2561 hwndInsertAfter = HWND_TOP;
2562 goto Pos;
2566 /* Check hwndInsertAfter */
2568 /* FIXME: TOPMOST not supported yet */
2569 if ((hwndInsertAfter == HWND_TOPMOST) ||
2570 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2572 /* hwndInsertAfter must be a sibling of the window */
2573 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2575 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2577 if( wnd ) {
2578 if( wnd->parent != wndPtr->parent )
2580 retvalue = FALSE;
2581 WIN_ReleaseWndPtr(wnd);
2582 goto END;
2584 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2586 WIN_ReleaseWndPtr(wnd);
2589 Pos: /* ------------------------------------------------------------------------ MAIN part */
2591 /* Fill the WINDOWPOS structure */
2593 winpos.hwnd = hwnd;
2594 winpos.hwndInsertAfter = hwndInsertAfter;
2595 winpos.x = x;
2596 winpos.y = y;
2597 winpos.cx = cx;
2598 winpos.cy = cy;
2599 winpos.flags = flags;
2601 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2603 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2605 if( wndPtr->parent == WIN_GetDesktop() )
2606 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2607 hwndInsertAfter, winpos.flags );
2608 WIN_ReleaseDesktop();
2611 if(!(wndPtr->flags & WIN_NATIVE) )
2613 if( hwndInsertAfter == HWND_TOP )
2614 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2615 else
2616 if( hwndInsertAfter == HWND_BOTTOM )
2617 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2618 else
2619 if( !(winpos.flags & SWP_NOZORDER) )
2620 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2621 winpos.flags |= SWP_NOZORDER;
2623 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2624 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2625 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2627 /* get a previous visible region for SWP_CopyValidBits() */
2628 DWORD flags = DCX_WINDOW;
2630 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2631 flags |= DCX_CLIPSIBLINGS;
2633 visRgn = DCE_GetVisRgn(hwnd, flags, 0, 0);
2637 /* Common operations */
2639 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2641 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2643 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2644 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2647 /* Reset active DCEs */
2649 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2650 wndPtr->dwStyle & WS_VISIBLE) ||
2651 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2653 RECT rect;
2655 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2656 DCE_InvalidateDCE(wndPtr, &rect);
2659 oldWindowRect = wndPtr->rectWindow;
2660 oldClientRect = wndPtr->rectClient;
2662 /* Find out if we have to redraw the whole client rect */
2664 if( oldClientRect.bottom - oldClientRect.top ==
2665 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2667 if( oldClientRect.right - oldClientRect.left ==
2668 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2670 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2671 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2673 uFlags |= SWP_EX_NOCOPY;
2676 * Use this later in CopyValidBits()
2678 else if( 0 )
2679 uFlags |= SWP_EX_NONCLIENT;
2682 /* FIXME: actually do something with WVR_VALIDRECTS */
2684 wndPtr->rectWindow = newWindowRect;
2685 wndPtr->rectClient = newClientRect;
2687 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2689 BOOL bCallDriver = TRUE;
2690 HWND tempInsertAfter = winpos.hwndInsertAfter;
2692 winpos.hwndInsertAfter = hwndInsertAfter;
2694 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2696 /* This is the only place where we need to force repainting of the contents
2697 of windows created by the host window system, all other cases go through the
2698 expose event handling */
2700 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2702 cx = newWindowRect.right - newWindowRect.left;
2703 cy = newWindowRect.bottom - newWindowRect.top;
2705 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2706 winpos.hwndInsertAfter = tempInsertAfter;
2707 bCallDriver = FALSE;
2709 if( winpos.flags & SWP_NOCLIENTMOVE )
2710 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2711 else
2713 /* client area moved but window extents remained the same, copy valid bits */
2715 visRgn = CreateRectRgn( 0, 0, cx, cy );
2716 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2717 uFlags | SWP_EX_PAINTSELF );
2722 if( bCallDriver )
2724 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2726 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2727 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2728 !(uFlags & SWP_EX_NOCOPY) )
2730 /* The origin of the client rect didn't move so we can try to repaint
2731 * only the nonclient area by setting bit gravity hint for the host window system.
2734 if( !(wndPtr->flags & WIN_MANAGED) )
2736 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2737 newWindowRect.bottom - newWindowRect.top);
2738 RECT rcn = newClientRect;
2739 RECT rco = oldClientRect;
2741 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2742 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2743 IntersectRect( &rcn, &rcn, &rco );
2744 visRgn = CreateRectRgnIndirect( &rcn );
2745 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2746 DeleteObject( hrgn );
2747 uFlags = SWP_EX_PAINTSELF;
2749 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2751 else
2752 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2755 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2756 winpos.hwndInsertAfter = tempInsertAfter;
2759 if( winpos.flags & SWP_SHOWWINDOW )
2761 HWND focus, curr;
2763 wndPtr->dwStyle |= WS_VISIBLE;
2765 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2767 /* focus was set to unmapped window, reset host focus
2768 * since the window is now visible */
2770 focus = curr = GetFocus();
2771 while (curr)
2773 if (curr == hwnd)
2775 WND *pFocus = WIN_FindWndPtr( focus );
2776 if (pFocus)
2777 pFocus->pDriver->pSetFocus(pFocus);
2778 WIN_ReleaseWndPtr(pFocus);
2779 break;
2781 curr = GetParent(curr);
2785 else /* -------------------------------------------- emulated window */
2787 if( winpos.flags & SWP_SHOWWINDOW )
2789 wndPtr->dwStyle |= WS_VISIBLE;
2790 uFlags |= SWP_EX_PAINTSELF;
2791 visRgn = 1; /* redraw the whole window */
2793 else if( !(winpos.flags & SWP_NOREDRAW) )
2795 if( winpos.flags & SWP_HIDEWINDOW )
2797 if( visRgn > 1 ) /* map to parent */
2798 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2799 else
2800 visRgn = 0;
2802 else
2804 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2805 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2806 &oldClientRect, uFlags);
2807 else
2809 /* nothing moved, redraw frame if needed */
2811 if( winpos.flags & SWP_FRAMECHANGED )
2812 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2813 if( visRgn )
2815 DeleteObject( visRgn );
2816 visRgn = 0;
2823 if( winpos.flags & SWP_HIDEWINDOW )
2825 wndPtr->dwStyle &= ~WS_VISIBLE;
2827 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2830 /* ------------------------------------------------------------------------ FINAL */
2832 if (wndPtr->flags & WIN_NATIVE)
2833 EVENT_Synchronize(); /* Synchronize with the host window system */
2835 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2837 /* Simulate a mouse event to set the cursor */
2838 int iWndsLocks = WIN_SuspendWndsLock();
2840 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2841 PosX, PosY, GetTickCount(), 0 );
2843 WIN_RestoreWndsLock(iWndsLocks);
2846 wndTemp = WIN_GetDesktop();
2848 /* repaint invalidated region (if any)
2850 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2851 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2854 if( visRgn )
2856 if( !(winpos.flags & SWP_NOREDRAW) )
2859 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2860 its parent and sibling and so on, and then erase the parent window
2861 back ground if the parent is either a top-level window or its parent's parent
2862 is top-level window. Rely on the system to repaint other affected
2863 windows later on. */
2864 if( uFlags & SWP_EX_PAINTSELF )
2866 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2867 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2868 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2870 else
2872 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2873 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2874 RDW_EX_USEHRGN );
2877 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2879 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2880 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2883 if( visRgn != 1 )
2884 DeleteObject( visRgn );
2887 WIN_ReleaseDesktop();
2889 if (!(flags & SWP_NOACTIVATE))
2890 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2892 /* And last, send the WM_WINDOWPOSCHANGED message */
2894 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2896 if ( resync ||
2897 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2898 !(winpos.flags & SWP_NOSENDCHANGING)) )
2900 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2901 if (resync) EVENT_Synchronize();
2904 retvalue = TRUE;
2905 END:
2906 WIN_ReleaseWndPtr(wndPtr);
2907 return retvalue;
2911 /***********************************************************************
2912 * BeginDeferWindowPos16 (USER.259)
2914 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2916 return BeginDeferWindowPos( count );
2920 /***********************************************************************
2921 * BeginDeferWindowPos (USER32.9)
2923 HDWP WINAPI BeginDeferWindowPos( INT count )
2925 HDWP handle;
2926 DWP *pDWP;
2928 if (count <= 0) return 0;
2929 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2930 if (!handle) return 0;
2931 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2932 pDWP->actualCount = 0;
2933 pDWP->suggestedCount = count;
2934 pDWP->valid = TRUE;
2935 pDWP->wMagic = DWP_MAGIC;
2936 pDWP->hwndParent = 0;
2937 return handle;
2941 /***********************************************************************
2942 * DeferWindowPos16 (USER.260)
2944 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2945 INT16 x, INT16 y, INT16 cx, INT16 cy,
2946 UINT16 flags )
2948 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2949 x, y, cx, cy, flags );
2953 /***********************************************************************
2954 * DeferWindowPos (USER32.128)
2956 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2957 INT x, INT y, INT cx, INT cy,
2958 UINT flags )
2960 DWP *pDWP;
2961 int i;
2962 HDWP newhdwp = hdwp,retvalue;
2963 /* HWND parent; */
2964 WND *pWnd;
2966 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2967 if (!pDWP) return 0;
2968 if (hwnd == GetDesktopWindow()) return 0;
2970 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2971 USER_HEAP_FREE( hdwp );
2972 return 0;
2975 /* Numega Bounds Checker Demo dislikes the following code.
2976 In fact, I've not been able to find any "same parent" requirement in any docu
2977 [AM 980509]
2979 #if 0
2980 /* All the windows of a DeferWindowPos() must have the same parent */
2981 parent = pWnd->parent->hwndSelf;
2982 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2983 else if (parent != pDWP->hwndParent)
2985 USER_HEAP_FREE( hdwp );
2986 retvalue = 0;
2987 goto END;
2989 #endif
2991 for (i = 0; i < pDWP->actualCount; i++)
2993 if (pDWP->winPos[i].hwnd == hwnd)
2995 /* Merge with the other changes */
2996 if (!(flags & SWP_NOZORDER))
2998 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3000 if (!(flags & SWP_NOMOVE))
3002 pDWP->winPos[i].x = x;
3003 pDWP->winPos[i].y = y;
3005 if (!(flags & SWP_NOSIZE))
3007 pDWP->winPos[i].cx = cx;
3008 pDWP->winPos[i].cy = cy;
3010 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3011 SWP_NOZORDER | SWP_NOREDRAW |
3012 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3013 SWP_NOOWNERZORDER);
3014 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3015 SWP_FRAMECHANGED);
3016 retvalue = hdwp;
3017 goto END;
3020 if (pDWP->actualCount >= pDWP->suggestedCount)
3022 newhdwp = USER_HEAP_REALLOC( hdwp,
3023 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3024 if (!newhdwp)
3026 retvalue = 0;
3027 goto END;
3029 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3030 pDWP->suggestedCount++;
3032 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3033 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3034 pDWP->winPos[pDWP->actualCount].x = x;
3035 pDWP->winPos[pDWP->actualCount].y = y;
3036 pDWP->winPos[pDWP->actualCount].cx = cx;
3037 pDWP->winPos[pDWP->actualCount].cy = cy;
3038 pDWP->winPos[pDWP->actualCount].flags = flags;
3039 pDWP->actualCount++;
3040 retvalue = newhdwp;
3041 END:
3042 WIN_ReleaseWndPtr(pWnd);
3043 return retvalue;
3047 /***********************************************************************
3048 * EndDeferWindowPos16 (USER.261)
3050 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3052 return EndDeferWindowPos( hdwp );
3056 /***********************************************************************
3057 * EndDeferWindowPos (USER32.173)
3059 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3061 DWP *pDWP;
3062 WINDOWPOS *winpos;
3063 BOOL res = TRUE;
3064 int i;
3066 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3067 if (!pDWP) return FALSE;
3068 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3070 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3071 winpos->x, winpos->y, winpos->cx,
3072 winpos->cy, winpos->flags ))) break;
3074 USER_HEAP_FREE( hdwp );
3075 return res;
3079 /***********************************************************************
3080 * TileChildWindows (USER.199)
3082 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3084 FIXME("(%04x, %d): stub\n", parent, action);
3087 /***********************************************************************
3088 * CascageChildWindows (USER.198)
3090 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3092 FIXME("(%04x, %d): stub\n", parent, action);
3095 /***********************************************************************
3096 * SetProgmanWindow [USER32.522]
3098 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3100 hGlobalProgmanWindow = hwnd;
3101 return hGlobalProgmanWindow;
3104 /***********************************************************************
3105 * GetProgmanWindow [USER32.289]
3107 HRESULT WINAPI GetProgmanWindow ( )
3109 return hGlobalProgmanWindow;
3112 /***********************************************************************
3113 * SetShellWindowEx [USER32.531]
3114 * hwndProgman = Progman[Program Manager]
3115 * |-> SHELLDLL_DefView
3116 * hwndListView = | |-> SysListView32
3117 * | | |-> tooltips_class32
3118 * | |
3119 * | |-> SysHeader32
3120 * |
3121 * |-> ProxyTarget
3123 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3125 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3126 hGlobalShellWindow = hwndProgman;
3127 return hGlobalShellWindow;
3131 /***********************************************************************
3132 * SetTaskmanWindow [USER32.537]
3133 * NOTES
3134 * hwnd = MSTaskSwWClass
3135 * |-> SysTabControl32
3137 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3139 hGlobalTaskmanWindow = hwnd;
3140 return hGlobalTaskmanWindow;
3143 /***********************************************************************
3144 * GetTaskmanWindow [USER32.304]
3146 HRESULT WINAPI GetTaskmanWindow ( )
3148 return hGlobalTaskmanWindow;