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