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