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