[NtUser]
[reactos.git] / reactos / win32ss / user / ntuser / winpos.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Windows
5 * FILE: win32ss/user/ntuser/winpos.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_NOCLIENTSIZE | SWP_NOZORDER)
21 #define SWP_AGG_NOPOSCHANGE \
22 (SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_NOZORDER)
23 #define SWP_AGG_STATUSFLAGS \
24 (SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
25 #define SWP_AGG_NOCLIENTCHANGE \
26 (SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
27
28 #define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
29 #define PLACE_MIN 0x0001
30 #define PLACE_MAX 0x0002
31 #define PLACE_RECT 0x0004
32
33 VOID FASTCALL IntLinkWindow(PWND Wnd,PWND WndInsertAfter);
34
35 /* FUNCTIONS *****************************************************************/
36
37 #if DBG
38 /***********************************************************************
39 * dump_winpos_flags
40 */
41 static void dump_winpos_flags(UINT flags)
42 {
43 static const DWORD dumped_flags = (SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW |
44 SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_SHOWWINDOW |
45 SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOOWNERZORDER |
46 SWP_NOSENDCHANGING | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS |
47 SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_STATECHANGED);
48 TRACE("flags:");
49 if(flags & SWP_NOSIZE) TRACE(" SWP_NOSIZE");
50 if(flags & SWP_NOMOVE) TRACE(" SWP_NOMOVE");
51 if(flags & SWP_NOZORDER) TRACE(" SWP_NOZORDER");
52 if(flags & SWP_NOREDRAW) TRACE(" SWP_NOREDRAW");
53 if(flags & SWP_NOACTIVATE) TRACE(" SWP_NOACTIVATE");
54 if(flags & SWP_FRAMECHANGED) TRACE(" SWP_FRAMECHANGED");
55 if(flags & SWP_SHOWWINDOW) TRACE(" SWP_SHOWWINDOW");
56 if(flags & SWP_HIDEWINDOW) TRACE(" SWP_HIDEWINDOW");
57 if(flags & SWP_NOCOPYBITS) TRACE(" SWP_NOCOPYBITS");
58 if(flags & SWP_NOOWNERZORDER) TRACE(" SWP_NOOWNERZORDER");
59 if(flags & SWP_NOSENDCHANGING) TRACE(" SWP_NOSENDCHANGING");
60 if(flags & SWP_DEFERERASE) TRACE(" SWP_DEFERERASE");
61 if(flags & SWP_ASYNCWINDOWPOS) TRACE(" SWP_ASYNCWINDOWPOS");
62 if(flags & SWP_NOCLIENTSIZE) TRACE(" SWP_NOCLIENTSIZE");
63 if(flags & SWP_NOCLIENTMOVE) TRACE(" SWP_NOCLIENTMOVE");
64 if(flags & SWP_STATECHANGED) TRACE(" SWP_STATECHANGED");
65
66 if(flags & ~dumped_flags) TRACE(" %08x", flags & ~dumped_flags);
67 TRACE("\n");
68 }
69 #endif
70
71 BOOL FASTCALL
72 IntGetClientOrigin(PWND Window OPTIONAL, LPPOINT Point)
73 {
74 Window = Window ? Window : UserGetDesktopWindow();
75 if (Window == NULL)
76 {
77 Point->x = Point->y = 0;
78 return FALSE;
79 }
80 Point->x = Window->rcClient.left;
81 Point->y = Window->rcClient.top;
82
83 return TRUE;
84 }
85
86 /*!
87 * Internal function.
88 * Returns client window rectangle relative to the upper-left corner of client area.
89 *
90 * \note Does not check the validity of the parameters
91 */
92 VOID FASTCALL
93 IntGetClientRect(PWND Wnd, RECTL *Rect)
94 {
95 ASSERT( Wnd );
96 ASSERT( Rect );
97 if (Wnd->style & WS_MINIMIZED)
98 {
99 Rect->left = Rect->top = 0;
100 Rect->right = UserGetSystemMetrics(SM_CXMINIMIZED);
101 Rect->bottom = UserGetSystemMetrics(SM_CYMINIMIZED);
102 return;
103 }
104 if (!UserIsDesktopWindow(Wnd))
105 {
106 *Rect = Wnd->rcClient;
107 RECTL_vOffsetRect(Rect, -Wnd->rcClient.left, -Wnd->rcClient.top);
108 }
109 else
110 {
111 Rect->left = Rect->top = 0;
112 Rect->right = Wnd->rcClient.right;
113 Rect->bottom = Wnd->rcClient.bottom;
114 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
115 Rect->right = UserGetSystemMetrics(SM_CXSCREEN);
116 Rect->bottom = UserGetSystemMetrics(SM_CYSCREEN);
117 */
118 }
119 }
120
121 BOOL FASTCALL
122 IntGetWindowRect(PWND Wnd, RECTL *Rect)
123 {
124 ASSERT( Wnd );
125 ASSERT( Rect );
126 if (!Wnd) return FALSE;
127 if (!UserIsDesktopWindow(Wnd))
128 {
129 *Rect = Wnd->rcWindow;
130 }
131 else
132 {
133 Rect->left = Rect->top = 0;
134 Rect->right = Wnd->rcWindow.right;
135 Rect->bottom = Wnd->rcWindow.bottom;
136 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics.
137 Rect->right = GetSystemMetrics(SM_CXSCREEN);
138 Rect->bottom = GetSystemMetrics(SM_CYSCREEN);
139 */ }
140 return TRUE;
141 }
142
143
144 INT FASTCALL
145 IntMapWindowPoints(PWND FromWnd, PWND ToWnd, LPPOINT lpPoints, UINT cPoints)
146 {
147 BOOL mirror_from, mirror_to;
148 POINT Delta;
149 UINT i;
150 int Change = 1;
151
152 /* Note: Desktop Top and Left is always 0! */
153 Delta.x = Delta.y = 0;
154 mirror_from = mirror_to = FALSE;
155
156 if (FromWnd && !UserIsDesktopWindow(FromWnd))
157 {
158 if (FromWnd->ExStyle & WS_EX_LAYOUTRTL)
159 {
160 mirror_from = TRUE;
161 Change = -Change;
162 Delta.x = -FromWnd->rcClient.right;
163 }
164 else
165 Delta.x = FromWnd->rcClient.left;
166 Delta.y = FromWnd->rcClient.top;
167 }
168
169 if (ToWnd && !UserIsDesktopWindow(ToWnd))
170 {
171 if (ToWnd->ExStyle & WS_EX_LAYOUTRTL)
172 {
173 mirror_to = TRUE;
174 Change = -Change;
175 Delta.x += Change * ToWnd->rcClient.right;
176 }
177 else
178 Delta.x -= Change * ToWnd->rcClient.left;
179 Delta.y -= ToWnd->rcClient.top;
180 }
181
182 for (i = 0; i != cPoints; i++)
183 {
184 lpPoints[i].x += Delta.x;
185 lpPoints[i].x *= Change;
186 lpPoints[i].y += Delta.y;
187 }
188
189 if ((mirror_from || mirror_to) && cPoints == 2) /* special case for rectangle */
190 {
191 int tmp = min(lpPoints[0].x, lpPoints[1].x);
192 lpPoints[1].x = max(lpPoints[0].x, lpPoints[1].x);
193 lpPoints[0].x = tmp;
194 }
195
196 return MAKELONG(LOWORD(Delta.x), LOWORD(Delta.y));
197 }
198
199 BOOL FASTCALL
200 IntClientToScreen(PWND Wnd, LPPOINT lpPoint)
201 {
202 if (Wnd && Wnd->fnid != FNID_DESKTOP )
203 {
204 if (Wnd->ExStyle & WS_EX_LAYOUTRTL)
205 lpPoint->x = Wnd->rcClient.right - lpPoint->x;
206 else
207 lpPoint->x += Wnd->rcClient.left;
208 lpPoint->y += Wnd->rcClient.top;
209 }
210 return TRUE;
211 }
212
213 BOOL FASTCALL
214 IntScreenToClient(PWND Wnd, LPPOINT lpPoint)
215 {
216 if (Wnd && Wnd->fnid != FNID_DESKTOP )
217 {
218 if (Wnd->ExStyle & WS_EX_LAYOUTRTL)
219 lpPoint->x = Wnd->rcClient.right - lpPoint->x;
220 else
221 lpPoint->x -= Wnd->rcClient.left;
222 lpPoint->y -= Wnd->rcClient.top;
223 }
224 return TRUE;
225 }
226
227 BOOL FASTCALL IsChildVisible(PWND pWnd)
228 {
229 do
230 {
231 if ( (pWnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD ||
232 !(pWnd = pWnd->spwndParent) )
233 return TRUE;
234 }
235 while (pWnd->style & WS_VISIBLE);
236 return FALSE;
237 }
238
239 PWND FASTCALL IntGetLastTopMostWindow(VOID)
240 {
241 PWND pWnd;
242 PDESKTOP rpdesk = gptiCurrent->rpdesk;
243
244 if ( rpdesk &&
245 (pWnd = rpdesk->pDeskInfo->spwnd->spwndChild) &&
246 pWnd->ExStyle & WS_EX_TOPMOST)
247 {
248 for (;;)
249 {
250 if (!pWnd->spwndNext) break;
251 if (!(pWnd->spwndNext->ExStyle & WS_EX_TOPMOST)) break;
252 pWnd = pWnd->spwndNext;
253 }
254 return pWnd;
255 }
256 return NULL;
257 }
258
259 VOID
260 SelectWindowRgn(PWND Window, HRGN hRgnClip)
261 {
262 if (Window->hrgnClip)
263 {
264 /* Delete no longer needed region handle */
265 IntGdiSetRegionOwner(Window->hrgnClip, GDI_OBJ_HMGR_POWNED);
266 GreDeleteObject(Window->hrgnClip);
267 Window->hrgnClip = NULL;
268 }
269
270 if (hRgnClip > HRGN_WINDOW)
271 {
272 /*if (!UserIsDesktopWindow(Window))
273 {
274 NtGdiOffsetRgn(hRgnClip, Window->rcWindow.left, Window->rcWindow.top);
275 }*/
276 /* Set public ownership */
277 IntGdiSetRegionOwner(hRgnClip, GDI_OBJ_HMGR_PUBLIC);
278
279 Window->hrgnClip = hRgnClip;
280 }
281 }
282
283 //
284 // This helps with CORE-6129 forcing modal dialog active when another app is minimized or closed.
285 //
286 BOOL FASTCALL ActivateOtherWindowMin(PWND Wnd)
287 {
288 BOOL ActivePrev, FindTopWnd;
289 PWND pWndTopMost, pWndChild, pWndSetActive, pWndTemp, pWndDesk;
290 USER_REFERENCE_ENTRY Ref;
291 PTHREADINFO pti = gptiCurrent;
292
293 //ERR("AOWM 1 %p\n",Wnd->head.h);
294 ActivePrev = (pti->MessageQueue->spwndActivePrev != NULL);
295 FindTopWnd = TRUE;
296
297 if ((pWndTopMost = IntGetLastTopMostWindow()))
298 pWndChild = pWndTopMost->spwndNext;
299 else
300 pWndChild = Wnd->spwndParent->spwndChild;
301
302 for (;;)
303 {
304 if ( ActivePrev )
305 pWndSetActive = pti->MessageQueue->spwndActivePrev;
306 else
307 pWndSetActive = pWndChild;
308
309 pWndTemp = NULL;
310
311 while(pWndSetActive)
312 {
313 if ( VerifyWnd(pWndSetActive) &&
314 !(pWndSetActive->ExStyle & WS_EX_NOACTIVATE) &&
315 (pWndSetActive->style & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE &&
316 (!(pWndSetActive->style & WS_ICONIC) /* FIXME MinMax pos? */ ) )
317 {
318 if (!(pWndSetActive->ExStyle & WS_EX_TOOLWINDOW) )
319 {
320 UserRefObjectCo(pWndSetActive, &Ref);
321 //ERR("ActivateOtherWindowMin Set FG 1\n");
322 co_IntSetForegroundWindow(pWndSetActive);
323 UserDerefObjectCo(pWndSetActive);
324 //ERR("AOWM 2 Exit Good %p\n",pWndSetActive->head.h);
325 return TRUE;
326 }
327 if (!pWndTemp ) pWndTemp = pWndSetActive;
328 }
329 if ( ActivePrev )
330 {
331 ActivePrev = FALSE;
332 pWndSetActive = pWndChild;
333 }
334 else
335 pWndSetActive = pWndSetActive->spwndNext;
336 }
337
338 if ( !FindTopWnd ) break;
339 FindTopWnd = FALSE;
340
341 if ( pWndChild )
342 {
343 pWndChild = pWndChild->spwndParent->spwndChild;
344 continue;
345 }
346
347 if (!(pWndDesk = IntGetThreadDesktopWindow(pti)))
348 {
349 pWndChild = NULL;
350 continue;
351 }
352 pWndChild = pWndDesk->spwndChild;
353 }
354
355 if ((pWndSetActive = pWndTemp))
356 {
357 UserRefObjectCo(pWndSetActive, &Ref);
358 //ERR("ActivateOtherWindowMin Set FG 2\n");
359 co_IntSetForegroundWindow(pWndSetActive);
360 UserDerefObjectCo(pWndSetActive);
361 //ERR("AOWM 3 Exit Good %p\n",pWndSetActive->head.h);
362 return TRUE;
363 }
364 //ERR("AOWM 4 Bad\n");
365 return FALSE;
366 }
367
368 /*******************************************************************
369 * can_activate_window
370 *
371 * Check if we can activate the specified window.
372 */
373 static
374 BOOL FASTCALL can_activate_window( PWND Wnd OPTIONAL)
375 {
376 LONG style;
377
378 if (!Wnd) return FALSE;
379
380 style = Wnd->style;
381 if (!(style & WS_VISIBLE)) return FALSE;
382 if (style & WS_MINIMIZE) return FALSE;
383 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
384 return TRUE;
385 /* FIXME: This window could be disable because the child that closed
386 was a popup. */
387 //return !(style & WS_DISABLED);
388 }
389
390
391 /*******************************************************************
392 * WinPosActivateOtherWindow
393 *
394 * Activates window other than pWnd.
395 */
396 VOID FASTCALL
397 co_WinPosActivateOtherWindow(PWND Wnd)
398 {
399 PWND WndTo = NULL;
400 USER_REFERENCE_ENTRY Ref;
401
402 ASSERT_REFS_CO(Wnd);
403
404 if (IntIsDesktopWindow(Wnd))
405 {
406 //ERR("WinPosActivateOtherWindow Set Focus Msg Q No window!\n");
407 IntSetFocusMessageQueue(NULL);
408 return;
409 }
410
411 /* If this is popup window, try to activate the owner first. */
412 if ((Wnd->style & WS_POPUP) && (WndTo = Wnd->spwndOwner))
413 {
414 TRACE("WPAOW Popup with Owner\n");
415 WndTo = UserGetAncestor( WndTo, GA_ROOT );
416 if (can_activate_window(WndTo)) goto done;
417 }
418
419 /* Pick a next top-level window. */
420 /* FIXME: Search for non-tooltip windows first. */
421 WndTo = Wnd;
422 for (;;)
423 {
424 if (!(WndTo = WndTo->spwndNext)) break;
425 if (can_activate_window( WndTo )) goto done;
426 }
427
428 /*
429 Fixes wine win.c:test_SetParent last ShowWindow test after popup dies.
430 Check for previous active window to bring to top.
431 */
432 if (Wnd)
433 {
434 WndTo = Wnd->head.pti->MessageQueue->spwndActivePrev;
435 if (can_activate_window( WndTo )) goto done;
436 }
437
438 // Find any window to bring to top. Works Okay for wine since it does not see X11 windows.
439 WndTo = UserGetDesktopWindow();
440 WndTo = WndTo->spwndChild;
441 if ( WndTo == NULL )
442 {
443 //ERR("WinPosActivateOtherWindow No window!\n");
444 return;
445 }
446 for (;;)
447 {
448 if (WndTo == Wnd)
449 {
450 WndTo = NULL;
451 break;
452 }
453 if (can_activate_window( WndTo )) goto done;
454 if (!(WndTo = WndTo->spwndNext)) break;
455 }
456
457 done:
458 if (WndTo) UserRefObjectCo(WndTo, &Ref);
459
460 if (gpqForeground && (!gpqForeground->spwndActive || Wnd == gpqForeground->spwndActive))
461 {
462 /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */
463 //ERR("WinPosActivateOtherWindow Set FG 0x%p hWnd %p\n",WndTo, WndTo ? WndTo->head.h : 0);
464 if (co_IntSetForegroundWindow(WndTo))
465 {
466 if (WndTo) UserDerefObjectCo(WndTo);
467 return;
468 }
469 }
470 //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo);
471 if (!UserSetActiveWindow(WndTo)) /* Ok for WndTo to be NULL here */
472 {
473 //ERR("WPAOW SA 1\n");
474 UserSetActiveWindow(NULL);
475 }
476 if (WndTo) UserDerefObjectCo(WndTo);
477 }
478
479 VOID FASTCALL
480 WinPosInitInternalPos(PWND Wnd, RECTL *RestoreRect)
481 {
482 POINT Size;
483 RECTL Rect = *RestoreRect;
484
485 if (Wnd->spwndParent && !UserIsDesktopWindow(Wnd->spwndParent))
486 {
487 RECTL_vOffsetRect(&Rect,
488 -Wnd->spwndParent->rcClient.left,
489 -Wnd->spwndParent->rcClient.top);
490 }
491
492 Size.x = Rect.left;
493 Size.y = Rect.top;
494
495 if (!Wnd->InternalPosInitialized)
496 {
497 // FIXME: Use check point Atom..
498 Wnd->InternalPos.flags = 0;
499 Wnd->InternalPos.MaxPos.x = Wnd->InternalPos.MaxPos.y = -1;
500 Wnd->InternalPos.IconPos.x = Wnd->InternalPos.IconPos.y = -1;
501 Wnd->InternalPos.NormalRect = Rect;
502 Wnd->InternalPosInitialized = TRUE;
503 }
504
505 if (Wnd->style & WS_MINIMIZE)
506 {
507 Wnd->InternalPos.IconPos = Size;
508 Wnd->InternalPos.flags |= WPF_MININIT;
509 }
510 else if (Wnd->style & WS_MAXIMIZE)
511 {
512 Wnd->InternalPos.flags |= WPF_MAXINIT;
513
514 if ( Wnd->spwndParent == Wnd->head.rpdesk->pDeskInfo->spwnd )
515 {
516 if (Wnd->state & WNDS_MAXIMIZESTOMONITOR)
517 {
518 Wnd->InternalPos.flags &= ~WPF_MAXINIT;
519 Wnd->InternalPos.MaxPos.x = Wnd->InternalPos.MaxPos.y = -1;
520 }
521 else
522 {
523 RECTL WorkArea;
524 PMONITOR pmonitor = UserMonitorFromRect(&Rect, MONITOR_DEFAULTTOPRIMARY );
525 // FIXME: support DPI aware, rcWorkDPI/Real etc..
526 WorkArea = pmonitor->rcMonitor;
527
528 if (Wnd->style & WS_MAXIMIZEBOX)
529 { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too.
530 if ((Wnd->style & WS_CAPTION) == WS_CAPTION || !(Wnd->style & (WS_CHILD | WS_POPUP)))
531 {
532 WorkArea = pmonitor->rcWork;
533 //ERR("rcWork\n");
534 }
535 }
536
537 Wnd->InternalPos.MaxPos.x = Rect.left - WorkArea.left;
538 Wnd->InternalPos.MaxPos.y = Rect.top - WorkArea.top;
539
540 /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n",
541 Wnd->InternalPos.MaxPos.x,
542 Rect.left, WorkArea.left,
543 Wnd->InternalPos.MaxPos.y,
544 Rect.top, WorkArea.top);*/
545 }
546 }
547 else
548 Wnd->InternalPos.MaxPos = Size;
549 }
550 else
551 {
552 Wnd->InternalPos.NormalRect = Rect;
553 }
554 }
555
556 BOOL
557 FASTCALL
558 IntGetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *lpwndpl)
559 {
560 if (!Wnd) return FALSE;
561
562 if(lpwndpl->length != sizeof(WINDOWPLACEMENT))
563 {
564 return FALSE;
565 }
566
567 lpwndpl->flags = 0;
568
569 WinPosInitInternalPos(Wnd, &Wnd->rcWindow);
570
571 lpwndpl->showCmd = SW_HIDE;
572
573 if ( Wnd->style & WS_MINIMIZE )
574 lpwndpl->showCmd = SW_SHOWMINIMIZED;
575 else
576 lpwndpl->showCmd = ( Wnd->style & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ;
577
578 lpwndpl->rcNormalPosition = Wnd->InternalPos.NormalRect;
579
580 if (Wnd->InternalPos.flags & WPF_MININIT) // Return if it was set!
581 {
582 lpwndpl->ptMinPosition.x = Wnd->InternalPos.IconPos.x;
583 lpwndpl->ptMinPosition.y = Wnd->InternalPos.IconPos.y;
584 }
585 else
586 lpwndpl->ptMinPosition.x = lpwndpl->ptMinPosition.y = -1;
587
588 if ( Wnd->InternalPos.flags & WPF_MAXINIT && // Return if set and not maximized to monitor!
589 !(Wnd->state & WNDS_MAXIMIZESTOMONITOR))
590 {
591 lpwndpl->ptMaxPosition.x = Wnd->InternalPos.MaxPos.x;
592 lpwndpl->ptMaxPosition.y = Wnd->InternalPos.MaxPos.y;
593 }
594 else
595 lpwndpl->ptMaxPosition.x = lpwndpl->ptMaxPosition.y = -1;
596
597 if ( Wnd->spwndParent == Wnd->head.rpdesk->pDeskInfo->spwnd &&
598 !(Wnd->ExStyle & WS_EX_TOOLWINDOW))
599 {
600 PMONITOR pmonitor = UserMonitorFromRect(&lpwndpl->rcNormalPosition, MONITOR_DEFAULTTOPRIMARY );
601
602 // FIXME: support DPI aware, rcWorkDPI/Real etc..
603 if (Wnd->InternalPos.flags & WPF_MININIT)
604 {
605 lpwndpl->ptMinPosition.x -= (pmonitor->rcWork.left - pmonitor->rcMonitor.left);
606 lpwndpl->ptMinPosition.y -= (pmonitor->rcWork.top - pmonitor->rcMonitor.top);
607 }
608 RECTL_vOffsetRect(&lpwndpl->rcNormalPosition,
609 pmonitor->rcMonitor.left - pmonitor->rcWork.left,
610 pmonitor->rcMonitor.top - pmonitor->rcWork.top);
611 }
612
613 if ( Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED || Wnd->style & WS_MAXIMIZE )
614 lpwndpl->flags |= WPF_RESTORETOMAXIMIZED;
615
616 if ( ((Wnd->style & (WS_CHILD|WS_POPUP)) == WS_CHILD) && Wnd->InternalPos.flags & WPF_SETMINPOSITION)
617 lpwndpl->flags |= WPF_SETMINPOSITION;
618
619 return TRUE;
620 }
621
622 /* make sure the specified rect is visible on screen */
623 static void make_rect_onscreen( RECT *rect )
624 {
625 PMONITOR pmonitor = UserMonitorFromRect( rect, MONITOR_DEFAULTTONEAREST ); // Wine uses this.
626
627 // FIXME: support DPI aware, rcWorkDPI/Real etc..
628 if (!pmonitor) return;
629 /* FIXME: map coordinates from rcWork to rcMonitor */
630 if (rect->right <= pmonitor->rcWork.left)
631 {
632 rect->right += pmonitor->rcWork.left - rect->left;
633 rect->left = pmonitor->rcWork.left;
634 }
635 else if (rect->left >= pmonitor->rcWork.right)
636 {
637 rect->left += pmonitor->rcWork.right - rect->right;
638 rect->right = pmonitor->rcWork.right;
639 }
640 if (rect->bottom <= pmonitor->rcWork.top)
641 {
642 rect->bottom += pmonitor->rcWork.top - rect->top;
643 rect->top = pmonitor->rcWork.top;
644 }
645 else if (rect->top >= pmonitor->rcWork.bottom)
646 {
647 rect->top += pmonitor->rcWork.bottom - rect->bottom;
648 rect->bottom = pmonitor->rcWork.bottom;
649 }
650 }
651
652 /* make sure the specified point is visible on screen */
653 static void make_point_onscreen( POINT *pt )
654 {
655 RECT rect;
656
657 RECTL_vSetRect( &rect, pt->x, pt->y, pt->x + 1, pt->y + 1 );
658 make_rect_onscreen( &rect );
659 pt->x = rect.left;
660 pt->y = rect.top;
661 }
662
663 BOOL FASTCALL
664 IntSetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *wpl, UINT Flags)
665 {
666 BOOL sAsync;
667 UINT SWP_Flags;
668
669 if ( Flags & PLACE_MIN) make_point_onscreen( &wpl->ptMinPosition );
670 if ( Flags & PLACE_MAX) make_point_onscreen( &wpl->ptMaxPosition );
671 if ( Flags & PLACE_RECT) make_rect_onscreen( &wpl->rcNormalPosition );
672
673 if (!Wnd || Wnd == Wnd->head.rpdesk->pDeskInfo->spwnd) return FALSE;
674
675 if ( Flags & PLACE_MIN ) Wnd->InternalPos.IconPos = wpl->ptMinPosition;
676 if ( Flags & PLACE_MAX ) Wnd->InternalPos.MaxPos = wpl->ptMaxPosition;
677 if ( Flags & PLACE_RECT) Wnd->InternalPos.NormalRect = wpl->rcNormalPosition;
678
679 SWP_Flags = SWP_NOZORDER | SWP_NOACTIVATE | ((wpl->flags & WPF_ASYNCWINDOWPLACEMENT) ? SWP_ASYNCWINDOWPOS : 0);
680
681 if (Wnd->style & WS_MINIMIZE )
682 {
683 if (Flags & PLACE_MIN || Wnd->InternalPos.flags & WPF_SETMINPOSITION)
684 {
685 co_WinPosSetWindowPos(Wnd, HWND_TOP,
686 wpl->ptMinPosition.x, wpl->ptMinPosition.y, 0, 0,
687 SWP_NOSIZE | SWP_Flags);
688 Wnd->InternalPos.flags |= WPF_MININIT;
689 }
690 }
691 else if (Wnd->style & WS_MAXIMIZE )
692 {
693 if (Flags & PLACE_MAX)
694 {
695 co_WinPosSetWindowPos(Wnd, HWND_TOP,
696 wpl->ptMaxPosition.x, wpl->ptMaxPosition.y, 0, 0,
697 SWP_NOSIZE | SWP_Flags);
698 Wnd->InternalPos.flags |= WPF_MAXINIT;
699 }
700 }
701 else if (Flags & PLACE_RECT)
702 {
703 co_WinPosSetWindowPos(Wnd, HWND_TOP,
704 wpl->rcNormalPosition.left, wpl->rcNormalPosition.top,
705 wpl->rcNormalPosition.right - wpl->rcNormalPosition.left,
706 wpl->rcNormalPosition.bottom - wpl->rcNormalPosition.top,
707 SWP_Flags);
708 }
709
710 sAsync = (Wnd->head.pti->MessageQueue != gptiCurrent->MessageQueue && wpl->flags & WPF_ASYNCWINDOWPLACEMENT);
711
712 if ( sAsync )
713 co_IntSendMessageNoWait( UserHMGetHandle(Wnd), WM_ASYNC_SHOWWINDOW, wpl->showCmd, 0 );
714 else
715 co_WinPosShowWindow(Wnd, wpl->showCmd);
716
717 if ( Wnd->style & WS_MINIMIZE && !sAsync )
718 {
719 if ( wpl->flags & WPF_SETMINPOSITION )
720 Wnd->InternalPos.flags |= WPF_SETMINPOSITION;
721
722 if ( wpl->flags & WPF_RESTORETOMAXIMIZED )
723 Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED;
724 }
725 return TRUE;
726 }
727
728 UINT
729 FASTCALL
730 co_WinPosArrangeIconicWindows(PWND parent)
731 {
732 RECTL rectParent;
733 PWND Child;
734 INT x, y, xspacing, yspacing, sx, sy;
735
736 ASSERT_REFS_CO(parent);
737
738 IntGetClientRect( parent, &rectParent );
739 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
740 // Default: ARW_BOTTOMLEFT
741 x = rectParent.left;
742 y = rectParent.bottom;
743
744 xspacing = UserGetSystemMetrics(SM_CXMINIMIZED);
745 yspacing = UserGetSystemMetrics(SM_CYMINIMIZED);
746
747 Child = parent->spwndChild;
748 while(Child)
749 {
750 if((Child->style & WS_MINIMIZE) != 0 )
751 {
752 USER_REFERENCE_ENTRY Ref;
753 UserRefObjectCo(Child, &Ref);
754
755 sx = x + UserGetSystemMetrics(SM_CXBORDER);
756 sy = y - yspacing - UserGetSystemMetrics(SM_CYBORDER);
757
758 Child->InternalPos.IconPos.x = sx;
759 Child->InternalPos.IconPos.y = sy;
760 Child->InternalPos.flags |= WPF_MININIT;
761
762 co_WinPosSetWindowPos( Child, 0, sx, sy, xspacing, yspacing, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_ASYNCWINDOWPOS);
763
764 UserDerefObjectCo(Child);
765
766 if (x <= rectParent.right - xspacing)
767 x += xspacing;
768 else
769 {
770 x = rectParent.left;
771 y -= yspacing;
772 }
773 }
774 Child = Child->spwndNext;
775 }
776 return yspacing;
777 }
778
779 static VOID FASTCALL
780 WinPosFindIconPos(PWND Window, POINT *Pos)
781 {
782 RECT rectParent;
783 PWND pwndChild, pwndParent;
784 int x, y, xspacing, yspacing;
785
786 pwndParent = Window->spwndParent;
787 if (UserIsDesktopWindow(pwndParent))
788 {
789 ERR("FIXME: Parent is Desktop, Min off screen!\n");
790 /* FIXME: ReactOS doesn't support iconic minimize to desktop */
791 Pos->x = Pos->y = -32000;
792 Window->InternalPos.flags |= WPF_MININIT;
793 Window->InternalPos.IconPos.x = Pos->x;
794 Window->InternalPos.IconPos.y = Pos->y;
795 return;
796 }
797
798 IntGetClientRect( pwndParent, &rectParent );
799 // FIXME: Support Minimize Metrics gspv.mm.iArrange.
800 // Default: ARW_BOTTOMLEFT
801 x = rectParent.left;
802 y = rectParent.bottom;
803
804 xspacing = UserGetSystemMetrics(SM_CXMINIMIZED);
805 yspacing = UserGetSystemMetrics(SM_CYMINIMIZED);
806
807 // Set to default position when minimized.
808 Pos->x = x + UserGetSystemMetrics(SM_CXBORDER);
809 Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER);
810
811 for (pwndChild = pwndParent->spwndChild; pwndChild; pwndChild = pwndChild->spwndNext)
812 {
813 if (pwndChild == Window) continue;
814
815 if ((pwndChild->style & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE) )
816 {
817 continue;
818 }
819
820 if ( pwndChild->InternalPos.IconPos.x != Pos->x && pwndChild->InternalPos.IconPos.y != Pos->y )
821 {
822 break;
823 }
824 if (x <= rectParent.right - xspacing)
825 x += xspacing;
826 else
827 {
828 x = rectParent.left;
829 y -= yspacing;
830 }
831 Pos->x = x + UserGetSystemMetrics(SM_CXBORDER);
832 Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER);
833 }
834
835 Window->InternalPos.IconPos.x = Pos->x;
836 Window->InternalPos.IconPos.y = Pos->y;
837 Window->InternalPos.flags |= WPF_MININIT;
838 TRACE("Position is set! X:%d Y:%d\n",Pos->x,Pos->y);
839 return;
840 }
841
842 BOOL
843 UserHasWindowEdge(DWORD Style, DWORD ExStyle)
844 {
845 if (Style & WS_MINIMIZE)
846 return TRUE;
847 if (ExStyle & WS_EX_DLGMODALFRAME)
848 return TRUE;
849 if (ExStyle & WS_EX_STATICEDGE)
850 return FALSE;
851 if (Style & WS_THICKFRAME)
852 return TRUE;
853 Style &= WS_CAPTION;
854 if (Style == WS_DLGFRAME || Style == WS_CAPTION)
855 return TRUE;
856 return FALSE;
857 }
858
859 VOID FASTCALL
860 IntGetWindowBorderMeasures(PWND Wnd, UINT *cx, UINT *cy)
861 {
862 if(HAS_DLGFRAME(Wnd->style, Wnd->ExStyle) && !(Wnd->style & WS_MINIMIZE))
863 {
864 *cx = UserGetSystemMetrics(SM_CXDLGFRAME);
865 *cy = UserGetSystemMetrics(SM_CYDLGFRAME);
866 }
867 else
868 {
869 if(HAS_THICKFRAME(Wnd->style, Wnd->ExStyle)&& !(Wnd->style & WS_MINIMIZE))
870 {
871 *cx = UserGetSystemMetrics(SM_CXFRAME);
872 *cy = UserGetSystemMetrics(SM_CYFRAME);
873 }
874 else if(HAS_THINFRAME(Wnd->style, Wnd->ExStyle))
875 {
876 *cx = UserGetSystemMetrics(SM_CXBORDER);
877 *cy = UserGetSystemMetrics(SM_CYBORDER);
878 }
879 else
880 {
881 *cx = *cy = 0;
882 }
883 }
884 }
885
886 VOID
887 UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient)
888 {
889 DWORD Border = 0;
890
891 if (UserHasWindowEdge(Style, ExStyle))
892 Border += 2;
893 else if (ExStyle & WS_EX_STATICEDGE)
894 Border += 1;
895 if ((ExStyle & WS_EX_CLIENTEDGE) && WithClient)
896 Border += 2;
897 if (Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME)
898 Border ++;
899 Size->cx = Size->cy = Border;
900 if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
901 {
902 Size->cx += UserGetSystemMetrics(SM_CXFRAME) - UserGetSystemMetrics(SM_CXDLGFRAME);
903 Size->cy += UserGetSystemMetrics(SM_CYFRAME) - UserGetSystemMetrics(SM_CYDLGFRAME);
904 }
905 Size->cx *= UserGetSystemMetrics(SM_CXBORDER);
906 Size->cy *= UserGetSystemMetrics(SM_CYBORDER);
907 }
908
909 BOOL WINAPI
910 UserAdjustWindowRectEx(LPRECT lpRect,
911 DWORD dwStyle,
912 BOOL bMenu,
913 DWORD dwExStyle)
914 {
915 SIZE BorderSize;
916
917 if (bMenu)
918 {
919 lpRect->top -= UserGetSystemMetrics(SM_CYMENU);
920 }
921 if ((dwStyle & WS_CAPTION) == WS_CAPTION)
922 {
923 if (dwExStyle & WS_EX_TOOLWINDOW)
924 lpRect->top -= UserGetSystemMetrics(SM_CYSMCAPTION);
925 else
926 lpRect->top -= UserGetSystemMetrics(SM_CYCAPTION);
927 }
928 UserGetWindowBorders(dwStyle, dwExStyle, &BorderSize, TRUE);
929 RECTL_vInflateRect(
930 lpRect,
931 BorderSize.cx,
932 BorderSize.cy);
933
934 return TRUE;
935 }
936
937 UINT FASTCALL
938 co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos,
939 POINT* MinTrack, POINT* MaxTrack)
940 {
941 MINMAXINFO MinMax;
942 PMONITOR monitor;
943 INT xinc, yinc;
944 LONG style = Window->style;
945 LONG adjustedStyle;
946 LONG exstyle = Window->ExStyle;
947 RECT rc;
948
949 ASSERT_REFS_CO(Window);
950
951 /* Compute default values */
952
953 rc = Window->rcWindow;
954 MinMax.ptReserved.x = rc.left;
955 MinMax.ptReserved.y = rc.top;
956
957 if ((style & WS_CAPTION) == WS_CAPTION)
958 adjustedStyle = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
959 else
960 adjustedStyle = style;
961
962 if(Window->spwndParent)
963 IntGetClientRect(Window->spwndParent, &rc);
964 UserAdjustWindowRectEx(&rc, adjustedStyle, ((style & WS_POPUP) && Window->IDMenu), exstyle);
965
966 xinc = -rc.left;
967 yinc = -rc.top;
968
969 MinMax.ptMaxSize.x = rc.right - rc.left;
970 MinMax.ptMaxSize.y = rc.bottom - rc.top;
971 if (style & (WS_DLGFRAME | WS_BORDER))
972 {
973 MinMax.ptMinTrackSize.x = UserGetSystemMetrics(SM_CXMINTRACK);
974 MinMax.ptMinTrackSize.y = UserGetSystemMetrics(SM_CYMINTRACK);
975 }
976 else
977 {
978 MinMax.ptMinTrackSize.x = 2 * xinc;
979 MinMax.ptMinTrackSize.y = 2 * yinc;
980 }
981 MinMax.ptMaxTrackSize.x = UserGetSystemMetrics(SM_CXMAXTRACK);
982 MinMax.ptMaxTrackSize.y = UserGetSystemMetrics(SM_CYMAXTRACK);
983 MinMax.ptMaxPosition.x = -xinc;
984 MinMax.ptMaxPosition.y = -yinc;
985
986 if (!EMPTYPOINT(Window->InternalPos.MaxPos)) MinMax.ptMaxPosition = Window->InternalPos.MaxPos;
987
988 co_IntSendMessage(Window->head.h, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax);
989
990 /* if the app didn't change the values, adapt them for the current monitor */
991 if ((monitor = UserGetPrimaryMonitor()))
992 {
993 RECT rc_work;
994
995 rc_work = monitor->rcMonitor;
996
997 if (style & WS_MAXIMIZEBOX)
998 {
999 if ((style & WS_CAPTION) == WS_CAPTION || !(style & (WS_CHILD | WS_POPUP)))
1000 rc_work = monitor->rcWork;
1001 }
1002
1003 if (MinMax.ptMaxSize.x == UserGetSystemMetrics(SM_CXSCREEN) + 2 * xinc &&
1004 MinMax.ptMaxSize.y == UserGetSystemMetrics(SM_CYSCREEN) + 2 * yinc)
1005 {
1006 MinMax.ptMaxSize.x = (rc_work.right - rc_work.left) + 2 * xinc;
1007 MinMax.ptMaxSize.y = (rc_work.bottom - rc_work.top) + 2 * yinc;
1008 }
1009 if (MinMax.ptMaxPosition.x == -xinc && MinMax.ptMaxPosition.y == -yinc)
1010 {
1011 MinMax.ptMaxPosition.x = rc_work.left - xinc;
1012 MinMax.ptMaxPosition.y = rc_work.top - yinc;
1013 }
1014 if (MinMax.ptMaxSize.x >= (monitor->rcMonitor.right - monitor->rcMonitor.left) &&
1015 MinMax.ptMaxSize.y >= (monitor->rcMonitor.bottom - monitor->rcMonitor.top) )
1016 Window->state |= WNDS_MAXIMIZESTOMONITOR;
1017 else
1018 Window->state &= ~WNDS_MAXIMIZESTOMONITOR;
1019 }
1020
1021
1022 MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x,
1023 MinMax.ptMinTrackSize.x);
1024 MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y,
1025 MinMax.ptMinTrackSize.y);
1026
1027 if (MaxSize)
1028 *MaxSize = MinMax.ptMaxSize;
1029 if (MaxPos)
1030 *MaxPos = MinMax.ptMaxPosition;
1031 if (MinTrack)
1032 *MinTrack = MinMax.ptMinTrackSize;
1033 if (MaxTrack)
1034 *MaxTrack = MinMax.ptMaxTrackSize;
1035
1036 return 0; // FIXME: What does it return?
1037 }
1038
1039 static
1040 BOOL
1041 IntValidateParent(PWND Child, PREGION ValidateRgn)
1042 {
1043 PWND ParentWnd = Child;
1044
1045 if (ParentWnd->style & WS_CHILD)
1046 {
1047 do
1048 ParentWnd = ParentWnd->spwndParent;
1049 while (ParentWnd->style & WS_CHILD);
1050 }
1051
1052 ParentWnd = Child->spwndParent;
1053 while (ParentWnd)
1054 {
1055 if (ParentWnd->style & WS_CLIPCHILDREN)
1056 break;
1057
1058 if (ParentWnd->hrgnUpdate != 0)
1059 {
1060 IntInvalidateWindows( ParentWnd,
1061 ValidateRgn,
1062 RDW_VALIDATE | RDW_NOCHILDREN);
1063 }
1064
1065 ParentWnd = ParentWnd->spwndParent;
1066 }
1067
1068 return TRUE;
1069 }
1070
1071 static
1072 VOID FASTCALL
1073 FixClientRect(PRECTL ClientRect, PRECTL WindowRect)
1074 {
1075 if (ClientRect->left < WindowRect->left)
1076 {
1077 ClientRect->left = WindowRect->left;
1078 }
1079 else if (WindowRect->right < ClientRect->left)
1080 {
1081 ClientRect->left = WindowRect->right;
1082 }
1083 if (ClientRect->right < WindowRect->left)
1084 {
1085 ClientRect->right = WindowRect->left;
1086 }
1087 else if (WindowRect->right < ClientRect->right)
1088 {
1089 ClientRect->right = WindowRect->right;
1090 }
1091 if (ClientRect->top < WindowRect->top)
1092 {
1093 ClientRect->top = WindowRect->top;
1094 }
1095 else if (WindowRect->bottom < ClientRect->top)
1096 {
1097 ClientRect->top = WindowRect->bottom;
1098 }
1099 if (ClientRect->bottom < WindowRect->top)
1100 {
1101 ClientRect->bottom = WindowRect->top;
1102 }
1103 else if (WindowRect->bottom < ClientRect->bottom)
1104 {
1105 ClientRect->bottom = WindowRect->bottom;
1106 }
1107 }
1108 /***********************************************************************
1109 * get_valid_rects
1110 *
1111 * Compute the valid rects from the old and new client rect and WVR_* flags.
1112 * Helper for WM_NCCALCSIZE handling.
1113 */
1114 static
1115 VOID FASTCALL
1116 get_valid_rects( RECTL *old_client, RECTL *new_client, UINT flags, RECTL *valid )
1117 {
1118 int cx, cy;
1119
1120 if (flags & WVR_REDRAW)
1121 {
1122 RECTL_vSetEmptyRect( &valid[0] );
1123 RECTL_vSetEmptyRect( &valid[1] );
1124 return;
1125 }
1126
1127 if (flags & WVR_VALIDRECTS)
1128 {
1129 if (!RECTL_bIntersectRect( &valid[0], &valid[0], new_client ) ||
1130 !RECTL_bIntersectRect( &valid[1], &valid[1], old_client ))
1131 {
1132 RECTL_vSetEmptyRect( &valid[0] );
1133 RECTL_vSetEmptyRect( &valid[1] );
1134 return;
1135 }
1136 flags = WVR_ALIGNLEFT | WVR_ALIGNTOP;
1137 }
1138 else
1139 {
1140 valid[0] = *new_client;
1141 valid[1] = *old_client;
1142 }
1143
1144 /* make sure the rectangles have the same size */
1145 cx = min( valid[0].right - valid[0].left, valid[1].right - valid[1].left );
1146 cy = min( valid[0].bottom - valid[0].top, valid[1].bottom - valid[1].top );
1147
1148 if (flags & WVR_ALIGNBOTTOM)
1149 {
1150 valid[0].top = valid[0].bottom - cy;
1151 valid[1].top = valid[1].bottom - cy;
1152 }
1153 else
1154 {
1155 valid[0].bottom = valid[0].top + cy;
1156 valid[1].bottom = valid[1].top + cy;
1157 }
1158 if (flags & WVR_ALIGNRIGHT)
1159 {
1160 valid[0].left = valid[0].right - cx;
1161 valid[1].left = valid[1].right - cx;
1162 }
1163 else
1164 {
1165 valid[0].right = valid[0].left + cx;
1166 valid[1].right = valid[1].left + cx;
1167 }
1168 }
1169
1170 static
1171 LONG FASTCALL
1172 co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, RECTL* WindowRect, RECTL* ClientRect, RECTL* validRects)
1173 {
1174 PWND Parent;
1175 UINT wvrFlags = 0;
1176
1177 ASSERT_REFS_CO(Window);
1178
1179 /* Send WM_NCCALCSIZE message to get new client area */
1180 if ((WinPos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE)
1181 {
1182 NCCALCSIZE_PARAMS params;
1183 WINDOWPOS winposCopy;
1184
1185 params.rgrc[0] = *WindowRect; // new coordinates of a window that has been moved or resized
1186 params.rgrc[1] = Window->rcWindow; // window before it was moved or resized
1187 params.rgrc[2] = Window->rcClient; // client area before the window was moved or resized
1188
1189 Parent = Window->spwndParent;
1190 if (0 != (Window->style & WS_CHILD) && Parent)
1191 {
1192 RECTL_vOffsetRect(&(params.rgrc[0]), - Parent->rcClient.left, - Parent->rcClient.top);
1193 RECTL_vOffsetRect(&(params.rgrc[1]), - Parent->rcClient.left, - Parent->rcClient.top);
1194 RECTL_vOffsetRect(&(params.rgrc[2]), - Parent->rcClient.left, - Parent->rcClient.top);
1195 }
1196
1197 params.lppos = &winposCopy;
1198 winposCopy = *WinPos;
1199
1200 wvrFlags = co_IntSendMessage(Window->head.h, WM_NCCALCSIZE, TRUE, (LPARAM) &params);
1201
1202 /* If the application send back garbage, ignore it */
1203 if (params.rgrc[0].left <= params.rgrc[0].right &&
1204 params.rgrc[0].top <= params.rgrc[0].bottom)
1205 {
1206 *ClientRect = params.rgrc[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize
1207 if ((Window->style & WS_CHILD) && Parent)
1208 {
1209 RECTL_vOffsetRect(ClientRect, Parent->rcClient.left, Parent->rcClient.top);
1210 }
1211 FixClientRect(ClientRect, WindowRect);
1212 }
1213
1214 if (ClientRect->left != Window->rcClient.left ||
1215 ClientRect->top != Window->rcClient.top)
1216 {
1217 WinPos->flags &= ~SWP_NOCLIENTMOVE;
1218 }
1219
1220 if (ClientRect->right - ClientRect->left != Window->rcClient.right - Window->rcClient.left)
1221 {
1222 WinPos->flags &= ~SWP_NOCLIENTSIZE;
1223 }
1224 else
1225 wvrFlags &= ~WVR_HREDRAW;
1226
1227 if (ClientRect->bottom - ClientRect->top != Window->rcClient.bottom - Window->rcClient.top)
1228 {
1229 WinPos->flags &= ~SWP_NOCLIENTSIZE;
1230 }
1231 else
1232 wvrFlags &= ~WVR_VREDRAW;
1233
1234 validRects[0] = params.rgrc[1]; // second rectangle contains the valid destination rectangle
1235 validRects[1] = params.rgrc[2]; // third rectangle contains the valid source rectangle
1236 }
1237 else
1238 {
1239 if (!(WinPos->flags & SWP_NOMOVE) &&
1240 (ClientRect->left != Window->rcClient.left ||
1241 ClientRect->top != Window->rcClient.top))
1242 {
1243 WinPos->flags &= ~SWP_NOCLIENTMOVE;
1244 }
1245 }
1246
1247 if (WinPos->flags & (SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_SHOWWINDOW | SWP_HIDEWINDOW))
1248 {
1249 RECTL_vSetEmptyRect( &validRects[0] );
1250 RECTL_vSetEmptyRect( &validRects[1] );
1251 }
1252 else get_valid_rects( &Window->rcClient, ClientRect, wvrFlags, validRects );
1253
1254 return wvrFlags;
1255 }
1256
1257 static
1258 BOOL FASTCALL
1259 co_WinPosDoWinPosChanging(PWND Window,
1260 PWINDOWPOS WinPos,
1261 PRECTL WindowRect,
1262 PRECTL ClientRect)
1263 {
1264 ASSERT_REFS_CO(Window);
1265
1266 /* Send WM_WINDOWPOSCHANGING message */
1267
1268 if (!(WinPos->flags & SWP_NOSENDCHANGING)
1269 && !((WinPos->flags & SWP_AGG_NOCLIENTCHANGE) && (WinPos->flags & SWP_SHOWWINDOW)))
1270 {
1271 TRACE("Sending WM_WINDOWPOSCHANGING to hwnd %p flags %04x.\n", Window->head.h,WinPos->flags);
1272 co_IntSendMessage(Window->head.h, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos);
1273 }
1274
1275 /* Calculate new position and size */
1276
1277 *WindowRect = Window->rcWindow;
1278 *ClientRect = (Window->style & WS_MINIMIZE) ? Window->rcWindow : Window->rcClient;
1279
1280 if (!(WinPos->flags & SWP_NOSIZE))
1281 {
1282 if (Window->style & WS_MINIMIZE)
1283 {
1284 WindowRect->right = WindowRect->left + UserGetSystemMetrics(SM_CXMINIMIZED);
1285 WindowRect->bottom = WindowRect->top + UserGetSystemMetrics(SM_CYMINIMIZED);
1286 }
1287 else
1288 {
1289 WindowRect->right = WindowRect->left + WinPos->cx;
1290 WindowRect->bottom = WindowRect->top + WinPos->cy;
1291 }
1292 }
1293
1294 if (!(WinPos->flags & SWP_NOMOVE))
1295 {
1296 INT X, Y;
1297 PWND Parent;
1298 X = WinPos->x;
1299 Y = WinPos->y;
1300
1301 Parent = Window->spwndParent;
1302
1303 // Parent child position issue is in here. SetParent_W7 test CORE-6651.
1304 if (//((Window->style & WS_CHILD) != 0) && <- Fixes wine msg test_SetParent: "rects do not match", the last test.
1305 Parent &&
1306 Parent != Window->head.rpdesk->pDeskInfo->spwnd)
1307 {
1308 TRACE("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X,Y);
1309 X += Parent->rcClient.left;
1310 Y += Parent->rcClient.top;
1311 TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X,Y);
1312 }
1313
1314 WindowRect->left = X;
1315 WindowRect->top = Y;
1316 WindowRect->right += X - Window->rcWindow.left;
1317 WindowRect->bottom += Y - Window->rcWindow.top;
1318
1319 RECTL_vOffsetRect(ClientRect, X - Window->rcWindow.left,
1320 Y - Window->rcWindow.top);
1321 }
1322 WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE;
1323
1324 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n",
1325 WinPos->hwnd, WinPos->hwndInsertAfter, WinPos->x, WinPos->y,
1326 WinPos->cx, WinPos->cy, WinPos->flags );
1327 TRACE("WindowRect: %d %d %d %d\n", WindowRect->left,WindowRect->top,WindowRect->right,WindowRect->bottom);
1328 TRACE("ClientRect: %d %d %d %d\n", ClientRect->left,ClientRect->top,ClientRect->right,ClientRect->bottom);
1329
1330 return TRUE;
1331 }
1332
1333 /*
1334 * Fix Z order taking into account owned popups -
1335 * basically we need to maintain them above the window that owns them
1336 *
1337 * FIXME: hide/show owned popups when owner visibility changes.
1338 *
1339 * ReactOS: See bug CORE-6129 and CORE-6554.
1340 *
1341 */
1342 ////
1343 // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out.
1344 // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!!
1345 static
1346 HWND FASTCALL
1347 WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter)
1348 {
1349 HWND *List = NULL;
1350 HWND Owner;
1351 LONG Style;
1352 PWND DesktopWindow, ChildObject;
1353 int i;
1354
1355 TRACE("(%p) hInsertAfter = %p\n", Window, hWndInsertAfter );
1356
1357 Style = Window->style;
1358
1359 if (Style & WS_CHILD)
1360 {
1361 TRACE("Window is child\n");
1362 return hWndInsertAfter;
1363 }
1364
1365 Owner = Window->spwndOwner ? Window->spwndOwner->head.h : NULL;
1366
1367 if (Owner)
1368 {
1369 /* Make sure this popup stays above the owner */
1370
1371 if (hWndInsertAfter != HWND_TOPMOST)
1372 {
1373 DesktopWindow = UserGetDesktopWindow();
1374 List = IntWinListChildren(DesktopWindow);
1375
1376 if (List != NULL)
1377 {
1378 for (i = 0; List[i]; i++)
1379 {
1380 BOOL topmost = FALSE;
1381
1382 ChildObject = ValidateHwndNoErr(List[i]);
1383 if (ChildObject)
1384 {
1385 topmost = (ChildObject->ExStyle & WS_EX_TOPMOST) != 0;
1386 }
1387
1388 if (List[i] == Owner)
1389 {
1390 if (i > 0) hWndInsertAfter = List[i-1];
1391 else hWndInsertAfter = topmost ? HWND_TOPMOST : HWND_TOP;
1392 break;
1393 }
1394
1395 if (hWndInsertAfter == HWND_TOP || hWndInsertAfter == HWND_NOTOPMOST)
1396 {
1397 if (!topmost) break;
1398 }
1399 else if (List[i] == hWndInsertAfter) break;
1400 }
1401 }
1402 else
1403 return hWndInsertAfter;
1404 }
1405 }
1406
1407 if (hWndInsertAfter == HWND_BOTTOM)
1408 {
1409 ERR("Window is HWND_BOTTOM hwnd %p\n",hWndInsertAfter);
1410 if (List) ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
1411 goto done;
1412 }
1413
1414 if (!List)
1415 {
1416 DesktopWindow = UserGetDesktopWindow();
1417 List = IntWinListChildren(DesktopWindow);
1418 }
1419
1420 if (List != NULL)
1421 {
1422 i = 0;
1423
1424 if (hWndInsertAfter == HWND_TOP || hWndInsertAfter == HWND_NOTOPMOST)
1425 {
1426 if (hWndInsertAfter == HWND_NOTOPMOST || !(Window->ExStyle & WS_EX_TOPMOST))
1427 {
1428 TRACE("skip all the topmost windows\n");
1429 /* skip all the topmost windows */
1430 while (List[i] &&
1431 (ChildObject = ValidateHwndNoErr(List[i])) &&
1432 (ChildObject->ExStyle & WS_EX_TOPMOST)) i++;
1433 }
1434 }
1435 else if (hWndInsertAfter != HWND_TOPMOST)
1436 {
1437 /* skip windows that are already placed correctly */
1438 for (i = 0; List[i]; i++)
1439 {
1440 if (List[i] == hWndInsertAfter) break;
1441 if (List[i] == UserHMGetHandle(Window))
1442 {
1443 ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
1444 goto done; /* nothing to do if window is moving backwards in z-order */
1445 }
1446 }
1447 }
1448
1449 for (; List[i]; i++)
1450 {
1451 PWND Wnd;
1452 USER_REFERENCE_ENTRY Ref;
1453
1454 if (List[i] == UserHMGetHandle(Window))
1455 break;
1456
1457 if (!(Wnd = ValidateHwndNoErr(List[i])))
1458 continue;
1459
1460 Owner = Wnd->spwndOwner ? Wnd->spwndOwner->head.h : NULL;
1461
1462 if (Owner != UserHMGetHandle(Window)) continue;
1463
1464 UserRefObjectCo(Wnd, &Ref);
1465 TRACE( "moving %p owned by %p after %p\n", List[i], UserHMGetHandle(Window), hWndInsertAfter );
1466 co_WinPosSetWindowPos(Wnd, hWndInsertAfter, 0, 0, 0, 0,
1467 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING| SWP_DEFERERASE);
1468
1469 UserDerefObjectCo(Wnd);
1470 hWndInsertAfter = List[i];
1471 }
1472 ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
1473 }
1474 done:
1475 return hWndInsertAfter;
1476 }
1477 ////
1478
1479 /***********************************************************************
1480 * WinPosInternalMoveWindow
1481 *
1482 * Update WindowRect and ClientRect of Window and all of its children
1483 * We keep both WindowRect and ClientRect in screen coordinates internally
1484 */
1485 static
1486 VOID FASTCALL
1487 WinPosInternalMoveWindow(PWND Window, INT MoveX, INT MoveY)
1488 {
1489 PWND Child;
1490
1491 ASSERT(Window != Window->spwndChild);
1492 TRACE("InternalMoveWin X %d Y %d\n", MoveX, MoveY);
1493
1494 Window->rcWindow.left += MoveX;
1495 Window->rcWindow.right += MoveX;
1496 Window->rcWindow.top += MoveY;
1497 Window->rcWindow.bottom += MoveY;
1498
1499 Window->rcClient.left += MoveX;
1500 Window->rcClient.right += MoveX;
1501 Window->rcClient.top += MoveY;
1502 Window->rcClient.bottom += MoveY;
1503
1504 for(Child = Window->spwndChild; Child; Child = Child->spwndNext)
1505 {
1506 WinPosInternalMoveWindow(Child, MoveX, MoveY);
1507 }
1508 }
1509
1510 /*
1511 * WinPosFixupSWPFlags
1512 *
1513 * Fix redundant flags and values in the WINDOWPOS structure.
1514 */
1515 static
1516 BOOL FASTCALL
1517 WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd)
1518 {
1519 PWND Parent;
1520 POINT pt;
1521
1522 /* Finally make sure that all coordinates are valid */
1523 if (WinPos->x < -32768) WinPos->x = -32768;
1524 else if (WinPos->x > 32767) WinPos->x = 32767;
1525 if (WinPos->y < -32768) WinPos->y = -32768;
1526 else if (WinPos->y > 32767) WinPos->y = 32767;
1527
1528 WinPos->cx = max(WinPos->cx, 0);
1529 WinPos->cy = max(WinPos->cy, 0);
1530
1531 Parent = UserGetAncestor( Wnd, GA_PARENT );
1532 if (!IntIsWindowVisible( Parent ) &&
1533 /* Fix B : wine msg test_SetParent:WmSetParentSeq_2:25 wParam bits! */
1534 (WinPos->flags & SWP_AGG_STATUSFLAGS) == SWP_AGG_NOPOSCHANGE) WinPos->flags |= SWP_NOREDRAW;
1535
1536 if (Wnd->style & WS_VISIBLE) WinPos->flags &= ~SWP_SHOWWINDOW;
1537 else
1538 {
1539 WinPos->flags &= ~SWP_HIDEWINDOW;
1540 if (!(WinPos->flags & SWP_SHOWWINDOW)) WinPos->flags |= SWP_NOREDRAW;
1541 }
1542
1543 /* Check for right size */
1544 if (Wnd->rcWindow.right - Wnd->rcWindow.left == WinPos->cx &&
1545 Wnd->rcWindow.bottom - Wnd->rcWindow.top == WinPos->cy)
1546 {
1547 WinPos->flags |= SWP_NOSIZE;
1548 }
1549
1550 pt.x = WinPos->x;
1551 pt.y = WinPos->y;
1552 IntClientToScreen( Parent, &pt );
1553 TRACE("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos->x,WinPos->y,pt.x,pt.y);
1554 /* Check for right position */
1555 if (Wnd->rcWindow.left == pt.x && Wnd->rcWindow.top == pt.y)
1556 {
1557 //ERR("In right pos\n");
1558 WinPos->flags |= SWP_NOMOVE;
1559 }
1560
1561 if ( WinPos->hwnd != UserGetForegroundWindow() && (Wnd->style & (WS_POPUP | WS_CHILD)) != WS_CHILD)
1562 {
1563 /* Bring to the top when activating */
1564 if (!(WinPos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)) &&
1565 (WinPos->flags & SWP_NOZORDER ||
1566 (WinPos->hwndInsertAfter != HWND_TOPMOST && WinPos->hwndInsertAfter != HWND_NOTOPMOST)))
1567 {
1568 WinPos->flags &= ~SWP_NOZORDER;
1569 WinPos->hwndInsertAfter = (0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP);
1570 }
1571 }
1572
1573 /* Check hwndInsertAfter */
1574 if (!(WinPos->flags & SWP_NOZORDER))
1575 {
1576 /* Fix sign extension */
1577 if (WinPos->hwndInsertAfter == (HWND)0xffff)
1578 {
1579 WinPos->hwndInsertAfter = HWND_TOPMOST;
1580 }
1581 else if (WinPos->hwndInsertAfter == (HWND)0xfffe)
1582 {
1583 WinPos->hwndInsertAfter = HWND_NOTOPMOST;
1584 }
1585
1586 if (WinPos->hwndInsertAfter == HWND_TOP)
1587 {
1588 /* Keep it topmost when it's already topmost */
1589 if ((Wnd->ExStyle & WS_EX_TOPMOST) != 0)
1590 WinPos->hwndInsertAfter = HWND_TOPMOST;
1591
1592 if (IntGetWindow(WinPos->hwnd, GW_HWNDFIRST) == WinPos->hwnd)
1593 {
1594 WinPos->flags |= SWP_NOZORDER;
1595 }
1596 }
1597 else if (WinPos->hwndInsertAfter == HWND_BOTTOM)
1598 {
1599 if (!(Wnd->ExStyle & WS_EX_TOPMOST) && IntGetWindow(WinPos->hwnd, GW_HWNDLAST) == WinPos->hwnd)
1600 WinPos->flags |= SWP_NOZORDER;
1601 }
1602 else if (WinPos->hwndInsertAfter == HWND_TOPMOST)
1603 {
1604 if ((Wnd->ExStyle & WS_EX_TOPMOST) && IntGetWindow(WinPos->hwnd, GW_HWNDFIRST) == WinPos->hwnd)
1605 WinPos->flags |= SWP_NOZORDER;
1606 }
1607 else if (WinPos->hwndInsertAfter == HWND_NOTOPMOST)
1608 {
1609 if (!(Wnd->ExStyle & WS_EX_TOPMOST))
1610 WinPos->flags |= SWP_NOZORDER;
1611 }
1612 else /* hwndInsertAfter must be a sibling of the window */
1613 {
1614 PWND InsAfterWnd;
1615
1616 InsAfterWnd = ValidateHwndNoErr(WinPos->hwndInsertAfter);
1617 if(!InsAfterWnd)
1618 {
1619 return TRUE;
1620 }
1621
1622 if (InsAfterWnd->spwndParent != Wnd->spwndParent)
1623 {
1624 /* Note from wine User32 Win test_SetWindowPos:
1625 "Returns TRUE also for windows that are not siblings"
1626 "Does not seem to do anything even without passing flags, still returns TRUE"
1627 "Same thing the other way around."
1628 ".. and with these windows."
1629 */
1630 return FALSE;
1631 }
1632 else
1633 {
1634 /*
1635 * We don't need to change the Z order of hwnd if it's already
1636 * inserted after hwndInsertAfter or when inserting hwnd after
1637 * itself.
1638 */
1639 if ((WinPos->hwnd == WinPos->hwndInsertAfter) ||
1640 ((InsAfterWnd->spwndNext) && (WinPos->hwnd == InsAfterWnd->spwndNext->head.h)))
1641 {
1642 WinPos->flags |= SWP_NOZORDER;
1643 }
1644 }
1645 }
1646 }
1647
1648 return TRUE;
1649 }
1650
1651 /* x and y are always screen relative */
1652 BOOLEAN FASTCALL
1653 co_WinPosSetWindowPos(
1654 PWND Window,
1655 HWND WndInsertAfter,
1656 INT x,
1657 INT y,
1658 INT cx,
1659 INT cy,
1660 UINT flags
1661 )
1662 {
1663 WINDOWPOS WinPos;
1664 RECTL NewWindowRect;
1665 RECTL NewClientRect;
1666 RECTL valid_rects[2];
1667 PREGION VisBefore = NULL;
1668 PREGION VisBeforeJustClient = NULL;
1669 PREGION VisAfter = NULL;
1670 PREGION CopyRgn = NULL;
1671 ULONG WvrFlags = 0;
1672 RECTL OldWindowRect, OldClientRect;
1673 int RgnType;
1674 HDC Dc;
1675 RECTL CopyRect;
1676 PWND Ancestor;
1677 BOOL bPointerInWindow, PosChanged = FALSE;
1678 PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
1679
1680 ASSERT_REFS_CO(Window);
1681
1682 TRACE("pwnd %p, after %p, %d,%d (%dx%d), flags %s",
1683 Window, WndInsertAfter, x, y, cx, cy, flags);
1684 #if DBG
1685 dump_winpos_flags(flags);
1686 #endif
1687
1688 /* FIXME: Get current active window from active queue. Why? since r2915. */
1689
1690 bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y);
1691
1692 WinPos.hwnd = Window->head.h;
1693 WinPos.hwndInsertAfter = WndInsertAfter;
1694 WinPos.x = x;
1695 WinPos.y = y;
1696 WinPos.cx = cx;
1697 WinPos.cy = cy;
1698 WinPos.flags = flags;
1699
1700 if ( flags & SWP_ASYNCWINDOWPOS )
1701 {
1702 LRESULT lRes;
1703 PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP);
1704 if ( ppos )
1705 {
1706 WinPos.flags &= ~SWP_ASYNCWINDOWPOS; // Clear flag.
1707 *ppos = WinPos;
1708 /* Yes it's a pointer inside Win32k! */
1709 lRes = co_IntSendMessageNoWait( WinPos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos);
1710 /* We handle this the same way as Event Hooks and Hooks. */
1711 if ( !lRes )
1712 {
1713 ExFreePoolWithTag(ppos, USERTAG_SWP);
1714 return FALSE;
1715 }
1716 return TRUE;
1717 }
1718 return FALSE;
1719 }
1720
1721 co_WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
1722
1723 /* Does the window still exist? */
1724 if (!IntIsWindow(WinPos.hwnd))
1725 {
1726 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos.hwnd);
1727 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
1728 return FALSE;
1729 }
1730
1731 /* Fix up the flags. */
1732 if (!WinPosFixupFlags(&WinPos, Window))
1733 {
1734 // See Note.
1735 return TRUE;
1736 }
1737
1738 Ancestor = UserGetAncestor(Window, GA_PARENT);
1739 if ( (WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER &&
1740 Ancestor && Ancestor->head.h == IntGetDesktopWindow() )
1741 {
1742 WinPos.hwndInsertAfter = WinPosDoOwnedPopups(Window, WinPos.hwndInsertAfter);
1743 }
1744
1745 if (!(WinPos.flags & SWP_NOREDRAW))
1746 {
1747 /* Compute the visible region before the window position is changed */
1748 if (!(WinPos.flags & SWP_SHOWWINDOW) &&
1749 (WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
1750 SWP_HIDEWINDOW | SWP_FRAMECHANGED)) !=
1751 (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
1752 {
1753 VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE,
1754 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
1755
1756 if ( VisBefore != NULL &&
1757 REGION_Complexity(VisBefore) == NULLREGION )
1758 {
1759 REGION_Delete(VisBefore);
1760 VisBefore = NULL;
1761 }
1762 else if(VisBefore)
1763 {
1764 REGION_bOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top);
1765 }
1766
1767 /* Calculate the non client area for resizes, as this is used in the copy region */
1768 if (!(WinPos.flags & SWP_NOSIZE))
1769 {
1770 VisBeforeJustClient = VIS_ComputeVisibleRegion(Window, TRUE, FALSE,
1771 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
1772
1773 if ( VisBeforeJustClient != NULL &&
1774 REGION_Complexity(VisBeforeJustClient) == NULLREGION )
1775 {
1776 REGION_Delete(VisBeforeJustClient);
1777 VisBeforeJustClient = NULL;
1778 }
1779 else if(VisBeforeJustClient)
1780 {
1781 REGION_bOffsetRgn(VisBeforeJustClient, -Window->rcWindow.left, -Window->rcWindow.top);
1782 }
1783 }
1784 }
1785 }
1786
1787 //// HACK 3
1788 if (Window->hrgnNewFrame)
1789 {
1790 SelectWindowRgn( Window, Window->hrgnNewFrame ); // Should be PSMWP->acvr->hrgnClip
1791 Window->hrgnNewFrame = NULL;
1792 }
1793
1794 WvrFlags = co_WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect, valid_rects);
1795
1796 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags,
1797 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom,
1798 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom);
1799
1800 /* Validate link windows. (also take into account shell window in hwndShellWindow) */
1801 if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow())
1802 {
1803 IntLinkHwnd(Window, WinPos.hwndInsertAfter);
1804 }
1805
1806 OldWindowRect = Window->rcWindow;
1807 OldClientRect = Window->rcClient;
1808
1809 if (NewClientRect.left != OldClientRect.left ||
1810 NewClientRect.top != OldClientRect.top)
1811 {
1812 // Move child window if their parent is moved. Keep Child window relative to Parent...
1813 WinPosInternalMoveWindow(Window,
1814 NewClientRect.left - OldClientRect.left,
1815 NewClientRect.top - OldClientRect.top);
1816 PosChanged = TRUE;
1817 }
1818
1819 Window->rcWindow = NewWindowRect;
1820 Window->rcClient = NewClientRect;
1821
1822 /* erase parent when hiding or resizing child */
1823 if (WinPos.flags & SWP_HIDEWINDOW)
1824 {
1825 /* Clear the update region */
1826 co_UserRedrawWindow( Window,
1827 NULL,
1828 0,
1829 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN);
1830
1831 if (UserIsDesktopWindow(Window->spwndParent))
1832 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM)Window->head.h, 0);
1833
1834 Window->style &= ~WS_VISIBLE; //IntSetStyle( Window, 0, WS_VISIBLE );
1835 Window->head.pti->cVisWindows--;
1836 IntNotifyWinEvent(EVENT_OBJECT_HIDE, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
1837 }
1838 else if (WinPos.flags & SWP_SHOWWINDOW)
1839 {
1840 if (UserIsDesktopWindow(Window->spwndParent) &&
1841 Window->spwndOwner == NULL &&
1842 (!(Window->ExStyle & WS_EX_TOOLWINDOW) ||
1843 (Window->ExStyle & WS_EX_APPWINDOW)))
1844 co_IntShellHookNotify(HSHELL_WINDOWCREATED, (WPARAM)Window->head.h, 0);
1845
1846 Window->style |= WS_VISIBLE; //IntSetStyle( Window, WS_VISIBLE, 0 );
1847 Window->head.pti->cVisWindows++;
1848 IntNotifyWinEvent(EVENT_OBJECT_SHOW, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
1849 }
1850
1851 if (Window->hrgnUpdate != NULL && Window->hrgnUpdate != HRGN_WINDOW)
1852 {
1853 NtGdiOffsetRgn(Window->hrgnUpdate,
1854 NewWindowRect.left - OldWindowRect.left,
1855 NewWindowRect.top - OldWindowRect.top);
1856 }
1857
1858 DceResetActiveDCEs(Window); // For WS_VISIBLE changes.
1859
1860 if (!(WinPos.flags & SWP_NOREDRAW))
1861 {
1862 /* Determine the new visible region */
1863 VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE,
1864 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE);
1865
1866 if ( VisAfter != NULL &&
1867 REGION_Complexity(VisAfter) == NULLREGION )
1868 {
1869 REGION_Delete(VisAfter);
1870 VisAfter = NULL;
1871 }
1872 else if(VisAfter)
1873 {
1874 REGION_bOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top);
1875 }
1876
1877 /*
1878 * Determine which pixels can be copied from the old window position
1879 * to the new. Those pixels must be visible in both the old and new
1880 * position. Also, check the class style to see if the windows of this
1881 * class need to be completely repainted on (horizontal/vertical) size
1882 * change.
1883 */
1884 if ( ( VisBefore != NULL &&
1885 VisAfter != NULL &&
1886 !(WinPos.flags & SWP_NOCOPYBITS) &&
1887 ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) &&
1888 !(Window->ExStyle & WS_EX_TRANSPARENT) ) ||
1889 ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) && VisBefore) )
1890 {
1891
1892 /*
1893 * If this is (also) a window resize, the whole nonclient area
1894 * needs to be repainted. So we limit the copy to the client area,
1895 * 'cause there is no use in copying it (would possibly cause
1896 * "flashing" too). However, if the copy region is already empty,
1897 * we don't have to crop (can't take anything away from an empty
1898 * region...)
1899 */
1900
1901 CopyRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
1902 if (WinPos.flags & SWP_NOSIZE)
1903 RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
1904 else if (VisBeforeJustClient != NULL)
1905 {
1906 RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND);
1907 REGION_Delete(VisBeforeJustClient);
1908 }
1909
1910 /* Now use in copying bits which are in the update region. */
1911 if (Window->hrgnUpdate != NULL)
1912 {
1913 PREGION RgnUpdate = REGION_LockRgn(Window->hrgnUpdate);
1914 if (RgnUpdate)
1915 {
1916 REGION_bOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
1917 IntGdiCombineRgn(CopyRgn, CopyRgn, RgnUpdate, RGN_DIFF);
1918 REGION_bOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
1919 REGION_UnlockRgn(RgnUpdate);
1920 }
1921 }
1922
1923 /*
1924 * Now, get the bounding box of the copy region. If it's empty
1925 * there's nothing to copy. Also, it's no use copying bits onto
1926 * themselves.
1927 */
1928 if (REGION_GetRgnBox(CopyRgn, &CopyRect) == NULLREGION)
1929 {
1930 /* Nothing to copy, clean up */
1931 REGION_Delete(CopyRgn);
1932 CopyRgn = NULL;
1933 }
1934 else if ( OldWindowRect.left != NewWindowRect.left ||
1935 OldWindowRect.top != NewWindowRect.top ||
1936 (WinPos.flags & SWP_FRAMECHANGED) )
1937 {
1938 HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
1939 PREGION DcRgnObj = REGION_LockRgn(DcRgn);
1940
1941 /*
1942 * Small trick here: there is no function to bitblt a region. So
1943 * we set the region as the clipping region, take the bounding box
1944 * of the region and bitblt that. Since nothing outside the clipping
1945 * region is copied, this has the effect of bitblt'ing the region.
1946 *
1947 * Since NtUserGetDCEx takes ownership of the clip region, we need
1948 * to create a copy of CopyRgn and pass that. We need CopyRgn later
1949 */
1950 IntGdiCombineRgn(DcRgnObj, CopyRgn, NULL, RGN_COPY);
1951 REGION_bOffsetRgn(DcRgnObj, NewWindowRect.left, NewWindowRect.top);
1952 REGION_UnlockRgn(DcRgnObj);
1953 Dc = UserGetDCEx( Window,
1954 DcRgn,
1955 DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN);
1956 NtGdiBitBlt( Dc,
1957 CopyRect.left, CopyRect.top,
1958 CopyRect.right - CopyRect.left,
1959 CopyRect.bottom - CopyRect.top,
1960 Dc,
1961 CopyRect.left + (OldWindowRect.left - NewWindowRect.left),
1962 CopyRect.top + (OldWindowRect.top - NewWindowRect.top),
1963 SRCCOPY,
1964 0,
1965 0);
1966
1967 UserReleaseDC(Window, Dc, FALSE);
1968 IntValidateParent(Window, CopyRgn);
1969 GreDeleteObject(DcRgn);
1970 }
1971 }
1972 else
1973 {
1974 CopyRgn = NULL;
1975 }
1976 #if 0
1977 /////// Fixes NoPopup tests but breaks msg_paint tests.
1978 if ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) && VisBefore)
1979 {
1980 PWND Parent = Window->spwndParent;
1981 ERR("SWP_FRAMECHANGED no chg\n");
1982 if ( !(Window->style & WS_CHILD) && (Parent) && (Parent->style & WS_CLIPCHILDREN))
1983 {
1984 ERR("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n");
1985 //IntInvalidateWindows( Window, VisBefore, /*RDW_ERASE |*/ RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1986 }
1987 }
1988 #endif
1989 /* We need to redraw what wasn't visible before */
1990 if (VisAfter != NULL)
1991 {
1992 PREGION DirtyRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
1993 if (DirtyRgn)
1994 {
1995 if (CopyRgn != NULL)
1996 {
1997 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
1998 }
1999 else
2000 {
2001 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY);
2002 }
2003
2004 if (RgnType != ERROR && RgnType != NULLREGION)
2005 {
2006 /* old code
2007 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
2008 IntInvalidateWindows( Window,
2009 DirtyRgn,
2010 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
2011 }
2012 GreDeleteObject(DirtyRgn);
2013 */
2014
2015 PWND Parent = Window->spwndParent;
2016
2017 REGION_bOffsetRgn( DirtyRgn, Window->rcWindow.left, Window->rcWindow.top);
2018
2019 if ( (Window->style & WS_CHILD) && (Parent) && !(Parent->style & WS_CLIPCHILDREN))
2020 {
2021 IntInvalidateWindows( Parent, DirtyRgn, RDW_ERASE | RDW_INVALIDATE);
2022 co_IntPaintWindows(Parent, RDW_NOCHILDREN, FALSE);
2023 }
2024 else
2025 {
2026 IntInvalidateWindows( Window, DirtyRgn, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
2027 }
2028 }
2029 REGION_Delete(DirtyRgn);
2030 }
2031 }
2032
2033 if (CopyRgn != NULL)
2034 {
2035 REGION_Delete(CopyRgn);
2036 }
2037
2038 /* Expose what was covered before but not covered anymore */
2039 if (VisBefore != NULL)
2040 {
2041 PREGION ExposedRgn = IntSysCreateRectpRgn(0, 0, 0, 0);
2042 if (ExposedRgn)
2043 {
2044 RgnType = IntGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
2045 REGION_bOffsetRgn(ExposedRgn,
2046 OldWindowRect.left - NewWindowRect.left,
2047 OldWindowRect.top - NewWindowRect.top);
2048
2049 if (VisAfter != NULL)
2050 RgnType = IntGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
2051
2052 if (RgnType != ERROR && RgnType != NULLREGION)
2053 {
2054 co_VIS_WindowLayoutChanged(Window, ExposedRgn);
2055 }
2056 REGION_Delete(ExposedRgn);
2057 }
2058 REGION_Delete(VisBefore);
2059 }
2060
2061 if (VisAfter != NULL)
2062 {
2063 REGION_Delete(VisAfter);
2064 }
2065 }
2066
2067 if (!(WinPos.flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)))
2068 {
2069 if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
2070 {
2071 co_IntSendMessageNoWait(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0);
2072 }
2073 else
2074 {
2075 //ERR("SetWindowPos Set FG Window!\n");
2076 if ( pti->MessageQueue->spwndActive != Window ||
2077 pti->MessageQueue != gpqForeground )
2078 {
2079 //ERR("WPSWP : set active window\n");
2080 if (!(Window->state & WNDS_BEINGACTIVATED)) // Inside SAW?
2081 {
2082 co_IntSetForegroundWindow(Window); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow.
2083 }
2084 }
2085 }
2086 }
2087
2088 if ( !PosChanged &&
2089 (WinPos.flags & SWP_FRAMECHANGED) &&
2090 !(WinPos.flags & SWP_DEFERERASE) && // Prevent sending WM_SYNCPAINT message.
2091 VisAfter )
2092 {
2093 PWND Parent = Window->spwndParent;
2094 if ( !(Window->style & WS_CHILD) && (Parent) && (Parent->style & WS_CLIPCHILDREN))
2095 {
2096 TRACE("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n");
2097 UserSyncAndPaintWindows( Parent, RDW_CLIPCHILDREN);
2098 }
2099 }
2100
2101 // Fix wine msg test_SetFocus, prevents sending WM_WINDOWPOSCHANGED.
2102 if ( VisBefore == NULL &&
2103 VisBeforeJustClient == NULL &&
2104 !(Window->ExStyle & WS_EX_TOPMOST) &&
2105 (WinPos.flags & SWP_AGG_STATUSFLAGS) == (SWP_AGG_NOPOSCHANGE & ~SWP_NOZORDER))
2106 {
2107 TRACE("No drawing, set no Z order and no redraw!\n");
2108 WinPos.flags |= SWP_NOZORDER|SWP_NOREDRAW;
2109 }
2110
2111 if(!(flags & SWP_DEFERERASE))
2112 {
2113 /* erase parent when hiding or resizing child */
2114 if ((flags & SWP_HIDEWINDOW) ||
2115 (!(flags & SWP_SHOWWINDOW) &&
2116 (WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOGEOMETRYCHANGE))
2117 {
2118 PWND Parent = Window->spwndParent;
2119 if (!Parent || UserIsDesktopWindow(Parent)) Parent = Window;
2120 UserSyncAndPaintWindows( Parent, RDW_ERASENOW);
2121 }
2122
2123 /* Give newly shown windows a chance to redraw */
2124 if(((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)
2125 && !(flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW))
2126 {
2127 UserSyncAndPaintWindows( Window, RDW_ERASENOW);
2128 }
2129 }
2130
2131 /* And last, send the WM_WINDOWPOSCHANGED message */
2132
2133 TRACE("\tstatus hwnd %p flags = %04x\n",Window?Window->head.h:NULL,WinPos.flags & SWP_AGG_STATUSFLAGS);
2134
2135 if (((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE)
2136 && !((flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW)))
2137 {
2138 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set
2139 and always contains final window position.
2140 */
2141 WinPos.x = NewWindowRect.left;
2142 WinPos.y = NewWindowRect.top;
2143 WinPos.cx = NewWindowRect.right - NewWindowRect.left;
2144 WinPos.cy = NewWindowRect.bottom - NewWindowRect.top;
2145 TRACE("WM_WINDOWPOSCHANGED hwnd %p Flags %04x\n",WinPos.hwnd,WinPos.flags);
2146 co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos);
2147 }
2148
2149 if ( WinPos.flags & SWP_FRAMECHANGED || WinPos.flags & SWP_STATECHANGED ||
2150 !(WinPos.flags & SWP_NOCLIENTSIZE) || !(WinPos.flags & SWP_NOCLIENTMOVE) )
2151 {
2152 PWND pWnd = ValidateHwndNoErr(WinPos.hwnd);
2153 if (pWnd)
2154 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
2155 }
2156
2157 if(bPointerInWindow != IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y))
2158 {
2159 /* Generate mouse move message */
2160 MSG msg;
2161 msg.message = WM_MOUSEMOVE;
2162 msg.wParam = UserGetMouseButtonsState();
2163 msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y);
2164 msg.pt = gpsi->ptCursor;
2165 co_MsqInsertMouseMessage(&msg, 0, 0, TRUE);
2166 }
2167
2168 return TRUE;
2169 }
2170
2171 LRESULT FASTCALL
2172 co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect)
2173 {
2174 LRESULT Result;
2175
2176 ASSERT_REFS_CO(Window);
2177
2178 *ClientRect = *WindowRect;
2179 Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect);
2180
2181 FixClientRect(ClientRect, WindowRect);
2182
2183 return Result;
2184 }
2185
2186 void FASTCALL
2187 co_WinPosSendSizeMove(PWND Wnd)
2188 {
2189 RECTL Rect;
2190 LPARAM lParam;
2191 WPARAM wParam = SIZE_RESTORED;
2192
2193 IntGetClientRect(Wnd, &Rect);
2194 lParam = MAKELONG(Rect.right-Rect.left, Rect.bottom-Rect.top);
2195
2196 Wnd->state &= ~WNDS_SENDSIZEMOVEMSGS;
2197
2198 if (Wnd->style & WS_MAXIMIZE)
2199 {
2200 wParam = SIZE_MAXIMIZED;
2201 }
2202 else if (Wnd->style & WS_MINIMIZE)
2203 {
2204 wParam = SIZE_MINIMIZED;
2205 lParam = 0;
2206 }
2207
2208 co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SIZE, wParam, lParam);
2209
2210 if (UserIsDesktopWindow(Wnd->spwndParent))
2211 lParam = MAKELONG(Wnd->rcClient.left, Wnd->rcClient.top);
2212 else
2213 lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top);
2214
2215 co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_MOVE, 0, lParam);
2216
2217 IntEngWindowChanged(Wnd, WOC_RGN_CLIENT);
2218 }
2219
2220 UINT FASTCALL
2221 co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos)
2222 {
2223 POINT Size;
2224 WINDOWPLACEMENT wpl;
2225 LONG old_style;
2226 UINT SwpFlags = 0;
2227
2228 ASSERT_REFS_CO(Wnd);
2229
2230 wpl.length = sizeof(wpl);
2231 IntGetWindowPlacement( Wnd, &wpl );
2232
2233 if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag))
2234 {
2235 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n");
2236 return SWP_NOSIZE | SWP_NOMOVE;
2237 }
2238 if (Wnd->style & WS_MINIMIZE)
2239 {
2240 switch (ShowFlag)
2241 {
2242 case SW_MINIMIZE:
2243 case SW_SHOWMINNOACTIVE:
2244 case SW_SHOWMINIMIZED:
2245 case SW_FORCEMINIMIZE:
2246 return SWP_NOSIZE | SWP_NOMOVE;
2247 }
2248 if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0))
2249 {
2250 return(SWP_NOSIZE | SWP_NOMOVE);
2251 }
2252 SwpFlags |= SWP_NOCOPYBITS;
2253 }
2254 switch (ShowFlag)
2255 {
2256 case SW_MINIMIZE:
2257 case SW_SHOWMINNOACTIVE:
2258 case SW_SHOWMINIMIZED:
2259 case SW_FORCEMINIMIZE:
2260 {
2261 //ERR("MinMaximize Minimize\n");
2262 if (Wnd->style & WS_MAXIMIZE)
2263 {
2264 Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED;
2265 }
2266 else
2267 {
2268 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
2269 }
2270
2271 old_style = IntSetStyle( Wnd, WS_MINIMIZE, WS_MAXIMIZE );
2272
2273 co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT);
2274
2275 if (!(Wnd->InternalPos.flags & WPF_SETMINPOSITION))
2276 Wnd->InternalPos.flags &= ~WPF_MININIT;
2277
2278 WinPosFindIconPos(Wnd, &wpl.ptMinPosition);
2279
2280 /*if (!(old_style & WS_MINIMIZE))
2281 {
2282 SwpFlags |= SWP_STATECHANGED;
2283 IntShowOwnedPopups(Wnd, FALSE);
2284 }*/
2285
2286 RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
2287 wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED),
2288 wpl.ptMinPosition.y + UserGetSystemMetrics(SM_CYMINIMIZED));
2289 SwpFlags |= SWP_NOCOPYBITS;
2290 break;
2291 }
2292
2293 case SW_MAXIMIZE:
2294 {
2295 //ERR("MinMaximize Maximize\n");
2296 if ((Wnd->style & WS_MAXIMIZE) && (Wnd->style & WS_VISIBLE))
2297 {
2298 SwpFlags = SWP_NOSIZE | SWP_NOMOVE;
2299 break;
2300 }
2301 co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
2302
2303 /*ERR("Maximize: %d,%d %dx%d\n",
2304 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y);
2305 */
2306 old_style = IntSetStyle( Wnd, WS_MAXIMIZE, WS_MINIMIZE );
2307 /*if (old_style & WS_MINIMIZE)
2308 {
2309 IntShowOwnedPopups(Wnd, TRUE);
2310 }*/
2311
2312 if (!(old_style & WS_MAXIMIZE)) SwpFlags |= SWP_STATECHANGED;
2313 RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y,
2314 //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
2315 Size.x, Size.y);
2316 break;
2317 }
2318
2319 case SW_SHOWNOACTIVATE:
2320 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
2321 /* fall through */
2322 case SW_SHOWNORMAL:
2323 case SW_RESTORE:
2324 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
2325 {
2326 //ERR("MinMaximize Restore\n");
2327 old_style = IntSetStyle( Wnd, 0, WS_MINIMIZE | WS_MAXIMIZE );
2328 if (old_style & WS_MINIMIZE)
2329 {
2330 //IntShowOwnedPopups(Wnd, TRUE);
2331
2332 if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED)
2333 {
2334 co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL);
2335 IntSetStyle( Wnd, WS_MAXIMIZE, 0 );
2336 SwpFlags |= SWP_STATECHANGED;
2337 RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y,
2338 wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y);
2339 break;
2340 }
2341 else
2342 {
2343 *NewPos = wpl.rcNormalPosition;
2344 NewPos->right -= NewPos->left;
2345 NewPos->bottom -= NewPos->top;
2346 break;
2347 }
2348 }
2349 else
2350 {
2351 if (!(old_style & WS_MAXIMIZE))
2352 {
2353 break;
2354 }
2355 SwpFlags |= SWP_STATECHANGED;
2356 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED;
2357 *NewPos = wpl.rcNormalPosition;
2358 NewPos->right -= NewPos->left;
2359 NewPos->bottom -= NewPos->top;
2360 break;
2361 }
2362 }
2363 }
2364 return SwpFlags;
2365 }
2366
2367 /*
2368 ShowWindow does not set SWP_FRAMECHANGED!!! Fix wine msg test_SetParent:WmSetParentSeq_2:23 wParam bits!
2369 */
2370 BOOLEAN FASTCALL
2371 co_WinPosShowWindow(PWND Wnd, INT Cmd)
2372 {
2373 BOOLEAN WasVisible;
2374 UINT Swp = 0, EventMsg = 0;
2375 RECTL NewPos = {0, 0, 0, 0};
2376 BOOLEAN ShowFlag;
2377 LONG style;
2378 PWND Parent;
2379 PTHREADINFO pti;
2380 //HRGN VisibleRgn;
2381 BOOL ShowOwned = FALSE;
2382 BOOL FirstTime = FALSE;
2383 ASSERT_REFS_CO(Wnd);
2384 //KeRosDumpStackFrames(NULL, 20);
2385 pti = PsGetCurrentThreadWin32Thread();
2386 WasVisible = (Wnd->style & WS_VISIBLE) != 0;
2387 style = Wnd->style;
2388
2389 TRACE("co_WinPosShowWindow START hwnd %p Cmd %d usicmd %u\n",
2390 Wnd->head.h, Cmd, pti->ppi->usi.wShowWindow);
2391
2392 if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW )
2393 {
2394 if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD)
2395 {
2396 if ((Wnd->style & WS_CAPTION) == WS_CAPTION)
2397 {
2398 if (Wnd->spwndOwner == NULL)
2399 {
2400 if ( Cmd == SW_SHOWNORMAL || Cmd == SW_SHOW)
2401 {
2402 Cmd = SW_SHOWDEFAULT;
2403 }
2404 FirstTime = TRUE;
2405 TRACE("co_WPSW FT 1\n");
2406 }
2407 }
2408 }
2409 }
2410
2411 if ( Cmd == SW_SHOWDEFAULT )
2412 {
2413 if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW )
2414 {
2415 Cmd = pti->ppi->usi.wShowWindow;
2416 FirstTime = TRUE;
2417 TRACE("co_WPSW FT 2\n");
2418 }
2419 }
2420
2421 if (FirstTime)
2422 {
2423 pti->ppi->usi.dwFlags &= ~(STARTF_USEPOSITION|STARTF_USESIZE|STARTF_USESHOWWINDOW);
2424 }
2425
2426 switch (Cmd)
2427 {
2428 case SW_HIDE:
2429 {
2430 if (!WasVisible)
2431 {
2432 //ERR("co_WinPosShowWindow Exit Bad\n");
2433 return FALSE;
2434 }
2435 Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2436 if (Wnd != pti->MessageQueue->spwndActive)
2437 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2438 break;
2439 }
2440
2441 case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */
2442 case SW_SHOWMINNOACTIVE:
2443 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2444 /* Fall through. */
2445 case SW_SHOWMINIMIZED:
2446 Swp |= SWP_SHOWWINDOW;
2447 /* Fall through. */
2448 case SW_MINIMIZE:
2449 {
2450 Swp |= SWP_NOACTIVATE;
2451 if (!(style & WS_MINIMIZE))
2452 {
2453 IntShowOwnedPopups(Wnd, FALSE );
2454 // Fix wine Win test_SetFocus todo #1 & #2,
2455 if (Cmd == SW_SHOWMINIMIZED)
2456 {
2457 //ERR("co_WinPosShowWindow Set focus 1\n");
2458 if ((style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
2459 co_UserSetFocus(Wnd->spwndParent);
2460 else
2461 co_UserSetFocus(0);
2462 }
2463
2464 Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos);
2465
2466 EventMsg = EVENT_SYSTEM_MINIMIZESTART;
2467 }
2468 else
2469 {
2470 if (WasVisible)
2471 {
2472 //ERR("co_WinPosShowWindow Exit Good\n");
2473 return TRUE;
2474 }
2475 Swp |= SWP_NOSIZE | SWP_NOMOVE;
2476 }
2477 break;
2478 }
2479
2480 case SW_SHOWMAXIMIZED:
2481 {
2482 Swp |= SWP_SHOWWINDOW;
2483 if (!(style & WS_MAXIMIZE))
2484 {
2485 ShowOwned = TRUE;
2486
2487 Swp |= co_WinPosMinMaximize(Wnd, SW_MAXIMIZE, &NewPos);
2488
2489 EventMsg = EVENT_SYSTEM_MINIMIZEEND;
2490 }
2491 else
2492 {
2493 if (WasVisible)
2494 {
2495 //ERR("co_WinPosShowWindow Exit Good 1\n");
2496 return TRUE;
2497 }
2498 Swp |= SWP_NOSIZE | SWP_NOMOVE;
2499 }
2500 break;
2501 }
2502
2503 case SW_SHOWNA:
2504 Swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2505 if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOZORDER;
2506 break;
2507 case SW_SHOW:
2508 if (WasVisible) return(TRUE); // Nothing to do!
2509 Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
2510 /* Don't activate the topmost window. */
2511 if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2512 break;
2513
2514 case SW_SHOWNOACTIVATE:
2515 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2516 /* Fall through. */
2517 case SW_SHOWNORMAL:
2518 case SW_SHOWDEFAULT:
2519 case SW_RESTORE:
2520 if (!WasVisible) Swp |= SWP_SHOWWINDOW;
2521 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
2522 {
2523 Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos);
2524 if (style & WS_MINIMIZE) EventMsg = EVENT_SYSTEM_MINIMIZEEND;
2525 }
2526 else
2527 {
2528 if (WasVisible)
2529 {
2530 //ERR("co_WinPosShowWindow Exit Good 3\n");
2531 return TRUE;
2532 }
2533 Swp |= SWP_NOSIZE | SWP_NOMOVE;
2534 }
2535 if ( style & WS_CHILD &&
2536 !(Wnd->ExStyle & WS_EX_MDICHILD) &&
2537 !(Swp & SWP_STATECHANGED))
2538 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2539 break;
2540
2541 default:
2542 //ERR("co_WinPosShowWindow Exit Good 4\n");
2543 return WasVisible;
2544 }
2545
2546 ShowFlag = (Cmd != SW_HIDE);
2547
2548 if ((ShowFlag != WasVisible || Cmd == SW_SHOWNA) && Cmd != SW_SHOWMAXIMIZED && !(Swp & SWP_STATECHANGED))
2549 {
2550 co_IntSendMessageNoWait(Wnd->head.h, WM_SHOWWINDOW, ShowFlag, 0);
2551 #if 0 // Fix wine msg test_SetParent:WmSetParentSeq_1:2
2552 if (!(Wnd->state2 & WNDS2_WIN31COMPAT)) // <------------- XP sets this bit!
2553 co_IntSendMessageNoWait(Wnd->head.h, WM_SETVISIBLE, ShowFlag, 0);
2554 #endif
2555 if (!VerifyWnd(Wnd)) return WasVisible;
2556 }
2557
2558 /* We can't activate a child window */
2559 if ((Wnd->style & WS_CHILD) &&
2560 !(Wnd->ExStyle & WS_EX_MDICHILD) &&
2561 Cmd != SW_SHOWNA)
2562 {
2563 //ERR("SWP Child No active and ZOrder\n");
2564 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2565 }
2566
2567 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works.
2568 // Breaks startup and shutdown active window...
2569 if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD &&
2570 Wnd->pcls->style & CS_SAVEBITS &&
2571 ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL)))
2572 {
2573 ERR("WinPosShowWindow Set active\n");
2574 //UserSetActiveWindow(Wnd);
2575 co_IntSetForegroundWindow(Wnd); // HACK
2576 Swp |= SWP_NOACTIVATE | SWP_NOZORDER;
2577 }
2578 #endif
2579
2580 if (IsChildVisible(Wnd) || Swp & SWP_STATECHANGED)
2581 {
2582 TRACE("Child is Vis %s or State changed %s. ShowFlag %s Swp %04x\n",
2583 (IsChildVisible(Wnd) ? "TRUE" : "FALSE"), (Swp & SWP_STATECHANGED ? "TRUE" : "FALSE"),
2584 (ShowFlag ? "TRUE" : "FALSE"),LOWORD(Swp));
2585 co_WinPosSetWindowPos( Wnd,
2586 0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP,
2587 NewPos.left,
2588 NewPos.top,
2589 NewPos.right, // NewPos.right - NewPos.left, when minimized and restore, the window becomes smaller.
2590 NewPos.bottom,// NewPos.bottom - NewPos.top,
2591 LOWORD(Swp));
2592 }
2593 else
2594 {
2595 TRACE("Parent Vis?\n");
2596 /* if parent is not visible simply toggle WS_VISIBLE and return */
2597 if (ShowFlag) IntSetStyle( Wnd, WS_VISIBLE, 0 );
2598 else IntSetStyle( Wnd, 0, WS_VISIBLE );
2599 }
2600
2601 if ( EventMsg ) IntNotifyWinEvent(EventMsg, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
2602
2603 if ( ShowOwned ) IntShowOwnedPopups(Wnd, TRUE );
2604
2605 if ((Cmd == SW_HIDE) || (Cmd == SW_MINIMIZE))
2606 {
2607 if ( Wnd == pti->MessageQueue->spwndActive && pti->MessageQueue == IntGetFocusMessageQueue() )
2608 {
2609 if (UserIsDesktopWindow(Wnd->spwndParent))
2610 {
2611 if (!ActivateOtherWindowMin(Wnd))
2612 {
2613 co_WinPosActivateOtherWindow(Wnd);
2614 }
2615 }
2616 else
2617 {
2618 co_WinPosActivateOtherWindow(Wnd);
2619 }
2620 }
2621
2622 /* Revert focus to parent */
2623 if (Wnd == pti->MessageQueue->spwndFocus)
2624 {
2625 Parent = Wnd->spwndParent;
2626 if (UserIsDesktopWindow(Wnd->spwndParent))
2627 Parent = 0;
2628 co_UserSetFocus(Parent);
2629 }
2630 // Hide, just return.
2631 if (Cmd == SW_HIDE) return WasVisible;
2632 }
2633
2634 /* FIXME: Check for window destruction. */
2635
2636 if ((Wnd->state & WNDS_SENDSIZEMOVEMSGS) &&
2637 !(Wnd->state2 & WNDS2_INDESTROY))
2638 {
2639 co_WinPosSendSizeMove(Wnd);
2640 }
2641
2642 /* if previous state was minimized Windows sets focus to the window */
2643 if (style & WS_MINIMIZE)
2644 {
2645 co_UserSetFocus(Wnd);
2646 // Fix wine Win test_SetFocus todo #3,
2647 if (!(style & WS_CHILD)) co_IntSendMessage(UserHMGetHandle(Wnd), WM_ACTIVATE, WA_ACTIVE, 0);
2648 }
2649 //ERR("co_WinPosShowWindow EXIT\n");
2650 return WasVisible;
2651 }
2652
2653 static PWND
2654 co_WinPosSearchChildren(
2655 IN PWND ScopeWin,
2656 IN POINT *Point,
2657 IN OUT USHORT *HitTest,
2658 IN BOOL Ignore
2659 )
2660 {
2661 HWND *List, *phWnd;
2662 PWND pwndChild = NULL;
2663
2664 /* not visible */
2665 if (!(ScopeWin->style & WS_VISIBLE))
2666 {
2667 return NULL;
2668 }
2669
2670 /* not in window or in window region */
2671 if (!IntPtInWindow(ScopeWin, Point->x, Point->y))
2672 {
2673 return NULL;
2674 }
2675
2676 /* transparent */
2677 if ((ScopeWin->ExStyle & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == (WS_EX_LAYERED|WS_EX_TRANSPARENT))
2678 {
2679 return NULL;
2680 }
2681
2682 if (!Ignore && (ScopeWin->style & WS_DISABLED))
2683 { /* disabled child */
2684 if ((ScopeWin->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return NULL;
2685 /* process the hit error */
2686 *HitTest = HTERROR;
2687 return ScopeWin;
2688 }
2689
2690 /* not minimized and check if point is inside the window */
2691 if (!(ScopeWin->style & WS_MINIMIZE) &&
2692 RECTL_bPointInRect(&ScopeWin->rcClient, Point->x, Point->y) )
2693 {
2694 UserReferenceObject(ScopeWin);
2695
2696 List = IntWinListChildren(ScopeWin);
2697 if (List)
2698 {
2699 for (phWnd = List; *phWnd; ++phWnd)
2700 {
2701 if (!(pwndChild = ValidateHwndNoErr(*phWnd)))
2702 {
2703 continue;
2704 }
2705
2706 pwndChild = co_WinPosSearchChildren(pwndChild, Point, HitTest, Ignore);
2707
2708 if (pwndChild != NULL)
2709 {
2710 /* We found a window. Don't send any more WM_NCHITTEST messages */
2711 ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2712 UserDereferenceObject(ScopeWin);
2713 return pwndChild;
2714 }
2715 }
2716 ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2717 }
2718 UserDereferenceObject(ScopeWin);
2719 }
2720
2721 if (ScopeWin->head.pti == PsGetCurrentThreadWin32Thread())
2722 {
2723 *HitTest = (USHORT)co_IntSendMessage(ScopeWin->head.h, WM_NCHITTEST, 0, MAKELONG(Point->x, Point->y));
2724
2725 if ((*HitTest) == (USHORT)HTTRANSPARENT)
2726 {
2727 return NULL;
2728 }
2729 }
2730 else
2731 {
2732 if (*HitTest == HTNOWHERE && pwndChild == NULL) *HitTest = HTCLIENT;
2733 }
2734
2735 return ScopeWin;
2736 }
2737
2738 PWND APIENTRY
2739 co_WinPosWindowFromPoint(
2740 IN PWND ScopeWin,
2741 IN POINT *WinPoint,
2742 IN OUT USHORT* HitTest,
2743 IN BOOL Ignore)
2744 {
2745 PWND Window;
2746 POINT Point = *WinPoint;
2747 USER_REFERENCE_ENTRY Ref;
2748
2749 if( ScopeWin == NULL )
2750 {
2751 ScopeWin = UserGetDesktopWindow();
2752 if(ScopeWin == NULL)
2753 return NULL;
2754 }
2755
2756 *HitTest = HTNOWHERE;
2757
2758 ASSERT_REFS_CO(ScopeWin);
2759 UserRefObjectCo(ScopeWin, &Ref);
2760
2761 Window = co_WinPosSearchChildren(ScopeWin, &Point, HitTest, Ignore);
2762
2763 UserDerefObjectCo(ScopeWin);
2764 if (Window)
2765 ASSERT_REFS_CO(Window);
2766 ASSERT_REFS_CO(ScopeWin);
2767
2768 return Window;
2769 }
2770
2771 PWND FASTCALL
2772 IntRealChildWindowFromPoint(PWND Parent, LONG x, LONG y)
2773 {
2774 POINTL Pt;
2775 HWND *List, *phWnd;
2776 PWND pwndHit = NULL;
2777
2778 Pt.x = x;
2779 Pt.y = y;
2780
2781 if (!UserIsDesktopWindow(Parent))
2782 {
2783 Pt.x += Parent->rcClient.left;
2784 Pt.y += Parent->rcClient.top;
2785 }
2786
2787 if (!IntPtInWindow(Parent, Pt.x, Pt.y)) return NULL;
2788
2789 if ((List = IntWinListChildren(Parent)))
2790 {
2791 for (phWnd = List; *phWnd; phWnd++)
2792 {
2793 PWND Child;
2794 if ((Child = ValidateHwndNoErr(*phWnd)))
2795 {
2796 if ( Child->style & WS_VISIBLE && IntPtInWindow(Child, Pt.x, Pt.y) )
2797 {
2798 if ( Child->pcls->atomClassName != gpsi->atomSysClass[ICLS_BUTTON] ||
2799 (Child->style & BS_TYPEMASK) != BS_GROUPBOX )
2800 {
2801 ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2802 return Child;
2803 }
2804 pwndHit = Child;
2805 }
2806 }
2807 }
2808 ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2809 }
2810 return pwndHit ? pwndHit : Parent;
2811 }
2812
2813 PWND APIENTRY
2814 IntChildWindowFromPointEx(PWND Parent, LONG x, LONG y, UINT uiFlags)
2815 {
2816 POINTL Pt;
2817 HWND *List, *phWnd;
2818 PWND pwndHit = NULL;
2819
2820 Pt.x = x;
2821 Pt.y = y;
2822
2823 if (!UserIsDesktopWindow(Parent))
2824 {
2825 if (Parent->ExStyle & WS_EX_LAYOUTRTL)
2826 Pt.x = Parent->rcClient.right - Pt.x;
2827 else
2828 Pt.x += Parent->rcClient.left;
2829 Pt.y += Parent->rcClient.top;
2830 }
2831
2832 if (!IntPtInWindow(Parent, Pt.x, Pt.y)) return NULL;
2833
2834 if ((List = IntWinListChildren(Parent)))
2835 {
2836 for (phWnd = List; *phWnd; phWnd++)
2837 {
2838 PWND Child;
2839 if ((Child = ValidateHwndNoErr(*phWnd)))
2840 {
2841 if (uiFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED))
2842 {
2843 if (!(Child->style & WS_VISIBLE) && (uiFlags & CWP_SKIPINVISIBLE)) continue;
2844 if ((Child->style & WS_DISABLED) && (uiFlags & CWP_SKIPDISABLED)) continue;
2845 }
2846
2847 if (uiFlags & CWP_SKIPTRANSPARENT)
2848 {
2849 if (Child->ExStyle & WS_EX_TRANSPARENT) continue;
2850 }
2851
2852 if (IntPtInWindow(Child, Pt.x, Pt.y))
2853 {
2854 pwndHit = Child;
2855 break;
2856 }
2857 }
2858 }
2859 ExFreePoolWithTag(List, USERTAG_WINDOWLIST);
2860 }
2861 return pwndHit ? pwndHit : Parent;
2862 }
2863
2864 HDWP
2865 FASTCALL
2866 IntDeferWindowPos( HDWP hdwp,
2867 HWND hwnd,
2868 HWND hwndAfter,
2869 INT x,
2870 INT y,
2871 INT cx,
2872 INT cy,
2873 UINT flags )
2874 {
2875 PSMWP pDWP;
2876 int i;
2877 HDWP retvalue = hdwp;
2878
2879 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2880 hdwp, hwnd, hwndAfter, x, y, cx, cy, flags);
2881
2882 if (flags & ~(SWP_NOSIZE | SWP_NOMOVE |
2883 SWP_NOZORDER | SWP_NOREDRAW |
2884 SWP_NOACTIVATE | SWP_NOCOPYBITS |
2885 SWP_NOOWNERZORDER|SWP_SHOWWINDOW |
2886 SWP_HIDEWINDOW | SWP_FRAMECHANGED))
2887 {
2888 EngSetLastError(ERROR_INVALID_PARAMETER);
2889 return NULL;
2890 }
2891
2892 if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, TYPE_SETWINDOWPOS)))
2893 {
2894 EngSetLastError(ERROR_INVALID_DWP_HANDLE);
2895 return NULL;
2896 }
2897
2898 for (i = 0; i < pDWP->ccvr; i++)
2899 {
2900 if (pDWP->acvr[i].pos.hwnd == hwnd)
2901 {
2902 /* Merge with the other changes */
2903 if (!(flags & SWP_NOZORDER))
2904 {
2905 pDWP->acvr[i].pos.hwndInsertAfter = hwndAfter;
2906 }
2907 if (!(flags & SWP_NOMOVE))
2908 {
2909 pDWP->acvr[i].pos.x = x;
2910 pDWP->acvr[i].pos.y = y;
2911 }
2912 if (!(flags & SWP_NOSIZE))
2913 {
2914 pDWP->acvr[i].pos.cx = cx;
2915 pDWP->acvr[i].pos.cy = cy;
2916 }
2917 pDWP->acvr[i].pos.flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE |
2918 SWP_NOZORDER | SWP_NOREDRAW |
2919 SWP_NOACTIVATE | SWP_NOCOPYBITS|
2920 SWP_NOOWNERZORDER);
2921 pDWP->acvr[i].pos.flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW |
2922 SWP_FRAMECHANGED);
2923 goto END;
2924 }
2925 }
2926 if (pDWP->ccvr >= pDWP->ccvrAlloc)
2927 {
2928 PCVR newpos = ExAllocatePoolWithTag(PagedPool, pDWP->ccvrAlloc * 2 * sizeof(CVR), USERTAG_SWP);
2929 if (!newpos)
2930 {
2931 retvalue = NULL;
2932 goto END;
2933 }
2934 RtlZeroMemory(newpos, pDWP->ccvrAlloc * 2 * sizeof(CVR));
2935 RtlCopyMemory(newpos, pDWP->acvr, pDWP->ccvrAlloc * sizeof(CVR));
2936 ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP);
2937 pDWP->ccvrAlloc *= 2;
2938 pDWP->acvr = newpos;
2939 }
2940 pDWP->acvr[pDWP->ccvr].pos.hwnd = hwnd;
2941 pDWP->acvr[pDWP->ccvr].pos.hwndInsertAfter = hwndAfter;
2942 pDWP->acvr[pDWP->ccvr].pos.x = x;
2943 pDWP->acvr[pDWP->ccvr].pos.y = y;
2944 pDWP->acvr[pDWP->ccvr].pos.cx = cx;
2945 pDWP->acvr[pDWP->ccvr].pos.cy = cy;
2946 pDWP->acvr[pDWP->ccvr].pos.flags = flags;
2947 pDWP->acvr[pDWP->ccvr].hrgnClip = NULL;
2948 pDWP->acvr[pDWP->ccvr].hrgnInterMonitor = NULL;
2949 pDWP->ccvr++;
2950 END:
2951 return retvalue;
2952 }
2953
2954 BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp, BOOL sAsync )
2955 {
2956 PSMWP pDWP;
2957 PCVR winpos;
2958 BOOL res = TRUE;
2959 int i;
2960
2961 TRACE("%p\n", hdwp);
2962
2963 if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, TYPE_SETWINDOWPOS)))
2964 {
2965 EngSetLastError(ERROR_INVALID_DWP_HANDLE);
2966 return FALSE;
2967 }
2968
2969 for (i = 0, winpos = pDWP->acvr; res && i < pDWP->ccvr; i++, winpos++)
2970 {
2971 PWND pwnd;
2972 USER_REFERENCE_ENTRY Ref;
2973
2974 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n",
2975 winpos->pos.hwnd, winpos->pos.hwndInsertAfter, winpos->pos.x, winpos->pos.y,
2976 winpos->pos.cx, winpos->pos.cy, winpos->pos.flags);
2977
2978 pwnd = ValidateHwndNoErr(winpos->pos.hwnd);
2979 if (!pwnd)
2980 continue;
2981
2982 UserRefObjectCo(pwnd, &Ref);
2983
2984 if ( sAsync )
2985 {
2986 LRESULT lRes;
2987 PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP);
2988 if ( ppos )
2989 {
2990 *ppos = winpos->pos;
2991 /* Yes it's a pointer inside Win32k! */
2992 lRes = co_IntSendMessageNoWait( winpos->pos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos);
2993 /* We handle this the same way as Event Hooks and Hooks. */
2994 if ( !lRes )
2995 {
2996 ExFreePoolWithTag(ppos, USERTAG_SWP);
2997 }
2998 }
2999 }
3000 else
3001 res = co_WinPosSetWindowPos( pwnd,
3002 winpos->pos.hwndInsertAfter,
3003 winpos->pos.x,
3004 winpos->pos.y,
3005 winpos->pos.cx,
3006 winpos->pos.cy,
3007 winpos->pos.flags);
3008
3009 // Hack to pass tests.... Must have some work to do so clear the error.
3010 if (res && (winpos->pos.flags & (SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER)) == SWP_NOZORDER )
3011 EngSetLastError(ERROR_SUCCESS);
3012
3013 UserDerefObjectCo(pwnd);
3014 }
3015 ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP);
3016 UserDereferenceObject(pDWP);
3017 UserDeleteObject(hdwp, TYPE_SETWINDOWPOS);
3018 return res;
3019 }
3020
3021 /*
3022 * @implemented
3023 */
3024 HWND APIENTRY
3025 NtUserChildWindowFromPointEx(HWND hwndParent,
3026 LONG x,
3027 LONG y,
3028 UINT uiFlags)
3029 {
3030 PWND pwndParent;
3031 TRACE("Enter NtUserChildWindowFromPointEx\n");
3032 UserEnterExclusive();
3033 if ((pwndParent = UserGetWindowObject(hwndParent)))
3034 {
3035 pwndParent = IntChildWindowFromPointEx(pwndParent, x, y, uiFlags);
3036 }
3037 UserLeave();
3038 TRACE("Leave NtUserChildWindowFromPointEx\n");
3039 return pwndParent ? UserHMGetHandle(pwndParent) : NULL;
3040 }
3041
3042 /*
3043 * @implemented
3044 */
3045 BOOL APIENTRY
3046 NtUserEndDeferWindowPosEx(HDWP WinPosInfo,
3047 DWORD Unknown1)
3048 {
3049 BOOL Ret;
3050 TRACE("Enter NtUserEndDeferWindowPosEx\n");
3051 UserEnterExclusive();
3052 Ret = IntEndDeferWindowPosEx(WinPosInfo, (BOOL)Unknown1);
3053 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret);
3054 UserLeave();
3055 return Ret;
3056 }
3057
3058 /*
3059 * @implemented
3060 */
3061 HDWP APIENTRY
3062 NtUserDeferWindowPos(HDWP WinPosInfo,
3063 HWND Wnd,
3064 HWND WndInsertAfter,
3065 int x,
3066 int y,
3067 int cx,
3068 int cy,
3069 UINT Flags)
3070 {
3071 PWND pWnd, pWndIA;
3072 HDWP Ret = NULL;
3073 UINT Tmp = ~(SWP_ASYNCWINDOWPOS|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_NOREPOSITION|
3074 SWP_NOCOPYBITS|SWP_HIDEWINDOW|SWP_SHOWWINDOW|SWP_FRAMECHANGED|
3075 SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE);
3076
3077 TRACE("Enter NtUserDeferWindowPos\n");
3078 UserEnterExclusive();
3079
3080 if ( Flags & Tmp )
3081 {
3082 EngSetLastError(ERROR_INVALID_FLAGS);
3083 goto Exit;
3084 }
3085
3086 pWnd = UserGetWindowObject(Wnd);
3087 if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd))
3088 {
3089 goto Exit;
3090 }
3091
3092 if ( WndInsertAfter &&
3093 WndInsertAfter != HWND_BOTTOM &&
3094 WndInsertAfter != HWND_TOPMOST &&
3095 WndInsertAfter != HWND_NOTOPMOST )
3096 {
3097 pWndIA = UserGetWindowObject(WndInsertAfter);
3098 if (!pWndIA || UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA))
3099 {
3100 goto Exit;
3101 }
3102 }
3103
3104 Ret = IntDeferWindowPos(WinPosInfo, Wnd, WndInsertAfter, x, y, cx, cy, Flags);
3105
3106 Exit:
3107 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret);
3108 UserLeave();
3109 return Ret;
3110 }
3111
3112 /*
3113 * @implemented
3114 */
3115 DWORD APIENTRY
3116 NtUserGetInternalWindowPos( HWND hWnd,
3117 LPRECT rectWnd,
3118 LPPOINT ptIcon)
3119 {
3120 PWND Window;
3121 DWORD Ret = 0;
3122 BOOL Hit = FALSE;
3123 WINDOWPLACEMENT wndpl;
3124
3125 UserEnterShared();
3126
3127 if (!(Window = UserGetWindowObject(hWnd)))
3128 {
3129 Hit = FALSE;
3130 goto Exit;
3131 }
3132
3133 _SEH2_TRY
3134 {
3135 if(rectWnd)
3136 {
3137 ProbeForWrite(rectWnd,
3138 sizeof(RECT),
3139 1);
3140 }
3141 if(ptIcon)
3142 {
3143 ProbeForWrite(ptIcon,
3144 sizeof(POINT),
3145 1);
3146 }
3147
3148 }
3149 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3150 {
3151 SetLastNtError(_SEH2_GetExceptionCode());
3152 Hit = TRUE;
3153 }
3154 _SEH2_END;
3155
3156 wndpl.length = sizeof(WINDOWPLACEMENT);
3157
3158 if (IntGetWindowPlacement(Window, &wndpl) && !Hit)
3159 {
3160 _SEH2_TRY
3161 {
3162 if (rectWnd)
3163 {
3164 RtlCopyMemory(rectWnd, &wndpl.rcNormalPosition , sizeof(RECT));
3165 }
3166 if (ptIcon)
3167 {
3168 RtlCopyMemory(ptIcon, &wndpl.ptMinPosition, sizeof(POINT));
3169 }
3170
3171 }
3172 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3173 {
3174 SetLastNtError(_SEH2_GetExceptionCode());
3175 Hit = TRUE;
3176 }
3177 _SEH2_END;
3178
3179 if (!Hit) Ret = wndpl.showCmd;
3180 }
3181 Exit:
3182 UserLeave();
3183 return Ret;
3184 }
3185
3186 /*
3187 * @implemented
3188 */
3189 BOOL APIENTRY
3190 NtUserGetWindowPlacement(HWND hWnd,
3191 WINDOWPLACEMENT *lpwndpl)
3192 {
3193 PWND Wnd;
3194 WINDOWPLACEMENT Safepl;
3195 NTSTATUS Status;
3196 DECLARE_RETURN(BOOL);
3197
3198 TRACE("Enter NtUserGetWindowPlacement\n");
3199 UserEnterShared();
3200
3201 if (!(Wnd = UserGetWindowObject(hWnd)))
3202 {
3203 RETURN( FALSE);
3204 }
3205
3206 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
3207 if (!NT_SUCCESS(Status))
3208 {
3209 SetLastNtError(Status);
3210 RETURN( FALSE);
3211 }
3212
3213 Safepl.length = sizeof(WINDOWPLACEMENT);
3214
3215 IntGetWindowPlacement(Wnd, &Safepl);
3216
3217 Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT));
3218 if (!NT_SUCCESS(Status))
3219 {
3220 SetLastNtError(Status);
3221 RETURN( FALSE);
3222 }
3223
3224 RETURN( TRUE);
3225
3226 CLEANUP:
3227 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_);
3228 UserLeave();
3229 END_CLEANUP;
3230 }
3231
3232 DWORD
3233 APIENTRY
3234 NtUserMinMaximize(
3235 HWND hWnd,
3236 UINT cmd, // Wine SW_ commands
3237 BOOL Hide)
3238 {
3239 PWND pWnd;
3240
3241 TRACE("Enter NtUserMinMaximize\n");
3242 UserEnterExclusive();
3243
3244 pWnd = UserGetWindowObject(hWnd);
3245 if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd))
3246 {
3247 goto Exit;
3248 }
3249
3250 if ( cmd > SW_MAX || pWnd->state2 & WNDS2_INDESTROY)
3251 {
3252 EngSetLastError(ERROR_INVALID_PARAMETER);
3253 goto Exit;
3254 }
3255
3256 cmd |= Hide ? SW_HIDE : 0;
3257
3258 co_WinPosShowWindow(pWnd, cmd);
3259
3260 Exit:
3261 TRACE("Leave NtUserMinMaximize\n");
3262 UserLeave();
3263 return 0; // Always NULL?
3264 }
3265
3266 /*
3267 * @implemented
3268 */
3269 BOOL APIENTRY
3270 NtUserMoveWindow(
3271 HWND hWnd,
3272 int X,
3273 int Y,
3274 int nWidth,
3275 int nHeight,
3276 BOOL bRepaint)
3277 {
3278 return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight,
3279 (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE :
3280 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW));
3281 }
3282
3283 /*
3284 * @implemented
3285 */
3286 HWND APIENTRY
3287 NtUserRealChildWindowFromPoint(HWND Parent,
3288 LONG x,
3289 LONG y)
3290 {
3291 PWND pwndParent;
3292 TRACE("Enter NtUserRealChildWindowFromPoint\n");
3293 UserEnterShared();
3294 if ((pwndParent = UserGetWindowObject(Parent)))
3295 {
3296 pwndParent = IntRealChildWindowFromPoint(pwndParent, x, y);
3297 }
3298 UserLeave();
3299 TRACE("Leave NtUserRealChildWindowFromPoint\n");
3300 return pwndParent ? UserHMGetHandle(pwndParent) : NULL;
3301 }
3302
3303 /*
3304 * @implemented
3305 */
3306 BOOL APIENTRY
3307 NtUserSetWindowPos(
3308 HWND hWnd,
3309 HWND hWndInsertAfter,
3310 int X,
3311 int Y,
3312 int cx,
3313 int cy,
3314 UINT uFlags)
3315 {
3316 DECLARE_RETURN(BOOL);
3317 PWND Window, pWndIA;
3318 BOOL ret;
3319 USER_REFERENCE_ENTRY Ref;
3320
3321 TRACE("Enter NtUserSetWindowPos\n");
3322 UserEnterExclusive();
3323
3324 if (!(Window = UserGetWindowObject(hWnd)) ||
3325 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
3326 {
3327 ERR("NtUserSetWindowPos bad window handle!\n");
3328 RETURN(FALSE);
3329 }
3330
3331 if ( hWndInsertAfter &&
3332 hWndInsertAfter != HWND_BOTTOM &&
3333 hWndInsertAfter != HWND_TOPMOST &&
3334 hWndInsertAfter != HWND_NOTOPMOST )
3335 {
3336 if (!(pWndIA = UserGetWindowObject(hWndInsertAfter)) ||
3337 UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA))
3338 {
3339 ERR("NtUserSetWindowPos bad insert window handle!\n");
3340 RETURN(FALSE);
3341 }
3342 }
3343
3344 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */
3345 if (!(uFlags & SWP_NOMOVE))
3346 {
3347 if (X < -32768) X = -32768;
3348 else if (X > 32767) X = 32767;
3349 if (Y < -32768) Y = -32768;
3350 else if (Y > 32767) Y = 32767;
3351 }
3352 if (!(uFlags & SWP_NOSIZE))
3353 {
3354 if (cx < 0) cx = 0;
3355 else if (cx > 32767) cx = 32767;
3356 if (cy < 0) cy = 0;
3357 else if (cy > 32767) cy = 32767;
3358 }
3359
3360 UserRefObjectCo(Window, &Ref);
3361 ret = co_WinPosSetWindowPos(Window, hWndInsertAfter, X, Y, cx, cy, uFlags);
3362 UserDerefObjectCo(Window);
3363
3364 RETURN(ret);
3365
3366 CLEANUP:
3367 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_);
3368 UserLeave();
3369 END_CLEANUP;
3370 }
3371
3372 /*
3373 * @implemented
3374 */
3375 INT APIENTRY
3376 NtUserSetWindowRgn(
3377 HWND hWnd,
3378 HRGN hRgn,
3379 BOOL bRedraw)
3380 {
3381 HRGN hrgnCopy = NULL;
3382 PWND Window;
3383 INT flags = (SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE);
3384 BOOLEAN Ret = FALSE;
3385 DECLARE_RETURN(INT);
3386
3387 TRACE("Enter NtUserSetWindowRgn\n");
3388 UserEnterExclusive();
3389
3390 if (!(Window = UserGetWindowObject(hWnd)) ||
3391 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
3392 {
3393 RETURN( 0);
3394 }
3395
3396 if (hRgn) // The region will be deleted in user32.
3397 {
3398 if (GreIsHandleValid(hRgn))
3399 {
3400 hrgnCopy = NtGdiCreateRectRgn(0, 0, 0, 0);
3401 /* The coordinates of a window's window region are relative to the
3402 upper-left corner of the window, not the client area of the window. */
3403 NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY);
3404 }
3405 else
3406 RETURN( 0);
3407 }
3408
3409 //// HACK 1 : Work around the lack of supporting DeferWindowPos.
3410 if (hrgnCopy)
3411 {
3412 Window->hrgnNewFrame = hrgnCopy; // Should be PSMWP->acvr->hrgnClip
3413 }
3414 else
3415 {
3416 Window->hrgnNewFrame = HRGN_WINDOW;
3417 }
3418 //// HACK 2
3419 Ret = co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, bRedraw ? flags : (flags|SWP_NOREDRAW) );
3420
3421 RETURN( (INT)Ret);
3422
3423 CLEANUP:
3424 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_);
3425 UserLeave();
3426 END_CLEANUP;
3427 }
3428
3429 /*
3430 * @implemented
3431 */
3432 DWORD APIENTRY
3433 NtUserSetInternalWindowPos(
3434 HWND hwnd,
3435 UINT showCmd,
3436 LPRECT lprect,
3437 LPPOINT lppt)
3438 {
3439 WINDOWPLACEMENT wndpl;
3440 UINT flags;
3441 PWND Wnd;
3442 RECT rect;
3443 POINT pt = {0};
3444 DECLARE_RETURN(BOOL);
3445 USER_REFERENCE_ENTRY Ref;
3446
3447 TRACE("Enter NtUserSetWindowPlacement\n");
3448 UserEnterExclusive();
3449
3450 if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME:
3451 UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd))
3452 {
3453 RETURN( FALSE);
3454 }
3455
3456 _SEH2_TRY
3457 {
3458 if (lppt)
3459 {
3460 ProbeForRead(lppt, sizeof(POINT), 1);
3461 RtlCopyMemory(&pt, lppt, sizeof(POINT));
3462 }
3463 if (lprect)
3464 {
3465 ProbeForRead(lprect, sizeof(RECT), 1);
3466 RtlCopyMemory(&rect, lprect, sizeof(RECT));
3467 }
3468 }
3469 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3470 {
3471 SetLastNtError(_SEH2_GetExceptionCode());
3472 _SEH2_YIELD(RETURN( FALSE));
3473 }
3474 _SEH2_END
3475
3476 wndpl.length = sizeof(wndpl);
3477 wndpl.showCmd = showCmd;
3478 wndpl.flags = flags = 0;
3479
3480 if ( lppt )
3481 {
3482 flags |= PLACE_MIN;
3483 wndpl.flags |= WPF_SETMINPOSITION;
3484 wndpl.ptMinPosition = pt;
3485 }
3486 if ( lprect )
3487 {
3488 flags |= PLACE_RECT;
3489 wndpl.rcNormalPosition = rect;
3490 }
3491
3492 UserRefObjectCo(Wnd, &Ref);
3493 IntSetWindowPlacement(Wnd, &wndpl, flags);
3494 UserDerefObjectCo(Wnd);
3495 RETURN(TRUE);
3496
3497 CLEANUP:
3498 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
3499 UserLeave();
3500 END_CLEANUP;
3501 }
3502
3503 /*
3504 * @implemented
3505 */
3506 BOOL APIENTRY
3507 NtUserSetWindowPlacement(HWND hWnd,
3508 WINDOWPLACEMENT *lpwndpl)
3509 {
3510 PWND Wnd;
3511 WINDOWPLACEMENT Safepl;
3512 UINT Flags;
3513 DECLARE_RETURN(BOOL);
3514 USER_REFERENCE_ENTRY Ref;
3515
3516 TRACE("Enter NtUserSetWindowPlacement\n");
3517 UserEnterExclusive();
3518
3519 if (!(Wnd = UserGetWindowObject(hWnd)) ||
3520 UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd))
3521 {
3522 RETURN( FALSE);
3523 }
3524
3525 _SEH2_TRY
3526 {
3527 ProbeForRead(lpwndpl, sizeof(WINDOWPLACEMENT), 1);
3528 RtlCopyMemory(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT));
3529 }
3530 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3531 {
3532 SetLastNtError(_SEH2_GetExceptionCode());
3533 _SEH2_YIELD(RETURN( FALSE));
3534 }
3535 _SEH2_END
3536
3537 if(Safepl.length != sizeof(WINDOWPLACEMENT))
3538 {
3539 RETURN( FALSE);
3540 }
3541
3542 Flags = PLACE_MAX | PLACE_RECT;
3543 if (Safepl.flags & WPF_SETMINPOSITION) Flags |= PLACE_MIN;
3544 UserRefObjectCo(Wnd, &Ref);
3545 IntSetWindowPlacement(Wnd, &Safepl, Flags);
3546 UserDerefObjectCo(Wnd);
3547 RETURN(TRUE);
3548
3549 CLEANUP:
3550 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_);
3551 UserLeave();
3552 END_CLEANUP;
3553 }
3554
3555 /*
3556 * @implemented
3557 */
3558 BOOL APIENTRY
3559 NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow)
3560 {
3561 PWND Window;
3562 BOOL ret;
3563 DECLARE_RETURN(BOOL);
3564 USER_REFERENCE_ENTRY Ref;
3565
3566 TRACE("Enter NtUserShowWindowAsync\n");
3567 UserEnterExclusive();
3568
3569 if (!(Window = UserGetWindowObject(hWnd)) ||
3570 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
3571 {
3572 RETURN(FALSE);
3573 }
3574
3575 if ( nCmdShow > SW_MAX )
3576 {
3577 EngSetLastError(ERROR_INVALID_PARAMETER);
3578 RETURN(FALSE);
3579 }
3580
3581 UserRefObjectCo(Window, &Ref);
3582 ret = co_IntSendMessageNoWait( hWnd, WM_ASYNC_SHOWWINDOW, nCmdShow, 0 );
3583 UserDerefObjectCo(Window);
3584 if (-1 == (int) ret || !ret) ret = FALSE;
3585
3586 RETURN(ret);
3587
3588 CLEANUP:
3589 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_);
3590 UserLeave();
3591 END_CLEANUP;
3592 }
3593
3594 /*
3595 * @implemented
3596 */
3597 BOOL APIENTRY
3598 NtUserShowWindow(HWND hWnd, LONG nCmdShow)
3599 {
3600 PWND Window;
3601 BOOL ret;
3602 DECLARE_RETURN(BOOL);
3603 USER_REFERENCE_ENTRY Ref;
3604
3605 TRACE("Enter NtUserShowWindow hWnd %p SW_ %d\n",hWnd, nCmdShow);
3606 UserEnterExclusive();
3607
3608 if (!(Window = UserGetWindowObject(hWnd)) ||
3609 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window))
3610 {
3611 RETURN(FALSE);
3612 }
3613
3614 if ( nCmdShow > SW_MAX || Window->state2 & WNDS2_INDESTROY)
3615 {
3616 EngSetLastError(ERROR_INVALID_PARAMETER);
3617 RETURN(FALSE);
3618 }
3619
3620 UserRefObjectCo(Window, &Ref);
3621 ret = co_WinPosShowWindow(Window, nCmdShow);
3622 UserDerefObjectCo(Window);
3623
3624 RETURN(ret);
3625
3626 CLEANUP:
3627 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_);
3628 UserLeave();
3629 END_CLEANUP;
3630 }
3631
3632
3633 /*
3634 * @implemented
3635 */
3636 HWND APIENTRY
3637 NtUserWindowFromPoint(LONG X, LONG Y)
3638 {
3639 POINT pt;
3640 HWND Ret;
3641 PWND DesktopWindow = NULL, Window = NULL;
3642 USHORT hittest;
3643 DECLARE_RETURN(HWND);
3644 USER_REFERENCE_ENTRY Ref;
3645
3646 TRACE("Enter NtUserWindowFromPoint\n");
3647 UserEnterExclusive();
3648
3649 if ((DesktopWindow = UserGetWindowObject(IntGetDesktopWindow())))
3650 {
3651 //PTHREADINFO pti;
3652
3653 pt.x = X;
3654 pt.y = Y;
3655
3656 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window.
3657 // It is possible this referencing is useless, though it should not hurt...
3658 UserRefObjectCo(DesktopWindow, &Ref);
3659
3660 //pti = PsGetCurrentThreadWin32Thread();
3661 Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest, FALSE);
3662
3663 if (Window)
3664 {
3665 Ret = UserHMGetHandle(Window);
3666
3667 RETURN( Ret);
3668 }
3669 }
3670
3671 RETURN( NULL);
3672
3673 CLEANUP:
3674 if (DesktopWindow) UserDerefObjectCo(DesktopWindow);
3675
3676 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_);
3677 UserLeave();
3678 END_CLEANUP;
3679 }
3680
3681 /* EOF */