Create dll/kernel/messages directory.
[wine/dcerpc.git] / windows / winpos.c
blob9b4b36ccbe6f23bd8afaf7df4ab15ada3dd4690b
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 *ppWnd = NULL;
442 wndPtr = WIN_LockWndPtr(wndScope->child);
444 if( wndScope->dwStyle & WS_DISABLED )
446 retvalue = HTERROR;
447 goto end;
450 if( wndScope->flags & WIN_MANAGED )
452 /* In managed mode we have to check wndScope first as it is also
453 * a window which received the mouse event. */
455 if( pt.x < wndScope->rectClient.left || pt.x >= wndScope->rectClient.right ||
456 pt.y < wndScope->rectClient.top || pt.y >= wndScope->rectClient.bottom )
457 goto hittest;
459 MapWindowPoints16( GetDesktopWindow16(), wndScope->hwndSelf, &xy, 1 );
461 for (;;)
463 while (wndPtr)
465 /* If point is in window, and window is visible, and it */
466 /* is enabled (or it's a top-level window), then explore */
467 /* its children. Otherwise, go to the next window. */
469 if ((wndPtr->dwStyle & WS_VISIBLE) &&
470 (!(wndPtr->dwStyle & WS_DISABLED) ||
471 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD)) &&
472 (xy.x >= wndPtr->rectWindow.left) &&
473 (xy.x < wndPtr->rectWindow.right) &&
474 (xy.y >= wndPtr->rectWindow.top) &&
475 (xy.y < wndPtr->rectWindow.bottom))
477 *ppWnd = wndPtr; /* Got a suitable window */
479 /* If window is minimized or disabled, return at once */
480 if (wndPtr->dwStyle & WS_MINIMIZE)
482 retvalue = HTCAPTION;
483 goto end;
485 if (wndPtr->dwStyle & WS_DISABLED)
487 retvalue = HTERROR;
488 goto end;
491 /* If point is not in client area, ignore the children */
492 if ((xy.x < wndPtr->rectClient.left) ||
493 (xy.x >= wndPtr->rectClient.right) ||
494 (xy.y < wndPtr->rectClient.top) ||
495 (xy.y >= wndPtr->rectClient.bottom)) break;
497 xy.x -= wndPtr->rectClient.left;
498 xy.y -= wndPtr->rectClient.top;
499 WIN_UpdateWndPtr(&wndPtr,wndPtr->child);
501 else
503 WIN_UpdateWndPtr(&wndPtr,wndPtr->next);
507 hittest:
508 /* If nothing found, try the scope window */
509 if (!*ppWnd) *ppWnd = wndScope;
511 /* Send the WM_NCHITTEST message (only if to the same task) */
512 if ((*ppWnd)->hmemTaskQ == GetFastQueue16())
514 hittest = (INT16)SendMessage16( (*ppWnd)->hwndSelf, WM_NCHITTEST,
515 0, MAKELONG( pt.x, pt.y ) );
516 if (hittest != HTTRANSPARENT)
518 retvalue = hittest; /* Found the window */
519 goto end;
522 else
524 retvalue = HTCLIENT;
525 goto end;
528 /* If no children found in last search, make point relative to parent */
529 if (!wndPtr)
531 xy.x += (*ppWnd)->rectClient.left;
532 xy.y += (*ppWnd)->rectClient.top;
535 /* Restart the search from the next sibling */
536 WIN_UpdateWndPtr(&wndPtr,(*ppWnd)->next);
537 *ppWnd = (*ppWnd)->parent;
540 end:
541 WIN_ReleaseWndPtr(wndPtr);
542 return retvalue;
546 /*******************************************************************
547 * WindowFromPoint16 (USER.30)
549 HWND16 WINAPI WindowFromPoint16( POINT16 pt )
551 WND *pWnd;
552 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt, &pWnd );
553 WIN_ReleaseDesktop();
554 return pWnd->hwndSelf;
558 /*******************************************************************
559 * WindowFromPoint (USER32.582)
561 HWND WINAPI WindowFromPoint( POINT pt )
563 WND *pWnd;
564 POINT16 pt16;
565 CONV_POINT32TO16( &pt, &pt16 );
566 WINPOS_WindowFromPoint( WIN_GetDesktop(), pt16, &pWnd );
567 WIN_ReleaseDesktop();
568 return (HWND)pWnd->hwndSelf;
572 /*******************************************************************
573 * ChildWindowFromPoint16 (USER.191)
575 HWND16 WINAPI ChildWindowFromPoint16( HWND16 hwndParent, POINT16 pt )
577 POINT pt32;
578 CONV_POINT16TO32( &pt, &pt32 );
579 return (HWND16)ChildWindowFromPoint( hwndParent, pt32 );
583 /*******************************************************************
584 * ChildWindowFromPoint (USER32.49)
586 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
588 /* pt is in the client coordinates */
590 WND* wnd = WIN_FindWndPtr(hwndParent);
591 RECT rect;
592 HWND retvalue;
594 if( !wnd ) return 0;
596 /* get client rect fast */
597 rect.top = rect.left = 0;
598 rect.right = wnd->rectClient.right - wnd->rectClient.left;
599 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
601 if (!PtInRect( &rect, pt ))
603 retvalue = 0;
604 goto end;
606 WIN_UpdateWndPtr(&wnd,wnd->child);
607 while ( wnd )
609 if (PtInRect( &wnd->rectWindow, pt ))
611 retvalue = wnd->hwndSelf;
612 goto end;
614 WIN_UpdateWndPtr(&wnd,wnd->next);
616 retvalue = hwndParent;
617 end:
618 WIN_ReleaseWndPtr(wnd);
619 return retvalue;
622 /*******************************************************************
623 * ChildWindowFromPointEx16 (USER.50)
625 HWND16 WINAPI ChildWindowFromPointEx16( HWND16 hwndParent, POINT16 pt, UINT16 uFlags)
627 POINT pt32;
628 CONV_POINT16TO32( &pt, &pt32 );
629 return (HWND16)ChildWindowFromPointEx( hwndParent, pt32, uFlags );
633 /*******************************************************************
634 * ChildWindowFromPointEx (USER32.50)
636 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt,
637 UINT uFlags)
639 /* pt is in the client coordinates */
641 WND* wnd = WIN_FindWndPtr(hwndParent);
642 RECT rect;
643 HWND retvalue;
645 if( !wnd ) return 0;
647 /* get client rect fast */
648 rect.top = rect.left = 0;
649 rect.right = wnd->rectClient.right - wnd->rectClient.left;
650 rect.bottom = wnd->rectClient.bottom - wnd->rectClient.top;
652 if (!PtInRect( &rect, pt ))
654 retvalue = 0;
655 goto end;
657 WIN_UpdateWndPtr(&wnd,wnd->child);
659 while ( wnd )
661 if (PtInRect( &wnd->rectWindow, pt )) {
662 if ( (uFlags & CWP_SKIPINVISIBLE) &&
663 !(wnd->dwStyle & WS_VISIBLE) );
664 else if ( (uFlags & CWP_SKIPDISABLED) &&
665 (wnd->dwStyle & WS_DISABLED) );
666 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
667 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
668 else
670 retvalue = wnd->hwndSelf;
671 goto end;
675 WIN_UpdateWndPtr(&wnd,wnd->next);
677 retvalue = hwndParent;
678 end:
679 WIN_ReleaseWndPtr(wnd);
680 return retvalue;
684 /*******************************************************************
685 * WINPOS_GetWinOffset
687 * Calculate the offset between the origin of the two windows. Used
688 * to implement MapWindowPoints.
690 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo,
691 POINT *offset )
693 WND * wndPtr = 0;
695 offset->x = offset->y = 0;
696 if (hwndFrom == hwndTo ) return;
698 /* Translate source window origin to screen coords */
699 if (hwndFrom)
701 if (!(wndPtr = WIN_FindWndPtr( hwndFrom )))
703 ERR("bad hwndFrom = %04x\n",hwndFrom);
704 return;
706 while (wndPtr->parent)
708 offset->x += wndPtr->rectClient.left;
709 offset->y += wndPtr->rectClient.top;
710 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
712 WIN_ReleaseWndPtr(wndPtr);
715 /* Translate origin to destination window coords */
716 if (hwndTo)
718 if (!(wndPtr = WIN_FindWndPtr( hwndTo )))
720 ERR("bad hwndTo = %04x\n", hwndTo );
721 return;
723 while (wndPtr->parent)
725 offset->x -= wndPtr->rectClient.left;
726 offset->y -= wndPtr->rectClient.top;
727 WIN_UpdateWndPtr(&wndPtr,wndPtr->parent);
729 WIN_ReleaseWndPtr(wndPtr);
734 /*******************************************************************
735 * MapWindowPoints16 (USER.258)
737 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
738 LPPOINT16 lppt, UINT16 count )
740 POINT offset;
742 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
743 while (count--)
745 lppt->x += offset.x;
746 lppt->y += offset.y;
747 lppt++;
752 /*******************************************************************
753 * MapWindowPoints (USER32.386)
755 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo,
756 LPPOINT lppt, UINT count )
758 POINT offset;
760 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
761 while (count--)
763 lppt->x += offset.x;
764 lppt->y += offset.y;
765 lppt++;
767 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
771 /***********************************************************************
772 * IsIconic16 (USER.31)
774 BOOL16 WINAPI IsIconic16(HWND16 hWnd)
776 return IsIconic(hWnd);
780 /***********************************************************************
781 * IsIconic (USER32.345)
783 BOOL WINAPI IsIconic(HWND hWnd)
785 BOOL retvalue;
786 WND * wndPtr = WIN_FindWndPtr(hWnd);
787 if (wndPtr == NULL) return FALSE;
788 retvalue = (wndPtr->dwStyle & WS_MINIMIZE) != 0;
789 WIN_ReleaseWndPtr(wndPtr);
790 return retvalue;
794 /***********************************************************************
795 * IsZoomed (USER.272)
797 BOOL16 WINAPI IsZoomed16(HWND16 hWnd)
799 return IsZoomed(hWnd);
803 /***********************************************************************
804 * IsZoomed (USER.352)
806 BOOL WINAPI IsZoomed(HWND hWnd)
808 BOOL retvalue;
809 WND * wndPtr = WIN_FindWndPtr(hWnd);
810 if (wndPtr == NULL) return FALSE;
811 retvalue = (wndPtr->dwStyle & WS_MAXIMIZE) != 0;
812 WIN_ReleaseWndPtr(wndPtr);
813 return retvalue;
817 /*******************************************************************
818 * GetActiveWindow (USER.60)
820 HWND16 WINAPI GetActiveWindow16(void)
822 return (HWND16)GetActiveWindow();
825 /*******************************************************************
826 * GetActiveWindow (USER32.205)
828 HWND WINAPI GetActiveWindow(void)
830 MESSAGEQUEUE *pCurMsgQ = 0;
831 HWND hwndActive = 0;
833 /* Get the messageQ for the current thread */
834 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
836 WARN("\tCurrent message queue not found. Exiting!\n" );
837 return 0;
840 /* Return the current active window from the perQ data of the current message Q */
841 hwndActive = PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
843 QUEUE_Unlock( pCurMsgQ );
844 return hwndActive;
848 /*******************************************************************
849 * WINPOS_CanActivate
851 static BOOL WINPOS_CanActivate(WND* pWnd)
853 if( pWnd && ( (pWnd->dwStyle & (WS_DISABLED | WS_VISIBLE | WS_CHILD))
854 == WS_VISIBLE ) ) return TRUE;
855 return FALSE;
859 /*******************************************************************
860 * SetActiveWindow16 (USER.59)
862 HWND16 WINAPI SetActiveWindow16( HWND16 hwnd )
864 return SetActiveWindow(hwnd);
868 /*******************************************************************
869 * SetActiveWindow (USER32.463)
871 HWND WINAPI SetActiveWindow( HWND hwnd )
873 HWND prev = 0;
874 WND *wndPtr = WIN_FindWndPtr( hwnd );
875 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
877 if (!wndPtr || (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)))
879 prev = 0;
880 goto end;
883 /* Get the messageQ for the current thread */
884 if (!(pCurMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() )))
886 WARN("\tCurrent message queue not found. Exiting!\n" );
887 goto CLEANUP;
890 /* Retrieve the message queue associated with this window */
891 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
892 if ( !pMsgQ )
894 WARN("\tWindow message queue not found. Exiting!\n" );
895 goto CLEANUP;
898 /* Make sure that the window is associated with the calling threads
899 * message queue. It must share the same perQ data.
902 if ( pCurMsgQ->pQData != pMsgQ->pQData )
903 goto CLEANUP;
905 /* Save current active window */
906 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
908 WINPOS_SetActiveWindow( hwnd, 0, 0 );
910 CLEANUP:
911 /* Unlock the queues before returning */
912 if ( pMsgQ )
913 QUEUE_Unlock( pMsgQ );
914 if ( pCurMsgQ )
915 QUEUE_Unlock( pCurMsgQ );
917 end:
918 WIN_ReleaseWndPtr(wndPtr);
919 return prev;
923 /*******************************************************************
924 * GetForegroundWindow16 (USER.608)
926 HWND16 WINAPI GetForegroundWindow16(void)
928 return (HWND16)GetForegroundWindow();
932 /*******************************************************************
933 * SetForegroundWindow16 (USER.609)
935 BOOL16 WINAPI SetForegroundWindow16( HWND16 hwnd )
937 return SetForegroundWindow( hwnd );
941 /*******************************************************************
942 * GetForegroundWindow (USER32.241)
944 HWND WINAPI GetForegroundWindow(void)
946 HWND hwndActive = 0;
948 /* Get the foreground window (active window of hActiveQueue) */
949 if ( hActiveQueue )
951 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
952 if ( pActiveQueue )
953 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
955 QUEUE_Unlock( pActiveQueue );
958 return hwndActive;
961 /*******************************************************************
962 * SetForegroundWindow (USER32.482)
964 BOOL WINAPI SetForegroundWindow( HWND hwnd )
966 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
970 /*******************************************************************
971 * GetShellWindow16 (USER.600)
973 HWND16 WINAPI GetShellWindow16(void)
975 return GetShellWindow();
978 /*******************************************************************
979 * SetShellWindow (USER32.504)
981 HWND WINAPI SetShellWindow(HWND hwndshell)
982 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
984 hGlobalShellWindow = hwndshell;
985 return hGlobalShellWindow;
989 /*******************************************************************
990 * GetShellWindow (USER32.287)
992 HWND WINAPI GetShellWindow(void)
993 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
995 return hGlobalShellWindow;
999 /***********************************************************************
1000 * BringWindowToTop16 (USER.45)
1002 BOOL16 WINAPI BringWindowToTop16( HWND16 hwnd )
1004 return BringWindowToTop(hwnd);
1008 /***********************************************************************
1009 * BringWindowToTop (USER32.11)
1011 BOOL WINAPI BringWindowToTop( HWND hwnd )
1013 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
1017 /***********************************************************************
1018 * MoveWindow16 (USER.56)
1020 BOOL16 WINAPI MoveWindow16( HWND16 hwnd, INT16 x, INT16 y, INT16 cx, INT16 cy,
1021 BOOL16 repaint )
1023 return MoveWindow(hwnd,x,y,cx,cy,repaint);
1027 /***********************************************************************
1028 * MoveWindow (USER32.399)
1030 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
1031 BOOL repaint )
1033 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
1034 if (!repaint) flags |= SWP_NOREDRAW;
1035 TRACE("%04x %d,%d %dx%d %d\n",
1036 hwnd, x, y, cx, cy, repaint );
1037 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
1040 /***********************************************************************
1041 * WINPOS_InitInternalPos
1043 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt,
1044 LPRECT restoreRect )
1046 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
1047 atomInternalPos );
1048 if( !lpPos )
1050 /* this happens when the window is minimized/maximized
1051 * for the first time (rectWindow is not adjusted yet) */
1053 lpPos = HeapAlloc( SystemHeap, 0, sizeof(INTERNALPOS) );
1054 if( !lpPos ) return NULL;
1056 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
1057 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
1058 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
1059 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
1062 if( wnd->dwStyle & WS_MINIMIZE )
1063 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
1064 else if( wnd->dwStyle & WS_MAXIMIZE )
1065 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1066 else if( restoreRect )
1067 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
1069 return lpPos;
1072 /***********************************************************************
1073 * WINPOS_RedrawIconTitle
1075 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
1077 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
1078 if( lpPos )
1080 if( lpPos->hwndIconTitle )
1082 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
1083 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
1084 return TRUE;
1087 return FALSE;
1090 /***********************************************************************
1091 * WINPOS_ShowIconTitle
1093 BOOL WINPOS_ShowIconTitle( WND* pWnd, BOOL bShow )
1095 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( pWnd->hwndSelf, atomInternalPos );
1097 if( lpPos && !(pWnd->flags & WIN_MANAGED))
1099 HWND16 hWnd = lpPos->hwndIconTitle;
1101 TRACE("0x%04x %i\n", pWnd->hwndSelf, (bShow != 0) );
1103 if( !hWnd )
1104 lpPos->hwndIconTitle = hWnd = ICONTITLE_Create( pWnd );
1105 if( bShow )
1107 if( ( pWnd = WIN_FindWndPtr(hWnd) ) != NULL)
1109 if( !(pWnd->dwStyle & WS_VISIBLE) )
1111 SendMessageA( hWnd, WM_SHOWWINDOW, TRUE, 0 );
1112 SetWindowPos( hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
1113 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
1115 WIN_ReleaseWndPtr(pWnd);
1118 else ShowWindow( hWnd, SW_HIDE );
1120 return FALSE;
1123 /*******************************************************************
1124 * WINPOS_GetMinMaxInfo
1126 * Get the minimized and maximized information for a window.
1128 void WINPOS_GetMinMaxInfo( WND *wndPtr, POINT *maxSize, POINT *maxPos,
1129 POINT *minTrack, POINT *maxTrack )
1131 LPINTERNALPOS lpPos;
1132 MINMAXINFO MinMax;
1133 INT xinc, yinc;
1135 /* Compute default values */
1137 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
1138 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
1139 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
1140 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
1141 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
1142 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
1144 if (wndPtr->flags & WIN_MANAGED) xinc = yinc = 0;
1145 else if (HAS_DLGFRAME( wndPtr->dwStyle, wndPtr->dwExStyle ))
1147 xinc = GetSystemMetrics(SM_CXDLGFRAME);
1148 yinc = GetSystemMetrics(SM_CYDLGFRAME);
1150 else
1152 xinc = yinc = 0;
1153 if (HAS_THICKFRAME(wndPtr->dwStyle))
1155 xinc += GetSystemMetrics(SM_CXFRAME);
1156 yinc += GetSystemMetrics(SM_CYFRAME);
1158 if (wndPtr->dwStyle & WS_BORDER)
1160 xinc += GetSystemMetrics(SM_CXBORDER);
1161 yinc += GetSystemMetrics(SM_CYBORDER);
1164 MinMax.ptMaxSize.x += 2 * xinc;
1165 MinMax.ptMaxSize.y += 2 * yinc;
1167 lpPos = (LPINTERNALPOS)GetPropA( wndPtr->hwndSelf, atomInternalPos );
1168 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
1169 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
1170 else
1172 MinMax.ptMaxPosition.x = -xinc;
1173 MinMax.ptMaxPosition.y = -yinc;
1176 SendMessageA( wndPtr->hwndSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
1178 /* Some sanity checks */
1180 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
1181 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
1182 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
1183 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
1184 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
1185 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
1186 MinMax.ptMinTrackSize.x );
1187 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
1188 MinMax.ptMinTrackSize.y );
1190 if (maxSize) *maxSize = MinMax.ptMaxSize;
1191 if (maxPos) *maxPos = MinMax.ptMaxPosition;
1192 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
1193 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
1196 /***********************************************************************
1197 * WINPOS_MinMaximize
1199 * Fill in lpRect and return additional flags to be used with SetWindowPos().
1200 * This function assumes that 'cmd' is different from the current window
1201 * state.
1203 UINT WINPOS_MinMaximize( WND* wndPtr, UINT16 cmd, LPRECT16 lpRect )
1205 UINT swpFlags = 0;
1206 POINT pt, size;
1207 LPINTERNALPOS lpPos;
1209 TRACE("0x%04x %u\n", wndPtr->hwndSelf, cmd );
1211 size.x = wndPtr->rectWindow.left; size.y = wndPtr->rectWindow.top;
1212 lpPos = WINPOS_InitInternalPos( wndPtr, size, &wndPtr->rectWindow );
1214 if (lpPos && !HOOK_CallHooks16(WH_CBT, HCBT_MINMAX, wndPtr->hwndSelf, cmd))
1216 if( wndPtr->dwStyle & WS_MINIMIZE )
1218 if( !SendMessageA( wndPtr->hwndSelf, WM_QUERYOPEN, 0, 0L ) )
1219 return (SWP_NOSIZE | SWP_NOMOVE);
1220 swpFlags |= SWP_NOCOPYBITS;
1222 switch( cmd )
1224 case SW_MINIMIZE:
1225 if( wndPtr->dwStyle & WS_MAXIMIZE)
1227 wndPtr->flags |= WIN_RESTORE_MAX;
1228 wndPtr->dwStyle &= ~WS_MAXIMIZE;
1230 else
1231 wndPtr->flags &= ~WIN_RESTORE_MAX;
1232 wndPtr->dwStyle |= WS_MINIMIZE;
1234 if( wndPtr->flags & WIN_NATIVE )
1235 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, TRUE ) )
1236 swpFlags |= MINMAX_NOSWP;
1238 lpPos->ptIconPos = WINPOS_FindIconPos( wndPtr, lpPos->ptIconPos );
1240 SetRect16( lpRect, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1241 GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON) );
1242 swpFlags |= SWP_NOCOPYBITS;
1243 break;
1245 case SW_MAXIMIZE:
1246 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1247 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL );
1248 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1250 if( wndPtr->dwStyle & WS_MINIMIZE )
1252 if( wndPtr->flags & WIN_NATIVE )
1253 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1254 swpFlags |= MINMAX_NOSWP;
1256 WINPOS_ShowIconTitle( wndPtr, FALSE );
1257 wndPtr->dwStyle &= ~WS_MINIMIZE;
1259 wndPtr->dwStyle |= WS_MAXIMIZE;
1261 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1262 size.x, size.y );
1263 break;
1265 case SW_RESTORE:
1266 if( wndPtr->dwStyle & WS_MINIMIZE )
1268 if( wndPtr->flags & WIN_NATIVE )
1269 if( wndPtr->pDriver->pSetHostAttr( wndPtr, HAK_ICONICSTATE, FALSE ) )
1270 swpFlags |= MINMAX_NOSWP;
1272 wndPtr->dwStyle &= ~WS_MINIMIZE;
1273 WINPOS_ShowIconTitle( wndPtr, FALSE );
1275 if( wndPtr->flags & WIN_RESTORE_MAX)
1277 /* Restore to maximized position */
1278 CONV_POINT16TO32( &lpPos->ptMaxPos, &pt );
1279 WINPOS_GetMinMaxInfo( wndPtr, &size, &pt, NULL, NULL);
1280 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
1281 wndPtr->dwStyle |= WS_MAXIMIZE;
1282 SetRect16( lpRect, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y, size.x, size.y );
1283 break;
1286 else
1287 if( !(wndPtr->dwStyle & WS_MAXIMIZE) ) return (UINT16)(-1);
1288 else wndPtr->dwStyle &= ~WS_MAXIMIZE;
1290 /* Restore to normal position */
1292 *lpRect = lpPos->rectNormal;
1293 lpRect->right -= lpRect->left;
1294 lpRect->bottom -= lpRect->top;
1296 break;
1298 } else swpFlags |= SWP_NOSIZE | SWP_NOMOVE;
1299 return swpFlags;
1302 /***********************************************************************
1303 * ShowWindowAsync (USER32.535)
1305 * doesn't wait; returns immediately.
1306 * used by threads to toggle windows in other (possibly hanging) threads
1308 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1310 /* FIXME: does ShowWindow() return immediately ? */
1311 return ShowWindow(hwnd, cmd);
1315 /***********************************************************************
1316 * ShowWindow16 (USER.42)
1318 BOOL16 WINAPI ShowWindow16( HWND16 hwnd, INT16 cmd )
1320 return ShowWindow(hwnd,cmd);
1324 /***********************************************************************
1325 * ShowWindow (USER32.534)
1327 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1329 WND* wndPtr = WIN_FindWndPtr( hwnd );
1330 BOOL wasVisible, showFlag;
1331 RECT16 newPos = {0, 0, 0, 0};
1332 UINT swp = 0;
1334 if (!wndPtr) return FALSE;
1336 TRACE("hwnd=%04x, cmd=%d\n", hwnd, cmd);
1338 wasVisible = (wndPtr->dwStyle & WS_VISIBLE) != 0;
1340 switch(cmd)
1342 case SW_HIDE:
1343 if (!wasVisible) goto END;;
1344 swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE |
1345 SWP_NOACTIVATE | SWP_NOZORDER;
1346 break;
1348 case SW_SHOWMINNOACTIVE:
1349 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1350 /* fall through */
1351 case SW_SHOWMINIMIZED:
1352 swp |= SWP_SHOWWINDOW;
1353 /* fall through */
1354 case SW_MINIMIZE:
1355 swp |= SWP_FRAMECHANGED;
1356 if( !(wndPtr->dwStyle & WS_MINIMIZE) )
1357 swp |= WINPOS_MinMaximize( wndPtr, SW_MINIMIZE, &newPos );
1358 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1359 break;
1361 case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
1362 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1363 if( !(wndPtr->dwStyle & WS_MAXIMIZE) )
1364 swp |= WINPOS_MinMaximize( wndPtr, SW_MAXIMIZE, &newPos );
1365 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1366 break;
1368 case SW_SHOWNA:
1369 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1370 /* fall through */
1371 case SW_SHOW:
1372 swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1375 * ShowWindow has a little peculiar behavior that if the
1376 * window is already the topmost window, it will not
1377 * activate it.
1379 if (GetTopWindow((HWND)0)==hwnd && (wasVisible || GetActiveWindow() == hwnd))
1380 swp |= SWP_NOACTIVATE;
1382 break;
1384 case SW_SHOWNOACTIVATE:
1385 swp |= SWP_NOZORDER;
1386 if (GetActiveWindow()) swp |= SWP_NOACTIVATE;
1387 /* fall through */
1388 case SW_SHOWNORMAL: /* same as SW_NORMAL: */
1389 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
1390 case SW_RESTORE:
1391 swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1393 if( wndPtr->dwStyle & (WS_MINIMIZE | WS_MAXIMIZE) )
1394 swp |= WINPOS_MinMaximize( wndPtr, SW_RESTORE, &newPos );
1395 else swp |= SWP_NOSIZE | SWP_NOMOVE;
1396 break;
1399 showFlag = (cmd != SW_HIDE);
1400 if (showFlag != wasVisible)
1402 SendMessageA( hwnd, WM_SHOWWINDOW, showFlag, 0 );
1403 if (!IsWindow( hwnd )) goto END;
1406 if ((wndPtr->dwStyle & WS_CHILD) &&
1407 !IsWindowVisible( wndPtr->parent->hwndSelf ) &&
1408 (swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE) )
1410 /* Don't call SetWindowPos() on invisible child windows */
1411 if (cmd == SW_HIDE) wndPtr->dwStyle &= ~WS_VISIBLE;
1412 else wndPtr->dwStyle |= WS_VISIBLE;
1414 else
1416 /* We can't activate a child window */
1417 if ((wndPtr->dwStyle & WS_CHILD) &&
1418 !(wndPtr->dwExStyle & WS_EX_MDICHILD))
1419 swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1420 if (!(swp & MINMAX_NOSWP))
1422 SetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
1423 newPos.right, newPos.bottom, LOWORD(swp) );
1424 if (cmd == SW_HIDE)
1426 /* FIXME: This will cause the window to be activated irrespective
1427 * of whether it is owned by the same thread. Has to be done
1428 * asynchronously.
1431 if (hwnd == GetActiveWindow())
1432 WINPOS_ActivateOtherWindow(wndPtr);
1434 /* Revert focus to parent */
1435 if (hwnd == GetFocus() || IsChild(hwnd, GetFocus()))
1436 SetFocus( GetParent(hwnd) );
1439 if (!IsWindow( hwnd )) goto END;
1440 else if( wndPtr->dwStyle & WS_MINIMIZE ) WINPOS_ShowIconTitle( wndPtr, TRUE );
1443 if (wndPtr->flags & WIN_NEED_SIZE)
1445 /* should happen only in CreateWindowEx() */
1446 int wParam = SIZE_RESTORED;
1448 wndPtr->flags &= ~WIN_NEED_SIZE;
1449 if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
1450 else if (wndPtr->dwStyle & WS_MINIMIZE) wParam = SIZE_MINIMIZED;
1451 SendMessageA( hwnd, WM_SIZE, wParam,
1452 MAKELONG(wndPtr->rectClient.right-wndPtr->rectClient.left,
1453 wndPtr->rectClient.bottom-wndPtr->rectClient.top));
1454 SendMessageA( hwnd, WM_MOVE, 0,
1455 MAKELONG(wndPtr->rectClient.left, wndPtr->rectClient.top) );
1458 END:
1459 WIN_ReleaseWndPtr(wndPtr);
1460 return wasVisible;
1464 /***********************************************************************
1465 * GetInternalWindowPos16 (USER.460)
1467 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1468 LPPOINT16 ptIcon )
1470 WINDOWPLACEMENT16 wndpl;
1471 if (GetWindowPlacement16( hwnd, &wndpl ))
1473 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1474 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1475 return wndpl.showCmd;
1477 return 0;
1481 /***********************************************************************
1482 * GetInternalWindowPos (USER32.245)
1484 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1485 LPPOINT ptIcon )
1487 WINDOWPLACEMENT wndpl;
1488 if (GetWindowPlacement( hwnd, &wndpl ))
1490 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1491 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1492 return wndpl.showCmd;
1494 return 0;
1497 /***********************************************************************
1498 * GetWindowPlacement16 (USER.370)
1500 BOOL16 WINAPI GetWindowPlacement16( HWND16 hwnd, WINDOWPLACEMENT16 *wndpl )
1502 WND *pWnd = WIN_FindWndPtr( hwnd );
1503 LPINTERNALPOS lpPos;
1505 if(!pWnd ) return FALSE;
1507 lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1508 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1509 wndpl->length = sizeof(*wndpl);
1510 if( pWnd->dwStyle & WS_MINIMIZE )
1511 wndpl->showCmd = SW_SHOWMINIMIZED;
1512 else
1513 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE )
1514 ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1515 if( pWnd->flags & WIN_RESTORE_MAX )
1516 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1517 else
1518 wndpl->flags = 0;
1519 wndpl->ptMinPosition = lpPos->ptIconPos;
1520 wndpl->ptMaxPosition = lpPos->ptMaxPos;
1521 wndpl->rcNormalPosition = lpPos->rectNormal;
1523 WIN_ReleaseWndPtr(pWnd);
1524 return TRUE;
1528 /***********************************************************************
1529 * GetWindowPlacement (USER32.307)
1531 * Win95:
1532 * Fails if wndpl->length of Win95 (!) apps is invalid.
1534 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *pwpl32 )
1536 if( pwpl32 )
1538 WINDOWPLACEMENT16 wpl;
1539 wpl.length = sizeof(wpl);
1540 if( GetWindowPlacement16( hwnd, &wpl ) )
1542 pwpl32->length = sizeof(*pwpl32);
1543 pwpl32->flags = wpl.flags;
1544 pwpl32->showCmd = wpl.showCmd;
1545 CONV_POINT16TO32( &wpl.ptMinPosition, &pwpl32->ptMinPosition );
1546 CONV_POINT16TO32( &wpl.ptMaxPosition, &pwpl32->ptMaxPosition );
1547 CONV_RECT16TO32( &wpl.rcNormalPosition, &pwpl32->rcNormalPosition );
1548 return TRUE;
1551 return FALSE;
1555 /***********************************************************************
1556 * WINPOS_SetPlacement
1558 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT16 *wndpl,
1559 UINT flags )
1561 WND *pWnd = WIN_FindWndPtr( hwnd );
1562 if( pWnd )
1564 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1565 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1567 if( flags & PLACE_MIN ) lpPos->ptIconPos = wndpl->ptMinPosition;
1568 if( flags & PLACE_MAX ) lpPos->ptMaxPos = wndpl->ptMaxPosition;
1569 if( flags & PLACE_RECT) lpPos->rectNormal = wndpl->rcNormalPosition;
1571 if( pWnd->dwStyle & WS_MINIMIZE )
1573 WINPOS_ShowIconTitle( pWnd, FALSE );
1574 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1575 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1576 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1578 else if( pWnd->dwStyle & WS_MAXIMIZE )
1580 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1581 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1582 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1584 else if( flags & PLACE_RECT )
1585 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1586 lpPos->rectNormal.right - lpPos->rectNormal.left,
1587 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1588 SWP_NOZORDER | SWP_NOACTIVATE );
1590 ShowWindow( hwnd, wndpl->showCmd );
1591 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1593 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd, TRUE );
1595 /* SDK: ...valid only the next time... */
1596 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1598 WIN_ReleaseWndPtr(pWnd);
1599 return TRUE;
1601 return FALSE;
1605 /***********************************************************************
1606 * SetWindowPlacement16 (USER.371)
1608 BOOL16 WINAPI SetWindowPlacement16(HWND16 hwnd, const WINDOWPLACEMENT16 *wndpl)
1610 return WINPOS_SetPlacement( hwnd, wndpl,
1611 PLACE_MIN | PLACE_MAX | PLACE_RECT );
1614 /***********************************************************************
1615 * SetWindowPlacement (USER32.519)
1617 * Win95:
1618 * Fails if wndpl->length of Win95 (!) apps is invalid.
1620 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *pwpl32 )
1622 if( pwpl32 )
1624 WINDOWPLACEMENT16 wpl;
1626 wpl.length = sizeof(WINDOWPLACEMENT16);
1627 wpl.flags = pwpl32->flags;
1628 wpl.showCmd = pwpl32->showCmd;
1629 wpl.ptMinPosition.x = pwpl32->ptMinPosition.x;
1630 wpl.ptMinPosition.y = pwpl32->ptMinPosition.y;
1631 wpl.ptMaxPosition.x = pwpl32->ptMaxPosition.x;
1632 wpl.ptMaxPosition.y = pwpl32->ptMaxPosition.y;
1633 wpl.rcNormalPosition.left = pwpl32->rcNormalPosition.left;
1634 wpl.rcNormalPosition.top = pwpl32->rcNormalPosition.top;
1635 wpl.rcNormalPosition.right = pwpl32->rcNormalPosition.right;
1636 wpl.rcNormalPosition.bottom = pwpl32->rcNormalPosition.bottom;
1638 return WINPOS_SetPlacement( hwnd, &wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1640 return FALSE;
1644 /***********************************************************************
1645 * SetInternalWindowPos16 (USER.461)
1647 void WINAPI SetInternalWindowPos16( HWND16 hwnd, UINT16 showCmd,
1648 LPRECT16 rect, LPPOINT16 pt )
1650 if( IsWindow16(hwnd) )
1652 WINDOWPLACEMENT16 wndpl;
1653 UINT flags;
1655 wndpl.length = sizeof(wndpl);
1656 wndpl.showCmd = showCmd;
1657 wndpl.flags = flags = 0;
1659 if( pt )
1661 flags |= PLACE_MIN;
1662 wndpl.flags |= WPF_SETMINPOSITION;
1663 wndpl.ptMinPosition = *pt;
1665 if( rect )
1667 flags |= PLACE_RECT;
1668 wndpl.rcNormalPosition = *rect;
1670 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1675 /***********************************************************************
1676 * SetInternalWindowPos (USER32.483)
1678 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1679 LPRECT rect, LPPOINT pt )
1681 if( IsWindow(hwnd) )
1683 WINDOWPLACEMENT16 wndpl;
1684 UINT flags;
1686 wndpl.length = sizeof(wndpl);
1687 wndpl.showCmd = showCmd;
1688 wndpl.flags = flags = 0;
1690 if( pt )
1692 flags |= PLACE_MIN;
1693 wndpl.flags |= WPF_SETMINPOSITION;
1694 CONV_POINT32TO16( pt, &wndpl.ptMinPosition );
1696 if( rect )
1698 flags |= PLACE_RECT;
1699 CONV_RECT32TO16( rect, &wndpl.rcNormalPosition );
1701 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1705 /*******************************************************************
1706 * WINPOS_SetActiveWindow
1708 * SetActiveWindow() back-end. This is the only function that
1709 * can assign active status to a window. It must be called only
1710 * for the top level windows.
1712 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1714 CBTACTIVATESTRUCT16* cbtStruct;
1715 WND* wndPtr=0, *wndTemp;
1716 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1717 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1718 WORD wIconized = 0;
1719 HWND hwndActive = 0;
1720 BOOL bRet = 0;
1722 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1724 /* Get current active window from the active queue */
1725 if ( hActiveQueue )
1727 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1728 if ( pOldActiveQueue )
1729 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1732 /* paranoid checks */
1733 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1734 goto CLEANUP_END;
1736 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1737 * return 0;
1739 wndPtr = WIN_FindWndPtr(hWnd);
1740 hOldActiveQueue = hActiveQueue;
1742 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1744 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1745 WIN_ReleaseWndPtr(wndTemp);
1747 else
1748 TRACE("no current active window.\n");
1750 /* call CBT hook chain */
1751 if ((cbtStruct = SEGPTR_NEW(CBTACTIVATESTRUCT16)))
1753 cbtStruct->fMouse = fMouse;
1754 cbtStruct->hWndActive = hwndActive;
1755 bRet = (BOOL)HOOK_CallHooks16( WH_CBT, HCBT_ACTIVATE, (WPARAM16)hWnd,
1756 (LPARAM)SEGPTR_GET(cbtStruct) );
1757 SEGPTR_FREE(cbtStruct);
1758 if (bRet) goto CLEANUP_END;
1761 /* set prev active wnd to current active wnd and send notification */
1762 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1764 MESSAGEQUEUE *pTempActiveQueue = 0;
1766 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1768 if (GetSysModalWindow16() != hWnd)
1769 goto CLEANUP_END;
1770 /* disregard refusal if hWnd is sysmodal */
1773 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1774 MAKEWPARAM( WA_INACTIVE, wIconized ),
1775 (LPARAM)hWnd );
1777 /* check if something happened during message processing
1778 * (global active queue may have changed)
1780 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1781 if(!pTempActiveQueue)
1782 goto CLEANUP_END;
1784 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1785 QUEUE_Unlock( pTempActiveQueue );
1786 if( hwndPrevActive != hwndActive )
1787 goto CLEANUP_END;
1790 /* Set new active window in the message queue */
1791 hwndActive = hWnd;
1792 if ( wndPtr )
1794 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1795 if ( pNewActiveQueue )
1796 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1798 else /* have to do this or MDI frame activation goes to hell */
1799 if( pOldActiveQueue )
1800 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1802 /* send palette messages */
1803 if (hWnd && SendMessage16( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1804 SendMessage16((HWND16)-1, WM_PALETTEISCHANGING, (WPARAM16)hWnd, 0L );
1806 /* if prev wnd is minimized redraw icon title */
1807 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1809 /* managed windows will get ConfigureNotify event */
1810 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->flags & WIN_MANAGED))
1812 /* check Z-order and bring hWnd to the top */
1813 for (wndTemp = WIN_LockWndPtr(WIN_GetDesktop()->child); wndTemp; WIN_UpdateWndPtr(&wndTemp,wndTemp->next))
1815 if (wndTemp->dwStyle & WS_VISIBLE) break;
1817 WIN_ReleaseDesktop();
1818 WIN_ReleaseWndPtr(wndTemp);
1820 if( wndTemp != wndPtr )
1821 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1822 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1823 if (!IsWindow(hWnd))
1824 goto CLEANUP;
1827 /* Get a handle to the new active queue */
1828 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1830 /* send WM_ACTIVATEAPP if necessary */
1831 if (hOldActiveQueue != hNewActiveQueue)
1833 WND **list, **ppWnd;
1834 WND *pDesktop = WIN_GetDesktop();
1836 if ((list = WIN_BuildWinArray( pDesktop, 0, NULL )))
1838 for (ppWnd = list; *ppWnd; ppWnd++)
1840 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1842 if ((*ppWnd)->hmemTaskQ == hOldActiveQueue)
1843 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1844 0, QUEUE_GetQueueTask(hNewActiveQueue) );
1846 WIN_ReleaseWinArray(list);
1849 hActiveQueue = hNewActiveQueue;
1851 if ((list = WIN_BuildWinArray(pDesktop, 0, NULL )))
1853 for (ppWnd = list; *ppWnd; ppWnd++)
1855 if (!IsWindow( (*ppWnd)->hwndSelf )) continue;
1857 if ((*ppWnd)->hmemTaskQ == hNewActiveQueue)
1858 SendMessage16( (*ppWnd)->hwndSelf, WM_ACTIVATEAPP,
1859 1, QUEUE_GetQueueTask( hOldActiveQueue ) );
1861 WIN_ReleaseWinArray(list);
1863 WIN_ReleaseDesktop();
1865 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1868 if (hWnd)
1870 /* walk up to the first unowned window */
1871 wndTemp = WIN_LockWndPtr(wndPtr);
1872 while (wndTemp->owner)
1874 WIN_UpdateWndPtr(&wndTemp,wndTemp->owner);
1876 /* and set last active owned popup */
1877 wndTemp->hwndLastActive = hWnd;
1879 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1880 WIN_ReleaseWndPtr(wndTemp);
1881 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1882 SendMessageA( hWnd, WM_ACTIVATE,
1883 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1884 (LPARAM)hwndPrevActive );
1885 if( !IsWindow(hWnd) ) goto CLEANUP;
1888 /* change focus if possible */
1889 if ( fChangeFocus )
1891 if ( pNewActiveQueue )
1893 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1895 if ( hOldFocus && WIN_GetTopParent( hOldFocus ) != hwndActive )
1896 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1897 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1898 0 : hwndActive );
1901 if ( pOldActiveQueue &&
1902 ( !pNewActiveQueue ||
1903 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1905 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1906 if ( hOldFocus )
1907 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1911 if( !hwndPrevActive && wndPtr )
1912 (*wndPtr->pDriver->pForceWindowRaise)(wndPtr);
1914 /* if active wnd is minimized redraw icon title */
1915 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1917 bRet = (hWnd == hwndActive); /* Success? */
1919 CLEANUP: /* Unlock the message queues before returning */
1921 if ( pNewActiveQueue )
1922 QUEUE_Unlock( pNewActiveQueue );
1924 CLEANUP_END:
1926 if ( pOldActiveQueue )
1927 QUEUE_Unlock( pOldActiveQueue );
1929 WIN_ReleaseWndPtr(wndPtr);
1930 return bRet;
1933 /*******************************************************************
1934 * WINPOS_ActivateOtherWindow
1936 * Activates window other than pWnd.
1938 BOOL WINPOS_ActivateOtherWindow(WND* pWnd)
1940 BOOL bRet = 0;
1941 WND* pWndTo = NULL;
1942 HWND hwndActive = 0;
1944 /* Get current active window from the active queue */
1945 if ( hActiveQueue )
1947 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1948 if ( pActiveQueue )
1950 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1951 QUEUE_Unlock( pActiveQueue );
1955 if( pWnd->hwndSelf == hwndPrevActive )
1956 hwndPrevActive = 0;
1958 if( hwndActive != pWnd->hwndSelf &&
1959 ( hwndActive || QUEUE_IsExitingQueue(pWnd->hmemTaskQ)) )
1960 return 0;
1962 if( !(pWnd->dwStyle & WS_POPUP) || !(pWnd->owner) ||
1963 !WINPOS_CanActivate((pWndTo = WIN_GetTopParentPtr(pWnd->owner))) )
1965 WND* pWndPtr = WIN_GetTopParentPtr(pWnd);
1967 WIN_ReleaseWndPtr(pWndTo);
1968 pWndTo = WIN_FindWndPtr(hwndPrevActive);
1970 while( !WINPOS_CanActivate(pWndTo) )
1972 /* by now owned windows should've been taken care of */
1973 WIN_UpdateWndPtr(&pWndTo,pWndPtr->next);
1974 WIN_UpdateWndPtr(&pWndPtr,pWndTo);
1975 if( !pWndTo ) break;
1977 WIN_ReleaseWndPtr(pWndPtr);
1980 bRet = WINPOS_SetActiveWindow( pWndTo ? pWndTo->hwndSelf : 0, FALSE, TRUE );
1982 /* switch desktop queue to current active */
1983 if( pWndTo )
1985 WIN_GetDesktop()->hmemTaskQ = pWndTo->hmemTaskQ;
1986 WIN_ReleaseWndPtr(pWndTo);
1987 WIN_ReleaseDesktop();
1990 hwndPrevActive = 0;
1991 return bRet;
1994 /*******************************************************************
1995 * WINPOS_ChangeActiveWindow
1998 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
2000 WND *wndPtr, *wndTemp;
2001 BOOL retvalue;
2002 HWND hwndActive = 0;
2004 /* Get current active window from the active queue */
2005 if ( hActiveQueue )
2007 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2008 if ( pActiveQueue )
2010 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2011 QUEUE_Unlock( pActiveQueue );
2015 if (!hWnd)
2016 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
2018 wndPtr = WIN_FindWndPtr(hWnd);
2019 if( !wndPtr ) return FALSE;
2021 /* child windows get WM_CHILDACTIVATE message */
2022 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
2024 retvalue = SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
2025 goto end;
2028 if( hWnd == hwndActive )
2030 retvalue = FALSE;
2031 goto end;
2034 if( !WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE) )
2036 retvalue = FALSE;
2037 goto end;
2040 /* switch desktop queue to current active */
2041 wndTemp = WIN_GetDesktop();
2042 if( wndPtr->parent == wndTemp)
2043 wndTemp->hmemTaskQ = wndPtr->hmemTaskQ;
2044 WIN_ReleaseDesktop();
2046 retvalue = TRUE;
2047 end:
2048 WIN_ReleaseWndPtr(wndPtr);
2049 return retvalue;
2053 /***********************************************************************
2054 * WINPOS_SendNCCalcSize
2056 * Send a WM_NCCALCSIZE message to a window.
2057 * All parameters are read-only except newClientRect.
2058 * oldWindowRect, oldClientRect and winpos must be non-NULL only
2059 * when calcValidRect is TRUE.
2061 LONG WINPOS_SendNCCalcSize( HWND hwnd, BOOL calcValidRect,
2062 RECT *newWindowRect, RECT *oldWindowRect,
2063 RECT *oldClientRect, WINDOWPOS *winpos,
2064 RECT *newClientRect )
2066 NCCALCSIZE_PARAMS params;
2067 WINDOWPOS winposCopy;
2068 LONG result;
2070 params.rgrc[0] = *newWindowRect;
2071 if (calcValidRect)
2073 winposCopy = *winpos;
2074 params.rgrc[1] = *oldWindowRect;
2075 params.rgrc[2] = *oldClientRect;
2076 params.lppos = &winposCopy;
2078 result = SendMessageA( hwnd, WM_NCCALCSIZE, calcValidRect,
2079 (LPARAM)&params );
2080 TRACE("%d,%d-%d,%d\n",
2081 params.rgrc[0].left, params.rgrc[0].top,
2082 params.rgrc[0].right, params.rgrc[0].bottom );
2084 /* If the application send back garbage, ignore it */
2085 if (params.rgrc[0].left <= params.rgrc[0].right && params.rgrc[0].top <= params.rgrc[0].bottom)
2086 *newClientRect = params.rgrc[0];
2088 return result;
2092 /***********************************************************************
2093 * WINPOS_HandleWindowPosChanging16
2095 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2097 LONG WINPOS_HandleWindowPosChanging16( WND *wndPtr, WINDOWPOS16 *winpos )
2099 POINT maxSize, minTrack;
2100 if (winpos->flags & SWP_NOSIZE) return 0;
2101 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2102 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2104 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, &minTrack, NULL );
2105 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
2106 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
2107 if (!(wndPtr->dwStyle & WS_MINIMIZE))
2109 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
2110 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
2113 return 0;
2117 /***********************************************************************
2118 * WINPOS_HandleWindowPosChanging
2120 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
2122 LONG WINPOS_HandleWindowPosChanging( WND *wndPtr, WINDOWPOS *winpos )
2124 POINT maxSize;
2125 if (winpos->flags & SWP_NOSIZE) return 0;
2126 if ((wndPtr->dwStyle & WS_THICKFRAME) ||
2127 ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) == 0))
2129 WINPOS_GetMinMaxInfo( wndPtr, &maxSize, NULL, NULL, NULL );
2130 winpos->cx = min( winpos->cx, maxSize.x );
2131 winpos->cy = min( winpos->cy, maxSize.y );
2133 return 0;
2136 /***********************************************************************
2137 * SWP_DoOwnedPopups
2139 * fix Z order taking into account owned popups -
2140 * basically we need to maintain them above the window that owns them
2142 * FIXME: hide/show owned popups when owner visibility changes.
2144 static HWND SWP_DoOwnedPopups(WND* pDesktop, WND* wndPtr, HWND hwndInsertAfter, WORD flags)
2146 WND* w = WIN_LockWndPtr(pDesktop->child);
2148 WARN("(%04x) hInsertAfter = %04x\n", wndPtr->hwndSelf, hwndInsertAfter );
2150 if( (wndPtr->dwStyle & WS_POPUP) && wndPtr->owner )
2152 /* make sure this popup stays above the owner */
2154 HWND hwndLocalPrev = HWND_TOP;
2156 if( hwndInsertAfter != HWND_TOP )
2158 while( w != wndPtr->owner )
2160 if (w != wndPtr) hwndLocalPrev = w->hwndSelf;
2161 if( hwndLocalPrev == hwndInsertAfter ) break;
2162 WIN_UpdateWndPtr(&w,w->next);
2164 hwndInsertAfter = hwndLocalPrev;
2167 else if( wndPtr->dwStyle & WS_CHILD )
2168 goto END;
2170 WIN_UpdateWndPtr(&w, pDesktop->child);
2172 while( w )
2174 if( w == wndPtr ) break;
2176 if( (w->dwStyle & WS_POPUP) && w->owner == wndPtr )
2178 SetWindowPos(w->hwndSelf, hwndInsertAfter, 0, 0, 0, 0,
2179 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING | SWP_DEFERERASE);
2180 hwndInsertAfter = w->hwndSelf;
2182 WIN_UpdateWndPtr(&w, w->next);
2185 END:
2186 WIN_ReleaseWndPtr(w);
2187 return hwndInsertAfter;
2190 /***********************************************************************
2191 * SWP_CopyValidBits
2193 * Make window look nice without excessive repainting
2195 * visible and update regions are in window coordinates
2196 * client and window rectangles are in parent client coordinates
2198 * FIXME: SWP_EX_PAINTSELF in uFlags works only if both old and new
2199 * window rects have the same origin.
2201 * Returns: uFlags and a dirty region in *pVisRgn.
2203 static UINT SWP_CopyValidBits( WND* Wnd, HRGN* pVisRgn,
2204 LPRECT lpOldWndRect,
2205 LPRECT lpOldClientRect, UINT uFlags )
2207 RECT r;
2208 HRGN newVisRgn, dirtyRgn;
2209 INT my = COMPLEXREGION;
2211 TRACE("\tnew wnd=(%i %i-%i %i) old wnd=(%i %i-%i %i), %04x\n",
2212 Wnd->rectWindow.left, Wnd->rectWindow.top,
2213 Wnd->rectWindow.right, Wnd->rectWindow.bottom,
2214 lpOldWndRect->left, lpOldWndRect->top,
2215 lpOldWndRect->right, lpOldWndRect->bottom, *pVisRgn);
2216 TRACE("\tnew client=(%i %i-%i %i) old client=(%i %i-%i %i)\n",
2217 Wnd->rectClient.left, Wnd->rectClient.top,
2218 Wnd->rectClient.right, Wnd->rectClient.bottom,
2219 lpOldClientRect->left, lpOldClientRect->top,
2220 lpOldClientRect->right,lpOldClientRect->bottom );
2222 if( Wnd->hrgnUpdate == 1 )
2223 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
2225 newVisRgn = DCE_GetVisRgn( Wnd->hwndSelf, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
2226 dirtyRgn = CreateRectRgn( 0, 0, 0, 0 );
2228 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
2229 my = CombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
2231 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
2233 nocopy:
2235 TRACE("\twon't copy anything!\n");
2237 /* set dirtyRgn to the sum of old and new visible regions
2238 * in parent client coordinates */
2240 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2241 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2243 CombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
2245 else /* copy valid bits to a new location */
2247 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
2248 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
2250 /* subtract already invalid region inside Wnd from the dst region */
2252 if( Wnd->hrgnUpdate )
2253 if( CombineRgn( hrgnValid, hrgnValid, Wnd->hrgnUpdate, RGN_DIFF) == NULLREGION )
2254 goto nocopy;
2256 /* check if entire window can be copied */
2258 ow = lpOldWndRect->right - lpOldWndRect->left;
2259 oh = lpOldWndRect->bottom - lpOldWndRect->top;
2260 nw = Wnd->rectWindow.right - Wnd->rectWindow.left;
2261 nh = Wnd->rectWindow.bottom - Wnd->rectWindow.top;
2263 ocw = lpOldClientRect->right - lpOldClientRect->left;
2264 och = lpOldClientRect->bottom - lpOldClientRect->top;
2265 ncw = Wnd->rectClient.right - Wnd->rectClient.left;
2266 nch = Wnd->rectClient.bottom - Wnd->rectClient.top;
2268 if( (ocw != ncw) || (och != nch) ||
2269 ( ow != nw) || ( oh != nh) ||
2270 ((lpOldClientRect->top - lpOldWndRect->top) !=
2271 (Wnd->rectClient.top - Wnd->rectWindow.top)) ||
2272 ((lpOldClientRect->left - lpOldWndRect->left) !=
2273 (Wnd->rectClient.left - Wnd->rectWindow.left)) )
2275 dx = Wnd->rectClient.left - lpOldClientRect->left;
2276 dy = Wnd->rectClient.top - lpOldClientRect->top;
2278 /* restrict valid bits to the common client rect */
2280 r.left = Wnd->rectClient.left - Wnd->rectWindow.left;
2281 r.top = Wnd->rectClient.top - Wnd->rectWindow.top;
2282 r.right = r.left + min( ocw, ncw );
2283 r.bottom = r.top + min( och, nch );
2285 REGION_CropRgn( hrgnValid, hrgnValid, &r,
2286 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->rectWindow));
2287 GetRgnBox( hrgnValid, &r );
2288 if( IsRectEmpty( &r ) )
2289 goto nocopy;
2290 r = *lpOldClientRect;
2292 else
2294 dx = Wnd->rectWindow.left - lpOldWndRect->left;
2295 dy = Wnd->rectWindow.top - lpOldWndRect->top;
2296 if( !(uFlags & SWP_EX_PAINTSELF) )
2297 OffsetRgn( hrgnValid, Wnd->rectWindow.left, Wnd->rectWindow.top );
2298 r = *lpOldWndRect;
2301 if( !(uFlags & SWP_EX_PAINTSELF) )
2303 /* Move remaining regions to parent coordinates */
2304 OffsetRgn( newVisRgn, Wnd->rectWindow.left, Wnd->rectWindow.top );
2305 OffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
2307 else
2308 OffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
2310 TRACE("\tcomputing dirty region!\n");
2312 /* Compute combined dirty region (old + new - valid) */
2313 CombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
2314 CombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
2316 /* Blt valid bits, r is the rect to copy */
2318 if( dx || dy )
2320 RECT rClip;
2321 HDC hDC;
2322 DC* dc;
2324 /* get DC and clip rect with drawable rect to avoid superfluous expose events
2325 from copying clipped areas */
2327 if( uFlags & SWP_EX_PAINTSELF )
2329 hDC = GetDCEx( Wnd->hwndSelf, hrgnValid, DCX_WINDOW | DCX_CACHE |
2330 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2331 rClip.right = nw; rClip.bottom = nh;
2333 else
2335 hDC = GetDCEx( Wnd->parent->hwndSelf, hrgnValid, DCX_CACHE |
2336 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
2337 rClip.right = Wnd->parent->rectClient.right - Wnd->parent->rectClient.left;
2338 rClip.bottom = Wnd->parent->rectClient.bottom - Wnd->parent->rectClient.top;
2340 rClip.left = rClip.top = 0;
2342 if( (dc = (DC *)GDI_GetObjPtr(hDC, DC_MAGIC)) )
2344 if( oh > nh ) r.bottom = r.top + nh;
2345 if( ow < nw ) r.right = r.left + nw;
2347 if( IntersectRect( &r, &r, &rClip ) )
2349 Wnd->pDriver->pSurfaceCopy( Wnd->parent, dc, dx, dy, &r, TRUE );
2351 /* When you copy the bits without repainting, parent doesn't
2352 get validated appropriately. Therefore, we have to validate
2353 the parent with the windows' updated region when the
2354 parent's update region is not empty. */
2356 if (Wnd->parent->hrgnUpdate != 0 && !(Wnd->parent->dwStyle & WS_CLIPCHILDREN))
2358 OffsetRect(&r, dx, dy);
2359 ValidateRect(Wnd->parent->hwndSelf, &r);
2363 GDI_HEAP_UNLOCK( hDC );
2365 ReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
2366 Wnd->hwndSelf : Wnd->parent->hwndSelf, hDC);
2370 /* *pVisRgn now points to the invalidated region */
2372 DeleteObject(newVisRgn);
2373 DeleteObject(dirtyRgn);
2374 return uFlags;
2377 /***********************************************************************
2378 * SWP_DoSimpleFrameChanged
2380 * NOTE: old and new client rect origins are identical, only
2381 * extents may have changed. Window extents are the same.
2383 static void SWP_DoSimpleFrameChanged( WND* wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
2385 INT i = 0;
2386 RECT rect;
2387 HRGN hrgn = 0;
2389 if( !(swpFlags & SWP_NOCLIENTSIZE) )
2391 /* Client rect changed its position/size, most likely a scrollar
2392 * was added/removed.
2394 * FIXME: WVR alignment flags
2397 if( wndPtr->rectClient.right > pOldClientRect->right ) /* right edge */
2399 i++;
2400 rect.top = 0;
2401 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2402 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2403 if(!(uFlags & SWP_EX_NOCOPY))
2404 rect.left = pOldClientRect->right - wndPtr->rectClient.left;
2405 else
2407 rect.left = 0;
2408 goto redraw;
2412 if( wndPtr->rectClient.bottom > pOldClientRect->bottom ) /* bottom edge */
2414 if( i )
2415 hrgn = CreateRectRgnIndirect( &rect );
2416 rect.left = 0;
2417 rect.right = wndPtr->rectClient.right - wndPtr->rectClient.left;
2418 rect.bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
2419 if(!(uFlags & SWP_EX_NOCOPY))
2420 rect.top = pOldClientRect->bottom - wndPtr->rectClient.top;
2421 else
2422 rect.top = 0;
2423 if( i++ )
2424 REGION_UnionRectWithRgn( hrgn, &rect );
2427 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
2429 rect = wndPtr->rectWindow;
2430 OffsetRect( &rect, wndPtr->rectWindow.left - wndPtr->rectClient.left,
2431 wndPtr->rectWindow.top - wndPtr->rectClient.top );
2432 i++;
2436 if( i )
2438 redraw:
2439 PAINT_RedrawWindow( wndPtr->hwndSelf, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
2440 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
2442 else
2444 WIN_UpdateNCRgn(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
2447 if( hrgn > 1 )
2448 DeleteObject( hrgn );
2451 /***********************************************************************
2452 * SWP_DoWinPosChanging
2454 static BOOL SWP_DoWinPosChanging( WND* wndPtr, WINDOWPOS* pWinpos,
2455 RECT* pNewWindowRect, RECT* pNewClientRect )
2457 /* Send WM_WINDOWPOSCHANGING message */
2459 if (!(pWinpos->flags & SWP_NOSENDCHANGING))
2460 SendMessageA( wndPtr->hwndSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM)pWinpos );
2462 /* Calculate new position and size */
2464 *pNewWindowRect = wndPtr->rectWindow;
2465 *pNewClientRect = (wndPtr->dwStyle & WS_MINIMIZE) ? wndPtr->rectWindow
2466 : wndPtr->rectClient;
2468 if (!(pWinpos->flags & SWP_NOSIZE))
2470 pNewWindowRect->right = pNewWindowRect->left + pWinpos->cx;
2471 pNewWindowRect->bottom = pNewWindowRect->top + pWinpos->cy;
2473 if (!(pWinpos->flags & SWP_NOMOVE))
2475 pNewWindowRect->left = pWinpos->x;
2476 pNewWindowRect->top = pWinpos->y;
2477 pNewWindowRect->right += pWinpos->x - wndPtr->rectWindow.left;
2478 pNewWindowRect->bottom += pWinpos->y - wndPtr->rectWindow.top;
2480 OffsetRect( pNewClientRect, pWinpos->x - wndPtr->rectWindow.left,
2481 pWinpos->y - wndPtr->rectWindow.top );
2484 pWinpos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
2485 return TRUE;
2488 /***********************************************************************
2489 * SWP_DoNCCalcSize
2491 static UINT SWP_DoNCCalcSize( WND* wndPtr, WINDOWPOS* pWinpos,
2492 RECT* pNewWindowRect, RECT* pNewClientRect, WORD f)
2494 UINT wvrFlags = 0;
2496 /* Send WM_NCCALCSIZE message to get new client area */
2497 if( (pWinpos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE )
2499 wvrFlags = WINPOS_SendNCCalcSize( pWinpos->hwnd, TRUE, pNewWindowRect,
2500 &wndPtr->rectWindow, &wndPtr->rectClient,
2501 pWinpos, pNewClientRect );
2503 /* FIXME: WVR_ALIGNxxx */
2505 if( pNewClientRect->left != wndPtr->rectClient.left ||
2506 pNewClientRect->top != wndPtr->rectClient.top )
2507 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2509 if( (pNewClientRect->right - pNewClientRect->left !=
2510 wndPtr->rectClient.right - wndPtr->rectClient.left) ||
2511 (pNewClientRect->bottom - pNewClientRect->top !=
2512 wndPtr->rectClient.bottom - wndPtr->rectClient.top) )
2513 pWinpos->flags &= ~SWP_NOCLIENTSIZE;
2515 else
2516 if( !(f & SWP_NOMOVE) && (pNewClientRect->left != wndPtr->rectClient.left ||
2517 pNewClientRect->top != wndPtr->rectClient.top) )
2518 pWinpos->flags &= ~SWP_NOCLIENTMOVE;
2519 return wvrFlags;
2522 /***********************************************************************
2523 * SetWindowPos (USER.2)
2525 BOOL16 WINAPI SetWindowPos16( HWND16 hwnd, HWND16 hwndInsertAfter,
2526 INT16 x, INT16 y, INT16 cx, INT16 cy, WORD flags)
2528 return SetWindowPos(hwnd,(INT)(INT16)hwndInsertAfter,x,y,cx,cy,flags);
2531 /***********************************************************************
2532 * SetWindowPos (USER32.520)
2534 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
2535 INT x, INT y, INT cx, INT cy, UINT flags )
2537 WINDOWPOS winpos;
2538 WND * wndPtr,*wndTemp;
2539 RECT newWindowRect, newClientRect;
2540 RECT oldWindowRect, oldClientRect;
2541 HRGN visRgn = 0;
2542 UINT wvrFlags = 0, uFlags = 0;
2543 BOOL retvalue, resync = FALSE, bChangePos;
2544 HWND hwndActive = 0;
2546 /* Get current active window from the active queue */
2547 if ( hActiveQueue )
2549 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
2550 if ( pActiveQueue )
2552 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
2553 QUEUE_Unlock( pActiveQueue );
2557 TRACE("hwnd %04x, swp (%i,%i)-(%i,%i) flags %08x\n",
2558 hwnd, x, y, x+cx, y+cy, flags);
2560 bChangePos = !(flags & SWP_WINE_NOHOSTMOVE);
2561 flags &= ~SWP_WINE_NOHOSTMOVE;
2564 /* ------------------------------------------------------------------------ CHECKS */
2566 /* Check window handle */
2568 if (hwnd == GetDesktopWindow()) return FALSE;
2569 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
2571 TRACE("\tcurrent (%i,%i)-(%i,%i), style %08x\n", wndPtr->rectWindow.left, wndPtr->rectWindow.top,
2572 wndPtr->rectWindow.right, wndPtr->rectWindow.bottom, (unsigned)wndPtr->dwStyle );
2574 /* Fix redundant flags */
2576 if(wndPtr->dwStyle & WS_VISIBLE)
2577 flags &= ~SWP_SHOWWINDOW;
2578 else
2580 if (!(flags & SWP_SHOWWINDOW))
2581 flags |= SWP_NOREDRAW;
2582 flags &= ~SWP_HIDEWINDOW;
2585 if ( cx < 0 ) cx = 0; if( cy < 0 ) cy = 0;
2587 if ((wndPtr->rectWindow.right - wndPtr->rectWindow.left == cx) &&
2588 (wndPtr->rectWindow.bottom - wndPtr->rectWindow.top == cy))
2589 flags |= SWP_NOSIZE; /* Already the right size */
2591 if ((wndPtr->rectWindow.left == x) && (wndPtr->rectWindow.top == y))
2592 flags |= SWP_NOMOVE; /* Already the right position */
2594 if (hwnd == hwndActive)
2595 flags |= SWP_NOACTIVATE; /* Already active */
2596 else if ( (wndPtr->dwStyle & (WS_POPUP | WS_CHILD)) != WS_CHILD )
2598 if(!(flags & SWP_NOACTIVATE)) /* Bring to the top when activating */
2600 flags &= ~SWP_NOZORDER;
2601 hwndInsertAfter = HWND_TOP;
2602 goto Pos;
2606 /* Check hwndInsertAfter */
2608 /* FIXME: TOPMOST not supported yet */
2609 if ((hwndInsertAfter == HWND_TOPMOST) ||
2610 (hwndInsertAfter == HWND_NOTOPMOST)) hwndInsertAfter = HWND_TOP;
2612 /* hwndInsertAfter must be a sibling of the window */
2613 if ((hwndInsertAfter != HWND_TOP) && (hwndInsertAfter != HWND_BOTTOM))
2615 WND* wnd = WIN_FindWndPtr(hwndInsertAfter);
2617 if( wnd ) {
2618 if( wnd->parent != wndPtr->parent )
2620 retvalue = FALSE;
2621 WIN_ReleaseWndPtr(wnd);
2622 goto END;
2624 /* don't need to change the Zorder of hwnd if it's already inserted
2625 * after hwndInsertAfter or when inserting hwnd after itself.
2627 if(( wnd->next == wndPtr ) || (hwnd == hwndInsertAfter)) flags |= SWP_NOZORDER;
2629 WIN_ReleaseWndPtr(wnd);
2632 Pos: /* ------------------------------------------------------------------------ MAIN part */
2634 /* Fill the WINDOWPOS structure */
2636 winpos.hwnd = hwnd;
2637 winpos.hwndInsertAfter = hwndInsertAfter;
2638 winpos.x = x;
2639 winpos.y = y;
2640 winpos.cx = cx;
2641 winpos.cy = cy;
2642 winpos.flags = flags;
2644 SWP_DoWinPosChanging( wndPtr, &winpos, &newWindowRect, &newClientRect );
2646 if((winpos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER)
2648 if( wndPtr->parent == WIN_GetDesktop() )
2649 hwndInsertAfter = SWP_DoOwnedPopups( wndPtr->parent, wndPtr,
2650 hwndInsertAfter, winpos.flags );
2651 WIN_ReleaseDesktop();
2654 if(!(wndPtr->flags & WIN_NATIVE) )
2656 if( hwndInsertAfter == HWND_TOP )
2657 winpos.flags |= ( wndPtr->parent->child == wndPtr)? SWP_NOZORDER: 0;
2658 else
2659 if( hwndInsertAfter == HWND_BOTTOM )
2660 winpos.flags |= ( wndPtr->next )? 0: SWP_NOZORDER;
2661 else
2662 if( !(winpos.flags & SWP_NOZORDER) )
2663 if( GetWindow(hwndInsertAfter, GW_HWNDNEXT) == wndPtr->hwndSelf )
2664 winpos.flags |= SWP_NOZORDER;
2666 if( !(winpos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
2667 ((winpos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2668 != (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) )
2670 /* get a previous visible region for SWP_CopyValidBits() */
2671 DWORD flags = DCX_WINDOW;
2673 if (wndPtr->dwStyle & WS_CLIPSIBLINGS)
2674 flags |= DCX_CLIPSIBLINGS;
2676 visRgn = DCE_GetVisRgn(hwnd, flags, 0, 0);
2680 /* Common operations */
2682 wvrFlags = SWP_DoNCCalcSize( wndPtr, &winpos, &newWindowRect, &newClientRect, flags );
2684 if(!(winpos.flags & SWP_NOZORDER) && winpos.hwnd != hwndInsertAfter)
2686 if ( WIN_UnlinkWindow( winpos.hwnd ) )
2687 WIN_LinkWindow( winpos.hwnd, hwndInsertAfter );
2690 /* Reset active DCEs */
2692 if( (((winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) &&
2693 wndPtr->dwStyle & WS_VISIBLE) ||
2694 (flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW)) )
2696 RECT rect;
2698 UnionRect(&rect, &newWindowRect, &wndPtr->rectWindow);
2699 DCE_InvalidateDCE(wndPtr, &rect);
2702 oldWindowRect = wndPtr->rectWindow;
2703 oldClientRect = wndPtr->rectClient;
2705 /* Find out if we have to redraw the whole client rect */
2707 if( oldClientRect.bottom - oldClientRect.top ==
2708 newClientRect.bottom - newClientRect.top ) wvrFlags &= ~WVR_VREDRAW;
2710 if( oldClientRect.right - oldClientRect.left ==
2711 newClientRect.right - newClientRect.left ) wvrFlags &= ~WVR_HREDRAW;
2713 if( (winpos.flags & SWP_NOCOPYBITS) || (!(winpos.flags & SWP_NOCLIENTSIZE) &&
2714 (wvrFlags >= WVR_HREDRAW) && (wvrFlags < WVR_VALIDRECTS)) )
2716 uFlags |= SWP_EX_NOCOPY;
2719 * Use this later in CopyValidBits()
2721 else if( 0 )
2722 uFlags |= SWP_EX_NONCLIENT;
2725 /* FIXME: actually do something with WVR_VALIDRECTS */
2727 wndPtr->rectWindow = newWindowRect;
2728 wndPtr->rectClient = newClientRect;
2730 if (wndPtr->flags & WIN_NATIVE) /* -------------------------------------------- hosted window */
2732 BOOL bCallDriver = TRUE;
2733 HWND tempInsertAfter = winpos.hwndInsertAfter;
2735 winpos.hwndInsertAfter = hwndInsertAfter;
2737 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2739 /* This is the only place where we need to force repainting of the contents
2740 of windows created by the host window system, all other cases go through the
2741 expose event handling */
2743 if( (winpos.flags & (SWP_NOSIZE | SWP_FRAMECHANGED)) == (SWP_NOSIZE | SWP_FRAMECHANGED) )
2745 cx = newWindowRect.right - newWindowRect.left;
2746 cy = newWindowRect.bottom - newWindowRect.top;
2748 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2749 winpos.hwndInsertAfter = tempInsertAfter;
2750 bCallDriver = FALSE;
2752 if( winpos.flags & SWP_NOCLIENTMOVE )
2753 SWP_DoSimpleFrameChanged(wndPtr, &oldClientRect, winpos.flags, uFlags );
2754 else
2756 /* client area moved but window extents remained the same, copy valid bits */
2758 visRgn = CreateRectRgn( 0, 0, cx, cy );
2759 uFlags = SWP_CopyValidBits( wndPtr, &visRgn, &oldWindowRect, &oldClientRect,
2760 uFlags | SWP_EX_PAINTSELF );
2765 if( bCallDriver )
2767 if( !(winpos.flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | SWP_NOREDRAW)) )
2769 if( (oldClientRect.left - oldWindowRect.left == newClientRect.left - newWindowRect.left) &&
2770 (oldClientRect.top - oldWindowRect.top == newClientRect.top - newWindowRect.top) &&
2771 !(uFlags & SWP_EX_NOCOPY) )
2773 /* The origin of the client rect didn't move so we can try to repaint
2774 * only the nonclient area by setting bit gravity hint for the host window system.
2777 if( !(wndPtr->flags & WIN_MANAGED) )
2779 HRGN hrgn = CreateRectRgn( 0, 0, newWindowRect.right - newWindowRect.left,
2780 newWindowRect.bottom - newWindowRect.top);
2781 RECT rcn = newClientRect;
2782 RECT rco = oldClientRect;
2784 OffsetRect( &rcn, -newWindowRect.left, -newWindowRect.top );
2785 OffsetRect( &rco, -oldWindowRect.left, -oldWindowRect.top );
2786 IntersectRect( &rcn, &rcn, &rco );
2787 visRgn = CreateRectRgnIndirect( &rcn );
2788 CombineRgn( visRgn, hrgn, visRgn, RGN_DIFF );
2789 DeleteObject( hrgn );
2790 uFlags = SWP_EX_PAINTSELF;
2792 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGNorthWest );
2794 else
2795 wndPtr->pDriver->pSetHostAttr(wndPtr, HAK_BITGRAVITY, BGForget );
2798 wndPtr->pDriver->pSetWindowPos(wndPtr, &winpos, bChangePos);
2799 winpos.hwndInsertAfter = tempInsertAfter;
2802 if( winpos.flags & SWP_SHOWWINDOW )
2804 HWND focus, curr;
2806 wndPtr->dwStyle |= WS_VISIBLE;
2808 if (wndPtr->flags & WIN_MANAGED) resync = TRUE;
2810 /* focus was set to unmapped window, reset host focus
2811 * since the window is now visible */
2813 focus = curr = GetFocus();
2814 while (curr)
2816 if (curr == hwnd)
2818 WND *pFocus = WIN_FindWndPtr( focus );
2819 if (pFocus)
2820 pFocus->pDriver->pSetFocus(pFocus);
2821 WIN_ReleaseWndPtr(pFocus);
2822 break;
2824 curr = GetParent(curr);
2828 else /* -------------------------------------------- emulated window */
2830 if( winpos.flags & SWP_SHOWWINDOW )
2832 wndPtr->dwStyle |= WS_VISIBLE;
2833 uFlags |= SWP_EX_PAINTSELF;
2834 visRgn = 1; /* redraw the whole window */
2836 else if( !(winpos.flags & SWP_NOREDRAW) )
2838 if( winpos.flags & SWP_HIDEWINDOW )
2840 if( visRgn > 1 ) /* map to parent */
2841 OffsetRgn( visRgn, oldWindowRect.left, oldWindowRect.top );
2842 else
2843 visRgn = 0;
2845 else
2847 if( (winpos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE )
2848 uFlags = SWP_CopyValidBits(wndPtr, &visRgn, &oldWindowRect,
2849 &oldClientRect, uFlags);
2850 else
2852 /* nothing moved, redraw frame if needed */
2854 if( winpos.flags & SWP_FRAMECHANGED )
2855 SWP_DoSimpleFrameChanged( wndPtr, &oldClientRect, winpos.flags, uFlags );
2856 if( visRgn )
2858 DeleteObject( visRgn );
2859 visRgn = 0;
2866 if( winpos.flags & SWP_HIDEWINDOW )
2868 wndPtr->dwStyle &= ~WS_VISIBLE;
2871 if (hwnd == CARET_GetHwnd())
2873 if( winpos.flags & SWP_HIDEWINDOW )
2874 HideCaret(hwnd);
2875 else if (winpos.flags & SWP_SHOWWINDOW)
2876 ShowCaret(hwnd);
2879 /* ------------------------------------------------------------------------ FINAL */
2881 if (wndPtr->flags & WIN_NATIVE)
2882 EVENT_Synchronize(); /* Synchronize with the host window system */
2884 if (!GetCapture() && ((wndPtr->dwStyle & WS_VISIBLE) || (flags & SWP_HIDEWINDOW)))
2886 /* Simulate a mouse event to set the cursor */
2887 int iWndsLocks = WIN_SuspendWndsLock();
2889 hardware_event( WM_MOUSEMOVE, GET_KEYSTATE(), 0,
2890 PosX, PosY, GetTickCount(), 0 );
2892 WIN_RestoreWndsLock(iWndsLocks);
2895 wndTemp = WIN_GetDesktop();
2897 /* repaint invalidated region (if any)
2899 * FIXME: if SWP_NOACTIVATE is not set then set invalid regions here without any painting
2900 * and force update after ChangeActiveWindow() to avoid painting frames twice.
2903 if( visRgn )
2905 if( !(winpos.flags & SWP_NOREDRAW) )
2908 /* Use PAINT_RedrawWindow to explicitly force an invalidation of the window,
2909 its parent and sibling and so on, and then erase the parent window
2910 back ground if the parent is either a top-level window or its parent's parent
2911 is top-level window. Rely on the system to repaint other affected
2912 windows later on. */
2913 if( uFlags & SWP_EX_PAINTSELF )
2915 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2916 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN,
2917 RDW_EX_XYWINDOW | RDW_EX_USEHRGN );
2919 else
2921 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, (visRgn == 1) ? 0 : visRgn,
2922 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
2923 RDW_EX_USEHRGN );
2926 if(wndPtr -> parent == wndTemp || wndPtr->parent->parent == wndTemp )
2928 PAINT_RedrawWindow( wndPtr->parent->hwndSelf, NULL, 0,
2929 RDW_ERASENOW | RDW_NOCHILDREN, 0 );
2932 if( visRgn != 1 )
2933 DeleteObject( visRgn );
2936 WIN_ReleaseDesktop();
2938 if (!(flags & SWP_NOACTIVATE))
2939 WINPOS_ChangeActiveWindow( winpos.hwnd, FALSE );
2941 /* And last, send the WM_WINDOWPOSCHANGED message */
2943 TRACE("\tstatus flags = %04x\n", winpos.flags & SWP_AGG_STATUSFLAGS);
2945 if ( resync ||
2946 (((winpos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) &&
2947 !(winpos.flags & SWP_NOSENDCHANGING)) )
2949 SendMessageA( winpos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&winpos );
2950 if (resync) EVENT_Synchronize();
2953 retvalue = TRUE;
2954 END:
2955 WIN_ReleaseWndPtr(wndPtr);
2956 return retvalue;
2960 /***********************************************************************
2961 * BeginDeferWindowPos16 (USER.259)
2963 HDWP16 WINAPI BeginDeferWindowPos16( INT16 count )
2965 return BeginDeferWindowPos( count );
2969 /***********************************************************************
2970 * BeginDeferWindowPos (USER32.9)
2972 HDWP WINAPI BeginDeferWindowPos( INT count )
2974 HDWP handle;
2975 DWP *pDWP;
2977 if (count < 0)
2979 SetLastError(ERROR_INVALID_PARAMETER);
2980 return 0;
2982 /* Windows allows zero count, in which case it allocates context for 8 moves */
2983 if (count == 0) count = 8;
2985 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
2986 if (!handle) return 0;
2987 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
2988 pDWP->actualCount = 0;
2989 pDWP->suggestedCount = count;
2990 pDWP->valid = TRUE;
2991 pDWP->wMagic = DWP_MAGIC;
2992 pDWP->hwndParent = 0;
2993 return handle;
2997 /***********************************************************************
2998 * DeferWindowPos16 (USER.260)
3000 HDWP16 WINAPI DeferWindowPos16( HDWP16 hdwp, HWND16 hwnd, HWND16 hwndAfter,
3001 INT16 x, INT16 y, INT16 cx, INT16 cy,
3002 UINT16 flags )
3004 return DeferWindowPos( hdwp, hwnd, (INT)(INT16)hwndAfter,
3005 x, y, cx, cy, flags );
3009 /***********************************************************************
3010 * DeferWindowPos (USER32.128)
3012 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
3013 INT x, INT y, INT cx, INT cy,
3014 UINT flags )
3016 DWP *pDWP;
3017 int i;
3018 HDWP newhdwp = hdwp,retvalue;
3019 /* HWND parent; */
3020 WND *pWnd;
3022 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3023 if (!pDWP) return 0;
3024 if (hwnd == GetDesktopWindow()) return 0;
3026 if (!(pWnd=WIN_FindWndPtr( hwnd ))) {
3027 USER_HEAP_FREE( hdwp );
3028 return 0;
3031 /* Numega Bounds Checker Demo dislikes the following code.
3032 In fact, I've not been able to find any "same parent" requirement in any docu
3033 [AM 980509]
3035 #if 0
3036 /* All the windows of a DeferWindowPos() must have the same parent */
3037 parent = pWnd->parent->hwndSelf;
3038 if (pDWP->actualCount == 0) pDWP->hwndParent = parent;
3039 else if (parent != pDWP->hwndParent)
3041 USER_HEAP_FREE( hdwp );
3042 retvalue = 0;
3043 goto END;
3045 #endif
3047 for (i = 0; i < pDWP->actualCount; i++)
3049 if (pDWP->winPos[i].hwnd == hwnd)
3051 /* Merge with the other changes */
3052 if (!(flags & SWP_NOZORDER))
3054 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
3056 if (!(flags & SWP_NOMOVE))
3058 pDWP->winPos[i].x = x;
3059 pDWP->winPos[i].y = y;
3061 if (!(flags & SWP_NOSIZE))
3063 pDWP->winPos[i].cx = cx;
3064 pDWP->winPos[i].cy = cy;
3066 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
3067 SWP_NOZORDER | SWP_NOREDRAW |
3068 SWP_NOACTIVATE | SWP_NOCOPYBITS|
3069 SWP_NOOWNERZORDER);
3070 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
3071 SWP_FRAMECHANGED);
3072 retvalue = hdwp;
3073 goto END;
3076 if (pDWP->actualCount >= pDWP->suggestedCount)
3078 newhdwp = USER_HEAP_REALLOC( hdwp,
3079 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
3080 if (!newhdwp)
3082 retvalue = 0;
3083 goto END;
3085 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
3086 pDWP->suggestedCount++;
3088 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
3089 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
3090 pDWP->winPos[pDWP->actualCount].x = x;
3091 pDWP->winPos[pDWP->actualCount].y = y;
3092 pDWP->winPos[pDWP->actualCount].cx = cx;
3093 pDWP->winPos[pDWP->actualCount].cy = cy;
3094 pDWP->winPos[pDWP->actualCount].flags = flags;
3095 pDWP->actualCount++;
3096 retvalue = newhdwp;
3097 END:
3098 WIN_ReleaseWndPtr(pWnd);
3099 return retvalue;
3103 /***********************************************************************
3104 * EndDeferWindowPos16 (USER.261)
3106 BOOL16 WINAPI EndDeferWindowPos16( HDWP16 hdwp )
3108 return EndDeferWindowPos( hdwp );
3112 /***********************************************************************
3113 * EndDeferWindowPos (USER32.173)
3115 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
3117 DWP *pDWP;
3118 WINDOWPOS *winpos;
3119 BOOL res = TRUE;
3120 int i;
3122 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
3123 if (!pDWP) return FALSE;
3124 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
3126 if (!(res = SetWindowPos( winpos->hwnd, winpos->hwndInsertAfter,
3127 winpos->x, winpos->y, winpos->cx,
3128 winpos->cy, winpos->flags ))) break;
3130 USER_HEAP_FREE( hdwp );
3131 return res;
3135 /***********************************************************************
3136 * TileChildWindows (USER.199)
3138 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
3140 FIXME("(%04x, %d): stub\n", parent, action);
3143 /***********************************************************************
3144 * CascadeChildWindows (USER.198)
3146 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
3148 FIXME("(%04x, %d): stub\n", parent, action);
3151 /***********************************************************************
3152 * SetProgmanWindow [USER32.522]
3154 HRESULT WINAPI SetProgmanWindow ( HWND hwnd )
3156 hGlobalProgmanWindow = hwnd;
3157 return hGlobalProgmanWindow;
3160 /***********************************************************************
3161 * GetProgmanWindow [USER32.289]
3163 HRESULT WINAPI GetProgmanWindow ( )
3165 return hGlobalProgmanWindow;
3168 /***********************************************************************
3169 * SetShellWindowEx [USER32.531]
3170 * hwndProgman = Progman[Program Manager]
3171 * |-> SHELLDLL_DefView
3172 * hwndListView = | |-> SysListView32
3173 * | | |-> tooltips_class32
3174 * | |
3175 * | |-> SysHeader32
3176 * |
3177 * |-> ProxyTarget
3179 HRESULT WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
3181 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
3182 hGlobalShellWindow = hwndProgman;
3183 return hGlobalShellWindow;
3187 /***********************************************************************
3188 * SetTaskmanWindow [USER32.537]
3189 * NOTES
3190 * hwnd = MSTaskSwWClass
3191 * |-> SysTabControl32
3193 HRESULT WINAPI SetTaskmanWindow ( HWND hwnd )
3195 hGlobalTaskmanWindow = hwnd;
3196 return hGlobalTaskmanWindow;
3199 /***********************************************************************
3200 * GetTaskmanWindow [USER32.304]
3202 HRESULT WINAPI GetTaskmanWindow ( )
3204 return hGlobalTaskmanWindow;