[WIN32K]
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / winpos.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Windows
5 * FILE: subsystems/win32/win32k/ntuser/window.c
6 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 */
8
9 #include <win32k.h>
10 DBG_DEFAULT_CHANNEL(UserWinpos);
11
12 /* GLOBALS *******************************************************************/
13
14 #define MINMAX_NOSWP (0x00010000)
15
16 #define SWP_EX_NOCOPY 0x0001
17 #define SWP_EX_PAINTSELF 0x0002
18
19 #define SWP_AGG_NOGEOMETRYCHANGE \
20 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
21 #define SWP_AGG_NOPOSCHANGE \
22 (SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
23 #define SWP_AGG_STATUSFLAGS \
24 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
25
26 #define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
27 #define PLACE_MIN 0x0001
28 #define PLACE_MAX 0x0002
29 #define PLACE_RECT 0x0004
30
31 /* FUNCTIONS *****************************************************************/
32
33 BOOL FASTCALL
34 IntGetClientOrigin(PWND Window OPTIONAL, LPPOINT Point)
35 {
36 Window = Window ? Window : UserGetWindowObject(IntGetDesktopWindow());
37 if (Window == NULL)
38 {
39 Point->x = Point->y = 0;
40 return FALSE;
41 }
42 Point->x = Window->rcClient.left;
43 Point->y = Window->rcClient.top;
44
45 return TRUE;
46 }
47
48
49 /*******************************************************************
50 * can_activate_window
51 *
52 * Check if we can activate the specified window.
53 */
54 static
55 BOOL FASTCALL can_activate_window( PWND Wnd OPTIONAL)
56 {
57 LONG style;
58
59 if (!Wnd) return FALSE;
60
61 style = Wnd->style;
62 if (!(style & WS_VISIBLE) &&
63 Wnd->head.pti->pEThread->ThreadsProcess != CsrProcess) return FALSE;
64 if ((style & WS_MINIMIZE) &&
65 Wnd->head.pti->pEThread->ThreadsProcess != CsrProcess) return FALSE;
66 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
67 return TRUE;
68 /* FIXME: This window could be disable because the child that closed
69 was a popup. */
70 //return !(style & WS_DISABLED);
71 }
72
73
74 /*******************************************************************
75 * WinPosActivateOtherWindow
76 *
77 * Activates window other than pWnd.
78 */
79 VOID FASTCALL
80 co_WinPosActivateOtherWindow(PWND Wnd)
81 {
82 PWND WndTo = NULL;
83 HWND Fg;
84 USER_REFERENCE_ENTRY Ref;
85
86 ASSERT_REFS_CO(Wnd);
87
88 if (IntIsDesktopWindow(Wnd))
89 {
90 IntSetFocusMessageQueue(NULL);
91 return;
92 }
93
94 /* If this is popup window, try to activate the owner first. */
95 if ((Wnd->style & WS_POPUP) && (WndTo = Wnd->spwndOwner))
96 {
97 WndTo = UserGetAncestor( WndTo, GA_ROOT );
98 if (can_activate_window(WndTo)) goto done;
99 }
100
101 /* Pick a next top-level window. */
102 /* FIXME: Search for non-tooltip windows first. */
103 WndTo = Wnd;
104 for (;;)
105 {
106 if (!(WndTo = WndTo->spwndNext)) break;
107 if (can_activate_window( WndTo )) break;
108 }
109
110 done:
111
112 if (WndTo) UserRefObjectCo(WndTo, &Ref);
113
114 Fg = UserGetForegroundWindow();
115 if ((!Fg || Wnd->head.h == Fg) && WndTo) // FIXME: Ok if WndTo is NULL??
116 {
117 /* FIXME: Wine can pass WndTo = NULL to co_IntSetForegroundWindow. Hmm... */
118 if (co_IntSetForegroundWindow(WndTo))
119 {
120 UserDerefObjectCo(WndTo);
121 return;
122 }
123 }
124
125 if (!co_IntSetActiveWindow(WndTo)) /* Ok for WndTo to be NULL here */
126 co_IntSetActiveWindow(0);
127
128 if (WndTo) UserDerefObjectCo(WndTo);
129 }
130
131 BOOL
132 FASTCALL
133 WinPosShowIconTitle( PWND pWnd, BOOL bShow )
134 {
135 HICON hIcon;
136 if (!pWnd->pcls || pWnd->fnid == FNID_DESKTOP) return FALSE;
137 if (!hIcon) hIcon = pWnd->pcls->hIconSm;
138 if (!hIcon) hIcon = pWnd->pcls->hIcon;
139 if (!hIcon) return FALSE;
140
141 if ( bShow )
142 {
143 // FIXME: Draw ICON!
144 }
145 else if (hIcon)
146 return FALSE;
147
148 return FALSE;
149 }
150
151 UINT
152 FASTCALL
153 co_WinPosArrangeIconicWindows(PWND parent)
154 {
155 RECTL rectParent;
156 INT i, x, y, xspacing, yspacing;
157 HWND *List = IntWinListChildren(parent);
158
159 ASSERT_REFS_CO(parent);
160
161 /* Check if we found any children */
162 if(List == NULL)
163 {
164 return 0;
165 }
166
167 IntGetClientRect( parent, &rectParent );
168 x = rectParent.left;
169 y = rectParent.bottom;
170
171 xspacing = UserGetSystemMetrics(SM_CXICONSPACING);
172 yspacing = UserGetSystemMetrics(SM_CYICONSPACING);
173
174 TRACE("X:%d Y:%d XS:%d YS:%d\n",x,y,xspacing,yspacing);
175
176 for( i = 0; List[i]; i++)
177 {
178 PWND Child;
179
180 if (!(Child = UserGetWindowObject(List[i])))
181 continue;
182
183 if((Child->style & WS_MINIMIZE) != 0 )
184 {
185 USER_REFERENCE_ENTRY Ref;
186 UserRefObjectCo(Child, &Ref);
187
188 co_WinPosSetWindowPos( Child,
189 0,
190 x + (xspacing - UserGetSystemMetrics(SM_CXICON)) / 2,
191 y - yspacing - UserGetSystemMetrics(SM_CYICON) / 2,
192 0,
193 0,
194 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
195
196 UserDerefObjectCo(Child);
197
198 if (x <= rectParent.right - xspacing)
199 x += xspacing;
200 else
201 {
202 x = rectParent.left;
203 y -= yspacing;
204 }
205 }
206 }
207 ExFreePool(List);
208 return yspacing;
209 }
210
211
212 static VOID FASTCALL
213 WinPosFindIconPos(PWND Window, POINT *Pos)
214 {
215 RECT rect, rectParent;
216 PWND pwndChild, pwndParent;
217 HRGN hrgn, tmp;
218 int xspacing, yspacing;
219
220 pwndParent = Window->spwndParent;
221 if (pwndParent == UserGetDesktopWindow())
222 {
223 /* ReactOS doesn't support iconic minimize to desktop */
224 Pos->x = Pos->y = -32000;
225 return;
226 }
227
228 IntGetClientRect( pwndParent, &rectParent );
229 if ((Pos->x >= rectParent.left) && (Pos->x + UserGetSystemMetrics(SM_CXICON) < rectParent.right) &&
230 (Pos->y >= rectParent.top) && (Pos->y + UserGetSystemMetrics(SM_CYICON) < rectParent.bottom))
231 return; /* The icon already has a suitable position */
232
233 xspacing = UserGetSystemMetrics(SM_CXICONSPACING);
234 yspacing = UserGetSystemMetrics(SM_CYICONSPACING);
235
236 /* Check if another icon already occupies this spot */
237 /* FIXME: this is completely inefficient */
238
239 hrgn = IntSysCreateRectRgn( 0, 0, 0, 0 );
240 tmp = IntSysCreateRectRgn( 0, 0, 0, 0 );
241 for (pwndChild = pwndParent->spwndChild; pwndChild; pwndChild = pwndChild->spwndNext)
242 {
243 if (pwndChild == Window) continue;
244 if ((pwndChild->style & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE))
245 continue;
246 if ( pwndChild->spwndParent )
247 {
248 PWND Parent = pwndChild->spwndParent;
249 rect.left = rect.top = 0;
250 rect.right = Parent->rcWindow.right - Parent->rcWindow.left;
251 rect.bottom = Parent->rcWindow.bottom - Parent->rcWindow.top;
252 NtGdiSetRectRgn( tmp, rect.left, rect.top, rect.right, rect.bottom );
253 NtGdiCombineRgn( hrgn, hrgn, tmp, RGN_OR );
254 }
255 }
256 GreDeleteObject( tmp );
257
258 for (rect.bottom = rectParent.bottom; rect.bottom >= yspacing; rect.bottom -= yspacing)
259 {
260 for (rect.left = rectParent.left; rect.left <= rectParent.right - xspacing; rect.left += xspacing)
261 {
262 rect.right = rect.left + xspacing;
263 rect.top = rect.bottom - yspacing;
264 if (!IntRectInRegion( hrgn, &rect ))
265 {
266 /* No window was found, so it's OK for us */
267 Pos->x = rect.left + (xspacing - UserGetSystemMetrics(SM_CXICON)) / 2;
268 Pos->y = rect.top + (yspacing - UserGetSystemMetrics(SM_CYICON)) / 2;
269 GreDeleteObject( hrgn );
270 return;
271 }
272 }
273 }
274 GreDeleteObject( hrgn );
275 Pos->x = Pos->y = 0;
276 return;
277 }
278
279 VOID FASTCALL
280 WinPosInitInternalPos(PWND Wnd, RECTL *RestoreRect)
281 {
282 POINT Size;
283 RECTL Rect = *RestoreRect;
284
285 if (Wnd->spwndParent != UserGetDesktopWindow())
286 {
287 RECTL_vOffsetRect(&Rect,
288 -Wnd->spwndParent->rcClient.left,
289 -Wnd->spwndParent->rcClient.top);
290 }
291
292 Size.x = Rect.left;
293 Size.y = Rect.top;
294
295 if (!Wnd->InternalPosInitialized)
296 {
297 // FIXME: Use check point Atom..
298 Wnd->InternalPos.flags = 0;
299 Wnd->InternalPos.MaxPos.x = Wnd->InternalPos.MaxPos.y = -1;
300 Wnd->InternalPos.IconPos.x = Wnd->InternalPos.IconPos.y = -1;
301 Wnd->InternalPos.NormalRect = Rect;
302 Wnd->InternalPosInitialized = TRUE;
303 }
304
305 if (Wnd->style & WS_MINIMIZE)
306 {
307 Wnd->InternalPos.IconPos = Size;
308 Wnd->InternalPos.flags |= WPF_MININIT;
309 }
310 else if (Wnd->style & WS_MAXIMIZE)
311 {
312 Wnd->InternalPos.flags |= WPF_MAXINIT;
313
314 if ( Wnd->spwndParent == Wnd->head.rpdesk->pDeskInfo->spwnd )
315 {
316 if (Wnd->state & WNDS_MAXIMIZESTOMONITOR)
317 {
318 Wnd->InternalPos.flags &= ~WPF_MAXINIT;
319 Wnd->InternalPos.MaxPos.x = Wnd->InternalPos.MaxPos.y = -1;
320 }
321 else
322 {
323 RECTL WorkArea;
324 PMONITOR pmonitor = IntMonitorFromRect(&Rect, MONITOR_DEFAULTTOPRIMARY );
325
326 // FIXME: support DPI aware, rcWorkDPI/Real etc..
327 if (!(Wnd->style & WS_MAXIMIZEBOX) || (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen)
328 WorkArea = pmonitor->rcMonitor;
329 else
330 WorkArea = pmonitor->rcWork;
331
332 Wnd->InternalPos.MaxPos.x = Rect.left - WorkArea.left;
333 Wnd->InternalPos.MaxPos.y = Rect.top - WorkArea.top;
334 TRACE("WinPosIP 2 X %d Y %d\n",Wnd->InternalPos.MaxPos.x,Wnd->InternalPos.MaxPos.y);
335 }
336 }
337 else
338 Wnd->InternalPos.MaxPos = Size;
339 }
340 else
341 {
342 Wnd->InternalPos.NormalRect = Rect;
343 }
344 }
345
346 BOOL
347 FASTCALL
348 IntGetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *lpwndpl)
349 {
350 if (!Wnd) return FALSE;
351
352 if(lpwndpl->length != sizeof(WINDOWPLACEMENT))
353 {
354 return FALSE;
355 }
356
357 lpwndpl->flags = 0;
358
359 WinPosInitInternalPos(Wnd, &Wnd->rcWindow);
360
361 lpwndpl->showCmd = SW_HIDE;
362
363 if ( Wnd->style & WS_MINIMIZE )
364 lpwndpl->showCmd = SW_SHOWMINIMIZED;
365 else
366 lpwndpl->showCmd = ( Wnd->style & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
367
368 lpwndpl->rcNormalPosition = Wnd->InternalPos.NormalRect;
369
370 if (Wnd->InternalPos.flags & WPF_MININIT) // Return if it was set!
371 {
372 lpwndpl->ptMinPosition.x = Wnd->InternalPos.IconPos.x;
373 lpwndpl->ptMinPosition.y = Wnd->InternalPos.IconPos.y;
374 }
375 else
376 lpwndpl->ptMinPosition.x = lpwndpl->ptMinPosition.y = -1;
377
378 if ( Wnd->InternalPos.flags & WPF_MAXINIT && // Return if set and not maximized to monitor!
379 !(Wnd->state & WNDS_MAXIMIZESTOMONITOR))
380 {
381 lpwndpl->ptMaxPosition.x = Wnd->InternalPos.MaxPos.x;
382 lpwndpl->ptMaxPosition.y = Wnd->InternalPos.MaxPos.y;
383 }
384 else
385 lpwndpl->ptMaxPosition.x = lpwndpl->ptMaxPosition.y = -1;
386
387 if ( Wnd->spwndParent == Wnd->head.rpdesk->pDeskInfo->spwnd &&
388 !(Wnd->ExStyle & WS_EX_TOOLWINDOW))
389 {
390 PMONITOR pmonitor = IntMonitorFromRect(&lpwndpl->rcNormalPosition, MONITOR_DEFAULTTOPRIMARY );
391
392 // FIXME: support DPI aware, rcWorkDPI/Real etc..
393 if (Wnd->InternalPos.flags & WPF_MININIT)
394 {
395 lpwndpl->ptMinPosition.x -= (pmonitor->rcWork.left - pmonitor->rcMonitor.left);
396 lpwndpl->ptMinPosition.y -= (pmonitor->rcWork.top - pmonitor->rcMonitor.top);
397 }
398 RECTL_vOffsetRect(&lpwndpl->rcNormalPosition,
399 pmonitor->rcMonitor.left - pmonitor->rcWork.left,
400 pmonitor->rcMonitor.top - pmonitor->rcWork.top);
401 }
402
403 if ( Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED || Wnd->style & WS_MAXIMIZE )
404 lpwndpl->flags |= WPF_RESTORETOMAXIMIZED;
405
406 if ( ((Wnd->style & (WS_CHILD|WS_POPUP)) == WS_CHILD) && Wnd->InternalPos.flags & WPF_SETMINPOSITION)
407 lpwndpl->flags |= WPF_SETMINPOSITION;
408
409 return TRUE;
410 }
411
412 /* make sure the specified rect is visible on screen */
413 static void make_rect_onscreen( RECT *rect )
414 {
415 PMONITOR pmonitor = IntMonitorFromRect( rect, MONITOR_DEFAULTTONEAREST ); // Wine uses this.
416
417 // FIXME: support DPI aware, rcWorkDPI/Real etc..
418 if (!pmonitor) return;
419 /* FIXME: map coordinates from rcWork to rcMonitor */
420 if (rect->right <= pmonitor->rcWork.left)
421 {
422 rect->right += pmonitor->rcWork.left - rect->left;
423 rect->left = pmonitor->rcWork.left;
424 }
425 else if (rect->left >= pmonitor->rcWork.right)
426 {
427 rect->left += pmonitor->rcWork.right - rect->right;
428 rect->right = pmonitor->rcWork.right;
429 }
430 if (rect->bottom <= pmonitor->rcWork.top)
431 {
432 rect->bottom += pmonitor->rcWork.top - rect->top;
433 rect->top = pmonitor->rcWork.top;
434 }
435 else if (rect->top >= pmonitor->rcWork.bottom)
436 {
437 rect->top += pmonitor->rcWork.bottom - rect->bottom;
438 rect->bottom = pmonitor->rcWork.bottom;
439 }
440 }
441
442 /* make sure the specified point is visible on screen */
443 static void make_point_onscreen( POINT *pt )
444 {
445 RECT rect;
446
447 RECTL_vSetRect( &rect, pt->x, pt->y, pt->x + 1, pt->y + 1 );
448 make_rect_onscreen( &rect );
449 pt->x = rect.left;
450 pt->y = rect.top;
451 }
452
453 BOOL FASTCALL
454 IntSetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *wpl, UINT Flags)
455 {
456 BOOL sAsync;
457 UINT SWP_Flags;
458
459 if ( Flags & PLACE_MIN) make_point_onscreen( &wpl->ptMinPosition );
460 if ( Flags & PLACE_MAX) make_point_onscreen( &wpl->ptMaxPosition );
461 if ( Flags & PLACE_RECT) make_rect_onscreen( &wpl->rcNormalPosition );
462
463 if (!Wnd || Wnd == Wnd->head.rpdesk->pDeskInfo->spwnd) return FALSE;
464
465 if ( Flags & PLACE_MIN ) Wnd->InternalPos.IconPos = wpl->ptMinPosition;
466 if ( Flags & PLACE_MAX ) Wnd->InternalPos.MaxPos = wpl->ptMaxPosition;
467 if ( Flags & PLACE_RECT) Wnd->InternalPos.NormalRect = wpl->rcNormalPosition;
468
469 SWP_Flags = SWP_NOZORDER | SWP_NOACTIVATE | ((wpl->flags & WPF_ASYNCWINDOWPLACEMENT) ? SWP_ASYNCWINDOWPOS : 0);
470
471 if (Wnd->style & WS_MINIMIZE )
472 {
473 if (Flags & PLACE_MIN)
474 {
475 co_WinPosSetWindowPos(Wnd, HWND_TOP,
476 wpl->ptMinPosition.x, wpl->ptMinPosition.y, 0, 0,
477 SWP_NOSIZE | SWP_Flags);
478 Wnd->InternalPos.flags |= WPF_MININIT;
479 }
480 }
481 else if (Wnd->style & WS_MAXIMIZE )
482 {
483 if (Flags & PLACE_MAX)
484 {
485 co_WinPosSetWindowPos(Wnd, HWND_TOP,
486 wpl->ptMaxPosition.x, wpl->ptMaxPosition.y, 0, 0,
487 SWP_NOSIZE | SWP_Flags);
488 Wnd->InternalPos.flags |= WPF_MAXINIT;
489 }
490 }
491 else if (Flags & PLACE_RECT)
492 {
493 co_WinPosSetWindowPos(Wnd, HWND_TOP,
494 wpl->rcNormalPosition.left, wpl->rcNormalPosition.top,
495 wpl->rcNormalPosition.right - wpl->rcNormalPosition.left,
496 wpl->rcNormalPosition.bottom - wpl->rcNormalPosition.top,
497 SWP_Flags);
498 }
499
500 sAsync = (Wnd->head.pti->MessageQueue != gptiCurrent->MessageQueue && wpl->flags & WPF_ASYNCWINDOWPLACEMENT);
501
502 if ( sAsync )
503 co_IntSendMessageNoWait( UserHMGetHandle(Wnd), WM_ASYNC_SHOWWINDOW, wpl->showCmd, 0 );
504 else
505 co_WinPosShowWindow(Wnd, wpl->showCmd);
506
507 if ( Wnd->style & WS_MINIMIZE && !sAsync )
508 {
509 if ( wpl->flags & WPF_SETMINPOSITION )
510 Wnd->InternalPos.flags |= WPF_SETMINPOSITION;
511
512 if ( wpl->flags & WPF_RESTORETOMAXIMIZED )
513 Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED;
514 }
515 return TRUE;
516 }
517
518 UINT FASTCALL
519 co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
520 {
521 POINT Size;
522 WINDOWPLACEMENT wpl;
523 UINT SwpFlags = 0;
524
525 ASSERT_REFS_CO(Wnd);
526
527 wpl.length = sizeof(wpl);
528 IntGetWindowPlacement( Wnd, &wpl );
529
530 if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag))
531 {
532 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
533 return SWP_NOSIZE | SWP_NOMOVE;
534 }
535 if (Wnd->style & WS_MINIMIZE)
536 {
537 if (ShowFlag == SW_MINIMIZE) return SWP_NOSIZE | SWP_NOMOVE;
538
539 if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0))
540 {
541 return(SWP_NOSIZE | SWP_NOMOVE);
542 }
543 SwpFlags |= SWP_NOCOPYBITS;
544 }
545 switch (ShowFlag)
546 {
547 case SW_MINIMIZE:
548 {
549 if (Wnd->style & WS_MAXIMIZE)
550 {
551 Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED;
552 Wnd->style &= ~WS_MAXIMIZE;
553 }
554 else
555 {
556 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
557 }
558 co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE |
559 RDW_NOINTERNALPAINT);
560 Wnd->style |= WS_MINIMIZE;
561 WinPosFindIconPos(Wnd, &wpl.ptMinPosition);
562 RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
563 UserGetSystemMetrics(SM_CXMINIMIZED),
564 UserGetSystemMetrics(SM_CYMINIMIZED));
565 SwpFlags |= SWP_NOCOPYBITS;
566 break;
567 }
568
569 case SW_MAXIMIZE:
570 {
571 co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
572
573 TRACE("Maximize: %d,%d %dx%d\n",
574 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
575 if (Wnd->style & WS_MINIMIZE)
576 {
577 Wnd->style &= ~WS_MINIMIZE;
578 }
579 Wnd->style |= WS_MAXIMIZE;
580 RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
581 break;
582 }
583
584 case SW_RESTORE:
585 {
586 if (Wnd->style & WS_MINIMIZE)
587 {
588 Wnd->style &= ~WS_MINIMIZE;
589 if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED)
590 {
591 co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
592
593 Wnd->style |= WS_MAXIMIZE;
594 RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
595 break;
596 }
597 else
598 {
599 *NewPos = wpl.rcNormalPosition;
600 NewPos->right -= NewPos->left;
601 NewPos->bottom -= NewPos->top;
602 break;
603 }
604 }
605 else
606 {
607 if (!(Wnd->style & WS_MAXIMIZE))
608 {
609 return 0;
610 }
611 Wnd->style &= ~WS_MAXIMIZE;
612 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
613 *NewPos = wpl.rcNormalPosition;
614 NewPos->right -= NewPos->left;
615 NewPos->bottom -= NewPos->top;
616 break;
617 }
618 }
619 }
620 return(SwpFlags);
621 }
622
623 BOOL
624 UserHasWindowEdge(DWORD Style, DWORD ExStyle)
625 {
626 if (Style & WS_MINIMIZE)
627 return TRUE;
628 if (ExStyle & WS_EX_DLGMODALFRAME)
629 return TRUE;
630 if (ExStyle & WS_EX_STATICEDGE)
631 return FALSE;
632 if (Style & WS_THICKFRAME)
633 return TRUE;
634 Style &= WS_CAPTION;
635 if (Style == WS_DLGFRAME || Style == WS_CAPTION)
636 return TRUE;
637 return FALSE;
638 }
639
640 VOID
641 UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient)
642 {
643 DWORD Border = 0;
644
645 if (UserHasWindowEdge(Style, ExStyle))
646 Border += 2;
647 else if (ExStyle & WS_EX_STATICEDGE)
648 Border += 1;
649 if ((ExStyle & WS_EX_CLIENTEDGE) && WithClient)
650 Border += 2;
651 if (Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME)
652 Border ++;
653 Size->cx = Size->cy = Border;
654 if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
655 {
656 Size->cx += UserGetSystemMetrics(SM_CXFRAME) - UserGetSystemMetrics(SM_CXDLGFRAME);
657 Size->cy += UserGetSystemMetrics(SM_CYFRAME) - UserGetSystemMetrics(SM_CYDLGFRAME);
658 }
659 Size->cx *= UserGetSystemMetrics(SM_CXBORDER);
660 Size->cy *= UserGetSystemMetrics(SM_CYBORDER);
661 }
662
663 BOOL WINAPI
664 UserAdjustWindowRectEx(LPRECT lpRect,
665 DWORD dwStyle,
666 BOOL bMenu,
667 DWORD dwExStyle)
668 {
669 SIZE BorderSize;
670
671 if (bMenu)
672 {
673 lpRect->top -= UserGetSystemMetrics(SM_CYMENU);
674 }
675 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
676 {
677 if (dwExStyle & WS_EX_TOOLWINDOW)
678 lpRect->top -= UserGetSystemMetrics(SM_CYSMCAPTION);
679 else
680 lpRect->top -= UserGetSystemMetrics(SM_CYCAPTION);
681 }
682 UserGetWindowBorders(dwStyle, dwExStyle, &BorderSize, TRUE);
683 RECTL_vInflateRect(
684 lpRect,
685 BorderSize.cx,
686 BorderSize.cy);
687
688 return TRUE;
689 }
690
691 UINT FASTCALL
692 co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos,
693 POINT* MinTrack, POINT* MaxTrack)
694 {
695 MINMAXINFO MinMax;
696 PMONITOR monitor;
697 INT xinc, yinc;
698 LONG style = Window->style;
699 LONG adjustedStyle;
700 LONG exstyle = Window->ExStyle;
701 RECT rc;
702
703 ASSERT_REFS_CO(Window);
704
705 /* Compute default values */
706
707 rc = Window->rcWindow;
708 MinMax.ptReserved.x = rc.left;
709 MinMax.ptReserved.y = rc.top;
710
711 if ((style & WS_CAPTION) == WS_CAPTION)
712 adjustedStyle = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
713 else
714 adjustedStyle = style;
715
716 if(Window->spwndParent)
717 IntGetClientRect(Window->spwndParent, &rc);
718 UserAdjustWindowRectEx(&rc, adjustedStyle, ((style & WS_POPUP) && Window->IDMenu), exstyle);
719
720 xinc = -rc.left;
721 yinc = -rc.top;
722
723 MinMax.ptMaxSize.x = rc.right - rc.left;
724 MinMax.ptMaxSize.y = rc.bottom - rc.top;
725 if (style & (WS_DLGFRAME | WS_BORDER))
726 {
727 MinMax.ptMinTrackSize.x = UserGetSystemMetrics(SM_CXMINTRACK);
728 MinMax.ptMinTrackSize.y = UserGetSystemMetrics(SM_CYMINTRACK);
729 }
730 else
731 {
732 MinMax.ptMinTrackSize.x = 2 * xinc;
733 MinMax.ptMinTrackSize.y = 2 * yinc;
734 }
735 MinMax.ptMaxTrackSize.x = UserGetSystemMetrics(SM_CXMAXTRACK);
736 MinMax.ptMaxTrackSize.y = UserGetSystemMetrics(SM_CYMAXTRACK);
737 MinMax.ptMaxPosition.x = -xinc;
738 MinMax.ptMaxPosition.y = -yinc;
739
740 if (!EMPTYPOINT(Window->InternalPos.MaxPos)) MinMax.ptMaxPosition = Window->InternalPos.MaxPos;
741
742 co_IntSendMessage(Window->head.h, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax);
743
744 /* if the app didn't change the values, adapt them for the current monitor */
745 if ((monitor = IntGetPrimaryMonitor()))
746 {
747 RECT rc_work;
748
749 rc_work = monitor->rcMonitor;
750
751 if (style & WS_MAXIMIZEBOX)
752 {
753 if ((style & WS_CAPTION) == WS_CAPTION || !(style & (WS_CHILD | WS_POPUP)))
754 rc_work = monitor->rcWork;
755 }
756
757 if (MinMax.ptMaxSize.x == UserGetSystemMetrics(SM_CXSCREEN) + 2 * xinc &&
758 MinMax.ptMaxSize.y == UserGetSystemMetrics(SM_CYSCREEN) + 2 * yinc)
759 {
760 MinMax.ptMaxSize.x = (rc_work.right - rc_work.left) + 2 * xinc;
761 MinMax.ptMaxSize.y = (rc_work.bottom - rc_work.top) + 2 * yinc;
762 }
763 if (MinMax.ptMaxPosition.x == -xinc && MinMax.ptMaxPosition.y == -yinc)
764 {
765 MinMax.ptMaxPosition.x = rc_work.left - xinc;
766 MinMax.ptMaxPosition.y = rc_work.top - yinc;
767 }
768 }
769
770
771 MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
772 MinMax.ptMinTrackSize.x);
773 MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y,
774 MinMax.ptMinTrackSize.y);
775
776 if (MaxSize)
777 *MaxSize = MinMax.ptMaxSize;
778 if (MaxPos)
779 *MaxPos = MinMax.ptMaxPosition;
780 if (MinTrack)
781 *MinTrack = MinMax.ptMinTrackSize;
782 if (MaxTrack)
783 *MaxTrack = MinMax.ptMaxTrackSize;
784
785 return 0; // FIXME: What does it return?
786 }
787
788 static
789 VOID FASTCALL
790 FixClientRect(PRECTL ClientRect, PRECTL WindowRect)
791 {
792 if (ClientRect->left < WindowRect->left)
793 {
794 ClientRect->left = WindowRect->left;
795 }
796 else if (WindowRect->right < ClientRect->left)
797 {
798 ClientRect->left = WindowRect->right;
799 }
800 if (ClientRect->right < WindowRect->left)
801 {
802 ClientRect->right = WindowRect->left;
803 }
804 else if (WindowRect->right < ClientRect->right)
805 {
806 ClientRect->right = WindowRect->right;
807 }
808 if (ClientRect->top < WindowRect->top)
809 {
810 ClientRect->top = WindowRect->top;
811 }
812 else if (WindowRect->bottom < ClientRect->top)
813 {
814 ClientRect->top = WindowRect->bottom;
815 }
816 if (ClientRect->bottom < WindowRect->top)
817 {
818 ClientRect->bottom = WindowRect->top;
819 }
820 else if (WindowRect->bottom < ClientRect->bottom)
821 {
822 ClientRect->bottom = WindowRect->bottom;
823 }
824 }
825
826 static
827 LONG FASTCALL
828 co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos,
829 RECT* WindowRect, RECT* ClientRect)
830 {
831 PWND Parent;
832 UINT wvrFlags = 0;
833
834 ASSERT_REFS_CO(Window);
835
836 /* Send WM_NCCALCSIZE message to get new client area */
837 if ((WinPos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE)
838 {
839 NCCALCSIZE_PARAMS params;
840 WINDOWPOS winposCopy;
841
842 params.rgrc[0] = *WindowRect;
843 params.rgrc[1] = Window->rcWindow;
844 params.rgrc[2] = Window->rcClient;
845 Parent = Window->spwndParent;
846 if (0 != (Window->style & WS_CHILD) && Parent)
847 {
848 RECTL_vOffsetRect(&(params.rgrc[0]), - Parent->rcClient.left,
849 - Parent->rcClient.top);
850 RECTL_vOffsetRect(&(params.rgrc[1]), - Parent->rcClient.left,
851 - Parent->rcClient.top);
852 RECTL_vOffsetRect(&(params.rgrc[2]), - Parent->rcClient.left,
853 - Parent->rcClient.top);
854 }
855 params.lppos = &winposCopy;
856 winposCopy = *WinPos;
857
858 wvrFlags = co_IntSendMessage(Window->head.h, WM_NCCALCSIZE, TRUE, (LPARAM) &params);
859
860 /* If the application send back garbage, ignore it */
861 if (params.rgrc[0].left <= params.rgrc[0].right &&
862 params.rgrc[0].top <= params.rgrc[0].bottom)
863 {
864 *ClientRect = params.rgrc[0];
865 if ((Window->style & WS_CHILD) && Parent)
866 {
867 RECTL_vOffsetRect(ClientRect, Parent->rcClient.left,
868 Parent->rcClient.top);
869 }
870 FixClientRect(ClientRect, WindowRect);
871 }
872
873 /* FIXME: WVR_ALIGNxxx */
874
875 if (ClientRect->left != Window->rcClient.left ||
876 ClientRect->top != Window->rcClient.top)
877 {
878 WinPos->flags &= ~SWP_NOCLIENTMOVE;
879 }
880
881 if ((ClientRect->right - ClientRect->left !=
882 Window->rcClient.right - Window->rcClient.left) ||
883 (ClientRect->bottom - ClientRect->top !=
884 Window->rcClient.bottom - Window->rcClient.top))
885 {
886 WinPos->flags &= ~SWP_NOCLIENTSIZE;
887 }
888 }
889 else
890 {
891 if (! (WinPos->flags & SWP_NOMOVE)
892 && (ClientRect->left != Window->rcClient.left ||
893 ClientRect->top != Window->rcClient.top))
894 {
895 WinPos->flags &= ~SWP_NOCLIENTMOVE;
896 }
897 }
898
899 return wvrFlags;
900 }
901
902 static
903 BOOL FASTCALL
904 co_WinPosDoWinPosChanging(PWND Window,
905 PWINDOWPOS WinPos,
906 PRECTL WindowRect,
907 PRECTL ClientRect)
908 {
909 INT X, Y;
910
911 ASSERT_REFS_CO(Window);
912
913 if (!(WinPos->flags & SWP_NOSENDCHANGING))
914 {
915 co_IntSendMessageNoWait(Window->head.h, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos);
916 }
917
918 *WindowRect = Window->rcWindow;
919 *ClientRect = Window->rcClient;
920
921 if (!(WinPos->flags & SWP_NOSIZE))
922 {
923 WindowRect->right = WindowRect->left + WinPos->cx;
924 WindowRect->bottom = WindowRect->top + WinPos->cy;
925 }
926
927 if (!(WinPos->flags & SWP_NOMOVE))
928 {
929 PWND Parent;
930 X = WinPos->x;
931 Y = WinPos->y;
932 Parent = Window->spwndParent;
933 if ((0 != (Window->style & WS_CHILD)) && Parent)
934 {
935 X += Parent->rcClient.left;
936 Y += Parent->rcClient.top;
937 }
938
939 WindowRect->left = X;
940 WindowRect->top = Y;
941 WindowRect->right += X - Window->rcWindow.left;
942 WindowRect->bottom += Y - Window->rcWindow.top;
943 RECTL_vOffsetRect(ClientRect,
944 X - Window->rcWindow.left,
945 Y - Window->rcWindow.top);
946 }
947
948 WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
949
950 return TRUE;
951 }
952
953 /*
954 * Fix Z order taking into account owned popups -
955 * basically we need to maintain them above the window that owns them
956 */
957 static
958 HWND FASTCALL
959 WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter)
960 {
961 HWND *List = NULL;
962 HWND Owner;
963 LONG Style;
964 PWND DesktopWindow, ChildObject;
965 int i;
966
967 Owner = Window->spwndOwner ? Window->spwndOwner->head.h : NULL;
968 Style = Window->style;
969
970 if ((Style & WS_POPUP) && Owner)
971 {
972 /* Make sure this popup stays above the owner */
973 HWND hWndLocalPrev = HWND_TOPMOST;
974
975 if (hWndInsertAfter != HWND_TOPMOST)
976 {
977 DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
978 List = IntWinListChildren(DesktopWindow);
979
980 if (List != NULL)
981 {
982 for (i = 0; List[i]; i++)
983 {
984 if (List[i] == Owner)
985 break;
986 if (HWND_TOP == hWndInsertAfter)
987 {
988 ChildObject = UserGetWindowObject(List[i]);
989 if (NULL != ChildObject)
990 {
991 if (0 == (ChildObject->ExStyle & WS_EX_TOPMOST))
992 {
993 break;
994 }
995 }
996 }
997 if (List[i] != Window->head.h)
998 hWndLocalPrev = List[i];
999 if (hWndLocalPrev == hWndInsertAfter)
1000 break;
1001 }
1002 hWndInsertAfter = hWndLocalPrev;
1003 }
1004 }
1005 }
1006 else if (Style & WS_CHILD)
1007 {
1008 return hWndInsertAfter;
1009 }
1010
1011 if (!List)
1012 {
1013 DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
1014 List = IntWinListChildren(DesktopWindow);
1015 }
1016 if (List != NULL)
1017 {
1018 for (i = 0; List[i]; i++)
1019 {
1020 PWND Wnd;
1021
1022 if (List[i] == Window->head.h)
1023 break;
1024
1025 if (!(Wnd = UserGetWindowObject(List[i])))
1026 continue;
1027
1028 if (Wnd->style & WS_POPUP && Wnd->spwndOwner == Window)
1029 {
1030 USER_REFERENCE_ENTRY Ref;
1031 UserRefObjectCo(Wnd, &Ref);
1032
1033 co_WinPosSetWindowPos(Wnd, hWndInsertAfter, 0, 0, 0, 0,
1034 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING);
1035
1036 UserDerefObjectCo(Wnd);
1037
1038 hWndInsertAfter = List[i];
1039 }
1040 }
1041 ExFreePool(List);
1042 }
1043
1044 return hWndInsertAfter;
1045 }
1046
1047 /***********************************************************************
1048 * WinPosInternalMoveWindow
1049 *
1050 * Update WindowRect and ClientRect of Window and all of its children
1051 * We keep both WindowRect and ClientRect in screen coordinates internally
1052 */
1053 static
1054 VOID FASTCALL
1055 WinPosInternalMoveWindow(PWND Window, INT MoveX, INT MoveY)
1056 {
1057 PWND Child;
1058
1059 ASSERT(Window != Window->spwndChild);
1060
1061 Window->rcWindow.left += MoveX;
1062 Window->rcWindow.right += MoveX;
1063 Window->rcWindow.top += MoveY;
1064 Window->rcWindow.bottom += MoveY;
1065
1066 Window->rcClient.left += MoveX;
1067 Window->rcClient.right += MoveX;
1068 Window->rcClient.top += MoveY;
1069 Window->rcClient.bottom += MoveY;
1070
1071 for(Child = Window->spwndChild; Child; Child = Child->spwndNext)
1072 {
1073 WinPosInternalMoveWindow(Child, MoveX, MoveY);
1074 }
1075 }
1076
1077 /*
1078 * WinPosFixupSWPFlags
1079 *
1080 * Fix redundant flags and values in the WINDOWPOS structure.
1081 */
1082 static
1083 BOOL FASTCALL
1084 WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd)
1085 {
1086 if (Wnd->style & WS_VISIBLE)
1087 {
1088 WinPos->flags &= ~SWP_SHOWWINDOW;
1089 }
1090 else
1091 {
1092 WinPos->flags &= ~SWP_HIDEWINDOW;
1093 if (!(WinPos->flags & SWP_SHOWWINDOW))
1094 WinPos->flags |= SWP_NOREDRAW;
1095 }
1096
1097 WinPos->cx = max(WinPos->cx, 0);
1098 WinPos->cy = max(WinPos->cy, 0);
1099
1100 /* Check for right size */
1101 if (Wnd->rcWindow.right - Wnd->rcWindow.left == WinPos->cx &&
1102 Wnd->rcWindow.bottom - Wnd->rcWindow.top == WinPos->cy)
1103 {
1104 WinPos->flags |= SWP_NOSIZE;
1105 }
1106
1107 /* Check for right position */
1108 if (Wnd->rcWindow.left == WinPos->x &&
1109 Wnd->rcWindow.top == WinPos->y)
1110 {
1111 WinPos->flags |= SWP_NOMOVE;
1112 }
1113
1114 if (WinPos->hwnd == UserGetForegroundWindow())
1115 {
1116 WinPos->flags |= SWP_NOACTIVATE; /* Already active */
1117 }
1118 else
1119 if ((Wnd->style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
1120 {
1121 /* Bring to the top when activating */
1122 if (!(WinPos->flags & SWP_NOACTIVATE))
1123 {
1124 WinPos->flags &= ~SWP_NOZORDER;
1125 WinPos->hwndInsertAfter = (0 != (Wnd->ExStyle & WS_EX_TOPMOST) ?
1126 HWND_TOPMOST : HWND_TOP);
1127 return TRUE;
1128 }
1129 }
1130
1131 /* Check hwndInsertAfter */
1132 if (!(WinPos->flags & SWP_NOZORDER))
1133 {
1134 /* Fix sign extension */
1135 if (WinPos->hwndInsertAfter == (HWND)0xffff)
1136 {
1137 WinPos->hwndInsertAfter = HWND_TOPMOST;
1138 }
1139 else if (WinPos->hwndInsertAfter == (HWND)0xfffe)
1140 {
1141 WinPos->hwndInsertAfter = HWND_NOTOPMOST;
1142 }
1143
1144 if (WinPos->hwndInsertAfter == HWND_NOTOPMOST)
1145 {
1146 WinPos->hwndInsertAfter = HWND_TOP;
1147 }
1148 else if (HWND_TOP == WinPos->hwndInsertAfter
1149 && 0 != (Wnd->ExStyle & WS_EX_TOPMOST))
1150 {
1151 /* Keep it topmost when it's already topmost */
1152 WinPos->hwndInsertAfter = HWND_TOPMOST;
1153 }
1154
1155 /* hwndInsertAfter must be a sibling of the window */
1156 if (HWND_TOPMOST != WinPos->hwndInsertAfter
1157 && HWND_TOP != WinPos->hwndInsertAfter
1158 && HWND_NOTOPMOST != WinPos->hwndInsertAfter
1159 && HWND_BOTTOM != WinPos->hwndInsertAfter)
1160 {
1161 PWND InsAfterWnd;
1162
1163 InsAfterWnd = UserGetWindowObject(WinPos->hwndInsertAfter);
1164 if(!InsAfterWnd)
1165 {
1166 return TRUE;
1167 }
1168
1169 if (InsAfterWnd->spwndParent != Wnd->spwndParent)
1170 {
1171 return FALSE;
1172 }
1173 else
1174 {
1175 /*
1176 * We don't need to change the Z order of hwnd if it's already
1177 * inserted after hwndInsertAfter or when inserting hwnd after
1178 * itself.
1179 */
1180 if ((WinPos->hwnd == WinPos->hwndInsertAfter) ||
1181 ((InsAfterWnd->spwndNext) && (WinPos->hwnd == InsAfterWnd->spwndNext->head.h)))
1182 {
1183 WinPos->flags |= SWP_NOZORDER;
1184 }
1185 }
1186 }
1187 }
1188
1189 return TRUE;
1190 }
1191
1192 /* x and y are always screen relative */
1193 BOOLEAN FASTCALL
1194 co_WinPosSetWindowPos(
1195 PWND Window,
1196 HWND WndInsertAfter,
1197 INT x,
1198 INT y,
1199 INT cx,
1200 INT cy,
1201 UINT flags
1202 )
1203 {
1204 WINDOWPOS WinPos;
1205 RECTL NewWindowRect;
1206 RECTL NewClientRect;
1207 PROSRGNDATA VisRgn;
1208 HRGN VisBefore = NULL;
1209 HRGN VisAfter = NULL;
1210 HRGN DirtyRgn = NULL;
1211 HRGN ExposedRgn = NULL;
1212 HRGN CopyRgn = NULL;
1213 ULONG WvrFlags = 0;
1214 RECTL OldWindowRect, OldClientRect;
1215 int RgnType;
1216 HDC Dc;
1217 RECTL CopyRect;
1218 PWND Ancestor;
1219 BOOL bPointerInWindow;
1220
1221 ASSERT_REFS_CO(Window);
1222
1223 /* FIXME: Get current active window from active queue. */
1224 /*
1225 * Only allow CSRSS to mess with the desktop window
1226 */
1227
1228 if ( Window->head.h == IntGetDesktopWindow() &&
1229 Window->head.pti->pEThread->ThreadsProcess != PsGetCurrentProcess())
1230 {
1231 ERR("Desktop Window...\n");
1232 return FALSE;
1233 }
1234 bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y);
1235
1236 WinPos.hwnd = Window->head.h;
1237 WinPos.hwndInsertAfter = WndInsertAfter;
1238 WinPos.x = x;
1239 WinPos.y = y;
1240 WinPos.cx = cx;
1241 WinPos.cy = cy;
1242 WinPos.flags = flags;
1243
1244 co_WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
1245
1246 /* Does the window still exist? */
1247 if (!IntIsWindow(WinPos.hwnd))
1248 {
1249 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
1250 return FALSE;
1251 }
1252
1253 /* Fix up the flags. */
1254 if (!WinPosFixupFlags(&WinPos, Window))
1255 {
1256 EngSetLastError(ERROR_INVALID_PARAMETER);
1257 return FALSE;
1258 }
1259
1260 Ancestor = UserGetAncestor(Window, GA_PARENT);
1261 if ( (WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
1262 SWP_NOZORDER &&
1263 Ancestor && Ancestor->head.h == IntGetDesktopWindow() )
1264 {
1265 WinPos.hwndInsertAfter = WinPosDoOwnedPopups(Window, WinPos.hwndInsertAfter);
1266 }
1267
1268 if (!(WinPos.flags & SWP_NOREDRAW))
1269 {
1270 /* Compute the visible region before the window position is changed */
1271 if (!(WinPos.flags & SWP_SHOWWINDOW) &&
1272 (WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
1273 SWP_HIDEWINDOW | SWP_FRAMECHANGED)) !=
1274 (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
1275 {
1276 VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE,
1277 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
1278 VisRgn = NULL;
1279
1280 if ( VisBefore != NULL &&
1281 (VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisBefore, NULL)) &&
1282 REGION_Complexity(VisRgn) == NULLREGION )
1283 {
1284 RGNOBJAPI_Unlock(VisRgn);
1285 GreDeleteObject(VisBefore);
1286 VisBefore = NULL;
1287 }
1288 else if(VisRgn)
1289 {
1290 RGNOBJAPI_Unlock(VisRgn);
1291 NtGdiOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top);
1292 }
1293 }
1294 }
1295
1296 WvrFlags = co_WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect);
1297
1298 TRACE("co_WinPosDoNCCALCSize returned %d\n", WvrFlags);
1299
1300 /* Relink windows. (also take into account shell window in hwndShellWindow) */
1301 if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow())
1302 {
1303 IntLinkHwnd(Window, WndInsertAfter);
1304 }
1305
1306 OldWindowRect = Window->rcWindow;
1307 OldClientRect = Window->rcClient;
1308
1309 if (OldClientRect.bottom - OldClientRect.top ==
1310 NewClientRect.bottom - NewClientRect.top)
1311 {
1312 WvrFlags &= ~WVR_VREDRAW;
1313 }
1314
1315 if (OldClientRect.right - OldClientRect.left ==
1316 NewClientRect.right - NewClientRect.left)
1317 {
1318 WvrFlags &= ~WVR_HREDRAW;
1319 }
1320
1321 /* FIXME: Actually do something with WVR_VALIDRECTS */
1322
1323 if (NewClientRect.left != OldClientRect.left ||
1324 NewClientRect.top != OldClientRect.top)
1325 {
1326 WinPosInternalMoveWindow(Window,
1327 NewClientRect.left - OldClientRect.left,
1328 NewClientRect.top - OldClientRect.top);
1329 }
1330
1331 Window->rcWindow = NewWindowRect;
1332 Window->rcClient = NewClientRect;
1333
1334 if (WinPos.flags & SWP_HIDEWINDOW)
1335 {
1336 /* Clear the update region */
1337 co_UserRedrawWindow( Window,
1338 NULL,
1339 0,
1340 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN);
1341
1342 if (Window->spwndParent == UserGetDesktopWindow())
1343 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (LPARAM)Window->head.h);
1344
1345 Window->style &= ~WS_VISIBLE;
1346 }
1347 else if (WinPos.flags & SWP_SHOWWINDOW)
1348 {
1349 if (Window->spwndParent == UserGetDesktopWindow())
1350 co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)Window->head.h);
1351
1352 Window->style |= WS_VISIBLE;
1353 }
1354
1355 if (Window->hrgnUpdate != NULL && Window->hrgnUpdate != HRGN_WINDOW)
1356 {
1357 NtGdiOffsetRgn(Window->hrgnUpdate,
1358 NewWindowRect.left - OldWindowRect.left,
1359 NewWindowRect.top - OldWindowRect.top);
1360 }
1361
1362 DceResetActiveDCEs(Window);
1363
1364 if (!(WinPos.flags & SWP_NOREDRAW))
1365 {
1366 /* Determine the new visible region */
1367 VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE,
1368 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
1369 VisRgn = NULL;
1370
1371 if ( VisAfter != NULL &&
1372 (VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(VisAfter, NULL)) &&
1373 REGION_Complexity(VisRgn) == NULLREGION )
1374 {
1375 RGNOBJAPI_Unlock(VisRgn);
1376 GreDeleteObject(VisAfter);
1377 VisAfter = NULL;
1378 }
1379 else if(VisRgn)
1380 {
1381 RGNOBJAPI_Unlock(VisRgn);
1382 NtGdiOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top);
1383 }
1384
1385 /*
1386 * Determine which pixels can be copied from the old window position
1387 * to the new. Those pixels must be visible in both the old and new
1388 * position. Also, check the class style to see if the windows of this
1389 * class need to be completely repainted on (horizontal/vertical) size
1390 * change.
1391 */
1392 if ( VisBefore != NULL &&
1393 VisAfter != NULL &&
1394 !(WinPos.flags & SWP_NOCOPYBITS) &&
1395 ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) &&
1396 !(Window->ExStyle & WS_EX_TRANSPARENT) )
1397 {
1398 CopyRgn = IntSysCreateRectRgn(0, 0, 0, 0);
1399 RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
1400
1401 /*
1402 * If this is (also) a window resize, the whole nonclient area
1403 * needs to be repainted. So we limit the copy to the client area,
1404 * 'cause there is no use in copying it (would possibly cause
1405 * "flashing" too). However, if the copy region is already empty,
1406 * we don't have to crop (can't take anything away from an empty
1407 * region...)
1408 */
1409 if (!(WinPos.flags & SWP_NOSIZE) &&
1410 RgnType != ERROR &&
1411 RgnType != NULLREGION )
1412 {
1413 PROSRGNDATA pCopyRgn;
1414 RECTL ORect = OldClientRect;
1415 RECTL NRect = NewClientRect;
1416 RECTL_vOffsetRect(&ORect, - OldWindowRect.left, - OldWindowRect.top);
1417 RECTL_vOffsetRect(&NRect, - NewWindowRect.left, - NewWindowRect.top);
1418 RECTL_bIntersectRect(&CopyRect, &ORect, &NRect);
1419 pCopyRgn = RGNOBJAPI_Lock(CopyRgn, NULL);
1420 REGION_CropAndOffsetRegion(pCopyRgn, pCopyRgn, &CopyRect, NULL);
1421 RGNOBJAPI_Unlock(pCopyRgn);
1422 }
1423
1424 /* No use in copying bits which are in the update region. */
1425 if (Window->hrgnUpdate != NULL)
1426 {
1427 NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
1428 NtGdiCombineRgn(CopyRgn, CopyRgn, Window->hrgnUpdate, RGN_DIFF);
1429 NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
1430 }
1431
1432 /*
1433 * Now, get the bounding box of the copy region. If it's empty
1434 * there's nothing to copy. Also, it's no use copying bits onto
1435 * themselves.
1436 */
1437 if ( (VisRgn = (PROSRGNDATA)RGNOBJAPI_Lock(CopyRgn, NULL)) &&
1438 REGION_GetRgnBox(VisRgn, &CopyRect) == NULLREGION)
1439 {
1440 /* Nothing to copy, clean up */
1441 RGNOBJAPI_Unlock(VisRgn);
1442 GreDeleteObject(CopyRgn);
1443 CopyRgn = NULL;
1444 }
1445 else if (OldWindowRect.left != NewWindowRect.left ||
1446 OldWindowRect.top != NewWindowRect.top)
1447 {
1448 if(VisRgn)
1449 {
1450 RGNOBJAPI_Unlock(VisRgn);
1451 }
1452
1453 /*
1454 * Small trick here: there is no function to bitblt a region. So
1455 * we set the region as the clipping region, take the bounding box
1456 * of the region and bitblt that. Since nothing outside the clipping
1457 * region is copied, this has the effect of bitblt'ing the region.
1458 *
1459 * Since NtUserGetDCEx takes ownership of the clip region, we need
1460 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1461 */
1462 NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
1463 Dc = UserGetDCEx( Window,
1464 CopyRgn,
1465 DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN);
1466 NtGdiBitBlt( Dc,
1467 CopyRect.left, CopyRect.top,
1468 CopyRect.right - CopyRect.left,
1469 CopyRect.bottom - CopyRect.top,
1470 Dc,
1471 CopyRect.left + (OldWindowRect.left - NewWindowRect.left),
1472 CopyRect.top + (OldWindowRect.top - NewWindowRect.top),
1473 SRCCOPY,
1474 0,
1475 0);
1476
1477 UserReleaseDC(Window, Dc, FALSE);
1478 IntValidateParent(Window, CopyRgn, FALSE);
1479 NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
1480 }
1481 else if(VisRgn)
1482 {
1483 RGNOBJAPI_Unlock(VisRgn);
1484 }
1485 }
1486 else
1487 {
1488 CopyRgn = NULL;
1489 }
1490
1491 /* We need to redraw what wasn't visible before */
1492 if (VisAfter != NULL)
1493 {
1494 DirtyRgn = IntSysCreateRectRgn(0, 0, 0, 0);
1495 if (CopyRgn != NULL)
1496 {
1497 RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
1498 }
1499 else
1500 {
1501 RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY);
1502 }
1503 if (RgnType != ERROR && RgnType != NULLREGION)
1504 {
1505 /* old code
1506 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
1507 IntInvalidateWindows( Window,
1508 DirtyRgn,
1509 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1510 }
1511 GreDeleteObject(DirtyRgn);
1512 */
1513
1514 PWND Parent = Window->spwndParent;
1515
1516 NtGdiOffsetRgn( DirtyRgn,
1517 Window->rcWindow.left,
1518 Window->rcWindow.top);
1519 if ( (Window->style & WS_CHILD) &&
1520 (Parent) &&
1521 !(Parent->style & WS_CLIPCHILDREN))
1522 {
1523 IntInvalidateWindows( Parent,
1524 DirtyRgn,
1525 RDW_ERASE | RDW_INVALIDATE);
1526 co_IntPaintWindows(Parent, RDW_ERASENOW, FALSE);
1527 }
1528 else
1529 {
1530 IntInvalidateWindows( Window,
1531 DirtyRgn,
1532 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1533 }
1534 }
1535 GreDeleteObject(DirtyRgn);
1536 }
1537
1538 if (CopyRgn != NULL)
1539 {
1540 GreDeleteObject(CopyRgn);
1541 }
1542
1543 /* Expose what was covered before but not covered anymore */
1544 if (VisBefore != NULL)
1545 {
1546 ExposedRgn = IntSysCreateRectRgn(0, 0, 0, 0);
1547 RgnType = NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
1548 NtGdiOffsetRgn( ExposedRgn,
1549 OldWindowRect.left - NewWindowRect.left,
1550 OldWindowRect.top - NewWindowRect.top);
1551
1552 if (VisAfter != NULL)
1553 RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
1554
1555 if (RgnType != ERROR && RgnType != NULLREGION)
1556 {
1557 co_VIS_WindowLayoutChanged(Window, ExposedRgn);
1558 }
1559 GreDeleteObject(ExposedRgn);
1560 GreDeleteObject(VisBefore);
1561 }
1562
1563 if (VisAfter != NULL)
1564 {
1565 GreDeleteObject(VisAfter);
1566 }
1567
1568 if (!(WinPos.flags & SWP_NOACTIVATE))
1569 {
1570 if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
1571 {
1572 co_IntSendMessageNoWait(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0);
1573 }
1574 else
1575 {
1576 co_IntSetForegroundWindow(Window);
1577 }
1578 }
1579 }
1580
1581 if ((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)
1582 {
1583 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
1584 and always contains final window position.
1585 */
1586 WinPos.x = NewWindowRect.left;
1587 WinPos.y = NewWindowRect.top;
1588 WinPos.cx = NewWindowRect.right - NewWindowRect.left;
1589 WinPos.cy = NewWindowRect.bottom - NewWindowRect.top;
1590 co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos);
1591 }
1592
1593 if ( WinPos.flags & SWP_FRAMECHANGED || WinPos.flags & SWP_STATECHANGED ||
1594 !(WinPos.flags & SWP_NOCLIENTSIZE) || !(WinPos.flags & SWP_NOCLIENTMOVE) )
1595 {
1596 PWND pWnd = UserGetWindowObject(WinPos.hwnd);
1597 if (pWnd)
1598 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
1599 }
1600
1601 if(bPointerInWindow != IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y))
1602 {
1603 /* Generate mouse move message */
1604 MSG msg;
1605 msg.message = WM_MOUSEMOVE;
1606 msg.wParam = UserGetMouseButtonsState();
1607 msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y);
1608 msg.pt = gpsi->ptCursor;
1609 co_MsqInsertMouseMessage(&msg, 0, 0, TRUE);
1610 }
1611
1612 return TRUE;
1613 }
1614
1615 LRESULT FASTCALL
1616 co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect)
1617 {
1618 LRESULT Result;
1619
1620 ASSERT_REFS_CO(Window);
1621
1622 *ClientRect = *WindowRect;
1623 Result = co_IntSendMessage(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect);
1624
1625 FixClientRect(ClientRect, WindowRect);
1626
1627 return Result;
1628 }
1629
1630 void FASTCALL
1631 co_WinPosSendSizeMove(PWND Wnd)
1632 {
1633 RECTL Rect;
1634 LPARAM lParam;
1635 WPARAM wParam = SIZE_RESTORED;
1636
1637 IntGetClientRect(Wnd, &Rect);
1638
1639 Wnd->state &= ~WNDS_SENDSIZEMOVEMSGS;
1640 if (Wnd->style & WS_MAXIMIZE)
1641 {
1642 wParam = SIZE_MAXIMIZED;
1643 }
1644 else if (Wnd->style & WS_MINIMIZE)
1645 {
1646 wParam = SIZE_MINIMIZED;
1647 }
1648
1649 co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SIZE, wParam, MAKELONG(Rect.right-Rect.left, Rect.bottom-Rect.top));
1650
1651 if (Wnd->spwndParent == UserGetDesktopWindow()) // Wnd->spwndParent->fnid != FNID_DESKTOP )
1652 lParam = MAKELONG(Wnd->rcClient.left, Wnd->rcClient.top);
1653 else
1654 lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top);
1655
1656 co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_MOVE, 0, lParam);
1657 IntEngWindowChanged(Wnd, WOC_RGN_CLIENT);
1658 }
1659
1660 BOOLEAN FASTCALL
1661 co_WinPosShowWindow(PWND Wnd, INT Cmd)
1662 {
1663 BOOLEAN WasVisible;
1664 UINT Swp = 0;
1665 RECTL NewPos;
1666 BOOLEAN ShowFlag;
1667 LONG style;
1668 // HRGN VisibleRgn;
1669
1670 ASSERT_REFS_CO(Wnd);
1671
1672 WasVisible = (Wnd->style & WS_VISIBLE) != 0;
1673 style = Wnd->style;
1674
1675 switch (Cmd)
1676 {
1677 case SW_HIDE:
1678 {
1679 if (!WasVisible)
1680 {
1681 return(FALSE);
1682 }
1683 Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1684 if (Wnd->head.h != UserGetActiveWindow())
1685 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1686 break;
1687 }
1688
1689 case SW_SHOWMINNOACTIVE:
1690 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1691 /* Fall through. */
1692 case SW_SHOWMINIMIZED:
1693 Swp |= SWP_SHOWWINDOW;
1694 /* Fall through. */
1695 case SW_MINIMIZE:
1696 {
1697 Swp |= SWP_NOACTIVATE;
1698 if (!(style & WS_MINIMIZE))
1699 {
1700 Swp |= co_WinPosMinMaximize(Wnd, SW_MINIMIZE, &NewPos) |
1701 SWP_FRAMECHANGED;
1702 }
1703 else
1704 {
1705 Swp |= SWP_NOSIZE | SWP_NOMOVE;
1706 if (! WasVisible)
1707 {
1708 Swp |= SWP_FRAMECHANGED;
1709 }
1710 }
1711 break;
1712 }
1713
1714 case SW_SHOWMAXIMIZED:
1715 {
1716 Swp |= SWP_SHOWWINDOW;
1717 if (!(style & WS_MAXIMIZE))
1718 {
1719 Swp |= co_WinPosMinMaximize(Wnd, SW_MAXIMIZE, &NewPos) |
1720 SWP_FRAMECHANGED;
1721 }
1722 else
1723 {
1724 Swp |= SWP_NOSIZE | SWP_NOMOVE;
1725 if (! WasVisible)
1726 {
1727 Swp |= SWP_FRAMECHANGED;
1728 }
1729 }
1730 break;
1731 }
1732
1733 case SW_SHOWNA:
1734 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1735 /* Fall through. */
1736 case SW_SHOW:
1737 if (WasVisible) return(TRUE); // Nothing to do!
1738 Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
1739 /* Don't activate the topmost window. */
1740 if (style & WS_CHILD) Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1741 break;
1742
1743 case SW_SHOWNOACTIVATE:
1744 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
1745 //Swp |= SWP_NOZORDER;
1746 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1747 /* Fall through. */
1748 case SW_SHOWNORMAL:
1749 case SW_SHOWDEFAULT:
1750 case SW_RESTORE:
1751 Swp |= SWP_SHOWWINDOW;
1752 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1753 {
1754 Swp |= co_WinPosMinMaximize(Wnd, SW_RESTORE, &NewPos) |
1755 SWP_FRAMECHANGED;
1756 }
1757 else
1758 {
1759 Swp |= SWP_NOSIZE | SWP_NOMOVE;
1760 if (! WasVisible)
1761 {
1762 Swp |= SWP_FRAMECHANGED;
1763 }
1764 }
1765 break;
1766 }
1767
1768 ShowFlag = (Cmd != SW_HIDE);
1769
1770 if (ShowFlag != WasVisible)
1771 {
1772 co_IntSendMessageNoWait(Wnd->head.h, WM_SHOWWINDOW, ShowFlag, 0);
1773 if (!(Wnd->state2 & WNDS2_WIN31COMPAT))
1774 co_IntSendMessageNoWait(Wnd->head.h, WM_SETVISIBLE, ShowFlag, 0);
1775 }
1776
1777 /* We can't activate a child window */
1778 if ((Wnd->style & WS_CHILD) &&
1779 !(Wnd->ExStyle & WS_EX_MDICHILD))
1780 {
1781 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1782 }
1783 #if 0 // Explorer issues with common controls. Someone does not know how CS_SAVEBITS works.
1784 if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD &&
1785 Wnd->pcls->style & CS_SAVEBITS &&
1786 ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL)))
1787 {
1788 co_IntSetActiveWindow(Wnd);
1789 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
1790 }
1791 #endif
1792 co_WinPosSetWindowPos(Wnd, 0 != (Wnd->ExStyle & WS_EX_TOPMOST)
1793 ? HWND_TOPMOST : HWND_TOP,
1794 NewPos.left, NewPos.top, NewPos.right, NewPos.bottom, LOWORD(Swp));
1795
1796 if ((Cmd == SW_HIDE) || (Cmd == SW_MINIMIZE))
1797 {
1798 PWND ThreadFocusWindow;
1799
1800 /* FIXME: This will cause the window to be activated irrespective
1801 * of whether it is owned by the same thread. Has to be done
1802 * asynchronously.
1803 */
1804
1805 if (Wnd->head.h == UserGetActiveWindow())
1806 {
1807 co_WinPosActivateOtherWindow(Wnd);
1808 }
1809
1810
1811 // Temp HACK
1812 ThreadFocusWindow = UserGetWindowObject(IntGetThreadFocusWindow());
1813
1814 /* Revert focus to parent */
1815 /* if (ThreadFocusWindow && (Wnd == ThreadFocusWindow ||
1816 IntIsChildWindow(Wnd, ThreadFocusWindow)))
1817 */
1818 if (Wnd == ThreadFocusWindow)
1819 {
1820 // FIXME: As long as we have ref on Window, we also, indirectly, have ref on parent...
1821 co_UserSetFocus(Wnd->spwndParent);
1822 }
1823 }
1824
1825 /* FIXME: Check for window destruction. */
1826
1827 if ((Wnd->state & WNDS_SENDSIZEMOVEMSGS) &&
1828 !(Wnd->state2 & WNDS2_INDESTROY))
1829 {
1830 co_WinPosSendSizeMove(Wnd);
1831 }
1832
1833 /* if previous state was minimized Windows sets focus to the window */
1834 if (style & WS_MINIMIZE) co_UserSetFocus(Wnd);
1835
1836 return(WasVisible);
1837 }
1838
1839 static
1840 PWND FASTCALL
1841 co_WinPosSearchChildren(
1842 PWND ScopeWin,
1843 POINT *Point,
1844 USHORT *HitTest
1845 )
1846 {
1847 PWND pwndChild;
1848 HWND *List, *phWnd;
1849
1850 if (!(ScopeWin->style & WS_VISIBLE))
1851 {
1852 return NULL;
1853 }
1854
1855 if ((ScopeWin->style & WS_DISABLED))
1856 {
1857 return NULL;
1858 }
1859
1860 if (!IntPtInWindow(ScopeWin, Point->x, Point->y))
1861 {
1862 return NULL;
1863 }
1864
1865 UserReferenceObject(ScopeWin);
1866
1867 if (Point->x - ScopeWin->rcClient.left < ScopeWin->rcClient.right &&
1868 Point->y - ScopeWin->rcClient.top < ScopeWin->rcClient.bottom )
1869 {
1870 List = IntWinListChildren(ScopeWin);
1871 if(List)
1872 {
1873 for (phWnd = List; *phWnd; ++phWnd)
1874 {
1875 if (!(pwndChild = UserGetWindowObject(*phWnd)))
1876 {
1877 continue;
1878 }
1879
1880 pwndChild = co_WinPosSearchChildren(pwndChild, Point, HitTest);
1881
1882 if(pwndChild != NULL)
1883 {
1884 /* We found a window. Don't send any more WM_NCHITTEST messages */
1885 ExFreePool(List);
1886 UserDereferenceObject(ScopeWin);
1887 return pwndChild;
1888 }
1889 }
1890 ExFreePool(List);
1891 }
1892 }
1893
1894 *HitTest = co_IntSendMessage(ScopeWin->head.h, WM_NCHITTEST, 0,
1895 MAKELONG(Point->x, Point->y));
1896 if ((*HitTest) == (USHORT)HTTRANSPARENT)
1897 {
1898 UserDereferenceObject(ScopeWin);
1899 return NULL;
1900 }
1901
1902 return ScopeWin;
1903 }
1904
1905 PWND FASTCALL
1906 co_WinPosWindowFromPoint(PWND ScopeWin, POINT *WinPoint, USHORT* HitTest)
1907 {
1908 PWND Window;
1909 POINT Point = *WinPoint;
1910 USER_REFERENCE_ENTRY Ref;
1911
1912 if( ScopeWin == NULL )
1913 {
1914 ScopeWin = UserGetDesktopWindow();
1915 if(ScopeWin == NULL)
1916 return NULL;
1917 }
1918
1919 *HitTest = HTNOWHERE;
1920
1921 ASSERT_REFS_CO(ScopeWin);
1922 UserRefObjectCo(ScopeWin, &Ref);
1923
1924 Window = co_WinPosSearchChildren(ScopeWin, &Point, HitTest);
1925
1926 UserDerefObjectCo(ScopeWin);
1927 if(Window)
1928 ASSERT_REFS_CO(Window);
1929 ASSERT_REFS_CO(ScopeWin);
1930
1931 return Window;
1932 }
1933
1934 HDWP
1935 FASTCALL
1936 IntDeferWindowPos( HDWP hdwp,
1937 HWND hwnd,
1938 HWND hwndAfter,
1939 INT x,
1940 INT y,
1941 INT cx,
1942 INT cy,
1943 UINT flags )
1944 {
1945 PSMWP pDWP;
1946 int i;
1947 HDWP retvalue = hdwp;
1948
1949 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
1950 hdwp, hwnd, hwndAfter, x, y, cx, cy, flags);
1951
1952 if (flags & ~(SWP_NOSIZE | SWP_NOMOVE |
1953 SWP_NOZORDER | SWP_NOREDRAW |
1954 SWP_NOACTIVATE | SWP_NOCOPYBITS |
1955 SWP_NOOWNERZORDER|SWP_SHOWWINDOW |
1956 SWP_HIDEWINDOW | SWP_FRAMECHANGED))
1957 {
1958 EngSetLastError(ERROR_INVALID_PARAMETER);
1959 return NULL;
1960 }
1961
1962 if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, otSMWP)))
1963 {
1964 EngSetLastError(ERROR_INVALID_DWP_HANDLE);
1965 return NULL;
1966 }
1967
1968 for (i = 0; i < pDWP->ccvr; i++)
1969 {
1970 if (pDWP->acvr[i].pos.hwnd == hwnd)
1971 {
1972 /* Merge with the other changes */
1973 if (!(flags & SWP_NOZORDER))
1974 {
1975 pDWP->acvr[i].pos.hwndInsertAfter = hwndAfter;
1976 }
1977 if (!(flags & SWP_NOMOVE))
1978 {
1979 pDWP->acvr[i].pos.x = x;
1980 pDWP->acvr[i].pos.y = y;
1981 }
1982 if (!(flags & SWP_NOSIZE))
1983 {
1984 pDWP->acvr[i].pos.cx = cx;
1985 pDWP->acvr[i].pos.cy = cy;
1986 }
1987 pDWP->acvr[i].pos.flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
1988 SWP_NOZORDER | SWP_NOREDRAW |
1989 SWP_NOACTIVATE | SWP_NOCOPYBITS|
1990 SWP_NOOWNERZORDER);
1991 pDWP->acvr[i].pos.flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
1992 SWP_FRAMECHANGED);
1993 goto END;
1994 }
1995 }
1996 if (pDWP->ccvr >= pDWP->ccvrAlloc)
1997 {
1998 PCVR newpos = ExAllocatePoolWithTag(PagedPool, pDWP->ccvrAlloc * 2 * sizeof(CVR), USERTAG_SWP);
1999 if (!newpos)
2000 {
2001 retvalue = NULL;
2002 goto END;
2003 }
2004 RtlZeroMemory(newpos, pDWP->ccvrAlloc * 2 * sizeof(CVR));
2005 RtlCopyMemory(newpos, pDWP->acvr, pDWP->ccvrAlloc * sizeof(CVR));
2006 ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP);
2007 pDWP->ccvrAlloc *= 2;
2008 pDWP->acvr = newpos;
2009 }
2010 pDWP->acvr[pDWP->ccvr].pos.hwnd = hwnd;
2011 pDWP->acvr[pDWP->ccvr].pos.hwndInsertAfter = hwndAfter;
2012 pDWP->acvr[pDWP->ccvr].pos.x = x;
2013 pDWP->acvr[pDWP->ccvr].pos.y = y;
2014 pDWP->acvr[pDWP->ccvr].pos.cx = cx;
2015 pDWP->acvr[pDWP->ccvr].pos.cy = cy;
2016 pDWP->acvr[pDWP->ccvr].pos.flags = flags;
2017 pDWP->acvr[pDWP->ccvr].hrgnClip = NULL;
2018 pDWP->acvr[pDWP->ccvr].hrgnInterMonitor = NULL;
2019 pDWP->ccvr++;
2020 END:
2021 return retvalue;
2022 }
2023
2024 BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp, BOOL sAsync )
2025 {
2026 PSMWP pDWP;
2027 PCVR winpos;
2028 BOOL res = TRUE;
2029 int i;
2030
2031 TRACE("%p\n", hdwp);
2032
2033 if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, otSMWP)))
2034 {
2035 EngSetLastError(ERROR_INVALID_DWP_HANDLE);
2036 return FALSE;
2037 }
2038
2039 for (i = 0, winpos = pDWP->acvr; res && i < pDWP->ccvr; i++, winpos++)
2040 {
2041 PWND pwnd;
2042 USER_REFERENCE_ENTRY Ref;
2043
2044 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2045 winpos->pos.hwnd, winpos->pos.hwndInsertAfter, winpos->pos.x, winpos->pos.y,
2046 winpos->pos.cx, winpos->pos.cy, winpos->pos.flags);
2047
2048 pwnd = UserGetWindowObject(winpos->pos.hwnd);
2049 if (!pwnd)
2050 continue;
2051
2052 UserRefObjectCo(pwnd, &Ref);
2053
2054 if ( sAsync )
2055 {
2056 LRESULT lRes;
2057 PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP);
2058 if ( ppos )
2059 {
2060 *ppos = winpos->pos;
2061 /* Yes it's a pointer inside Win32k! */
2062 lRes = co_IntSendMessageNoWait( winpos->pos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos);
2063 /* We handle this the same way as Event Hooks and Hooks. */
2064 if ( -1 == (int) lRes )
2065 {
2066 ExFreePoolWithTag(ppos, USERTAG_SWP);
2067 }
2068 }
2069 }
2070 else
2071 res = co_WinPosSetWindowPos( pwnd,
2072 winpos->pos.hwndInsertAfter,
2073 winpos->pos.x,
2074 winpos->pos.y,
2075 winpos->pos.cx,
2076 winpos->pos.cy,
2077 winpos->pos.flags);
2078
2079 UserDerefObjectCo(pwnd);
2080 }
2081 ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP);
2082 UserDereferenceObject(pDWP);
2083 UserDeleteObject(hdwp, otSMWP);
2084 return res;
2085 }
2086
2087
2088 /*
2089 * @implemented
2090 */
2091 HWND APIENTRY
2092 NtUserChildWindowFromPointEx(HWND hwndParent,
2093 LONG x,
2094 LONG y,
2095 UINT uiFlags)
2096 {
2097 PWND Parent;
2098 POINTL Pt;
2099 HWND Ret;
2100 HWND *List, *phWnd;
2101
2102 if(!(Parent = UserGetWindowObject(hwndParent)))
2103 {
2104 return NULL;
2105 }
2106
2107 Pt.x = x;
2108 Pt.y = y;
2109
2110 if(Parent->head.h != IntGetDesktopWindow())
2111 {
2112 Pt.x += Parent->rcClient.left;
2113 Pt.y += Parent->rcClient.top;
2114 }
2115
2116 if(!IntPtInWindow(Parent, Pt.x, Pt.y))
2117 {
2118 return NULL;
2119 }
2120
2121 Ret = Parent->head.h;
2122 if((List = IntWinListChildren(Parent)))
2123 {
2124 for(phWnd = List; *phWnd; phWnd++)
2125 {
2126 PWND Child;
2127 if((Child = UserGetWindowObject(*phWnd)))
2128 {
2129 if(!(Child->style & WS_VISIBLE) && (uiFlags & CWP_SKIPINVISIBLE))
2130 {
2131 continue;
2132 }
2133 if((Child->style & WS_DISABLED) && (uiFlags & CWP_SKIPDISABLED))
2134 {
2135 continue;
2136 }
2137 if((Child->ExStyle & WS_EX_TRANSPARENT) && (uiFlags & CWP_SKIPTRANSPARENT))
2138 {
2139 continue;
2140 }
2141 if(IntPtInWindow(Child, Pt.x, Pt.y))
2142 {
2143 Ret = Child->head.h;
2144 break;
2145 }
2146 }
2147 }
2148 ExFreePool(List);
2149 }
2150
2151 return Ret;
2152 }
2153
2154 /*
2155 * @implemented
2156 */
2157 BOOL APIENTRY
2158 NtUserEndDeferWindowPosEx(HDWP WinPosInfo,
2159 DWORD Unknown1)
2160 {
2161 BOOL Ret;
2162 TRACE("Enter NtUserEndDeferWindowPosEx\n");
2163 UserEnterExclusive();
2164 Ret = IntEndDeferWindowPosEx(WinPosInfo, (BOOL)Unknown1);
2165 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret);
2166 UserLeave();
2167 return Ret;
2168 }
2169
2170 /*
2171 * @implemented
2172 */
2173 HDWP APIENTRY
2174 NtUserDeferWindowPos(HDWP WinPosInfo,
2175 HWND Wnd,
2176 HWND WndInsertAfter,
2177 int x,
2178 int y,
2179 int cx,
2180 int cy,
2181 UINT Flags)
2182 {
2183 PWND pWnd, pWndIA;
2184 HDWP Ret = NULL;
2185 UINT Tmp = ~(SWP_ASYNCWINDOWPOS|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_NOREPOSITION|
2186 SWP_NOCOPYBITS|SWP_HIDEWINDOW|SWP_SHOWWINDOW|SWP_FRAMECHANGED|
2187 SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE);
2188
2189 TRACE("Enter NtUserDeferWindowPos\n");
2190 UserEnterExclusive();
2191
2192 if ( Flags & Tmp )
2193 {
2194 EngSetLastError(ERROR_INVALID_FLAGS);
2195 goto Exit;
2196 }
2197
2198 pWnd = UserGetWindowObject(Wnd);
2199 if ( !pWnd || // FIXME:
2200 pWnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2201 pWnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2202 {
2203 goto Exit;
2204 }
2205
2206 if ( WndInsertAfter &&
2207 WndInsertAfter != HWND_BOTTOM &&
2208 WndInsertAfter != HWND_TOPMOST &&
2209 WndInsertAfter != HWND_NOTOPMOST )
2210 {
2211 pWndIA = UserGetWindowObject(WndInsertAfter);
2212 if ( !pWndIA ||
2213 pWndIA == IntGetDesktopWindow() ||
2214 pWndIA == IntGetMessageWindow() )
2215 {
2216 goto Exit;
2217 }
2218 }
2219
2220 Ret = IntDeferWindowPos(WinPosInfo, Wnd, WndInsertAfter, x, y, cx, cy, Flags);
2221
2222 Exit:
2223 TRACE("Leave NtUserDeferWindowPos, ret=%i\n", Ret);
2224 UserLeave();
2225 return Ret;
2226 }
2227
2228 /*
2229 * @implemented
2230 */
2231 DWORD APIENTRY
2232 NtUserGetInternalWindowPos( HWND hWnd,
2233 LPRECT rectWnd,
2234 LPPOINT ptIcon)
2235 {
2236 PWND Window;
2237 DWORD Ret = 0;
2238 BOOL Hit = FALSE;
2239 WINDOWPLACEMENT wndpl;
2240
2241 UserEnterShared();
2242
2243 if (!(Window = UserGetWindowObject(hWnd)))
2244 {
2245 Hit = FALSE;
2246 goto Exit;
2247 }
2248
2249 _SEH2_TRY
2250 {
2251 if(rectWnd)
2252 {
2253 ProbeForWrite(rectWnd,
2254 sizeof(RECT),
2255 1);
2256 }
2257 if(ptIcon)
2258 {
2259 ProbeForWrite(ptIcon,
2260 sizeof(POINT),
2261 1);
2262 }
2263
2264 }
2265 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2266 {
2267 SetLastNtError(_SEH2_GetExceptionCode());
2268 Hit = TRUE;
2269 }
2270 _SEH2_END;
2271
2272 wndpl.length = sizeof(WINDOWPLACEMENT);
2273
2274 if (IntGetWindowPlacement(Window, &wndpl) && !Hit)
2275 {
2276 _SEH2_TRY
2277 {
2278 if (rectWnd)
2279 {
2280 RtlCopyMemory(rectWnd, &wndpl.rcNormalPosition , sizeof(RECT));
2281 }
2282 if (ptIcon)
2283 {
2284 RtlCopyMemory(ptIcon, &wndpl.ptMinPosition, sizeof(POINT));
2285 }
2286
2287 }
2288 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2289 {
2290 SetLastNtError(_SEH2_GetExceptionCode());
2291 Hit = TRUE;
2292 }
2293 _SEH2_END;
2294
2295 if (!Hit) Ret = wndpl.showCmd;
2296 }
2297 Exit:
2298 UserLeave();
2299 return Ret;
2300 }
2301
2302 /*
2303 * @implemented
2304 */
2305 BOOL APIENTRY
2306 NtUserGetWindowPlacement(HWND hWnd,
2307 WINDOWPLACEMENT *lpwndpl)
2308 {
2309 PWND Wnd;
2310 WINDOWPLACEMENT Safepl;
2311 NTSTATUS Status;
2312 DECLARE_RETURN(BOOL);
2313
2314 TRACE("Enter NtUserGetWindowPlacement\n");
2315 UserEnterShared();
2316
2317 if (!(Wnd = UserGetWindowObject(hWnd)))
2318 {
2319 RETURN( FALSE);
2320 }
2321
2322 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
2323 if(!NT_SUCCESS(Status))
2324 {
2325 SetLastNtError(Status);
2326 RETURN( FALSE);
2327 }
2328 if(Safepl.length != sizeof(WINDOWPLACEMENT))
2329 {
2330 RETURN( FALSE);
2331 }
2332
2333 IntGetWindowPlacement(Wnd, &Safepl);
2334
2335 Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
2336 if(!NT_SUCCESS(Status))
2337 {
2338 SetLastNtError(Status);
2339 RETURN( FALSE);
2340 }
2341
2342 RETURN( TRUE);
2343
2344 CLEANUP:
2345 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_);
2346 UserLeave();
2347 END_CLEANUP;
2348 }
2349
2350 DWORD
2351 APIENTRY
2352 NtUserMinMaximize(
2353 HWND hWnd,
2354 UINT cmd, // Wine SW_ commands
2355 BOOL Hide)
2356 {
2357 RECTL NewPos;
2358 UINT SwFlags;
2359 PWND pWnd;
2360
2361 TRACE("Enter NtUserMinMaximize\n");
2362 UserEnterExclusive();
2363
2364 pWnd = UserGetWindowObject(hWnd);
2365 if ( !pWnd || // FIXME:
2366 pWnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2367 pWnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2368 {
2369 goto Exit;
2370 }
2371
2372 if ( cmd > SW_MAX || pWnd->state2 & WNDS2_INDESTROY)
2373 {
2374 EngSetLastError(ERROR_INVALID_PARAMETER);
2375 goto Exit;
2376 }
2377
2378 co_WinPosMinMaximize(pWnd, cmd, &NewPos);
2379
2380 SwFlags = Hide ? SWP_NOACTIVATE|SWP_NOZORDER|SWP_FRAMECHANGED : SWP_NOZORDER|SWP_FRAMECHANGED;
2381
2382 co_WinPosSetWindowPos( pWnd,
2383 NULL,
2384 NewPos.left,
2385 NewPos.top,
2386 NewPos.right,
2387 NewPos.bottom,
2388 SwFlags);
2389
2390 co_WinPosShowWindow(pWnd, cmd);
2391
2392 Exit:
2393 TRACE("Leave NtUserMinMaximize\n");
2394 UserLeave();
2395 return 0; // Always NULL?
2396 }
2397
2398 /*
2399 * @implemented
2400 */
2401 BOOL APIENTRY
2402 NtUserMoveWindow(
2403 HWND hWnd,
2404 int X,
2405 int Y,
2406 int nWidth,
2407 int nHeight,
2408 BOOL bRepaint)
2409 {
2410 return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight,
2411 (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE :
2412 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW));
2413 }
2414
2415 /*
2416 * @implemented
2417 */
2418 BOOL APIENTRY
2419 NtUserSetWindowPos(
2420 HWND hWnd,
2421 HWND hWndInsertAfter,
2422 int X,
2423 int Y,
2424 int cx,
2425 int cy,
2426 UINT uFlags)
2427 {
2428 DECLARE_RETURN(BOOL);
2429 PWND Window, pWndIA;
2430 BOOL ret;
2431 USER_REFERENCE_ENTRY Ref;
2432
2433 TRACE("Enter NtUserSetWindowPos\n");
2434 UserEnterExclusive();
2435
2436 if (!(Window = UserGetWindowObject(hWnd)) || // FIXME:
2437 Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2438 Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2439 {
2440 RETURN(FALSE);
2441 }
2442
2443 if ( hWndInsertAfter &&
2444 hWndInsertAfter != HWND_BOTTOM &&
2445 hWndInsertAfter != HWND_TOPMOST &&
2446 hWndInsertAfter != HWND_NOTOPMOST )
2447 {
2448 pWndIA = UserGetWindowObject(hWndInsertAfter);
2449 if ( !pWndIA ||
2450 pWndIA == IntGetDesktopWindow() ||
2451 pWndIA == IntGetMessageWindow() )
2452 {
2453 RETURN(FALSE);
2454 }
2455 }
2456
2457 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
2458 if (!(uFlags & SWP_NOMOVE))
2459 {
2460 if (X < -32768) X = -32768;
2461 else if (X > 32767) X = 32767;
2462 if (Y < -32768) Y = -32768;
2463 else if (Y > 32767) Y = 32767;
2464 }
2465 if (!(uFlags & SWP_NOSIZE))
2466 {
2467 if (cx < 0) cx = 0;
2468 else if (cx > 32767) cx = 32767;
2469 if (cy < 0) cy = 0;
2470 else if (cy > 32767) cy = 32767;
2471 }
2472
2473 UserRefObjectCo(Window, &Ref);
2474 ret = co_WinPosSetWindowPos(Window, hWndInsertAfter, X, Y, cx, cy, uFlags);
2475 UserDerefObjectCo(Window);
2476
2477 RETURN(ret);
2478
2479 CLEANUP:
2480 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_);
2481 UserLeave();
2482 END_CLEANUP;
2483 }
2484
2485 /*
2486 * @implemented
2487 */
2488 INT APIENTRY
2489 NtUserSetWindowRgn(
2490 HWND hWnd,
2491 HRGN hRgn,
2492 BOOL bRedraw)
2493 {
2494 HRGN hrgnCopy;
2495 PWND Window;
2496 INT flags = (SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE);
2497 BOOLEAN Ret = FALSE;
2498 DECLARE_RETURN(INT);
2499
2500 TRACE("Enter NtUserSetWindowRgn\n");
2501 UserEnterExclusive();
2502
2503 if (!(Window = UserGetWindowObject(hWnd)) || // FIXME:
2504 Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2505 Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2506 {
2507 RETURN( 0);
2508 }
2509
2510 if (hRgn) // The region will be deleted in user32.
2511 {
2512 if (GreIsHandleValid(hRgn))
2513 {
2514 hrgnCopy = IntSysCreateRectRgn(0, 0, 0, 0);
2515 /* The coordinates of a window's window region are relative to the
2516 upper-left corner of the window, not the client area of the window. */
2517 NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY);
2518 }
2519 else
2520 RETURN( 0);
2521 }
2522 else
2523 {
2524 hrgnCopy = NULL;
2525 }
2526
2527 if (Window->hrgnClip)
2528 {
2529 /* Delete no longer needed region handle */
2530 IntGdiSetRegionOwner(Window->hrgnClip, GDI_OBJ_HMGR_POWNED);
2531 GreDeleteObject(Window->hrgnClip);
2532 }
2533
2534 if (hrgnCopy)
2535 {
2536 /* Set public ownership */
2537 IntGdiSetRegionOwner(hrgnCopy, GDI_OBJ_HMGR_PUBLIC);
2538 }
2539 Window->hrgnClip = hrgnCopy;
2540
2541 Ret = co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, bRedraw ? flags : (flags|SWP_NOREDRAW) );
2542
2543 RETURN( (INT)Ret);
2544
2545 CLEANUP:
2546 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_);
2547 UserLeave();
2548 END_CLEANUP;
2549 }
2550
2551 /*
2552 * @implemented
2553 */
2554 DWORD APIENTRY
2555 NtUserSetInternalWindowPos(
2556 HWND hwnd,
2557 UINT showCmd,
2558 LPRECT lprect,
2559 LPPOINT lppt)
2560 {
2561 WINDOWPLACEMENT wndpl;
2562 UINT flags;
2563 PWND Wnd;
2564 RECT rect;
2565 POINT pt = {0};
2566 DECLARE_RETURN(BOOL);
2567 USER_REFERENCE_ENTRY Ref;
2568
2569 TRACE("Enter NtUserSetWindowPlacement\n");
2570 UserEnterExclusive();
2571
2572 if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME:
2573 Wnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2574 Wnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2575 {
2576 RETURN( FALSE);
2577 }
2578
2579 _SEH2_TRY
2580 {
2581 if (lppt)
2582 {
2583 ProbeForRead(lppt, sizeof(POINT), 1);
2584 RtlCopyMemory(&pt, lppt, sizeof(POINT));
2585 }
2586 if (lprect)
2587 {
2588 ProbeForRead(lprect, sizeof(RECT), 1);
2589 RtlCopyMemory(&rect, lprect, sizeof(RECT));
2590 }
2591 }
2592 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2593 {
2594 SetLastNtError(_SEH2_GetExceptionCode());
2595 _SEH2_YIELD(RETURN( FALSE));
2596 }
2597 _SEH2_END
2598
2599 wndpl.length = sizeof(wndpl);
2600 wndpl.showCmd = showCmd;
2601 wndpl.flags = flags = 0;
2602
2603 if ( lppt )
2604 {
2605 flags |= PLACE_MIN;
2606 wndpl.flags |= WPF_SETMINPOSITION;
2607 wndpl.ptMinPosition = pt;
2608 }
2609 if ( lprect )
2610 {
2611 flags |= PLACE_RECT;
2612 wndpl.rcNormalPosition = rect;
2613 }
2614
2615 UserRefObjectCo(Wnd, &Ref);
2616 IntSetWindowPlacement(Wnd, &wndpl, flags);
2617 UserDerefObjectCo(Wnd);
2618 RETURN(TRUE);
2619
2620 CLEANUP:
2621 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
2622 UserLeave();
2623 END_CLEANUP;
2624 }
2625
2626 /*
2627 * @implemented
2628 */
2629 BOOL APIENTRY
2630 NtUserSetWindowPlacement(HWND hWnd,
2631 WINDOWPLACEMENT *lpwndpl)
2632 {
2633 PWND Wnd;
2634 WINDOWPLACEMENT Safepl;
2635 UINT Flags;
2636 DECLARE_RETURN(BOOL);
2637 USER_REFERENCE_ENTRY Ref;
2638
2639 TRACE("Enter NtUserSetWindowPlacement\n");
2640 UserEnterExclusive();
2641
2642 if (!(Wnd = UserGetWindowObject(hWnd)) || // FIXME:
2643 Wnd == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2644 Wnd == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2645 {
2646 RETURN( FALSE);
2647 }
2648
2649 _SEH2_TRY
2650 {
2651 ProbeForRead(lpwndpl, sizeof(WINDOWPLACEMENT), 1);
2652 RtlCopyMemory(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
2653 }
2654 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
2655 {
2656 SetLastNtError(_SEH2_GetExceptionCode());
2657 _SEH2_YIELD(RETURN( FALSE));
2658 }
2659 _SEH2_END
2660
2661 if(Safepl.length != sizeof(WINDOWPLACEMENT))
2662 {
2663 RETURN( FALSE);
2664 }
2665
2666 Flags = PLACE_MAX | PLACE_RECT;
2667 if (Safepl.flags & WPF_SETMINPOSITION) Flags |= PLACE_MIN;
2668 UserRefObjectCo(Wnd, &Ref);
2669 IntSetWindowPlacement(Wnd, &Safepl, Flags);
2670 UserDerefObjectCo(Wnd);
2671 RETURN(TRUE);
2672
2673 CLEANUP:
2674 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
2675 UserLeave();
2676 END_CLEANUP;
2677 }
2678
2679 /*
2680 * @implemented
2681 */
2682 BOOL APIENTRY
2683 NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow)
2684 {
2685 PWND Window;
2686 BOOL ret;
2687 DECLARE_RETURN(BOOL);
2688 USER_REFERENCE_ENTRY Ref;
2689
2690 TRACE("Enter NtUserShowWindowAsync\n");
2691 UserEnterExclusive();
2692
2693 if (!(Window = UserGetWindowObject(hWnd)) || // FIXME:
2694 Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2695 Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2696 {
2697 RETURN(FALSE);
2698 }
2699
2700 if ( nCmdShow > SW_MAX )
2701 {
2702 EngSetLastError(ERROR_INVALID_PARAMETER);
2703 RETURN(FALSE);
2704 }
2705
2706 UserRefObjectCo(Window, &Ref);
2707 ret = co_IntSendMessageNoWait( hWnd, WM_ASYNC_SHOWWINDOW, nCmdShow, 0 );
2708 UserDerefObjectCo(Window);
2709 if (-1 == (int) ret || !ret) ret = FALSE;
2710
2711 RETURN(ret);
2712
2713 CLEANUP:
2714 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_);
2715 UserLeave();
2716 END_CLEANUP;
2717 }
2718
2719 /*
2720 * @implemented
2721 */
2722 BOOL APIENTRY
2723 NtUserShowWindow(HWND hWnd, LONG nCmdShow)
2724 {
2725 PWND Window;
2726 BOOL ret;
2727 DECLARE_RETURN(BOOL);
2728 USER_REFERENCE_ENTRY Ref;
2729
2730 TRACE("Enter NtUserShowWindow\n");
2731 UserEnterExclusive();
2732
2733 if (!(Window = UserGetWindowObject(hWnd)) || // FIXME:
2734 Window == IntGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP
2735 Window == IntGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND
2736 {
2737 RETURN(FALSE);
2738 }
2739
2740 if ( nCmdShow > SW_MAX || Window->state2 & WNDS2_INDESTROY)
2741 {
2742 EngSetLastError(ERROR_INVALID_PARAMETER);
2743 RETURN(FALSE);
2744 }
2745
2746 UserRefObjectCo(Window, &Ref);
2747 ret = co_WinPosShowWindow(Window, nCmdShow);
2748 UserDerefObjectCo(Window);
2749
2750 RETURN(ret);
2751
2752 CLEANUP:
2753 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_);
2754 UserLeave();
2755 END_CLEANUP;
2756 }
2757
2758
2759 /*
2760 * @implemented
2761 */
2762 HWND APIENTRY
2763 NtUserWindowFromPoint(LONG X, LONG Y)
2764 {
2765 POINT pt;
2766 HWND Ret;
2767 PWND DesktopWindow = NULL, Window = NULL;
2768 USHORT hittest;
2769 DECLARE_RETURN(HWND);
2770 USER_REFERENCE_ENTRY Ref;
2771
2772 TRACE("Enter NtUserWindowFromPoint\n");
2773 UserEnterExclusive();
2774
2775 if ((DesktopWindow = UserGetWindowObject(IntGetDesktopWindow())))
2776 {
2777 //PTHREADINFO pti;
2778
2779 pt.x = X;
2780 pt.y = Y;
2781
2782 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
2783 // It is possible this referencing is useless, though it should not hurt...
2784 UserRefObjectCo(DesktopWindow, &Ref);
2785
2786 //pti = PsGetCurrentThreadWin32Thread();
2787 Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest);
2788
2789 if(Window)
2790 {
2791 Ret = Window->head.h;
2792
2793 RETURN( Ret);
2794 }
2795 }
2796
2797 RETURN( NULL);
2798
2799 CLEANUP:
2800 if (Window) UserDereferenceObject(Window);
2801 if (DesktopWindow) UserDerefObjectCo(DesktopWindow);
2802
2803 TRACE("Leave NtUserWindowFromPoint, ret=%i\n",_ret_);
2804 UserLeave();
2805 END_CLEANUP;
2806 }
2807
2808 /* EOF */