SetScrollInfo : don't show/hide scrollbar if no parameter (minval,
[wine.git] / windows / winpos.c
blob8a418f793f6970cfa46064de83c82611eff9279b
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 wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE );
1260 WINPOS_ShowIconTitle( wndPtr, FALSE );
1261 wndPtr->dwStyle &= ~WS_MINIMIZE;
1263 wndPtr->dwStyle |= WS_MAXIMIZE;
1265 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1266 size.x, size.y );
1267 break;
1269 case SW_RESTORE:
1270 if( wndPtr->dwStyle & WS_MINIMIZE )
1272 if( wndPtr->flags & WIN_NATIVE )
1273 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1274 swpFlags |= MINMAX_NOSWP;
1276 wndPtr->dwStyle &= ~WS_MINIMIZE;
1277 WINPOS_ShowIconTitle( wndPtr, FALSE );
1279 if( wndPtr->flags & WIN_RESTORE_MAX)
1281 /* Restore to maximized position */
1282 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1283 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1284 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1285 wndPtr->dwStyle |= WS_MAXIMIZE;
1286 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1287 break;
1290 else
1291 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1292 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1294 /* Restore to normal position */
1296 *lpRect = lpPos->rectNormal;
1297 lpRect->right -= lpRect->left;
1298 lpRect->bottom -= lpRect->top;
1300 break;
1302 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1303 return swpFlags;
1306 /***********************************************************************
1307 * ShowWindowAsync (USER32.535)
1309 * doesn't wait; returns immediately.
1310 * used by threads to toggle windows in other (possibly hanging) threads
1312 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1314 /* FIXME: does ShowWindow() return immediately ? */
1315 return ShowWindow(hwnd, cmd);
1319 /***********************************************************************
1320 * ShowWindow16 (USER.42)
1322 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1324 return ShowWindow(hwnd,cmd);
1328 /***********************************************************************
1329 * ShowWindow (USER32.534)
1331 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1333 WND* wndPtr = WIN_FindWndPtr( hwnd );
1334 BOOL wasVisible, showFlag;
1335 RECT16 newPos = {0, 0, 0, 0};
1336 UINT swp = 0;
1338 if (!wndPtr) return FALSE;
1340 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1342 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1344 switch(cmd)
1346 case SW_HIDE:
1347 if (!wasVisible) goto END;;
1348 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1349 SWP_NOACTIVATE | SWP_NOZORDER;
1350 break;
1352 case SW_SHOWMINNOACTIVE:
1353 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1354 /* fall through */
1355 case SW_SHOWMINIMIZED:
1356 swp |= SWP_SHOWWINDOW;
1357 /* fall through */
1358 case SW_MINIMIZE:
1359 swp |= SWP_FRAMECHANGED;
1360 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1361 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1362 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1363 break;
1365 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1366 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1367 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1368 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1369 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1370 break;
1372 case SW_SHOWNA:
1373 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1374 /* fall through */
1375 case SW_SHOW:
1376 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1379 * ShowWindow has a little peculiar behavior that if the
1380 * window is already the topmost window, it will not
1381 * activate it.
1383 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1384 swp |= SWP_NOACTIVATE;
1386 break;
1388 case SW_SHOWNOACTIVATE:
1389 swp |= SWP_NOZORDER;
1390 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1391 /* fall through */
1392 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1393 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1394 case SW_RESTORE:
1395 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1397 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1398 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1399 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1400 break;
1403 showFlag = (cmd != SW_HIDE);
1404 if (showFlag != wasVisible)
1406 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1407 if (!IsWindow( hwnd )) goto END;
1410 if ((wndPtr->dwStyle & WS_CHILD) &&
1411 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1412 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1414 /* Don't call SetWindowPos() on invisible child windows */
1415 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1416 else wndPtr->dwStyle |= WS_VISIBLE;
1418 else
1420 /* We can't activate a child window */
1421 if ((wndPtr->dwStyle & WS_CHILD) &&
1422 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1423 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1424 if (!(swp & MINMAX_NOSWP))
1426 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1427 newPos.right, newPos.bottom, LOWORD(swp) );
1428 if (cmd == SW_HIDE)
1430 /* FIXME: This will cause the window to be activated irrespective
1431 * of whether it is owned by the same thread. Has to be done
1432 * asynchronously.
1435 if (hwnd == GetActiveWindow())
1436 WINPOS_ActivateOtherWindow(wndPtr);
1438 /* Revert focus to parent */
1439 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1440 SetFocus( GetParent(hwnd) );
1443 if (!IsWindow( hwnd )) goto END;
1444 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1447 if (wndPtr->flags & WIN_NEED_SIZE)
1449 /* should happen only in CreateWindowEx() */
1450 int wParam = SIZE_RESTORED;
1452 wndPtr->flags &= ~WIN_NEED_SIZE;
1453 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1454 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1455 SendMessageA( hwnd, WM_SIZE, wParam,
1456 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1457 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1458 SendMessageA( hwnd, WM_MOVE, 0,
1459 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1462 END:
1463 WIN_ReleaseWndPtr(wndPtr);
1464 return wasVisible;
1468 /***********************************************************************
1469 * GetInternalWindowPos16 (USER.460)
1471 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1472 LPPOINT16 ptIcon )
1474 WINDOWPLACEMENT16 wndpl;
1475 if (GetWindowPlacement16( hwnd, &wndpl ))
1477 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1478 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1479 return wndpl.showCmd;
1481 return 0;
1485 /***********************************************************************
1486 * GetInternalWindowPos (USER32.245)
1488 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1489 LPPOINT ptIcon )
1491 WINDOWPLACEMENT wndpl;
1492 if (GetWindowPlacement( hwnd, &wndpl ))
1494 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1495 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1496 return wndpl.showCmd;
1498 return 0;
1501 /***********************************************************************
1502 * GetWindowPlacement16 (USER.370)
1504 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1506 WND *pWnd = WIN_FindWndPtr( hwnd );
1507 LPINTERNALPOS lpPos;
1509 if(!pWnd ) return FALSE;
1511 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1512 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1513 wndpl->length = sizeof(*wndpl);
1514 if( pWnd->dwStyle & WS_MINIMIZE )
1515 wndpl->showCmd = SW_SHOWMINIMIZED;
1516 else
1517 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1518 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1519 if( pWnd->flags & WIN_RESTORE_MAX )
1520 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1521 else
1522 wndpl->flags = 0;
1523 wndpl->ptMinPosition = lpPos->ptIconPos;
1524 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1525 wndpl->rcNormalPosition = lpPos->rectNormal;
1527 WIN_ReleaseWndPtr(pWnd);
1528 return TRUE;
1532 /***********************************************************************
1533 * GetWindowPlacement (USER32.307)
1535 * Win95:
1536 * Fails if wndpl->length of Win95 (!) apps is invalid.
1538 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1540 if( pwpl32 )
1542 WINDOWPLACEMENT16 wpl;
1543 wpl.length = sizeof(wpl);
1544 if( GetWindowPlacement16( hwnd, &wpl ) )
1546 pwpl32->length = sizeof(*pwpl32);
1547 pwpl32->flags = wpl.flags;
1548 pwpl32->showCmd = wpl.showCmd;
1549 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1550 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1551 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1552 return TRUE;
1555 return FALSE;
1559 /***********************************************************************
1560 * WINPOS_SetPlacement
1562 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1563 UINT flags )
1565 WND *pWnd = WIN_FindWndPtr( hwnd );
1566 if( pWnd )
1568 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1569 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1571 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1572 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1573 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1575 if( pWnd->dwStyle & WS_MINIMIZE )
1577 WINPOS_ShowIconTitle( pWnd, FALSE );
1578 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1579 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1580 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1582 else if( pWnd->dwStyle & WS_MAXIMIZE )
1584 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1585 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1586 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1588 else if( flags & PLACE_RECT )
1589 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1590 lpPos->rectNormal.right - lpPos->rectNormal.left,
1591 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1592 SWP_NOZORDER | SWP_NOACTIVATE );
1594 ShowWindow( hwnd, wndpl->showCmd );
1595 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1597 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1599 /* SDK: ...valid only the next time... */
1600 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1602 WIN_ReleaseWndPtr(pWnd);
1603 return TRUE;
1605 return FALSE;
1609 /***********************************************************************
1610 * SetWindowPlacement16 (USER.371)
1612 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1614 return WINPOS_SetPlacement( hwnd, wndpl,
1615 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1618 /***********************************************************************
1619 * SetWindowPlacement (USER32.519)
1621 * Win95:
1622 * Fails if wndpl->length of Win95 (!) apps is invalid.
1624 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1626 if( pwpl32 )
1628 WINDOWPLACEMENT16 wpl;
1630 wpl.length = sizeof(WINDOWPLACEMENT16);
1631 wpl.flags = pwpl32->flags;
1632 wpl.showCmd = pwpl32->showCmd;
1633 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1634 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1635 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1636 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1637 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1638 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1639 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1640 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1642 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1644 return FALSE;
1648 /***********************************************************************
1649 * SetInternalWindowPos16 (USER.461)
1651 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1652 LPRECT16 rect, LPPOINT16 pt )
1654 if( IsWindow16(hwnd) )
1656 WINDOWPLACEMENT16 wndpl;
1657 UINT flags;
1659 wndpl.length = sizeof(wndpl);
1660 wndpl.showCmd = showCmd;
1661 wndpl.flags = flags = 0;
1663 if( pt )
1665 flags |= PLACE_MIN;
1666 wndpl.flags |= WPF_SETMINPOSITION;
1667 wndpl.ptMinPosition = *pt;
1669 if( rect )
1671 flags |= PLACE_RECT;
1672 wndpl.rcNormalPosition = *rect;
1674 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1679 /***********************************************************************
1680 * SetInternalWindowPos (USER32.483)
1682 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1683 LPRECT rect, LPPOINT pt )
1685 if( IsWindow(hwnd) )
1687 WINDOWPLACEMENT16 wndpl;
1688 UINT flags;
1690 wndpl.length = sizeof(wndpl);
1691 wndpl.showCmd = showCmd;
1692 wndpl.flags = flags = 0;
1694 if( pt )
1696 flags |= PLACE_MIN;
1697 wndpl.flags |= WPF_SETMINPOSITION;
1698 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1700 if( rect )
1702 flags |= PLACE_RECT;
1703 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1705 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1709 /*******************************************************************
1710 * WINPOS_SetActiveWindow
1712 * SetActiveWindow() back-end. This is the only function that
1713 * can assign active status to a window. It must be called only
1714 * for the top level windows.
1716 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1718 CBTACTIVATESTRUCT16* cbtStruct;
1719 WND* wndPtr=0, *wndTemp;
1720 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1721 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1722 WORD wIconized = 0;
1723 HWND hwndActive = 0;
1724 BOOL bRet = 0;
1726 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1728 /* Get current active window from the active queue */
1729 if ( hActiveQueue )
1731 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1732 if ( pOldActiveQueue )
1733 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1736 /* paranoid checks */
1737 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1738 goto CLEANUP_END;
1740 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1741 * return 0;
1743 wndPtr = WIN_FindWndPtr(hWnd);
1744 hOldActiveQueue = hActiveQueue;
1746 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1748 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1749 WIN_ReleaseWndPtr(wndTemp);
1751 else
1752 TRACE("no current active window.\n");
1754 /* call CBT hook chain */
1755 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1757 cbtStruct->fMouse = fMouse;
1758 cbtStruct->hWndActive = hwndActive;
1759 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1760 (LPARAM)SEGPTR_GET(cbtStruct) );
1761 SEGPTR_FREE(cbtStruct);
1762 if (bRet) goto CLEANUP_END;
1765 /* set prev active wnd to current active wnd and send notification */
1766 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1768 MESSAGEQUEUE *pTempActiveQueue = 0;
1770 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1772 if (GetSysModalWindow16() != hWnd)
1773 goto CLEANUP_END;
1774 /* disregard refusal if hWnd is sysmodal */
1777 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1778 MAKEWPARAM( WA_INACTIVE, wIconized ),
1779 (LPARAM)hWnd );
1781 /* check if something happened during message processing
1782 * (global active queue may have changed)
1784 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1785 if(!pTempActiveQueue)
1786 goto CLEANUP_END;
1788 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1789 QUEUE_Unlock( pTempActiveQueue );
1790 if( hwndPrevActive != hwndActive )
1791 goto CLEANUP_END;
1794 /* Set new active window in the message queue */
1795 hwndActive = hWnd;
1796 if ( wndPtr )
1798 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1799 if ( pNewActiveQueue )
1800 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1802 else /* have to do this or MDI frame activation goes to hell */
1803 if( pOldActiveQueue )
1804 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1806 /* send palette messages */
1807 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1808 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1810 /* if prev wnd is minimized redraw icon title */
1811 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1813 /* managed windows will get ConfigureNotify event */
1814 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1816 /* check Z-order and bring hWnd to the top */
1817 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1819 if (wndTemp->dwStyle & WS_VISIBLE) break;
1821 WIN_ReleaseDesktop();
1822 WIN_ReleaseWndPtr(wndTemp);
1824 if( wndTemp != wndPtr )
1825 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1826 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1827 if (!IsWindow(hWnd))
1828 goto CLEANUP;
1831 /* Get a handle to the new active queue */
1832 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1834 /* send WM_ACTIVATEAPP if necessary */
1835 if (hOldActiveQueue != hNewActiveQueue)
1837 WND **list, **ppWnd;
1838 WND *pDesktop = WIN_GetDesktop();
1840 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1842 for (ppWnd = list; *ppWnd; ppWnd++)
1844 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1846 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1847 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1848 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1850 WIN_ReleaseWinArray(list);
1853 hActiveQueue = hNewActiveQueue;
1855 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1857 for (ppWnd = list; *ppWnd; ppWnd++)
1859 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1861 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1862 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1863 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1865 WIN_ReleaseWinArray(list);
1867 WIN_ReleaseDesktop();
1869 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1872 if (hWnd)
1874 /* walk up to the first unowned window */
1875 wndTemp = WIN_LockWndPtr(wndPtr);
1876 while (wndTemp->owner)
1878 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1880 /* and set last active owned popup */
1881 wndTemp->hwndLastActive = hWnd;
1883 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1884 WIN_ReleaseWndPtr(wndTemp);
1885 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1886 SendMessageA( hWnd, WM_ACTIVATE,
1887 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1888 (LPARAM)hwndPrevActive );
1889 if( !IsWindow(hWnd) ) goto CLEANUP;
1892 /* change focus if possible */
1893 if ( fChangeFocus )
1895 if ( pNewActiveQueue )
1897 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1899 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1900 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1901 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1902 0 : hwndActive );
1905 if ( pOldActiveQueue &&
1906 ( !pNewActiveQueue ||
1907 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1909 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1910 if ( hOldFocus )
1911 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1915 if( !hwndPrevActive && wndPtr )
1916 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1918 /* if active wnd is minimized redraw icon title */
1919 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1921 bRet = (hWnd == hwndActive); /* Success? */
1923 CLEANUP: /* Unlock the message queues before returning */
1925 if ( pNewActiveQueue )
1926 QUEUE_Unlock( pNewActiveQueue );
1928 CLEANUP_END:
1930 if ( pOldActiveQueue )
1931 QUEUE_Unlock( pOldActiveQueue );
1933 WIN_ReleaseWndPtr(wndPtr);
1934 return bRet;
1937 /*******************************************************************
1938 * WINPOS_ActivateOtherWindow
1940 * Activates window other than pWnd.
1942 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1944 BOOL bRet = 0;
1945 WND* pWndTo = NULL;
1946 HWND hwndActive = 0;
1948 /* Get current active window from the active queue */
1949 if ( hActiveQueue )
1951 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1952 if ( pActiveQueue )
1954 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1955 QUEUE_Unlock( pActiveQueue );
1959 if( pWnd->hwndSelf == hwndPrevActive )
1960 hwndPrevActive = 0;
1962 if( hwndActive != pWnd->hwndSelf &&
1963 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1964 return 0;
1966 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1967 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1969 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1971 WIN_ReleaseWndPtr(pWndTo);
1972 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1974 while( !WINPOS_CanActivate(pWndTo) )
1976 /* by now owned windows should've been taken care of */
1977 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1978 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1979 if( !pWndTo ) break;
1981 WIN_ReleaseWndPtr(pWndPtr);
1984 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1986 /* switch desktop queue to current active */
1987 if( pWndTo )
1989 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1990 WIN_ReleaseWndPtr(pWndTo);
1991 WIN_ReleaseDesktop();
1994 hwndPrevActive = 0;
1995 return bRet;
1998 /*******************************************************************
1999 * WINPOS_ChangeActiveWindow
2002 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2004 WND *wndPtr, *wndTemp;
2005 BOOL retvalue;
2006 HWND hwndActive = 0;
2008 /* Get current active window from the active queue */
2009 if ( hActiveQueue )
2011 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2012 if ( pActiveQueue )
2014 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2015 QUEUE_Unlock( pActiveQueue );
2019 if (!hWnd)
2020 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2022 wndPtr = WIN_FindWndPtr(hWnd);
2023 if( !wndPtr ) return FALSE;
2025 /* child windows get WM_CHILDACTIVATE message */
2026 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2028 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2029 goto end;
2032 if( hWnd == hwndActive )
2034 retvalue = FALSE;
2035 goto end;
2038 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2040 retvalue = FALSE;
2041 goto end;
2044 /* switch desktop queue to current active */
2045 wndTemp = WIN_GetDesktop();
2046 if( wndPtr->parent == wndTemp)
2047 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2048 WIN_ReleaseDesktop();
2050 retvalue = TRUE;
2051 end:
2052 WIN_ReleaseWndPtr(wndPtr);
2053 return retvalue;
2057 /***********************************************************************
2058 * WINPOS_SendNCCalcSize
2060 * Send a WM_NCCALCSIZE message to a window.
2061 * All parameters are read-only except newClientRect.
2062 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2063 * when calcValidRect is TRUE.
2065 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2066 RECT *newWindowRect, RECT *oldWindowRect,
2067 RECT *oldClientRect, WINDOWPOS *winpos,
2068 RECT *newClientRect )
2070 NCCALCSIZE_PARAMS params;
2071 WINDOWPOS winposCopy;
2072 LONG result;
2074 params.rgrc[0] = *newWindowRect;
2075 if (calcValidRect)
2077 winposCopy = *winpos;
2078 params.rgrc[1] = *oldWindowRect;
2079 params.rgrc[2] = *oldClientRect;
2080 params.lppos = &winposCopy;
2082 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2083 (LPARAM)&params );
2084 TRACE("%d,%d-%d,%d\n",
2085 params.rgrc[0].left, params.rgrc[0].top,
2086 params.rgrc[0].right, params.rgrc[0].bottom );
2088 /* If the application send back garbage, ignore it */
2089 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2090 *newClientRect = params.rgrc[0];
2092 return result;
2096 /***********************************************************************
2097 * WINPOS_HandleWindowPosChanging16
2099 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2101 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2103 POINT maxSize, minTrack;
2104 if (winpos->flags & SWP_NOSIZE) return 0;
2105 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2106 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2108 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2109 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2110 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2111 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2113 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2114 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2117 return 0;
2121 /***********************************************************************
2122 * WINPOS_HandleWindowPosChanging
2124 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2126 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2128 POINT maxSize;
2129 if (winpos->flags & SWP_NOSIZE) return 0;
2130 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2131 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2133 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2134 winpos->cx = min( winpos->cx, maxSize.x );
2135 winpos->cy = min( winpos->cy, maxSize.y );
2137 return 0;
2140 /***********************************************************************
2141 * SWP_DoOwnedPopups
2143 * fix Z order taking into account owned popups -
2144 * basically we need to maintain them above the window that owns them
2146 * FIXME: hide/show owned popups when owner visibility changes.
2148 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2150 WND* w = WIN_LockWndPtr(pDesktop->child);
2152 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2154 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2156 /* make sure this popup stays above the owner */
2158 HWND hwndLocalPrev = HWND_TOP;
2160 if( hwndInsertAfter != HWND_TOP )
2162 while( w != wndPtr->owner )
2164 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2165 if( hwndLocalPrev == hwndInsertAfter ) break;
2166 WIN_UpdateWndPtr(&w,w->next);
2168 hwndInsertAfter = hwndLocalPrev;
2171 else if( wndPtr->dwStyle & WS_CHILD )
2172 goto END;
2174 WIN_UpdateWndPtr(&w, pDesktop->child);
2176 while( w )
2178 if( w == wndPtr ) break;
2180 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2182 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2183 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2184 hwndInsertAfter = w->hwndSelf;
2186 WIN_UpdateWndPtr(&w, w->next);
2189 END:
2190 WIN_ReleaseWndPtr(w);
2191 return hwndInsertAfter;
2194 /***********************************************************************
2195 * SWP_CopyValidBits
2197 * Make window look nice without excessive repainting
2199 * visible and update regions are in window coordinates
2200 * client and window rectangles are in parent client coordinates
2202 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2203 * window rects have the same origin.
2205 * Returns: uFlags and a dirty region in *pVisRgn.
2207 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2208 LPRECT lpOldWndRect,
2209 LPRECT lpOldClientRect, UINT uFlags )
2211 RECT r;
2212 HRGN newVisRgn, dirtyRgn;
2213 INT my = COMPLEXREGION;
2215 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2216 Wnd->rectWindow.left, Wnd->rectWindow.top,
2217 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2218 lpOldWndRect->left, lpOldWndRect->top,
2219 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2220 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2221 Wnd->rectClient.left, Wnd->rectClient.top,
2222 Wnd->rectClient.right, Wnd->rectClient.bottom,
2223 lpOldClientRect->left, lpOldClientRect->top,
2224 lpOldClientRect->right,lpOldClientRect->bottom );
2226 if( Wnd->hrgnUpdate == 1 )
2227 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2229 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2230 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2232 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2233 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2235 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2237 nocopy:
2239 TRACE("\twon't copy anything!\n");
2241 /* set dirtyRgn to the sum of old and new visible regions
2242 * in parent client coordinates */
2244 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2245 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2247 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2249 else /* copy valid bits to a new location */
2251 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2252 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2254 /* subtract already invalid region inside Wnd from the dst region */
2256 if( Wnd->hrgnUpdate )
2257 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2258 goto nocopy;
2260 /* check if entire window can be copied */
2262 ow = lpOldWndRect->right - lpOldWndRect->left;
2263 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2264 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2265 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2267 ocw = lpOldClientRect->right - lpOldClientRect->left;
2268 och = lpOldClientRect->bottom - lpOldClientRect->top;
2269 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2270 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2272 if( (ocw != ncw) || (och != nch) ||
2273 ( ow != nw) || ( oh != nh) ||
2274 ((lpOldClientRect->top - lpOldWndRect->top) !=
2275 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2276 ((lpOldClientRect->left - lpOldWndRect->left) !=
2277 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2279 dx = Wnd->rectClient.left - lpOldClientRect->left;
2280 dy = Wnd->rectClient.top - lpOldClientRect->top;
2282 /* restrict valid bits to the common client rect */
2284 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2285 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2286 r.right = r.left + min( ocw, ncw );
2287 r.bottom = r.top + min( och, nch );
2289 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2290 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2291 GetRgnBox( hrgnValid, &r );
2292 if( IsRectEmpty( &r ) )
2293 goto nocopy;
2294 r = *lpOldClientRect;
2296 else
2298 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2299 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2300 if( !(uFlags & SWP_EX_PAINTSELF) )
2301 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2302 r = *lpOldWndRect;
2305 if( !(uFlags & SWP_EX_PAINTSELF) )
2307 /* Move remaining regions to parent coordinates */
2308 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2309 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2311 else
2312 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2314 TRACE("\tcomputing dirty region!\n");
2316 /* Compute combined dirty region (old + new - valid) */
2317 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2318 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2320 /* Blt valid bits, r is the rect to copy */
2322 if( dx || dy )
2324 RECT rClip;
2325 HDC hDC;
2327 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2328 from copying clipped areas */
2330 if( uFlags & SWP_EX_PAINTSELF )
2332 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2333 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2334 rClip.right = nw; rClip.bottom = nh;
2336 else
2338 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2339 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2340 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2341 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2343 rClip.left = rClip.top = 0;
2345 if( oh > nh ) r.bottom = r.top + nh;
2346 if( ow < nw ) r.right = r.left + nw;
2348 if( IntersectRect( &r, &r, &rClip ) )
2350 Wnd->pDriver->pSurfaceCopy( Wnd->parent, hDC, dx, dy, &r, TRUE );
2352 /* When you copy the bits without repainting, parent doesn't
2353 get validated appropriately. Therefore, we have to validate
2354 the parent with the windows' updated region when the
2355 parent's update region is not empty. */
2357 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2359 OffsetRect(&r, dx, dy);
2360 ValidateRect(Wnd->parent->hwndSelf, &r);
2363 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2364 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2368 /* *pVisRgn now points to the invalidated region */
2370 DeleteObject(newVisRgn);
2371 DeleteObject(dirtyRgn);
2372 return uFlags;
2375 /***********************************************************************
2376 * SWP_DoSimpleFrameChanged
2378 * NOTE: old and new client rect origins are identical, only
2379 * extents may have changed. Window extents are the same.
2381 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2383 INT i = 0;
2384 RECT rect;
2385 HRGN hrgn = 0;
2387 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2389 /* Client rect changed its position/size, most likely a scrollar
2390 * was added/removed.
2392 * FIXME: WVR alignment flags
2395 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2397 i++;
2398 rect.top = 0;
2399 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2400 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2401 if(!(uFlags & SWP_EX_NOCOPY))
2402 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2403 else
2405 rect.left = 0;
2406 goto redraw;
2410 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2412 if( i )
2413 hrgn = CreateRectRgnIndirect( &rect );
2414 rect.left = 0;
2415 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2416 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2417 if(!(uFlags & SWP_EX_NOCOPY))
2418 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2419 else
2420 rect.top = 0;
2421 if( i++ )
2422 REGION_UnionRectWithRgn( hrgn, &rect );
2425 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2427 rect = wndPtr->rectWindow;
2428 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2429 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2430 i++;
2434 if( i )
2436 redraw:
2437 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2438 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2440 else
2442 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2445 if( hrgn > 1 )
2446 DeleteObject( hrgn );
2449 /***********************************************************************
2450 * SWP_DoWinPosChanging
2452 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2453 RECT* pNewWindowRect, RECT* pNewClientRect )
2455 /* Send WM_WINDOWPOSCHANGING message */
2457 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2458 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2460 /* Calculate new position and size */
2462 *pNewWindowRect = wndPtr->rectWindow;
2463 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2464 : wndPtr->rectClient;
2466 if (!(pWinpos->flags & SWP_NOSIZE))
2468 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2469 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2471 if (!(pWinpos->flags & SWP_NOMOVE))
2473 pNewWindowRect->left = pWinpos->x;
2474 pNewWindowRect->top = pWinpos->y;
2475 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2476 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2478 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2479 pWinpos->y - wndPtr->rectWindow.top );
2482 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2483 return TRUE;
2486 /***********************************************************************
2487 * SWP_DoNCCalcSize
2489 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2490 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2492 UINT wvrFlags = 0;
2494 /* Send WM_NCCALCSIZE message to get new client area */
2495 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2497 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2498 &wndPtr->rectWindow, &wndPtr->rectClient,
2499 pWinpos, pNewClientRect );
2501 /* FIXME: WVR_ALIGNxxx */
2503 if( pNewClientRect->left != wndPtr->rectClient.left ||
2504 pNewClientRect->top != wndPtr->rectClient.top )
2505 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2507 if( (pNewClientRect->right - pNewClientRect->left !=
2508 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2509 (pNewClientRect->bottom - pNewClientRect->top !=
2510 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2511 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2513 else
2514 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2515 pNewClientRect->top != wndPtr->rectClient.top) )
2516 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2517 return wvrFlags;
2520 /***********************************************************************
2521 * SetWindowPos (USER.2)
2523 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2524 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2526 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2529 /***********************************************************************
2530 * SetWindowPos (USER32.520)
2532 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2533 INT x, INT y, INT cx, INT cy, UINT flags )
2535 WINDOWPOS winpos;
2536 WND * wndPtr,*wndTemp;
2537 RECT newWindowRect, newClientRect;
2538 RECT oldWindowRect, oldClientRect;
2539 HRGN visRgn = 0;
2540 UINT wvrFlags = 0, uFlags = 0;
2541 BOOL retvalue, resync = FALSE, bChangePos;
2542 HWND hwndActive = 0;
2544 /* Get current active window from the active queue */
2545 if ( hActiveQueue )
2547 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2548 if ( pActiveQueue )
2550 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2551 QUEUE_Unlock( pActiveQueue );
2555 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2556 hwnd, x, y, x+cx, y+cy, flags);
2558 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2559 flags &= ~SWP_WINE_NOHOSTMOVE;
2562 /* ------------------------------------------------------------------------ CHECKS */
2564 /* Check window handle */
2566 if (hwnd == GetDesktopWindow()) return FALSE;
2567 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2569 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2570 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2572 /* Fix redundant flags */
2574 if(wndPtr->dwStyle & WS_VISIBLE)
2575 flags &= ~SWP_SHOWWINDOW;
2576 else
2578 if (!(flags & SWP_SHOWWINDOW))
2579 flags |= SWP_NOREDRAW;
2580 flags &= ~SWP_HIDEWINDOW;
2583 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2585 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2586 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2587 flags |= SWP_NOSIZE; /* Already the right size */
2589 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2590 flags |= SWP_NOMOVE; /* Already the right position */
2592 if (hwnd == hwndActive)
2593 flags |= SWP_NOACTIVATE; /* Already active */
2594 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2596 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2598 flags &= ~SWP_NOZORDER;
2599 hwndInsertAfter = HWND_TOP;
2600 goto Pos;
2604 /* Check hwndInsertAfter */
2606 /* FIXME: TOPMOST not supported yet */
2607 if ((hwndInsertAfter == HWND_TOPMOST) ||
2608 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2610 /* hwndInsertAfter must be a sibling of the window */
2611 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2613 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2615 if( wnd ) {
2616 if( wnd->parent != wndPtr->parent )
2618 retvalue = FALSE;
2619 WIN_ReleaseWndPtr(wnd);
2620 goto END;
2622 /* don't need to change the Zorder of hwnd if it's already inserted
2623 * after hwndInsertAfter or when inserting hwnd after itself.
2625 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2627 WIN_ReleaseWndPtr(wnd);
2630 Pos: /* ------------------------------------------------------------------------ MAIN part */
2632 /* Fill the WINDOWPOS structure */
2634 winpos.hwnd = hwnd;
2635 winpos.hwndInsertAfter = hwndInsertAfter;
2636 winpos.x = x;
2637 winpos.y = y;
2638 winpos.cx = cx;
2639 winpos.cy = cy;
2640 winpos.flags = flags;
2642 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2644 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2646 if( wndPtr->parent == WIN_GetDesktop() )
2647 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2648 hwndInsertAfter, winpos.flags );
2649 WIN_ReleaseDesktop();
2652 if(!(wndPtr->flags & WIN_NATIVE) )
2654 if( hwndInsertAfter == HWND_TOP )
2655 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2656 else
2657 if( hwndInsertAfter == HWND_BOTTOM )
2658 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2659 else
2660 if( !(winpos.flags & SWP_NOZORDER) )
2661 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2662 winpos.flags |= SWP_NOZORDER;
2664 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2665 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2666 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2668 /* get a previous visible region for SWP_CopyValidBits() */
2669 DWORD dflags = DCX_WINDOW;
2671 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2672 dflags |= DCX_CLIPSIBLINGS;
2674 visRgn = DCE_GetVisRgn(hwnd, dflags, 0, 0);
2678 /* Common operations */
2680 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2682 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2684 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2685 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2688 /* Reset active DCEs */
2690 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2691 wndPtr->dwStyle & WS_VISIBLE) ||
2692 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2694 RECT rect;
2696 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2697 DCE_InvalidateDCE(wndPtr, &rect);
2700 oldWindowRect = wndPtr->rectWindow;
2701 oldClientRect = wndPtr->rectClient;
2703 /* Find out if we have to redraw the whole client rect */
2705 if( oldClientRect.bottom - oldClientRect.top ==
2706 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2708 if( oldClientRect.right - oldClientRect.left ==
2709 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2711 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2712 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2714 uFlags |= SWP_EX_NOCOPY;
2717 * Use this later in CopyValidBits()
2719 else if( 0 )
2720 uFlags |= SWP_EX_NONCLIENT;
2723 /* FIXME: actually do something with WVR_VALIDRECTS */
2725 wndPtr->rectWindow = newWindowRect;
2726 wndPtr->rectClient = newClientRect;
2728 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2730 BOOL bCallDriver = TRUE;
2731 HWND tempInsertAfter = winpos.hwndInsertAfter;
2733 winpos.hwndInsertAfter = hwndInsertAfter;
2735 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2737 /* This is the only place where we need to force repainting of the contents
2738 of windows created by the host window system, all other cases go through the
2739 expose event handling */
2741 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2743 cx = newWindowRect.right - newWindowRect.left;
2744 cy = newWindowRect.bottom - newWindowRect.top;
2746 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2747 winpos.hwndInsertAfter = tempInsertAfter;
2748 bCallDriver = FALSE;
2750 if( winpos.flags & SWP_NOCLIENTMOVE )
2751 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2752 else
2754 /* client area moved but window extents remained the same, copy valid bits */
2756 visRgn = CreateRectRgn( 0, 0, cx, cy );
2757 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2758 uFlags | SWP_EX_PAINTSELF );
2763 if( bCallDriver )
2765 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2767 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2768 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2769 !(uFlags & SWP_EX_NOCOPY) )
2771 /* The origin of the client rect didn't move so we can try to repaint
2772 * only the nonclient area by setting bit gravity hint for the host window system.
2775 if( !(wndPtr->flags & WIN_MANAGED) )
2777 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2778 newWindowRect.bottom - newWindowRect.top);
2779 RECT rcn = newClientRect;
2780 RECT rco = oldClientRect;
2782 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2783 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2784 IntersectRect( &rcn, &rcn, &rco );
2785 visRgn = CreateRectRgnIndirect( &rcn );
2786 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2787 DeleteObject( hrgn );
2788 uFlags = SWP_EX_PAINTSELF;
2790 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2792 else
2793 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2796 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2797 winpos.hwndInsertAfter = tempInsertAfter;
2800 if( winpos.flags & SWP_SHOWWINDOW )
2802 HWND focus, curr;
2804 wndPtr->dwStyle |= WS_VISIBLE;
2806 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2808 /* focus was set to unmapped window, reset host focus
2809 * since the window is now visible */
2811 focus = curr = GetFocus();
2812 while (curr)
2814 if (curr == hwnd)
2816 WND *pFocus = WIN_FindWndPtr( focus );
2817 if (pFocus)
2818 pFocus->pDriver->pSetFocus(pFocus);
2819 WIN_ReleaseWndPtr(pFocus);
2820 break;
2822 curr = GetParent(curr);
2826 else /* -------------------------------------------- emulated window */
2828 if( winpos.flags & SWP_SHOWWINDOW )
2830 wndPtr->dwStyle |= WS_VISIBLE;
2831 uFlags |= SWP_EX_PAINTSELF;
2832 visRgn = 1; /* redraw the whole window */
2834 else if( !(winpos.flags & SWP_NOREDRAW) )
2836 if( winpos.flags & SWP_HIDEWINDOW )
2838 if( visRgn > 1 ) /* map to parent */
2839 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2840 else
2841 visRgn = 0;
2843 else
2845 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2846 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2847 &oldClientRect, uFlags);
2848 else
2850 /* nothing moved, redraw frame if needed */
2852 if( winpos.flags & SWP_FRAMECHANGED )
2853 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2854 if( visRgn )
2856 DeleteObject( visRgn );
2857 visRgn = 0;
2864 if( winpos.flags & SWP_HIDEWINDOW )
2866 wndPtr->dwStyle &= ~WS_VISIBLE;
2869 if (hwnd == CARET_GetHwnd())
2871 if( winpos.flags & SWP_HIDEWINDOW )
2872 HideCaret(hwnd);
2873 else if (winpos.flags & SWP_SHOWWINDOW)
2874 ShowCaret(hwnd);
2877 /* ------------------------------------------------------------------------ FINAL */
2879 if (wndPtr->flags & WIN_NATIVE)
2880 EVENT_Synchronize(); /* Synchronize with the host window system */
2882 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2884 /* Simulate a mouse event to set the cursor */
2885 int iWndsLocks = WIN_SuspendWndsLock();
2887 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2888 PosX, PosY, GetTickCount(), 0 );
2890 WIN_RestoreWndsLock(iWndsLocks);
2893 wndTemp = WIN_GetDesktop();
2895 /* repaint invalidated region (if any)
2897 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2898 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2901 if( visRgn )
2903 if( !(winpos.flags & SWP_NOREDRAW) )
2906 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2907 its parent and sibling and so on, and then erase the parent window
2908 back ground if the parent is either a top-level window or its parent's parent
2909 is top-level window. Rely on the system to repaint other affected
2910 windows later on. */
2911 if( uFlags & SWP_EX_PAINTSELF )
2913 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2914 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2915 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2917 else
2919 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2920 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2921 RDW_EX_USEHRGN );
2924 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2926 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2927 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2930 if( visRgn != 1 )
2931 DeleteObject( visRgn );
2934 WIN_ReleaseDesktop();
2936 if (!(flags & SWP_NOACTIVATE))
2937 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2939 /* And last, send the WM_WINDOWPOSCHANGED message */
2941 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2943 if ( resync ||
2944 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2945 !(winpos.flags & SWP_NOSENDCHANGING)) )
2947 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2948 if (resync) EVENT_Synchronize();
2951 retvalue = TRUE;
2952 END:
2953 WIN_ReleaseWndPtr(wndPtr);
2954 return retvalue;
2958 /***********************************************************************
2959 * BeginDeferWindowPos16 (USER.259)
2961 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2963 return BeginDeferWindowPos( count );
2967 /***********************************************************************
2968 * BeginDeferWindowPos (USER32.9)
2970 HDWP WINAPI BeginDeferWindowPos( INT count )
2972 HDWP handle;
2973 DWP *pDWP;
2975 if (count < 0)
2977 SetLastError(ERROR_INVALID_PARAMETER);
2978 return 0;
2980 /* Windows allows zero count, in which case it allocates context for 8 moves */
2981 if (count == 0) count = 8;
2983 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2984 if (!handle) return 0;
2985 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2986 pDWP->actualCount = 0;
2987 pDWP->suggestedCount = count;
2988 pDWP->valid = TRUE;
2989 pDWP->wMagic = DWP_MAGIC;
2990 pDWP->hwndParent = 0;
2991 return handle;
2995 /***********************************************************************
2996 * DeferWindowPos16 (USER.260)
2998 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
2999 INT16 x, INT16 y, INT16 cx, INT16 cy,
3000 UINT16 flags )
3002 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3003 x, y, cx, cy, flags );
3007 /***********************************************************************
3008 * DeferWindowPos (USER32.128)
3010 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3011 INT x, INT y, INT cx, INT cy,
3012 UINT flags )
3014 DWP *pDWP;
3015 int i;
3016 HDWP newhdwp = hdwp,retvalue;
3017 /* HWND parent; */
3018 WND *pWnd;
3020 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3021 if (!pDWP) return 0;
3022 if (hwnd == GetDesktopWindow()) return 0;
3024 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3025 USER_HEAP_FREE( hdwp );
3026 return 0;
3029 /* Numega Bounds Checker Demo dislikes the following code.
3030 In fact, I've not been able to find any "same parent" requirement in any docu
3031 [AM 980509]
3033 #if 0
3034 /* All the windows of a DeferWindowPos() must have the same parent */
3035 parent = pWnd->parent->hwndSelf;
3036 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3037 else if (parent != pDWP->hwndParent)
3039 USER_HEAP_FREE( hdwp );
3040 retvalue = 0;
3041 goto END;
3043 #endif
3045 for (i = 0; i < pDWP->actualCount; i++)
3047 if (pDWP->winPos[i].hwnd == hwnd)
3049 /* Merge with the other changes */
3050 if (!(flags & SWP_NOZORDER))
3052 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3054 if (!(flags & SWP_NOMOVE))
3056 pDWP->winPos[i].x = x;
3057 pDWP->winPos[i].y = y;
3059 if (!(flags & SWP_NOSIZE))
3061 pDWP->winPos[i].cx = cx;
3062 pDWP->winPos[i].cy = cy;
3064 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3065 SWP_NOZORDER | SWP_NOREDRAW |
3066 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3067 SWP_NOOWNERZORDER);
3068 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3069 SWP_FRAMECHANGED);
3070 retvalue = hdwp;
3071 goto END;
3074 if (pDWP->actualCount >= pDWP->suggestedCount)
3076 newhdwp = USER_HEAP_REALLOC( hdwp,
3077 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3078 if (!newhdwp)
3080 retvalue = 0;
3081 goto END;
3083 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3084 pDWP->suggestedCount++;
3086 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3087 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3088 pDWP->winPos[pDWP->actualCount].x = x;
3089 pDWP->winPos[pDWP->actualCount].y = y;
3090 pDWP->winPos[pDWP->actualCount].cx = cx;
3091 pDWP->winPos[pDWP->actualCount].cy = cy;
3092 pDWP->winPos[pDWP->actualCount].flags = flags;
3093 pDWP->actualCount++;
3094 retvalue = newhdwp;
3095 END:
3096 WIN_ReleaseWndPtr(pWnd);
3097 return retvalue;
3101 /***********************************************************************
3102 * EndDeferWindowPos16 (USER.261)
3104 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3106 return EndDeferWindowPos( hdwp );
3110 /***********************************************************************
3111 * EndDeferWindowPos (USER32.173)
3113 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3115 DWP *pDWP;
3116 WINDOWPOS *winpos;
3117 BOOL res = TRUE;
3118 int i;
3120 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3121 if (!pDWP) return FALSE;
3122 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3124 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3125 winpos->x, winpos->y, winpos->cx,
3126 winpos->cy, winpos->flags ))) break;
3128 USER_HEAP_FREE( hdwp );
3129 return res;
3133 /***********************************************************************
3134 * TileChildWindows (USER.199)
3136 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3138 FIXME("(%04x, %d): stub\n", parent, action);
3141 /***********************************************************************
3142 * CascadeChildWindows (USER.198)
3144 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3146 FIXME("(%04x, %d): stub\n", parent, action);
3149 /***********************************************************************
3150 * SetProgmanWindow [USER32.522]
3152 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3154 hGlobalProgmanWindow = hwnd;
3155 return hGlobalProgmanWindow;
3158 /***********************************************************************
3159 * GetProgmanWindow [USER32.289]
3161 HRESULT WINAPI GetProgmanWindow ( )
3163 return hGlobalProgmanWindow;
3166 /***********************************************************************
3167 * SetShellWindowEx [USER32.531]
3168 * hwndProgman = Progman[Program Manager]
3169 * |-> SHELLDLL_DefView
3170 * hwndListView = | |-> SysListView32
3171 * | | |-> tooltips_class32
3172 * | |
3173 * | |-> SysHeader32
3174 * |
3175 * |-> ProxyTarget
3177 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3179 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3180 hGlobalShellWindow = hwndProgman;
3181 return hGlobalShellWindow;
3185 /***********************************************************************
3186 * SetTaskmanWindow [USER32.537]
3187 * NOTES
3188 * hwnd = MSTaskSwWClass
3189 * |-> SysTabControl32
3191 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3193 hGlobalTaskmanWindow = hwnd;
3194 return hGlobalTaskmanWindow;
3197 /***********************************************************************
3198 * GetTaskmanWindow [USER32.304]
3200 HRESULT WINAPI GetTaskmanWindow ( )
3202 return hGlobalTaskmanWindow;