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