Fix maximizing problem introduced by r17764
[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$
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 <w32k.h>
32
33 #define NDEBUG
34 #include <debug.h>
35
36 /* GLOBALS *******************************************************************/
37
38 #define MINMAX_NOSWP (0x00010000)
39
40 #define SWP_EX_NOCOPY 0x0001
41 #define SWP_EX_PAINTSELF 0x0002
42
43 #define SWP_AGG_NOGEOMETRYCHANGE \
44 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
45 #define SWP_AGG_NOPOSCHANGE \
46 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
47 #define SWP_AGG_STATUSFLAGS \
48 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
49
50 /* FUNCTIONS *****************************************************************/
51
52 BOOL FASTCALL
53 IntGetClientOrigin(PWINDOW_OBJECT Window OPTIONAL, LPPOINT Point)
54 {
55 Window = Window ? Window : UserGetWindowObject(IntGetDesktopWindow());
56 if (Window == NULL)
57 {
58 Point->x = Point->y = 0;
59 return FALSE;
60 }
61 Point->x = Window->ClientRect.left;
62 Point->y = Window->ClientRect.top;
63
64 return TRUE;
65 }
66
67
68
69
70 BOOL FASTCALL
71 UserGetClientOrigin(PWINDOW_OBJECT Window, LPPOINT Point)
72 {
73 BOOL Ret;
74 POINT pt;
75 NTSTATUS Status;
76
77 if(!Point)
78 {
79 SetLastWin32Error(ERROR_INVALID_PARAMETER);
80 return FALSE;
81 }
82
83 Ret = IntGetClientOrigin(Window, &pt);
84
85 if(!Ret)
86 {
87 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
88 return FALSE;
89 }
90
91 Status = MmCopyToCaller(Point, &pt, sizeof(POINT));
92 if(!NT_SUCCESS(Status))
93 {
94 SetLastNtError(Status);
95 return FALSE;
96 }
97
98 return Ret;
99 }
100
101
102
103 BOOL STDCALL
104 NtUserGetClientOrigin(HWND hWnd, LPPOINT Point)
105 {
106 DECLARE_RETURN(BOOL);
107 PWINDOW_OBJECT Window;
108
109 DPRINT("Enter NtUserGetClientOrigin\n");
110 UserEnterShared();
111
112 if (!(Window = UserGetWindowObject(hWnd)))
113 RETURN(FALSE);
114
115 RETURN(UserGetClientOrigin(Window, Point));
116
117 CLEANUP:
118 DPRINT("Leave NtUserGetClientOrigin, ret=%i\n",_ret_);
119 UserLeave();
120 END_CLEANUP;
121 }
122
123
124 /*******************************************************************
125 * can_activate_window
126 *
127 * Check if we can activate the specified window.
128 */
129 static BOOL FASTCALL can_activate_window( PWINDOW_OBJECT Wnd )
130 {
131 LONG style;
132
133 if (!Wnd) return FALSE;
134 style = Wnd->Style;
135 if (!(style & WS_VISIBLE)) return FALSE;
136 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
137 return !(style & WS_DISABLED);
138 }
139
140
141 /*******************************************************************
142 * WinPosActivateOtherWindow
143 *
144 * Activates window other than pWnd.
145 */
146 VOID FASTCALL
147 co_WinPosActivateOtherWindow(PWINDOW_OBJECT Window OPTIONAL)
148 {
149 PWINDOW_OBJECT Wnd;
150 HWND Fg;
151
152 if (Window)
153 ASSERT_REFS_CO(Window);
154
155 if (!Window || IntIsDesktopWindow(Window))
156 {
157 IntSetFocusMessageQueue(NULL);
158 return;
159 }
160
161 /* If this is popup window, try to activate the owner first. */
162 if ((Window->Style & WS_POPUP) && (Wnd = IntGetOwner(Window)))
163 {
164 Wnd = UserGetAncestor( Wnd, GA_ROOT );
165 if (can_activate_window(Wnd)) goto done;
166 }
167
168 /* Pick a next top-level window. */
169 /* FIXME: Search for non-tooltip windows first. */
170 Wnd = Window;
171 while (Wnd != NULL)
172 {
173 if (Wnd->NextSibling == NULL)
174 {
175 Wnd = NULL;
176 break;
177 }
178
179 Wnd = Wnd->NextSibling;
180
181 if ((Wnd->Style & (WS_DISABLED | WS_VISIBLE)) == WS_VISIBLE &&
182 (Wnd->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
183 break;
184 }
185
186 done:
187
188 if (Wnd)
189 UserRefObjectCo(Wnd);
190
191 Fg = UserGetForegroundWindow();
192 if (Wnd && (!Fg || Window->hSelf == Fg))
193 {
194 if (co_IntSetForegroundWindow(Wnd))
195 {
196 UserDerefObjectCo(Wnd);
197 return;
198 }
199 }
200
201 if (!co_IntSetActiveWindow(Wnd))
202 co_IntSetActiveWindow(0);
203
204 if (Wnd)
205 UserDerefObjectCo(Wnd);
206 }
207
208
209 UINT
210 FASTCALL
211 co_WinPosArrangeIconicWindows(PWINDOW_OBJECT parent)
212 {
213 RECT rectParent;
214 INT i, x, y, xspacing, yspacing;
215 HWND *List = IntWinListChildren(parent);
216
217 ASSERT_REFS_CO(parent);
218
219 IntGetClientRect( parent, &rectParent );
220 x = rectParent.left;
221 y = rectParent.bottom;
222
223 xspacing = UserGetSystemMetrics(SM_CXMINSPACING);
224 yspacing = UserGetSystemMetrics(SM_CYMINSPACING);
225
226 DPRINT("X:%d Y:%d XS:%d YS:%d\n",x,y,xspacing,yspacing);
227
228 for( i = 0; List[i]; i++)
229 {
230 PWINDOW_OBJECT WndChild;
231
232 if (!(WndChild = UserGetWindowObject(List[i])))
233 continue;
234
235 if((WndChild->Style & WS_MINIMIZE) != 0 )
236 {
237 UserRefObjectCo(WndChild);
238
239 co_WinPosSetWindowPos(WndChild, 0, x + UserGetSystemMetrics(SM_CXBORDER),
240 y - yspacing - UserGetSystemMetrics(SM_CYBORDER)
241 , 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
242
243 UserDerefObjectCo(WndChild);
244
245 if (x <= rectParent.right - xspacing)
246 x += xspacing;
247 else
248 {
249 x = rectParent.left;
250 y -= yspacing;
251 }
252 }
253 }
254 ExFreePool(List);
255 return yspacing;
256 }
257
258
259 VOID STATIC FASTCALL
260 WinPosFindIconPos(PWINDOW_OBJECT Window, POINT *Pos)
261 {
262 /* FIXME */
263 }
264
265 PINTERNALPOS FASTCALL
266 WinPosInitInternalPos(PWINDOW_OBJECT Window, POINT *pt, PRECT RestoreRect)
267 {
268 PWINDOW_OBJECT Parent;
269 UINT XInc, YInc;
270
271 if (Window->InternalPos == NULL)
272 {
273 RECT WorkArea;
274 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop; /* Or rather get it from the window? */
275
276 Parent = Window->Parent;
277 if(Parent)
278 {
279 if(IntIsDesktopWindow(Parent))
280 IntGetDesktopWorkArea(Desktop, &WorkArea);
281 else
282 WorkArea = Parent->ClientRect;
283 }
284 else
285 IntGetDesktopWorkArea(Desktop, &WorkArea);
286
287 Window->InternalPos = ExAllocatePoolWithTag(PagedPool, sizeof(INTERNALPOS), TAG_WININTLIST);
288 if(!Window->InternalPos)
289 {
290 DPRINT1("Failed to allocate INTERNALPOS structure for window 0x%x\n", Window->hSelf);
291 return NULL;
292 }
293 Window->InternalPos->NormalRect = Window->WindowRect;
294 IntGetWindowBorderMeasures(Window, &XInc, &YInc);
295 Window->InternalPos->MaxPos.x = WorkArea.left - XInc;
296 Window->InternalPos->MaxPos.y = WorkArea.top - YInc;
297 Window->InternalPos->IconPos.x = WorkArea.left;
298 Window->InternalPos->IconPos.y = WorkArea.bottom - UserGetSystemMetrics(SM_CYMINIMIZED);
299 }
300 if (Window->Style & WS_MINIMIZE)
301 {
302 Window->InternalPos->IconPos = *pt;
303 }
304 else if (Window->Style & WS_MAXIMIZE)
305 {
306 Window->InternalPos->MaxPos = *pt;
307 }
308 else if (RestoreRect != NULL)
309 {
310 Window->InternalPos->NormalRect = *RestoreRect;
311 }
312 return(Window->InternalPos);
313 }
314
315 UINT FASTCALL
316 co_WinPosMinMaximize(PWINDOW_OBJECT Window, UINT ShowFlag, RECT* NewPos)
317 {
318 POINT Size;
319 PINTERNALPOS InternalPos;
320 UINT SwpFlags = 0;
321
322 ASSERT_REFS_CO(Window);
323
324 Size.x = Window->WindowRect.left;
325 Size.y = Window->WindowRect.top;
326 InternalPos = WinPosInitInternalPos(Window, &Size, &Window->WindowRect);
327
328 if (InternalPos)
329 {
330 if (Window->Style & WS_MINIMIZE)
331 {
332 if (!co_IntSendMessage(Window->hSelf, WM_QUERYOPEN, 0, 0))
333 {
334 return(SWP_NOSIZE | SWP_NOMOVE);
335 }
336 SwpFlags |= SWP_NOCOPYBITS;
337 }
338 switch (ShowFlag)
339 {
340 case SW_MINIMIZE:
341 {
342 if (Window->Style & WS_MAXIMIZE)
343 {
344 Window->Flags |= WINDOWOBJECT_RESTOREMAX;
345 Window->Style &= ~WS_MAXIMIZE;
346 }
347 else
348 {
349 Window->Flags &= ~WINDOWOBJECT_RESTOREMAX;
350 }
351 co_UserRedrawWindow(Window, NULL, 0, RDW_VALIDATE | RDW_NOERASE |
352 RDW_NOINTERNALPAINT);
353 Window->Style |= WS_MINIMIZE;
354 WinPosFindIconPos(Window, &InternalPos->IconPos);
355 IntGdiSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
356 UserGetSystemMetrics(SM_CXMINIMIZED),
357 UserGetSystemMetrics(SM_CYMINIMIZED));
358 SwpFlags |= SWP_NOCOPYBITS;
359 break;
360 }
361
362 case SW_MAXIMIZE:
363 {
364 co_WinPosGetMinMaxInfo(Window, NULL, &InternalPos->MaxPos,
365 NULL, &Size);
366 DPRINT("Maximize: %d,%d %dx%d\n",
367 InternalPos->MaxPos.x, InternalPos->MaxPos.y, Size.x, Size.y);
368 if (Window->Style & WS_MINIMIZE)
369 {
370 Window->Style &= ~WS_MINIMIZE;
371 }
372 Window->Style |= WS_MAXIMIZE;
373 IntGdiSetRect(NewPos, InternalPos->MaxPos.x, InternalPos->MaxPos.y,
374 Size.x, Size.y);
375 break;
376 }
377
378 case SW_RESTORE:
379 {
380 if (Window->Style & WS_MINIMIZE)
381 {
382 Window->Style &= ~WS_MINIMIZE;
383 if (Window->Flags & WINDOWOBJECT_RESTOREMAX)
384 {
385 co_WinPosGetMinMaxInfo(Window, NULL,
386 &InternalPos->MaxPos, NULL, &Size);
387 Window->Style |= WS_MAXIMIZE;
388 IntGdiSetRect(NewPos, InternalPos->MaxPos.x,
389 InternalPos->MaxPos.y, Size.x, Size.y);
390 break;
391 }
392 else
393 {
394 *NewPos = InternalPos->NormalRect;
395 NewPos->right -= NewPos->left;
396 NewPos->bottom -= NewPos->top;
397 break;
398 }
399 }
400 else
401 {
402 if (!(Window->Style & WS_MAXIMIZE))
403 {
404 return 0;
405 }
406 Window->Style &= ~WS_MAXIMIZE;
407 *NewPos = InternalPos->NormalRect;
408 NewPos->right -= NewPos->left;
409 NewPos->bottom -= NewPos->top;
410 break;
411 }
412 }
413 }
414 }
415 else
416 {
417 SwpFlags |= SWP_NOSIZE | SWP_NOMOVE;
418 }
419 return(SwpFlags);
420 }
421
422 VOID FASTCALL
423 WinPosFillMinMaxInfoStruct(PWINDOW_OBJECT Window, MINMAXINFO *Info)
424 {
425 UINT XInc, YInc;
426 RECT WorkArea;
427 PDESKTOP_OBJECT Desktop = PsGetWin32Thread()->Desktop; /* Or rather get it from the window? */
428
429 IntGetDesktopWorkArea(Desktop, &WorkArea);
430
431 /* Get default values. */
432 Info->ptMaxSize.x = WorkArea.right - WorkArea.left;
433 Info->ptMaxSize.y = WorkArea.bottom - WorkArea.top;
434 Info->ptMinTrackSize.x = UserGetSystemMetrics(SM_CXMINTRACK);
435 Info->ptMinTrackSize.y = UserGetSystemMetrics(SM_CYMINTRACK);
436 Info->ptMaxTrackSize.x = Info->ptMaxSize.x;
437 Info->ptMaxTrackSize.y = Info->ptMaxSize.y;
438
439 IntGetWindowBorderMeasures(Window, &XInc, &YInc);
440 Info->ptMaxTrackSize.x += 2 * XInc;
441 Info->ptMaxTrackSize.y += 2 * YInc;
442
443 if (Window->InternalPos != NULL)
444 {
445 Info->ptMaxPosition = Window->InternalPos->MaxPos;
446 }
447 else
448 {
449 Info->ptMaxPosition.x -= WorkArea.left + XInc;
450 Info->ptMaxPosition.y -= WorkArea.top + YInc;
451 }
452 }
453
454 UINT FASTCALL
455 co_WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
456 POINT* MinTrack, POINT* MaxTrack)
457 {
458 MINMAXINFO MinMax;
459
460 ASSERT_REFS_CO(Window);
461
462 WinPosFillMinMaxInfoStruct(Window, &MinMax);
463
464 co_IntSendMessage(Window->hSelf, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax);
465
466 MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
467 MinMax.ptMinTrackSize.x);
468 MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y,
469 MinMax.ptMinTrackSize.y);
470
471 if (MaxSize)
472 *MaxSize = MinMax.ptMaxSize;
473 if (MaxPos)
474 *MaxPos = MinMax.ptMaxPosition;
475 if (MinTrack)
476 *MinTrack = MinMax.ptMinTrackSize;
477 if (MaxTrack)
478 *MaxTrack = MinMax.ptMaxTrackSize;
479
480 return 0; //FIXME: what does it return?
481 }
482
483 STATIC VOID FASTCALL
484 FixClientRect(PRECT ClientRect, PRECT WindowRect)
485 {
486 if (ClientRect->left < WindowRect->left)
487 {
488 ClientRect->left = WindowRect->left;
489 }
490 else if (WindowRect->right < ClientRect->left)
491 {
492 ClientRect->left = WindowRect->right;
493 }
494 if (ClientRect->right < WindowRect->left)
495 {
496 ClientRect->right = WindowRect->left;
497 }
498 else if (WindowRect->right < ClientRect->right)
499 {
500 ClientRect->right = WindowRect->right;
501 }
502 if (ClientRect->top < WindowRect->top)
503 {
504 ClientRect->top = WindowRect->top;
505 }
506 else if (WindowRect->bottom < ClientRect->top)
507 {
508 ClientRect->top = WindowRect->bottom;
509 }
510 if (ClientRect->bottom < WindowRect->top)
511 {
512 ClientRect->bottom = WindowRect->top;
513 }
514 else if (WindowRect->bottom < ClientRect->bottom)
515 {
516 ClientRect->bottom = WindowRect->bottom;
517 }
518 }
519
520 LONG STATIC FASTCALL
521 co_WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos,
522 RECT* WindowRect, RECT* ClientRect)
523 {
524 PWINDOW_OBJECT Parent;
525 UINT wvrFlags = 0;
526
527 ASSERT_REFS_CO(Window);
528
529 /* Send WM_NCCALCSIZE message to get new client area */
530 if ((WinPos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE)
531 {
532 NCCALCSIZE_PARAMS params;
533 WINDOWPOS winposCopy;
534
535 params.rgrc[0] = *WindowRect;
536 params.rgrc[1] = Window->WindowRect;
537 params.rgrc[2] = Window->ClientRect;
538 Parent = Window->Parent;
539 if (0 != (Window->Style & WS_CHILD) && Parent)
540 {
541 IntGdiOffsetRect(&(params.rgrc[0]), - Parent->ClientRect.left,
542 - Parent->ClientRect.top);
543 IntGdiOffsetRect(&(params.rgrc[1]), - Parent->ClientRect.left,
544 - Parent->ClientRect.top);
545 IntGdiOffsetRect(&(params.rgrc[2]), - Parent->ClientRect.left,
546 - Parent->ClientRect.top);
547 }
548 params.lppos = &winposCopy;
549 winposCopy = *WinPos;
550
551 wvrFlags = co_IntSendMessage(Window->hSelf, WM_NCCALCSIZE, TRUE, (LPARAM) &params);
552
553 /* If the application send back garbage, ignore it */
554 if (params.rgrc[0].left <= params.rgrc[0].right &&
555 params.rgrc[0].top <= params.rgrc[0].bottom)
556 {
557 *ClientRect = params.rgrc[0];
558 if ((Window->Style & WS_CHILD) && Parent)
559 {
560 IntGdiOffsetRect(ClientRect, Parent->ClientRect.left,
561 Parent->ClientRect.top);
562 }
563 FixClientRect(ClientRect, WindowRect);
564 }
565
566 /* FIXME: WVR_ALIGNxxx */
567
568 if (ClientRect->left != Window->ClientRect.left ||
569 ClientRect->top != Window->ClientRect.top)
570 {
571 WinPos->flags &= ~SWP_NOCLIENTMOVE;
572 }
573
574 if ((ClientRect->right - ClientRect->left !=
575 Window->ClientRect.right - Window->ClientRect.left) ||
576 (ClientRect->bottom - ClientRect->top !=
577 Window->ClientRect.bottom - Window->ClientRect.top))
578 {
579 WinPos->flags &= ~SWP_NOCLIENTSIZE;
580 }
581 }
582 else
583 {
584 if (! (WinPos->flags & SWP_NOMOVE)
585 && (ClientRect->left != Window->ClientRect.left ||
586 ClientRect->top != Window->ClientRect.top))
587 {
588 WinPos->flags &= ~SWP_NOCLIENTMOVE;
589 }
590 }
591
592 return wvrFlags;
593 }
594
595 BOOL FASTCALL
596 co_WinPosDoWinPosChanging(PWINDOW_OBJECT Window,
597 PWINDOWPOS WinPos,
598 PRECT WindowRect,
599 PRECT ClientRect)
600 {
601 INT X, Y;
602
603 ASSERT_REFS_CO(Window);
604
605 if (!(WinPos->flags & SWP_NOSENDCHANGING))
606 {
607 co_IntSendMessage(Window->hSelf, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos);
608 }
609
610 *WindowRect = Window->WindowRect;
611 *ClientRect = Window->ClientRect;
612
613 if (!(WinPos->flags & SWP_NOSIZE))
614 {
615 WindowRect->right = WindowRect->left + WinPos->cx;
616 WindowRect->bottom = WindowRect->top + WinPos->cy;
617 }
618
619 if (!(WinPos->flags & SWP_NOMOVE))
620 {
621 PWINDOW_OBJECT Parent;
622 X = WinPos->x;
623 Y = WinPos->y;
624 Parent = Window->Parent;
625 if ((0 != (Window->Style & WS_CHILD)) && Parent)
626 {
627 X += Parent->ClientRect.left;
628 Y += Parent->ClientRect.top;
629 }
630
631 WindowRect->left = X;
632 WindowRect->top = Y;
633 WindowRect->right += X - Window->WindowRect.left;
634 WindowRect->bottom += Y - Window->WindowRect.top;
635 IntGdiOffsetRect(ClientRect,
636 X - Window->WindowRect.left,
637 Y - Window->WindowRect.top);
638 }
639
640 WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
641
642 return TRUE;
643 }
644
645 /*
646 * Fix Z order taking into account owned popups -
647 * basically we need to maintain them above the window that owns them
648 */
649 HWND FASTCALL
650 WinPosDoOwnedPopups(HWND hWnd, HWND hWndInsertAfter)
651 {
652 HWND *List = NULL;
653 HWND Owner = UserGetWindow(hWnd, GW_OWNER);
654 LONG Style = UserGetWindowLong(hWnd, GWL_STYLE, FALSE);
655 PWINDOW_OBJECT DesktopWindow, ChildObject;
656 int i;
657
658 if ((Style & WS_POPUP) && Owner)
659 {
660 /* Make sure this popup stays above the owner */
661 HWND hWndLocalPrev = HWND_TOPMOST;
662
663 if (hWndInsertAfter != HWND_TOPMOST)
664 {
665 DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
666 List = IntWinListChildren(DesktopWindow);
667 IntReleaseWindowObject(DesktopWindow);
668 if (List != NULL)
669 {
670 for (i = 0; List[i]; i++)
671 {
672 if (List[i] == Owner)
673 break;
674 if (HWND_TOP == hWndInsertAfter)
675 {
676 ChildObject = IntGetWindowObject(List[i]);
677 if (NULL != ChildObject)
678 {
679 if (0 == (ChildObject->ExStyle & WS_EX_TOPMOST))
680 {
681 IntReleaseWindowObject(ChildObject);
682 break;
683 }
684 IntReleaseWindowObject(ChildObject);
685 }
686 }
687 if (List[i] != hWnd)
688 hWndLocalPrev = List[i];
689 if (hWndLocalPrev == hWndInsertAfter)
690 break;
691 }
692 hWndInsertAfter = hWndLocalPrev;
693 }
694 }
695 }
696 else if (Style & WS_CHILD)
697 {
698 return hWndInsertAfter;
699 }
700
701 if (!List)
702 {
703 DesktopWindow = IntGetWindowObject(IntGetDesktopWindow());
704 List = IntWinListChildren(DesktopWindow);
705 IntReleaseWindowObject(DesktopWindow);
706 }
707 if (List != NULL)
708 {
709 for (i = 0; List[i]; i++)
710 {
711 PWINDOW_OBJECT Wnd;
712
713 if (List[i] == hWnd)
714 break;
715
716 if (!(Wnd = UserGetWindowObject(List[i])))
717 continue;
718
719 if ((Wnd->Style & WS_POPUP) &&
720 UserGetWindow(List[i], GW_OWNER) == hWnd)
721 {
722 UserRefObjectCo(Wnd);
723
724 co_WinPosSetWindowPos(Wnd, hWndInsertAfter, 0, 0, 0, 0,
725 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
726
727 UserDerefObjectCo(Wnd);
728
729 hWndInsertAfter = List[i];
730 }
731 }
732 ExFreePool(List);
733 }
734
735 return hWndInsertAfter;
736 }
737
738 /***********************************************************************
739 * WinPosInternalMoveWindow
740 *
741 * Update WindowRect and ClientRect of Window and all of its children
742 * We keep both WindowRect and ClientRect in screen coordinates internally
743 */
744 VOID STATIC FASTCALL
745 WinPosInternalMoveWindow(PWINDOW_OBJECT Window, INT MoveX, INT MoveY)
746 {
747 PWINDOW_OBJECT Child;
748
749 Window->WindowRect.left += MoveX;
750 Window->WindowRect.right += MoveX;
751 Window->WindowRect.top += MoveY;
752 Window->WindowRect.bottom += MoveY;
753
754 Window->ClientRect.left += MoveX;
755 Window->ClientRect.right += MoveX;
756 Window->ClientRect.top += MoveY;
757 Window->ClientRect.bottom += MoveY;
758
759 for(Child = Window->FirstChild; Child; Child = Child->NextSibling)
760 {
761 WinPosInternalMoveWindow(Child, MoveX, MoveY);
762 }
763 }
764
765 /*
766 * WinPosFixupSWPFlags
767 *
768 * Fix redundant flags and values in the WINDOWPOS structure.
769 */
770
771 BOOL FASTCALL
772 WinPosFixupFlags(WINDOWPOS *WinPos, PWINDOW_OBJECT Window)
773 {
774 if (Window->Style & WS_VISIBLE)
775 {
776 WinPos->flags &= ~SWP_SHOWWINDOW;
777 }
778 else
779 {
780 WinPos->flags &= ~SWP_HIDEWINDOW;
781 if (!(WinPos->flags & SWP_SHOWWINDOW))
782 WinPos->flags |= SWP_NOREDRAW;
783 }
784
785 WinPos->cx = max(WinPos->cx, 0);
786 WinPos->cy = max(WinPos->cy, 0);
787
788 /* Check for right size */
789 if (Window->WindowRect.right - Window->WindowRect.left == WinPos->cx &&
790 Window->WindowRect.bottom - Window->WindowRect.top == WinPos->cy)
791 {
792 WinPos->flags |= SWP_NOSIZE;
793 }
794
795 /* Check for right position */
796 if (Window->WindowRect.left == WinPos->x &&
797 Window->WindowRect.top == WinPos->y)
798 {
799 WinPos->flags |= SWP_NOMOVE;
800 }
801
802 if (WinPos->hwnd == UserGetForegroundWindow())
803 {
804 WinPos->flags |= SWP_NOACTIVATE; /* Already active */
805 }
806 else
807 if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
808 {
809 /* Bring to the top when activating */
810 if (!(WinPos->flags & SWP_NOACTIVATE))
811 {
812 WinPos->flags &= ~SWP_NOZORDER;
813 WinPos->hwndInsertAfter = (0 != (Window->ExStyle & WS_EX_TOPMOST) ?
814 HWND_TOPMOST : HWND_TOP);
815 return TRUE;
816 }
817 }
818
819 /* Check hwndInsertAfter */
820 if (!(WinPos->flags & SWP_NOZORDER))
821 {
822 /* Fix sign extension */
823 if (WinPos->hwndInsertAfter == (HWND)0xffff)
824 {
825 WinPos->hwndInsertAfter = HWND_TOPMOST;
826 }
827 else if (WinPos->hwndInsertAfter == (HWND)0xfffe)
828 {
829 WinPos->hwndInsertAfter = HWND_NOTOPMOST;
830 }
831
832 if (WinPos->hwndInsertAfter == HWND_NOTOPMOST)
833 {
834 WinPos->hwndInsertAfter = HWND_TOP;
835 }
836 else if (HWND_TOP == WinPos->hwndInsertAfter
837 && 0 != (Window->ExStyle & WS_EX_TOPMOST))
838 {
839 /* Keep it topmost when it's already topmost */
840 WinPos->hwndInsertAfter = HWND_TOPMOST;
841 }
842
843 /* hwndInsertAfter must be a sibling of the window */
844 if (HWND_TOPMOST != WinPos->hwndInsertAfter
845 && HWND_TOP != WinPos->hwndInsertAfter
846 && HWND_NOTOPMOST != WinPos->hwndInsertAfter
847 && HWND_BOTTOM != WinPos->hwndInsertAfter)
848 {
849 PWINDOW_OBJECT InsAfterWnd, Parent = Window->Parent;
850
851 InsAfterWnd = UserGetWindowObject(WinPos->hwndInsertAfter);
852
853 if (InsAfterWnd && UserGetAncestor(InsAfterWnd, GA_PARENT) != Parent)
854 {
855 return FALSE;
856 }
857 else
858 {
859 /*
860 * We don't need to change the Z order of hwnd if it's already
861 * inserted after hwndInsertAfter or when inserting hwnd after
862 * itself.
863 */
864 if ((WinPos->hwnd == WinPos->hwndInsertAfter) ||
865 (WinPos->hwnd == UserGetWindow(WinPos->hwndInsertAfter, GW_HWNDNEXT)))
866 {
867 WinPos->flags |= SWP_NOZORDER;
868 }
869 }
870 }
871 }
872
873 return TRUE;
874 }
875
876 /* x and y are always screen relative */
877 BOOLEAN FASTCALL
878 co_WinPosSetWindowPos(
879 PWINDOW_OBJECT Window,
880 HWND WndInsertAfter,
881 INT x,
882 INT y,
883 INT cx,
884 INT cy,
885 UINT flags
886 )
887 {
888 WINDOWPOS WinPos;
889 RECT NewWindowRect;
890 RECT NewClientRect;
891 PROSRGNDATA VisRgn;
892 HRGN VisBefore = NULL;
893 HRGN VisAfter = NULL;
894 HRGN DirtyRgn = NULL;
895 HRGN ExposedRgn = NULL;
896 HRGN CopyRgn = NULL;
897 ULONG WvrFlags = 0;
898 RECT OldWindowRect, OldClientRect;
899 int RgnType;
900 HDC Dc;
901 RECT CopyRect;
902 RECT TempRect;
903
904 ASSERT_REFS_CO(Window);
905
906 /* FIXME: Get current active window from active queue. */
907
908 /*
909 * Only allow CSRSS to mess with the desktop window
910 */
911 if (Window->hSelf == IntGetDesktopWindow() &&
912 Window->OwnerThread->ThreadsProcess != PsGetCurrentProcess())
913 {
914 return FALSE;
915 }
916
917 WinPos.hwnd = Window->hSelf;
918 WinPos.hwndInsertAfter = WndInsertAfter;
919 WinPos.x = x;
920 WinPos.y = y;
921 WinPos.cx = cx;
922 WinPos.cy = cy;
923 WinPos.flags = flags;
924
925 co_WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
926
927 /* Fix up the flags. */
928 if (!WinPosFixupFlags(&WinPos, Window))
929 {
930 SetLastWin32Error(ERROR_INVALID_PARAMETER);
931 return FALSE;
932 }
933
934 /* Does the window still exist? */
935 if (!IntIsWindow(WinPos.hwnd))
936 {
937 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
938 return FALSE;
939 }
940
941 if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
942 SWP_NOZORDER &&
943 // UserGetAncestor(WinPos.hwnd, GA_PARENT) == IntGetDesktopWindow())
944 //faxme: is WinPos.hwnd constant?? (WinPos.hwnd = Window->hSelf above)
945 UserGetAncestor(Window, GA_PARENT)->hSelf == IntGetDesktopWindow())
946 {
947 WinPos.hwndInsertAfter = WinPosDoOwnedPopups(WinPos.hwnd, WinPos.hwndInsertAfter);
948 }
949
950 if (!(WinPos.flags & SWP_NOREDRAW))
951 {
952 /* Compute the visible region before the window position is changed */
953 if (!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
954 (WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
955 SWP_HIDEWINDOW | SWP_FRAMECHANGED)) !=
956 (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
957 {
958 VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE);
959 VisRgn = NULL;
960
961 if (VisBefore != NULL && (VisRgn = (PROSRGNDATA)RGNDATA_LockRgn(VisBefore)) &&
962 UnsafeIntGetRgnBox(VisRgn, &TempRect) == NULLREGION)
963 {
964 RGNDATA_UnlockRgn(VisRgn);
965 NtGdiDeleteObject(VisBefore);
966 VisBefore = NULL;
967 }
968 else if(VisRgn)
969 {
970 RGNDATA_UnlockRgn(VisRgn);
971 }
972 }
973 }
974
975 WvrFlags = co_WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect);
976
977 /* Relink windows. (also take into account shell window in hwndShellWindow) */
978 if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow())
979 {
980 PWINDOW_OBJECT ParentWindow;
981 PWINDOW_OBJECT Sibling;
982 PWINDOW_OBJECT InsertAfterWindow;
983
984 if ((ParentWindow = Window->Parent))
985 {
986 if (HWND_TOPMOST == WinPos.hwndInsertAfter)
987 {
988 InsertAfterWindow = NULL;
989 }
990 else if (HWND_TOP == WinPos.hwndInsertAfter
991 || HWND_NOTOPMOST == WinPos.hwndInsertAfter)
992 {
993 InsertAfterWindow = NULL;
994 Sibling = ParentWindow->FirstChild;
995 while (NULL != Sibling && 0 != (Sibling->ExStyle & WS_EX_TOPMOST))
996 {
997 InsertAfterWindow = Sibling;
998 Sibling = Sibling->NextSibling;
999 }
1000 if (NULL != InsertAfterWindow)
1001 {
1002 IntReferenceWindowObject(InsertAfterWindow);
1003 }
1004 }
1005 else if (WinPos.hwndInsertAfter == HWND_BOTTOM)
1006 {
1007 if(ParentWindow->LastChild)
1008 {
1009 IntReferenceWindowObject(ParentWindow->LastChild);
1010 InsertAfterWindow = ParentWindow->LastChild;
1011 }
1012 else
1013 InsertAfterWindow = NULL;
1014 }
1015 else
1016 InsertAfterWindow = IntGetWindowObject(WinPos.hwndInsertAfter);
1017 /* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already
1018 the last window */
1019 if (InsertAfterWindow != Window)
1020 {
1021 IntUnlinkWindow(Window);
1022 IntLinkWindow(Window, ParentWindow, InsertAfterWindow);
1023 }
1024 if (InsertAfterWindow != NULL)
1025 IntReleaseWindowObject(InsertAfterWindow);
1026 if ((HWND_TOPMOST == WinPos.hwndInsertAfter)
1027 || (0 != (Window->ExStyle & WS_EX_TOPMOST)
1028 && NULL != Window->PrevSibling
1029 && 0 != (Window->PrevSibling->ExStyle & WS_EX_TOPMOST))
1030 || (NULL != Window->NextSibling
1031 && 0 != (Window->NextSibling->ExStyle & WS_EX_TOPMOST)))
1032 {
1033 Window->ExStyle |= WS_EX_TOPMOST;
1034 }
1035 else
1036 {
1037 Window->ExStyle &= ~ WS_EX_TOPMOST;
1038 }
1039
1040 }
1041 }
1042
1043 OldWindowRect = Window->WindowRect;
1044 OldClientRect = Window->ClientRect;
1045
1046 if (OldClientRect.bottom - OldClientRect.top ==
1047 NewClientRect.bottom - NewClientRect.top)
1048 {
1049 WvrFlags &= ~WVR_VREDRAW;
1050 }
1051
1052 if (OldClientRect.right - OldClientRect.left ==
1053 NewClientRect.right - NewClientRect.left)
1054 {
1055 WvrFlags &= ~WVR_HREDRAW;
1056 }
1057
1058 /* FIXME: Actually do something with WVR_VALIDRECTS */
1059
1060 if (NewClientRect.left != OldClientRect.left ||
1061 NewClientRect.top != OldClientRect.top)
1062 {
1063 WinPosInternalMoveWindow(Window,
1064 NewClientRect.left - OldClientRect.left,
1065 NewClientRect.top - OldClientRect.top);
1066 }
1067
1068 Window->WindowRect = NewWindowRect;
1069 Window->ClientRect = NewClientRect;
1070
1071 if (!(WinPos.flags & SWP_SHOWWINDOW) && (WinPos.flags & SWP_HIDEWINDOW))
1072 {
1073 /* Clear the update region */
1074 co_UserRedrawWindow(Window, NULL, 0, RDW_VALIDATE | RDW_NOFRAME |
1075 RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN);
1076 Window->Style &= ~WS_VISIBLE;
1077 }
1078 else if (WinPos.flags & SWP_SHOWWINDOW)
1079 {
1080 Window->Style |= WS_VISIBLE;
1081 }
1082
1083 DceResetActiveDCEs(Window);
1084
1085 if (!(WinPos.flags & SWP_NOREDRAW))
1086 {
1087 /* Determine the new visible region */
1088 VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE);
1089 VisRgn = NULL;
1090
1091 if (VisAfter != NULL && (VisRgn = (PROSRGNDATA)RGNDATA_LockRgn(VisAfter)) &&
1092 UnsafeIntGetRgnBox(VisRgn, &TempRect) == NULLREGION)
1093 {
1094 RGNDATA_UnlockRgn(VisRgn);
1095 NtGdiDeleteObject(VisAfter);
1096 VisAfter = NULL;
1097 }
1098 else if(VisRgn)
1099 {
1100 RGNDATA_UnlockRgn(VisRgn);
1101 }
1102
1103 /*
1104 * Determine which pixels can be copied from the old window position
1105 * to the new. Those pixels must be visible in both the old and new
1106 * position. Also, check the class style to see if the windows of this
1107 * class need to be completely repainted on (horizontal/vertical) size
1108 * change.
1109 */
1110 if (VisBefore != NULL && VisAfter != NULL && !(WinPos.flags & SWP_NOCOPYBITS) &&
1111 ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)))
1112 {
1113 CopyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
1114 RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
1115
1116 /*
1117 * If this is (also) a window resize, the whole nonclient area
1118 * needs to be repainted. So we limit the copy to the client area,
1119 * 'cause there is no use in copying it (would possibly cause
1120 * "flashing" too). However, if the copy region is already empty,
1121 * we don't have to crop (can't take anything away from an empty
1122 * region...)
1123 */
1124 if (!(WinPos.flags & SWP_NOSIZE) && RgnType != ERROR &&
1125 RgnType != NULLREGION)
1126 {
1127 RECT ORect = OldClientRect;
1128 RECT NRect = NewClientRect;
1129 IntGdiOffsetRect(&ORect, - OldWindowRect.left, - OldWindowRect.top);
1130 IntGdiOffsetRect(&NRect, - NewWindowRect.left, - NewWindowRect.top);
1131 IntGdiIntersectRect(&CopyRect, &ORect, &NRect);
1132 REGION_CropRgn(CopyRgn, CopyRgn, &CopyRect, NULL);
1133 }
1134
1135 /* No use in copying bits which are in the update region. */
1136 if (Window->UpdateRegion != NULL)
1137 {
1138 NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF);
1139 }
1140 if (Window->NCUpdateRegion != NULL)
1141 {
1142 NtGdiCombineRgn(CopyRgn, CopyRgn, Window->NCUpdateRegion, RGN_DIFF);
1143 }
1144
1145 /*
1146 * Now, get the bounding box of the copy region. If it's empty
1147 * there's nothing to copy. Also, it's no use copying bits onto
1148 * themselves.
1149 */
1150 if ((VisRgn = (PROSRGNDATA)RGNDATA_LockRgn(CopyRgn)) &&
1151 UnsafeIntGetRgnBox(VisRgn, &CopyRect) == NULLREGION)
1152 {
1153 /* Nothing to copy, clean up */
1154 RGNDATA_UnlockRgn(VisRgn);
1155 NtGdiDeleteObject(CopyRgn);
1156 CopyRgn = NULL;
1157 }
1158 else if (OldWindowRect.left != NewWindowRect.left ||
1159 OldWindowRect.top != NewWindowRect.top)
1160 {
1161 if(VisRgn)
1162 {
1163 RGNDATA_UnlockRgn(VisRgn);
1164 }
1165 /*
1166 * Small trick here: there is no function to bitblt a region. So
1167 * we set the region as the clipping region, take the bounding box
1168 * of the region and bitblt that. Since nothing outside the clipping
1169 * region is copied, this has the effect of bitblt'ing the region.
1170 *
1171 * Since NtUserGetDCEx takes ownership of the clip region, we need
1172 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1173 */
1174 HRGN ClipRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
1175
1176 NtGdiCombineRgn(ClipRgn, CopyRgn, NULL, RGN_COPY);
1177 Dc = UserGetDCEx(Window, ClipRgn, DCX_WINDOW | DCX_CACHE |
1178 DCX_INTERSECTRGN | DCX_CLIPSIBLINGS);
1179 NtGdiBitBlt(Dc,
1180 CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left,
1181 CopyRect.bottom - CopyRect.top, Dc,
1182 CopyRect.left + (OldWindowRect.left - NewWindowRect.left),
1183 CopyRect.top + (OldWindowRect.top - NewWindowRect.top), SRCCOPY);
1184 UserReleaseDC(Window, Dc);
1185 IntValidateParent(Window, CopyRgn);
1186 }
1187 else if(VisRgn)
1188 {
1189 RGNDATA_UnlockRgn(VisRgn);
1190 }
1191 }
1192 else
1193 {
1194 CopyRgn = NULL;
1195 }
1196
1197 /* We need to redraw what wasn't visible before */
1198 if (VisAfter != NULL)
1199 {
1200 DirtyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
1201 if (CopyRgn != NULL)
1202 {
1203 RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
1204 }
1205 else
1206 {
1207 RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY);
1208 }
1209 if (RgnType != ERROR && RgnType != NULLREGION)
1210 {
1211 NtGdiOffsetRgn(DirtyRgn,
1212 Window->WindowRect.left - Window->ClientRect.left,
1213 Window->WindowRect.top - Window->ClientRect.top);
1214 co_UserRedrawWindow(Window, NULL, DirtyRgn,
1215 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1216 }
1217 NtGdiDeleteObject(DirtyRgn);
1218 }
1219
1220 if (CopyRgn != NULL)
1221 {
1222 NtGdiDeleteObject(CopyRgn);
1223 }
1224
1225 /* Expose what was covered before but not covered anymore */
1226 if (VisBefore != NULL)
1227 {
1228 ExposedRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
1229 NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
1230 NtGdiOffsetRgn(ExposedRgn, OldWindowRect.left - NewWindowRect.left,
1231 OldWindowRect.top - NewWindowRect.top);
1232 if (VisAfter != NULL)
1233 RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
1234 else
1235 RgnType = SIMPLEREGION;
1236
1237 if (RgnType != ERROR && RgnType != NULLREGION)
1238 {
1239 co_VIS_WindowLayoutChanged(Window, ExposedRgn);
1240 }
1241 NtGdiDeleteObject(ExposedRgn);
1242 NtGdiDeleteObject(VisBefore);
1243 }
1244
1245 if (VisAfter != NULL)
1246 {
1247 NtGdiDeleteObject(VisAfter);
1248 }
1249
1250 if (!(WinPos.flags & SWP_NOACTIVATE))
1251 {
1252 if ((Window->Style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
1253 {
1254 co_IntSendMessage(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0);
1255 }
1256 else
1257 {
1258 co_IntSetForegroundWindow(Window);
1259 }
1260 }
1261 }
1262
1263 if ((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)
1264 co_IntSendMessage(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos);
1265
1266 return TRUE;
1267 }
1268
1269 LRESULT FASTCALL
1270 co_WinPosGetNonClientSize(PWINDOW_OBJECT Window, RECT* WindowRect, RECT* ClientRect)
1271 {
1272 LRESULT Result;
1273
1274 ASSERT_REFS_CO(Window);
1275
1276 *ClientRect = *WindowRect;
1277 Result = co_IntSendMessage(Window->hSelf, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect);
1278
1279 FixClientRect(ClientRect, WindowRect);
1280
1281 return Result;
1282 }
1283
1284 BOOLEAN FASTCALL
1285 co_WinPosShowWindow(PWINDOW_OBJECT Window, INT Cmd)
1286 {
1287 BOOLEAN WasVisible;
1288 UINT Swp = 0;
1289 RECT NewPos;
1290 BOOLEAN ShowFlag;
1291 // HRGN VisibleRgn;
1292
1293 ASSERT_REFS_CO(Window);
1294
1295 WasVisible = (Window->Style & WS_VISIBLE) != 0;
1296
1297 switch (Cmd)
1298 {
1299 case SW_HIDE:
1300 {
1301 if (!WasVisible)
1302 {
1303 return(FALSE);
1304 }
1305 Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1306 if (Window->hSelf != UserGetActiveWindow())
1307 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1308 break;
1309 }
1310
1311 case SW_SHOWMINNOACTIVE:
1312 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1313 /* Fall through. */
1314 case SW_SHOWMINIMIZED:
1315 Swp |= SWP_SHOWWINDOW;
1316 /* Fall through. */
1317 case SW_MINIMIZE:
1318 {
1319 Swp |= SWP_FRAMECHANGED | SWP_NOACTIVATE;
1320 if (!(Window->Style & WS_MINIMIZE))
1321 {
1322 Swp |= co_WinPosMinMaximize(Window, SW_MINIMIZE, &NewPos);
1323 }
1324 else
1325 {
1326 Swp |= SWP_NOSIZE | SWP_NOMOVE;
1327 }
1328 break;
1329 }
1330
1331 case SW_SHOWMAXIMIZED:
1332 {
1333 Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1334 if (!(Window->Style & WS_MAXIMIZE))
1335 {
1336 Swp |= co_WinPosMinMaximize(Window, SW_MAXIMIZE, &NewPos);
1337 }
1338 else
1339 {
1340 Swp |= SWP_NOSIZE | SWP_NOMOVE;
1341 }
1342 break;
1343 }
1344
1345 case SW_SHOWNA:
1346 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1347 /* Fall through. */
1348 case SW_SHOW:
1349 Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1350 /* Don't activate the topmost window. */
1351 break;
1352
1353 case SW_SHOWNOACTIVATE:
1354 Swp |= SWP_NOZORDER;
1355 /* Fall through. */
1356 case SW_SHOWNORMAL:
1357 case SW_SHOWDEFAULT:
1358 case SW_RESTORE:
1359 Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1360 if (Window->Style & (WS_MINIMIZE | WS_MAXIMIZE))
1361 {
1362 Swp |= co_WinPosMinMaximize(Window, SW_RESTORE, &NewPos);
1363 }
1364 else
1365 {
1366 Swp |= SWP_NOSIZE | SWP_NOMOVE;
1367 }
1368 break;
1369 }
1370
1371 ShowFlag = (Cmd != SW_HIDE);
1372 if (ShowFlag != WasVisible)
1373 {
1374 co_IntSendMessage(Window->hSelf, WM_SHOWWINDOW, ShowFlag, 0);
1375 /*
1376 * FIXME: Need to check the window wasn't destroyed during the
1377 * window procedure.
1378 */
1379 if (!(Window->Parent))
1380 {
1381 co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)Window->hSelf);
1382 }
1383 }
1384
1385 /* We can't activate a child window */
1386 if ((Window->Style & WS_CHILD) &&
1387 !(Window->ExStyle & WS_EX_MDICHILD))
1388 {
1389 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1390 }
1391
1392 co_WinPosSetWindowPos(Window, 0 != (Window->ExStyle & WS_EX_TOPMOST)
1393 ? HWND_TOPMOST : HWND_TOP,
1394 NewPos.left, NewPos.top, NewPos.right, NewPos.bottom, LOWORD(Swp));
1395
1396 if (Cmd == SW_HIDE)
1397 {
1398 /* FIXME: This will cause the window to be activated irrespective
1399 * of whether it is owned by the same thread. Has to be done
1400 * asynchronously.
1401 */
1402
1403 if (Window->hSelf == UserGetActiveWindow())
1404 {
1405 co_WinPosActivateOtherWindow(Window);
1406 }
1407
1408 /* Revert focus to parent */
1409 if (Window->hSelf == IntGetThreadFocusWindow() ||
1410 IntIsChildWindow(Window->hSelf, IntGetThreadFocusWindow()))
1411 {
1412 //faxme: as long as we have ref on Window, we also, indirectly, have ref on parent...
1413 co_UserSetFocus(Window->Parent);
1414 }
1415
1416 if (!(Window->Parent))
1417 {
1418 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (LPARAM)Window->hSelf);
1419 }
1420 }
1421
1422 /* FIXME: Check for window destruction. */
1423
1424 if ((Window->Flags & WINDOWOBJECT_NEED_SIZE) &&
1425 !(Window->Status & WINDOWSTATUS_DESTROYING))
1426 {
1427 WPARAM wParam = SIZE_RESTORED;
1428
1429 Window->Flags &= ~WINDOWOBJECT_NEED_SIZE;
1430 if (Window->Style & WS_MAXIMIZE)
1431 {
1432 wParam = SIZE_MAXIMIZED;
1433 }
1434 else if (Window->Style & WS_MINIMIZE)
1435 {
1436 wParam = SIZE_MINIMIZED;
1437 }
1438
1439 co_IntSendMessage(Window->hSelf, WM_SIZE, wParam,
1440 MAKELONG(Window->ClientRect.right -
1441 Window->ClientRect.left,
1442 Window->ClientRect.bottom -
1443 Window->ClientRect.top));
1444 co_IntSendMessage(Window->hSelf, WM_MOVE, 0,
1445 MAKELONG(Window->ClientRect.left,
1446 Window->ClientRect.top));
1447 IntEngWindowChanged(Window, WOC_RGN_CLIENT);
1448 }
1449
1450 /* Activate the window if activation is not requested and the window is not minimized */
1451 /*
1452 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->Style & WS_MINIMIZE))
1453 {
1454 WinPosChangeActiveWindow(Wnd, FALSE);
1455 }
1456 */
1457 return(WasVisible);
1458 }
1459
1460 STATIC VOID FASTCALL
1461 co_WinPosSearchChildren(
1462 PWINDOW_OBJECT ScopeWin, PUSER_MESSAGE_QUEUE OnlyHitTests, POINT *Point,
1463 PWINDOW_OBJECT* Window, USHORT *HitTest)
1464 {
1465 PWINDOW_OBJECT Current;
1466 HWND *List, *phWnd;
1467
1468 ASSERT_REFS_CO(ScopeWin);
1469
1470 if ((List = IntWinListChildren(ScopeWin)))
1471 {
1472 for (phWnd = List; *phWnd; ++phWnd)
1473 {
1474 if (!(Current = IntGetWindowObject(*phWnd)))
1475 continue;
1476
1477 if (!(Current->Style & WS_VISIBLE))
1478 {
1479 IntReleaseWindowObject(Current);
1480 continue;
1481 }
1482
1483 if ((Current->Style & (WS_POPUP | WS_CHILD | WS_DISABLED)) ==
1484 (WS_CHILD | WS_DISABLED))
1485 {
1486 IntReleaseWindowObject(Current);
1487 continue;
1488 }
1489
1490 if (!IntPtInWindow(Current, Point->x, Point->y))
1491 {
1492 IntReleaseWindowObject(Current);
1493 continue;
1494 }
1495
1496 if (*Window)
1497 IntReleaseWindowObject(*Window);
1498 *Window = Current;
1499
1500 if (Current->Style & WS_MINIMIZE)
1501 {
1502 *HitTest = HTCAPTION;
1503 break;
1504 }
1505
1506 if (Current->Style & WS_DISABLED)
1507 {
1508 *HitTest = HTERROR;
1509 break;
1510 }
1511
1512 if (OnlyHitTests && (Current->MessageQueue == OnlyHitTests))
1513 {
1514 *HitTest = co_IntSendMessage(Current->hSelf, WM_NCHITTEST, 0,
1515 MAKELONG(Point->x, Point->y));
1516 if ((*HitTest) == (USHORT)HTTRANSPARENT)
1517 continue;
1518 }
1519 else
1520 *HitTest = HTCLIENT;
1521
1522 if (Point->x >= Current->ClientRect.left &&
1523 Point->x < Current->ClientRect.right &&
1524 Point->y >= Current->ClientRect.top &&
1525 Point->y < Current->ClientRect.bottom)
1526 {
1527 co_WinPosSearchChildren(Current, OnlyHitTests, Point, Window, HitTest);
1528 }
1529
1530 break;
1531 }
1532 ExFreePool(List);
1533 }
1534 }
1535
1536 USHORT FASTCALL
1537 co_WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, PUSER_MESSAGE_QUEUE OnlyHitTests, POINT *WinPoint,
1538 PWINDOW_OBJECT* Window)
1539 {
1540 HWND DesktopWindowHandle;
1541 PWINDOW_OBJECT DesktopWindow;
1542 POINT Point = *WinPoint;
1543 USHORT HitTest;
1544
1545 ASSERT_REFS_CO(ScopeWin);
1546
1547 *Window = NULL;
1548
1549 if(!ScopeWin)
1550 {
1551 DPRINT1("WinPosWindowFromPoint(): ScopeWin == NULL!\n");
1552 return(HTERROR);
1553 }
1554
1555 if (ScopeWin->Style & WS_DISABLED)
1556 {
1557 return(HTERROR);
1558 }
1559
1560 /* Translate the point to the space of the scope window. */
1561 DesktopWindowHandle = IntGetDesktopWindow();
1562 if((DesktopWindowHandle != ScopeWin->hSelf) &&
1563 (DesktopWindow = IntGetWindowObject(DesktopWindowHandle)))
1564 {
1565 Point.x += ScopeWin->ClientRect.left - DesktopWindow->ClientRect.left;
1566 Point.y += ScopeWin->ClientRect.top - DesktopWindow->ClientRect.top;
1567 IntReleaseWindowObject(DesktopWindow);
1568 }
1569
1570 HitTest = HTNOWHERE;
1571
1572 co_WinPosSearchChildren(ScopeWin, OnlyHitTests, &Point, Window, &HitTest);
1573
1574 return ((*Window) ? HitTest : HTNOWHERE);
1575 }
1576
1577 BOOL
1578 STDCALL
1579 NtUserGetMinMaxInfo(
1580 HWND hWnd,
1581 MINMAXINFO *MinMaxInfo,
1582 BOOL SendMessage)
1583 {
1584 POINT Size;
1585 PINTERNALPOS InternalPos;
1586 PWINDOW_OBJECT Window = NULL;
1587 MINMAXINFO SafeMinMax;
1588 NTSTATUS Status;
1589 DECLARE_RETURN(BOOL);
1590
1591 DPRINT("Enter NtUserGetMinMaxInfo\n");
1592 UserEnterExclusive();
1593
1594 if(!(Window = UserGetWindowObject(hWnd)))
1595 {
1596 RETURN( FALSE);
1597 }
1598
1599 UserRefObjectCo(Window);
1600
1601 Size.x = Window->WindowRect.left;
1602 Size.y = Window->WindowRect.top;
1603 InternalPos = WinPosInitInternalPos(Window, &Size,
1604 &Window->WindowRect);
1605 if(InternalPos)
1606 {
1607 if(SendMessage)
1608 {
1609 co_WinPosGetMinMaxInfo(Window, &SafeMinMax.ptMaxSize, &SafeMinMax.ptMaxPosition,
1610 &SafeMinMax.ptMinTrackSize, &SafeMinMax.ptMaxTrackSize);
1611 }
1612 else
1613 {
1614 WinPosFillMinMaxInfoStruct(Window, &SafeMinMax);
1615 }
1616 Status = MmCopyToCaller(MinMaxInfo, &SafeMinMax, sizeof(MINMAXINFO));
1617 if(!NT_SUCCESS(Status))
1618 {
1619 SetLastNtError(Status);
1620 RETURN( FALSE);
1621 }
1622
1623 RETURN( TRUE);
1624 }
1625
1626 RETURN( FALSE);
1627
1628 CLEANUP:
1629 if (Window)
1630 UserDerefObjectCo(Window);
1631
1632 DPRINT("Leave NtUserGetMinMaxInfo, ret=%i\n",_ret_);
1633 UserLeave();
1634 END_CLEANUP;
1635 }
1636
1637 /* EOF */