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