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