update for HEAD-2002110401
[reactos.git] / subsys / win32k / ntuser / winpos.c
1 /* $Id$
2  *
3  * COPYRIGHT:        See COPYING in the top level directory
4  * PROJECT:          ReactOS kernel
5  * PURPOSE:          Windows
6  * FILE:             subsys/win32k/ntuser/window.c
7  * PROGRAMER:        Casper S. Hornstrup (chorns@users.sourceforge.net)
8  * REVISION HISTORY:
9  *       06-06-2001  CSH  Created
10  */
11 /* INCLUDES ******************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <win32k/win32k.h>
15 #include <include/object.h>
16 #include <include/guicheck.h>
17 #include <include/window.h>
18 #include <include/class.h>
19 #include <include/error.h>
20 #include <include/winsta.h>
21 #include <windows.h>
22 #include <include/winpos.h>
23 #include <include/rect.h>
24 #include <include/callback.h>
25 #include <include/painting.h>
26
27 #define NDEBUG
28 #include <debug.h>
29
30 /* GLOBALS *******************************************************************/
31
32 #define MINMAX_NOSWP  (0x00010000)
33
34 #define SWP_EX_PAINTSELF 0x0002
35
36 ATOM AtomInternalPos = NULL;
37
38 /* FUNCTIONS *****************************************************************/
39
40 #define HAS_DLGFRAME(Style, ExStyle) \
41        (((ExStyle) & WS_EX_DLGMODALFRAME) || \
42         (((Style) & WS_DLGFRAME) && !((Style) & WS_BORDER)))
43
44 #define HAS_THICKFRAME(Style, ExStyle) \
45        (((Style) & WS_THICKFRAME) && \
46         !((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)
47
48 VOID
49 WinPosSetupInternalPos(VOID)
50 {
51   AtomInternalPos = NtAddAtom(L"SysIP", (ATOM*)(PULONG)&AtomInternalPos);
52 }
53
54 BOOL STDCALL
55 NtUserGetClientOrigin(HWND hWnd, LPPOINT Point)
56 {
57   PWINDOW_OBJECT WindowObject;
58
59   WindowObject = W32kGetWindowObject(hWnd);
60   if (WindowObject == NULL)
61     {
62       Point->x = Point->y = 0;
63       return(TRUE);
64     }
65   Point->x = WindowObject->ClientRect.left;
66   Point->y = WindowObject->ClientRect.top;
67   return(TRUE);
68 }
69
70 BOOL
71 WinPosActivateOtherWindow(PWINDOW_OBJECT Window)
72 {
73 }
74
75 POINT STATIC
76 WinPosFindIconPos(HWND hWnd, POINT Pos)
77 {
78 }
79
80 HWND STATIC
81 WinPosCreateIconTitle(PWINDOW_OBJECT WindowObject)
82 {
83   return(NULL);
84 }
85
86 BOOL STATIC
87 WinPosShowIconTitle(PWINDOW_OBJECT WindowObject, BOOL Show)
88 {
89   PINTERNALPOS InternalPos = NtUserGetProp(WindowObject->Self,
90                                            AtomInternalPos);
91   PWINDOW_OBJECT IconWindow;
92   NTSTATUS Status;
93
94   if (InternalPos)
95     {
96       HWND hWnd = InternalPos->IconTitle;
97
98       if (hWnd == NULL)
99         {
100           hWnd = WinPosCreateIconTitle(WindowObject);
101         }
102       if (Show)
103         {
104           Status = 
105             ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->
106                                        HandleTable,
107                                        hWnd,
108                                        otWindow,
109                                        (PVOID*)&IconWindow);
110           if (NT_SUCCESS(Status))
111             {
112               if (!(IconWindow->Style & WS_VISIBLE))
113                 {
114                   NtUserSendMessage(hWnd, WM_SHOWWINDOW, TRUE, 0);
115                   WinPosSetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE |
116                                      SWP_NOMOVE | SWP_NOACTIVATE | 
117                                      SWP_NOZORDER | SWP_SHOWWINDOW);
118                 }
119               ObmDereferenceObject(IconWindow);
120             }
121         }
122       else
123         {
124           WinPosShowWindow(hWnd, SW_HIDE);
125         }
126     }
127   return(FALSE);
128 }
129
130 PINTERNALPOS STATIC
131 WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT pt, PRECT RestoreRect)
132 {
133   PINTERNALPOS InternalPos = NtUserGetProp(WindowObject->Self, 
134                                            AtomInternalPos);
135   if (InternalPos == NULL)
136     {
137       InternalPos = 
138         ExAllocatePool(NonPagedPool, sizeof(INTERNALPOS));
139       NtUserSetProp(WindowObject->Self, AtomInternalPos, InternalPos);
140       InternalPos->IconTitle = 0;
141       InternalPos->NormalRect = WindowObject->WindowRect;
142       InternalPos->IconPos.x = InternalPos->MaxPos.x = 0xFFFFFFFF;
143       InternalPos->IconPos.y = InternalPos->MaxPos.y = 0xFFFFFFFF;
144     }
145   if (WindowObject->Style & WS_MINIMIZE)
146     {
147       InternalPos->IconPos = pt;
148     }
149   else if (WindowObject->Style & WS_MAXIMIZE)
150     {
151       InternalPos->MaxPos = pt;
152     }
153   else if (RestoreRect != NULL)
154     {
155       InternalPos->NormalRect = *RestoreRect;
156     }
157   return(InternalPos);
158 }
159
160 UINT
161 WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
162 {
163   POINT Size;
164   PINTERNALPOS InternalPos;
165   UINT SwpFlags = 0;
166
167   Size.x = WindowObject->WindowRect.left;
168   Size.y = WindowObject->WindowRect.top;
169   InternalPos = WinPosInitInternalPos(WindowObject, Size, 
170                                       &WindowObject->WindowRect); 
171
172   if (InternalPos)
173     {
174       if (WindowObject->Style & WS_MINIMIZE)
175         {
176           if (!NtUserSendMessage(WindowObject->Self, WM_QUERYOPEN, 0, 0))
177             {
178               return(SWP_NOSIZE | SWP_NOMOVE);
179             }
180           SwpFlags |= SWP_NOCOPYBITS;
181         }
182       switch (ShowFlag)
183         {
184         case SW_MINIMIZE:
185           {
186             if (WindowObject->Style & WS_MAXIMIZE)
187               {
188                 WindowObject->Flags |= WINDOWOBJECT_RESTOREMAX;
189                 WindowObject->Style &= ~WS_MAXIMIZE;
190               }
191             else
192               {
193                 WindowObject->Style &= ~WINDOWOBJECT_RESTOREMAX;
194               }
195             WindowObject->Style |= WS_MINIMIZE;
196             InternalPos->IconPos = WinPosFindIconPos(WindowObject,
197                                                      InternalPos->IconPos);
198             W32kSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
199                         NtUserGetSystemMetrics(SM_CXICON),
200                         NtUserGetSystemMetrics(SM_CYICON));
201             SwpFlags |= SWP_NOCOPYBITS;
202             break;
203           }
204
205         case SW_MAXIMIZE:
206           {
207             WinPosGetMinMaxInfo(WindowObject, &Size, &InternalPos->MaxPos, 
208                                 NULL, NULL);
209             if (WindowObject->Style & WS_MINIMIZE)
210               {
211                 WinPosShowIconTitle(WindowObject, FALSE);
212                 WindowObject->Style &= ~WS_MINIMIZE;
213               }
214             WindowObject->Style |= WS_MINIMIZE;
215             W32kSetRect(NewPos, InternalPos->MaxPos.x, InternalPos->MaxPos.y,
216                         Size.x, Size.y);
217             break;
218           }
219
220         case SW_RESTORE:
221           {
222             if (WindowObject->Style & WS_MINIMIZE)
223               {
224                 WindowObject->Style &= ~WS_MINIMIZE;
225                 WinPosShowIconTitle(WindowObject, FALSE);
226                 if (WindowObject->Flags & WINDOWOBJECT_RESTOREMAX)
227                   {
228                     WinPosGetMinMaxInfo(WindowObject, &Size,
229                                         &InternalPos->MaxPos, NULL, NULL);
230                     WindowObject->Style |= WS_MAXIMIZE;
231                     W32kSetRect(NewPos, InternalPos->MaxPos.x,
232                                 InternalPos->MaxPos.y, Size.x, Size.y);
233                     break;
234                   }
235               }
236             else
237               {
238                 if (!(WindowObject->Style & WS_MAXIMIZE))
239                   {
240                     return(-1);
241                   }
242                 else
243                   {
244                     WindowObject->Style &= ~WS_MAXIMIZE;
245                   }           
246                 *NewPos = InternalPos->NormalRect;
247                 NewPos->right -= NewPos->left;
248                 NewPos->bottom -= NewPos->top;
249                 break;
250               }
251           }
252         }
253     }
254   else
255     {
256       SwpFlags |= SWP_NOSIZE | SWP_NOMOVE;
257     }
258   return(SwpFlags);
259 }
260
261 UINT
262 WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
263                     POINT* MinTrack, POINT* MaxTrack)
264 {
265   MINMAXINFO MinMax;
266   INT XInc, YInc;
267   INTERNALPOS* Pos;
268
269   /* Get default values. */
270   MinMax.ptMaxSize.x = NtUserGetSystemMetrics(SM_CXSCREEN);
271   MinMax.ptMaxSize.y = NtUserGetSystemMetrics(SM_CYSCREEN);
272   MinMax.ptMinTrackSize.x = NtUserGetSystemMetrics(SM_CXMINTRACK);
273   MinMax.ptMinTrackSize.y = NtUserGetSystemMetrics(SM_CYMINTRACK);
274   MinMax.ptMaxTrackSize.x = NtUserGetSystemMetrics(SM_CXSCREEN);
275   MinMax.ptMaxTrackSize.y = NtUserGetSystemMetrics(SM_CYSCREEN);
276
277   if (HAS_DLGFRAME(Window->Style, Window->ExStyle))
278     {
279       XInc = NtUserGetSystemMetrics(SM_CXDLGFRAME);
280       YInc = NtUserGetSystemMetrics(SM_CYDLGFRAME);
281     }
282   else
283     {
284       XInc = YInc = 0;
285       if (HAS_THICKFRAME(Window->Style, Window->ExStyle))
286         {
287           XInc += NtUserGetSystemMetrics(SM_CXFRAME);
288           YInc += NtUserGetSystemMetrics(SM_CYFRAME);
289         }
290       if (Window->Style & WS_BORDER)
291         {
292           XInc += NtUserGetSystemMetrics(SM_CXBORDER);
293           YInc += NtUserGetSystemMetrics(SM_CYBORDER);
294         }
295     }
296   MinMax.ptMaxSize.x += 2 * XInc;
297   MinMax.ptMaxSize.y += 2 * YInc;
298
299   Pos = NtUserGetProp(Window->Self, AtomInternalPos);
300   if (Pos != NULL)
301     {
302       MinMax.ptMaxPosition = Pos->MaxPos;
303     }
304   else
305     {
306       MinMax.ptMaxPosition.x -= XInc;
307       MinMax.ptMaxPosition.y -= YInc;
308     }
309
310   W32kSendMessage(Window->Self, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax, TRUE);
311
312   MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
313                                 MinMax.ptMinTrackSize.x);
314   MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y,
315                                 MinMax.ptMinTrackSize.y);
316
317   if (MaxSize) *MaxSize = MinMax.ptMaxSize;
318   if (MaxPos) *MaxPos = MinMax.ptMaxPosition;
319   if (MinTrack) *MinTrack = MinMax.ptMinTrackSize;
320   if (MaxTrack) *MaxTrack = MinMax.ptMaxTrackSize;
321 }
322
323 BOOL STATIC
324 WinPosChangeActiveWindow(HWND Wnd, BOOL MouseMsg)
325 {
326 }
327
328 LONG STATIC
329 WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos,
330                    RECT* WindowRect, RECT* ClientRect)
331 {
332 }
333
334 BOOL
335 WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject,
336                        PWINDOWPOS WinPos,
337                        PRECT WindowRect,
338                        PRECT ClientRect)
339 {
340   if (!(WinPos->flags & SWP_NOSENDCHANGING))
341     {
342       NtUserSendMessage(WindowObject->Self, WM_WINDOWPOSCHANGING, 0,
343                         (LPARAM)WinPos);
344     }
345   
346   *WindowRect = WindowObject->WindowRect;
347   *ClientRect = 
348     (WindowObject->Style & WS_MINIMIZE) ? WindowObject->WindowRect :
349     WindowObject->ClientRect;
350
351   if (!(WinPos->flags & SWP_NOSIZE))
352     {
353       WindowRect->right = WindowRect->left + WinPos->cx;
354       WindowRect->bottom = WindowRect->top + WinPos->cy;
355     }
356
357   if (!(WinPos->flags & SWP_NOMOVE))
358     {
359       WindowRect->left = WinPos->x;
360       WindowRect->top = WinPos->y;
361       WindowRect->right += WinPos->x - WindowObject->WindowRect.left;
362       WindowRect->bottom += WinPos->y - WindowObject->WindowRect.top;
363
364       W32kOffsetRect(ClientRect, WinPos->x - WindowObject->WindowRect.left,
365                      WinPos->y - WindowObject->WindowRect.top);
366     }
367
368   WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
369   return(TRUE);
370 }
371
372 BOOLEAN
373 WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
374                    INT cy, UINT flags)
375 {
376   PWINDOW_OBJECT Window;
377   NTSTATUS Status;
378   WINDOWPOS WinPos;
379   RECT NewWindowRect;
380   RECT NewClientRect;
381   HRGN VisRgn = NULL;
382   ULONG WvrFlags = 0;
383
384   /* FIXME: Get current active window from active queue. */
385
386   /* Check if the window is for a desktop. */
387   if (Wnd == PsGetWin32Thread()->Desktop->DesktopWindow)
388     {
389       return(FALSE);
390     }
391
392   Status = 
393     ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
394                                Wnd,
395                                otWindow,
396                                (PVOID*)&Window);
397   if (!NT_SUCCESS(Status))
398     {
399       return(FALSE);
400     }
401   
402   /* Fix up the flags. */
403   if (Window->Style & WS_VISIBLE)
404     {
405       flags &= ~SWP_SHOWWINDOW;
406     }
407   else 
408     {
409       if (!(flags & SWP_SHOWWINDOW))
410         {
411           flags |= SWP_NOREDRAW;
412         }
413       flags &= ~SWP_HIDEWINDOW;
414     }
415
416   cx = max(cx, 0);
417   cy = max(cy, 0);
418
419   if ((Window->WindowRect.right - Window->WindowRect.left) == cx &&
420       (Window->WindowRect.bottom - Window->WindowRect.top) == cy)
421     {
422       flags |= SWP_NOSIZE;
423     }
424   if (Window->WindowRect.left == x && Window->WindowRect.top == y)
425     {
426       flags |= SWP_NOMOVE;
427     }
428   if (FALSE /* FIXME: Check if the window if already active. */)
429     {
430       flags |= SWP_NOACTIVATE;
431     }
432   else if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
433     {
434       if (!(flags & SWP_NOACTIVATE))
435         {
436           flags &= ~SWP_NOZORDER;
437           WndInsertAfter = HWND_TOP;
438         }
439     }
440
441   if (WndInsertAfter == HWND_TOPMOST || WndInsertAfter == HWND_NOTOPMOST)
442     {
443       WndInsertAfter = HWND_TOP;
444     }
445
446   if (WndInsertAfter != HWND_TOP && WndInsertAfter != HWND_BOTTOM)
447     {
448       /* FIXME: Find the window to insert after. */
449     }
450
451   WinPos.hwnd = Wnd;
452   WinPos.hwndInsertAfter = WndInsertAfter;
453   WinPos.x = x;
454   WinPos.y = y;
455   WinPos.cx = cx;
456   WinPos.cy = cy;
457   WinPos.flags = flags;
458
459   WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
460
461   if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
462       SWP_NOZORDER)
463     {
464       /* FIXME: SWP_DoOwnedPopups. */
465     }
466   
467   /* FIXME: Adjust flags based on WndInsertAfter */
468
469   if ((!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
470        WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | 
471                        SWP_HIDEWINDOW | SWP_FRAMECHANGED)) != 
472       (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
473     {
474       if (Window->Style & WS_CLIPCHILDREN)
475         {
476           VisRgn = DceGetVisRgn(Wnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
477         }
478       else
479         {
480           VisRgn = DceGetVisRgn(Wnd, DCX_WINDOW, 0, 0);
481         }
482     }
483
484   WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect,
485                                 &NewClientRect);
486
487   /* FIXME: Relink windows. */
488
489   /* FIXME: Reset active DCEs */
490
491   /* FIXME: Check for redrawing the whole client rect. */
492
493   if (WinPos.flags & SWP_SHOWWINDOW)
494     {
495       Window->Style |= WS_VISIBLE;
496       flags |= SWP_EX_PAINTSELF;
497       VisRgn = 1;
498     }
499   else
500     {
501       /* FIXME: Move the window bits */
502     }
503
504   if (WinPos.flags & SWP_HIDEWINDOW)
505     {
506       Window->Style &= ~WS_VISIBLE;
507     }
508
509   /* FIXME: Hide or show the claret */
510
511   if (VisRgn)
512     {
513       if (!(WinPos.flags & SWP_NOREDRAW))
514         {
515           if (flags & SWP_EX_PAINTSELF)
516             {
517               PaintRedrawWindow(Window->Self, NULL,
518                                 (VisRgn == 1) ? 0 : VisRgn,
519                                 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
520                                 RDW_ALLCHILDREN, 
521                                 RDW_EX_XYWINDOW | RDW_EX_USEHRGN);
522             }
523           else
524             {
525               PaintRedrawWindow(Window->Self, NULL,
526                                 (VisRgn == 1) ? 0 : VisRgn,
527                                 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN,
528                                 RDW_EX_USEHRGN);
529             }
530           /* FIXME: Redraw the window parent. */
531         }
532       /* FIXME: Delete VisRgn */
533     }
534
535   if (!(flags & SWP_NOACTIVATE))
536     {
537       WinPosChangeActiveWindow(WinPos.hwnd, FALSE);
538     }
539
540   /* FIXME: Check some conditions before doing this. */
541   NtUserSendMessage(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM)&WinPos);
542
543   ObmDereferenceObject(Window);
544   return(TRUE);
545 }
546
547 LRESULT
548 WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect)
549 {
550   *ClientRect = *WindowRect;
551   return(W32kSendNCCALCSIZEMessage(Wnd, FALSE, ClientRect, NULL));
552 }
553
554 BOOLEAN
555 WinPosShowWindow(HWND Wnd, INT Cmd)
556 {
557   BOOLEAN WasVisible;
558   PWINDOW_OBJECT Window;
559   NTSTATUS Status;
560   UINT Swp = 0;
561   RECT NewPos;
562   BOOLEAN ShowFlag;
563
564   Status = 
565     ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
566                                Wnd,
567                                otWindow,
568                                (PVOID*)&Window);
569   if (!NT_SUCCESS(Status))
570     {
571       return(FALSE);
572     }
573   
574   WasVisible = (Window->Style & WS_VISIBLE) != 0;
575
576   switch (Cmd)
577     {
578     case SW_HIDE:
579       {
580         if (!WasVisible)
581           {
582             ObmDereferenceObject(Window);
583             return(FALSE);
584           }
585         Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE |
586           SWP_NOZORDER;
587         break;
588       }
589
590     case SW_SHOWMINNOACTIVE:
591       Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
592       /* Fall through. */
593     case SW_SHOWMINIMIZED:
594       Swp |= SWP_SHOWWINDOW;
595       /* Fall through. */
596     case SW_MINIMIZE:
597       {
598         Swp |= SWP_FRAMECHANGED;
599         if (!(Window->Style & WS_MINIMIZE))
600           {
601             Swp |= WinPosMinMaximize(Window, SW_MINIMIZE, &NewPos);
602           }
603         else
604           {
605             Swp |= SWP_NOSIZE | SWP_NOMOVE;
606           }
607         break;
608       }
609
610     case SW_SHOWMAXIMIZED:
611       {
612         Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
613         if (!(Window->Style & WS_MAXIMIZE))
614           {
615             Swp |= WinPosMinMaximize(Window, SW_MAXIMIZE, &NewPos);
616           }
617         else
618           {
619             Swp |= SWP_NOSIZE | SWP_NOMOVE;
620           }
621         break;
622       }
623
624     case SW_SHOWNA:
625       Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
626       /* Fall through. */
627     case SW_SHOW:
628       Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
629       /* Don't activate the topmost window. */
630       break;
631
632     case SW_SHOWNOACTIVATE:
633       Swp |= SWP_NOZORDER;
634       /* Fall through. */
635     case SW_SHOWNORMAL:
636     case SW_SHOWDEFAULT:
637     case SW_RESTORE:
638       Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
639       if (Window->Style & (WS_MINIMIZE | WS_MAXIMIZE))
640         {
641           Swp |= WinPosMinMaximize(Window, SW_RESTORE, &NewPos);         
642         }
643       else
644         {
645           Swp |= SWP_NOSIZE | SWP_NOMOVE;
646         }
647       break;
648     }
649
650   ShowFlag = (Cmd != SW_HIDE);
651   if (ShowFlag != WasVisible)
652     {
653       NtUserSendMessage(Wnd, WM_SHOWWINDOW, ShowFlag, 0);
654       /* 
655        * FIXME: Need to check the window wasn't destroyed during the 
656        * window procedure. 
657        */
658     }
659
660   if (Window->Style & WS_CHILD &&
661       !W32kIsWindowVisible(Window->Parent->Self) &&
662       (Swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE))
663     {
664       if (Cmd == SW_HIDE)
665         {
666           Window->Style &= ~WS_VISIBLE;
667         }
668       else
669         {
670           Window->Style |= WS_VISIBLE;
671         }
672     }
673   else
674     {
675       if (Window->Style & WS_CHILD &&
676           !(Window->ExStyle & WS_EX_MDICHILD))
677         {
678           Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
679         }
680       if (!(Swp & MINMAX_NOSWP))
681         {
682           WinPosSetWindowPos(Wnd, HWND_TOP, NewPos.left, NewPos.top,
683                              NewPos.right, NewPos.bottom, LOWORD(Swp));
684           if (Cmd == SW_HIDE)
685             {
686               /* Hide the window. */
687               if (Wnd == W32kGetActiveWindow())
688                 {
689                   WinPosActivateOtherWindow(Window);
690                 }
691               /* Revert focus to parent. */
692               if (Wnd == W32kGetFocusWindow() ||
693                   W32kIsChildWindow(Wnd, W32kGetFocusWindow()))
694                 {
695                   W32kSetFocusWindow(Window->Parent->Self);
696                 }
697             }
698         }
699       /* FIXME: Check for window destruction. */
700       /* Show title for minimized windows. */
701       if (Window->Style & WS_MINIMIZE)
702         {
703           WinPosShowIconTitle(Window, TRUE);
704         }
705     }
706
707   if (Window->Flags & WINDOWOBJECT_NEED_SIZE)
708     {
709       WPARAM wParam = SIZE_RESTORED;
710
711       Window->Flags &= ~WINDOWOBJECT_NEED_SIZE;
712       if (Window->Style & WS_MAXIMIZE)
713         {
714           wParam = SIZE_MAXIMIZED;
715         }
716       else if (Window->Style & WS_MINIMIZE)
717         {
718           wParam = SIZE_MINIMIZED;
719         }
720
721       NtUserSendMessage(Wnd, WM_SIZE, wParam,
722                         MAKELONG(Window->ClientRect.right - 
723                                  Window->ClientRect.left,
724                                  Window->ClientRect.bottom -
725                                  Window->ClientRect.top));
726       NtUserSendMessage(Wnd, WM_MOVE, 0,
727                         MAKELONG(Window->ClientRect.left,
728                                  Window->ClientRect.top));
729     }
730   ObmDereferenceObject(Window);
731   return(WasVisible);
732 }
733
734 BOOL STATIC
735 WinPosPtInWindow(PWINDOW_OBJECT Window, POINT Point)
736 {
737   return(Point.x >= Window->WindowRect.left &&
738          Point.x < Window->WindowRect.right &&
739          Point.y >= Window->WindowRect.top &&
740          Point.y < Window->WindowRect.bottom);
741 }
742
743 USHORT STATIC
744 WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, POINT Point,
745                      PWINDOW_OBJECT* Window)
746 {
747   PLIST_ENTRY CurrentEntry;
748   PWINDOW_OBJECT Current;
749
750   CurrentEntry = ScopeWin->ChildrenListHead.Flink;
751   while (CurrentEntry != &ScopeWin->ChildrenListHead)
752     {
753       Current = 
754         CONTAINING_RECORD(CurrentEntry, WINDOW_OBJECT, SiblingListEntry);
755
756       if (Current->Style & WS_VISIBLE &&
757           ((!(Current->Style & WS_DISABLED)) ||
758            (Current->Style & (WS_CHILD | WS_POPUP)) != WS_CHILD) &&
759           WinPosPtInWindow(Current, Point))
760         {
761           *Window = Current;
762           if (Current->Style & WS_DISABLED)
763             {
764               return(HTERROR);
765             }
766           if (Current->Style & WS_MINIMIZE)
767             {
768               return(HTCAPTION);
769             }
770           if (Point.x >= Current->ClientRect.left &&
771               Point.x < Current->ClientRect.right &&
772               Point.y >= Current->ClientRect.top &&
773               Point.y < Current->ClientRect.bottom)
774             {
775               Point.x -= Current->ClientRect.left;
776               Point.y -= Current->ClientRect.top;
777
778               return(WinPosSearchChildren(Current, Point, Window));
779             }
780           return(0);
781         }
782       CurrentEntry = CurrentEntry->Flink;
783     }
784   return(0);
785 }
786
787 USHORT
788 WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint, 
789                       PWINDOW_OBJECT* Window)
790 {
791   HWND DesktopWindowHandle;
792   PWINDOW_OBJECT DesktopWindow;
793   POINT Point = WinPoint;
794   USHORT HitTest;
795   
796   *Window = NULL;
797
798   if (ScopeWin->Style & WS_DISABLED)
799     {
800       return(HTERROR);
801     }
802
803   /* Translate the point to the space of the scope window. */
804   DesktopWindowHandle = W32kGetDesktopWindow();
805   DesktopWindow = W32kGetWindowObject(DesktopWindowHandle);
806   Point.x += ScopeWin->ClientRect.left - DesktopWindow->ClientRect.left;
807   Point.y += ScopeWin->ClientRect.top - DesktopWindow->ClientRect.top;
808   W32kReleaseWindowObject(DesktopWindow);
809
810   HitTest = WinPosSearchChildren(ScopeWin, Point, Window);
811   if (HitTest != 0)
812     {
813       return(HitTest);
814     }
815
816   if ((*Window) == NULL)
817     {
818       return(HTNOWHERE);
819     }
820   if ((*Window)->MessageQueue == PsGetWin32Thread()->MessageQueue)
821     {
822       HitTest = W32kSendMessage((*Window)->Self, WM_NCHITTEST, 0,
823                                 MAKELONG(Point.x, Point.y), FALSE);
824       /* FIXME: Check for HTTRANSPARENT here. */
825     }
826   else
827     {
828       HitTest = HTCLIENT;
829     }
830
831   return(HitTest);
832 }