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