Removed SUBDIRS in winmm Makefile.
[wine/multimedia.git] / windows / winpos.c
blob109b73eefd4123d219adbf75a1a9e5c230efb76f
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 "heap.h"
15 #include "module.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 "local.h"
29 #include "ldt.h"
30 #include "input.h"
32 DEFAULT_DEBUG_CHANNEL(win)
34 #define HAS_DLGFRAME(style,exStyle) \
35 (((exStyle) & WS_EX_DLGMODALFRAME) || \
36 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
38 #define HAS_THICKFRAME(style) \
39 (((style) & WS_THICKFRAME) && \
40 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
42 #define SWP_AGG_NOGEOMETRYCHANGE \
43 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
44 #define SWP_AGG_NOPOSCHANGE \
45 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
46 #define SWP_AGG_STATUSFLAGS \
47 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
49 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
51 #define PLACE_MIN 0x0001
52 #define PLACE_MAX 0x0002
53 #define PLACE_RECT 0x0004
55 #define SWP_EX_NOCOPY 0x0001
56 #define SWP_EX_PAINTSELF 0x0002
57 #define SWP_EX_NONCLIENT 0x0004
59 #define MINMAX_NOSWP 0x00010000
61 /* ----- internal variables ----- */
63 static HWND hwndPrevActive = 0; /* Previously active window */
64 static HWND hGlobalShellWindow=0; /*the shell*/
65 static HWND hGlobalTaskmanWindow=0;
66 static HWND hGlobalProgmanWindow=0;
68 static LPCSTR atomInternalPos;
70 extern HQUEUE16 hActiveQueue;
72 /***********************************************************************
73 * WINPOS_CreateInternalPosAtom
75 BOOL WINPOS_CreateInternalPosAtom()
77 LPSTR str = "SysIP";
78 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
79 return (atomInternalPos) ? TRUE : FALSE;
82 /***********************************************************************
83 * WINPOS_CheckInternalPos
85 * Called when a window is destroyed.
87 void WINPOS_CheckInternalPos( WND* wndPtr )
89 LPINTERNALPOS lpPos;
90 MESSAGEQUEUE *pMsgQ = 0;
91 HWND hwnd = wndPtr->hwndSelf;
93 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
95 /* Retrieve the message queue associated with this window */
96 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
97 if ( !pMsgQ )
99 WARN("\tMessage queue not found. Exiting!\n" );
100 return;
103 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
105 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
107 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
108 WARN("\tattempt to activate destroyed window!\n");
111 if( lpPos )
113 if( IsWindow(lpPos->hwndIconTitle) )
114 DestroyWindow( lpPos->hwndIconTitle );
115 HeapFree( SystemHeap, 0, lpPos );
118 QUEUE_Unlock( pMsgQ );
119 return;
122 /***********************************************************************
123 * WINPOS_FindIconPos
125 * Find a suitable place for an iconic window.
127 static POINT16 WINPOS_FindIconPos( WND* wndPtr, POINT16 pt )
129 RECT16 rectParent;
130 short x, y, xspacing, yspacing;
132 GetClientRect16( wndPtr->parent->hwndSelf, &rectParent );
133 if ((pt.x >= rectParent.left) && (pt.x + GetSystemMetrics(SM_CXICON) < rectParent.right) &&
134 (pt.y >= rectParent.top) && (pt.y + GetSystemMetrics(SM_CYICON) < rectParent.bottom))
135 return pt; /* The icon already has a suitable position */
137 xspacing = GetSystemMetrics(SM_CXICONSPACING);
138 yspacing = GetSystemMetrics(SM_CYICONSPACING);
140 y = rectParent.bottom;
141 for (;;)
143 x = rectParent.left;
146 /* Check if another icon already occupies this spot */
147 WND *childPtr = WIN_LockWndPtr(wndPtr->parent->child);
148 while (childPtr)
150 if ((childPtr->dwStyle & WS_MINIMIZE) && (childPtr != wndPtr))
152 if ((childPtr->rectWindow.left < x + xspacing) &&
153 (childPtr->rectWindow.right >= x) &&
154 (childPtr->rectWindow.top <= y) &&
155 (childPtr->rectWindow.bottom > y - yspacing))
156 break; /* There's a window in there */
158 WIN_UpdateWndPtr(&childPtr,childPtr->next);
160 WIN_ReleaseWndPtr(childPtr);
161 if (!childPtr) /* No window was found, so it's OK for us */
163 pt.x = x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2;
164 pt.y = y - (yspacing + GetSystemMetrics(SM_CYICON)) / 2;
165 return pt;
167 x += xspacing;
168 } while(x <= rectParent.right-xspacing);
169 y -= yspacing;
174 /***********************************************************************
175 * ArrangeIconicWindows16 (USER.170)
177 UINT16 WINAPI ArrangeIconicWindows16( HWND16 parent)
179 return ArrangeIconicWindows(parent);
181 /***********************************************************************
182 * ArrangeIconicWindows (USER32.7)
184 UINT WINAPI ArrangeIconicWindows( HWND parent )
186 RECT rectParent;
187 HWND hwndChild;
188 INT x, y, xspacing, yspacing;
190 GetClientRect( parent, &rectParent );
191 x = rectParent.left;
192 y = rectParent.bottom;
193 xspacing = GetSystemMetrics(SM_CXICONSPACING);
194 yspacing = GetSystemMetrics(SM_CYICONSPACING);
196 hwndChild = GetWindow( parent, GW_CHILD );
197 while (hwndChild)
199 if( IsIconic( hwndChild ) )
201 WND *wndPtr = WIN_FindWndPtr(hwndChild);
203 WINPOS_ShowIconTitle( wndPtr, FALSE );
205 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
206 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
207 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
208 if( IsWindow(hwndChild) )
209 WINPOS_ShowIconTitle(wndPtr , TRUE );
210 WIN_ReleaseWndPtr(wndPtr);
212 if (x <= rectParent.right - xspacing) x += xspacing;
213 else
215 x = rectParent.left;
216 y -= yspacing;
219 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
221 return yspacing;
225 /***********************************************************************
226 * SwitchToThisWindow16 (USER.172)
228 void WINAPI SwitchToThisWindow16( HWND16 hwnd, BOOL16 restore )
230 SwitchToThisWindow( hwnd, restore );
234 /***********************************************************************
235 * SwitchToThisWindow (USER32.539)
237 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
239 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
243 /***********************************************************************
244 * GetWindowRect16 (USER.32)
246 void WINAPI GetWindowRect16( HWND16 hwnd, LPRECT16 rect )
248 WND * wndPtr = WIN_FindWndPtr( hwnd );
249 if (!wndPtr) return;
251 CONV_RECT32TO16( &wndPtr->rectWindow, rect );
252 if (wndPtr->dwStyle & WS_CHILD)
253 MapWindowPoints16( wndPtr->parent->hwndSelf, 0, (POINT16 *)rect, 2 );
254 WIN_ReleaseWndPtr(wndPtr);
258 /***********************************************************************
259 * GetWindowRect (USER32.308)
261 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
263 WND * wndPtr = WIN_FindWndPtr( hwnd );
264 if (!wndPtr) return FALSE;
266 *rect = wndPtr->rectWindow;
267 if (wndPtr->dwStyle & WS_CHILD)
268 MapWindowPoints( wndPtr->parent->hwndSelf, 0, (POINT *)rect, 2 );
269 WIN_ReleaseWndPtr(wndPtr);
270 return TRUE;
274 /***********************************************************************
275 * GetWindowRgn (USER32)
277 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
279 int nRet = ERROR;
280 WND *wndPtr = WIN_FindWndPtr( hwnd );
281 if (wndPtr)
283 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
284 WIN_ReleaseWndPtr(wndPtr);
286 return nRet;
289 /***********************************************************************
290 * SetWindowRgn (USER32)
292 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
294 int ret = FALSE;
295 RECT tempRect;
297 WND *wndPtr = WIN_FindWndPtr(hwnd);
299 if (!wndPtr) return FALSE;
301 /* a region exists for this window */
302 if (hrgn != 0 && hrgn == wndPtr->hrgnWnd)
304 /* can't replace actual region with same region
305 since we're now owner of that region
307 SetLastError(ERROR_INVALID_HANDLE);
308 goto done;
312 /* we'd like to set it back to 0 */
313 if (hrgn == 0)
315 GetWindowRect(hwnd, &tempRect);
317 else
319 /* verify that region really exists */
320 if (GetRgnBox(hrgn, &tempRect) == ERROR) goto done;
324 /* Size the window to the rectangle of the new region
325 (if it isn't NULL) */
326 SetWindowPos( hwnd, NULL, tempRect.left, tempRect.top,
327 tempRect.right - tempRect.left, tempRect.bottom - tempRect.top,
328 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE |
329 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
332 if (wndPtr->hrgnWnd)
334 /* delete previous region */
335 DeleteObject(wndPtr->hrgnWnd);
336 wndPtr->hrgnWnd = 0;
338 else if (hrgn == NULL)
340 /* if there was no previous region (stored in wndPtr->hrgnWnd) and
341 the region to be set is also NULL, there is nothing more to do
343 ret = TRUE;
344 goto done;
347 /* valid region handle */
348 wndPtr->hrgnWnd = hrgn;
349 wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn);
351 ret = TRUE;
353 done:
354 WIN_ReleaseWndPtr(wndPtr);
355 return ret;
358 /***********************************************************************
359 * SetWindowRgn16
361 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
365 FIXME("SetWindowRgn16: stub\n");
366 return TRUE;
370 /***********************************************************************
371 * GetClientRect16 (USER.33)
373 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
375 WND * wndPtr = WIN_FindWndPtr( hwnd );
377 rect->left = rect->top = rect->right = rect->bottom = 0;
378 if (wndPtr)
380 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
381 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
383 WIN_ReleaseWndPtr(wndPtr);
387 /***********************************************************************
388 * GetClientRect (USER.220)
390 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
392 WND * wndPtr = WIN_FindWndPtr( hwnd );
394 rect->left = rect->top = rect->right = rect->bottom = 0;
395 if (!wndPtr) return FALSE;
396 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
397 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
399 WIN_ReleaseWndPtr(wndPtr);
400 return TRUE;
404 /*******************************************************************
405 * ClientToScreen16 (USER.28)
407 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
409 MapWindowPoints16( hwnd, 0, lppnt, 1 );
413 /*******************************************************************
414 * ClientToScreen (USER32.52)
416 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
418 MapWindowPoints( hwnd, 0, lppnt, 1 );
419 return TRUE;
423 /*******************************************************************
424 * ScreenToClient16 (USER.29)
426 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
428 MapWindowPoints16( 0, hwnd, lppnt, 1 );
432 /*******************************************************************
433 * ScreenToClient (USER32.447)
435 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
437 MapWindowPoints( 0, hwnd, lppnt, 1 );
438 return TRUE;
442 /***********************************************************************
443 * WINPOS_WindowFromPoint
445 * Find the window and hittest for a given point.
447 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
449 WND *wndPtr;
450 INT16 hittest = HTERROR;
451 INT16 retvalue;
452 POINT16 xy = pt;
454 TRACE("scope %04x %d,%d\n", wndScope->hwndSelf, pt.x, pt.y);
455 *ppWnd = NULL;
456 wndPtr = WIN_LockWndPtr(wndScope->child);
458 if( wndScope->dwStyle & WS_DISABLED )
460 retvalue = HTERROR;
461 goto end;
464 if( wndScope->dwExStyle & WS_EX_MANAGED)
466 /* In managed mode we have to check wndScope first as it is also
467 * a window which received the mouse event. */
469 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
470 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
471 goto hittest;
473 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
475 for (;;)
477 while (wndPtr)
479 /* If point is in window, and window is visible, and it */
480 /* is enabled (or it's a top-level window), then explore */
481 /* its children. Otherwise, go to the next window. */
483 if ((wndPtr->dwStyle & WS_VISIBLE) &&
484 (!(wndPtr->dwStyle & WS_DISABLED) ||
485 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
486 (wndPtr->hrgnWnd ?
487 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
488 xy.y - wndPtr->rectWindow.top) :
489 ((xy.x >= wndPtr->rectWindow.left) &&
490 (xy.x < wndPtr->rectWindow.right) &&
491 (xy.y >= wndPtr->rectWindow.top) &&
492 (xy.y < wndPtr->rectWindow.bottom))))
494 TRACE("%d,%d is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
495 *ppWnd = wndPtr; /* Got a suitable window */
497 /* If window is minimized or disabled, return at once */
498 if (wndPtr->dwStyle & WS_MINIMIZE)
500 retvalue = HTCAPTION;
501 goto end;
503 if (wndPtr->dwStyle & WS_DISABLED)
505 retvalue = HTERROR;
506 goto end;
509 /* If point is not in client area, ignore the children */
510 if ((xy.x < wndPtr->rectClient.left) ||
511 (xy.x >= wndPtr->rectClient.right) ||
512 (xy.y < wndPtr->rectClient.top) ||
513 (xy.y >= wndPtr->rectClient.bottom)) break;
515 xy.x -= wndPtr->rectClient.left;
516 xy.y -= wndPtr->rectClient.top;
517 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
519 else
521 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
525 hittest:
526 /* If nothing found, try the scope window */
527 if (!*ppWnd) *ppWnd = wndScope;
529 /* Send the WM_NCHITTEST message (only if to the same task) */
530 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
532 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
533 0, MAKELONG( pt.x, pt.y ) );
534 if (hittest != HTTRANSPARENT)
536 retvalue = hittest; /* Found the window */
537 goto end;
540 else
542 retvalue = HTCLIENT;
543 goto end;
546 /* If no children found in last search, make point relative to parent */
547 if (!wndPtr)
549 xy.x += (*ppWnd)->rectClient.left;
550 xy.y += (*ppWnd)->rectClient.top;
553 /* Restart the search from the next sibling */
554 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
555 *ppWnd = (*ppWnd)->parent;
558 end:
559 WIN_ReleaseWndPtr(wndPtr);
560 return retvalue;
564 /*******************************************************************
565 * WindowFromPoint16 (USER.30)
567 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
569 WND *pWnd;
570 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
571 WIN_ReleaseDesktop();
572 return pWnd->hwndSelf;
576 /*******************************************************************
577 * WindowFromPoint (USER32.582)
579 HWND WINAPI WindowFromPoint( POINT pt )
581 WND *pWnd;
582 POINT16 pt16;
583 CONV_POINT32TO16( &pt, &pt16 );
584 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
585 WIN_ReleaseDesktop();
586 return (HWND)pWnd->hwndSelf;
590 /*******************************************************************
591 * ChildWindowFromPoint16 (USER.191)
593 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
595 POINT pt32;
596 CONV_POINT16TO32( &pt, &pt32 );
597 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
601 /*******************************************************************
602 * ChildWindowFromPoint (USER32.49)
604 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
606 /* pt is in the client coordinates */
608 WND* wnd = WIN_FindWndPtr(hwndParent);
609 RECT rect;
610 HWND retvalue;
612 if( !wnd ) return 0;
614 /* get client rect fast */
615 rect.top = rect.left = 0;
616 rect.right = wnd->rectClient.right - wnd->rectClient.left;
617 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
619 if (!PtInRect( &rect, pt ))
621 retvalue = 0;
622 goto end;
624 WIN_UpdateWndPtr(&wnd,wnd->child);
625 while ( wnd )
627 if (PtInRect( &wnd->rectWindow, pt ))
629 retvalue = wnd->hwndSelf;
630 goto end;
632 WIN_UpdateWndPtr(&wnd,wnd->next);
634 retvalue = hwndParent;
635 end:
636 WIN_ReleaseWndPtr(wnd);
637 return retvalue;
640 /*******************************************************************
641 * ChildWindowFromPointEx16 (USER.50)
643 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
645 POINT pt32;
646 CONV_POINT16TO32( &pt, &pt32 );
647 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
651 /*******************************************************************
652 * ChildWindowFromPointEx (USER32.50)
654 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
655 UINT uFlags)
657 /* pt is in the client coordinates */
659 WND* wnd = WIN_FindWndPtr(hwndParent);
660 RECT rect;
661 HWND retvalue;
663 if( !wnd ) return 0;
665 /* get client rect fast */
666 rect.top = rect.left = 0;
667 rect.right = wnd->rectClient.right - wnd->rectClient.left;
668 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
670 if (!PtInRect( &rect, pt ))
672 retvalue = 0;
673 goto end;
675 WIN_UpdateWndPtr(&wnd,wnd->child);
677 while ( wnd )
679 if (PtInRect( &wnd->rectWindow, pt )) {
680 if ( (uFlags & CWP_SKIPINVISIBLE) &&
681 !(wnd->dwStyle & WS_VISIBLE) );
682 else if ( (uFlags & CWP_SKIPDISABLED) &&
683 (wnd->dwStyle & WS_DISABLED) );
684 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
685 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
686 else
688 retvalue = wnd->hwndSelf;
689 goto end;
693 WIN_UpdateWndPtr(&wnd,wnd->next);
695 retvalue = hwndParent;
696 end:
697 WIN_ReleaseWndPtr(wnd);
698 return retvalue;
702 /*******************************************************************
703 * WINPOS_GetWinOffset
705 * Calculate the offset between the origin of the two windows. Used
706 * to implement MapWindowPoints.
708 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
709 POINT *offset )
711 WND * wndPtr = 0;
713 offset->x = offset->y = 0;
714 if (hwndFrom == hwndTo ) return;
716 /* Translate source window origin to screen coords */
717 if (hwndFrom)
719 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
721 ERR("bad hwndFrom = %04x\n",hwndFrom);
722 return;
724 while (wndPtr->parent)
726 offset->x += wndPtr->rectClient.left;
727 offset->y += wndPtr->rectClient.top;
728 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
730 WIN_ReleaseWndPtr(wndPtr);
733 /* Translate origin to destination window coords */
734 if (hwndTo)
736 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
738 ERR("bad hwndTo = %04x\n", hwndTo );
739 return;
741 while (wndPtr->parent)
743 offset->x -= wndPtr->rectClient.left;
744 offset->y -= wndPtr->rectClient.top;
745 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
747 WIN_ReleaseWndPtr(wndPtr);
752 /*******************************************************************
753 * MapWindowPoints16 (USER.258)
755 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
756 LPPOINT16 lppt, UINT16 count )
758 POINT offset;
760 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
761 while (count--)
763 lppt->x += offset.x;
764 lppt->y += offset.y;
765 lppt++;
770 /*******************************************************************
771 * MapWindowPoints (USER32.386)
773 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
774 LPPOINT lppt, UINT count )
776 POINT offset;
778 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
779 while (count--)
781 lppt->x += offset.x;
782 lppt->y += offset.y;
783 lppt++;
785 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
789 /***********************************************************************
790 * IsIconic16 (USER.31)
792 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
794 return IsIconic(hWnd);
798 /***********************************************************************
799 * IsIconic (USER32.345)
801 BOOL WINAPI IsIconic(HWND hWnd)
803 BOOL retvalue;
804 WND * wndPtr = WIN_FindWndPtr(hWnd);
805 if (wndPtr == NULL) return FALSE;
806 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
807 WIN_ReleaseWndPtr(wndPtr);
808 return retvalue;
812 /***********************************************************************
813 * IsZoomed (USER.272)
815 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
817 return IsZoomed(hWnd);
821 /***********************************************************************
822 * IsZoomed (USER.352)
824 BOOL WINAPI IsZoomed(HWND hWnd)
826 BOOL retvalue;
827 WND * wndPtr = WIN_FindWndPtr(hWnd);
828 if (wndPtr == NULL) return FALSE;
829 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
830 WIN_ReleaseWndPtr(wndPtr);
831 return retvalue;
835 /*******************************************************************
836 * GetActiveWindow (USER.60)
838 HWND16 WINAPI GetActiveWindow16(void)
840 return (HWND16)GetActiveWindow();
843 /*******************************************************************
844 * GetActiveWindow (USER32.205)
846 HWND WINAPI GetActiveWindow(void)
848 MESSAGEQUEUE *pCurMsgQ = 0;
849 HWND hwndActive = 0;
851 /* Get the messageQ for the current thread */
852 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
854 WARN("\tCurrent message queue not found. Exiting!\n" );
855 return 0;
858 /* Return the current active window from the perQ data of the current message Q */
859 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
861 QUEUE_Unlock( pCurMsgQ );
862 return hwndActive;
866 /*******************************************************************
867 * WINPOS_CanActivate
869 static BOOL WINPOS_CanActivate(WND* pWnd)
871 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
872 == WS_VISIBLE ) ) return TRUE;
873 return FALSE;
877 /*******************************************************************
878 * SetActiveWindow16 (USER.59)
880 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
882 return SetActiveWindow(hwnd);
886 /*******************************************************************
887 * SetActiveWindow (USER32.463)
889 HWND WINAPI SetActiveWindow( HWND hwnd )
891 HWND prev = 0;
892 WND *wndPtr = WIN_FindWndPtr( hwnd );
893 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
895 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
897 prev = 0;
898 goto end;
901 /* Get the messageQ for the current thread */
902 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
904 WARN("\tCurrent message queue not found. Exiting!\n" );
905 goto CLEANUP;
908 /* Retrieve the message queue associated with this window */
909 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
910 if ( !pMsgQ )
912 WARN("\tWindow message queue not found. Exiting!\n" );
913 goto CLEANUP;
916 /* Make sure that the window is associated with the calling threads
917 * message queue. It must share the same perQ data.
920 if ( pCurMsgQ->pQData != pMsgQ->pQData )
921 goto CLEANUP;
923 /* Save current active window */
924 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
926 WINPOS_SetActiveWindow( hwnd, 0, 0 );
928 CLEANUP:
929 /* Unlock the queues before returning */
930 if ( pMsgQ )
931 QUEUE_Unlock( pMsgQ );
932 if ( pCurMsgQ )
933 QUEUE_Unlock( pCurMsgQ );
935 end:
936 WIN_ReleaseWndPtr(wndPtr);
937 return prev;
941 /*******************************************************************
942 * GetForegroundWindow16 (USER.608)
944 HWND16 WINAPI GetForegroundWindow16(void)
946 return (HWND16)GetForegroundWindow();
950 /*******************************************************************
951 * SetForegroundWindow16 (USER.609)
953 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
955 return SetForegroundWindow( hwnd );
959 /*******************************************************************
960 * GetForegroundWindow (USER32.241)
962 HWND WINAPI GetForegroundWindow(void)
964 HWND hwndActive = 0;
966 /* Get the foreground window (active window of hActiveQueue) */
967 if ( hActiveQueue )
969 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
970 if ( pActiveQueue )
971 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
973 QUEUE_Unlock( pActiveQueue );
976 return hwndActive;
979 /*******************************************************************
980 * SetForegroundWindow (USER32.482)
982 BOOL WINAPI SetForegroundWindow( HWND hwnd )
984 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
988 /*******************************************************************
989 * AllowSetForegroundWindow (USER32)
991 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
993 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
994 * implemented, then fix this function. */
995 return TRUE;
999 /*******************************************************************
1000 * LockSetForegroundWindow (USER32)
1002 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
1004 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
1005 * implemented, then fix this function. */
1006 return TRUE;
1010 /*******************************************************************
1011 * GetShellWindow16 (USER.600)
1013 HWND16 WINAPI GetShellWindow16(void)
1015 return GetShellWindow();
1018 /*******************************************************************
1019 * SetShellWindow (USER32.504)
1021 HWND WINAPI SetShellWindow(HWND hwndshell)
1022 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
1024 hGlobalShellWindow = hwndshell;
1025 return hGlobalShellWindow;
1029 /*******************************************************************
1030 * GetShellWindow (USER32.287)
1032 HWND WINAPI GetShellWindow(void)
1033 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
1035 return hGlobalShellWindow;
1039 /***********************************************************************
1040 * BringWindowToTop16 (USER.45)
1042 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1044 return BringWindowToTop(hwnd);
1048 /***********************************************************************
1049 * BringWindowToTop (USER32.11)
1051 BOOL WINAPI BringWindowToTop( HWND hwnd )
1053 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1057 /***********************************************************************
1058 * MoveWindow16 (USER.56)
1060 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1061 BOOL16 repaint )
1063 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1067 /***********************************************************************
1068 * MoveWindow (USER32.399)
1070 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1071 BOOL repaint )
1073 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1074 if (!repaint) flags |= SWP_NOREDRAW;
1075 TRACE("%04x %d,%d %dx%d %d\n",
1076 hwnd, x, y, cx, cy, repaint );
1077 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1080 /***********************************************************************
1081 * WINPOS_InitInternalPos
1083 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1084 LPRECT restoreRect )
1086 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1087 atomInternalPos );
1088 if( !lpPos )
1090 /* this happens when the window is minimized/maximized
1091 * for the first time (rectWindow is not adjusted yet) */
1093 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1094 if( !lpPos ) return NULL;
1096 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1097 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1098 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1099 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1102 if( wnd->dwStyle & WS_MINIMIZE )
1103 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1104 else if( wnd->dwStyle & WS_MAXIMIZE )
1105 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1106 else if( restoreRect )
1107 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1109 return lpPos;
1112 /***********************************************************************
1113 * WINPOS_RedrawIconTitle
1115 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1117 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1118 if( lpPos )
1120 if( lpPos->hwndIconTitle )
1122 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1123 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1124 return TRUE;
1127 return FALSE;
1130 /***********************************************************************
1131 * WINPOS_ShowIconTitle
1133 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1135 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1137 if( lpPos && !(pWnd->dwExStyle & WS_EX_MANAGED))
1139 HWND16 hWnd = lpPos->hwndIconTitle;
1141 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1143 if( !hWnd )
1144 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1145 if( bShow )
1147 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1149 if( !(pWnd->dwStyle & WS_VISIBLE) )
1151 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1152 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1153 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1155 WIN_ReleaseWndPtr(pWnd);
1158 else ShowWindow( hWnd, SW_HIDE );
1160 return FALSE;
1163 /*******************************************************************
1164 * WINPOS_GetMinMaxInfo
1166 * Get the minimized and maximized information for a window.
1168 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1169 POINT *minTrack, POINT *maxTrack )
1171 LPINTERNALPOS lpPos;
1172 MINMAXINFO MinMax;
1173 INT xinc, yinc;
1175 /* Compute default values */
1177 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1178 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1179 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1180 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1181 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1182 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1184 if (wndPtr->dwExStyle & WS_EX_MANAGED) xinc = yinc = 0;
1185 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1187 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1188 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1190 else
1192 xinc = yinc = 0;
1193 if (HAS_THICKFRAME(wndPtr->dwStyle))
1195 xinc += GetSystemMetrics(SM_CXFRAME);
1196 yinc += GetSystemMetrics(SM_CYFRAME);
1198 if (wndPtr->dwStyle & WS_BORDER)
1200 xinc += GetSystemMetrics(SM_CXBORDER);
1201 yinc += GetSystemMetrics(SM_CYBORDER);
1204 MinMax.ptMaxSize.x += 2 * xinc;
1205 MinMax.ptMaxSize.y += 2 * yinc;
1207 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1208 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1209 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1210 else
1212 MinMax.ptMaxPosition.x = -xinc;
1213 MinMax.ptMaxPosition.y = -yinc;
1216 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1218 /* Some sanity checks */
1220 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1221 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1222 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1223 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1224 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1225 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1226 MinMax.ptMinTrackSize.x );
1227 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1228 MinMax.ptMinTrackSize.y );
1230 if (maxSize) *maxSize = MinMax.ptMaxSize;
1231 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1232 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1233 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1236 /***********************************************************************
1237 * WINPOS_MinMaximize
1239 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1240 * This function assumes that 'cmd' is different from the current window
1241 * state.
1243 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1245 UINT swpFlags = 0;
1246 POINT pt, size;
1247 LPINTERNALPOS lpPos;
1249 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1251 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1252 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1254 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1256 if( wndPtr->dwStyle & WS_MINIMIZE )
1258 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1259 return (SWP_NOSIZE | SWP_NOMOVE);
1260 swpFlags |= SWP_NOCOPYBITS;
1262 switch( cmd )
1264 case SW_MINIMIZE:
1265 if( wndPtr->dwStyle & WS_MAXIMIZE)
1267 wndPtr->flags |= WIN_RESTORE_MAX;
1268 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1270 else
1271 wndPtr->flags &= ~WIN_RESTORE_MAX;
1272 wndPtr->dwStyle |= WS_MINIMIZE;
1274 if( wndPtr->flags & WIN_NATIVE )
1275 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1276 swpFlags |= MINMAX_NOSWP;
1278 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1280 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1281 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1282 swpFlags |= SWP_NOCOPYBITS;
1283 break;
1285 case SW_MAXIMIZE:
1286 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1287 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1288 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1290 if( wndPtr->dwStyle & WS_MINIMIZE )
1292 if( wndPtr->flags & WIN_NATIVE )
1293 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1295 WINPOS_ShowIconTitle( wndPtr, FALSE );
1296 wndPtr->dwStyle &= ~WS_MINIMIZE;
1298 wndPtr->dwStyle |= WS_MAXIMIZE;
1300 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1301 size.x, size.y );
1302 break;
1304 case SW_RESTORE:
1305 if( wndPtr->dwStyle & WS_MINIMIZE )
1307 if( wndPtr->flags & WIN_NATIVE )
1308 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1309 swpFlags |= MINMAX_NOSWP;
1311 wndPtr->dwStyle &= ~WS_MINIMIZE;
1312 WINPOS_ShowIconTitle( wndPtr, FALSE );
1314 if( wndPtr->flags & WIN_RESTORE_MAX)
1316 /* Restore to maximized position */
1317 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1318 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1319 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1320 wndPtr->dwStyle |= WS_MAXIMIZE;
1321 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1322 break;
1325 else
1326 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1327 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1329 /* Restore to normal position */
1331 *lpRect = lpPos->rectNormal;
1332 lpRect->right -= lpRect->left;
1333 lpRect->bottom -= lpRect->top;
1335 break;
1337 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1338 return swpFlags;
1341 /***********************************************************************
1342 * ShowWindowAsync (USER32.535)
1344 * doesn't wait; returns immediately.
1345 * used by threads to toggle windows in other (possibly hanging) threads
1347 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1349 /* FIXME: does ShowWindow() return immediately ? */
1350 return ShowWindow(hwnd, cmd);
1354 /***********************************************************************
1355 * ShowWindow16 (USER.42)
1357 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1359 return ShowWindow(hwnd,cmd);
1363 /***********************************************************************
1364 * ShowWindow (USER32.534)
1366 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1368 WND* wndPtr = WIN_FindWndPtr( hwnd );
1369 BOOL wasVisible, showFlag;
1370 RECT16 newPos = {0, 0, 0, 0};
1371 UINT swp = 0;
1373 if (!wndPtr) return FALSE;
1375 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1377 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1379 switch(cmd)
1381 case SW_HIDE:
1382 if (!wasVisible) goto END;;
1383 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1384 SWP_NOACTIVATE | SWP_NOZORDER;
1385 break;
1387 case SW_SHOWMINNOACTIVE:
1388 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1389 /* fall through */
1390 case SW_SHOWMINIMIZED:
1391 swp |= SWP_SHOWWINDOW;
1392 /* fall through */
1393 case SW_MINIMIZE:
1394 swp |= SWP_FRAMECHANGED;
1395 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1396 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1397 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1398 break;
1400 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1401 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1402 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1403 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1404 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1405 break;
1407 case SW_SHOWNA:
1408 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1409 /* fall through */
1410 case SW_SHOW:
1411 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1414 * ShowWindow has a little peculiar behavior that if the
1415 * window is already the topmost window, it will not
1416 * activate it.
1418 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1419 swp |= SWP_NOACTIVATE;
1421 break;
1423 case SW_SHOWNOACTIVATE:
1424 swp |= SWP_NOZORDER;
1425 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1426 /* fall through */
1427 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1428 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1429 case SW_RESTORE:
1430 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1432 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1433 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1434 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1435 break;
1438 showFlag = (cmd != SW_HIDE);
1439 if (showFlag != wasVisible)
1441 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1442 if (!IsWindow( hwnd )) goto END;
1445 if ((wndPtr->dwStyle & WS_CHILD) &&
1446 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1447 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1449 /* Don't call SetWindowPos() on invisible child windows */
1450 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1451 else wndPtr->dwStyle |= WS_VISIBLE;
1453 else
1455 /* We can't activate a child window */
1456 if ((wndPtr->dwStyle & WS_CHILD) &&
1457 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1458 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1459 if (!(swp & MINMAX_NOSWP))
1461 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1462 newPos.right, newPos.bottom, LOWORD(swp) );
1463 if (cmd == SW_HIDE)
1465 /* FIXME: This will cause the window to be activated irrespective
1466 * of whether it is owned by the same thread. Has to be done
1467 * asynchronously.
1470 if (hwnd == GetActiveWindow())
1471 WINPOS_ActivateOtherWindow(wndPtr);
1473 /* Revert focus to parent */
1474 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1475 SetFocus( GetParent(hwnd) );
1478 if (!IsWindow( hwnd )) goto END;
1479 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1482 if (wndPtr->flags & WIN_NEED_SIZE)
1484 /* should happen only in CreateWindowEx() */
1485 int wParam = SIZE_RESTORED;
1487 wndPtr->flags &= ~WIN_NEED_SIZE;
1488 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1489 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1490 SendMessageA( hwnd, WM_SIZE, wParam,
1491 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1492 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1493 SendMessageA( hwnd, WM_MOVE, 0,
1494 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1497 END:
1498 WIN_ReleaseWndPtr(wndPtr);
1499 return wasVisible;
1503 /***********************************************************************
1504 * GetInternalWindowPos16 (USER.460)
1506 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1507 LPPOINT16 ptIcon )
1509 WINDOWPLACEMENT16 wndpl;
1510 if (GetWindowPlacement16( hwnd, &wndpl ))
1512 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1513 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1514 return wndpl.showCmd;
1516 return 0;
1520 /***********************************************************************
1521 * GetInternalWindowPos (USER32.245)
1523 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1524 LPPOINT ptIcon )
1526 WINDOWPLACEMENT wndpl;
1527 if (GetWindowPlacement( hwnd, &wndpl ))
1529 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1530 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1531 return wndpl.showCmd;
1533 return 0;
1536 /***********************************************************************
1537 * GetWindowPlacement16 (USER.370)
1539 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1541 WND *pWnd = WIN_FindWndPtr( hwnd );
1542 LPINTERNALPOS lpPos;
1544 if(!pWnd ) return FALSE;
1546 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1547 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1548 wndpl->length = sizeof(*wndpl);
1549 if( pWnd->dwStyle & WS_MINIMIZE )
1550 wndpl->showCmd = SW_SHOWMINIMIZED;
1551 else
1552 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1553 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1554 if( pWnd->flags & WIN_RESTORE_MAX )
1555 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1556 else
1557 wndpl->flags = 0;
1558 wndpl->ptMinPosition = lpPos->ptIconPos;
1559 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1560 wndpl->rcNormalPosition = lpPos->rectNormal;
1562 WIN_ReleaseWndPtr(pWnd);
1563 return TRUE;
1567 /***********************************************************************
1568 * GetWindowPlacement (USER32.307)
1570 * Win95:
1571 * Fails if wndpl->length of Win95 (!) apps is invalid.
1573 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1575 if( pwpl32 )
1577 WINDOWPLACEMENT16 wpl;
1578 wpl.length = sizeof(wpl);
1579 if( GetWindowPlacement16( hwnd, &wpl ) )
1581 pwpl32->length = sizeof(*pwpl32);
1582 pwpl32->flags = wpl.flags;
1583 pwpl32->showCmd = wpl.showCmd;
1584 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1585 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1586 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1587 return TRUE;
1590 return FALSE;
1594 /***********************************************************************
1595 * WINPOS_SetPlacement
1597 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1598 UINT flags )
1600 WND *pWnd = WIN_FindWndPtr( hwnd );
1601 if( pWnd )
1603 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1604 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1606 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1607 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1608 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1610 if( pWnd->dwStyle & WS_MINIMIZE )
1612 WINPOS_ShowIconTitle( pWnd, FALSE );
1613 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1614 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1615 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1617 else if( pWnd->dwStyle & WS_MAXIMIZE )
1619 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1620 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1621 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1623 else if( flags & PLACE_RECT )
1624 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1625 lpPos->rectNormal.right - lpPos->rectNormal.left,
1626 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1627 SWP_NOZORDER | SWP_NOACTIVATE );
1629 ShowWindow( hwnd, wndpl->showCmd );
1630 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1632 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1634 /* SDK: ...valid only the next time... */
1635 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1637 WIN_ReleaseWndPtr(pWnd);
1638 return TRUE;
1640 return FALSE;
1644 /***********************************************************************
1645 * SetWindowPlacement16 (USER.371)
1647 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1649 return WINPOS_SetPlacement( hwnd, wndpl,
1650 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1653 /***********************************************************************
1654 * SetWindowPlacement (USER32.519)
1656 * Win95:
1657 * Fails if wndpl->length of Win95 (!) apps is invalid.
1659 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1661 if( pwpl32 )
1663 WINDOWPLACEMENT16 wpl;
1665 wpl.length = sizeof(WINDOWPLACEMENT16);
1666 wpl.flags = pwpl32->flags;
1667 wpl.showCmd = pwpl32->showCmd;
1668 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1669 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1670 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1671 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1672 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1673 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1674 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1675 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1677 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1679 return FALSE;
1683 /***********************************************************************
1684 * SetInternalWindowPos16 (USER.461)
1686 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1687 LPRECT16 rect, LPPOINT16 pt )
1689 if( IsWindow16(hwnd) )
1691 WINDOWPLACEMENT16 wndpl;
1692 UINT flags;
1694 wndpl.length = sizeof(wndpl);
1695 wndpl.showCmd = showCmd;
1696 wndpl.flags = flags = 0;
1698 if( pt )
1700 flags |= PLACE_MIN;
1701 wndpl.flags |= WPF_SETMINPOSITION;
1702 wndpl.ptMinPosition = *pt;
1704 if( rect )
1706 flags |= PLACE_RECT;
1707 wndpl.rcNormalPosition = *rect;
1709 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1714 /***********************************************************************
1715 * SetInternalWindowPos (USER32.483)
1717 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1718 LPRECT rect, LPPOINT pt )
1720 if( IsWindow(hwnd) )
1722 WINDOWPLACEMENT16 wndpl;
1723 UINT flags;
1725 wndpl.length = sizeof(wndpl);
1726 wndpl.showCmd = showCmd;
1727 wndpl.flags = flags = 0;
1729 if( pt )
1731 flags |= PLACE_MIN;
1732 wndpl.flags |= WPF_SETMINPOSITION;
1733 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1735 if( rect )
1737 flags |= PLACE_RECT;
1738 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1740 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1744 /*******************************************************************
1745 * WINPOS_SetActiveWindow
1747 * SetActiveWindow() back-end. This is the only function that
1748 * can assign active status to a window. It must be called only
1749 * for the top level windows.
1751 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1753 CBTACTIVATESTRUCT16* cbtStruct;
1754 WND* wndPtr=0, *wndTemp;
1755 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1756 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1757 WORD wIconized = 0;
1758 HWND hwndActive = 0;
1759 BOOL bRet = 0;
1761 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1763 /* Get current active window from the active queue */
1764 if ( hActiveQueue )
1766 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1767 if ( pOldActiveQueue )
1768 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1771 /* paranoid checks */
1772 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1773 goto CLEANUP_END;
1775 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1776 * return 0;
1778 wndPtr = WIN_FindWndPtr(hWnd);
1779 hOldActiveQueue = hActiveQueue;
1781 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1783 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1784 WIN_ReleaseWndPtr(wndTemp);
1786 else
1787 TRACE("no current active window.\n");
1789 /* call CBT hook chain */
1790 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1792 cbtStruct->fMouse = fMouse;
1793 cbtStruct->hWndActive = hwndActive;
1794 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1795 (LPARAM)SEGPTR_GET(cbtStruct) );
1796 SEGPTR_FREE(cbtStruct);
1797 if (bRet) goto CLEANUP_END;
1800 /* set prev active wnd to current active wnd and send notification */
1801 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1803 MESSAGEQUEUE *pTempActiveQueue = 0;
1805 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1807 if (GetSysModalWindow16() != hWnd)
1808 goto CLEANUP_END;
1809 /* disregard refusal if hWnd is sysmodal */
1812 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1813 MAKEWPARAM( WA_INACTIVE, wIconized ),
1814 (LPARAM)hWnd );
1816 /* check if something happened during message processing
1817 * (global active queue may have changed)
1819 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1820 if(!pTempActiveQueue)
1821 goto CLEANUP_END;
1823 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1824 QUEUE_Unlock( pTempActiveQueue );
1825 if( hwndPrevActive != hwndActive )
1826 goto CLEANUP_END;
1829 /* Set new active window in the message queue */
1830 hwndActive = hWnd;
1831 if ( wndPtr )
1833 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1834 if ( pNewActiveQueue )
1835 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1837 else /* have to do this or MDI frame activation goes to hell */
1838 if( pOldActiveQueue )
1839 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1841 /* send palette messages */
1842 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1843 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1845 /* if prev wnd is minimized redraw icon title */
1846 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1848 /* managed windows will get ConfigureNotify event */
1849 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1851 /* check Z-order and bring hWnd to the top */
1852 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1854 if (wndTemp->dwStyle & WS_VISIBLE) break;
1856 WIN_ReleaseDesktop();
1857 WIN_ReleaseWndPtr(wndTemp);
1859 if( wndTemp != wndPtr )
1860 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1861 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1862 if (!IsWindow(hWnd))
1863 goto CLEANUP;
1866 /* Get a handle to the new active queue */
1867 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1869 /* send WM_ACTIVATEAPP if necessary */
1870 if (hOldActiveQueue != hNewActiveQueue)
1872 WND **list, **ppWnd;
1873 WND *pDesktop = WIN_GetDesktop();
1875 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1877 for (ppWnd = list; *ppWnd; ppWnd++)
1879 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1881 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1882 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1883 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1885 WIN_ReleaseWinArray(list);
1888 hActiveQueue = hNewActiveQueue;
1890 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1892 for (ppWnd = list; *ppWnd; ppWnd++)
1894 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1896 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1897 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1898 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1900 WIN_ReleaseWinArray(list);
1902 WIN_ReleaseDesktop();
1904 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1907 if (hWnd)
1909 /* walk up to the first unowned window */
1910 wndTemp = WIN_LockWndPtr(wndPtr);
1911 while (wndTemp->owner)
1913 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1915 /* and set last active owned popup */
1916 wndTemp->hwndLastActive = hWnd;
1918 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1919 WIN_ReleaseWndPtr(wndTemp);
1920 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1921 SendMessageA( hWnd, WM_ACTIVATE,
1922 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1923 (LPARAM)hwndPrevActive );
1924 if( !IsWindow(hWnd) ) goto CLEANUP;
1927 /* change focus if possible */
1928 if ( fChangeFocus )
1930 if ( pNewActiveQueue )
1932 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1934 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1935 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1936 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1937 0 : hwndActive );
1940 if ( pOldActiveQueue &&
1941 ( !pNewActiveQueue ||
1942 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1944 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1945 if ( hOldFocus )
1946 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1950 if( !hwndPrevActive && wndPtr )
1951 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1953 /* if active wnd is minimized redraw icon title */
1954 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1956 bRet = (hWnd == hwndActive); /* Success? */
1958 CLEANUP: /* Unlock the message queues before returning */
1960 if ( pNewActiveQueue )
1961 QUEUE_Unlock( pNewActiveQueue );
1963 CLEANUP_END:
1965 if ( pOldActiveQueue )
1966 QUEUE_Unlock( pOldActiveQueue );
1968 WIN_ReleaseWndPtr(wndPtr);
1969 return bRet;
1972 /*******************************************************************
1973 * WINPOS_ActivateOtherWindow
1975 * Activates window other than pWnd.
1977 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1979 BOOL bRet = 0;
1980 WND* pWndTo = NULL;
1981 HWND hwndActive = 0;
1983 /* Get current active window from the active queue */
1984 if ( hActiveQueue )
1986 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1987 if ( pActiveQueue )
1989 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1990 QUEUE_Unlock( pActiveQueue );
1994 if( pWnd->hwndSelf == hwndPrevActive )
1995 hwndPrevActive = 0;
1997 if( hwndActive != pWnd->hwndSelf &&
1998 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1999 return 0;
2001 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
2002 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
2004 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
2006 WIN_ReleaseWndPtr(pWndTo);
2007 pWndTo = WIN_FindWndPtr(hwndPrevActive);
2009 while( !WINPOS_CanActivate(pWndTo) )
2011 /* by now owned windows should've been taken care of */
2012 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
2013 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
2014 if( !pWndTo ) break;
2016 WIN_ReleaseWndPtr(pWndPtr);
2019 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
2021 /* switch desktop queue to current active */
2022 if( pWndTo )
2024 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
2025 WIN_ReleaseWndPtr(pWndTo);
2026 WIN_ReleaseDesktop();
2029 hwndPrevActive = 0;
2030 return bRet;
2033 /*******************************************************************
2034 * WINPOS_ChangeActiveWindow
2037 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2039 WND *wndPtr, *wndTemp;
2040 BOOL retvalue;
2041 HWND hwndActive = 0;
2043 /* Get current active window from the active queue */
2044 if ( hActiveQueue )
2046 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2047 if ( pActiveQueue )
2049 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2050 QUEUE_Unlock( pActiveQueue );
2054 if (!hWnd)
2055 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2057 wndPtr = WIN_FindWndPtr(hWnd);
2058 if( !wndPtr ) return FALSE;
2060 /* child windows get WM_CHILDACTIVATE message */
2061 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2063 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2064 goto end;
2067 if( hWnd == hwndActive )
2069 retvalue = FALSE;
2070 goto end;
2073 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2075 retvalue = FALSE;
2076 goto end;
2079 /* switch desktop queue to current active */
2080 wndTemp = WIN_GetDesktop();
2081 if( wndPtr->parent == wndTemp)
2082 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2083 WIN_ReleaseDesktop();
2085 retvalue = TRUE;
2086 end:
2087 WIN_ReleaseWndPtr(wndPtr);
2088 return retvalue;
2092 /***********************************************************************
2093 * WINPOS_SendNCCalcSize
2095 * Send a WM_NCCALCSIZE message to a window.
2096 * All parameters are read-only except newClientRect.
2097 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2098 * when calcValidRect is TRUE.
2100 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2101 RECT *newWindowRect, RECT *oldWindowRect,
2102 RECT *oldClientRect, WINDOWPOS *winpos,
2103 RECT *newClientRect )
2105 NCCALCSIZE_PARAMS params;
2106 WINDOWPOS winposCopy;
2107 LONG result;
2109 params.rgrc[0] = *newWindowRect;
2110 if (calcValidRect)
2112 winposCopy = *winpos;
2113 params.rgrc[1] = *oldWindowRect;
2114 params.rgrc[2] = *oldClientRect;
2115 params.lppos = &winposCopy;
2117 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2118 (LPARAM)&params );
2119 TRACE("%d,%d-%d,%d\n",
2120 params.rgrc[0].left, params.rgrc[0].top,
2121 params.rgrc[0].right, params.rgrc[0].bottom );
2123 /* If the application send back garbage, ignore it */
2124 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2125 *newClientRect = params.rgrc[0];
2127 return result;
2131 /***********************************************************************
2132 * WINPOS_HandleWindowPosChanging16
2134 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2136 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2138 POINT maxSize, minTrack;
2139 if (winpos->flags & SWP_NOSIZE) return 0;
2140 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2141 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2143 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2144 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2145 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2146 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2148 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2149 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2152 return 0;
2156 /***********************************************************************
2157 * WINPOS_HandleWindowPosChanging
2159 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2161 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2163 POINT maxSize;
2164 if (winpos->flags & SWP_NOSIZE) return 0;
2165 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2166 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2168 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2169 winpos->cx = min( winpos->cx, maxSize.x );
2170 winpos->cy = min( winpos->cy, maxSize.y );
2172 return 0;
2175 /***********************************************************************
2176 * SWP_DoOwnedPopups
2178 * fix Z order taking into account owned popups -
2179 * basically we need to maintain them above the window that owns them
2181 * FIXME: hide/show owned popups when owner visibility changes.
2183 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2185 WND* w = WIN_LockWndPtr(pDesktop->child);
2187 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2189 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2191 /* make sure this popup stays above the owner */
2193 HWND hwndLocalPrev = HWND_TOP;
2195 if( hwndInsertAfter != HWND_TOP )
2197 while( w != wndPtr->owner )
2199 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2200 if( hwndLocalPrev == hwndInsertAfter ) break;
2201 WIN_UpdateWndPtr(&w,w->next);
2203 hwndInsertAfter = hwndLocalPrev;
2206 else if( wndPtr->dwStyle & WS_CHILD )
2207 goto END;
2209 WIN_UpdateWndPtr(&w, pDesktop->child);
2211 while( w )
2213 if( w == wndPtr ) break;
2215 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2217 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2218 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2219 hwndInsertAfter = w->hwndSelf;
2221 WIN_UpdateWndPtr(&w, w->next);
2224 END:
2225 WIN_ReleaseWndPtr(w);
2226 return hwndInsertAfter;
2229 /***********************************************************************
2230 * SWP_CopyValidBits
2232 * Make window look nice without excessive repainting
2234 * visible and update regions are in window coordinates
2235 * client and window rectangles are in parent client coordinates
2237 * Returns: uFlags and a dirty region in *pVisRgn.
2239 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2240 LPRECT lpOldWndRect,
2241 LPRECT lpOldClientRect, UINT uFlags )
2243 RECT r;
2244 HRGN newVisRgn, dirtyRgn;
2245 INT my = COMPLEXREGION;
2247 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2248 Wnd->rectWindow.left, Wnd->rectWindow.top,
2249 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2250 lpOldWndRect->left, lpOldWndRect->top,
2251 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2252 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2253 Wnd->rectClient.left, Wnd->rectClient.top,
2254 Wnd->rectClient.right, Wnd->rectClient.bottom,
2255 lpOldClientRect->left, lpOldClientRect->top,
2256 lpOldClientRect->right,lpOldClientRect->bottom );
2258 if( Wnd->hrgnUpdate == 1 )
2259 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2261 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2262 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2264 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2265 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2267 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2269 nocopy:
2271 TRACE("\twon't copy anything!\n");
2273 /* set dirtyRgn to the sum of old and new visible regions
2274 * in parent client coordinates */
2276 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2277 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2279 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2281 else /* copy valid bits to a new location */
2283 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2284 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2286 /* subtract already invalid region inside Wnd from the dst region */
2288 if( Wnd->hrgnUpdate )
2289 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2290 goto nocopy;
2292 /* check if entire window can be copied */
2294 ow = lpOldWndRect->right - lpOldWndRect->left;
2295 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2296 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2297 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2299 ocw = lpOldClientRect->right - lpOldClientRect->left;
2300 och = lpOldClientRect->bottom - lpOldClientRect->top;
2301 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2302 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2304 if( (ocw != ncw) || (och != nch) ||
2305 ( ow != nw) || ( oh != nh) ||
2306 ((lpOldClientRect->top - lpOldWndRect->top) !=
2307 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2308 ((lpOldClientRect->left - lpOldWndRect->left) !=
2309 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2311 if(uFlags & SWP_EX_PAINTSELF)
2313 /* movement relative to the window itself */
2314 dx = (Wnd->rectClient.left - Wnd->rectWindow.left) -
2315 (lpOldClientRect->left - lpOldWndRect->left) ;
2316 dy = (Wnd->rectClient.top - Wnd->rectWindow.top) -
2317 (lpOldClientRect->top - lpOldWndRect->top) ;
2319 else
2321 /* movement relative to the parent's client area */
2322 dx = Wnd->rectClient.left - lpOldClientRect->left;
2323 dy = Wnd->rectClient.top - lpOldClientRect->top;
2326 /* restrict valid bits to the common client rect */
2328 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2329 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2330 r.right = r.left + min( ocw, ncw );
2331 r.bottom = r.top + min( och, nch );
2333 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2334 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2335 GetRgnBox( hrgnValid, &r );
2336 if( IsRectEmpty( &r ) )
2337 goto nocopy;
2338 r = *lpOldClientRect;
2340 else
2342 if(uFlags & SWP_EX_PAINTSELF) {
2344 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
2345 * relative to itself, only the client area can change.
2346 * if the client rect didn't change, there's nothing to do.
2348 dx = 0;
2349 dy = 0;
2351 else
2353 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2354 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2355 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2357 r = *lpOldWndRect;
2360 if( !(uFlags & SWP_EX_PAINTSELF) )
2362 /* Move remaining regions to parent coordinates */
2363 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2364 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2366 else
2367 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2369 TRACE("\tcomputing dirty region!\n");
2371 /* Compute combined dirty region (old + new - valid) */
2372 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2373 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2375 /* Blt valid bits, r is the rect to copy */
2377 if( dx || dy )
2379 RECT rClip;
2380 HDC hDC;
2382 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2383 from copying clipped areas */
2385 if( uFlags & SWP_EX_PAINTSELF )
2387 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2388 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2389 rClip.right = nw; rClip.bottom = nh;
2391 else
2393 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2394 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2395 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2396 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2398 rClip.left = rClip.top = 0;
2400 if( oh > nh ) r.bottom = r.top + nh;
2401 if( ow < nw ) r.right = r.left + nw;
2403 if( IntersectRect( &r, &r, &rClip ) )
2405 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2407 /* When you copy the bits without repainting, parent doesn't
2408 get validated appropriately. Therefore, we have to validate
2409 the parent with the windows' updated region when the
2410 parent's update region is not empty. */
2412 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2414 OffsetRect(&r, dx, dy);
2415 ValidateRect(Wnd->parent->hwndSelf, &r);
2418 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2419 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2423 /* *pVisRgn now points to the invalidated region */
2425 DeleteObject(newVisRgn);
2426 DeleteObject(dirtyRgn);
2427 return uFlags;
2430 /***********************************************************************
2431 * SWP_DoSimpleFrameChanged
2433 * NOTE: old and new client rect origins are identical, only
2434 * extents may have changed. Window extents are the same.
2436 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2438 INT i = 0;
2439 RECT rect;
2440 HRGN hrgn = 0;
2442 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2444 /* Client rect changed its position/size, most likely a scrollar
2445 * was added/removed.
2447 * FIXME: WVR alignment flags
2450 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2452 i++;
2453 rect.top = 0;
2454 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2455 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2456 if(!(uFlags & SWP_EX_NOCOPY))
2457 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2458 else
2460 rect.left = 0;
2461 goto redraw;
2465 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2467 if( i )
2468 hrgn = CreateRectRgnIndirect( &rect );
2469 rect.left = 0;
2470 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2471 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2472 if(!(uFlags & SWP_EX_NOCOPY))
2473 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2474 else
2475 rect.top = 0;
2476 if( i++ )
2477 REGION_UnionRectWithRgn( hrgn, &rect );
2480 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2482 rect = wndPtr->rectWindow;
2483 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2484 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2485 i++;
2489 if( i )
2491 redraw:
2492 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2493 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2495 else
2497 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2500 if( hrgn > 1 )
2501 DeleteObject( hrgn );
2504 /***********************************************************************
2505 * SWP_DoWinPosChanging
2507 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2508 RECT* pNewWindowRect, RECT* pNewClientRect )
2510 /* Send WM_WINDOWPOSCHANGING message */
2512 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2513 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2515 /* Calculate new position and size */
2517 *pNewWindowRect = wndPtr->rectWindow;
2518 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2519 : wndPtr->rectClient;
2521 if (!(pWinpos->flags & SWP_NOSIZE))
2523 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2524 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2526 if (!(pWinpos->flags & SWP_NOMOVE))
2528 pNewWindowRect->left = pWinpos->x;
2529 pNewWindowRect->top = pWinpos->y;
2530 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2531 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2533 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2534 pWinpos->y - wndPtr->rectWindow.top );
2537 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2538 return TRUE;
2541 /***********************************************************************
2542 * SWP_DoNCCalcSize
2544 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2545 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2547 UINT wvrFlags = 0;
2549 /* Send WM_NCCALCSIZE message to get new client area */
2550 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2552 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2553 &wndPtr->rectWindow, &wndPtr->rectClient,
2554 pWinpos, pNewClientRect );
2556 /* FIXME: WVR_ALIGNxxx */
2558 if( pNewClientRect->left != wndPtr->rectClient.left ||
2559 pNewClientRect->top != wndPtr->rectClient.top )
2560 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2562 if( (pNewClientRect->right - pNewClientRect->left !=
2563 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2564 (pNewClientRect->bottom - pNewClientRect->top !=
2565 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2566 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2568 else
2569 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2570 pNewClientRect->top != wndPtr->rectClient.top) )
2571 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2572 return wvrFlags;
2575 /***********************************************************************
2576 * SetWindowPos (USER.2)
2578 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2579 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2581 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2584 /***********************************************************************
2585 * SetWindowPos (USER32.520)
2587 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2588 INT x, INT y, INT cx, INT cy, UINT flags )
2590 WINDOWPOS winpos;
2591 WND * wndPtr,*wndTemp;
2592 RECT newWindowRect, newClientRect;
2593 RECT oldWindowRect, oldClientRect;
2594 HRGN visRgn = 0;
2595 UINT wvrFlags = 0, uFlags = 0;
2596 BOOL retvalue, resync = FALSE, bChangePos;
2597 HWND hwndActive = 0;
2599 /* Get current active window from the active queue */
2600 if ( hActiveQueue )
2602 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2603 if ( pActiveQueue )
2605 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2606 QUEUE_Unlock( pActiveQueue );
2610 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2611 hwnd, x, y, x+cx, y+cy, flags);
2613 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2614 flags &= ~SWP_WINE_NOHOSTMOVE;
2617 /* ------------------------------------------------------------------------ CHECKS */
2619 /* Check window handle */
2621 if (hwnd == GetDesktopWindow()) return FALSE;
2622 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2624 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2625 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2627 /* Fix redundant flags */
2629 if(wndPtr->dwStyle & WS_VISIBLE)
2630 flags &= ~SWP_SHOWWINDOW;
2631 else
2633 if (!(flags & SWP_SHOWWINDOW))
2634 flags |= SWP_NOREDRAW;
2635 flags &= ~SWP_HIDEWINDOW;
2638 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2640 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2641 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2642 flags |= SWP_NOSIZE; /* Already the right size */
2644 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2645 flags |= SWP_NOMOVE; /* Already the right position */
2647 if (hwnd == hwndActive)
2648 flags |= SWP_NOACTIVATE; /* Already active */
2649 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2651 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2653 flags &= ~SWP_NOZORDER;
2654 hwndInsertAfter = HWND_TOP;
2655 goto Pos;
2659 /* Check hwndInsertAfter */
2661 /* FIXME: TOPMOST not supported yet */
2662 if ((hwndInsertAfter == HWND_TOPMOST) ||
2663 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2665 /* hwndInsertAfter must be a sibling of the window */
2666 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2668 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2670 if( wnd ) {
2671 if( wnd->parent != wndPtr->parent )
2673 retvalue = FALSE;
2674 WIN_ReleaseWndPtr(wnd);
2675 goto END;
2677 /* don't need to change the Zorder of hwnd if it's already inserted
2678 * after hwndInsertAfter or when inserting hwnd after itself.
2680 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2682 WIN_ReleaseWndPtr(wnd);
2685 Pos: /* ------------------------------------------------------------------------ MAIN part */
2687 /* Fill the WINDOWPOS structure */
2689 winpos.hwnd = hwnd;
2690 winpos.hwndInsertAfter = hwndInsertAfter;
2691 winpos.x = x;
2692 winpos.y = y;
2693 winpos.cx = cx;
2694 winpos.cy = cy;
2695 winpos.flags = flags;
2697 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2699 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2701 if( wndPtr->parent == WIN_GetDesktop() )
2702 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2703 hwndInsertAfter, winpos.flags );
2704 WIN_ReleaseDesktop();
2707 if(!(wndPtr->flags & WIN_NATIVE) )
2709 if( hwndInsertAfter == HWND_TOP )
2710 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2711 else
2712 if( hwndInsertAfter == HWND_BOTTOM )
2713 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2714 else
2715 if( !(winpos.flags & SWP_NOZORDER) )
2716 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2717 winpos.flags |= SWP_NOZORDER;
2719 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2720 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2721 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2723 /* get a previous visible region for SWP_CopyValidBits() */
2724 DWORD dflags = DCX_WINDOW;
2726 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2727 dflags |= DCX_CLIPSIBLINGS;
2729 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2733 /* Common operations */
2735 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2737 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2739 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2740 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2743 /* Reset active DCEs */
2745 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2746 wndPtr->dwStyle & WS_VISIBLE) ||
2747 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2749 RECT rect;
2751 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2752 DCE_InvalidateDCE(wndPtr, &rect);
2755 oldWindowRect = wndPtr->rectWindow;
2756 oldClientRect = wndPtr->rectClient;
2758 /* Find out if we have to redraw the whole client rect */
2760 if( oldClientRect.bottom - oldClientRect.top ==
2761 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2763 if( oldClientRect.right - oldClientRect.left ==
2764 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2766 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2767 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2769 uFlags |= SWP_EX_NOCOPY;
2772 * Use this later in CopyValidBits()
2774 else if( 0 )
2775 uFlags |= SWP_EX_NONCLIENT;
2778 /* FIXME: actually do something with WVR_VALIDRECTS */
2780 wndPtr->rectWindow = newWindowRect;
2781 wndPtr->rectClient = newClientRect;
2783 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2785 BOOL bCallDriver = TRUE;
2786 HWND tempInsertAfter = winpos.hwndInsertAfter;
2788 winpos.hwndInsertAfter = hwndInsertAfter;
2790 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2792 /* This is the only place where we need to force repainting of the contents
2793 of windows created by the host window system, all other cases go through the
2794 expose event handling */
2796 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2798 cx = newWindowRect.right - newWindowRect.left;
2799 cy = newWindowRect.bottom - newWindowRect.top;
2801 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2802 winpos.hwndInsertAfter = tempInsertAfter;
2803 bCallDriver = FALSE;
2805 if( winpos.flags & SWP_NOCLIENTMOVE )
2806 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2807 else
2809 /* client area moved but window extents remained the same, copy valid bits */
2811 visRgn = CreateRectRgn( 0, 0, cx, cy );
2812 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2813 uFlags | SWP_EX_PAINTSELF );
2818 if( bCallDriver )
2820 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2822 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2823 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2824 !(uFlags & SWP_EX_NOCOPY) )
2826 /* The origin of the client rect didn't move so we can try to repaint
2827 * only the nonclient area by setting bit gravity hint for the host window system.
2830 if( !(wndPtr->dwExStyle & WS_EX_MANAGED) )
2832 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2833 newWindowRect.bottom - newWindowRect.top);
2834 RECT rcn = newClientRect;
2835 RECT rco = oldClientRect;
2837 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2838 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2839 IntersectRect( &rcn, &rcn, &rco );
2840 visRgn = CreateRectRgnIndirect( &rcn );
2841 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2842 DeleteObject( hrgn );
2843 uFlags = SWP_EX_PAINTSELF;
2845 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2847 else
2848 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2851 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2852 winpos.hwndInsertAfter = tempInsertAfter;
2855 if( winpos.flags & SWP_SHOWWINDOW )
2857 HWND focus, curr;
2859 wndPtr->dwStyle |= WS_VISIBLE;
2861 if (wndPtr->dwExStyle & WS_EX_MANAGED) resync = TRUE;
2863 /* focus was set to unmapped window, reset host focus
2864 * since the window is now visible */
2866 focus = curr = GetFocus();
2867 while (curr)
2869 if (curr == hwnd)
2871 WND *pFocus = WIN_FindWndPtr( focus );
2872 if (pFocus)
2873 pFocus->pDriver->pSetFocus(pFocus);
2874 WIN_ReleaseWndPtr(pFocus);
2875 break;
2877 curr = GetParent(curr);
2881 else /* -------------------------------------------- emulated window */
2883 if( winpos.flags & SWP_SHOWWINDOW )
2885 wndPtr->dwStyle |= WS_VISIBLE;
2886 uFlags |= SWP_EX_PAINTSELF;
2887 visRgn = 1; /* redraw the whole window */
2889 else if( !(winpos.flags & SWP_NOREDRAW) )
2891 if( winpos.flags & SWP_HIDEWINDOW )
2893 if( visRgn > 1 ) /* map to parent */
2894 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2895 else
2896 visRgn = 0;
2898 else
2900 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2902 /* if window was not resized and not moved try to repaint itself */
2903 if((winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) == SWP_AGG_NOGEOMETRYCHANGE)
2904 uFlags |= SWP_EX_PAINTSELF;
2905 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2906 &oldClientRect, uFlags);
2908 else
2910 /* nothing moved, redraw frame if needed */
2912 if( winpos.flags & SWP_FRAMECHANGED )
2913 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2914 if( visRgn )
2916 DeleteObject( visRgn );
2917 visRgn = 0;
2924 if( winpos.flags & SWP_HIDEWINDOW )
2926 wndPtr->dwStyle &= ~WS_VISIBLE;
2929 if (hwnd == CARET_GetHwnd())
2931 if( winpos.flags & SWP_HIDEWINDOW )
2932 HideCaret(hwnd);
2933 else if (winpos.flags & SWP_SHOWWINDOW)
2934 ShowCaret(hwnd);
2937 /* ------------------------------------------------------------------------ FINAL */
2939 if (wndPtr->flags & WIN_NATIVE)
2940 EVENT_Synchronize(); /* Synchronize with the host window system */
2942 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2944 /* Simulate a mouse event to set the cursor */
2945 int iWndsLocks = WIN_SuspendWndsLock();
2947 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2948 PosX, PosY, GetTickCount(), 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;