Link only a single .rc file with application.
[wine/multimedia.git] / windows / winpos.c
blob1c6fb94195b59e3bf8c27ff33d60ec9a7c61611d
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"
26 #include "input.h"
28 DEFAULT_DEBUG_CHANNEL(win)
30 #define HAS_DLGFRAME(style,exStyle) \
31 (((exStyle) & WS_EX_DLGMODALFRAME) || \
32 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
34 #define HAS_THICKFRAME(style) \
35 (((style) & WS_THICKFRAME) && \
36 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
38 #define SWP_AGG_NOGEOMETRYCHANGE \
39 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
40 #define SWP_AGG_NOPOSCHANGE \
41 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
42 #define SWP_AGG_STATUSFLAGS \
43 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
45 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
47 #define PLACE_MIN 0x0001
48 #define PLACE_MAX 0x0002
49 #define PLACE_RECT 0x0004
51 #define SWP_EX_NOCOPY 0x0001
52 #define SWP_EX_PAINTSELF 0x0002
53 #define SWP_EX_NONCLIENT 0x0004
55 #define MINMAX_NOSWP 0x00010000
57 /* ----- internal variables ----- */
59 static HWND hwndPrevActive = 0; /* Previously active window */
60 static HWND hGlobalShellWindow=0; /*the shell*/
61 static HWND hGlobalTaskmanWindow=0;
62 static HWND hGlobalProgmanWindow=0;
64 static LPCSTR atomInternalPos;
66 extern HQUEUE16 hActiveQueue;
68 /***********************************************************************
69 * WINPOS_CreateInternalPosAtom
71 BOOL WINPOS_CreateInternalPosAtom()
73 LPSTR str = "SysIP";
74 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
75 return (atomInternalPos) ? TRUE : FALSE;
78 /***********************************************************************
79 * WINPOS_CheckInternalPos
81 * Called when a window is destroyed.
83 void WINPOS_CheckInternalPos( WND* wndPtr )
85 LPINTERNALPOS lpPos;
86 MESSAGEQUEUE *pMsgQ = 0;
87 HWND hwnd = wndPtr->hwndSelf;
89 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
91 /* Retrieve the message queue associated with this window */
92 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
93 if ( !pMsgQ )
95 WARN("\tMessage queue not found. Exiting!\n" );
96 return;
99 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
101 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
103 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
104 WARN("\tattempt to activate destroyed window!\n");
107 if( lpPos )
109 if( IsWindow(lpPos->hwndIconTitle) )
110 DestroyWindow( lpPos->hwndIconTitle );
111 HeapFree( SystemHeap, 0, lpPos );
114 QUEUE_Unlock( pMsgQ );
115 return;
118 /***********************************************************************
119 * WINPOS_FindIconPos
121 * Find a suitable place for an iconic window.
123 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
125 RECT16 rectParent;
126 short x, y, xspacing, yspacing;
128 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
129 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
130 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
131 return pt; /* The icon already has a suitable position */
133 xspacing = GetSystemMetrics(SM_CXICONSPACING);
134 yspacing = GetSystemMetrics(SM_CYICONSPACING);
136 y = rectParent.bottom;
137 for (;;)
139 x = rectParent.left;
142 /* Check if another icon already occupies this spot */
143 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
144 while (childPtr)
146 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
148 if ((childPtr->rectWindow.left < x + xspacing) &&
149 (childPtr->rectWindow.right >= x) &&
150 (childPtr->rectWindow.top <= y) &&
151 (childPtr->rectWindow.bottom > y - yspacing))
152 break; /* There's a window in there */
154 WIN_UpdateWndPtr(&childPtr,childPtr->next);
156 WIN_ReleaseWndPtr(childPtr);
157 if (!childPtr) /* No window was found, so it's OK for us */
159 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
160 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
161 return pt;
163 x += xspacing;
164 } while(x <= rectParent.right-xspacing);
165 y -= yspacing;
170 /***********************************************************************
171 * ArrangeIconicWindows16 (USER.170)
173 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
175 return ArrangeIconicWindows(parent);
177 /***********************************************************************
178 * ArrangeIconicWindows (USER32.7)
180 UINT WINAPI ArrangeIconicWindows( HWND parent )
182 RECT rectParent;
183 HWND hwndChild;
184 INT x, y, xspacing, yspacing;
186 GetClientRect( parent, &rectParent );
187 x = rectParent.left;
188 y = rectParent.bottom;
189 xspacing = GetSystemMetrics(SM_CXICONSPACING);
190 yspacing = GetSystemMetrics(SM_CYICONSPACING);
192 hwndChild = GetWindow( parent, GW_CHILD );
193 while (hwndChild)
195 if( IsIconic( hwndChild ) )
197 WND *wndPtr = WIN_FindWndPtr(hwndChild);
199 WINPOS_ShowIconTitle( wndPtr, FALSE );
201 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
202 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
203 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
204 if( IsWindow(hwndChild) )
205 WINPOS_ShowIconTitle(wndPtr , TRUE );
206 WIN_ReleaseWndPtr(wndPtr);
208 if (x <= rectParent.right - xspacing) x += xspacing;
209 else
211 x = rectParent.left;
212 y -= yspacing;
215 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
217 return yspacing;
221 /***********************************************************************
222 * SwitchToThisWindow16 (USER.172)
224 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
226 SwitchToThisWindow( hwnd, restore );
230 /***********************************************************************
231 * SwitchToThisWindow (USER32.539)
233 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
235 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
239 /***********************************************************************
240 * GetWindowRect16 (USER.32)
242 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
244 WND * wndPtr = WIN_FindWndPtr( hwnd );
245 if (!wndPtr) return;
247 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
248 if (wndPtr->dwStyle & WS_CHILD)
249 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
250 WIN_ReleaseWndPtr(wndPtr);
254 /***********************************************************************
255 * GetWindowRect (USER32.308)
257 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
259 WND * wndPtr = WIN_FindWndPtr( hwnd );
260 if (!wndPtr) return FALSE;
262 *rect = wndPtr->rectWindow;
263 if (wndPtr->dwStyle & WS_CHILD)
264 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
265 WIN_ReleaseWndPtr(wndPtr);
266 return TRUE;
270 /***********************************************************************
271 * GetWindowRgn
273 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
276 RECT rect;
277 WND * wndPtr = WIN_FindWndPtr( hwnd );
278 if (!wndPtr) return (ERROR);
280 FIXME("GetWindowRgn: doesn't really do regions\n");
282 memset (&rect, 0, sizeof(rect));
284 GetWindowRect ( hwnd, &rect );
286 FIXME("Check whether a valid region here\n");
288 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
290 WIN_ReleaseWndPtr(wndPtr);
291 return (SIMPLEREGION);
294 /***********************************************************************
295 * SetWindowRgn
297 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
301 FIXME("SetWindowRgn: stub\n");
302 return TRUE;
305 /***********************************************************************
306 * SetWindowRgn16
308 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
312 FIXME("SetWindowRgn16: stub\n");
313 return TRUE;
317 /***********************************************************************
318 * GetClientRect16 (USER.33)
320 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
322 WND * wndPtr = WIN_FindWndPtr( hwnd );
324 rect->left = rect->top = rect->right = rect->bottom = 0;
325 if (wndPtr)
327 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
328 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
330 WIN_ReleaseWndPtr(wndPtr);
334 /***********************************************************************
335 * GetClientRect (USER.220)
337 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
339 WND * wndPtr = WIN_FindWndPtr( hwnd );
341 rect->left = rect->top = rect->right = rect->bottom = 0;
342 if (!wndPtr) return FALSE;
343 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
344 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
346 WIN_ReleaseWndPtr(wndPtr);
347 return TRUE;
351 /*******************************************************************
352 * ClientToScreen16 (USER.28)
354 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
356 MapWindowPoints16( hwnd, 0, lppnt, 1 );
360 /*******************************************************************
361 * ClientToScreen (USER32.52)
363 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
365 MapWindowPoints( hwnd, 0, lppnt, 1 );
366 return TRUE;
370 /*******************************************************************
371 * ScreenToClient16 (USER.29)
373 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
375 MapWindowPoints16( 0, hwnd, lppnt, 1 );
379 /*******************************************************************
380 * ScreenToClient (USER32.447)
382 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
384 MapWindowPoints( 0, hwnd, lppnt, 1 );
385 return TRUE;
389 /***********************************************************************
390 * WINPOS_WindowFromPoint
392 * Find the window and hittest for a given point.
394 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
396 WND *wndPtr;
397 INT16 hittest = HTERROR;
398 INT16 retvalue;
399 POINT16 xy = pt;
401 *ppWnd = NULL;
402 wndPtr = WIN_LockWndPtr(wndScope->child);
404 if( wndScope->flags & WIN_MANAGED )
406 /* In managed mode we have to check wndScope first as it is also
407 * a window which received the mouse event. */
409 if( wndScope->dwStyle & WS_DISABLED )
411 retvalue = HTERROR;
412 goto end;
414 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
415 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
416 goto hittest;
418 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
420 for (;;)
422 while (wndPtr)
424 /* If point is in window, and window is visible, and it */
425 /* is enabled (or it's a top-level window), then explore */
426 /* its children. Otherwise, go to the next window. */
428 if ((wndPtr->dwStyle & WS_VISIBLE) &&
429 (!(wndPtr->dwStyle & WS_DISABLED) ||
430 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
431 (xy.x >= wndPtr->rectWindow.left) &&
432 (xy.x < wndPtr->rectWindow.right) &&
433 (xy.y >= wndPtr->rectWindow.top) &&
434 (xy.y < wndPtr->rectWindow.bottom))
436 *ppWnd = wndPtr; /* Got a suitable window */
438 /* If window is minimized or disabled, return at once */
439 if (wndPtr->dwStyle & WS_MINIMIZE)
441 retvalue = HTCAPTION;
442 goto end;
444 if (wndPtr->dwStyle & WS_DISABLED)
446 retvalue = HTERROR;
447 goto end;
450 /* If point is not in client area, ignore the children */
451 if ((xy.x < wndPtr->rectClient.left) ||
452 (xy.x >= wndPtr->rectClient.right) ||
453 (xy.y < wndPtr->rectClient.top) ||
454 (xy.y >= wndPtr->rectClient.bottom)) break;
456 xy.x -= wndPtr->rectClient.left;
457 xy.y -= wndPtr->rectClient.top;
458 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
460 else
462 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
466 hittest:
467 /* If nothing found, try the scope window */
468 if (!*ppWnd) *ppWnd = wndScope;
470 /* Send the WM_NCHITTEST message (only if to the same task) */
471 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
473 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
474 0, MAKELONG( pt.x, pt.y ) );
475 if (hittest != HTTRANSPARENT)
477 retvalue = hittest; /* Found the window */
478 goto end;
481 else
483 retvalue = HTCLIENT;
484 goto end;
487 /* If no children found in last search, make point relative to parent */
488 if (!wndPtr)
490 xy.x += (*ppWnd)->rectClient.left;
491 xy.y += (*ppWnd)->rectClient.top;
494 /* Restart the search from the next sibling */
495 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
496 *ppWnd = (*ppWnd)->parent;
499 end:
500 WIN_ReleaseWndPtr(wndPtr);
501 return retvalue;
505 /*******************************************************************
506 * WindowFromPoint16 (USER.30)
508 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
510 WND *pWnd;
511 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
512 WIN_ReleaseDesktop();
513 return pWnd->hwndSelf;
517 /*******************************************************************
518 * WindowFromPoint (USER32.582)
520 HWND WINAPI WindowFromPoint( POINT pt )
522 WND *pWnd;
523 POINT16 pt16;
524 CONV_POINT32TO16( &pt, &pt16 );
525 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
526 WIN_ReleaseDesktop();
527 return (HWND)pWnd->hwndSelf;
531 /*******************************************************************
532 * ChildWindowFromPoint16 (USER.191)
534 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
536 POINT pt32;
537 CONV_POINT16TO32( &pt, &pt32 );
538 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
542 /*******************************************************************
543 * ChildWindowFromPoint (USER32.49)
545 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
547 /* pt is in the client coordinates */
549 WND* wnd = WIN_FindWndPtr(hwndParent);
550 RECT rect;
551 HWND retvalue;
553 if( !wnd ) return 0;
555 /* get client rect fast */
556 rect.top = rect.left = 0;
557 rect.right = wnd->rectClient.right - wnd->rectClient.left;
558 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
560 if (!PtInRect( &rect, pt ))
562 retvalue = 0;
563 goto end;
565 WIN_UpdateWndPtr(&wnd,wnd->child);
566 while ( wnd )
568 if (PtInRect( &wnd->rectWindow, pt ))
570 retvalue = wnd->hwndSelf;
571 goto end;
573 WIN_UpdateWndPtr(&wnd,wnd->next);
575 retvalue = hwndParent;
576 end:
577 WIN_ReleaseWndPtr(wnd);
578 return retvalue;
581 /*******************************************************************
582 * ChildWindowFromPointEx16 (USER.50)
584 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
586 POINT pt32;
587 CONV_POINT16TO32( &pt, &pt32 );
588 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
592 /*******************************************************************
593 * ChildWindowFromPointEx32 (USER32.50)
595 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
596 UINT uFlags)
598 /* pt is in the client coordinates */
600 WND* wnd = WIN_FindWndPtr(hwndParent);
601 RECT rect;
602 HWND retvalue;
604 if( !wnd ) return 0;
606 /* get client rect fast */
607 rect.top = rect.left = 0;
608 rect.right = wnd->rectClient.right - wnd->rectClient.left;
609 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
611 if (!PtInRect( &rect, pt ))
613 retvalue = 0;
614 goto end;
616 WIN_UpdateWndPtr(&wnd,wnd->child);
618 while ( wnd )
620 if (PtInRect( &wnd->rectWindow, pt )) {
621 if ( (uFlags & CWP_SKIPINVISIBLE) &&
622 !(wnd->dwStyle & WS_VISIBLE) );
623 else if ( (uFlags & CWP_SKIPDISABLED) &&
624 (wnd->dwStyle & WS_DISABLED) );
625 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
626 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
627 else
629 retvalue = wnd->hwndSelf;
630 goto end;
634 WIN_UpdateWndPtr(&wnd,wnd->next);
636 retvalue = hwndParent;
637 end:
638 WIN_ReleaseWndPtr(wnd);
639 return retvalue;
643 /*******************************************************************
644 * WINPOS_GetWinOffset
646 * Calculate the offset between the origin of the two windows. Used
647 * to implement MapWindowPoints.
649 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
650 POINT *offset )
652 WND * wndPtr = 0;
654 offset->x = offset->y = 0;
655 if (hwndFrom == hwndTo ) return;
657 /* Translate source window origin to screen coords */
658 if (hwndFrom)
660 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
662 ERR("bad hwndFrom = %04x\n",hwndFrom);
663 return;
665 while (wndPtr->parent)
667 offset->x += wndPtr->rectClient.left;
668 offset->y += wndPtr->rectClient.top;
669 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
671 WIN_ReleaseWndPtr(wndPtr);
674 /* Translate origin to destination window coords */
675 if (hwndTo)
677 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
679 ERR("bad hwndTo = %04x\n", hwndTo );
680 return;
682 while (wndPtr->parent)
684 offset->x -= wndPtr->rectClient.left;
685 offset->y -= wndPtr->rectClient.top;
686 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
688 WIN_ReleaseWndPtr(wndPtr);
693 /*******************************************************************
694 * MapWindowPoints16 (USER.258)
696 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
697 LPPOINT16 lppt, UINT16 count )
699 POINT offset;
701 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
702 while (count--)
704 lppt->x += offset.x;
705 lppt->y += offset.y;
706 lppt++;
711 /*******************************************************************
712 * MapWindowPoints (USER32.386)
714 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
715 LPPOINT lppt, UINT count )
717 POINT offset;
719 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
720 while (count--)
722 lppt->x += offset.x;
723 lppt->y += offset.y;
724 lppt++;
726 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
730 /***********************************************************************
731 * IsIconic16 (USER.31)
733 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
735 return IsIconic(hWnd);
739 /***********************************************************************
740 * IsIconic (USER32.345)
742 BOOL WINAPI IsIconic(HWND hWnd)
744 BOOL retvalue;
745 WND * wndPtr = WIN_FindWndPtr(hWnd);
746 if (wndPtr == NULL) return FALSE;
747 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
748 WIN_ReleaseWndPtr(wndPtr);
749 return retvalue;
753 /***********************************************************************
754 * IsZoomed (USER.272)
756 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
758 return IsZoomed(hWnd);
762 /***********************************************************************
763 * IsZoomed (USER.352)
765 BOOL WINAPI IsZoomed(HWND hWnd)
767 BOOL retvalue;
768 WND * wndPtr = WIN_FindWndPtr(hWnd);
769 if (wndPtr == NULL) return FALSE;
770 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
771 WIN_ReleaseWndPtr(wndPtr);
772 return retvalue;
776 /*******************************************************************
777 * GetActiveWindow (USER.60)
779 HWND16 WINAPI GetActiveWindow16(void)
781 return (HWND16)GetActiveWindow();
784 /*******************************************************************
785 * GetActiveWindow (USER32.205)
787 HWND WINAPI GetActiveWindow(void)
789 MESSAGEQUEUE *pCurMsgQ = 0;
790 HWND hwndActive = 0;
792 /* Get the messageQ for the current thread */
793 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
795 WARN("\tCurrent message queue not found. Exiting!\n" );
796 return 0;
799 /* Return the current active window from the perQ data of the current message Q */
800 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
802 QUEUE_Unlock( pCurMsgQ );
803 return hwndActive;
807 /*******************************************************************
808 * WINPOS_CanActivate
810 static BOOL WINPOS_CanActivate(WND* pWnd)
812 if( pWnd && !(pWnd->dwStyle & (WS_DISABLED | WS_CHILD)) ) return TRUE;
813 return FALSE;
817 /*******************************************************************
818 * SetActiveWindow16 (USER.59)
820 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
822 return SetActiveWindow(hwnd);
826 /*******************************************************************
827 * SetActiveWindow (USER32.463)
829 HWND WINAPI SetActiveWindow( HWND hwnd )
831 HWND prev = 0;
832 WND *wndPtr = WIN_FindWndPtr( hwnd );
833 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
835 if ( !WINPOS_CanActivate(wndPtr) )
837 prev = 0;
838 goto end;
841 /* Get the messageQ for the current thread */
842 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
844 WARN("\tCurrent message queue not found. Exiting!\n" );
845 goto CLEANUP;
848 /* Retrieve the message queue associated with this window */
849 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
850 if ( !pMsgQ )
852 WARN("\tWindow message queue not found. Exiting!\n" );
853 goto CLEANUP;
856 /* Make sure that the window is associated with the calling threads
857 * message queue. It must share the same perQ data.
860 if ( pCurMsgQ->pQData != pMsgQ->pQData )
861 goto CLEANUP;
863 /* Save current active window */
864 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
866 WINPOS_SetActiveWindow( hwnd, 0, 0 );
868 CLEANUP:
869 /* Unlock the queues before returning */
870 if ( pMsgQ )
871 QUEUE_Unlock( pMsgQ );
872 if ( pCurMsgQ )
873 QUEUE_Unlock( pCurMsgQ );
875 end:
876 WIN_ReleaseWndPtr(wndPtr);
877 return prev;
881 /*******************************************************************
882 * GetForegroundWindow16 (USER.608)
884 HWND16 WINAPI GetForegroundWindow16(void)
886 return (HWND16)GetForegroundWindow();
890 /*******************************************************************
891 * SetForegroundWindow16 (USER.609)
893 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
895 return SetForegroundWindow( hwnd );
899 /*******************************************************************
900 * GetForegroundWindow (USER32.241)
902 HWND WINAPI GetForegroundWindow(void)
904 HWND hwndActive = 0;
906 /* Get the foreground window (active window of hActiveQueue) */
907 if ( hActiveQueue )
909 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
910 if ( pActiveQueue )
911 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
913 QUEUE_Unlock( pActiveQueue );
916 return hwndActive;
919 /*******************************************************************
920 * SetForegroundWindow (USER32.482)
922 BOOL WINAPI SetForegroundWindow( HWND hwnd )
924 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
928 /*******************************************************************
929 * GetShellWindow16 (USER.600)
931 HWND16 WINAPI GetShellWindow16(void)
933 return GetShellWindow();
936 /*******************************************************************
937 * SetShellWindow (USER32.504)
939 HWND WINAPI SetShellWindow(HWND hwndshell)
940 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
942 hGlobalShellWindow = hwndshell;
943 return hGlobalShellWindow;
947 /*******************************************************************
948 * GetShellWindow (USER32.287)
950 HWND WINAPI GetShellWindow(void)
951 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
953 return hGlobalShellWindow;
957 /***********************************************************************
958 * BringWindowToTop16 (USER.45)
960 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
962 return BringWindowToTop(hwnd);
966 /***********************************************************************
967 * BringWindowToTop (USER32.11)
969 BOOL WINAPI BringWindowToTop( HWND hwnd )
971 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
975 /***********************************************************************
976 * MoveWindow16 (USER.56)
978 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
979 BOOL16 repaint )
981 return MoveWindow(hwnd,x,y,cx,cy,repaint);
985 /***********************************************************************
986 * MoveWindow (USER32.399)
988 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
989 BOOL repaint )
991 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
992 if (!repaint) flags |= SWP_NOREDRAW;
993 TRACE("%04x %d,%d %dx%d %d\n",
994 hwnd, x, y, cx, cy, repaint );
995 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
998 /***********************************************************************
999 * WINPOS_InitInternalPos
1001 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1002 LPRECT restoreRect )
1004 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1005 atomInternalPos );
1006 if( !lpPos )
1008 /* this happens when the window is minimized/maximized
1009 * for the first time (rectWindow is not adjusted yet) */
1011 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1012 if( !lpPos ) return NULL;
1014 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1015 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1016 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1017 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1020 if( wnd->dwStyle & WS_MINIMIZE )
1021 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1022 else if( wnd->dwStyle & WS_MAXIMIZE )
1023 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1024 else if( restoreRect )
1025 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1027 return lpPos;
1030 /***********************************************************************
1031 * WINPOS_RedrawIconTitle
1033 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1035 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1036 if( lpPos )
1038 if( lpPos->hwndIconTitle )
1040 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1041 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1042 return TRUE;
1045 return FALSE;
1048 /***********************************************************************
1049 * WINPOS_ShowIconTitle
1051 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1053 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1055 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1057 HWND16 hWnd = lpPos->hwndIconTitle;
1059 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1061 if( !hWnd )
1062 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1063 if( bShow )
1065 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1067 if( !(pWnd->dwStyle & WS_VISIBLE) )
1069 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1070 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1071 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1073 WIN_ReleaseWndPtr(pWnd);
1076 else ShowWindow( hWnd, SW_HIDE );
1078 return FALSE;
1081 /*******************************************************************
1082 * WINPOS_GetMinMaxInfo
1084 * Get the minimized and maximized information for a window.
1086 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1087 POINT *minTrack, POINT *maxTrack )
1089 LPINTERNALPOS lpPos;
1090 MINMAXINFO MinMax;
1091 INT xinc, yinc;
1093 /* Compute default values */
1095 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1096 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1097 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1098 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1099 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1100 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1102 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1103 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1105 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1106 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1108 else
1110 xinc = yinc = 0;
1111 if (HAS_THICKFRAME(wndPtr->dwStyle))
1113 xinc += GetSystemMetrics(SM_CXFRAME);
1114 yinc += GetSystemMetrics(SM_CYFRAME);
1116 if (wndPtr->dwStyle & WS_BORDER)
1118 xinc += GetSystemMetrics(SM_CXBORDER);
1119 yinc += GetSystemMetrics(SM_CYBORDER);
1122 MinMax.ptMaxSize.x += 2 * xinc;
1123 MinMax.ptMaxSize.y += 2 * yinc;
1125 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1126 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1127 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1128 else
1130 MinMax.ptMaxPosition.x = -xinc;
1131 MinMax.ptMaxPosition.y = -yinc;
1134 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1136 /* Some sanity checks */
1138 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1139 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1140 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1141 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1142 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1143 MinMax.ptMaxTrackSize.x = MAX( MinMax.ptMaxTrackSize.x,
1144 MinMax.ptMinTrackSize.x );
1145 MinMax.ptMaxTrackSize.y = MAX( MinMax.ptMaxTrackSize.y,
1146 MinMax.ptMinTrackSize.y );
1148 if (maxSize) *maxSize = MinMax.ptMaxSize;
1149 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1150 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1151 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1154 /***********************************************************************
1155 * WINPOS_MinMaximize
1157 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1158 * This function assumes that 'cmd' is different from the current window
1159 * state.
1161 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1163 UINT swpFlags = 0;
1164 POINT pt, size;
1165 LPINTERNALPOS lpPos;
1167 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1169 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1170 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1172 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1174 if( wndPtr->dwStyle & WS_MINIMIZE )
1176 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1177 return (SWP_NOSIZE | SWP_NOMOVE);
1178 swpFlags |= SWP_NOCOPYBITS;
1180 switch( cmd )
1182 case SW_MINIMIZE:
1183 if( wndPtr->dwStyle & WS_MAXIMIZE)
1185 wndPtr->flags |= WIN_RESTORE_MAX;
1186 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1188 else
1189 wndPtr->flags &= ~WIN_RESTORE_MAX;
1190 wndPtr->dwStyle |= WS_MINIMIZE;
1192 if( wndPtr->flags & WIN_NATIVE )
1193 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1194 swpFlags |= MINMAX_NOSWP;
1196 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1198 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1199 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1200 swpFlags |= SWP_NOCOPYBITS;
1201 break;
1203 case SW_MAXIMIZE:
1204 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1205 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1206 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1208 if( wndPtr->dwStyle & WS_MINIMIZE )
1210 if( wndPtr->flags & WIN_NATIVE )
1211 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1212 swpFlags |= MINMAX_NOSWP;
1214 WINPOS_ShowIconTitle( wndPtr, FALSE );
1215 wndPtr->dwStyle &= ~WS_MINIMIZE;
1217 wndPtr->dwStyle |= WS_MAXIMIZE;
1219 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1220 size.x, size.y );
1221 break;
1223 case SW_RESTORE:
1224 if( wndPtr->dwStyle & WS_MINIMIZE )
1226 if( wndPtr->flags & WIN_NATIVE )
1227 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1228 swpFlags |= MINMAX_NOSWP;
1230 wndPtr->dwStyle &= ~WS_MINIMIZE;
1231 WINPOS_ShowIconTitle( wndPtr, FALSE );
1233 if( wndPtr->flags & WIN_RESTORE_MAX)
1235 /* Restore to maximized position */
1236 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1237 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1238 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1239 wndPtr->dwStyle |= WS_MAXIMIZE;
1240 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1241 break;
1244 else
1245 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1246 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1248 /* Restore to normal position */
1250 *lpRect = lpPos->rectNormal;
1251 lpRect->right -= lpRect->left;
1252 lpRect->bottom -= lpRect->top;
1254 break;
1256 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1257 return swpFlags;
1260 /***********************************************************************
1261 * ShowWindowAsync (USER32.535)
1263 * doesn't wait; returns immediately.
1264 * used by threads to toggle windows in other (possibly hanging) threads
1266 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1268 /* FIXME: does ShowWindow() return immediately ? */
1269 return ShowWindow(hwnd, cmd);
1273 /***********************************************************************
1274 * ShowWindow16 (USER.42)
1276 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1278 return ShowWindow(hwnd,cmd);
1282 /***********************************************************************
1283 * ShowWindow (USER32.534)
1285 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1287 WND* wndPtr = WIN_FindWndPtr( hwnd );
1288 BOOL wasVisible, showFlag;
1289 RECT16 newPos = {0, 0, 0, 0};
1290 UINT swp = 0;
1292 if (!wndPtr) return FALSE;
1294 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1296 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1298 switch(cmd)
1300 case SW_HIDE:
1301 if (!wasVisible) goto END;;
1302 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1303 SWP_NOACTIVATE | SWP_NOZORDER;
1304 break;
1306 case SW_SHOWMINNOACTIVE:
1307 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1308 /* fall through */
1309 case SW_SHOWMINIMIZED:
1310 swp |= SWP_SHOWWINDOW;
1311 /* fall through */
1312 case SW_MINIMIZE:
1313 swp |= SWP_FRAMECHANGED;
1314 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1315 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1316 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1317 break;
1319 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1320 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1321 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1322 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1323 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1324 break;
1326 case SW_SHOWNA:
1327 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1328 /* fall through */
1329 case SW_SHOW:
1330 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1333 * ShowWindow has a little peculiar behavior that if the
1334 * window is already the topmost window, it will not
1335 * activate it.
1337 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1338 swp |= SWP_NOACTIVATE;
1340 break;
1342 case SW_SHOWNOACTIVATE:
1343 swp |= SWP_NOZORDER;
1344 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1345 /* fall through */
1346 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1347 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1348 case SW_RESTORE:
1349 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1351 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1352 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1353 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1354 break;
1357 showFlag = (cmd != SW_HIDE);
1358 if (showFlag != wasVisible)
1360 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1361 if (!IsWindow( hwnd )) goto END;
1364 if ((wndPtr->dwStyle & WS_CHILD) &&
1365 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1366 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1368 /* Don't call SetWindowPos() on invisible child windows */
1369 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1370 else wndPtr->dwStyle |= WS_VISIBLE;
1372 else
1374 /* We can't activate a child window */
1375 if ((wndPtr->dwStyle & WS_CHILD) &&
1376 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1377 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1378 if (!(swp & MINMAX_NOSWP))
1380 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1381 newPos.right, newPos.bottom, LOWORD(swp) );
1382 if (cmd == SW_HIDE)
1384 /* FIXME: This will cause the window to be activated irrespective
1385 * of whether it is owned by the same thread. Has to be done
1386 * asynchronously.
1389 if (hwnd == GetActiveWindow())
1390 WINPOS_ActivateOtherWindow(wndPtr);
1392 /* Revert focus to parent */
1393 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1394 SetFocus( GetParent(hwnd) );
1397 if (!IsWindow( hwnd )) goto END;
1398 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1401 if (wndPtr->flags & WIN_NEED_SIZE)
1403 /* should happen only in CreateWindowEx() */
1404 int wParam = SIZE_RESTORED;
1406 wndPtr->flags &= ~WIN_NEED_SIZE;
1407 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1408 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1409 SendMessageA( hwnd, WM_SIZE, wParam,
1410 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1411 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1412 SendMessageA( hwnd, WM_MOVE, 0,
1413 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1416 END:
1417 WIN_ReleaseWndPtr(wndPtr);
1418 return wasVisible;
1422 /***********************************************************************
1423 * GetInternalWindowPos16 (USER.460)
1425 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1426 LPPOINT16 ptIcon )
1428 WINDOWPLACEMENT16 wndpl;
1429 if (GetWindowPlacement16( hwnd, &wndpl ))
1431 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1432 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1433 return wndpl.showCmd;
1435 return 0;
1439 /***********************************************************************
1440 * GetInternalWindowPos (USER32.245)
1442 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1443 LPPOINT ptIcon )
1445 WINDOWPLACEMENT wndpl;
1446 if (GetWindowPlacement( hwnd, &wndpl ))
1448 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1449 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1450 return wndpl.showCmd;
1452 return 0;
1455 /***********************************************************************
1456 * GetWindowPlacement16 (USER.370)
1458 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1460 WND *pWnd = WIN_FindWndPtr( hwnd );
1461 LPINTERNALPOS lpPos;
1463 if(!pWnd ) return FALSE;
1465 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1466 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1467 wndpl->length = sizeof(*wndpl);
1468 if( pWnd->dwStyle & WS_MINIMIZE )
1469 wndpl->showCmd = SW_SHOWMINIMIZED;
1470 else
1471 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1472 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1473 if( pWnd->flags & WIN_RESTORE_MAX )
1474 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1475 else
1476 wndpl->flags = 0;
1477 wndpl->ptMinPosition = lpPos->ptIconPos;
1478 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1479 wndpl->rcNormalPosition = lpPos->rectNormal;
1481 WIN_ReleaseWndPtr(pWnd);
1482 return TRUE;
1486 /***********************************************************************
1487 * GetWindowPlacement (USER32.307)
1489 * Win95:
1490 * Fails if wndpl->length of Win95 (!) apps is invalid.
1492 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1494 if( pwpl32 )
1496 WINDOWPLACEMENT16 wpl;
1497 wpl.length = sizeof(wpl);
1498 if( GetWindowPlacement16( hwnd, &wpl ) )
1500 pwpl32->length = sizeof(*pwpl32);
1501 pwpl32->flags = wpl.flags;
1502 pwpl32->showCmd = wpl.showCmd;
1503 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1504 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1505 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1506 return TRUE;
1509 return FALSE;
1513 /***********************************************************************
1514 * WINPOS_SetPlacement
1516 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1517 UINT flags )
1519 WND *pWnd = WIN_FindWndPtr( hwnd );
1520 if( pWnd )
1522 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1523 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1525 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1526 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1527 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1529 if( pWnd->dwStyle & WS_MINIMIZE )
1531 WINPOS_ShowIconTitle( pWnd, FALSE );
1532 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1533 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1534 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1536 else if( pWnd->dwStyle & WS_MAXIMIZE )
1538 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1539 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1540 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1542 else if( flags & PLACE_RECT )
1543 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1544 lpPos->rectNormal.right - lpPos->rectNormal.left,
1545 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1546 SWP_NOZORDER | SWP_NOACTIVATE );
1548 ShowWindow( hwnd, wndpl->showCmd );
1549 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1551 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1553 /* SDK: ...valid only the next time... */
1554 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1556 WIN_ReleaseWndPtr(pWnd);
1557 return TRUE;
1559 return FALSE;
1563 /***********************************************************************
1564 * SetWindowPlacement16 (USER.371)
1566 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1568 return WINPOS_SetPlacement( hwnd, wndpl,
1569 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1572 /***********************************************************************
1573 * SetWindowPlacement (USER32.519)
1575 * Win95:
1576 * Fails if wndpl->length of Win95 (!) apps is invalid.
1578 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1580 if( pwpl32 )
1582 WINDOWPLACEMENT16 wpl;
1584 wpl.length = sizeof(WINDOWPLACEMENT16);
1585 wpl.flags = pwpl32->flags;
1586 wpl.showCmd = pwpl32->showCmd;
1587 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1588 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1589 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1590 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1591 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1592 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1593 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1594 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1596 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1598 return FALSE;
1602 /***********************************************************************
1603 * SetInternalWindowPos16 (USER.461)
1605 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1606 LPRECT16 rect, LPPOINT16 pt )
1608 if( IsWindow16(hwnd) )
1610 WINDOWPLACEMENT16 wndpl;
1611 UINT flags;
1613 wndpl.length = sizeof(wndpl);
1614 wndpl.showCmd = showCmd;
1615 wndpl.flags = flags = 0;
1617 if( pt )
1619 flags |= PLACE_MIN;
1620 wndpl.flags |= WPF_SETMINPOSITION;
1621 wndpl.ptMinPosition = *pt;
1623 if( rect )
1625 flags |= PLACE_RECT;
1626 wndpl.rcNormalPosition = *rect;
1628 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1633 /***********************************************************************
1634 * SetInternalWindowPos (USER32.483)
1636 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1637 LPRECT rect, LPPOINT pt )
1639 if( IsWindow(hwnd) )
1641 WINDOWPLACEMENT16 wndpl;
1642 UINT flags;
1644 wndpl.length = sizeof(wndpl);
1645 wndpl.showCmd = showCmd;
1646 wndpl.flags = flags = 0;
1648 if( pt )
1650 flags |= PLACE_MIN;
1651 wndpl.flags |= WPF_SETMINPOSITION;
1652 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1654 if( rect )
1656 flags |= PLACE_RECT;
1657 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1659 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1663 /*******************************************************************
1664 * WINPOS_SetActiveWindow
1666 * SetActiveWindow() back-end. This is the only function that
1667 * can assign active status to a window. It must be called only
1668 * for the top level windows.
1670 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1672 CBTACTIVATESTRUCT16* cbtStruct;
1673 WND* wndPtr=0, *wndTemp;
1674 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1675 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1676 WORD wIconized = 0;
1677 HWND hwndActive = 0;
1678 BOOL bRet = 0;
1680 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1682 /* Get current active window from the active queue */
1683 if ( hActiveQueue )
1685 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1686 if ( pOldActiveQueue )
1687 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1690 /* paranoid checks */
1691 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1692 goto CLEANUP_END;
1694 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1695 * return 0;
1697 wndPtr = WIN_FindWndPtr(hWnd);
1698 hOldActiveQueue = hActiveQueue;
1700 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1702 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1703 WIN_ReleaseWndPtr(wndTemp);
1705 else
1706 TRACE("no current active window.\n");
1708 /* call CBT hook chain */
1709 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1711 cbtStruct->fMouse = fMouse;
1712 cbtStruct->hWndActive = hwndActive;
1713 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1714 (LPARAM)SEGPTR_GET(cbtStruct) );
1715 SEGPTR_FREE(cbtStruct);
1716 if (bRet) goto CLEANUP_END;
1719 /* set prev active wnd to current active wnd and send notification */
1720 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1722 MESSAGEQUEUE *pTempActiveQueue = 0;
1724 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1726 if (GetSysModalWindow16() != hWnd)
1727 goto CLEANUP_END;
1728 /* disregard refusal if hWnd is sysmodal */
1731 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1732 MAKEWPARAM( WA_INACTIVE, wIconized ),
1733 (LPARAM)hWnd );
1735 /* check if something happened during message processing
1736 * (global active queue may have changed)
1738 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1739 if(!pTempActiveQueue)
1740 goto CLEANUP_END;
1742 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1743 QUEUE_Unlock( pTempActiveQueue );
1744 if( hwndPrevActive != hwndActive )
1745 goto CLEANUP_END;
1748 /* Set new active window in the message queue */
1749 hwndActive = hWnd;
1750 if ( wndPtr )
1752 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1753 if ( pNewActiveQueue )
1754 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1756 else /* have to do this or MDI frame activation goes to hell */
1757 if( pOldActiveQueue )
1758 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1760 /* send palette messages */
1761 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1762 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1764 /* if prev wnd is minimized redraw icon title */
1765 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1767 /* managed windows will get ConfigureNotify event */
1768 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1770 /* check Z-order and bring hWnd to the top */
1771 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1773 if (wndTemp->dwStyle & WS_VISIBLE) break;
1775 WIN_ReleaseDesktop();
1776 WIN_ReleaseWndPtr(wndTemp);
1778 if( wndTemp != wndPtr )
1779 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1780 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1781 if (!IsWindow(hWnd))
1782 goto CLEANUP;
1785 /* Get a handle to the new active queue */
1786 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1788 /* send WM_ACTIVATEAPP if necessary */
1789 if (hOldActiveQueue != hNewActiveQueue)
1791 WND **list, **ppWnd;
1792 WND *pDesktop = WIN_GetDesktop();
1794 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1796 for (ppWnd = list; *ppWnd; ppWnd++)
1798 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1800 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1801 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1802 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1804 WIN_ReleaseWinArray(list);
1807 hActiveQueue = hNewActiveQueue;
1809 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1811 for (ppWnd = list; *ppWnd; ppWnd++)
1813 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1815 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1816 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1817 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1819 WIN_ReleaseWinArray(list);
1821 WIN_ReleaseDesktop();
1823 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1826 if (hWnd)
1828 /* walk up to the first unowned window */
1829 wndTemp = WIN_LockWndPtr(wndPtr);
1830 while (wndTemp->owner)
1832 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1834 /* and set last active owned popup */
1835 wndTemp->hwndLastActive = hWnd;
1837 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1838 WIN_ReleaseWndPtr(wndTemp);
1839 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1840 SendMessageA( hWnd, WM_ACTIVATE,
1841 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1842 (LPARAM)hwndPrevActive );
1843 if( !IsWindow(hWnd) ) goto CLEANUP;
1846 /* change focus if possible */
1847 if ( fChangeFocus )
1849 if ( pNewActiveQueue )
1851 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1853 if ( WIN_GetTopParent( hOldFocus ) != hwndActive )
1854 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1855 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1856 0 : hwndActive );
1859 if ( pOldActiveQueue &&
1860 ( !pNewActiveQueue ||
1861 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1863 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1864 if ( hOldFocus )
1865 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1869 if( !hwndPrevActive && wndPtr )
1870 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1872 /* if active wnd is minimized redraw icon title */
1873 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1875 bRet = (hWnd == hwndActive); /* Success? */
1877 CLEANUP: /* Unlock the message queues before returning */
1879 if ( pNewActiveQueue )
1880 QUEUE_Unlock( pNewActiveQueue );
1882 CLEANUP_END:
1884 if ( pOldActiveQueue )
1885 QUEUE_Unlock( pOldActiveQueue );
1887 WIN_ReleaseWndPtr(wndPtr);
1888 return bRet;
1891 /*******************************************************************
1892 * WINPOS_ActivateOtherWindow
1894 * Activates window other than pWnd.
1896 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1898 BOOL bRet = 0;
1899 WND* pWndTo = NULL;
1900 HWND hwndActive = 0;
1902 /* Get current active window from the active queue */
1903 if ( hActiveQueue )
1905 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1906 if ( pActiveQueue )
1908 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1909 QUEUE_Unlock( pActiveQueue );
1913 if( pWnd->hwndSelf == hwndPrevActive )
1914 hwndPrevActive = 0;
1916 if( hwndActive != pWnd->hwndSelf &&
1917 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1918 return 0;
1920 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1921 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1923 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1925 WIN_ReleaseWndPtr(pWndTo);
1926 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1928 while( !WINPOS_CanActivate(pWndTo) )
1930 /* by now owned windows should've been taken care of */
1931 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1932 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1933 if( !pWndTo ) break;
1935 WIN_ReleaseWndPtr(pWndPtr);
1938 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1940 /* switch desktop queue to current active */
1941 if( pWndTo )
1943 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1944 WIN_ReleaseWndPtr(pWndTo);
1945 WIN_ReleaseDesktop();
1948 hwndPrevActive = 0;
1949 return bRet;
1952 /*******************************************************************
1953 * WINPOS_ChangeActiveWindow
1956 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1958 WND *wndPtr, *wndTemp;
1959 BOOL retvalue;
1960 HWND hwndActive = 0;
1962 /* Get current active window from the active queue */
1963 if ( hActiveQueue )
1965 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1966 if ( pActiveQueue )
1968 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1969 QUEUE_Unlock( pActiveQueue );
1973 if (!hWnd)
1974 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1976 wndPtr = WIN_FindWndPtr(hWnd);
1977 if( !wndPtr ) return FALSE;
1979 /* child windows get WM_CHILDACTIVATE message */
1980 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1982 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1983 goto end;
1986 if( hWnd == hwndActive )
1988 retvalue = FALSE;
1989 goto end;
1992 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1994 retvalue = FALSE;
1995 goto end;
1998 /* switch desktop queue to current active */
1999 wndTemp = WIN_GetDesktop();
2000 if( wndPtr->parent == wndTemp)
2001 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2002 WIN_ReleaseDesktop();
2004 retvalue = TRUE;
2005 end:
2006 WIN_ReleaseWndPtr(wndPtr);
2007 return retvalue;
2011 /***********************************************************************
2012 * WINPOS_SendNCCalcSize
2014 * Send a WM_NCCALCSIZE message to a window.
2015 * All parameters are read-only except newClientRect.
2016 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2017 * when calcValidRect is TRUE.
2019 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2020 RECT *newWindowRect, RECT *oldWindowRect,
2021 RECT *oldClientRect, WINDOWPOS *winpos,
2022 RECT *newClientRect )
2024 NCCALCSIZE_PARAMS params;
2025 WINDOWPOS winposCopy;
2026 LONG result;
2028 params.rgrc[0] = *newWindowRect;
2029 if (calcValidRect)
2031 winposCopy = *winpos;
2032 params.rgrc[1] = *oldWindowRect;
2033 params.rgrc[2] = *oldClientRect;
2034 params.lppos = &winposCopy;
2036 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2037 (LPARAM)&params );
2038 TRACE("%d,%d-%d,%d\n",
2039 params.rgrc[0].left, params.rgrc[0].top,
2040 params.rgrc[0].right, params.rgrc[0].bottom );
2042 /* If the application send back garbage, ignore it */
2043 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2044 *newClientRect = params.rgrc[0];
2046 return result;
2050 /***********************************************************************
2051 * WINPOS_HandleWindowPosChanging16
2053 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2055 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2057 POINT maxSize, minTrack;
2058 if (winpos->flags & SWP_NOSIZE) return 0;
2059 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2060 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2062 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2063 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2064 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2065 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2067 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2068 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2071 return 0;
2075 /***********************************************************************
2076 * WINPOS_HandleWindowPosChanging
2078 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2080 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2082 POINT maxSize;
2083 if (winpos->flags & SWP_NOSIZE) return 0;
2084 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2085 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2087 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2088 winpos->cx = MIN( winpos->cx, maxSize.x );
2089 winpos->cy = MIN( winpos->cy, maxSize.y );
2091 return 0;
2094 /***********************************************************************
2095 * SWP_DoOwnedPopups
2097 * fix Z order taking into account owned popups -
2098 * basically we need to maintain them above the window that owns them
2100 * FIXME: hide/show owned popups when owner visibility changes.
2102 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2104 WND* w = WIN_LockWndPtr(pDesktop->child);
2106 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2108 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2110 /* make sure this popup stays above the owner */
2112 HWND hwndLocalPrev = HWND_TOP;
2114 if( hwndInsertAfter != HWND_TOP )
2116 while( w != wndPtr->owner )
2118 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2119 if( hwndLocalPrev == hwndInsertAfter ) break;
2120 WIN_UpdateWndPtr(&w,w->next);
2122 hwndInsertAfter = hwndLocalPrev;
2125 else if( wndPtr->dwStyle & WS_CHILD )
2126 goto END;
2128 WIN_UpdateWndPtr(&w, pDesktop->child);
2130 while( w )
2132 if( w == wndPtr ) break;
2134 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2136 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2137 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2138 hwndInsertAfter = w->hwndSelf;
2140 WIN_UpdateWndPtr(&w, w->next);
2143 END:
2144 WIN_ReleaseWndPtr(w);
2145 return hwndInsertAfter;
2148 /***********************************************************************
2149 * SWP_CopyValidBits
2151 * Make window look nice without excessive repainting
2153 * visible and update regions are in window coordinates
2154 * client and window rectangles are in parent client coordinates
2156 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2157 * window rects have the same origin.
2159 * Returns: uFlags and a dirty region in *pVisRgn.
2161 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2162 LPRECT lpOldWndRect,
2163 LPRECT lpOldClientRect, UINT uFlags )
2165 RECT r;
2166 HRGN newVisRgn, dirtyRgn;
2167 INT my = COMPLEXREGION;
2169 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2170 Wnd->rectWindow.left, Wnd->rectWindow.top,
2171 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2172 lpOldWndRect->left, lpOldWndRect->top,
2173 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2174 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2175 Wnd->rectClient.left, Wnd->rectClient.top,
2176 Wnd->rectClient.right, Wnd->rectClient.bottom,
2177 lpOldClientRect->left, lpOldClientRect->top,
2178 lpOldClientRect->right,lpOldClientRect->bottom );
2180 if( Wnd->hrgnUpdate == 1 )
2181 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2183 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2184 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2186 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2187 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2189 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2191 nocopy:
2193 TRACE("\twon't copy anything!\n");
2195 /* set dirtyRgn to the sum of old and new visible regions
2196 * in parent client coordinates */
2198 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2199 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2201 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2203 else /* copy valid bits to a new location */
2205 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2206 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2208 /* subtract already invalid region inside Wnd from the dst region */
2210 if( Wnd->hrgnUpdate )
2211 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2212 goto nocopy;
2214 /* check if entire window can be copied */
2216 ow = lpOldWndRect->right - lpOldWndRect->left;
2217 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2218 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2219 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2221 ocw = lpOldClientRect->right - lpOldClientRect->left;
2222 och = lpOldClientRect->bottom - lpOldClientRect->top;
2223 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2224 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2226 if( (ocw != ncw) || (och != nch) ||
2227 ( ow != nw) || ( oh != nh) ||
2228 ((lpOldClientRect->top - lpOldWndRect->top) !=
2229 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2230 ((lpOldClientRect->left - lpOldWndRect->left) !=
2231 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2233 dx = Wnd->rectClient.left - lpOldClientRect->left;
2234 dy = Wnd->rectClient.top - lpOldClientRect->top;
2236 /* restrict valid bits to the common client rect */
2238 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2239 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2240 r.right = r.left + MIN( ocw, ncw );
2241 r.bottom = r.top + MIN( och, nch );
2243 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2244 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2245 GetRgnBox( hrgnValid, &r );
2246 if( IsRectEmpty( &r ) )
2247 goto nocopy;
2248 r = *lpOldClientRect;
2250 else
2252 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2253 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2254 if( !(uFlags & SWP_EX_PAINTSELF) )
2255 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2256 r = *lpOldWndRect;
2259 if( !(uFlags & SWP_EX_PAINTSELF) )
2261 /* Move remaining regions to parent coordinates */
2262 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2263 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2265 else
2266 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2268 TRACE("\tcomputing dirty region!\n");
2270 /* Compute combined dirty region (old + new - valid) */
2271 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2272 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2274 /* Blt valid bits, r is the rect to copy */
2276 if( dx || dy )
2278 RECT rClip;
2279 HDC hDC;
2280 DC* dc;
2282 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2283 from copying clipped areas */
2285 if( uFlags & SWP_EX_PAINTSELF )
2287 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2288 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2289 rClip.right = nw; rClip.bottom = nh;
2291 else
2293 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2294 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2295 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2296 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2298 rClip.left = rClip.top = 0;
2300 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2302 if( oh > nh ) r.bottom = r.top + nh;
2303 if( ow < nw ) r.right = r.left + nw;
2305 if( IntersectRect( &r, &r, &rClip ) )
2307 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2309 /* When you copy the bits without repainting, parent doesn't
2310 get validated appropriately. Therefore, we have to validate
2311 the parent with the windows' updated region when the
2312 parent's update region is not empty. */
2314 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2316 OffsetRect(&r, dx, dy);
2317 ValidateRect(Wnd->parent->hwndSelf, &r);
2321 GDI_HEAP_UNLOCK( hDC );
2323 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2324 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2328 /* *pVisRgn now points to the invalidated region */
2330 DeleteObject(newVisRgn);
2331 DeleteObject(dirtyRgn);
2332 return uFlags;
2335 /***********************************************************************
2336 * SWP_DoSimpleFrameChanged
2338 * NOTE: old and new client rect origins are identical, only
2339 * extents may have changed. Window extents are the same.
2341 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2343 INT i = 0;
2344 RECT rect;
2345 HRGN hrgn = 0;
2347 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2349 /* Client rect changed its position/size, most likely a scrollar
2350 * was added/removed.
2352 * FIXME: WVR alignment flags
2355 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2357 i++;
2358 rect.top = 0;
2359 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2360 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2361 if(!(uFlags & SWP_EX_NOCOPY))
2362 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2363 else
2365 rect.left = 0;
2366 goto redraw;
2370 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2372 if( i )
2373 hrgn = CreateRectRgnIndirect( &rect );
2374 rect.left = 0;
2375 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2376 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2377 if(!(uFlags & SWP_EX_NOCOPY))
2378 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2379 else
2380 rect.top = 0;
2381 if( i++ )
2382 REGION_UnionRectWithRgn( hrgn, &rect );
2385 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2387 rect = wndPtr->rectWindow;
2388 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2389 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2390 i++;
2394 if( i )
2396 redraw:
2397 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2398 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2400 else
2402 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2405 if( hrgn > 1 )
2406 DeleteObject( hrgn );
2409 /***********************************************************************
2410 * SWP_DoWinPosChanging
2412 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2413 RECT* pNewWindowRect, RECT* pNewClientRect )
2415 /* Send WM_WINDOWPOSCHANGING message */
2417 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2418 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2420 /* Calculate new position and size */
2422 *pNewWindowRect = wndPtr->rectWindow;
2423 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2424 : wndPtr->rectClient;
2426 if (!(pWinpos->flags & SWP_NOSIZE))
2428 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2429 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2431 if (!(pWinpos->flags & SWP_NOMOVE))
2433 pNewWindowRect->left = pWinpos->x;
2434 pNewWindowRect->top = pWinpos->y;
2435 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2436 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2438 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2439 pWinpos->y - wndPtr->rectWindow.top );
2442 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2443 return TRUE;
2446 /***********************************************************************
2447 * SWP_DoNCCalcSize
2449 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2450 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2452 UINT wvrFlags = 0;
2454 /* Send WM_NCCALCSIZE message to get new client area */
2455 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2457 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2458 &wndPtr->rectWindow, &wndPtr->rectClient,
2459 pWinpos, pNewClientRect );
2461 /* FIXME: WVR_ALIGNxxx */
2463 if( pNewClientRect->left != wndPtr->rectClient.left ||
2464 pNewClientRect->top != wndPtr->rectClient.top )
2465 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2467 if( (pNewClientRect->right - pNewClientRect->left !=
2468 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2469 (pNewClientRect->bottom - pNewClientRect->top !=
2470 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2471 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2473 else
2474 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2475 pNewClientRect->top != wndPtr->rectClient.top) )
2476 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2477 return wvrFlags;
2480 /***********************************************************************
2481 * SetWindowPos (USER.2)
2483 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2484 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2486 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2489 /***********************************************************************
2490 * SetWindowPos (USER32.520)
2492 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2493 INT x, INT y, INT cx, INT cy, UINT flags )
2495 WINDOWPOS winpos;
2496 WND * wndPtr,*wndTemp;
2497 RECT newWindowRect, newClientRect;
2498 RECT oldWindowRect, oldClientRect;
2499 HRGN visRgn = 0;
2500 UINT wvrFlags = 0, uFlags = 0;
2501 BOOL retvalue, resync = FALSE, bChangePos;
2502 HWND hwndActive = 0;
2504 /* Get current active window from the active queue */
2505 if ( hActiveQueue )
2507 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2508 if ( pActiveQueue )
2510 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2511 QUEUE_Unlock( pActiveQueue );
2515 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2516 hwnd, x, y, x+cx, y+cy, flags);
2518 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2519 flags &= ~SWP_WINE_NOHOSTMOVE;
2522 /* ------------------------------------------------------------------------ CHECKS */
2524 /* Check window handle */
2526 if (hwnd == GetDesktopWindow()) return FALSE;
2527 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2529 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2530 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2532 /* Fix redundant flags */
2534 if(wndPtr->dwStyle & WS_VISIBLE)
2535 flags &= ~SWP_SHOWWINDOW;
2536 else
2538 if (!(flags & SWP_SHOWWINDOW))
2539 flags |= SWP_NOREDRAW;
2540 flags &= ~SWP_HIDEWINDOW;
2543 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2545 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2546 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2547 flags |= SWP_NOSIZE; /* Already the right size */
2549 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2550 flags |= SWP_NOMOVE; /* Already the right position */
2552 if (hwnd == hwndActive)
2553 flags |= SWP_NOACTIVATE; /* Already active */
2554 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2556 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2558 flags &= ~SWP_NOZORDER;
2559 hwndInsertAfter = HWND_TOP;
2560 goto Pos;
2564 /* Check hwndInsertAfter */
2566 /* FIXME: TOPMOST not supported yet */
2567 if ((hwndInsertAfter == HWND_TOPMOST) ||
2568 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2570 /* hwndInsertAfter must be a sibling of the window */
2571 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2573 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2575 if( wnd ) {
2576 if( wnd->parent != wndPtr->parent )
2578 retvalue = FALSE;
2579 WIN_ReleaseWndPtr(wnd);
2580 goto END;
2582 if( wnd->next == wndPtr ) flags |= SWP_NOZORDER;
2584 WIN_ReleaseWndPtr(wnd);
2587 Pos: /* ------------------------------------------------------------------------ MAIN part */
2589 /* Fill the WINDOWPOS structure */
2591 winpos.hwnd = hwnd;
2592 winpos.hwndInsertAfter = hwndInsertAfter;
2593 winpos.x = x;
2594 winpos.y = y;
2595 winpos.cx = cx;
2596 winpos.cy = cy;
2597 winpos.flags = flags;
2599 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2601 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2603 if( wndPtr->parent == WIN_GetDesktop() )
2604 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2605 hwndInsertAfter, winpos.flags );
2606 WIN_ReleaseDesktop();
2609 if(!(wndPtr->flags & WIN_NATIVE) )
2611 if( hwndInsertAfter == HWND_TOP )
2612 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2613 else
2614 if( hwndInsertAfter == HWND_BOTTOM )
2615 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2616 else
2617 if( !(winpos.flags & SWP_NOZORDER) )
2618 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2619 winpos.flags |= SWP_NOZORDER;
2621 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2622 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2623 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2625 /* get a previous visible region for SWP_CopyValidBits() */
2626 DWORD flags = DCX_WINDOW;
2628 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2629 flags |= DCX_CLIPSIBLINGS;
2631 visRgn = DCE_GetVisRgn(hwnd, flags, 0, 0);
2635 /* Common operations */
2637 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2639 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2641 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2642 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2645 /* Reset active DCEs */
2647 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2648 wndPtr->dwStyle & WS_VISIBLE) ||
2649 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2651 RECT rect;
2653 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2654 DCE_InvalidateDCE(wndPtr, &rect);
2657 oldWindowRect = wndPtr->rectWindow;
2658 oldClientRect = wndPtr->rectClient;
2660 /* Find out if we have to redraw the whole client rect */
2662 if( oldClientRect.bottom - oldClientRect.top ==
2663 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2665 if( oldClientRect.right - oldClientRect.left ==
2666 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2668 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2669 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2671 uFlags |= SWP_EX_NOCOPY;
2674 * Use this later in CopyValidBits()
2676 else if( 0 )
2677 uFlags |= SWP_EX_NONCLIENT;
2680 /* FIXME: actually do something with WVR_VALIDRECTS */
2682 wndPtr->rectWindow = newWindowRect;
2683 wndPtr->rectClient = newClientRect;
2685 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2687 BOOL bCallDriver = TRUE;
2688 HWND tempInsertAfter = winpos.hwndInsertAfter;
2690 winpos.hwndInsertAfter = hwndInsertAfter;
2692 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2694 /* This is the only place where we need to force repainting of the contents
2695 of windows created by the host window system, all other cases go through the
2696 expose event handling */
2698 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2700 cx = newWindowRect.right - newWindowRect.left;
2701 cy = newWindowRect.bottom - newWindowRect.top;
2703 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2704 winpos.hwndInsertAfter = tempInsertAfter;
2705 bCallDriver = FALSE;
2707 if( winpos.flags & SWP_NOCLIENTMOVE )
2708 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2709 else
2711 /* client area moved but window extents remained the same, copy valid bits */
2713 visRgn = CreateRectRgn( 0, 0, cx, cy );
2714 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2715 uFlags | SWP_EX_PAINTSELF );
2720 if( bCallDriver )
2722 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2724 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2725 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2726 !(uFlags & SWP_EX_NOCOPY) )
2728 /* The origin of the client rect didn't move so we can try to repaint
2729 * only the nonclient area by setting bit gravity hint for the host window system.
2732 if( !(wndPtr->flags & WIN_MANAGED) )
2734 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2735 newWindowRect.bottom - newWindowRect.top);
2736 RECT rcn = newClientRect;
2737 RECT rco = oldClientRect;
2739 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2740 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2741 IntersectRect( &rcn, &rcn, &rco );
2742 visRgn = CreateRectRgnIndirect( &rcn );
2743 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2744 DeleteObject( hrgn );
2745 uFlags = SWP_EX_PAINTSELF;
2747 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2749 else
2750 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2753 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2754 winpos.hwndInsertAfter = tempInsertAfter;
2757 if( winpos.flags & SWP_SHOWWINDOW )
2759 HWND focus, curr;
2761 wndPtr->dwStyle |= WS_VISIBLE;
2763 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2765 /* focus was set to unmapped window, reset host focus
2766 * since the window is now visible */
2768 focus = curr = GetFocus();
2769 while (curr)
2771 if (curr == hwnd)
2773 WND *pFocus = WIN_FindWndPtr( focus );
2774 if (pFocus)
2775 pFocus->pDriver->pSetFocus(pFocus);
2776 WIN_ReleaseWndPtr(pFocus);
2777 break;
2779 curr = GetParent(curr);
2783 else /* -------------------------------------------- emulated window */
2785 if( winpos.flags & SWP_SHOWWINDOW )
2787 wndPtr->dwStyle |= WS_VISIBLE;
2788 uFlags |= SWP_EX_PAINTSELF;
2789 visRgn = 1; /* redraw the whole window */
2791 else if( !(winpos.flags & SWP_NOREDRAW) )
2793 if( winpos.flags & SWP_HIDEWINDOW )
2795 if( visRgn > 1 ) /* map to parent */
2796 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2797 else
2798 visRgn = 0;
2800 else
2802 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2803 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2804 &oldClientRect, uFlags);
2805 else
2807 /* nothing moved, redraw frame if needed */
2809 if( winpos.flags & SWP_FRAMECHANGED )
2810 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2811 if( visRgn )
2813 DeleteObject( visRgn );
2814 visRgn = 0;
2821 if( winpos.flags & SWP_HIDEWINDOW )
2823 wndPtr->dwStyle &= ~WS_VISIBLE;
2825 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2828 /* ------------------------------------------------------------------------ FINAL */
2830 if (wndPtr->flags & WIN_NATIVE)
2831 EVENT_Synchronize(); /* Synchronize with the host window system */
2833 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2835 /* Simulate a mouse event to set the cursor */
2836 int iWndsLocks = WIN_SuspendWndsLock();
2838 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2839 PosX, PosY, GetTickCount(), 0 );
2841 WIN_RestoreWndsLock(iWndsLocks);
2844 wndTemp = WIN_GetDesktop();
2846 /* repaint invalidated region (if any)
2848 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2849 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2852 if( visRgn )
2854 if( !(winpos.flags & SWP_NOREDRAW) )
2857 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2858 its parent and sibling and so on, and then erase the parent window
2859 back ground if the parent is either a top-level window or its parent's parent
2860 is top-level window. Rely on the system to repaint other affected
2861 windows later on. */
2862 if( uFlags & SWP_EX_PAINTSELF )
2864 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2865 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2866 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2868 else
2870 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2871 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2872 RDW_EX_USEHRGN );
2875 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2877 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2878 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2881 if( visRgn != 1 )
2882 DeleteObject( visRgn );
2885 WIN_ReleaseDesktop();
2887 if (!(flags & SWP_NOACTIVATE))
2888 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2890 /* And last, send the WM_WINDOWPOSCHANGED message */
2892 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2894 if ( resync ||
2895 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2896 !(winpos.flags & SWP_NOSENDCHANGING)) )
2898 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2899 if (resync) EVENT_Synchronize();
2902 retvalue = TRUE;
2903 END:
2904 WIN_ReleaseWndPtr(wndPtr);
2905 return retvalue;
2909 /***********************************************************************
2910 * BeginDeferWindowPos16 (USER.259)
2912 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2914 return BeginDeferWindowPos( count );
2918 /***********************************************************************
2919 * BeginDeferWindowPos (USER32.9)
2921 HDWP WINAPI BeginDeferWindowPos( INT count )
2923 HDWP handle;
2924 DWP *pDWP;
2926 if (count <= 0) return 0;
2927 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2928 if (!handle) return 0;
2929 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2930 pDWP->actualCount = 0;
2931 pDWP->suggestedCount = count;
2932 pDWP->valid = TRUE;
2933 pDWP->wMagic = DWP_MAGIC;
2934 pDWP->hwndParent = 0;
2935 return handle;
2939 /***********************************************************************
2940 * DeferWindowPos16 (USER.260)
2942 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2943 INT16 x, INT16 y, INT16 cx, INT16 cy,
2944 UINT16 flags )
2946 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2947 x, y, cx, cy, flags );
2951 /***********************************************************************
2952 * DeferWindowPos (USER32.128)
2954 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2955 INT x, INT y, INT cx, INT cy,
2956 UINT flags )
2958 DWP *pDWP;
2959 int i;
2960 HDWP newhdwp = hdwp,retvalue;
2961 /* HWND parent; */
2962 WND *pWnd;
2964 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2965 if (!pDWP) return 0;
2966 if (hwnd == GetDesktopWindow()) return 0;
2968 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2969 USER_HEAP_FREE( hdwp );
2970 return 0;
2973 /* Numega Bounds Checker Demo dislikes the following code.
2974 In fact, I've not been able to find any "same parent" requirement in any docu
2975 [AM 980509]
2977 #if 0
2978 /* All the windows of a DeferWindowPos() must have the same parent */
2979 parent = pWnd->parent->hwndSelf;
2980 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2981 else if (parent != pDWP->hwndParent)
2983 USER_HEAP_FREE( hdwp );
2984 retvalue = 0;
2985 goto END;
2987 #endif
2989 for (i = 0; i < pDWP->actualCount; i++)
2991 if (pDWP->winPos[i].hwnd == hwnd)
2993 /* Merge with the other changes */
2994 if (!(flags & SWP_NOZORDER))
2996 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
2998 if (!(flags & SWP_NOMOVE))
3000 pDWP->winPos[i].x = x;
3001 pDWP->winPos[i].y = y;
3003 if (!(flags & SWP_NOSIZE))
3005 pDWP->winPos[i].cx = cx;
3006 pDWP->winPos[i].cy = cy;
3008 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3009 SWP_NOZORDER | SWP_NOREDRAW |
3010 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3011 SWP_NOOWNERZORDER);
3012 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3013 SWP_FRAMECHANGED);
3014 retvalue = hdwp;
3015 goto END;
3018 if (pDWP->actualCount >= pDWP->suggestedCount)
3020 newhdwp = USER_HEAP_REALLOC( hdwp,
3021 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3022 if (!newhdwp)
3024 retvalue = 0;
3025 goto END;
3027 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3028 pDWP->suggestedCount++;
3030 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3031 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3032 pDWP->winPos[pDWP->actualCount].x = x;
3033 pDWP->winPos[pDWP->actualCount].y = y;
3034 pDWP->winPos[pDWP->actualCount].cx = cx;
3035 pDWP->winPos[pDWP->actualCount].cy = cy;
3036 pDWP->winPos[pDWP->actualCount].flags = flags;
3037 pDWP->actualCount++;
3038 retvalue = newhdwp;
3039 END:
3040 WIN_ReleaseWndPtr(pWnd);
3041 return retvalue;
3045 /***********************************************************************
3046 * EndDeferWindowPos16 (USER.261)
3048 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3050 return EndDeferWindowPos( hdwp );
3054 /***********************************************************************
3055 * EndDeferWindowPos (USER32.173)
3057 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3059 DWP *pDWP;
3060 WINDOWPOS *winpos;
3061 BOOL res = TRUE;
3062 int i;
3064 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3065 if (!pDWP) return FALSE;
3066 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3068 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3069 winpos->x, winpos->y, winpos->cx,
3070 winpos->cy, winpos->flags ))) break;
3072 USER_HEAP_FREE( hdwp );
3073 return res;
3077 /***********************************************************************
3078 * TileChildWindows (USER.199)
3080 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3082 FIXME("(%04x, %d): stub\n", parent, action);
3085 /***********************************************************************
3086 * CascageChildWindows (USER.198)
3088 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3090 FIXME("(%04x, %d): stub\n", parent, action);
3093 /***********************************************************************
3094 * SetProgmanWindow [USER32.522]
3096 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3098 hGlobalProgmanWindow = hwnd;
3099 return hGlobalProgmanWindow;
3102 /***********************************************************************
3103 * GetProgmanWindow [USER32.289]
3105 HRESULT WINAPI GetProgmanWindow ( )
3107 return hGlobalProgmanWindow;
3110 /***********************************************************************
3111 * SetShellWindowEx [USER32.531]
3112 * hwndProgman = Progman[Program Manager]
3113 * |-> SHELLDLL_DefView
3114 * hwndListView = | |-> SysListView32
3115 * | | |-> tooltips_class32
3116 * | |
3117 * | |-> SysHeader32
3118 * |
3119 * |-> ProxyTarget
3121 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3123 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3124 hGlobalShellWindow = hwndProgman;
3125 return hGlobalShellWindow;
3129 /***********************************************************************
3130 * SetTaskmanWindow [USER32.537]
3131 * NOTES
3132 * hwnd = MSTaskSwWClass
3133 * |-> SysTabControl32
3135 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3137 hGlobalTaskmanWindow = hwnd;
3138 return hGlobalTaskmanWindow;
3141 /***********************************************************************
3142 * GetTaskmanWindow [USER32.304]
3144 HRESULT WINAPI GetTaskmanWindow ( )
3146 return hGlobalTaskmanWindow;