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->style & WS_CHILD) 1908 { 1909 if ((Window->style & WS_POPUP) && (Window->ExStyle & WS_EX_APPWINDOW)) 1910 { 1911 co_IntShellHookNotify(HSHELL_WINDOWCREATED, (WPARAM)Window->head.h, 0); 1912 if (!(WinPos.flags & SWP_NOACTIVATE)) 1913 UpdateShellHook(Window); 1914 } 1915 } 1916 else if ((Window->ExStyle & WS_EX_APPWINDOW) || 1917 (!(Window->ExStyle & WS_EX_TOOLWINDOW) && !Window->spwndOwner && 1918 (!Window->spwndParent || UserIsDesktopWindow(Window->spwndParent)))) 1919 { 1920 co_IntShellHookNotify(HSHELL_WINDOWCREATED, (WPARAM)Window->head.h, 0); 1921 if (!(WinPos.flags & SWP_NOACTIVATE)) 1922 UpdateShellHook(Window); 1923 } 1924 1925 Window->style |= WS_VISIBLE; //IntSetStyle( Window, WS_VISIBLE, 0 ); 1926 Window->head.pti->cVisWindows++; 1927 IntNotifyWinEvent(EVENT_OBJECT_SHOW, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); 1928 } 1929 1930 if (Window->hrgnUpdate != NULL && Window->hrgnUpdate != HRGN_WINDOW) 1931 { 1932 NtGdiOffsetRgn(Window->hrgnUpdate, 1933 NewWindowRect.left - OldWindowRect.left, 1934 NewWindowRect.top - OldWindowRect.top); 1935 } 1936 1937 DceResetActiveDCEs(Window); // For WS_VISIBLE changes. 1938 1939 // Change or update, set send non-client paint flag. 1940 if ( Window->style & WS_VISIBLE && 1941 (WinPos.flags & SWP_STATECHANGED || (!(Window->state2 & WNDS2_WIN31COMPAT) && WinPos.flags & SWP_NOREDRAW ) ) ) 1942 { 1943 TRACE("Set WNDS_SENDNCPAINT %p\n",Window); 1944 Window->state |= WNDS_SENDNCPAINT; 1945 } 1946 1947 if (!(WinPos.flags & SWP_NOREDRAW)) 1948 { 1949 /* Determine the new visible region */ 1950 VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, 1951 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); 1952 1953 if ( VisAfter != NULL && 1954 REGION_Complexity(VisAfter) == NULLREGION ) 1955 { 1956 REGION_Delete(VisAfter); 1957 VisAfter = NULL; 1958 } 1959 else if(VisAfter) 1960 { 1961 REGION_bOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top); 1962 } 1963 1964 /* 1965 * Determine which pixels can be copied from the old window position 1966 * to the new. Those pixels must be visible in both the old and new 1967 * position. Also, check the class style to see if the windows of this 1968 * class need to be completely repainted on (horizontal/vertical) size 1969 * change. 1970 */ 1971 if ( ( VisBefore != NULL && 1972 VisAfter != NULL && 1973 !(WinPos.flags & SWP_NOCOPYBITS) && 1974 ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) && 1975 !(Window->ExStyle & WS_EX_TRANSPARENT) ) ) 1976 { 1977 1978 /* 1979 * If this is (also) a window resize, the whole nonclient area 1980 * needs to be repainted. So we limit the copy to the client area, 1981 * 'cause there is no use in copying it (would possibly cause 1982 * "flashing" too). However, if the copy region is already empty, 1983 * we don't have to crop (can't take anything away from an empty 1984 * region...) 1985 */ 1986 1987 CopyRgn = IntSysCreateRectpRgn(0, 0, 0, 0); 1988 if ((WinPos.flags & SWP_NOSIZE) && (WinPos.flags & SWP_NOCLIENTSIZE)) 1989 RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND); 1990 else if (VisBeforeJustClient != NULL) 1991 { 1992 RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND); 1993 } 1994 1995 if (VisBeforeJustClient != NULL) 1996 { 1997 REGION_Delete(VisBeforeJustClient); 1998 } 1999 2000 /* Now use in copying bits which are in the update region. */ 2001 if (Window->hrgnUpdate != NULL) 2002 { 2003 PREGION RgnUpdate = REGION_LockRgn(Window->hrgnUpdate); 2004 if (RgnUpdate) 2005 { 2006 REGION_bOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top); 2007 IntGdiCombineRgn(CopyRgn, CopyRgn, RgnUpdate, RGN_DIFF); 2008 REGION_bOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top); 2009 REGION_UnlockRgn(RgnUpdate); 2010 } 2011 } 2012 2013 /* 2014 * Now, get the bounding box of the copy region. If it's empty 2015 * there's nothing to copy. Also, it's no use copying bits onto 2016 * themselves. 2017 */ 2018 if (REGION_GetRgnBox(CopyRgn, &CopyRect) == NULLREGION) 2019 { 2020 /* Nothing to copy, clean up */ 2021 REGION_Delete(CopyRgn); 2022 CopyRgn = NULL; 2023 } 2024 else if ( OldWindowRect.left != NewWindowRect.left || 2025 OldWindowRect.top != NewWindowRect.top || 2026 (WinPos.flags & SWP_FRAMECHANGED) ) 2027 { 2028 HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0); 2029 PREGION DcRgnObj = REGION_LockRgn(DcRgn); 2030 2031 /* 2032 * Small trick here: there is no function to bitblt a region. So 2033 * we set the region as the clipping region, take the bounding box 2034 * of the region and bitblt that. Since nothing outside the clipping 2035 * region is copied, this has the effect of bitblt'ing the region. 2036 * 2037 * Since NtUserGetDCEx takes ownership of the clip region, we need 2038 * to create a copy of CopyRgn and pass that. We need CopyRgn later 2039 */ 2040 IntGdiCombineRgn(DcRgnObj, CopyRgn, NULL, RGN_COPY); 2041 REGION_bOffsetRgn(DcRgnObj, NewWindowRect.left, NewWindowRect.top); 2042 REGION_UnlockRgn(DcRgnObj); 2043 Dc = UserGetDCEx( Window, 2044 DcRgn, 2045 DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN); // DCX_WINDOW will set first, go read WinDC.c. 2046 NtGdiBitBlt( Dc, 2047 CopyRect.left, CopyRect.top, 2048 CopyRect.right - CopyRect.left, 2049 CopyRect.bottom - CopyRect.top, 2050 Dc, 2051 CopyRect.left + (OldWindowRect.left - NewWindowRect.left), 2052 CopyRect.top + (OldWindowRect.top - NewWindowRect.top), 2053 SRCCOPY, 2054 0, 2055 0); 2056 2057 UserReleaseDC(Window, Dc, FALSE); 2058 IntValidateParent(Window, CopyRgn); 2059 GreDeleteObject(DcRgn); 2060 } 2061 } 2062 else 2063 { 2064 CopyRgn = NULL; 2065 } 2066 2067 /* We need to redraw what wasn't visible before or force a redraw */ 2068 if (VisAfter != NULL) 2069 { 2070 PREGION DirtyRgn = IntSysCreateRectpRgn(0, 0, 0, 0); 2071 if (DirtyRgn) 2072 { 2073 if (CopyRgn != NULL) 2074 { 2075 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF); 2076 } 2077 else 2078 { 2079 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY); 2080 } 2081 2082 if (RgnType != ERROR && RgnType != NULLREGION) // Regions moved. 2083 { 2084 /* old code 2085 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top); 2086 IntInvalidateWindows( Window, 2087 DirtyRgn, 2088 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); 2089 } 2090 GreDeleteObject(DirtyRgn); 2091 */ 2092 2093 PWND Parent = Window->spwndParent; 2094 2095 REGION_bOffsetRgn( DirtyRgn, Window->rcWindow.left, Window->rcWindow.top); 2096 2097 if ( (Window->style & WS_CHILD) && (Parent) && !(Parent->style & WS_CLIPCHILDREN)) 2098 { 2099 IntInvalidateWindows( Parent, DirtyRgn, RDW_ERASE | RDW_INVALIDATE); 2100 co_IntPaintWindows(Parent, RDW_NOCHILDREN, FALSE); 2101 } 2102 else 2103 { 2104 IntInvalidateWindows( Window, DirtyRgn, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); 2105 } 2106 } 2107 else if ( RgnType != ERROR && RgnType == NULLREGION ) // Must be the same. See CORE-7166 & CORE-15934, NC HACK fix. 2108 { 2109 if ( !PosChanged && 2110 !(WinPos.flags & SWP_DEFERERASE) && 2111 (WinPos.flags & SWP_FRAMECHANGED) ) 2112 { 2113 PWND pwnd = Window; 2114 PWND Parent = Window->spwndParent; 2115 2116 if ( pwnd->style & WS_CHILD ) // Fix ProgMan menu bar drawing. 2117 { 2118 TRACE("SWP_FRAMECHANGED win child %p Parent %p\n",pwnd,Parent); 2119 pwnd = Parent ? Parent : pwnd; 2120 } 2121 2122 if ( !(pwnd->style & WS_CHILD) ) 2123 { 2124 /* 2125 * Check if we have these specific windows style bits set/reset. 2126 * FIXME: There may be other combinations of styles that need this handling as well. 2127 * This fixes the ReactOS Calculator buttons disappearing in CORE-16827. 2128 */ 2129 if ((Window->style & WS_CLIPSIBLINGS) && !(Window->style & (WS_POPUP | WS_CLIPCHILDREN | WS_SIZEBOX))) 2130 { 2131 IntSendNCPaint(pwnd, HRGN_WINDOW); // Paint the whole frame. 2132 } 2133 else // Use region handling 2134 { 2135 HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0); 2136 PREGION DcRgnObj = REGION_LockRgn(DcRgn); 2137 TRACE("SWP_FRAMECHANGED win %p hRgn %p\n",pwnd, DcRgn); 2138 IntGdiCombineRgn(DcRgnObj, VisBefore, NULL, RGN_COPY); 2139 REGION_UnlockRgn(DcRgnObj); 2140 ForceNCPaintErase(pwnd, DcRgn, DcRgnObj); 2141 GreDeleteObject(DcRgn); 2142 } 2143 } 2144 } 2145 } 2146 REGION_Delete(DirtyRgn); 2147 } 2148 } 2149 2150 if (CopyRgn != NULL) 2151 { 2152 REGION_Delete(CopyRgn); 2153 } 2154 2155 /* Expose what was covered before but not covered anymore */ 2156 if ( VisBefore != NULL ) 2157 { 2158 PREGION ExposedRgn = IntSysCreateRectpRgn(0, 0, 0, 0); 2159 if (ExposedRgn) 2160 { 2161 RgnType = IntGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY); 2162 REGION_bOffsetRgn(ExposedRgn, 2163 OldWindowRect.left - NewWindowRect.left, 2164 OldWindowRect.top - NewWindowRect.top); 2165 2166 if ( VisAfter != NULL ) 2167 RgnType = IntGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF); 2168 2169 if (RgnType != ERROR && RgnType != NULLREGION) 2170 { 2171 co_VIS_WindowLayoutChanged(Window, ExposedRgn); 2172 } 2173 REGION_Delete(ExposedRgn); 2174 } 2175 REGION_Delete(VisBefore); 2176 } 2177 2178 if (VisAfter != NULL) 2179 { 2180 REGION_Delete(VisAfter); 2181 } 2182 } 2183 2184 if (!(WinPos.flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW))) 2185 { 2186 if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD) 2187 { 2188 co_IntSendMessageNoWait(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0); 2189 } 2190 else 2191 { 2192 //ERR("SetWindowPos Set FG Window!\n"); 2193 if ( pti->MessageQueue->spwndActive != Window || 2194 pti->MessageQueue != gpqForeground ) 2195 { 2196 //ERR("WPSWP : set active window\n"); 2197 if (!(Window->state & WNDS_BEINGACTIVATED)) // Inside SAW? 2198 { 2199 co_IntSetForegroundWindow(Window); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow. 2200 } 2201 } 2202 } 2203 } 2204 2205 if ( !PosChanged && 2206 (WinPos.flags & SWP_FRAMECHANGED) && 2207 !(WinPos.flags & SWP_DEFERERASE) && // Prevent sending WM_SYNCPAINT message. 2208 VisAfter ) 2209 { 2210 PWND Parent = Window->spwndParent; 2211 if ( !(Window->style & WS_CHILD) && (Parent) && (Parent->style & WS_CLIPCHILDREN)) 2212 { 2213 TRACE("SWP_FRAMECHANGED Parent %p WS_CLIPCHILDREN %p\n",Parent,Window); 2214 UserSyncAndPaintWindows( Parent, RDW_CLIPCHILDREN); // NC should redraw here, see NC HACK fix. 2215 } 2216 } 2217 2218 // Fix wine msg test_SetFocus, prevents sending WM_WINDOWPOSCHANGED. 2219 if ( VisBefore == NULL && 2220 VisBeforeJustClient == NULL && 2221 !(Window->ExStyle & WS_EX_TOPMOST) && 2222 (WinPos.flags & SWP_AGG_STATUSFLAGS) == (SWP_AGG_NOPOSCHANGE & ~SWP_NOZORDER)) 2223 { 2224 TRACE("No drawing, set no Z order and no redraw!\n"); 2225 WinPos.flags |= SWP_NOZORDER|SWP_NOREDRAW; 2226 } 2227 2228 if(!(flags & SWP_DEFERERASE)) 2229 { 2230 /* erase parent when hiding or resizing child */ 2231 if ((flags & SWP_HIDEWINDOW) || 2232 (!(flags & SWP_SHOWWINDOW) && 2233 (WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOGEOMETRYCHANGE)) 2234 { 2235 PWND Parent = Window->spwndParent; 2236 if (!Parent || UserIsDesktopWindow(Parent)) Parent = Window; 2237 UserSyncAndPaintWindows( Parent, RDW_ERASENOW); 2238 } 2239 2240 /* Give newly shown windows a chance to redraw */ 2241 if(((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) 2242 && !(flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW)) 2243 { 2244 UserSyncAndPaintWindows( Window, RDW_ERASENOW); 2245 } 2246 } 2247 2248 /* And last, send the WM_WINDOWPOSCHANGED message */ 2249 2250 TRACE("\tstatus hwnd %p flags = %04x\n",Window?Window->head.h:NULL,WinPos.flags & SWP_AGG_STATUSFLAGS); 2251 2252 if (((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) 2253 && !((flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW))) 2254 { 2255 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set 2256 and always contains final window position. 2257 */ 2258 WinPos.x = NewWindowRect.left; 2259 WinPos.y = NewWindowRect.top; 2260 WinPos.cx = NewWindowRect.right - NewWindowRect.left; 2261 WinPos.cy = NewWindowRect.bottom - NewWindowRect.top; 2262 TRACE("WM_WINDOWPOSCHANGED hwnd %p Flags %04x\n",WinPos.hwnd,WinPos.flags); 2263 co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos); 2264 } 2265 2266 if ( WinPos.flags & SWP_FRAMECHANGED || WinPos.flags & SWP_STATECHANGED || 2267 !(WinPos.flags & SWP_NOCLIENTSIZE) || !(WinPos.flags & SWP_NOCLIENTMOVE) ) 2268 { 2269 PWND pWnd = ValidateHwndNoErr(WinPos.hwnd); 2270 if (pWnd) 2271 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); 2272 } 2273 2274 if(bPointerInWindow != IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y)) 2275 { 2276 /* Generate mouse move message */ 2277 MSG msg; 2278 msg.message = WM_MOUSEMOVE; 2279 msg.wParam = UserGetMouseButtonsState(); 2280 msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y); 2281 msg.pt = gpsi->ptCursor; 2282 co_MsqInsertMouseMessage(&msg, 0, 0, TRUE); 2283 } 2284 2285 return TRUE; 2286 } 2287 2288 LRESULT FASTCALL 2289 co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect) 2290 { 2291 LRESULT Result; 2292 2293 ASSERT_REFS_CO(Window); 2294 2295 *ClientRect = *WindowRect; 2296 Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect); 2297 2298 FixClientRect(ClientRect, WindowRect); 2299 2300 return Result; 2301 } 2302 2303 void FASTCALL 2304 co_WinPosSendSizeMove(PWND Wnd) 2305 { 2306 RECTL Rect; 2307 LPARAM lParam; 2308 WPARAM wParam = SIZE_RESTORED; 2309 2310 IntGetClientRect(Wnd, &Rect); 2311 lParam = MAKELONG(Rect.right-Rect.left, Rect.bottom-Rect.top); 2312 2313 Wnd->state &= ~WNDS_SENDSIZEMOVEMSGS; 2314 2315 if (Wnd->style & WS_MAXIMIZE) 2316 { 2317 wParam = SIZE_MAXIMIZED; 2318 } 2319 else if (Wnd->style & WS_MINIMIZE) 2320 { 2321 wParam = SIZE_MINIMIZED; 2322 lParam = 0; 2323 } 2324 2325 co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SIZE, wParam, lParam); 2326 2327 if (UserIsDesktopWindow(Wnd->spwndParent)) 2328 lParam = MAKELONG(Wnd->rcClient.left, Wnd->rcClient.top); 2329 else 2330 lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top); 2331 2332 co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_MOVE, 0, lParam); 2333 2334 IntEngWindowChanged(Wnd, WOC_RGN_CLIENT); 2335 } 2336 2337 UINT FASTCALL 2338 co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) 2339 { 2340 POINT Size; 2341 WINDOWPLACEMENT wpl; 2342 LONG old_style; 2343 UINT SwpFlags = 0; 2344 2345 ASSERT_REFS_CO(Wnd); 2346 2347 wpl.length = sizeof(wpl); 2348 IntGetWindowPlacement( Wnd, &wpl ); 2349 2350 if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag)) 2351 { 2352 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n"); 2353 return SWP_NOSIZE | SWP_NOMOVE; 2354 } 2355 if (Wnd->style & WS_MINIMIZE) 2356 { 2357 switch (ShowFlag) 2358 { 2359 case SW_MINIMIZE: 2360 case SW_SHOWMINNOACTIVE: 2361 case SW_SHOWMINIMIZED: 2362 case SW_FORCEMINIMIZE: 2363 return SWP_NOSIZE | SWP_NOMOVE; 2364 } 2365 if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0)) 2366 { 2367 return(SWP_NOSIZE | SWP_NOMOVE); 2368 } 2369 SwpFlags |= SWP_NOCOPYBITS; 2370 } 2371 switch (ShowFlag) 2372 { 2373 case SW_MINIMIZE: 2374 case SW_SHOWMINNOACTIVE: 2375 case SW_SHOWMINIMIZED: 2376 case SW_FORCEMINIMIZE: 2377 { 2378 //ERR("MinMaximize Minimize\n"); 2379 if (Wnd->style & WS_MAXIMIZE) 2380 { 2381 Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED; 2382 } 2383 else 2384 { 2385 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; 2386 } 2387 2388 old_style = IntSetStyle( Wnd, WS_MINIMIZE, WS_MAXIMIZE ); 2389 2390 co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT); 2391 2392 if (!(Wnd->InternalPos.flags & WPF_SETMINPOSITION)) 2393 Wnd->InternalPos.flags &= ~WPF_MININIT; 2394 2395 WinPosFindIconPos(Wnd, &wpl.ptMinPosition); 2396 2397 if (!(old_style & WS_MINIMIZE)) 2398 { 2399 SwpFlags |= SWP_STATECHANGED; 2400 IntShowOwnedPopups(Wnd, FALSE); 2401 } 2402 2403 RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y, 2404 wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED), 2405 wpl.ptMinPosition.y + UserGetSystemMetrics(SM_CYMINIMIZED)); 2406 SwpFlags |= SWP_NOCOPYBITS; 2407 break; 2408 } 2409 2410 case SW_MAXIMIZE: 2411 { 2412 //ERR("MinMaximize Maximize\n"); 2413 if ((Wnd->style & WS_MAXIMIZE) && (Wnd->style & WS_VISIBLE)) 2414 { 2415 SwpFlags = SWP_NOSIZE | SWP_NOMOVE; 2416 break; 2417 } 2418 co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); 2419 2420 /*ERR("Maximize: %d,%d %dx%d\n", 2421 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y); 2422 */ 2423 old_style = IntSetStyle( Wnd, WS_MAXIMIZE, WS_MINIMIZE ); 2424 /*if (old_style & WS_MINIMIZE) 2425 { 2426 IntShowOwnedPopups(Wnd, TRUE); 2427 }*/ 2428 2429 if (!(old_style & WS_MAXIMIZE)) SwpFlags |= SWP_STATECHANGED; 2430 RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, 2431 //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y); 2432 Size.x, Size.y); 2433 break; 2434 } 2435 2436 case SW_SHOWNOACTIVATE: 2437 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; 2438 /* fall through */ 2439 case SW_SHOWNORMAL: 2440 case SW_RESTORE: 2441 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */ 2442 { 2443 //ERR("MinMaximize Restore\n"); 2444 old_style = IntSetStyle( Wnd, 0, WS_MINIMIZE | WS_MAXIMIZE ); 2445 if (old_style & WS_MINIMIZE) 2446 { 2447 IntShowOwnedPopups(Wnd, TRUE); 2448 2449 if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED) 2450 { 2451 co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); 2452 IntSetStyle( Wnd, WS_MAXIMIZE, 0 ); 2453 SwpFlags |= SWP_STATECHANGED; 2454 RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, 2455 wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y); 2456 break; 2457 } 2458 else 2459 { 2460 *NewPos = wpl.rcNormalPosition; 2461 NewPos->right -= NewPos->left; 2462 NewPos->bottom -= NewPos->top; 2463 break; 2464 } 2465 } 2466 else 2467 { 2468 if (!(old_style & WS_MAXIMIZE)) 2469 { 2470 break; 2471 } 2472 SwpFlags |= SWP_STATECHANGED; 2473 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; 2474 *NewPos = wpl.rcNormalPosition; 2475 NewPos->right -= NewPos->left; 2476 NewPos->bottom -= NewPos->top; 2477 break; 2478 } 2479 } 2480 } 2481 return SwpFlags; 2482 } 2483 2484 /* 2485 ShowWindow does not set SWP_FRAMECHANGED!!! Fix wine msg test_SetParent:WmSetParentSeq_2:23 wParam bits! 2486 */ 2487 BOOLEAN FASTCALL 2488 co_WinPosShowWindow(PWND Wnd, INT Cmd) 2489 { 2490 BOOLEAN WasVisible; 2491 UINT Swp = 0, EventMsg = 0; 2492 RECTL NewPos = {0, 0, 0, 0}; 2493 BOOLEAN ShowFlag; 2494 LONG style; 2495 PWND Parent; 2496 PTHREADINFO pti; 2497 //HRGN VisibleRgn; 2498 BOOL ShowOwned = FALSE; 2499 BOOL FirstTime = FALSE; 2500 ASSERT_REFS_CO(Wnd); 2501 //KeRosDumpStackFrames(NULL, 20); 2502 pti = PsGetCurrentThreadWin32Thread(); 2503 WasVisible = (Wnd->style & WS_VISIBLE) != 0; 2504 style = Wnd->style; 2505 2506 TRACE("co_WinPosShowWindow START hwnd %p Cmd %d usicmd %u\n", 2507 Wnd->head.h, Cmd, pti->ppi->usi.wShowWindow); 2508 2509 if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW ) 2510 { 2511 if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) 2512 { 2513 if ((Wnd->style & WS_CAPTION) == WS_CAPTION) 2514 { 2515 if (Wnd->spwndOwner == NULL) 2516 { 2517 if ( Cmd == SW_SHOWNORMAL || Cmd == SW_SHOW) 2518 { 2519 Cmd = SW_SHOWDEFAULT; 2520 } 2521 FirstTime = TRUE; 2522 TRACE("co_WPSW FT 1\n"); 2523 } 2524 } 2525 } 2526 } 2527 2528 if ( Cmd == SW_SHOWDEFAULT ) 2529 { 2530 if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW ) 2531 { 2532 Cmd = pti->ppi->usi.wShowWindow; 2533 FirstTime = TRUE; 2534 TRACE("co_WPSW FT 2\n"); 2535 } 2536 } 2537 2538 if (FirstTime) 2539 { 2540 pti->ppi->usi.dwFlags &= ~(STARTF_USEPOSITION|STARTF_USESIZE|STARTF_USESHOWWINDOW); 2541 } 2542 2543 switch (Cmd) 2544 { 2545 case SW_HIDE: 2546 { 2547 if (!WasVisible) 2548 { 2549 //ERR("co_WinPosShowWindow Exit Bad\n"); 2550 return FALSE; 2551 } 2552 Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE; 2553 if (Wnd != pti->MessageQueue->spwndActive) 2554 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2555 break; 2556 } 2557 2558 case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */ 2559 case SW_SHOWMINNOACTIVE: 2560 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2561 /* Fall through. */ 2562 case SW_SHOWMINIMIZED: 2563 case SW_MINIMIZE: /* CORE-15669: SW_MINIMIZE also shows */ 2564 Swp |= SWP_SHOWWINDOW; 2565 { 2566 Swp |= SWP_NOACTIVATE; 2567 if (!(style & WS_MINIMIZE)) 2568 { 2569 IntShowOwnedPopups(Wnd, FALSE ); 2570 // Fix wine Win test_SetFocus todo #1 & #2, 2571 if (Cmd == SW_SHOWMINIMIZED) 2572 { 2573 //ERR("co_WinPosShowWindow Set focus 1\n"); 2574 if ((style & (WS_CHILD | WS_POPUP)) == WS_CHILD) 2575 co_UserSetFocus(Wnd->spwndParent); 2576 else 2577 co_UserSetFocus(0); 2578 } 2579 2580 Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos); 2581 2582 EventMsg = EVENT_SYSTEM_MINIMIZESTART; 2583 } 2584 else 2585 { 2586 if (WasVisible) 2587 { 2588 //ERR("co_WinPosShowWindow Exit Good\n"); 2589 return TRUE; 2590 } 2591 Swp |= SWP_NOSIZE | SWP_NOMOVE; 2592 } 2593 break; 2594 } 2595 2596 case SW_SHOWMAXIMIZED: 2597 { 2598 Swp |= SWP_SHOWWINDOW; 2599 if (!(style & WS_MAXIMIZE)) 2600 { 2601 ShowOwned = TRUE; 2602 2603 Swp |= co_WinPosMinMaximize(Wnd, SW_MAXIMIZE, &NewPos); 2604 2605 EventMsg = EVENT_SYSTEM_MINIMIZEEND; 2606 } 2607 else 2608 { 2609 if (WasVisible) 2610 { 2611 //ERR("co_WinPosShowWindow Exit Good 1\n"); 2612 return TRUE; 2613 } 2614 Swp |= SWP_NOSIZE | SWP_NOMOVE; 2615 } 2616 break; 2617 } 2618 2619 case SW_SHOWNA: 2620 Swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; 2621 if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOZORDER; 2622 break; 2623 case SW_SHOW: 2624 if (WasVisible) return(TRUE); // Nothing to do! 2625 Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; 2626 /* Don't activate the topmost window. */ 2627 if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2628 break; 2629 2630 case SW_SHOWNOACTIVATE: 2631 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2632 /* Fall through. */ 2633 case SW_SHOWNORMAL: 2634 case SW_SHOWDEFAULT: 2635 case SW_RESTORE: 2636 if (!WasVisible) Swp |= SWP_SHOWWINDOW; 2637 if (style & (WS_MINIMIZE | WS_MAXIMIZE)) 2638 { 2639 Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos); 2640 if (style & WS_MINIMIZE) EventMsg = EVENT_SYSTEM_MINIMIZEEND; 2641 } 2642 else 2643 { 2644 if (WasVisible) 2645 { 2646 //ERR("co_WinPosShowWindow Exit Good 3\n"); 2647 return TRUE; 2648 } 2649 Swp |= SWP_NOSIZE | SWP_NOMOVE; 2650 } 2651 if ( style & WS_CHILD && 2652 !(Wnd->ExStyle & WS_EX_MDICHILD) && 2653 !(Swp & SWP_STATECHANGED)) 2654 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2655 break; 2656 2657 default: 2658 //ERR("co_WinPosShowWindow Exit Good 4\n"); 2659 return FALSE; 2660 } 2661 2662 ShowFlag = (Cmd != SW_HIDE); 2663 2664 if ((ShowFlag != WasVisible || Cmd == SW_SHOWNA) && Cmd != SW_SHOWMAXIMIZED && !(Swp & SWP_STATECHANGED)) 2665 { 2666 co_IntSendMessageNoWait(Wnd->head.h, WM_SHOWWINDOW, ShowFlag, 0); 2667 #if 0 // Fix wine msg test_SetParent:WmSetParentSeq_1:2 2668 if (!(Wnd->state2 & WNDS2_WIN31COMPAT)) // <------------- XP sets this bit! 2669 co_IntSendMessageNoWait(Wnd->head.h, WM_SETVISIBLE, ShowFlag, 0); 2670 #endif 2671 if (!VerifyWnd(Wnd)) return WasVisible; 2672 } 2673 2674 /* We can't activate a child window */ 2675 if ((Wnd->style & WS_CHILD) && 2676 !(Wnd->ExStyle & WS_EX_MDICHILD) && 2677 Cmd != SW_SHOWNA) 2678 { 2679 //ERR("SWP Child No active and ZOrder\n"); 2680 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2681 } 2682 2683 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works. 2684 // Breaks startup and shutdown active window... 2685 if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD && 2686 Wnd->pcls->style & CS_SAVEBITS && 2687 ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL))) 2688 { 2689 ERR("WinPosShowWindow Set active\n"); 2690 //UserSetActiveWindow(Wnd); 2691 co_IntSetForegroundWindow(Wnd); // HACK 2692 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2693 } 2694 #endif 2695 2696 if (IsChildVisible(Wnd) || Swp & SWP_STATECHANGED) 2697 { 2698 TRACE("Child is Vis %s or State changed %s. ShowFlag %s Swp %04x\n", 2699 (IsChildVisible(Wnd) ? "TRUE" : "FALSE"), (Swp & SWP_STATECHANGED ? "TRUE" : "FALSE"), 2700 (ShowFlag ? "TRUE" : "FALSE"),LOWORD(Swp)); 2701 co_WinPosSetWindowPos( Wnd, 2702 0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP, 2703 NewPos.left, 2704 NewPos.top, 2705 NewPos.right, // NewPos.right - NewPos.left, when minimized and restore, the window becomes smaller. 2706 NewPos.bottom,// NewPos.bottom - NewPos.top, 2707 LOWORD(Swp)); 2708 } 2709 else 2710 { 2711 TRACE("Parent Vis?\n"); 2712 /* if parent is not visible simply toggle WS_VISIBLE and return */ 2713 if (ShowFlag) IntSetStyle( Wnd, WS_VISIBLE, 0 ); 2714 else IntSetStyle( Wnd, 0, WS_VISIBLE ); 2715 } 2716 2717 if ( EventMsg ) IntNotifyWinEvent(EventMsg, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); 2718 2719 if ( ShowOwned ) IntShowOwnedPopups(Wnd, TRUE ); 2720 2721 if ((Cmd == SW_HIDE) || (Cmd == SW_MINIMIZE)) 2722 { 2723 if ( Wnd == pti->MessageQueue->spwndActive && pti->MessageQueue == IntGetFocusMessageQueue() ) 2724 { 2725 if (UserIsDesktopWindow(Wnd->spwndParent)) 2726 { 2727 if (!ActivateOtherWindowMin(Wnd)) 2728 { 2729 co_WinPosActivateOtherWindow(Wnd); 2730 } 2731 } 2732 else 2733 { 2734 co_WinPosActivateOtherWindow(Wnd); 2735 } 2736 } 2737 2738 /* Revert focus to parent */ 2739 if (Wnd == pti->MessageQueue->spwndFocus) 2740 { 2741 Parent = Wnd->spwndParent; 2742 if (UserIsDesktopWindow(Wnd->spwndParent)) 2743 Parent = 0; 2744 co_UserSetFocus(Parent); 2745 } 2746 // Hide, just return. 2747 if (Cmd == SW_HIDE) return WasVisible; 2748 } 2749 2750 /* FIXME: Check for window destruction. */ 2751 2752 if ((Wnd->state & WNDS_SENDSIZEMOVEMSGS) && 2753 !(Wnd->state2 & WNDS2_INDESTROY)) 2754 { 2755 co_WinPosSendSizeMove(Wnd); 2756 } 2757 2758 /* if previous state was minimized Windows sets focus to the window */ 2759 if (style & WS_MINIMIZE) 2760 { 2761 co_UserSetFocus(Wnd); 2762 // Fix wine Win test_SetFocus todo #3, 2763 if (!(style & WS_CHILD)) co_IntSendMessage(UserHMGetHandle(Wnd), WM_ACTIVATE, WA_ACTIVE, 0); 2764 } 2765 //ERR("co_WinPosShowWindow EXIT\n"); 2766 return WasVisible; 2767 } 2768 2769 static PWND 2770 co_WinPosSearchChildren( 2771 IN PWND ScopeWin, 2772 IN POINT *Point, 2773 IN OUT USHORT *HitTest, 2774 IN BOOL Ignore 2775 ) 2776 { 2777 HWND *List, *phWnd; 2778 PWND pwndChild = NULL; 2779 2780 /* not visible */ 2781 if (!(ScopeWin->style & WS_VISIBLE)) 2782 { 2783 return NULL; 2784 } 2785 2786 /* not in window or in window region */ 2787 if (!IntPtInWindow(ScopeWin, Point->x, Point->y)) 2788 { 2789 return NULL; 2790 } 2791 2792 /* transparent */ 2793 if ((ScopeWin->ExStyle & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == (WS_EX_LAYERED|WS_EX_TRANSPARENT)) 2794 { 2795 return NULL; 2796 } 2797 2798 if (!Ignore && (ScopeWin->style & WS_DISABLED)) 2799 { /* disabled child */ 2800 if ((ScopeWin->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return NULL; 2801 /* process the hit error */ 2802 *HitTest = HTERROR; 2803 return ScopeWin; 2804 } 2805 2806 /* not minimized and check if point is inside the window */ 2807 if (!(ScopeWin->style & WS_MINIMIZE) && 2808 RECTL_bPointInRect(&ScopeWin->rcClient, Point->x, Point->y) ) 2809 { 2810 UserReferenceObject(ScopeWin); 2811 2812 List = IntWinListChildren(ScopeWin); 2813 if (List) 2814 { 2815 for (phWnd = List; *phWnd; ++phWnd) 2816 { 2817 if (!(pwndChild = ValidateHwndNoErr(*phWnd))) 2818 { 2819 continue; 2820 } 2821 2822 pwndChild = co_WinPosSearchChildren(pwndChild, Point, HitTest, Ignore); 2823 2824 if (pwndChild != NULL) 2825 { 2826 /* We found a window. Don't send any more WM_NCHITTEST messages */ 2827 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2828 UserDereferenceObject(ScopeWin); 2829 return pwndChild; 2830 } 2831 } 2832 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2833 } 2834 UserDereferenceObject(ScopeWin); 2835 } 2836 2837 if (ScopeWin->head.pti == PsGetCurrentThreadWin32Thread()) 2838 { 2839 *HitTest = (USHORT)co_IntSendMessage(ScopeWin->head.h, WM_NCHITTEST, 0, MAKELONG(Point->x, Point->y)); 2840 2841 if ((*HitTest) == (USHORT)HTTRANSPARENT) 2842 { 2843 return NULL; 2844 } 2845 } 2846 else 2847 { 2848 if (*HitTest == HTNOWHERE && pwndChild == NULL) *HitTest = HTCLIENT; 2849 } 2850 2851 return ScopeWin; 2852 } 2853 2854 PWND APIENTRY 2855 co_WinPosWindowFromPoint( 2856 IN PWND ScopeWin, 2857 IN POINT *WinPoint, 2858 IN OUT USHORT* HitTest, 2859 IN BOOL Ignore) 2860 { 2861 PWND Window; 2862 POINT Point = *WinPoint; 2863 USER_REFERENCE_ENTRY Ref; 2864 2865 if( ScopeWin == NULL ) 2866 { 2867 ScopeWin = UserGetDesktopWindow(); 2868 if(ScopeWin == NULL) 2869 return NULL; 2870 } 2871 2872 *HitTest = HTNOWHERE; 2873 2874 ASSERT_REFS_CO(ScopeWin); 2875 UserRefObjectCo(ScopeWin, &Ref); 2876 2877 Window = co_WinPosSearchChildren(ScopeWin, &Point, HitTest, Ignore); 2878 2879 UserDerefObjectCo(ScopeWin); 2880 if (Window) 2881 ASSERT_REFS_CO(Window); 2882 ASSERT_REFS_CO(ScopeWin); 2883 2884 return Window; 2885 } 2886 2887 PWND FASTCALL 2888 IntRealChildWindowFromPoint(PWND Parent, LONG x, LONG y) 2889 { 2890 POINTL Pt; 2891 HWND *List, *phWnd; 2892 PWND pwndHit = NULL; 2893 2894 Pt.x = x; 2895 Pt.y = y; 2896 2897 if (!UserIsDesktopWindow(Parent)) 2898 { 2899 Pt.x += Parent->rcClient.left; 2900 Pt.y += Parent->rcClient.top; 2901 } 2902 2903 if (!IntPtInWindow(Parent, Pt.x, Pt.y)) return NULL; 2904 2905 if ((List = IntWinListChildren(Parent))) 2906 { 2907 for (phWnd = List; *phWnd; phWnd++) 2908 { 2909 PWND Child; 2910 if ((Child = ValidateHwndNoErr(*phWnd))) 2911 { 2912 if ( Child->style & WS_VISIBLE && IntPtInWindow(Child, Pt.x, Pt.y) ) 2913 { 2914 if ( Child->pcls->atomClassName != gpsi->atomSysClass[ICLS_BUTTON] || 2915 (Child->style & BS_TYPEMASK) != BS_GROUPBOX ) 2916 { 2917 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2918 return Child; 2919 } 2920 pwndHit = Child; 2921 } 2922 } 2923 } 2924 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2925 } 2926 return pwndHit ? pwndHit : Parent; 2927 } 2928 2929 PWND APIENTRY 2930 IntChildWindowFromPointEx(PWND Parent, LONG x, LONG y, UINT uiFlags) 2931 { 2932 POINTL Pt; 2933 HWND *List, *phWnd; 2934 PWND pwndHit = NULL; 2935 2936 Pt.x = x; 2937 Pt.y = y; 2938 2939 if (!UserIsDesktopWindow(Parent)) 2940 { 2941 if (Parent->ExStyle & WS_EX_LAYOUTRTL) 2942 Pt.x = Parent->rcClient.right - Pt.x; 2943 else 2944 Pt.x += Parent->rcClient.left; 2945 Pt.y += Parent->rcClient.top; 2946 } 2947 2948 if (!IntPtInWindow(Parent, Pt.x, Pt.y)) return NULL; 2949 2950 if ((List = IntWinListChildren(Parent))) 2951 { 2952 for (phWnd = List; *phWnd; phWnd++) 2953 { 2954 PWND Child; 2955 if ((Child = ValidateHwndNoErr(*phWnd))) 2956 { 2957 if (uiFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED)) 2958 { 2959 if (!(Child->style & WS_VISIBLE) && (uiFlags & CWP_SKIPINVISIBLE)) continue; 2960 if ((Child->style & WS_DISABLED) && (uiFlags & CWP_SKIPDISABLED)) continue; 2961 } 2962 2963 if (uiFlags & CWP_SKIPTRANSPARENT) 2964 { 2965 if (Child->ExStyle & WS_EX_TRANSPARENT) continue; 2966 } 2967 2968 if (IntPtInWindow(Child, Pt.x, Pt.y)) 2969 { 2970 pwndHit = Child; 2971 break; 2972 } 2973 } 2974 } 2975 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2976 } 2977 return pwndHit ? pwndHit : Parent; 2978 } 2979 2980 HDWP 2981 FASTCALL 2982 IntDeferWindowPos( HDWP hdwp, 2983 HWND hwnd, 2984 HWND hwndAfter, 2985 INT x, 2986 INT y, 2987 INT cx, 2988 INT cy, 2989 UINT flags ) 2990 { 2991 PSMWP pDWP; 2992 int i; 2993 HDWP retvalue = hdwp; 2994 2995 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n", 2996 hdwp, hwnd, hwndAfter, x, y, cx, cy, flags); 2997 2998 if (flags & ~(SWP_NOSIZE | SWP_NOMOVE | 2999 SWP_NOZORDER | SWP_NOREDRAW | 3000 SWP_NOACTIVATE | SWP_NOCOPYBITS | 3001 SWP_NOOWNERZORDER|SWP_SHOWWINDOW | 3002 SWP_HIDEWINDOW | SWP_FRAMECHANGED)) 3003 { 3004 EngSetLastError(ERROR_INVALID_PARAMETER); 3005 return NULL; 3006 } 3007 3008 if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, TYPE_SETWINDOWPOS))) 3009 { 3010 EngSetLastError(ERROR_INVALID_DWP_HANDLE); 3011 return NULL; 3012 } 3013 3014 for (i = 0; i < pDWP->ccvr; i++) 3015 { 3016 if (pDWP->acvr[i].pos.hwnd == hwnd) 3017 { 3018 /* Merge with the other changes */ 3019 if (!(flags & SWP_NOZORDER)) 3020 { 3021 pDWP->acvr[i].pos.hwndInsertAfter = hwndAfter; 3022 } 3023 if (!(flags & SWP_NOMOVE)) 3024 { 3025 pDWP->acvr[i].pos.x = x; 3026 pDWP->acvr[i].pos.y = y; 3027 } 3028 if (!(flags & SWP_NOSIZE)) 3029 { 3030 pDWP->acvr[i].pos.cx = cx; 3031 pDWP->acvr[i].pos.cy = cy; 3032 } 3033 pDWP->acvr[i].pos.flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE | 3034 SWP_NOZORDER | SWP_NOREDRAW | 3035 SWP_NOACTIVATE | SWP_NOCOPYBITS| 3036 SWP_NOOWNERZORDER); 3037 pDWP->acvr[i].pos.flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | 3038 SWP_FRAMECHANGED); 3039 goto END; 3040 } 3041 } 3042 if (pDWP->ccvr >= pDWP->ccvrAlloc) 3043 { 3044 PCVR newpos = ExAllocatePoolWithTag(PagedPool, pDWP->ccvrAlloc * 2 * sizeof(CVR), USERTAG_SWP); 3045 if (!newpos) 3046 { 3047 retvalue = NULL; 3048 goto END; 3049 } 3050 RtlZeroMemory(newpos, pDWP->ccvrAlloc * 2 * sizeof(CVR)); 3051 RtlCopyMemory(newpos, pDWP->acvr, pDWP->ccvrAlloc * sizeof(CVR)); 3052 ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP); 3053 pDWP->ccvrAlloc *= 2; 3054 pDWP->acvr = newpos; 3055 } 3056 pDWP->acvr[pDWP->ccvr].pos.hwnd = hwnd; 3057 pDWP->acvr[pDWP->ccvr].pos.hwndInsertAfter = hwndAfter; 3058 pDWP->acvr[pDWP->ccvr].pos.x = x; 3059 pDWP->acvr[pDWP->ccvr].pos.y = y; 3060 pDWP->acvr[pDWP->ccvr].pos.cx = cx; 3061 pDWP->acvr[pDWP->ccvr].pos.cy = cy; 3062 pDWP->acvr[pDWP->ccvr].pos.flags = flags; 3063 pDWP->acvr[pDWP->ccvr].hrgnClip = NULL; 3064 pDWP->acvr[pDWP->ccvr].hrgnInterMonitor = NULL; 3065 pDWP->ccvr++; 3066 END: 3067 return retvalue; 3068 } 3069 3070 BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp, BOOL sAsync ) 3071 { 3072 PSMWP pDWP; 3073 PCVR winpos; 3074 BOOL res = TRUE; 3075 int i; 3076 3077 TRACE("%p\n", hdwp); 3078 3079 if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, TYPE_SETWINDOWPOS))) 3080 { 3081 EngSetLastError(ERROR_INVALID_DWP_HANDLE); 3082 return FALSE; 3083 } 3084 3085 for (i = 0, winpos = pDWP->acvr; res && i < pDWP->ccvr; i++, winpos++) 3086 { 3087 PWND pwnd; 3088 USER_REFERENCE_ENTRY Ref; 3089 3090 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n", 3091 winpos->pos.hwnd, winpos->pos.hwndInsertAfter, winpos->pos.x, winpos->pos.y, 3092 winpos->pos.cx, winpos->pos.cy, winpos->pos.flags); 3093 3094 pwnd = ValidateHwndNoErr(winpos->pos.hwnd); 3095 if (!pwnd) 3096 continue; 3097 3098 UserRefObjectCo(pwnd, &Ref); 3099 3100 if ( sAsync ) 3101 { 3102 LRESULT lRes; 3103 PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP); 3104 if ( ppos ) 3105 { 3106 *ppos = winpos->pos; 3107 /* Yes it's a pointer inside Win32k! */ 3108 lRes = co_IntSendMessageNoWait( winpos->pos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos); 3109 /* We handle this the same way as Event Hooks and Hooks. */ 3110 if ( !lRes ) 3111 { 3112 ExFreePoolWithTag(ppos, USERTAG_SWP); 3113 } 3114 } 3115 } 3116 else 3117 res = co_WinPosSetWindowPos( pwnd, 3118 winpos->pos.hwndInsertAfter, 3119 winpos->pos.x, 3120 winpos->pos.y, 3121 winpos->pos.cx, 3122 winpos->pos.cy, 3123 winpos->pos.flags); 3124 3125 // Hack to pass tests.... Must have some work to do so clear the error. 3126 if (res && (winpos->pos.flags & (SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER)) == SWP_NOZORDER ) 3127 EngSetLastError(ERROR_SUCCESS); 3128 3129 UserDerefObjectCo(pwnd); 3130 } 3131 ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP); 3132 UserDereferenceObject(pDWP); 3133 UserDeleteObject(hdwp, TYPE_SETWINDOWPOS); 3134 return res; 3135 } 3136 3137 /* 3138 * @implemented 3139 */ 3140 HWND APIENTRY 3141 NtUserChildWindowFromPointEx(HWND hwndParent, 3142 LONG x, 3143 LONG y, 3144 UINT uiFlags) 3145 { 3146 PWND pwndParent; 3147 TRACE("Enter NtUserChildWindowFromPointEx\n"); 3148 UserEnterExclusive(); 3149 if ((pwndParent = UserGetWindowObject(hwndParent))) 3150 { 3151 pwndParent = IntChildWindowFromPointEx(pwndParent, x, y, uiFlags); 3152 } 3153 UserLeave(); 3154 TRACE("Leave NtUserChildWindowFromPointEx\n"); 3155 return pwndParent ? UserHMGetHandle(pwndParent) : NULL; 3156 } 3157 3158 /* 3159 * @implemented 3160 */ 3161 BOOL APIENTRY 3162 NtUserEndDeferWindowPosEx(HDWP WinPosInfo, 3163 DWORD Unknown1) 3164 { 3165 BOOL Ret; 3166 TRACE("Enter NtUserEndDeferWindowPosEx\n"); 3167 UserEnterExclusive(); 3168 Ret = IntEndDeferWindowPosEx(WinPosInfo, (BOOL)Unknown1); 3169 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret); 3170 UserLeave(); 3171 return Ret; 3172 } 3173 3174 /* 3175 * @implemented 3176 */ 3177 HDWP APIENTRY 3178 NtUserDeferWindowPos(HDWP WinPosInfo, 3179 HWND Wnd, 3180 HWND WndInsertAfter, 3181 int x, 3182 int y, 3183 int cx, 3184 int cy, 3185 UINT Flags) 3186 { 3187 PWND pWnd, pWndIA; 3188 HDWP Ret = NULL; 3189 UINT Tmp = ~(SWP_ASYNCWINDOWPOS|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_NOREPOSITION| 3190 SWP_NOCOPYBITS|SWP_HIDEWINDOW|SWP_SHOWWINDOW|SWP_FRAMECHANGED| 3191 SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE); 3192 3193 TRACE("Enter NtUserDeferWindowPos\n"); 3194 UserEnterExclusive(); 3195 3196 if ( Flags & Tmp ) 3197 { 3198 EngSetLastError(ERROR_INVALID_FLAGS); 3199 goto Exit; 3200 } 3201 3202 pWnd = UserGetWindowObject(Wnd); 3203 if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd)) 3204 { 3205 goto Exit; 3206 } 3207 3208 if ( WndInsertAfter && 3209 WndInsertAfter != HWND_BOTTOM && 3210 WndInsertAfter != HWND_TOPMOST && 3211 WndInsertAfter != HWND_NOTOPMOST ) 3212 { 3213 pWndIA = UserGetWindowObject(WndInsertAfter); 3214 if (!pWndIA || UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA)) 3215 { 3216 goto Exit; 3217 } 3218 } 3219 3220 Ret = IntDeferWindowPos(WinPosInfo, Wnd, WndInsertAfter, x, y, cx, cy, Flags); 3221 3222 Exit: 3223 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret); 3224 UserLeave(); 3225 return Ret; 3226 } 3227 3228 /* 3229 * @implemented 3230 */ 3231 DWORD APIENTRY 3232 NtUserGetInternalWindowPos( HWND hWnd, 3233 LPRECT rectWnd, 3234 LPPOINT ptIcon) 3235 { 3236 PWND Window; 3237 DWORD Ret = 0; 3238 BOOL Hit = FALSE; 3239 WINDOWPLACEMENT wndpl; 3240 3241 UserEnterShared(); 3242 3243 if (!(Window = UserGetWindowObject(hWnd))) 3244 { 3245 Hit = FALSE; 3246 goto Exit; 3247 } 3248 3249 _SEH2_TRY 3250 { 3251 if(rectWnd) 3252 { 3253 ProbeForWrite(rectWnd, 3254 sizeof(RECT), 3255 1); 3256 } 3257 if(ptIcon) 3258 { 3259 ProbeForWrite(ptIcon, 3260 sizeof(POINT), 3261 1); 3262 } 3263 3264 } 3265 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3266 { 3267 SetLastNtError(_SEH2_GetExceptionCode()); 3268 Hit = TRUE; 3269 } 3270 _SEH2_END; 3271 3272 wndpl.length = sizeof(WINDOWPLACEMENT); 3273 3274 if (IntGetWindowPlacement(Window, &wndpl) && !Hit) 3275 { 3276 _SEH2_TRY 3277 { 3278 if (rectWnd) 3279 { 3280 RtlCopyMemory(rectWnd, &wndpl.rcNormalPosition , sizeof(RECT)); 3281 } 3282 if (ptIcon) 3283 { 3284 RtlCopyMemory(ptIcon, &wndpl.ptMinPosition, sizeof(POINT)); 3285 } 3286 3287 } 3288 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3289 { 3290 SetLastNtError(_SEH2_GetExceptionCode()); 3291 Hit = TRUE; 3292 } 3293 _SEH2_END; 3294 3295 if (!Hit) Ret = wndpl.showCmd; 3296 } 3297 Exit: 3298 UserLeave(); 3299 return Ret; 3300 } 3301 3302 /* 3303 * @implemented 3304 */ 3305 BOOL APIENTRY 3306 NtUserGetWindowPlacement(HWND hWnd, 3307 WINDOWPLACEMENT *lpwndpl) 3308 { 3309 PWND Wnd; 3310 WINDOWPLACEMENT Safepl; 3311 NTSTATUS Status; 3312 DECLARE_RETURN(BOOL); 3313 3314 TRACE("Enter NtUserGetWindowPlacement\n"); 3315 UserEnterShared(); 3316 3317 if (!(Wnd = UserGetWindowObject(hWnd))) 3318 { 3319 RETURN( FALSE); 3320 } 3321 3322 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT)); 3323 if (!NT_SUCCESS(Status)) 3324 { 3325 SetLastNtError(Status); 3326 RETURN( FALSE); 3327 } 3328 3329 Safepl.length = sizeof(WINDOWPLACEMENT); 3330 3331 IntGetWindowPlacement(Wnd, &Safepl); 3332 3333 Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT)); 3334 if (!NT_SUCCESS(Status)) 3335 { 3336 SetLastNtError(Status); 3337 RETURN( FALSE); 3338 } 3339 3340 RETURN( TRUE); 3341 3342 CLEANUP: 3343 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_); 3344 UserLeave(); 3345 END_CLEANUP; 3346 } 3347 3348 DWORD 3349 APIENTRY 3350 NtUserMinMaximize( 3351 HWND hWnd, 3352 UINT cmd, // Wine SW_ commands 3353 BOOL Hide) 3354 { 3355 PWND pWnd; 3356 3357 TRACE("Enter NtUserMinMaximize\n"); 3358 UserEnterExclusive(); 3359 3360 pWnd = UserGetWindowObject(hWnd); 3361 if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd)) 3362 { 3363 goto Exit; 3364 } 3365 3366 if ( cmd > SW_MAX || pWnd->state2 & WNDS2_INDESTROY) 3367 { 3368 EngSetLastError(ERROR_INVALID_PARAMETER); 3369 goto Exit; 3370 } 3371 3372 cmd |= Hide ? SW_HIDE : 0; 3373 3374 co_WinPosShowWindow(pWnd, cmd); 3375 3376 Exit: 3377 TRACE("Leave NtUserMinMaximize\n"); 3378 UserLeave(); 3379 return 0; // Always NULL? 3380 } 3381 3382 /* 3383 * @implemented 3384 */ 3385 BOOL APIENTRY 3386 NtUserMoveWindow( 3387 HWND hWnd, 3388 int X, 3389 int Y, 3390 int nWidth, 3391 int nHeight, 3392 BOOL bRepaint) 3393 { 3394 return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight, 3395 (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE : 3396 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW)); 3397 } 3398 3399 /* 3400 * @implemented 3401 */ 3402 HWND APIENTRY 3403 NtUserRealChildWindowFromPoint(HWND Parent, 3404 LONG x, 3405 LONG y) 3406 { 3407 PWND pwndParent; 3408 TRACE("Enter NtUserRealChildWindowFromPoint\n"); 3409 UserEnterShared(); 3410 if ((pwndParent = UserGetWindowObject(Parent))) 3411 { 3412 pwndParent = IntRealChildWindowFromPoint(pwndParent, x, y); 3413 } 3414 UserLeave(); 3415 TRACE("Leave NtUserRealChildWindowFromPoint\n"); 3416 return pwndParent ? UserHMGetHandle(pwndParent) : NULL; 3417 } 3418 3419 /* 3420 * @implemented 3421 */ 3422 BOOL APIENTRY 3423 NtUserSetWindowPos( 3424 HWND hWnd, 3425 HWND hWndInsertAfter, 3426 int X, 3427 int Y, 3428 int cx, 3429 int cy, 3430 UINT uFlags) 3431 { 3432 DECLARE_RETURN(BOOL); 3433 PWND Window, pWndIA; 3434 BOOL ret; 3435 USER_REFERENCE_ENTRY Ref; 3436 3437 TRACE("Enter NtUserSetWindowPos\n"); 3438 UserEnterExclusive(); 3439 3440 if (!(Window = UserGetWindowObject(hWnd)) || 3441 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 3442 { 3443 ERR("NtUserSetWindowPos bad window handle!\n"); 3444 RETURN(FALSE); 3445 } 3446 3447 if ( hWndInsertAfter != HWND_TOP && 3448 hWndInsertAfter != HWND_BOTTOM && 3449 hWndInsertAfter != HWND_TOPMOST && 3450 hWndInsertAfter != HWND_NOTOPMOST ) 3451 { 3452 if (!(pWndIA = UserGetWindowObject(hWndInsertAfter)) || 3453 UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA)) 3454 { 3455 ERR("NtUserSetWindowPos bad insert window handle!\n"); 3456 RETURN(FALSE); 3457 } 3458 } 3459 3460 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */ 3461 if (!(uFlags & SWP_NOMOVE)) 3462 { 3463 if (X < -32768) X = -32768; 3464 else if (X > 32767) X = 32767; 3465 if (Y < -32768) Y = -32768; 3466 else if (Y > 32767) Y = 32767; 3467 } 3468 if (!(uFlags & SWP_NOSIZE)) 3469 { 3470 if (cx < 0) cx = 0; 3471 else if (cx > 32767) cx = 32767; 3472 if (cy < 0) cy = 0; 3473 else if (cy > 32767) cy = 32767; 3474 } 3475 3476 UserRefObjectCo(Window, &Ref); 3477 ret = co_WinPosSetWindowPos(Window, hWndInsertAfter, X, Y, cx, cy, uFlags); 3478 UserDerefObjectCo(Window); 3479 3480 RETURN(ret); 3481 3482 CLEANUP: 3483 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_); 3484 UserLeave(); 3485 END_CLEANUP; 3486 } 3487 3488 /* 3489 * @implemented 3490 */ 3491 INT APIENTRY 3492 NtUserSetWindowRgn( 3493 HWND hWnd, 3494 HRGN hRgn, 3495 BOOL bRedraw) 3496 { 3497 HRGN hrgnCopy = NULL; 3498 PWND Window; 3499 INT flags = (SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE); 3500 BOOLEAN Ret = FALSE; 3501 DECLARE_RETURN(INT); 3502 3503 TRACE("Enter NtUserSetWindowRgn\n"); 3504 UserEnterExclusive(); 3505 3506 if (!(Window = UserGetWindowObject(hWnd)) || 3507 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 3508 { 3509 RETURN( 0); 3510 } 3511 3512 if (hRgn) // The region will be deleted in user32. 3513 { 3514 if (GreIsHandleValid(hRgn)) 3515 { 3516 hrgnCopy = NtGdiCreateRectRgn(0, 0, 0, 0); 3517 /* The coordinates of a window's window region are relative to the 3518 upper-left corner of the window, not the client area of the window. */ 3519 NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY); 3520 } 3521 else 3522 RETURN( 0); 3523 } 3524 3525 //// HACK 1 : Work around the lack of supporting DeferWindowPos. 3526 if (hrgnCopy) 3527 { 3528 Window->hrgnNewFrame = hrgnCopy; // Should be PSMWP->acvr->hrgnClip 3529 } 3530 else 3531 { 3532 Window->hrgnNewFrame = HRGN_WINDOW; 3533 } 3534 //// HACK 2 3535 Ret = co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, bRedraw ? flags : (flags|SWP_NOREDRAW) ); 3536 3537 RETURN( (INT)Ret); 3538 3539 CLEANUP: 3540 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_); 3541 UserLeave(); 3542 END_CLEANUP; 3543 } 3544 3545 /* 3546 * @implemented 3547 */ 3548 DWORD APIENTRY 3549 NtUserSetInternalWindowPos( 3550 HWND hwnd, 3551 UINT showCmd, 3552 LPRECT lprect, 3553 LPPOINT lppt) 3554 { 3555 WINDOWPLACEMENT wndpl; 3556 UINT flags; 3557 PWND Wnd; 3558 RECT rect; 3559 POINT pt = {0}; 3560 DECLARE_RETURN(BOOL); 3561 USER_REFERENCE_ENTRY Ref; 3562 3563 TRACE("Enter NtUserSetWindowPlacement\n"); 3564 UserEnterExclusive(); 3565 3566 if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME: 3567 UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd)) 3568 { 3569 RETURN( FALSE); 3570 } 3571 3572 _SEH2_TRY 3573 { 3574 if (lppt) 3575 { 3576 ProbeForRead(lppt, sizeof(POINT), 1); 3577 RtlCopyMemory(&pt, lppt, sizeof(POINT)); 3578 } 3579 if (lprect) 3580 { 3581 ProbeForRead(lprect, sizeof(RECT), 1); 3582 RtlCopyMemory(&rect, lprect, sizeof(RECT)); 3583 } 3584 } 3585 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3586 { 3587 SetLastNtError(_SEH2_GetExceptionCode()); 3588 _SEH2_YIELD(RETURN( FALSE)); 3589 } 3590 _SEH2_END 3591 3592 wndpl.length = sizeof(wndpl); 3593 wndpl.showCmd = showCmd; 3594 wndpl.flags = flags = 0; 3595 3596 if ( lppt ) 3597 { 3598 flags |= PLACE_MIN; 3599 wndpl.flags |= WPF_SETMINPOSITION; 3600 wndpl.ptMinPosition = pt; 3601 } 3602 if ( lprect ) 3603 { 3604 flags |= PLACE_RECT; 3605 wndpl.rcNormalPosition = rect; 3606 } 3607 3608 UserRefObjectCo(Wnd, &Ref); 3609 IntSetWindowPlacement(Wnd, &wndpl, flags); 3610 UserDerefObjectCo(Wnd); 3611 RETURN(TRUE); 3612 3613 CLEANUP: 3614 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_); 3615 UserLeave(); 3616 END_CLEANUP; 3617 } 3618 3619 /* 3620 * @implemented 3621 */ 3622 BOOL APIENTRY 3623 NtUserSetWindowPlacement(HWND hWnd, 3624 WINDOWPLACEMENT *lpwndpl) 3625 { 3626 PWND Wnd; 3627 WINDOWPLACEMENT Safepl; 3628 UINT Flags; 3629 DECLARE_RETURN(BOOL); 3630 USER_REFERENCE_ENTRY Ref; 3631 3632 TRACE("Enter NtUserSetWindowPlacement\n"); 3633 UserEnterExclusive(); 3634 3635 if (!(Wnd = UserGetWindowObject(hWnd)) || 3636 UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd)) 3637 { 3638 RETURN( FALSE); 3639 } 3640 3641 _SEH2_TRY 3642 { 3643 ProbeForRead(lpwndpl, sizeof(WINDOWPLACEMENT), 1); 3644 RtlCopyMemory(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT)); 3645 } 3646 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3647 { 3648 SetLastNtError(_SEH2_GetExceptionCode()); 3649 _SEH2_YIELD(RETURN( FALSE)); 3650 } 3651 _SEH2_END 3652 3653 if(Safepl.length != sizeof(WINDOWPLACEMENT)) 3654 { 3655 RETURN( FALSE); 3656 } 3657 3658 Flags = PLACE_MAX | PLACE_RECT; 3659 if (Safepl.flags & WPF_SETMINPOSITION) Flags |= PLACE_MIN; 3660 UserRefObjectCo(Wnd, &Ref); 3661 IntSetWindowPlacement(Wnd, &Safepl, Flags); 3662 UserDerefObjectCo(Wnd); 3663 RETURN(TRUE); 3664 3665 CLEANUP: 3666 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_); 3667 UserLeave(); 3668 END_CLEANUP; 3669 } 3670 3671 /* 3672 * @implemented 3673 */ 3674 BOOL APIENTRY 3675 NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow) 3676 { 3677 PWND Window; 3678 BOOL ret; 3679 DECLARE_RETURN(BOOL); 3680 USER_REFERENCE_ENTRY Ref; 3681 3682 TRACE("Enter NtUserShowWindowAsync\n"); 3683 UserEnterExclusive(); 3684 3685 if (!(Window = UserGetWindowObject(hWnd)) || 3686 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 3687 { 3688 RETURN(FALSE); 3689 } 3690 3691 if ( nCmdShow > SW_MAX ) 3692 { 3693 EngSetLastError(ERROR_INVALID_PARAMETER); 3694 RETURN(FALSE); 3695 } 3696 3697 UserRefObjectCo(Window, &Ref); 3698 ret = co_IntSendMessageNoWait( hWnd, WM_ASYNC_SHOWWINDOW, nCmdShow, 0 ); 3699 UserDerefObjectCo(Window); 3700 if (-1 == (int) ret || !ret) ret = FALSE; 3701 3702 RETURN(ret); 3703 3704 CLEANUP: 3705 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_); 3706 UserLeave(); 3707 END_CLEANUP; 3708 } 3709 3710 /* 3711 * @implemented 3712 */ 3713 BOOL APIENTRY 3714 NtUserShowWindow(HWND hWnd, LONG nCmdShow) 3715 { 3716 PWND Window; 3717 BOOL ret; 3718 DECLARE_RETURN(BOOL); 3719 USER_REFERENCE_ENTRY Ref; 3720 3721 TRACE("Enter NtUserShowWindow hWnd %p SW_ %d\n",hWnd, nCmdShow); 3722 UserEnterExclusive(); 3723 3724 if (!(Window = UserGetWindowObject(hWnd)) || 3725 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 3726 { 3727 RETURN(FALSE); 3728 } 3729 3730 if ( nCmdShow > SW_MAX || Window->state2 & WNDS2_INDESTROY) 3731 { 3732 EngSetLastError(ERROR_INVALID_PARAMETER); 3733 RETURN(FALSE); 3734 } 3735 3736 UserRefObjectCo(Window, &Ref); 3737 ret = co_WinPosShowWindow(Window, nCmdShow); 3738 UserDerefObjectCo(Window); 3739 3740 RETURN(ret); 3741 3742 CLEANUP: 3743 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_); 3744 UserLeave(); 3745 END_CLEANUP; 3746 } 3747 3748 3749 /* 3750 * @implemented 3751 */ 3752 HWND APIENTRY 3753 NtUserWindowFromPoint(LONG X, LONG Y) 3754 { 3755 POINT pt; 3756 HWND Ret; 3757 PWND DesktopWindow = NULL, Window = NULL; 3758 USHORT hittest; 3759 DECLARE_RETURN(HWND); 3760 USER_REFERENCE_ENTRY Ref; 3761 3762 TRACE("Enter NtUserWindowFromPoint\n"); 3763 UserEnterExclusive(); 3764 3765 if ((DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()))) 3766 { 3767 //PTHREADINFO pti; 3768 3769 pt.x = X; 3770 pt.y = Y; 3771 3772 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window. 3773 // It is possible this referencing is useless, though it should not hurt... 3774 UserRefObjectCo(DesktopWindow, &Ref); 3775 3776 //pti = PsGetCurrentThreadWin32Thread(); 3777 Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest, FALSE); 3778 3779 if (Window) 3780 { 3781 Ret = UserHMGetHandle(Window); 3782 3783 RETURN( Ret); 3784 } 3785 } 3786 3787 RETURN( NULL); 3788 3789 CLEANUP: 3790 if (DesktopWindow) UserDerefObjectCo(DesktopWindow); 3791 3792 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_); 3793 UserLeave(); 3794 END_CLEANUP; 3795 } 3796 3797 /* EOF */ 3798