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; 1057 1058 if (ParentWnd->style & WS_CHILD) 1059 { 1060 do 1061 ParentWnd = ParentWnd->spwndParent; 1062 while (ParentWnd->style & WS_CHILD); 1063 } 1064 1065 ParentWnd = Child->spwndParent; 1066 while (ParentWnd) 1067 { 1068 if (ParentWnd->style & WS_CLIPCHILDREN) 1069 break; 1070 1071 if (ParentWnd->hrgnUpdate != 0) 1072 { 1073 IntInvalidateWindows( ParentWnd, 1074 ValidateRgn, 1075 RDW_VALIDATE | RDW_NOCHILDREN); 1076 } 1077 1078 ParentWnd = ParentWnd->spwndParent; 1079 } 1080 1081 return TRUE; 1082 } 1083 1084 static 1085 VOID FASTCALL 1086 FixClientRect(PRECTL ClientRect, PRECTL WindowRect) 1087 { 1088 if (ClientRect->left < WindowRect->left) 1089 { 1090 ClientRect->left = WindowRect->left; 1091 } 1092 else if (WindowRect->right < ClientRect->left) 1093 { 1094 ClientRect->left = WindowRect->right; 1095 } 1096 if (ClientRect->right < WindowRect->left) 1097 { 1098 ClientRect->right = WindowRect->left; 1099 } 1100 else if (WindowRect->right < ClientRect->right) 1101 { 1102 ClientRect->right = WindowRect->right; 1103 } 1104 if (ClientRect->top < WindowRect->top) 1105 { 1106 ClientRect->top = WindowRect->top; 1107 } 1108 else if (WindowRect->bottom < ClientRect->top) 1109 { 1110 ClientRect->top = WindowRect->bottom; 1111 } 1112 if (ClientRect->bottom < WindowRect->top) 1113 { 1114 ClientRect->bottom = WindowRect->top; 1115 } 1116 else if (WindowRect->bottom < ClientRect->bottom) 1117 { 1118 ClientRect->bottom = WindowRect->bottom; 1119 } 1120 } 1121 /*********************************************************************** 1122 * get_valid_rects 1123 * 1124 * Compute the valid rects from the old and new client rect and WVR_* flags. 1125 * Helper for WM_NCCALCSIZE handling. 1126 */ 1127 static 1128 VOID FASTCALL 1129 get_valid_rects( RECTL *old_client, RECTL *new_client, UINT flags, RECTL *valid ) 1130 { 1131 int cx, cy; 1132 1133 if (flags & WVR_REDRAW) 1134 { 1135 RECTL_vSetEmptyRect( &valid[0] ); 1136 RECTL_vSetEmptyRect( &valid[1] ); 1137 return; 1138 } 1139 1140 if (flags & WVR_VALIDRECTS) 1141 { 1142 if (!RECTL_bIntersectRect( &valid[0], &valid[0], new_client ) || 1143 !RECTL_bIntersectRect( &valid[1], &valid[1], old_client )) 1144 { 1145 RECTL_vSetEmptyRect( &valid[0] ); 1146 RECTL_vSetEmptyRect( &valid[1] ); 1147 return; 1148 } 1149 flags = WVR_ALIGNLEFT | WVR_ALIGNTOP; 1150 } 1151 else 1152 { 1153 valid[0] = *new_client; 1154 valid[1] = *old_client; 1155 } 1156 1157 /* make sure the rectangles have the same size */ 1158 cx = min( valid[0].right - valid[0].left, valid[1].right - valid[1].left ); 1159 cy = min( valid[0].bottom - valid[0].top, valid[1].bottom - valid[1].top ); 1160 1161 if (flags & WVR_ALIGNBOTTOM) 1162 { 1163 valid[0].top = valid[0].bottom - cy; 1164 valid[1].top = valid[1].bottom - cy; 1165 } 1166 else 1167 { 1168 valid[0].bottom = valid[0].top + cy; 1169 valid[1].bottom = valid[1].top + cy; 1170 } 1171 if (flags & WVR_ALIGNRIGHT) 1172 { 1173 valid[0].left = valid[0].right - cx; 1174 valid[1].left = valid[1].right - cx; 1175 } 1176 else 1177 { 1178 valid[0].right = valid[0].left + cx; 1179 valid[1].right = valid[1].left + cx; 1180 } 1181 } 1182 1183 static 1184 LONG FASTCALL 1185 co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, RECTL* WindowRect, RECTL* ClientRect, RECTL* validRects) 1186 { 1187 PWND Parent; 1188 UINT wvrFlags = 0; 1189 1190 ASSERT_REFS_CO(Window); 1191 1192 /* Send WM_NCCALCSIZE message to get new client area */ 1193 if ((WinPos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE) 1194 { 1195 NCCALCSIZE_PARAMS params; 1196 WINDOWPOS winposCopy; 1197 1198 params.rgrc[0] = *WindowRect; // new coordinates of a window that has been moved or resized 1199 params.rgrc[1] = Window->rcWindow; // window before it was moved or resized 1200 params.rgrc[2] = Window->rcClient; // client area before the window was moved or resized 1201 1202 Parent = Window->spwndParent; 1203 if (0 != (Window->style & WS_CHILD) && Parent) 1204 { 1205 RECTL_vOffsetRect(&(params.rgrc[0]), - Parent->rcClient.left, - Parent->rcClient.top); 1206 RECTL_vOffsetRect(&(params.rgrc[1]), - Parent->rcClient.left, - Parent->rcClient.top); 1207 RECTL_vOffsetRect(&(params.rgrc[2]), - Parent->rcClient.left, - Parent->rcClient.top); 1208 } 1209 1210 params.lppos = &winposCopy; 1211 winposCopy = *WinPos; 1212 1213 wvrFlags = co_IntSendMessage(Window->head.h, WM_NCCALCSIZE, TRUE, (LPARAM) ¶ms); 1214 1215 /* If the application send back garbage, ignore it */ 1216 if (params.rgrc[0].left <= params.rgrc[0].right && 1217 params.rgrc[0].top <= params.rgrc[0].bottom) 1218 { 1219 *ClientRect = params.rgrc[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize 1220 if ((Window->style & WS_CHILD) && Parent) 1221 { 1222 RECTL_vOffsetRect(ClientRect, Parent->rcClient.left, Parent->rcClient.top); 1223 } 1224 FixClientRect(ClientRect, WindowRect); 1225 } 1226 1227 if (ClientRect->left != Window->rcClient.left || 1228 ClientRect->top != Window->rcClient.top) 1229 { 1230 WinPos->flags &= ~SWP_NOCLIENTMOVE; 1231 } 1232 1233 if (ClientRect->right - ClientRect->left != Window->rcClient.right - Window->rcClient.left) 1234 { 1235 WinPos->flags &= ~SWP_NOCLIENTSIZE; 1236 } 1237 else 1238 wvrFlags &= ~WVR_HREDRAW; 1239 1240 if (ClientRect->bottom - ClientRect->top != Window->rcClient.bottom - Window->rcClient.top) 1241 { 1242 WinPos->flags &= ~SWP_NOCLIENTSIZE; 1243 } 1244 else 1245 wvrFlags &= ~WVR_VREDRAW; 1246 1247 validRects[0] = params.rgrc[1]; // second rectangle contains the valid destination rectangle 1248 validRects[1] = params.rgrc[2]; // third rectangle contains the valid source rectangle 1249 } 1250 else 1251 { 1252 if (!(WinPos->flags & SWP_NOMOVE) && 1253 (ClientRect->left != Window->rcClient.left || 1254 ClientRect->top != Window->rcClient.top)) 1255 { 1256 WinPos->flags &= ~SWP_NOCLIENTMOVE; 1257 } 1258 } 1259 1260 if (WinPos->flags & (SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_SHOWWINDOW | SWP_HIDEWINDOW)) 1261 { 1262 RECTL_vSetEmptyRect( &validRects[0] ); 1263 RECTL_vSetEmptyRect( &validRects[1] ); 1264 } 1265 else get_valid_rects( &Window->rcClient, ClientRect, wvrFlags, validRects ); 1266 1267 return wvrFlags; 1268 } 1269 1270 static 1271 BOOL FASTCALL 1272 co_WinPosDoWinPosChanging(PWND Window, 1273 PWINDOWPOS WinPos, 1274 PRECTL WindowRect, 1275 PRECTL ClientRect) 1276 { 1277 ASSERT_REFS_CO(Window); 1278 1279 /* Send WM_WINDOWPOSCHANGING message */ 1280 1281 if (!(WinPos->flags & SWP_NOSENDCHANGING) 1282 && !((WinPos->flags & SWP_AGG_NOCLIENTCHANGE) && (WinPos->flags & SWP_SHOWWINDOW))) 1283 { 1284 TRACE("Sending WM_WINDOWPOSCHANGING to hwnd %p flags %04x.\n", Window->head.h,WinPos->flags); 1285 co_IntSendMessage(Window->head.h, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos); 1286 } 1287 1288 /* Calculate new position and size */ 1289 1290 *WindowRect = Window->rcWindow; 1291 *ClientRect = (Window->style & WS_MINIMIZE) ? Window->rcWindow : Window->rcClient; 1292 1293 if (!(WinPos->flags & SWP_NOSIZE)) 1294 { 1295 if (Window->style & WS_MINIMIZE) 1296 { 1297 WindowRect->right = WindowRect->left + UserGetSystemMetrics(SM_CXMINIMIZED); 1298 WindowRect->bottom = WindowRect->top + UserGetSystemMetrics(SM_CYMINIMIZED); 1299 } 1300 else 1301 { 1302 WindowRect->right = WindowRect->left + WinPos->cx; 1303 WindowRect->bottom = WindowRect->top + WinPos->cy; 1304 } 1305 } 1306 1307 if (!(WinPos->flags & SWP_NOMOVE)) 1308 { 1309 INT X, Y; 1310 PWND Parent; 1311 X = WinPos->x; 1312 Y = WinPos->y; 1313 1314 Parent = Window->spwndParent; 1315 1316 // Parent child position issue is in here. SetParent_W7 test CORE-6651. 1317 if (//((Window->style & WS_CHILD) != 0) && <- Fixes wine msg test_SetParent: "rects do not match", the last test. 1318 Parent && 1319 Parent != Window->head.rpdesk->pDeskInfo->spwnd) 1320 { 1321 TRACE("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X,Y); 1322 X += Parent->rcClient.left; 1323 Y += Parent->rcClient.top; 1324 TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X,Y); 1325 } 1326 1327 WindowRect->left = X; 1328 WindowRect->top = Y; 1329 WindowRect->right += X - Window->rcWindow.left; 1330 WindowRect->bottom += Y - Window->rcWindow.top; 1331 1332 RECTL_vOffsetRect(ClientRect, X - Window->rcWindow.left, 1333 Y - Window->rcWindow.top); 1334 } 1335 WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE; 1336 1337 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n", 1338 WinPos->hwnd, WinPos->hwndInsertAfter, WinPos->x, WinPos->y, 1339 WinPos->cx, WinPos->cy, WinPos->flags ); 1340 TRACE("WindowRect: %d %d %d %d\n", WindowRect->left,WindowRect->top,WindowRect->right,WindowRect->bottom); 1341 TRACE("ClientRect: %d %d %d %d\n", ClientRect->left,ClientRect->top,ClientRect->right,ClientRect->bottom); 1342 1343 return TRUE; 1344 } 1345 1346 /* 1347 * Fix Z order taking into account owned popups - 1348 * basically we need to maintain them above the window that owns them 1349 * 1350 * FIXME: hide/show owned popups when owner visibility changes. 1351 * 1352 * ReactOS: See bug CORE-6129 and CORE-6554. 1353 * 1354 */ 1355 //// 1356 // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out. 1357 // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!! 1358 static 1359 HWND FASTCALL 1360 WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) 1361 { 1362 HWND *List = NULL; 1363 HWND Owner; 1364 LONG Style; 1365 PWND DesktopWindow, ChildObject; 1366 int i; 1367 1368 TRACE("(%p) hInsertAfter = %p\n", Window, hWndInsertAfter ); 1369 1370 Style = Window->style; 1371 1372 if (Style & WS_CHILD) 1373 { 1374 TRACE("Window is child\n"); 1375 return hWndInsertAfter; 1376 } 1377 1378 Owner = Window->spwndOwner ? Window->spwndOwner->head.h : NULL; 1379 1380 if (Owner) 1381 { 1382 /* Make sure this popup stays above the owner */ 1383 1384 if (hWndInsertAfter != HWND_TOPMOST) 1385 { 1386 DesktopWindow = UserGetDesktopWindow(); 1387 List = IntWinListChildren(DesktopWindow); 1388 1389 if (List != NULL) 1390 { 1391 for (i = 0; List[i]; i++) 1392 { 1393 BOOL topmost = FALSE; 1394 1395 ChildObject = ValidateHwndNoErr(List[i]); 1396 if (ChildObject) 1397 { 1398 topmost = (ChildObject->ExStyle & WS_EX_TOPMOST) != 0; 1399 } 1400 1401 if (List[i] == Owner) 1402 { 1403 if (i > 0) hWndInsertAfter = List[i-1]; 1404 else hWndInsertAfter = topmost ? HWND_TOPMOST : HWND_TOP; 1405 break; 1406 } 1407 1408 if (hWndInsertAfter == HWND_TOP || hWndInsertAfter == HWND_NOTOPMOST) 1409 { 1410 if (!topmost) break; 1411 } 1412 else if (List[i] == hWndInsertAfter) break; 1413 } 1414 } 1415 else 1416 return hWndInsertAfter; 1417 } 1418 } 1419 1420 if (hWndInsertAfter == HWND_BOTTOM) 1421 { 1422 ERR("Window is HWND_BOTTOM hwnd %p\n",hWndInsertAfter); 1423 if (List) ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 1424 goto done; 1425 } 1426 1427 if (!List) 1428 { 1429 DesktopWindow = UserGetDesktopWindow(); 1430 List = IntWinListChildren(DesktopWindow); 1431 } 1432 1433 if (List != NULL) 1434 { 1435 i = 0; 1436 1437 if (hWndInsertAfter == HWND_TOP || hWndInsertAfter == HWND_NOTOPMOST) 1438 { 1439 if (hWndInsertAfter == HWND_NOTOPMOST || !(Window->ExStyle & WS_EX_TOPMOST)) 1440 { 1441 TRACE("skip all the topmost windows\n"); 1442 /* skip all the topmost windows */ 1443 while (List[i] && 1444 (ChildObject = ValidateHwndNoErr(List[i])) && 1445 (ChildObject->ExStyle & WS_EX_TOPMOST)) i++; 1446 } 1447 } 1448 else if (hWndInsertAfter != HWND_TOPMOST) 1449 { 1450 /* skip windows that are already placed correctly */ 1451 for (i = 0; List[i]; i++) 1452 { 1453 if (List[i] == hWndInsertAfter) break; 1454 if (List[i] == UserHMGetHandle(Window)) 1455 { 1456 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 1457 goto done; /* nothing to do if window is moving backwards in z-order */ 1458 } 1459 } 1460 } 1461 1462 for (; List[i]; i++) 1463 { 1464 PWND Wnd; 1465 USER_REFERENCE_ENTRY Ref; 1466 1467 if (List[i] == UserHMGetHandle(Window)) 1468 break; 1469 1470 if (!(Wnd = ValidateHwndNoErr(List[i]))) 1471 continue; 1472 1473 Owner = Wnd->spwndOwner ? Wnd->spwndOwner->head.h : NULL; 1474 1475 if (Owner != UserHMGetHandle(Window)) continue; 1476 1477 UserRefObjectCo(Wnd, &Ref); 1478 TRACE( "moving %p owned by %p after %p\n", List[i], UserHMGetHandle(Window), hWndInsertAfter ); 1479 co_WinPosSetWindowPos(Wnd, hWndInsertAfter, 0, 0, 0, 0, 1480 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING| SWP_DEFERERASE); 1481 1482 UserDerefObjectCo(Wnd); 1483 hWndInsertAfter = List[i]; 1484 } 1485 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 1486 } 1487 done: 1488 return hWndInsertAfter; 1489 } 1490 //// 1491 1492 /*********************************************************************** 1493 * WinPosInternalMoveWindow 1494 * 1495 * Update WindowRect and ClientRect of Window and all of its children 1496 * We keep both WindowRect and ClientRect in screen coordinates internally 1497 */ 1498 static 1499 VOID FASTCALL 1500 WinPosInternalMoveWindow(PWND Window, INT MoveX, INT MoveY) 1501 { 1502 PWND Child; 1503 1504 ASSERT(Window != Window->spwndChild); 1505 TRACE("InternalMoveWin X %d Y %d\n", MoveX, MoveY); 1506 1507 Window->rcWindow.left += MoveX; 1508 Window->rcWindow.right += MoveX; 1509 Window->rcWindow.top += MoveY; 1510 Window->rcWindow.bottom += MoveY; 1511 1512 Window->rcClient.left += MoveX; 1513 Window->rcClient.right += MoveX; 1514 Window->rcClient.top += MoveY; 1515 Window->rcClient.bottom += MoveY; 1516 1517 for(Child = Window->spwndChild; Child; Child = Child->spwndNext) 1518 { 1519 WinPosInternalMoveWindow(Child, MoveX, MoveY); 1520 } 1521 } 1522 1523 /* 1524 * WinPosFixupSWPFlags 1525 * 1526 * Fix redundant flags and values in the WINDOWPOS structure. 1527 */ 1528 static 1529 BOOL FASTCALL 1530 WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) 1531 { 1532 PWND Parent; 1533 POINT pt; 1534 1535 /* Finally make sure that all coordinates are valid */ 1536 if (WinPos->x < -32768) WinPos->x = -32768; 1537 else if (WinPos->x > 32767) WinPos->x = 32767; 1538 if (WinPos->y < -32768) WinPos->y = -32768; 1539 else if (WinPos->y > 32767) WinPos->y = 32767; 1540 1541 WinPos->cx = max(WinPos->cx, 0); 1542 WinPos->cy = max(WinPos->cy, 0); 1543 1544 Parent = UserGetAncestor( Wnd, GA_PARENT ); 1545 if (!IntIsWindowVisible( Parent ) && 1546 /* Fix B : wine msg test_SetParent:WmSetParentSeq_2:25 wParam bits! */ 1547 (WinPos->flags & SWP_AGG_STATUSFLAGS) == SWP_AGG_NOPOSCHANGE) WinPos->flags |= SWP_NOREDRAW; 1548 1549 if (Wnd->style & WS_VISIBLE) WinPos->flags &= ~SWP_SHOWWINDOW; 1550 else 1551 { 1552 WinPos->flags &= ~SWP_HIDEWINDOW; 1553 if (!(WinPos->flags & SWP_SHOWWINDOW)) WinPos->flags |= SWP_NOREDRAW; 1554 } 1555 1556 /* Check for right size */ 1557 if (Wnd->rcWindow.right - Wnd->rcWindow.left == WinPos->cx && 1558 Wnd->rcWindow.bottom - Wnd->rcWindow.top == WinPos->cy) 1559 { 1560 WinPos->flags |= SWP_NOSIZE; 1561 } 1562 1563 pt.x = WinPos->x; 1564 pt.y = WinPos->y; 1565 IntClientToScreen( Parent, &pt ); 1566 TRACE("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos->x,WinPos->y,pt.x,pt.y); 1567 /* Check for right position */ 1568 if (Wnd->rcWindow.left == pt.x && Wnd->rcWindow.top == pt.y) 1569 { 1570 //ERR("In right pos\n"); 1571 WinPos->flags |= SWP_NOMOVE; 1572 } 1573 1574 if ( WinPos->hwnd != UserGetForegroundWindow() && (Wnd->style & (WS_POPUP | WS_CHILD)) != WS_CHILD) 1575 { 1576 /* Bring to the top when activating */ 1577 if (!(WinPos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)) && 1578 (WinPos->flags & SWP_NOZORDER || 1579 (WinPos->hwndInsertAfter != HWND_TOPMOST && WinPos->hwndInsertAfter != HWND_NOTOPMOST))) 1580 { 1581 WinPos->flags &= ~SWP_NOZORDER; 1582 WinPos->hwndInsertAfter = (0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP); 1583 } 1584 } 1585 1586 /* Check hwndInsertAfter */ 1587 if (!(WinPos->flags & SWP_NOZORDER)) 1588 { 1589 /* Fix sign extension */ 1590 if (WinPos->hwndInsertAfter == (HWND)0xffff) 1591 { 1592 WinPos->hwndInsertAfter = HWND_TOPMOST; 1593 } 1594 else if (WinPos->hwndInsertAfter == (HWND)0xfffe) 1595 { 1596 WinPos->hwndInsertAfter = HWND_NOTOPMOST; 1597 } 1598 1599 if (WinPos->hwndInsertAfter == HWND_TOP) 1600 { 1601 /* Keep it topmost when it's already topmost */ 1602 if ((Wnd->ExStyle & WS_EX_TOPMOST) != 0) 1603 WinPos->hwndInsertAfter = HWND_TOPMOST; 1604 1605 if (IntGetWindow(WinPos->hwnd, GW_HWNDFIRST) == WinPos->hwnd) 1606 { 1607 WinPos->flags |= SWP_NOZORDER; 1608 } 1609 } 1610 else if (WinPos->hwndInsertAfter == HWND_BOTTOM) 1611 { 1612 if (!(Wnd->ExStyle & WS_EX_TOPMOST) && IntGetWindow(WinPos->hwnd, GW_HWNDLAST) == WinPos->hwnd) 1613 WinPos->flags |= SWP_NOZORDER; 1614 } 1615 else if (WinPos->hwndInsertAfter == HWND_TOPMOST) 1616 { 1617 if ((Wnd->ExStyle & WS_EX_TOPMOST) && IntGetWindow(WinPos->hwnd, GW_HWNDFIRST) == WinPos->hwnd) 1618 WinPos->flags |= SWP_NOZORDER; 1619 } 1620 else if (WinPos->hwndInsertAfter == HWND_NOTOPMOST) 1621 { 1622 if (!(Wnd->ExStyle & WS_EX_TOPMOST)) 1623 WinPos->flags |= SWP_NOZORDER; 1624 } 1625 else /* hwndInsertAfter must be a sibling of the window */ 1626 { 1627 PWND InsAfterWnd; 1628 1629 InsAfterWnd = ValidateHwndNoErr(WinPos->hwndInsertAfter); 1630 if(!InsAfterWnd) 1631 { 1632 return TRUE; 1633 } 1634 1635 if (InsAfterWnd->spwndParent != Wnd->spwndParent) 1636 { 1637 /* Note from wine User32 Win test_SetWindowPos: 1638 "Returns TRUE also for windows that are not siblings" 1639 "Does not seem to do anything even without passing flags, still returns TRUE" 1640 "Same thing the other way around." 1641 ".. and with these windows." 1642 */ 1643 return FALSE; 1644 } 1645 else 1646 { 1647 /* 1648 * We don't need to change the Z order of hwnd if it's already 1649 * inserted after hwndInsertAfter or when inserting hwnd after 1650 * itself. 1651 */ 1652 if ((WinPos->hwnd == WinPos->hwndInsertAfter) || 1653 ((InsAfterWnd->spwndNext) && (WinPos->hwnd == InsAfterWnd->spwndNext->head.h))) 1654 { 1655 WinPos->flags |= SWP_NOZORDER; 1656 } 1657 } 1658 } 1659 } 1660 1661 return TRUE; 1662 } 1663 1664 /* x and y are always screen relative */ 1665 BOOLEAN FASTCALL 1666 co_WinPosSetWindowPos( 1667 PWND Window, 1668 HWND WndInsertAfter, 1669 INT x, 1670 INT y, 1671 INT cx, 1672 INT cy, 1673 UINT flags 1674 ) 1675 { 1676 WINDOWPOS WinPos; 1677 RECTL NewWindowRect; 1678 RECTL NewClientRect; 1679 RECTL valid_rects[2]; 1680 PREGION VisBefore = NULL; 1681 PREGION VisBeforeJustClient = NULL; 1682 PREGION VisAfter = NULL; 1683 PREGION CopyRgn = NULL; 1684 ULONG WvrFlags = 0; 1685 RECTL OldWindowRect, OldClientRect; 1686 int RgnType; 1687 HDC Dc; 1688 RECTL CopyRect; 1689 PWND Ancestor; 1690 BOOL bPointerInWindow, PosChanged = FALSE; 1691 PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); 1692 1693 ASSERT_REFS_CO(Window); 1694 1695 TRACE("pwnd %p, after %p, %d,%d (%dx%d), flags %s", 1696 Window, WndInsertAfter, x, y, cx, cy, flags); 1697 #if DBG 1698 dump_winpos_flags(flags); 1699 #endif 1700 1701 /* FIXME: Get current active window from active queue. Why? since r2915. */ 1702 1703 bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y); 1704 1705 WinPos.hwnd = Window->head.h; 1706 WinPos.hwndInsertAfter = WndInsertAfter; 1707 WinPos.x = x; 1708 WinPos.y = y; 1709 WinPos.cx = cx; 1710 WinPos.cy = cy; 1711 WinPos.flags = flags; 1712 1713 if ( flags & SWP_ASYNCWINDOWPOS ) 1714 { 1715 LRESULT lRes; 1716 PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP); 1717 if ( ppos ) 1718 { 1719 WinPos.flags &= ~SWP_ASYNCWINDOWPOS; // Clear flag. 1720 *ppos = WinPos; 1721 /* Yes it's a pointer inside Win32k! */ 1722 lRes = co_IntSendMessageNoWait( WinPos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos); 1723 /* We handle this the same way as Event Hooks and Hooks. */ 1724 if ( !lRes ) 1725 { 1726 ExFreePoolWithTag(ppos, USERTAG_SWP); 1727 return FALSE; 1728 } 1729 return TRUE; 1730 } 1731 return FALSE; 1732 } 1733 1734 co_WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect); 1735 1736 /* Does the window still exist? */ 1737 if (!IntIsWindow(WinPos.hwnd)) 1738 { 1739 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos.hwnd); 1740 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); 1741 return FALSE; 1742 } 1743 1744 /* Fix up the flags. */ 1745 if (!WinPosFixupFlags(&WinPos, Window)) 1746 { 1747 // See Note. 1748 return TRUE; 1749 } 1750 1751 Ancestor = UserGetAncestor(Window, GA_PARENT); 1752 if ( (WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER && 1753 Ancestor && Ancestor->head.h == IntGetDesktopWindow() ) 1754 { 1755 WinPos.hwndInsertAfter = WinPosDoOwnedPopups(Window, WinPos.hwndInsertAfter); 1756 } 1757 1758 if (!(WinPos.flags & SWP_NOREDRAW)) 1759 { 1760 /* Compute the visible region before the window position is changed */ 1761 if (!(WinPos.flags & SWP_SHOWWINDOW) && 1762 (WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | 1763 SWP_HIDEWINDOW | SWP_FRAMECHANGED)) != 1764 (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) 1765 { 1766 VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, 1767 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); 1768 1769 if ( VisBefore != NULL && 1770 REGION_Complexity(VisBefore) == NULLREGION ) 1771 { 1772 REGION_Delete(VisBefore); 1773 VisBefore = NULL; 1774 } 1775 else if(VisBefore) 1776 { 1777 REGION_bOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top); 1778 } 1779 1780 /* Calculate the non client area for resizes, as this is used in the copy region */ 1781 if (!(WinPos.flags & SWP_NOSIZE)) 1782 { 1783 VisBeforeJustClient = VIS_ComputeVisibleRegion(Window, TRUE, FALSE, 1784 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); 1785 1786 if ( VisBeforeJustClient != NULL && 1787 REGION_Complexity(VisBeforeJustClient) == NULLREGION ) 1788 { 1789 REGION_Delete(VisBeforeJustClient); 1790 VisBeforeJustClient = NULL; 1791 } 1792 else if(VisBeforeJustClient) 1793 { 1794 REGION_bOffsetRgn(VisBeforeJustClient, -Window->rcWindow.left, -Window->rcWindow.top); 1795 } 1796 } 1797 } 1798 } 1799 1800 //// HACK 3 1801 if (Window->hrgnNewFrame) 1802 { 1803 SelectWindowRgn( Window, Window->hrgnNewFrame ); // Should be PSMWP->acvr->hrgnClip 1804 Window->hrgnNewFrame = NULL; 1805 } 1806 1807 WvrFlags = co_WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect, valid_rects); 1808 1809 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags, 1810 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom, 1811 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom); 1812 1813 /* Validate link windows. (also take into account shell window in hwndShellWindow) */ 1814 if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow()) 1815 { 1816 IntLinkHwnd(Window, WinPos.hwndInsertAfter); 1817 } 1818 1819 OldWindowRect = Window->rcWindow; 1820 OldClientRect = Window->rcClient; 1821 1822 if (NewClientRect.left != OldClientRect.left || 1823 NewClientRect.top != OldClientRect.top) 1824 { 1825 // Move child window if their parent is moved. Keep Child window relative to Parent... 1826 WinPosInternalMoveWindow(Window, 1827 NewClientRect.left - OldClientRect.left, 1828 NewClientRect.top - OldClientRect.top); 1829 PosChanged = TRUE; 1830 } 1831 1832 Window->rcWindow = NewWindowRect; 1833 Window->rcClient = NewClientRect; 1834 1835 /* erase parent when hiding or resizing child */ 1836 if (WinPos.flags & SWP_HIDEWINDOW) 1837 { 1838 /* Clear the update region */ 1839 co_UserRedrawWindow( Window, 1840 NULL, 1841 0, 1842 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN); 1843 1844 if (UserIsDesktopWindow(Window->spwndParent)) 1845 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM)Window->head.h, 0); 1846 1847 Window->style &= ~WS_VISIBLE; //IntSetStyle( Window, 0, WS_VISIBLE ); 1848 Window->head.pti->cVisWindows--; 1849 IntNotifyWinEvent(EVENT_OBJECT_HIDE, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); 1850 } 1851 else if (WinPos.flags & SWP_SHOWWINDOW) 1852 { 1853 if (UserIsDesktopWindow(Window->spwndParent) && 1854 Window->spwndOwner == NULL && 1855 (!(Window->ExStyle & WS_EX_TOOLWINDOW) || 1856 (Window->ExStyle & WS_EX_APPWINDOW))) 1857 co_IntShellHookNotify(HSHELL_WINDOWCREATED, (WPARAM)Window->head.h, 0); 1858 1859 Window->style |= WS_VISIBLE; //IntSetStyle( Window, WS_VISIBLE, 0 ); 1860 Window->head.pti->cVisWindows++; 1861 IntNotifyWinEvent(EVENT_OBJECT_SHOW, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); 1862 } 1863 1864 if (Window->hrgnUpdate != NULL && Window->hrgnUpdate != HRGN_WINDOW) 1865 { 1866 NtGdiOffsetRgn(Window->hrgnUpdate, 1867 NewWindowRect.left - OldWindowRect.left, 1868 NewWindowRect.top - OldWindowRect.top); 1869 } 1870 1871 DceResetActiveDCEs(Window); // For WS_VISIBLE changes. 1872 1873 if (!(WinPos.flags & SWP_NOREDRAW)) 1874 { 1875 /* Determine the new visible region */ 1876 VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, 1877 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); 1878 1879 if ( VisAfter != NULL && 1880 REGION_Complexity(VisAfter) == NULLREGION ) 1881 { 1882 REGION_Delete(VisAfter); 1883 VisAfter = NULL; 1884 } 1885 else if(VisAfter) 1886 { 1887 REGION_bOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top); 1888 } 1889 1890 /* 1891 * Determine which pixels can be copied from the old window position 1892 * to the new. Those pixels must be visible in both the old and new 1893 * position. Also, check the class style to see if the windows of this 1894 * class need to be completely repainted on (horizontal/vertical) size 1895 * change. 1896 */ 1897 if ( ( VisBefore != NULL && 1898 VisAfter != NULL && 1899 !(WinPos.flags & SWP_NOCOPYBITS) && 1900 ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) && 1901 !(Window->ExStyle & WS_EX_TRANSPARENT) ) || 1902 ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) && VisBefore) ) 1903 { 1904 1905 /* 1906 * If this is (also) a window resize, the whole nonclient area 1907 * needs to be repainted. So we limit the copy to the client area, 1908 * 'cause there is no use in copying it (would possibly cause 1909 * "flashing" too). However, if the copy region is already empty, 1910 * we don't have to crop (can't take anything away from an empty 1911 * region...) 1912 */ 1913 1914 CopyRgn = IntSysCreateRectpRgn(0, 0, 0, 0); 1915 if (WinPos.flags & SWP_NOSIZE) 1916 RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND); 1917 else if (VisBeforeJustClient != NULL) 1918 { 1919 RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND); 1920 REGION_Delete(VisBeforeJustClient); 1921 } 1922 1923 /* Now use in copying bits which are in the update region. */ 1924 if (Window->hrgnUpdate != NULL) 1925 { 1926 PREGION RgnUpdate = REGION_LockRgn(Window->hrgnUpdate); 1927 if (RgnUpdate) 1928 { 1929 REGION_bOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top); 1930 IntGdiCombineRgn(CopyRgn, CopyRgn, RgnUpdate, RGN_DIFF); 1931 REGION_bOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top); 1932 REGION_UnlockRgn(RgnUpdate); 1933 } 1934 } 1935 1936 /* 1937 * Now, get the bounding box of the copy region. If it's empty 1938 * there's nothing to copy. Also, it's no use copying bits onto 1939 * themselves. 1940 */ 1941 if (REGION_GetRgnBox(CopyRgn, &CopyRect) == NULLREGION) 1942 { 1943 /* Nothing to copy, clean up */ 1944 REGION_Delete(CopyRgn); 1945 CopyRgn = NULL; 1946 } 1947 else if ( OldWindowRect.left != NewWindowRect.left || 1948 OldWindowRect.top != NewWindowRect.top || 1949 (WinPos.flags & SWP_FRAMECHANGED) ) 1950 { 1951 HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0); 1952 PREGION DcRgnObj = REGION_LockRgn(DcRgn); 1953 1954 /* 1955 * Small trick here: there is no function to bitblt a region. So 1956 * we set the region as the clipping region, take the bounding box 1957 * of the region and bitblt that. Since nothing outside the clipping 1958 * region is copied, this has the effect of bitblt'ing the region. 1959 * 1960 * Since NtUserGetDCEx takes ownership of the clip region, we need 1961 * to create a copy of CopyRgn and pass that. We need CopyRgn later 1962 */ 1963 IntGdiCombineRgn(DcRgnObj, CopyRgn, NULL, RGN_COPY); 1964 REGION_bOffsetRgn(DcRgnObj, NewWindowRect.left, NewWindowRect.top); 1965 REGION_UnlockRgn(DcRgnObj); 1966 Dc = UserGetDCEx( Window, 1967 DcRgn, 1968 DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN); // DCX_WINDOW will set first, go read WinDC.c. 1969 NtGdiBitBlt( Dc, 1970 CopyRect.left, CopyRect.top, 1971 CopyRect.right - CopyRect.left, 1972 CopyRect.bottom - CopyRect.top, 1973 Dc, 1974 CopyRect.left + (OldWindowRect.left - NewWindowRect.left), 1975 CopyRect.top + (OldWindowRect.top - NewWindowRect.top), 1976 SRCCOPY, 1977 0, 1978 0); 1979 1980 UserReleaseDC(Window, Dc, FALSE); 1981 IntValidateParent(Window, CopyRgn); 1982 GreDeleteObject(DcRgn); 1983 } 1984 } 1985 else 1986 { 1987 CopyRgn = NULL; 1988 } 1989 1990 if ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) && VisBefore ) 1991 { 1992 PWND pwnd = Window; 1993 PWND Parent = pwnd->spwndParent; 1994 1995 TRACE("SWP_FRAMECHANGED no chg\n"); 1996 1997 if ( pwnd->style & WS_CHILD ) // Fix ProgMan menu bar drawing. 1998 { 1999 TRACE("SWP_FRAMECHANGED win child %p Parent %p\n",pwnd,Parent); 2000 pwnd = Parent ? Parent : pwnd; 2001 } 2002 2003 if ( !(pwnd->style & WS_CHILD) ) 2004 { 2005 HDC hdc; 2006 HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0); 2007 PREGION DcRgnObj = REGION_LockRgn(DcRgn); 2008 2009 TRACE("SWP_FRAMECHANGED Draw\n"); 2010 2011 IntGdiCombineRgn(DcRgnObj, VisBefore, NULL, RGN_COPY); 2012 REGION_UnlockRgn(DcRgnObj); 2013 2014 hdc = UserGetDCEx( pwnd, 2015 DcRgn, 2016 DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN); // DCX_WINDOW, see note above.... 2017 2018 NC_DoNCPaint(pwnd, hdc, -1); // Force full redraw of nonclient area. 2019 2020 UserReleaseDC(pwnd, hdc, FALSE); 2021 IntValidateParent(pwnd, DcRgnObj); 2022 GreDeleteObject(DcRgn); 2023 } 2024 } 2025 2026 /* We need to redraw what wasn't visible before */ 2027 if (VisAfter != NULL) 2028 { 2029 PREGION DirtyRgn = IntSysCreateRectpRgn(0, 0, 0, 0); 2030 if (DirtyRgn) 2031 { 2032 if (CopyRgn != NULL) 2033 { 2034 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF); 2035 } 2036 else 2037 { 2038 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY); 2039 } 2040 2041 if (RgnType != ERROR && RgnType != NULLREGION) 2042 { 2043 /* old code 2044 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top); 2045 IntInvalidateWindows( Window, 2046 DirtyRgn, 2047 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); 2048 } 2049 GreDeleteObject(DirtyRgn); 2050 */ 2051 2052 PWND Parent = Window->spwndParent; 2053 2054 REGION_bOffsetRgn( DirtyRgn, Window->rcWindow.left, Window->rcWindow.top); 2055 2056 if ( (Window->style & WS_CHILD) && (Parent) && !(Parent->style & WS_CLIPCHILDREN)) 2057 { 2058 IntInvalidateWindows( Parent, DirtyRgn, RDW_ERASE | RDW_INVALIDATE); 2059 co_IntPaintWindows(Parent, RDW_NOCHILDREN, FALSE); 2060 } 2061 else 2062 { 2063 IntInvalidateWindows( Window, DirtyRgn, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); 2064 } 2065 } 2066 REGION_Delete(DirtyRgn); 2067 } 2068 } 2069 2070 if (CopyRgn != NULL) 2071 { 2072 REGION_Delete(CopyRgn); 2073 } 2074 2075 /* Expose what was covered before but not covered anymore */ 2076 if (VisBefore != NULL) 2077 { 2078 PREGION ExposedRgn = IntSysCreateRectpRgn(0, 0, 0, 0); 2079 if (ExposedRgn) 2080 { 2081 RgnType = IntGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY); 2082 REGION_bOffsetRgn(ExposedRgn, 2083 OldWindowRect.left - NewWindowRect.left, 2084 OldWindowRect.top - NewWindowRect.top); 2085 2086 if (VisAfter != NULL) 2087 RgnType = IntGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF); 2088 2089 if (RgnType != ERROR && RgnType != NULLREGION) 2090 { 2091 co_VIS_WindowLayoutChanged(Window, ExposedRgn); 2092 } 2093 REGION_Delete(ExposedRgn); 2094 } 2095 REGION_Delete(VisBefore); 2096 } 2097 2098 if (VisAfter != NULL) 2099 { 2100 REGION_Delete(VisAfter); 2101 } 2102 } 2103 2104 if (!(WinPos.flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW))) 2105 { 2106 if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD) 2107 { 2108 co_IntSendMessageNoWait(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0); 2109 } 2110 else 2111 { 2112 //ERR("SetWindowPos Set FG Window!\n"); 2113 if ( pti->MessageQueue->spwndActive != Window || 2114 pti->MessageQueue != gpqForeground ) 2115 { 2116 //ERR("WPSWP : set active window\n"); 2117 if (!(Window->state & WNDS_BEINGACTIVATED)) // Inside SAW? 2118 { 2119 co_IntSetForegroundWindow(Window); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow. 2120 } 2121 } 2122 } 2123 } 2124 2125 if ( !PosChanged && 2126 (WinPos.flags & SWP_FRAMECHANGED) && 2127 !(WinPos.flags & SWP_DEFERERASE) && // Prevent sending WM_SYNCPAINT message. 2128 VisAfter ) 2129 { 2130 PWND Parent = Window->spwndParent; 2131 if ( !(Window->style & WS_CHILD) && (Parent) && (Parent->style & WS_CLIPCHILDREN)) 2132 { 2133 TRACE("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n"); 2134 UserSyncAndPaintWindows( Parent, RDW_CLIPCHILDREN); 2135 } 2136 } 2137 2138 // Fix wine msg test_SetFocus, prevents sending WM_WINDOWPOSCHANGED. 2139 if ( VisBefore == NULL && 2140 VisBeforeJustClient == NULL && 2141 !(Window->ExStyle & WS_EX_TOPMOST) && 2142 (WinPos.flags & SWP_AGG_STATUSFLAGS) == (SWP_AGG_NOPOSCHANGE & ~SWP_NOZORDER)) 2143 { 2144 TRACE("No drawing, set no Z order and no redraw!\n"); 2145 WinPos.flags |= SWP_NOZORDER|SWP_NOREDRAW; 2146 } 2147 2148 if(!(flags & SWP_DEFERERASE)) 2149 { 2150 /* erase parent when hiding or resizing child */ 2151 if ((flags & SWP_HIDEWINDOW) || 2152 (!(flags & SWP_SHOWWINDOW) && 2153 (WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOGEOMETRYCHANGE)) 2154 { 2155 PWND Parent = Window->spwndParent; 2156 if (!Parent || UserIsDesktopWindow(Parent)) Parent = Window; 2157 UserSyncAndPaintWindows( Parent, RDW_ERASENOW); 2158 } 2159 2160 /* Give newly shown windows a chance to redraw */ 2161 if(((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) 2162 && !(flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW)) 2163 { 2164 UserSyncAndPaintWindows( Window, RDW_ERASENOW); 2165 } 2166 } 2167 2168 /* And last, send the WM_WINDOWPOSCHANGED message */ 2169 2170 TRACE("\tstatus hwnd %p flags = %04x\n",Window?Window->head.h:NULL,WinPos.flags & SWP_AGG_STATUSFLAGS); 2171 2172 if (((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) 2173 && !((flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW))) 2174 { 2175 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set 2176 and always contains final window position. 2177 */ 2178 WinPos.x = NewWindowRect.left; 2179 WinPos.y = NewWindowRect.top; 2180 WinPos.cx = NewWindowRect.right - NewWindowRect.left; 2181 WinPos.cy = NewWindowRect.bottom - NewWindowRect.top; 2182 TRACE("WM_WINDOWPOSCHANGED hwnd %p Flags %04x\n",WinPos.hwnd,WinPos.flags); 2183 co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos); 2184 } 2185 2186 if ( WinPos.flags & SWP_FRAMECHANGED || WinPos.flags & SWP_STATECHANGED || 2187 !(WinPos.flags & SWP_NOCLIENTSIZE) || !(WinPos.flags & SWP_NOCLIENTMOVE) ) 2188 { 2189 PWND pWnd = ValidateHwndNoErr(WinPos.hwnd); 2190 if (pWnd) 2191 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); 2192 } 2193 2194 if(bPointerInWindow != IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y)) 2195 { 2196 /* Generate mouse move message */ 2197 MSG msg; 2198 msg.message = WM_MOUSEMOVE; 2199 msg.wParam = UserGetMouseButtonsState(); 2200 msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y); 2201 msg.pt = gpsi->ptCursor; 2202 co_MsqInsertMouseMessage(&msg, 0, 0, TRUE); 2203 } 2204 2205 return TRUE; 2206 } 2207 2208 LRESULT FASTCALL 2209 co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect) 2210 { 2211 LRESULT Result; 2212 2213 ASSERT_REFS_CO(Window); 2214 2215 *ClientRect = *WindowRect; 2216 Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect); 2217 2218 FixClientRect(ClientRect, WindowRect); 2219 2220 return Result; 2221 } 2222 2223 void FASTCALL 2224 co_WinPosSendSizeMove(PWND Wnd) 2225 { 2226 RECTL Rect; 2227 LPARAM lParam; 2228 WPARAM wParam = SIZE_RESTORED; 2229 2230 IntGetClientRect(Wnd, &Rect); 2231 lParam = MAKELONG(Rect.right-Rect.left, Rect.bottom-Rect.top); 2232 2233 Wnd->state &= ~WNDS_SENDSIZEMOVEMSGS; 2234 2235 if (Wnd->style & WS_MAXIMIZE) 2236 { 2237 wParam = SIZE_MAXIMIZED; 2238 } 2239 else if (Wnd->style & WS_MINIMIZE) 2240 { 2241 wParam = SIZE_MINIMIZED; 2242 lParam = 0; 2243 } 2244 2245 co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SIZE, wParam, lParam); 2246 2247 if (UserIsDesktopWindow(Wnd->spwndParent)) 2248 lParam = MAKELONG(Wnd->rcClient.left, Wnd->rcClient.top); 2249 else 2250 lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top); 2251 2252 co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_MOVE, 0, lParam); 2253 2254 IntEngWindowChanged(Wnd, WOC_RGN_CLIENT); 2255 } 2256 2257 UINT FASTCALL 2258 co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) 2259 { 2260 POINT Size; 2261 WINDOWPLACEMENT wpl; 2262 LONG old_style; 2263 UINT SwpFlags = 0; 2264 2265 ASSERT_REFS_CO(Wnd); 2266 2267 wpl.length = sizeof(wpl); 2268 IntGetWindowPlacement( Wnd, &wpl ); 2269 2270 if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag)) 2271 { 2272 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n"); 2273 return SWP_NOSIZE | SWP_NOMOVE; 2274 } 2275 if (Wnd->style & WS_MINIMIZE) 2276 { 2277 switch (ShowFlag) 2278 { 2279 case SW_MINIMIZE: 2280 case SW_SHOWMINNOACTIVE: 2281 case SW_SHOWMINIMIZED: 2282 case SW_FORCEMINIMIZE: 2283 return SWP_NOSIZE | SWP_NOMOVE; 2284 } 2285 if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0)) 2286 { 2287 return(SWP_NOSIZE | SWP_NOMOVE); 2288 } 2289 SwpFlags |= SWP_NOCOPYBITS; 2290 } 2291 switch (ShowFlag) 2292 { 2293 case SW_MINIMIZE: 2294 case SW_SHOWMINNOACTIVE: 2295 case SW_SHOWMINIMIZED: 2296 case SW_FORCEMINIMIZE: 2297 { 2298 //ERR("MinMaximize Minimize\n"); 2299 if (Wnd->style & WS_MAXIMIZE) 2300 { 2301 Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED; 2302 } 2303 else 2304 { 2305 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; 2306 } 2307 2308 old_style = IntSetStyle( Wnd, WS_MINIMIZE, WS_MAXIMIZE ); 2309 2310 co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT); 2311 2312 if (!(Wnd->InternalPos.flags & WPF_SETMINPOSITION)) 2313 Wnd->InternalPos.flags &= ~WPF_MININIT; 2314 2315 WinPosFindIconPos(Wnd, &wpl.ptMinPosition); 2316 2317 if (!(old_style & WS_MINIMIZE)) 2318 { 2319 SwpFlags |= SWP_STATECHANGED; 2320 IntShowOwnedPopups(Wnd, FALSE); 2321 } 2322 2323 RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y, 2324 wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED), 2325 wpl.ptMinPosition.y + UserGetSystemMetrics(SM_CYMINIMIZED)); 2326 SwpFlags |= SWP_NOCOPYBITS; 2327 break; 2328 } 2329 2330 case SW_MAXIMIZE: 2331 { 2332 //ERR("MinMaximize Maximize\n"); 2333 if ((Wnd->style & WS_MAXIMIZE) && (Wnd->style & WS_VISIBLE)) 2334 { 2335 SwpFlags = SWP_NOSIZE | SWP_NOMOVE; 2336 break; 2337 } 2338 co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); 2339 2340 /*ERR("Maximize: %d,%d %dx%d\n", 2341 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y); 2342 */ 2343 old_style = IntSetStyle( Wnd, WS_MAXIMIZE, WS_MINIMIZE ); 2344 /*if (old_style & WS_MINIMIZE) 2345 { 2346 IntShowOwnedPopups(Wnd, TRUE); 2347 }*/ 2348 2349 if (!(old_style & WS_MAXIMIZE)) 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 Size.x, Size.y); 2353 break; 2354 } 2355 2356 case SW_SHOWNOACTIVATE: 2357 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; 2358 /* fall through */ 2359 case SW_SHOWNORMAL: 2360 case SW_RESTORE: 2361 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */ 2362 { 2363 //ERR("MinMaximize Restore\n"); 2364 old_style = IntSetStyle( Wnd, 0, WS_MINIMIZE | WS_MAXIMIZE ); 2365 if (old_style & WS_MINIMIZE) 2366 { 2367 IntShowOwnedPopups(Wnd, TRUE); 2368 2369 if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED) 2370 { 2371 co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); 2372 IntSetStyle( Wnd, WS_MAXIMIZE, 0 ); 2373 SwpFlags |= SWP_STATECHANGED; 2374 RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, 2375 wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y); 2376 break; 2377 } 2378 else 2379 { 2380 *NewPos = wpl.rcNormalPosition; 2381 NewPos->right -= NewPos->left; 2382 NewPos->bottom -= NewPos->top; 2383 break; 2384 } 2385 } 2386 else 2387 { 2388 if (!(old_style & WS_MAXIMIZE)) 2389 { 2390 break; 2391 } 2392 SwpFlags |= SWP_STATECHANGED; 2393 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; 2394 *NewPos = wpl.rcNormalPosition; 2395 NewPos->right -= NewPos->left; 2396 NewPos->bottom -= NewPos->top; 2397 break; 2398 } 2399 } 2400 } 2401 return SwpFlags; 2402 } 2403 2404 /* 2405 ShowWindow does not set SWP_FRAMECHANGED!!! Fix wine msg test_SetParent:WmSetParentSeq_2:23 wParam bits! 2406 */ 2407 BOOLEAN FASTCALL 2408 co_WinPosShowWindow(PWND Wnd, INT Cmd) 2409 { 2410 BOOLEAN WasVisible; 2411 UINT Swp = 0, EventMsg = 0; 2412 RECTL NewPos = {0, 0, 0, 0}; 2413 BOOLEAN ShowFlag; 2414 LONG style; 2415 PWND Parent; 2416 PTHREADINFO pti; 2417 //HRGN VisibleRgn; 2418 BOOL ShowOwned = FALSE; 2419 BOOL FirstTime = FALSE; 2420 ASSERT_REFS_CO(Wnd); 2421 //KeRosDumpStackFrames(NULL, 20); 2422 pti = PsGetCurrentThreadWin32Thread(); 2423 WasVisible = (Wnd->style & WS_VISIBLE) != 0; 2424 style = Wnd->style; 2425 2426 TRACE("co_WinPosShowWindow START hwnd %p Cmd %d usicmd %u\n", 2427 Wnd->head.h, Cmd, pti->ppi->usi.wShowWindow); 2428 2429 if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW ) 2430 { 2431 if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) 2432 { 2433 if ((Wnd->style & WS_CAPTION) == WS_CAPTION) 2434 { 2435 if (Wnd->spwndOwner == NULL) 2436 { 2437 if ( Cmd == SW_SHOWNORMAL || Cmd == SW_SHOW) 2438 { 2439 Cmd = SW_SHOWDEFAULT; 2440 } 2441 FirstTime = TRUE; 2442 TRACE("co_WPSW FT 1\n"); 2443 } 2444 } 2445 } 2446 } 2447 2448 if ( Cmd == SW_SHOWDEFAULT ) 2449 { 2450 if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW ) 2451 { 2452 Cmd = pti->ppi->usi.wShowWindow; 2453 FirstTime = TRUE; 2454 TRACE("co_WPSW FT 2\n"); 2455 } 2456 } 2457 2458 if (FirstTime) 2459 { 2460 pti->ppi->usi.dwFlags &= ~(STARTF_USEPOSITION|STARTF_USESIZE|STARTF_USESHOWWINDOW); 2461 } 2462 2463 switch (Cmd) 2464 { 2465 case SW_HIDE: 2466 { 2467 if (!WasVisible) 2468 { 2469 //ERR("co_WinPosShowWindow Exit Bad\n"); 2470 return FALSE; 2471 } 2472 Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE; 2473 if (Wnd != pti->MessageQueue->spwndActive) 2474 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2475 break; 2476 } 2477 2478 case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */ 2479 case SW_SHOWMINNOACTIVE: 2480 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2481 /* Fall through. */ 2482 case SW_SHOWMINIMIZED: 2483 Swp |= SWP_SHOWWINDOW; 2484 /* Fall through. */ 2485 case SW_MINIMIZE: 2486 { 2487 Swp |= SWP_NOACTIVATE; 2488 if (!(style & WS_MINIMIZE)) 2489 { 2490 IntShowOwnedPopups(Wnd, FALSE ); 2491 // Fix wine Win test_SetFocus todo #1 & #2, 2492 if (Cmd == SW_SHOWMINIMIZED) 2493 { 2494 //ERR("co_WinPosShowWindow Set focus 1\n"); 2495 if ((style & (WS_CHILD | WS_POPUP)) == WS_CHILD) 2496 co_UserSetFocus(Wnd->spwndParent); 2497 else 2498 co_UserSetFocus(0); 2499 } 2500 2501 Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos); 2502 2503 EventMsg = EVENT_SYSTEM_MINIMIZESTART; 2504 } 2505 else 2506 { 2507 if (WasVisible) 2508 { 2509 //ERR("co_WinPosShowWindow Exit Good\n"); 2510 return TRUE; 2511 } 2512 Swp |= SWP_NOSIZE | SWP_NOMOVE; 2513 } 2514 break; 2515 } 2516 2517 case SW_SHOWMAXIMIZED: 2518 { 2519 Swp |= SWP_SHOWWINDOW; 2520 if (!(style & WS_MAXIMIZE)) 2521 { 2522 ShowOwned = TRUE; 2523 2524 Swp |= co_WinPosMinMaximize(Wnd, SW_MAXIMIZE, &NewPos); 2525 2526 EventMsg = EVENT_SYSTEM_MINIMIZEEND; 2527 } 2528 else 2529 { 2530 if (WasVisible) 2531 { 2532 //ERR("co_WinPosShowWindow Exit Good 1\n"); 2533 return TRUE; 2534 } 2535 Swp |= SWP_NOSIZE | SWP_NOMOVE; 2536 } 2537 break; 2538 } 2539 2540 case SW_SHOWNA: 2541 Swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; 2542 if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOZORDER; 2543 break; 2544 case SW_SHOW: 2545 if (WasVisible) return(TRUE); // Nothing to do! 2546 Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; 2547 /* Don't activate the topmost window. */ 2548 if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2549 break; 2550 2551 case SW_SHOWNOACTIVATE: 2552 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2553 /* Fall through. */ 2554 case SW_SHOWNORMAL: 2555 case SW_SHOWDEFAULT: 2556 case SW_RESTORE: 2557 if (!WasVisible) Swp |= SWP_SHOWWINDOW; 2558 if (style & (WS_MINIMIZE | WS_MAXIMIZE)) 2559 { 2560 Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos); 2561 if (style & WS_MINIMIZE) EventMsg = EVENT_SYSTEM_MINIMIZEEND; 2562 } 2563 else 2564 { 2565 if (WasVisible) 2566 { 2567 //ERR("co_WinPosShowWindow Exit Good 3\n"); 2568 return TRUE; 2569 } 2570 Swp |= SWP_NOSIZE | SWP_NOMOVE; 2571 } 2572 if ( style & WS_CHILD && 2573 !(Wnd->ExStyle & WS_EX_MDICHILD) && 2574 !(Swp & SWP_STATECHANGED)) 2575 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2576 break; 2577 2578 default: 2579 //ERR("co_WinPosShowWindow Exit Good 4\n"); 2580 return WasVisible; 2581 } 2582 2583 ShowFlag = (Cmd != SW_HIDE); 2584 2585 if ((ShowFlag != WasVisible || Cmd == SW_SHOWNA) && Cmd != SW_SHOWMAXIMIZED && !(Swp & SWP_STATECHANGED)) 2586 { 2587 co_IntSendMessageNoWait(Wnd->head.h, WM_SHOWWINDOW, ShowFlag, 0); 2588 #if 0 // Fix wine msg test_SetParent:WmSetParentSeq_1:2 2589 if (!(Wnd->state2 & WNDS2_WIN31COMPAT)) // <------------- XP sets this bit! 2590 co_IntSendMessageNoWait(Wnd->head.h, WM_SETVISIBLE, ShowFlag, 0); 2591 #endif 2592 if (!VerifyWnd(Wnd)) return WasVisible; 2593 } 2594 2595 /* We can't activate a child window */ 2596 if ((Wnd->style & WS_CHILD) && 2597 !(Wnd->ExStyle & WS_EX_MDICHILD) && 2598 Cmd != SW_SHOWNA) 2599 { 2600 //ERR("SWP Child No active and ZOrder\n"); 2601 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2602 } 2603 2604 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works. 2605 // Breaks startup and shutdown active window... 2606 if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD && 2607 Wnd->pcls->style & CS_SAVEBITS && 2608 ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL))) 2609 { 2610 ERR("WinPosShowWindow Set active\n"); 2611 //UserSetActiveWindow(Wnd); 2612 co_IntSetForegroundWindow(Wnd); // HACK 2613 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2614 } 2615 #endif 2616 2617 if (IsChildVisible(Wnd) || Swp & SWP_STATECHANGED) 2618 { 2619 TRACE("Child is Vis %s or State changed %s. ShowFlag %s Swp %04x\n", 2620 (IsChildVisible(Wnd) ? "TRUE" : "FALSE"), (Swp & SWP_STATECHANGED ? "TRUE" : "FALSE"), 2621 (ShowFlag ? "TRUE" : "FALSE"),LOWORD(Swp)); 2622 co_WinPosSetWindowPos( Wnd, 2623 0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP, 2624 NewPos.left, 2625 NewPos.top, 2626 NewPos.right, // NewPos.right - NewPos.left, when minimized and restore, the window becomes smaller. 2627 NewPos.bottom,// NewPos.bottom - NewPos.top, 2628 LOWORD(Swp)); 2629 } 2630 else 2631 { 2632 TRACE("Parent Vis?\n"); 2633 /* if parent is not visible simply toggle WS_VISIBLE and return */ 2634 if (ShowFlag) IntSetStyle( Wnd, WS_VISIBLE, 0 ); 2635 else IntSetStyle( Wnd, 0, WS_VISIBLE ); 2636 } 2637 2638 if ( EventMsg ) IntNotifyWinEvent(EventMsg, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); 2639 2640 if ( ShowOwned ) IntShowOwnedPopups(Wnd, TRUE ); 2641 2642 if ((Cmd == SW_HIDE) || (Cmd == SW_MINIMIZE)) 2643 { 2644 if ( Wnd == pti->MessageQueue->spwndActive && pti->MessageQueue == IntGetFocusMessageQueue() ) 2645 { 2646 if (UserIsDesktopWindow(Wnd->spwndParent)) 2647 { 2648 if (!ActivateOtherWindowMin(Wnd)) 2649 { 2650 co_WinPosActivateOtherWindow(Wnd); 2651 } 2652 } 2653 else 2654 { 2655 co_WinPosActivateOtherWindow(Wnd); 2656 } 2657 } 2658 2659 /* Revert focus to parent */ 2660 if (Wnd == pti->MessageQueue->spwndFocus) 2661 { 2662 Parent = Wnd->spwndParent; 2663 if (UserIsDesktopWindow(Wnd->spwndParent)) 2664 Parent = 0; 2665 co_UserSetFocus(Parent); 2666 } 2667 // Hide, just return. 2668 if (Cmd == SW_HIDE) return WasVisible; 2669 } 2670 2671 /* FIXME: Check for window destruction. */ 2672 2673 if ((Wnd->state & WNDS_SENDSIZEMOVEMSGS) && 2674 !(Wnd->state2 & WNDS2_INDESTROY)) 2675 { 2676 co_WinPosSendSizeMove(Wnd); 2677 } 2678 2679 /* if previous state was minimized Windows sets focus to the window */ 2680 if (style & WS_MINIMIZE) 2681 { 2682 co_UserSetFocus(Wnd); 2683 // Fix wine Win test_SetFocus todo #3, 2684 if (!(style & WS_CHILD)) co_IntSendMessage(UserHMGetHandle(Wnd), WM_ACTIVATE, WA_ACTIVE, 0); 2685 } 2686 //ERR("co_WinPosShowWindow EXIT\n"); 2687 return WasVisible; 2688 } 2689 2690 static PWND 2691 co_WinPosSearchChildren( 2692 IN PWND ScopeWin, 2693 IN POINT *Point, 2694 IN OUT USHORT *HitTest, 2695 IN BOOL Ignore 2696 ) 2697 { 2698 HWND *List, *phWnd; 2699 PWND pwndChild = NULL; 2700 2701 /* not visible */ 2702 if (!(ScopeWin->style & WS_VISIBLE)) 2703 { 2704 return NULL; 2705 } 2706 2707 /* not in window or in window region */ 2708 if (!IntPtInWindow(ScopeWin, Point->x, Point->y)) 2709 { 2710 return NULL; 2711 } 2712 2713 /* transparent */ 2714 if ((ScopeWin->ExStyle & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == (WS_EX_LAYERED|WS_EX_TRANSPARENT)) 2715 { 2716 return NULL; 2717 } 2718 2719 if (!Ignore && (ScopeWin->style & WS_DISABLED)) 2720 { /* disabled child */ 2721 if ((ScopeWin->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return NULL; 2722 /* process the hit error */ 2723 *HitTest = HTERROR; 2724 return ScopeWin; 2725 } 2726 2727 /* not minimized and check if point is inside the window */ 2728 if (!(ScopeWin->style & WS_MINIMIZE) && 2729 RECTL_bPointInRect(&ScopeWin->rcClient, Point->x, Point->y) ) 2730 { 2731 UserReferenceObject(ScopeWin); 2732 2733 List = IntWinListChildren(ScopeWin); 2734 if (List) 2735 { 2736 for (phWnd = List; *phWnd; ++phWnd) 2737 { 2738 if (!(pwndChild = ValidateHwndNoErr(*phWnd))) 2739 { 2740 continue; 2741 } 2742 2743 pwndChild = co_WinPosSearchChildren(pwndChild, Point, HitTest, Ignore); 2744 2745 if (pwndChild != NULL) 2746 { 2747 /* We found a window. Don't send any more WM_NCHITTEST messages */ 2748 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2749 UserDereferenceObject(ScopeWin); 2750 return pwndChild; 2751 } 2752 } 2753 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2754 } 2755 UserDereferenceObject(ScopeWin); 2756 } 2757 2758 if (ScopeWin->head.pti == PsGetCurrentThreadWin32Thread()) 2759 { 2760 *HitTest = (USHORT)co_IntSendMessage(ScopeWin->head.h, WM_NCHITTEST, 0, MAKELONG(Point->x, Point->y)); 2761 2762 if ((*HitTest) == (USHORT)HTTRANSPARENT) 2763 { 2764 return NULL; 2765 } 2766 } 2767 else 2768 { 2769 if (*HitTest == HTNOWHERE && pwndChild == NULL) *HitTest = HTCLIENT; 2770 } 2771 2772 return ScopeWin; 2773 } 2774 2775 PWND APIENTRY 2776 co_WinPosWindowFromPoint( 2777 IN PWND ScopeWin, 2778 IN POINT *WinPoint, 2779 IN OUT USHORT* HitTest, 2780 IN BOOL Ignore) 2781 { 2782 PWND Window; 2783 POINT Point = *WinPoint; 2784 USER_REFERENCE_ENTRY Ref; 2785 2786 if( ScopeWin == NULL ) 2787 { 2788 ScopeWin = UserGetDesktopWindow(); 2789 if(ScopeWin == NULL) 2790 return NULL; 2791 } 2792 2793 *HitTest = HTNOWHERE; 2794 2795 ASSERT_REFS_CO(ScopeWin); 2796 UserRefObjectCo(ScopeWin, &Ref); 2797 2798 Window = co_WinPosSearchChildren(ScopeWin, &Point, HitTest, Ignore); 2799 2800 UserDerefObjectCo(ScopeWin); 2801 if (Window) 2802 ASSERT_REFS_CO(Window); 2803 ASSERT_REFS_CO(ScopeWin); 2804 2805 return Window; 2806 } 2807 2808 PWND FASTCALL 2809 IntRealChildWindowFromPoint(PWND Parent, LONG x, LONG y) 2810 { 2811 POINTL Pt; 2812 HWND *List, *phWnd; 2813 PWND pwndHit = NULL; 2814 2815 Pt.x = x; 2816 Pt.y = y; 2817 2818 if (!UserIsDesktopWindow(Parent)) 2819 { 2820 Pt.x += Parent->rcClient.left; 2821 Pt.y += Parent->rcClient.top; 2822 } 2823 2824 if (!IntPtInWindow(Parent, Pt.x, Pt.y)) return NULL; 2825 2826 if ((List = IntWinListChildren(Parent))) 2827 { 2828 for (phWnd = List; *phWnd; phWnd++) 2829 { 2830 PWND Child; 2831 if ((Child = ValidateHwndNoErr(*phWnd))) 2832 { 2833 if ( Child->style & WS_VISIBLE && IntPtInWindow(Child, Pt.x, Pt.y) ) 2834 { 2835 if ( Child->pcls->atomClassName != gpsi->atomSysClass[ICLS_BUTTON] || 2836 (Child->style & BS_TYPEMASK) != BS_GROUPBOX ) 2837 { 2838 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2839 return Child; 2840 } 2841 pwndHit = Child; 2842 } 2843 } 2844 } 2845 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2846 } 2847 return pwndHit ? pwndHit : Parent; 2848 } 2849 2850 PWND APIENTRY 2851 IntChildWindowFromPointEx(PWND Parent, LONG x, LONG y, UINT uiFlags) 2852 { 2853 POINTL Pt; 2854 HWND *List, *phWnd; 2855 PWND pwndHit = NULL; 2856 2857 Pt.x = x; 2858 Pt.y = y; 2859 2860 if (!UserIsDesktopWindow(Parent)) 2861 { 2862 if (Parent->ExStyle & WS_EX_LAYOUTRTL) 2863 Pt.x = Parent->rcClient.right - Pt.x; 2864 else 2865 Pt.x += Parent->rcClient.left; 2866 Pt.y += Parent->rcClient.top; 2867 } 2868 2869 if (!IntPtInWindow(Parent, Pt.x, Pt.y)) return NULL; 2870 2871 if ((List = IntWinListChildren(Parent))) 2872 { 2873 for (phWnd = List; *phWnd; phWnd++) 2874 { 2875 PWND Child; 2876 if ((Child = ValidateHwndNoErr(*phWnd))) 2877 { 2878 if (uiFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED)) 2879 { 2880 if (!(Child->style & WS_VISIBLE) && (uiFlags & CWP_SKIPINVISIBLE)) continue; 2881 if ((Child->style & WS_DISABLED) && (uiFlags & CWP_SKIPDISABLED)) continue; 2882 } 2883 2884 if (uiFlags & CWP_SKIPTRANSPARENT) 2885 { 2886 if (Child->ExStyle & WS_EX_TRANSPARENT) continue; 2887 } 2888 2889 if (IntPtInWindow(Child, Pt.x, Pt.y)) 2890 { 2891 pwndHit = Child; 2892 break; 2893 } 2894 } 2895 } 2896 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2897 } 2898 return pwndHit ? pwndHit : Parent; 2899 } 2900 2901 HDWP 2902 FASTCALL 2903 IntDeferWindowPos( HDWP hdwp, 2904 HWND hwnd, 2905 HWND hwndAfter, 2906 INT x, 2907 INT y, 2908 INT cx, 2909 INT cy, 2910 UINT flags ) 2911 { 2912 PSMWP pDWP; 2913 int i; 2914 HDWP retvalue = hdwp; 2915 2916 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n", 2917 hdwp, hwnd, hwndAfter, x, y, cx, cy, flags); 2918 2919 if (flags & ~(SWP_NOSIZE | SWP_NOMOVE | 2920 SWP_NOZORDER | SWP_NOREDRAW | 2921 SWP_NOACTIVATE | SWP_NOCOPYBITS | 2922 SWP_NOOWNERZORDER|SWP_SHOWWINDOW | 2923 SWP_HIDEWINDOW | SWP_FRAMECHANGED)) 2924 { 2925 EngSetLastError(ERROR_INVALID_PARAMETER); 2926 return NULL; 2927 } 2928 2929 if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, TYPE_SETWINDOWPOS))) 2930 { 2931 EngSetLastError(ERROR_INVALID_DWP_HANDLE); 2932 return NULL; 2933 } 2934 2935 for (i = 0; i < pDWP->ccvr; i++) 2936 { 2937 if (pDWP->acvr[i].pos.hwnd == hwnd) 2938 { 2939 /* Merge with the other changes */ 2940 if (!(flags & SWP_NOZORDER)) 2941 { 2942 pDWP->acvr[i].pos.hwndInsertAfter = hwndAfter; 2943 } 2944 if (!(flags & SWP_NOMOVE)) 2945 { 2946 pDWP->acvr[i].pos.x = x; 2947 pDWP->acvr[i].pos.y = y; 2948 } 2949 if (!(flags & SWP_NOSIZE)) 2950 { 2951 pDWP->acvr[i].pos.cx = cx; 2952 pDWP->acvr[i].pos.cy = cy; 2953 } 2954 pDWP->acvr[i].pos.flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE | 2955 SWP_NOZORDER | SWP_NOREDRAW | 2956 SWP_NOACTIVATE | SWP_NOCOPYBITS| 2957 SWP_NOOWNERZORDER); 2958 pDWP->acvr[i].pos.flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | 2959 SWP_FRAMECHANGED); 2960 goto END; 2961 } 2962 } 2963 if (pDWP->ccvr >= pDWP->ccvrAlloc) 2964 { 2965 PCVR newpos = ExAllocatePoolWithTag(PagedPool, pDWP->ccvrAlloc * 2 * sizeof(CVR), USERTAG_SWP); 2966 if (!newpos) 2967 { 2968 retvalue = NULL; 2969 goto END; 2970 } 2971 RtlZeroMemory(newpos, pDWP->ccvrAlloc * 2 * sizeof(CVR)); 2972 RtlCopyMemory(newpos, pDWP->acvr, pDWP->ccvrAlloc * sizeof(CVR)); 2973 ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP); 2974 pDWP->ccvrAlloc *= 2; 2975 pDWP->acvr = newpos; 2976 } 2977 pDWP->acvr[pDWP->ccvr].pos.hwnd = hwnd; 2978 pDWP->acvr[pDWP->ccvr].pos.hwndInsertAfter = hwndAfter; 2979 pDWP->acvr[pDWP->ccvr].pos.x = x; 2980 pDWP->acvr[pDWP->ccvr].pos.y = y; 2981 pDWP->acvr[pDWP->ccvr].pos.cx = cx; 2982 pDWP->acvr[pDWP->ccvr].pos.cy = cy; 2983 pDWP->acvr[pDWP->ccvr].pos.flags = flags; 2984 pDWP->acvr[pDWP->ccvr].hrgnClip = NULL; 2985 pDWP->acvr[pDWP->ccvr].hrgnInterMonitor = NULL; 2986 pDWP->ccvr++; 2987 END: 2988 return retvalue; 2989 } 2990 2991 BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp, BOOL sAsync ) 2992 { 2993 PSMWP pDWP; 2994 PCVR winpos; 2995 BOOL res = TRUE; 2996 int i; 2997 2998 TRACE("%p\n", hdwp); 2999 3000 if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, TYPE_SETWINDOWPOS))) 3001 { 3002 EngSetLastError(ERROR_INVALID_DWP_HANDLE); 3003 return FALSE; 3004 } 3005 3006 for (i = 0, winpos = pDWP->acvr; res && i < pDWP->ccvr; i++, winpos++) 3007 { 3008 PWND pwnd; 3009 USER_REFERENCE_ENTRY Ref; 3010 3011 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n", 3012 winpos->pos.hwnd, winpos->pos.hwndInsertAfter, winpos->pos.x, winpos->pos.y, 3013 winpos->pos.cx, winpos->pos.cy, winpos->pos.flags); 3014 3015 pwnd = ValidateHwndNoErr(winpos->pos.hwnd); 3016 if (!pwnd) 3017 continue; 3018 3019 UserRefObjectCo(pwnd, &Ref); 3020 3021 if ( sAsync ) 3022 { 3023 LRESULT lRes; 3024 PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP); 3025 if ( ppos ) 3026 { 3027 *ppos = winpos->pos; 3028 /* Yes it's a pointer inside Win32k! */ 3029 lRes = co_IntSendMessageNoWait( winpos->pos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos); 3030 /* We handle this the same way as Event Hooks and Hooks. */ 3031 if ( !lRes ) 3032 { 3033 ExFreePoolWithTag(ppos, USERTAG_SWP); 3034 } 3035 } 3036 } 3037 else 3038 res = co_WinPosSetWindowPos( pwnd, 3039 winpos->pos.hwndInsertAfter, 3040 winpos->pos.x, 3041 winpos->pos.y, 3042 winpos->pos.cx, 3043 winpos->pos.cy, 3044 winpos->pos.flags); 3045 3046 // Hack to pass tests.... Must have some work to do so clear the error. 3047 if (res && (winpos->pos.flags & (SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER)) == SWP_NOZORDER ) 3048 EngSetLastError(ERROR_SUCCESS); 3049 3050 UserDerefObjectCo(pwnd); 3051 } 3052 ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP); 3053 UserDereferenceObject(pDWP); 3054 UserDeleteObject(hdwp, TYPE_SETWINDOWPOS); 3055 return res; 3056 } 3057 3058 /* 3059 * @implemented 3060 */ 3061 HWND APIENTRY 3062 NtUserChildWindowFromPointEx(HWND hwndParent, 3063 LONG x, 3064 LONG y, 3065 UINT uiFlags) 3066 { 3067 PWND pwndParent; 3068 TRACE("Enter NtUserChildWindowFromPointEx\n"); 3069 UserEnterExclusive(); 3070 if ((pwndParent = UserGetWindowObject(hwndParent))) 3071 { 3072 pwndParent = IntChildWindowFromPointEx(pwndParent, x, y, uiFlags); 3073 } 3074 UserLeave(); 3075 TRACE("Leave NtUserChildWindowFromPointEx\n"); 3076 return pwndParent ? UserHMGetHandle(pwndParent) : NULL; 3077 } 3078 3079 /* 3080 * @implemented 3081 */ 3082 BOOL APIENTRY 3083 NtUserEndDeferWindowPosEx(HDWP WinPosInfo, 3084 DWORD Unknown1) 3085 { 3086 BOOL Ret; 3087 TRACE("Enter NtUserEndDeferWindowPosEx\n"); 3088 UserEnterExclusive(); 3089 Ret = IntEndDeferWindowPosEx(WinPosInfo, (BOOL)Unknown1); 3090 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret); 3091 UserLeave(); 3092 return Ret; 3093 } 3094 3095 /* 3096 * @implemented 3097 */ 3098 HDWP APIENTRY 3099 NtUserDeferWindowPos(HDWP WinPosInfo, 3100 HWND Wnd, 3101 HWND WndInsertAfter, 3102 int x, 3103 int y, 3104 int cx, 3105 int cy, 3106 UINT Flags) 3107 { 3108 PWND pWnd, pWndIA; 3109 HDWP Ret = NULL; 3110 UINT Tmp = ~(SWP_ASYNCWINDOWPOS|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_NOREPOSITION| 3111 SWP_NOCOPYBITS|SWP_HIDEWINDOW|SWP_SHOWWINDOW|SWP_FRAMECHANGED| 3112 SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE); 3113 3114 TRACE("Enter NtUserDeferWindowPos\n"); 3115 UserEnterExclusive(); 3116 3117 if ( Flags & Tmp ) 3118 { 3119 EngSetLastError(ERROR_INVALID_FLAGS); 3120 goto Exit; 3121 } 3122 3123 pWnd = UserGetWindowObject(Wnd); 3124 if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd)) 3125 { 3126 goto Exit; 3127 } 3128 3129 if ( WndInsertAfter && 3130 WndInsertAfter != HWND_BOTTOM && 3131 WndInsertAfter != HWND_TOPMOST && 3132 WndInsertAfter != HWND_NOTOPMOST ) 3133 { 3134 pWndIA = UserGetWindowObject(WndInsertAfter); 3135 if (!pWndIA || UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA)) 3136 { 3137 goto Exit; 3138 } 3139 } 3140 3141 Ret = IntDeferWindowPos(WinPosInfo, Wnd, WndInsertAfter, x, y, cx, cy, Flags); 3142 3143 Exit: 3144 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret); 3145 UserLeave(); 3146 return Ret; 3147 } 3148 3149 /* 3150 * @implemented 3151 */ 3152 DWORD APIENTRY 3153 NtUserGetInternalWindowPos( HWND hWnd, 3154 LPRECT rectWnd, 3155 LPPOINT ptIcon) 3156 { 3157 PWND Window; 3158 DWORD Ret = 0; 3159 BOOL Hit = FALSE; 3160 WINDOWPLACEMENT wndpl; 3161 3162 UserEnterShared(); 3163 3164 if (!(Window = UserGetWindowObject(hWnd))) 3165 { 3166 Hit = FALSE; 3167 goto Exit; 3168 } 3169 3170 _SEH2_TRY 3171 { 3172 if(rectWnd) 3173 { 3174 ProbeForWrite(rectWnd, 3175 sizeof(RECT), 3176 1); 3177 } 3178 if(ptIcon) 3179 { 3180 ProbeForWrite(ptIcon, 3181 sizeof(POINT), 3182 1); 3183 } 3184 3185 } 3186 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3187 { 3188 SetLastNtError(_SEH2_GetExceptionCode()); 3189 Hit = TRUE; 3190 } 3191 _SEH2_END; 3192 3193 wndpl.length = sizeof(WINDOWPLACEMENT); 3194 3195 if (IntGetWindowPlacement(Window, &wndpl) && !Hit) 3196 { 3197 _SEH2_TRY 3198 { 3199 if (rectWnd) 3200 { 3201 RtlCopyMemory(rectWnd, &wndpl.rcNormalPosition , sizeof(RECT)); 3202 } 3203 if (ptIcon) 3204 { 3205 RtlCopyMemory(ptIcon, &wndpl.ptMinPosition, sizeof(POINT)); 3206 } 3207 3208 } 3209 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3210 { 3211 SetLastNtError(_SEH2_GetExceptionCode()); 3212 Hit = TRUE; 3213 } 3214 _SEH2_END; 3215 3216 if (!Hit) Ret = wndpl.showCmd; 3217 } 3218 Exit: 3219 UserLeave(); 3220 return Ret; 3221 } 3222 3223 /* 3224 * @implemented 3225 */ 3226 BOOL APIENTRY 3227 NtUserGetWindowPlacement(HWND hWnd, 3228 WINDOWPLACEMENT *lpwndpl) 3229 { 3230 PWND Wnd; 3231 WINDOWPLACEMENT Safepl; 3232 NTSTATUS Status; 3233 DECLARE_RETURN(BOOL); 3234 3235 TRACE("Enter NtUserGetWindowPlacement\n"); 3236 UserEnterShared(); 3237 3238 if (!(Wnd = UserGetWindowObject(hWnd))) 3239 { 3240 RETURN( FALSE); 3241 } 3242 3243 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT)); 3244 if (!NT_SUCCESS(Status)) 3245 { 3246 SetLastNtError(Status); 3247 RETURN( FALSE); 3248 } 3249 3250 Safepl.length = sizeof(WINDOWPLACEMENT); 3251 3252 IntGetWindowPlacement(Wnd, &Safepl); 3253 3254 Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT)); 3255 if (!NT_SUCCESS(Status)) 3256 { 3257 SetLastNtError(Status); 3258 RETURN( FALSE); 3259 } 3260 3261 RETURN( TRUE); 3262 3263 CLEANUP: 3264 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_); 3265 UserLeave(); 3266 END_CLEANUP; 3267 } 3268 3269 DWORD 3270 APIENTRY 3271 NtUserMinMaximize( 3272 HWND hWnd, 3273 UINT cmd, // Wine SW_ commands 3274 BOOL Hide) 3275 { 3276 PWND pWnd; 3277 3278 TRACE("Enter NtUserMinMaximize\n"); 3279 UserEnterExclusive(); 3280 3281 pWnd = UserGetWindowObject(hWnd); 3282 if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd)) 3283 { 3284 goto Exit; 3285 } 3286 3287 if ( cmd > SW_MAX || pWnd->state2 & WNDS2_INDESTROY) 3288 { 3289 EngSetLastError(ERROR_INVALID_PARAMETER); 3290 goto Exit; 3291 } 3292 3293 cmd |= Hide ? SW_HIDE : 0; 3294 3295 co_WinPosShowWindow(pWnd, cmd); 3296 3297 Exit: 3298 TRACE("Leave NtUserMinMaximize\n"); 3299 UserLeave(); 3300 return 0; // Always NULL? 3301 } 3302 3303 /* 3304 * @implemented 3305 */ 3306 BOOL APIENTRY 3307 NtUserMoveWindow( 3308 HWND hWnd, 3309 int X, 3310 int Y, 3311 int nWidth, 3312 int nHeight, 3313 BOOL bRepaint) 3314 { 3315 return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight, 3316 (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE : 3317 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW)); 3318 } 3319 3320 /* 3321 * @implemented 3322 */ 3323 HWND APIENTRY 3324 NtUserRealChildWindowFromPoint(HWND Parent, 3325 LONG x, 3326 LONG y) 3327 { 3328 PWND pwndParent; 3329 TRACE("Enter NtUserRealChildWindowFromPoint\n"); 3330 UserEnterShared(); 3331 if ((pwndParent = UserGetWindowObject(Parent))) 3332 { 3333 pwndParent = IntRealChildWindowFromPoint(pwndParent, x, y); 3334 } 3335 UserLeave(); 3336 TRACE("Leave NtUserRealChildWindowFromPoint\n"); 3337 return pwndParent ? UserHMGetHandle(pwndParent) : NULL; 3338 } 3339 3340 /* 3341 * @implemented 3342 */ 3343 BOOL APIENTRY 3344 NtUserSetWindowPos( 3345 HWND hWnd, 3346 HWND hWndInsertAfter, 3347 int X, 3348 int Y, 3349 int cx, 3350 int cy, 3351 UINT uFlags) 3352 { 3353 DECLARE_RETURN(BOOL); 3354 PWND Window, pWndIA; 3355 BOOL ret; 3356 USER_REFERENCE_ENTRY Ref; 3357 3358 TRACE("Enter NtUserSetWindowPos\n"); 3359 UserEnterExclusive(); 3360 3361 if (!(Window = UserGetWindowObject(hWnd)) || 3362 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 3363 { 3364 ERR("NtUserSetWindowPos bad window handle!\n"); 3365 RETURN(FALSE); 3366 } 3367 3368 if ( hWndInsertAfter != HWND_TOP && 3369 hWndInsertAfter != HWND_BOTTOM && 3370 hWndInsertAfter != HWND_TOPMOST && 3371 hWndInsertAfter != HWND_NOTOPMOST ) 3372 { 3373 if (!(pWndIA = UserGetWindowObject(hWndInsertAfter)) || 3374 UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA)) 3375 { 3376 ERR("NtUserSetWindowPos bad insert window handle!\n"); 3377 RETURN(FALSE); 3378 } 3379 } 3380 3381 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */ 3382 if (!(uFlags & SWP_NOMOVE)) 3383 { 3384 if (X < -32768) X = -32768; 3385 else if (X > 32767) X = 32767; 3386 if (Y < -32768) Y = -32768; 3387 else if (Y > 32767) Y = 32767; 3388 } 3389 if (!(uFlags & SWP_NOSIZE)) 3390 { 3391 if (cx < 0) cx = 0; 3392 else if (cx > 32767) cx = 32767; 3393 if (cy < 0) cy = 0; 3394 else if (cy > 32767) cy = 32767; 3395 } 3396 3397 UserRefObjectCo(Window, &Ref); 3398 ret = co_WinPosSetWindowPos(Window, hWndInsertAfter, X, Y, cx, cy, uFlags); 3399 UserDerefObjectCo(Window); 3400 3401 RETURN(ret); 3402 3403 CLEANUP: 3404 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_); 3405 UserLeave(); 3406 END_CLEANUP; 3407 } 3408 3409 /* 3410 * @implemented 3411 */ 3412 INT APIENTRY 3413 NtUserSetWindowRgn( 3414 HWND hWnd, 3415 HRGN hRgn, 3416 BOOL bRedraw) 3417 { 3418 HRGN hrgnCopy = NULL; 3419 PWND Window; 3420 INT flags = (SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE); 3421 BOOLEAN Ret = FALSE; 3422 DECLARE_RETURN(INT); 3423 3424 TRACE("Enter NtUserSetWindowRgn\n"); 3425 UserEnterExclusive(); 3426 3427 if (!(Window = UserGetWindowObject(hWnd)) || 3428 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 3429 { 3430 RETURN( 0); 3431 } 3432 3433 if (hRgn) // The region will be deleted in user32. 3434 { 3435 if (GreIsHandleValid(hRgn)) 3436 { 3437 hrgnCopy = NtGdiCreateRectRgn(0, 0, 0, 0); 3438 /* The coordinates of a window's window region are relative to the 3439 upper-left corner of the window, not the client area of the window. */ 3440 NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY); 3441 } 3442 else 3443 RETURN( 0); 3444 } 3445 3446 //// HACK 1 : Work around the lack of supporting DeferWindowPos. 3447 if (hrgnCopy) 3448 { 3449 Window->hrgnNewFrame = hrgnCopy; // Should be PSMWP->acvr->hrgnClip 3450 } 3451 else 3452 { 3453 Window->hrgnNewFrame = HRGN_WINDOW; 3454 } 3455 //// HACK 2 3456 Ret = co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, bRedraw ? flags : (flags|SWP_NOREDRAW) ); 3457 3458 RETURN( (INT)Ret); 3459 3460 CLEANUP: 3461 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_); 3462 UserLeave(); 3463 END_CLEANUP; 3464 } 3465 3466 /* 3467 * @implemented 3468 */ 3469 DWORD APIENTRY 3470 NtUserSetInternalWindowPos( 3471 HWND hwnd, 3472 UINT showCmd, 3473 LPRECT lprect, 3474 LPPOINT lppt) 3475 { 3476 WINDOWPLACEMENT wndpl; 3477 UINT flags; 3478 PWND Wnd; 3479 RECT rect; 3480 POINT pt = {0}; 3481 DECLARE_RETURN(BOOL); 3482 USER_REFERENCE_ENTRY Ref; 3483 3484 TRACE("Enter NtUserSetWindowPlacement\n"); 3485 UserEnterExclusive(); 3486 3487 if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME: 3488 UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd)) 3489 { 3490 RETURN( FALSE); 3491 } 3492 3493 _SEH2_TRY 3494 { 3495 if (lppt) 3496 { 3497 ProbeForRead(lppt, sizeof(POINT), 1); 3498 RtlCopyMemory(&pt, lppt, sizeof(POINT)); 3499 } 3500 if (lprect) 3501 { 3502 ProbeForRead(lprect, sizeof(RECT), 1); 3503 RtlCopyMemory(&rect, lprect, sizeof(RECT)); 3504 } 3505 } 3506 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3507 { 3508 SetLastNtError(_SEH2_GetExceptionCode()); 3509 _SEH2_YIELD(RETURN( FALSE)); 3510 } 3511 _SEH2_END 3512 3513 wndpl.length = sizeof(wndpl); 3514 wndpl.showCmd = showCmd; 3515 wndpl.flags = flags = 0; 3516 3517 if ( lppt ) 3518 { 3519 flags |= PLACE_MIN; 3520 wndpl.flags |= WPF_SETMINPOSITION; 3521 wndpl.ptMinPosition = pt; 3522 } 3523 if ( lprect ) 3524 { 3525 flags |= PLACE_RECT; 3526 wndpl.rcNormalPosition = rect; 3527 } 3528 3529 UserRefObjectCo(Wnd, &Ref); 3530 IntSetWindowPlacement(Wnd, &wndpl, flags); 3531 UserDerefObjectCo(Wnd); 3532 RETURN(TRUE); 3533 3534 CLEANUP: 3535 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_); 3536 UserLeave(); 3537 END_CLEANUP; 3538 } 3539 3540 /* 3541 * @implemented 3542 */ 3543 BOOL APIENTRY 3544 NtUserSetWindowPlacement(HWND hWnd, 3545 WINDOWPLACEMENT *lpwndpl) 3546 { 3547 PWND Wnd; 3548 WINDOWPLACEMENT Safepl; 3549 UINT Flags; 3550 DECLARE_RETURN(BOOL); 3551 USER_REFERENCE_ENTRY Ref; 3552 3553 TRACE("Enter NtUserSetWindowPlacement\n"); 3554 UserEnterExclusive(); 3555 3556 if (!(Wnd = UserGetWindowObject(hWnd)) || 3557 UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd)) 3558 { 3559 RETURN( FALSE); 3560 } 3561 3562 _SEH2_TRY 3563 { 3564 ProbeForRead(lpwndpl, sizeof(WINDOWPLACEMENT), 1); 3565 RtlCopyMemory(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT)); 3566 } 3567 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3568 { 3569 SetLastNtError(_SEH2_GetExceptionCode()); 3570 _SEH2_YIELD(RETURN( FALSE)); 3571 } 3572 _SEH2_END 3573 3574 if(Safepl.length != sizeof(WINDOWPLACEMENT)) 3575 { 3576 RETURN( FALSE); 3577 } 3578 3579 Flags = PLACE_MAX | PLACE_RECT; 3580 if (Safepl.flags & WPF_SETMINPOSITION) Flags |= PLACE_MIN; 3581 UserRefObjectCo(Wnd, &Ref); 3582 IntSetWindowPlacement(Wnd, &Safepl, Flags); 3583 UserDerefObjectCo(Wnd); 3584 RETURN(TRUE); 3585 3586 CLEANUP: 3587 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_); 3588 UserLeave(); 3589 END_CLEANUP; 3590 } 3591 3592 /* 3593 * @implemented 3594 */ 3595 BOOL APIENTRY 3596 NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow) 3597 { 3598 PWND Window; 3599 BOOL ret; 3600 DECLARE_RETURN(BOOL); 3601 USER_REFERENCE_ENTRY Ref; 3602 3603 TRACE("Enter NtUserShowWindowAsync\n"); 3604 UserEnterExclusive(); 3605 3606 if (!(Window = UserGetWindowObject(hWnd)) || 3607 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 3608 { 3609 RETURN(FALSE); 3610 } 3611 3612 if ( nCmdShow > SW_MAX ) 3613 { 3614 EngSetLastError(ERROR_INVALID_PARAMETER); 3615 RETURN(FALSE); 3616 } 3617 3618 UserRefObjectCo(Window, &Ref); 3619 ret = co_IntSendMessageNoWait( hWnd, WM_ASYNC_SHOWWINDOW, nCmdShow, 0 ); 3620 UserDerefObjectCo(Window); 3621 if (-1 == (int) ret || !ret) ret = FALSE; 3622 3623 RETURN(ret); 3624 3625 CLEANUP: 3626 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_); 3627 UserLeave(); 3628 END_CLEANUP; 3629 } 3630 3631 /* 3632 * @implemented 3633 */ 3634 BOOL APIENTRY 3635 NtUserShowWindow(HWND hWnd, LONG nCmdShow) 3636 { 3637 PWND Window; 3638 BOOL ret; 3639 DECLARE_RETURN(BOOL); 3640 USER_REFERENCE_ENTRY Ref; 3641 3642 TRACE("Enter NtUserShowWindow hWnd %p SW_ %d\n",hWnd, nCmdShow); 3643 UserEnterExclusive(); 3644 3645 if (!(Window = UserGetWindowObject(hWnd)) || 3646 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 3647 { 3648 RETURN(FALSE); 3649 } 3650 3651 if ( nCmdShow > SW_MAX || Window->state2 & WNDS2_INDESTROY) 3652 { 3653 EngSetLastError(ERROR_INVALID_PARAMETER); 3654 RETURN(FALSE); 3655 } 3656 3657 UserRefObjectCo(Window, &Ref); 3658 ret = co_WinPosShowWindow(Window, nCmdShow); 3659 UserDerefObjectCo(Window); 3660 3661 RETURN(ret); 3662 3663 CLEANUP: 3664 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_); 3665 UserLeave(); 3666 END_CLEANUP; 3667 } 3668 3669 3670 /* 3671 * @implemented 3672 */ 3673 HWND APIENTRY 3674 NtUserWindowFromPoint(LONG X, LONG Y) 3675 { 3676 POINT pt; 3677 HWND Ret; 3678 PWND DesktopWindow = NULL, Window = NULL; 3679 USHORT hittest; 3680 DECLARE_RETURN(HWND); 3681 USER_REFERENCE_ENTRY Ref; 3682 3683 TRACE("Enter NtUserWindowFromPoint\n"); 3684 UserEnterExclusive(); 3685 3686 if ((DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()))) 3687 { 3688 //PTHREADINFO pti; 3689 3690 pt.x = X; 3691 pt.y = Y; 3692 3693 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window. 3694 // It is possible this referencing is useless, though it should not hurt... 3695 UserRefObjectCo(DesktopWindow, &Ref); 3696 3697 //pti = PsGetCurrentThreadWin32Thread(); 3698 Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest, FALSE); 3699 3700 if (Window) 3701 { 3702 Ret = UserHMGetHandle(Window); 3703 3704 RETURN( Ret); 3705 } 3706 } 3707 3708 RETURN( NULL); 3709 3710 CLEANUP: 3711 if (DesktopWindow) UserDerefObjectCo(DesktopWindow); 3712 3713 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_); 3714 UserLeave(); 3715 END_CLEANUP; 3716 } 3717 3718 /* EOF */ 3719