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