1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "fpdfsdk/pwl/cpwl_wnd.h" 8 9 #include <map> 10 #include <sstream> 11 #include <vector> 12 13 #include "core/fxge/cfx_renderdevice.h" 14 #include "fpdfsdk/pwl/cpwl_scroll_bar.h" 15 #include "third_party/base/ptr_util.h" 16 #include "third_party/base/stl_util.h" 17 18 namespace { 19 20 constexpr float kDefaultFontSize = 9.0f; 21 22 } // namespace 23 24 CPWL_Wnd::CreateParams::CreateParams() 25 : rcRectWnd(0, 0, 0, 0), 26 pSystemHandler(nullptr), 27 pFontMap(nullptr), 28 pProvider(nullptr), 29 pFocusHandler(nullptr), 30 dwFlags(0), 31 sBackgroundColor(), 32 pAttachedWidget(nullptr), 33 nBorderStyle(BorderStyle::SOLID), 34 dwBorderWidth(1), 35 sBorderColor(), 36 sTextColor(), 37 nTransparency(255), 38 fFontSize(kDefaultFontSize), 39 sDash(3, 0, 0), 40 pAttachedData(nullptr), 41 pParentWnd(nullptr), 42 pMsgControl(nullptr), 43 eCursorType(FXCT_ARROW) {} 44 45 CPWL_Wnd::CreateParams::CreateParams(const CreateParams& other) = default; 46 47 CPWL_Wnd::CreateParams::~CreateParams() = default; 48 49 class CPWL_MsgControl : public Observable<CPWL_MsgControl> { 50 public: 51 explicit CPWL_MsgControl(CPWL_Wnd* pWnd) : m_pCreatedWnd(pWnd) {} 52 ~CPWL_MsgControl() {} 53 54 bool IsWndCreated(const CPWL_Wnd* pWnd) const { 55 return m_pCreatedWnd == pWnd; 56 } 57 58 bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const { 59 return pWnd && pdfium::ContainsValue(m_aMousePath, pWnd); 60 } 61 62 bool IsMainCaptureKeyboard(const CPWL_Wnd* pWnd) const { 63 return pWnd == m_pMainKeyboardWnd; 64 } 65 66 bool IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const { 67 return pWnd && pdfium::ContainsValue(m_aKeyboardPath, pWnd); 68 } 69 70 void SetFocus(CPWL_Wnd* pWnd) { 71 m_aKeyboardPath.clear(); 72 if (!pWnd) 73 return; 74 75 m_pMainKeyboardWnd = pWnd; 76 CPWL_Wnd* pParent = pWnd; 77 while (pParent) { 78 m_aKeyboardPath.push_back(pParent); 79 pParent = pParent->GetParentWindow(); 80 } 81 // Note, pWnd may get destroyed in the OnSetFocus call. 82 pWnd->OnSetFocus(); 83 } 84 85 void KillFocus() { 86 ObservedPtr observed_ptr(this); 87 if (!m_aKeyboardPath.empty()) 88 if (CPWL_Wnd* pWnd = m_aKeyboardPath[0]) 89 pWnd->OnKillFocus(); 90 if (!observed_ptr) 91 return; 92 93 m_pMainKeyboardWnd = nullptr; 94 m_aKeyboardPath.clear(); 95 } 96 97 void SetCapture(CPWL_Wnd* pWnd) { 98 m_aMousePath.clear(); 99 if (pWnd) { 100 CPWL_Wnd* pParent = pWnd; 101 while (pParent) { 102 m_aMousePath.push_back(pParent); 103 pParent = pParent->GetParentWindow(); 104 } 105 } 106 } 107 108 void ReleaseCapture() { 109 m_aMousePath.clear(); 110 } 111 112 CPWL_Wnd* GetFocusedWindow() const { return m_pMainKeyboardWnd.Get(); } 113 114 private: 115 std::vector<CPWL_Wnd*> m_aMousePath; 116 std::vector<CPWL_Wnd*> m_aKeyboardPath; 117 UnownedPtr<CPWL_Wnd> m_pCreatedWnd; 118 UnownedPtr<CPWL_Wnd> m_pMainKeyboardWnd; 119 }; 120 121 CPWL_Wnd::CPWL_Wnd() 122 : m_rcWindow(), 123 m_rcClip(), 124 m_bCreated(false), 125 m_bVisible(false), 126 m_bNotifying(false), 127 m_bEnabled(true) {} 128 129 CPWL_Wnd::~CPWL_Wnd() { 130 ASSERT(!m_bCreated); 131 } 132 133 ByteString CPWL_Wnd::GetClassName() const { 134 return "CPWL_Wnd"; 135 } 136 137 void CPWL_Wnd::Create(const CreateParams& cp) { 138 if (IsValid()) 139 return; 140 141 m_CreationParams = cp; 142 OnCreate(&m_CreationParams); 143 m_CreationParams.rcRectWnd.Normalize(); 144 m_rcWindow = m_CreationParams.rcRectWnd; 145 m_rcClip = m_rcWindow; 146 if (!m_rcClip.IsEmpty()) { 147 m_rcClip.Inflate(1.0f, 1.0f); 148 m_rcClip.Normalize(); 149 } 150 CreateMsgControl(); 151 if (m_CreationParams.pParentWnd) 152 m_CreationParams.pParentWnd->AddChild(this); 153 154 CreateParams ccp = m_CreationParams; 155 ccp.dwFlags &= 0xFFFF0000L; // remove sub styles 156 CreateScrollBar(ccp); 157 CreateChildWnd(ccp); 158 m_bVisible = HasFlag(PWS_VISIBLE); 159 OnCreated(); 160 if (!RePosChildWnd()) 161 return; 162 163 m_bCreated = true; 164 } 165 166 void CPWL_Wnd::OnCreate(CreateParams* pParamsToAdjust) {} 167 168 void CPWL_Wnd::OnCreated() {} 169 170 void CPWL_Wnd::OnDestroy() {} 171 172 void CPWL_Wnd::InvalidateFocusHandler(FocusHandlerIface* handler) { 173 if (m_CreationParams.pFocusHandler == handler) 174 m_CreationParams.pFocusHandler = nullptr; 175 } 176 177 void CPWL_Wnd::InvalidateProvider(ProviderIface* provider) { 178 if (m_CreationParams.pProvider.Get() == provider) 179 m_CreationParams.pProvider.Reset(); 180 } 181 182 void CPWL_Wnd::Destroy() { 183 KillFocus(); 184 OnDestroy(); 185 if (m_bCreated) { 186 m_pVScrollBar = nullptr; 187 for (auto it = m_Children.rbegin(); it != m_Children.rend(); ++it) { 188 CPWL_Wnd* pChild = *it; 189 if (pChild) { 190 *it = nullptr; 191 pChild->Destroy(); 192 delete pChild; 193 } 194 } 195 if (m_CreationParams.pParentWnd) 196 m_CreationParams.pParentWnd->RemoveChild(this); 197 198 m_bCreated = false; 199 } 200 DestroyMsgControl(); 201 m_Children.clear(); 202 } 203 204 bool CPWL_Wnd::Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh) { 205 if (!IsValid()) 206 return true; 207 208 CFX_FloatRect rcOld = GetWindowRect(); 209 m_rcWindow = rcNew; 210 m_rcWindow.Normalize(); 211 212 if (bReset) { 213 if (rcOld.left != rcNew.left || rcOld.right != rcNew.right || 214 rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom) { 215 if (!RePosChildWnd()) 216 return false; 217 } 218 } 219 if (bRefresh && !InvalidateRectMove(rcOld, rcNew)) 220 return false; 221 222 m_CreationParams.rcRectWnd = m_rcWindow; 223 return true; 224 } 225 226 bool CPWL_Wnd::InvalidateRectMove(const CFX_FloatRect& rcOld, 227 const CFX_FloatRect& rcNew) { 228 CFX_FloatRect rcUnion = rcOld; 229 rcUnion.Union(rcNew); 230 231 return InvalidateRect(&rcUnion); 232 } 233 234 void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice, 235 const CFX_Matrix& mtUser2Device) { 236 if (IsValid() && IsVisible()) { 237 DrawThisAppearance(pDevice, mtUser2Device); 238 DrawChildAppearance(pDevice, mtUser2Device); 239 } 240 } 241 242 void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice, 243 const CFX_Matrix& mtUser2Device) { 244 CFX_FloatRect rectWnd = GetWindowRect(); 245 if (rectWnd.IsEmpty()) 246 return; 247 248 if (HasFlag(PWS_BACKGROUND)) { 249 float width = static_cast<float>(GetBorderWidth() + GetInnerBorderWidth()); 250 pDevice->DrawFillRect(&mtUser2Device, rectWnd.GetDeflated(width, width), 251 GetBackgroundColor(), GetTransparency()); 252 } 253 254 if (HasFlag(PWS_BORDER)) { 255 pDevice->DrawBorder(&mtUser2Device, rectWnd, 256 static_cast<float>(GetBorderWidth()), GetBorderColor(), 257 GetBorderLeftTopColor(GetBorderStyle()), 258 GetBorderRightBottomColor(GetBorderStyle()), 259 GetBorderStyle(), GetTransparency()); 260 } 261 } 262 263 void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice, 264 const CFX_Matrix& mtUser2Device) { 265 for (CPWL_Wnd* pChild : m_Children) { 266 if (!pChild) 267 continue; 268 269 CFX_Matrix mt = pChild->GetChildMatrix(); 270 if (mt.IsIdentity()) { 271 pChild->DrawAppearance(pDevice, mtUser2Device); 272 } else { 273 mt.Concat(mtUser2Device); 274 pChild->DrawAppearance(pDevice, mt); 275 } 276 } 277 } 278 279 bool CPWL_Wnd::InvalidateRect(CFX_FloatRect* pRect) { 280 ObservedPtr thisObserved(this); 281 if (!IsValid()) 282 return true; 283 284 CFX_FloatRect rcRefresh = pRect ? *pRect : GetWindowRect(); 285 286 if (!HasFlag(PWS_NOREFRESHCLIP)) { 287 CFX_FloatRect rcClip = GetClipRect(); 288 if (!rcClip.IsEmpty()) { 289 rcRefresh.Intersect(rcClip); 290 } 291 } 292 293 CFX_FloatRect rcWin = PWLtoWnd(rcRefresh); 294 rcWin.Inflate(1, 1); 295 rcWin.Normalize(); 296 297 if (CFX_SystemHandler* pSH = GetSystemHandler()) { 298 if (CPDFSDK_Widget* widget = static_cast<CPDFSDK_Widget*>( 299 m_CreationParams.pAttachedWidget.Get())) { 300 pSH->InvalidateRect(widget, rcWin); 301 if (!thisObserved) 302 return false; 303 } 304 } 305 306 return true; 307 } 308 309 #define PWL_IMPLEMENT_KEY_METHOD(key_method_name) \ 310 bool CPWL_Wnd::key_method_name(uint16_t nChar, uint32_t nFlag) { \ 311 if (!IsValid() || !IsVisible() || !IsEnabled()) \ 312 return false; \ 313 if (!IsWndCaptureKeyboard(this)) \ 314 return false; \ 315 for (auto* pChild : m_Children) { \ 316 if (pChild && IsWndCaptureKeyboard(pChild)) \ 317 return pChild->key_method_name(nChar, nFlag); \ 318 } \ 319 return false; \ 320 } 321 322 PWL_IMPLEMENT_KEY_METHOD(OnKeyDown) 323 PWL_IMPLEMENT_KEY_METHOD(OnChar) 324 #undef PWL_IMPLEMENT_KEY_METHOD 325 326 #define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name) \ 327 bool CPWL_Wnd::mouse_method_name(const CFX_PointF& point, uint32_t nFlag) { \ 328 if (!IsValid() || !IsVisible() || !IsEnabled()) \ 329 return false; \ 330 if (IsWndCaptureMouse(this)) { \ 331 for (auto* pChild : m_Children) { \ 332 if (pChild && IsWndCaptureMouse(pChild)) { \ 333 return pChild->mouse_method_name(pChild->ParentToChild(point), \ 334 nFlag); \ 335 } \ 336 } \ 337 SetCursor(); \ 338 return false; \ 339 } \ 340 for (auto* pChild : m_Children) { \ 341 if (pChild && pChild->WndHitTest(pChild->ParentToChild(point))) { \ 342 return pChild->mouse_method_name(pChild->ParentToChild(point), nFlag); \ 343 } \ 344 } \ 345 if (WndHitTest(point)) \ 346 SetCursor(); \ 347 return false; \ 348 } 349 350 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk) 351 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown) 352 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp) 353 PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDown) 354 PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonUp) 355 PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove) 356 #undef PWL_IMPLEMENT_MOUSE_METHOD 357 358 WideString CPWL_Wnd::GetSelectedText() { 359 return WideString(); 360 } 361 362 void CPWL_Wnd::ReplaceSelection(const WideString& text) {} 363 364 bool CPWL_Wnd::OnMouseWheel(short zDelta, 365 const CFX_PointF& point, 366 uint32_t nFlag) { 367 if (!IsValid() || !IsVisible() || !IsEnabled()) 368 return false; 369 370 SetCursor(); 371 if (!IsWndCaptureKeyboard(this)) 372 return false; 373 374 for (auto* pChild : m_Children) { 375 if (pChild && IsWndCaptureKeyboard(pChild)) 376 return pChild->OnMouseWheel(zDelta, pChild->ParentToChild(point), nFlag); 377 } 378 return false; 379 } 380 381 void CPWL_Wnd::AddChild(CPWL_Wnd* pWnd) { 382 m_Children.push_back(pWnd); 383 } 384 385 void CPWL_Wnd::RemoveChild(CPWL_Wnd* pWnd) { 386 for (auto it = m_Children.rbegin(); it != m_Children.rend(); ++it) { 387 if (*it && *it == pWnd) { 388 m_Children.erase(std::next(it).base()); 389 break; 390 } 391 } 392 } 393 394 void CPWL_Wnd::SetScrollInfo(const PWL_SCROLL_INFO& info) {} 395 396 void CPWL_Wnd::SetScrollPosition(float pos) {} 397 398 void CPWL_Wnd::ScrollWindowVertically(float pos) {} 399 400 void CPWL_Wnd::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {} 401 402 void CPWL_Wnd::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {} 403 404 void CPWL_Wnd::NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) {} 405 406 CPWL_Wnd* CPWL_Wnd::GetParentWindow() const { 407 return m_CreationParams.pParentWnd; 408 } 409 410 CFX_FloatRect CPWL_Wnd::GetWindowRect() const { 411 return m_rcWindow; 412 } 413 414 CFX_FloatRect CPWL_Wnd::GetClientRect() const { 415 CFX_FloatRect rcWindow = GetWindowRect(); 416 417 float width = static_cast<float>(GetBorderWidth() + GetInnerBorderWidth()); 418 CFX_FloatRect rcClient = rcWindow.GetDeflated(width, width); 419 if (CPWL_ScrollBar* pVSB = GetVScrollBar()) 420 rcClient.right -= pVSB->GetScrollBarWidth(); 421 422 rcClient.Normalize(); 423 return rcWindow.Contains(rcClient) ? rcClient : CFX_FloatRect(); 424 } 425 426 CFX_PointF CPWL_Wnd::GetCenterPoint() const { 427 CFX_FloatRect rcClient = GetClientRect(); 428 return CFX_PointF((rcClient.left + rcClient.right) * 0.5f, 429 (rcClient.top + rcClient.bottom) * 0.5f); 430 } 431 432 bool CPWL_Wnd::HasFlag(uint32_t dwFlags) const { 433 return (m_CreationParams.dwFlags & dwFlags) != 0; 434 } 435 436 void CPWL_Wnd::RemoveFlag(uint32_t dwFlags) { 437 m_CreationParams.dwFlags &= ~dwFlags; 438 } 439 440 void CPWL_Wnd::AddFlag(uint32_t dwFlags) { 441 m_CreationParams.dwFlags |= dwFlags; 442 } 443 444 CFX_Color CPWL_Wnd::GetBackgroundColor() const { 445 return m_CreationParams.sBackgroundColor; 446 } 447 448 void CPWL_Wnd::SetBackgroundColor(const CFX_Color& color) { 449 m_CreationParams.sBackgroundColor = color; 450 } 451 452 CFX_Color CPWL_Wnd::GetTextColor() const { 453 return m_CreationParams.sTextColor; 454 } 455 456 BorderStyle CPWL_Wnd::GetBorderStyle() const { 457 return m_CreationParams.nBorderStyle; 458 } 459 460 void CPWL_Wnd::SetBorderStyle(BorderStyle nBorderStyle) { 461 if (HasFlag(PWS_BORDER)) 462 m_CreationParams.nBorderStyle = nBorderStyle; 463 } 464 465 int32_t CPWL_Wnd::GetBorderWidth() const { 466 return HasFlag(PWS_BORDER) ? m_CreationParams.dwBorderWidth : 0; 467 } 468 469 int32_t CPWL_Wnd::GetInnerBorderWidth() const { 470 return 0; 471 } 472 473 CFX_Color CPWL_Wnd::GetBorderColor() const { 474 return HasFlag(PWS_BORDER) ? m_CreationParams.sBorderColor : CFX_Color(); 475 } 476 477 const CPWL_Dash& CPWL_Wnd::GetBorderDash() const { 478 return m_CreationParams.sDash; 479 } 480 481 CPWL_Wnd::PrivateData* CPWL_Wnd::GetAttachedData() const { 482 return m_CreationParams.pAttachedData.Get(); 483 } 484 485 CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const { 486 return HasFlag(PWS_VSCROLL) ? m_pVScrollBar.Get() : nullptr; 487 } 488 489 void CPWL_Wnd::CreateScrollBar(const CreateParams& cp) { 490 CreateVScrollBar(cp); 491 } 492 493 void CPWL_Wnd::CreateVScrollBar(const CreateParams& cp) { 494 if (m_pVScrollBar || !HasFlag(PWS_VSCROLL)) 495 return; 496 497 CreateParams scp = cp; 498 499 // flags 500 scp.dwFlags = 501 PWS_CHILD | PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP; 502 503 scp.pParentWnd = this; 504 scp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR; 505 scp.eCursorType = FXCT_ARROW; 506 scp.nTransparency = PWL_SCROLLBAR_TRANSPARENCY; 507 508 m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL); 509 m_pVScrollBar->Create(scp); 510 } 511 512 void CPWL_Wnd::SetCapture() { 513 if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) 514 pMsgCtrl->SetCapture(this); 515 } 516 517 void CPWL_Wnd::ReleaseCapture() { 518 for (auto* pChild : m_Children) { 519 if (pChild) 520 pChild->ReleaseCapture(); 521 } 522 if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) 523 pMsgCtrl->ReleaseCapture(); 524 } 525 526 void CPWL_Wnd::SetFocus() { 527 if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) { 528 if (!pMsgCtrl->IsMainCaptureKeyboard(this)) 529 pMsgCtrl->KillFocus(); 530 pMsgCtrl->SetFocus(this); 531 } 532 } 533 534 void CPWL_Wnd::KillFocus() { 535 if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) { 536 if (pMsgCtrl->IsWndCaptureKeyboard(this)) 537 pMsgCtrl->KillFocus(); 538 } 539 } 540 541 void CPWL_Wnd::OnSetFocus() {} 542 543 void CPWL_Wnd::OnKillFocus() {} 544 545 bool CPWL_Wnd::WndHitTest(const CFX_PointF& point) const { 546 return IsValid() && IsVisible() && GetWindowRect().Contains(point); 547 } 548 549 bool CPWL_Wnd::ClientHitTest(const CFX_PointF& point) const { 550 return IsValid() && IsVisible() && GetClientRect().Contains(point); 551 } 552 553 const CPWL_Wnd* CPWL_Wnd::GetRootWnd() const { 554 auto* pParent = m_CreationParams.pParentWnd; 555 return pParent ? pParent->GetRootWnd() : this; 556 } 557 558 bool CPWL_Wnd::SetVisible(bool bVisible) { 559 if (!IsValid()) 560 return true; 561 562 ObservedPtr thisObserved(this); 563 564 for (auto* pChild : m_Children) { 565 if (pChild) { 566 pChild->SetVisible(bVisible); 567 if (!thisObserved) 568 return false; 569 } 570 } 571 572 if (bVisible != m_bVisible) { 573 m_bVisible = bVisible; 574 if (!RePosChildWnd()) 575 return false; 576 577 if (!InvalidateRect(nullptr)) 578 return false; 579 } 580 return true; 581 } 582 583 void CPWL_Wnd::SetClipRect(const CFX_FloatRect& rect) { 584 m_rcClip = rect; 585 m_rcClip.Normalize(); 586 } 587 588 const CFX_FloatRect& CPWL_Wnd::GetClipRect() const { 589 return m_rcClip; 590 } 591 592 bool CPWL_Wnd::IsReadOnly() const { 593 return HasFlag(PWS_READONLY); 594 } 595 596 bool CPWL_Wnd::RePosChildWnd() { 597 CPWL_ScrollBar* pVSB = GetVScrollBar(); 598 if (!pVSB) 599 return true; 600 601 CFX_FloatRect rcContent = GetWindowRect(); 602 if (!rcContent.IsEmpty()) { 603 float width = static_cast<float>(GetBorderWidth() + GetInnerBorderWidth()); 604 rcContent.Deflate(width, width); 605 rcContent.Normalize(); 606 } 607 CFX_FloatRect rcVScroll = 608 CFX_FloatRect(rcContent.right - PWL_SCROLLBAR_WIDTH, rcContent.bottom, 609 rcContent.right - 1.0f, rcContent.top); 610 611 ObservedPtr thisObserved(this); 612 613 pVSB->Move(rcVScroll, true, false); 614 if (!thisObserved) 615 return false; 616 617 return true; 618 } 619 620 void CPWL_Wnd::CreateChildWnd(const CreateParams& cp) {} 621 622 void CPWL_Wnd::SetCursor() { 623 if (IsValid()) { 624 if (CFX_SystemHandler* pSH = GetSystemHandler()) { 625 int32_t nCursorType = GetCreationParams().eCursorType; 626 pSH->SetCursor(nCursorType); 627 } 628 } 629 } 630 631 void CPWL_Wnd::CreateMsgControl() { 632 if (!m_CreationParams.pMsgControl) 633 m_CreationParams.pMsgControl = new CPWL_MsgControl(this); 634 } 635 636 void CPWL_Wnd::DestroyMsgControl() { 637 CPWL_MsgControl* pMsgControl = GetMsgControl(); 638 if (pMsgControl && pMsgControl->IsWndCreated(this)) 639 delete pMsgControl; 640 } 641 642 CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const { 643 return m_CreationParams.pMsgControl; 644 } 645 646 bool CPWL_Wnd::IsCaptureMouse() const { 647 return IsWndCaptureMouse(this); 648 } 649 650 bool CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd* pWnd) const { 651 CPWL_MsgControl* pCtrl = GetMsgControl(); 652 return pCtrl ? pCtrl->IsWndCaptureMouse(pWnd) : false; 653 } 654 655 bool CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const { 656 CPWL_MsgControl* pCtrl = GetMsgControl(); 657 return pCtrl ? pCtrl->IsWndCaptureKeyboard(pWnd) : false; 658 } 659 660 bool CPWL_Wnd::IsFocused() const { 661 CPWL_MsgControl* pCtrl = GetMsgControl(); 662 return pCtrl ? pCtrl->IsMainCaptureKeyboard(this) : false; 663 } 664 665 CFX_FloatRect CPWL_Wnd::GetFocusRect() const { 666 CFX_FloatRect rect = GetWindowRect(); 667 if (!rect.IsEmpty()) { 668 rect.Inflate(1.0f, 1.0f); 669 rect.Normalize(); 670 } 671 return rect; 672 } 673 674 float CPWL_Wnd::GetFontSize() const { 675 return m_CreationParams.fFontSize; 676 } 677 678 void CPWL_Wnd::SetFontSize(float fFontSize) { 679 m_CreationParams.fFontSize = fFontSize; 680 } 681 682 CFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const { 683 return m_CreationParams.pSystemHandler; 684 } 685 686 CPWL_Wnd::FocusHandlerIface* CPWL_Wnd::GetFocusHandler() const { 687 return m_CreationParams.pFocusHandler.Get(); 688 } 689 690 CPWL_Wnd::ProviderIface* CPWL_Wnd::GetProvider() const { 691 return m_CreationParams.pProvider.Get(); 692 } 693 694 IPVT_FontMap* CPWL_Wnd::GetFontMap() const { 695 return m_CreationParams.pFontMap; 696 } 697 698 CFX_Color CPWL_Wnd::GetBorderLeftTopColor(BorderStyle nBorderStyle) const { 699 switch (nBorderStyle) { 700 case BorderStyle::BEVELED: 701 return CFX_Color(CFX_Color::kGray, 1); 702 case BorderStyle::INSET: 703 return CFX_Color(CFX_Color::kGray, 0.5f); 704 default: 705 return CFX_Color(); 706 } 707 } 708 709 CFX_Color CPWL_Wnd::GetBorderRightBottomColor(BorderStyle nBorderStyle) const { 710 switch (nBorderStyle) { 711 case BorderStyle::BEVELED: 712 return GetBackgroundColor() / 2.0f; 713 case BorderStyle::INSET: 714 return CFX_Color(CFX_Color::kGray, 0.75f); 715 default: 716 return CFX_Color(); 717 } 718 } 719 720 int32_t CPWL_Wnd::GetTransparency() { 721 return m_CreationParams.nTransparency; 722 } 723 724 void CPWL_Wnd::SetTransparency(int32_t nTransparency) { 725 for (auto* pChild : m_Children) { 726 if (pChild) 727 pChild->SetTransparency(nTransparency); 728 } 729 m_CreationParams.nTransparency = nTransparency; 730 } 731 732 CFX_Matrix CPWL_Wnd::GetWindowMatrix() const { 733 CFX_Matrix mt = GetChildToRoot(); 734 if (ProviderIface* pProvider = GetProvider()) 735 mt.Concat(pProvider->GetWindowMatrix(GetAttachedData())); 736 return mt; 737 } 738 739 CFX_FloatRect CPWL_Wnd::PWLtoWnd(const CFX_FloatRect& rect) const { 740 CFX_Matrix mt = GetWindowMatrix(); 741 return mt.TransformRect(rect); 742 } 743 744 CFX_PointF CPWL_Wnd::ParentToChild(const CFX_PointF& point) const { 745 CFX_Matrix mt = GetChildMatrix(); 746 if (mt.IsIdentity()) 747 return point; 748 749 CFX_Matrix inverse = mt.GetInverse(); 750 if (!inverse.IsIdentity()) 751 mt = inverse; 752 return mt.Transform(point); 753 } 754 755 CFX_FloatRect CPWL_Wnd::ParentToChild(const CFX_FloatRect& rect) const { 756 CFX_Matrix mt = GetChildMatrix(); 757 if (mt.IsIdentity()) 758 return rect; 759 760 CFX_Matrix inverse = mt.GetInverse(); 761 if (!inverse.IsIdentity()) 762 mt = inverse; 763 764 return mt.TransformRect(rect); 765 } 766 767 CFX_Matrix CPWL_Wnd::GetChildToRoot() const { 768 CFX_Matrix mt; 769 if (HasFlag(PWS_CHILD)) { 770 const CPWL_Wnd* pParent = this; 771 while (pParent) { 772 mt.Concat(pParent->GetChildMatrix()); 773 pParent = pParent->GetParentWindow(); 774 } 775 } 776 return mt; 777 } 778 779 CFX_Matrix CPWL_Wnd::GetChildMatrix() const { 780 return HasFlag(PWS_CHILD) ? m_CreationParams.mtChild : CFX_Matrix(); 781 } 782 783 void CPWL_Wnd::SetChildMatrix(const CFX_Matrix& mt) { 784 m_CreationParams.mtChild = mt; 785 } 786 787 const CPWL_Wnd* CPWL_Wnd::GetFocused() const { 788 CPWL_MsgControl* pMsgCtrl = GetMsgControl(); 789 return pMsgCtrl ? pMsgCtrl->GetFocusedWindow() : nullptr; 790 } 791 792 void CPWL_Wnd::EnableWindow(bool bEnable) { 793 if (m_bEnabled == bEnable) 794 return; 795 796 for (auto* pChild : m_Children) { 797 if (pChild) 798 pChild->EnableWindow(bEnable); 799 } 800 m_bEnabled = bEnable; 801 } 802