Added missing configuration #if:s and #includes:s.
[wine/dcerpc.git] / windows / winpos.c
blob9b6e0b73da4a1c8263516a2d2e1e618ce02aa957
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 "wine/winuser16.h"
10 #include "heap.h"
11 #include "module.h"
12 #include "user.h"
13 #include "region.h"
14 #include "win.h"
15 #include "hook.h"
16 #include "message.h"
17 #include "queue.h"
18 #include "options.h"
19 #include "task.h"
20 #include "winpos.h"
21 #include "dce.h"
22 #include "nonclient.h"
23 #include "debugtools.h"
24 #include "local.h"
25 #include "ldt.h"
27 DEFAULT_DEBUG_CHANNEL(win)
29 #define HAS_DLGFRAME(style,exStyle) \
30 (((exStyle) & WS_EX_DLGMODALFRAME) || \
31 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
33 #define HAS_THICKFRAME(style) \
34 (((style) & WS_THICKFRAME) && \
35 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
37 #define SWP_AGG_NOGEOMETRYCHANGE \
38 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
39 #define SWP_AGG_NOPOSCHANGE \
40 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
41 #define SWP_AGG_STATUSFLAGS \
42 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
44 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
46 #define PLACE_MIN 0x0001
47 #define PLACE_MAX 0x0002
48 #define PLACE_RECT 0x0004
50 #define SWP_EX_NOCOPY 0x0001
51 #define SWP_EX_PAINTSELF 0x0002
52 #define SWP_EX_NONCLIENT 0x0004
54 #define MINMAX_NOSWP 0x00010000
56 /* ----- internal variables ----- */
58 static HWND hwndPrevActive = 0; /* Previously active window */
59 static HWND hGlobalShellWindow=0; /*the shell*/
60 static HWND hGlobalTaskmanWindow=0;
61 static HWND hGlobalProgmanWindow=0;
63 static LPCSTR atomInternalPos;
65 extern HQUEUE16 hActiveQueue;
67 /***********************************************************************
68 * WINPOS_CreateInternalPosAtom
70 BOOL WINPOS_CreateInternalPosAtom()
72 LPSTR str = "SysIP";
73 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
74 return (atomInternalPos) ? TRUE : FALSE;
77 /***********************************************************************
78 * WINPOS_CheckInternalPos
80 * Called when a window is destroyed.
82 void WINPOS_CheckInternalPos( WND* wndPtr )
84 LPINTERNALPOS lpPos;
85 MESSAGEQUEUE *pMsgQ = 0;
86 HWND hwnd = wndPtr->hwndSelf;
88 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
90 /* Retrieve the message queue associated with this window */
91 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
92 if ( !pMsgQ )
94 WARN("\tMessage queue not found. Exiting!\n" );
95 return;
98 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
100 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
102 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
103 WARN("\tattempt to activate destroyed window!\n");
106 if( lpPos )
108 if( IsWindow(lpPos->hwndIconTitle) )
109 DestroyWindow( lpPos->hwndIconTitle );
110 HeapFree( SystemHeap, 0, lpPos );
113 QUEUE_Unlock( pMsgQ );
114 return;
117 /***********************************************************************
118 * WINPOS_FindIconPos
120 * Find a suitable place for an iconic window.
122 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
124 RECT16 rectParent;
125 short x, y, xspacing, yspacing;
127 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
128 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
129 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
130 return pt; /* The icon already has a suitable position */
132 xspacing = GetSystemMetrics(SM_CXICONSPACING);
133 yspacing = GetSystemMetrics(SM_CYICONSPACING);
135 y = rectParent.bottom;
136 for (;;)
138 for (x = rectParent.left; x <= rectParent.right-xspacing; x += xspacing)
140 /* Check if another icon already occupies this spot */
141 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
142 while (childPtr)
144 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
146 if ((childPtr->rectWindow.left < x + xspacing) &&
147 (childPtr->rectWindow.right >= x) &&
148 (childPtr->rectWindow.top <= y) &&
149 (childPtr->rectWindow.bottom > y - yspacing))
150 break; /* There's a window in there */
152 WIN_UpdateWndPtr(&childPtr,childPtr->next);
154 WIN_ReleaseWndPtr(childPtr);
155 if (!childPtr) /* No window was found, so it's OK for us */
157 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
158 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
159 return pt;
162 y -= yspacing;
167 /***********************************************************************
168 * ArrangeIconicWindows16 (USER.170)
170 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
172 return ArrangeIconicWindows(parent);
174 /***********************************************************************
175 * ArrangeIconicWindows (USER32.7)
177 UINT WINAPI ArrangeIconicWindows( HWND parent )
179 RECT rectParent;
180 HWND hwndChild;
181 INT x, y, xspacing, yspacing;
183 GetClientRect( parent, &rectParent );
184 x = rectParent.left;
185 y = rectParent.bottom;
186 xspacing = GetSystemMetrics(SM_CXICONSPACING);
187 yspacing = GetSystemMetrics(SM_CYICONSPACING);
189 hwndChild = GetWindow( parent, GW_CHILD );
190 while (hwndChild)
192 if( IsIconic( hwndChild ) )
194 WND *wndPtr = WIN_FindWndPtr(hwndChild);
196 WINPOS_ShowIconTitle( wndPtr, FALSE );
198 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
199 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
200 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
201 if( IsWindow(hwndChild) )
202 WINPOS_ShowIconTitle(wndPtr , TRUE );
203 WIN_ReleaseWndPtr(wndPtr);
205 if (x <= rectParent.right - xspacing) x += xspacing;
206 else
208 x = rectParent.left;
209 y -= yspacing;
212 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
214 return yspacing;
218 /***********************************************************************
219 * SwitchToThisWindow16 (USER.172)
221 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
223 SwitchToThisWindow( hwnd, restore );
227 /***********************************************************************
228 * SwitchToThisWindow (USER32.539)
230 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
232 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
236 /***********************************************************************
237 * GetWindowRect16 (USER.32)
239 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
241 WND * wndPtr = WIN_FindWndPtr( hwnd );
242 if (!wndPtr) return;
244 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
245 if (wndPtr->dwStyle & WS_CHILD)
246 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
247 WIN_ReleaseWndPtr(wndPtr);
251 /***********************************************************************
252 * GetWindowRect (USER32.308)
254 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
256 WND * wndPtr = WIN_FindWndPtr( hwnd );
257 if (!wndPtr) return FALSE;
259 *rect = wndPtr->rectWindow;
260 if (wndPtr->dwStyle & WS_CHILD)
261 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
262 WIN_ReleaseWndPtr(wndPtr);
263 return TRUE;
267 /***********************************************************************
268 * GetWindowRgn
270 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
273 RECT rect;
274 WND * wndPtr = WIN_FindWndPtr( hwnd );
275 if (!wndPtr) return (ERROR);
277 FIXME("GetWindowRgn: doesn't really do regions\n");
279 memset (&rect, 0, sizeof(rect));
281 GetWindowRect ( hwnd, &rect );
283 FIXME("Check whether a valid region here\n");
285 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
287 WIN_ReleaseWndPtr(wndPtr);
288 return (SIMPLEREGION);
291 /***********************************************************************
292 * SetWindowRgn
294 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
298 FIXME("SetWindowRgn: stub\n");
299 return TRUE;
302 /***********************************************************************
303 * SetWindowRgn16
305 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
309 FIXME("SetWindowRgn16: stub\n");
310 return TRUE;
314 /***********************************************************************
315 * GetClientRect16 (USER.33)
317 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
319 WND * wndPtr = WIN_FindWndPtr( hwnd );
321 rect->left = rect->top = rect->right = rect->bottom = 0;
322 if (wndPtr)
324 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
325 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
327 WIN_ReleaseWndPtr(wndPtr);
331 /***********************************************************************
332 * GetClientRect (USER.220)
334 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
336 WND * wndPtr = WIN_FindWndPtr( hwnd );
338 rect->left = rect->top = rect->right = rect->bottom = 0;
339 if (!wndPtr) return FALSE;
340 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
341 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
343 WIN_ReleaseWndPtr(wndPtr);
344 return TRUE;
348 /*******************************************************************
349 * ClientToScreen16 (USER.28)
351 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
353 MapWindowPoints16( hwnd, 0, lppnt, 1 );
357 /*******************************************************************
358 * ClientToScreen (USER32.52)
360 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
362 MapWindowPoints( hwnd, 0, lppnt, 1 );
363 return TRUE;
367 /*******************************************************************
368 * ScreenToClient16 (USER.29)
370 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
372 MapWindowPoints16( 0, hwnd, lppnt, 1 );
376 /*******************************************************************
377 * ScreenToClient (USER32.447)
379 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
381 MapWindowPoints( 0, hwnd, lppnt, 1 );
382 return TRUE;
386 /***********************************************************************
387 * WINPOS_WindowFromPoint
389 * Find the window and hittest for a given point.
391 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
393 WND *wndPtr;
394 INT16 hittest = HTERROR;
395 INT16 retvalue;
396 POINT16 xy = pt;
398 *ppWnd = NULL;
399 wndPtr = WIN_LockWndPtr(wndScope->child);
401 if( wndScope->flags & WIN_MANAGED )
403 /* In managed mode we have to check wndScope first as it is also
404 * a window which received the mouse event. */
406 if( wndScope->dwStyle & WS_DISABLED )
408 retvalue = HTERROR;
409 goto end;
411 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
412 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
413 goto hittest;
415 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
417 for (;;)
419 while (wndPtr)
421 /* If point is in window, and window is visible, and it */
422 /* is enabled (or it's a top-level window), then explore */
423 /* its children. Otherwise, go to the next window. */
425 if ((wndPtr->dwStyle & WS_VISIBLE) &&
426 (!(wndPtr->dwStyle & WS_DISABLED) ||
427 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
428 (xy.x >= wndPtr->rectWindow.left) &&
429 (xy.x < wndPtr->rectWindow.right) &&
430 (xy.y >= wndPtr->rectWindow.top) &&
431 (xy.y < wndPtr->rectWindow.bottom))
433 *ppWnd = wndPtr; /* Got a suitable window */
435 /* If window is minimized or disabled, return at once */
436 if (wndPtr->dwStyle & WS_MINIMIZE)
438 retvalue = HTCAPTION;
439 goto end;
441 if (wndPtr->dwStyle & WS_DISABLED)
443 retvalue = HTERROR;
444 goto end;
447 /* If point is not in client area, ignore the children */
448 if ((xy.x < wndPtr->rectClient.left) ||
449 (xy.x >= wndPtr->rectClient.right) ||
450 (xy.y < wndPtr->rectClient.top) ||
451 (xy.y >= wndPtr->rectClient.bottom)) break;
453 xy.x -= wndPtr->rectClient.left;
454 xy.y -= wndPtr->rectClient.top;
455 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
457 else
459 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
463 hittest:
464 /* If nothing found, try the scope window */
465 if (!*ppWnd) *ppWnd = wndScope;
467 /* Send the WM_NCHITTEST message (only if to the same task) */
468 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
470 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
471 0, MAKELONG( pt.x, pt.y ) );
472 if (hittest != HTTRANSPARENT)
474 retvalue = hittest; /* Found the window */
475 goto end;
478 else
480 retvalue = HTCLIENT;
481 goto end;
484 /* If no children found in last search, make point relative to parent */
485 if (!wndPtr)
487 xy.x += (*ppWnd)->rectClient.left;
488 xy.y += (*ppWnd)->rectClient.top;
491 /* Restart the search from the next sibling */
492 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
493 *ppWnd = (*ppWnd)->parent;
496 end:
497 WIN_ReleaseWndPtr(wndPtr);
498 return retvalue;
502 /*******************************************************************
503 * WindowFromPoint16 (USER.30)
505 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
507 WND *pWnd;
508 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
509 WIN_ReleaseDesktop();
510 return pWnd->hwndSelf;
514 /*******************************************************************
515 * WindowFromPoint (USER32.582)
517 HWND WINAPI WindowFromPoint( POINT pt )
519 WND *pWnd;
520 POINT16 pt16;
521 CONV_POINT32TO16( &pt, &pt16 );
522 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
523 WIN_ReleaseDesktop();
524 return (HWND)pWnd->hwndSelf;
528 /*******************************************************************
529 * ChildWindowFromPoint16 (USER.191)
531 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
533 POINT pt32;
534 CONV_POINT16TO32( &pt, &pt32 );
535 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
539 /*******************************************************************
540 * ChildWindowFromPoint (USER32.49)
542 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
544 /* pt is in the client coordinates */
546 WND* wnd = WIN_FindWndPtr(hwndParent);
547 RECT rect;
548 HWND retvalue;
550 if( !wnd ) return 0;
552 /* get client rect fast */
553 rect.top = rect.left = 0;
554 rect.right = wnd->rectClient.right - wnd->rectClient.left;
555 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
557 if (!PtInRect( &rect, pt ))
559 retvalue = 0;
560 goto end;
562 WIN_UpdateWndPtr(&wnd,wnd->child);
563 while ( wnd )
565 if (PtInRect( &wnd->rectWindow, pt ))
567 retvalue = wnd->hwndSelf;
568 goto end;
570 WIN_UpdateWndPtr(&wnd,wnd->next);
572 retvalue = hwndParent;
573 end:
574 WIN_ReleaseWndPtr(wnd);
575 return retvalue;
578 /*******************************************************************
579 * ChildWindowFromPointEx16 (USER.50)
581 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
583 POINT pt32;
584 CONV_POINT16TO32( &pt, &pt32 );
585 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
589 /*******************************************************************
590 * ChildWindowFromPointEx32 (USER32.50)
592 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
593 UINT uFlags)
595 /* pt is in the client coordinates */
597 WND* wnd = WIN_FindWndPtr(hwndParent);
598 RECT rect;
599 HWND retvalue;
601 if( !wnd ) return 0;
603 /* get client rect fast */
604 rect.top = rect.left = 0;
605 rect.right = wnd->rectClient.right - wnd->rectClient.left;
606 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
608 if (!PtInRect( &rect, pt ))
610 retvalue = 0;
611 goto end;
613 WIN_UpdateWndPtr(&wnd,wnd->child);
615 while ( wnd )
617 if (PtInRect( &wnd->rectWindow, pt )) {
618 if ( (uFlags & CWP_SKIPINVISIBLE) &&
619 !(wnd->dwStyle & WS_VISIBLE) );
620 else if ( (uFlags & CWP_SKIPDISABLED) &&
621 (wnd->dwStyle & WS_DISABLED) );
622 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
623 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
624 else
626 retvalue = wnd->hwndSelf;
627 goto end;
631 WIN_UpdateWndPtr(&wnd,wnd->next);
633 retvalue = hwndParent;
634 end:
635 WIN_ReleaseWndPtr(wnd);
636 return retvalue;
640 /*******************************************************************
641 * WINPOS_GetWinOffset
643 * Calculate the offset between the origin of the two windows. Used
644 * to implement MapWindowPoints.
646 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
647 POINT *offset )
649 WND * wndPtr = 0;
651 offset->x = offset->y = 0;
652 if (hwndFrom == hwndTo ) return;
654 /* Translate source window origin to screen coords */
655 if (hwndFrom)
657 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
659 ERR("bad hwndFrom = %04x\n",hwndFrom);
660 return;
662 while (wndPtr->parent)
664 offset->x += wndPtr->rectClient.left;
665 offset->y += wndPtr->rectClient.top;
666 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
668 WIN_ReleaseWndPtr(wndPtr);
671 /* Translate origin to destination window coords */
672 if (hwndTo)
674 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
676 ERR("bad hwndTo = %04x\n", hwndTo );
677 return;
679 while (wndPtr->parent)
681 offset->x -= wndPtr->rectClient.left;
682 offset->y -= wndPtr->rectClient.top;
683 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
685 WIN_ReleaseWndPtr(wndPtr);
690 /*******************************************************************
691 * MapWindowPoints16 (USER.258)
693 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
694 LPPOINT16 lppt, UINT16 count )
696 POINT offset;
698 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
699 while (count--)
701 lppt->x += offset.x;
702 lppt->y += offset.y;
703 lppt++;
708 /*******************************************************************
709 * MapWindowPoints (USER32.386)
711 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
712 LPPOINT lppt, UINT count )
714 POINT offset;
716 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
717 while (count--)
719 lppt->x += offset.x;
720 lppt->y += offset.y;
721 lppt++;
723 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
727 /***********************************************************************
728 * IsIconic16 (USER.31)
730 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
732 return IsIconic(hWnd);
736 /***********************************************************************
737 * IsIconic (USER32.345)
739 BOOL WINAPI IsIconic(HWND hWnd)
741 BOOL retvalue;
742 WND * wndPtr = WIN_FindWndPtr(hWnd);
743 if (wndPtr == NULL) return FALSE;
744 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
745 WIN_ReleaseWndPtr(wndPtr);
746 return retvalue;
750 /***********************************************************************
751 * IsZoomed (USER.272)
753 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
755 return IsZoomed(hWnd);
759 /***********************************************************************
760 * IsZoomed (USER.352)
762 BOOL WINAPI IsZoomed(HWND hWnd)
764 BOOL retvalue;
765 WND * wndPtr = WIN_FindWndPtr(hWnd);
766 if (wndPtr == NULL) return FALSE;
767 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
768 WIN_ReleaseWndPtr(wndPtr);
769 return retvalue;
773 /*******************************************************************
774 * GetActiveWindow (USER.60)
776 HWND16 WINAPI GetActiveWindow16(void)
778 return (HWND16)GetActiveWindow();
781 /*******************************************************************
782 * GetActiveWindow (USER32.205)
784 HWND WINAPI GetActiveWindow(void)
786 MESSAGEQUEUE *pCurMsgQ = 0;
787 HWND hwndActive = 0;
789 /* Get the messageQ for the current thread */
790 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
792 WARN("\tCurrent message queue not found. Exiting!\n" );
793 return 0;
796 /* Return the current active window from the perQ data of the current message Q */
797 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
799 QUEUE_Unlock( pCurMsgQ );
800 return hwndActive;
804 /*******************************************************************
805 * WINPOS_CanActivate
807 static BOOL WINPOS_CanActivate(WND* pWnd)
809 if( pWnd && !(pWnd->dwStyle & (WS_DISABLED | WS_CHILD)) ) return TRUE;
810 return FALSE;
814 /*******************************************************************
815 * SetActiveWindow16 (USER.59)
817 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
819 return SetActiveWindow(hwnd);
823 /*******************************************************************
824 * SetActiveWindow (USER32.463)
826 HWND WINAPI SetActiveWindow( HWND hwnd )
828 HWND prev = 0;
829 WND *wndPtr = WIN_FindWndPtr( hwnd );
830 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
832 if ( !WINPOS_CanActivate(wndPtr) )
834 prev = 0;
835 goto end;
838 /* Get the messageQ for the current thread */
839 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
841 WARN("\tCurrent message queue not found. Exiting!\n" );
842 goto CLEANUP;
845 /* Retrieve the message queue associated with this window */
846 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
847 if ( !pMsgQ )
849 WARN("\tWindow message queue not found. Exiting!\n" );
850 goto CLEANUP;
853 /* Make sure that the window is associated with the calling threads
854 * message queue. It must share the same perQ data.
857 if ( pCurMsgQ->pQData != pMsgQ->pQData )
858 goto CLEANUP;
860 /* Save current active window */
861 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
863 WINPOS_SetActiveWindow( hwnd, 0, 0 );
865 CLEANUP:
866 /* Unlock the queues before returning */
867 if ( pMsgQ )
868 QUEUE_Unlock( pMsgQ );
869 if ( pCurMsgQ )
870 QUEUE_Unlock( pCurMsgQ );
872 end:
873 WIN_ReleaseWndPtr(wndPtr);
874 return prev;
878 /*******************************************************************
879 * GetForegroundWindow16 (USER.608)
881 HWND16 WINAPI GetForegroundWindow16(void)
883 return (HWND16)GetForegroundWindow();
887 /*******************************************************************
888 * SetForegroundWindow16 (USER.609)
890 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
892 return SetForegroundWindow( hwnd );
896 /*******************************************************************
897 * GetForegroundWindow (USER32.241)
899 HWND WINAPI GetForegroundWindow(void)
901 HWND hwndActive = 0;
903 /* Get the foreground window (active window of hActiveQueue) */
904 if ( hActiveQueue )
906 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
907 if ( pActiveQueue )
908 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
910 QUEUE_Unlock( pActiveQueue );
913 return hwndActive;
916 /*******************************************************************
917 * SetForegroundWindow (USER32.482)
919 BOOL WINAPI SetForegroundWindow( HWND hwnd )
921 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
925 /*******************************************************************
926 * GetShellWindow16 (USER.600)
928 HWND16 WINAPI GetShellWindow16(void)
930 return GetShellWindow();
933 /*******************************************************************
934 * SetShellWindow (USER32.504)
936 HWND WINAPI SetShellWindow(HWND hwndshell)
937 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
939 hGlobalShellWindow = hwndshell;
940 return hGlobalShellWindow;
944 /*******************************************************************
945 * GetShellWindow (USER32.287)
947 HWND WINAPI GetShellWindow(void)
948 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
950 return hGlobalShellWindow;
954 /***********************************************************************
955 * BringWindowToTop16 (USER.45)
957 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
959 return BringWindowToTop(hwnd);
963 /***********************************************************************
964 * BringWindowToTop (USER32.11)
966 BOOL WINAPI BringWindowToTop( HWND hwnd )
968 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
972 /***********************************************************************
973 * MoveWindow16 (USER.56)
975 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
976 BOOL16 repaint )
978 return MoveWindow(hwnd,x,y,cx,cy,repaint);
982 /***********************************************************************
983 * MoveWindow (USER32.399)
985 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
986 BOOL repaint )
988 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
989 if (!repaint) flags |= SWP_NOREDRAW;
990 TRACE("%04x %d,%d %dx%d %d\n",
991 hwnd, x, y, cx, cy, repaint );
992 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
995 /***********************************************************************
996 * WINPOS_InitInternalPos
998 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
999 LPRECT restoreRect )
1001 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1002 atomInternalPos );
1003 if( !lpPos )
1005 /* this happens when the window is minimized/maximized
1006 * for the first time (rectWindow is not adjusted yet) */
1008 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1009 if( !lpPos ) return NULL;
1011 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1012 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1013 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1014 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1017 if( wnd->dwStyle & WS_MINIMIZE )
1018 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1019 else if( wnd->dwStyle & WS_MAXIMIZE )
1020 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1021 else if( restoreRect )
1022 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1024 return lpPos;
1027 /***********************************************************************
1028 * WINPOS_RedrawIconTitle
1030 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1032 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1033 if( lpPos )
1035 if( lpPos->hwndIconTitle )
1037 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1038 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1039 return TRUE;
1042 return FALSE;
1045 /***********************************************************************
1046 * WINPOS_ShowIconTitle
1048 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1050 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1052 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1054 HWND16 hWnd = lpPos->hwndIconTitle;
1056 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1058 if( !hWnd )
1059 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1060 if( bShow )
1062 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1064 if( !(pWnd->dwStyle & WS_VISIBLE) )
1066 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1067 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1068 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1070 WIN_ReleaseWndPtr(pWnd);
1073 else ShowWindow( hWnd, SW_HIDE );
1075 return FALSE;
1078 /*******************************************************************
1079 * WINPOS_GetMinMaxInfo
1081 * Get the minimized and maximized information for a window.
1083 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1084 POINT *minTrack, POINT *maxTrack )
1086 LPINTERNALPOS lpPos;
1087 MINMAXINFO MinMax;
1088 INT xinc, yinc;
1090 /* Compute default values */
1092 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1093 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1094 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1095 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1096 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1097 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1099 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1100 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1102 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1103 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1105 else
1107 xinc = yinc = 0;
1108 if (HAS_THICKFRAME(wndPtr->dwStyle))
1110 xinc += GetSystemMetrics(SM_CXFRAME);
1111 yinc += GetSystemMetrics(SM_CYFRAME);
1113 if (wndPtr->dwStyle & WS_BORDER)
1115 xinc += GetSystemMetrics(SM_CXBORDER);
1116 yinc += GetSystemMetrics(SM_CYBORDER);
1119 MinMax.ptMaxSize.x += 2 * xinc;
1120 MinMax.ptMaxSize.y += 2 * yinc;
1122 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1123 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1124 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1125 else
1127 MinMax.ptMaxPosition.x = -xinc;
1128 MinMax.ptMaxPosition.y = -yinc;
1131 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1133 /* Some sanity checks */
1135 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1136 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1137 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1138 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1139 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1140 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1141 MinMax.ptMinTrackSize.x );
1142 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1143 MinMax.ptMinTrackSize.y );
1145 if (maxSize) *maxSize = MinMax.ptMaxSize;
1146 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1147 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1148 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1151 /***********************************************************************
1152 * WINPOS_MinMaximize
1154 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1155 * This function assumes that 'cmd' is different from the current window
1156 * state.
1158 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1160 UINT swpFlags = 0;
1161 POINT pt, size;
1162 LPINTERNALPOS lpPos;
1164 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1166 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1167 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1169 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1171 if( wndPtr->dwStyle & WS_MINIMIZE )
1173 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1174 return (SWP_NOSIZE | SWP_NOMOVE);
1175 swpFlags |= SWP_NOCOPYBITS;
1177 switch( cmd )
1179 case SW_MINIMIZE:
1180 if( wndPtr->dwStyle & WS_MAXIMIZE)
1182 wndPtr->flags |= WIN_RESTORE_MAX;
1183 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1185 else
1186 wndPtr->flags &= ~WIN_RESTORE_MAX;
1187 wndPtr->dwStyle |= WS_MINIMIZE;
1189 if( wndPtr->flags & WIN_NATIVE )
1190 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1191 swpFlags |= MINMAX_NOSWP;
1193 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1195 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1196 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1197 swpFlags |= SWP_NOCOPYBITS;
1198 break;
1200 case SW_MAXIMIZE:
1201 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1202 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1203 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1205 if( wndPtr->dwStyle & WS_MINIMIZE )
1207 if( wndPtr->flags & WIN_NATIVE )
1208 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1209 swpFlags |= MINMAX_NOSWP;
1211 WINPOS_ShowIconTitle( wndPtr, FALSE );
1212 wndPtr->dwStyle &= ~WS_MINIMIZE;
1214 wndPtr->dwStyle |= WS_MAXIMIZE;
1216 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1217 size.x, size.y );
1218 break;
1220 case SW_RESTORE:
1221 if( wndPtr->dwStyle & WS_MINIMIZE )
1223 if( wndPtr->flags & WIN_NATIVE )
1224 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1225 swpFlags |= MINMAX_NOSWP;
1227 wndPtr->dwStyle &= ~WS_MINIMIZE;
1228 WINPOS_ShowIconTitle( wndPtr, FALSE );
1230 if( wndPtr->flags & WIN_RESTORE_MAX)
1232 /* Restore to maximized position */
1233 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1234 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1235 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1236 wndPtr->dwStyle |= WS_MAXIMIZE;
1237 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1238 break;
1241 else
1242 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1243 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1245 /* Restore to normal position */
1247 *lpRect = lpPos->rectNormal;
1248 lpRect->right -= lpRect->left;
1249 lpRect->bottom -= lpRect->top;
1251 break;
1253 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1254 return swpFlags;
1257 /***********************************************************************
1258 * ShowWindowAsync (USER32.535)
1260 * doesn't wait; returns immediately.
1261 * used by threads to toggle windows in other (possibly hanging) threads
1263 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1265 /* FIXME: does ShowWindow() return immediately ? */
1266 return ShowWindow(hwnd, cmd);
1270 /***********************************************************************
1271 * ShowWindow16 (USER.42)
1273 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1275 return ShowWindow(hwnd,cmd);
1279 /***********************************************************************
1280 * ShowWindow (USER32.534)
1282 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1284 WND* wndPtr = WIN_FindWndPtr( hwnd );
1285 BOOL wasVisible, showFlag;
1286 RECT16 newPos = {0, 0, 0, 0};
1287 UINT swp = 0;
1289 if (!wndPtr) return FALSE;
1291 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1293 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1295 switch(cmd)
1297 case SW_HIDE:
1298 if (!wasVisible) goto END;;
1299 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1300 SWP_NOACTIVATE | SWP_NOZORDER;
1301 break;
1303 case SW_SHOWMINNOACTIVE:
1304 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1305 /* fall through */
1306 case SW_SHOWMINIMIZED:
1307 swp |= SWP_SHOWWINDOW;
1308 /* fall through */
1309 case SW_MINIMIZE:
1310 swp |= SWP_FRAMECHANGED;
1311 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1312 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1313 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1314 break;
1316 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1317 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1318 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1319 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1320 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1321 break;
1323 case SW_SHOWNA:
1324 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1325 /* fall through */
1326 case SW_SHOW:
1327 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1330 * ShowWindow has a little peculiar behavior that if the
1331 * window is already the topmost window, it will not
1332 * activate it.
1334 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1335 swp |= SWP_NOACTIVATE;
1337 break;
1339 case SW_SHOWNOACTIVATE:
1340 swp |= SWP_NOZORDER;
1341 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1342 /* fall through */
1343 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1344 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1345 case SW_RESTORE:
1346 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1348 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1349 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1350 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1351 break;
1354 showFlag = (cmd != SW_HIDE);
1355 if (showFlag != wasVisible)
1357 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1358 if (!IsWindow( hwnd )) goto END;
1361 if ((wndPtr->dwStyle & WS_CHILD) &&
1362 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1363 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1365 /* Don't call SetWindowPos() on invisible child windows */
1366 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1367 else wndPtr->dwStyle |= WS_VISIBLE;
1369 else
1371 /* We can't activate a child window */
1372 if ((wndPtr->dwStyle & WS_CHILD) &&
1373 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1374 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1375 if (!(swp & MINMAX_NOSWP))
1377 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1378 newPos.right, newPos.bottom, LOWORD(swp) );
1379 if (cmd == SW_HIDE)
1381 /* FIXME: This will cause the window to be activated irrespective
1382 * of whether it is owned by the same thread. Has to be done
1383 * asynchronously.
1386 if (hwnd == GetActiveWindow())
1387 WINPOS_ActivateOtherWindow(wndPtr);
1389 /* Revert focus to parent */
1390 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1391 SetFocus( GetParent(hwnd) );
1394 if (!IsWindow( hwnd )) goto END;
1395 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1398 if (wndPtr->flags & WIN_NEED_SIZE)
1400 /* should happen only in CreateWindowEx() */
1401 int wParam = SIZE_RESTORED;
1403 wndPtr->flags &= ~WIN_NEED_SIZE;
1404 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1405 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1406 SendMessageA( hwnd, WM_SIZE, wParam,
1407 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1408 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1409 SendMessageA( hwnd, WM_MOVE, 0,
1410 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1413 END:
1414 WIN_ReleaseWndPtr(wndPtr);
1415 return wasVisible;
1419 /***********************************************************************
1420 * GetInternalWindowPos16 (USER.460)
1422 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1423 LPPOINT16 ptIcon )
1425 WINDOWPLACEMENT16 wndpl;
1426 if (GetWindowPlacement16( hwnd, &wndpl ))
1428 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1429 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1430 return wndpl.showCmd;
1432 return 0;
1436 /***********************************************************************
1437 * GetInternalWindowPos (USER32.245)
1439 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1440 LPPOINT ptIcon )
1442 WINDOWPLACEMENT wndpl;
1443 if (GetWindowPlacement( hwnd, &wndpl ))
1445 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1446 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1447 return wndpl.showCmd;
1449 return 0;
1452 /***********************************************************************
1453 * GetWindowPlacement16 (USER.370)
1455 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1457 WND *pWnd = WIN_FindWndPtr( hwnd );
1458 LPINTERNALPOS lpPos;
1460 if(!pWnd ) return FALSE;
1462 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1463 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1464 wndpl->length = sizeof(*wndpl);
1465 if( pWnd->dwStyle & WS_MINIMIZE )
1466 wndpl->showCmd = SW_SHOWMINIMIZED;
1467 else
1468 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1469 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1470 if( pWnd->flags & WIN_RESTORE_MAX )
1471 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1472 else
1473 wndpl->flags = 0;
1474 wndpl->ptMinPosition = lpPos->ptIconPos;
1475 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1476 wndpl->rcNormalPosition = lpPos->rectNormal;
1478 WIN_ReleaseWndPtr(pWnd);
1479 return TRUE;
1483 /***********************************************************************
1484 * GetWindowPlacement (USER32.307)
1486 * Win95:
1487 * Fails if wndpl->length of Win95 (!) apps is invalid.
1489 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1491 if( pwpl32 )
1493 WINDOWPLACEMENT16 wpl;
1494 wpl.length = sizeof(wpl);
1495 if( GetWindowPlacement16( hwnd, &wpl ) )
1497 pwpl32->length = sizeof(*pwpl32);
1498 pwpl32->flags = wpl.flags;
1499 pwpl32->showCmd = wpl.showCmd;
1500 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1501 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1502 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1503 return TRUE;
1506 return FALSE;
1510 /***********************************************************************
1511 * WINPOS_SetPlacement
1513 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1514 UINT flags )
1516 WND *pWnd = WIN_FindWndPtr( hwnd );
1517 if( pWnd )
1519 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1520 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1522 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1523 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1524 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1526 if( pWnd->dwStyle & WS_MINIMIZE )
1528 WINPOS_ShowIconTitle( pWnd, FALSE );
1529 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1530 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1531 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1533 else if( pWnd->dwStyle & WS_MAXIMIZE )
1535 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1536 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1537 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1539 else if( flags & PLACE_RECT )
1540 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1541 lpPos->rectNormal.right - lpPos->rectNormal.left,
1542 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1543 SWP_NOZORDER | SWP_NOACTIVATE );
1545 ShowWindow( hwnd, wndpl->showCmd );
1546 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1548 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1550 /* SDK: ...valid only the next time... */
1551 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1553 WIN_ReleaseWndPtr(pWnd);
1554 return TRUE;
1556 return FALSE;
1560 /***********************************************************************
1561 * SetWindowPlacement16 (USER.371)
1563 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1565 return WINPOS_SetPlacement( hwnd, wndpl,
1566 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1569 /***********************************************************************
1570 * SetWindowPlacement (USER32.519)
1572 * Win95:
1573 * Fails if wndpl->length of Win95 (!) apps is invalid.
1575 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1577 if( pwpl32 )
1579 WINDOWPLACEMENT16 wpl;
1581 wpl.length = sizeof(WINDOWPLACEMENT16);
1582 wpl.flags = pwpl32->flags;
1583 wpl.showCmd = pwpl32->showCmd;
1584 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1585 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1586 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1587 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1588 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1589 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1590 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1591 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1593 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1595 return FALSE;
1599 /***********************************************************************
1600 * SetInternalWindowPos16 (USER.461)
1602 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1603 LPRECT16 rect, LPPOINT16 pt )
1605 if( IsWindow16(hwnd) )
1607 WINDOWPLACEMENT16 wndpl;
1608 UINT flags;
1610 wndpl.length = sizeof(wndpl);
1611 wndpl.showCmd = showCmd;
1612 wndpl.flags = flags = 0;
1614 if( pt )
1616 flags |= PLACE_MIN;
1617 wndpl.flags |= WPF_SETMINPOSITION;
1618 wndpl.ptMinPosition = *pt;
1620 if( rect )
1622 flags |= PLACE_RECT;
1623 wndpl.rcNormalPosition = *rect;
1625 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1630 /***********************************************************************
1631 * SetInternalWindowPos (USER32.483)
1633 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1634 LPRECT rect, LPPOINT pt )
1636 if( IsWindow(hwnd) )
1638 WINDOWPLACEMENT16 wndpl;
1639 UINT flags;
1641 wndpl.length = sizeof(wndpl);
1642 wndpl.showCmd = showCmd;
1643 wndpl.flags = flags = 0;
1645 if( pt )
1647 flags |= PLACE_MIN;
1648 wndpl.flags |= WPF_SETMINPOSITION;
1649 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1651 if( rect )
1653 flags |= PLACE_RECT;
1654 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1656 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1660 /*******************************************************************
1661 * WINPOS_SetActiveWindow
1663 * SetActiveWindow() back-end. This is the only function that
1664 * can assign active status to a window. It must be called only
1665 * for the top level windows.
1667 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1669 CBTACTIVATESTRUCT16* cbtStruct;
1670 WND* wndPtr=0, *wndTemp;
1671 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1672 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1673 WORD wIconized = 0;
1674 HWND hwndActive = 0;
1675 BOOL bRet = 0;
1677 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1679 /* Get current active window from the active queue */
1680 if ( hActiveQueue )
1682 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1683 if ( pOldActiveQueue )
1684 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1687 /* paranoid checks */
1688 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1689 goto CLEANUP_END;
1691 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1692 * return 0;
1694 wndPtr = WIN_FindWndPtr(hWnd);
1695 hOldActiveQueue = hActiveQueue;
1697 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1699 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1700 WIN_ReleaseWndPtr(wndTemp);
1702 else
1703 TRACE("no current active window.\n");
1705 /* call CBT hook chain */
1706 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1708 cbtStruct->fMouse = fMouse;
1709 cbtStruct->hWndActive = hwndActive;
1710 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1711 (LPARAM)SEGPTR_GET(cbtStruct) );
1712 SEGPTR_FREE(cbtStruct);
1713 if (bRet) goto CLEANUP_END;
1716 /* set prev active wnd to current active wnd and send notification */
1717 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1719 MESSAGEQUEUE *pTempActiveQueue = 0;
1721 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1723 if (GetSysModalWindow16() != hWnd)
1724 goto CLEANUP_END;
1725 /* disregard refusal if hWnd is sysmodal */
1728 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1729 MAKEWPARAM( WA_INACTIVE, wIconized ),
1730 (LPARAM)hWnd );
1732 /* check if something happened during message processing
1733 * (global active queue may have changed)
1735 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1736 if(!pTempActiveQueue)
1737 goto CLEANUP_END;
1739 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1740 QUEUE_Unlock( pTempActiveQueue );
1741 if( hwndPrevActive != hwndActive )
1742 goto CLEANUP_END;
1745 /* Set new active window in the message queue */
1746 hwndActive = hWnd;
1747 if ( wndPtr )
1749 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1750 if ( pNewActiveQueue )
1751 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1753 else /* have to do this or MDI frame activation goes to hell */
1754 if( pOldActiveQueue )
1755 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1757 /* send palette messages */
1758 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1759 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1761 /* if prev wnd is minimized redraw icon title */
1762 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1764 /* managed windows will get ConfigureNotify event */
1765 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1767 /* check Z-order and bring hWnd to the top */
1768 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1770 if (wndTemp->dwStyle & WS_VISIBLE) break;
1772 WIN_ReleaseDesktop();
1773 WIN_ReleaseWndPtr(wndTemp);
1775 if( wndTemp != wndPtr )
1776 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1777 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1778 if (!IsWindow(hWnd))
1779 goto CLEANUP;
1782 /* Get a handle to the new active queue */
1783 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1785 /* send WM_ACTIVATEAPP if necessary */
1786 if (hOldActiveQueue != hNewActiveQueue)
1788 WND **list, **ppWnd;
1789 WND *pDesktop = WIN_GetDesktop();
1791 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1793 for (ppWnd = list; *ppWnd; ppWnd++)
1795 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1797 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1798 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1799 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1801 WIN_ReleaseWinArray(list);
1804 hActiveQueue = hNewActiveQueue;
1806 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1808 for (ppWnd = list; *ppWnd; ppWnd++)
1810 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1812 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1813 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1814 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1816 WIN_ReleaseWinArray(list);
1818 WIN_ReleaseDesktop();
1820 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1823 if (hWnd)
1825 /* walk up to the first unowned window */
1826 wndTemp = WIN_LockWndPtr(wndPtr);
1827 while (wndTemp->owner)
1829 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1831 /* and set last active owned popup */
1832 wndTemp->hwndLastActive = hWnd;
1834 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1835 WIN_ReleaseWndPtr(wndTemp);
1836 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1837 SendMessageA( hWnd, WM_ACTIVATE,
1838 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1839 (LPARAM)hwndPrevActive );
1840 if( !IsWindow(hWnd) ) goto CLEANUP;
1843 /* change focus if possible */
1844 if ( fChangeFocus )
1846 if ( pNewActiveQueue )
1848 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1850 if ( WIN_GetTopParent( hOldFocus ) != hwndActive )
1851 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1852 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1853 0 : hwndActive );
1856 if ( pOldActiveQueue &&
1857 ( !pNewActiveQueue ||
1858 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1860 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1861 if ( hOldFocus )
1862 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1866 if( !hwndPrevActive && wndPtr )
1867 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1869 /* if active wnd is minimized redraw icon title */
1870 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1872 bRet = (hWnd == hwndActive); /* Success? */
1874 CLEANUP: /* Unlock the message queues before returning */
1876 if ( pNewActiveQueue )
1877 QUEUE_Unlock( pNewActiveQueue );
1879 CLEANUP_END:
1881 if ( pOldActiveQueue )
1882 QUEUE_Unlock( pOldActiveQueue );
1884 WIN_ReleaseWndPtr(wndPtr);
1885 return bRet;
1888 /*******************************************************************
1889 * WINPOS_ActivateOtherWindow
1891 * Activates window other than pWnd.
1893 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1895 BOOL bRet = 0;
1896 WND* pWndTo = NULL;
1897 HWND hwndActive = 0;
1899 /* Get current active window from the active queue */
1900 if ( hActiveQueue )
1902 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1903 if ( pActiveQueue )
1905 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1906 QUEUE_Unlock( pActiveQueue );
1910 if( pWnd->hwndSelf == hwndPrevActive )
1911 hwndPrevActive = 0;
1913 if( hwndActive != pWnd->hwndSelf &&
1914 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1915 return 0;
1917 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1918 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1920 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1922 WIN_ReleaseWndPtr(pWndTo);
1923 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1925 while( !WINPOS_CanActivate(pWndTo) )
1927 /* by now owned windows should've been taken care of */
1928 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1929 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1930 if( !pWndTo ) break;
1932 WIN_ReleaseWndPtr(pWndPtr);
1935 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1937 /* switch desktop queue to current active */
1938 if( pWndTo )
1940 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1941 WIN_ReleaseWndPtr(pWndTo);
1942 WIN_ReleaseDesktop();
1945 hwndPrevActive = 0;
1946 return bRet;
1949 /*******************************************************************
1950 * WINPOS_ChangeActiveWindow
1953 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1955 WND *wndPtr, *wndTemp;
1956 BOOL retvalue;
1957 HWND hwndActive = 0;
1959 /* Get current active window from the active queue */
1960 if ( hActiveQueue )
1962 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1963 if ( pActiveQueue )
1965 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1966 QUEUE_Unlock( pActiveQueue );
1970 if (!hWnd)
1971 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1973 wndPtr = WIN_FindWndPtr(hWnd);
1974 if( !wndPtr ) return FALSE;
1976 /* child windows get WM_CHILDACTIVATE message */
1977 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1979 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1980 goto end;
1983 if( hWnd == hwndActive )
1985 retvalue = FALSE;
1986 goto end;
1989 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1991 retvalue = FALSE;
1992 goto end;
1995 /* switch desktop queue to current active */
1996 wndTemp = WIN_GetDesktop();
1997 if( wndPtr->parent == wndTemp)
1998 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
1999 WIN_ReleaseDesktop();
2001 retvalue = TRUE;
2002 end:
2003 WIN_ReleaseWndPtr(wndPtr);
2004 return retvalue;
2008 /***********************************************************************
2009 * WINPOS_SendNCCalcSize
2011 * Send a WM_NCCALCSIZE message to a window.
2012 * All parameters are read-only except newClientRect.
2013 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2014 * when calcValidRect is TRUE.
2016 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2017 RECT *newWindowRect, RECT *oldWindowRect,
2018 RECT *oldClientRect, WINDOWPOS *winpos,
2019 RECT *newClientRect )
2021 NCCALCSIZE_PARAMS params;
2022 WINDOWPOS winposCopy;
2023 LONG result;
2025 params.rgrc[0] = *newWindowRect;
2026 if (calcValidRect)
2028 winposCopy = *winpos;
2029 params.rgrc[1] = *oldWindowRect;
2030 params.rgrc[2] = *oldClientRect;
2031 params.lppos = &winposCopy;
2033 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2034 (LPARAM)&params );
2035 TRACE("%d,%d-%d,%d\n",
2036 params.rgrc[0].left, params.rgrc[0].top,
2037 params.rgrc[0].right, params.rgrc[0].bottom );
2039 /* If the application send back garbage, ignore it */
2040 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2041 *newClientRect = params.rgrc[0];
2043 return result;
2047 /***********************************************************************
2048 * WINPOS_HandleWindowPosChanging16
2050 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2052 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2054 POINT maxSize, minTrack;
2055 if (winpos->flags & SWP_NOSIZE) return 0;
2056 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2057 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2059 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2060 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2061 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2062 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2064 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2065 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2068 return 0;
2072 /***********************************************************************
2073 * WINPOS_HandleWindowPosChanging
2075 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2077 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2079 POINT maxSize;
2080 if (winpos->flags & SWP_NOSIZE) return 0;
2081 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2082 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2084 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2085 winpos->cx = MIN( winpos->cx, maxSize.x );
2086 winpos->cy = MIN( winpos->cy, maxSize.y );
2088 return 0;
2091 /***********************************************************************
2092 * SWP_DoOwnedPopups
2094 * fix Z order taking into account owned popups -
2095 * basically we need to maintain them above the window that owns them
2097 * FIXME: hide/show owned popups when owner visibility changes.
2099 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2101 WND* w = WIN_LockWndPtr(pDesktop->child);
2103 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2105 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2107 /* make sure this popup stays above the owner */
2109 HWND hwndLocalPrev = HWND_TOP;
2111 if( hwndInsertAfter != HWND_TOP )
2113 while( w != wndPtr->owner )
2115 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2116 if( hwndLocalPrev == hwndInsertAfter ) break;
2117 WIN_UpdateWndPtr(&w,w->next);
2119 hwndInsertAfter = hwndLocalPrev;
2122 else if( wndPtr->dwStyle & WS_CHILD )
2123 goto END;
2125 WIN_UpdateWndPtr(&w, pDesktop->child);
2127 while( w )
2129 if( w == wndPtr ) break;
2131 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2133 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2134 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2135 hwndInsertAfter = w->hwndSelf;
2137 WIN_UpdateWndPtr(&w, w->next);
2140 END:
2141 WIN_ReleaseWndPtr(w);
2142 return hwndInsertAfter;
2145 /***********************************************************************
2146 * SWP_CopyValidBits
2148 * Make window look nice without excessive repainting
2150 * visible and update regions are in window coordinates
2151 * client and window rectangles are in parent client coordinates
2153 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2154 * window rects have the same origin.
2156 * Returns: uFlags and a dirty region in *pVisRgn.
2158 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2159 LPRECT lpOldWndRect,
2160 LPRECT lpOldClientRect, UINT uFlags )
2162 RECT r;
2163 HRGN newVisRgn, dirtyRgn;
2164 INT my = COMPLEXREGION;
2166 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2167 Wnd->rectWindow.left, Wnd->rectWindow.top,
2168 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2169 lpOldWndRect->left, lpOldWndRect->top,
2170 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2171 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2172 Wnd->rectClient.left, Wnd->rectClient.top,
2173 Wnd->rectClient.right, Wnd->rectClient.bottom,
2174 lpOldClientRect->left, lpOldClientRect->top,
2175 lpOldClientRect->right,lpOldClientRect->bottom );
2177 if( Wnd->hrgnUpdate == 1 )
2178 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2180 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2181 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2183 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2184 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2186 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2188 nocopy:
2190 TRACE("\twon't copy anything!\n");
2192 /* set dirtyRgn to the sum of old and new visible regions
2193 * in parent client coordinates */
2195 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2196 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2198 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2200 else /* copy valid bits to a new location */
2202 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2203 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2205 /* subtract already invalid region inside Wnd from the dst region */
2207 if( Wnd->hrgnUpdate )
2208 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2209 goto nocopy;
2211 /* check if entire window can be copied */
2213 ow = lpOldWndRect->right - lpOldWndRect->left;
2214 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2215 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2216 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2218 ocw = lpOldClientRect->right - lpOldClientRect->left;
2219 och = lpOldClientRect->bottom - lpOldClientRect->top;
2220 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2221 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2223 if( (ocw != ncw) || (och != nch) ||
2224 ( ow != nw) || ( oh != nh) ||
2225 ((lpOldClientRect->top - lpOldWndRect->top) !=
2226 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2227 ((lpOldClientRect->left - lpOldWndRect->left) !=
2228 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2230 dx = Wnd->rectClient.left - lpOldClientRect->left;
2231 dy = Wnd->rectClient.top - lpOldClientRect->top;
2233 /* restrict valid bits to the common client rect */
2235 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2236 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2237 r.right = r.left + MIN( ocw, ncw );
2238 r.bottom = r.top + MIN( och, nch );
2240 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2241 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2242 GetRgnBox( hrgnValid, &r );
2243 if( IsRectEmpty( &r ) )
2244 goto nocopy;
2245 r = *lpOldClientRect;
2247 else
2249 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2250 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2251 if( !(uFlags & SWP_EX_PAINTSELF) )
2252 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2253 r = *lpOldWndRect;
2256 if( !(uFlags & SWP_EX_PAINTSELF) )
2258 /* Move remaining regions to parent coordinates */
2259 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2260 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2262 else
2263 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2265 TRACE("\tcomputing dirty region!\n");
2267 /* Compute combined dirty region (old + new - valid) */
2268 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2269 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2271 /* Blt valid bits, r is the rect to copy */
2273 if( dx || dy )
2275 RECT rClip;
2276 HDC hDC;
2277 DC* dc;
2279 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2280 from copying clipped areas */
2282 if( uFlags & SWP_EX_PAINTSELF )
2284 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2285 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2286 rClip.right = nw; rClip.bottom = nh;
2288 else
2290 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2291 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2292 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2293 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2295 rClip.left = rClip.top = 0;
2297 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2299 if( oh > nh ) r.bottom = r.top + nh;
2300 if( ow < nw ) r.right = r.left + nw;
2302 if( IntersectRect( &r, &r, &rClip ) )
2304 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2306 /* When you copy the bits without repainting, parent doesn't
2307 get validated appropriately. Therefore, we have to validate
2308 the parent with the windows' updated region when the
2309 parent's update region is not empty. */
2311 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2313 OffsetRect(&r, dx, dy);
2314 ValidateRect(Wnd->parent->hwndSelf, &r);
2318 GDI_HEAP_UNLOCK( hDC );
2320 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2321 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2325 /* *pVisRgn now points to the invalidated region */
2327 DeleteObject(newVisRgn);
2328 DeleteObject(dirtyRgn);
2329 return uFlags;
2332 /***********************************************************************
2333 * SWP_DoSimpleFrameChanged
2335 * NOTE: old and new client rect origins are identical, only
2336 * extents may have changed. Window extents are the same.
2338 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2340 INT i = 0;
2341 RECT rect;
2342 HRGN hrgn = 0;
2344 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2346 /* Client rect changed its position/size, most likely a scrollar
2347 * was added/removed.
2349 * FIXME: WVR alignment flags
2352 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2354 i++;
2355 rect.top = 0;
2356 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2357 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2358 if(!(uFlags & SWP_EX_NOCOPY))
2359 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2360 else
2362 rect.left = 0;
2363 goto redraw;
2367 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2369 if( i )
2370 hrgn = CreateRectRgnIndirect( &rect );
2371 rect.left = 0;
2372 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2373 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2374 if(!(uFlags & SWP_EX_NOCOPY))
2375 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2376 else
2377 rect.top = 0;
2378 if( i++ )
2379 REGION_UnionRectWithRgn( hrgn, &rect );
2382 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2384 rect = wndPtr->rectWindow;
2385 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2386 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2387 i++;
2391 if( i )
2393 redraw:
2394 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2395 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2397 else
2399 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2402 if( hrgn > 1 )
2403 DeleteObject( hrgn );
2406 /***********************************************************************
2407 * SWP_DoWinPosChanging
2409 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2410 RECT* pNewWindowRect, RECT* pNewClientRect )
2412 /* Send WM_WINDOWPOSCHANGING message */
2414 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2415 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2417 /* Calculate new position and size */
2419 *pNewWindowRect = wndPtr->rectWindow;
2420 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2421 : wndPtr->rectClient;
2423 if (!(pWinpos->flags & SWP_NOSIZE))
2425 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2426 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2428 if (!(pWinpos->flags & SWP_NOMOVE))
2430 pNewWindowRect->left = pWinpos->x;
2431 pNewWindowRect->top = pWinpos->y;
2432 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2433 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2435 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2436 pWinpos->y - wndPtr->rectWindow.top );
2439 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2440 return TRUE;
2443 /***********************************************************************
2444 * SWP_DoNCCalcSize
2446 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2447 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2449 UINT wvrFlags = 0;
2451 /* Send WM_NCCALCSIZE message to get new client area */
2452 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2454 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2455 &wndPtr->rectWindow, &wndPtr->rectClient,
2456 pWinpos, pNewClientRect );
2458 /* FIXME: WVR_ALIGNxxx */
2460 if( pNewClientRect->left != wndPtr->rectClient.left ||
2461 pNewClientRect->top != wndPtr->rectClient.top )
2462 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2464 if( (pNewClientRect->right - pNewClientRect->left !=
2465 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2466 (pNewClientRect->bottom - pNewClientRect->top !=
2467 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2468 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2470 else
2471 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2472 pNewClientRect->top != wndPtr->rectClient.top) )
2473 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2474 return wvrFlags;
2477 /***********************************************************************
2478 * SetWindowPos (USER.2)
2480 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2481 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2483 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2486 /***********************************************************************
2487 * SetWindowPos (USER32.520)
2489 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2490 INT x, INT y, INT cx, INT cy, UINT flags )
2492 WINDOWPOS winpos;
2493 WND * wndPtr,*wndTemp;
2494 RECT newWindowRect, newClientRect;
2495 RECT oldWindowRect, oldClientRect;
2496 HRGN visRgn = 0;
2497 UINT wvrFlags = 0, uFlags = 0;
2498 BOOL retvalue, resync = FALSE, bChangePos;
2499 HWND hwndActive = 0;
2501 /* Get current active window from the active queue */
2502 if ( hActiveQueue )
2504 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2505 if ( pActiveQueue )
2507 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2508 QUEUE_Unlock( pActiveQueue );
2512 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2513 hwnd, x, y, x+cx, y+cy, flags);
2515 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2516 flags &= ~SWP_WINE_NOHOSTMOVE;
2519 /* ------------------------------------------------------------------------ CHECKS */
2521 /* Check window handle */
2523 if (hwnd == GetDesktopWindow()) return FALSE;
2524 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2526 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2527 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2529 /* Fix redundant flags */
2531 if(wndPtr->dwStyle & WS_VISIBLE)
2532 flags &= ~SWP_SHOWWINDOW;
2533 else
2535 if (!(flags & SWP_SHOWWINDOW))
2536 flags |= SWP_NOREDRAW;
2537 flags &= ~SWP_HIDEWINDOW;
2540 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2542 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2543 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2544 flags |= SWP_NOSIZE; /* Already the right size */
2546 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2547 flags |= SWP_NOMOVE; /* Already the right position */
2549 if (hwnd == hwndActive)
2550 flags |= SWP_NOACTIVATE; /* Already active */
2551 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2553 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2555 flags &= ~SWP_NOZORDER;
2556 hwndInsertAfter = HWND_TOP;
2557 goto Pos;
2561 /* Check hwndInsertAfter */
2563 /* FIXME: TOPMOST not supported yet */
2564 if ((hwndInsertAfter == HWND_TOPMOST) ||
2565 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2567 /* hwndInsertAfter must be a sibling of the window */
2568 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2570 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2572 if( wnd ) {
2573 if( wnd->parent != wndPtr->parent )
2575 retvalue = FALSE;
2576 WIN_ReleaseWndPtr(wnd);
2577 goto END;
2579 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2581 WIN_ReleaseWndPtr(wnd);
2584 Pos: /* ------------------------------------------------------------------------ MAIN part */
2586 /* Fill the WINDOWPOS structure */
2588 winpos.hwnd = hwnd;
2589 winpos.hwndInsertAfter = hwndInsertAfter;
2590 winpos.x = x;
2591 winpos.y = y;
2592 winpos.cx = cx;
2593 winpos.cy = cy;
2594 winpos.flags = flags;
2596 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2598 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2600 if( wndPtr->parent == WIN_GetDesktop() )
2601 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2602 hwndInsertAfter, winpos.flags );
2603 WIN_ReleaseDesktop();
2606 if(!(wndPtr->flags & WIN_NATIVE) )
2608 if( hwndInsertAfter == HWND_TOP )
2609 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2610 else
2611 if( hwndInsertAfter == HWND_BOTTOM )
2612 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2613 else
2614 if( !(winpos.flags & SWP_NOZORDER) )
2615 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2616 winpos.flags |= SWP_NOZORDER;
2618 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2619 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2620 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2622 /* get a previous visible region for SWP_CopyValidBits() */
2623 DWORD flags = DCX_WINDOW;
2625 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2626 flags |= DCX_CLIPSIBLINGS;
2628 visRgn = DCE_GetVisRgn(hwnd, flags, 0, 0);
2632 /* Common operations */
2634 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2636 if(!(winpos.flags & SWP_NOZORDER))
2638 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2639 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2642 /* Reset active DCEs */
2644 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2645 wndPtr->dwStyle & WS_VISIBLE) ||
2646 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2648 RECT rect;
2650 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2651 DCE_InvalidateDCE(wndPtr, &rect);
2654 oldWindowRect = wndPtr->rectWindow;
2655 oldClientRect = wndPtr->rectClient;
2657 /* Find out if we have to redraw the whole client rect */
2659 if( oldClientRect.bottom - oldClientRect.top ==
2660 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2662 if( oldClientRect.right - oldClientRect.left ==
2663 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2665 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2666 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2668 uFlags |= SWP_EX_NOCOPY;
2671 * Use this later in CopyValidBits()
2673 else if( 0 )
2674 uFlags |= SWP_EX_NONCLIENT;
2677 /* FIXME: actually do something with WVR_VALIDRECTS */
2679 wndPtr->rectWindow = newWindowRect;
2680 wndPtr->rectClient = newClientRect;
2682 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2684 BOOL bCallDriver = TRUE;
2685 HWND tempInsertAfter = winpos.hwndInsertAfter;
2687 winpos.hwndInsertAfter = hwndInsertAfter;
2689 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2691 /* This is the only place where we need to force repainting of the contents
2692 of windows created by the host window system, all other cases go through the
2693 expose event handling */
2695 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2697 cx = newWindowRect.right - newWindowRect.left;
2698 cy = newWindowRect.bottom - newWindowRect.top;
2700 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2701 winpos.hwndInsertAfter = tempInsertAfter;
2702 bCallDriver = FALSE;
2704 if( winpos.flags & SWP_NOCLIENTMOVE )
2705 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2706 else
2708 /* client area moved but window extents remained the same, copy valid bits */
2710 visRgn = CreateRectRgn( 0, 0, cx, cy );
2711 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2712 uFlags | SWP_EX_PAINTSELF );
2717 if( bCallDriver )
2719 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2721 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2722 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2723 !(uFlags & SWP_EX_NOCOPY) )
2725 /* The origin of the client rect didn't move so we can try to repaint
2726 * only the nonclient area by setting bit gravity hint for the host window system.
2729 if( !(wndPtr->flags & WIN_MANAGED) )
2731 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2732 newWindowRect.bottom - newWindowRect.top);
2733 RECT rcn = newClientRect;
2734 RECT rco = oldClientRect;
2736 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2737 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2738 IntersectRect( &rcn, &rcn, &rco );
2739 visRgn = CreateRectRgnIndirect( &rcn );
2740 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2741 DeleteObject( hrgn );
2742 uFlags = SWP_EX_PAINTSELF;
2744 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2746 else
2747 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2750 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2751 winpos.hwndInsertAfter = tempInsertAfter;
2754 if( winpos.flags & SWP_SHOWWINDOW )
2756 HWND focus, curr;
2758 wndPtr->dwStyle |= WS_VISIBLE;
2760 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2762 /* focus was set to unmapped window, reset host focus
2763 * since the window is now visible */
2765 focus = curr = GetFocus();
2766 while (curr)
2768 if (curr == hwnd)
2770 WND *pFocus = WIN_FindWndPtr( focus );
2771 if (pFocus)
2772 pFocus->pDriver->pSetFocus(pFocus);
2773 WIN_ReleaseWndPtr(pFocus);
2774 break;
2776 curr = GetParent(curr);
2780 else /* -------------------------------------------- emulated window */
2782 if( winpos.flags & SWP_SHOWWINDOW )
2784 wndPtr->dwStyle |= WS_VISIBLE;
2785 uFlags |= SWP_EX_PAINTSELF;
2786 visRgn = 1; /* redraw the whole window */
2788 else if( !(winpos.flags & SWP_NOREDRAW) )
2790 if( winpos.flags & SWP_HIDEWINDOW )
2792 if( visRgn > 1 ) /* map to parent */
2793 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2794 else
2795 visRgn = 0;
2797 else
2799 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2800 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2801 &oldClientRect, uFlags);
2802 else
2804 /* nothing moved, redraw frame if needed */
2806 if( winpos.flags & SWP_FRAMECHANGED )
2807 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2808 if( visRgn )
2810 DeleteObject( visRgn );
2811 visRgn = 0;
2818 if( winpos.flags & SWP_HIDEWINDOW )
2820 wndPtr->dwStyle &= ~WS_VISIBLE;
2822 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2825 /* ------------------------------------------------------------------------ FINAL */
2827 if (wndPtr->flags & WIN_NATIVE)
2828 EVENT_Synchronize(); /* Synchronize with the host window system */
2830 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2832 /* Simulate a mouse event to set the cursor */
2833 DWORD posX, posY, keyState;
2835 if ( EVENT_QueryPointer( &posX, &posY, &keyState ) )
2837 int iWndsLocks = WIN_SuspendWndsLock();
2839 hardware_event( WM_MOUSEMOVE, keyState, 0,
2840 posX, posY, GetTickCount(), 0 );
2842 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;