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