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 VOID FASTCALL IntLinkWindow(PWND Wnd,PWND WndInsertAfter); 34 35 /* FUNCTIONS *****************************************************************/ 36 37 #if DBG 38 /*********************************************************************** 39 * dump_winpos_flags 40 */ 41 static void dump_winpos_flags(UINT flags) 42 { 43 static const DWORD dumped_flags = (SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOREDRAW | 44 SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_SHOWWINDOW | 45 SWP_HIDEWINDOW | SWP_NOCOPYBITS | SWP_NOOWNERZORDER | 46 SWP_NOSENDCHANGING | SWP_DEFERERASE | SWP_ASYNCWINDOWPOS | 47 SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | SWP_STATECHANGED); 48 TRACE("flags:"); 49 if(flags & SWP_NOSIZE) TRACE(" SWP_NOSIZE"); 50 if(flags & SWP_NOMOVE) TRACE(" SWP_NOMOVE"); 51 if(flags & SWP_NOZORDER) TRACE(" SWP_NOZORDER"); 52 if(flags & SWP_NOREDRAW) TRACE(" SWP_NOREDRAW"); 53 if(flags & SWP_NOACTIVATE) TRACE(" SWP_NOACTIVATE"); 54 if(flags & SWP_FRAMECHANGED) TRACE(" SWP_FRAMECHANGED"); 55 if(flags & SWP_SHOWWINDOW) TRACE(" SWP_SHOWWINDOW"); 56 if(flags & SWP_HIDEWINDOW) TRACE(" SWP_HIDEWINDOW"); 57 if(flags & SWP_NOCOPYBITS) TRACE(" SWP_NOCOPYBITS"); 58 if(flags & SWP_NOOWNERZORDER) TRACE(" SWP_NOOWNERZORDER"); 59 if(flags & SWP_NOSENDCHANGING) TRACE(" SWP_NOSENDCHANGING"); 60 if(flags & SWP_DEFERERASE) TRACE(" SWP_DEFERERASE"); 61 if(flags & SWP_ASYNCWINDOWPOS) TRACE(" SWP_ASYNCWINDOWPOS"); 62 if(flags & SWP_NOCLIENTSIZE) TRACE(" SWP_NOCLIENTSIZE"); 63 if(flags & SWP_NOCLIENTMOVE) TRACE(" SWP_NOCLIENTMOVE"); 64 if(flags & SWP_STATECHANGED) TRACE(" SWP_STATECHANGED"); 65 66 if(flags & ~dumped_flags) TRACE(" %08x", flags & ~dumped_flags); 67 TRACE("\n"); 68 } 69 #endif 70 71 BOOL FASTCALL 72 IntGetClientOrigin(PWND Window OPTIONAL, LPPOINT Point) 73 { 74 Window = Window ? Window : UserGetDesktopWindow(); 75 if (Window == NULL) 76 { 77 Point->x = Point->y = 0; 78 return FALSE; 79 } 80 Point->x = Window->rcClient.left; 81 Point->y = Window->rcClient.top; 82 83 return TRUE; 84 } 85 86 /*! 87 * Internal function. 88 * Returns client window rectangle relative to the upper-left corner of client area. 89 * 90 * \note Does not check the validity of the parameters 91 */ 92 VOID FASTCALL 93 IntGetClientRect(PWND Wnd, RECTL *Rect) 94 { 95 ASSERT( Wnd ); 96 ASSERT( Rect ); 97 if (Wnd->style & WS_MINIMIZED) 98 { 99 Rect->left = Rect->top = 0; 100 Rect->right = UserGetSystemMetrics(SM_CXMINIMIZED); 101 Rect->bottom = UserGetSystemMetrics(SM_CYMINIMIZED); 102 return; 103 } 104 if (!UserIsDesktopWindow(Wnd)) 105 { 106 *Rect = Wnd->rcClient; 107 RECTL_vOffsetRect(Rect, -Wnd->rcClient.left, -Wnd->rcClient.top); 108 } 109 else 110 { 111 Rect->left = Rect->top = 0; 112 Rect->right = Wnd->rcClient.right; 113 Rect->bottom = Wnd->rcClient.bottom; 114 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics. 115 Rect->right = UserGetSystemMetrics(SM_CXSCREEN); 116 Rect->bottom = UserGetSystemMetrics(SM_CYSCREEN); 117 */ 118 } 119 } 120 121 BOOL FASTCALL 122 IntGetWindowRect(PWND Wnd, RECTL *Rect) 123 { 124 ASSERT( Wnd ); 125 ASSERT( Rect ); 126 if (!Wnd) return FALSE; 127 if (!UserIsDesktopWindow(Wnd)) 128 { 129 *Rect = Wnd->rcWindow; 130 } 131 else 132 { 133 Rect->left = Rect->top = 0; 134 Rect->right = Wnd->rcWindow.right; 135 Rect->bottom = Wnd->rcWindow.bottom; 136 /* Do this until Init bug is fixed. This sets 640x480, see InitMetrics. 137 Rect->right = GetSystemMetrics(SM_CXSCREEN); 138 Rect->bottom = GetSystemMetrics(SM_CYSCREEN); 139 */ } 140 return TRUE; 141 } 142 143 144 INT FASTCALL 145 IntMapWindowPoints(PWND FromWnd, PWND ToWnd, LPPOINT lpPoints, UINT cPoints) 146 { 147 BOOL mirror_from, mirror_to; 148 POINT Delta; 149 UINT i; 150 int Change = 1; 151 152 /* Note: Desktop Top and Left is always 0! */ 153 Delta.x = Delta.y = 0; 154 mirror_from = mirror_to = FALSE; 155 156 if (FromWnd && !UserIsDesktopWindow(FromWnd)) 157 { 158 if (FromWnd->ExStyle & WS_EX_LAYOUTRTL) 159 { 160 mirror_from = TRUE; 161 Change = -Change; 162 Delta.x = -FromWnd->rcClient.right; 163 } 164 else 165 Delta.x = FromWnd->rcClient.left; 166 Delta.y = FromWnd->rcClient.top; 167 } 168 169 if (ToWnd && !UserIsDesktopWindow(ToWnd)) 170 { 171 if (ToWnd->ExStyle & WS_EX_LAYOUTRTL) 172 { 173 mirror_to = TRUE; 174 Change = -Change; 175 Delta.x += Change * ToWnd->rcClient.right; 176 } 177 else 178 Delta.x -= Change * ToWnd->rcClient.left; 179 Delta.y -= ToWnd->rcClient.top; 180 } 181 182 for (i = 0; i != cPoints; i++) 183 { 184 lpPoints[i].x += Delta.x; 185 lpPoints[i].x *= Change; 186 lpPoints[i].y += Delta.y; 187 } 188 189 if ((mirror_from || mirror_to) && cPoints == 2) /* special case for rectangle */ 190 { 191 int tmp = min(lpPoints[0].x, lpPoints[1].x); 192 lpPoints[1].x = max(lpPoints[0].x, lpPoints[1].x); 193 lpPoints[0].x = tmp; 194 } 195 196 return MAKELONG(LOWORD(Delta.x), LOWORD(Delta.y)); 197 } 198 199 BOOL FASTCALL 200 IntClientToScreen(PWND Wnd, LPPOINT lpPoint) 201 { 202 if (Wnd && Wnd->fnid != FNID_DESKTOP ) 203 { 204 if (Wnd->ExStyle & WS_EX_LAYOUTRTL) 205 lpPoint->x = Wnd->rcClient.right - lpPoint->x; 206 else 207 lpPoint->x += Wnd->rcClient.left; 208 lpPoint->y += Wnd->rcClient.top; 209 } 210 return TRUE; 211 } 212 213 BOOL FASTCALL 214 IntScreenToClient(PWND Wnd, LPPOINT lpPoint) 215 { 216 if (Wnd && Wnd->fnid != FNID_DESKTOP ) 217 { 218 if (Wnd->ExStyle & WS_EX_LAYOUTRTL) 219 lpPoint->x = Wnd->rcClient.right - lpPoint->x; 220 else 221 lpPoint->x -= Wnd->rcClient.left; 222 lpPoint->y -= Wnd->rcClient.top; 223 } 224 return TRUE; 225 } 226 227 BOOL FASTCALL IsChildVisible(PWND pWnd) 228 { 229 do 230 { 231 if ( (pWnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD || 232 !(pWnd = pWnd->spwndParent) ) 233 return TRUE; 234 } 235 while (pWnd->style & WS_VISIBLE); 236 return FALSE; 237 } 238 239 PWND FASTCALL IntGetLastTopMostWindow(VOID) 240 { 241 PWND pWnd; 242 PDESKTOP rpdesk = gptiCurrent->rpdesk; 243 244 if ( rpdesk && 245 (pWnd = rpdesk->pDeskInfo->spwnd->spwndChild) && 246 pWnd->ExStyle & WS_EX_TOPMOST) 247 { 248 for (;;) 249 { 250 if (!pWnd->spwndNext) break; 251 if (!(pWnd->spwndNext->ExStyle & WS_EX_TOPMOST)) break; 252 pWnd = pWnd->spwndNext; 253 } 254 return pWnd; 255 } 256 return NULL; 257 } 258 259 VOID 260 SelectWindowRgn(PWND Window, HRGN hRgnClip) 261 { 262 if (Window->hrgnClip) 263 { 264 /* Delete no longer needed region handle */ 265 IntGdiSetRegionOwner(Window->hrgnClip, GDI_OBJ_HMGR_POWNED); 266 GreDeleteObject(Window->hrgnClip); 267 Window->hrgnClip = NULL; 268 } 269 270 if (hRgnClip > HRGN_WINDOW) 271 { 272 /*if (!UserIsDesktopWindow(Window)) 273 { 274 NtGdiOffsetRgn(hRgnClip, Window->rcWindow.left, Window->rcWindow.top); 275 }*/ 276 /* Set public ownership */ 277 IntGdiSetRegionOwner(hRgnClip, GDI_OBJ_HMGR_PUBLIC); 278 279 Window->hrgnClip = hRgnClip; 280 } 281 } 282 283 // 284 // This helps with CORE-6129 forcing modal dialog active when another app is minimized or closed. 285 // 286 BOOL FASTCALL ActivateOtherWindowMin(PWND Wnd) 287 { 288 BOOL ActivePrev, FindTopWnd; 289 PWND pWndTopMost, pWndChild, pWndSetActive, pWndTemp, pWndDesk; 290 USER_REFERENCE_ENTRY Ref; 291 PTHREADINFO pti = gptiCurrent; 292 293 //ERR("AOWM 1 %p\n",Wnd->head.h); 294 ActivePrev = (pti->MessageQueue->spwndActivePrev != NULL); 295 FindTopWnd = TRUE; 296 297 if ((pWndTopMost = IntGetLastTopMostWindow())) 298 pWndChild = pWndTopMost->spwndNext; 299 else 300 pWndChild = Wnd->spwndParent->spwndChild; 301 302 for (;;) 303 { 304 if ( ActivePrev ) 305 pWndSetActive = pti->MessageQueue->spwndActivePrev; 306 else 307 pWndSetActive = pWndChild; 308 309 pWndTemp = NULL; 310 311 while(pWndSetActive) 312 { 313 if ( VerifyWnd(pWndSetActive) && 314 !(pWndSetActive->ExStyle & WS_EX_NOACTIVATE) && 315 (pWndSetActive->style & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE && 316 (!(pWndSetActive->style & WS_ICONIC) /* FIXME MinMax pos? */ ) ) 317 { 318 if (!(pWndSetActive->ExStyle & WS_EX_TOOLWINDOW) ) 319 { 320 UserRefObjectCo(pWndSetActive, &Ref); 321 //ERR("ActivateOtherWindowMin Set FG 1\n"); 322 co_IntSetForegroundWindow(pWndSetActive); 323 UserDerefObjectCo(pWndSetActive); 324 //ERR("AOWM 2 Exit Good %p\n",pWndSetActive->head.h); 325 return TRUE; 326 } 327 if (!pWndTemp ) pWndTemp = pWndSetActive; 328 } 329 if ( ActivePrev ) 330 { 331 ActivePrev = FALSE; 332 pWndSetActive = pWndChild; 333 } 334 else 335 pWndSetActive = pWndSetActive->spwndNext; 336 } 337 338 if ( !FindTopWnd ) break; 339 FindTopWnd = FALSE; 340 341 if ( pWndChild ) 342 { 343 pWndChild = pWndChild->spwndParent->spwndChild; 344 continue; 345 } 346 347 if (!(pWndDesk = IntGetThreadDesktopWindow(pti))) 348 { 349 pWndChild = NULL; 350 continue; 351 } 352 pWndChild = pWndDesk->spwndChild; 353 } 354 355 if ((pWndSetActive = pWndTemp)) 356 { 357 UserRefObjectCo(pWndSetActive, &Ref); 358 //ERR("ActivateOtherWindowMin Set FG 2\n"); 359 co_IntSetForegroundWindow(pWndSetActive); 360 UserDerefObjectCo(pWndSetActive); 361 //ERR("AOWM 3 Exit Good %p\n",pWndSetActive->head.h); 362 return TRUE; 363 } 364 //ERR("AOWM 4 Bad\n"); 365 return FALSE; 366 } 367 368 /******************************************************************* 369 * can_activate_window 370 * 371 * Check if we can activate the specified window. 372 */ 373 static 374 BOOL FASTCALL can_activate_window( PWND Wnd OPTIONAL) 375 { 376 LONG style; 377 378 if (!Wnd) return FALSE; 379 380 style = Wnd->style; 381 if (!(style & WS_VISIBLE)) return FALSE; 382 if (style & WS_MINIMIZE) return FALSE; 383 if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE; 384 return TRUE; 385 /* FIXME: This window could be disable because the child that closed 386 was a popup. */ 387 //return !(style & WS_DISABLED); 388 } 389 390 391 /******************************************************************* 392 * WinPosActivateOtherWindow 393 * 394 * Activates window other than pWnd. 395 */ 396 VOID FASTCALL 397 co_WinPosActivateOtherWindow(PWND Wnd) 398 { 399 PWND WndTo = NULL; 400 USER_REFERENCE_ENTRY Ref; 401 402 ASSERT_REFS_CO(Wnd); 403 404 if (IntIsDesktopWindow(Wnd)) 405 { 406 //ERR("WinPosActivateOtherWindow Set Focus Msg Q No window!\n"); 407 IntSetFocusMessageQueue(NULL); 408 return; 409 } 410 411 /* If this is popup window, try to activate the owner first. */ 412 if ((Wnd->style & WS_POPUP) && (WndTo = Wnd->spwndOwner)) 413 { 414 TRACE("WPAOW Popup with Owner\n"); 415 WndTo = UserGetAncestor( WndTo, GA_ROOT ); 416 if (can_activate_window(WndTo)) goto done; 417 } 418 419 /* Pick a next top-level window. */ 420 /* FIXME: Search for non-tooltip windows first. */ 421 WndTo = Wnd; 422 for (;;) 423 { 424 if (!(WndTo = WndTo->spwndNext)) break; 425 if (can_activate_window( WndTo )) goto done; 426 } 427 428 /* 429 Fixes wine win.c:test_SetParent last ShowWindow test after popup dies. 430 Check for previous active window to bring to top. 431 */ 432 if (Wnd) 433 { 434 WndTo = Wnd->head.pti->MessageQueue->spwndActivePrev; 435 if (can_activate_window( WndTo )) goto done; 436 } 437 438 // Find any window to bring to top. Works Okay for wine since it does not see X11 windows. 439 WndTo = UserGetDesktopWindow(); 440 WndTo = WndTo->spwndChild; 441 if ( WndTo == NULL ) 442 { 443 //ERR("WinPosActivateOtherWindow No window!\n"); 444 return; 445 } 446 for (;;) 447 { 448 if (WndTo == Wnd) 449 { 450 WndTo = NULL; 451 break; 452 } 453 if (can_activate_window( WndTo )) goto done; 454 if (!(WndTo = WndTo->spwndNext)) break; 455 } 456 457 done: 458 if (WndTo) UserRefObjectCo(WndTo, &Ref); 459 460 if (gpqForeground && (!gpqForeground->spwndActive || Wnd == gpqForeground->spwndActive)) 461 { 462 /* ReactOS can pass WndTo = NULL to co_IntSetForegroundWindow and returns FALSE. */ 463 //ERR("WinPosActivateOtherWindow Set FG 0x%p hWnd %p\n",WndTo, WndTo ? WndTo->head.h : 0); 464 if (co_IntSetForegroundWindow(WndTo)) 465 { 466 if (WndTo) UserDerefObjectCo(WndTo); 467 return; 468 } 469 } 470 //ERR("WinPosActivateOtherWindow Set Active 0x%p\n",WndTo); 471 if (!UserSetActiveWindow(WndTo)) /* Ok for WndTo to be NULL here */ 472 { 473 //ERR("WPAOW SA 1\n"); 474 UserSetActiveWindow(NULL); 475 } 476 if (WndTo) UserDerefObjectCo(WndTo); 477 } 478 479 VOID FASTCALL 480 WinPosInitInternalPos(PWND Wnd, RECTL *RestoreRect) 481 { 482 POINT Size; 483 RECTL Rect = *RestoreRect; 484 485 if (Wnd->spwndParent && !UserIsDesktopWindow(Wnd->spwndParent)) 486 { 487 RECTL_vOffsetRect(&Rect, 488 -Wnd->spwndParent->rcClient.left, 489 -Wnd->spwndParent->rcClient.top); 490 } 491 492 Size.x = Rect.left; 493 Size.y = Rect.top; 494 495 if (!Wnd->InternalPosInitialized) 496 { 497 // FIXME: Use check point Atom.. 498 Wnd->InternalPos.flags = 0; 499 Wnd->InternalPos.MaxPos.x = Wnd->InternalPos.MaxPos.y = -1; 500 Wnd->InternalPos.IconPos.x = Wnd->InternalPos.IconPos.y = -1; 501 Wnd->InternalPos.NormalRect = Rect; 502 Wnd->InternalPosInitialized = TRUE; 503 } 504 505 if (Wnd->style & WS_MINIMIZE) 506 { 507 Wnd->InternalPos.IconPos = Size; 508 Wnd->InternalPos.flags |= WPF_MININIT; 509 } 510 else if (Wnd->style & WS_MAXIMIZE) 511 { 512 Wnd->InternalPos.flags |= WPF_MAXINIT; 513 514 if ( Wnd->spwndParent == Wnd->head.rpdesk->pDeskInfo->spwnd ) 515 { 516 if (Wnd->state & WNDS_MAXIMIZESTOMONITOR) 517 { 518 Wnd->InternalPos.flags &= ~WPF_MAXINIT; 519 Wnd->InternalPos.MaxPos.x = Wnd->InternalPos.MaxPos.y = -1; 520 } 521 else 522 { 523 RECTL WorkArea; 524 PMONITOR pmonitor = UserMonitorFromRect(&Rect, MONITOR_DEFAULTTOPRIMARY ); 525 // FIXME: support DPI aware, rcWorkDPI/Real etc.. 526 WorkArea = pmonitor->rcMonitor; 527 528 if (Wnd->style & WS_MAXIMIZEBOX) 529 { // Support (Wnd->state & WNDS_HASCAPTION) || pmonitor->cFullScreen too. 530 if ((Wnd->style & WS_CAPTION) == WS_CAPTION || !(Wnd->style & (WS_CHILD | WS_POPUP))) 531 { 532 WorkArea = pmonitor->rcWork; 533 //ERR("rcWork\n"); 534 } 535 } 536 537 Wnd->InternalPos.MaxPos.x = Rect.left - WorkArea.left; 538 Wnd->InternalPos.MaxPos.y = Rect.top - WorkArea.top; 539 540 /*ERR("WinPosIP 2 X %d = R.l %d - W.l %d | Y %d = R.t %d - W.t %d\n", 541 Wnd->InternalPos.MaxPos.x, 542 Rect.left, WorkArea.left, 543 Wnd->InternalPos.MaxPos.y, 544 Rect.top, WorkArea.top);*/ 545 } 546 } 547 else 548 Wnd->InternalPos.MaxPos = Size; 549 } 550 else 551 { 552 Wnd->InternalPos.NormalRect = Rect; 553 } 554 } 555 556 BOOL 557 FASTCALL 558 IntGetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *lpwndpl) 559 { 560 if (!Wnd) return FALSE; 561 562 if(lpwndpl->length != sizeof(WINDOWPLACEMENT)) 563 { 564 return FALSE; 565 } 566 567 lpwndpl->flags = 0; 568 569 WinPosInitInternalPos(Wnd, &Wnd->rcWindow); 570 571 lpwndpl->showCmd = SW_HIDE; 572 573 if ( Wnd->style & WS_MINIMIZE ) 574 lpwndpl->showCmd = SW_SHOWMINIMIZED; 575 else 576 lpwndpl->showCmd = ( Wnd->style & WS_MAXIMIZE ) ? SW_SHOWMAXIMIZED : SW_SHOWNORMAL ; 577 578 lpwndpl->rcNormalPosition = Wnd->InternalPos.NormalRect; 579 580 if (Wnd->InternalPos.flags & WPF_MININIT) // Return if it was set! 581 { 582 lpwndpl->ptMinPosition.x = Wnd->InternalPos.IconPos.x; 583 lpwndpl->ptMinPosition.y = Wnd->InternalPos.IconPos.y; 584 } 585 else 586 lpwndpl->ptMinPosition.x = lpwndpl->ptMinPosition.y = -1; 587 588 if ( Wnd->InternalPos.flags & WPF_MAXINIT && // Return if set and not maximized to monitor! 589 !(Wnd->state & WNDS_MAXIMIZESTOMONITOR)) 590 { 591 lpwndpl->ptMaxPosition.x = Wnd->InternalPos.MaxPos.x; 592 lpwndpl->ptMaxPosition.y = Wnd->InternalPos.MaxPos.y; 593 } 594 else 595 lpwndpl->ptMaxPosition.x = lpwndpl->ptMaxPosition.y = -1; 596 597 if ( Wnd->spwndParent == Wnd->head.rpdesk->pDeskInfo->spwnd && 598 !(Wnd->ExStyle & WS_EX_TOOLWINDOW)) 599 { 600 PMONITOR pmonitor = UserMonitorFromRect(&lpwndpl->rcNormalPosition, MONITOR_DEFAULTTOPRIMARY ); 601 602 // FIXME: support DPI aware, rcWorkDPI/Real etc.. 603 if (Wnd->InternalPos.flags & WPF_MININIT) 604 { 605 lpwndpl->ptMinPosition.x -= (pmonitor->rcWork.left - pmonitor->rcMonitor.left); 606 lpwndpl->ptMinPosition.y -= (pmonitor->rcWork.top - pmonitor->rcMonitor.top); 607 } 608 RECTL_vOffsetRect(&lpwndpl->rcNormalPosition, 609 pmonitor->rcMonitor.left - pmonitor->rcWork.left, 610 pmonitor->rcMonitor.top - pmonitor->rcWork.top); 611 } 612 613 if ( Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED || Wnd->style & WS_MAXIMIZE ) 614 lpwndpl->flags |= WPF_RESTORETOMAXIMIZED; 615 616 if ( ((Wnd->style & (WS_CHILD|WS_POPUP)) == WS_CHILD) && Wnd->InternalPos.flags & WPF_SETMINPOSITION) 617 lpwndpl->flags |= WPF_SETMINPOSITION; 618 619 return TRUE; 620 } 621 622 /* make sure the specified rect is visible on screen */ 623 static void make_rect_onscreen( RECT *rect ) 624 { 625 PMONITOR pmonitor = UserMonitorFromRect( rect, MONITOR_DEFAULTTONEAREST ); // Wine uses this. 626 627 // FIXME: support DPI aware, rcWorkDPI/Real etc.. 628 if (!pmonitor) return; 629 /* FIXME: map coordinates from rcWork to rcMonitor */ 630 if (rect->right <= pmonitor->rcWork.left) 631 { 632 rect->right += pmonitor->rcWork.left - rect->left; 633 rect->left = pmonitor->rcWork.left; 634 } 635 else if (rect->left >= pmonitor->rcWork.right) 636 { 637 rect->left += pmonitor->rcWork.right - rect->right; 638 rect->right = pmonitor->rcWork.right; 639 } 640 if (rect->bottom <= pmonitor->rcWork.top) 641 { 642 rect->bottom += pmonitor->rcWork.top - rect->top; 643 rect->top = pmonitor->rcWork.top; 644 } 645 else if (rect->top >= pmonitor->rcWork.bottom) 646 { 647 rect->top += pmonitor->rcWork.bottom - rect->bottom; 648 rect->bottom = pmonitor->rcWork.bottom; 649 } 650 } 651 652 /* make sure the specified point is visible on screen */ 653 static void make_point_onscreen( POINT *pt ) 654 { 655 RECT rect; 656 657 RECTL_vSetRect( &rect, pt->x, pt->y, pt->x + 1, pt->y + 1 ); 658 make_rect_onscreen( &rect ); 659 pt->x = rect.left; 660 pt->y = rect.top; 661 } 662 663 BOOL FASTCALL 664 IntSetWindowPlacement(PWND Wnd, WINDOWPLACEMENT *wpl, UINT Flags) 665 { 666 BOOL sAsync; 667 UINT SWP_Flags; 668 669 if ( Flags & PLACE_MIN) make_point_onscreen( &wpl->ptMinPosition ); 670 if ( Flags & PLACE_MAX) make_point_onscreen( &wpl->ptMaxPosition ); 671 if ( Flags & PLACE_RECT) make_rect_onscreen( &wpl->rcNormalPosition ); 672 673 if (!Wnd || Wnd == Wnd->head.rpdesk->pDeskInfo->spwnd) return FALSE; 674 675 if ( Flags & PLACE_MIN ) Wnd->InternalPos.IconPos = wpl->ptMinPosition; 676 if ( Flags & PLACE_MAX ) Wnd->InternalPos.MaxPos = wpl->ptMaxPosition; 677 if ( Flags & PLACE_RECT) Wnd->InternalPos.NormalRect = wpl->rcNormalPosition; 678 679 SWP_Flags = SWP_NOZORDER | SWP_NOACTIVATE | ((wpl->flags & WPF_ASYNCWINDOWPLACEMENT) ? SWP_ASYNCWINDOWPOS : 0); 680 681 if (Wnd->style & WS_MINIMIZE ) 682 { 683 if (Flags & PLACE_MIN || Wnd->InternalPos.flags & WPF_SETMINPOSITION) 684 { 685 co_WinPosSetWindowPos(Wnd, HWND_TOP, 686 wpl->ptMinPosition.x, wpl->ptMinPosition.y, 0, 0, 687 SWP_NOSIZE | SWP_Flags); 688 Wnd->InternalPos.flags |= WPF_MININIT; 689 } 690 } 691 else if (Wnd->style & WS_MAXIMIZE ) 692 { 693 if (Flags & PLACE_MAX) 694 { 695 co_WinPosSetWindowPos(Wnd, HWND_TOP, 696 wpl->ptMaxPosition.x, wpl->ptMaxPosition.y, 0, 0, 697 SWP_NOSIZE | SWP_Flags); 698 Wnd->InternalPos.flags |= WPF_MAXINIT; 699 } 700 } 701 else if (Flags & PLACE_RECT) 702 { 703 co_WinPosSetWindowPos(Wnd, HWND_TOP, 704 wpl->rcNormalPosition.left, wpl->rcNormalPosition.top, 705 wpl->rcNormalPosition.right - wpl->rcNormalPosition.left, 706 wpl->rcNormalPosition.bottom - wpl->rcNormalPosition.top, 707 SWP_Flags); 708 } 709 710 sAsync = (Wnd->head.pti->MessageQueue != gptiCurrent->MessageQueue && wpl->flags & WPF_ASYNCWINDOWPLACEMENT); 711 712 if ( sAsync ) 713 co_IntSendMessageNoWait( UserHMGetHandle(Wnd), WM_ASYNC_SHOWWINDOW, wpl->showCmd, 0 ); 714 else 715 co_WinPosShowWindow(Wnd, wpl->showCmd); 716 717 if ( Wnd->style & WS_MINIMIZE && !sAsync ) 718 { 719 if ( wpl->flags & WPF_SETMINPOSITION ) 720 Wnd->InternalPos.flags |= WPF_SETMINPOSITION; 721 722 if ( wpl->flags & WPF_RESTORETOMAXIMIZED ) 723 Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED; 724 } 725 return TRUE; 726 } 727 728 UINT 729 FASTCALL 730 co_WinPosArrangeIconicWindows(PWND parent) 731 { 732 RECTL rectParent; 733 PWND Child; 734 INT x, y, xspacing, yspacing, sx, sy; 735 736 ASSERT_REFS_CO(parent); 737 738 IntGetClientRect( parent, &rectParent ); 739 // FIXME: Support Minimize Metrics gspv.mm.iArrange. 740 // Default: ARW_BOTTOMLEFT 741 x = rectParent.left; 742 y = rectParent.bottom; 743 744 xspacing = UserGetSystemMetrics(SM_CXMINIMIZED); 745 yspacing = UserGetSystemMetrics(SM_CYMINIMIZED); 746 747 Child = parent->spwndChild; 748 while(Child) 749 { 750 if((Child->style & WS_MINIMIZE) != 0 ) 751 { 752 USER_REFERENCE_ENTRY Ref; 753 UserRefObjectCo(Child, &Ref); 754 755 sx = x + UserGetSystemMetrics(SM_CXBORDER); 756 sy = y - yspacing - UserGetSystemMetrics(SM_CYBORDER); 757 758 Child->InternalPos.IconPos.x = sx; 759 Child->InternalPos.IconPos.y = sy; 760 Child->InternalPos.flags |= WPF_MININIT; 761 762 co_WinPosSetWindowPos( Child, 0, sx, sy, xspacing, yspacing, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_ASYNCWINDOWPOS); 763 764 UserDerefObjectCo(Child); 765 766 if (x <= rectParent.right - xspacing) 767 x += xspacing; 768 else 769 { 770 x = rectParent.left; 771 y -= yspacing; 772 } 773 } 774 Child = Child->spwndNext; 775 } 776 return yspacing; 777 } 778 779 static VOID FASTCALL 780 WinPosFindIconPos(PWND Window, POINT *Pos) 781 { 782 RECT rectParent; 783 PWND pwndChild, pwndParent; 784 int x, y, xspacing, yspacing; 785 786 pwndParent = Window->spwndParent; 787 if (UserIsDesktopWindow(pwndParent)) 788 { 789 ERR("FIXME: Parent is Desktop, Min off screen!\n"); 790 /* FIXME: ReactOS doesn't support iconic minimize to desktop */ 791 Pos->x = Pos->y = -32000; 792 Window->InternalPos.flags |= WPF_MININIT; 793 Window->InternalPos.IconPos.x = Pos->x; 794 Window->InternalPos.IconPos.y = Pos->y; 795 return; 796 } 797 798 IntGetClientRect( pwndParent, &rectParent ); 799 // FIXME: Support Minimize Metrics gspv.mm.iArrange. 800 // Default: ARW_BOTTOMLEFT 801 x = rectParent.left; 802 y = rectParent.bottom; 803 804 xspacing = UserGetSystemMetrics(SM_CXMINIMIZED); 805 yspacing = UserGetSystemMetrics(SM_CYMINIMIZED); 806 807 // Set to default position when minimized. 808 Pos->x = x + UserGetSystemMetrics(SM_CXBORDER); 809 Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER); 810 811 for (pwndChild = pwndParent->spwndChild; pwndChild; pwndChild = pwndChild->spwndNext) 812 { 813 if (pwndChild == Window) continue; 814 815 if ((pwndChild->style & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE) ) 816 { 817 continue; 818 } 819 820 if ( pwndChild->InternalPos.IconPos.x != Pos->x && pwndChild->InternalPos.IconPos.y != Pos->y ) 821 { 822 break; 823 } 824 if (x <= rectParent.right - xspacing) 825 x += xspacing; 826 else 827 { 828 x = rectParent.left; 829 y -= yspacing; 830 } 831 Pos->x = x + UserGetSystemMetrics(SM_CXBORDER); 832 Pos->y = y - yspacing - UserGetSystemMetrics(SM_CYBORDER); 833 } 834 835 Window->InternalPos.IconPos.x = Pos->x; 836 Window->InternalPos.IconPos.y = Pos->y; 837 Window->InternalPos.flags |= WPF_MININIT; 838 TRACE("Position is set! X:%d Y:%d\n",Pos->x,Pos->y); 839 return; 840 } 841 842 BOOL 843 UserHasWindowEdge(DWORD Style, DWORD ExStyle) 844 { 845 if (Style & WS_MINIMIZE) 846 return TRUE; 847 if (ExStyle & WS_EX_DLGMODALFRAME) 848 return TRUE; 849 if (ExStyle & WS_EX_STATICEDGE) 850 return FALSE; 851 if (Style & WS_THICKFRAME) 852 return TRUE; 853 Style &= WS_CAPTION; 854 if (Style == WS_DLGFRAME || Style == WS_CAPTION) 855 return TRUE; 856 return FALSE; 857 } 858 859 VOID FASTCALL 860 IntGetWindowBorderMeasures(PWND Wnd, UINT *cx, UINT *cy) 861 { 862 if(HAS_DLGFRAME(Wnd->style, Wnd->ExStyle) && !(Wnd->style & WS_MINIMIZE)) 863 { 864 *cx = UserGetSystemMetrics(SM_CXDLGFRAME); 865 *cy = UserGetSystemMetrics(SM_CYDLGFRAME); 866 } 867 else 868 { 869 if(HAS_THICKFRAME(Wnd->style, Wnd->ExStyle)&& !(Wnd->style & WS_MINIMIZE)) 870 { 871 *cx = UserGetSystemMetrics(SM_CXFRAME); 872 *cy = UserGetSystemMetrics(SM_CYFRAME); 873 } 874 else if(HAS_THINFRAME(Wnd->style, Wnd->ExStyle)) 875 { 876 *cx = UserGetSystemMetrics(SM_CXBORDER); 877 *cy = UserGetSystemMetrics(SM_CYBORDER); 878 } 879 else 880 { 881 *cx = *cy = 0; 882 } 883 } 884 } 885 886 VOID 887 UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient) 888 { 889 DWORD Border = 0; 890 891 if (UserHasWindowEdge(Style, ExStyle)) 892 Border += 2; 893 else if (ExStyle & WS_EX_STATICEDGE) 894 Border += 1; 895 if ((ExStyle & WS_EX_CLIENTEDGE) && WithClient) 896 Border += 2; 897 if (Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME) 898 Border ++; 899 Size->cx = Size->cy = Border; 900 if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE)) 901 { 902 Size->cx += UserGetSystemMetrics(SM_CXFRAME) - UserGetSystemMetrics(SM_CXDLGFRAME); 903 Size->cy += UserGetSystemMetrics(SM_CYFRAME) - UserGetSystemMetrics(SM_CYDLGFRAME); 904 } 905 Size->cx *= UserGetSystemMetrics(SM_CXBORDER); 906 Size->cy *= UserGetSystemMetrics(SM_CYBORDER); 907 } 908 909 BOOL WINAPI 910 UserAdjustWindowRectEx(LPRECT lpRect, 911 DWORD dwStyle, 912 BOOL bMenu, 913 DWORD dwExStyle) 914 { 915 SIZE BorderSize; 916 917 if (bMenu) 918 { 919 lpRect->top -= UserGetSystemMetrics(SM_CYMENU); 920 } 921 if ((dwStyle & WS_CAPTION) == WS_CAPTION) 922 { 923 if (dwExStyle & WS_EX_TOOLWINDOW) 924 lpRect->top -= UserGetSystemMetrics(SM_CYSMCAPTION); 925 else 926 lpRect->top -= UserGetSystemMetrics(SM_CYCAPTION); 927 } 928 UserGetWindowBorders(dwStyle, dwExStyle, &BorderSize, TRUE); 929 RECTL_vInflateRect( 930 lpRect, 931 BorderSize.cx, 932 BorderSize.cy); 933 934 return TRUE; 935 } 936 937 UINT FASTCALL 938 co_WinPosGetMinMaxInfo(PWND Window, POINT* MaxSize, POINT* MaxPos, 939 POINT* MinTrack, POINT* MaxTrack) 940 { 941 MINMAXINFO MinMax; 942 PMONITOR monitor; 943 INT xinc, yinc; 944 LONG style = Window->style; 945 LONG adjustedStyle; 946 LONG exstyle = Window->ExStyle; 947 RECT rc; 948 949 ASSERT_REFS_CO(Window); 950 951 /* Compute default values */ 952 953 rc = Window->rcWindow; 954 MinMax.ptReserved.x = rc.left; 955 MinMax.ptReserved.y = rc.top; 956 957 if ((style & WS_CAPTION) == WS_CAPTION) 958 adjustedStyle = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */ 959 else 960 adjustedStyle = style; 961 962 if(Window->spwndParent) 963 IntGetClientRect(Window->spwndParent, &rc); 964 UserAdjustWindowRectEx(&rc, adjustedStyle, ((style & WS_POPUP) && Window->IDMenu), exstyle); 965 966 xinc = -rc.left; 967 yinc = -rc.top; 968 969 MinMax.ptMaxSize.x = rc.right - rc.left; 970 MinMax.ptMaxSize.y = rc.bottom - rc.top; 971 if (style & (WS_DLGFRAME | WS_BORDER)) 972 { 973 MinMax.ptMinTrackSize.x = UserGetSystemMetrics(SM_CXMINTRACK); 974 MinMax.ptMinTrackSize.y = UserGetSystemMetrics(SM_CYMINTRACK); 975 } 976 else 977 { 978 MinMax.ptMinTrackSize.x = 2 * xinc; 979 MinMax.ptMinTrackSize.y = 2 * yinc; 980 } 981 MinMax.ptMaxTrackSize.x = UserGetSystemMetrics(SM_CXMAXTRACK); 982 MinMax.ptMaxTrackSize.y = UserGetSystemMetrics(SM_CYMAXTRACK); 983 MinMax.ptMaxPosition.x = -xinc; 984 MinMax.ptMaxPosition.y = -yinc; 985 986 if (!EMPTYPOINT(Window->InternalPos.MaxPos)) MinMax.ptMaxPosition = Window->InternalPos.MaxPos; 987 988 co_IntSendMessage(Window->head.h, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax); 989 990 /* if the app didn't change the values, adapt them for the current monitor */ 991 if ((monitor = UserGetPrimaryMonitor())) 992 { 993 RECT rc_work; 994 995 rc_work = monitor->rcMonitor; 996 997 if (style & WS_MAXIMIZEBOX) 998 { 999 if ((style & WS_CAPTION) == WS_CAPTION || !(style & (WS_CHILD | WS_POPUP))) 1000 rc_work = monitor->rcWork; 1001 } 1002 1003 if (MinMax.ptMaxSize.x == UserGetSystemMetrics(SM_CXSCREEN) + 2 * xinc && 1004 MinMax.ptMaxSize.y == UserGetSystemMetrics(SM_CYSCREEN) + 2 * yinc) 1005 { 1006 MinMax.ptMaxSize.x = (rc_work.right - rc_work.left) + 2 * xinc; 1007 MinMax.ptMaxSize.y = (rc_work.bottom - rc_work.top) + 2 * yinc; 1008 } 1009 if (MinMax.ptMaxPosition.x == -xinc && MinMax.ptMaxPosition.y == -yinc) 1010 { 1011 MinMax.ptMaxPosition.x = rc_work.left - xinc; 1012 MinMax.ptMaxPosition.y = rc_work.top - yinc; 1013 } 1014 if (MinMax.ptMaxSize.x >= (monitor->rcMonitor.right - monitor->rcMonitor.left) && 1015 MinMax.ptMaxSize.y >= (monitor->rcMonitor.bottom - monitor->rcMonitor.top) ) 1016 Window->state |= WNDS_MAXIMIZESTOMONITOR; 1017 else 1018 Window->state &= ~WNDS_MAXIMIZESTOMONITOR; 1019 } 1020 1021 1022 MinMax.ptMaxTrackSize.x = max(MinMax.ptMaxTrackSize.x, 1023 MinMax.ptMinTrackSize.x); 1024 MinMax.ptMaxTrackSize.y = max(MinMax.ptMaxTrackSize.y, 1025 MinMax.ptMinTrackSize.y); 1026 1027 if (MaxSize) 1028 *MaxSize = MinMax.ptMaxSize; 1029 if (MaxPos) 1030 *MaxPos = MinMax.ptMaxPosition; 1031 if (MinTrack) 1032 *MinTrack = MinMax.ptMinTrackSize; 1033 if (MaxTrack) 1034 *MaxTrack = MinMax.ptMaxTrackSize; 1035 1036 return 0; // FIXME: What does it return? 1037 } 1038 1039 static 1040 BOOL 1041 IntValidateParent(PWND Child, PREGION ValidateRgn) 1042 { 1043 PWND ParentWnd = Child; 1044 1045 if (ParentWnd->style & WS_CHILD) 1046 { 1047 do 1048 ParentWnd = ParentWnd->spwndParent; 1049 while (ParentWnd->style & WS_CHILD); 1050 } 1051 1052 ParentWnd = Child->spwndParent; 1053 while (ParentWnd) 1054 { 1055 if (ParentWnd->style & WS_CLIPCHILDREN) 1056 break; 1057 1058 if (ParentWnd->hrgnUpdate != 0) 1059 { 1060 IntInvalidateWindows( ParentWnd, 1061 ValidateRgn, 1062 RDW_VALIDATE | RDW_NOCHILDREN); 1063 } 1064 1065 ParentWnd = ParentWnd->spwndParent; 1066 } 1067 1068 return TRUE; 1069 } 1070 1071 static 1072 VOID FASTCALL 1073 FixClientRect(PRECTL ClientRect, PRECTL WindowRect) 1074 { 1075 if (ClientRect->left < WindowRect->left) 1076 { 1077 ClientRect->left = WindowRect->left; 1078 } 1079 else if (WindowRect->right < ClientRect->left) 1080 { 1081 ClientRect->left = WindowRect->right; 1082 } 1083 if (ClientRect->right < WindowRect->left) 1084 { 1085 ClientRect->right = WindowRect->left; 1086 } 1087 else if (WindowRect->right < ClientRect->right) 1088 { 1089 ClientRect->right = WindowRect->right; 1090 } 1091 if (ClientRect->top < WindowRect->top) 1092 { 1093 ClientRect->top = WindowRect->top; 1094 } 1095 else if (WindowRect->bottom < ClientRect->top) 1096 { 1097 ClientRect->top = WindowRect->bottom; 1098 } 1099 if (ClientRect->bottom < WindowRect->top) 1100 { 1101 ClientRect->bottom = WindowRect->top; 1102 } 1103 else if (WindowRect->bottom < ClientRect->bottom) 1104 { 1105 ClientRect->bottom = WindowRect->bottom; 1106 } 1107 } 1108 /*********************************************************************** 1109 * get_valid_rects 1110 * 1111 * Compute the valid rects from the old and new client rect and WVR_* flags. 1112 * Helper for WM_NCCALCSIZE handling. 1113 */ 1114 static 1115 VOID FASTCALL 1116 get_valid_rects( RECTL *old_client, RECTL *new_client, UINT flags, RECTL *valid ) 1117 { 1118 int cx, cy; 1119 1120 if (flags & WVR_REDRAW) 1121 { 1122 RECTL_vSetEmptyRect( &valid[0] ); 1123 RECTL_vSetEmptyRect( &valid[1] ); 1124 return; 1125 } 1126 1127 if (flags & WVR_VALIDRECTS) 1128 { 1129 if (!RECTL_bIntersectRect( &valid[0], &valid[0], new_client ) || 1130 !RECTL_bIntersectRect( &valid[1], &valid[1], old_client )) 1131 { 1132 RECTL_vSetEmptyRect( &valid[0] ); 1133 RECTL_vSetEmptyRect( &valid[1] ); 1134 return; 1135 } 1136 flags = WVR_ALIGNLEFT | WVR_ALIGNTOP; 1137 } 1138 else 1139 { 1140 valid[0] = *new_client; 1141 valid[1] = *old_client; 1142 } 1143 1144 /* make sure the rectangles have the same size */ 1145 cx = min( valid[0].right - valid[0].left, valid[1].right - valid[1].left ); 1146 cy = min( valid[0].bottom - valid[0].top, valid[1].bottom - valid[1].top ); 1147 1148 if (flags & WVR_ALIGNBOTTOM) 1149 { 1150 valid[0].top = valid[0].bottom - cy; 1151 valid[1].top = valid[1].bottom - cy; 1152 } 1153 else 1154 { 1155 valid[0].bottom = valid[0].top + cy; 1156 valid[1].bottom = valid[1].top + cy; 1157 } 1158 if (flags & WVR_ALIGNRIGHT) 1159 { 1160 valid[0].left = valid[0].right - cx; 1161 valid[1].left = valid[1].right - cx; 1162 } 1163 else 1164 { 1165 valid[0].right = valid[0].left + cx; 1166 valid[1].right = valid[1].left + cx; 1167 } 1168 } 1169 1170 static 1171 LONG FASTCALL 1172 co_WinPosDoNCCALCSize(PWND Window, PWINDOWPOS WinPos, RECTL* WindowRect, RECTL* ClientRect, RECTL* validRects) 1173 { 1174 PWND Parent; 1175 UINT wvrFlags = 0; 1176 1177 ASSERT_REFS_CO(Window); 1178 1179 /* Send WM_NCCALCSIZE message to get new client area */ 1180 if ((WinPos->flags & (SWP_FRAMECHANGED | SWP_NOSIZE)) != SWP_NOSIZE) 1181 { 1182 NCCALCSIZE_PARAMS params; 1183 WINDOWPOS winposCopy; 1184 1185 params.rgrc[0] = *WindowRect; // new coordinates of a window that has been moved or resized 1186 params.rgrc[1] = Window->rcWindow; // window before it was moved or resized 1187 params.rgrc[2] = Window->rcClient; // client area before the window was moved or resized 1188 1189 Parent = Window->spwndParent; 1190 if (0 != (Window->style & WS_CHILD) && Parent) 1191 { 1192 RECTL_vOffsetRect(&(params.rgrc[0]), - Parent->rcClient.left, - Parent->rcClient.top); 1193 RECTL_vOffsetRect(&(params.rgrc[1]), - Parent->rcClient.left, - Parent->rcClient.top); 1194 RECTL_vOffsetRect(&(params.rgrc[2]), - Parent->rcClient.left, - Parent->rcClient.top); 1195 } 1196 1197 params.lppos = &winposCopy; 1198 winposCopy = *WinPos; 1199 1200 wvrFlags = co_IntSendMessage(Window->head.h, WM_NCCALCSIZE, TRUE, (LPARAM) ¶ms); 1201 1202 /* If the application send back garbage, ignore it */ 1203 if (params.rgrc[0].left <= params.rgrc[0].right && 1204 params.rgrc[0].top <= params.rgrc[0].bottom) 1205 { 1206 *ClientRect = params.rgrc[0]; // First rectangle contains the coordinates of the new client rectangle resulting from the move or resize 1207 if ((Window->style & WS_CHILD) && Parent) 1208 { 1209 RECTL_vOffsetRect(ClientRect, Parent->rcClient.left, Parent->rcClient.top); 1210 } 1211 FixClientRect(ClientRect, WindowRect); 1212 } 1213 1214 if (ClientRect->left != Window->rcClient.left || 1215 ClientRect->top != Window->rcClient.top) 1216 { 1217 WinPos->flags &= ~SWP_NOCLIENTMOVE; 1218 } 1219 1220 if (ClientRect->right - ClientRect->left != Window->rcClient.right - Window->rcClient.left) 1221 { 1222 WinPos->flags &= ~SWP_NOCLIENTSIZE; 1223 } 1224 else 1225 wvrFlags &= ~WVR_HREDRAW; 1226 1227 if (ClientRect->bottom - ClientRect->top != Window->rcClient.bottom - Window->rcClient.top) 1228 { 1229 WinPos->flags &= ~SWP_NOCLIENTSIZE; 1230 } 1231 else 1232 wvrFlags &= ~WVR_VREDRAW; 1233 1234 validRects[0] = params.rgrc[1]; // second rectangle contains the valid destination rectangle 1235 validRects[1] = params.rgrc[2]; // third rectangle contains the valid source rectangle 1236 } 1237 else 1238 { 1239 if (!(WinPos->flags & SWP_NOMOVE) && 1240 (ClientRect->left != Window->rcClient.left || 1241 ClientRect->top != Window->rcClient.top)) 1242 { 1243 WinPos->flags &= ~SWP_NOCLIENTMOVE; 1244 } 1245 } 1246 1247 if (WinPos->flags & (SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_SHOWWINDOW | SWP_HIDEWINDOW)) 1248 { 1249 RECTL_vSetEmptyRect( &validRects[0] ); 1250 RECTL_vSetEmptyRect( &validRects[1] ); 1251 } 1252 else get_valid_rects( &Window->rcClient, ClientRect, wvrFlags, validRects ); 1253 1254 return wvrFlags; 1255 } 1256 1257 static 1258 BOOL FASTCALL 1259 co_WinPosDoWinPosChanging(PWND Window, 1260 PWINDOWPOS WinPos, 1261 PRECTL WindowRect, 1262 PRECTL ClientRect) 1263 { 1264 ASSERT_REFS_CO(Window); 1265 1266 /* Send WM_WINDOWPOSCHANGING message */ 1267 1268 if (!(WinPos->flags & SWP_NOSENDCHANGING) 1269 && !((WinPos->flags & SWP_AGG_NOCLIENTCHANGE) && (WinPos->flags & SWP_SHOWWINDOW))) 1270 { 1271 TRACE("Sending WM_WINDOWPOSCHANGING to hwnd %p flags %04x.\n", Window->head.h,WinPos->flags); 1272 co_IntSendMessage(Window->head.h, WM_WINDOWPOSCHANGING, 0, (LPARAM) WinPos); 1273 } 1274 1275 /* Calculate new position and size */ 1276 1277 *WindowRect = Window->rcWindow; 1278 *ClientRect = (Window->style & WS_MINIMIZE) ? Window->rcWindow : Window->rcClient; 1279 1280 if (!(WinPos->flags & SWP_NOSIZE)) 1281 { 1282 if (Window->style & WS_MINIMIZE) 1283 { 1284 WindowRect->right = WindowRect->left + UserGetSystemMetrics(SM_CXMINIMIZED); 1285 WindowRect->bottom = WindowRect->top + UserGetSystemMetrics(SM_CYMINIMIZED); 1286 } 1287 else 1288 { 1289 WindowRect->right = WindowRect->left + WinPos->cx; 1290 WindowRect->bottom = WindowRect->top + WinPos->cy; 1291 } 1292 } 1293 1294 if (!(WinPos->flags & SWP_NOMOVE)) 1295 { 1296 INT X, Y; 1297 PWND Parent; 1298 X = WinPos->x; 1299 Y = WinPos->y; 1300 1301 Parent = Window->spwndParent; 1302 1303 // Parent child position issue is in here. SetParent_W7 test CORE-6651. 1304 if (//((Window->style & WS_CHILD) != 0) && <- Fixes wine msg test_SetParent: "rects do not match", the last test. 1305 Parent && 1306 Parent != Window->head.rpdesk->pDeskInfo->spwnd) 1307 { 1308 TRACE("Not SWP_NOMOVE 1 Parent client offset X %d Y %d\n",X,Y); 1309 X += Parent->rcClient.left; 1310 Y += Parent->rcClient.top; 1311 TRACE("Not SWP_NOMOVE 2 Parent client offset X %d Y %d\n",X,Y); 1312 } 1313 1314 WindowRect->left = X; 1315 WindowRect->top = Y; 1316 WindowRect->right += X - Window->rcWindow.left; 1317 WindowRect->bottom += Y - Window->rcWindow.top; 1318 1319 RECTL_vOffsetRect(ClientRect, X - Window->rcWindow.left, 1320 Y - Window->rcWindow.top); 1321 } 1322 WinPos->flags |= SWP_NOCLIENTMOVE | SWP_NOCLIENTSIZE; 1323 1324 TRACE( "hwnd %p, after %p, swp %d,%d %dx%d flags %08x\n", 1325 WinPos->hwnd, WinPos->hwndInsertAfter, WinPos->x, WinPos->y, 1326 WinPos->cx, WinPos->cy, WinPos->flags ); 1327 TRACE("WindowRect: %d %d %d %d\n", WindowRect->left,WindowRect->top,WindowRect->right,WindowRect->bottom); 1328 TRACE("ClientRect: %d %d %d %d\n", ClientRect->left,ClientRect->top,ClientRect->right,ClientRect->bottom); 1329 1330 return TRUE; 1331 } 1332 1333 /* 1334 * Fix Z order taking into account owned popups - 1335 * basically we need to maintain them above the window that owns them 1336 * 1337 * FIXME: hide/show owned popups when owner visibility changes. 1338 * 1339 * ReactOS: See bug CORE-6129 and CORE-6554. 1340 * 1341 */ 1342 //// 1343 // Pass all the win:test_children/popup_zorder tests except "move hwnd_F and its popups down" which is if'ed out. 1344 // Side effect, breaks more of the DeferWindowPos api tests, but wine breaks more!!!! 1345 static 1346 HWND FASTCALL 1347 WinPosDoOwnedPopups(PWND Window, HWND hWndInsertAfter) 1348 { 1349 HWND *List = NULL; 1350 HWND Owner; 1351 LONG Style; 1352 PWND DesktopWindow, ChildObject; 1353 int i; 1354 1355 TRACE("(%p) hInsertAfter = %p\n", Window, hWndInsertAfter ); 1356 1357 Style = Window->style; 1358 1359 if (Style & WS_CHILD) 1360 { 1361 TRACE("Window is child\n"); 1362 return hWndInsertAfter; 1363 } 1364 1365 Owner = Window->spwndOwner ? Window->spwndOwner->head.h : NULL; 1366 1367 if (Owner) 1368 { 1369 /* Make sure this popup stays above the owner */ 1370 1371 if (hWndInsertAfter != HWND_TOPMOST) 1372 { 1373 DesktopWindow = UserGetDesktopWindow(); 1374 List = IntWinListChildren(DesktopWindow); 1375 1376 if (List != NULL) 1377 { 1378 for (i = 0; List[i]; i++) 1379 { 1380 BOOL topmost = FALSE; 1381 1382 ChildObject = ValidateHwndNoErr(List[i]); 1383 if (ChildObject) 1384 { 1385 topmost = (ChildObject->ExStyle & WS_EX_TOPMOST) != 0; 1386 } 1387 1388 if (List[i] == Owner) 1389 { 1390 if (i > 0) hWndInsertAfter = List[i-1]; 1391 else hWndInsertAfter = topmost ? HWND_TOPMOST : HWND_TOP; 1392 break; 1393 } 1394 1395 if (hWndInsertAfter == HWND_TOP || hWndInsertAfter == HWND_NOTOPMOST) 1396 { 1397 if (!topmost) break; 1398 } 1399 else if (List[i] == hWndInsertAfter) break; 1400 } 1401 } 1402 else 1403 return hWndInsertAfter; 1404 } 1405 } 1406 1407 if (hWndInsertAfter == HWND_BOTTOM) 1408 { 1409 ERR("Window is HWND_BOTTOM hwnd %p\n",hWndInsertAfter); 1410 if (List) ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 1411 goto done; 1412 } 1413 1414 if (!List) 1415 { 1416 DesktopWindow = UserGetDesktopWindow(); 1417 List = IntWinListChildren(DesktopWindow); 1418 } 1419 1420 if (List != NULL) 1421 { 1422 i = 0; 1423 1424 if (hWndInsertAfter == HWND_TOP || hWndInsertAfter == HWND_NOTOPMOST) 1425 { 1426 if (hWndInsertAfter == HWND_NOTOPMOST || !(Window->ExStyle & WS_EX_TOPMOST)) 1427 { 1428 TRACE("skip all the topmost windows\n"); 1429 /* skip all the topmost windows */ 1430 while (List[i] && 1431 (ChildObject = ValidateHwndNoErr(List[i])) && 1432 (ChildObject->ExStyle & WS_EX_TOPMOST)) i++; 1433 } 1434 } 1435 else if (hWndInsertAfter != HWND_TOPMOST) 1436 { 1437 /* skip windows that are already placed correctly */ 1438 for (i = 0; List[i]; i++) 1439 { 1440 if (List[i] == hWndInsertAfter) break; 1441 if (List[i] == UserHMGetHandle(Window)) 1442 { 1443 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 1444 goto done; /* nothing to do if window is moving backwards in z-order */ 1445 } 1446 } 1447 } 1448 1449 for (; List[i]; i++) 1450 { 1451 PWND Wnd; 1452 USER_REFERENCE_ENTRY Ref; 1453 1454 if (List[i] == UserHMGetHandle(Window)) 1455 break; 1456 1457 if (!(Wnd = ValidateHwndNoErr(List[i]))) 1458 continue; 1459 1460 Owner = Wnd->spwndOwner ? Wnd->spwndOwner->head.h : NULL; 1461 1462 if (Owner != UserHMGetHandle(Window)) continue; 1463 1464 UserRefObjectCo(Wnd, &Ref); 1465 TRACE( "moving %p owned by %p after %p\n", List[i], UserHMGetHandle(Window), hWndInsertAfter ); 1466 co_WinPosSetWindowPos(Wnd, hWndInsertAfter, 0, 0, 0, 0, 1467 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_NOSENDCHANGING| SWP_DEFERERASE); 1468 1469 UserDerefObjectCo(Wnd); 1470 hWndInsertAfter = List[i]; 1471 } 1472 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 1473 } 1474 done: 1475 return hWndInsertAfter; 1476 } 1477 //// 1478 1479 /*********************************************************************** 1480 * WinPosInternalMoveWindow 1481 * 1482 * Update WindowRect and ClientRect of Window and all of its children 1483 * We keep both WindowRect and ClientRect in screen coordinates internally 1484 */ 1485 static 1486 VOID FASTCALL 1487 WinPosInternalMoveWindow(PWND Window, INT MoveX, INT MoveY) 1488 { 1489 PWND Child; 1490 1491 ASSERT(Window != Window->spwndChild); 1492 TRACE("InternalMoveWin X %d Y %d\n", MoveX, MoveY); 1493 1494 Window->rcWindow.left += MoveX; 1495 Window->rcWindow.right += MoveX; 1496 Window->rcWindow.top += MoveY; 1497 Window->rcWindow.bottom += MoveY; 1498 1499 Window->rcClient.left += MoveX; 1500 Window->rcClient.right += MoveX; 1501 Window->rcClient.top += MoveY; 1502 Window->rcClient.bottom += MoveY; 1503 1504 for(Child = Window->spwndChild; Child; Child = Child->spwndNext) 1505 { 1506 WinPosInternalMoveWindow(Child, MoveX, MoveY); 1507 } 1508 } 1509 1510 /* 1511 * WinPosFixupSWPFlags 1512 * 1513 * Fix redundant flags and values in the WINDOWPOS structure. 1514 */ 1515 static 1516 BOOL FASTCALL 1517 WinPosFixupFlags(WINDOWPOS *WinPos, PWND Wnd) 1518 { 1519 PWND Parent; 1520 POINT pt; 1521 1522 /* Finally make sure that all coordinates are valid */ 1523 if (WinPos->x < -32768) WinPos->x = -32768; 1524 else if (WinPos->x > 32767) WinPos->x = 32767; 1525 if (WinPos->y < -32768) WinPos->y = -32768; 1526 else if (WinPos->y > 32767) WinPos->y = 32767; 1527 1528 WinPos->cx = max(WinPos->cx, 0); 1529 WinPos->cy = max(WinPos->cy, 0); 1530 1531 Parent = UserGetAncestor( Wnd, GA_PARENT ); 1532 if (!IntIsWindowVisible( Parent ) && 1533 /* Fix B : wine msg test_SetParent:WmSetParentSeq_2:25 wParam bits! */ 1534 (WinPos->flags & SWP_AGG_STATUSFLAGS) == SWP_AGG_NOPOSCHANGE) WinPos->flags |= SWP_NOREDRAW; 1535 1536 if (Wnd->style & WS_VISIBLE) WinPos->flags &= ~SWP_SHOWWINDOW; 1537 else 1538 { 1539 WinPos->flags &= ~SWP_HIDEWINDOW; 1540 if (!(WinPos->flags & SWP_SHOWWINDOW)) WinPos->flags |= SWP_NOREDRAW; 1541 } 1542 1543 /* Check for right size */ 1544 if (Wnd->rcWindow.right - Wnd->rcWindow.left == WinPos->cx && 1545 Wnd->rcWindow.bottom - Wnd->rcWindow.top == WinPos->cy) 1546 { 1547 WinPos->flags |= SWP_NOSIZE; 1548 } 1549 1550 pt.x = WinPos->x; 1551 pt.y = WinPos->y; 1552 IntClientToScreen( Parent, &pt ); 1553 TRACE("WPFU C2S wpx %d wpy %d ptx %d pty %d\n",WinPos->x,WinPos->y,pt.x,pt.y); 1554 /* Check for right position */ 1555 if (Wnd->rcWindow.left == pt.x && Wnd->rcWindow.top == pt.y) 1556 { 1557 //ERR("In right pos\n"); 1558 WinPos->flags |= SWP_NOMOVE; 1559 } 1560 1561 if ( WinPos->hwnd != UserGetForegroundWindow() && (Wnd->style & (WS_POPUP | WS_CHILD)) != WS_CHILD) 1562 { 1563 /* Bring to the top when activating */ 1564 if (!(WinPos->flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW)) && 1565 (WinPos->flags & SWP_NOZORDER || 1566 (WinPos->hwndInsertAfter != HWND_TOPMOST && WinPos->hwndInsertAfter != HWND_NOTOPMOST))) 1567 { 1568 WinPos->flags &= ~SWP_NOZORDER; 1569 WinPos->hwndInsertAfter = (0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP); 1570 } 1571 } 1572 1573 /* Check hwndInsertAfter */ 1574 if (!(WinPos->flags & SWP_NOZORDER)) 1575 { 1576 /* Fix sign extension */ 1577 if (WinPos->hwndInsertAfter == (HWND)0xffff) 1578 { 1579 WinPos->hwndInsertAfter = HWND_TOPMOST; 1580 } 1581 else if (WinPos->hwndInsertAfter == (HWND)0xfffe) 1582 { 1583 WinPos->hwndInsertAfter = HWND_NOTOPMOST; 1584 } 1585 1586 if (WinPos->hwndInsertAfter == HWND_TOP) 1587 { 1588 /* Keep it topmost when it's already topmost */ 1589 if ((Wnd->ExStyle & WS_EX_TOPMOST) != 0) 1590 WinPos->hwndInsertAfter = HWND_TOPMOST; 1591 1592 if (IntGetWindow(WinPos->hwnd, GW_HWNDFIRST) == WinPos->hwnd) 1593 { 1594 WinPos->flags |= SWP_NOZORDER; 1595 } 1596 } 1597 else if (WinPos->hwndInsertAfter == HWND_BOTTOM) 1598 { 1599 if (!(Wnd->ExStyle & WS_EX_TOPMOST) && IntGetWindow(WinPos->hwnd, GW_HWNDLAST) == WinPos->hwnd) 1600 WinPos->flags |= SWP_NOZORDER; 1601 } 1602 else if (WinPos->hwndInsertAfter == HWND_TOPMOST) 1603 { 1604 if ((Wnd->ExStyle & WS_EX_TOPMOST) && IntGetWindow(WinPos->hwnd, GW_HWNDFIRST) == WinPos->hwnd) 1605 WinPos->flags |= SWP_NOZORDER; 1606 } 1607 else if (WinPos->hwndInsertAfter == HWND_NOTOPMOST) 1608 { 1609 if (!(Wnd->ExStyle & WS_EX_TOPMOST)) 1610 WinPos->flags |= SWP_NOZORDER; 1611 } 1612 else /* hwndInsertAfter must be a sibling of the window */ 1613 { 1614 PWND InsAfterWnd; 1615 1616 InsAfterWnd = ValidateHwndNoErr(WinPos->hwndInsertAfter); 1617 if(!InsAfterWnd) 1618 { 1619 return TRUE; 1620 } 1621 1622 if (InsAfterWnd->spwndParent != Wnd->spwndParent) 1623 { 1624 /* Note from wine User32 Win test_SetWindowPos: 1625 "Returns TRUE also for windows that are not siblings" 1626 "Does not seem to do anything even without passing flags, still returns TRUE" 1627 "Same thing the other way around." 1628 ".. and with these windows." 1629 */ 1630 return FALSE; 1631 } 1632 else 1633 { 1634 /* 1635 * We don't need to change the Z order of hwnd if it's already 1636 * inserted after hwndInsertAfter or when inserting hwnd after 1637 * itself. 1638 */ 1639 if ((WinPos->hwnd == WinPos->hwndInsertAfter) || 1640 ((InsAfterWnd->spwndNext) && (WinPos->hwnd == InsAfterWnd->spwndNext->head.h))) 1641 { 1642 WinPos->flags |= SWP_NOZORDER; 1643 } 1644 } 1645 } 1646 } 1647 1648 return TRUE; 1649 } 1650 1651 /* x and y are always screen relative */ 1652 BOOLEAN FASTCALL 1653 co_WinPosSetWindowPos( 1654 PWND Window, 1655 HWND WndInsertAfter, 1656 INT x, 1657 INT y, 1658 INT cx, 1659 INT cy, 1660 UINT flags 1661 ) 1662 { 1663 WINDOWPOS WinPos; 1664 RECTL NewWindowRect; 1665 RECTL NewClientRect; 1666 RECTL valid_rects[2]; 1667 PREGION VisBefore = NULL; 1668 PREGION VisBeforeJustClient = NULL; 1669 PREGION VisAfter = NULL; 1670 PREGION CopyRgn = NULL; 1671 ULONG WvrFlags = 0; 1672 RECTL OldWindowRect, OldClientRect; 1673 int RgnType; 1674 HDC Dc; 1675 RECTL CopyRect; 1676 PWND Ancestor; 1677 BOOL bPointerInWindow, PosChanged = FALSE; 1678 PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); 1679 1680 ASSERT_REFS_CO(Window); 1681 1682 TRACE("pwnd %p, after %p, %d,%d (%dx%d), flags %s", 1683 Window, WndInsertAfter, x, y, cx, cy, flags); 1684 #if DBG 1685 dump_winpos_flags(flags); 1686 #endif 1687 1688 /* FIXME: Get current active window from active queue. Why? since r2915. */ 1689 1690 bPointerInWindow = IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y); 1691 1692 WinPos.hwnd = Window->head.h; 1693 WinPos.hwndInsertAfter = WndInsertAfter; 1694 WinPos.x = x; 1695 WinPos.y = y; 1696 WinPos.cx = cx; 1697 WinPos.cy = cy; 1698 WinPos.flags = flags; 1699 1700 if ( flags & SWP_ASYNCWINDOWPOS ) 1701 { 1702 LRESULT lRes; 1703 PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP); 1704 if ( ppos ) 1705 { 1706 WinPos.flags &= ~SWP_ASYNCWINDOWPOS; // Clear flag. 1707 *ppos = WinPos; 1708 /* Yes it's a pointer inside Win32k! */ 1709 lRes = co_IntSendMessageNoWait( WinPos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos); 1710 /* We handle this the same way as Event Hooks and Hooks. */ 1711 if ( !lRes ) 1712 { 1713 ExFreePoolWithTag(ppos, USERTAG_SWP); 1714 return FALSE; 1715 } 1716 return TRUE; 1717 } 1718 return FALSE; 1719 } 1720 1721 co_WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect); 1722 1723 /* Does the window still exist? */ 1724 if (!IntIsWindow(WinPos.hwnd)) 1725 { 1726 TRACE("WinPosSetWindowPos: Invalid handle 0x%p!\n",WinPos.hwnd); 1727 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); 1728 return FALSE; 1729 } 1730 1731 /* Fix up the flags. */ 1732 if (!WinPosFixupFlags(&WinPos, Window)) 1733 { 1734 // See Note. 1735 return TRUE; 1736 } 1737 1738 Ancestor = UserGetAncestor(Window, GA_PARENT); 1739 if ( (WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) != SWP_NOZORDER && 1740 Ancestor && Ancestor->head.h == IntGetDesktopWindow() ) 1741 { 1742 WinPos.hwndInsertAfter = WinPosDoOwnedPopups(Window, WinPos.hwndInsertAfter); 1743 } 1744 1745 if (!(WinPos.flags & SWP_NOREDRAW)) 1746 { 1747 /* Compute the visible region before the window position is changed */ 1748 if (!(WinPos.flags & SWP_SHOWWINDOW) && 1749 (WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | 1750 SWP_HIDEWINDOW | SWP_FRAMECHANGED)) != 1751 (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER)) 1752 { 1753 VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, 1754 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); 1755 1756 if ( VisBefore != NULL && 1757 REGION_Complexity(VisBefore) == NULLREGION ) 1758 { 1759 REGION_Delete(VisBefore); 1760 VisBefore = NULL; 1761 } 1762 else if(VisBefore) 1763 { 1764 REGION_bOffsetRgn(VisBefore, -Window->rcWindow.left, -Window->rcWindow.top); 1765 } 1766 1767 /* Calculate the non client area for resizes, as this is used in the copy region */ 1768 if (!(WinPos.flags & SWP_NOSIZE)) 1769 { 1770 VisBeforeJustClient = VIS_ComputeVisibleRegion(Window, TRUE, FALSE, 1771 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); 1772 1773 if ( VisBeforeJustClient != NULL && 1774 REGION_Complexity(VisBeforeJustClient) == NULLREGION ) 1775 { 1776 REGION_Delete(VisBeforeJustClient); 1777 VisBeforeJustClient = NULL; 1778 } 1779 else if(VisBeforeJustClient) 1780 { 1781 REGION_bOffsetRgn(VisBeforeJustClient, -Window->rcWindow.left, -Window->rcWindow.top); 1782 } 1783 } 1784 } 1785 } 1786 1787 //// HACK 3 1788 if (Window->hrgnNewFrame) 1789 { 1790 SelectWindowRgn( Window, Window->hrgnNewFrame ); // Should be PSMWP->acvr->hrgnClip 1791 Window->hrgnNewFrame = NULL; 1792 } 1793 1794 WvrFlags = co_WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect, valid_rects); 1795 1796 // ERR("co_WinPosDoNCCALCSize returned 0x%x\n valid dest: %d %d %d %d\n valid src : %d %d %d %d\n", WvrFlags, 1797 // valid_rects[0].left,valid_rects[0].top,valid_rects[0].right,valid_rects[0].bottom, 1798 // valid_rects[1].left,valid_rects[1].top,valid_rects[1].right,valid_rects[1].bottom); 1799 1800 /* Validate link windows. (also take into account shell window in hwndShellWindow) */ 1801 if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow()) 1802 { 1803 IntLinkHwnd(Window, WinPos.hwndInsertAfter); 1804 } 1805 1806 OldWindowRect = Window->rcWindow; 1807 OldClientRect = Window->rcClient; 1808 1809 if (NewClientRect.left != OldClientRect.left || 1810 NewClientRect.top != OldClientRect.top) 1811 { 1812 // Move child window if their parent is moved. Keep Child window relative to Parent... 1813 WinPosInternalMoveWindow(Window, 1814 NewClientRect.left - OldClientRect.left, 1815 NewClientRect.top - OldClientRect.top); 1816 PosChanged = TRUE; 1817 } 1818 1819 Window->rcWindow = NewWindowRect; 1820 Window->rcClient = NewClientRect; 1821 1822 /* erase parent when hiding or resizing child */ 1823 if (WinPos.flags & SWP_HIDEWINDOW) 1824 { 1825 /* Clear the update region */ 1826 co_UserRedrawWindow( Window, 1827 NULL, 1828 0, 1829 RDW_VALIDATE | RDW_NOFRAME | RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN); 1830 1831 if (UserIsDesktopWindow(Window->spwndParent)) 1832 co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (WPARAM)Window->head.h, 0); 1833 1834 Window->style &= ~WS_VISIBLE; //IntSetStyle( Window, 0, WS_VISIBLE ); 1835 Window->head.pti->cVisWindows--; 1836 IntNotifyWinEvent(EVENT_OBJECT_HIDE, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); 1837 } 1838 else if (WinPos.flags & SWP_SHOWWINDOW) 1839 { 1840 if (UserIsDesktopWindow(Window->spwndParent) && 1841 Window->spwndOwner == NULL && 1842 (!(Window->ExStyle & WS_EX_TOOLWINDOW) || 1843 (Window->ExStyle & WS_EX_APPWINDOW))) 1844 co_IntShellHookNotify(HSHELL_WINDOWCREATED, (WPARAM)Window->head.h, 0); 1845 1846 Window->style |= WS_VISIBLE; //IntSetStyle( Window, WS_VISIBLE, 0 ); 1847 Window->head.pti->cVisWindows++; 1848 IntNotifyWinEvent(EVENT_OBJECT_SHOW, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); 1849 } 1850 1851 if (Window->hrgnUpdate != NULL && Window->hrgnUpdate != HRGN_WINDOW) 1852 { 1853 NtGdiOffsetRgn(Window->hrgnUpdate, 1854 NewWindowRect.left - OldWindowRect.left, 1855 NewWindowRect.top - OldWindowRect.top); 1856 } 1857 1858 DceResetActiveDCEs(Window); // For WS_VISIBLE changes. 1859 1860 if (!(WinPos.flags & SWP_NOREDRAW)) 1861 { 1862 /* Determine the new visible region */ 1863 VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, 1864 (Window->style & WS_CLIPSIBLINGS) ? TRUE : FALSE); 1865 1866 if ( VisAfter != NULL && 1867 REGION_Complexity(VisAfter) == NULLREGION ) 1868 { 1869 REGION_Delete(VisAfter); 1870 VisAfter = NULL; 1871 } 1872 else if(VisAfter) 1873 { 1874 REGION_bOffsetRgn(VisAfter, -Window->rcWindow.left, -Window->rcWindow.top); 1875 } 1876 1877 /* 1878 * Determine which pixels can be copied from the old window position 1879 * to the new. Those pixels must be visible in both the old and new 1880 * position. Also, check the class style to see if the windows of this 1881 * class need to be completely repainted on (horizontal/vertical) size 1882 * change. 1883 */ 1884 if ( ( VisBefore != NULL && 1885 VisAfter != NULL && 1886 !(WinPos.flags & SWP_NOCOPYBITS) && 1887 ((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) && 1888 !(Window->ExStyle & WS_EX_TRANSPARENT) ) || 1889 ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) && VisBefore) ) 1890 { 1891 1892 /* 1893 * If this is (also) a window resize, the whole nonclient area 1894 * needs to be repainted. So we limit the copy to the client area, 1895 * 'cause there is no use in copying it (would possibly cause 1896 * "flashing" too). However, if the copy region is already empty, 1897 * we don't have to crop (can't take anything away from an empty 1898 * region...) 1899 */ 1900 1901 CopyRgn = IntSysCreateRectpRgn(0, 0, 0, 0); 1902 if (WinPos.flags & SWP_NOSIZE) 1903 RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND); 1904 else if (VisBeforeJustClient != NULL) 1905 { 1906 RgnType = IntGdiCombineRgn(CopyRgn, VisAfter, VisBeforeJustClient, RGN_AND); 1907 REGION_Delete(VisBeforeJustClient); 1908 } 1909 1910 /* Now use in copying bits which are in the update region. */ 1911 if (Window->hrgnUpdate != NULL) 1912 { 1913 PREGION RgnUpdate = REGION_LockRgn(Window->hrgnUpdate); 1914 if (RgnUpdate) 1915 { 1916 REGION_bOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top); 1917 IntGdiCombineRgn(CopyRgn, CopyRgn, RgnUpdate, RGN_DIFF); 1918 REGION_bOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top); 1919 REGION_UnlockRgn(RgnUpdate); 1920 } 1921 } 1922 1923 /* 1924 * Now, get the bounding box of the copy region. If it's empty 1925 * there's nothing to copy. Also, it's no use copying bits onto 1926 * themselves. 1927 */ 1928 if (REGION_GetRgnBox(CopyRgn, &CopyRect) == NULLREGION) 1929 { 1930 /* Nothing to copy, clean up */ 1931 REGION_Delete(CopyRgn); 1932 CopyRgn = NULL; 1933 } 1934 else if ( OldWindowRect.left != NewWindowRect.left || 1935 OldWindowRect.top != NewWindowRect.top || 1936 (WinPos.flags & SWP_FRAMECHANGED) ) 1937 { 1938 HRGN DcRgn = NtGdiCreateRectRgn(0, 0, 0, 0); 1939 PREGION DcRgnObj = REGION_LockRgn(DcRgn); 1940 1941 /* 1942 * Small trick here: there is no function to bitblt a region. So 1943 * we set the region as the clipping region, take the bounding box 1944 * of the region and bitblt that. Since nothing outside the clipping 1945 * region is copied, this has the effect of bitblt'ing the region. 1946 * 1947 * Since NtUserGetDCEx takes ownership of the clip region, we need 1948 * to create a copy of CopyRgn and pass that. We need CopyRgn later 1949 */ 1950 IntGdiCombineRgn(DcRgnObj, CopyRgn, NULL, RGN_COPY); 1951 REGION_bOffsetRgn(DcRgnObj, NewWindowRect.left, NewWindowRect.top); 1952 REGION_UnlockRgn(DcRgnObj); 1953 Dc = UserGetDCEx( Window, 1954 DcRgn, 1955 DCX_WINDOW|DCX_CACHE|DCX_INTERSECTRGN|DCX_CLIPSIBLINGS|DCX_KEEPCLIPRGN); 1956 NtGdiBitBlt( Dc, 1957 CopyRect.left, CopyRect.top, 1958 CopyRect.right - CopyRect.left, 1959 CopyRect.bottom - CopyRect.top, 1960 Dc, 1961 CopyRect.left + (OldWindowRect.left - NewWindowRect.left), 1962 CopyRect.top + (OldWindowRect.top - NewWindowRect.top), 1963 SRCCOPY, 1964 0, 1965 0); 1966 1967 UserReleaseDC(Window, Dc, FALSE); 1968 IntValidateParent(Window, CopyRgn); 1969 GreDeleteObject(DcRgn); 1970 } 1971 } 1972 else 1973 { 1974 CopyRgn = NULL; 1975 } 1976 #if 0 1977 /////// Fixes NoPopup tests but breaks msg_paint tests. 1978 if ( !PosChanged && (WinPos.flags & SWP_FRAMECHANGED) && VisBefore) 1979 { 1980 PWND Parent = Window->spwndParent; 1981 ERR("SWP_FRAMECHANGED no chg\n"); 1982 if ( !(Window->style & WS_CHILD) && (Parent) && (Parent->style & WS_CLIPCHILDREN)) 1983 { 1984 ERR("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n"); 1985 //IntInvalidateWindows( Window, VisBefore, /*RDW_ERASE |*/ RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); 1986 } 1987 } 1988 #endif 1989 /* We need to redraw what wasn't visible before */ 1990 if (VisAfter != NULL) 1991 { 1992 PREGION DirtyRgn = IntSysCreateRectpRgn(0, 0, 0, 0); 1993 if (DirtyRgn) 1994 { 1995 if (CopyRgn != NULL) 1996 { 1997 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF); 1998 } 1999 else 2000 { 2001 RgnType = IntGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY); 2002 } 2003 2004 if (RgnType != ERROR && RgnType != NULLREGION) 2005 { 2006 /* old code 2007 NtGdiOffsetRgn(DirtyRgn, Window->rcWindow.left, Window->rcWindow.top); 2008 IntInvalidateWindows( Window, 2009 DirtyRgn, 2010 RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); 2011 } 2012 GreDeleteObject(DirtyRgn); 2013 */ 2014 2015 PWND Parent = Window->spwndParent; 2016 2017 REGION_bOffsetRgn( DirtyRgn, Window->rcWindow.left, Window->rcWindow.top); 2018 2019 if ( (Window->style & WS_CHILD) && (Parent) && !(Parent->style & WS_CLIPCHILDREN)) 2020 { 2021 IntInvalidateWindows( Parent, DirtyRgn, RDW_ERASE | RDW_INVALIDATE); 2022 co_IntPaintWindows(Parent, RDW_NOCHILDREN, FALSE); 2023 } 2024 else 2025 { 2026 IntInvalidateWindows( Window, DirtyRgn, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); 2027 } 2028 } 2029 REGION_Delete(DirtyRgn); 2030 } 2031 } 2032 2033 if (CopyRgn != NULL) 2034 { 2035 REGION_Delete(CopyRgn); 2036 } 2037 2038 /* Expose what was covered before but not covered anymore */ 2039 if (VisBefore != NULL) 2040 { 2041 PREGION ExposedRgn = IntSysCreateRectpRgn(0, 0, 0, 0); 2042 if (ExposedRgn) 2043 { 2044 RgnType = IntGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY); 2045 REGION_bOffsetRgn(ExposedRgn, 2046 OldWindowRect.left - NewWindowRect.left, 2047 OldWindowRect.top - NewWindowRect.top); 2048 2049 if (VisAfter != NULL) 2050 RgnType = IntGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF); 2051 2052 if (RgnType != ERROR && RgnType != NULLREGION) 2053 { 2054 co_VIS_WindowLayoutChanged(Window, ExposedRgn); 2055 } 2056 REGION_Delete(ExposedRgn); 2057 } 2058 REGION_Delete(VisBefore); 2059 } 2060 2061 if (VisAfter != NULL) 2062 { 2063 REGION_Delete(VisAfter); 2064 } 2065 } 2066 2067 if (!(WinPos.flags & (SWP_NOACTIVATE|SWP_HIDEWINDOW))) 2068 { 2069 if ((Window->style & (WS_CHILD | WS_POPUP)) == WS_CHILD) 2070 { 2071 co_IntSendMessageNoWait(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0); 2072 } 2073 else 2074 { 2075 //ERR("SetWindowPos Set FG Window!\n"); 2076 if ( pti->MessageQueue->spwndActive != Window || 2077 pti->MessageQueue != gpqForeground ) 2078 { 2079 //ERR("WPSWP : set active window\n"); 2080 if (!(Window->state & WNDS_BEINGACTIVATED)) // Inside SAW? 2081 { 2082 co_IntSetForegroundWindow(Window); // Fixes SW_HIDE issues. Wine win test_SetActiveWindow & test_SetForegroundWindow. 2083 } 2084 } 2085 } 2086 } 2087 2088 if ( !PosChanged && 2089 (WinPos.flags & SWP_FRAMECHANGED) && 2090 !(WinPos.flags & SWP_DEFERERASE) && // Prevent sending WM_SYNCPAINT message. 2091 VisAfter ) 2092 { 2093 PWND Parent = Window->spwndParent; 2094 if ( !(Window->style & WS_CHILD) && (Parent) && (Parent->style & WS_CLIPCHILDREN)) 2095 { 2096 TRACE("SWP_FRAMECHANGED Parent WS_CLIPCHILDREN\n"); 2097 UserSyncAndPaintWindows( Parent, RDW_CLIPCHILDREN); 2098 } 2099 } 2100 2101 // Fix wine msg test_SetFocus, prevents sending WM_WINDOWPOSCHANGED. 2102 if ( VisBefore == NULL && 2103 VisBeforeJustClient == NULL && 2104 !(Window->ExStyle & WS_EX_TOPMOST) && 2105 (WinPos.flags & SWP_AGG_STATUSFLAGS) == (SWP_AGG_NOPOSCHANGE & ~SWP_NOZORDER)) 2106 { 2107 TRACE("No drawing, set no Z order and no redraw!\n"); 2108 WinPos.flags |= SWP_NOZORDER|SWP_NOREDRAW; 2109 } 2110 2111 if(!(flags & SWP_DEFERERASE)) 2112 { 2113 /* erase parent when hiding or resizing child */ 2114 if ((flags & SWP_HIDEWINDOW) || 2115 (!(flags & SWP_SHOWWINDOW) && 2116 (WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOGEOMETRYCHANGE)) 2117 { 2118 PWND Parent = Window->spwndParent; 2119 if (!Parent || UserIsDesktopWindow(Parent)) Parent = Window; 2120 UserSyncAndPaintWindows( Parent, RDW_ERASENOW); 2121 } 2122 2123 /* Give newly shown windows a chance to redraw */ 2124 if(((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) 2125 && !(flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW)) 2126 { 2127 UserSyncAndPaintWindows( Window, RDW_ERASENOW); 2128 } 2129 } 2130 2131 /* And last, send the WM_WINDOWPOSCHANGED message */ 2132 2133 TRACE("\tstatus hwnd %p flags = %04x\n",Window?Window->head.h:NULL,WinPos.flags & SWP_AGG_STATUSFLAGS); 2134 2135 if (((WinPos.flags & SWP_AGG_STATUSFLAGS) != SWP_AGG_NOPOSCHANGE) 2136 && !((flags & SWP_AGG_NOCLIENTCHANGE) && (flags & SWP_SHOWWINDOW))) 2137 { 2138 /* WM_WINDOWPOSCHANGED is sent even if SWP_NOSENDCHANGING is set 2139 and always contains final window position. 2140 */ 2141 WinPos.x = NewWindowRect.left; 2142 WinPos.y = NewWindowRect.top; 2143 WinPos.cx = NewWindowRect.right - NewWindowRect.left; 2144 WinPos.cy = NewWindowRect.bottom - NewWindowRect.top; 2145 TRACE("WM_WINDOWPOSCHANGED hwnd %p Flags %04x\n",WinPos.hwnd,WinPos.flags); 2146 co_IntSendMessageNoWait(WinPos.hwnd, WM_WINDOWPOSCHANGED, 0, (LPARAM) &WinPos); 2147 } 2148 2149 if ( WinPos.flags & SWP_FRAMECHANGED || WinPos.flags & SWP_STATECHANGED || 2150 !(WinPos.flags & SWP_NOCLIENTSIZE) || !(WinPos.flags & SWP_NOCLIENTMOVE) ) 2151 { 2152 PWND pWnd = ValidateHwndNoErr(WinPos.hwnd); 2153 if (pWnd) 2154 IntNotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, pWnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); 2155 } 2156 2157 if(bPointerInWindow != IntPtInWindow(Window, gpsi->ptCursor.x, gpsi->ptCursor.y)) 2158 { 2159 /* Generate mouse move message */ 2160 MSG msg; 2161 msg.message = WM_MOUSEMOVE; 2162 msg.wParam = UserGetMouseButtonsState(); 2163 msg.lParam = MAKELPARAM(gpsi->ptCursor.x, gpsi->ptCursor.y); 2164 msg.pt = gpsi->ptCursor; 2165 co_MsqInsertMouseMessage(&msg, 0, 0, TRUE); 2166 } 2167 2168 return TRUE; 2169 } 2170 2171 LRESULT FASTCALL 2172 co_WinPosGetNonClientSize(PWND Window, RECT* WindowRect, RECT* ClientRect) 2173 { 2174 LRESULT Result; 2175 2176 ASSERT_REFS_CO(Window); 2177 2178 *ClientRect = *WindowRect; 2179 Result = co_IntSendMessageNoWait(Window->head.h, WM_NCCALCSIZE, FALSE, (LPARAM) ClientRect); 2180 2181 FixClientRect(ClientRect, WindowRect); 2182 2183 return Result; 2184 } 2185 2186 void FASTCALL 2187 co_WinPosSendSizeMove(PWND Wnd) 2188 { 2189 RECTL Rect; 2190 LPARAM lParam; 2191 WPARAM wParam = SIZE_RESTORED; 2192 2193 IntGetClientRect(Wnd, &Rect); 2194 lParam = MAKELONG(Rect.right-Rect.left, Rect.bottom-Rect.top); 2195 2196 Wnd->state &= ~WNDS_SENDSIZEMOVEMSGS; 2197 2198 if (Wnd->style & WS_MAXIMIZE) 2199 { 2200 wParam = SIZE_MAXIMIZED; 2201 } 2202 else if (Wnd->style & WS_MINIMIZE) 2203 { 2204 wParam = SIZE_MINIMIZED; 2205 lParam = 0; 2206 } 2207 2208 co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_SIZE, wParam, lParam); 2209 2210 if (UserIsDesktopWindow(Wnd->spwndParent)) 2211 lParam = MAKELONG(Wnd->rcClient.left, Wnd->rcClient.top); 2212 else 2213 lParam = MAKELONG(Wnd->rcClient.left-Wnd->spwndParent->rcClient.left, Wnd->rcClient.top-Wnd->spwndParent->rcClient.top); 2214 2215 co_IntSendMessageNoWait(UserHMGetHandle(Wnd), WM_MOVE, 0, lParam); 2216 2217 IntEngWindowChanged(Wnd, WOC_RGN_CLIENT); 2218 } 2219 2220 UINT FASTCALL 2221 co_WinPosMinMaximize(PWND Wnd, UINT ShowFlag, RECT* NewPos) 2222 { 2223 POINT Size; 2224 WINDOWPLACEMENT wpl; 2225 LONG old_style; 2226 UINT SwpFlags = 0; 2227 2228 ASSERT_REFS_CO(Wnd); 2229 2230 wpl.length = sizeof(wpl); 2231 IntGetWindowPlacement( Wnd, &wpl ); 2232 2233 if (co_HOOK_CallHooks( WH_CBT, HCBT_MINMAX, (WPARAM)Wnd->head.h, ShowFlag)) 2234 { 2235 ERR("WinPosMinMaximize WH_CBT Call Hook return!\n"); 2236 return SWP_NOSIZE | SWP_NOMOVE; 2237 } 2238 if (Wnd->style & WS_MINIMIZE) 2239 { 2240 switch (ShowFlag) 2241 { 2242 case SW_MINIMIZE: 2243 case SW_SHOWMINNOACTIVE: 2244 case SW_SHOWMINIMIZED: 2245 case SW_FORCEMINIMIZE: 2246 return SWP_NOSIZE | SWP_NOMOVE; 2247 } 2248 if (!co_IntSendMessageNoWait(Wnd->head.h, WM_QUERYOPEN, 0, 0)) 2249 { 2250 return(SWP_NOSIZE | SWP_NOMOVE); 2251 } 2252 SwpFlags |= SWP_NOCOPYBITS; 2253 } 2254 switch (ShowFlag) 2255 { 2256 case SW_MINIMIZE: 2257 case SW_SHOWMINNOACTIVE: 2258 case SW_SHOWMINIMIZED: 2259 case SW_FORCEMINIMIZE: 2260 { 2261 //ERR("MinMaximize Minimize\n"); 2262 if (Wnd->style & WS_MAXIMIZE) 2263 { 2264 Wnd->InternalPos.flags |= WPF_RESTORETOMAXIMIZED; 2265 } 2266 else 2267 { 2268 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; 2269 } 2270 2271 old_style = IntSetStyle( Wnd, WS_MINIMIZE, WS_MAXIMIZE ); 2272 2273 co_UserRedrawWindow(Wnd, NULL, 0, RDW_VALIDATE | RDW_NOERASE | RDW_NOINTERNALPAINT); 2274 2275 if (!(Wnd->InternalPos.flags & WPF_SETMINPOSITION)) 2276 Wnd->InternalPos.flags &= ~WPF_MININIT; 2277 2278 WinPosFindIconPos(Wnd, &wpl.ptMinPosition); 2279 2280 /*if (!(old_style & WS_MINIMIZE)) 2281 { 2282 SwpFlags |= SWP_STATECHANGED; 2283 IntShowOwnedPopups(Wnd, FALSE); 2284 }*/ 2285 2286 RECTL_vSetRect(NewPos, wpl.ptMinPosition.x, wpl.ptMinPosition.y, 2287 wpl.ptMinPosition.x + UserGetSystemMetrics(SM_CXMINIMIZED), 2288 wpl.ptMinPosition.y + UserGetSystemMetrics(SM_CYMINIMIZED)); 2289 SwpFlags |= SWP_NOCOPYBITS; 2290 break; 2291 } 2292 2293 case SW_MAXIMIZE: 2294 { 2295 //ERR("MinMaximize Maximize\n"); 2296 if ((Wnd->style & WS_MAXIMIZE) && (Wnd->style & WS_VISIBLE)) 2297 { 2298 SwpFlags = SWP_NOSIZE | SWP_NOMOVE; 2299 break; 2300 } 2301 co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); 2302 2303 /*ERR("Maximize: %d,%d %dx%d\n", 2304 wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, Size.x, Size.y); 2305 */ 2306 old_style = IntSetStyle( Wnd, WS_MAXIMIZE, WS_MINIMIZE ); 2307 /*if (old_style & WS_MINIMIZE) 2308 { 2309 IntShowOwnedPopups(Wnd, TRUE); 2310 }*/ 2311 2312 if (!(old_style & WS_MAXIMIZE)) SwpFlags |= SWP_STATECHANGED; 2313 RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, 2314 //wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y); 2315 Size.x, Size.y); 2316 break; 2317 } 2318 2319 case SW_SHOWNOACTIVATE: 2320 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; 2321 /* fall through */ 2322 case SW_SHOWNORMAL: 2323 case SW_RESTORE: 2324 case SW_SHOWDEFAULT: /* FIXME: should have its own handler */ 2325 { 2326 //ERR("MinMaximize Restore\n"); 2327 old_style = IntSetStyle( Wnd, 0, WS_MINIMIZE | WS_MAXIMIZE ); 2328 if (old_style & WS_MINIMIZE) 2329 { 2330 //IntShowOwnedPopups(Wnd, TRUE); 2331 2332 if (Wnd->InternalPos.flags & WPF_RESTORETOMAXIMIZED) 2333 { 2334 co_WinPosGetMinMaxInfo(Wnd, &Size, &wpl.ptMaxPosition, NULL, NULL); 2335 IntSetStyle( Wnd, WS_MAXIMIZE, 0 ); 2336 SwpFlags |= SWP_STATECHANGED; 2337 RECTL_vSetRect(NewPos, wpl.ptMaxPosition.x, wpl.ptMaxPosition.y, 2338 wpl.ptMaxPosition.x + Size.x, wpl.ptMaxPosition.y + Size.y); 2339 break; 2340 } 2341 else 2342 { 2343 *NewPos = wpl.rcNormalPosition; 2344 NewPos->right -= NewPos->left; 2345 NewPos->bottom -= NewPos->top; 2346 break; 2347 } 2348 } 2349 else 2350 { 2351 if (!(old_style & WS_MAXIMIZE)) 2352 { 2353 break; 2354 } 2355 SwpFlags |= SWP_STATECHANGED; 2356 Wnd->InternalPos.flags &= ~WPF_RESTORETOMAXIMIZED; 2357 *NewPos = wpl.rcNormalPosition; 2358 NewPos->right -= NewPos->left; 2359 NewPos->bottom -= NewPos->top; 2360 break; 2361 } 2362 } 2363 } 2364 return SwpFlags; 2365 } 2366 2367 /* 2368 ShowWindow does not set SWP_FRAMECHANGED!!! Fix wine msg test_SetParent:WmSetParentSeq_2:23 wParam bits! 2369 */ 2370 BOOLEAN FASTCALL 2371 co_WinPosShowWindow(PWND Wnd, INT Cmd) 2372 { 2373 BOOLEAN WasVisible; 2374 UINT Swp = 0, EventMsg = 0; 2375 RECTL NewPos = {0, 0, 0, 0}; 2376 BOOLEAN ShowFlag; 2377 LONG style; 2378 PWND Parent; 2379 PTHREADINFO pti; 2380 //HRGN VisibleRgn; 2381 BOOL ShowOwned = FALSE; 2382 BOOL FirstTime = FALSE; 2383 ASSERT_REFS_CO(Wnd); 2384 //KeRosDumpStackFrames(NULL, 20); 2385 pti = PsGetCurrentThreadWin32Thread(); 2386 WasVisible = (Wnd->style & WS_VISIBLE) != 0; 2387 style = Wnd->style; 2388 2389 TRACE("co_WinPosShowWindow START hwnd %p Cmd %d usicmd %u\n", 2390 Wnd->head.h, Cmd, pti->ppi->usi.wShowWindow); 2391 2392 if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW ) 2393 { 2394 if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD) 2395 { 2396 if ((Wnd->style & WS_CAPTION) == WS_CAPTION) 2397 { 2398 if (Wnd->spwndOwner == NULL) 2399 { 2400 if ( Cmd == SW_SHOWNORMAL || Cmd == SW_SHOW) 2401 { 2402 Cmd = SW_SHOWDEFAULT; 2403 } 2404 FirstTime = TRUE; 2405 TRACE("co_WPSW FT 1\n"); 2406 } 2407 } 2408 } 2409 } 2410 2411 if ( Cmd == SW_SHOWDEFAULT ) 2412 { 2413 if ( pti->ppi->usi.dwFlags & STARTF_USESHOWWINDOW ) 2414 { 2415 Cmd = pti->ppi->usi.wShowWindow; 2416 FirstTime = TRUE; 2417 TRACE("co_WPSW FT 2\n"); 2418 } 2419 } 2420 2421 if (FirstTime) 2422 { 2423 pti->ppi->usi.dwFlags &= ~(STARTF_USEPOSITION|STARTF_USESIZE|STARTF_USESHOWWINDOW); 2424 } 2425 2426 switch (Cmd) 2427 { 2428 case SW_HIDE: 2429 { 2430 if (!WasVisible) 2431 { 2432 //ERR("co_WinPosShowWindow Exit Bad\n"); 2433 return FALSE; 2434 } 2435 Swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE; 2436 if (Wnd != pti->MessageQueue->spwndActive) 2437 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2438 break; 2439 } 2440 2441 case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */ 2442 case SW_SHOWMINNOACTIVE: 2443 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2444 /* Fall through. */ 2445 case SW_SHOWMINIMIZED: 2446 Swp |= SWP_SHOWWINDOW; 2447 /* Fall through. */ 2448 case SW_MINIMIZE: 2449 { 2450 Swp |= SWP_NOACTIVATE; 2451 if (!(style & WS_MINIMIZE)) 2452 { 2453 IntShowOwnedPopups(Wnd, FALSE ); 2454 // Fix wine Win test_SetFocus todo #1 & #2, 2455 if (Cmd == SW_SHOWMINIMIZED) 2456 { 2457 //ERR("co_WinPosShowWindow Set focus 1\n"); 2458 if ((style & (WS_CHILD | WS_POPUP)) == WS_CHILD) 2459 co_UserSetFocus(Wnd->spwndParent); 2460 else 2461 co_UserSetFocus(0); 2462 } 2463 2464 Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos); 2465 2466 EventMsg = EVENT_SYSTEM_MINIMIZESTART; 2467 } 2468 else 2469 { 2470 if (WasVisible) 2471 { 2472 //ERR("co_WinPosShowWindow Exit Good\n"); 2473 return TRUE; 2474 } 2475 Swp |= SWP_NOSIZE | SWP_NOMOVE; 2476 } 2477 break; 2478 } 2479 2480 case SW_SHOWMAXIMIZED: 2481 { 2482 Swp |= SWP_SHOWWINDOW; 2483 if (!(style & WS_MAXIMIZE)) 2484 { 2485 ShowOwned = TRUE; 2486 2487 Swp |= co_WinPosMinMaximize(Wnd, SW_MAXIMIZE, &NewPos); 2488 2489 EventMsg = EVENT_SYSTEM_MINIMIZEEND; 2490 } 2491 else 2492 { 2493 if (WasVisible) 2494 { 2495 //ERR("co_WinPosShowWindow Exit Good 1\n"); 2496 return TRUE; 2497 } 2498 Swp |= SWP_NOSIZE | SWP_NOMOVE; 2499 } 2500 break; 2501 } 2502 2503 case SW_SHOWNA: 2504 Swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; 2505 if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOZORDER; 2506 break; 2507 case SW_SHOW: 2508 if (WasVisible) return(TRUE); // Nothing to do! 2509 Swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; 2510 /* Don't activate the topmost window. */ 2511 if (style & WS_CHILD && !(Wnd->ExStyle & WS_EX_MDICHILD)) Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2512 break; 2513 2514 case SW_SHOWNOACTIVATE: 2515 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2516 /* Fall through. */ 2517 case SW_SHOWNORMAL: 2518 case SW_SHOWDEFAULT: 2519 case SW_RESTORE: 2520 if (!WasVisible) Swp |= SWP_SHOWWINDOW; 2521 if (style & (WS_MINIMIZE | WS_MAXIMIZE)) 2522 { 2523 Swp |= co_WinPosMinMaximize(Wnd, Cmd, &NewPos); 2524 if (style & WS_MINIMIZE) EventMsg = EVENT_SYSTEM_MINIMIZEEND; 2525 } 2526 else 2527 { 2528 if (WasVisible) 2529 { 2530 //ERR("co_WinPosShowWindow Exit Good 3\n"); 2531 return TRUE; 2532 } 2533 Swp |= SWP_NOSIZE | SWP_NOMOVE; 2534 } 2535 if ( style & WS_CHILD && 2536 !(Wnd->ExStyle & WS_EX_MDICHILD) && 2537 !(Swp & SWP_STATECHANGED)) 2538 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2539 break; 2540 2541 default: 2542 //ERR("co_WinPosShowWindow Exit Good 4\n"); 2543 return WasVisible; 2544 } 2545 2546 ShowFlag = (Cmd != SW_HIDE); 2547 2548 if ((ShowFlag != WasVisible || Cmd == SW_SHOWNA) && Cmd != SW_SHOWMAXIMIZED && !(Swp & SWP_STATECHANGED)) 2549 { 2550 co_IntSendMessageNoWait(Wnd->head.h, WM_SHOWWINDOW, ShowFlag, 0); 2551 #if 0 // Fix wine msg test_SetParent:WmSetParentSeq_1:2 2552 if (!(Wnd->state2 & WNDS2_WIN31COMPAT)) // <------------- XP sets this bit! 2553 co_IntSendMessageNoWait(Wnd->head.h, WM_SETVISIBLE, ShowFlag, 0); 2554 #endif 2555 if (!VerifyWnd(Wnd)) return WasVisible; 2556 } 2557 2558 /* We can't activate a child window */ 2559 if ((Wnd->style & WS_CHILD) && 2560 !(Wnd->ExStyle & WS_EX_MDICHILD) && 2561 Cmd != SW_SHOWNA) 2562 { 2563 //ERR("SWP Child No active and ZOrder\n"); 2564 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2565 } 2566 2567 #if 0 // Explorer issues with common controls? Someone does not know how CS_SAVEBITS works. 2568 // Breaks startup and shutdown active window... 2569 if ((Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD && 2570 Wnd->pcls->style & CS_SAVEBITS && 2571 ((Cmd == SW_SHOW) || (Cmd == SW_NORMAL))) 2572 { 2573 ERR("WinPosShowWindow Set active\n"); 2574 //UserSetActiveWindow(Wnd); 2575 co_IntSetForegroundWindow(Wnd); // HACK 2576 Swp |= SWP_NOACTIVATE | SWP_NOZORDER; 2577 } 2578 #endif 2579 2580 if (IsChildVisible(Wnd) || Swp & SWP_STATECHANGED) 2581 { 2582 TRACE("Child is Vis %s or State changed %s. ShowFlag %s Swp %04x\n", 2583 (IsChildVisible(Wnd) ? "TRUE" : "FALSE"), (Swp & SWP_STATECHANGED ? "TRUE" : "FALSE"), 2584 (ShowFlag ? "TRUE" : "FALSE"),LOWORD(Swp)); 2585 co_WinPosSetWindowPos( Wnd, 2586 0 != (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOPMOST : HWND_TOP, 2587 NewPos.left, 2588 NewPos.top, 2589 NewPos.right, // NewPos.right - NewPos.left, when minimized and restore, the window becomes smaller. 2590 NewPos.bottom,// NewPos.bottom - NewPos.top, 2591 LOWORD(Swp)); 2592 } 2593 else 2594 { 2595 TRACE("Parent Vis?\n"); 2596 /* if parent is not visible simply toggle WS_VISIBLE and return */ 2597 if (ShowFlag) IntSetStyle( Wnd, WS_VISIBLE, 0 ); 2598 else IntSetStyle( Wnd, 0, WS_VISIBLE ); 2599 } 2600 2601 if ( EventMsg ) IntNotifyWinEvent(EventMsg, Wnd, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI); 2602 2603 if ( ShowOwned ) IntShowOwnedPopups(Wnd, TRUE ); 2604 2605 if ((Cmd == SW_HIDE) || (Cmd == SW_MINIMIZE)) 2606 { 2607 if ( Wnd == pti->MessageQueue->spwndActive && pti->MessageQueue == IntGetFocusMessageQueue() ) 2608 { 2609 if (UserIsDesktopWindow(Wnd->spwndParent)) 2610 { 2611 if (!ActivateOtherWindowMin(Wnd)) 2612 { 2613 co_WinPosActivateOtherWindow(Wnd); 2614 } 2615 } 2616 else 2617 { 2618 co_WinPosActivateOtherWindow(Wnd); 2619 } 2620 } 2621 2622 /* Revert focus to parent */ 2623 if (Wnd == pti->MessageQueue->spwndFocus) 2624 { 2625 Parent = Wnd->spwndParent; 2626 if (UserIsDesktopWindow(Wnd->spwndParent)) 2627 Parent = 0; 2628 co_UserSetFocus(Parent); 2629 } 2630 // Hide, just return. 2631 if (Cmd == SW_HIDE) return WasVisible; 2632 } 2633 2634 /* FIXME: Check for window destruction. */ 2635 2636 if ((Wnd->state & WNDS_SENDSIZEMOVEMSGS) && 2637 !(Wnd->state2 & WNDS2_INDESTROY)) 2638 { 2639 co_WinPosSendSizeMove(Wnd); 2640 } 2641 2642 /* if previous state was minimized Windows sets focus to the window */ 2643 if (style & WS_MINIMIZE) 2644 { 2645 co_UserSetFocus(Wnd); 2646 // Fix wine Win test_SetFocus todo #3, 2647 if (!(style & WS_CHILD)) co_IntSendMessage(UserHMGetHandle(Wnd), WM_ACTIVATE, WA_ACTIVE, 0); 2648 } 2649 //ERR("co_WinPosShowWindow EXIT\n"); 2650 return WasVisible; 2651 } 2652 2653 static PWND 2654 co_WinPosSearchChildren( 2655 IN PWND ScopeWin, 2656 IN POINT *Point, 2657 IN OUT USHORT *HitTest, 2658 IN BOOL Ignore 2659 ) 2660 { 2661 HWND *List, *phWnd; 2662 PWND pwndChild = NULL; 2663 2664 /* not visible */ 2665 if (!(ScopeWin->style & WS_VISIBLE)) 2666 { 2667 return NULL; 2668 } 2669 2670 /* not in window or in window region */ 2671 if (!IntPtInWindow(ScopeWin, Point->x, Point->y)) 2672 { 2673 return NULL; 2674 } 2675 2676 /* transparent */ 2677 if ((ScopeWin->ExStyle & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == (WS_EX_LAYERED|WS_EX_TRANSPARENT)) 2678 { 2679 return NULL; 2680 } 2681 2682 if (!Ignore && (ScopeWin->style & WS_DISABLED)) 2683 { /* disabled child */ 2684 if ((ScopeWin->style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return NULL; 2685 /* process the hit error */ 2686 *HitTest = HTERROR; 2687 return ScopeWin; 2688 } 2689 2690 /* not minimized and check if point is inside the window */ 2691 if (!(ScopeWin->style & WS_MINIMIZE) && 2692 RECTL_bPointInRect(&ScopeWin->rcClient, Point->x, Point->y) ) 2693 { 2694 UserReferenceObject(ScopeWin); 2695 2696 List = IntWinListChildren(ScopeWin); 2697 if (List) 2698 { 2699 for (phWnd = List; *phWnd; ++phWnd) 2700 { 2701 if (!(pwndChild = ValidateHwndNoErr(*phWnd))) 2702 { 2703 continue; 2704 } 2705 2706 pwndChild = co_WinPosSearchChildren(pwndChild, Point, HitTest, Ignore); 2707 2708 if (pwndChild != NULL) 2709 { 2710 /* We found a window. Don't send any more WM_NCHITTEST messages */ 2711 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2712 UserDereferenceObject(ScopeWin); 2713 return pwndChild; 2714 } 2715 } 2716 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2717 } 2718 UserDereferenceObject(ScopeWin); 2719 } 2720 2721 if (ScopeWin->head.pti == PsGetCurrentThreadWin32Thread()) 2722 { 2723 *HitTest = (USHORT)co_IntSendMessage(ScopeWin->head.h, WM_NCHITTEST, 0, MAKELONG(Point->x, Point->y)); 2724 2725 if ((*HitTest) == (USHORT)HTTRANSPARENT) 2726 { 2727 return NULL; 2728 } 2729 } 2730 else 2731 { 2732 if (*HitTest == HTNOWHERE && pwndChild == NULL) *HitTest = HTCLIENT; 2733 } 2734 2735 return ScopeWin; 2736 } 2737 2738 PWND APIENTRY 2739 co_WinPosWindowFromPoint( 2740 IN PWND ScopeWin, 2741 IN POINT *WinPoint, 2742 IN OUT USHORT* HitTest, 2743 IN BOOL Ignore) 2744 { 2745 PWND Window; 2746 POINT Point = *WinPoint; 2747 USER_REFERENCE_ENTRY Ref; 2748 2749 if( ScopeWin == NULL ) 2750 { 2751 ScopeWin = UserGetDesktopWindow(); 2752 if(ScopeWin == NULL) 2753 return NULL; 2754 } 2755 2756 *HitTest = HTNOWHERE; 2757 2758 ASSERT_REFS_CO(ScopeWin); 2759 UserRefObjectCo(ScopeWin, &Ref); 2760 2761 Window = co_WinPosSearchChildren(ScopeWin, &Point, HitTest, Ignore); 2762 2763 UserDerefObjectCo(ScopeWin); 2764 if (Window) 2765 ASSERT_REFS_CO(Window); 2766 ASSERT_REFS_CO(ScopeWin); 2767 2768 return Window; 2769 } 2770 2771 PWND FASTCALL 2772 IntRealChildWindowFromPoint(PWND Parent, LONG x, LONG y) 2773 { 2774 POINTL Pt; 2775 HWND *List, *phWnd; 2776 PWND pwndHit = NULL; 2777 2778 Pt.x = x; 2779 Pt.y = y; 2780 2781 if (!UserIsDesktopWindow(Parent)) 2782 { 2783 Pt.x += Parent->rcClient.left; 2784 Pt.y += Parent->rcClient.top; 2785 } 2786 2787 if (!IntPtInWindow(Parent, Pt.x, Pt.y)) return NULL; 2788 2789 if ((List = IntWinListChildren(Parent))) 2790 { 2791 for (phWnd = List; *phWnd; phWnd++) 2792 { 2793 PWND Child; 2794 if ((Child = ValidateHwndNoErr(*phWnd))) 2795 { 2796 if ( Child->style & WS_VISIBLE && IntPtInWindow(Child, Pt.x, Pt.y) ) 2797 { 2798 if ( Child->pcls->atomClassName != gpsi->atomSysClass[ICLS_BUTTON] || 2799 (Child->style & BS_TYPEMASK) != BS_GROUPBOX ) 2800 { 2801 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2802 return Child; 2803 } 2804 pwndHit = Child; 2805 } 2806 } 2807 } 2808 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2809 } 2810 return pwndHit ? pwndHit : Parent; 2811 } 2812 2813 PWND APIENTRY 2814 IntChildWindowFromPointEx(PWND Parent, LONG x, LONG y, UINT uiFlags) 2815 { 2816 POINTL Pt; 2817 HWND *List, *phWnd; 2818 PWND pwndHit = NULL; 2819 2820 Pt.x = x; 2821 Pt.y = y; 2822 2823 if (!UserIsDesktopWindow(Parent)) 2824 { 2825 if (Parent->ExStyle & WS_EX_LAYOUTRTL) 2826 Pt.x = Parent->rcClient.right - Pt.x; 2827 else 2828 Pt.x += Parent->rcClient.left; 2829 Pt.y += Parent->rcClient.top; 2830 } 2831 2832 if (!IntPtInWindow(Parent, Pt.x, Pt.y)) return NULL; 2833 2834 if ((List = IntWinListChildren(Parent))) 2835 { 2836 for (phWnd = List; *phWnd; phWnd++) 2837 { 2838 PWND Child; 2839 if ((Child = ValidateHwndNoErr(*phWnd))) 2840 { 2841 if (uiFlags & (CWP_SKIPINVISIBLE|CWP_SKIPDISABLED)) 2842 { 2843 if (!(Child->style & WS_VISIBLE) && (uiFlags & CWP_SKIPINVISIBLE)) continue; 2844 if ((Child->style & WS_DISABLED) && (uiFlags & CWP_SKIPDISABLED)) continue; 2845 } 2846 2847 if (uiFlags & CWP_SKIPTRANSPARENT) 2848 { 2849 if (Child->ExStyle & WS_EX_TRANSPARENT) continue; 2850 } 2851 2852 if (IntPtInWindow(Child, Pt.x, Pt.y)) 2853 { 2854 pwndHit = Child; 2855 break; 2856 } 2857 } 2858 } 2859 ExFreePoolWithTag(List, USERTAG_WINDOWLIST); 2860 } 2861 return pwndHit ? pwndHit : Parent; 2862 } 2863 2864 HDWP 2865 FASTCALL 2866 IntDeferWindowPos( HDWP hdwp, 2867 HWND hwnd, 2868 HWND hwndAfter, 2869 INT x, 2870 INT y, 2871 INT cx, 2872 INT cy, 2873 UINT flags ) 2874 { 2875 PSMWP pDWP; 2876 int i; 2877 HDWP retvalue = hdwp; 2878 2879 TRACE("hdwp %p, hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n", 2880 hdwp, hwnd, hwndAfter, x, y, cx, cy, flags); 2881 2882 if (flags & ~(SWP_NOSIZE | SWP_NOMOVE | 2883 SWP_NOZORDER | SWP_NOREDRAW | 2884 SWP_NOACTIVATE | SWP_NOCOPYBITS | 2885 SWP_NOOWNERZORDER|SWP_SHOWWINDOW | 2886 SWP_HIDEWINDOW | SWP_FRAMECHANGED)) 2887 { 2888 EngSetLastError(ERROR_INVALID_PARAMETER); 2889 return NULL; 2890 } 2891 2892 if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, TYPE_SETWINDOWPOS))) 2893 { 2894 EngSetLastError(ERROR_INVALID_DWP_HANDLE); 2895 return NULL; 2896 } 2897 2898 for (i = 0; i < pDWP->ccvr; i++) 2899 { 2900 if (pDWP->acvr[i].pos.hwnd == hwnd) 2901 { 2902 /* Merge with the other changes */ 2903 if (!(flags & SWP_NOZORDER)) 2904 { 2905 pDWP->acvr[i].pos.hwndInsertAfter = hwndAfter; 2906 } 2907 if (!(flags & SWP_NOMOVE)) 2908 { 2909 pDWP->acvr[i].pos.x = x; 2910 pDWP->acvr[i].pos.y = y; 2911 } 2912 if (!(flags & SWP_NOSIZE)) 2913 { 2914 pDWP->acvr[i].pos.cx = cx; 2915 pDWP->acvr[i].pos.cy = cy; 2916 } 2917 pDWP->acvr[i].pos.flags &= flags | ~(SWP_NOSIZE | SWP_NOMOVE | 2918 SWP_NOZORDER | SWP_NOREDRAW | 2919 SWP_NOACTIVATE | SWP_NOCOPYBITS| 2920 SWP_NOOWNERZORDER); 2921 pDWP->acvr[i].pos.flags |= flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW | 2922 SWP_FRAMECHANGED); 2923 goto END; 2924 } 2925 } 2926 if (pDWP->ccvr >= pDWP->ccvrAlloc) 2927 { 2928 PCVR newpos = ExAllocatePoolWithTag(PagedPool, pDWP->ccvrAlloc * 2 * sizeof(CVR), USERTAG_SWP); 2929 if (!newpos) 2930 { 2931 retvalue = NULL; 2932 goto END; 2933 } 2934 RtlZeroMemory(newpos, pDWP->ccvrAlloc * 2 * sizeof(CVR)); 2935 RtlCopyMemory(newpos, pDWP->acvr, pDWP->ccvrAlloc * sizeof(CVR)); 2936 ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP); 2937 pDWP->ccvrAlloc *= 2; 2938 pDWP->acvr = newpos; 2939 } 2940 pDWP->acvr[pDWP->ccvr].pos.hwnd = hwnd; 2941 pDWP->acvr[pDWP->ccvr].pos.hwndInsertAfter = hwndAfter; 2942 pDWP->acvr[pDWP->ccvr].pos.x = x; 2943 pDWP->acvr[pDWP->ccvr].pos.y = y; 2944 pDWP->acvr[pDWP->ccvr].pos.cx = cx; 2945 pDWP->acvr[pDWP->ccvr].pos.cy = cy; 2946 pDWP->acvr[pDWP->ccvr].pos.flags = flags; 2947 pDWP->acvr[pDWP->ccvr].hrgnClip = NULL; 2948 pDWP->acvr[pDWP->ccvr].hrgnInterMonitor = NULL; 2949 pDWP->ccvr++; 2950 END: 2951 return retvalue; 2952 } 2953 2954 BOOL FASTCALL IntEndDeferWindowPosEx( HDWP hdwp, BOOL sAsync ) 2955 { 2956 PSMWP pDWP; 2957 PCVR winpos; 2958 BOOL res = TRUE; 2959 int i; 2960 2961 TRACE("%p\n", hdwp); 2962 2963 if (!(pDWP = (PSMWP)UserGetObject(gHandleTable, hdwp, TYPE_SETWINDOWPOS))) 2964 { 2965 EngSetLastError(ERROR_INVALID_DWP_HANDLE); 2966 return FALSE; 2967 } 2968 2969 for (i = 0, winpos = pDWP->acvr; res && i < pDWP->ccvr; i++, winpos++) 2970 { 2971 PWND pwnd; 2972 USER_REFERENCE_ENTRY Ref; 2973 2974 TRACE("hwnd %p, after %p, %d,%d (%dx%d), flags %08x\n", 2975 winpos->pos.hwnd, winpos->pos.hwndInsertAfter, winpos->pos.x, winpos->pos.y, 2976 winpos->pos.cx, winpos->pos.cy, winpos->pos.flags); 2977 2978 pwnd = ValidateHwndNoErr(winpos->pos.hwnd); 2979 if (!pwnd) 2980 continue; 2981 2982 UserRefObjectCo(pwnd, &Ref); 2983 2984 if ( sAsync ) 2985 { 2986 LRESULT lRes; 2987 PWINDOWPOS ppos = ExAllocatePoolWithTag(PagedPool, sizeof(WINDOWPOS), USERTAG_SWP); 2988 if ( ppos ) 2989 { 2990 *ppos = winpos->pos; 2991 /* Yes it's a pointer inside Win32k! */ 2992 lRes = co_IntSendMessageNoWait( winpos->pos.hwnd, WM_ASYNC_SETWINDOWPOS, 0, (LPARAM)ppos); 2993 /* We handle this the same way as Event Hooks and Hooks. */ 2994 if ( !lRes ) 2995 { 2996 ExFreePoolWithTag(ppos, USERTAG_SWP); 2997 } 2998 } 2999 } 3000 else 3001 res = co_WinPosSetWindowPos( pwnd, 3002 winpos->pos.hwndInsertAfter, 3003 winpos->pos.x, 3004 winpos->pos.y, 3005 winpos->pos.cx, 3006 winpos->pos.cy, 3007 winpos->pos.flags); 3008 3009 // Hack to pass tests.... Must have some work to do so clear the error. 3010 if (res && (winpos->pos.flags & (SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER)) == SWP_NOZORDER ) 3011 EngSetLastError(ERROR_SUCCESS); 3012 3013 UserDerefObjectCo(pwnd); 3014 } 3015 ExFreePoolWithTag(pDWP->acvr, USERTAG_SWP); 3016 UserDereferenceObject(pDWP); 3017 UserDeleteObject(hdwp, TYPE_SETWINDOWPOS); 3018 return res; 3019 } 3020 3021 /* 3022 * @implemented 3023 */ 3024 HWND APIENTRY 3025 NtUserChildWindowFromPointEx(HWND hwndParent, 3026 LONG x, 3027 LONG y, 3028 UINT uiFlags) 3029 { 3030 PWND pwndParent; 3031 TRACE("Enter NtUserChildWindowFromPointEx\n"); 3032 UserEnterExclusive(); 3033 if ((pwndParent = UserGetWindowObject(hwndParent))) 3034 { 3035 pwndParent = IntChildWindowFromPointEx(pwndParent, x, y, uiFlags); 3036 } 3037 UserLeave(); 3038 TRACE("Leave NtUserChildWindowFromPointEx\n"); 3039 return pwndParent ? UserHMGetHandle(pwndParent) : NULL; 3040 } 3041 3042 /* 3043 * @implemented 3044 */ 3045 BOOL APIENTRY 3046 NtUserEndDeferWindowPosEx(HDWP WinPosInfo, 3047 DWORD Unknown1) 3048 { 3049 BOOL Ret; 3050 TRACE("Enter NtUserEndDeferWindowPosEx\n"); 3051 UserEnterExclusive(); 3052 Ret = IntEndDeferWindowPosEx(WinPosInfo, (BOOL)Unknown1); 3053 TRACE("Leave NtUserEndDeferWindowPosEx, ret=%i\n", Ret); 3054 UserLeave(); 3055 return Ret; 3056 } 3057 3058 /* 3059 * @implemented 3060 */ 3061 HDWP APIENTRY 3062 NtUserDeferWindowPos(HDWP WinPosInfo, 3063 HWND Wnd, 3064 HWND WndInsertAfter, 3065 int x, 3066 int y, 3067 int cx, 3068 int cy, 3069 UINT Flags) 3070 { 3071 PWND pWnd, pWndIA; 3072 HDWP Ret = NULL; 3073 UINT Tmp = ~(SWP_ASYNCWINDOWPOS|SWP_DEFERERASE|SWP_NOSENDCHANGING|SWP_NOREPOSITION| 3074 SWP_NOCOPYBITS|SWP_HIDEWINDOW|SWP_SHOWWINDOW|SWP_FRAMECHANGED| 3075 SWP_NOACTIVATE|SWP_NOREDRAW|SWP_NOZORDER|SWP_NOMOVE|SWP_NOSIZE); 3076 3077 TRACE("Enter NtUserDeferWindowPos\n"); 3078 UserEnterExclusive(); 3079 3080 if ( Flags & Tmp ) 3081 { 3082 EngSetLastError(ERROR_INVALID_FLAGS); 3083 goto Exit; 3084 } 3085 3086 pWnd = UserGetWindowObject(Wnd); 3087 if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd)) 3088 { 3089 goto Exit; 3090 } 3091 3092 if ( WndInsertAfter && 3093 WndInsertAfter != HWND_BOTTOM && 3094 WndInsertAfter != HWND_TOPMOST && 3095 WndInsertAfter != HWND_NOTOPMOST ) 3096 { 3097 pWndIA = UserGetWindowObject(WndInsertAfter); 3098 if (!pWndIA || UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA)) 3099 { 3100 goto Exit; 3101 } 3102 } 3103 3104 Ret = IntDeferWindowPos(WinPosInfo, Wnd, WndInsertAfter, x, y, cx, cy, Flags); 3105 3106 Exit: 3107 TRACE("Leave NtUserDeferWindowPos, ret=%p\n", Ret); 3108 UserLeave(); 3109 return Ret; 3110 } 3111 3112 /* 3113 * @implemented 3114 */ 3115 DWORD APIENTRY 3116 NtUserGetInternalWindowPos( HWND hWnd, 3117 LPRECT rectWnd, 3118 LPPOINT ptIcon) 3119 { 3120 PWND Window; 3121 DWORD Ret = 0; 3122 BOOL Hit = FALSE; 3123 WINDOWPLACEMENT wndpl; 3124 3125 UserEnterShared(); 3126 3127 if (!(Window = UserGetWindowObject(hWnd))) 3128 { 3129 Hit = FALSE; 3130 goto Exit; 3131 } 3132 3133 _SEH2_TRY 3134 { 3135 if(rectWnd) 3136 { 3137 ProbeForWrite(rectWnd, 3138 sizeof(RECT), 3139 1); 3140 } 3141 if(ptIcon) 3142 { 3143 ProbeForWrite(ptIcon, 3144 sizeof(POINT), 3145 1); 3146 } 3147 3148 } 3149 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3150 { 3151 SetLastNtError(_SEH2_GetExceptionCode()); 3152 Hit = TRUE; 3153 } 3154 _SEH2_END; 3155 3156 wndpl.length = sizeof(WINDOWPLACEMENT); 3157 3158 if (IntGetWindowPlacement(Window, &wndpl) && !Hit) 3159 { 3160 _SEH2_TRY 3161 { 3162 if (rectWnd) 3163 { 3164 RtlCopyMemory(rectWnd, &wndpl.rcNormalPosition , sizeof(RECT)); 3165 } 3166 if (ptIcon) 3167 { 3168 RtlCopyMemory(ptIcon, &wndpl.ptMinPosition, sizeof(POINT)); 3169 } 3170 3171 } 3172 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3173 { 3174 SetLastNtError(_SEH2_GetExceptionCode()); 3175 Hit = TRUE; 3176 } 3177 _SEH2_END; 3178 3179 if (!Hit) Ret = wndpl.showCmd; 3180 } 3181 Exit: 3182 UserLeave(); 3183 return Ret; 3184 } 3185 3186 /* 3187 * @implemented 3188 */ 3189 BOOL APIENTRY 3190 NtUserGetWindowPlacement(HWND hWnd, 3191 WINDOWPLACEMENT *lpwndpl) 3192 { 3193 PWND Wnd; 3194 WINDOWPLACEMENT Safepl; 3195 NTSTATUS Status; 3196 DECLARE_RETURN(BOOL); 3197 3198 TRACE("Enter NtUserGetWindowPlacement\n"); 3199 UserEnterShared(); 3200 3201 if (!(Wnd = UserGetWindowObject(hWnd))) 3202 { 3203 RETURN( FALSE); 3204 } 3205 3206 Status = MmCopyFromCaller(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT)); 3207 if (!NT_SUCCESS(Status)) 3208 { 3209 SetLastNtError(Status); 3210 RETURN( FALSE); 3211 } 3212 3213 Safepl.length = sizeof(WINDOWPLACEMENT); 3214 3215 IntGetWindowPlacement(Wnd, &Safepl); 3216 3217 Status = MmCopyToCaller(lpwndpl, &Safepl, sizeof(WINDOWPLACEMENT)); 3218 if (!NT_SUCCESS(Status)) 3219 { 3220 SetLastNtError(Status); 3221 RETURN( FALSE); 3222 } 3223 3224 RETURN( TRUE); 3225 3226 CLEANUP: 3227 TRACE("Leave NtUserGetWindowPlacement, ret=%i\n",_ret_); 3228 UserLeave(); 3229 END_CLEANUP; 3230 } 3231 3232 DWORD 3233 APIENTRY 3234 NtUserMinMaximize( 3235 HWND hWnd, 3236 UINT cmd, // Wine SW_ commands 3237 BOOL Hide) 3238 { 3239 PWND pWnd; 3240 3241 TRACE("Enter NtUserMinMaximize\n"); 3242 UserEnterExclusive(); 3243 3244 pWnd = UserGetWindowObject(hWnd); 3245 if (!pWnd || UserIsDesktopWindow(pWnd) || UserIsMessageWindow(pWnd)) 3246 { 3247 goto Exit; 3248 } 3249 3250 if ( cmd > SW_MAX || pWnd->state2 & WNDS2_INDESTROY) 3251 { 3252 EngSetLastError(ERROR_INVALID_PARAMETER); 3253 goto Exit; 3254 } 3255 3256 cmd |= Hide ? SW_HIDE : 0; 3257 3258 co_WinPosShowWindow(pWnd, cmd); 3259 3260 Exit: 3261 TRACE("Leave NtUserMinMaximize\n"); 3262 UserLeave(); 3263 return 0; // Always NULL? 3264 } 3265 3266 /* 3267 * @implemented 3268 */ 3269 BOOL APIENTRY 3270 NtUserMoveWindow( 3271 HWND hWnd, 3272 int X, 3273 int Y, 3274 int nWidth, 3275 int nHeight, 3276 BOOL bRepaint) 3277 { 3278 return NtUserSetWindowPos(hWnd, 0, X, Y, nWidth, nHeight, 3279 (bRepaint ? SWP_NOZORDER | SWP_NOACTIVATE : 3280 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW)); 3281 } 3282 3283 /* 3284 * @implemented 3285 */ 3286 HWND APIENTRY 3287 NtUserRealChildWindowFromPoint(HWND Parent, 3288 LONG x, 3289 LONG y) 3290 { 3291 PWND pwndParent; 3292 TRACE("Enter NtUserRealChildWindowFromPoint\n"); 3293 UserEnterShared(); 3294 if ((pwndParent = UserGetWindowObject(Parent))) 3295 { 3296 pwndParent = IntRealChildWindowFromPoint(pwndParent, x, y); 3297 } 3298 UserLeave(); 3299 TRACE("Leave NtUserRealChildWindowFromPoint\n"); 3300 return pwndParent ? UserHMGetHandle(pwndParent) : NULL; 3301 } 3302 3303 /* 3304 * @implemented 3305 */ 3306 BOOL APIENTRY 3307 NtUserSetWindowPos( 3308 HWND hWnd, 3309 HWND hWndInsertAfter, 3310 int X, 3311 int Y, 3312 int cx, 3313 int cy, 3314 UINT uFlags) 3315 { 3316 DECLARE_RETURN(BOOL); 3317 PWND Window, pWndIA; 3318 BOOL ret; 3319 USER_REFERENCE_ENTRY Ref; 3320 3321 TRACE("Enter NtUserSetWindowPos\n"); 3322 UserEnterExclusive(); 3323 3324 if (!(Window = UserGetWindowObject(hWnd)) || 3325 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 3326 { 3327 ERR("NtUserSetWindowPos bad window handle!\n"); 3328 RETURN(FALSE); 3329 } 3330 3331 if ( hWndInsertAfter && 3332 hWndInsertAfter != HWND_BOTTOM && 3333 hWndInsertAfter != HWND_TOPMOST && 3334 hWndInsertAfter != HWND_NOTOPMOST ) 3335 { 3336 if (!(pWndIA = UserGetWindowObject(hWndInsertAfter)) || 3337 UserIsDesktopWindow(pWndIA) || UserIsMessageWindow(pWndIA)) 3338 { 3339 ERR("NtUserSetWindowPos bad insert window handle!\n"); 3340 RETURN(FALSE); 3341 } 3342 } 3343 3344 /* First make sure that coordinates are valid for WM_WINDOWPOSCHANGING */ 3345 if (!(uFlags & SWP_NOMOVE)) 3346 { 3347 if (X < -32768) X = -32768; 3348 else if (X > 32767) X = 32767; 3349 if (Y < -32768) Y = -32768; 3350 else if (Y > 32767) Y = 32767; 3351 } 3352 if (!(uFlags & SWP_NOSIZE)) 3353 { 3354 if (cx < 0) cx = 0; 3355 else if (cx > 32767) cx = 32767; 3356 if (cy < 0) cy = 0; 3357 else if (cy > 32767) cy = 32767; 3358 } 3359 3360 UserRefObjectCo(Window, &Ref); 3361 ret = co_WinPosSetWindowPos(Window, hWndInsertAfter, X, Y, cx, cy, uFlags); 3362 UserDerefObjectCo(Window); 3363 3364 RETURN(ret); 3365 3366 CLEANUP: 3367 TRACE("Leave NtUserSetWindowPos, ret=%i\n",_ret_); 3368 UserLeave(); 3369 END_CLEANUP; 3370 } 3371 3372 /* 3373 * @implemented 3374 */ 3375 INT APIENTRY 3376 NtUserSetWindowRgn( 3377 HWND hWnd, 3378 HRGN hRgn, 3379 BOOL bRedraw) 3380 { 3381 HRGN hrgnCopy = NULL; 3382 PWND Window; 3383 INT flags = (SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE|SWP_NOACTIVATE|SWP_FRAMECHANGED|SWP_NOSIZE|SWP_NOMOVE); 3384 BOOLEAN Ret = FALSE; 3385 DECLARE_RETURN(INT); 3386 3387 TRACE("Enter NtUserSetWindowRgn\n"); 3388 UserEnterExclusive(); 3389 3390 if (!(Window = UserGetWindowObject(hWnd)) || 3391 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 3392 { 3393 RETURN( 0); 3394 } 3395 3396 if (hRgn) // The region will be deleted in user32. 3397 { 3398 if (GreIsHandleValid(hRgn)) 3399 { 3400 hrgnCopy = NtGdiCreateRectRgn(0, 0, 0, 0); 3401 /* The coordinates of a window's window region are relative to the 3402 upper-left corner of the window, not the client area of the window. */ 3403 NtGdiCombineRgn( hrgnCopy, hRgn, 0, RGN_COPY); 3404 } 3405 else 3406 RETURN( 0); 3407 } 3408 3409 //// HACK 1 : Work around the lack of supporting DeferWindowPos. 3410 if (hrgnCopy) 3411 { 3412 Window->hrgnNewFrame = hrgnCopy; // Should be PSMWP->acvr->hrgnClip 3413 } 3414 else 3415 { 3416 Window->hrgnNewFrame = HRGN_WINDOW; 3417 } 3418 //// HACK 2 3419 Ret = co_WinPosSetWindowPos(Window, HWND_TOP, 0, 0, 0, 0, bRedraw ? flags : (flags|SWP_NOREDRAW) ); 3420 3421 RETURN( (INT)Ret); 3422 3423 CLEANUP: 3424 TRACE("Leave NtUserSetWindowRgn, ret=%i\n",_ret_); 3425 UserLeave(); 3426 END_CLEANUP; 3427 } 3428 3429 /* 3430 * @implemented 3431 */ 3432 DWORD APIENTRY 3433 NtUserSetInternalWindowPos( 3434 HWND hwnd, 3435 UINT showCmd, 3436 LPRECT lprect, 3437 LPPOINT lppt) 3438 { 3439 WINDOWPLACEMENT wndpl; 3440 UINT flags; 3441 PWND Wnd; 3442 RECT rect; 3443 POINT pt = {0}; 3444 DECLARE_RETURN(BOOL); 3445 USER_REFERENCE_ENTRY Ref; 3446 3447 TRACE("Enter NtUserSetWindowPlacement\n"); 3448 UserEnterExclusive(); 3449 3450 if (!(Wnd = UserGetWindowObject(hwnd)) || // FIXME: 3451 UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd)) 3452 { 3453 RETURN( FALSE); 3454 } 3455 3456 _SEH2_TRY 3457 { 3458 if (lppt) 3459 { 3460 ProbeForRead(lppt, sizeof(POINT), 1); 3461 RtlCopyMemory(&pt, lppt, sizeof(POINT)); 3462 } 3463 if (lprect) 3464 { 3465 ProbeForRead(lprect, sizeof(RECT), 1); 3466 RtlCopyMemory(&rect, lprect, sizeof(RECT)); 3467 } 3468 } 3469 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3470 { 3471 SetLastNtError(_SEH2_GetExceptionCode()); 3472 _SEH2_YIELD(RETURN( FALSE)); 3473 } 3474 _SEH2_END 3475 3476 wndpl.length = sizeof(wndpl); 3477 wndpl.showCmd = showCmd; 3478 wndpl.flags = flags = 0; 3479 3480 if ( lppt ) 3481 { 3482 flags |= PLACE_MIN; 3483 wndpl.flags |= WPF_SETMINPOSITION; 3484 wndpl.ptMinPosition = pt; 3485 } 3486 if ( lprect ) 3487 { 3488 flags |= PLACE_RECT; 3489 wndpl.rcNormalPosition = rect; 3490 } 3491 3492 UserRefObjectCo(Wnd, &Ref); 3493 IntSetWindowPlacement(Wnd, &wndpl, flags); 3494 UserDerefObjectCo(Wnd); 3495 RETURN(TRUE); 3496 3497 CLEANUP: 3498 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_); 3499 UserLeave(); 3500 END_CLEANUP; 3501 } 3502 3503 /* 3504 * @implemented 3505 */ 3506 BOOL APIENTRY 3507 NtUserSetWindowPlacement(HWND hWnd, 3508 WINDOWPLACEMENT *lpwndpl) 3509 { 3510 PWND Wnd; 3511 WINDOWPLACEMENT Safepl; 3512 UINT Flags; 3513 DECLARE_RETURN(BOOL); 3514 USER_REFERENCE_ENTRY Ref; 3515 3516 TRACE("Enter NtUserSetWindowPlacement\n"); 3517 UserEnterExclusive(); 3518 3519 if (!(Wnd = UserGetWindowObject(hWnd)) || 3520 UserIsDesktopWindow(Wnd) || UserIsMessageWindow(Wnd)) 3521 { 3522 RETURN( FALSE); 3523 } 3524 3525 _SEH2_TRY 3526 { 3527 ProbeForRead(lpwndpl, sizeof(WINDOWPLACEMENT), 1); 3528 RtlCopyMemory(&Safepl, lpwndpl, sizeof(WINDOWPLACEMENT)); 3529 } 3530 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 3531 { 3532 SetLastNtError(_SEH2_GetExceptionCode()); 3533 _SEH2_YIELD(RETURN( FALSE)); 3534 } 3535 _SEH2_END 3536 3537 if(Safepl.length != sizeof(WINDOWPLACEMENT)) 3538 { 3539 RETURN( FALSE); 3540 } 3541 3542 Flags = PLACE_MAX | PLACE_RECT; 3543 if (Safepl.flags & WPF_SETMINPOSITION) Flags |= PLACE_MIN; 3544 UserRefObjectCo(Wnd, &Ref); 3545 IntSetWindowPlacement(Wnd, &Safepl, Flags); 3546 UserDerefObjectCo(Wnd); 3547 RETURN(TRUE); 3548 3549 CLEANUP: 3550 TRACE("Leave NtUserSetWindowPlacement, ret=%i\n",_ret_); 3551 UserLeave(); 3552 END_CLEANUP; 3553 } 3554 3555 /* 3556 * @implemented 3557 */ 3558 BOOL APIENTRY 3559 NtUserShowWindowAsync(HWND hWnd, LONG nCmdShow) 3560 { 3561 PWND Window; 3562 BOOL ret; 3563 DECLARE_RETURN(BOOL); 3564 USER_REFERENCE_ENTRY Ref; 3565 3566 TRACE("Enter NtUserShowWindowAsync\n"); 3567 UserEnterExclusive(); 3568 3569 if (!(Window = UserGetWindowObject(hWnd)) || 3570 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 3571 { 3572 RETURN(FALSE); 3573 } 3574 3575 if ( nCmdShow > SW_MAX ) 3576 { 3577 EngSetLastError(ERROR_INVALID_PARAMETER); 3578 RETURN(FALSE); 3579 } 3580 3581 UserRefObjectCo(Window, &Ref); 3582 ret = co_IntSendMessageNoWait( hWnd, WM_ASYNC_SHOWWINDOW, nCmdShow, 0 ); 3583 UserDerefObjectCo(Window); 3584 if (-1 == (int) ret || !ret) ret = FALSE; 3585 3586 RETURN(ret); 3587 3588 CLEANUP: 3589 TRACE("Leave NtUserShowWindowAsync, ret=%i\n",_ret_); 3590 UserLeave(); 3591 END_CLEANUP; 3592 } 3593 3594 /* 3595 * @implemented 3596 */ 3597 BOOL APIENTRY 3598 NtUserShowWindow(HWND hWnd, LONG nCmdShow) 3599 { 3600 PWND Window; 3601 BOOL ret; 3602 DECLARE_RETURN(BOOL); 3603 USER_REFERENCE_ENTRY Ref; 3604 3605 TRACE("Enter NtUserShowWindow hWnd %p SW_ %d\n",hWnd, nCmdShow); 3606 UserEnterExclusive(); 3607 3608 if (!(Window = UserGetWindowObject(hWnd)) || 3609 UserIsDesktopWindow(Window) || UserIsMessageWindow(Window)) 3610 { 3611 RETURN(FALSE); 3612 } 3613 3614 if ( nCmdShow > SW_MAX || Window->state2 & WNDS2_INDESTROY) 3615 { 3616 EngSetLastError(ERROR_INVALID_PARAMETER); 3617 RETURN(FALSE); 3618 } 3619 3620 UserRefObjectCo(Window, &Ref); 3621 ret = co_WinPosShowWindow(Window, nCmdShow); 3622 UserDerefObjectCo(Window); 3623 3624 RETURN(ret); 3625 3626 CLEANUP: 3627 TRACE("Leave NtUserShowWindow, ret=%i\n",_ret_); 3628 UserLeave(); 3629 END_CLEANUP; 3630 } 3631 3632 3633 /* 3634 * @implemented 3635 */ 3636 HWND APIENTRY 3637 NtUserWindowFromPoint(LONG X, LONG Y) 3638 { 3639 POINT pt; 3640 HWND Ret; 3641 PWND DesktopWindow = NULL, Window = NULL; 3642 USHORT hittest; 3643 DECLARE_RETURN(HWND); 3644 USER_REFERENCE_ENTRY Ref; 3645 3646 TRACE("Enter NtUserWindowFromPoint\n"); 3647 UserEnterExclusive(); 3648 3649 if ((DesktopWindow = UserGetWindowObject(IntGetDesktopWindow()))) 3650 { 3651 //PTHREADINFO pti; 3652 3653 pt.x = X; 3654 pt.y = Y; 3655 3656 // Hmm... Threads live on desktops thus we have a reference on the desktop and indirectly the desktop window. 3657 // It is possible this referencing is useless, though it should not hurt... 3658 UserRefObjectCo(DesktopWindow, &Ref); 3659 3660 //pti = PsGetCurrentThreadWin32Thread(); 3661 Window = co_WinPosWindowFromPoint(DesktopWindow, &pt, &hittest, FALSE); 3662 3663 if (Window) 3664 { 3665 Ret = UserHMGetHandle(Window); 3666 3667 RETURN( Ret); 3668 } 3669 } 3670 3671 RETURN( NULL); 3672 3673 CLEANUP: 3674 if (DesktopWindow) UserDerefObjectCo(DesktopWindow); 3675 3676 TRACE("Leave NtUserWindowFromPoint, ret=%p\n", _ret_); 3677 UserLeave(); 3678 END_CLEANUP; 3679 } 3680 3681 /* EOF */ 3682