A couple of optimizations.
[wine/multimedia.git] / windows / winpos.c
blobf288fcbfaa314a3562bbaa5a16ea91be1df07c78
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 "wine/server.h"
15 #include "controls.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 "winpos.h"
23 #include "dce.h"
24 #include "nonclient.h"
25 #include "debugtools.h"
26 #include "input.h"
28 DEFAULT_DEBUG_CHANNEL(win);
30 #define HAS_DLGFRAME(style,exStyle) \
31 (((exStyle) & WS_EX_DLGMODALFRAME) || \
32 (((style) & WS_DLGFRAME) && !((style) & WS_BORDER)))
34 #define HAS_THICKFRAME(style) \
35 (((style) & WS_THICKFRAME) && \
36 !(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
38 #define EMPTYPOINT(pt) ((*(LONG*)&(pt)) == -1)
40 #define PLACE_MIN 0x0001
41 #define PLACE_MAX 0x0002
42 #define PLACE_RECT 0x0004
45 #define DWP_MAGIC ((INT)('W' | ('P' << 8) | ('O' << 16) | ('S' << 24)))
47 typedef struct
49 INT actualCount;
50 INT suggestedCount;
51 BOOL valid;
52 INT wMagic;
53 HWND hwndParent;
54 WINDOWPOS winPos[1];
55 } DWP;
57 /* ----- internal variables ----- */
59 static HWND hwndPrevActive = 0; /* Previously active window */
60 static HWND hGlobalShellWindow=0; /*the shell*/
61 static HWND hGlobalTaskmanWindow=0;
62 static HWND hGlobalProgmanWindow=0;
64 static LPCSTR atomInternalPos;
66 extern HQUEUE16 hActiveQueue;
68 /***********************************************************************
69 * WINPOS_CreateInternalPosAtom
71 BOOL WINPOS_CreateInternalPosAtom()
73 LPSTR str = "SysIP";
74 atomInternalPos = (LPCSTR)(DWORD)GlobalAddAtomA(str);
75 return (atomInternalPos) ? TRUE : FALSE;
78 /***********************************************************************
79 * WINPOS_CheckInternalPos
81 * Called when a window is destroyed.
83 void WINPOS_CheckInternalPos( HWND hwnd )
85 LPINTERNALPOS lpPos;
86 MESSAGEQUEUE *pMsgQ = 0;
87 WND *wndPtr = WIN_GetPtr( hwnd );
89 if (!wndPtr || wndPtr == WND_OTHER_PROCESS) return;
91 lpPos = (LPINTERNALPOS) GetPropA( hwnd, atomInternalPos );
93 /* Retrieve the message queue associated with this window */
94 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
95 if ( !pMsgQ )
97 WARN("\tMessage queue not found. Exiting!\n" );
98 WIN_ReleasePtr( wndPtr );
99 return;
102 if( hwnd == hwndPrevActive ) hwndPrevActive = 0;
104 if( hwnd == PERQDATA_GetActiveWnd( pMsgQ->pQData ) )
106 PERQDATA_SetActiveWnd( pMsgQ->pQData, 0 );
107 WARN("\tattempt to activate destroyed window!\n");
110 if( lpPos )
112 if( IsWindow(lpPos->hwndIconTitle) )
113 DestroyWindow( lpPos->hwndIconTitle );
114 HeapFree( GetProcessHeap(), 0, lpPos );
117 QUEUE_Unlock( pMsgQ );
118 WIN_ReleasePtr( wndPtr );
121 /***********************************************************************
122 * ArrangeIconicWindows (USER32.@)
124 UINT WINAPI ArrangeIconicWindows( HWND parent )
126 RECT rectParent;
127 HWND hwndChild;
128 INT x, y, xspacing, yspacing;
130 GetClientRect( parent, &rectParent );
131 x = rectParent.left;
132 y = rectParent.bottom;
133 xspacing = GetSystemMetrics(SM_CXICONSPACING);
134 yspacing = GetSystemMetrics(SM_CYICONSPACING);
136 hwndChild = GetWindow( parent, GW_CHILD );
137 while (hwndChild)
139 if( IsIconic( hwndChild ) )
141 WINPOS_ShowIconTitle( hwndChild, FALSE );
143 SetWindowPos( hwndChild, 0, x + (xspacing - GetSystemMetrics(SM_CXICON)) / 2,
144 y - yspacing - GetSystemMetrics(SM_CYICON)/2, 0, 0,
145 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
146 if( IsWindow(hwndChild) )
147 WINPOS_ShowIconTitle(hwndChild , TRUE );
149 if (x <= rectParent.right - xspacing) x += xspacing;
150 else
152 x = rectParent.left;
153 y -= yspacing;
156 hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
158 return yspacing;
162 /***********************************************************************
163 * SwitchToThisWindow (USER32.@)
165 void WINAPI SwitchToThisWindow( HWND hwnd, BOOL restore )
167 ShowWindow( hwnd, restore ? SW_RESTORE : SW_SHOWMINIMIZED );
171 /***********************************************************************
172 * GetWindowRect (USER32.@)
174 BOOL WINAPI GetWindowRect( HWND hwnd, LPRECT rect )
176 BOOL ret;
177 WND *wndPtr = WIN_GetPtr( hwnd );
179 if (!wndPtr) return FALSE;
181 if (wndPtr != WND_OTHER_PROCESS)
183 *rect = wndPtr->rectWindow;
184 WIN_ReleasePtr( wndPtr );
185 ret = TRUE;
187 else
189 SERVER_START_REQ( get_window_rectangles )
191 req->handle = hwnd;
192 if ((ret = !SERVER_CALL_ERR()))
194 rect->left = req->window.left;
195 rect->top = req->window.top;
196 rect->right = req->window.right;
197 rect->bottom = req->window.bottom;
200 SERVER_END_REQ;
202 if (ret)
204 MapWindowPoints( GetAncestor( hwnd, GA_PARENT ), 0, (POINT *)rect, 2 );
205 TRACE( "hwnd %04x (%d,%d)-(%d,%d)\n",
206 hwnd, rect->left, rect->top, rect->right, rect->bottom);
208 return ret;
212 /***********************************************************************
213 * GetWindowRgn (USER32.@)
215 int WINAPI GetWindowRgn ( HWND hwnd, HRGN hrgn )
217 int nRet = ERROR;
218 WND *wndPtr = WIN_GetPtr( hwnd );
220 if (wndPtr == WND_OTHER_PROCESS)
222 if (IsWindow( hwnd ))
223 FIXME( "not supported on other process window %x\n", hwnd );
224 wndPtr = NULL;
226 if (!wndPtr)
228 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
229 return ERROR;
231 if (wndPtr->hrgnWnd) nRet = CombineRgn( hrgn, wndPtr->hrgnWnd, 0, RGN_COPY );
232 WIN_ReleasePtr( wndPtr );
233 return nRet;
237 /***********************************************************************
238 * SetWindowRgn (USER32.@)
240 int WINAPI SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL bRedraw )
242 RECT rect;
243 WND *wndPtr;
245 if (hrgn) /* verify that region really exists */
247 if (GetRgnBox( hrgn, &rect ) == ERROR) return FALSE;
250 if (USER_Driver.pSetWindowRgn)
251 return USER_Driver.pSetWindowRgn( hwnd, hrgn, bRedraw );
253 if ((wndPtr = WIN_GetPtr( hwnd )) == WND_OTHER_PROCESS)
255 if (IsWindow( hwnd ))
256 FIXME( "not supported on other process window %x\n", hwnd );
257 wndPtr = NULL;
259 if (!wndPtr)
261 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
262 return FALSE;
265 if (wndPtr->hrgnWnd == hrgn)
267 WIN_ReleasePtr( wndPtr );
268 return TRUE;
271 if (wndPtr->hrgnWnd)
273 /* delete previous region */
274 DeleteObject(wndPtr->hrgnWnd);
275 wndPtr->hrgnWnd = 0;
277 wndPtr->hrgnWnd = hrgn;
278 WIN_ReleasePtr( wndPtr );
280 /* Size the window to the rectangle of the new region (if it isn't NULL) */
281 if (hrgn) SetWindowPos( hwnd, 0, rect.left, rect.top,
282 rect.right - rect.left, rect.bottom - rect.top,
283 SWP_NOSIZE | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE |
284 SWP_NOZORDER | (bRedraw ? 0 : SWP_NOREDRAW) );
285 return TRUE;
289 /***********************************************************************
290 * GetClientRect (USER32.@)
292 BOOL WINAPI GetClientRect( HWND hwnd, LPRECT rect )
294 BOOL ret;
295 WND *wndPtr = WIN_GetPtr( hwnd );
297 rect->left = rect->top = rect->right = rect->bottom = 0;
298 if (!wndPtr) return FALSE;
300 if (wndPtr != WND_OTHER_PROCESS)
302 rect->right = wndPtr->rectClient.right - wndPtr->rectClient.left;
303 rect->bottom = wndPtr->rectClient.bottom - wndPtr->rectClient.top;
304 WIN_ReleasePtr( wndPtr );
305 ret = TRUE;
307 else
309 SERVER_START_REQ( get_window_rectangles )
311 req->handle = hwnd;
312 if ((ret = !SERVER_CALL_ERR()))
314 rect->right = req->client.right - req->client.left;
315 rect->bottom = req->client.bottom - req->client.top;
318 SERVER_END_REQ;
320 return ret;
324 /*******************************************************************
325 * ClientToScreen (USER32.@)
327 BOOL WINAPI ClientToScreen( HWND hwnd, LPPOINT lppnt )
329 MapWindowPoints( hwnd, 0, lppnt, 1 );
330 return TRUE;
334 /*******************************************************************
335 * ScreenToClient (USER32.@)
337 BOOL WINAPI ScreenToClient( HWND hwnd, LPPOINT lppnt )
339 MapWindowPoints( 0, hwnd, lppnt, 1 );
340 return TRUE;
344 /***********************************************************************
345 * find_child_from_point
347 * Find the child that contains pt. Helper for WindowFromPoint.
348 * pt is in parent client coordinates.
349 * lparam is the param to pass in the WM_NCHITTEST message.
351 static HWND find_child_from_point( HWND parent, POINT pt, INT *hittest, LPARAM lparam )
353 int i, res;
354 WND *wndPtr;
355 HWND *list = WIN_ListChildren( parent );
357 if (!list) return 0;
358 for (i = 0; list[i]; i++)
360 if (!(wndPtr = WIN_FindWndPtr( list[i] ))) continue;
361 /* If point is in window, and window is visible, and it */
362 /* is enabled (or it's a top-level window), then explore */
363 /* its children. Otherwise, go to the next window. */
365 if (!(wndPtr->dwStyle & WS_VISIBLE)) goto next; /* not visible -> skip */
366 if ((wndPtr->dwStyle & (WS_POPUP | WS_CHILD | WS_DISABLED)) == (WS_CHILD | WS_DISABLED))
367 goto next; /* disabled child -> skip */
368 if ((wndPtr->dwExStyle & (WS_EX_LAYERED | WS_EX_TRANSPARENT)) == (WS_EX_LAYERED | WS_EX_TRANSPARENT))
369 goto next; /* transparent -> skip */
370 if (wndPtr->hrgnWnd)
372 if (!PtInRegion( wndPtr->hrgnWnd, pt.x - wndPtr->rectWindow.left,
373 pt.y - wndPtr->rectWindow.top ))
374 goto next; /* point outside window region -> skip */
376 else if (!PtInRect( &wndPtr->rectWindow, pt )) goto next; /* not in window -> skip */
378 /* If window is minimized or disabled, return at once */
379 if (wndPtr->dwStyle & WS_MINIMIZE)
381 WIN_ReleaseWndPtr( wndPtr );
382 *hittest = HTCAPTION;
383 return list[i];
385 if (wndPtr->dwStyle & WS_DISABLED)
387 WIN_ReleaseWndPtr( wndPtr );
388 *hittest = HTERROR;
389 return list[i];
392 /* If point is in client area, explore children */
393 if (PtInRect( &wndPtr->rectClient, pt ))
395 POINT new_pt;
396 HWND ret;
398 new_pt.x = pt.x - wndPtr->rectClient.left;
399 new_pt.y = pt.y - wndPtr->rectClient.top;
400 WIN_ReleaseWndPtr( wndPtr );
401 if ((ret = find_child_from_point( list[i], new_pt, hittest, lparam )))
402 return ret;
404 else WIN_ReleaseWndPtr( wndPtr );
406 /* Now it's inside window, send WM_NCCHITTEST (if same thread) */
407 if (!WIN_IsCurrentThread( list[i] ))
409 *hittest = HTCLIENT;
410 return list[i];
412 if ((res = SendMessageA( list[i], WM_NCHITTEST, 0, lparam )) != HTTRANSPARENT)
414 *hittest = res; /* Found the window */
415 return list[i];
417 continue; /* continue search with next sibling */
419 next:
420 WIN_ReleaseWndPtr( wndPtr );
422 return 0;
426 /***********************************************************************
427 * WINPOS_WindowFromPoint
429 * Find the window and hittest for a given point.
431 HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest )
433 WND *wndScope;
434 POINT xy = pt;
435 int res;
437 TRACE("scope %04x %ld,%ld\n", hwndScope, pt.x, pt.y);
439 if (!hwndScope) hwndScope = GetDesktopWindow();
440 if (!(wndScope = WIN_FindWndPtr( hwndScope ))) return 0;
441 hwndScope = wndScope->hwndSelf; /* make it a full handle */
443 *hittest = HTERROR;
444 if( wndScope->dwStyle & WS_DISABLED )
446 WIN_ReleaseWndPtr(wndScope);
447 return 0;
450 if (wndScope->parent)
451 MapWindowPoints( GetDesktopWindow(), wndScope->parent, &xy, 1 );
453 if (!(wndScope->dwStyle & WS_MINIMIZE) && PtInRect( &wndScope->rectClient, xy ))
455 HWND ret;
457 xy.x -= wndScope->rectClient.left;
458 xy.y -= wndScope->rectClient.top;
459 WIN_ReleaseWndPtr( wndScope );
460 if ((ret = find_child_from_point( hwndScope, xy, hittest, MAKELONG( pt.x, pt.y ) )))
462 TRACE( "found child %x\n", ret );
463 return ret;
466 else WIN_ReleaseWndPtr( wndScope );
468 /* If nothing found, try the scope window */
469 if (!WIN_IsCurrentThread( hwndScope ))
471 *hittest = HTCLIENT;
472 TRACE( "returning %x\n", hwndScope );
473 return hwndScope;
475 res = SendMessageA( hwndScope, WM_NCHITTEST, 0, MAKELONG( pt.x, pt.y ) );
476 if (res != HTTRANSPARENT)
478 *hittest = res; /* Found the window */
479 TRACE( "returning %x\n", hwndScope );
480 return hwndScope;
482 *hittest = HTNOWHERE;
483 TRACE( "nothing found\n" );
484 return 0;
488 /*******************************************************************
489 * WindowFromPoint (USER32.@)
491 HWND WINAPI WindowFromPoint( POINT pt )
493 INT hittest;
494 return WINPOS_WindowFromPoint( 0, pt, &hittest );
498 /*******************************************************************
499 * ChildWindowFromPoint (USER32.@)
501 HWND WINAPI ChildWindowFromPoint( HWND hwndParent, POINT pt )
503 return ChildWindowFromPointEx( hwndParent, pt, CWP_ALL );
506 /*******************************************************************
507 * ChildWindowFromPointEx (USER32.@)
509 HWND WINAPI ChildWindowFromPointEx( HWND hwndParent, POINT pt, UINT uFlags)
511 /* pt is in the client coordinates */
512 HWND *list;
513 int i;
514 RECT rect;
515 HWND retvalue = 0;
517 GetClientRect( hwndParent, &rect );
518 if (!PtInRect( &rect, pt )) return 0;
519 if (!(list = WIN_ListChildren( hwndParent ))) return 0;
521 for (i = 0; list[i] && !retvalue; i++)
523 WND *wnd = WIN_FindWndPtr( list[i] );
524 if (!wnd) continue;
525 if (PtInRect( &wnd->rectWindow, pt ))
527 if ( (uFlags & CWP_SKIPINVISIBLE) &&
528 !(wnd->dwStyle & WS_VISIBLE) );
529 else if ( (uFlags & CWP_SKIPDISABLED) &&
530 (wnd->dwStyle & WS_DISABLED) );
531 else if ( (uFlags & CWP_SKIPTRANSPARENT) &&
532 (wnd->dwExStyle & WS_EX_TRANSPARENT) );
533 else retvalue = list[i];
535 WIN_ReleaseWndPtr( wnd );
537 HeapFree( GetProcessHeap(), 0, list );
538 if (!retvalue) retvalue = hwndParent;
539 return retvalue;
543 /*******************************************************************
544 * WINPOS_GetWinOffset
546 * Calculate the offset between the origin of the two windows. Used
547 * to implement MapWindowPoints.
549 static void WINPOS_GetWinOffset( HWND hwndFrom, HWND hwndTo, POINT *offset )
551 WND * wndPtr;
553 offset->x = offset->y = 0;
555 /* Translate source window origin to screen coords */
556 if (hwndFrom)
558 HWND hwnd = hwndFrom;
560 while (hwnd)
562 if (hwnd == hwndTo) return;
563 if (!(wndPtr = WIN_GetPtr( hwnd )))
565 ERR( "bad hwndFrom = %04x\n", hwnd );
566 return;
568 if (wndPtr == WND_OTHER_PROCESS) goto other_process;
569 offset->x += wndPtr->rectClient.left;
570 offset->y += wndPtr->rectClient.top;
571 hwnd = wndPtr->parent;
572 WIN_ReleasePtr( wndPtr );
576 /* Translate origin to destination window coords */
577 if (hwndTo)
579 HWND hwnd = hwndTo;
581 while (hwnd)
583 if (!(wndPtr = WIN_GetPtr( hwnd )))
585 ERR( "bad hwndTo = %04x\n", hwnd );
586 return;
588 if (wndPtr == WND_OTHER_PROCESS) goto other_process;
589 offset->x -= wndPtr->rectClient.left;
590 offset->y -= wndPtr->rectClient.top;
591 hwnd = wndPtr->parent;
592 WIN_ReleasePtr( wndPtr );
595 return;
597 other_process: /* one of the parents may belong to another process, do it the hard way */
598 offset->x = offset->y = 0;
599 SERVER_START_REQ( get_windows_offset )
601 req->from = hwndFrom;
602 req->to = hwndTo;
603 if (!SERVER_CALL())
605 offset->x = req->x;
606 offset->y = req->y;
609 SERVER_END_REQ;
613 /*******************************************************************
614 * MapWindowPoints (USER.258)
616 void WINAPI MapWindowPoints16( HWND16 hwndFrom, HWND16 hwndTo,
617 LPPOINT16 lppt, UINT16 count )
619 POINT offset;
621 WINPOS_GetWinOffset( WIN_Handle32(hwndFrom), WIN_Handle32(hwndTo), &offset );
622 while (count--)
624 lppt->x += offset.x;
625 lppt->y += offset.y;
626 lppt++;
631 /*******************************************************************
632 * MapWindowPoints (USER32.@)
634 INT WINAPI MapWindowPoints( HWND hwndFrom, HWND hwndTo, LPPOINT lppt, UINT count )
636 POINT offset;
638 WINPOS_GetWinOffset( hwndFrom, hwndTo, &offset );
639 while (count--)
641 lppt->x += offset.x;
642 lppt->y += offset.y;
643 lppt++;
645 return MAKELONG( LOWORD(offset.x), LOWORD(offset.y) );
649 /***********************************************************************
650 * IsIconic (USER32.@)
652 BOOL WINAPI IsIconic(HWND hWnd)
654 return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
658 /***********************************************************************
659 * IsZoomed (USER32.@)
661 BOOL WINAPI IsZoomed(HWND hWnd)
663 return (GetWindowLongW( hWnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
667 /*******************************************************************
668 * GetActiveWindow (USER32.@)
670 HWND WINAPI GetActiveWindow(void)
672 MESSAGEQUEUE *pCurMsgQ = 0;
674 /* Get the messageQ for the current thread */
675 if (!(pCurMsgQ = QUEUE_Current()))
677 WARN("\tCurrent message queue not found. Exiting!\n" );
678 return 0;
681 /* Return the current active window from the perQ data of the current message Q */
682 return PERQDATA_GetActiveWnd( pCurMsgQ->pQData );
686 /*******************************************************************
687 * WINPOS_CanActivate
689 static BOOL WINPOS_CanActivate(HWND hwnd)
691 if (!hwnd) return FALSE;
692 return ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_DISABLED|WS_VISIBLE|WS_CHILD)) == WS_VISIBLE);
696 /*******************************************************************
697 * SetActiveWindow (USER32.@)
699 HWND WINAPI SetActiveWindow( HWND hwnd )
701 HWND prev = 0;
702 WND *wndPtr = WIN_FindWndPtr( hwnd );
703 MESSAGEQUEUE *pMsgQ = 0, *pCurMsgQ = 0;
705 if (!wndPtr) return 0;
707 if (wndPtr->dwStyle & (WS_DISABLED | WS_CHILD)) goto error;
709 /* Get the messageQ for the current thread */
710 if (!(pCurMsgQ = QUEUE_Current()))
712 WARN("\tCurrent message queue not found. Exiting!\n" );
713 goto error;
716 /* Retrieve the message queue associated with this window */
717 pMsgQ = (MESSAGEQUEUE *)QUEUE_Lock( wndPtr->hmemTaskQ );
718 if ( !pMsgQ )
720 WARN("\tWindow message queue not found. Exiting!\n" );
721 goto error;
724 /* Make sure that the window is associated with the calling threads
725 * message queue. It must share the same perQ data.
727 if ( pCurMsgQ->pQData != pMsgQ->pQData )
729 QUEUE_Unlock( pMsgQ );
730 goto error;
733 /* Save current active window */
734 prev = PERQDATA_GetActiveWnd( pMsgQ->pQData );
735 QUEUE_Unlock( pMsgQ );
736 WIN_ReleaseWndPtr(wndPtr);
737 WINPOS_SetActiveWindow( hwnd, 0, 0 );
738 return prev;
740 error:
741 WIN_ReleaseWndPtr(wndPtr);
742 return 0;
746 /*******************************************************************
747 * GetForegroundWindow (USER32.@)
749 HWND WINAPI GetForegroundWindow(void)
751 HWND hwndActive = 0;
753 /* Get the foreground window (active window of hActiveQueue) */
754 if ( hActiveQueue )
756 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
757 if ( pActiveQueue )
758 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
760 QUEUE_Unlock( pActiveQueue );
763 return hwndActive;
766 /*******************************************************************
767 * SetForegroundWindow (USER32.@)
769 BOOL WINAPI SetForegroundWindow( HWND hwnd )
771 return WINPOS_ChangeActiveWindow( hwnd, FALSE );
775 /*******************************************************************
776 * AllowSetForegroundWindow (USER32.@)
778 BOOL WINAPI AllowSetForegroundWindow( DWORD procid )
780 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
781 * implemented, then fix this function. */
782 return TRUE;
786 /*******************************************************************
787 * LockSetForegroundWindow (USER32.@)
789 BOOL WINAPI LockSetForegroundWindow( UINT lockcode )
791 /* FIXME: If Win98/2000 style SetForegroundWindow behavior is
792 * implemented, then fix this function. */
793 return TRUE;
797 /*******************************************************************
798 * SetShellWindow (USER32.@)
800 HWND WINAPI SetShellWindow(HWND hwndshell)
801 { WARN("(hWnd=%08x) semi stub\n",hwndshell );
803 hGlobalShellWindow = WIN_GetFullHandle( hwndshell );
804 return hGlobalShellWindow;
808 /*******************************************************************
809 * GetShellWindow (USER32.@)
811 HWND WINAPI GetShellWindow(void)
812 { WARN("(hWnd=%x) semi stub\n",hGlobalShellWindow );
814 return hGlobalShellWindow;
818 /***********************************************************************
819 * BringWindowToTop (USER32.@)
821 BOOL WINAPI BringWindowToTop( HWND hwnd )
823 return SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE );
827 /***********************************************************************
828 * MoveWindow (USER32.@)
830 BOOL WINAPI MoveWindow( HWND hwnd, INT x, INT y, INT cx, INT cy,
831 BOOL repaint )
833 int flags = SWP_NOZORDER | SWP_NOACTIVATE;
834 if (!repaint) flags |= SWP_NOREDRAW;
835 TRACE("%04x %d,%d %dx%d %d\n",
836 hwnd, x, y, cx, cy, repaint );
837 return SetWindowPos( hwnd, 0, x, y, cx, cy, flags );
840 /***********************************************************************
841 * WINPOS_InitInternalPos
843 static LPINTERNALPOS WINPOS_InitInternalPos( WND* wnd, POINT pt, const RECT *restoreRect )
845 LPINTERNALPOS lpPos = (LPINTERNALPOS) GetPropA( wnd->hwndSelf,
846 atomInternalPos );
847 if( !lpPos )
849 /* this happens when the window is minimized/maximized
850 * for the first time (rectWindow is not adjusted yet) */
852 lpPos = HeapAlloc( GetProcessHeap(), 0, sizeof(INTERNALPOS) );
853 if( !lpPos ) return NULL;
855 SetPropA( wnd->hwndSelf, atomInternalPos, (HANDLE)lpPos );
856 lpPos->hwndIconTitle = 0; /* defer until needs to be shown */
857 CONV_RECT32TO16( &wnd->rectWindow, &lpPos->rectNormal );
858 *(UINT*)&lpPos->ptIconPos = *(UINT*)&lpPos->ptMaxPos = 0xFFFFFFFF;
861 if( wnd->dwStyle & WS_MINIMIZE )
862 CONV_POINT32TO16( &pt, &lpPos->ptIconPos );
863 else if( wnd->dwStyle & WS_MAXIMIZE )
864 CONV_POINT32TO16( &pt, &lpPos->ptMaxPos );
865 else if( restoreRect )
866 CONV_RECT32TO16( restoreRect, &lpPos->rectNormal );
868 return lpPos;
871 /***********************************************************************
872 * WINPOS_RedrawIconTitle
874 BOOL WINPOS_RedrawIconTitle( HWND hWnd )
876 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hWnd, atomInternalPos );
877 if( lpPos )
879 if( lpPos->hwndIconTitle )
881 SendMessageA( lpPos->hwndIconTitle, WM_SHOWWINDOW, TRUE, 0);
882 InvalidateRect( lpPos->hwndIconTitle, NULL, TRUE );
883 return TRUE;
886 return FALSE;
889 /***********************************************************************
890 * WINPOS_ShowIconTitle
892 BOOL WINPOS_ShowIconTitle( HWND hwnd, BOOL bShow )
894 LPINTERNALPOS lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
896 if( lpPos && !(GetWindowLongA( hwnd, GWL_EXSTYLE) & WS_EX_MANAGED))
898 HWND title = lpPos->hwndIconTitle;
900 TRACE("0x%04x %i\n", hwnd, (bShow != 0) );
902 if( !title )
903 lpPos->hwndIconTitle = title = ICONTITLE_Create( hwnd );
904 if( bShow )
906 if (!IsWindowVisible(title))
908 SendMessageA( title, WM_SHOWWINDOW, TRUE, 0 );
909 SetWindowPos( title, 0, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE |
910 SWP_NOACTIVATE | SWP_NOZORDER | SWP_SHOWWINDOW );
913 else ShowWindow( title, SW_HIDE );
915 return FALSE;
918 /*******************************************************************
919 * WINPOS_GetMinMaxInfo
921 * Get the minimized and maximized information for a window.
923 void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
924 POINT *minTrack, POINT *maxTrack )
926 LPINTERNALPOS lpPos;
927 MINMAXINFO MinMax;
928 INT xinc, yinc;
929 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
930 LONG exstyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
932 /* Compute default values */
934 MinMax.ptMaxSize.x = GetSystemMetrics(SM_CXSCREEN);
935 MinMax.ptMaxSize.y = GetSystemMetrics(SM_CYSCREEN);
936 MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
937 MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
938 MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXSCREEN);
939 MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYSCREEN);
941 if (HAS_DLGFRAME( style, exstyle ))
943 xinc = GetSystemMetrics(SM_CXDLGFRAME);
944 yinc = GetSystemMetrics(SM_CYDLGFRAME);
946 else
948 xinc = yinc = 0;
949 if (HAS_THICKFRAME(style))
951 xinc += GetSystemMetrics(SM_CXFRAME);
952 yinc += GetSystemMetrics(SM_CYFRAME);
954 if (style & WS_BORDER)
956 xinc += GetSystemMetrics(SM_CXBORDER);
957 yinc += GetSystemMetrics(SM_CYBORDER);
960 MinMax.ptMaxSize.x += 2 * xinc;
961 MinMax.ptMaxSize.y += 2 * yinc;
963 lpPos = (LPINTERNALPOS)GetPropA( hwnd, atomInternalPos );
964 if( lpPos && !EMPTYPOINT(lpPos->ptMaxPos) )
965 CONV_POINT16TO32( &lpPos->ptMaxPos, &MinMax.ptMaxPosition );
966 else
968 MinMax.ptMaxPosition.x = -xinc;
969 MinMax.ptMaxPosition.y = -yinc;
972 SendMessageA( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
974 /* Some sanity checks */
976 TRACE("%ld %ld / %ld %ld / %ld %ld / %ld %ld\n",
977 MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
978 MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
979 MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
980 MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
981 MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
982 MinMax.ptMinTrackSize.x );
983 MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
984 MinMax.ptMinTrackSize.y );
986 if (maxSize) *maxSize = MinMax.ptMaxSize;
987 if (maxPos) *maxPos = MinMax.ptMaxPosition;
988 if (minTrack) *minTrack = MinMax.ptMinTrackSize;
989 if (maxTrack) *maxTrack = MinMax.ptMaxTrackSize;
992 /***********************************************************************
993 * ShowWindowAsync (USER32.@)
995 * doesn't wait; returns immediately.
996 * used by threads to toggle windows in other (possibly hanging) threads
998 BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
1000 /* FIXME: does ShowWindow() return immediately ? */
1001 return ShowWindow(hwnd, cmd);
1005 /***********************************************************************
1006 * ShowWindow (USER32.@)
1008 BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
1010 HWND full_handle;
1012 if ((full_handle = WIN_IsCurrentThread( hwnd )))
1013 return USER_Driver.pShowWindow( full_handle, cmd );
1014 return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
1018 /***********************************************************************
1019 * GetInternalWindowPos (USER.460)
1021 UINT16 WINAPI GetInternalWindowPos16( HWND16 hwnd, LPRECT16 rectWnd,
1022 LPPOINT16 ptIcon )
1024 WINDOWPLACEMENT16 wndpl;
1025 if (GetWindowPlacement16( hwnd, &wndpl ))
1027 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1028 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1029 return wndpl.showCmd;
1031 return 0;
1035 /***********************************************************************
1036 * GetInternalWindowPos (USER32.@)
1038 UINT WINAPI GetInternalWindowPos( HWND hwnd, LPRECT rectWnd,
1039 LPPOINT ptIcon )
1041 WINDOWPLACEMENT wndpl;
1042 if (GetWindowPlacement( hwnd, &wndpl ))
1044 if (rectWnd) *rectWnd = wndpl.rcNormalPosition;
1045 if (ptIcon) *ptIcon = wndpl.ptMinPosition;
1046 return wndpl.showCmd;
1048 return 0;
1052 /***********************************************************************
1053 * GetWindowPlacement (USER32.@)
1055 * Win95:
1056 * Fails if wndpl->length of Win95 (!) apps is invalid.
1058 BOOL WINAPI GetWindowPlacement( HWND hwnd, WINDOWPLACEMENT *wndpl )
1060 WND *pWnd = WIN_FindWndPtr( hwnd );
1061 LPINTERNALPOS lpPos;
1063 if(!pWnd ) return FALSE;
1065 lpPos = WINPOS_InitInternalPos( pWnd, *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1066 wndpl->length = sizeof(*wndpl);
1067 if( pWnd->dwStyle & WS_MINIMIZE )
1068 wndpl->showCmd = SW_SHOWMINIMIZED;
1069 else
1070 wndpl->showCmd = ( pWnd->dwStyle & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
1071 if( pWnd->flags & WIN_RESTORE_MAX )
1072 wndpl->flags = WPF_RESTORETOMAXIMIZED;
1073 else
1074 wndpl->flags = 0;
1075 CONV_POINT16TO32( &lpPos->ptIconPos, &wndpl->ptMinPosition );
1076 CONV_POINT16TO32( &lpPos->ptMaxPos, &wndpl->ptMaxPosition );
1077 CONV_RECT16TO32( &lpPos->rectNormal, &wndpl->rcNormalPosition );
1078 WIN_ReleaseWndPtr(pWnd);
1079 return TRUE;
1083 /***********************************************************************
1084 * WINPOS_SetPlacement
1086 static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT flags )
1088 WND *pWnd = WIN_FindWndPtr( hwnd );
1089 if( pWnd )
1091 LPINTERNALPOS lpPos = (LPINTERNALPOS)WINPOS_InitInternalPos( pWnd,
1092 *(LPPOINT)&pWnd->rectWindow.left, &pWnd->rectWindow );
1094 if( flags & PLACE_MIN ) CONV_POINT32TO16( &wndpl->ptMinPosition, &lpPos->ptIconPos );
1095 if( flags & PLACE_MAX ) CONV_POINT32TO16( &wndpl->ptMaxPosition, &lpPos->ptMaxPos );
1096 if( flags & PLACE_RECT) CONV_RECT32TO16( &wndpl->rcNormalPosition, &lpPos->rectNormal );
1098 if( pWnd->dwStyle & WS_MINIMIZE )
1100 WINPOS_ShowIconTitle( pWnd->hwndSelf, FALSE );
1101 if( wndpl->flags & WPF_SETMINPOSITION && !EMPTYPOINT(lpPos->ptIconPos))
1102 SetWindowPos( hwnd, 0, lpPos->ptIconPos.x, lpPos->ptIconPos.y,
1103 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1105 else if( pWnd->dwStyle & WS_MAXIMIZE )
1107 if( !EMPTYPOINT(lpPos->ptMaxPos) )
1108 SetWindowPos( hwnd, 0, lpPos->ptMaxPos.x, lpPos->ptMaxPos.y,
1109 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
1111 else if( flags & PLACE_RECT )
1112 SetWindowPos( hwnd, 0, lpPos->rectNormal.left, lpPos->rectNormal.top,
1113 lpPos->rectNormal.right - lpPos->rectNormal.left,
1114 lpPos->rectNormal.bottom - lpPos->rectNormal.top,
1115 SWP_NOZORDER | SWP_NOACTIVATE );
1117 ShowWindow( hwnd, wndpl->showCmd );
1118 if( IsWindow(hwnd) && pWnd->dwStyle & WS_MINIMIZE )
1120 if( pWnd->dwStyle & WS_VISIBLE ) WINPOS_ShowIconTitle( pWnd->hwndSelf, TRUE );
1122 /* SDK: ...valid only the next time... */
1123 if( wndpl->flags & WPF_RESTORETOMAXIMIZED ) pWnd->flags |= WIN_RESTORE_MAX;
1125 WIN_ReleaseWndPtr(pWnd);
1126 return TRUE;
1128 return FALSE;
1132 /***********************************************************************
1133 * SetWindowPlacement (USER32.@)
1135 * Win95:
1136 * Fails if wndpl->length of Win95 (!) apps is invalid.
1138 BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl )
1140 if (!wpl) return FALSE;
1141 return WINPOS_SetPlacement( hwnd, wpl, PLACE_MIN | PLACE_MAX | PLACE_RECT );
1145 /***********************************************************************
1146 * AnimateWindow (USER32.@)
1147 * Shows/Hides a window with an animation
1148 * NO ANIMATION YET
1150 BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags)
1152 FIXME("partial stub\n");
1154 /* If trying to show/hide and it's already *
1155 * shown/hidden or invalid window, fail with *
1156 * invalid parameter */
1157 if(!IsWindow(hwnd) ||
1158 (IsWindowVisible(hwnd) && !(dwFlags & AW_HIDE)) ||
1159 (!IsWindowVisible(hwnd) && (dwFlags & AW_HIDE)))
1161 SetLastError(ERROR_INVALID_PARAMETER);
1162 return FALSE;
1165 ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1167 return TRUE;
1170 /***********************************************************************
1171 * SetInternalWindowPos (USER32.@)
1173 void WINAPI SetInternalWindowPos( HWND hwnd, UINT showCmd,
1174 LPRECT rect, LPPOINT pt )
1176 if( IsWindow(hwnd) )
1178 WINDOWPLACEMENT wndpl;
1179 UINT flags;
1181 wndpl.length = sizeof(wndpl);
1182 wndpl.showCmd = showCmd;
1183 wndpl.flags = flags = 0;
1185 if( pt )
1187 flags |= PLACE_MIN;
1188 wndpl.flags |= WPF_SETMINPOSITION;
1189 wndpl.ptMinPosition = *pt;
1191 if( rect )
1193 flags |= PLACE_RECT;
1194 wndpl.rcNormalPosition = *rect;
1196 WINPOS_SetPlacement( hwnd, &wndpl, flags );
1200 /*******************************************************************
1201 * WINPOS_SetActiveWindow
1203 * SetActiveWindow() back-end. This is the only function that
1204 * can assign active status to a window. It must be called only
1205 * for the top level windows.
1207 BOOL WINPOS_SetActiveWindow( HWND hWnd, BOOL fMouse, BOOL fChangeFocus)
1209 WND* wndPtr=0, *wndTemp;
1210 HQUEUE16 hOldActiveQueue, hNewActiveQueue;
1211 MESSAGEQUEUE *pOldActiveQueue = 0, *pNewActiveQueue = 0;
1212 WORD wIconized = 0;
1213 HWND hwndActive = 0;
1214 BOOL bRet = 0;
1216 TRACE("(%04x, %d, %d)\n", hWnd, fMouse, fChangeFocus );
1218 /* Get current active window from the active queue */
1219 if ( hActiveQueue )
1221 pOldActiveQueue = QUEUE_Lock( hActiveQueue );
1222 if ( pOldActiveQueue )
1223 hwndActive = PERQDATA_GetActiveWnd( pOldActiveQueue->pQData );
1226 if ((wndPtr = WIN_FindWndPtr(hWnd)))
1227 hWnd = wndPtr->hwndSelf; /* make it a full handle */
1229 /* paranoid checks */
1230 if( hWnd == GetDesktopWindow() || (bRet = (hWnd == hwndActive)) )
1231 goto CLEANUP_END;
1233 /* if (wndPtr && (GetFastQueue16() != wndPtr->hmemTaskQ))
1234 * return 0;
1236 hOldActiveQueue = hActiveQueue;
1238 if( (wndTemp = WIN_FindWndPtr(hwndActive)) )
1240 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1241 WIN_ReleaseWndPtr(wndTemp);
1243 else
1244 TRACE("no current active window.\n");
1246 /* call CBT hook chain */
1247 if (HOOK_IsHooked( WH_CBT ))
1249 CBTACTIVATESTRUCT cbt;
1250 cbt.fMouse = fMouse;
1251 cbt.hWndActive = hwndActive;
1252 if (HOOK_CallHooksA( WH_CBT, HCBT_ACTIVATE, (WPARAM)hWnd, (LPARAM)&cbt )) goto CLEANUP_END;
1255 /* set prev active wnd to current active wnd and send notification */
1256 if ((hwndPrevActive = hwndActive) && IsWindow(hwndPrevActive))
1258 MESSAGEQUEUE *pTempActiveQueue = 0;
1260 if (!SendMessageA( hwndPrevActive, WM_NCACTIVATE, FALSE, 0 ))
1262 if (GetSysModalWindow16() != WIN_Handle16(hWnd)) goto CLEANUP_END;
1263 /* disregard refusal if hWnd is sysmodal */
1266 SendMessageA( hwndPrevActive, WM_ACTIVATE,
1267 MAKEWPARAM( WA_INACTIVE, wIconized ),
1268 (LPARAM)hWnd );
1270 /* check if something happened during message processing
1271 * (global active queue may have changed)
1273 pTempActiveQueue = QUEUE_Lock( hActiveQueue );
1274 if(!pTempActiveQueue)
1275 goto CLEANUP_END;
1277 hwndActive = PERQDATA_GetActiveWnd( pTempActiveQueue->pQData );
1278 QUEUE_Unlock( pTempActiveQueue );
1279 if( hwndPrevActive != hwndActive )
1280 goto CLEANUP_END;
1283 /* Set new active window in the message queue */
1284 hwndActive = hWnd;
1285 if ( wndPtr )
1287 pNewActiveQueue = QUEUE_Lock( wndPtr->hmemTaskQ );
1288 if ( pNewActiveQueue )
1289 PERQDATA_SetActiveWnd( pNewActiveQueue->pQData, hwndActive );
1291 else /* have to do this or MDI frame activation goes to hell */
1292 if( pOldActiveQueue )
1293 PERQDATA_SetActiveWnd( pOldActiveQueue->pQData, 0 );
1295 /* send palette messages */
1296 if (hWnd && SendMessageW( hWnd, WM_QUERYNEWPALETTE, 0, 0L))
1297 SendMessageW( HWND_BROADCAST, WM_PALETTEISCHANGING, (WPARAM)hWnd, 0 );
1299 /* if prev wnd is minimized redraw icon title */
1300 if( IsIconic( hwndPrevActive ) ) WINPOS_RedrawIconTitle(hwndPrevActive);
1302 /* managed windows will get ConfigureNotify event */
1303 if (wndPtr && !(wndPtr->dwStyle & WS_CHILD) && !(wndPtr->dwExStyle & WS_EX_MANAGED))
1305 /* check Z-order and bring hWnd to the top */
1306 HWND tmp = GetTopWindow(0);
1307 while (tmp && !(GetWindowLongA( tmp, GWL_STYLE ) & WS_VISIBLE))
1308 tmp = GetWindow( tmp, GW_HWNDNEXT );
1310 if( tmp != hWnd )
1311 SetWindowPos(hWnd, HWND_TOP, 0,0,0,0,
1312 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );
1313 if (!IsWindow(hWnd))
1314 goto CLEANUP;
1317 /* Get a handle to the new active queue */
1318 hNewActiveQueue = wndPtr ? wndPtr->hmemTaskQ : 0;
1320 /* send WM_ACTIVATEAPP if necessary */
1321 if (hOldActiveQueue != hNewActiveQueue)
1323 HWND *list, *phwnd;
1324 DWORD old_thread = GetWindowThreadProcessId( hwndPrevActive, NULL );
1325 DWORD new_thread = GetWindowThreadProcessId( hwndActive, NULL );
1327 if ((list = WIN_ListChildren( GetDesktopWindow() )))
1329 for (phwnd = list; *phwnd; phwnd++)
1331 if (!IsWindow( *phwnd )) continue;
1332 if (GetWindowThreadProcessId( *phwnd, NULL ) == old_thread)
1333 SendMessageW( *phwnd, WM_ACTIVATEAPP, 0, new_thread );
1335 HeapFree( GetProcessHeap(), 0, list );
1338 hActiveQueue = hNewActiveQueue;
1340 if ((list = WIN_ListChildren( GetDesktopWindow() )))
1342 for (phwnd = list; *phwnd; phwnd++)
1344 if (!IsWindow( *phwnd )) continue;
1345 if (GetWindowThreadProcessId( *phwnd, NULL ) == new_thread)
1346 SendMessageW( *phwnd, WM_ACTIVATEAPP, 1, old_thread );
1348 HeapFree( GetProcessHeap(), 0, list );
1351 if (hWnd && !IsWindow(hWnd)) goto CLEANUP;
1354 if (hWnd)
1356 /* walk up to the first unowned window */
1357 HWND tmp = GetAncestor( hWnd, GA_ROOTOWNER );
1358 if ((wndTemp = WIN_FindWndPtr( tmp )))
1360 /* and set last active owned popup */
1361 wndTemp->hwndLastActive = hWnd;
1363 wIconized = HIWORD(wndTemp->dwStyle & WS_MINIMIZE);
1364 WIN_ReleaseWndPtr(wndTemp);
1366 SendMessageA( hWnd, WM_NCACTIVATE, TRUE, 0 );
1367 SendMessageA( hWnd, WM_ACTIVATE,
1368 MAKEWPARAM( (fMouse) ? WA_CLICKACTIVE : WA_ACTIVE, wIconized),
1369 (LPARAM)hwndPrevActive );
1370 if( !IsWindow(hWnd) ) goto CLEANUP;
1373 /* change focus if possible */
1374 if ( fChangeFocus )
1376 if ( pNewActiveQueue )
1378 HWND hOldFocus = PERQDATA_GetFocusWnd( pNewActiveQueue->pQData );
1380 if ( hOldFocus && GetAncestor( hOldFocus, GA_ROOT ) != hwndActive )
1381 FOCUS_SwitchFocus( pNewActiveQueue, hOldFocus,
1382 (wndPtr && (wndPtr->dwStyle & WS_MINIMIZE))?
1383 0 : hwndActive );
1386 if ( pOldActiveQueue &&
1387 ( !pNewActiveQueue ||
1388 pNewActiveQueue->pQData != pOldActiveQueue->pQData ) )
1390 HWND hOldFocus = PERQDATA_GetFocusWnd( pOldActiveQueue->pQData );
1391 if ( hOldFocus )
1392 FOCUS_SwitchFocus( pOldActiveQueue, hOldFocus, 0 );
1396 if( !hwndPrevActive && wndPtr )
1398 if (USER_Driver.pForceWindowRaise) USER_Driver.pForceWindowRaise( wndPtr->hwndSelf );
1401 /* if active wnd is minimized redraw icon title */
1402 if( IsIconic(hwndActive) ) WINPOS_RedrawIconTitle(hwndActive);
1404 bRet = (hWnd == hwndActive); /* Success? */
1406 CLEANUP: /* Unlock the message queues before returning */
1408 if ( pNewActiveQueue )
1409 QUEUE_Unlock( pNewActiveQueue );
1411 CLEANUP_END:
1413 if ( pOldActiveQueue )
1414 QUEUE_Unlock( pOldActiveQueue );
1416 WIN_ReleaseWndPtr(wndPtr);
1417 return bRet;
1420 /*******************************************************************
1421 * WINPOS_ActivateOtherWindow
1423 * Activates window other than pWnd.
1425 BOOL WINPOS_ActivateOtherWindow(HWND hwnd)
1427 BOOL bRet = 0;
1428 HWND hwndActive = 0;
1429 HWND hwndTo = 0;
1430 HWND owner;
1432 /* Get current active window from the active queue */
1433 if ( hActiveQueue )
1435 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1436 if ( pActiveQueue )
1438 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1439 QUEUE_Unlock( pActiveQueue );
1443 if (!(hwnd = WIN_IsCurrentThread( hwnd ))) return 0;
1445 if( hwnd == hwndPrevActive )
1446 hwndPrevActive = 0;
1448 if( hwndActive != hwnd && (hwndActive || USER_IsExitingThread( GetCurrentThreadId() )))
1449 return 0;
1451 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_POPUP) ||
1452 !(owner = GetWindow( hwnd, GW_OWNER )) ||
1453 !WINPOS_CanActivate((hwndTo = GetAncestor( owner, GA_ROOT ))) )
1455 HWND tmp = GetAncestor( hwnd, GA_ROOT );
1456 hwndTo = hwndPrevActive;
1458 while( !WINPOS_CanActivate(hwndTo) )
1460 /* by now owned windows should've been taken care of */
1461 tmp = hwndTo = GetWindow( tmp, GW_HWNDNEXT );
1462 if( !hwndTo ) break;
1466 bRet = WINPOS_SetActiveWindow( hwndTo, FALSE, TRUE );
1468 hwndPrevActive = 0;
1469 return bRet;
1472 /*******************************************************************
1473 * WINPOS_ChangeActiveWindow
1476 BOOL WINPOS_ChangeActiveWindow( HWND hWnd, BOOL mouseMsg )
1478 WND *wndPtr;
1479 HWND hwndActive = 0;
1481 /* Get current active window from the active queue */
1482 if ( hActiveQueue )
1484 MESSAGEQUEUE *pActiveQueue = QUEUE_Lock( hActiveQueue );
1485 if ( pActiveQueue )
1487 hwndActive = PERQDATA_GetActiveWnd( pActiveQueue->pQData );
1488 QUEUE_Unlock( pActiveQueue );
1492 if (!hWnd)
1493 return WINPOS_SetActiveWindow( 0, mouseMsg, TRUE );
1495 if (!(wndPtr = WIN_FindWndPtr(hWnd))) return FALSE;
1496 hWnd = wndPtr->hwndSelf;
1498 /* child windows get WM_CHILDACTIVATE message */
1499 if( (wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD )
1501 WIN_ReleaseWndPtr(wndPtr);
1502 return SendMessageA(hWnd, WM_CHILDACTIVATE, 0, 0L);
1504 WIN_ReleaseWndPtr(wndPtr);
1506 if( hWnd == hwndActive ) return FALSE;
1508 return WINPOS_SetActiveWindow(hWnd ,mouseMsg ,TRUE);
1512 /***********************************************************************
1513 * WINPOS_HandleWindowPosChanging16
1515 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1517 LONG WINPOS_HandleWindowPosChanging16( HWND hwnd, WINDOWPOS16 *winpos )
1519 POINT maxSize, minTrack;
1520 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1522 if (winpos->flags & SWP_NOSIZE) return 0;
1523 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1525 WINPOS_GetMinMaxInfo( hwnd, &maxSize, NULL, &minTrack, NULL );
1526 if (maxSize.x < winpos->cx) winpos->cx = maxSize.x;
1527 if (maxSize.y < winpos->cy) winpos->cy = maxSize.y;
1528 if (!(style & WS_MINIMIZE))
1530 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1531 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1534 return 0;
1538 /***********************************************************************
1539 * WINPOS_HandleWindowPosChanging
1541 * Default handling for a WM_WINDOWPOSCHANGING. Called from DefWindowProc().
1543 LONG WINPOS_HandleWindowPosChanging( HWND hwnd, WINDOWPOS *winpos )
1545 POINT maxSize, minTrack;
1546 LONG style = GetWindowLongA( hwnd, GWL_STYLE );
1548 if (winpos->flags & SWP_NOSIZE) return 0;
1549 if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
1551 WINPOS_GetMinMaxInfo( hwnd, &maxSize, NULL, &minTrack, NULL );
1552 winpos->cx = min( winpos->cx, maxSize.x );
1553 winpos->cy = min( winpos->cy, maxSize.y );
1554 if (!(style & WS_MINIMIZE))
1556 if (winpos->cx < minTrack.x ) winpos->cx = minTrack.x;
1557 if (winpos->cy < minTrack.y ) winpos->cy = minTrack.y;
1560 return 0;
1564 /***********************************************************************
1565 * SetWindowPos (USER32.@)
1567 BOOL WINAPI SetWindowPos( HWND hwnd, HWND hwndInsertAfter,
1568 INT x, INT y, INT cx, INT cy, UINT flags )
1570 WINDOWPOS winpos;
1572 winpos.hwnd = hwnd;
1573 winpos.hwndInsertAfter = hwndInsertAfter;
1574 winpos.x = x;
1575 winpos.y = y;
1576 winpos.cx = cx;
1577 winpos.cy = cy;
1578 winpos.flags = flags;
1579 if (WIN_IsCurrentThread( hwnd )) return USER_Driver.pSetWindowPos( &winpos );
1580 return SendMessageW( winpos.hwnd, WM_WINE_SETWINDOWPOS, 0, (LPARAM)&winpos );
1584 /***********************************************************************
1585 * BeginDeferWindowPos (USER32.@)
1587 HDWP WINAPI BeginDeferWindowPos( INT count )
1589 HDWP handle;
1590 DWP *pDWP;
1592 if (count < 0)
1594 SetLastError(ERROR_INVALID_PARAMETER);
1595 return 0;
1597 /* Windows allows zero count, in which case it allocates context for 8 moves */
1598 if (count == 0) count = 8;
1600 handle = USER_HEAP_ALLOC( sizeof(DWP) + (count-1)*sizeof(WINDOWPOS) );
1601 if (!handle) return 0;
1602 pDWP = (DWP *) USER_HEAP_LIN_ADDR( handle );
1603 pDWP->actualCount = 0;
1604 pDWP->suggestedCount = count;
1605 pDWP->valid = TRUE;
1606 pDWP->wMagic = DWP_MAGIC;
1607 pDWP->hwndParent = 0;
1608 return handle;
1612 /***********************************************************************
1613 * DeferWindowPos (USER32.@)
1615 HDWP WINAPI DeferWindowPos( HDWP hdwp, HWND hwnd, HWND hwndAfter,
1616 INT x, INT y, INT cx, INT cy,
1617 UINT flags )
1619 DWP *pDWP;
1620 int i;
1621 HDWP newhdwp = hdwp,retvalue;
1623 hwnd = WIN_GetFullHandle( hwnd );
1624 if (hwnd == GetDesktopWindow()) return 0;
1626 if (!(pDWP = USER_HEAP_LIN_ADDR( hdwp ))) return 0;
1628 USER_Lock();
1630 for (i = 0; i < pDWP->actualCount; i++)
1632 if (pDWP->winPos[i].hwnd == hwnd)
1634 /* Merge with the other changes */
1635 if (!(flags & SWP_NOZORDER))
1637 pDWP->winPos[i].hwndInsertAfter = hwndAfter;
1639 if (!(flags & SWP_NOMOVE))
1641 pDWP->winPos[i].x = x;
1642 pDWP->winPos[i].y = y;
1644 if (!(flags & SWP_NOSIZE))
1646 pDWP->winPos[i].cx = cx;
1647 pDWP->winPos[i].cy = cy;
1649 pDWP->winPos[i].flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
1650 SWP_NOZORDER | SWP_NOREDRAW |
1651 SWP_NOACTIVATE | SWP_NOCOPYBITS|
1652 SWP_NOOWNERZORDER);
1653 pDWP->winPos[i].flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
1654 SWP_FRAMECHANGED);
1655 retvalue = hdwp;
1656 goto END;
1659 if (pDWP->actualCount >= pDWP->suggestedCount)
1661 newhdwp = USER_HEAP_REALLOC( hdwp,
1662 sizeof(DWP) + pDWP->suggestedCount*sizeof(WINDOWPOS) );
1663 if (!newhdwp)
1665 retvalue = 0;
1666 goto END;
1668 pDWP = (DWP *) USER_HEAP_LIN_ADDR( newhdwp );
1669 pDWP->suggestedCount++;
1671 pDWP->winPos[pDWP->actualCount].hwnd = hwnd;
1672 pDWP->winPos[pDWP->actualCount].hwndInsertAfter = hwndAfter;
1673 pDWP->winPos[pDWP->actualCount].x = x;
1674 pDWP->winPos[pDWP->actualCount].y = y;
1675 pDWP->winPos[pDWP->actualCount].cx = cx;
1676 pDWP->winPos[pDWP->actualCount].cy = cy;
1677 pDWP->winPos[pDWP->actualCount].flags = flags;
1678 pDWP->actualCount++;
1679 retvalue = newhdwp;
1680 END:
1681 USER_Unlock();
1682 return retvalue;
1686 /***********************************************************************
1687 * EndDeferWindowPos (USER32.@)
1689 BOOL WINAPI EndDeferWindowPos( HDWP hdwp )
1691 DWP *pDWP;
1692 WINDOWPOS *winpos;
1693 BOOL res = TRUE;
1694 int i;
1696 pDWP = (DWP *) USER_HEAP_LIN_ADDR( hdwp );
1697 if (!pDWP) return FALSE;
1698 for (i = 0, winpos = pDWP->winPos; i < pDWP->actualCount; i++, winpos++)
1700 if (!(res = USER_Driver.pSetWindowPos( winpos ))) break;
1702 USER_HEAP_FREE( hdwp );
1703 return res;
1707 /***********************************************************************
1708 * TileChildWindows (USER.199)
1710 void WINAPI TileChildWindows16( HWND16 parent, WORD action )
1712 FIXME("(%04x, %d): stub\n", parent, action);
1715 /***********************************************************************
1716 * CascadeChildWindows (USER.198)
1718 void WINAPI CascadeChildWindows16( HWND16 parent, WORD action )
1720 FIXME("(%04x, %d): stub\n", parent, action);
1723 /***********************************************************************
1724 * SetProgmanWindow (USER32.@)
1726 HWND WINAPI SetProgmanWindow ( HWND hwnd )
1728 hGlobalProgmanWindow = hwnd;
1729 return hGlobalProgmanWindow;
1732 /***********************************************************************
1733 * GetProgmanWindow (USER32.@)
1735 HWND WINAPI GetProgmanWindow(void)
1737 return hGlobalProgmanWindow;
1740 /***********************************************************************
1741 * SetShellWindowEx (USER32.@)
1742 * hwndProgman = Progman[Program Manager]
1743 * |-> SHELLDLL_DefView
1744 * hwndListView = | |-> SysListView32
1745 * | | |-> tooltips_class32
1746 * | |
1747 * | |-> SysHeader32
1748 * |
1749 * |-> ProxyTarget
1751 HWND WINAPI SetShellWindowEx ( HWND hwndProgman, HWND hwndListView )
1753 FIXME("0x%08x 0x%08x stub\n",hwndProgman ,hwndListView );
1754 hGlobalShellWindow = hwndProgman;
1755 return hGlobalShellWindow;
1759 /***********************************************************************
1760 * SetTaskmanWindow (USER32.@)
1761 * NOTES
1762 * hwnd = MSTaskSwWClass
1763 * |-> SysTabControl32
1765 HWND WINAPI SetTaskmanWindow ( HWND hwnd )
1767 hGlobalTaskmanWindow = hwnd;
1768 return hGlobalTaskmanWindow;
1771 /***********************************************************************
1772 * GetTaskmanWindow (USER32.@)
1774 HWND WINAPI GetTaskmanWindow(void)
1776 return hGlobalTaskmanWindow;