shlwapi forwarders for SetWindowLongW and CallWindowProcW.
[wine/wine-kai.git] / windows / winpos.c
blobd1ad7582ed8eda1bb13e51082a8fafdc1c497dea
1 /*
2 * Window position related functions.
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 * 1995, 1996, 1999 Alex Korobka
6 */
8 #include <string.h>
9 #include "winerror.h"
10 #include "windef.h"
11 #include "wingdi.h"
12 #include "winerror.h"
13 #include "wine/winuser16.h"
14 #include "controls.h"
15 #include "heap.h"
16 #include "user.h"
17 #include "region.h"
18 #include "win.h"
19 #include "hook.h"
20 #include "message.h"
21 #include "queue.h"
22 #include "options.h"
23 #include "task.h"
24 #include "winpos.h"
25 #include "dce.h"
26 #include "nonclient.h"
27 #include "debugtools.h"
28 #include "input.h"
30 DEFAULT_DEBUG_CHANNEL(win);
32 #define HAS_DLGFRAME(style,exStyle) \
33 (((exStyle) & WS_EX_DLGMODALFRAME) || \
34 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
36 #define HAS_THICKFRAME(style) \
37 (((style) & WS_THICKFRAME) && \
38 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
40 #define SWP_AGG_NOGEOMETRYCHANGE \
41 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
42 #define SWP_AGG_NOPOSCHANGE \
43 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
44 #define SWP_AGG_STATUSFLAGS \
45 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
47 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
49 #define PLACE_MIN 0x0001
50 #define PLACE_MAX 0x0002
51 #define PLACE_RECT 0x0004
53 #define SWP_EX_NOCOPY 0x0001
54 #define SWP_EX_PAINTSELF 0x0002
55 #define SWP_EX_NONCLIENT 0x0004
57 #define MINMAX_NOSWP 0x00010000
59 /* ----- internal variables ----- */
61 static HWND hwndPrevActive = 0; /* Previously active window */
62 static HWND hGlobalShellWindow=0; /*the shell*/
63 static HWND hGlobalTaskmanWindow=0;
64 static HWND hGlobalProgmanWindow=0;
66 static LPCSTR atomInternalPos;
68 extern HQUEUE16 hActiveQueue;
70 /***********************************************************************
71 * WINPOS_CreateInternalPosAtom
73 BOOL WINPOS_CreateInternalPosAtom()
75 LPSTR str = "SysIP";
76 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
77 return (atomInternalPos) ? TRUE : FALSE;
80 /***********************************************************************
81 * WINPOS_CheckInternalPos
83 * Called when a window is destroyed.
85 void WINPOS_CheckInternalPos( WND* wndPtr )
87 LPINTERNALPOS lpPos;
88 MESSAGEQUEUE *pMsgQ = 0;
89 HWND hwnd = wndPtr->hwndSelf;
91 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
93 /* Retrieve the message queue associated with this window */
94 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
95 if ( !pMsgQ )
97 WARN("\tMessage queue not found. Exiting!\n" );
98 return;
101 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
103 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
105 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
106 WARN("\tattempt to activate destroyed window!\n");
109 if( lpPos )
111 if( IsWindow(lpPos->hwndIconTitle) )
112 DestroyWindow( lpPos->hwndIconTitle );
113 HeapFree( SystemHeap, 0, lpPos );
116 QUEUE_Unlock( pMsgQ );
117 return;
120 /***********************************************************************
121 * WINPOS_FindIconPos
123 * Find a suitable place for an iconic window.
125 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
127 RECT16 rectParent;
128 short x, y, xspacing, yspacing;
130 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
131 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
132 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
133 return pt; /* The icon already has a suitable position */
135 xspacing = GetSystemMetrics(SM_CXICONSPACING);
136 yspacing = GetSystemMetrics(SM_CYICONSPACING);
138 y = rectParent.bottom;
139 for (;;)
141 x = rectParent.left;
144 /* Check if another icon already occupies this spot */
145 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
146 while (childPtr)
148 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
150 if ((childPtr->rectWindow.left < x + xspacing) &&
151 (childPtr->rectWindow.right >= x) &&
152 (childPtr->rectWindow.top <= y) &&
153 (childPtr->rectWindow.bottom > y - yspacing))
154 break; /* There's a window in there */
156 WIN_UpdateWndPtr(&childPtr,childPtr->next);
158 WIN_ReleaseWndPtr(childPtr);
159 if (!childPtr) /* No window was found, so it's OK for us */
161 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
162 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
163 return pt;
165 x += xspacing;
166 } while(x <= rectParent.right-xspacing);
167 y -= yspacing;
172 /***********************************************************************
173 * ArrangeIconicWindows16 (USER.170)
175 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
177 return ArrangeIconicWindows(parent);
179 /***********************************************************************
180 * ArrangeIconicWindows (USER32.7)
182 UINT WINAPI ArrangeIconicWindows( HWND parent )
184 RECT rectParent;
185 HWND hwndChild;
186 INT x, y, xspacing, yspacing;
188 GetClientRect( parent, &rectParent );
189 x = rectParent.left;
190 y = rectParent.bottom;
191 xspacing = GetSystemMetrics(SM_CXICONSPACING);
192 yspacing = GetSystemMetrics(SM_CYICONSPACING);
194 hwndChild = GetWindow( parent, GW_CHILD );
195 while (hwndChild)
197 if( IsIconic( hwndChild ) )
199 WND *wndPtr = WIN_FindWndPtr(hwndChild);
201 WINPOS_ShowIconTitle( wndPtr, FALSE );
203 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
204 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
205 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
206 if( IsWindow(hwndChild) )
207 WINPOS_ShowIconTitle(wndPtr , TRUE );
208 WIN_ReleaseWndPtr(wndPtr);
210 if (x <= rectParent.right - xspacing) x += xspacing;
211 else
213 x = rectParent.left;
214 y -= yspacing;
217 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
219 return yspacing;
223 /***********************************************************************
224 * SwitchToThisWindow16 (USER.172)
226 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
228 SwitchToThisWindow( hwnd, restore );
232 /***********************************************************************
233 * SwitchToThisWindow (USER32.539)
235 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
237 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
241 /***********************************************************************
242 * GetWindowRect16 (USER.32)
244 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
246 WND * wndPtr = WIN_FindWndPtr( hwnd );
247 if (!wndPtr) return;
249 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
250 if (wndPtr->dwStyle & WS_CHILD)
251 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
252 WIN_ReleaseWndPtr(wndPtr);
256 /***********************************************************************
257 * GetWindowRect (USER32.308)
259 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
261 WND * wndPtr = WIN_FindWndPtr( hwnd );
262 if (!wndPtr) return FALSE;
264 *rect = wndPtr->rectWindow;
265 if (wndPtr->dwStyle & WS_CHILD)
266 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
267 WIN_ReleaseWndPtr(wndPtr);
268 return TRUE;
272 /***********************************************************************
273 * GetWindowRgn (USER32)
275 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
277 int nRet = ERROR;
278 WND *wndPtr = WIN_FindWndPtr( hwnd );
279 if (wndPtr)
281 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
282 WIN_ReleaseWndPtr(wndPtr);
284 return nRet;
287 /***********************************************************************
288 * SetWindowRgn (USER32)
290 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
292 int ret = FALSE;
293 RECT tempRect;
295 WND *wndPtr = WIN_FindWndPtr(hwnd);
297 if (!wndPtr) return FALSE;
299 /* a region exists for this window */
300 if (hrgn != 0 && hrgn == wndPtr->hrgnWnd)
302 /* can't replace actual region with same region
303 since we're now owner of that region
305 SetLastError(ERROR_INVALID_HANDLE);
306 goto done;
310 /* we'd like to set it back to 0 */
311 if (hrgn == 0)
313 GetWindowRect(hwnd, &tempRect);
315 else
317 /* verify that region really exists */
318 if (GetRgnBox(hrgn, &tempRect) == ERROR) goto done;
322 /* Size the window to the rectangle of the new region
323 (if it isn't NULL) */
324 SetWindowPos( hwnd, 0, tempRect.left, tempRect.top,
325 tempRect.right - tempRect.left, tempRect.bottom - tempRect.top,
326 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE |
327 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
330 if (wndPtr->hrgnWnd)
332 /* delete previous region */
333 DeleteObject(wndPtr->hrgnWnd);
334 wndPtr->hrgnWnd = 0;
336 else if (!hrgn)
338 /* if there was no previous region (stored in wndPtr->hrgnWnd) and
339 the region to be set is also NULL, there is nothing more to do
341 ret = TRUE;
342 goto done;
345 /* valid region handle */
346 wndPtr->hrgnWnd = hrgn;
347 wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn);
349 ret = TRUE;
351 done:
352 WIN_ReleaseWndPtr(wndPtr);
353 return ret;
356 /***********************************************************************
357 * SetWindowRgn16
359 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
363 FIXME("SetWindowRgn16: stub\n");
364 return TRUE;
368 /***********************************************************************
369 * GetClientRect16 (USER.33)
371 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
373 WND * wndPtr = WIN_FindWndPtr( hwnd );
375 rect->left = rect->top = rect->right = rect->bottom = 0;
376 if (wndPtr)
378 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
379 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
381 WIN_ReleaseWndPtr(wndPtr);
385 /***********************************************************************
386 * GetClientRect (USER.220)
388 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
390 WND * wndPtr = WIN_FindWndPtr( hwnd );
392 rect->left = rect->top = rect->right = rect->bottom = 0;
393 if (!wndPtr) return FALSE;
394 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
395 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
397 WIN_ReleaseWndPtr(wndPtr);
398 return TRUE;
402 /*******************************************************************
403 * ClientToScreen16 (USER.28)
405 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
407 MapWindowPoints16( hwnd, 0, lppnt, 1 );
411 /*******************************************************************
412 * ClientToScreen (USER32.52)
414 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
416 MapWindowPoints( hwnd, 0, lppnt, 1 );
417 return TRUE;
421 /*******************************************************************
422 * ScreenToClient16 (USER.29)
424 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
426 MapWindowPoints16( 0, hwnd, lppnt, 1 );
430 /*******************************************************************
431 * ScreenToClient (USER32.447)
433 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
435 MapWindowPoints( 0, hwnd, lppnt, 1 );
436 return TRUE;
440 /***********************************************************************
441 * WINPOS_WindowFromPoint
443 * Find the window and hittest for a given point.
445 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
447 WND *wndPtr;
448 INT16 hittest = HTERROR;
449 INT16 retvalue;
450 POINT16 xy = pt;
452 TRACE("scope %04x %d,%d\n", wndScope->hwndSelf, pt.x, pt.y);
453 *ppWnd = NULL;
454 wndPtr = WIN_LockWndPtr(wndScope->child);
456 if( wndScope->dwStyle & WS_DISABLED )
458 retvalue = HTERROR;
459 goto end;
462 if( wndScope->dwExStyle & WS_EX_MANAGED)
464 /* In managed mode we have to check wndScope first as it is also
465 * a window which received the mouse event. */
467 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
468 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
469 goto hittest;
471 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
473 for (;;)
475 while (wndPtr)
477 /* If point is in window, and window is visible, and it */
478 /* is enabled (or it's a top-level window), then explore */
479 /* its children. Otherwise, go to the next window. */
481 if ((wndPtr->dwStyle & WS_VISIBLE) &&
482 (!(wndPtr->dwStyle & WS_DISABLED) ||
483 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
484 (wndPtr->hrgnWnd ?
485 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
486 xy.y - wndPtr->rectWindow.top) :
487 ((xy.x >= wndPtr->rectWindow.left) &&
488 (xy.x < wndPtr->rectWindow.right) &&
489 (xy.y >= wndPtr->rectWindow.top) &&
490 (xy.y < wndPtr->rectWindow.bottom))))
492 TRACE("%d,%d is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
493 *ppWnd = wndPtr; /* Got a suitable window */
495 /* If window is minimized or disabled, return at once */
496 if (wndPtr->dwStyle & WS_MINIMIZE)
498 retvalue = HTCAPTION;
499 goto end;
501 if (wndPtr->dwStyle & WS_DISABLED)
503 retvalue = HTERROR;
504 goto end;
507 /* If point is not in client area, ignore the children */
508 if ((xy.x < wndPtr->rectClient.left) ||
509 (xy.x >= wndPtr->rectClient.right) ||
510 (xy.y < wndPtr->rectClient.top) ||
511 (xy.y >= wndPtr->rectClient.bottom)) break;
513 xy.x -= wndPtr->rectClient.left;
514 xy.y -= wndPtr->rectClient.top;
515 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
517 else
519 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
523 hittest:
524 /* If nothing found, try the scope window */
525 if (!*ppWnd) *ppWnd = wndScope;
527 /* Send the WM_NCHITTEST message (only if to the same task) */
528 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
530 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
531 0, MAKELONG( pt.x, pt.y ) );
532 if (hittest != HTTRANSPARENT)
534 retvalue = hittest; /* Found the window */
535 goto end;
538 else
540 retvalue = HTCLIENT;
541 goto end;
544 /* If no children found in last search, make point relative to parent */
545 if (!wndPtr)
547 xy.x += (*ppWnd)->rectClient.left;
548 xy.y += (*ppWnd)->rectClient.top;
551 /* Restart the search from the next sibling */
552 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
553 *ppWnd = (*ppWnd)->parent;
556 end:
557 WIN_ReleaseWndPtr(wndPtr);
558 return retvalue;
562 /*******************************************************************
563 * WindowFromPoint16 (USER.30)
565 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
567 WND *pWnd;
568 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
569 WIN_ReleaseDesktop();
570 return pWnd->hwndSelf;
574 /*******************************************************************
575 * WindowFromPoint (USER32.582)
577 HWND WINAPI WindowFromPoint( POINT pt )
579 WND *pWnd;
580 POINT16 pt16;
581 CONV_POINT32TO16( &pt, &pt16 );
582 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
583 WIN_ReleaseDesktop();
584 return (HWND)pWnd->hwndSelf;
588 /*******************************************************************
589 * ChildWindowFromPoint16 (USER.191)
591 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
593 POINT pt32;
594 CONV_POINT16TO32( &pt, &pt32 );
595 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
599 /*******************************************************************
600 * ChildWindowFromPoint (USER32.49)
602 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
604 /* pt is in the client coordinates */
606 WND* wnd = WIN_FindWndPtr(hwndParent);
607 RECT rect;
608 HWND retvalue;
610 if( !wnd ) return 0;
612 /* get client rect fast */
613 rect.top = rect.left = 0;
614 rect.right = wnd->rectClient.right - wnd->rectClient.left;
615 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
617 if (!PtInRect( &rect, pt ))
619 retvalue = 0;
620 goto end;
622 WIN_UpdateWndPtr(&wnd,wnd->child);
623 while ( wnd )
625 if (PtInRect( &wnd->rectWindow, pt ))
627 retvalue = wnd->hwndSelf;
628 goto end;
630 WIN_UpdateWndPtr(&wnd,wnd->next);
632 retvalue = hwndParent;
633 end:
634 WIN_ReleaseWndPtr(wnd);
635 return retvalue;
638 /*******************************************************************
639 * ChildWindowFromPointEx16 (USER.50)
641 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
643 POINT pt32;
644 CONV_POINT16TO32( &pt, &pt32 );
645 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
649 /*******************************************************************
650 * ChildWindowFromPointEx (USER32.50)
652 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
653 UINT uFlags)
655 /* pt is in the client coordinates */
657 WND* wnd = WIN_FindWndPtr(hwndParent);
658 RECT rect;
659 HWND retvalue;
661 if( !wnd ) return 0;
663 /* get client rect fast */
664 rect.top = rect.left = 0;
665 rect.right = wnd->rectClient.right - wnd->rectClient.left;
666 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
668 if (!PtInRect( &rect, pt ))
670 retvalue = 0;
671 goto end;
673 WIN_UpdateWndPtr(&wnd,wnd->child);
675 while ( wnd )
677 if (PtInRect( &wnd->rectWindow, pt )) {
678 if ( (uFlags & CWP_SKIPINVISIBLE) &&
679 !(wnd->dwStyle & WS_VISIBLE) );
680 else if ( (uFlags & CWP_SKIPDISABLED) &&
681 (wnd->dwStyle & WS_DISABLED) );
682 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
683 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
684 else
686 retvalue = wnd->hwndSelf;
687 goto end;
691 WIN_UpdateWndPtr(&wnd,wnd->next);
693 retvalue = hwndParent;
694 end:
695 WIN_ReleaseWndPtr(wnd);
696 return retvalue;
700 /*******************************************************************
701 * WINPOS_GetWinOffset
703 * Calculate the offset between the origin of the two windows. Used
704 * to implement MapWindowPoints.
706 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
707 POINT *offset )
709 WND * wndPtr = 0;
711 offset->x = offset->y = 0;
712 if (hwndFrom == hwndTo ) return;
714 /* Translate source window origin to screen coords */
715 if (hwndFrom)
717 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
719 ERR("bad hwndFrom = %04x\n",hwndFrom);
720 return;
722 while (wndPtr->parent)
724 offset->x += wndPtr->rectClient.left;
725 offset->y += wndPtr->rectClient.top;
726 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
728 WIN_ReleaseWndPtr(wndPtr);
731 /* Translate origin to destination window coords */
732 if (hwndTo)
734 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
736 ERR("bad hwndTo = %04x\n", hwndTo );
737 return;
739 while (wndPtr->parent)
741 offset->x -= wndPtr->rectClient.left;
742 offset->y -= wndPtr->rectClient.top;
743 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
745 WIN_ReleaseWndPtr(wndPtr);
750 /*******************************************************************
751 * MapWindowPoints16 (USER.258)
753 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
754 LPPOINT16 lppt, UINT16 count )
756 POINT offset;
758 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
759 while (count--)
761 lppt->x += offset.x;
762 lppt->y += offset.y;
763 lppt++;
768 /*******************************************************************
769 * MapWindowPoints (USER32.386)
771 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
772 LPPOINT lppt, UINT count )
774 POINT offset;
776 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
777 while (count--)
779 lppt->x += offset.x;
780 lppt->y += offset.y;
781 lppt++;
783 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
787 /***********************************************************************
788 * IsIconic16 (USER.31)
790 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
792 return IsIconic(hWnd);
796 /***********************************************************************
797 * IsIconic (USER32.345)
799 BOOL WINAPI IsIconic(HWND hWnd)
801 BOOL retvalue;
802 WND * wndPtr = WIN_FindWndPtr(hWnd);
803 if (wndPtr == NULL) return FALSE;
804 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
805 WIN_ReleaseWndPtr(wndPtr);
806 return retvalue;
810 /***********************************************************************
811 * IsZoomed (USER.272)
813 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
815 return IsZoomed(hWnd);
819 /***********************************************************************
820 * IsZoomed (USER.352)
822 BOOL WINAPI IsZoomed(HWND hWnd)
824 BOOL retvalue;
825 WND * wndPtr = WIN_FindWndPtr(hWnd);
826 if (wndPtr == NULL) return FALSE;
827 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
828 WIN_ReleaseWndPtr(wndPtr);
829 return retvalue;
833 /*******************************************************************
834 * GetActiveWindow (USER.60)
836 HWND16 WINAPI GetActiveWindow16(void)
838 return (HWND16)GetActiveWindow();
841 /*******************************************************************
842 * GetActiveWindow (USER32.205)
844 HWND WINAPI GetActiveWindow(void)
846 MESSAGEQUEUE *pCurMsgQ = 0;
847 HWND hwndActive = 0;
849 /* Get the messageQ for the current thread */
850 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
852 WARN("\tCurrent message queue not found. Exiting!\n" );
853 return 0;
856 /* Return the current active window from the perQ data of the current message Q */
857 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
859 QUEUE_Unlock( pCurMsgQ );
860 return hwndActive;
864 /*******************************************************************
865 * WINPOS_CanActivate
867 static BOOL WINPOS_CanActivate(WND* pWnd)
869 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
870 == WS_VISIBLE ) ) return TRUE;
871 return FALSE;
875 /*******************************************************************
876 * SetActiveWindow16 (USER.59)
878 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
880 return SetActiveWindow(hwnd);
884 /*******************************************************************
885 * SetActiveWindow (USER32.463)
887 HWND WINAPI SetActiveWindow( HWND hwnd )
889 HWND prev = 0;
890 WND *wndPtr = WIN_FindWndPtr( hwnd );
891 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
893 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
895 prev = 0;
896 goto end;
899 /* Get the messageQ for the current thread */
900 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
902 WARN("\tCurrent message queue not found. Exiting!\n" );
903 goto CLEANUP;
906 /* Retrieve the message queue associated with this window */
907 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
908 if ( !pMsgQ )
910 WARN("\tWindow message queue not found. Exiting!\n" );
911 goto CLEANUP;
914 /* Make sure that the window is associated with the calling threads
915 * message queue. It must share the same perQ data.
918 if ( pCurMsgQ->pQData != pMsgQ->pQData )
919 goto CLEANUP;
921 /* Save current active window */
922 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
924 WINPOS_SetActiveWindow( hwnd, 0, 0 );
926 CLEANUP:
927 /* Unlock the queues before returning */
928 if ( pMsgQ )
929 QUEUE_Unlock( pMsgQ );
930 if ( pCurMsgQ )
931 QUEUE_Unlock( pCurMsgQ );
933 end:
934 WIN_ReleaseWndPtr(wndPtr);
935 return prev;
939 /*******************************************************************
940 * GetForegroundWindow16 (USER.608)
942 HWND16 WINAPI GetForegroundWindow16(void)
944 return (HWND16)GetForegroundWindow();
948 /*******************************************************************
949 * SetForegroundWindow16 (USER.609)
951 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
953 return SetForegroundWindow( hwnd );
957 /*******************************************************************
958 * GetForegroundWindow (USER32.241)
960 HWND WINAPI GetForegroundWindow(void)
962 HWND hwndActive = 0;
964 /* Get the foreground window (active window of hActiveQueue) */
965 if ( hActiveQueue )
967 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
968 if ( pActiveQueue )
969 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
971 QUEUE_Unlock( pActiveQueue );
974 return hwndActive;
977 /*******************************************************************
978 * SetForegroundWindow (USER32.482)
980 BOOL WINAPI SetForegroundWindow( HWND hwnd )
982 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
986 /*******************************************************************
987 * AllowSetForegroundWindow (USER32)
989 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
991 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
992 * implemented, then fix this function. */
993 return TRUE;
997 /*******************************************************************
998 * LockSetForegroundWindow (USER32)
1000 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
1002 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
1003 * implemented, then fix this function. */
1004 return TRUE;
1008 /*******************************************************************
1009 * GetShellWindow16 (USER.600)
1011 HWND16 WINAPI GetShellWindow16(void)
1013 return GetShellWindow();
1016 /*******************************************************************
1017 * SetShellWindow (USER32.504)
1019 HWND WINAPI SetShellWindow(HWND hwndshell)
1020 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
1022 hGlobalShellWindow = hwndshell;
1023 return hGlobalShellWindow;
1027 /*******************************************************************
1028 * GetShellWindow (USER32.287)
1030 HWND WINAPI GetShellWindow(void)
1031 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
1033 return hGlobalShellWindow;
1037 /***********************************************************************
1038 * BringWindowToTop16 (USER.45)
1040 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1042 return BringWindowToTop(hwnd);
1046 /***********************************************************************
1047 * BringWindowToTop (USER32.11)
1049 BOOL WINAPI BringWindowToTop( HWND hwnd )
1051 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1055 /***********************************************************************
1056 * MoveWindow16 (USER.56)
1058 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1059 BOOL16 repaint )
1061 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1065 /***********************************************************************
1066 * MoveWindow (USER32.399)
1068 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1069 BOOL repaint )
1071 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1072 if (!repaint) flags |= SWP_NOREDRAW;
1073 TRACE("%04x %d,%d %dx%d %d\n",
1074 hwnd, x, y, cx, cy, repaint );
1075 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1078 /***********************************************************************
1079 * WINPOS_InitInternalPos
1081 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1082 LPRECT restoreRect )
1084 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1085 atomInternalPos );
1086 if( !lpPos )
1088 /* this happens when the window is minimized/maximized
1089 * for the first time (rectWindow is not adjusted yet) */
1091 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1092 if( !lpPos ) return NULL;
1094 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1095 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1096 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1097 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1100 if( wnd->dwStyle & WS_MINIMIZE )
1101 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1102 else if( wnd->dwStyle & WS_MAXIMIZE )
1103 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1104 else if( restoreRect )
1105 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1107 return lpPos;
1110 /***********************************************************************
1111 * WINPOS_RedrawIconTitle
1113 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1115 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1116 if( lpPos )
1118 if( lpPos->hwndIconTitle )
1120 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1121 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1122 return TRUE;
1125 return FALSE;
1128 /***********************************************************************
1129 * WINPOS_ShowIconTitle
1131 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1133 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1135 if( lpPos && !(pWnd->dwExStyle & WS_EX_MANAGED))
1137 HWND16 hWnd = lpPos->hwndIconTitle;
1139 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1141 if( !hWnd )
1142 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1143 if( bShow )
1145 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1147 if( !(pWnd->dwStyle & WS_VISIBLE) )
1149 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1150 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1151 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1153 WIN_ReleaseWndPtr(pWnd);
1156 else ShowWindow( hWnd, SW_HIDE );
1158 return FALSE;
1161 /*******************************************************************
1162 * WINPOS_GetMinMaxInfo
1164 * Get the minimized and maximized information for a window.
1166 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1167 POINT *minTrack, POINT *maxTrack )
1169 LPINTERNALPOS lpPos;
1170 MINMAXINFO MinMax;
1171 INT xinc, yinc;
1173 /* Compute default values */
1175 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1176 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1177 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1178 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1179 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1180 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1182 if (wndPtr->dwExStyle & WS_EX_MANAGED) xinc = yinc = 0;
1183 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1185 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1186 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1188 else
1190 xinc = yinc = 0;
1191 if (HAS_THICKFRAME(wndPtr->dwStyle))
1193 xinc += GetSystemMetrics(SM_CXFRAME);
1194 yinc += GetSystemMetrics(SM_CYFRAME);
1196 if (wndPtr->dwStyle & WS_BORDER)
1198 xinc += GetSystemMetrics(SM_CXBORDER);
1199 yinc += GetSystemMetrics(SM_CYBORDER);
1202 MinMax.ptMaxSize.x += 2 * xinc;
1203 MinMax.ptMaxSize.y += 2 * yinc;
1205 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1206 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1207 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1208 else
1210 MinMax.ptMaxPosition.x = -xinc;
1211 MinMax.ptMaxPosition.y = -yinc;
1214 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1216 /* Some sanity checks */
1218 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1219 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1220 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1221 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1222 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1223 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1224 MinMax.ptMinTrackSize.x );
1225 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1226 MinMax.ptMinTrackSize.y );
1228 if (maxSize) *maxSize = MinMax.ptMaxSize;
1229 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1230 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1231 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1234 /***********************************************************************
1235 * WINPOS_MinMaximize
1237 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1238 * This function assumes that 'cmd' is different from the current window
1239 * state.
1241 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1243 UINT swpFlags = 0;
1244 POINT pt, size;
1245 LPINTERNALPOS lpPos;
1247 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1249 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1250 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1252 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1254 if( wndPtr->dwStyle & WS_MINIMIZE )
1256 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1257 return (SWP_NOSIZE | SWP_NOMOVE);
1258 swpFlags |= SWP_NOCOPYBITS;
1260 switch( cmd )
1262 case SW_MINIMIZE:
1263 if( wndPtr->dwStyle & WS_MAXIMIZE)
1265 wndPtr->flags |= WIN_RESTORE_MAX;
1266 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1268 else
1269 wndPtr->flags &= ~WIN_RESTORE_MAX;
1270 wndPtr->dwStyle |= WS_MINIMIZE;
1272 if( wndPtr->flags & WIN_NATIVE )
1273 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1274 swpFlags |= MINMAX_NOSWP;
1276 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1278 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1279 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1280 swpFlags |= SWP_NOCOPYBITS;
1281 break;
1283 case SW_MAXIMIZE:
1284 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1285 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1286 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1288 if( wndPtr->dwStyle & WS_MINIMIZE )
1290 if( wndPtr->flags & WIN_NATIVE )
1291 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1293 WINPOS_ShowIconTitle( wndPtr, FALSE );
1294 wndPtr->dwStyle &= ~WS_MINIMIZE;
1296 wndPtr->dwStyle |= WS_MAXIMIZE;
1298 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1299 size.x, size.y );
1300 break;
1302 case SW_RESTORE:
1303 if( wndPtr->dwStyle & WS_MINIMIZE )
1305 if( wndPtr->flags & WIN_NATIVE )
1306 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1307 swpFlags |= MINMAX_NOSWP;
1309 wndPtr->dwStyle &= ~WS_MINIMIZE;
1310 WINPOS_ShowIconTitle( wndPtr, FALSE );
1312 if( wndPtr->flags & WIN_RESTORE_MAX)
1314 /* Restore to maximized position */
1315 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1316 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1317 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1318 wndPtr->dwStyle |= WS_MAXIMIZE;
1319 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1320 break;
1323 else
1324 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1325 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1327 /* Restore to normal position */
1329 *lpRect = lpPos->rectNormal;
1330 lpRect->right -= lpRect->left;
1331 lpRect->bottom -= lpRect->top;
1333 break;
1335 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1336 return swpFlags;
1339 /***********************************************************************
1340 * ShowWindowAsync (USER32.535)
1342 * doesn't wait; returns immediately.
1343 * used by threads to toggle windows in other (possibly hanging) threads
1345 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1347 /* FIXME: does ShowWindow() return immediately ? */
1348 return ShowWindow(hwnd, cmd);
1352 /***********************************************************************
1353 * ShowWindow16 (USER.42)
1355 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1357 return ShowWindow(hwnd,cmd);
1361 /***********************************************************************
1362 * ShowWindow (USER32.534)
1364 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1366 WND* wndPtr = WIN_FindWndPtr( hwnd );
1367 BOOL wasVisible, showFlag;
1368 RECT16 newPos = {0, 0, 0, 0};
1369 UINT swp = 0;
1371 if (!wndPtr) return FALSE;
1373 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1375 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1377 switch(cmd)
1379 case SW_HIDE:
1380 if (!wasVisible) goto END;;
1381 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1382 SWP_NOACTIVATE | SWP_NOZORDER;
1383 break;
1385 case SW_SHOWMINNOACTIVE:
1386 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1387 /* fall through */
1388 case SW_SHOWMINIMIZED:
1389 swp |= SWP_SHOWWINDOW;
1390 /* fall through */
1391 case SW_MINIMIZE:
1392 swp |= SWP_FRAMECHANGED;
1393 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1394 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1395 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1396 break;
1398 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1399 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1400 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1401 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1402 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1403 break;
1405 case SW_SHOWNA:
1406 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1407 /* fall through */
1408 case SW_SHOW:
1409 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1412 * ShowWindow has a little peculiar behavior that if the
1413 * window is already the topmost window, it will not
1414 * activate it.
1416 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1417 swp |= SWP_NOACTIVATE;
1419 break;
1421 case SW_SHOWNOACTIVATE:
1422 swp |= SWP_NOZORDER;
1423 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1424 /* fall through */
1425 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1426 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1427 case SW_RESTORE:
1428 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1430 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1431 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1432 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1433 break;
1436 showFlag = (cmd != SW_HIDE);
1437 if (showFlag != wasVisible)
1439 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1440 if (!IsWindow( hwnd )) goto END;
1443 if ((wndPtr->dwStyle & WS_CHILD) &&
1444 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1445 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1447 /* Don't call SetWindowPos() on invisible child windows */
1448 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1449 else wndPtr->dwStyle |= WS_VISIBLE;
1451 else
1453 /* We can't activate a child window */
1454 if ((wndPtr->dwStyle & WS_CHILD) &&
1455 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1456 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1457 if (!(swp & MINMAX_NOSWP))
1459 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1460 newPos.right, newPos.bottom, LOWORD(swp) );
1461 if (cmd == SW_HIDE)
1463 /* FIXME: This will cause the window to be activated irrespective
1464 * of whether it is owned by the same thread. Has to be done
1465 * asynchronously.
1468 if (hwnd == GetActiveWindow())
1469 WINPOS_ActivateOtherWindow(wndPtr);
1471 /* Revert focus to parent */
1472 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1473 SetFocus( GetParent(hwnd) );
1476 if (!IsWindow( hwnd )) goto END;
1477 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1480 if (wndPtr->flags & WIN_NEED_SIZE)
1482 /* should happen only in CreateWindowEx() */
1483 int wParam = SIZE_RESTORED;
1485 wndPtr->flags &= ~WIN_NEED_SIZE;
1486 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1487 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1488 SendMessageA( hwnd, WM_SIZE, wParam,
1489 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1490 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1491 SendMessageA( hwnd, WM_MOVE, 0,
1492 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1495 END:
1496 WIN_ReleaseWndPtr(wndPtr);
1497 return wasVisible;
1501 /***********************************************************************
1502 * GetInternalWindowPos16 (USER.460)
1504 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1505 LPPOINT16 ptIcon )
1507 WINDOWPLACEMENT16 wndpl;
1508 if (GetWindowPlacement16( hwnd, &wndpl ))
1510 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1511 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1512 return wndpl.showCmd;
1514 return 0;
1518 /***********************************************************************
1519 * GetInternalWindowPos (USER32.245)
1521 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1522 LPPOINT ptIcon )
1524 WINDOWPLACEMENT wndpl;
1525 if (GetWindowPlacement( hwnd, &wndpl ))
1527 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1528 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1529 return wndpl.showCmd;
1531 return 0;
1534 /***********************************************************************
1535 * GetWindowPlacement16 (USER.370)
1537 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1539 WND *pWnd = WIN_FindWndPtr( hwnd );
1540 LPINTERNALPOS lpPos;
1542 if(!pWnd ) return FALSE;
1544 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1545 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1546 wndpl->length = sizeof(*wndpl);
1547 if( pWnd->dwStyle & WS_MINIMIZE )
1548 wndpl->showCmd = SW_SHOWMINIMIZED;
1549 else
1550 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1551 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1552 if( pWnd->flags & WIN_RESTORE_MAX )
1553 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1554 else
1555 wndpl->flags = 0;
1556 wndpl->ptMinPosition = lpPos->ptIconPos;
1557 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1558 wndpl->rcNormalPosition = lpPos->rectNormal;
1560 WIN_ReleaseWndPtr(pWnd);
1561 return TRUE;
1565 /***********************************************************************
1566 * GetWindowPlacement (USER32.307)
1568 * Win95:
1569 * Fails if wndpl->length of Win95 (!) apps is invalid.
1571 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1573 if( pwpl32 )
1575 WINDOWPLACEMENT16 wpl;
1576 wpl.length = sizeof(wpl);
1577 if( GetWindowPlacement16( hwnd, &wpl ) )
1579 pwpl32->length = sizeof(*pwpl32);
1580 pwpl32->flags = wpl.flags;
1581 pwpl32->showCmd = wpl.showCmd;
1582 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1583 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1584 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1585 return TRUE;
1588 return FALSE;
1592 /***********************************************************************
1593 * WINPOS_SetPlacement
1595 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1596 UINT flags )
1598 WND *pWnd = WIN_FindWndPtr( hwnd );
1599 if( pWnd )
1601 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1602 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1604 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1605 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1606 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1608 if( pWnd->dwStyle & WS_MINIMIZE )
1610 WINPOS_ShowIconTitle( pWnd, FALSE );
1611 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1612 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1613 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1615 else if( pWnd->dwStyle & WS_MAXIMIZE )
1617 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1618 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1619 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1621 else if( flags & PLACE_RECT )
1622 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1623 lpPos->rectNormal.right - lpPos->rectNormal.left,
1624 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1625 SWP_NOZORDER | SWP_NOACTIVATE );
1627 ShowWindow( hwnd, wndpl->showCmd );
1628 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1630 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1632 /* SDK: ...valid only the next time... */
1633 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1635 WIN_ReleaseWndPtr(pWnd);
1636 return TRUE;
1638 return FALSE;
1642 /***********************************************************************
1643 * SetWindowPlacement16 (USER.371)
1645 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1647 return WINPOS_SetPlacement( hwnd, wndpl,
1648 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1651 /***********************************************************************
1652 * SetWindowPlacement (USER32.519)
1654 * Win95:
1655 * Fails if wndpl->length of Win95 (!) apps is invalid.
1657 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1659 if( pwpl32 )
1661 WINDOWPLACEMENT16 wpl;
1663 wpl.length = sizeof(WINDOWPLACEMENT16);
1664 wpl.flags = pwpl32->flags;
1665 wpl.showCmd = pwpl32->showCmd;
1666 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1667 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1668 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1669 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1670 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1671 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1672 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1673 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1675 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1677 return FALSE;
1681 /***********************************************************************
1682 * SetInternalWindowPos16 (USER.461)
1684 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1685 LPRECT16 rect, LPPOINT16 pt )
1687 if( IsWindow16(hwnd) )
1689 WINDOWPLACEMENT16 wndpl;
1690 UINT flags;
1692 wndpl.length = sizeof(wndpl);
1693 wndpl.showCmd = showCmd;
1694 wndpl.flags = flags = 0;
1696 if( pt )
1698 flags |= PLACE_MIN;
1699 wndpl.flags |= WPF_SETMINPOSITION;
1700 wndpl.ptMinPosition = *pt;
1702 if( rect )
1704 flags |= PLACE_RECT;
1705 wndpl.rcNormalPosition = *rect;
1707 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1712 /***********************************************************************
1713 * SetInternalWindowPos (USER32.483)
1715 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1716 LPRECT rect, LPPOINT pt )
1718 if( IsWindow(hwnd) )
1720 WINDOWPLACEMENT16 wndpl;
1721 UINT flags;
1723 wndpl.length = sizeof(wndpl);
1724 wndpl.showCmd = showCmd;
1725 wndpl.flags = flags = 0;
1727 if( pt )
1729 flags |= PLACE_MIN;
1730 wndpl.flags |= WPF_SETMINPOSITION;
1731 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1733 if( rect )
1735 flags |= PLACE_RECT;
1736 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1738 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1742 /*******************************************************************
1743 * WINPOS_SetActiveWindow
1745 * SetActiveWindow() back-end. This is the only function that
1746 * can assign active status to a window. It must be called only
1747 * for the top level windows.
1749 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1751 CBTACTIVATESTRUCT16* cbtStruct;
1752 WND* wndPtr=0, *wndTemp;
1753 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1754 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1755 WORD wIconized = 0;
1756 HWND hwndActive = 0;
1757 BOOL bRet = 0;
1759 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1761 /* Get current active window from the active queue */
1762 if ( hActiveQueue )
1764 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1765 if ( pOldActiveQueue )
1766 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1769 /* paranoid checks */
1770 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1771 goto CLEANUP_END;
1773 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1774 * return 0;
1776 wndPtr = WIN_FindWndPtr(hWnd);
1777 hOldActiveQueue = hActiveQueue;
1779 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1781 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1782 WIN_ReleaseWndPtr(wndTemp);
1784 else
1785 TRACE("no current active window.\n");
1787 /* call CBT hook chain */
1788 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1790 cbtStruct->fMouse = fMouse;
1791 cbtStruct->hWndActive = hwndActive;
1792 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1793 (LPARAM)SEGPTR_GET(cbtStruct) );
1794 SEGPTR_FREE(cbtStruct);
1795 if (bRet) goto CLEANUP_END;
1798 /* set prev active wnd to current active wnd and send notification */
1799 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1801 MESSAGEQUEUE *pTempActiveQueue = 0;
1803 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1805 if (GetSysModalWindow16() != hWnd)
1806 goto CLEANUP_END;
1807 /* disregard refusal if hWnd is sysmodal */
1810 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1811 MAKEWPARAM( WA_INACTIVE, wIconized ),
1812 (LPARAM)hWnd );
1814 /* check if something happened during message processing
1815 * (global active queue may have changed)
1817 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1818 if(!pTempActiveQueue)
1819 goto CLEANUP_END;
1821 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1822 QUEUE_Unlock( pTempActiveQueue );
1823 if( hwndPrevActive != hwndActive )
1824 goto CLEANUP_END;
1827 /* Set new active window in the message queue */
1828 hwndActive = hWnd;
1829 if ( wndPtr )
1831 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1832 if ( pNewActiveQueue )
1833 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1835 else /* have to do this or MDI frame activation goes to hell */
1836 if( pOldActiveQueue )
1837 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1839 /* send palette messages */
1840 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1841 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1843 /* if prev wnd is minimized redraw icon title */
1844 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1846 /* managed windows will get ConfigureNotify event */
1847 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1849 /* check Z-order and bring hWnd to the top */
1850 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1852 if (wndTemp->dwStyle & WS_VISIBLE) break;
1854 WIN_ReleaseDesktop();
1855 WIN_ReleaseWndPtr(wndTemp);
1857 if( wndTemp != wndPtr )
1858 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1859 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1860 if (!IsWindow(hWnd))
1861 goto CLEANUP;
1864 /* Get a handle to the new active queue */
1865 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1867 /* send WM_ACTIVATEAPP if necessary */
1868 if (hOldActiveQueue != hNewActiveQueue)
1870 WND **list, **ppWnd;
1871 WND *pDesktop = WIN_GetDesktop();
1873 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1875 for (ppWnd = list; *ppWnd; ppWnd++)
1877 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1879 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1880 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1881 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1883 WIN_ReleaseWinArray(list);
1886 hActiveQueue = hNewActiveQueue;
1888 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1890 for (ppWnd = list; *ppWnd; ppWnd++)
1892 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1894 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1895 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1896 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1898 WIN_ReleaseWinArray(list);
1900 WIN_ReleaseDesktop();
1902 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1905 if (hWnd)
1907 /* walk up to the first unowned window */
1908 wndTemp = WIN_LockWndPtr(wndPtr);
1909 while (wndTemp->owner)
1911 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1913 /* and set last active owned popup */
1914 wndTemp->hwndLastActive = hWnd;
1916 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1917 WIN_ReleaseWndPtr(wndTemp);
1918 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1919 SendMessageA( hWnd, WM_ACTIVATE,
1920 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1921 (LPARAM)hwndPrevActive );
1922 if( !IsWindow(hWnd) ) goto CLEANUP;
1925 /* change focus if possible */
1926 if ( fChangeFocus )
1928 if ( pNewActiveQueue )
1930 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1932 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1933 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1934 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1935 0 : hwndActive );
1938 if ( pOldActiveQueue &&
1939 ( !pNewActiveQueue ||
1940 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1942 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1943 if ( hOldFocus )
1944 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1948 if( !hwndPrevActive && wndPtr )
1949 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1951 /* if active wnd is minimized redraw icon title */
1952 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1954 bRet = (hWnd == hwndActive); /* Success? */
1956 CLEANUP: /* Unlock the message queues before returning */
1958 if ( pNewActiveQueue )
1959 QUEUE_Unlock( pNewActiveQueue );
1961 CLEANUP_END:
1963 if ( pOldActiveQueue )
1964 QUEUE_Unlock( pOldActiveQueue );
1966 WIN_ReleaseWndPtr(wndPtr);
1967 return bRet;
1970 /*******************************************************************
1971 * WINPOS_ActivateOtherWindow
1973 * Activates window other than pWnd.
1975 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1977 BOOL bRet = 0;
1978 WND* pWndTo = NULL;
1979 HWND hwndActive = 0;
1981 /* Get current active window from the active queue */
1982 if ( hActiveQueue )
1984 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1985 if ( pActiveQueue )
1987 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1988 QUEUE_Unlock( pActiveQueue );
1992 if( pWnd->hwndSelf == hwndPrevActive )
1993 hwndPrevActive = 0;
1995 if( hwndActive != pWnd->hwndSelf &&
1996 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1997 return 0;
1999 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
2000 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
2002 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
2004 WIN_ReleaseWndPtr(pWndTo);
2005 pWndTo = WIN_FindWndPtr(hwndPrevActive);
2007 while( !WINPOS_CanActivate(pWndTo) )
2009 /* by now owned windows should've been taken care of */
2010 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
2011 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
2012 if( !pWndTo ) break;
2014 WIN_ReleaseWndPtr(pWndPtr);
2017 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
2019 /* switch desktop queue to current active */
2020 if( pWndTo )
2022 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
2023 WIN_ReleaseWndPtr(pWndTo);
2024 WIN_ReleaseDesktop();
2027 hwndPrevActive = 0;
2028 return bRet;
2031 /*******************************************************************
2032 * WINPOS_ChangeActiveWindow
2035 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2037 WND *wndPtr, *wndTemp;
2038 BOOL retvalue;
2039 HWND hwndActive = 0;
2041 /* Get current active window from the active queue */
2042 if ( hActiveQueue )
2044 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2045 if ( pActiveQueue )
2047 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2048 QUEUE_Unlock( pActiveQueue );
2052 if (!hWnd)
2053 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2055 wndPtr = WIN_FindWndPtr(hWnd);
2056 if( !wndPtr ) return FALSE;
2058 /* child windows get WM_CHILDACTIVATE message */
2059 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2061 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2062 goto end;
2065 if( hWnd == hwndActive )
2067 retvalue = FALSE;
2068 goto end;
2071 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2073 retvalue = FALSE;
2074 goto end;
2077 /* switch desktop queue to current active */
2078 wndTemp = WIN_GetDesktop();
2079 if( wndPtr->parent == wndTemp)
2080 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2081 WIN_ReleaseDesktop();
2083 retvalue = TRUE;
2084 end:
2085 WIN_ReleaseWndPtr(wndPtr);
2086 return retvalue;
2090 /***********************************************************************
2091 * WINPOS_SendNCCalcSize
2093 * Send a WM_NCCALCSIZE message to a window.
2094 * All parameters are read-only except newClientRect.
2095 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2096 * when calcValidRect is TRUE.
2098 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2099 RECT *newWindowRect, RECT *oldWindowRect,
2100 RECT *oldClientRect, WINDOWPOS *winpos,
2101 RECT *newClientRect )
2103 NCCALCSIZE_PARAMS params;
2104 WINDOWPOS winposCopy;
2105 LONG result;
2107 params.rgrc[0] = *newWindowRect;
2108 if (calcValidRect)
2110 winposCopy = *winpos;
2111 params.rgrc[1] = *oldWindowRect;
2112 params.rgrc[2] = *oldClientRect;
2113 params.lppos = &winposCopy;
2115 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2116 (LPARAM)&params );
2117 TRACE("%d,%d-%d,%d\n",
2118 params.rgrc[0].left, params.rgrc[0].top,
2119 params.rgrc[0].right, params.rgrc[0].bottom );
2121 /* If the application send back garbage, ignore it */
2122 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2123 *newClientRect = params.rgrc[0];
2125 return result;
2129 /***********************************************************************
2130 * WINPOS_HandleWindowPosChanging16
2132 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2134 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2136 POINT maxSize, minTrack;
2137 if (winpos->flags & SWP_NOSIZE) return 0;
2138 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2139 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2141 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2142 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2143 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2144 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2146 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2147 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2150 return 0;
2154 /***********************************************************************
2155 * WINPOS_HandleWindowPosChanging
2157 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2159 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2161 POINT maxSize, minTrack;
2162 if (winpos->flags & SWP_NOSIZE) return 0;
2163 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2164 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2166 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2167 winpos->cx = min( winpos->cx, maxSize.x );
2168 winpos->cy = min( winpos->cy, maxSize.y );
2169 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2171 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2172 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2175 return 0;
2178 /***********************************************************************
2179 * SWP_DoOwnedPopups
2181 * fix Z order taking into account owned popups -
2182 * basically we need to maintain them above the window that owns them
2184 * FIXME: hide/show owned popups when owner visibility changes.
2186 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2188 WND* w = WIN_LockWndPtr(pDesktop->child);
2190 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2192 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2194 /* make sure this popup stays above the owner */
2196 HWND hwndLocalPrev = HWND_TOP;
2198 if( hwndInsertAfter != HWND_TOP )
2200 while( w != wndPtr->owner )
2202 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2203 if( hwndLocalPrev == hwndInsertAfter ) break;
2204 WIN_UpdateWndPtr(&w,w->next);
2206 hwndInsertAfter = hwndLocalPrev;
2209 else if( wndPtr->dwStyle & WS_CHILD )
2210 goto END;
2212 WIN_UpdateWndPtr(&w, pDesktop->child);
2214 while( w )
2216 if( w == wndPtr ) break;
2218 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2220 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2221 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2222 hwndInsertAfter = w->hwndSelf;
2224 WIN_UpdateWndPtr(&w, w->next);
2227 END:
2228 WIN_ReleaseWndPtr(w);
2229 return hwndInsertAfter;
2232 /***********************************************************************
2233 * SWP_CopyValidBits
2235 * Make window look nice without excessive repainting
2237 * visible and update regions are in window coordinates
2238 * client and window rectangles are in parent client coordinates
2240 * Returns: uFlags and a dirty region in *pVisRgn.
2242 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2243 LPRECT lpOldWndRect,
2244 LPRECT lpOldClientRect, UINT uFlags )
2246 RECT r;
2247 HRGN newVisRgn, dirtyRgn;
2248 INT my = COMPLEXREGION;
2250 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2251 Wnd->rectWindow.left, Wnd->rectWindow.top,
2252 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2253 lpOldWndRect->left, lpOldWndRect->top,
2254 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2255 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2256 Wnd->rectClient.left, Wnd->rectClient.top,
2257 Wnd->rectClient.right, Wnd->rectClient.bottom,
2258 lpOldClientRect->left, lpOldClientRect->top,
2259 lpOldClientRect->right,lpOldClientRect->bottom );
2261 if( Wnd->hrgnUpdate == 1 )
2262 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2264 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2265 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2267 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2268 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2270 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2272 nocopy:
2274 TRACE("\twon't copy anything!\n");
2276 /* set dirtyRgn to the sum of old and new visible regions
2277 * in parent client coordinates */
2279 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2280 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2282 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2284 else /* copy valid bits to a new location */
2286 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2287 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2289 /* subtract already invalid region inside Wnd from the dst region */
2291 if( Wnd->hrgnUpdate )
2292 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2293 goto nocopy;
2295 /* check if entire window can be copied */
2297 ow = lpOldWndRect->right - lpOldWndRect->left;
2298 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2299 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2300 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2302 ocw = lpOldClientRect->right - lpOldClientRect->left;
2303 och = lpOldClientRect->bottom - lpOldClientRect->top;
2304 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2305 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2307 if( (ocw != ncw) || (och != nch) ||
2308 ( ow != nw) || ( oh != nh) ||
2309 ((lpOldClientRect->top - lpOldWndRect->top) !=
2310 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2311 ((lpOldClientRect->left - lpOldWndRect->left) !=
2312 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2314 if(uFlags & SWP_EX_PAINTSELF)
2316 /* movement relative to the window itself */
2317 dx = (Wnd->rectClient.left - Wnd->rectWindow.left) -
2318 (lpOldClientRect->left - lpOldWndRect->left) ;
2319 dy = (Wnd->rectClient.top - Wnd->rectWindow.top) -
2320 (lpOldClientRect->top - lpOldWndRect->top) ;
2322 else
2324 /* movement relative to the parent's client area */
2325 dx = Wnd->rectClient.left - lpOldClientRect->left;
2326 dy = Wnd->rectClient.top - lpOldClientRect->top;
2329 /* restrict valid bits to the common client rect */
2331 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2332 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2333 r.right = r.left + min( ocw, ncw );
2334 r.bottom = r.top + min( och, nch );
2336 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2337 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2338 GetRgnBox( hrgnValid, &r );
2339 if( IsRectEmpty( &r ) )
2340 goto nocopy;
2341 r = *lpOldClientRect;
2343 else
2345 if(uFlags & SWP_EX_PAINTSELF) {
2347 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2348 * relative to itself, only the client area can change.
2349 * if the client rect didn't change, there's nothing to do.
2351 dx = 0;
2352 dy = 0;
2354 else
2356 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2357 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2358 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2360 r = *lpOldWndRect;
2363 if( !(uFlags & SWP_EX_PAINTSELF) )
2365 /* Move remaining regions to parent coordinates */
2366 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2367 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2369 else
2370 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2372 TRACE("\tcomputing dirty region!\n");
2374 /* Compute combined dirty region (old + new - valid) */
2375 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2376 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2378 /* Blt valid bits, r is the rect to copy */
2380 if( dx || dy )
2382 RECT rClip;
2383 HDC hDC;
2385 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2386 from copying clipped areas */
2388 if( uFlags & SWP_EX_PAINTSELF )
2390 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2391 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2392 rClip.right = nw; rClip.bottom = nh;
2394 else
2396 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2397 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2398 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2399 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2401 rClip.left = rClip.top = 0;
2403 if( oh > nh ) r.bottom = r.top + nh;
2404 if( ow < nw ) r.right = r.left + nw;
2406 if( IntersectRect( &r, &r, &rClip ) )
2408 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2410 /* When you copy the bits without repainting, parent doesn't
2411 get validated appropriately. Therefore, we have to validate
2412 the parent with the windows' updated region when the
2413 parent's update region is not empty. */
2415 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2417 OffsetRect(&r, dx, dy);
2418 ValidateRect(Wnd->parent->hwndSelf, &r);
2421 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2422 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2426 /* *pVisRgn now points to the invalidated region */
2428 DeleteObject(newVisRgn);
2429 DeleteObject(dirtyRgn);
2430 return uFlags;
2433 /***********************************************************************
2434 * SWP_DoSimpleFrameChanged
2436 * NOTE: old and new client rect origins are identical, only
2437 * extents may have changed. Window extents are the same.
2439 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2441 INT i = 0;
2442 RECT rect;
2443 HRGN hrgn = 0;
2445 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2447 /* Client rect changed its position/size, most likely a scrollar
2448 * was added/removed.
2450 * FIXME: WVR alignment flags
2453 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2455 i++;
2456 rect.top = 0;
2457 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2458 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2459 if(!(uFlags & SWP_EX_NOCOPY))
2460 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2461 else
2463 rect.left = 0;
2464 goto redraw;
2468 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2470 if( i )
2471 hrgn = CreateRectRgnIndirect( &rect );
2472 rect.left = 0;
2473 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2474 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2475 if(!(uFlags & SWP_EX_NOCOPY))
2476 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2477 else
2478 rect.top = 0;
2479 if( i++ )
2480 REGION_UnionRectWithRgn( hrgn, &rect );
2483 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2485 rect = wndPtr->rectWindow;
2486 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2487 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2488 i++;
2492 if( i )
2494 redraw:
2495 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2496 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2498 else
2500 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2503 if( hrgn > 1 )
2504 DeleteObject( hrgn );
2507 /***********************************************************************
2508 * SWP_DoWinPosChanging
2510 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2511 RECT* pNewWindowRect, RECT* pNewClientRect )
2513 /* Send WM_WINDOWPOSCHANGING message */
2515 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2516 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2518 /* Calculate new position and size */
2520 *pNewWindowRect = wndPtr->rectWindow;
2521 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2522 : wndPtr->rectClient;
2524 if (!(pWinpos->flags & SWP_NOSIZE))
2526 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2527 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2529 if (!(pWinpos->flags & SWP_NOMOVE))
2531 pNewWindowRect->left = pWinpos->x;
2532 pNewWindowRect->top = pWinpos->y;
2533 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2534 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2536 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2537 pWinpos->y - wndPtr->rectWindow.top );
2540 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2541 return TRUE;
2544 /***********************************************************************
2545 * SWP_DoNCCalcSize
2547 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2548 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2550 UINT wvrFlags = 0;
2552 /* Send WM_NCCALCSIZE message to get new client area */
2553 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2555 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2556 &wndPtr->rectWindow, &wndPtr->rectClient,
2557 pWinpos, pNewClientRect );
2559 /* FIXME: WVR_ALIGNxxx */
2561 if( pNewClientRect->left != wndPtr->rectClient.left ||
2562 pNewClientRect->top != wndPtr->rectClient.top )
2563 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2565 if( (pNewClientRect->right - pNewClientRect->left !=
2566 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2567 (pNewClientRect->bottom - pNewClientRect->top !=
2568 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2569 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2571 else
2572 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2573 pNewClientRect->top != wndPtr->rectClient.top) )
2574 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2575 return wvrFlags;
2578 /***********************************************************************
2579 * SetWindowPos (USER.2)
2581 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2582 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2584 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2587 /***********************************************************************
2588 * SetWindowPos (USER32.520)
2590 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2591 INT x, INT y, INT cx, INT cy, UINT flags )
2593 WINDOWPOS winpos;
2594 WND * wndPtr,*wndTemp;
2595 RECT newWindowRect, newClientRect;
2596 RECT oldWindowRect, oldClientRect;
2597 HRGN visRgn = 0;
2598 UINT wvrFlags = 0, uFlags = 0;
2599 BOOL retvalue, resync = FALSE, bChangePos;
2600 HWND hwndActive = 0;
2602 /* Get current active window from the active queue */
2603 if ( hActiveQueue )
2605 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2606 if ( pActiveQueue )
2608 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2609 QUEUE_Unlock( pActiveQueue );
2613 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2614 hwnd, x, y, x+cx, y+cy, flags);
2616 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2617 flags &= ~SWP_WINE_NOHOSTMOVE;
2620 /* ------------------------------------------------------------------------ CHECKS */
2622 /* Check window handle */
2624 if (hwnd == GetDesktopWindow()) return FALSE;
2625 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2627 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2628 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2630 /* Fix redundant flags */
2632 if(wndPtr->dwStyle & WS_VISIBLE)
2633 flags &= ~SWP_SHOWWINDOW;
2634 else
2636 if (!(flags & SWP_SHOWWINDOW))
2637 flags |= SWP_NOREDRAW;
2638 flags &= ~SWP_HIDEWINDOW;
2641 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2643 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2644 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2645 flags |= SWP_NOSIZE; /* Already the right size */
2647 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2648 flags |= SWP_NOMOVE; /* Already the right position */
2650 if (hwnd == hwndActive)
2651 flags |= SWP_NOACTIVATE; /* Already active */
2652 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2654 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2656 flags &= ~SWP_NOZORDER;
2657 hwndInsertAfter = HWND_TOP;
2658 goto Pos;
2662 /* Check hwndInsertAfter */
2664 /* FIXME: TOPMOST not supported yet */
2665 if ((hwndInsertAfter == HWND_TOPMOST) ||
2666 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2668 /* hwndInsertAfter must be a sibling of the window */
2669 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2671 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2673 if( wnd ) {
2674 if( wnd->parent != wndPtr->parent )
2676 retvalue = FALSE;
2677 WIN_ReleaseWndPtr(wnd);
2678 goto END;
2680 /* don't need to change the Zorder of hwnd if it's already inserted
2681 * after hwndInsertAfter or when inserting hwnd after itself.
2683 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2685 WIN_ReleaseWndPtr(wnd);
2688 Pos: /* ------------------------------------------------------------------------ MAIN part */
2690 /* Fill the WINDOWPOS structure */
2692 winpos.hwnd = hwnd;
2693 winpos.hwndInsertAfter = hwndInsertAfter;
2694 winpos.x = x;
2695 winpos.y = y;
2696 winpos.cx = cx;
2697 winpos.cy = cy;
2698 winpos.flags = flags;
2700 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2702 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2704 if( wndPtr->parent == WIN_GetDesktop() )
2705 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2706 hwndInsertAfter, winpos.flags );
2707 WIN_ReleaseDesktop();
2710 if(!(wndPtr->flags & WIN_NATIVE) )
2712 if( hwndInsertAfter == HWND_TOP )
2713 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2714 else
2715 if( hwndInsertAfter == HWND_BOTTOM )
2716 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2717 else
2718 if( !(winpos.flags & SWP_NOZORDER) )
2719 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2720 winpos.flags |= SWP_NOZORDER;
2722 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2723 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2724 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2726 /* get a previous visible region for SWP_CopyValidBits() */
2727 DWORD dflags = DCX_WINDOW;
2729 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2730 dflags |= DCX_CLIPSIBLINGS;
2732 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2736 /* Common operations */
2738 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2740 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2742 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2743 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2746 /* Reset active DCEs */
2748 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2749 wndPtr->dwStyle & WS_VISIBLE) ||
2750 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2752 RECT rect;
2754 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2755 DCE_InvalidateDCE(wndPtr, &rect);
2758 oldWindowRect = wndPtr->rectWindow;
2759 oldClientRect = wndPtr->rectClient;
2761 /* Find out if we have to redraw the whole client rect */
2763 if( oldClientRect.bottom - oldClientRect.top ==
2764 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2766 if( oldClientRect.right - oldClientRect.left ==
2767 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2769 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2770 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2772 uFlags |= SWP_EX_NOCOPY;
2775 * Use this later in CopyValidBits()
2777 else if( 0 )
2778 uFlags |= SWP_EX_NONCLIENT;
2781 /* FIXME: actually do something with WVR_VALIDRECTS */
2783 wndPtr->rectWindow = newWindowRect;
2784 wndPtr->rectClient = newClientRect;
2786 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2788 BOOL bCallDriver = TRUE;
2789 HWND tempInsertAfter = winpos.hwndInsertAfter;
2791 winpos.hwndInsertAfter = hwndInsertAfter;
2793 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2795 /* This is the only place where we need to force repainting of the contents
2796 of windows created by the host window system, all other cases go through the
2797 expose event handling */
2799 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2801 cx = newWindowRect.right - newWindowRect.left;
2802 cy = newWindowRect.bottom - newWindowRect.top;
2804 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2805 winpos.hwndInsertAfter = tempInsertAfter;
2806 bCallDriver = FALSE;
2808 if( winpos.flags & SWP_NOCLIENTMOVE )
2809 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2810 else
2812 /* client area moved but window extents remained the same, copy valid bits */
2814 visRgn = CreateRectRgn( 0, 0, cx, cy );
2815 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2816 uFlags | SWP_EX_PAINTSELF );
2821 if( bCallDriver )
2823 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2825 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2826 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2827 !(uFlags & SWP_EX_NOCOPY) )
2829 /* The origin of the client rect didn't move so we can try to repaint
2830 * only the nonclient area by setting bit gravity hint for the host window system.
2833 if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
2835 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2836 newWindowRect.bottom - newWindowRect.top);
2837 RECT rcn = newClientRect;
2838 RECT rco = oldClientRect;
2840 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2841 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2842 IntersectRect( &rcn, &rcn, &rco );
2843 visRgn = CreateRectRgnIndirect( &rcn );
2844 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2845 DeleteObject( hrgn );
2846 uFlags = SWP_EX_PAINTSELF;
2848 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2850 else
2851 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2854 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2855 winpos.hwndInsertAfter = tempInsertAfter;
2858 if( winpos.flags & SWP_SHOWWINDOW )
2860 HWND focus, curr;
2862 wndPtr->dwStyle |= WS_VISIBLE;
2864 if (wndPtr->dwExStyle & WS_EX_MANAGED) resync = TRUE;
2866 /* focus was set to unmapped window, reset host focus
2867 * since the window is now visible */
2869 focus = curr = GetFocus();
2870 while (curr)
2872 if (curr == hwnd)
2874 WND *pFocus = WIN_FindWndPtr( focus );
2875 if (pFocus)
2876 pFocus->pDriver->pSetFocus(pFocus);
2877 WIN_ReleaseWndPtr(pFocus);
2878 break;
2880 curr = GetParent(curr);
2884 else /* -------------------------------------------- emulated window */
2886 if( winpos.flags & SWP_SHOWWINDOW )
2888 wndPtr->dwStyle |= WS_VISIBLE;
2889 uFlags |= SWP_EX_PAINTSELF;
2890 visRgn = 1; /* redraw the whole window */
2892 else if( !(winpos.flags & SWP_NOREDRAW) )
2894 if( winpos.flags & SWP_HIDEWINDOW )
2896 if( visRgn > 1 ) /* map to parent */
2897 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2898 else
2899 visRgn = 0;
2901 else
2903 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2905 /* if window was not resized and not moved try to repaint itself */
2906 if((winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) == SWP_AGG_NOGEOMETRYCHANGE)
2907 uFlags |= SWP_EX_PAINTSELF;
2908 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2909 &oldClientRect, uFlags);
2911 else
2913 /* nothing moved, redraw frame if needed */
2915 if( winpos.flags & SWP_FRAMECHANGED )
2916 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2917 if( visRgn )
2919 DeleteObject( visRgn );
2920 visRgn = 0;
2927 if( winpos.flags & SWP_HIDEWINDOW )
2929 wndPtr->dwStyle &= ~WS_VISIBLE;
2932 if (hwnd == CARET_GetHwnd())
2934 if( winpos.flags & SWP_HIDEWINDOW )
2935 HideCaret(hwnd);
2936 else if (winpos.flags & SWP_SHOWWINDOW)
2937 ShowCaret(hwnd);
2940 /* ------------------------------------------------------------------------ FINAL */
2942 if (wndPtr->flags & WIN_NATIVE)
2943 EVENT_Synchronize(); /* Synchronize with the host window system */
2945 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2947 /* Simulate a mouse event to set the cursor */
2948 int iWndsLocks = WIN_SuspendWndsLock();
2949 mouse_event( MOUSEEVENTF_MOVE, 0, 0, 0, 0 );
2950 WIN_RestoreWndsLock(iWndsLocks);
2953 wndTemp = WIN_GetDesktop();
2955 /* repaint invalidated region (if any)
2957 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2958 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2961 if( visRgn )
2963 if( !(winpos.flags & SWP_NOREDRAW) )
2966 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2967 its parent and sibling and so on, and then erase the parent window
2968 back ground if the parent is either a top-level window or its parent's parent
2969 is top-level window. Rely on the system to repaint other affected
2970 windows later on. */
2971 if( uFlags & SWP_EX_PAINTSELF )
2973 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2974 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2975 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2977 else
2979 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2980 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2981 RDW_EX_USEHRGN );
2984 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2986 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2987 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2990 if( visRgn != 1 )
2991 DeleteObject( visRgn );
2994 WIN_ReleaseDesktop();
2996 if (!(flags & SWP_NOACTIVATE))
2997 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2999 /* And last, send the WM_WINDOWPOSCHANGED message */
3001 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
3003 if ( resync ||
3004 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
3005 !(winpos.flags & SWP_NOSENDCHANGING)) )
3007 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
3008 if (resync) EVENT_Synchronize();
3011 retvalue = TRUE;
3012 END:
3013 WIN_ReleaseWndPtr(wndPtr);
3014 return retvalue;
3018 /***********************************************************************
3019 * BeginDeferWindowPos16 (USER.259)
3021 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
3023 return BeginDeferWindowPos( count );
3027 /***********************************************************************
3028 * BeginDeferWindowPos (USER32.9)
3030 HDWP WINAPI BeginDeferWindowPos( INT count )
3032 HDWP handle;
3033 DWP *pDWP;
3035 if (count < 0)
3037 SetLastError(ERROR_INVALID_PARAMETER);
3038 return 0;
3040 /* Windows allows zero count, in which case it allocates context for 8 moves */
3041 if (count == 0) count = 8;
3043 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
3044 if (!handle) return 0;
3045 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
3046 pDWP->actualCount = 0;
3047 pDWP->suggestedCount = count;
3048 pDWP->valid = TRUE;
3049 pDWP->wMagic = DWP_MAGIC;
3050 pDWP->hwndParent = 0;
3051 return handle;
3055 /***********************************************************************
3056 * DeferWindowPos16 (USER.260)
3058 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
3059 INT16 x, INT16 y, INT16 cx, INT16 cy,
3060 UINT16 flags )
3062 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3063 x, y, cx, cy, flags );
3067 /***********************************************************************
3068 * DeferWindowPos (USER32.128)
3070 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3071 INT x, INT y, INT cx, INT cy,
3072 UINT flags )
3074 DWP *pDWP;
3075 int i;
3076 HDWP newhdwp = hdwp,retvalue;
3077 /* HWND parent; */
3078 WND *pWnd;
3080 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3081 if (!pDWP) return 0;
3082 if (hwnd == GetDesktopWindow()) return 0;
3084 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3085 USER_HEAP_FREE( hdwp );
3086 return 0;
3089 /* Numega Bounds Checker Demo dislikes the following code.
3090 In fact, I've not been able to find any "same parent" requirement in any docu
3091 [AM 980509]
3093 #if 0
3094 /* All the windows of a DeferWindowPos() must have the same parent */
3095 parent = pWnd->parent->hwndSelf;
3096 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3097 else if (parent != pDWP->hwndParent)
3099 USER_HEAP_FREE( hdwp );
3100 retvalue = 0;
3101 goto END;
3103 #endif
3105 for (i = 0; i < pDWP->actualCount; i++)
3107 if (pDWP->winPos[i].hwnd == hwnd)
3109 /* Merge with the other changes */
3110 if (!(flags & SWP_NOZORDER))
3112 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3114 if (!(flags & SWP_NOMOVE))
3116 pDWP->winPos[i].x = x;
3117 pDWP->winPos[i].y = y;
3119 if (!(flags & SWP_NOSIZE))
3121 pDWP->winPos[i].cx = cx;
3122 pDWP->winPos[i].cy = cy;
3124 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3125 SWP_NOZORDER | SWP_NOREDRAW |
3126 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3127 SWP_NOOWNERZORDER);
3128 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3129 SWP_FRAMECHANGED);
3130 retvalue = hdwp;
3131 goto END;
3134 if (pDWP->actualCount >= pDWP->suggestedCount)
3136 newhdwp = USER_HEAP_REALLOC( hdwp,
3137 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3138 if (!newhdwp)
3140 retvalue = 0;
3141 goto END;
3143 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3144 pDWP->suggestedCount++;
3146 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3147 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3148 pDWP->winPos[pDWP->actualCount].x = x;
3149 pDWP->winPos[pDWP->actualCount].y = y;
3150 pDWP->winPos[pDWP->actualCount].cx = cx;
3151 pDWP->winPos[pDWP->actualCount].cy = cy;
3152 pDWP->winPos[pDWP->actualCount].flags = flags;
3153 pDWP->actualCount++;
3154 retvalue = newhdwp;
3155 END:
3156 WIN_ReleaseWndPtr(pWnd);
3157 return retvalue;
3161 /***********************************************************************
3162 * EndDeferWindowPos16 (USER.261)
3164 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3166 return EndDeferWindowPos( hdwp );
3170 /***********************************************************************
3171 * EndDeferWindowPos (USER32.173)
3173 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3175 DWP *pDWP;
3176 WINDOWPOS *winpos;
3177 BOOL res = TRUE;
3178 int i;
3180 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3181 if (!pDWP) return FALSE;
3182 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3184 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3185 winpos->x, winpos->y, winpos->cx,
3186 winpos->cy, winpos->flags ))) break;
3188 USER_HEAP_FREE( hdwp );
3189 return res;
3193 /***********************************************************************
3194 * TileChildWindows (USER.199)
3196 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3198 FIXME("(%04x, %d): stub\n", parent, action);
3201 /***********************************************************************
3202 * CascadeChildWindows (USER.198)
3204 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3206 FIXME("(%04x, %d): stub\n", parent, action);
3209 /***********************************************************************
3210 * SetProgmanWindow [USER32.522]
3212 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3214 hGlobalProgmanWindow = hwnd;
3215 return hGlobalProgmanWindow;
3218 /***********************************************************************
3219 * GetProgmanWindow [USER32.289]
3221 HRESULT WINAPI GetProgmanWindow ( )
3223 return hGlobalProgmanWindow;
3226 /***********************************************************************
3227 * SetShellWindowEx [USER32.531]
3228 * hwndProgman = Progman[Program Manager]
3229 * |-> SHELLDLL_DefView
3230 * hwndListView = | |-> SysListView32
3231 * | | |-> tooltips_class32
3232 * | |
3233 * | |-> SysHeader32
3234 * |
3235 * |-> ProxyTarget
3237 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3239 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3240 hGlobalShellWindow = hwndProgman;
3241 return hGlobalShellWindow;
3245 /***********************************************************************
3246 * SetTaskmanWindow [USER32.537]
3247 * NOTES
3248 * hwnd = MSTaskSwWClass
3249 * |-> SysTabControl32
3251 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3253 hGlobalTaskmanWindow = hwnd;
3254 return hGlobalTaskmanWindow;
3257 /***********************************************************************
3258 * GetTaskmanWindow [USER32.304]
3260 HRESULT WINAPI GetTaskmanWindow ( )
3262 return hGlobalTaskmanWindow;