reverted SetWindowPos change, causes display errors in other windows...
[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.16 2003/07/29 05:37:23 rcampbell 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 hWnd, BOOL MouseMsg)
350 {
351 PWINDOW_OBJECT WindowObject;
352
353 WindowObject = W32kGetWindowObject(hWnd);
354 if (WindowObject == NULL)
355 {
356 return FALSE;
357 }
358
359 NtUserSendMessage(hWnd,
360 WM_ACTIVATE,
361 MAKELONG(MouseMsg ? WA_CLICKACTIVE : WA_CLICKACTIVE,
362 (WindowObject->Style & WS_MINIMIZE) ? 1 : 0),
363 (LPARAM)W32kGetDesktopWindow()); /* FIXME: Previous active window */
364
365 W32kReleaseWindowObject(WindowObject);
366
367 return TRUE;
368 }
369
370 LONG STATIC STDCALL
371 WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos,
372 RECT* WindowRect, RECT* ClientRect)
373 {
374 return 0; /* FIXME: Calculate non client size */
375 }
376
377 BOOL STDCALL
378 WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject,
379 PWINDOWPOS WinPos,
380 PRECT WindowRect,
381 PRECT ClientRect)
382 {
383 if (!(WinPos->flags & SWP_NOSENDCHANGING))
384 {
385 W32kSendWINDOWPOSCHANGINGMessage(WindowObject->Self, WinPos);
386 }
387
388 *WindowRect = WindowObject->WindowRect;
389 *ClientRect =
390 (WindowObject->Style & WS_MINIMIZE) ? WindowObject->WindowRect :
391 WindowObject->ClientRect;
392
393 /* Temp fix for WineMine */
394
395 if (!(WinPos->flags & SWP_NOSIZE))
396 {
397 WindowRect->right = WindowRect->left + WinPos->cx;
398 WindowRect->bottom = WindowRect->top + WinPos->cy;
399 }
400
401 if (!(WinPos->flags & SWP_NOMOVE))
402 {
403 WindowRect->left = WinPos->x;
404 WindowRect->top = WinPos->y;
405 WindowRect->right += WinPos->x - WindowObject->WindowRect.left;
406 WindowRect->bottom += WinPos->y - WindowObject->WindowRect.top;
407 }
408
409 if (!(WinPos->flags & SWP_NOSIZE) || !(WinPos->flags & SWP_NOMOVE))
410 {
411 WinPosGetNonClientSize(WindowObject->Self, WindowRect, ClientRect);
412 }
413
414 WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
415 return(TRUE);
416 }
417
418 BOOLEAN STDCALL
419 WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
420 INT cy, UINT flags)
421 {
422 PWINDOW_OBJECT Window;
423 NTSTATUS Status;
424 WINDOWPOS WinPos;
425 RECT NewWindowRect;
426 RECT NewClientRect;
427 HRGN VisRgn = NULL;
428 ULONG WvrFlags = 0;
429
430 /* FIXME: Get current active window from active queue. */
431
432 /* Check if the window is for a desktop. */
433 if (Wnd == PsGetWin32Thread()->Desktop->DesktopWindow)
434 {
435 return(FALSE);
436 }
437
438 Status =
439 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
440 Wnd,
441 otWindow,
442 (PVOID*)&Window);
443 if (!NT_SUCCESS(Status))
444 {
445 return(FALSE);
446 }
447
448 /* Fix up the flags. */
449 if (Window->Style & WS_VISIBLE)
450 {
451 flags &= ~SWP_SHOWWINDOW;
452 }
453 else
454 {
455 if (!(flags & SWP_SHOWWINDOW))
456 {
457 flags |= SWP_NOREDRAW;
458 }
459 flags &= ~SWP_HIDEWINDOW;
460 }
461
462 cx = max(cx, 0);
463 cy = max(cy, 0);
464
465 if ((Window->WindowRect.right - Window->WindowRect.left) == cx &&
466 (Window->WindowRect.bottom - Window->WindowRect.top) == cy)
467 {
468 flags |= SWP_NOSIZE;
469 }
470 if (Window->WindowRect.left == x && Window->WindowRect.top == y)
471 {
472 flags |= SWP_NOMOVE;
473 }
474 if (FALSE /* FIXME: Check if the window if already active. */)
475 {
476 flags |= SWP_NOACTIVATE;
477 }
478 else if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
479 {
480 if (!(flags & SWP_NOACTIVATE))
481 {
482 flags &= ~SWP_NOZORDER;
483 WndInsertAfter = HWND_TOP;
484 }
485 }
486
487 if (WndInsertAfter == HWND_TOPMOST || WndInsertAfter == HWND_NOTOPMOST)
488 {
489 WndInsertAfter = HWND_TOP;
490 }
491
492 if (WndInsertAfter != HWND_TOP && WndInsertAfter != HWND_BOTTOM)
493 {
494 /* FIXME: Find the window to insert after. */
495 }
496
497 WinPos.hwnd = Wnd;
498 WinPos.hwndInsertAfter = WndInsertAfter;
499 WinPos.x = x;
500 WinPos.y = y;
501 WinPos.cx = cx;
502 WinPos.cy = cy;
503 WinPos.flags = flags;
504
505 WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
506
507 if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
508 SWP_NOZORDER)
509 {
510 /* FIXME: SWP_DoOwnedPopups. */
511 }
512
513 /* FIXME: Adjust flags based on WndInsertAfter */
514
515 if ((!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
516 WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
517 SWP_HIDEWINDOW | SWP_FRAMECHANGED)) !=
518 (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
519 {
520 if (Window->Style & WS_CLIPCHILDREN)
521 {
522 VisRgn = DceGetVisRgn(Wnd, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
523 }
524 else
525 {
526 VisRgn = DceGetVisRgn(Wnd, DCX_WINDOW, 0, 0);
527 }
528 }
529
530 WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect,
531 &NewClientRect);
532
533 /* FIXME: Relink windows. */
534
535 /* FIXME: Reset active DCEs */
536
537 /* FIXME: Check for redrawing the whole client rect. */
538
539 if (WinPos.flags & SWP_SHOWWINDOW)
540 {
541 Window->Style |= WS_VISIBLE;
542 flags |= SWP_EX_PAINTSELF;
543 VisRgn = (HRGN) 1;
544 }
545 else
546 {
547 /* FIXME: Move the window bits */
548 }
549
550 Window->WindowRect = NewWindowRect;
551 Window->ClientRect = NewClientRect;
552
553 if (WinPos.flags & SWP_HIDEWINDOW)
554 {
555 Window->Style &= ~WS_VISIBLE;
556 }
557
558 /* FIXME: Hide or show the claret */
559
560 if (VisRgn)
561 {
562 if (!(WinPos.flags & SWP_NOREDRAW))
563 {
564 if (flags & SWP_EX_PAINTSELF)
565 {
566 PaintRedrawWindow(Window->Self, NULL,
567 (VisRgn == (HRGN) 1) ? 0 : VisRgn,
568 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
569 RDW_ALLCHILDREN | RDW_ERASENOW,
570 RDW_EX_XYWINDOW | RDW_EX_USEHRGN);
571 }
572 else
573 {
574 PaintRedrawWindow(Window->Self, NULL,
575 (VisRgn == (HRGN) 1) ? 0 : VisRgn,
576 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN |
577 RDW_ERASENOW,
578 RDW_EX_USEHRGN);
579 }
580 /* FIXME: Redraw the window parent. */
581 }
582 /* FIXME: Delete VisRgn */
583 }
584
585 if (!(flags & SWP_NOACTIVATE))
586 {
587 WinPosChangeActiveWindow(WinPos.hwnd, FALSE);
588 }
589
590 /* FIXME: Check some conditions before doing this. */
591 W32kSendWINDOWPOSCHANGEDMessage(Window->Self, &WinPos);
592
593 ObmDereferenceObject(Window);
594 return(TRUE);
595 }
596
597 LRESULT STDCALL
598 WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect)
599 {
600 *ClientRect = *WindowRect;
601 return(W32kSendNCCALCSIZEMessage(Wnd, FALSE, ClientRect, NULL));
602 }
603
604 BOOLEAN FASTCALL
605 WinPosShowWindow(HWND Wnd, INT Cmd)
606 {
607 BOOLEAN WasVisible;
608 PWINDOW_OBJECT Window;
609 NTSTATUS Status;
610 UINT Swp = 0;
611 RECT NewPos;
612 BOOLEAN ShowFlag;
613
614 Status =
615 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
616 Wnd,
617 otWindow,
618 (PVOID*)&Window);
619 if (!NT_SUCCESS(Status))
620 {
621 return(FALSE);
622 }
623
624 WasVisible = (Window->Style & WS_VISIBLE) != 0;
625
626 switch (Cmd)
627 {
628 case SW_HIDE:
629 {
630 if (!WasVisible)
631 {
632 ObmDereferenceObject(Window);
633 return(FALSE);
634 }
635 Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE |
636 SWP_NOZORDER;
637 break;
638 }
639
640 case SW_SHOWMINNOACTIVE:
641 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
642 /* Fall through. */
643 case SW_SHOWMINIMIZED:
644 Swp |= SWP_SHOWWINDOW;
645 /* Fall through. */
646 case SW_MINIMIZE:
647 {
648 Swp |= SWP_FRAMECHANGED;
649 if (!(Window->Style & WS_MINIMIZE))
650 {
651 Swp |= WinPosMinMaximize(Window, SW_MINIMIZE, &NewPos);
652 }
653 else
654 {
655 Swp |= SWP_NOSIZE | SWP_NOMOVE;
656 }
657 break;
658 }
659
660 case SW_SHOWMAXIMIZED:
661 {
662 Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
663 if (!(Window->Style & WS_MAXIMIZE))
664 {
665 Swp |= WinPosMinMaximize(Window, SW_MAXIMIZE, &NewPos);
666 }
667 else
668 {
669 Swp |= SWP_NOSIZE | SWP_NOMOVE;
670 }
671 break;
672 }
673
674 case SW_SHOWNA:
675 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
676 /* Fall through. */
677 case SW_SHOW:
678 Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
679 /* Don't activate the topmost window. */
680 break;
681
682 case SW_SHOWNOACTIVATE:
683 Swp |= SWP_NOZORDER;
684 /* Fall through. */
685 case SW_SHOWNORMAL:
686 case SW_SHOWDEFAULT:
687 case SW_RESTORE:
688 Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
689 if (Window->Style & (WS_MINIMIZE | WS_MAXIMIZE))
690 {
691 Swp |= WinPosMinMaximize(Window, SW_RESTORE, &NewPos);
692 }
693 else
694 {
695 Swp |= SWP_NOSIZE | SWP_NOMOVE;
696 }
697 break;
698 }
699
700 ShowFlag = (Cmd != SW_HIDE);
701 if (ShowFlag != WasVisible)
702 {
703 NtUserSendMessage(Wnd, WM_SHOWWINDOW, ShowFlag, 0);
704 /*
705 * FIXME: Need to check the window wasn't destroyed during the
706 * window procedure.
707 */
708 }
709
710 if (Window->Style & WS_CHILD &&
711 !W32kIsWindowVisible(Window->Parent->Self) &&
712 (Swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE))
713 {
714 if (Cmd == SW_HIDE)
715 {
716 Window->Style &= ~WS_VISIBLE;
717 }
718 else
719 {
720 Window->Style |= WS_VISIBLE;
721 }
722 }
723 else
724 {
725 if (Window->Style & WS_CHILD &&
726 !(Window->ExStyle & WS_EX_MDICHILD))
727 {
728 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
729 }
730 if (!(Swp & MINMAX_NOSWP))
731 {
732 WinPosSetWindowPos(Wnd, HWND_TOP, NewPos.left, NewPos.top,
733 NewPos.right, NewPos.bottom, LOWORD(Swp));
734 if (Cmd == SW_HIDE)
735 {
736 /* Hide the window. */
737 if (Wnd == W32kGetActiveWindow())
738 {
739 WinPosActivateOtherWindow(Window);
740 }
741 /* Revert focus to parent. */
742 if (Wnd == W32kGetFocusWindow() ||
743 W32kIsChildWindow(Wnd, W32kGetFocusWindow()))
744 {
745 W32kSetFocusWindow(Window->Parent->Self);
746 }
747 }
748 }
749 /* FIXME: Check for window destruction. */
750 /* Show title for minimized windows. */
751 if (Window->Style & WS_MINIMIZE)
752 {
753 WinPosShowIconTitle(Window, TRUE);
754 }
755 }
756
757 if (Window->Flags & WINDOWOBJECT_NEED_SIZE)
758 {
759 WPARAM wParam = SIZE_RESTORED;
760
761 Window->Flags &= ~WINDOWOBJECT_NEED_SIZE;
762 if (Window->Style & WS_MAXIMIZE)
763 {
764 wParam = SIZE_MAXIMIZED;
765 }
766 else if (Window->Style & WS_MINIMIZE)
767 {
768 wParam = SIZE_MINIMIZED;
769 }
770
771 NtUserSendMessage(Wnd, WM_SIZE, wParam,
772 MAKELONG(Window->ClientRect.right -
773 Window->ClientRect.left,
774 Window->ClientRect.bottom -
775 Window->ClientRect.top));
776 NtUserSendMessage(Wnd, WM_MOVE, 0,
777 MAKELONG(Window->ClientRect.left,
778 Window->ClientRect.top));
779 }
780
781 /* Activate the window if activation is not requested and the window is not minimized */
782 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->Style & WS_MINIMIZE))
783 {
784 WinPosChangeActiveWindow(Wnd, FALSE);
785 }
786
787 ObmDereferenceObject(Window);
788 return(WasVisible);
789 }
790
791 BOOL STATIC FASTCALL
792 WinPosPtInWindow(PWINDOW_OBJECT Window, POINT Point)
793 {
794 return(Point.x >= Window->WindowRect.left &&
795 Point.x < Window->WindowRect.right &&
796 Point.y >= Window->WindowRect.top &&
797 Point.y < Window->WindowRect.bottom);
798 }
799
800 USHORT STATIC STDCALL
801 WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, POINT Point,
802 PWINDOW_OBJECT* Window)
803 {
804 PLIST_ENTRY CurrentEntry;
805 PWINDOW_OBJECT Current;
806
807
808 ExAcquireFastMutexUnsafe(&ScopeWin->ChildrenListLock);
809 CurrentEntry = ScopeWin->ChildrenListHead.Flink;
810 while (CurrentEntry != &ScopeWin->ChildrenListHead)
811 {
812 Current =
813 CONTAINING_RECORD(CurrentEntry, WINDOW_OBJECT, SiblingListEntry);
814
815 if (Current->Style & WS_VISIBLE &&
816 ((!(Current->Style & WS_DISABLED)) ||
817 (Current->Style & (WS_CHILD | WS_POPUP)) != WS_CHILD) &&
818 WinPosPtInWindow(Current, Point))
819 {
820 *Window = Current;
821 if (Current->Style & WS_DISABLED)
822 {
823 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
824 return(HTERROR);
825 }
826 if (Current->Style & WS_MINIMIZE)
827 {
828 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
829 return(HTCAPTION);
830 }
831 if (Point.x >= Current->ClientRect.left &&
832 Point.x < Current->ClientRect.right &&
833 Point.y >= Current->ClientRect.top &&
834 Point.y < Current->ClientRect.bottom)
835 {
836 Point.x -= Current->ClientRect.left;
837 Point.y -= Current->ClientRect.top;
838
839 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
840 return(WinPosSearchChildren(Current, Point, Window));
841 }
842
843 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
844 return(0);
845 }
846 CurrentEntry = CurrentEntry->Flink;
847 }
848
849 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
850 return(0);
851 }
852
853 USHORT STDCALL
854 WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint,
855 PWINDOW_OBJECT* Window)
856 {
857 HWND DesktopWindowHandle;
858 PWINDOW_OBJECT DesktopWindow;
859 POINT Point = WinPoint;
860 USHORT HitTest;
861
862 *Window = NULL;
863
864 if (ScopeWin->Style & WS_DISABLED)
865 {
866 return(HTERROR);
867 }
868
869 /* Translate the point to the space of the scope window. */
870 DesktopWindowHandle = W32kGetDesktopWindow();
871 DesktopWindow = W32kGetWindowObject(DesktopWindowHandle);
872 Point.x += ScopeWin->ClientRect.left - DesktopWindow->ClientRect.left;
873 Point.y += ScopeWin->ClientRect.top - DesktopWindow->ClientRect.top;
874 W32kReleaseWindowObject(DesktopWindow);
875
876 HitTest = WinPosSearchChildren(ScopeWin, Point, Window);
877 if (HitTest != 0)
878 {
879 return(HitTest);
880 }
881
882 if ((*Window) == NULL)
883 {
884 return(HTNOWHERE);
885 }
886 if ((*Window)->MessageQueue == PsGetWin32Thread()->MessageQueue)
887 {
888 HitTest = W32kSendMessage((*Window)->Self, WM_NCHITTEST, 0,
889 MAKELONG(Point.x, Point.y), FALSE);
890 /* FIXME: Check for HTTRANSPARENT here. */
891 }
892 else
893 {
894 HitTest = HTCLIENT;
895 }
896
897 return(HitTest);
898 }
899
900 BOOL
901 WinPosSetActiveWindow(PWINDOW_OBJECT Window, BOOL Mouse, BOOL ChangeFocus)
902 {
903 PUSER_MESSAGE_QUEUE ActiveQueue;
904 HWND PrevActive;
905
906 ActiveQueue = W32kGetFocusMessageQueue();
907 if (ActiveQueue != NULL)
908 {
909 PrevActive = ActiveQueue->ActiveWindow;
910 }
911 else
912 {
913 PrevActive = NULL;
914 }
915
916 if (Window->Self == W32kGetActiveDesktop() || Window->Self == PrevActive)
917 {
918 return(FALSE);
919 }
920 if (PrevActive != NULL)
921 {
922 PWINDOW_OBJECT PrevActiveWindow = W32kGetWindowObject(PrevActive);
923 WORD Iconised = HIWORD(PrevActiveWindow->Style & WS_MINIMIZE);
924 if (!W32kSendMessage(PrevActive, WM_NCACTIVATE, FALSE, 0, TRUE))
925 {
926 /* FIXME: Check if the new window is system modal. */
927 return(FALSE);
928 }
929 W32kSendMessage(PrevActive,
930 WM_ACTIVATE,
931 MAKEWPARAM(WA_INACTIVE, Iconised),
932 (LPARAM)Window->Self,
933 TRUE);
934 /* FIXME: Check if anything changed while processing the message. */
935 W32kReleaseWindowObject(PrevActiveWindow);
936 }
937
938 if (Window != NULL)
939 {
940 Window->MessageQueue->ActiveWindow = Window->Self;
941 }
942 else if (ActiveQueue != NULL)
943 {
944 ActiveQueue->ActiveWindow = NULL;
945 }
946
947 /* FIXME: Send palette messages. */
948
949 /* FIXME: Redraw icon title of previously active window. */
950
951 /* FIXME: Bring the window to the top. */
952
953 /* FIXME: Send WM_ACTIVATEAPP */
954
955 W32kSetFocusMessageQueue(Window->MessageQueue);
956
957 /* FIXME: Send activate messages. */
958
959 /* FIXME: Change focus. */
960
961 /* FIXME: Redraw new window icon title. */
962
963 return(TRUE);
964 }
965
966 HWND STDCALL
967 NtUserGetActiveWindow(VOID)
968 {
969 PUSER_MESSAGE_QUEUE ActiveQueue;
970
971 ActiveQueue = W32kGetFocusMessageQueue();
972 if (ActiveQueue == NULL)
973 {
974 return(NULL);
975 }
976 return(ActiveQueue->ActiveWindow);
977 }
978
979 HWND STDCALL
980 NtUserSetActiveWindow(HWND hWnd)
981 {
982 PWINDOW_OBJECT Window;
983 PUSER_MESSAGE_QUEUE ThreadQueue;
984 HWND Prev;
985
986 Window = W32kGetWindowObject(hWnd);
987 if (Window == NULL || (Window->Style & (WS_DISABLED | WS_CHILD)))
988 {
989 W32kReleaseWindowObject(Window);
990 return(0);
991 }
992 ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
993 if (Window->MessageQueue != ThreadQueue)
994 {
995 W32kReleaseWindowObject(Window);
996 return(0);
997 }
998 Prev = Window->MessageQueue->ActiveWindow;
999 WinPosSetActiveWindow(Window, FALSE, FALSE);
1000 W32kReleaseWindowObject(Window);
1001 return(Prev);
1002 }
1003
1004
1005 /* EOF */