- Store GDI object type in the handle itself
[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.26 2003/08/20 07:45:01 gvg 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 BOOL FASTCALL
99 WinPosActivateOtherWindow(PWINDOW_OBJECT Window)
100 {
101 return FALSE;
102 }
103
104 POINT STATIC FASTCALL
105 WinPosFindIconPos(HWND hWnd, POINT Pos)
106 {
107 POINT point;
108 //FIXME
109 return point;
110 }
111
112 HWND STATIC FASTCALL
113 WinPosNtGdiIconTitle(PWINDOW_OBJECT WindowObject)
114 {
115 return(NULL);
116 }
117
118 BOOL STATIC FASTCALL
119 WinPosShowIconTitle(PWINDOW_OBJECT WindowObject, BOOL Show)
120 {
121 PINTERNALPOS InternalPos = (PINTERNALPOS)IntGetProp(WindowObject, AtomInternalPos);
122 PWINDOW_OBJECT IconWindow;
123 NTSTATUS Status;
124
125 if (InternalPos)
126 {
127 HWND hWnd = InternalPos->IconTitle;
128
129 if (hWnd == NULL)
130 {
131 hWnd = WinPosNtGdiIconTitle(WindowObject);
132 }
133 if (Show)
134 {
135 Status =
136 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->
137 HandleTable,
138 hWnd,
139 otWindow,
140 (PVOID*)&IconWindow);
141 if (NT_SUCCESS(Status))
142 {
143 if (!(IconWindow->Style & WS_VISIBLE))
144 {
145 NtUserSendMessage(hWnd, WM_SHOWWINDOW, TRUE, 0);
146 WinPosSetWindowPos(hWnd, 0, 0, 0, 0, 0, SWP_NOSIZE |
147 SWP_NOMOVE | SWP_NOACTIVATE |
148 SWP_NOZORDER | SWP_SHOWWINDOW);
149 }
150 ObmDereferenceObject(IconWindow);
151 }
152 }
153 else
154 {
155 WinPosShowWindow(hWnd, SW_HIDE);
156 }
157 }
158 return(FALSE);
159 }
160
161 PINTERNALPOS STATIC STDCALL
162 WinPosInitInternalPos(PWINDOW_OBJECT WindowObject, POINT pt, PRECT RestoreRect)
163 {
164 PINTERNALPOS InternalPos = (PINTERNALPOS)IntGetProp(WindowObject, AtomInternalPos);
165 if (InternalPos == NULL)
166 {
167 InternalPos =
168 ExAllocatePool(NonPagedPool, sizeof(INTERNALPOS));
169 IntSetProp(WindowObject, AtomInternalPos, InternalPos);
170 InternalPos->IconTitle = 0;
171 InternalPos->NormalRect = WindowObject->WindowRect;
172 InternalPos->IconPos.x = InternalPos->MaxPos.x = 0xFFFFFFFF;
173 InternalPos->IconPos.y = InternalPos->MaxPos.y = 0xFFFFFFFF;
174 }
175 if (WindowObject->Style & WS_MINIMIZE)
176 {
177 InternalPos->IconPos = pt;
178 }
179 else if (WindowObject->Style & WS_MAXIMIZE)
180 {
181 InternalPos->MaxPos = pt;
182 }
183 else if (RestoreRect != NULL)
184 {
185 InternalPos->NormalRect = *RestoreRect;
186 }
187 return(InternalPos);
188 }
189
190 UINT STDCALL
191 WinPosMinMaximize(PWINDOW_OBJECT WindowObject, UINT ShowFlag, RECT* NewPos)
192 {
193 POINT Size;
194 PINTERNALPOS InternalPos;
195 UINT SwpFlags = 0;
196
197 Size.x = WindowObject->WindowRect.left;
198 Size.y = WindowObject->WindowRect.top;
199 InternalPos = WinPosInitInternalPos(WindowObject, Size,
200 &WindowObject->WindowRect);
201
202 if (InternalPos)
203 {
204 if (WindowObject->Style & WS_MINIMIZE)
205 {
206 if (!NtUserSendMessage(WindowObject->Self, WM_QUERYOPEN, 0, 0))
207 {
208 return(SWP_NOSIZE | SWP_NOMOVE);
209 }
210 SwpFlags |= SWP_NOCOPYBITS;
211 }
212 switch (ShowFlag)
213 {
214 case SW_MINIMIZE:
215 {
216 if (WindowObject->Style & WS_MAXIMIZE)
217 {
218 WindowObject->Flags |= WINDOWOBJECT_RESTOREMAX;
219 WindowObject->Style &= ~WS_MAXIMIZE;
220 }
221 else
222 {
223 WindowObject->Style &= ~WINDOWOBJECT_RESTOREMAX;
224 }
225 WindowObject->Style |= WS_MINIMIZE;
226 InternalPos->IconPos = WinPosFindIconPos(WindowObject,
227 InternalPos->IconPos);
228 NtGdiSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
229 NtUserGetSystemMetrics(SM_CXICON),
230 NtUserGetSystemMetrics(SM_CYICON));
231 SwpFlags |= SWP_NOCOPYBITS;
232 break;
233 }
234
235 case SW_MAXIMIZE:
236 {
237 WinPosGetMinMaxInfo(WindowObject, &Size, &InternalPos->MaxPos,
238 NULL, NULL);
239 if (WindowObject->Style & WS_MINIMIZE)
240 {
241 WinPosShowIconTitle(WindowObject, FALSE);
242 WindowObject->Style &= ~WS_MINIMIZE;
243 }
244 WindowObject->Style |= WS_MINIMIZE;
245 NtGdiSetRect(NewPos, InternalPos->MaxPos.x, InternalPos->MaxPos.y,
246 Size.x, Size.y);
247 break;
248 }
249
250 case SW_RESTORE:
251 {
252 if (WindowObject->Style & WS_MINIMIZE)
253 {
254 WindowObject->Style &= ~WS_MINIMIZE;
255 WinPosShowIconTitle(WindowObject, FALSE);
256 if (WindowObject->Flags & WINDOWOBJECT_RESTOREMAX)
257 {
258 WinPosGetMinMaxInfo(WindowObject, &Size,
259 &InternalPos->MaxPos, NULL, NULL);
260 WindowObject->Style |= WS_MAXIMIZE;
261 NtGdiSetRect(NewPos, InternalPos->MaxPos.x,
262 InternalPos->MaxPos.y, Size.x, Size.y);
263 break;
264 }
265 }
266 else
267 {
268 if (!(WindowObject->Style & WS_MAXIMIZE))
269 {
270 return(-1);
271 }
272 else
273 {
274 WindowObject->Style &= ~WS_MAXIMIZE;
275 }
276 *NewPos = InternalPos->NormalRect;
277 NewPos->right -= NewPos->left;
278 NewPos->bottom -= NewPos->top;
279 break;
280 }
281 }
282 }
283 }
284 else
285 {
286 SwpFlags |= SWP_NOSIZE | SWP_NOMOVE;
287 }
288 return(SwpFlags);
289 }
290
291 UINT STDCALL
292 WinPosGetMinMaxInfo(PWINDOW_OBJECT Window, POINT* MaxSize, POINT* MaxPos,
293 POINT* MinTrack, POINT* MaxTrack)
294 {
295 MINMAXINFO MinMax;
296 INT XInc, YInc;
297 INTERNALPOS* Pos;
298
299 /* Get default values. */
300 MinMax.ptMaxSize.x = NtUserGetSystemMetrics(SM_CXSCREEN);
301 MinMax.ptMaxSize.y = NtUserGetSystemMetrics(SM_CYSCREEN);
302 MinMax.ptMinTrackSize.x = NtUserGetSystemMetrics(SM_CXMINTRACK);
303 MinMax.ptMinTrackSize.y = NtUserGetSystemMetrics(SM_CYMINTRACK);
304 MinMax.ptMaxTrackSize.x = NtUserGetSystemMetrics(SM_CXSCREEN);
305 MinMax.ptMaxTrackSize.y = NtUserGetSystemMetrics(SM_CYSCREEN);
306
307 if (HAS_DLGFRAME(Window->Style, Window->ExStyle))
308 {
309 XInc = NtUserGetSystemMetrics(SM_CXDLGFRAME);
310 YInc = NtUserGetSystemMetrics(SM_CYDLGFRAME);
311 }
312 else
313 {
314 XInc = YInc = 0;
315 if (HAS_THICKFRAME(Window->Style, Window->ExStyle))
316 {
317 XInc += NtUserGetSystemMetrics(SM_CXFRAME);
318 YInc += NtUserGetSystemMetrics(SM_CYFRAME);
319 }
320 if (Window->Style & WS_BORDER)
321 {
322 XInc += NtUserGetSystemMetrics(SM_CXBORDER);
323 YInc += NtUserGetSystemMetrics(SM_CYBORDER);
324 }
325 }
326 MinMax.ptMaxSize.x += 2 * XInc;
327 MinMax.ptMaxSize.y += 2 * YInc;
328
329 Pos = (PINTERNALPOS)IntGetProp(Window, AtomInternalPos);
330 if (Pos != NULL)
331 {
332 MinMax.ptMaxPosition = Pos->MaxPos;
333 }
334 else
335 {
336 MinMax.ptMaxPosition.x -= XInc;
337 MinMax.ptMaxPosition.y -= YInc;
338 }
339
340 IntSendMessage(Window->Self, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax, TRUE);
341
342 MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
343 MinMax.ptMinTrackSize.x);
344 MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y,
345 MinMax.ptMinTrackSize.y);
346
347 if (MaxSize) *MaxSize = MinMax.ptMaxSize;
348 if (MaxPos) *MaxPos = MinMax.ptMaxPosition;
349 if (MinTrack) *MinTrack = MinMax.ptMinTrackSize;
350 if (MaxTrack) *MaxTrack = MinMax.ptMaxTrackSize;
351
352 return 0; //FIXME: what does it return?
353 }
354
355 BOOL STATIC FASTCALL
356 WinPosChangeActiveWindow(HWND hWnd, BOOL MouseMsg)
357 {
358 PWINDOW_OBJECT WindowObject;
359
360 WindowObject = IntGetWindowObject(hWnd);
361 if (WindowObject == NULL)
362 {
363 return FALSE;
364 }
365
366 NtUserSendMessage(hWnd,
367 WM_ACTIVATE,
368 MAKELONG(MouseMsg ? WA_CLICKACTIVE : WA_CLICKACTIVE,
369 (WindowObject->Style & WS_MINIMIZE) ? 1 : 0),
370 (LPARAM)IntGetDesktopWindow()); /* FIXME: Previous active window */
371
372 IntReleaseWindowObject(WindowObject);
373
374 return TRUE;
375 }
376
377 LONG STATIC STDCALL
378 WinPosDoNCCALCSize(PWINDOW_OBJECT Window, PWINDOWPOS WinPos,
379 RECT* WindowRect, RECT* ClientRect)
380 {
381 return 0; /* FIXME: Calculate non client size */
382 }
383
384 BOOL STDCALL
385 WinPosDoWinPosChanging(PWINDOW_OBJECT WindowObject,
386 PWINDOWPOS WinPos,
387 PRECT WindowRect,
388 PRECT ClientRect)
389 {
390 if (!(WinPos->flags & SWP_NOSENDCHANGING))
391 {
392 IntSendWINDOWPOSCHANGINGMessage(WindowObject->Self, WinPos);
393 }
394
395 *WindowRect = WindowObject->WindowRect;
396 *ClientRect =
397 (WindowObject->Style & WS_MINIMIZE) ? WindowObject->WindowRect :
398 WindowObject->ClientRect;
399
400 if (!(WinPos->flags & SWP_NOSIZE))
401 {
402 WindowRect->right = WindowRect->left + WinPos->cx;
403 WindowRect->bottom = WindowRect->top + WinPos->cy;
404 }
405
406 if (!(WinPos->flags & SWP_NOMOVE))
407 {
408 WindowRect->left = WinPos->x;
409 WindowRect->top = WinPos->y;
410 WindowRect->right += WinPos->x - WindowObject->WindowRect.left;
411 WindowRect->bottom += WinPos->y - WindowObject->WindowRect.top;
412 }
413
414 if (!(WinPos->flags & SWP_NOSIZE) || !(WinPos->flags & SWP_NOMOVE))
415 {
416 WinPosGetNonClientSize(WindowObject->Self, WindowRect, ClientRect);
417 }
418
419 WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
420 return(TRUE);
421 }
422
423 /***********************************************************************
424 * SWP_DoSimpleFrameChanged
425 *
426 * NOTE: old and new client rect origins are identical, only
427 * extents may have changed. Window extents are the same.
428 */
429 VOID STATIC
430 WinPosDoSimpleFrameChanged( PWINDOW_OBJECT wndPtr, RECT* pOldClientRect, WORD swpFlags, UINT uFlags )
431 {
432 INT i = 0;
433 RECT rect;
434 HRGN hrgn = 0;
435
436 if( !(swpFlags & SWP_NOCLIENTSIZE) )
437 {
438 /* Client rect changed its position/size, most likely a scrollar
439 * was added/removed.
440 *
441 * FIXME: WVR alignment flags
442 */
443
444 if( wndPtr->ClientRect.right > pOldClientRect->right ) /* right edge */
445 {
446 i++;
447 rect.top = 0;
448 rect.bottom = wndPtr->ClientRect.bottom - wndPtr->ClientRect.top;
449 rect.right = wndPtr->ClientRect.right - wndPtr->ClientRect.left;
450 if(!(uFlags & SWP_EX_NOCOPY))
451 rect.left = pOldClientRect->right - wndPtr->ClientRect.left;
452 else
453 {
454 rect.left = 0;
455 goto redraw;
456 }
457 }
458
459 if( wndPtr->ClientRect.bottom > pOldClientRect->bottom ) /* bottom edge */
460 {
461 if( i )
462 hrgn = NtGdiCreateRectRgnIndirect( &rect );
463 rect.left = 0;
464 rect.right = wndPtr->ClientRect.right - wndPtr->ClientRect.left;
465 rect.bottom = wndPtr->ClientRect.bottom - wndPtr->ClientRect.top;
466 if(!(uFlags & SWP_EX_NOCOPY))
467 rect.top = pOldClientRect->bottom - wndPtr->ClientRect.top;
468 else
469 rect.top = 0;
470 if( i++ )
471 {
472 HRGN hRectRgn = NtGdiCreateRectRgnIndirect(&rect);
473 NtGdiCombineRgn(hrgn, hrgn, hRectRgn, RGN_OR);
474 NtGdiDeleteObject(hRectRgn);
475 }
476 }
477
478 if( i == 0 && (uFlags & SWP_EX_NOCOPY) ) /* force redraw anyway */
479 {
480 rect = wndPtr->WindowRect;
481 NtGdiOffsetRect( &rect, wndPtr->WindowRect.left - wndPtr->ClientRect.left,
482 wndPtr->WindowRect.top - wndPtr->ClientRect.top );
483 i++;
484 }
485 }
486
487 if( i )
488 {
489 redraw:
490 PaintRedrawWindow( wndPtr, &rect, hrgn, RDW_INVALIDATE | RDW_FRAME | RDW_ERASE |
491 RDW_ERASENOW | RDW_ALLCHILDREN, RDW_EX_TOPFRAME | RDW_EX_USEHRGN );
492 }
493 else
494 {
495 PaintUpdateNCRegion(wndPtr, 0, UNC_UPDATE | UNC_ENTIRE);
496 }
497
498 if( hrgn > (HRGN)1 )
499 NtGdiDeleteObject( hrgn );
500 }
501
502 /***********************************************************************
503 * SWP_CopyValidBits
504 *
505 * Make window look nice without excessive repainting
506 *
507 * visible and update regions are in window coordinates
508 * client and window rectangles are in parent client coordinates
509 *
510 * Returns: uFlags and a dirty region in *pVisRgn.
511 */
512 static UINT WinPosCopyValidBits( PWINDOW_OBJECT Wnd, HRGN* pVisRgn,
513 LPRECT lpOldWndRect,
514 LPRECT lpOldClientRect, UINT uFlags )
515 {
516 RECT r;
517 HRGN newVisRgn, dirtyRgn;
518 INT my = COMPLEXREGION;
519
520 if( Wnd->UpdateRegion == (HRGN)1 )
521 uFlags |= SWP_EX_NOCOPY; /* whole window is invalid, nothing to copy */
522
523 newVisRgn = DceGetVisRgn( Wnd->Self, DCX_WINDOW | DCX_CLIPSIBLINGS, 0, 0);
524 NtGdiOffsetRgn(newVisRgn, -Wnd->WindowRect.left, -Wnd->WindowRect.top);
525 dirtyRgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
526
527 if( !(uFlags & SWP_EX_NOCOPY) ) /* make sure dst region covers only valid bits */
528 my = NtGdiCombineRgn( dirtyRgn, newVisRgn, *pVisRgn, RGN_AND );
529
530 if( (my == NULLREGION) || (uFlags & SWP_EX_NOCOPY) )
531 {
532 nocopy:
533
534 /* set dirtyRgn to the sum of old and new visible regions
535 * in parent client coordinates */
536
537 NtGdiOffsetRgn( newVisRgn, Wnd->WindowRect.left, Wnd->WindowRect.top );
538 NtGdiOffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
539
540 NtGdiCombineRgn(*pVisRgn, *pVisRgn, newVisRgn, RGN_OR );
541 }
542 else /* copy valid bits to a new location */
543 {
544 INT dx, dy, ow, oh, nw, nh, ocw, ncw, och, nch;
545 HRGN hrgnValid = dirtyRgn; /* non-empty intersection of old and new visible rgns */
546
547 /* subtract already invalid region inside Wnd from the dst region */
548
549 if( Wnd->UpdateRegion )
550 if( NtGdiCombineRgn( hrgnValid, hrgnValid, Wnd->UpdateRegion, RGN_DIFF) == NULLREGION )
551 goto nocopy;
552
553 /* check if entire window can be copied */
554
555 ow = lpOldWndRect->right - lpOldWndRect->left;
556 oh = lpOldWndRect->bottom - lpOldWndRect->top;
557 nw = Wnd->WindowRect.right - Wnd->WindowRect.left;
558 nh = Wnd->WindowRect.bottom - Wnd->WindowRect.top;
559
560 ocw = lpOldClientRect->right - lpOldClientRect->left;
561 och = lpOldClientRect->bottom - lpOldClientRect->top;
562 ncw = Wnd->ClientRect.right - Wnd->ClientRect.left;
563 nch = Wnd->ClientRect.bottom - Wnd->ClientRect.top;
564
565 if( (ocw != ncw) || (och != nch) ||
566 ( ow != nw) || ( oh != nh) ||
567 ((lpOldClientRect->top - lpOldWndRect->top) !=
568 (Wnd->ClientRect.top - Wnd->WindowRect.top)) ||
569 ((lpOldClientRect->left - lpOldWndRect->left) !=
570 (Wnd->ClientRect.left - Wnd->WindowRect.left)) )
571 {
572 if(uFlags & SWP_EX_PAINTSELF)
573 {
574 /* movement relative to the window itself */
575 dx = (Wnd->ClientRect.left - Wnd->WindowRect.left) -
576 (lpOldClientRect->left - lpOldWndRect->left) ;
577 dy = (Wnd->ClientRect.top - Wnd->WindowRect.top) -
578 (lpOldClientRect->top - lpOldWndRect->top) ;
579 }
580 else
581 {
582 /* movement relative to the parent's client area */
583 dx = Wnd->ClientRect.left - lpOldClientRect->left;
584 dy = Wnd->ClientRect.top - lpOldClientRect->top;
585 }
586
587 /* restrict valid bits to the common client rect */
588
589 r.left = Wnd->ClientRect.left - Wnd->WindowRect.left;
590 r.top = Wnd->ClientRect.top - Wnd->WindowRect.top;
591 r.right = r.left + min( ocw, ncw );
592 r.bottom = r.top + min( och, nch );
593
594 REGION_CropRgn( hrgnValid, hrgnValid, &r,
595 (uFlags & SWP_EX_PAINTSELF) ? NULL : (POINT*)&(Wnd->WindowRect));
596 NtGdiGetRgnBox( hrgnValid, &r );
597 if( NtGdiIsEmptyRect( &r ) )
598 goto nocopy;
599 r = *lpOldClientRect;
600 }
601 else
602 {
603 if(uFlags & SWP_EX_PAINTSELF) {
604 /*
605 * with SWP_EX_PAINTSELF, the window repaints itself. Since a window can't move
606 * relative to itself, only the client area can change.
607 * if the client rect didn't change, there's nothing to do.
608 */
609 dx = 0;
610 dy = 0;
611 }
612 else
613 {
614 dx = Wnd->WindowRect.left - lpOldWndRect->left;
615 dy = Wnd->WindowRect.top - lpOldWndRect->top;
616 NtGdiOffsetRgn( hrgnValid, Wnd->WindowRect.left, Wnd->WindowRect.top );
617 }
618 r = *lpOldWndRect;
619 }
620
621 if( !(uFlags & SWP_EX_PAINTSELF) )
622 {
623 /* Move remaining regions to parent coordinates */
624 NtGdiOffsetRgn( newVisRgn, Wnd->WindowRect.left, Wnd->WindowRect.top );
625 NtGdiOffsetRgn( *pVisRgn, lpOldWndRect->left, lpOldWndRect->top );
626 }
627 else
628 NtGdiOffsetRect( &r, -lpOldWndRect->left, -lpOldWndRect->top );
629
630 /* Compute combined dirty region (old + new - valid) */
631 NtGdiCombineRgn( *pVisRgn, *pVisRgn, newVisRgn, RGN_OR);
632 NtGdiCombineRgn( *pVisRgn, *pVisRgn, hrgnValid, RGN_DIFF);
633
634 /* Blt valid bits, r is the rect to copy */
635
636 if( dx || dy )
637 {
638 RECT rClip;
639 HDC hDC;
640
641 /* get DC and clip rect with drawable rect to avoid superfluous expose events
642 from copying clipped areas */
643
644 if( uFlags & SWP_EX_PAINTSELF )
645 {
646 hDC = NtUserGetDCEx( Wnd->Self, hrgnValid, DCX_WINDOW | DCX_CACHE |
647 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
648 rClip.right = nw; rClip.bottom = nh;
649 }
650 else
651 {
652 hDC = NtUserGetDCEx( Wnd->Parent->Self, hrgnValid, DCX_CACHE |
653 DCX_KEEPCLIPRGN | DCX_INTERSECTRGN | DCX_CLIPSIBLINGS );
654 rClip.right = Wnd->Parent->ClientRect.right - Wnd->Parent->ClientRect.left;
655 rClip.bottom = Wnd->Parent->ClientRect.bottom - Wnd->Parent->ClientRect.top;
656 }
657 rClip.left = rClip.top = 0;
658
659 if( oh > nh ) r.bottom = r.top + nh;
660 if( ow < nw ) r.right = r.left + nw;
661
662 if( NtGdiIntersectRect( &r, &r, &rClip ) )
663 {
664 NtGdiBitBlt(hDC, dx + r.left, dy + r.top, r.right - r.left, r.bottom - r.top, hDC, r.left, r.top, SRCCOPY);
665
666 /* When you copy the bits without repainting, parent doesn't
667 get validated appropriately. Therefore, we have to validate
668 the parent with the windows' updated region when the
669 parent's update region is not empty. */
670
671 if (Wnd->Parent->UpdateRegion != 0 && !(Wnd->Parent->Style & WS_CLIPCHILDREN))
672 {
673 NtGdiOffsetRect(&r, dx, dy);
674 NtUserValidateRect(Wnd->Parent->Self, &r);
675 }
676 }
677 NtUserReleaseDC( (uFlags & SWP_EX_PAINTSELF) ?
678 Wnd->Self : Wnd->Parent->Self, hDC);
679 }
680 }
681
682 /* *pVisRgn now points to the invalidated region */
683
684 NtGdiDeleteObject(newVisRgn);
685 NtGdiDeleteObject(dirtyRgn);
686 return uFlags;
687 }
688
689
690 BOOLEAN STDCALL
691 WinPosSetWindowPos(HWND Wnd, HWND WndInsertAfter, INT x, INT y, INT cx,
692 INT cy, UINT flags)
693 {
694 PWINDOW_OBJECT Window;
695 NTSTATUS Status;
696 WINDOWPOS WinPos;
697 RECT NewWindowRect;
698 RECT NewClientRect;
699 HRGN VisRgn = NULL;
700 HRGN VisibleRgn = NULL;
701 ULONG WvrFlags = 0;
702 RECT OldWindowRect, OldClientRect;
703 UINT FlagsEx = 0;
704
705 /* FIXME: Get current active window from active queue. */
706
707 /* Check if the window is for a desktop. */
708 if (Wnd == PsGetWin32Thread()->Desktop->DesktopWindow)
709 {
710 return(FALSE);
711 }
712
713 Status =
714 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
715 Wnd,
716 otWindow,
717 (PVOID*)&Window);
718 if (!NT_SUCCESS(Status))
719 {
720 return(FALSE);
721 }
722
723 /* Fix up the flags. */
724 if (Window->Style & WS_VISIBLE)
725 {
726 flags &= ~SWP_SHOWWINDOW;
727 }
728 else
729 {
730 if (!(flags & SWP_SHOWWINDOW))
731 {
732 flags |= SWP_NOREDRAW;
733 }
734 flags &= ~SWP_HIDEWINDOW;
735 }
736
737 cx = max(cx, 0);
738 cy = max(cy, 0);
739
740 if ((Window->WindowRect.right - Window->WindowRect.left) == cx &&
741 (Window->WindowRect.bottom - Window->WindowRect.top) == cy)
742 {
743 flags |= SWP_NOSIZE;
744 }
745 if (Window->WindowRect.left == x && Window->WindowRect.top == y)
746 {
747 flags |= SWP_NOMOVE;
748 }
749 if (Window->Style & WIN_NCACTIVATED)
750 {
751 flags |= SWP_NOACTIVATE;
752 }
753 else if ((Window->Style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
754 {
755 if (!(flags & SWP_NOACTIVATE))
756 {
757 flags &= ~SWP_NOZORDER;
758 WndInsertAfter = HWND_TOP;
759 }
760 }
761
762 if (WndInsertAfter == HWND_TOPMOST || WndInsertAfter == HWND_NOTOPMOST)
763 {
764 WndInsertAfter = HWND_TOP;
765 }
766
767 if (WndInsertAfter != HWND_TOP && WndInsertAfter != HWND_BOTTOM)
768 {
769 /* FIXME: Find the window to insert after. */
770 }
771
772 WinPos.hwnd = Wnd;
773 WinPos.hwndInsertAfter = WndInsertAfter;
774 WinPos.x = x;
775 WinPos.y = y;
776 WinPos.cx = cx;
777 WinPos.cy = cy;
778 WinPos.flags = flags;
779
780 WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
781
782 if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
783 SWP_NOZORDER)
784 {
785 /* FIXME: SWP_DoOwnedPopups. */
786 }
787
788 /* FIXME: Adjust flags based on WndInsertAfter */
789
790 if ((!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
791 WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
792 SWP_HIDEWINDOW | SWP_FRAMECHANGED)) !=
793 (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
794 {
795 if (Window->Style & WS_CLIPCHILDREN)
796 {
797 VisRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
798 Window, FALSE, FALSE, TRUE);
799 }
800 else
801 {
802 VisRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop,
803 Window, FALSE, FALSE, FALSE);
804 }
805 NtGdiOffsetRgn(VisRgn, -Window->WindowRect.left, -Window->WindowRect.top);
806 }
807
808 WvrFlags = WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect,
809 &NewClientRect);
810
811 /* FIXME: Relink windows. */
812
813 /* FIXME: Reset active DCEs */
814
815 OldWindowRect = Window->WindowRect;
816 OldClientRect = Window->ClientRect;
817
818 /* FIXME: Check for redrawing the whole client rect. */
819
820 Window->WindowRect = NewWindowRect;
821 Window->ClientRect = NewClientRect;
822
823 if (WinPos.flags & SWP_SHOWWINDOW)
824 {
825 Window->Style |= WS_VISIBLE;
826 FlagsEx |= SWP_EX_PAINTSELF;
827 /* Redraw entire window. */
828 VisRgn = (HRGN) 1;
829 }
830 else if (!(WinPos.flags & SWP_NOREDRAW))
831 {
832 if (WinPos.flags & SWP_HIDEWINDOW)
833 {
834 if (VisRgn > (HRGN)1)
835 {
836 NtGdiOffsetRgn(VisRgn, OldWindowRect.left, OldWindowRect.top);
837 }
838 else
839 {
840 VisRgn = 0;
841 }
842 }
843 else
844 {
845 if ((WinPos.flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE)
846 {
847 if ((WinPos.flags & SWP_AGG_NOGEOMETRYCHANGE) == SWP_AGG_NOGEOMETRYCHANGE)
848 {
849 FlagsEx |= SWP_EX_PAINTSELF;
850 }
851 FlagsEx = WinPosCopyValidBits(Window, &VisRgn, &OldWindowRect, &OldClientRect, FlagsEx);
852 }
853 else
854 {
855 if (WinPos.flags & SWP_FRAMECHANGED)
856 {
857 WinPosDoSimpleFrameChanged(Window, &OldClientRect, WinPos.flags, FlagsEx);
858 }
859 if (VisRgn != 0)
860 {
861 NtGdiDeleteObject(VisRgn);
862 VisRgn = 0;
863 }
864 }
865 }
866 }
867
868 if (WinPos.flags & SWP_HIDEWINDOW)
869 {
870 VisibleRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window,
871 FALSE, FALSE, FALSE);
872 Window->Style &= ~WS_VISIBLE;
873 VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, VisibleRgn);
874 NtGdiDeleteObject(VisibleRgn);
875 }
876
877 /* FIXME: Hide or show the claret */
878
879 if (VisRgn)
880 {
881 if (!(WinPos.flags & SWP_NOREDRAW))
882 {
883 if (FlagsEx & SWP_EX_PAINTSELF)
884 {
885 PaintRedrawWindow(Window, NULL,
886 (VisRgn == (HRGN) 1) ? 0 : VisRgn,
887 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE |
888 RDW_ALLCHILDREN | RDW_ERASENOW,
889 RDW_EX_XYWINDOW | RDW_EX_USEHRGN);
890 }
891 else
892 {
893 PaintRedrawWindow(Window->Parent, NULL,
894 (VisRgn == (HRGN) 1) ? 0 : VisRgn,
895 RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN |
896 RDW_ERASENOW,
897 RDW_EX_USEHRGN);
898 }
899 /* FIXME: Redraw the window parent. */
900 }
901 NtGdiDeleteObject(VisRgn);
902 }
903
904 if (!(flags & SWP_NOACTIVATE))
905 {
906 WinPosChangeActiveWindow(WinPos.hwnd, FALSE);
907 }
908
909 /* FIXME: Check some conditions before doing this. */
910 IntSendWINDOWPOSCHANGEDMessage(Window->Self, &WinPos);
911
912 ObmDereferenceObject(Window);
913 return(TRUE);
914 }
915
916 LRESULT STDCALL
917 WinPosGetNonClientSize(HWND Wnd, RECT* WindowRect, RECT* ClientRect)
918 {
919 *ClientRect = *WindowRect;
920 return(IntSendNCCALCSIZEMessage(Wnd, FALSE, ClientRect, NULL));
921 }
922
923 BOOLEAN FASTCALL
924 WinPosShowWindow(HWND Wnd, INT Cmd)
925 {
926 BOOLEAN WasVisible;
927 PWINDOW_OBJECT Window;
928 NTSTATUS Status;
929 UINT Swp = 0;
930 RECT NewPos;
931 BOOLEAN ShowFlag;
932 HRGN VisibleRgn;
933
934 Status =
935 ObmReferenceObjectByHandle(PsGetWin32Process()->WindowStation->HandleTable,
936 Wnd,
937 otWindow,
938 (PVOID*)&Window);
939 if (!NT_SUCCESS(Status))
940 {
941 return(FALSE);
942 }
943
944 WasVisible = (Window->Style & WS_VISIBLE) != 0;
945
946 switch (Cmd)
947 {
948 case SW_HIDE:
949 {
950 if (!WasVisible)
951 {
952 ObmDereferenceObject(Window);
953 return(FALSE);
954 }
955 Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE |
956 SWP_NOZORDER;
957 break;
958 }
959
960 case SW_SHOWMINNOACTIVE:
961 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
962 /* Fall through. */
963 case SW_SHOWMINIMIZED:
964 Swp |= SWP_SHOWWINDOW;
965 /* Fall through. */
966 case SW_MINIMIZE:
967 {
968 Swp |= SWP_FRAMECHANGED;
969 if (!(Window->Style & WS_MINIMIZE))
970 {
971 Swp |= WinPosMinMaximize(Window, SW_MINIMIZE, &NewPos);
972 }
973 else
974 {
975 Swp |= SWP_NOSIZE | SWP_NOMOVE;
976 }
977 break;
978 }
979
980 case SW_SHOWMAXIMIZED:
981 {
982 Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
983 if (!(Window->Style & WS_MAXIMIZE))
984 {
985 Swp |= WinPosMinMaximize(Window, SW_MAXIMIZE, &NewPos);
986 }
987 else
988 {
989 Swp |= SWP_NOSIZE | SWP_NOMOVE;
990 }
991 break;
992 }
993
994 case SW_SHOWNA:
995 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
996 /* Fall through. */
997 case SW_SHOW:
998 Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
999 /* Don't activate the topmost window. */
1000 break;
1001
1002 case SW_SHOWNOACTIVATE:
1003 Swp |= SWP_NOZORDER;
1004 /* Fall through. */
1005 case SW_SHOWNORMAL:
1006 case SW_SHOWDEFAULT:
1007 case SW_RESTORE:
1008 Swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
1009 if (Window->Style & (WS_MINIMIZE | WS_MAXIMIZE))
1010 {
1011 Swp |= WinPosMinMaximize(Window, SW_RESTORE, &NewPos);
1012 }
1013 else
1014 {
1015 Swp |= SWP_NOSIZE | SWP_NOMOVE;
1016 }
1017 break;
1018 }
1019
1020 ShowFlag = (Cmd != SW_HIDE);
1021 if (ShowFlag != WasVisible)
1022 {
1023 NtUserSendMessage(Wnd, WM_SHOWWINDOW, ShowFlag, 0);
1024 /*
1025 * FIXME: Need to check the window wasn't destroyed during the
1026 * window procedure.
1027 */
1028 }
1029
1030 if (Window->Style & WS_CHILD &&
1031 !IntIsWindowVisible(Window->Parent->Self) &&
1032 (Swp & (SWP_NOSIZE | SWP_NOMOVE)) == (SWP_NOSIZE | SWP_NOMOVE))
1033 {
1034 if (Cmd == SW_HIDE)
1035 {
1036 VisibleRgn = VIS_ComputeVisibleRegion(PsGetWin32Thread()->Desktop, Window,
1037 FALSE, FALSE, FALSE);
1038 Window->Style &= ~WS_VISIBLE;
1039 VIS_WindowLayoutChanged(PsGetWin32Thread()->Desktop, Window, VisibleRgn);
1040 NtGdiDeleteObject(VisibleRgn);
1041 }
1042 else
1043 {
1044 Window->Style |= WS_VISIBLE;
1045 }
1046 }
1047 else
1048 {
1049 if (Window->Style & WS_CHILD &&
1050 !(Window->ExStyle & WS_EX_MDICHILD))
1051 {
1052 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1053 }
1054 if (!(Swp & MINMAX_NOSWP))
1055 {
1056 WinPosSetWindowPos(Wnd, HWND_TOP, NewPos.left, NewPos.top,
1057 NewPos.right, NewPos.bottom, LOWORD(Swp));
1058 if (Cmd == SW_HIDE)
1059 {
1060 /* Hide the window. */
1061 if (Wnd == IntGetActiveWindow())
1062 {
1063 WinPosActivateOtherWindow(Window);
1064 }
1065 /* Revert focus to parent. */
1066 if (Wnd == IntGetFocusWindow() ||
1067 IntIsChildWindow(Wnd, IntGetFocusWindow()))
1068 {
1069 IntSetFocusWindow(Window->Parent->Self);
1070 }
1071 }
1072 }
1073 /* FIXME: Check for window destruction. */
1074 /* Show title for minimized windows. */
1075 if (Window->Style & WS_MINIMIZE)
1076 {
1077 WinPosShowIconTitle(Window, TRUE);
1078 }
1079 }
1080
1081 if (Window->Flags & WINDOWOBJECT_NEED_SIZE)
1082 {
1083 WPARAM wParam = SIZE_RESTORED;
1084
1085 Window->Flags &= ~WINDOWOBJECT_NEED_SIZE;
1086 if (Window->Style & WS_MAXIMIZE)
1087 {
1088 wParam = SIZE_MAXIMIZED;
1089 }
1090 else if (Window->Style & WS_MINIMIZE)
1091 {
1092 wParam = SIZE_MINIMIZED;
1093 }
1094
1095 NtUserSendMessage(Wnd, WM_SIZE, wParam,
1096 MAKELONG(Window->ClientRect.right -
1097 Window->ClientRect.left,
1098 Window->ClientRect.bottom -
1099 Window->ClientRect.top));
1100 NtUserSendMessage(Wnd, WM_MOVE, 0,
1101 MAKELONG(Window->ClientRect.left,
1102 Window->ClientRect.top));
1103 }
1104
1105 /* Activate the window if activation is not requested and the window is not minimized */
1106 if (!(Swp & (SWP_NOACTIVATE | SWP_HIDEWINDOW)) && !(Window->Style & WS_MINIMIZE))
1107 {
1108 WinPosChangeActiveWindow(Wnd, FALSE);
1109 }
1110
1111 ObmDereferenceObject(Window);
1112 return(WasVisible);
1113 }
1114
1115 BOOL STATIC FASTCALL
1116 WinPosPtInWindow(PWINDOW_OBJECT Window, POINT Point)
1117 {
1118 return(Point.x >= Window->WindowRect.left &&
1119 Point.x < Window->WindowRect.right &&
1120 Point.y >= Window->WindowRect.top &&
1121 Point.y < Window->WindowRect.bottom);
1122 }
1123
1124 USHORT STATIC STDCALL
1125 WinPosSearchChildren(PWINDOW_OBJECT ScopeWin, POINT Point,
1126 PWINDOW_OBJECT* Window)
1127 {
1128 PWINDOW_OBJECT Current;
1129
1130 ExAcquireFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1131 Current = ScopeWin->FirstChild;
1132 while (Current)
1133 {
1134 if (Current->Style & WS_VISIBLE &&
1135 ((!(Current->Style & WS_DISABLED)) ||
1136 (Current->Style & (WS_CHILD | WS_POPUP)) != WS_CHILD) &&
1137 WinPosPtInWindow(Current, Point))
1138 {
1139 *Window = Current;
1140 if (Current->Style & WS_DISABLED)
1141 {
1142 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1143 return(HTERROR);
1144 }
1145 if (Current->Style & WS_MINIMIZE)
1146 {
1147 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1148 return(HTCAPTION);
1149 }
1150 if (Point.x >= Current->ClientRect.left &&
1151 Point.x < Current->ClientRect.right &&
1152 Point.y >= Current->ClientRect.top &&
1153 Point.y < Current->ClientRect.bottom)
1154 {
1155
1156 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1157 return(WinPosSearchChildren(Current, Point, Window));
1158 }
1159
1160 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1161 return(0);
1162 }
1163 Current = Current->NextSibling;
1164 }
1165
1166 ExReleaseFastMutexUnsafe(&ScopeWin->ChildrenListLock);
1167 return(0);
1168 }
1169
1170 USHORT STDCALL
1171 WinPosWindowFromPoint(PWINDOW_OBJECT ScopeWin, POINT WinPoint,
1172 PWINDOW_OBJECT* Window)
1173 {
1174 HWND DesktopWindowHandle;
1175 PWINDOW_OBJECT DesktopWindow;
1176 POINT Point = WinPoint;
1177 USHORT HitTest;
1178
1179 *Window = NULL;
1180
1181 if (ScopeWin->Style & WS_DISABLED)
1182 {
1183 return(HTERROR);
1184 }
1185
1186 /* Translate the point to the space of the scope window. */
1187 DesktopWindowHandle = IntGetDesktopWindow();
1188 DesktopWindow = IntGetWindowObject(DesktopWindowHandle);
1189 Point.x += ScopeWin->ClientRect.left - DesktopWindow->ClientRect.left;
1190 Point.y += ScopeWin->ClientRect.top - DesktopWindow->ClientRect.top;
1191 IntReleaseWindowObject(DesktopWindow);
1192
1193 HitTest = WinPosSearchChildren(ScopeWin, Point, Window);
1194 if (HitTest != 0)
1195 {
1196 return(HitTest);
1197 }
1198
1199 if ((*Window) == NULL)
1200 {
1201 return(HTNOWHERE);
1202 }
1203 if ((*Window)->MessageQueue == PsGetWin32Thread()->MessageQueue)
1204 {
1205 HitTest = IntSendMessage((*Window)->Self, WM_NCHITTEST, 0,
1206 MAKELONG(Point.x, Point.y), FALSE);
1207 /* FIXME: Check for HTTRANSPARENT here. */
1208 }
1209 else
1210 {
1211 HitTest = HTCLIENT;
1212 }
1213
1214 return(HitTest);
1215 }
1216
1217 BOOL
1218 WinPosSetActiveWindow(PWINDOW_OBJECT Window, BOOL Mouse, BOOL ChangeFocus)
1219 {
1220 PUSER_MESSAGE_QUEUE ActiveQueue;
1221 HWND PrevActive;
1222
1223 ActiveQueue = IntGetFocusMessageQueue();
1224 if (ActiveQueue != NULL)
1225 {
1226 PrevActive = ActiveQueue->ActiveWindow;
1227 }
1228 else
1229 {
1230 PrevActive = NULL;
1231 }
1232
1233 if (Window->Self == IntGetActiveDesktop() || Window->Self == PrevActive)
1234 {
1235 return(FALSE);
1236 }
1237 if (PrevActive != NULL)
1238 {
1239 PWINDOW_OBJECT PrevActiveWindow = IntGetWindowObject(PrevActive);
1240 WORD Iconised = HIWORD(PrevActiveWindow->Style & WS_MINIMIZE);
1241 if (!IntSendMessage(PrevActive, WM_NCACTIVATE, FALSE, 0, TRUE))
1242 {
1243 /* FIXME: Check if the new window is system modal. */
1244 return(FALSE);
1245 }
1246 IntSendMessage(PrevActive,
1247 WM_ACTIVATE,
1248 MAKEWPARAM(WA_INACTIVE, Iconised),
1249 (LPARAM)Window->Self,
1250 TRUE);
1251 /* FIXME: Check if anything changed while processing the message. */
1252 IntReleaseWindowObject(PrevActiveWindow);
1253 }
1254
1255 if (Window != NULL)
1256 {
1257 Window->MessageQueue->ActiveWindow = Window->Self;
1258 }
1259 else if (ActiveQueue != NULL)
1260 {
1261 ActiveQueue->ActiveWindow = NULL;
1262 }
1263 /* FIXME: Unset this flag for inactive windows */
1264 //if ((Window->Style) & WS_CHILD) Window->Flags |= WIN_NCACTIVATED;
1265
1266 /* FIXME: Send palette messages. */
1267
1268 /* FIXME: Redraw icon title of previously active window. */
1269
1270 /* FIXME: Bring the window to the top. */
1271
1272 /* FIXME: Send WM_ACTIVATEAPP */
1273
1274 IntSetFocusMessageQueue(Window->MessageQueue);
1275
1276 /* FIXME: Send activate messages. */
1277
1278 /* FIXME: Change focus. */
1279
1280 /* FIXME: Redraw new window icon title. */
1281
1282 return(TRUE);
1283 }
1284
1285 HWND STDCALL
1286 NtUserGetActiveWindow(VOID)
1287 {
1288 PUSER_MESSAGE_QUEUE ActiveQueue;
1289
1290 ActiveQueue = IntGetFocusMessageQueue();
1291 if (ActiveQueue == NULL)
1292 {
1293 return(NULL);
1294 }
1295 return(ActiveQueue->ActiveWindow);
1296 }
1297
1298 HWND STDCALL
1299 NtUserSetActiveWindow(HWND hWnd)
1300 {
1301 PWINDOW_OBJECT Window;
1302 PUSER_MESSAGE_QUEUE ThreadQueue;
1303 HWND Prev;
1304
1305 Window = IntGetWindowObject(hWnd);
1306 if (Window == NULL || (Window->Style & (WS_DISABLED | WS_CHILD)))
1307 {
1308 IntReleaseWindowObject(Window);
1309 return(0);
1310 }
1311 ThreadQueue = (PUSER_MESSAGE_QUEUE)PsGetWin32Thread()->MessageQueue;
1312 if (Window->MessageQueue != ThreadQueue)
1313 {
1314 IntReleaseWindowObject(Window);
1315 return(0);
1316 }
1317 Prev = Window->MessageQueue->ActiveWindow;
1318 WinPosSetActiveWindow(Window, FALSE, FALSE);
1319 IntReleaseWindowObject(Window);
1320 return(Prev);
1321 }
1322
1323
1324 /* EOF */