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