GetDateFormatA: Check range and recalculate wDayOfWeek.
[wine.git] / windows / winpos.c
blob35ad25a1228196218a885ebac541dfe2716cae25
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->flags & WIN_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 * GetShellWindow16 (USER.600)
991 HWND16 WINAPI GetShellWindow16(void)
993 return GetShellWindow();
996 /*******************************************************************
997 * SetShellWindow (USER32.504)
999 HWND WINAPI SetShellWindow(HWND hwndshell)
1000 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
1002 hGlobalShellWindow = hwndshell;
1003 return hGlobalShellWindow;
1007 /*******************************************************************
1008 * GetShellWindow (USER32.287)
1010 HWND WINAPI GetShellWindow(void)
1011 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
1013 return hGlobalShellWindow;
1017 /***********************************************************************
1018 * BringWindowToTop16 (USER.45)
1020 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1022 return BringWindowToTop(hwnd);
1026 /***********************************************************************
1027 * BringWindowToTop (USER32.11)
1029 BOOL WINAPI BringWindowToTop( HWND hwnd )
1031 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1035 /***********************************************************************
1036 * MoveWindow16 (USER.56)
1038 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1039 BOOL16 repaint )
1041 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1045 /***********************************************************************
1046 * MoveWindow (USER32.399)
1048 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1049 BOOL repaint )
1051 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1052 if (!repaint) flags |= SWP_NOREDRAW;
1053 TRACE("%04x %d,%d %dx%d %d\n",
1054 hwnd, x, y, cx, cy, repaint );
1055 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1058 /***********************************************************************
1059 * WINPOS_InitInternalPos
1061 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1062 LPRECT restoreRect )
1064 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1065 atomInternalPos );
1066 if( !lpPos )
1068 /* this happens when the window is minimized/maximized
1069 * for the first time (rectWindow is not adjusted yet) */
1071 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1072 if( !lpPos ) return NULL;
1074 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1075 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1076 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1077 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1080 if( wnd->dwStyle & WS_MINIMIZE )
1081 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1082 else if( wnd->dwStyle & WS_MAXIMIZE )
1083 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1084 else if( restoreRect )
1085 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1087 return lpPos;
1090 /***********************************************************************
1091 * WINPOS_RedrawIconTitle
1093 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1095 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1096 if( lpPos )
1098 if( lpPos->hwndIconTitle )
1100 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1101 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1102 return TRUE;
1105 return FALSE;
1108 /***********************************************************************
1109 * WINPOS_ShowIconTitle
1111 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1113 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1115 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1117 HWND16 hWnd = lpPos->hwndIconTitle;
1119 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1121 if( !hWnd )
1122 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1123 if( bShow )
1125 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1127 if( !(pWnd->dwStyle & WS_VISIBLE) )
1129 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1130 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1131 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1133 WIN_ReleaseWndPtr(pWnd);
1136 else ShowWindow( hWnd, SW_HIDE );
1138 return FALSE;
1141 /*******************************************************************
1142 * WINPOS_GetMinMaxInfo
1144 * Get the minimized and maximized information for a window.
1146 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1147 POINT *minTrack, POINT *maxTrack )
1149 LPINTERNALPOS lpPos;
1150 MINMAXINFO MinMax;
1151 INT xinc, yinc;
1153 /* Compute default values */
1155 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1156 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1157 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1158 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1159 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1160 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1162 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1163 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1165 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1166 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1168 else
1170 xinc = yinc = 0;
1171 if (HAS_THICKFRAME(wndPtr->dwStyle))
1173 xinc += GetSystemMetrics(SM_CXFRAME);
1174 yinc += GetSystemMetrics(SM_CYFRAME);
1176 if (wndPtr->dwStyle & WS_BORDER)
1178 xinc += GetSystemMetrics(SM_CXBORDER);
1179 yinc += GetSystemMetrics(SM_CYBORDER);
1182 MinMax.ptMaxSize.x += 2 * xinc;
1183 MinMax.ptMaxSize.y += 2 * yinc;
1185 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1186 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1187 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1188 else
1190 MinMax.ptMaxPosition.x = -xinc;
1191 MinMax.ptMaxPosition.y = -yinc;
1194 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1196 /* Some sanity checks */
1198 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1199 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1200 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1201 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1202 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1203 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1204 MinMax.ptMinTrackSize.x );
1205 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1206 MinMax.ptMinTrackSize.y );
1208 if (maxSize) *maxSize = MinMax.ptMaxSize;
1209 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1210 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1211 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1214 /***********************************************************************
1215 * WINPOS_MinMaximize
1217 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1218 * This function assumes that 'cmd' is different from the current window
1219 * state.
1221 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1223 UINT swpFlags = 0;
1224 POINT pt, size;
1225 LPINTERNALPOS lpPos;
1227 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1229 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1230 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1232 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1234 if( wndPtr->dwStyle & WS_MINIMIZE )
1236 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1237 return (SWP_NOSIZE | SWP_NOMOVE);
1238 swpFlags |= SWP_NOCOPYBITS;
1240 switch( cmd )
1242 case SW_MINIMIZE:
1243 if( wndPtr->dwStyle & WS_MAXIMIZE)
1245 wndPtr->flags |= WIN_RESTORE_MAX;
1246 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1248 else
1249 wndPtr->flags &= ~WIN_RESTORE_MAX;
1250 wndPtr->dwStyle |= WS_MINIMIZE;
1252 if( wndPtr->flags & WIN_NATIVE )
1253 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1254 swpFlags |= MINMAX_NOSWP;
1256 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1258 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1259 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1260 swpFlags |= SWP_NOCOPYBITS;
1261 break;
1263 case SW_MAXIMIZE:
1264 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1265 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1266 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1268 if( wndPtr->dwStyle & WS_MINIMIZE )
1270 if( wndPtr->flags & WIN_NATIVE )
1271 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1273 WINPOS_ShowIconTitle( wndPtr, FALSE );
1274 wndPtr->dwStyle &= ~WS_MINIMIZE;
1276 wndPtr->dwStyle |= WS_MAXIMIZE;
1278 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1279 size.x, size.y );
1280 break;
1282 case SW_RESTORE:
1283 if( wndPtr->dwStyle & WS_MINIMIZE )
1285 if( wndPtr->flags & WIN_NATIVE )
1286 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1287 swpFlags |= MINMAX_NOSWP;
1289 wndPtr->dwStyle &= ~WS_MINIMIZE;
1290 WINPOS_ShowIconTitle( wndPtr, FALSE );
1292 if( wndPtr->flags & WIN_RESTORE_MAX)
1294 /* Restore to maximized position */
1295 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1296 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1297 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1298 wndPtr->dwStyle |= WS_MAXIMIZE;
1299 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1300 break;
1303 else
1304 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1305 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1307 /* Restore to normal position */
1309 *lpRect = lpPos->rectNormal;
1310 lpRect->right -= lpRect->left;
1311 lpRect->bottom -= lpRect->top;
1313 break;
1315 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1316 return swpFlags;
1319 /***********************************************************************
1320 * ShowWindowAsync (USER32.535)
1322 * doesn't wait; returns immediately.
1323 * used by threads to toggle windows in other (possibly hanging) threads
1325 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1327 /* FIXME: does ShowWindow() return immediately ? */
1328 return ShowWindow(hwnd, cmd);
1332 /***********************************************************************
1333 * ShowWindow16 (USER.42)
1335 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1337 return ShowWindow(hwnd,cmd);
1341 /***********************************************************************
1342 * ShowWindow (USER32.534)
1344 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1346 WND* wndPtr = WIN_FindWndPtr( hwnd );
1347 BOOL wasVisible, showFlag;
1348 RECT16 newPos = {0, 0, 0, 0};
1349 UINT swp = 0;
1351 if (!wndPtr) return FALSE;
1353 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1355 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1357 switch(cmd)
1359 case SW_HIDE:
1360 if (!wasVisible) goto END;;
1361 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1362 SWP_NOACTIVATE | SWP_NOZORDER;
1363 break;
1365 case SW_SHOWMINNOACTIVE:
1366 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1367 /* fall through */
1368 case SW_SHOWMINIMIZED:
1369 swp |= SWP_SHOWWINDOW;
1370 /* fall through */
1371 case SW_MINIMIZE:
1372 swp |= SWP_FRAMECHANGED;
1373 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1374 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1375 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1376 break;
1378 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1379 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1380 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1381 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1382 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1383 break;
1385 case SW_SHOWNA:
1386 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1387 /* fall through */
1388 case SW_SHOW:
1389 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1392 * ShowWindow has a little peculiar behavior that if the
1393 * window is already the topmost window, it will not
1394 * activate it.
1396 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1397 swp |= SWP_NOACTIVATE;
1399 break;
1401 case SW_SHOWNOACTIVATE:
1402 swp |= SWP_NOZORDER;
1403 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1404 /* fall through */
1405 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1406 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1407 case SW_RESTORE:
1408 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1410 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1411 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1412 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1413 break;
1416 showFlag = (cmd != SW_HIDE);
1417 if (showFlag != wasVisible)
1419 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1420 if (!IsWindow( hwnd )) goto END;
1423 if ((wndPtr->dwStyle & WS_CHILD) &&
1424 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1425 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1427 /* Don't call SetWindowPos() on invisible child windows */
1428 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1429 else wndPtr->dwStyle |= WS_VISIBLE;
1431 else
1433 /* We can't activate a child window */
1434 if ((wndPtr->dwStyle & WS_CHILD) &&
1435 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1436 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1437 if (!(swp & MINMAX_NOSWP))
1439 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1440 newPos.right, newPos.bottom, LOWORD(swp) );
1441 if (cmd == SW_HIDE)
1443 /* FIXME: This will cause the window to be activated irrespective
1444 * of whether it is owned by the same thread. Has to be done
1445 * asynchronously.
1448 if (hwnd == GetActiveWindow())
1449 WINPOS_ActivateOtherWindow(wndPtr);
1451 /* Revert focus to parent */
1452 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1453 SetFocus( GetParent(hwnd) );
1456 if (!IsWindow( hwnd )) goto END;
1457 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1460 if (wndPtr->flags & WIN_NEED_SIZE)
1462 /* should happen only in CreateWindowEx() */
1463 int wParam = SIZE_RESTORED;
1465 wndPtr->flags &= ~WIN_NEED_SIZE;
1466 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1467 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1468 SendMessageA( hwnd, WM_SIZE, wParam,
1469 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1470 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1471 SendMessageA( hwnd, WM_MOVE, 0,
1472 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1475 END:
1476 WIN_ReleaseWndPtr(wndPtr);
1477 return wasVisible;
1481 /***********************************************************************
1482 * GetInternalWindowPos16 (USER.460)
1484 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1485 LPPOINT16 ptIcon )
1487 WINDOWPLACEMENT16 wndpl;
1488 if (GetWindowPlacement16( hwnd, &wndpl ))
1490 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1491 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1492 return wndpl.showCmd;
1494 return 0;
1498 /***********************************************************************
1499 * GetInternalWindowPos (USER32.245)
1501 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1502 LPPOINT ptIcon )
1504 WINDOWPLACEMENT wndpl;
1505 if (GetWindowPlacement( hwnd, &wndpl ))
1507 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1508 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1509 return wndpl.showCmd;
1511 return 0;
1514 /***********************************************************************
1515 * GetWindowPlacement16 (USER.370)
1517 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1519 WND *pWnd = WIN_FindWndPtr( hwnd );
1520 LPINTERNALPOS lpPos;
1522 if(!pWnd ) return FALSE;
1524 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1525 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1526 wndpl->length = sizeof(*wndpl);
1527 if( pWnd->dwStyle & WS_MINIMIZE )
1528 wndpl->showCmd = SW_SHOWMINIMIZED;
1529 else
1530 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1531 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1532 if( pWnd->flags & WIN_RESTORE_MAX )
1533 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1534 else
1535 wndpl->flags = 0;
1536 wndpl->ptMinPosition = lpPos->ptIconPos;
1537 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1538 wndpl->rcNormalPosition = lpPos->rectNormal;
1540 WIN_ReleaseWndPtr(pWnd);
1541 return TRUE;
1545 /***********************************************************************
1546 * GetWindowPlacement (USER32.307)
1548 * Win95:
1549 * Fails if wndpl->length of Win95 (!) apps is invalid.
1551 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1553 if( pwpl32 )
1555 WINDOWPLACEMENT16 wpl;
1556 wpl.length = sizeof(wpl);
1557 if( GetWindowPlacement16( hwnd, &wpl ) )
1559 pwpl32->length = sizeof(*pwpl32);
1560 pwpl32->flags = wpl.flags;
1561 pwpl32->showCmd = wpl.showCmd;
1562 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1563 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1564 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1565 return TRUE;
1568 return FALSE;
1572 /***********************************************************************
1573 * WINPOS_SetPlacement
1575 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1576 UINT flags )
1578 WND *pWnd = WIN_FindWndPtr( hwnd );
1579 if( pWnd )
1581 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1582 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1584 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1585 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1586 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1588 if( pWnd->dwStyle & WS_MINIMIZE )
1590 WINPOS_ShowIconTitle( pWnd, FALSE );
1591 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1592 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1593 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1595 else if( pWnd->dwStyle & WS_MAXIMIZE )
1597 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1598 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1599 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1601 else if( flags & PLACE_RECT )
1602 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1603 lpPos->rectNormal.right - lpPos->rectNormal.left,
1604 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1605 SWP_NOZORDER | SWP_NOACTIVATE );
1607 ShowWindow( hwnd, wndpl->showCmd );
1608 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1610 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1612 /* SDK: ...valid only the next time... */
1613 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1615 WIN_ReleaseWndPtr(pWnd);
1616 return TRUE;
1618 return FALSE;
1622 /***********************************************************************
1623 * SetWindowPlacement16 (USER.371)
1625 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1627 return WINPOS_SetPlacement( hwnd, wndpl,
1628 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1631 /***********************************************************************
1632 * SetWindowPlacement (USER32.519)
1634 * Win95:
1635 * Fails if wndpl->length of Win95 (!) apps is invalid.
1637 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1639 if( pwpl32 )
1641 WINDOWPLACEMENT16 wpl;
1643 wpl.length = sizeof(WINDOWPLACEMENT16);
1644 wpl.flags = pwpl32->flags;
1645 wpl.showCmd = pwpl32->showCmd;
1646 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1647 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1648 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1649 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1650 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1651 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1652 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1653 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1655 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1657 return FALSE;
1661 /***********************************************************************
1662 * SetInternalWindowPos16 (USER.461)
1664 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1665 LPRECT16 rect, LPPOINT16 pt )
1667 if( IsWindow16(hwnd) )
1669 WINDOWPLACEMENT16 wndpl;
1670 UINT flags;
1672 wndpl.length = sizeof(wndpl);
1673 wndpl.showCmd = showCmd;
1674 wndpl.flags = flags = 0;
1676 if( pt )
1678 flags |= PLACE_MIN;
1679 wndpl.flags |= WPF_SETMINPOSITION;
1680 wndpl.ptMinPosition = *pt;
1682 if( rect )
1684 flags |= PLACE_RECT;
1685 wndpl.rcNormalPosition = *rect;
1687 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1692 /***********************************************************************
1693 * SetInternalWindowPos (USER32.483)
1695 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1696 LPRECT rect, LPPOINT pt )
1698 if( IsWindow(hwnd) )
1700 WINDOWPLACEMENT16 wndpl;
1701 UINT flags;
1703 wndpl.length = sizeof(wndpl);
1704 wndpl.showCmd = showCmd;
1705 wndpl.flags = flags = 0;
1707 if( pt )
1709 flags |= PLACE_MIN;
1710 wndpl.flags |= WPF_SETMINPOSITION;
1711 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1713 if( rect )
1715 flags |= PLACE_RECT;
1716 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1718 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1722 /*******************************************************************
1723 * WINPOS_SetActiveWindow
1725 * SetActiveWindow() back-end. This is the only function that
1726 * can assign active status to a window. It must be called only
1727 * for the top level windows.
1729 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1731 CBTACTIVATESTRUCT16* cbtStruct;
1732 WND* wndPtr=0, *wndTemp;
1733 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1734 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1735 WORD wIconized = 0;
1736 HWND hwndActive = 0;
1737 BOOL bRet = 0;
1739 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1741 /* Get current active window from the active queue */
1742 if ( hActiveQueue )
1744 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1745 if ( pOldActiveQueue )
1746 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1749 /* paranoid checks */
1750 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1751 goto CLEANUP_END;
1753 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1754 * return 0;
1756 wndPtr = WIN_FindWndPtr(hWnd);
1757 hOldActiveQueue = hActiveQueue;
1759 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1761 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1762 WIN_ReleaseWndPtr(wndTemp);
1764 else
1765 TRACE("no current active window.\n");
1767 /* call CBT hook chain */
1768 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1770 cbtStruct->fMouse = fMouse;
1771 cbtStruct->hWndActive = hwndActive;
1772 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1773 (LPARAM)SEGPTR_GET(cbtStruct) );
1774 SEGPTR_FREE(cbtStruct);
1775 if (bRet) goto CLEANUP_END;
1778 /* set prev active wnd to current active wnd and send notification */
1779 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1781 MESSAGEQUEUE *pTempActiveQueue = 0;
1783 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1785 if (GetSysModalWindow16() != hWnd)
1786 goto CLEANUP_END;
1787 /* disregard refusal if hWnd is sysmodal */
1790 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1791 MAKEWPARAM( WA_INACTIVE, wIconized ),
1792 (LPARAM)hWnd );
1794 /* check if something happened during message processing
1795 * (global active queue may have changed)
1797 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1798 if(!pTempActiveQueue)
1799 goto CLEANUP_END;
1801 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1802 QUEUE_Unlock( pTempActiveQueue );
1803 if( hwndPrevActive != hwndActive )
1804 goto CLEANUP_END;
1807 /* Set new active window in the message queue */
1808 hwndActive = hWnd;
1809 if ( wndPtr )
1811 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1812 if ( pNewActiveQueue )
1813 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1815 else /* have to do this or MDI frame activation goes to hell */
1816 if( pOldActiveQueue )
1817 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1819 /* send palette messages */
1820 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1821 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1823 /* if prev wnd is minimized redraw icon title */
1824 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1826 /* managed windows will get ConfigureNotify event */
1827 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1829 /* check Z-order and bring hWnd to the top */
1830 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1832 if (wndTemp->dwStyle & WS_VISIBLE) break;
1834 WIN_ReleaseDesktop();
1835 WIN_ReleaseWndPtr(wndTemp);
1837 if( wndTemp != wndPtr )
1838 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1839 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1840 if (!IsWindow(hWnd))
1841 goto CLEANUP;
1844 /* Get a handle to the new active queue */
1845 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1847 /* send WM_ACTIVATEAPP if necessary */
1848 if (hOldActiveQueue != hNewActiveQueue)
1850 WND **list, **ppWnd;
1851 WND *pDesktop = WIN_GetDesktop();
1853 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1855 for (ppWnd = list; *ppWnd; ppWnd++)
1857 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1859 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1860 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1861 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1863 WIN_ReleaseWinArray(list);
1866 hActiveQueue = hNewActiveQueue;
1868 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1870 for (ppWnd = list; *ppWnd; ppWnd++)
1872 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1874 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1875 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1876 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1878 WIN_ReleaseWinArray(list);
1880 WIN_ReleaseDesktop();
1882 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1885 if (hWnd)
1887 /* walk up to the first unowned window */
1888 wndTemp = WIN_LockWndPtr(wndPtr);
1889 while (wndTemp->owner)
1891 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1893 /* and set last active owned popup */
1894 wndTemp->hwndLastActive = hWnd;
1896 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1897 WIN_ReleaseWndPtr(wndTemp);
1898 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1899 SendMessageA( hWnd, WM_ACTIVATE,
1900 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1901 (LPARAM)hwndPrevActive );
1902 if( !IsWindow(hWnd) ) goto CLEANUP;
1905 /* change focus if possible */
1906 if ( fChangeFocus )
1908 if ( pNewActiveQueue )
1910 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1912 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1913 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1914 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1915 0 : hwndActive );
1918 if ( pOldActiveQueue &&
1919 ( !pNewActiveQueue ||
1920 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1922 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1923 if ( hOldFocus )
1924 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1928 if( !hwndPrevActive && wndPtr )
1929 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1931 /* if active wnd is minimized redraw icon title */
1932 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1934 bRet = (hWnd == hwndActive); /* Success? */
1936 CLEANUP: /* Unlock the message queues before returning */
1938 if ( pNewActiveQueue )
1939 QUEUE_Unlock( pNewActiveQueue );
1941 CLEANUP_END:
1943 if ( pOldActiveQueue )
1944 QUEUE_Unlock( pOldActiveQueue );
1946 WIN_ReleaseWndPtr(wndPtr);
1947 return bRet;
1950 /*******************************************************************
1951 * WINPOS_ActivateOtherWindow
1953 * Activates window other than pWnd.
1955 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1957 BOOL bRet = 0;
1958 WND* pWndTo = NULL;
1959 HWND hwndActive = 0;
1961 /* Get current active window from the active queue */
1962 if ( hActiveQueue )
1964 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1965 if ( pActiveQueue )
1967 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1968 QUEUE_Unlock( pActiveQueue );
1972 if( pWnd->hwndSelf == hwndPrevActive )
1973 hwndPrevActive = 0;
1975 if( hwndActive != pWnd->hwndSelf &&
1976 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1977 return 0;
1979 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1980 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1982 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1984 WIN_ReleaseWndPtr(pWndTo);
1985 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1987 while( !WINPOS_CanActivate(pWndTo) )
1989 /* by now owned windows should've been taken care of */
1990 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1991 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1992 if( !pWndTo ) break;
1994 WIN_ReleaseWndPtr(pWndPtr);
1997 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1999 /* switch desktop queue to current active */
2000 if( pWndTo )
2002 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
2003 WIN_ReleaseWndPtr(pWndTo);
2004 WIN_ReleaseDesktop();
2007 hwndPrevActive = 0;
2008 return bRet;
2011 /*******************************************************************
2012 * WINPOS_ChangeActiveWindow
2015 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2017 WND *wndPtr, *wndTemp;
2018 BOOL retvalue;
2019 HWND hwndActive = 0;
2021 /* Get current active window from the active queue */
2022 if ( hActiveQueue )
2024 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2025 if ( pActiveQueue )
2027 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2028 QUEUE_Unlock( pActiveQueue );
2032 if (!hWnd)
2033 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2035 wndPtr = WIN_FindWndPtr(hWnd);
2036 if( !wndPtr ) return FALSE;
2038 /* child windows get WM_CHILDACTIVATE message */
2039 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2041 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2042 goto end;
2045 if( hWnd == hwndActive )
2047 retvalue = FALSE;
2048 goto end;
2051 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2053 retvalue = FALSE;
2054 goto end;
2057 /* switch desktop queue to current active */
2058 wndTemp = WIN_GetDesktop();
2059 if( wndPtr->parent == wndTemp)
2060 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2061 WIN_ReleaseDesktop();
2063 retvalue = TRUE;
2064 end:
2065 WIN_ReleaseWndPtr(wndPtr);
2066 return retvalue;
2070 /***********************************************************************
2071 * WINPOS_SendNCCalcSize
2073 * Send a WM_NCCALCSIZE message to a window.
2074 * All parameters are read-only except newClientRect.
2075 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2076 * when calcValidRect is TRUE.
2078 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2079 RECT *newWindowRect, RECT *oldWindowRect,
2080 RECT *oldClientRect, WINDOWPOS *winpos,
2081 RECT *newClientRect )
2083 NCCALCSIZE_PARAMS params;
2084 WINDOWPOS winposCopy;
2085 LONG result;
2087 params.rgrc[0] = *newWindowRect;
2088 if (calcValidRect)
2090 winposCopy = *winpos;
2091 params.rgrc[1] = *oldWindowRect;
2092 params.rgrc[2] = *oldClientRect;
2093 params.lppos = &winposCopy;
2095 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2096 (LPARAM)&params );
2097 TRACE("%d,%d-%d,%d\n",
2098 params.rgrc[0].left, params.rgrc[0].top,
2099 params.rgrc[0].right, params.rgrc[0].bottom );
2101 /* If the application send back garbage, ignore it */
2102 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2103 *newClientRect = params.rgrc[0];
2105 return result;
2109 /***********************************************************************
2110 * WINPOS_HandleWindowPosChanging16
2112 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2114 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2116 POINT maxSize, minTrack;
2117 if (winpos->flags & SWP_NOSIZE) return 0;
2118 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2119 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2121 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2122 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2123 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2124 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2126 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2127 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2130 return 0;
2134 /***********************************************************************
2135 * WINPOS_HandleWindowPosChanging
2137 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2139 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2141 POINT maxSize;
2142 if (winpos->flags & SWP_NOSIZE) return 0;
2143 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2144 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2146 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2147 winpos->cx = min( winpos->cx, maxSize.x );
2148 winpos->cy = min( winpos->cy, maxSize.y );
2150 return 0;
2153 /***********************************************************************
2154 * SWP_DoOwnedPopups
2156 * fix Z order taking into account owned popups -
2157 * basically we need to maintain them above the window that owns them
2159 * FIXME: hide/show owned popups when owner visibility changes.
2161 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2163 WND* w = WIN_LockWndPtr(pDesktop->child);
2165 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2167 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2169 /* make sure this popup stays above the owner */
2171 HWND hwndLocalPrev = HWND_TOP;
2173 if( hwndInsertAfter != HWND_TOP )
2175 while( w != wndPtr->owner )
2177 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2178 if( hwndLocalPrev == hwndInsertAfter ) break;
2179 WIN_UpdateWndPtr(&w,w->next);
2181 hwndInsertAfter = hwndLocalPrev;
2184 else if( wndPtr->dwStyle & WS_CHILD )
2185 goto END;
2187 WIN_UpdateWndPtr(&w, pDesktop->child);
2189 while( w )
2191 if( w == wndPtr ) break;
2193 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2195 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2196 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2197 hwndInsertAfter = w->hwndSelf;
2199 WIN_UpdateWndPtr(&w, w->next);
2202 END:
2203 WIN_ReleaseWndPtr(w);
2204 return hwndInsertAfter;
2207 /***********************************************************************
2208 * SWP_CopyValidBits
2210 * Make window look nice without excessive repainting
2212 * visible and update regions are in window coordinates
2213 * client and window rectangles are in parent client coordinates
2215 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2216 * window rects have the same origin.
2218 * Returns: uFlags and a dirty region in *pVisRgn.
2220 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2221 LPRECT lpOldWndRect,
2222 LPRECT lpOldClientRect, UINT uFlags )
2224 RECT r;
2225 HRGN newVisRgn, dirtyRgn;
2226 INT my = COMPLEXREGION;
2228 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2229 Wnd->rectWindow.left, Wnd->rectWindow.top,
2230 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2231 lpOldWndRect->left, lpOldWndRect->top,
2232 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2233 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2234 Wnd->rectClient.left, Wnd->rectClient.top,
2235 Wnd->rectClient.right, Wnd->rectClient.bottom,
2236 lpOldClientRect->left, lpOldClientRect->top,
2237 lpOldClientRect->right,lpOldClientRect->bottom );
2239 if( Wnd->hrgnUpdate == 1 )
2240 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2242 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2243 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2245 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2246 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2248 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2250 nocopy:
2252 TRACE("\twon't copy anything!\n");
2254 /* set dirtyRgn to the sum of old and new visible regions
2255 * in parent client coordinates */
2257 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2258 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2260 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2262 else /* copy valid bits to a new location */
2264 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2265 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2267 /* subtract already invalid region inside Wnd from the dst region */
2269 if( Wnd->hrgnUpdate )
2270 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2271 goto nocopy;
2273 /* check if entire window can be copied */
2275 ow = lpOldWndRect->right - lpOldWndRect->left;
2276 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2277 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2278 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2280 ocw = lpOldClientRect->right - lpOldClientRect->left;
2281 och = lpOldClientRect->bottom - lpOldClientRect->top;
2282 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2283 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2285 if( (ocw != ncw) || (och != nch) ||
2286 ( ow != nw) || ( oh != nh) ||
2287 ((lpOldClientRect->top - lpOldWndRect->top) !=
2288 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2289 ((lpOldClientRect->left - lpOldWndRect->left) !=
2290 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2292 dx = Wnd->rectClient.left - lpOldClientRect->left;
2293 dy = Wnd->rectClient.top - lpOldClientRect->top;
2295 /* restrict valid bits to the common client rect */
2297 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2298 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2299 r.right = r.left + min( ocw, ncw );
2300 r.bottom = r.top + min( och, nch );
2302 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2303 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2304 GetRgnBox( hrgnValid, &r );
2305 if( IsRectEmpty( &r ) )
2306 goto nocopy;
2307 r = *lpOldClientRect;
2309 else
2311 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2312 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2313 if( !(uFlags & SWP_EX_PAINTSELF) )
2314 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2315 r = *lpOldWndRect;
2318 if( !(uFlags & SWP_EX_PAINTSELF) )
2320 /* Move remaining regions to parent coordinates */
2321 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2322 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2324 else
2325 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2327 TRACE("\tcomputing dirty region!\n");
2329 /* Compute combined dirty region (old + new - valid) */
2330 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2331 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2333 /* Blt valid bits, r is the rect to copy */
2335 if( dx || dy )
2337 RECT rClip;
2338 HDC hDC;
2340 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2341 from copying clipped areas */
2343 if( uFlags & SWP_EX_PAINTSELF )
2345 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2346 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2347 rClip.right = nw; rClip.bottom = nh;
2349 else
2351 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2352 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2353 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2354 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2356 rClip.left = rClip.top = 0;
2358 if( oh > nh ) r.bottom = r.top + nh;
2359 if( ow < nw ) r.right = r.left + nw;
2361 if( IntersectRect( &r, &r, &rClip ) )
2363 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2365 /* When you copy the bits without repainting, parent doesn't
2366 get validated appropriately. Therefore, we have to validate
2367 the parent with the windows' updated region when the
2368 parent's update region is not empty. */
2370 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2372 OffsetRect(&r, dx, dy);
2373 ValidateRect(Wnd->parent->hwndSelf, &r);
2376 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2377 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2381 /* *pVisRgn now points to the invalidated region */
2383 DeleteObject(newVisRgn);
2384 DeleteObject(dirtyRgn);
2385 return uFlags;
2388 /***********************************************************************
2389 * SWP_DoSimpleFrameChanged
2391 * NOTE: old and new client rect origins are identical, only
2392 * extents may have changed. Window extents are the same.
2394 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2396 INT i = 0;
2397 RECT rect;
2398 HRGN hrgn = 0;
2400 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2402 /* Client rect changed its position/size, most likely a scrollar
2403 * was added/removed.
2405 * FIXME: WVR alignment flags
2408 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2410 i++;
2411 rect.top = 0;
2412 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2413 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2414 if(!(uFlags & SWP_EX_NOCOPY))
2415 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2416 else
2418 rect.left = 0;
2419 goto redraw;
2423 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2425 if( i )
2426 hrgn = CreateRectRgnIndirect( &rect );
2427 rect.left = 0;
2428 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2429 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2430 if(!(uFlags & SWP_EX_NOCOPY))
2431 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2432 else
2433 rect.top = 0;
2434 if( i++ )
2435 REGION_UnionRectWithRgn( hrgn, &rect );
2438 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2440 rect = wndPtr->rectWindow;
2441 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2442 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2443 i++;
2447 if( i )
2449 redraw:
2450 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2451 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2453 else
2455 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2458 if( hrgn > 1 )
2459 DeleteObject( hrgn );
2462 /***********************************************************************
2463 * SWP_DoWinPosChanging
2465 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2466 RECT* pNewWindowRect, RECT* pNewClientRect )
2468 /* Send WM_WINDOWPOSCHANGING message */
2470 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2471 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2473 /* Calculate new position and size */
2475 *pNewWindowRect = wndPtr->rectWindow;
2476 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2477 : wndPtr->rectClient;
2479 if (!(pWinpos->flags & SWP_NOSIZE))
2481 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2482 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2484 if (!(pWinpos->flags & SWP_NOMOVE))
2486 pNewWindowRect->left = pWinpos->x;
2487 pNewWindowRect->top = pWinpos->y;
2488 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2489 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2491 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2492 pWinpos->y - wndPtr->rectWindow.top );
2495 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2496 return TRUE;
2499 /***********************************************************************
2500 * SWP_DoNCCalcSize
2502 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2503 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2505 UINT wvrFlags = 0;
2507 /* Send WM_NCCALCSIZE message to get new client area */
2508 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2510 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2511 &wndPtr->rectWindow, &wndPtr->rectClient,
2512 pWinpos, pNewClientRect );
2514 /* FIXME: WVR_ALIGNxxx */
2516 if( pNewClientRect->left != wndPtr->rectClient.left ||
2517 pNewClientRect->top != wndPtr->rectClient.top )
2518 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2520 if( (pNewClientRect->right - pNewClientRect->left !=
2521 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2522 (pNewClientRect->bottom - pNewClientRect->top !=
2523 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2524 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2526 else
2527 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2528 pNewClientRect->top != wndPtr->rectClient.top) )
2529 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2530 return wvrFlags;
2533 /***********************************************************************
2534 * SetWindowPos (USER.2)
2536 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2537 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2539 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2542 /***********************************************************************
2543 * SetWindowPos (USER32.520)
2545 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2546 INT x, INT y, INT cx, INT cy, UINT flags )
2548 WINDOWPOS winpos;
2549 WND * wndPtr,*wndTemp;
2550 RECT newWindowRect, newClientRect;
2551 RECT oldWindowRect, oldClientRect;
2552 HRGN visRgn = 0;
2553 UINT wvrFlags = 0, uFlags = 0;
2554 BOOL retvalue, resync = FALSE, bChangePos;
2555 HWND hwndActive = 0;
2557 /* Get current active window from the active queue */
2558 if ( hActiveQueue )
2560 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2561 if ( pActiveQueue )
2563 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2564 QUEUE_Unlock( pActiveQueue );
2568 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2569 hwnd, x, y, x+cx, y+cy, flags);
2571 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2572 flags &= ~SWP_WINE_NOHOSTMOVE;
2575 /* ------------------------------------------------------------------------ CHECKS */
2577 /* Check window handle */
2579 if (hwnd == GetDesktopWindow()) return FALSE;
2580 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2582 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2583 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2585 /* Fix redundant flags */
2587 if(wndPtr->dwStyle & WS_VISIBLE)
2588 flags &= ~SWP_SHOWWINDOW;
2589 else
2591 if (!(flags & SWP_SHOWWINDOW))
2592 flags |= SWP_NOREDRAW;
2593 flags &= ~SWP_HIDEWINDOW;
2596 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2598 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2599 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2600 flags |= SWP_NOSIZE; /* Already the right size */
2602 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2603 flags |= SWP_NOMOVE; /* Already the right position */
2605 if (hwnd == hwndActive)
2606 flags |= SWP_NOACTIVATE; /* Already active */
2607 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2609 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2611 flags &= ~SWP_NOZORDER;
2612 hwndInsertAfter = HWND_TOP;
2613 goto Pos;
2617 /* Check hwndInsertAfter */
2619 /* FIXME: TOPMOST not supported yet */
2620 if ((hwndInsertAfter == HWND_TOPMOST) ||
2621 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2623 /* hwndInsertAfter must be a sibling of the window */
2624 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2626 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2628 if( wnd ) {
2629 if( wnd->parent != wndPtr->parent )
2631 retvalue = FALSE;
2632 WIN_ReleaseWndPtr(wnd);
2633 goto END;
2635 /* don't need to change the Zorder of hwnd if it's already inserted
2636 * after hwndInsertAfter or when inserting hwnd after itself.
2638 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2640 WIN_ReleaseWndPtr(wnd);
2643 Pos: /* ------------------------------------------------------------------------ MAIN part */
2645 /* Fill the WINDOWPOS structure */
2647 winpos.hwnd = hwnd;
2648 winpos.hwndInsertAfter = hwndInsertAfter;
2649 winpos.x = x;
2650 winpos.y = y;
2651 winpos.cx = cx;
2652 winpos.cy = cy;
2653 winpos.flags = flags;
2655 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2657 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2659 if( wndPtr->parent == WIN_GetDesktop() )
2660 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2661 hwndInsertAfter, winpos.flags );
2662 WIN_ReleaseDesktop();
2665 if(!(wndPtr->flags & WIN_NATIVE) )
2667 if( hwndInsertAfter == HWND_TOP )
2668 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2669 else
2670 if( hwndInsertAfter == HWND_BOTTOM )
2671 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2672 else
2673 if( !(winpos.flags & SWP_NOZORDER) )
2674 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2675 winpos.flags |= SWP_NOZORDER;
2677 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2678 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2679 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2681 /* get a previous visible region for SWP_CopyValidBits() */
2682 DWORD dflags = DCX_WINDOW;
2684 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2685 dflags |= DCX_CLIPSIBLINGS;
2687 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2691 /* Common operations */
2693 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2695 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2697 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2698 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2701 /* Reset active DCEs */
2703 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2704 wndPtr->dwStyle & WS_VISIBLE) ||
2705 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2707 RECT rect;
2709 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2710 DCE_InvalidateDCE(wndPtr, &rect);
2713 oldWindowRect = wndPtr->rectWindow;
2714 oldClientRect = wndPtr->rectClient;
2716 /* Find out if we have to redraw the whole client rect */
2718 if( oldClientRect.bottom - oldClientRect.top ==
2719 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2721 if( oldClientRect.right - oldClientRect.left ==
2722 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2724 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2725 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2727 uFlags |= SWP_EX_NOCOPY;
2730 * Use this later in CopyValidBits()
2732 else if( 0 )
2733 uFlags |= SWP_EX_NONCLIENT;
2736 /* FIXME: actually do something with WVR_VALIDRECTS */
2738 wndPtr->rectWindow = newWindowRect;
2739 wndPtr->rectClient = newClientRect;
2741 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2743 BOOL bCallDriver = TRUE;
2744 HWND tempInsertAfter = winpos.hwndInsertAfter;
2746 winpos.hwndInsertAfter = hwndInsertAfter;
2748 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2750 /* This is the only place where we need to force repainting of the contents
2751 of windows created by the host window system, all other cases go through the
2752 expose event handling */
2754 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2756 cx = newWindowRect.right - newWindowRect.left;
2757 cy = newWindowRect.bottom - newWindowRect.top;
2759 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2760 winpos.hwndInsertAfter = tempInsertAfter;
2761 bCallDriver = FALSE;
2763 if( winpos.flags & SWP_NOCLIENTMOVE )
2764 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2765 else
2767 /* client area moved but window extents remained the same, copy valid bits */
2769 visRgn = CreateRectRgn( 0, 0, cx, cy );
2770 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2771 uFlags | SWP_EX_PAINTSELF );
2776 if( bCallDriver )
2778 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2780 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2781 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2782 !(uFlags & SWP_EX_NOCOPY) )
2784 /* The origin of the client rect didn't move so we can try to repaint
2785 * only the nonclient area by setting bit gravity hint for the host window system.
2788 if( !(wndPtr->flags & WIN_MANAGED) )
2790 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2791 newWindowRect.bottom - newWindowRect.top);
2792 RECT rcn = newClientRect;
2793 RECT rco = oldClientRect;
2795 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2796 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2797 IntersectRect( &rcn, &rcn, &rco );
2798 visRgn = CreateRectRgnIndirect( &rcn );
2799 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2800 DeleteObject( hrgn );
2801 uFlags = SWP_EX_PAINTSELF;
2803 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2805 else
2806 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2809 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2810 winpos.hwndInsertAfter = tempInsertAfter;
2813 if( winpos.flags & SWP_SHOWWINDOW )
2815 HWND focus, curr;
2817 wndPtr->dwStyle |= WS_VISIBLE;
2819 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2821 /* focus was set to unmapped window, reset host focus
2822 * since the window is now visible */
2824 focus = curr = GetFocus();
2825 while (curr)
2827 if (curr == hwnd)
2829 WND *pFocus = WIN_FindWndPtr( focus );
2830 if (pFocus)
2831 pFocus->pDriver->pSetFocus(pFocus);
2832 WIN_ReleaseWndPtr(pFocus);
2833 break;
2835 curr = GetParent(curr);
2839 else /* -------------------------------------------- emulated window */
2841 if( winpos.flags & SWP_SHOWWINDOW )
2843 wndPtr->dwStyle |= WS_VISIBLE;
2844 uFlags |= SWP_EX_PAINTSELF;
2845 visRgn = 1; /* redraw the whole window */
2847 else if( !(winpos.flags & SWP_NOREDRAW) )
2849 if( winpos.flags & SWP_HIDEWINDOW )
2851 if( visRgn > 1 ) /* map to parent */
2852 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2853 else
2854 visRgn = 0;
2856 else
2858 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2860 /* if window was not resized and not moved try to repaint itself */
2861 if((winpos.flags & SWP_AGG_NOGEOMETRYCHANGE) == SWP_AGG_NOGEOMETRYCHANGE)
2862 uFlags |= SWP_EX_PAINTSELF;
2863 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2864 &oldClientRect, uFlags);
2866 else
2868 /* nothing moved, redraw frame if needed */
2870 if( winpos.flags & SWP_FRAMECHANGED )
2871 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2872 if( visRgn )
2874 DeleteObject( visRgn );
2875 visRgn = 0;
2882 if( winpos.flags & SWP_HIDEWINDOW )
2884 wndPtr->dwStyle &= ~WS_VISIBLE;
2887 if (hwnd == CARET_GetHwnd())
2889 if( winpos.flags & SWP_HIDEWINDOW )
2890 HideCaret(hwnd);
2891 else if (winpos.flags & SWP_SHOWWINDOW)
2892 ShowCaret(hwnd);
2895 /* ------------------------------------------------------------------------ FINAL */
2897 if (wndPtr->flags & WIN_NATIVE)
2898 EVENT_Synchronize(); /* Synchronize with the host window system */
2900 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2902 /* Simulate a mouse event to set the cursor */
2903 int iWndsLocks = WIN_SuspendWndsLock();
2905 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2906 PosX, PosY, GetTickCount(), 0 );
2908 WIN_RestoreWndsLock(iWndsLocks);
2911 wndTemp = WIN_GetDesktop();
2913 /* repaint invalidated region (if any)
2915 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2916 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2919 if( visRgn )
2921 if( !(winpos.flags & SWP_NOREDRAW) )
2924 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2925 its parent and sibling and so on, and then erase the parent window
2926 back ground if the parent is either a top-level window or its parent's parent
2927 is top-level window. Rely on the system to repaint other affected
2928 windows later on. */
2929 if( uFlags & SWP_EX_PAINTSELF )
2931 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2932 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2933 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2935 else
2937 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2938 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2939 RDW_EX_USEHRGN );
2942 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2944 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2945 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2948 if( visRgn != 1 )
2949 DeleteObject( visRgn );
2952 WIN_ReleaseDesktop();
2954 if (!(flags & SWP_NOACTIVATE))
2955 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2957 /* And last, send the WM_WINDOWPOSCHANGED message */
2959 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2961 if ( resync ||
2962 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2963 !(winpos.flags & SWP_NOSENDCHANGING)) )
2965 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2966 if (resync) EVENT_Synchronize();
2969 retvalue = TRUE;
2970 END:
2971 WIN_ReleaseWndPtr(wndPtr);
2972 return retvalue;
2976 /***********************************************************************
2977 * BeginDeferWindowPos16 (USER.259)
2979 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2981 return BeginDeferWindowPos( count );
2985 /***********************************************************************
2986 * BeginDeferWindowPos (USER32.9)
2988 HDWP WINAPI BeginDeferWindowPos( INT count )
2990 HDWP handle;
2991 DWP *pDWP;
2993 if (count < 0)
2995 SetLastError(ERROR_INVALID_PARAMETER);
2996 return 0;
2998 /* Windows allows zero count, in which case it allocates context for 8 moves */
2999 if (count == 0) count = 8;
3001 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
3002 if (!handle) return 0;
3003 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
3004 pDWP->actualCount = 0;
3005 pDWP->suggestedCount = count;
3006 pDWP->valid = TRUE;
3007 pDWP->wMagic = DWP_MAGIC;
3008 pDWP->hwndParent = 0;
3009 return handle;
3013 /***********************************************************************
3014 * DeferWindowPos16 (USER.260)
3016 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
3017 INT16 x, INT16 y, INT16 cx, INT16 cy,
3018 UINT16 flags )
3020 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3021 x, y, cx, cy, flags );
3025 /***********************************************************************
3026 * DeferWindowPos (USER32.128)
3028 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3029 INT x, INT y, INT cx, INT cy,
3030 UINT flags )
3032 DWP *pDWP;
3033 int i;
3034 HDWP newhdwp = hdwp,retvalue;
3035 /* HWND parent; */
3036 WND *pWnd;
3038 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3039 if (!pDWP) return 0;
3040 if (hwnd == GetDesktopWindow()) return 0;
3042 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3043 USER_HEAP_FREE( hdwp );
3044 return 0;
3047 /* Numega Bounds Checker Demo dislikes the following code.
3048 In fact, I've not been able to find any "same parent" requirement in any docu
3049 [AM 980509]
3051 #if 0
3052 /* All the windows of a DeferWindowPos() must have the same parent */
3053 parent = pWnd->parent->hwndSelf;
3054 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3055 else if (parent != pDWP->hwndParent)
3057 USER_HEAP_FREE( hdwp );
3058 retvalue = 0;
3059 goto END;
3061 #endif
3063 for (i = 0; i < pDWP->actualCount; i++)
3065 if (pDWP->winPos[i].hwnd == hwnd)
3067 /* Merge with the other changes */
3068 if (!(flags & SWP_NOZORDER))
3070 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3072 if (!(flags & SWP_NOMOVE))
3074 pDWP->winPos[i].x = x;
3075 pDWP->winPos[i].y = y;
3077 if (!(flags & SWP_NOSIZE))
3079 pDWP->winPos[i].cx = cx;
3080 pDWP->winPos[i].cy = cy;
3082 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3083 SWP_NOZORDER | SWP_NOREDRAW |
3084 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3085 SWP_NOOWNERZORDER);
3086 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3087 SWP_FRAMECHANGED);
3088 retvalue = hdwp;
3089 goto END;
3092 if (pDWP->actualCount >= pDWP->suggestedCount)
3094 newhdwp = USER_HEAP_REALLOC( hdwp,
3095 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3096 if (!newhdwp)
3098 retvalue = 0;
3099 goto END;
3101 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3102 pDWP->suggestedCount++;
3104 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3105 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3106 pDWP->winPos[pDWP->actualCount].x = x;
3107 pDWP->winPos[pDWP->actualCount].y = y;
3108 pDWP->winPos[pDWP->actualCount].cx = cx;
3109 pDWP->winPos[pDWP->actualCount].cy = cy;
3110 pDWP->winPos[pDWP->actualCount].flags = flags;
3111 pDWP->actualCount++;
3112 retvalue = newhdwp;
3113 END:
3114 WIN_ReleaseWndPtr(pWnd);
3115 return retvalue;
3119 /***********************************************************************
3120 * EndDeferWindowPos16 (USER.261)
3122 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3124 return EndDeferWindowPos( hdwp );
3128 /***********************************************************************
3129 * EndDeferWindowPos (USER32.173)
3131 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3133 DWP *pDWP;
3134 WINDOWPOS *winpos;
3135 BOOL res = TRUE;
3136 int i;
3138 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3139 if (!pDWP) return FALSE;
3140 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3142 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3143 winpos->x, winpos->y, winpos->cx,
3144 winpos->cy, winpos->flags ))) break;
3146 USER_HEAP_FREE( hdwp );
3147 return res;
3151 /***********************************************************************
3152 * TileChildWindows (USER.199)
3154 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3156 FIXME("(%04x, %d): stub\n", parent, action);
3159 /***********************************************************************
3160 * CascadeChildWindows (USER.198)
3162 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3164 FIXME("(%04x, %d): stub\n", parent, action);
3167 /***********************************************************************
3168 * SetProgmanWindow [USER32.522]
3170 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3172 hGlobalProgmanWindow = hwnd;
3173 return hGlobalProgmanWindow;
3176 /***********************************************************************
3177 * GetProgmanWindow [USER32.289]
3179 HRESULT WINAPI GetProgmanWindow ( )
3181 return hGlobalProgmanWindow;
3184 /***********************************************************************
3185 * SetShellWindowEx [USER32.531]
3186 * hwndProgman = Progman[Program Manager]
3187 * |-> SHELLDLL_DefView
3188 * hwndListView = | |-> SysListView32
3189 * | | |-> tooltips_class32
3190 * | |
3191 * | |-> SysHeader32
3192 * |
3193 * |-> ProxyTarget
3195 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3197 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3198 hGlobalShellWindow = hwndProgman;
3199 return hGlobalShellWindow;
3203 /***********************************************************************
3204 * SetTaskmanWindow [USER32.537]
3205 * NOTES
3206 * hwnd = MSTaskSwWClass
3207 * |-> SysTabControl32
3209 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3211 hGlobalTaskmanWindow = hwnd;
3212 return hGlobalTaskmanWindow;
3215 /***********************************************************************
3216 * GetTaskmanWindow [USER32.304]
3218 HRESULT WINAPI GetTaskmanWindow ( )
3220 return hGlobalTaskmanWindow;