- Rewritten painting implementation (not complete yet, but better then the current).
[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.41 2003/11/18 20:49:39 navaraf 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 NtGdid
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 #include <include/vis.h>
46
47 #define NDEBUG
48 #include <debug.h>
49
50 /* GLOBALS *******************************************************************/
51
52 #define MINMAX_NOSWP (0x00010000)
53
54 #define SWP_EX_NOCOPY 0x0001
55 #define SWP_EX_PAINTSELF 0x0002
56
57 #define SWP_AGG_NOGEOMETRYCHANGE \
58 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
59 #define SWP_AGG_NOPOSCHANGE \
60 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
61 #define SWP_AGG_STATUSFLAGS \
62 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
63
64 ATOM AtomInternalPos = (ATOM) NULL;
65
66 /* FUNCTIONS *****************************************************************/
67
68 #define HAS_DLGFRAME(Style, ExStyle) \
69 (((ExStyle) & WS_EX_DLGMODALFRAME) || \
70 (((Style) & WS_DLGFRAME) && !((Style) & WS_BORDER)))
71
72 #define HAS_THICKFRAME(Style, ExStyle) \
73 (((Style) & WS_THICKFRAME) && \
74 !((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)
75
76 VOID FASTCALL
77 WinPosSetupInternalPos(VOID)
78 {
79 AtomInternalPos = NtAddAtom(L"SysIP", (ATOM*)(PULONG)&AtomInternalPos);
80 }
81
82 BOOL STDCALL
83 NtUserGetClientOrigin(HWND hWnd, LPPOINT Point)
84 {
85 PWINDOW_OBJECT WindowObject;
86
87 WindowObject = IntGetWindowObject(hWnd);
88 if (WindowObject == NULL)
89 {
90 Point->x = Point->y = 0;
91 return(TRUE);
92 }
93 Point->x = WindowObject->ClientRect.left;
94 Point->y = WindowObject->ClientRect.top;
95 return(TRUE);
96 }
97
98 /*******************************************************************
99 * can_activate_window
100 *
101 * Check if we can activate the specified window.
102 */
103 static BOOL FASTCALL
104 can_activate_window(HWND hwnd)
105 {
106 LONG style;
107
108 if (! hwnd)
109 {
110 return FALSE;
111 }
112 style = NtUserGetWindowLong(hwnd, GWL_STYLE, FALSE);
113 if (! (style & WS_VISIBLE))
114 {
115 return FALSE;
116 }
117 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD)
118 {
119 return FALSE;
120 }
121 return ! (style & WS_DISABLED);
122 }
123
124 /*******************************************************************
125 * WinPosActivateOtherWindow
126 *
127 * Activates window other than pWnd.
128 */
129 void FASTCALL
130 WinPosActivateOtherWindow(PWINDOW_OBJECT Window)
131 {
132 HWND hwndTo;
133 #if 0
134 HWND fg;
135 #endif
136
137 if ((NtUserGetWindowLong(Window->Self, GWL_STYLE, FALSE) & WS_POPUP)
138 && (hwndTo = NtUserGetWindow(Window->Self, GW_OWNER)))
139 {
140 hwndTo = NtUserGetAncestor(hwndTo, GA_ROOT);
141 if (can_activate_window(hwndTo)) goto done;
142 }
143
144 hwndTo = Window->Self;
145 for (;;)
146 {
147 if (!(hwndTo = NtUserGetWindow(hwndTo, GW_HWNDNEXT)))
148 {
149 break;
150 }
151 if (can_activate_window(hwndTo))
152 {
153 break;
154 }
155 }
156
157 done:
158 #ifdef TODO
159 fg = NtUserGetForegroundWindow();
160 /* TRACE("win = %p fg = %p\n", hwndTo, fg); */
161 if (! fg || (hwnd == fg))
162 {
163 if (NtUserSetForegroundWindow(hwndTo))
164 {
165 return;
166 }
167 }
168 #endif
169
170 if (! NtUserSetActiveWindow(hwndTo))
171 {
172 NtUserSetActiveWindow(NULL);
173 }
174 }
175
176 POINT STATIC FASTCALL
177 WinPosFindIconPos(HWND hWnd, POINT Pos)
178 {
179 POINT point;
180 //FIXME
181 return point;
182 }
183
184 HWND STATIC FASTCALL
185 WinPosNtGdiIconTitle(PWINDOW_OBJECT WindowObject)
186 {
187 return(NULL);
188 }
189
190 BOOL STATIC FASTCALL
191 WinPosShowIconTitle(PWINDOW_OBJECT WindowObject, BOOL Show)
192 {
193 PINTERNALPOS InternalPos = (PINTERNALPOS)IntGetProp(WindowObject, AtomInternalPos);
194 PWINDOW_OBJECT IconWindow;
195 NTSTATUS Status;
196
197 if (InternalPos)
198 {
199 HWND hWnd = InternalPos->IconTitle;
200
201 if (hWnd == NULL)
202 {
203 hWnd = WinPosNtGdiIconTitle(WindowObject);
204 }
205 if (Show)
206 {
207 Status =
208 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->
209 HandleTable,
210 hWnd,
211 otWindow,
212 (PVOID*)&IconWindow);
213 if (NT_SUCCESS(Status))
214 {
215 if (!(IconWindow->Style & WS_VISIBLE))
216 {
217 NtUserSendMessage(hWnd, WM_SHOWWINDOW, TRUE, 0);
218 WinPosSetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE |
219 SWP_NOMOVE | SWP_NOACTIVATE |
220 SWP_NOZORDER | SWP_SHOWWINDOW);
221 }
222 ObmDereferenceObject(IconWindow);
223 }
224 }
225 else
226 {
227 WinPosShowWindow(hWnd, SW_HIDE);
228 }
229 }
230 return(FALSE);
231 }
232
233 PINTERNALPOS STATIC STDCALL
234 WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT pt, PRECT RestoreRect)
235 {
236 PINTERNALPOS InternalPos = (PINTERNALPOS)IntGetProp(WindowObject, AtomInternalPos);
237 if (InternalPos == NULL)
238 {
239 InternalPos =
240 ExAllocatePool(NonPagedPool, sizeof(INTERNALPOS));
241 IntSetProp(WindowObject, AtomInternalPos, InternalPos);
242 InternalPos->IconTitle = 0;
243 InternalPos->NormalRect = WindowObject->WindowRect;
244 InternalPos->IconPos.x = InternalPos->MaxPos.x = 0xFFFFFFFF;
245 InternalPos->IconPos.y = InternalPos->MaxPos.y = 0xFFFFFFFF;
246 }
247 if (WindowObject->Style & WS_MINIMIZE)
248 {
249 InternalPos->IconPos = pt;
250 }
251 else if (WindowObject->Style & WS_MAXIMIZE)
252 {
253 InternalPos->MaxPos = pt;
254 }
255 else if (RestoreRect != NULL)
256 {
257 InternalPos->NormalRect = *RestoreRect;
258 }
259 return(InternalPos);
260 }
261
262 UINT STDCALL
263 WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
264 {
265 POINT Size;
266 PINTERNALPOS InternalPos;
267 UINT SwpFlags = 0;
268
269 Size.x = WindowObject->WindowRect.left;
270 Size.y = WindowObject->WindowRect.top;
271 InternalPos = WinPosInitInternalPos(WindowObject, Size,
272 &WindowObject->WindowRect);
273
274 if (InternalPos)
275 {
276 if (WindowObject->Style & WS_MINIMIZE)
277 {
278 if (!NtUserSendMessage(WindowObject->Self, WM_QUERYOPEN, 0, 0))
279 {
280 return(SWP_NOSIZE | SWP_NOMOVE);
281 }
282 SwpFlags |= SWP_NOCOPYBITS;
283 }
284 switch (ShowFlag)
285 {
286 case SW_MINIMIZE:
287 {
288 if (WindowObject->Style & WS_MAXIMIZE)
289 {
290 WindowObject->Flags |= WINDOWOBJECT_RESTOREMAX;
291 WindowObject->Style &= ~WS_MAXIMIZE;
292 }
293 else
294 {
295 WindowObject->Style &= ~WINDOWOBJECT_RESTOREMAX;
296 }
297 WindowObject->Style |= WS_MINIMIZE;
298 InternalPos->IconPos = WinPosFindIconPos(WindowObject,
299 InternalPos->IconPos);
300 NtGdiSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
301 NtUserGetSystemMetrics(SM_CXICON),
302 NtUserGetSystemMetrics(SM_CYICON));
303 SwpFlags |= SWP_NOCOPYBITS;
304 break;
305 }
306
307 case SW_MAXIMIZE:
308 {
309 WinPosGetMinMaxInfo(WindowObject, &Size, &InternalPos->MaxPos,
310 NULL, NULL);
311 if (WindowObject->Style & WS_MINIMIZE)
312 {
313 WinPosShowIconTitle(WindowObject, FALSE);
314 WindowObject->Style &= ~WS_MINIMIZE;
315 }
316 WindowObject->Style |= WS_MINIMIZE;
317 NtGdiSetRect(NewPos, InternalPos->MaxPos.x, InternalPos->MaxPos.y,
318 Size.x, Size.y);
319 break;
320 }
321
322 case SW_RESTORE:
323 {
324 if (WindowObject->Style & WS_MINIMIZE)
325 {
326 WindowObject->Style &= ~WS_MINIMIZE;
327 WinPosShowIconTitle(WindowObject, FALSE);
328 if (WindowObject->Flags & WINDOWOBJECT_RESTOREMAX)
329 {
330 WinPosGetMinMaxInfo(WindowObject, &Size,
331 &InternalPos->MaxPos, NULL, NULL);
332 WindowObject->Style |= WS_MAXIMIZE;
333 NtGdiSetRect(NewPos, InternalPos->MaxPos.x,
334 InternalPos->MaxPos.y, Size.x, Size.y);
335 break;
336 }
337 }
338 else
339 {
340 if (!(WindowObject->Style & WS_MAXIMIZE))
341 {
342 return(-1);
343 }
344 else
345 {
346 WindowObject->Style &= ~WS_MAXIMIZE;
347 }
348 *NewPos = InternalPos->NormalRect;
349 NewPos->right -= NewPos->left;
350 NewPos->bottom -= NewPos->top;
351 break;
352 }
353 }
354 }
355 }
356 else
357 {
358 SwpFlags |= SWP_NOSIZE | SWP_NOMOVE;
359 }
360 return(SwpFlags);
361 }
362
363 UINT STDCALL
364 WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
365 POINT* MinTrack, POINT* MaxTrack)
366 {
367 MINMAXINFO MinMax;
368 INT XInc, YInc;
369 INTERNALPOS* Pos;
370
371 /* Get default values. */
372 MinMax.ptMaxSize.x = NtUserGetSystemMetrics(SM_CXSCREEN);
373 MinMax.ptMaxSize.y = NtUserGetSystemMetrics(SM_CYSCREEN);
374 MinMax.ptMinTrackSize.x = NtUserGetSystemMetrics(SM_CXMINTRACK);
375 MinMax.ptMinTrackSize.y = NtUserGetSystemMetrics(SM_CYMINTRACK);
376 MinMax.ptMaxTrackSize.x = NtUserGetSystemMetrics(SM_CXSCREEN);
377 MinMax.ptMaxTrackSize.y = NtUserGetSystemMetrics(SM_CYSCREEN);
378
379 if (HAS_DLGFRAME(Window->Style, Window->ExStyle))
380 {
381 XInc = NtUserGetSystemMetrics(SM_CXDLGFRAME);
382 YInc = NtUserGetSystemMetrics(SM_CYDLGFRAME);
383 }
384 else
385 {
386 XInc = YInc = 0;
387 if (HAS_THICKFRAME(Window->Style, Window->ExStyle))
388 {
389 XInc += NtUserGetSystemMetrics(SM_CXFRAME);
390 YInc += NtUserGetSystemMetrics(SM_CYFRAME);
391 }
392 if (Window->Style & WS_BORDER)
393 {
394 XInc += NtUserGetSystemMetrics(SM_CXBORDER);
395 YInc += NtUserGetSystemMetrics(SM_CYBORDER);
396 }
397 }
398 MinMax.ptMaxSize.x += 2 * XInc;
399 MinMax.ptMaxSize.y += 2 * YInc;
400
401 Pos = (PINTERNALPOS)IntGetProp(Window, AtomInternalPos);
402 if (Pos != NULL)
403 {
404 MinMax.ptMaxPosition = Pos->MaxPos;
405 }
406 else
407 {
408 MinMax.ptMaxPosition.x -= XInc;
409 MinMax.ptMaxPosition.y -= YInc;
410 }
411
412 IntSendMessage(Window->Self, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax, TRUE);
413
414 MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
415 MinMax.ptMinTrackSize.x);
416 MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y,
417 MinMax.ptMinTrackSize.y);
418
419 if (MaxSize) *MaxSize = MinMax.ptMaxSize;
420 if (MaxPos) *MaxPos = MinMax.ptMaxPosition;
421 if (MinTrack) *MinTrack = MinMax.ptMinTrackSize;
422 if (MaxTrack) *MaxTrack = MinMax.ptMaxTrackSize;
423
424 return 0; //FIXME: what does it return?
425 }
426
427 BOOL STATIC FASTCALL
428 WinPosChangeActiveWindow(HWND hWnd, BOOL MouseMsg)
429 {
430 PWINDOW_OBJECT WindowObject;
431
432 WindowObject = IntGetWindowObject(hWnd);
433 if (WindowObject == NULL)
434 {
435 return FALSE;
436 }
437
438 NtUserSendMessage(hWnd,
439 WM_ACTIVATE,
440 MAKELONG(MouseMsg ? WA_CLICKACTIVE : WA_CLICKACTIVE,
441 (WindowObject->Style & WS_MINIMIZE) ? 1 : 0),
442 (LPARAM)IntGetDesktopWindow()); /* FIXME: Previous active window */
443
444 IntReleaseWindowObject(WindowObject);
445
446 return TRUE;
447 }
448
449 LONG STATIC STDCALL
450 WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos,
451 RECT* WindowRect, RECT* ClientRect)
452 {
453 UINT wvrFlags = 0;
454
455 /* Send WM_NCCALCSIZE message to get new client area */
456 if ((WinPos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE)
457 {
458 NCCALCSIZE_PARAMS params;
459 WINDOWPOS winposCopy;
460
461 params.rgrc[0] = *WindowRect;
462 params.rgrc[1] = Window->WindowRect;
463 params.rgrc[2] = Window->ClientRect;
464 if (0 != (Window->Style & WS_CHILD))
465 {
466 NtGdiOffsetRect(&(params.rgrc[0]), - Window->Parent->ClientRect.left,
467 - Window->Parent->ClientRect.top);
468 NtGdiOffsetRect(&(params.rgrc[1]), - Window->Parent->ClientRect.left,
469 - Window->Parent->ClientRect.top);
470 NtGdiOffsetRect(&(params.rgrc[2]), - Window->Parent->ClientRect.left,
471 - Window->Parent->ClientRect.top);
472 }
473 params.lppos = &winposCopy;
474 winposCopy = *WinPos;
475
476 wvrFlags = IntSendNCCALCSIZEMessage(Window->Self, TRUE, NULL, &params);
477
478 /* If the application send back garbage, ignore it */
479 if (params.rgrc[0].left <= params.rgrc[0].right &&
480 params.rgrc[0].top <= params.rgrc[0].bottom)
481 {
482 *ClientRect = params.rgrc[0];
483 if (Window->Style & WS_CHILD)
484 {
485 NtGdiOffsetRect(ClientRect, Window->Parent->ClientRect.left,
486 Window->Parent->ClientRect.top);
487 }
488 }
489
490 /* FIXME: WVR_ALIGNxxx */
491
492 if (ClientRect->left != Window->ClientRect.left ||
493 ClientRect->top != Window->ClientRect.top)
494 {
495 WinPos->flags &= ~SWP_NOCLIENTMOVE;
496 }
497
498 if ((ClientRect->right - ClientRect->left !=
499 Window->ClientRect.right - Window->ClientRect.left) ||
500 (ClientRect->bottom - ClientRect->top !=
501 Window->ClientRect.bottom - Window->ClientRect.top))
502 {
503 WinPos->flags &= ~SWP_NOCLIENTSIZE;
504 }
505 }
506 else
507 {
508 if (! (WinPos->flags & SWP_NOMOVE)
509 && (ClientRect->left != Window->ClientRect.left ||
510 ClientRect->top != Window->ClientRect.top))
511 {
512 WinPos->flags &= ~SWP_NOCLIENTMOVE;
513 }
514 }
515
516 return wvrFlags;
517 }
518
519 BOOL STDCALL
520 WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject,
521 PWINDOWPOS WinPos,
522 PRECT WindowRect,
523 PRECT ClientRect)
524 {
525 INT X, Y;
526
527 if (!(WinPos->flags & SWP_NOSENDCHANGING))
528 {
529 IntSendWINDOWPOSCHANGINGMessage(WindowObject->Self, WinPos);
530 }
531
532 *WindowRect = WindowObject->WindowRect;
533 *ClientRect =
534 (WindowObject->Style & WS_MINIMIZE) ? WindowObject->WindowRect :
535 WindowObject->ClientRect;
536
537 if (!(WinPos->flags & SWP_NOSIZE))
538 {
539 WindowRect->right = WindowRect->left + WinPos->cx;
540 WindowRect->bottom = WindowRect->top + WinPos->cy;
541 }
542
543 if (!(WinPos->flags & SWP_NOMOVE))
544 {
545 X = WinPos->x;
546 Y = WinPos->y;
547 if (0 != (WindowObject->Style & WS_CHILD))
548 {
549 X += WindowObject->Parent->ClientRect.left;
550 Y += WindowObject->Parent->ClientRect.top;
551 }
552 WindowRect->left = X;
553 WindowRect->top = Y;
554 WindowRect->right += X - WindowObject->WindowRect.left;
555 WindowRect->bottom += Y - WindowObject->WindowRect.top;
556 NtGdiOffsetRect(ClientRect,
557 X - WindowObject->WindowRect.left,
558 Y - WindowObject->WindowRect.top);
559 }
560
561 WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
562
563 return TRUE;
564 }
565
566 /*
567 * Fix Z order taking into account owned popups -
568 * basically we need to maintain them above the window that owns them
569 */
570 HWND FASTCALL
571 WinPosDoOwnedPopups(HWND hWnd, HWND hWndInsertAfter)
572 {
573 /* FIXME */
574 return hWndInsertAfter;
575 }
576
577 /***********************************************************************
578 * WinPosInternalMoveWindow
579 *
580 * Update WindowRect and ClientRect of Window and all of its children
581 * We keep both WindowRect and ClientRect in screen coordinates internally
582 */
583 static VOID
584 WinPosInternalMoveWindow(PWINDOW_OBJECT Window, INT MoveX, INT MoveY)
585 {
586 PWINDOW_OBJECT Child;
587
588 Window->WindowRect.left += MoveX;
589 Window->WindowRect.right += MoveX;
590 Window->WindowRect.top += MoveY;
591 Window->WindowRect.bottom += MoveY;
592
593 Window->ClientRect.left += MoveX;
594 Window->ClientRect.right += MoveX;
595 Window->ClientRect.top += MoveY;
596 Window->ClientRect.bottom += MoveY;
597
598 ExAcquireFastMutexUnsafe(&Window->ChildrenListLock);
599 Child = Window->FirstChild;
600 while (Child)
601 {
602 WinPosInternalMoveWindow(Child, MoveX, MoveY);
603 Child = Child->NextSibling;
604 }
605 ExReleaseFastMutexUnsafe(&Window->ChildrenListLock);
606 }
607
608
609 /* x and y are always screen relative */
610 BOOLEAN STDCALL
611 WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
612 INT cy, UINT flags)
613 {
614 PWINDOW_OBJECT Window;
615 NTSTATUS Status;
616 WINDOWPOS WinPos;
617 RECT NewWindowRect;
618 RECT NewClientRect;
619 HRGN VisBefore = NULL;
620 HRGN VisAfter = NULL;
621 HRGN DirtyRgn = NULL;
622 HRGN ExposedRgn = NULL;
623 HRGN CopyRgn = NULL;
624 ULONG WvrFlags = 0;
625 RECT OldWindowRect, OldClientRect;
626 UINT FlagsEx = 0;
627 int RgnType;
628 HDC Dc;
629 RECT CopyRect;
630 RECT TempRect;
631
632 /* FIXME: Get current active window from active queue. */
633
634 /* Check if the window is for a desktop. */
635 if (Wnd == PsGetWin32Thread()->Desktop->DesktopWindow)
636 {
637 return(FALSE);
638 }
639
640 Status =
641 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
642 Wnd,
643 otWindow,
644 (PVOID*)&Window);
645 if (!NT_SUCCESS(Status))
646 {
647 return(FALSE);
648 }
649
650 /* Fix up the flags. */
651 if (Window->Style & WS_VISIBLE)
652 {
653 flags &= ~SWP_SHOWWINDOW;
654 }
655 else
656 {
657 if (!(flags & SWP_SHOWWINDOW))
658 {
659 flags |= SWP_NOREDRAW;
660 }
661 flags &= ~SWP_HIDEWINDOW;
662 }
663
664 cx = max(cx, 0);
665 cy = max(cy, 0);
666
667 if ((Window->WindowRect.right - Window->WindowRect.left) == cx &&
668 (Window->WindowRect.bottom - Window->WindowRect.top) == cy)
669 {
670 flags |= SWP_NOSIZE;
671 }
672 if (Window->WindowRect.left == x && Window->WindowRect.top == y)
673 {
674 flags |= SWP_NOMOVE;
675 }
676 if (Window->Flags & WIN_NCACTIVATED)
677 {
678 flags |= SWP_NOACTIVATE;
679 }
680 else if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
681 {
682 if (!(flags & SWP_NOACTIVATE))
683 {
684 flags &= ~SWP_NOZORDER;
685 WndInsertAfter = HWND_TOP;
686 }
687 }
688
689 if (WndInsertAfter == HWND_TOPMOST || WndInsertAfter == HWND_NOTOPMOST)
690 {
691 WndInsertAfter = HWND_TOP;
692 }
693
694 if (WndInsertAfter != HWND_TOP && WndInsertAfter != HWND_BOTTOM)
695 {
696 if (NtUserGetAncestor(WndInsertAfter, GA_PARENT) != Window->Parent)
697 {
698 SetLastWin32Error(ERROR_INVALID_PARAMETER);
699 return FALSE;
700 }
701 else
702 {
703 /*
704 * Don't need to change the Zorder of hwnd if it's already inserted
705 * after hwndInsertAfter or when inserting hwnd after itself.
706 */
707 if (Wnd == WndInsertAfter ||
708 Wnd == NtUserGetWindow(WndInsertAfter, GW_HWNDNEXT))
709 {
710 flags |= SWP_NOZORDER;
711 }
712 }
713 }
714
715 WinPos.hwnd = Wnd;
716 WinPos.hwndInsertAfter = WndInsertAfter;
717 WinPos.x = x;
718 WinPos.y = y;
719 WinPos.cx = cx;
720 WinPos.cy = cy;
721 WinPos.flags = flags;
722 if (0 != (Window->Style & WS_CHILD))
723 {
724 WinPos.x -= Window->Parent->ClientRect.left;
725 WinPos.y -= Window->Parent->ClientRect.top;
726 }
727
728 WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
729
730 if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
731 SWP_NOZORDER &&
732 NtUserGetAncestor(WinPos.hwnd, GA_PARENT) ==
733 PsGetWin32Thread()->Desktop->DesktopWindow)
734 {
735 WinPos.hwndInsertAfter = WinPosDoOwnedPopups(WinPos.hwnd, WinPos.hwndInsertAfter);
736 }
737
738 /* FIXME: Adjust flags based on WndInsertAfter */
739
740 /* Compute the visible region before the window position is changed */
741 if ((!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
742 WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
743 SWP_HIDEWINDOW | SWP_FRAMECHANGED)) !=
744 (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
745 {
746 if (Window->Style & WS_CLIPCHILDREN)
747 {
748 VisBefore = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
749 Window, FALSE, FALSE, TRUE);
750 }
751 else
752 {
753 VisBefore = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
754 Window, FALSE, FALSE, FALSE);
755 }
756 if (NULLREGION == UnsafeIntGetRgnBox(VisBefore, &TempRect))
757 {
758 NtGdiDeleteObject(VisBefore);
759 VisBefore = NULL;
760 }
761 }
762
763 WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect,
764 &NewClientRect);
765
766 /*
767 * FIXME: Relink windows. (also take into account shell window in hwndShellWindow)
768 */
769 if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwndInsertAfter != WinPos.hwnd &&
770 WinPos.hwnd != NtUserGetShellWindow())
771 {
772 PWINDOW_OBJECT ParentWindow;
773 PWINDOW_OBJECT InsertAfterWindow;
774
775 ParentWindow = Window->Parent;
776 if (ParentWindow)
777 {
778 if (WndInsertAfter == HWND_TOP)
779 InsertAfterWindow = NULL;
780 else if (WndInsertAfter == HWND_BOTTOM)
781 InsertAfterWindow = ParentWindow->LastChild;
782 else
783 InsertAfterWindow = IntGetWindowObject(WinPos.hwndInsertAfter);
784 ExAcquireFastMutexUnsafe(&ParentWindow->ChildrenListLock);
785 IntUnlinkWindow(Window);
786 IntLinkWindow(Window, ParentWindow, InsertAfterWindow);
787 ExReleaseFastMutexUnsafe(&ParentWindow->ChildrenListLock);
788 if (InsertAfterWindow != NULL)
789 IntReleaseWindowObject(InsertAfterWindow);
790 }
791 }
792
793 /* FIXME: Reset active DCEs */
794
795 OldWindowRect = Window->WindowRect;
796 OldClientRect = Window->ClientRect;
797
798 /* FIXME: Check for redrawing the whole client rect. */
799
800 if (! (WinPos.flags & SWP_NOMOVE))
801 {
802 WinPosInternalMoveWindow(Window,
803 NewWindowRect.left - OldWindowRect.left,
804 NewWindowRect.top - OldWindowRect.top);
805 }
806 Window->WindowRect = NewWindowRect;
807 Window->ClientRect = NewClientRect;
808
809 if (WinPos.flags & SWP_SHOWWINDOW)
810 {
811 Window->Style |= WS_VISIBLE;
812 FlagsEx |= SWP_EX_PAINTSELF;
813 }
814 else if (WinPos.flags & SWP_HIDEWINDOW)
815 {
816 Window->Style &= ~WS_VISIBLE;
817 }
818
819 if (!(WinPos.flags & SWP_NOREDRAW))
820 {
821 /* Determine the new visible region */
822 if (Window->Style & WS_CLIPCHILDREN)
823 {
824 VisAfter = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
825 Window, FALSE, FALSE, TRUE);
826 }
827 else
828 {
829 VisAfter = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
830 Window, FALSE, FALSE, FALSE);
831 }
832 if (NULLREGION == UnsafeIntGetRgnBox(VisAfter, &TempRect))
833 {
834 NtGdiDeleteObject(VisAfter);
835 VisAfter = NULL;
836 }
837
838 /* Determine which pixels can be copied from the old window position
839 to the new. Those pixels must be visible in both the old and new
840 position. Also, check the class style to see if the windows of this
841 class need to be completely repainted on (horizontal/vertical) size
842 change */
843 if (NULL != VisBefore && NULL != VisAfter && ! (WinPos.flags & SWP_NOCOPYBITS)
844 && ((WinPos.flags & SWP_NOSIZE)
845 || ! (Window->Class->style & (CS_HREDRAW | CS_VREDRAW))))
846 {
847 CopyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
848 RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
849
850 /* If this is (also) a window resize, the whole nonclient area
851 needs to be repainted. So we limit the copy to the client area,
852 'cause there is no use in copying it (would possibly cause
853 "flashing" too). However, if the copy region is already empty,
854 we don't have to crop (can't take anything away from an empty
855 region...) */
856 if (! (WinPos.flags & SWP_NOSIZE)
857 && ERROR != RgnType && NULLREGION != RgnType)
858 {
859 RECT ORect = OldClientRect;
860 RECT NRect = NewClientRect;
861 NtGdiOffsetRect(&ORect, - OldWindowRect.left, - OldWindowRect.top);
862 NtGdiOffsetRect(&NRect, - NewWindowRect.left, - NewWindowRect.top);
863 NtGdiIntersectRect(&CopyRect, &ORect, &NRect);
864 REGION_CropRgn(CopyRgn, CopyRgn, &CopyRect, NULL);
865 }
866
867 /* No use in copying bits which are in the update region. */
868 if ((HRGN) 1 == Window->UpdateRegion)
869 {
870 /* The whole window is in the update region. No use
871 copying anything, so set the copy region empty */
872 NtGdiSetRectRgn(CopyRgn, 0, 0, 0, 0);
873 }
874 else if (1 < (DWORD) Window->UpdateRegion)
875 {
876 NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF);
877 }
878
879
880 /* Now, get the bounding box of the copy region. If it's empty
881 there's nothing to copy. Also, it's no use copying bits onto
882 themselves */
883 UnsafeIntGetRgnBox(CopyRgn, &CopyRect);
884 if (NtGdiIsEmptyRect(&CopyRect))
885 {
886 /* Nothing to copy, clean up */
887 NtGdiDeleteObject(CopyRgn);
888 CopyRgn = NULL;
889 }
890 else if (OldWindowRect.left != NewWindowRect.left
891 || OldWindowRect.top != NewWindowRect.top)
892 {
893 /* Small trick here: there is no function to bitblt a region. So
894 we set the region as the clipping region, take the bounding box
895 of the region and bitblt that. Since nothing outside the clipping
896 region is copied, this has the effect of bitblt'ing the region.
897
898 Since NtUserGetDCEx takes ownership of the clip region, we need
899 to create a copy of CopyRgn and pass that. We need CopyRgn later */
900 HRGN ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
901 NtGdiCombineRgn(ClipRgn, CopyRgn, NULL, RGN_COPY);
902 Dc = NtUserGetDCEx(Wnd, ClipRgn, DCX_WINDOW | DCX_CACHE |
903 DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
904 NtGdiBitBlt(Dc, CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left,
905 CopyRect.bottom - CopyRect.top, Dc,
906 CopyRect.left + (OldWindowRect.left - NewWindowRect.left),
907 CopyRect.top + (OldWindowRect.top - NewWindowRect.top), SRCCOPY);
908 NtUserReleaseDC(Wnd, Dc);
909 }
910 }
911 else
912 {
913 CopyRgn = NULL;
914 }
915
916 /* We need to redraw what wasn't visible before */
917 if (NULL != VisAfter)
918 {
919 if (NULL != CopyRgn)
920 {
921 DirtyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
922 RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
923 if (ERROR != RgnType && NULLREGION != RgnType)
924 {
925 IntRedrawWindow(Window, NULL, DirtyRgn,
926 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
927 RDW_ALLCHILDREN | RDW_ERASENOW);
928 }
929 NtGdiDeleteObject(DirtyRgn);
930 }
931 else
932 {
933 IntRedrawWindow(Window, NULL, NULL,
934 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
935 RDW_ALLCHILDREN | RDW_ERASENOW);
936 }
937 }
938
939 if (NULL != CopyRgn)
940 {
941 NtGdiDeleteObject(CopyRgn);
942 }
943 }
944
945 /* Expose what was covered before but not covered anymore */
946 if (NULL != VisBefore)
947 {
948 ExposedRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
949 NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
950 NtGdiOffsetRgn(ExposedRgn, OldWindowRect.left - NewWindowRect.left,
951 OldWindowRect.top - NewWindowRect.top);
952 if (NULL != VisAfter)
953 {
954 RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
955 }
956 else
957 {
958 RgnType = SIMPLEREGION;
959 }
960 if (ERROR != RgnType && NULLREGION != RgnType)
961 {
962 VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, ExposedRgn);
963 }
964 NtGdiDeleteObject(ExposedRgn);
965
966 NtGdiDeleteObject(VisBefore);
967 }
968
969 if (NULL != VisAfter)
970 {
971 NtGdiDeleteObject(VisAfter);
972 }
973
974 /* FIXME: Hide or show the claret */
975
976 if (!(flags & SWP_NOACTIVATE))
977 {
978 WinPosChangeActiveWindow(WinPos.hwnd, FALSE);
979 }
980
981 /* FIXME: Check some conditions before doing this. */
982 IntSendWINDOWPOSCHANGEDMessage(WinPos.hwnd, &WinPos);
983
984 IntReleaseWindowObject(Window);
985 return(TRUE);
986 }
987
988 LRESULT STDCALL
989 WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect)
990 {
991 *ClientRect = *WindowRect;
992 return(IntSendNCCALCSIZEMessage(Wnd, FALSE, ClientRect, NULL));
993 }
994
995 BOOLEAN FASTCALL
996 WinPosShowWindow(HWND Wnd, INT Cmd)
997 {
998 BOOLEAN WasVisible;
999 PWINDOW_OBJECT Window;
1000 UINT Swp = 0;
1001 RECT NewPos = {0, 0, 0, 0};
1002 BOOLEAN ShowFlag;
1003 /* HRGN VisibleRgn;*/
1004
1005 Window = IntGetWindowObject(Wnd);
1006 if (!Window)
1007 {
1008 return(FALSE);
1009 }
1010
1011 WasVisible = (Window->Style & WS_VISIBLE) != 0;
1012
1013 switch (Cmd)
1014 {
1015 case SW_HIDE:
1016 {
1017 if (!WasVisible)
1018 {
1019 ObmDereferenceObject(Window);
1020 return(FALSE);
1021 }
1022 Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE |
1023 SWP_NOZORDER;
1024 break;
1025 }
1026
1027 case SW_SHOWMINNOACTIVE:
1028 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1029 /* Fall through. */
1030 case SW_SHOWMINIMIZED:
1031 Swp |= SWP_SHOWWINDOW;
1032 /* Fall through. */
1033 case SW_MINIMIZE:
1034 {
1035 Swp |= SWP_FRAMECHANGED;
1036 if (!(Window->Style & WS_MINIMIZE))
1037 {
1038 Swp |= WinPosMinMaximize(Window, SW_MINIMIZE, &NewPos);
1039 }
1040 else
1041 {
1042 Swp |= SWP_NOSIZE | SWP_NOMOVE;
1043 }
1044 break;
1045 }
1046
1047 case SW_SHOWMAXIMIZED:
1048 {
1049 Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1050 if (!(Window->Style & WS_MAXIMIZE))
1051 {
1052 Swp |= WinPosMinMaximize(Window, SW_MAXIMIZE, &NewPos);
1053 }
1054 else
1055 {
1056 Swp |= SWP_NOSIZE | SWP_NOMOVE;
1057 }
1058 break;
1059 }
1060
1061 case SW_SHOWNA:
1062 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1063 /* Fall through. */
1064 case SW_SHOW:
1065 Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1066 /* Don't activate the topmost window. */
1067 break;
1068
1069 case SW_SHOWNOACTIVATE:
1070 Swp |= SWP_NOZORDER;
1071 /* Fall through. */
1072 case SW_SHOWNORMAL:
1073 case SW_SHOWDEFAULT:
1074 case SW_RESTORE:
1075 Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1076 if (Window->Style & (WS_MINIMIZE | WS_MAXIMIZE))
1077 {
1078 Swp |= WinPosMinMaximize(Window, SW_RESTORE, &NewPos);
1079 }
1080 else
1081 {
1082 Swp |= SWP_NOSIZE | SWP_NOMOVE;
1083 }
1084 break;
1085 }
1086
1087 ShowFlag = (Cmd != SW_HIDE);
1088 if (ShowFlag != WasVisible)
1089 {
1090 NtUserSendMessage(Wnd, WM_SHOWWINDOW, ShowFlag, 0);
1091 /*
1092 * FIXME: Need to check the window wasn't destroyed during the
1093 * window procedure.
1094 */
1095 }
1096
1097 /* We can't activate a child window */
1098 if ((Window->Style & WS_CHILD) &&
1099 !(Window->ExStyle & WS_EX_MDICHILD))
1100 {
1101 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1102 }
1103
1104 WinPosSetWindowPos(Wnd, HWND_TOP, NewPos.left, NewPos.top,
1105 NewPos.right, NewPos.bottom, LOWORD(Swp));
1106
1107 if (Cmd == SW_HIDE)
1108 {
1109 /* FIXME: This will cause the window to be activated irrespective
1110 * of whether it is owned by the same thread. Has to be done
1111 * asynchronously.
1112 */
1113
1114 if (Wnd == IntGetActiveWindow())
1115 {
1116 WinPosActivateOtherWindow(Window);
1117 }
1118
1119 /* Revert focus to parent */
1120 if (Wnd == IntGetFocusWindow() ||
1121 IntIsChildWindow(Wnd, IntGetFocusWindow()))
1122 {
1123 IntSetFocusWindow(Window->Parent->Self);
1124 }
1125 }
1126
1127 if (!IntIsWindow(Wnd))
1128 {
1129 IntReleaseWindowObject(Window);
1130 return WasVisible;
1131 }
1132 else if (Window->Style & WS_MINIMIZE)
1133 {
1134 WinPosShowIconTitle(Window, TRUE);
1135 }
1136
1137 if (Window->Flags & WINDOWOBJECT_NEED_SIZE)
1138 {
1139 /* should happen only in CreateWindowEx() */
1140 int wParam = SIZE_RESTORED;
1141
1142 Window->Flags &= ~WINDOWOBJECT_NEED_SIZE;
1143 if (Window->Style & WS_MAXIMIZE)
1144 {
1145 wParam = SIZE_MAXIMIZED;
1146 }
1147 else if (Window->Style & WS_MINIMIZE)
1148 {
1149 wParam = SIZE_MINIMIZED;
1150 }
1151
1152 NtUserSendMessage(Wnd, WM_SIZE, wParam,
1153 MAKELONG(Window->ClientRect.right -
1154 Window->ClientRect.left,
1155 Window->ClientRect.bottom -
1156 Window->ClientRect.top));
1157 NtUserSendMessage(Wnd, WM_MOVE, 0,
1158 MAKELONG(Window->ClientRect.left,
1159 Window->ClientRect.top));
1160 }
1161
1162 /* Activate the window if activation is not requested and the window is not minimized */
1163 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->Style & WS_MINIMIZE))
1164 {
1165 WinPosChangeActiveWindow(Wnd, FALSE);
1166 }
1167
1168 IntReleaseWindowObject(Window);
1169 return WasVisible;
1170 }
1171
1172 BOOL STATIC FASTCALL
1173 WinPosPtInWindow(PWINDOW_OBJECT Window, POINT Point)
1174 {
1175 return(Point.x >= Window->WindowRect.left &&
1176 Point.x < Window->WindowRect.right &&
1177 Point.y >= Window->WindowRect.top &&
1178 Point.y < Window->WindowRect.bottom);
1179 }
1180
1181 USHORT STATIC STDCALL
1182 WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, POINT Point,
1183 PWINDOW_OBJECT* Window)
1184 {
1185 PWINDOW_OBJECT Current;
1186
1187 ExAcquireFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1188 Current = ScopeWin->FirstChild;
1189 while (Current)
1190 {
1191 if (Current->Style & WS_VISIBLE &&
1192 ((!(Current->Style & WS_DISABLED)) ||
1193 (Current->Style & (WS_CHILD | WS_POPUP)) != WS_CHILD) &&
1194 WinPosPtInWindow(Current, Point))
1195 {
1196 *Window = Current;
1197 if (Current->Style & WS_DISABLED)
1198 {
1199 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1200 return(HTERROR);
1201 }
1202 if (Current->Style & WS_MINIMIZE)
1203 {
1204 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1205 return(HTCAPTION);
1206 }
1207 if (Point.x >= Current->ClientRect.left &&
1208 Point.x < Current->ClientRect.right &&
1209 Point.y >= Current->ClientRect.top &&
1210 Point.y < Current->ClientRect.bottom)
1211 {
1212
1213 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1214 return(WinPosSearchChildren(Current, Point, Window));
1215 }
1216
1217 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1218 return(0);
1219 }
1220 Current = Current->NextSibling;
1221 }
1222
1223 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1224 return(0);
1225 }
1226
1227 USHORT STDCALL
1228 WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint,
1229 PWINDOW_OBJECT* Window)
1230 {
1231 HWND DesktopWindowHandle;
1232 PWINDOW_OBJECT DesktopWindow;
1233 POINT Point = WinPoint;
1234 USHORT HitTest;
1235
1236 *Window = NULL;
1237
1238 if (ScopeWin->Style & WS_DISABLED)
1239 {
1240 return(HTERROR);
1241 }
1242
1243 /* Translate the point to the space of the scope window. */
1244 DesktopWindowHandle = IntGetDesktopWindow();
1245 DesktopWindow = IntGetWindowObject(DesktopWindowHandle);
1246 Point.x += ScopeWin->ClientRect.left - DesktopWindow->ClientRect.left;
1247 Point.y += ScopeWin->ClientRect.top - DesktopWindow->ClientRect.top;
1248 IntReleaseWindowObject(DesktopWindow);
1249
1250 HitTest = WinPosSearchChildren(ScopeWin, Point, Window);
1251 if (HitTest != 0)
1252 {
1253 return(HitTest);
1254 }
1255
1256 if ((*Window) == NULL)
1257 {
1258 return(HTNOWHERE);
1259 }
1260 if ((*Window)->MessageQueue == PsGetWin32Thread()->MessageQueue)
1261 {
1262 HitTest = IntSendMessage((*Window)->Self, WM_NCHITTEST, 0,
1263 MAKELONG(Point.x, Point.y), FALSE);
1264 /* FIXME: Check for HTTRANSPARENT here. */
1265 }
1266 else
1267 {
1268 HitTest = HTCLIENT;
1269 }
1270
1271 return(HitTest);
1272 }
1273
1274 BOOL
1275 WinPosSetActiveWindow(PWINDOW_OBJECT Window, BOOL Mouse, BOOL ChangeFocus)
1276 {
1277 PUSER_MESSAGE_QUEUE ActiveQueue;
1278 HWND PrevActive;
1279
1280 ActiveQueue = IntGetFocusMessageQueue();
1281 if (ActiveQueue != NULL)
1282 {
1283 PrevActive = ActiveQueue->ActiveWindow;
1284 }
1285 else
1286 {
1287 PrevActive = NULL;
1288 }
1289
1290 if (Window->Self == IntGetActiveDesktop() || Window->Self == PrevActive)
1291 {
1292 return(FALSE);
1293 }
1294 if (PrevActive != NULL)
1295 {
1296 PWINDOW_OBJECT PrevActiveWindow = IntGetWindowObject(PrevActive);
1297 if(PrevActiveWindow)
1298 {
1299 WORD Iconised = HIWORD(PrevActiveWindow->Style & WS_MINIMIZE);
1300 if (!IntSendMessage(PrevActive, WM_NCACTIVATE, FALSE, 0, TRUE))
1301 {
1302 /* FIXME: Check if the new window is system modal. */
1303 return(FALSE);
1304 }
1305 IntSendMessage(PrevActive,
1306 WM_ACTIVATE,
1307 MAKEWPARAM(WA_INACTIVE, Iconised),
1308 (LPARAM)Window->Self,
1309 TRUE);
1310 /* FIXME: Check if anything changed while processing the message. */
1311 IntReleaseWindowObject(PrevActiveWindow);
1312 }
1313 else
1314 {
1315 if(ActiveQueue)
1316 ActiveQueue->ActiveWindow = NULL;
1317 PrevActive = NULL;
1318 }
1319 }
1320
1321 if (Window != NULL)
1322 {
1323 Window->MessageQueue->ActiveWindow = Window->Self;
1324 }
1325 else if (ActiveQueue != NULL)
1326 {
1327 ActiveQueue->ActiveWindow = NULL;
1328 }
1329 /* FIXME: Unset this flag for inactive windows */
1330 //if ((Window->Style) & WS_CHILD) Window->Flags |= WIN_NCACTIVATED;
1331
1332 /* FIXME: Send palette messages. */
1333
1334 /* FIXME: Redraw icon title of previously active window. */
1335
1336 /* FIXME: Bring the window to the top. */
1337
1338 /* FIXME: Send WM_ACTIVATEAPP */
1339
1340 IntSetFocusMessageQueue(Window->MessageQueue);
1341
1342 /* FIXME: Send activate messages. */
1343
1344 /* FIXME: Change focus. */
1345
1346 /* FIXME: Redraw new window icon title. */
1347
1348 return(TRUE);
1349 }
1350
1351 HWND STDCALL
1352 NtUserGetActiveWindow(VOID)
1353 {
1354 PUSER_MESSAGE_QUEUE ActiveQueue;
1355
1356 ActiveQueue = IntGetFocusMessageQueue();
1357 if (ActiveQueue == NULL)
1358 {
1359 return(NULL);
1360 }
1361 return(ActiveQueue->ActiveWindow);
1362 }
1363
1364 HWND STDCALL
1365 NtUserSetActiveWindow(HWND hWnd)
1366 {
1367 PWINDOW_OBJECT Window;
1368 PUSER_MESSAGE_QUEUE ThreadQueue;
1369 HWND Prev;
1370
1371 Window = IntGetWindowObject(hWnd);
1372 if (Window == NULL || (Window->Style & (WS_DISABLED | WS_CHILD)))
1373 {
1374 IntReleaseWindowObject(Window);
1375 return(0);
1376 }
1377 ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
1378 if (Window->MessageQueue != ThreadQueue)
1379 {
1380 IntReleaseWindowObject(Window);
1381 return(0);
1382 }
1383 Prev = Window->MessageQueue->ActiveWindow;
1384 WinPosSetActiveWindow(Window, FALSE, FALSE);
1385 IntReleaseWindowObject(Window);
1386 return(Prev);
1387 }
1388
1389
1390 /* EOF */