Fixed return value of CDROM_GetLabel if CDROM_Open failed (e.g. no
[wine/multimedia.git] / windows / winpos.c
blob013dd9055d0670b54545dfaa6d42adc5ab241a29
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;
311 if (wndPtr->hrgnWnd)
313 /* delete previous region */
314 DeleteObject(wndPtr->hrgnWnd);
315 wndPtr->hrgnWnd = 0;
318 /* we'd like to set it back to 0 */
319 if (hrgn == 0)
321 GetWindowRect(hwnd, &tempRect);
323 else
325 /* verify that region really exists */
326 if (GetRgnBox(hrgn, &tempRect) == ERROR) goto done;
329 /* valid region handle */
330 wndPtr->hrgnWnd = hrgn;
331 SetWindowPos( hwnd, NULL, tempRect.left, tempRect.top,
332 tempRect.right - tempRect.left, tempRect.bottom - tempRect.top,
333 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE |
334 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
336 wndPtr->pDriver->pSetWindowRgn(wndPtr, hrgn);
338 ret = TRUE;
340 done:
341 WIN_ReleaseWndPtr(wndPtr);
342 return ret;
345 /***********************************************************************
346 * SetWindowRgn16
348 INT16 WINAPI SetWindowRgn16( HWND16 hwnd, HRGN16 hrgn,BOOL16 bRedraw)
352 FIXME("SetWindowRgn16: stub\n");
353 return TRUE;
357 /***********************************************************************
358 * GetClientRect16 (USER.33)
360 void WINAPI GetClientRect16( HWND16 hwnd, LPRECT16 rect )
362 WND * wndPtr = WIN_FindWndPtr( hwnd );
364 rect->left = rect->top = rect->right = rect->bottom = 0;
365 if (wndPtr)
367 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
368 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
370 WIN_ReleaseWndPtr(wndPtr);
374 /***********************************************************************
375 * GetClientRect (USER.220)
377 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
379 WND * wndPtr = WIN_FindWndPtr( hwnd );
381 rect->left = rect->top = rect->right = rect->bottom = 0;
382 if (!wndPtr) return FALSE;
383 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
384 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
386 WIN_ReleaseWndPtr(wndPtr);
387 return TRUE;
391 /*******************************************************************
392 * ClientToScreen16 (USER.28)
394 void WINAPI ClientToScreen16( HWND16 hwnd, LPPOINT16 lppnt )
396 MapWindowPoints16( hwnd, 0, lppnt, 1 );
400 /*******************************************************************
401 * ClientToScreen (USER32.52)
403 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
405 MapWindowPoints( hwnd, 0, lppnt, 1 );
406 return TRUE;
410 /*******************************************************************
411 * ScreenToClient16 (USER.29)
413 void WINAPI ScreenToClient16( HWND16 hwnd, LPPOINT16 lppnt )
415 MapWindowPoints16( 0, hwnd, lppnt, 1 );
419 /*******************************************************************
420 * ScreenToClient (USER32.447)
422 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
424 MapWindowPoints( 0, hwnd, lppnt, 1 );
425 return TRUE;
429 /***********************************************************************
430 * WINPOS_WindowFromPoint
432 * Find the window and hittest for a given point.
434 INT16 WINPOS_WindowFromPoint( WND* wndScope, POINT16 pt, WND **ppWnd )
436 WND *wndPtr;
437 INT16 hittest = HTERROR;
438 INT16 retvalue;
439 POINT16 xy = pt;
441 TRACE("scope %04x %d,%d\n", wndScope->hwndSelf, pt.x, pt.y);
442 *ppWnd = NULL;
443 wndPtr = WIN_LockWndPtr(wndScope->child);
445 if( wndScope->dwStyle & WS_DISABLED )
447 retvalue = HTERROR;
448 goto end;
451 if( wndScope->flags & WIN_MANAGED )
453 /* In managed mode we have to check wndScope first as it is also
454 * a window which received the mouse event. */
456 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
457 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
458 goto hittest;
460 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
462 for (;;)
464 while (wndPtr)
466 /* If point is in window, and window is visible, and it */
467 /* is enabled (or it's a top-level window), then explore */
468 /* its children. Otherwise, go to the next window. */
470 if ((wndPtr->dwStyle & WS_VISIBLE) &&
471 (!(wndPtr->dwStyle & WS_DISABLED) ||
472 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
473 (wndPtr->hrgnWnd ?
474 PtInRegion(wndPtr->hrgnWnd, xy.x - wndPtr->rectWindow.left,
475 xy.y - wndPtr->rectWindow.top) :
476 ((xy.x >= wndPtr->rectWindow.left) &&
477 (xy.x < wndPtr->rectWindow.right) &&
478 (xy.y >= wndPtr->rectWindow.top) &&
479 (xy.y < wndPtr->rectWindow.bottom))))
481 TRACE("%d,%d is inside %04x\n", xy.x, xy.y, wndPtr->hwndSelf);
482 *ppWnd = wndPtr; /* Got a suitable window */
484 /* If window is minimized or disabled, return at once */
485 if (wndPtr->dwStyle & WS_MINIMIZE)
487 retvalue = HTCAPTION;
488 goto end;
490 if (wndPtr->dwStyle & WS_DISABLED)
492 retvalue = HTERROR;
493 goto end;
496 /* If point is not in client area, ignore the children */
497 if ((xy.x < wndPtr->rectClient.left) ||
498 (xy.x >= wndPtr->rectClient.right) ||
499 (xy.y < wndPtr->rectClient.top) ||
500 (xy.y >= wndPtr->rectClient.bottom)) break;
502 xy.x -= wndPtr->rectClient.left;
503 xy.y -= wndPtr->rectClient.top;
504 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
506 else
508 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
512 hittest:
513 /* If nothing found, try the scope window */
514 if (!*ppWnd) *ppWnd = wndScope;
516 /* Send the WM_NCHITTEST message (only if to the same task) */
517 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
519 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
520 0, MAKELONG( pt.x, pt.y ) );
521 if (hittest != HTTRANSPARENT)
523 retvalue = hittest; /* Found the window */
524 goto end;
527 else
529 retvalue = HTCLIENT;
530 goto end;
533 /* If no children found in last search, make point relative to parent */
534 if (!wndPtr)
536 xy.x += (*ppWnd)->rectClient.left;
537 xy.y += (*ppWnd)->rectClient.top;
540 /* Restart the search from the next sibling */
541 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
542 *ppWnd = (*ppWnd)->parent;
545 end:
546 WIN_ReleaseWndPtr(wndPtr);
547 return retvalue;
551 /*******************************************************************
552 * WindowFromPoint16 (USER.30)
554 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
556 WND *pWnd;
557 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
558 WIN_ReleaseDesktop();
559 return pWnd->hwndSelf;
563 /*******************************************************************
564 * WindowFromPoint (USER32.582)
566 HWND WINAPI WindowFromPoint( POINT pt )
568 WND *pWnd;
569 POINT16 pt16;
570 CONV_POINT32TO16( &pt, &pt16 );
571 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
572 WIN_ReleaseDesktop();
573 return (HWND)pWnd->hwndSelf;
577 /*******************************************************************
578 * ChildWindowFromPoint16 (USER.191)
580 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
582 POINT pt32;
583 CONV_POINT16TO32( &pt, &pt32 );
584 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
588 /*******************************************************************
589 * ChildWindowFromPoint (USER32.49)
591 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
593 /* pt is in the client coordinates */
595 WND* wnd = WIN_FindWndPtr(hwndParent);
596 RECT rect;
597 HWND retvalue;
599 if( !wnd ) return 0;
601 /* get client rect fast */
602 rect.top = rect.left = 0;
603 rect.right = wnd->rectClient.right - wnd->rectClient.left;
604 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
606 if (!PtInRect( &rect, pt ))
608 retvalue = 0;
609 goto end;
611 WIN_UpdateWndPtr(&wnd,wnd->child);
612 while ( wnd )
614 if (PtInRect( &wnd->rectWindow, pt ))
616 retvalue = wnd->hwndSelf;
617 goto end;
619 WIN_UpdateWndPtr(&wnd,wnd->next);
621 retvalue = hwndParent;
622 end:
623 WIN_ReleaseWndPtr(wnd);
624 return retvalue;
627 /*******************************************************************
628 * ChildWindowFromPointEx16 (USER.50)
630 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
632 POINT pt32;
633 CONV_POINT16TO32( &pt, &pt32 );
634 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
638 /*******************************************************************
639 * ChildWindowFromPointEx (USER32.50)
641 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
642 UINT uFlags)
644 /* pt is in the client coordinates */
646 WND* wnd = WIN_FindWndPtr(hwndParent);
647 RECT rect;
648 HWND retvalue;
650 if( !wnd ) return 0;
652 /* get client rect fast */
653 rect.top = rect.left = 0;
654 rect.right = wnd->rectClient.right - wnd->rectClient.left;
655 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
657 if (!PtInRect( &rect, pt ))
659 retvalue = 0;
660 goto end;
662 WIN_UpdateWndPtr(&wnd,wnd->child);
664 while ( wnd )
666 if (PtInRect( &wnd->rectWindow, pt )) {
667 if ( (uFlags & CWP_SKIPINVISIBLE) &&
668 !(wnd->dwStyle & WS_VISIBLE) );
669 else if ( (uFlags & CWP_SKIPDISABLED) &&
670 (wnd->dwStyle & WS_DISABLED) );
671 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
672 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
673 else
675 retvalue = wnd->hwndSelf;
676 goto end;
680 WIN_UpdateWndPtr(&wnd,wnd->next);
682 retvalue = hwndParent;
683 end:
684 WIN_ReleaseWndPtr(wnd);
685 return retvalue;
689 /*******************************************************************
690 * WINPOS_GetWinOffset
692 * Calculate the offset between the origin of the two windows. Used
693 * to implement MapWindowPoints.
695 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
696 POINT *offset )
698 WND * wndPtr = 0;
700 offset->x = offset->y = 0;
701 if (hwndFrom == hwndTo ) return;
703 /* Translate source window origin to screen coords */
704 if (hwndFrom)
706 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
708 ERR("bad hwndFrom = %04x\n",hwndFrom);
709 return;
711 while (wndPtr->parent)
713 offset->x += wndPtr->rectClient.left;
714 offset->y += wndPtr->rectClient.top;
715 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
717 WIN_ReleaseWndPtr(wndPtr);
720 /* Translate origin to destination window coords */
721 if (hwndTo)
723 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
725 ERR("bad hwndTo = %04x\n", hwndTo );
726 return;
728 while (wndPtr->parent)
730 offset->x -= wndPtr->rectClient.left;
731 offset->y -= wndPtr->rectClient.top;
732 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
734 WIN_ReleaseWndPtr(wndPtr);
739 /*******************************************************************
740 * MapWindowPoints16 (USER.258)
742 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
743 LPPOINT16 lppt, UINT16 count )
745 POINT offset;
747 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
748 while (count--)
750 lppt->x += offset.x;
751 lppt->y += offset.y;
752 lppt++;
757 /*******************************************************************
758 * MapWindowPoints (USER32.386)
760 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
761 LPPOINT lppt, UINT count )
763 POINT offset;
765 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
766 while (count--)
768 lppt->x += offset.x;
769 lppt->y += offset.y;
770 lppt++;
772 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
776 /***********************************************************************
777 * IsIconic16 (USER.31)
779 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
781 return IsIconic(hWnd);
785 /***********************************************************************
786 * IsIconic (USER32.345)
788 BOOL WINAPI IsIconic(HWND hWnd)
790 BOOL retvalue;
791 WND * wndPtr = WIN_FindWndPtr(hWnd);
792 if (wndPtr == NULL) return FALSE;
793 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
794 WIN_ReleaseWndPtr(wndPtr);
795 return retvalue;
799 /***********************************************************************
800 * IsZoomed (USER.272)
802 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
804 return IsZoomed(hWnd);
808 /***********************************************************************
809 * IsZoomed (USER.352)
811 BOOL WINAPI IsZoomed(HWND hWnd)
813 BOOL retvalue;
814 WND * wndPtr = WIN_FindWndPtr(hWnd);
815 if (wndPtr == NULL) return FALSE;
816 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
817 WIN_ReleaseWndPtr(wndPtr);
818 return retvalue;
822 /*******************************************************************
823 * GetActiveWindow (USER.60)
825 HWND16 WINAPI GetActiveWindow16(void)
827 return (HWND16)GetActiveWindow();
830 /*******************************************************************
831 * GetActiveWindow (USER32.205)
833 HWND WINAPI GetActiveWindow(void)
835 MESSAGEQUEUE *pCurMsgQ = 0;
836 HWND hwndActive = 0;
838 /* Get the messageQ for the current thread */
839 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
841 WARN("\tCurrent message queue not found. Exiting!\n" );
842 return 0;
845 /* Return the current active window from the perQ data of the current message Q */
846 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
848 QUEUE_Unlock( pCurMsgQ );
849 return hwndActive;
853 /*******************************************************************
854 * WINPOS_CanActivate
856 static BOOL WINPOS_CanActivate(WND* pWnd)
858 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
859 == WS_VISIBLE ) ) return TRUE;
860 return FALSE;
864 /*******************************************************************
865 * SetActiveWindow16 (USER.59)
867 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
869 return SetActiveWindow(hwnd);
873 /*******************************************************************
874 * SetActiveWindow (USER32.463)
876 HWND WINAPI SetActiveWindow( HWND hwnd )
878 HWND prev = 0;
879 WND *wndPtr = WIN_FindWndPtr( hwnd );
880 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
882 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
884 prev = 0;
885 goto end;
888 /* Get the messageQ for the current thread */
889 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
891 WARN("\tCurrent message queue not found. Exiting!\n" );
892 goto CLEANUP;
895 /* Retrieve the message queue associated with this window */
896 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
897 if ( !pMsgQ )
899 WARN("\tWindow message queue not found. Exiting!\n" );
900 goto CLEANUP;
903 /* Make sure that the window is associated with the calling threads
904 * message queue. It must share the same perQ data.
907 if ( pCurMsgQ->pQData != pMsgQ->pQData )
908 goto CLEANUP;
910 /* Save current active window */
911 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
913 WINPOS_SetActiveWindow( hwnd, 0, 0 );
915 CLEANUP:
916 /* Unlock the queues before returning */
917 if ( pMsgQ )
918 QUEUE_Unlock( pMsgQ );
919 if ( pCurMsgQ )
920 QUEUE_Unlock( pCurMsgQ );
922 end:
923 WIN_ReleaseWndPtr(wndPtr);
924 return prev;
928 /*******************************************************************
929 * GetForegroundWindow16 (USER.608)
931 HWND16 WINAPI GetForegroundWindow16(void)
933 return (HWND16)GetForegroundWindow();
937 /*******************************************************************
938 * SetForegroundWindow16 (USER.609)
940 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
942 return SetForegroundWindow( hwnd );
946 /*******************************************************************
947 * GetForegroundWindow (USER32.241)
949 HWND WINAPI GetForegroundWindow(void)
951 HWND hwndActive = 0;
953 /* Get the foreground window (active window of hActiveQueue) */
954 if ( hActiveQueue )
956 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
957 if ( pActiveQueue )
958 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
960 QUEUE_Unlock( pActiveQueue );
963 return hwndActive;
966 /*******************************************************************
967 * SetForegroundWindow (USER32.482)
969 BOOL WINAPI SetForegroundWindow( HWND hwnd )
971 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
975 /*******************************************************************
976 * GetShellWindow16 (USER.600)
978 HWND16 WINAPI GetShellWindow16(void)
980 return GetShellWindow();
983 /*******************************************************************
984 * SetShellWindow (USER32.504)
986 HWND WINAPI SetShellWindow(HWND hwndshell)
987 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
989 hGlobalShellWindow = hwndshell;
990 return hGlobalShellWindow;
994 /*******************************************************************
995 * GetShellWindow (USER32.287)
997 HWND WINAPI GetShellWindow(void)
998 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
1000 return hGlobalShellWindow;
1004 /***********************************************************************
1005 * BringWindowToTop16 (USER.45)
1007 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1009 return BringWindowToTop(hwnd);
1013 /***********************************************************************
1014 * BringWindowToTop (USER32.11)
1016 BOOL WINAPI BringWindowToTop( HWND hwnd )
1018 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1022 /***********************************************************************
1023 * MoveWindow16 (USER.56)
1025 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1026 BOOL16 repaint )
1028 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1032 /***********************************************************************
1033 * MoveWindow (USER32.399)
1035 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1036 BOOL repaint )
1038 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1039 if (!repaint) flags |= SWP_NOREDRAW;
1040 TRACE("%04x %d,%d %dx%d %d\n",
1041 hwnd, x, y, cx, cy, repaint );
1042 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1045 /***********************************************************************
1046 * WINPOS_InitInternalPos
1048 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1049 LPRECT restoreRect )
1051 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1052 atomInternalPos );
1053 if( !lpPos )
1055 /* this happens when the window is minimized/maximized
1056 * for the first time (rectWindow is not adjusted yet) */
1058 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1059 if( !lpPos ) return NULL;
1061 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1062 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1063 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1064 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1067 if( wnd->dwStyle & WS_MINIMIZE )
1068 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1069 else if( wnd->dwStyle & WS_MAXIMIZE )
1070 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1071 else if( restoreRect )
1072 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1074 return lpPos;
1077 /***********************************************************************
1078 * WINPOS_RedrawIconTitle
1080 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1082 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1083 if( lpPos )
1085 if( lpPos->hwndIconTitle )
1087 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1088 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1089 return TRUE;
1092 return FALSE;
1095 /***********************************************************************
1096 * WINPOS_ShowIconTitle
1098 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1100 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1102 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1104 HWND16 hWnd = lpPos->hwndIconTitle;
1106 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1108 if( !hWnd )
1109 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1110 if( bShow )
1112 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1114 if( !(pWnd->dwStyle & WS_VISIBLE) )
1116 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1117 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1118 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1120 WIN_ReleaseWndPtr(pWnd);
1123 else ShowWindow( hWnd, SW_HIDE );
1125 return FALSE;
1128 /*******************************************************************
1129 * WINPOS_GetMinMaxInfo
1131 * Get the minimized and maximized information for a window.
1133 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1134 POINT *minTrack, POINT *maxTrack )
1136 LPINTERNALPOS lpPos;
1137 MINMAXINFO MinMax;
1138 INT xinc, yinc;
1140 /* Compute default values */
1142 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1143 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1144 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1145 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1146 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1147 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1149 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1150 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1152 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1153 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1155 else
1157 xinc = yinc = 0;
1158 if (HAS_THICKFRAME(wndPtr->dwStyle))
1160 xinc += GetSystemMetrics(SM_CXFRAME);
1161 yinc += GetSystemMetrics(SM_CYFRAME);
1163 if (wndPtr->dwStyle & WS_BORDER)
1165 xinc += GetSystemMetrics(SM_CXBORDER);
1166 yinc += GetSystemMetrics(SM_CYBORDER);
1169 MinMax.ptMaxSize.x += 2 * xinc;
1170 MinMax.ptMaxSize.y += 2 * yinc;
1172 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1173 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1174 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1175 else
1177 MinMax.ptMaxPosition.x = -xinc;
1178 MinMax.ptMaxPosition.y = -yinc;
1181 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1183 /* Some sanity checks */
1185 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1186 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1187 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1188 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1189 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1190 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1191 MinMax.ptMinTrackSize.x );
1192 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1193 MinMax.ptMinTrackSize.y );
1195 if (maxSize) *maxSize = MinMax.ptMaxSize;
1196 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1197 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1198 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1201 /***********************************************************************
1202 * WINPOS_MinMaximize
1204 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1205 * This function assumes that 'cmd' is different from the current window
1206 * state.
1208 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1210 UINT swpFlags = 0;
1211 POINT pt, size;
1212 LPINTERNALPOS lpPos;
1214 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1216 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1217 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1219 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1221 if( wndPtr->dwStyle & WS_MINIMIZE )
1223 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1224 return (SWP_NOSIZE | SWP_NOMOVE);
1225 swpFlags |= SWP_NOCOPYBITS;
1227 switch( cmd )
1229 case SW_MINIMIZE:
1230 if( wndPtr->dwStyle & WS_MAXIMIZE)
1232 wndPtr->flags |= WIN_RESTORE_MAX;
1233 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1235 else
1236 wndPtr->flags &= ~WIN_RESTORE_MAX;
1237 wndPtr->dwStyle |= WS_MINIMIZE;
1239 if( wndPtr->flags & WIN_NATIVE )
1240 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1241 swpFlags |= MINMAX_NOSWP;
1243 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1245 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1246 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1247 swpFlags |= SWP_NOCOPYBITS;
1248 break;
1250 case SW_MAXIMIZE:
1251 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1252 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1253 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1255 if( wndPtr->dwStyle & WS_MINIMIZE )
1257 if( wndPtr->flags & WIN_NATIVE )
1258 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1259 swpFlags |= MINMAX_NOSWP;
1261 WINPOS_ShowIconTitle( wndPtr, FALSE );
1262 wndPtr->dwStyle &= ~WS_MINIMIZE;
1264 wndPtr->dwStyle |= WS_MAXIMIZE;
1266 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1267 size.x, size.y );
1268 break;
1270 case SW_RESTORE:
1271 if( wndPtr->dwStyle & WS_MINIMIZE )
1273 if( wndPtr->flags & WIN_NATIVE )
1274 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1275 swpFlags |= MINMAX_NOSWP;
1277 wndPtr->dwStyle &= ~WS_MINIMIZE;
1278 WINPOS_ShowIconTitle( wndPtr, FALSE );
1280 if( wndPtr->flags & WIN_RESTORE_MAX)
1282 /* Restore to maximized position */
1283 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1284 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1285 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1286 wndPtr->dwStyle |= WS_MAXIMIZE;
1287 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1288 break;
1291 else
1292 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1293 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1295 /* Restore to normal position */
1297 *lpRect = lpPos->rectNormal;
1298 lpRect->right -= lpRect->left;
1299 lpRect->bottom -= lpRect->top;
1301 break;
1303 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1304 return swpFlags;
1307 /***********************************************************************
1308 * ShowWindowAsync (USER32.535)
1310 * doesn't wait; returns immediately.
1311 * used by threads to toggle windows in other (possibly hanging) threads
1313 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1315 /* FIXME: does ShowWindow() return immediately ? */
1316 return ShowWindow(hwnd, cmd);
1320 /***********************************************************************
1321 * ShowWindow16 (USER.42)
1323 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1325 return ShowWindow(hwnd,cmd);
1329 /***********************************************************************
1330 * ShowWindow (USER32.534)
1332 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1334 WND* wndPtr = WIN_FindWndPtr( hwnd );
1335 BOOL wasVisible, showFlag;
1336 RECT16 newPos = {0, 0, 0, 0};
1337 UINT swp = 0;
1339 if (!wndPtr) return FALSE;
1341 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1343 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1345 switch(cmd)
1347 case SW_HIDE:
1348 if (!wasVisible) goto END;;
1349 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1350 SWP_NOACTIVATE | SWP_NOZORDER;
1351 break;
1353 case SW_SHOWMINNOACTIVE:
1354 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1355 /* fall through */
1356 case SW_SHOWMINIMIZED:
1357 swp |= SWP_SHOWWINDOW;
1358 /* fall through */
1359 case SW_MINIMIZE:
1360 swp |= SWP_FRAMECHANGED;
1361 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1362 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1363 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1364 break;
1366 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1367 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1368 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1369 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1370 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1371 break;
1373 case SW_SHOWNA:
1374 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1375 /* fall through */
1376 case SW_SHOW:
1377 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1380 * ShowWindow has a little peculiar behavior that if the
1381 * window is already the topmost window, it will not
1382 * activate it.
1384 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1385 swp |= SWP_NOACTIVATE;
1387 break;
1389 case SW_SHOWNOACTIVATE:
1390 swp |= SWP_NOZORDER;
1391 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1392 /* fall through */
1393 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1394 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1395 case SW_RESTORE:
1396 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1398 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1399 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1400 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1401 break;
1404 showFlag = (cmd != SW_HIDE);
1405 if (showFlag != wasVisible)
1407 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1408 if (!IsWindow( hwnd )) goto END;
1411 if ((wndPtr->dwStyle & WS_CHILD) &&
1412 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1413 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1415 /* Don't call SetWindowPos() on invisible child windows */
1416 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1417 else wndPtr->dwStyle |= WS_VISIBLE;
1419 else
1421 /* We can't activate a child window */
1422 if ((wndPtr->dwStyle & WS_CHILD) &&
1423 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1424 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1425 if (!(swp & MINMAX_NOSWP))
1427 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1428 newPos.right, newPos.bottom, LOWORD(swp) );
1429 if (cmd == SW_HIDE)
1431 /* FIXME: This will cause the window to be activated irrespective
1432 * of whether it is owned by the same thread. Has to be done
1433 * asynchronously.
1436 if (hwnd == GetActiveWindow())
1437 WINPOS_ActivateOtherWindow(wndPtr);
1439 /* Revert focus to parent */
1440 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1441 SetFocus( GetParent(hwnd) );
1444 if (!IsWindow( hwnd )) goto END;
1445 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1448 if (wndPtr->flags & WIN_NEED_SIZE)
1450 /* should happen only in CreateWindowEx() */
1451 int wParam = SIZE_RESTORED;
1453 wndPtr->flags &= ~WIN_NEED_SIZE;
1454 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1455 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1456 SendMessageA( hwnd, WM_SIZE, wParam,
1457 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1458 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1459 SendMessageA( hwnd, WM_MOVE, 0,
1460 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1463 END:
1464 WIN_ReleaseWndPtr(wndPtr);
1465 return wasVisible;
1469 /***********************************************************************
1470 * GetInternalWindowPos16 (USER.460)
1472 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1473 LPPOINT16 ptIcon )
1475 WINDOWPLACEMENT16 wndpl;
1476 if (GetWindowPlacement16( hwnd, &wndpl ))
1478 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1479 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1480 return wndpl.showCmd;
1482 return 0;
1486 /***********************************************************************
1487 * GetInternalWindowPos (USER32.245)
1489 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1490 LPPOINT ptIcon )
1492 WINDOWPLACEMENT wndpl;
1493 if (GetWindowPlacement( hwnd, &wndpl ))
1495 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1496 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1497 return wndpl.showCmd;
1499 return 0;
1502 /***********************************************************************
1503 * GetWindowPlacement16 (USER.370)
1505 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1507 WND *pWnd = WIN_FindWndPtr( hwnd );
1508 LPINTERNALPOS lpPos;
1510 if(!pWnd ) return FALSE;
1512 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1513 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1514 wndpl->length = sizeof(*wndpl);
1515 if( pWnd->dwStyle & WS_MINIMIZE )
1516 wndpl->showCmd = SW_SHOWMINIMIZED;
1517 else
1518 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1519 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1520 if( pWnd->flags & WIN_RESTORE_MAX )
1521 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1522 else
1523 wndpl->flags = 0;
1524 wndpl->ptMinPosition = lpPos->ptIconPos;
1525 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1526 wndpl->rcNormalPosition = lpPos->rectNormal;
1528 WIN_ReleaseWndPtr(pWnd);
1529 return TRUE;
1533 /***********************************************************************
1534 * GetWindowPlacement (USER32.307)
1536 * Win95:
1537 * Fails if wndpl->length of Win95 (!) apps is invalid.
1539 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1541 if( pwpl32 )
1543 WINDOWPLACEMENT16 wpl;
1544 wpl.length = sizeof(wpl);
1545 if( GetWindowPlacement16( hwnd, &wpl ) )
1547 pwpl32->length = sizeof(*pwpl32);
1548 pwpl32->flags = wpl.flags;
1549 pwpl32->showCmd = wpl.showCmd;
1550 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1551 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1552 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1553 return TRUE;
1556 return FALSE;
1560 /***********************************************************************
1561 * WINPOS_SetPlacement
1563 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1564 UINT flags )
1566 WND *pWnd = WIN_FindWndPtr( hwnd );
1567 if( pWnd )
1569 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1570 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1572 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1573 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1574 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1576 if( pWnd->dwStyle & WS_MINIMIZE )
1578 WINPOS_ShowIconTitle( pWnd, FALSE );
1579 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1580 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1581 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1583 else if( pWnd->dwStyle & WS_MAXIMIZE )
1585 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1586 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1587 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1589 else if( flags & PLACE_RECT )
1590 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1591 lpPos->rectNormal.right - lpPos->rectNormal.left,
1592 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1593 SWP_NOZORDER | SWP_NOACTIVATE );
1595 ShowWindow( hwnd, wndpl->showCmd );
1596 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1598 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1600 /* SDK: ...valid only the next time... */
1601 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1603 WIN_ReleaseWndPtr(pWnd);
1604 return TRUE;
1606 return FALSE;
1610 /***********************************************************************
1611 * SetWindowPlacement16 (USER.371)
1613 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1615 return WINPOS_SetPlacement( hwnd, wndpl,
1616 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1619 /***********************************************************************
1620 * SetWindowPlacement (USER32.519)
1622 * Win95:
1623 * Fails if wndpl->length of Win95 (!) apps is invalid.
1625 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1627 if( pwpl32 )
1629 WINDOWPLACEMENT16 wpl;
1631 wpl.length = sizeof(WINDOWPLACEMENT16);
1632 wpl.flags = pwpl32->flags;
1633 wpl.showCmd = pwpl32->showCmd;
1634 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1635 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1636 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1637 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1638 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1639 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1640 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1641 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1643 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1645 return FALSE;
1649 /***********************************************************************
1650 * SetInternalWindowPos16 (USER.461)
1652 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1653 LPRECT16 rect, LPPOINT16 pt )
1655 if( IsWindow16(hwnd) )
1657 WINDOWPLACEMENT16 wndpl;
1658 UINT flags;
1660 wndpl.length = sizeof(wndpl);
1661 wndpl.showCmd = showCmd;
1662 wndpl.flags = flags = 0;
1664 if( pt )
1666 flags |= PLACE_MIN;
1667 wndpl.flags |= WPF_SETMINPOSITION;
1668 wndpl.ptMinPosition = *pt;
1670 if( rect )
1672 flags |= PLACE_RECT;
1673 wndpl.rcNormalPosition = *rect;
1675 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1680 /***********************************************************************
1681 * SetInternalWindowPos (USER32.483)
1683 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1684 LPRECT rect, LPPOINT pt )
1686 if( IsWindow(hwnd) )
1688 WINDOWPLACEMENT16 wndpl;
1689 UINT flags;
1691 wndpl.length = sizeof(wndpl);
1692 wndpl.showCmd = showCmd;
1693 wndpl.flags = flags = 0;
1695 if( pt )
1697 flags |= PLACE_MIN;
1698 wndpl.flags |= WPF_SETMINPOSITION;
1699 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1701 if( rect )
1703 flags |= PLACE_RECT;
1704 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1706 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1710 /*******************************************************************
1711 * WINPOS_SetActiveWindow
1713 * SetActiveWindow() back-end. This is the only function that
1714 * can assign active status to a window. It must be called only
1715 * for the top level windows.
1717 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1719 CBTACTIVATESTRUCT16* cbtStruct;
1720 WND* wndPtr=0, *wndTemp;
1721 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1722 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1723 WORD wIconized = 0;
1724 HWND hwndActive = 0;
1725 BOOL bRet = 0;
1727 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1729 /* Get current active window from the active queue */
1730 if ( hActiveQueue )
1732 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1733 if ( pOldActiveQueue )
1734 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1737 /* paranoid checks */
1738 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1739 goto CLEANUP_END;
1741 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1742 * return 0;
1744 wndPtr = WIN_FindWndPtr(hWnd);
1745 hOldActiveQueue = hActiveQueue;
1747 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1749 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1750 WIN_ReleaseWndPtr(wndTemp);
1752 else
1753 TRACE("no current active window.\n");
1755 /* call CBT hook chain */
1756 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1758 cbtStruct->fMouse = fMouse;
1759 cbtStruct->hWndActive = hwndActive;
1760 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1761 (LPARAM)SEGPTR_GET(cbtStruct) );
1762 SEGPTR_FREE(cbtStruct);
1763 if (bRet) goto CLEANUP_END;
1766 /* set prev active wnd to current active wnd and send notification */
1767 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1769 MESSAGEQUEUE *pTempActiveQueue = 0;
1771 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1773 if (GetSysModalWindow16() != hWnd)
1774 goto CLEANUP_END;
1775 /* disregard refusal if hWnd is sysmodal */
1778 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1779 MAKEWPARAM( WA_INACTIVE, wIconized ),
1780 (LPARAM)hWnd );
1782 /* check if something happened during message processing
1783 * (global active queue may have changed)
1785 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1786 if(!pTempActiveQueue)
1787 goto CLEANUP_END;
1789 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1790 QUEUE_Unlock( pTempActiveQueue );
1791 if( hwndPrevActive != hwndActive )
1792 goto CLEANUP_END;
1795 /* Set new active window in the message queue */
1796 hwndActive = hWnd;
1797 if ( wndPtr )
1799 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1800 if ( pNewActiveQueue )
1801 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1803 else /* have to do this or MDI frame activation goes to hell */
1804 if( pOldActiveQueue )
1805 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1807 /* send palette messages */
1808 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1809 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1811 /* if prev wnd is minimized redraw icon title */
1812 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1814 /* managed windows will get ConfigureNotify event */
1815 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1817 /* check Z-order and bring hWnd to the top */
1818 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1820 if (wndTemp->dwStyle & WS_VISIBLE) break;
1822 WIN_ReleaseDesktop();
1823 WIN_ReleaseWndPtr(wndTemp);
1825 if( wndTemp != wndPtr )
1826 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1827 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1828 if (!IsWindow(hWnd))
1829 goto CLEANUP;
1832 /* Get a handle to the new active queue */
1833 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1835 /* send WM_ACTIVATEAPP if necessary */
1836 if (hOldActiveQueue != hNewActiveQueue)
1838 WND **list, **ppWnd;
1839 WND *pDesktop = WIN_GetDesktop();
1841 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1843 for (ppWnd = list; *ppWnd; ppWnd++)
1845 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1847 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1848 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1849 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1851 WIN_ReleaseWinArray(list);
1854 hActiveQueue = hNewActiveQueue;
1856 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1858 for (ppWnd = list; *ppWnd; ppWnd++)
1860 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1862 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1863 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1864 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1866 WIN_ReleaseWinArray(list);
1868 WIN_ReleaseDesktop();
1870 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1873 if (hWnd)
1875 /* walk up to the first unowned window */
1876 wndTemp = WIN_LockWndPtr(wndPtr);
1877 while (wndTemp->owner)
1879 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1881 /* and set last active owned popup */
1882 wndTemp->hwndLastActive = hWnd;
1884 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1885 WIN_ReleaseWndPtr(wndTemp);
1886 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1887 SendMessageA( hWnd, WM_ACTIVATE,
1888 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1889 (LPARAM)hwndPrevActive );
1890 if( !IsWindow(hWnd) ) goto CLEANUP;
1893 /* change focus if possible */
1894 if ( fChangeFocus )
1896 if ( pNewActiveQueue )
1898 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1900 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1901 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1902 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1903 0 : hwndActive );
1906 if ( pOldActiveQueue &&
1907 ( !pNewActiveQueue ||
1908 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1910 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1911 if ( hOldFocus )
1912 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1916 if( !hwndPrevActive && wndPtr )
1917 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1919 /* if active wnd is minimized redraw icon title */
1920 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1922 bRet = (hWnd == hwndActive); /* Success? */
1924 CLEANUP: /* Unlock the message queues before returning */
1926 if ( pNewActiveQueue )
1927 QUEUE_Unlock( pNewActiveQueue );
1929 CLEANUP_END:
1931 if ( pOldActiveQueue )
1932 QUEUE_Unlock( pOldActiveQueue );
1934 WIN_ReleaseWndPtr(wndPtr);
1935 return bRet;
1938 /*******************************************************************
1939 * WINPOS_ActivateOtherWindow
1941 * Activates window other than pWnd.
1943 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1945 BOOL bRet = 0;
1946 WND* pWndTo = NULL;
1947 HWND hwndActive = 0;
1949 /* Get current active window from the active queue */
1950 if ( hActiveQueue )
1952 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1953 if ( pActiveQueue )
1955 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1956 QUEUE_Unlock( pActiveQueue );
1960 if( pWnd->hwndSelf == hwndPrevActive )
1961 hwndPrevActive = 0;
1963 if( hwndActive != pWnd->hwndSelf &&
1964 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1965 return 0;
1967 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1968 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1970 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1972 WIN_ReleaseWndPtr(pWndTo);
1973 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1975 while( !WINPOS_CanActivate(pWndTo) )
1977 /* by now owned windows should've been taken care of */
1978 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1979 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1980 if( !pWndTo ) break;
1982 WIN_ReleaseWndPtr(pWndPtr);
1985 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1987 /* switch desktop queue to current active */
1988 if( pWndTo )
1990 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1991 WIN_ReleaseWndPtr(pWndTo);
1992 WIN_ReleaseDesktop();
1995 hwndPrevActive = 0;
1996 return bRet;
1999 /*******************************************************************
2000 * WINPOS_ChangeActiveWindow
2003 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2005 WND *wndPtr, *wndTemp;
2006 BOOL retvalue;
2007 HWND hwndActive = 0;
2009 /* Get current active window from the active queue */
2010 if ( hActiveQueue )
2012 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2013 if ( pActiveQueue )
2015 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2016 QUEUE_Unlock( pActiveQueue );
2020 if (!hWnd)
2021 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2023 wndPtr = WIN_FindWndPtr(hWnd);
2024 if( !wndPtr ) return FALSE;
2026 /* child windows get WM_CHILDACTIVATE message */
2027 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2029 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2030 goto end;
2033 if( hWnd == hwndActive )
2035 retvalue = FALSE;
2036 goto end;
2039 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2041 retvalue = FALSE;
2042 goto end;
2045 /* switch desktop queue to current active */
2046 wndTemp = WIN_GetDesktop();
2047 if( wndPtr->parent == wndTemp)
2048 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2049 WIN_ReleaseDesktop();
2051 retvalue = TRUE;
2052 end:
2053 WIN_ReleaseWndPtr(wndPtr);
2054 return retvalue;
2058 /***********************************************************************
2059 * WINPOS_SendNCCalcSize
2061 * Send a WM_NCCALCSIZE message to a window.
2062 * All parameters are read-only except newClientRect.
2063 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2064 * when calcValidRect is TRUE.
2066 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2067 RECT *newWindowRect, RECT *oldWindowRect,
2068 RECT *oldClientRect, WINDOWPOS *winpos,
2069 RECT *newClientRect )
2071 NCCALCSIZE_PARAMS params;
2072 WINDOWPOS winposCopy;
2073 LONG result;
2075 params.rgrc[0] = *newWindowRect;
2076 if (calcValidRect)
2078 winposCopy = *winpos;
2079 params.rgrc[1] = *oldWindowRect;
2080 params.rgrc[2] = *oldClientRect;
2081 params.lppos = &winposCopy;
2083 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2084 (LPARAM)&params );
2085 TRACE("%d,%d-%d,%d\n",
2086 params.rgrc[0].left, params.rgrc[0].top,
2087 params.rgrc[0].right, params.rgrc[0].bottom );
2089 /* If the application send back garbage, ignore it */
2090 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2091 *newClientRect = params.rgrc[0];
2093 return result;
2097 /***********************************************************************
2098 * WINPOS_HandleWindowPosChanging16
2100 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2102 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2104 POINT maxSize, minTrack;
2105 if (winpos->flags & SWP_NOSIZE) return 0;
2106 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2107 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2109 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2110 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2111 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2112 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2114 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2115 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2118 return 0;
2122 /***********************************************************************
2123 * WINPOS_HandleWindowPosChanging
2125 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2127 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2129 POINT maxSize;
2130 if (winpos->flags & SWP_NOSIZE) return 0;
2131 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2132 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2134 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2135 winpos->cx = min( winpos->cx, maxSize.x );
2136 winpos->cy = min( winpos->cy, maxSize.y );
2138 return 0;
2141 /***********************************************************************
2142 * SWP_DoOwnedPopups
2144 * fix Z order taking into account owned popups -
2145 * basically we need to maintain them above the window that owns them
2147 * FIXME: hide/show owned popups when owner visibility changes.
2149 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2151 WND* w = WIN_LockWndPtr(pDesktop->child);
2153 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2155 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2157 /* make sure this popup stays above the owner */
2159 HWND hwndLocalPrev = HWND_TOP;
2161 if( hwndInsertAfter != HWND_TOP )
2163 while( w != wndPtr->owner )
2165 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2166 if( hwndLocalPrev == hwndInsertAfter ) break;
2167 WIN_UpdateWndPtr(&w,w->next);
2169 hwndInsertAfter = hwndLocalPrev;
2172 else if( wndPtr->dwStyle & WS_CHILD )
2173 goto END;
2175 WIN_UpdateWndPtr(&w, pDesktop->child);
2177 while( w )
2179 if( w == wndPtr ) break;
2181 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2183 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2184 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2185 hwndInsertAfter = w->hwndSelf;
2187 WIN_UpdateWndPtr(&w, w->next);
2190 END:
2191 WIN_ReleaseWndPtr(w);
2192 return hwndInsertAfter;
2195 /***********************************************************************
2196 * SWP_CopyValidBits
2198 * Make window look nice without excessive repainting
2200 * visible and update regions are in window coordinates
2201 * client and window rectangles are in parent client coordinates
2203 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2204 * window rects have the same origin.
2206 * Returns: uFlags and a dirty region in *pVisRgn.
2208 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2209 LPRECT lpOldWndRect,
2210 LPRECT lpOldClientRect, UINT uFlags )
2212 RECT r;
2213 HRGN newVisRgn, dirtyRgn;
2214 INT my = COMPLEXREGION;
2216 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2217 Wnd->rectWindow.left, Wnd->rectWindow.top,
2218 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2219 lpOldWndRect->left, lpOldWndRect->top,
2220 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2221 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2222 Wnd->rectClient.left, Wnd->rectClient.top,
2223 Wnd->rectClient.right, Wnd->rectClient.bottom,
2224 lpOldClientRect->left, lpOldClientRect->top,
2225 lpOldClientRect->right,lpOldClientRect->bottom );
2227 if( Wnd->hrgnUpdate == 1 )
2228 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2230 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2231 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2233 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2234 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2236 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2238 nocopy:
2240 TRACE("\twon't copy anything!\n");
2242 /* set dirtyRgn to the sum of old and new visible regions
2243 * in parent client coordinates */
2245 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2246 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2248 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2250 else /* copy valid bits to a new location */
2252 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2253 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2255 /* subtract already invalid region inside Wnd from the dst region */
2257 if( Wnd->hrgnUpdate )
2258 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2259 goto nocopy;
2261 /* check if entire window can be copied */
2263 ow = lpOldWndRect->right - lpOldWndRect->left;
2264 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2265 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2266 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2268 ocw = lpOldClientRect->right - lpOldClientRect->left;
2269 och = lpOldClientRect->bottom - lpOldClientRect->top;
2270 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2271 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2273 if( (ocw != ncw) || (och != nch) ||
2274 ( ow != nw) || ( oh != nh) ||
2275 ((lpOldClientRect->top - lpOldWndRect->top) !=
2276 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2277 ((lpOldClientRect->left - lpOldWndRect->left) !=
2278 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2280 dx = Wnd->rectClient.left - lpOldClientRect->left;
2281 dy = Wnd->rectClient.top - lpOldClientRect->top;
2283 /* restrict valid bits to the common client rect */
2285 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2286 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2287 r.right = r.left + min( ocw, ncw );
2288 r.bottom = r.top + min( och, nch );
2290 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2291 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2292 GetRgnBox( hrgnValid, &r );
2293 if( IsRectEmpty( &r ) )
2294 goto nocopy;
2295 r = *lpOldClientRect;
2297 else
2299 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2300 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2301 if( !(uFlags & SWP_EX_PAINTSELF) )
2302 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2303 r = *lpOldWndRect;
2306 if( !(uFlags & SWP_EX_PAINTSELF) )
2308 /* Move remaining regions to parent coordinates */
2309 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2310 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2312 else
2313 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2315 TRACE("\tcomputing dirty region!\n");
2317 /* Compute combined dirty region (old + new - valid) */
2318 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2319 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2321 /* Blt valid bits, r is the rect to copy */
2323 if( dx || dy )
2325 RECT rClip;
2326 HDC hDC;
2328 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2329 from copying clipped areas */
2331 if( uFlags & SWP_EX_PAINTSELF )
2333 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2334 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2335 rClip.right = nw; rClip.bottom = nh;
2337 else
2339 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2340 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2341 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2342 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2344 rClip.left = rClip.top = 0;
2346 if( oh > nh ) r.bottom = r.top + nh;
2347 if( ow < nw ) r.right = r.left + nw;
2349 if( IntersectRect( &r, &r, &rClip ) )
2351 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2353 /* When you copy the bits without repainting, parent doesn't
2354 get validated appropriately. Therefore, we have to validate
2355 the parent with the windows' updated region when the
2356 parent's update region is not empty. */
2358 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2360 OffsetRect(&r, dx, dy);
2361 ValidateRect(Wnd->parent->hwndSelf, &r);
2364 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2365 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2369 /* *pVisRgn now points to the invalidated region */
2371 DeleteObject(newVisRgn);
2372 DeleteObject(dirtyRgn);
2373 return uFlags;
2376 /***********************************************************************
2377 * SWP_DoSimpleFrameChanged
2379 * NOTE: old and new client rect origins are identical, only
2380 * extents may have changed. Window extents are the same.
2382 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2384 INT i = 0;
2385 RECT rect;
2386 HRGN hrgn = 0;
2388 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2390 /* Client rect changed its position/size, most likely a scrollar
2391 * was added/removed.
2393 * FIXME: WVR alignment flags
2396 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2398 i++;
2399 rect.top = 0;
2400 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2401 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2402 if(!(uFlags & SWP_EX_NOCOPY))
2403 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2404 else
2406 rect.left = 0;
2407 goto redraw;
2411 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2413 if( i )
2414 hrgn = CreateRectRgnIndirect( &rect );
2415 rect.left = 0;
2416 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2417 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2418 if(!(uFlags & SWP_EX_NOCOPY))
2419 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2420 else
2421 rect.top = 0;
2422 if( i++ )
2423 REGION_UnionRectWithRgn( hrgn, &rect );
2426 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2428 rect = wndPtr->rectWindow;
2429 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2430 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2431 i++;
2435 if( i )
2437 redraw:
2438 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2439 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2441 else
2443 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2446 if( hrgn > 1 )
2447 DeleteObject( hrgn );
2450 /***********************************************************************
2451 * SWP_DoWinPosChanging
2453 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2454 RECT* pNewWindowRect, RECT* pNewClientRect )
2456 /* Send WM_WINDOWPOSCHANGING message */
2458 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2459 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2461 /* Calculate new position and size */
2463 *pNewWindowRect = wndPtr->rectWindow;
2464 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2465 : wndPtr->rectClient;
2467 if (!(pWinpos->flags & SWP_NOSIZE))
2469 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2470 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2472 if (!(pWinpos->flags & SWP_NOMOVE))
2474 pNewWindowRect->left = pWinpos->x;
2475 pNewWindowRect->top = pWinpos->y;
2476 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2477 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2479 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2480 pWinpos->y - wndPtr->rectWindow.top );
2483 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2484 return TRUE;
2487 /***********************************************************************
2488 * SWP_DoNCCalcSize
2490 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2491 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2493 UINT wvrFlags = 0;
2495 /* Send WM_NCCALCSIZE message to get new client area */
2496 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2498 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2499 &wndPtr->rectWindow, &wndPtr->rectClient,
2500 pWinpos, pNewClientRect );
2502 /* FIXME: WVR_ALIGNxxx */
2504 if( pNewClientRect->left != wndPtr->rectClient.left ||
2505 pNewClientRect->top != wndPtr->rectClient.top )
2506 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2508 if( (pNewClientRect->right - pNewClientRect->left !=
2509 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2510 (pNewClientRect->bottom - pNewClientRect->top !=
2511 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2512 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2514 else
2515 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2516 pNewClientRect->top != wndPtr->rectClient.top) )
2517 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2518 return wvrFlags;
2521 /***********************************************************************
2522 * SetWindowPos (USER.2)
2524 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2525 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2527 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2530 /***********************************************************************
2531 * SetWindowPos (USER32.520)
2533 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2534 INT x, INT y, INT cx, INT cy, UINT flags )
2536 WINDOWPOS winpos;
2537 WND * wndPtr,*wndTemp;
2538 RECT newWindowRect, newClientRect;
2539 RECT oldWindowRect, oldClientRect;
2540 HRGN visRgn = 0;
2541 UINT wvrFlags = 0, uFlags = 0;
2542 BOOL retvalue, resync = FALSE, bChangePos;
2543 HWND hwndActive = 0;
2545 /* Get current active window from the active queue */
2546 if ( hActiveQueue )
2548 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2549 if ( pActiveQueue )
2551 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2552 QUEUE_Unlock( pActiveQueue );
2556 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2557 hwnd, x, y, x+cx, y+cy, flags);
2559 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2560 flags &= ~SWP_WINE_NOHOSTMOVE;
2563 /* ------------------------------------------------------------------------ CHECKS */
2565 /* Check window handle */
2567 if (hwnd == GetDesktopWindow()) return FALSE;
2568 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2570 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2571 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2573 /* Fix redundant flags */
2575 if(wndPtr->dwStyle & WS_VISIBLE)
2576 flags &= ~SWP_SHOWWINDOW;
2577 else
2579 if (!(flags & SWP_SHOWWINDOW))
2580 flags |= SWP_NOREDRAW;
2581 flags &= ~SWP_HIDEWINDOW;
2584 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2586 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2587 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2588 flags |= SWP_NOSIZE; /* Already the right size */
2590 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2591 flags |= SWP_NOMOVE; /* Already the right position */
2593 if (hwnd == hwndActive)
2594 flags |= SWP_NOACTIVATE; /* Already active */
2595 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2597 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2599 flags &= ~SWP_NOZORDER;
2600 hwndInsertAfter = HWND_TOP;
2601 goto Pos;
2605 /* Check hwndInsertAfter */
2607 /* FIXME: TOPMOST not supported yet */
2608 if ((hwndInsertAfter == HWND_TOPMOST) ||
2609 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2611 /* hwndInsertAfter must be a sibling of the window */
2612 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2614 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2616 if( wnd ) {
2617 if( wnd->parent != wndPtr->parent )
2619 retvalue = FALSE;
2620 WIN_ReleaseWndPtr(wnd);
2621 goto END;
2623 /* don't need to change the Zorder of hwnd if it's already inserted
2624 * after hwndInsertAfter or when inserting hwnd after itself.
2626 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2628 WIN_ReleaseWndPtr(wnd);
2631 Pos: /* ------------------------------------------------------------------------ MAIN part */
2633 /* Fill the WINDOWPOS structure */
2635 winpos.hwnd = hwnd;
2636 winpos.hwndInsertAfter = hwndInsertAfter;
2637 winpos.x = x;
2638 winpos.y = y;
2639 winpos.cx = cx;
2640 winpos.cy = cy;
2641 winpos.flags = flags;
2643 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2645 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2647 if( wndPtr->parent == WIN_GetDesktop() )
2648 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2649 hwndInsertAfter, winpos.flags );
2650 WIN_ReleaseDesktop();
2653 if(!(wndPtr->flags & WIN_NATIVE) )
2655 if( hwndInsertAfter == HWND_TOP )
2656 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2657 else
2658 if( hwndInsertAfter == HWND_BOTTOM )
2659 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2660 else
2661 if( !(winpos.flags & SWP_NOZORDER) )
2662 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2663 winpos.flags |= SWP_NOZORDER;
2665 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2666 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2667 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2669 /* get a previous visible region for SWP_CopyValidBits() */
2670 DWORD dflags = DCX_WINDOW;
2672 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2673 dflags |= DCX_CLIPSIBLINGS;
2675 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2679 /* Common operations */
2681 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2683 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2685 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2686 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2689 /* Reset active DCEs */
2691 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2692 wndPtr->dwStyle & WS_VISIBLE) ||
2693 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2695 RECT rect;
2697 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2698 DCE_InvalidateDCE(wndPtr, &rect);
2701 oldWindowRect = wndPtr->rectWindow;
2702 oldClientRect = wndPtr->rectClient;
2704 /* Find out if we have to redraw the whole client rect */
2706 if( oldClientRect.bottom - oldClientRect.top ==
2707 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2709 if( oldClientRect.right - oldClientRect.left ==
2710 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2712 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2713 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2715 uFlags |= SWP_EX_NOCOPY;
2718 * Use this later in CopyValidBits()
2720 else if( 0 )
2721 uFlags |= SWP_EX_NONCLIENT;
2724 /* FIXME: actually do something with WVR_VALIDRECTS */
2726 wndPtr->rectWindow = newWindowRect;
2727 wndPtr->rectClient = newClientRect;
2729 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2731 BOOL bCallDriver = TRUE;
2732 HWND tempInsertAfter = winpos.hwndInsertAfter;
2734 winpos.hwndInsertAfter = hwndInsertAfter;
2736 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2738 /* This is the only place where we need to force repainting of the contents
2739 of windows created by the host window system, all other cases go through the
2740 expose event handling */
2742 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2744 cx = newWindowRect.right - newWindowRect.left;
2745 cy = newWindowRect.bottom - newWindowRect.top;
2747 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2748 winpos.hwndInsertAfter = tempInsertAfter;
2749 bCallDriver = FALSE;
2751 if( winpos.flags & SWP_NOCLIENTMOVE )
2752 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2753 else
2755 /* client area moved but window extents remained the same, copy valid bits */
2757 visRgn = CreateRectRgn( 0, 0, cx, cy );
2758 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2759 uFlags | SWP_EX_PAINTSELF );
2764 if( bCallDriver )
2766 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2768 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2769 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2770 !(uFlags & SWP_EX_NOCOPY) )
2772 /* The origin of the client rect didn't move so we can try to repaint
2773 * only the nonclient area by setting bit gravity hint for the host window system.
2776 if( !(wndPtr->flags & WIN_MANAGED) )
2778 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2779 newWindowRect.bottom - newWindowRect.top);
2780 RECT rcn = newClientRect;
2781 RECT rco = oldClientRect;
2783 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2784 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2785 IntersectRect( &rcn, &rcn, &rco );
2786 visRgn = CreateRectRgnIndirect( &rcn );
2787 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2788 DeleteObject( hrgn );
2789 uFlags = SWP_EX_PAINTSELF;
2791 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2793 else
2794 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2797 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2798 winpos.hwndInsertAfter = tempInsertAfter;
2801 if( winpos.flags & SWP_SHOWWINDOW )
2803 HWND focus, curr;
2805 wndPtr->dwStyle |= WS_VISIBLE;
2807 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2809 /* focus was set to unmapped window, reset host focus
2810 * since the window is now visible */
2812 focus = curr = GetFocus();
2813 while (curr)
2815 if (curr == hwnd)
2817 WND *pFocus = WIN_FindWndPtr( focus );
2818 if (pFocus)
2819 pFocus->pDriver->pSetFocus(pFocus);
2820 WIN_ReleaseWndPtr(pFocus);
2821 break;
2823 curr = GetParent(curr);
2827 else /* -------------------------------------------- emulated window */
2829 if( winpos.flags & SWP_SHOWWINDOW )
2831 wndPtr->dwStyle |= WS_VISIBLE;
2832 uFlags |= SWP_EX_PAINTSELF;
2833 visRgn = 1; /* redraw the whole window */
2835 else if( !(winpos.flags & SWP_NOREDRAW) )
2837 if( winpos.flags & SWP_HIDEWINDOW )
2839 if( visRgn > 1 ) /* map to parent */
2840 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2841 else
2842 visRgn = 0;
2844 else
2846 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2847 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2848 &oldClientRect, uFlags);
2849 else
2851 /* nothing moved, redraw frame if needed */
2853 if( winpos.flags & SWP_FRAMECHANGED )
2854 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2855 if( visRgn )
2857 DeleteObject( visRgn );
2858 visRgn = 0;
2865 if( winpos.flags & SWP_HIDEWINDOW )
2867 wndPtr->dwStyle &= ~WS_VISIBLE;
2870 if (hwnd == CARET_GetHwnd())
2872 if( winpos.flags & SWP_HIDEWINDOW )
2873 HideCaret(hwnd);
2874 else if (winpos.flags & SWP_SHOWWINDOW)
2875 ShowCaret(hwnd);
2878 /* ------------------------------------------------------------------------ FINAL */
2880 if (wndPtr->flags & WIN_NATIVE)
2881 EVENT_Synchronize(); /* Synchronize with the host window system */
2883 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2885 /* Simulate a mouse event to set the cursor */
2886 int iWndsLocks = WIN_SuspendWndsLock();
2888 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2889 PosX, PosY, GetTickCount(), 0 );
2891 WIN_RestoreWndsLock(iWndsLocks);
2894 wndTemp = WIN_GetDesktop();
2896 /* repaint invalidated region (if any)
2898 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2899 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2902 if( visRgn )
2904 if( !(winpos.flags & SWP_NOREDRAW) )
2907 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2908 its parent and sibling and so on, and then erase the parent window
2909 back ground if the parent is either a top-level window or its parent's parent
2910 is top-level window. Rely on the system to repaint other affected
2911 windows later on. */
2912 if( uFlags & SWP_EX_PAINTSELF )
2914 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2915 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2916 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2918 else
2920 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2921 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2922 RDW_EX_USEHRGN );
2925 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2927 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2928 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2931 if( visRgn != 1 )
2932 DeleteObject( visRgn );
2935 WIN_ReleaseDesktop();
2937 if (!(flags & SWP_NOACTIVATE))
2938 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2940 /* And last, send the WM_WINDOWPOSCHANGED message */
2942 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2944 if ( resync ||
2945 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2946 !(winpos.flags & SWP_NOSENDCHANGING)) )
2948 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2949 if (resync) EVENT_Synchronize();
2952 retvalue = TRUE;
2953 END:
2954 WIN_ReleaseWndPtr(wndPtr);
2955 return retvalue;
2959 /***********************************************************************
2960 * BeginDeferWindowPos16 (USER.259)
2962 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2964 return BeginDeferWindowPos( count );
2968 /***********************************************************************
2969 * BeginDeferWindowPos (USER32.9)
2971 HDWP WINAPI BeginDeferWindowPos( INT count )
2973 HDWP handle;
2974 DWP *pDWP;
2976 if (count < 0)
2978 SetLastError(ERROR_INVALID_PARAMETER);
2979 return 0;
2981 /* Windows allows zero count, in which case it allocates context for 8 moves */
2982 if (count == 0) count = 8;
2984 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2985 if (!handle) return 0;
2986 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2987 pDWP->actualCount = 0;
2988 pDWP->suggestedCount = count;
2989 pDWP->valid = TRUE;
2990 pDWP->wMagic = DWP_MAGIC;
2991 pDWP->hwndParent = 0;
2992 return handle;
2996 /***********************************************************************
2997 * DeferWindowPos16 (USER.260)
2999 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
3000 INT16 x, INT16 y, INT16 cx, INT16 cy,
3001 UINT16 flags )
3003 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3004 x, y, cx, cy, flags );
3008 /***********************************************************************
3009 * DeferWindowPos (USER32.128)
3011 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3012 INT x, INT y, INT cx, INT cy,
3013 UINT flags )
3015 DWP *pDWP;
3016 int i;
3017 HDWP newhdwp = hdwp,retvalue;
3018 /* HWND parent; */
3019 WND *pWnd;
3021 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3022 if (!pDWP) return 0;
3023 if (hwnd == GetDesktopWindow()) return 0;
3025 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3026 USER_HEAP_FREE( hdwp );
3027 return 0;
3030 /* Numega Bounds Checker Demo dislikes the following code.
3031 In fact, I've not been able to find any "same parent" requirement in any docu
3032 [AM 980509]
3034 #if 0
3035 /* All the windows of a DeferWindowPos() must have the same parent */
3036 parent = pWnd->parent->hwndSelf;
3037 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3038 else if (parent != pDWP->hwndParent)
3040 USER_HEAP_FREE( hdwp );
3041 retvalue = 0;
3042 goto END;
3044 #endif
3046 for (i = 0; i < pDWP->actualCount; i++)
3048 if (pDWP->winPos[i].hwnd == hwnd)
3050 /* Merge with the other changes */
3051 if (!(flags & SWP_NOZORDER))
3053 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3055 if (!(flags & SWP_NOMOVE))
3057 pDWP->winPos[i].x = x;
3058 pDWP->winPos[i].y = y;
3060 if (!(flags & SWP_NOSIZE))
3062 pDWP->winPos[i].cx = cx;
3063 pDWP->winPos[i].cy = cy;
3065 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3066 SWP_NOZORDER | SWP_NOREDRAW |
3067 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3068 SWP_NOOWNERZORDER);
3069 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3070 SWP_FRAMECHANGED);
3071 retvalue = hdwp;
3072 goto END;
3075 if (pDWP->actualCount >= pDWP->suggestedCount)
3077 newhdwp = USER_HEAP_REALLOC( hdwp,
3078 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3079 if (!newhdwp)
3081 retvalue = 0;
3082 goto END;
3084 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3085 pDWP->suggestedCount++;
3087 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3088 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3089 pDWP->winPos[pDWP->actualCount].x = x;
3090 pDWP->winPos[pDWP->actualCount].y = y;
3091 pDWP->winPos[pDWP->actualCount].cx = cx;
3092 pDWP->winPos[pDWP->actualCount].cy = cy;
3093 pDWP->winPos[pDWP->actualCount].flags = flags;
3094 pDWP->actualCount++;
3095 retvalue = newhdwp;
3096 END:
3097 WIN_ReleaseWndPtr(pWnd);
3098 return retvalue;
3102 /***********************************************************************
3103 * EndDeferWindowPos16 (USER.261)
3105 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3107 return EndDeferWindowPos( hdwp );
3111 /***********************************************************************
3112 * EndDeferWindowPos (USER32.173)
3114 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3116 DWP *pDWP;
3117 WINDOWPOS *winpos;
3118 BOOL res = TRUE;
3119 int i;
3121 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3122 if (!pDWP) return FALSE;
3123 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3125 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3126 winpos->x, winpos->y, winpos->cx,
3127 winpos->cy, winpos->flags ))) break;
3129 USER_HEAP_FREE( hdwp );
3130 return res;
3134 /***********************************************************************
3135 * TileChildWindows (USER.199)
3137 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3139 FIXME("(%04x, %d): stub\n", parent, action);
3142 /***********************************************************************
3143 * CascadeChildWindows (USER.198)
3145 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3147 FIXME("(%04x, %d): stub\n", parent, action);
3150 /***********************************************************************
3151 * SetProgmanWindow [USER32.522]
3153 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3155 hGlobalProgmanWindow = hwnd;
3156 return hGlobalProgmanWindow;
3159 /***********************************************************************
3160 * GetProgmanWindow [USER32.289]
3162 HRESULT WINAPI GetProgmanWindow ( )
3164 return hGlobalProgmanWindow;
3167 /***********************************************************************
3168 * SetShellWindowEx [USER32.531]
3169 * hwndProgman = Progman[Program Manager]
3170 * |-> SHELLDLL_DefView
3171 * hwndListView = | |-> SysListView32
3172 * | | |-> tooltips_class32
3173 * | |
3174 * | |-> SysHeader32
3175 * |
3176 * |-> ProxyTarget
3178 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3180 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3181 hGlobalShellWindow = hwndProgman;
3182 return hGlobalShellWindow;
3186 /***********************************************************************
3187 * SetTaskmanWindow [USER32.537]
3188 * NOTES
3189 * hwnd = MSTaskSwWClass
3190 * |-> SysTabControl32
3192 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3194 hGlobalTaskmanWindow = hwnd;
3195 return hGlobalTaskmanWindow;
3198 /***********************************************************************
3199 * GetTaskmanWindow [USER32.304]
3201 HRESULT WINAPI GetTaskmanWindow ( )
3203 return hGlobalTaskmanWindow;