Fixed some warnings.
[wine.git] / windows / winpos.c
blobe2f56e484a60d0c043e1221b4af374d121118a01
1 /*
2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
6 */
8 #include <string.h>
9 #include "windef.h"
10 #include "wingdi.h"
11 #include "winerror.h"
12 #include "wine/winuser16.h"
13 #include "heap.h"
14 #include "module.h"
15 #include "user.h"
16 #include "region.h"
17 #include "win.h"
18 #include "hook.h"
19 #include "message.h"
20 #include "queue.h"
21 #include "options.h"
22 #include "task.h"
23 #include "winpos.h"
24 #include "dce.h"
25 #include "nonclient.h"
26 #include "debugtools.h"
27 #include "local.h"
28 #include "ldt.h"
29 #include "input.h"
31 DEFAULT_DEBUG_CHANNEL(win)
33 #define HAS_DLGFRAME(style,exStyle) \
34 (((exStyle) & WS_EX_DLGMODALFRAME) || \
35 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
37 #define HAS_THICKFRAME(style) \
38 (((style) & WS_THICKFRAME) && \
39 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
41 #define SWP_AGG_NOGEOMETRYCHANGE \
42 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
43 #define SWP_AGG_NOPOSCHANGE \
44 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
45 #define SWP_AGG_STATUSFLAGS \
46 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
48 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
50 #define PLACE_MIN 0x0001
51 #define PLACE_MAX 0x0002
52 #define PLACE_RECT 0x0004
54 #define SWP_EX_NOCOPY 0x0001
55 #define SWP_EX_PAINTSELF 0x0002
56 #define SWP_EX_NONCLIENT 0x0004
58 #define MINMAX_NOSWP 0x00010000
60 /* ----- internal variables ----- */
62 static HWND hwndPrevActive = 0; /* Previously active window */
63 static HWND hGlobalShellWindow=0; /*the shell*/
64 static HWND hGlobalTaskmanWindow=0;
65 static HWND hGlobalProgmanWindow=0;
67 static LPCSTR atomInternalPos;
69 extern HQUEUE16 hActiveQueue;
71 /***********************************************************************
72 * WINPOS_CreateInternalPosAtom
74 BOOL WINPOS_CreateInternalPosAtom()
76 LPSTR str = "SysIP";
77 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
78 return (atomInternalPos) ? TRUE : FALSE;
81 /***********************************************************************
82 * WINPOS_CheckInternalPos
84 * Called when a window is destroyed.
86 void WINPOS_CheckInternalPos( WND* wndPtr )
88 LPINTERNALPOS lpPos;
89 MESSAGEQUEUE *pMsgQ = 0;
90 HWND hwnd = wndPtr->hwndSelf;
92 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
94 /* Retrieve the message queue associated with this window */
95 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
96 if ( !pMsgQ )
98 WARN("\tMessage queue not found. Exiting!\n" );
99 return;
102 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
104 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
106 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
107 WARN("\tattempt to activate destroyed window!\n");
110 if( lpPos )
112 if( IsWindow(lpPos->hwndIconTitle) )
113 DestroyWindow( lpPos->hwndIconTitle );
114 HeapFree( SystemHeap, 0, lpPos );
117 QUEUE_Unlock( pMsgQ );
118 return;
121 /***********************************************************************
122 * WINPOS_FindIconPos
124 * Find a suitable place for an iconic window.
126 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
128 RECT16 rectParent;
129 short x, y, xspacing, yspacing;
131 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
132 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
133 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
134 return pt; /* The icon already has a suitable position */
136 xspacing = GetSystemMetrics(SM_CXICONSPACING);
137 yspacing = GetSystemMetrics(SM_CYICONSPACING);
139 y = rectParent.bottom;
140 for (;;)
142 x = rectParent.left;
145 /* Check if another icon already occupies this spot */
146 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
147 while (childPtr)
149 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
151 if ((childPtr->rectWindow.left < x + xspacing) &&
152 (childPtr->rectWindow.right >= x) &&
153 (childPtr->rectWindow.top <= y) &&
154 (childPtr->rectWindow.bottom > y - yspacing))
155 break; /* There's a window in there */
157 WIN_UpdateWndPtr(&childPtr,childPtr->next);
159 WIN_ReleaseWndPtr(childPtr);
160 if (!childPtr) /* No window was found, so it's OK for us */
162 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
163 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
164 return pt;
166 x += xspacing;
167 } while(x <= rectParent.right-xspacing);
168 y -= yspacing;
173 /***********************************************************************
174 * ArrangeIconicWindows16 (USER.170)
176 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
178 return ArrangeIconicWindows(parent);
180 /***********************************************************************
181 * ArrangeIconicWindows (USER32.7)
183 UINT WINAPI ArrangeIconicWindows( HWND parent )
185 RECT rectParent;
186 HWND hwndChild;
187 INT x, y, xspacing, yspacing;
189 GetClientRect( parent, &rectParent );
190 x = rectParent.left;
191 y = rectParent.bottom;
192 xspacing = GetSystemMetrics(SM_CXICONSPACING);
193 yspacing = GetSystemMetrics(SM_CYICONSPACING);
195 hwndChild = GetWindow( parent, GW_CHILD );
196 while (hwndChild)
198 if( IsIconic( hwndChild ) )
200 WND *wndPtr = WIN_FindWndPtr(hwndChild);
202 WINPOS_ShowIconTitle( wndPtr, FALSE );
204 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
205 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
206 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
207 if( IsWindow(hwndChild) )
208 WINPOS_ShowIconTitle(wndPtr , TRUE );
209 WIN_ReleaseWndPtr(wndPtr);
211 if (x <= rectParent.right - xspacing) x += xspacing;
212 else
214 x = rectParent.left;
215 y -= yspacing;
218 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
220 return yspacing;
224 /***********************************************************************
225 * SwitchToThisWindow16 (USER.172)
227 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
229 SwitchToThisWindow( hwnd, restore );
233 /***********************************************************************
234 * SwitchToThisWindow (USER32.539)
236 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
238 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
242 /***********************************************************************
243 * GetWindowRect16 (USER.32)
245 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
247 WND * wndPtr = WIN_FindWndPtr( hwnd );
248 if (!wndPtr) return;
250 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
251 if (wndPtr->dwStyle & WS_CHILD)
252 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
253 WIN_ReleaseWndPtr(wndPtr);
257 /***********************************************************************
258 * GetWindowRect (USER32.308)
260 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
262 WND * wndPtr = WIN_FindWndPtr( hwnd );
263 if (!wndPtr) return FALSE;
265 *rect = wndPtr->rectWindow;
266 if (wndPtr->dwStyle & WS_CHILD)
267 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
268 WIN_ReleaseWndPtr(wndPtr);
269 return TRUE;
273 /***********************************************************************
274 * GetWindowRgn
276 BOOL WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
279 RECT rect;
280 WND * wndPtr = WIN_FindWndPtr( hwnd );
281 if (!wndPtr) return (ERROR);
283 FIXME("GetWindowRgn: doesn't really do regions\n");
285 memset (&rect, 0, sizeof(rect));
287 GetWindowRect ( hwnd, &rect );
289 FIXME("Check whether a valid region here\n");
291 SetRectRgn ( hrgn, rect.left, rect.top, rect.right, rect.bottom );
293 WIN_ReleaseWndPtr(wndPtr);
294 return (SIMPLEREGION);
297 /***********************************************************************
298 * SetWindowRgn
300 INT WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn,BOOL bRedraw)
304 FIXME("SetWindowRgn: stub\n");
305 return TRUE;
308 /***********************************************************************
309 * SetWindowRgn16
311 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
315 FIXME("SetWindowRgn16: stub\n");
316 return TRUE;
320 /***********************************************************************
321 * GetClientRect16 (USER.33)
323 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
325 WND * wndPtr = WIN_FindWndPtr( hwnd );
327 rect->left = rect->top = rect->right = rect->bottom = 0;
328 if (wndPtr)
330 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
331 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
333 WIN_ReleaseWndPtr(wndPtr);
337 /***********************************************************************
338 * GetClientRect (USER.220)
340 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
342 WND * wndPtr = WIN_FindWndPtr( hwnd );
344 rect->left = rect->top = rect->right = rect->bottom = 0;
345 if (!wndPtr) return FALSE;
346 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
347 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
349 WIN_ReleaseWndPtr(wndPtr);
350 return TRUE;
354 /*******************************************************************
355 * ClientToScreen16 (USER.28)
357 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
359 MapWindowPoints16( hwnd, 0, lppnt, 1 );
363 /*******************************************************************
364 * ClientToScreen (USER32.52)
366 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
368 MapWindowPoints( hwnd, 0, lppnt, 1 );
369 return TRUE;
373 /*******************************************************************
374 * ScreenToClient16 (USER.29)
376 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
378 MapWindowPoints16( 0, hwnd, lppnt, 1 );
382 /*******************************************************************
383 * ScreenToClient (USER32.447)
385 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
387 MapWindowPoints( 0, hwnd, lppnt, 1 );
388 return TRUE;
392 /***********************************************************************
393 * WINPOS_WindowFromPoint
395 * Find the window and hittest for a given point.
397 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
399 WND *wndPtr;
400 INT16 hittest = HTERROR;
401 INT16 retvalue;
402 POINT16 xy = pt;
404 *ppWnd = NULL;
405 wndPtr = WIN_LockWndPtr(wndScope->child);
407 if( wndScope->dwStyle & WS_DISABLED )
409 retvalue = HTERROR;
410 goto end;
413 if( wndScope->flags & WIN_MANAGED )
415 /* In managed mode we have to check wndScope first as it is also
416 * a window which received the mouse event. */
418 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
419 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
420 goto hittest;
422 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
424 for (;;)
426 while (wndPtr)
428 /* If point is in window, and window is visible, and it */
429 /* is enabled (or it's a top-level window), then explore */
430 /* its children. Otherwise, go to the next window. */
432 if ((wndPtr->dwStyle & WS_VISIBLE) &&
433 (!(wndPtr->dwStyle & WS_DISABLED) ||
434 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
435 (xy.x >= wndPtr->rectWindow.left) &&
436 (xy.x < wndPtr->rectWindow.right) &&
437 (xy.y >= wndPtr->rectWindow.top) &&
438 (xy.y < wndPtr->rectWindow.bottom))
440 *ppWnd = wndPtr; /* Got a suitable window */
442 /* If window is minimized or disabled, return at once */
443 if (wndPtr->dwStyle & WS_MINIMIZE)
445 retvalue = HTCAPTION;
446 goto end;
448 if (wndPtr->dwStyle & WS_DISABLED)
450 retvalue = HTERROR;
451 goto end;
454 /* If point is not in client area, ignore the children */
455 if ((xy.x < wndPtr->rectClient.left) ||
456 (xy.x >= wndPtr->rectClient.right) ||
457 (xy.y < wndPtr->rectClient.top) ||
458 (xy.y >= wndPtr->rectClient.bottom)) break;
460 xy.x -= wndPtr->rectClient.left;
461 xy.y -= wndPtr->rectClient.top;
462 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
464 else
466 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
470 hittest:
471 /* If nothing found, try the scope window */
472 if (!*ppWnd) *ppWnd = wndScope;
474 /* Send the WM_NCHITTEST message (only if to the same task) */
475 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
477 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
478 0, MAKELONG( pt.x, pt.y ) );
479 if (hittest != HTTRANSPARENT)
481 retvalue = hittest; /* Found the window */
482 goto end;
485 else
487 retvalue = HTCLIENT;
488 goto end;
491 /* If no children found in last search, make point relative to parent */
492 if (!wndPtr)
494 xy.x += (*ppWnd)->rectClient.left;
495 xy.y += (*ppWnd)->rectClient.top;
498 /* Restart the search from the next sibling */
499 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
500 *ppWnd = (*ppWnd)->parent;
503 end:
504 WIN_ReleaseWndPtr(wndPtr);
505 return retvalue;
509 /*******************************************************************
510 * WindowFromPoint16 (USER.30)
512 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
514 WND *pWnd;
515 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
516 WIN_ReleaseDesktop();
517 return pWnd->hwndSelf;
521 /*******************************************************************
522 * WindowFromPoint (USER32.582)
524 HWND WINAPI WindowFromPoint( POINT pt )
526 WND *pWnd;
527 POINT16 pt16;
528 CONV_POINT32TO16( &pt, &pt16 );
529 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
530 WIN_ReleaseDesktop();
531 return (HWND)pWnd->hwndSelf;
535 /*******************************************************************
536 * ChildWindowFromPoint16 (USER.191)
538 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
540 POINT pt32;
541 CONV_POINT16TO32( &pt, &pt32 );
542 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
546 /*******************************************************************
547 * ChildWindowFromPoint (USER32.49)
549 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
551 /* pt is in the client coordinates */
553 WND* wnd = WIN_FindWndPtr(hwndParent);
554 RECT rect;
555 HWND retvalue;
557 if( !wnd ) return 0;
559 /* get client rect fast */
560 rect.top = rect.left = 0;
561 rect.right = wnd->rectClient.right - wnd->rectClient.left;
562 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
564 if (!PtInRect( &rect, pt ))
566 retvalue = 0;
567 goto end;
569 WIN_UpdateWndPtr(&wnd,wnd->child);
570 while ( wnd )
572 if (PtInRect( &wnd->rectWindow, pt ))
574 retvalue = wnd->hwndSelf;
575 goto end;
577 WIN_UpdateWndPtr(&wnd,wnd->next);
579 retvalue = hwndParent;
580 end:
581 WIN_ReleaseWndPtr(wnd);
582 return retvalue;
585 /*******************************************************************
586 * ChildWindowFromPointEx16 (USER.50)
588 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
590 POINT pt32;
591 CONV_POINT16TO32( &pt, &pt32 );
592 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
596 /*******************************************************************
597 * ChildWindowFromPointEx (USER32.50)
599 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
600 UINT uFlags)
602 /* pt is in the client coordinates */
604 WND* wnd = WIN_FindWndPtr(hwndParent);
605 RECT rect;
606 HWND retvalue;
608 if( !wnd ) return 0;
610 /* get client rect fast */
611 rect.top = rect.left = 0;
612 rect.right = wnd->rectClient.right - wnd->rectClient.left;
613 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
615 if (!PtInRect( &rect, pt ))
617 retvalue = 0;
618 goto end;
620 WIN_UpdateWndPtr(&wnd,wnd->child);
622 while ( wnd )
624 if (PtInRect( &wnd->rectWindow, pt )) {
625 if ( (uFlags & CWP_SKIPINVISIBLE) &&
626 !(wnd->dwStyle & WS_VISIBLE) );
627 else if ( (uFlags & CWP_SKIPDISABLED) &&
628 (wnd->dwStyle & WS_DISABLED) );
629 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
630 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
631 else
633 retvalue = wnd->hwndSelf;
634 goto end;
638 WIN_UpdateWndPtr(&wnd,wnd->next);
640 retvalue = hwndParent;
641 end:
642 WIN_ReleaseWndPtr(wnd);
643 return retvalue;
647 /*******************************************************************
648 * WINPOS_GetWinOffset
650 * Calculate the offset between the origin of the two windows. Used
651 * to implement MapWindowPoints.
653 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
654 POINT *offset )
656 WND * wndPtr = 0;
658 offset->x = offset->y = 0;
659 if (hwndFrom == hwndTo ) return;
661 /* Translate source window origin to screen coords */
662 if (hwndFrom)
664 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
666 ERR("bad hwndFrom = %04x\n",hwndFrom);
667 return;
669 while (wndPtr->parent)
671 offset->x += wndPtr->rectClient.left;
672 offset->y += wndPtr->rectClient.top;
673 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
675 WIN_ReleaseWndPtr(wndPtr);
678 /* Translate origin to destination window coords */
679 if (hwndTo)
681 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
683 ERR("bad hwndTo = %04x\n", hwndTo );
684 return;
686 while (wndPtr->parent)
688 offset->x -= wndPtr->rectClient.left;
689 offset->y -= wndPtr->rectClient.top;
690 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
692 WIN_ReleaseWndPtr(wndPtr);
697 /*******************************************************************
698 * MapWindowPoints16 (USER.258)
700 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
701 LPPOINT16 lppt, UINT16 count )
703 POINT offset;
705 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
706 while (count--)
708 lppt->x += offset.x;
709 lppt->y += offset.y;
710 lppt++;
715 /*******************************************************************
716 * MapWindowPoints (USER32.386)
718 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
719 LPPOINT lppt, UINT count )
721 POINT offset;
723 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
724 while (count--)
726 lppt->x += offset.x;
727 lppt->y += offset.y;
728 lppt++;
730 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
734 /***********************************************************************
735 * IsIconic16 (USER.31)
737 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
739 return IsIconic(hWnd);
743 /***********************************************************************
744 * IsIconic (USER32.345)
746 BOOL WINAPI IsIconic(HWND hWnd)
748 BOOL retvalue;
749 WND * wndPtr = WIN_FindWndPtr(hWnd);
750 if (wndPtr == NULL) return FALSE;
751 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
752 WIN_ReleaseWndPtr(wndPtr);
753 return retvalue;
757 /***********************************************************************
758 * IsZoomed (USER.272)
760 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
762 return IsZoomed(hWnd);
766 /***********************************************************************
767 * IsZoomed (USER.352)
769 BOOL WINAPI IsZoomed(HWND hWnd)
771 BOOL retvalue;
772 WND * wndPtr = WIN_FindWndPtr(hWnd);
773 if (wndPtr == NULL) return FALSE;
774 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
775 WIN_ReleaseWndPtr(wndPtr);
776 return retvalue;
780 /*******************************************************************
781 * GetActiveWindow (USER.60)
783 HWND16 WINAPI GetActiveWindow16(void)
785 return (HWND16)GetActiveWindow();
788 /*******************************************************************
789 * GetActiveWindow (USER32.205)
791 HWND WINAPI GetActiveWindow(void)
793 MESSAGEQUEUE *pCurMsgQ = 0;
794 HWND hwndActive = 0;
796 /* Get the messageQ for the current thread */
797 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
799 WARN("\tCurrent message queue not found. Exiting!\n" );
800 return 0;
803 /* Return the current active window from the perQ data of the current message Q */
804 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
806 QUEUE_Unlock( pCurMsgQ );
807 return hwndActive;
811 /*******************************************************************
812 * WINPOS_CanActivate
814 static BOOL WINPOS_CanActivate(WND* pWnd)
816 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
817 == WS_VISIBLE ) ) return TRUE;
818 return FALSE;
822 /*******************************************************************
823 * SetActiveWindow16 (USER.59)
825 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
827 return SetActiveWindow(hwnd);
831 /*******************************************************************
832 * SetActiveWindow (USER32.463)
834 HWND WINAPI SetActiveWindow( HWND hwnd )
836 HWND prev = 0;
837 WND *wndPtr = WIN_FindWndPtr( hwnd );
838 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
840 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
842 prev = 0;
843 goto end;
846 /* Get the messageQ for the current thread */
847 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
849 WARN("\tCurrent message queue not found. Exiting!\n" );
850 goto CLEANUP;
853 /* Retrieve the message queue associated with this window */
854 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
855 if ( !pMsgQ )
857 WARN("\tWindow message queue not found. Exiting!\n" );
858 goto CLEANUP;
861 /* Make sure that the window is associated with the calling threads
862 * message queue. It must share the same perQ data.
865 if ( pCurMsgQ->pQData != pMsgQ->pQData )
866 goto CLEANUP;
868 /* Save current active window */
869 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
871 WINPOS_SetActiveWindow( hwnd, 0, 0 );
873 CLEANUP:
874 /* Unlock the queues before returning */
875 if ( pMsgQ )
876 QUEUE_Unlock( pMsgQ );
877 if ( pCurMsgQ )
878 QUEUE_Unlock( pCurMsgQ );
880 end:
881 WIN_ReleaseWndPtr(wndPtr);
882 return prev;
886 /*******************************************************************
887 * GetForegroundWindow16 (USER.608)
889 HWND16 WINAPI GetForegroundWindow16(void)
891 return (HWND16)GetForegroundWindow();
895 /*******************************************************************
896 * SetForegroundWindow16 (USER.609)
898 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
900 return SetForegroundWindow( hwnd );
904 /*******************************************************************
905 * GetForegroundWindow (USER32.241)
907 HWND WINAPI GetForegroundWindow(void)
909 HWND hwndActive = 0;
911 /* Get the foreground window (active window of hActiveQueue) */
912 if ( hActiveQueue )
914 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
915 if ( pActiveQueue )
916 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
918 QUEUE_Unlock( pActiveQueue );
921 return hwndActive;
924 /*******************************************************************
925 * SetForegroundWindow (USER32.482)
927 BOOL WINAPI SetForegroundWindow( HWND hwnd )
929 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
933 /*******************************************************************
934 * GetShellWindow16 (USER.600)
936 HWND16 WINAPI GetShellWindow16(void)
938 return GetShellWindow();
941 /*******************************************************************
942 * SetShellWindow (USER32.504)
944 HWND WINAPI SetShellWindow(HWND hwndshell)
945 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
947 hGlobalShellWindow = hwndshell;
948 return hGlobalShellWindow;
952 /*******************************************************************
953 * GetShellWindow (USER32.287)
955 HWND WINAPI GetShellWindow(void)
956 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
958 return hGlobalShellWindow;
962 /***********************************************************************
963 * BringWindowToTop16 (USER.45)
965 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
967 return BringWindowToTop(hwnd);
971 /***********************************************************************
972 * BringWindowToTop (USER32.11)
974 BOOL WINAPI BringWindowToTop( HWND hwnd )
976 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
980 /***********************************************************************
981 * MoveWindow16 (USER.56)
983 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
984 BOOL16 repaint )
986 return MoveWindow(hwnd,x,y,cx,cy,repaint);
990 /***********************************************************************
991 * MoveWindow (USER32.399)
993 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
994 BOOL repaint )
996 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
997 if (!repaint) flags |= SWP_NOREDRAW;
998 TRACE("%04x %d,%d %dx%d %d\n",
999 hwnd, x, y, cx, cy, repaint );
1000 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1003 /***********************************************************************
1004 * WINPOS_InitInternalPos
1006 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1007 LPRECT restoreRect )
1009 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1010 atomInternalPos );
1011 if( !lpPos )
1013 /* this happens when the window is minimized/maximized
1014 * for the first time (rectWindow is not adjusted yet) */
1016 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1017 if( !lpPos ) return NULL;
1019 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1020 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1021 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1022 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1025 if( wnd->dwStyle & WS_MINIMIZE )
1026 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1027 else if( wnd->dwStyle & WS_MAXIMIZE )
1028 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1029 else if( restoreRect )
1030 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1032 return lpPos;
1035 /***********************************************************************
1036 * WINPOS_RedrawIconTitle
1038 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1040 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1041 if( lpPos )
1043 if( lpPos->hwndIconTitle )
1045 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1046 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1047 return TRUE;
1050 return FALSE;
1053 /***********************************************************************
1054 * WINPOS_ShowIconTitle
1056 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1058 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1060 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1062 HWND16 hWnd = lpPos->hwndIconTitle;
1064 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1066 if( !hWnd )
1067 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1068 if( bShow )
1070 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1072 if( !(pWnd->dwStyle & WS_VISIBLE) )
1074 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1075 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1076 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1078 WIN_ReleaseWndPtr(pWnd);
1081 else ShowWindow( hWnd, SW_HIDE );
1083 return FALSE;
1086 /*******************************************************************
1087 * WINPOS_GetMinMaxInfo
1089 * Get the minimized and maximized information for a window.
1091 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1092 POINT *minTrack, POINT *maxTrack )
1094 LPINTERNALPOS lpPos;
1095 MINMAXINFO MinMax;
1096 INT xinc, yinc;
1098 /* Compute default values */
1100 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1101 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1102 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1103 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1104 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1105 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1107 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1108 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1110 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1111 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1113 else
1115 xinc = yinc = 0;
1116 if (HAS_THICKFRAME(wndPtr->dwStyle))
1118 xinc += GetSystemMetrics(SM_CXFRAME);
1119 yinc += GetSystemMetrics(SM_CYFRAME);
1121 if (wndPtr->dwStyle & WS_BORDER)
1123 xinc += GetSystemMetrics(SM_CXBORDER);
1124 yinc += GetSystemMetrics(SM_CYBORDER);
1127 MinMax.ptMaxSize.x += 2 * xinc;
1128 MinMax.ptMaxSize.y += 2 * yinc;
1130 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1131 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1132 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1133 else
1135 MinMax.ptMaxPosition.x = -xinc;
1136 MinMax.ptMaxPosition.y = -yinc;
1139 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1141 /* Some sanity checks */
1143 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1144 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1145 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1146 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1147 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1148 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1149 MinMax.ptMinTrackSize.x );
1150 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1151 MinMax.ptMinTrackSize.y );
1153 if (maxSize) *maxSize = MinMax.ptMaxSize;
1154 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1155 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1156 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1159 /***********************************************************************
1160 * WINPOS_MinMaximize
1162 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1163 * This function assumes that 'cmd' is different from the current window
1164 * state.
1166 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1168 UINT swpFlags = 0;
1169 POINT pt, size;
1170 LPINTERNALPOS lpPos;
1172 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1174 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1175 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1177 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1179 if( wndPtr->dwStyle & WS_MINIMIZE )
1181 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1182 return (SWP_NOSIZE | SWP_NOMOVE);
1183 swpFlags |= SWP_NOCOPYBITS;
1185 switch( cmd )
1187 case SW_MINIMIZE:
1188 if( wndPtr->dwStyle & WS_MAXIMIZE)
1190 wndPtr->flags |= WIN_RESTORE_MAX;
1191 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1193 else
1194 wndPtr->flags &= ~WIN_RESTORE_MAX;
1195 wndPtr->dwStyle |= WS_MINIMIZE;
1197 if( wndPtr->flags & WIN_NATIVE )
1198 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1199 swpFlags |= MINMAX_NOSWP;
1201 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1203 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1204 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1205 swpFlags |= SWP_NOCOPYBITS;
1206 break;
1208 case SW_MAXIMIZE:
1209 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1210 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1211 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1213 if( wndPtr->dwStyle & WS_MINIMIZE )
1215 if( wndPtr->flags & WIN_NATIVE )
1216 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1217 swpFlags |= MINMAX_NOSWP;
1219 WINPOS_ShowIconTitle( wndPtr, FALSE );
1220 wndPtr->dwStyle &= ~WS_MINIMIZE;
1222 wndPtr->dwStyle |= WS_MAXIMIZE;
1224 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1225 size.x, size.y );
1226 break;
1228 case SW_RESTORE:
1229 if( wndPtr->dwStyle & WS_MINIMIZE )
1231 if( wndPtr->flags & WIN_NATIVE )
1232 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1233 swpFlags |= MINMAX_NOSWP;
1235 wndPtr->dwStyle &= ~WS_MINIMIZE;
1236 WINPOS_ShowIconTitle( wndPtr, FALSE );
1238 if( wndPtr->flags & WIN_RESTORE_MAX)
1240 /* Restore to maximized position */
1241 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1242 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1243 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1244 wndPtr->dwStyle |= WS_MAXIMIZE;
1245 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1246 break;
1249 else
1250 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1251 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1253 /* Restore to normal position */
1255 *lpRect = lpPos->rectNormal;
1256 lpRect->right -= lpRect->left;
1257 lpRect->bottom -= lpRect->top;
1259 break;
1261 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1262 return swpFlags;
1265 /***********************************************************************
1266 * ShowWindowAsync (USER32.535)
1268 * doesn't wait; returns immediately.
1269 * used by threads to toggle windows in other (possibly hanging) threads
1271 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1273 /* FIXME: does ShowWindow() return immediately ? */
1274 return ShowWindow(hwnd, cmd);
1278 /***********************************************************************
1279 * ShowWindow16 (USER.42)
1281 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1283 return ShowWindow(hwnd,cmd);
1287 /***********************************************************************
1288 * ShowWindow (USER32.534)
1290 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1292 WND* wndPtr = WIN_FindWndPtr( hwnd );
1293 BOOL wasVisible, showFlag;
1294 RECT16 newPos = {0, 0, 0, 0};
1295 UINT swp = 0;
1297 if (!wndPtr) return FALSE;
1299 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1301 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1303 switch(cmd)
1305 case SW_HIDE:
1306 if (!wasVisible) goto END;;
1307 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1308 SWP_NOACTIVATE | SWP_NOZORDER;
1309 break;
1311 case SW_SHOWMINNOACTIVE:
1312 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1313 /* fall through */
1314 case SW_SHOWMINIMIZED:
1315 swp |= SWP_SHOWWINDOW;
1316 /* fall through */
1317 case SW_MINIMIZE:
1318 swp |= SWP_FRAMECHANGED;
1319 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1320 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1321 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1322 break;
1324 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1325 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1326 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1327 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1328 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1329 break;
1331 case SW_SHOWNA:
1332 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1333 /* fall through */
1334 case SW_SHOW:
1335 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1338 * ShowWindow has a little peculiar behavior that if the
1339 * window is already the topmost window, it will not
1340 * activate it.
1342 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1343 swp |= SWP_NOACTIVATE;
1345 break;
1347 case SW_SHOWNOACTIVATE:
1348 swp |= SWP_NOZORDER;
1349 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1350 /* fall through */
1351 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1352 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1353 case SW_RESTORE:
1354 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1356 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1357 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1358 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1359 break;
1362 showFlag = (cmd != SW_HIDE);
1363 if (showFlag != wasVisible)
1365 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1366 if (!IsWindow( hwnd )) goto END;
1369 if ((wndPtr->dwStyle & WS_CHILD) &&
1370 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1371 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1373 /* Don't call SetWindowPos() on invisible child windows */
1374 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1375 else wndPtr->dwStyle |= WS_VISIBLE;
1377 else
1379 /* We can't activate a child window */
1380 if ((wndPtr->dwStyle & WS_CHILD) &&
1381 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1382 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1383 if (!(swp & MINMAX_NOSWP))
1385 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1386 newPos.right, newPos.bottom, LOWORD(swp) );
1387 if (cmd == SW_HIDE)
1389 /* FIXME: This will cause the window to be activated irrespective
1390 * of whether it is owned by the same thread. Has to be done
1391 * asynchronously.
1394 if (hwnd == GetActiveWindow())
1395 WINPOS_ActivateOtherWindow(wndPtr);
1397 /* Revert focus to parent */
1398 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1399 SetFocus( GetParent(hwnd) );
1402 if (!IsWindow( hwnd )) goto END;
1403 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1406 if (wndPtr->flags & WIN_NEED_SIZE)
1408 /* should happen only in CreateWindowEx() */
1409 int wParam = SIZE_RESTORED;
1411 wndPtr->flags &= ~WIN_NEED_SIZE;
1412 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1413 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1414 SendMessageA( hwnd, WM_SIZE, wParam,
1415 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1416 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1417 SendMessageA( hwnd, WM_MOVE, 0,
1418 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1421 END:
1422 WIN_ReleaseWndPtr(wndPtr);
1423 return wasVisible;
1427 /***********************************************************************
1428 * GetInternalWindowPos16 (USER.460)
1430 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1431 LPPOINT16 ptIcon )
1433 WINDOWPLACEMENT16 wndpl;
1434 if (GetWindowPlacement16( hwnd, &wndpl ))
1436 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1437 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1438 return wndpl.showCmd;
1440 return 0;
1444 /***********************************************************************
1445 * GetInternalWindowPos (USER32.245)
1447 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1448 LPPOINT ptIcon )
1450 WINDOWPLACEMENT wndpl;
1451 if (GetWindowPlacement( hwnd, &wndpl ))
1453 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1454 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1455 return wndpl.showCmd;
1457 return 0;
1460 /***********************************************************************
1461 * GetWindowPlacement16 (USER.370)
1463 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1465 WND *pWnd = WIN_FindWndPtr( hwnd );
1466 LPINTERNALPOS lpPos;
1468 if(!pWnd ) return FALSE;
1470 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1471 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1472 wndpl->length = sizeof(*wndpl);
1473 if( pWnd->dwStyle & WS_MINIMIZE )
1474 wndpl->showCmd = SW_SHOWMINIMIZED;
1475 else
1476 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1477 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1478 if( pWnd->flags & WIN_RESTORE_MAX )
1479 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1480 else
1481 wndpl->flags = 0;
1482 wndpl->ptMinPosition = lpPos->ptIconPos;
1483 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1484 wndpl->rcNormalPosition = lpPos->rectNormal;
1486 WIN_ReleaseWndPtr(pWnd);
1487 return TRUE;
1491 /***********************************************************************
1492 * GetWindowPlacement (USER32.307)
1494 * Win95:
1495 * Fails if wndpl->length of Win95 (!) apps is invalid.
1497 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1499 if( pwpl32 )
1501 WINDOWPLACEMENT16 wpl;
1502 wpl.length = sizeof(wpl);
1503 if( GetWindowPlacement16( hwnd, &wpl ) )
1505 pwpl32->length = sizeof(*pwpl32);
1506 pwpl32->flags = wpl.flags;
1507 pwpl32->showCmd = wpl.showCmd;
1508 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1509 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1510 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1511 return TRUE;
1514 return FALSE;
1518 /***********************************************************************
1519 * WINPOS_SetPlacement
1521 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1522 UINT flags )
1524 WND *pWnd = WIN_FindWndPtr( hwnd );
1525 if( pWnd )
1527 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1528 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1530 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1531 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1532 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1534 if( pWnd->dwStyle & WS_MINIMIZE )
1536 WINPOS_ShowIconTitle( pWnd, FALSE );
1537 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1538 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1539 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1541 else if( pWnd->dwStyle & WS_MAXIMIZE )
1543 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1544 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1545 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1547 else if( flags & PLACE_RECT )
1548 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1549 lpPos->rectNormal.right - lpPos->rectNormal.left,
1550 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1551 SWP_NOZORDER | SWP_NOACTIVATE );
1553 ShowWindow( hwnd, wndpl->showCmd );
1554 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1556 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1558 /* SDK: ...valid only the next time... */
1559 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1561 WIN_ReleaseWndPtr(pWnd);
1562 return TRUE;
1564 return FALSE;
1568 /***********************************************************************
1569 * SetWindowPlacement16 (USER.371)
1571 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1573 return WINPOS_SetPlacement( hwnd, wndpl,
1574 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1577 /***********************************************************************
1578 * SetWindowPlacement (USER32.519)
1580 * Win95:
1581 * Fails if wndpl->length of Win95 (!) apps is invalid.
1583 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1585 if( pwpl32 )
1587 WINDOWPLACEMENT16 wpl;
1589 wpl.length = sizeof(WINDOWPLACEMENT16);
1590 wpl.flags = pwpl32->flags;
1591 wpl.showCmd = pwpl32->showCmd;
1592 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1593 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1594 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1595 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1596 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1597 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1598 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1599 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1601 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1603 return FALSE;
1607 /***********************************************************************
1608 * SetInternalWindowPos16 (USER.461)
1610 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1611 LPRECT16 rect, LPPOINT16 pt )
1613 if( IsWindow16(hwnd) )
1615 WINDOWPLACEMENT16 wndpl;
1616 UINT flags;
1618 wndpl.length = sizeof(wndpl);
1619 wndpl.showCmd = showCmd;
1620 wndpl.flags = flags = 0;
1622 if( pt )
1624 flags |= PLACE_MIN;
1625 wndpl.flags |= WPF_SETMINPOSITION;
1626 wndpl.ptMinPosition = *pt;
1628 if( rect )
1630 flags |= PLACE_RECT;
1631 wndpl.rcNormalPosition = *rect;
1633 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1638 /***********************************************************************
1639 * SetInternalWindowPos (USER32.483)
1641 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1642 LPRECT rect, LPPOINT pt )
1644 if( IsWindow(hwnd) )
1646 WINDOWPLACEMENT16 wndpl;
1647 UINT flags;
1649 wndpl.length = sizeof(wndpl);
1650 wndpl.showCmd = showCmd;
1651 wndpl.flags = flags = 0;
1653 if( pt )
1655 flags |= PLACE_MIN;
1656 wndpl.flags |= WPF_SETMINPOSITION;
1657 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1659 if( rect )
1661 flags |= PLACE_RECT;
1662 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1664 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1668 /*******************************************************************
1669 * WINPOS_SetActiveWindow
1671 * SetActiveWindow() back-end. This is the only function that
1672 * can assign active status to a window. It must be called only
1673 * for the top level windows.
1675 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1677 CBTACTIVATESTRUCT16* cbtStruct;
1678 WND* wndPtr=0, *wndTemp;
1679 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1680 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1681 WORD wIconized = 0;
1682 HWND hwndActive = 0;
1683 BOOL bRet = 0;
1685 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1687 /* Get current active window from the active queue */
1688 if ( hActiveQueue )
1690 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1691 if ( pOldActiveQueue )
1692 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1695 /* paranoid checks */
1696 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1697 goto CLEANUP_END;
1699 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1700 * return 0;
1702 wndPtr = WIN_FindWndPtr(hWnd);
1703 hOldActiveQueue = hActiveQueue;
1705 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1707 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1708 WIN_ReleaseWndPtr(wndTemp);
1710 else
1711 TRACE("no current active window.\n");
1713 /* call CBT hook chain */
1714 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1716 cbtStruct->fMouse = fMouse;
1717 cbtStruct->hWndActive = hwndActive;
1718 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1719 (LPARAM)SEGPTR_GET(cbtStruct) );
1720 SEGPTR_FREE(cbtStruct);
1721 if (bRet) goto CLEANUP_END;
1724 /* set prev active wnd to current active wnd and send notification */
1725 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1727 MESSAGEQUEUE *pTempActiveQueue = 0;
1729 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1731 if (GetSysModalWindow16() != hWnd)
1732 goto CLEANUP_END;
1733 /* disregard refusal if hWnd is sysmodal */
1736 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1737 MAKEWPARAM( WA_INACTIVE, wIconized ),
1738 (LPARAM)hWnd );
1740 /* check if something happened during message processing
1741 * (global active queue may have changed)
1743 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1744 if(!pTempActiveQueue)
1745 goto CLEANUP_END;
1747 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1748 QUEUE_Unlock( pTempActiveQueue );
1749 if( hwndPrevActive != hwndActive )
1750 goto CLEANUP_END;
1753 /* Set new active window in the message queue */
1754 hwndActive = hWnd;
1755 if ( wndPtr )
1757 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1758 if ( pNewActiveQueue )
1759 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1761 else /* have to do this or MDI frame activation goes to hell */
1762 if( pOldActiveQueue )
1763 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1765 /* send palette messages */
1766 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1767 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1769 /* if prev wnd is minimized redraw icon title */
1770 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1772 /* managed windows will get ConfigureNotify event */
1773 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1775 /* check Z-order and bring hWnd to the top */
1776 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1778 if (wndTemp->dwStyle & WS_VISIBLE) break;
1780 WIN_ReleaseDesktop();
1781 WIN_ReleaseWndPtr(wndTemp);
1783 if( wndTemp != wndPtr )
1784 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1785 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1786 if (!IsWindow(hWnd))
1787 goto CLEANUP;
1790 /* Get a handle to the new active queue */
1791 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1793 /* send WM_ACTIVATEAPP if necessary */
1794 if (hOldActiveQueue != hNewActiveQueue)
1796 WND **list, **ppWnd;
1797 WND *pDesktop = WIN_GetDesktop();
1799 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1801 for (ppWnd = list; *ppWnd; ppWnd++)
1803 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1805 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1806 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1807 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1809 WIN_ReleaseWinArray(list);
1812 hActiveQueue = hNewActiveQueue;
1814 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1816 for (ppWnd = list; *ppWnd; ppWnd++)
1818 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1820 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1821 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1822 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1824 WIN_ReleaseWinArray(list);
1826 WIN_ReleaseDesktop();
1828 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1831 if (hWnd)
1833 /* walk up to the first unowned window */
1834 wndTemp = WIN_LockWndPtr(wndPtr);
1835 while (wndTemp->owner)
1837 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1839 /* and set last active owned popup */
1840 wndTemp->hwndLastActive = hWnd;
1842 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1843 WIN_ReleaseWndPtr(wndTemp);
1844 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1845 SendMessageA( hWnd, WM_ACTIVATE,
1846 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1847 (LPARAM)hwndPrevActive );
1848 if( !IsWindow(hWnd) ) goto CLEANUP;
1851 /* change focus if possible */
1852 if ( fChangeFocus )
1854 if ( pNewActiveQueue )
1856 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1858 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1859 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1860 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1861 0 : hwndActive );
1864 if ( pOldActiveQueue &&
1865 ( !pNewActiveQueue ||
1866 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1868 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1869 if ( hOldFocus )
1870 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1874 if( !hwndPrevActive && wndPtr )
1875 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1877 /* if active wnd is minimized redraw icon title */
1878 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1880 bRet = (hWnd == hwndActive); /* Success? */
1882 CLEANUP: /* Unlock the message queues before returning */
1884 if ( pNewActiveQueue )
1885 QUEUE_Unlock( pNewActiveQueue );
1887 CLEANUP_END:
1889 if ( pOldActiveQueue )
1890 QUEUE_Unlock( pOldActiveQueue );
1892 WIN_ReleaseWndPtr(wndPtr);
1893 return bRet;
1896 /*******************************************************************
1897 * WINPOS_ActivateOtherWindow
1899 * Activates window other than pWnd.
1901 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1903 BOOL bRet = 0;
1904 WND* pWndTo = NULL;
1905 HWND hwndActive = 0;
1907 /* Get current active window from the active queue */
1908 if ( hActiveQueue )
1910 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1911 if ( pActiveQueue )
1913 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1914 QUEUE_Unlock( pActiveQueue );
1918 if( pWnd->hwndSelf == hwndPrevActive )
1919 hwndPrevActive = 0;
1921 if( hwndActive != pWnd->hwndSelf &&
1922 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1923 return 0;
1925 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1926 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1928 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1930 WIN_ReleaseWndPtr(pWndTo);
1931 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1933 while( !WINPOS_CanActivate(pWndTo) )
1935 /* by now owned windows should've been taken care of */
1936 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1937 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1938 if( !pWndTo ) break;
1940 WIN_ReleaseWndPtr(pWndPtr);
1943 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1945 /* switch desktop queue to current active */
1946 if( pWndTo )
1948 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1949 WIN_ReleaseWndPtr(pWndTo);
1950 WIN_ReleaseDesktop();
1953 hwndPrevActive = 0;
1954 return bRet;
1957 /*******************************************************************
1958 * WINPOS_ChangeActiveWindow
1961 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1963 WND *wndPtr, *wndTemp;
1964 BOOL retvalue;
1965 HWND hwndActive = 0;
1967 /* Get current active window from the active queue */
1968 if ( hActiveQueue )
1970 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1971 if ( pActiveQueue )
1973 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1974 QUEUE_Unlock( pActiveQueue );
1978 if (!hWnd)
1979 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1981 wndPtr = WIN_FindWndPtr(hWnd);
1982 if( !wndPtr ) return FALSE;
1984 /* child windows get WM_CHILDACTIVATE message */
1985 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1987 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1988 goto end;
1991 if( hWnd == hwndActive )
1993 retvalue = FALSE;
1994 goto end;
1997 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
1999 retvalue = FALSE;
2000 goto end;
2003 /* switch desktop queue to current active */
2004 wndTemp = WIN_GetDesktop();
2005 if( wndPtr->parent == wndTemp)
2006 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2007 WIN_ReleaseDesktop();
2009 retvalue = TRUE;
2010 end:
2011 WIN_ReleaseWndPtr(wndPtr);
2012 return retvalue;
2016 /***********************************************************************
2017 * WINPOS_SendNCCalcSize
2019 * Send a WM_NCCALCSIZE message to a window.
2020 * All parameters are read-only except newClientRect.
2021 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2022 * when calcValidRect is TRUE.
2024 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2025 RECT *newWindowRect, RECT *oldWindowRect,
2026 RECT *oldClientRect, WINDOWPOS *winpos,
2027 RECT *newClientRect )
2029 NCCALCSIZE_PARAMS params;
2030 WINDOWPOS winposCopy;
2031 LONG result;
2033 params.rgrc[0] = *newWindowRect;
2034 if (calcValidRect)
2036 winposCopy = *winpos;
2037 params.rgrc[1] = *oldWindowRect;
2038 params.rgrc[2] = *oldClientRect;
2039 params.lppos = &winposCopy;
2041 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2042 (LPARAM)&params );
2043 TRACE("%d,%d-%d,%d\n",
2044 params.rgrc[0].left, params.rgrc[0].top,
2045 params.rgrc[0].right, params.rgrc[0].bottom );
2047 /* If the application send back garbage, ignore it */
2048 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2049 *newClientRect = params.rgrc[0];
2051 return result;
2055 /***********************************************************************
2056 * WINPOS_HandleWindowPosChanging16
2058 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2060 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2062 POINT maxSize, minTrack;
2063 if (winpos->flags & SWP_NOSIZE) return 0;
2064 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2065 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2067 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2068 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2069 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2070 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2072 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2073 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2076 return 0;
2080 /***********************************************************************
2081 * WINPOS_HandleWindowPosChanging
2083 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2085 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2087 POINT maxSize;
2088 if (winpos->flags & SWP_NOSIZE) return 0;
2089 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2090 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2092 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2093 winpos->cx = min( winpos->cx, maxSize.x );
2094 winpos->cy = min( winpos->cy, maxSize.y );
2096 return 0;
2099 /***********************************************************************
2100 * SWP_DoOwnedPopups
2102 * fix Z order taking into account owned popups -
2103 * basically we need to maintain them above the window that owns them
2105 * FIXME: hide/show owned popups when owner visibility changes.
2107 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2109 WND* w = WIN_LockWndPtr(pDesktop->child);
2111 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2113 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2115 /* make sure this popup stays above the owner */
2117 HWND hwndLocalPrev = HWND_TOP;
2119 if( hwndInsertAfter != HWND_TOP )
2121 while( w != wndPtr->owner )
2123 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2124 if( hwndLocalPrev == hwndInsertAfter ) break;
2125 WIN_UpdateWndPtr(&w,w->next);
2127 hwndInsertAfter = hwndLocalPrev;
2130 else if( wndPtr->dwStyle & WS_CHILD )
2131 goto END;
2133 WIN_UpdateWndPtr(&w, pDesktop->child);
2135 while( w )
2137 if( w == wndPtr ) break;
2139 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2141 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2142 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2143 hwndInsertAfter = w->hwndSelf;
2145 WIN_UpdateWndPtr(&w, w->next);
2148 END:
2149 WIN_ReleaseWndPtr(w);
2150 return hwndInsertAfter;
2153 /***********************************************************************
2154 * SWP_CopyValidBits
2156 * Make window look nice without excessive repainting
2158 * visible and update regions are in window coordinates
2159 * client and window rectangles are in parent client coordinates
2161 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2162 * window rects have the same origin.
2164 * Returns: uFlags and a dirty region in *pVisRgn.
2166 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2167 LPRECT lpOldWndRect,
2168 LPRECT lpOldClientRect, UINT uFlags )
2170 RECT r;
2171 HRGN newVisRgn, dirtyRgn;
2172 INT my = COMPLEXREGION;
2174 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2175 Wnd->rectWindow.left, Wnd->rectWindow.top,
2176 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2177 lpOldWndRect->left, lpOldWndRect->top,
2178 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2179 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2180 Wnd->rectClient.left, Wnd->rectClient.top,
2181 Wnd->rectClient.right, Wnd->rectClient.bottom,
2182 lpOldClientRect->left, lpOldClientRect->top,
2183 lpOldClientRect->right,lpOldClientRect->bottom );
2185 if( Wnd->hrgnUpdate == 1 )
2186 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2188 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2189 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2191 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2192 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2194 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2196 nocopy:
2198 TRACE("\twon't copy anything!\n");
2200 /* set dirtyRgn to the sum of old and new visible regions
2201 * in parent client coordinates */
2203 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2204 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2206 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2208 else /* copy valid bits to a new location */
2210 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2211 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2213 /* subtract already invalid region inside Wnd from the dst region */
2215 if( Wnd->hrgnUpdate )
2216 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2217 goto nocopy;
2219 /* check if entire window can be copied */
2221 ow = lpOldWndRect->right - lpOldWndRect->left;
2222 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2223 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2224 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2226 ocw = lpOldClientRect->right - lpOldClientRect->left;
2227 och = lpOldClientRect->bottom - lpOldClientRect->top;
2228 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2229 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2231 if( (ocw != ncw) || (och != nch) ||
2232 ( ow != nw) || ( oh != nh) ||
2233 ((lpOldClientRect->top - lpOldWndRect->top) !=
2234 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2235 ((lpOldClientRect->left - lpOldWndRect->left) !=
2236 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2238 dx = Wnd->rectClient.left - lpOldClientRect->left;
2239 dy = Wnd->rectClient.top - lpOldClientRect->top;
2241 /* restrict valid bits to the common client rect */
2243 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2244 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2245 r.right = r.left + min( ocw, ncw );
2246 r.bottom = r.top + min( och, nch );
2248 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2249 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2250 GetRgnBox( hrgnValid, &r );
2251 if( IsRectEmpty( &r ) )
2252 goto nocopy;
2253 r = *lpOldClientRect;
2255 else
2257 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2258 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2259 if( !(uFlags & SWP_EX_PAINTSELF) )
2260 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2261 r = *lpOldWndRect;
2264 if( !(uFlags & SWP_EX_PAINTSELF) )
2266 /* Move remaining regions to parent coordinates */
2267 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2268 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2270 else
2271 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2273 TRACE("\tcomputing dirty region!\n");
2275 /* Compute combined dirty region (old + new - valid) */
2276 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2277 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2279 /* Blt valid bits, r is the rect to copy */
2281 if( dx || dy )
2283 RECT rClip;
2284 HDC hDC;
2285 DC* dc;
2287 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2288 from copying clipped areas */
2290 if( uFlags & SWP_EX_PAINTSELF )
2292 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2293 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2294 rClip.right = nw; rClip.bottom = nh;
2296 else
2298 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2299 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2300 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2301 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2303 rClip.left = rClip.top = 0;
2305 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2307 if( oh > nh ) r.bottom = r.top + nh;
2308 if( ow < nw ) r.right = r.left + nw;
2310 if( IntersectRect( &r, &r, &rClip ) )
2312 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2314 /* When you copy the bits without repainting, parent doesn't
2315 get validated appropriately. Therefore, we have to validate
2316 the parent with the windows' updated region when the
2317 parent's update region is not empty. */
2319 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2321 OffsetRect(&r, dx, dy);
2322 ValidateRect(Wnd->parent->hwndSelf, &r);
2326 GDI_HEAP_UNLOCK( hDC );
2328 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2329 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2333 /* *pVisRgn now points to the invalidated region */
2335 DeleteObject(newVisRgn);
2336 DeleteObject(dirtyRgn);
2337 return uFlags;
2340 /***********************************************************************
2341 * SWP_DoSimpleFrameChanged
2343 * NOTE: old and new client rect origins are identical, only
2344 * extents may have changed. Window extents are the same.
2346 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2348 INT i = 0;
2349 RECT rect;
2350 HRGN hrgn = 0;
2352 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2354 /* Client rect changed its position/size, most likely a scrollar
2355 * was added/removed.
2357 * FIXME: WVR alignment flags
2360 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2362 i++;
2363 rect.top = 0;
2364 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2365 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2366 if(!(uFlags & SWP_EX_NOCOPY))
2367 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2368 else
2370 rect.left = 0;
2371 goto redraw;
2375 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2377 if( i )
2378 hrgn = CreateRectRgnIndirect( &rect );
2379 rect.left = 0;
2380 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2381 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2382 if(!(uFlags & SWP_EX_NOCOPY))
2383 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2384 else
2385 rect.top = 0;
2386 if( i++ )
2387 REGION_UnionRectWithRgn( hrgn, &rect );
2390 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2392 rect = wndPtr->rectWindow;
2393 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2394 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2395 i++;
2399 if( i )
2401 redraw:
2402 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2403 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2405 else
2407 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2410 if( hrgn > 1 )
2411 DeleteObject( hrgn );
2414 /***********************************************************************
2415 * SWP_DoWinPosChanging
2417 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2418 RECT* pNewWindowRect, RECT* pNewClientRect )
2420 /* Send WM_WINDOWPOSCHANGING message */
2422 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2423 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2425 /* Calculate new position and size */
2427 *pNewWindowRect = wndPtr->rectWindow;
2428 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2429 : wndPtr->rectClient;
2431 if (!(pWinpos->flags & SWP_NOSIZE))
2433 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2434 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2436 if (!(pWinpos->flags & SWP_NOMOVE))
2438 pNewWindowRect->left = pWinpos->x;
2439 pNewWindowRect->top = pWinpos->y;
2440 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2441 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2443 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2444 pWinpos->y - wndPtr->rectWindow.top );
2447 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2448 return TRUE;
2451 /***********************************************************************
2452 * SWP_DoNCCalcSize
2454 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2455 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2457 UINT wvrFlags = 0;
2459 /* Send WM_NCCALCSIZE message to get new client area */
2460 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2462 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2463 &wndPtr->rectWindow, &wndPtr->rectClient,
2464 pWinpos, pNewClientRect );
2466 /* FIXME: WVR_ALIGNxxx */
2468 if( pNewClientRect->left != wndPtr->rectClient.left ||
2469 pNewClientRect->top != wndPtr->rectClient.top )
2470 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2472 if( (pNewClientRect->right - pNewClientRect->left !=
2473 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2474 (pNewClientRect->bottom - pNewClientRect->top !=
2475 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2476 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2478 else
2479 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2480 pNewClientRect->top != wndPtr->rectClient.top) )
2481 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2482 return wvrFlags;
2485 /***********************************************************************
2486 * SetWindowPos (USER.2)
2488 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2489 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2491 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2494 /***********************************************************************
2495 * SetWindowPos (USER32.520)
2497 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2498 INT x, INT y, INT cx, INT cy, UINT flags )
2500 WINDOWPOS winpos;
2501 WND * wndPtr,*wndTemp;
2502 RECT newWindowRect, newClientRect;
2503 RECT oldWindowRect, oldClientRect;
2504 HRGN visRgn = 0;
2505 UINT wvrFlags = 0, uFlags = 0;
2506 BOOL retvalue, resync = FALSE, bChangePos;
2507 HWND hwndActive = 0;
2509 /* Get current active window from the active queue */
2510 if ( hActiveQueue )
2512 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2513 if ( pActiveQueue )
2515 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2516 QUEUE_Unlock( pActiveQueue );
2520 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2521 hwnd, x, y, x+cx, y+cy, flags);
2523 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2524 flags &= ~SWP_WINE_NOHOSTMOVE;
2527 /* ------------------------------------------------------------------------ CHECKS */
2529 /* Check window handle */
2531 if (hwnd == GetDesktopWindow()) return FALSE;
2532 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2534 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2535 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2537 /* Fix redundant flags */
2539 if(wndPtr->dwStyle & WS_VISIBLE)
2540 flags &= ~SWP_SHOWWINDOW;
2541 else
2543 if (!(flags & SWP_SHOWWINDOW))
2544 flags |= SWP_NOREDRAW;
2545 flags &= ~SWP_HIDEWINDOW;
2548 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2550 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2551 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2552 flags |= SWP_NOSIZE; /* Already the right size */
2554 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2555 flags |= SWP_NOMOVE; /* Already the right position */
2557 if (hwnd == hwndActive)
2558 flags |= SWP_NOACTIVATE; /* Already active */
2559 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2561 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2563 flags &= ~SWP_NOZORDER;
2564 hwndInsertAfter = HWND_TOP;
2565 goto Pos;
2569 /* Check hwndInsertAfter */
2571 /* FIXME: TOPMOST not supported yet */
2572 if ((hwndInsertAfter == HWND_TOPMOST) ||
2573 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2575 /* hwndInsertAfter must be a sibling of the window */
2576 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2578 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2580 if( wnd ) {
2581 if( wnd->parent != wndPtr->parent )
2583 retvalue = FALSE;
2584 WIN_ReleaseWndPtr(wnd);
2585 goto END;
2587 /* don't need to change the Zorder of hwnd if it's already inserted
2588 * after hwndInsertAfter or when inserting hwnd after itself.
2590 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2592 WIN_ReleaseWndPtr(wnd);
2595 Pos: /* ------------------------------------------------------------------------ MAIN part */
2597 /* Fill the WINDOWPOS structure */
2599 winpos.hwnd = hwnd;
2600 winpos.hwndInsertAfter = hwndInsertAfter;
2601 winpos.x = x;
2602 winpos.y = y;
2603 winpos.cx = cx;
2604 winpos.cy = cy;
2605 winpos.flags = flags;
2607 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2609 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2611 if( wndPtr->parent == WIN_GetDesktop() )
2612 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2613 hwndInsertAfter, winpos.flags );
2614 WIN_ReleaseDesktop();
2617 if(!(wndPtr->flags & WIN_NATIVE) )
2619 if( hwndInsertAfter == HWND_TOP )
2620 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2621 else
2622 if( hwndInsertAfter == HWND_BOTTOM )
2623 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2624 else
2625 if( !(winpos.flags & SWP_NOZORDER) )
2626 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2627 winpos.flags |= SWP_NOZORDER;
2629 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2630 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2631 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2633 /* get a previous visible region for SWP_CopyValidBits() */
2634 DWORD flags = DCX_WINDOW;
2636 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2637 flags |= DCX_CLIPSIBLINGS;
2639 visRgn = DCE_GetVisRgn(hwnd, flags, 0, 0);
2643 /* Common operations */
2645 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2647 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2649 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2650 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2653 /* Reset active DCEs */
2655 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2656 wndPtr->dwStyle & WS_VISIBLE) ||
2657 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2659 RECT rect;
2661 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2662 DCE_InvalidateDCE(wndPtr, &rect);
2665 oldWindowRect = wndPtr->rectWindow;
2666 oldClientRect = wndPtr->rectClient;
2668 /* Find out if we have to redraw the whole client rect */
2670 if( oldClientRect.bottom - oldClientRect.top ==
2671 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2673 if( oldClientRect.right - oldClientRect.left ==
2674 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2676 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2677 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2679 uFlags |= SWP_EX_NOCOPY;
2682 * Use this later in CopyValidBits()
2684 else if( 0 )
2685 uFlags |= SWP_EX_NONCLIENT;
2688 /* FIXME: actually do something with WVR_VALIDRECTS */
2690 wndPtr->rectWindow = newWindowRect;
2691 wndPtr->rectClient = newClientRect;
2693 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2695 BOOL bCallDriver = TRUE;
2696 HWND tempInsertAfter = winpos.hwndInsertAfter;
2698 winpos.hwndInsertAfter = hwndInsertAfter;
2700 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2702 /* This is the only place where we need to force repainting of the contents
2703 of windows created by the host window system, all other cases go through the
2704 expose event handling */
2706 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2708 cx = newWindowRect.right - newWindowRect.left;
2709 cy = newWindowRect.bottom - newWindowRect.top;
2711 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2712 winpos.hwndInsertAfter = tempInsertAfter;
2713 bCallDriver = FALSE;
2715 if( winpos.flags & SWP_NOCLIENTMOVE )
2716 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2717 else
2719 /* client area moved but window extents remained the same, copy valid bits */
2721 visRgn = CreateRectRgn( 0, 0, cx, cy );
2722 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2723 uFlags | SWP_EX_PAINTSELF );
2728 if( bCallDriver )
2730 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2732 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2733 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2734 !(uFlags & SWP_EX_NOCOPY) )
2736 /* The origin of the client rect didn't move so we can try to repaint
2737 * only the nonclient area by setting bit gravity hint for the host window system.
2740 if( !(wndPtr->flags & WIN_MANAGED) )
2742 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2743 newWindowRect.bottom - newWindowRect.top);
2744 RECT rcn = newClientRect;
2745 RECT rco = oldClientRect;
2747 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2748 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2749 IntersectRect( &rcn, &rcn, &rco );
2750 visRgn = CreateRectRgnIndirect( &rcn );
2751 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2752 DeleteObject( hrgn );
2753 uFlags = SWP_EX_PAINTSELF;
2755 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2757 else
2758 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2761 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2762 winpos.hwndInsertAfter = tempInsertAfter;
2765 if( winpos.flags & SWP_SHOWWINDOW )
2767 HWND focus, curr;
2769 wndPtr->dwStyle |= WS_VISIBLE;
2771 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2773 /* focus was set to unmapped window, reset host focus
2774 * since the window is now visible */
2776 focus = curr = GetFocus();
2777 while (curr)
2779 if (curr == hwnd)
2781 WND *pFocus = WIN_FindWndPtr( focus );
2782 if (pFocus)
2783 pFocus->pDriver->pSetFocus(pFocus);
2784 WIN_ReleaseWndPtr(pFocus);
2785 break;
2787 curr = GetParent(curr);
2791 else /* -------------------------------------------- emulated window */
2793 if( winpos.flags & SWP_SHOWWINDOW )
2795 wndPtr->dwStyle |= WS_VISIBLE;
2796 uFlags |= SWP_EX_PAINTSELF;
2797 visRgn = 1; /* redraw the whole window */
2799 else if( !(winpos.flags & SWP_NOREDRAW) )
2801 if( winpos.flags & SWP_HIDEWINDOW )
2803 if( visRgn > 1 ) /* map to parent */
2804 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2805 else
2806 visRgn = 0;
2808 else
2810 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2811 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2812 &oldClientRect, uFlags);
2813 else
2815 /* nothing moved, redraw frame if needed */
2817 if( winpos.flags & SWP_FRAMECHANGED )
2818 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2819 if( visRgn )
2821 DeleteObject( visRgn );
2822 visRgn = 0;
2829 if( winpos.flags & SWP_HIDEWINDOW )
2831 wndPtr->dwStyle &= ~WS_VISIBLE;
2833 if (hwnd == CARET_GetHwnd()) DestroyCaret();
2836 /* ------------------------------------------------------------------------ FINAL */
2838 if (wndPtr->flags & WIN_NATIVE)
2839 EVENT_Synchronize(); /* Synchronize with the host window system */
2841 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2843 /* Simulate a mouse event to set the cursor */
2844 int iWndsLocks = WIN_SuspendWndsLock();
2846 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2847 PosX, PosY, GetTickCount(), 0 );
2849 WIN_RestoreWndsLock(iWndsLocks);
2852 wndTemp = WIN_GetDesktop();
2854 /* repaint invalidated region (if any)
2856 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2857 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2860 if( visRgn )
2862 if( !(winpos.flags & SWP_NOREDRAW) )
2865 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2866 its parent and sibling and so on, and then erase the parent window
2867 back ground if the parent is either a top-level window or its parent's parent
2868 is top-level window. Rely on the system to repaint other affected
2869 windows later on. */
2870 if( uFlags & SWP_EX_PAINTSELF )
2872 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2873 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2874 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2876 else
2878 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2879 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2880 RDW_EX_USEHRGN );
2883 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2885 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2886 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2889 if( visRgn != 1 )
2890 DeleteObject( visRgn );
2893 WIN_ReleaseDesktop();
2895 if (!(flags & SWP_NOACTIVATE))
2896 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2898 /* And last, send the WM_WINDOWPOSCHANGED message */
2900 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2902 if ( resync ||
2903 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2904 !(winpos.flags & SWP_NOSENDCHANGING)) )
2906 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2907 if (resync) EVENT_Synchronize();
2910 retvalue = TRUE;
2911 END:
2912 WIN_ReleaseWndPtr(wndPtr);
2913 return retvalue;
2917 /***********************************************************************
2918 * BeginDeferWindowPos16 (USER.259)
2920 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2922 return BeginDeferWindowPos( count );
2926 /***********************************************************************
2927 * BeginDeferWindowPos (USER32.9)
2929 HDWP WINAPI BeginDeferWindowPos( INT count )
2931 HDWP handle;
2932 DWP *pDWP;
2934 if (count < 0)
2936 SetLastError(ERROR_INVALID_PARAMETER);
2937 return 0;
2939 /* Windows allows zero count, in which case it allocates context for 8 moves */
2940 if (count == 0) count = 8;
2942 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2943 if (!handle) return 0;
2944 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2945 pDWP->actualCount = 0;
2946 pDWP->suggestedCount = count;
2947 pDWP->valid = TRUE;
2948 pDWP->wMagic = DWP_MAGIC;
2949 pDWP->hwndParent = 0;
2950 return handle;
2954 /***********************************************************************
2955 * DeferWindowPos16 (USER.260)
2957 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2958 INT16 x, INT16 y, INT16 cx, INT16 cy,
2959 UINT16 flags )
2961 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
2962 x, y, cx, cy, flags );
2966 /***********************************************************************
2967 * DeferWindowPos (USER32.128)
2969 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
2970 INT x, INT y, INT cx, INT cy,
2971 UINT flags )
2973 DWP *pDWP;
2974 int i;
2975 HDWP newhdwp = hdwp,retvalue;
2976 /* HWND parent; */
2977 WND *pWnd;
2979 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
2980 if (!pDWP) return 0;
2981 if (hwnd == GetDesktopWindow()) return 0;
2983 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
2984 USER_HEAP_FREE( hdwp );
2985 return 0;
2988 /* Numega Bounds Checker Demo dislikes the following code.
2989 In fact, I've not been able to find any "same parent" requirement in any docu
2990 [AM 980509]
2992 #if 0
2993 /* All the windows of a DeferWindowPos() must have the same parent */
2994 parent = pWnd->parent->hwndSelf;
2995 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
2996 else if (parent != pDWP->hwndParent)
2998 USER_HEAP_FREE( hdwp );
2999 retvalue = 0;
3000 goto END;
3002 #endif
3004 for (i = 0; i < pDWP->actualCount; i++)
3006 if (pDWP->winPos[i].hwnd == hwnd)
3008 /* Merge with the other changes */
3009 if (!(flags & SWP_NOZORDER))
3011 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3013 if (!(flags & SWP_NOMOVE))
3015 pDWP->winPos[i].x = x;
3016 pDWP->winPos[i].y = y;
3018 if (!(flags & SWP_NOSIZE))
3020 pDWP->winPos[i].cx = cx;
3021 pDWP->winPos[i].cy = cy;
3023 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3024 SWP_NOZORDER | SWP_NOREDRAW |
3025 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3026 SWP_NOOWNERZORDER);
3027 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3028 SWP_FRAMECHANGED);
3029 retvalue = hdwp;
3030 goto END;
3033 if (pDWP->actualCount >= pDWP->suggestedCount)
3035 newhdwp = USER_HEAP_REALLOC( hdwp,
3036 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3037 if (!newhdwp)
3039 retvalue = 0;
3040 goto END;
3042 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3043 pDWP->suggestedCount++;
3045 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3046 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3047 pDWP->winPos[pDWP->actualCount].x = x;
3048 pDWP->winPos[pDWP->actualCount].y = y;
3049 pDWP->winPos[pDWP->actualCount].cx = cx;
3050 pDWP->winPos[pDWP->actualCount].cy = cy;
3051 pDWP->winPos[pDWP->actualCount].flags = flags;
3052 pDWP->actualCount++;
3053 retvalue = newhdwp;
3054 END:
3055 WIN_ReleaseWndPtr(pWnd);
3056 return retvalue;
3060 /***********************************************************************
3061 * EndDeferWindowPos16 (USER.261)
3063 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3065 return EndDeferWindowPos( hdwp );
3069 /***********************************************************************
3070 * EndDeferWindowPos (USER32.173)
3072 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3074 DWP *pDWP;
3075 WINDOWPOS *winpos;
3076 BOOL res = TRUE;
3077 int i;
3079 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3080 if (!pDWP) return FALSE;
3081 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3083 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3084 winpos->x, winpos->y, winpos->cx,
3085 winpos->cy, winpos->flags ))) break;
3087 USER_HEAP_FREE( hdwp );
3088 return res;
3092 /***********************************************************************
3093 * TileChildWindows (USER.199)
3095 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3097 FIXME("(%04x, %d): stub\n", parent, action);
3100 /***********************************************************************
3101 * CascadeChildWindows (USER.198)
3103 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3105 FIXME("(%04x, %d): stub\n", parent, action);
3108 /***********************************************************************
3109 * SetProgmanWindow [USER32.522]
3111 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3113 hGlobalProgmanWindow = hwnd;
3114 return hGlobalProgmanWindow;
3117 /***********************************************************************
3118 * GetProgmanWindow [USER32.289]
3120 HRESULT WINAPI GetProgmanWindow ( )
3122 return hGlobalProgmanWindow;
3125 /***********************************************************************
3126 * SetShellWindowEx [USER32.531]
3127 * hwndProgman = Progman[Program Manager]
3128 * |-> SHELLDLL_DefView
3129 * hwndListView = | |-> SysListView32
3130 * | | |-> tooltips_class32
3131 * | |
3132 * | |-> SysHeader32
3133 * |
3134 * |-> ProxyTarget
3136 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3138 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3139 hGlobalShellWindow = hwndProgman;
3140 return hGlobalShellWindow;
3144 /***********************************************************************
3145 * SetTaskmanWindow [USER32.537]
3146 * NOTES
3147 * hwnd = MSTaskSwWClass
3148 * |-> SysTabControl32
3150 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3152 hGlobalTaskmanWindow = hwnd;
3153 return hGlobalTaskmanWindow;
3156 /***********************************************************************
3157 * GetTaskmanWindow [USER32.304]
3159 HRESULT WINAPI GetTaskmanWindow ( )
3161 return hGlobalTaskmanWindow;