• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The PDFium Authors
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 <sstream>
10 #include <utility>
11 #include <vector>
12 
13 #include "build/build_config.h"
14 #include "core/fxcrt/check.h"
15 #include "core/fxcrt/check_op.h"
16 #include "core/fxcrt/containers/contains.h"
17 #include "core/fxcrt/stl_util.h"
18 #include "core/fxge/cfx_renderdevice.h"
19 #include "fpdfsdk/pwl/cpwl_scroll_bar.h"
20 #include "public/fpdf_fwlevent.h"
21 
22 namespace {
23 
24 constexpr float kDefaultFontSize = 9.0f;
25 
26 }  // namespace
27 
28 // static
29 const CFX_Color CPWL_Wnd::kDefaultBlackColor =
30     CFX_Color(CFX_Color::Type::kGray, 0);
31 
32 // static
33 const CFX_Color CPWL_Wnd::kDefaultWhiteColor =
34     CFX_Color(CFX_Color::Type::kGray, 1);
35 
CreateParams(CFX_Timer::HandlerIface * timer_handler,IPWL_FillerNotify * filler_notify,ProviderIface * provider)36 CPWL_Wnd::CreateParams::CreateParams(CFX_Timer::HandlerIface* timer_handler,
37                                      IPWL_FillerNotify* filler_notify,
38                                      ProviderIface* provider)
39     : pTimerHandler(timer_handler),
40       pFillerNotify(filler_notify),
41       pProvider(provider),
42       fFontSize(kDefaultFontSize),
43       sDash{3, 0, 0} {}
44 
45 CPWL_Wnd::CreateParams::CreateParams(const CreateParams& other) = default;
46 
47 CPWL_Wnd::CreateParams::~CreateParams() = default;
48 
49 // For a compound window (a window containing a child window as occurs in a
50 // list box, combo box, or even a scroll bar), this class contains information
51 // shared amongst the parent and children.
52 class CPWL_Wnd::SharedCaptureFocusState final : public Observable {
53  public:
SharedCaptureFocusState(const CPWL_Wnd * pOwnerWnd)54   explicit SharedCaptureFocusState(const CPWL_Wnd* pOwnerWnd)
55       : m_pOwnerWnd(pOwnerWnd) {}
56   ~SharedCaptureFocusState() = default;
57 
IsOwnedByWnd(const CPWL_Wnd * pWnd) const58   bool IsOwnedByWnd(const CPWL_Wnd* pWnd) const { return m_pOwnerWnd == pWnd; }
59 
IsWndCaptureMouse(const CPWL_Wnd * pWnd) const60   bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
61     return pWnd && pdfium::Contains(m_MousePaths, pWnd);
62   }
63 
IsMainCaptureKeyboard(const CPWL_Wnd * pWnd) const64   bool IsMainCaptureKeyboard(const CPWL_Wnd* pWnd) const {
65     return pWnd == m_pMainKeyboardWnd;
66   }
67 
IsWndCaptureKeyboard(const CPWL_Wnd * pWnd) const68   bool IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
69     return pWnd && pdfium::Contains(m_KeyboardPaths, pWnd);
70   }
71 
SetCapture(CPWL_Wnd * pWnd)72   void SetCapture(CPWL_Wnd* pWnd) { m_MousePaths = pWnd->GetAncestors(); }
ReleaseCapture()73   void ReleaseCapture() { m_MousePaths.clear(); }
74 
SetFocus(CPWL_Wnd * pWnd)75   void SetFocus(CPWL_Wnd* pWnd) {
76     m_KeyboardPaths = pWnd->GetAncestors();
77     m_pMainKeyboardWnd = pWnd;
78 
79     // Note, pWnd may get destroyed in the OnSetFocus call.
80     pWnd->OnSetFocus();
81   }
82 
ReleaseFocus()83   void ReleaseFocus() {
84     ObservedPtr<SharedCaptureFocusState> this_observed(this);
85     if (!this_observed->m_KeyboardPaths.empty()) {
86       CPWL_Wnd* pWnd = this_observed->m_KeyboardPaths.front();
87       if (pWnd)
88         pWnd->OnKillFocus();
89     }
90     if (!this_observed) {
91       return;
92     }
93     this_observed->m_pMainKeyboardWnd = nullptr;
94     this_observed->m_KeyboardPaths.clear();
95   }
96 
RemoveWnd(CPWL_Wnd * pWnd)97   void RemoveWnd(CPWL_Wnd* pWnd) {
98     if (pWnd == m_pOwnerWnd) {
99       m_pOwnerWnd = nullptr;
100     }
101     if (pWnd == m_pMainKeyboardWnd) {
102       m_pMainKeyboardWnd = nullptr;
103     }
104     auto mouse_it = std::find(m_MousePaths.begin(), m_MousePaths.end(), pWnd);
105     if (mouse_it != m_MousePaths.end()) {
106       m_MousePaths.erase(mouse_it);
107     }
108     auto keyboard_it =
109         std::find(m_KeyboardPaths.begin(), m_KeyboardPaths.end(), pWnd);
110     if (keyboard_it != m_KeyboardPaths.end()) {
111       m_KeyboardPaths.erase(keyboard_it);
112     }
113   }
114 
115  private:
116   UnownedPtr<const CPWL_Wnd> m_pOwnerWnd;
117   UnownedPtr<const CPWL_Wnd> m_pMainKeyboardWnd;
118   std::vector<UnownedPtr<CPWL_Wnd>> m_MousePaths;
119   std::vector<UnownedPtr<CPWL_Wnd>> m_KeyboardPaths;
120 };
121 
122 // static
IsSHIFTKeyDown(Mask<FWL_EVENTFLAG> nFlag)123 bool CPWL_Wnd::IsSHIFTKeyDown(Mask<FWL_EVENTFLAG> nFlag) {
124   return !!(nFlag & FWL_EVENTFLAG_ShiftKey);
125 }
126 
127 // static
IsCTRLKeyDown(Mask<FWL_EVENTFLAG> nFlag)128 bool CPWL_Wnd::IsCTRLKeyDown(Mask<FWL_EVENTFLAG> nFlag) {
129   return !!(nFlag & FWL_EVENTFLAG_ControlKey);
130 }
131 
132 // static
IsALTKeyDown(Mask<FWL_EVENTFLAG> nFlag)133 bool CPWL_Wnd::IsALTKeyDown(Mask<FWL_EVENTFLAG> nFlag) {
134   return !!(nFlag & FWL_EVENTFLAG_AltKey);
135 }
136 
137 // static
IsMETAKeyDown(Mask<FWL_EVENTFLAG> nFlag)138 bool CPWL_Wnd::IsMETAKeyDown(Mask<FWL_EVENTFLAG> nFlag) {
139   return !!(nFlag & FWL_EVENTFLAG_MetaKey);
140 }
141 
142 // static
IsPlatformShortcutKey(Mask<FWL_EVENTFLAG> nFlag)143 bool CPWL_Wnd::IsPlatformShortcutKey(Mask<FWL_EVENTFLAG> nFlag) {
144 #if BUILDFLAG(IS_APPLE)
145   return IsMETAKeyDown(nFlag);
146 #else
147   return IsCTRLKeyDown(nFlag);
148 #endif
149 }
150 
CPWL_Wnd(const CreateParams & cp,std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData)151 CPWL_Wnd::CPWL_Wnd(
152     const CreateParams& cp,
153     std::unique_ptr<IPWL_FillerNotify::PerWindowData> pAttachedData)
154     : m_CreationParams(cp), m_pAttachedData(std::move(pAttachedData)) {}
155 
~CPWL_Wnd()156 CPWL_Wnd::~CPWL_Wnd() {
157   DCHECK(!m_bCreated);
158 }
159 
Realize()160 void CPWL_Wnd::Realize() {
161   DCHECK(!m_bCreated);
162 
163   m_CreationParams.rcRectWnd.Normalize();
164   m_rcWindow = m_CreationParams.rcRectWnd;
165   m_rcClip = m_rcWindow;
166   if (!m_rcClip.IsEmpty()) {
167     m_rcClip.Inflate(1.0f, 1.0f);
168     m_rcClip.Normalize();
169   }
170   CreateSharedCaptureFocusState();
171 
172   CreateParams ccp = m_CreationParams;
173   ccp.dwFlags &= 0xFFFF0000L;  // remove sub styles
174   CreateVScrollBar(ccp);
175   CreateChildWnd(ccp);
176   m_bVisible = HasFlag(PWS_VISIBLE);
177   OnCreated();
178   if (!RepositionChildWnd()) {
179     return;
180   }
181 
182   m_bCreated = true;
183 }
184 
OnCreated()185 void CPWL_Wnd::OnCreated() {}
186 
OnDestroy()187 void CPWL_Wnd::OnDestroy() {}
188 
InvalidateProvider(ProviderIface * provider)189 void CPWL_Wnd::InvalidateProvider(ProviderIface* provider) {
190   if (m_CreationParams.pProvider.Get() == provider)
191     m_CreationParams.pProvider.Reset();
192 }
193 
Destroy()194 void CPWL_Wnd::Destroy() {
195   KillFocus();
196   OnDestroy();
197   if (m_bCreated) {
198     m_pVScrollBar = nullptr;
199     while (!m_Children.empty()) {
200       std::unique_ptr<CPWL_Wnd> pChild = std::move(m_Children.back());
201       m_Children.pop_back();
202       pChild->Destroy();
203     }
204     if (m_pParent)
205       m_pParent->RemoveChild(this);
206     m_bCreated = false;
207   }
208   DestroySharedCaptureFocusState();
209 }
210 
Move(const CFX_FloatRect & rcNew,bool bReset,bool bRefresh)211 bool CPWL_Wnd::Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh) {
212   if (!IsValid())
213     return true;
214 
215   CFX_FloatRect rcOld = GetWindowRect();
216   m_rcWindow = rcNew;
217   m_rcWindow.Normalize();
218 
219   if (bReset) {
220     if (rcOld.left != rcNew.left || rcOld.right != rcNew.right ||
221         rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom) {
222       if (!RepositionChildWnd()) {
223         return false;
224       }
225     }
226   }
227   if (bRefresh && !InvalidateRectMove(rcOld, rcNew))
228     return false;
229 
230   m_CreationParams.rcRectWnd = m_rcWindow;
231   return true;
232 }
233 
InvalidateRectMove(const CFX_FloatRect & rcOld,const CFX_FloatRect & rcNew)234 bool CPWL_Wnd::InvalidateRectMove(const CFX_FloatRect& rcOld,
235                                   const CFX_FloatRect& rcNew) {
236   CFX_FloatRect rcUnion = rcOld;
237   rcUnion.Union(rcNew);
238 
239   return InvalidateRect(&rcUnion);
240 }
241 
DrawAppearance(CFX_RenderDevice * pDevice,const CFX_Matrix & mtUser2Device)242 void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice,
243                               const CFX_Matrix& mtUser2Device) {
244   if (IsValid() && IsVisible()) {
245     DrawThisAppearance(pDevice, mtUser2Device);
246     DrawChildAppearance(pDevice, mtUser2Device);
247   }
248 }
249 
DrawThisAppearance(CFX_RenderDevice * pDevice,const CFX_Matrix & mtUser2Device)250 void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice,
251                                   const CFX_Matrix& mtUser2Device) {
252   CFX_FloatRect rectWnd = GetWindowRect();
253   if (rectWnd.IsEmpty())
254     return;
255 
256   if (HasFlag(PWS_BACKGROUND)) {
257     float width = static_cast<float>(GetBorderWidth() + GetInnerBorderWidth());
258     pDevice->DrawFillRect(&mtUser2Device, rectWnd.GetDeflated(width, width),
259                           GetBackgroundColor(), GetTransparency());
260   }
261 
262   if (HasFlag(PWS_BORDER)) {
263     pDevice->DrawBorder(&mtUser2Device, rectWnd,
264                         static_cast<float>(GetBorderWidth()), GetBorderColor(),
265                         GetBorderLeftTopColor(GetBorderStyle()),
266                         GetBorderRightBottomColor(GetBorderStyle()),
267                         GetBorderStyle(), GetTransparency());
268   }
269 }
270 
DrawChildAppearance(CFX_RenderDevice * pDevice,const CFX_Matrix & mtUser2Device)271 void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice,
272                                    const CFX_Matrix& mtUser2Device) {
273   for (const auto& pChild : m_Children) {
274     pChild->DrawAppearance(pDevice, mtUser2Device);
275   }
276 }
277 
InvalidateRect(const CFX_FloatRect * pRect)278 bool CPWL_Wnd::InvalidateRect(const CFX_FloatRect* pRect) {
279   ObservedPtr<CPWL_Wnd> this_observed(this);
280   if (!this_observed->IsValid()) {
281     return true;
282   }
283   CFX_FloatRect rcRefresh = pRect ? *pRect : this_observed->GetWindowRect();
284   if (!this_observed->HasFlag(PWS_NOREFRESHCLIP)) {
285     CFX_FloatRect rcClip = this_observed->GetClipRect();
286     if (!rcClip.IsEmpty())
287       rcRefresh.Intersect(rcClip);
288   }
289 
290   CFX_FloatRect rcWin = this_observed->PWLtoWnd(rcRefresh);
291   rcWin.Inflate(1, 1);
292   rcWin.Normalize();
293   this_observed->GetFillerNotify()->InvalidateRect(
294       this_observed->m_pAttachedData.get(), rcWin);
295   return !!this_observed;
296 }
297 
OnKeyDown(FWL_VKEYCODE nKeyCode,Mask<FWL_EVENTFLAG> nFlag)298 bool CPWL_Wnd::OnKeyDown(FWL_VKEYCODE nKeyCode, Mask<FWL_EVENTFLAG> nFlag) {
299   if (!IsValid() || !IsVisible())
300     return false;
301   if (!IsWndCaptureKeyboard(this))
302     return false;
303   for (const auto& pChild : m_Children) {
304     if (IsWndCaptureKeyboard(pChild.get()))
305       return pChild->OnKeyDown(nKeyCode, nFlag);
306   }
307   return false;
308 }
309 
OnChar(uint16_t nChar,Mask<FWL_EVENTFLAG> nFlag)310 bool CPWL_Wnd::OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag) {
311   if (!IsValid() || !IsVisible())
312     return false;
313   if (!IsWndCaptureKeyboard(this))
314     return false;
315   for (const auto& pChild : m_Children) {
316     if (IsWndCaptureKeyboard(pChild.get()))
317       return pChild->OnChar(nChar, nFlag);
318   }
319   return false;
320 }
321 
322 #define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name)         \
323   bool CPWL_Wnd::mouse_method_name(Mask<FWL_EVENTFLAG> nFlag, \
324                                    const CFX_PointF& point) { \
325     if (!IsValid() || !IsVisible())                           \
326       return false;                                           \
327     if (IsWndCaptureMouse(this)) {                            \
328       for (const auto& pChild : m_Children) {                 \
329         if (IsWndCaptureMouse(pChild.get())) {                \
330           return pChild->mouse_method_name(nFlag, point);     \
331         }                                                     \
332       }                                                       \
333       SetCursor();                                            \
334       return false;                                           \
335     }                                                         \
336     for (const auto& pChild : m_Children) {                   \
337       if (pChild->WndHitTest(point)) {                        \
338         return pChild->mouse_method_name(nFlag, point);       \
339       }                                                       \
340     }                                                         \
341     if (WndHitTest(point))                                    \
342       SetCursor();                                            \
343     return false;                                             \
344   }
345 
346 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk)
PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown)347 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown)
348 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp)
349 PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove)
350 #undef PWL_IMPLEMENT_MOUSE_METHOD
351 
352 // Unlike their FWL counterparts, PWL windows don't handle right clicks.
353 bool CPWL_Wnd::OnRButtonDown(Mask<FWL_EVENTFLAG> nFlag,
354                              const CFX_PointF& point) {
355   return false;
356 }
357 
OnRButtonUp(Mask<FWL_EVENTFLAG> nFlag,const CFX_PointF & point)358 bool CPWL_Wnd::OnRButtonUp(Mask<FWL_EVENTFLAG> nFlag, const CFX_PointF& point) {
359   return false;
360 }
361 
GetText()362 WideString CPWL_Wnd::GetText() {
363   return WideString();
364 }
365 
GetSelectedText()366 WideString CPWL_Wnd::GetSelectedText() {
367   return WideString();
368 }
369 
ReplaceAndKeepSelection(const WideString & text)370 void CPWL_Wnd::ReplaceAndKeepSelection(const WideString& text) {}
371 
ReplaceSelection(const WideString & text)372 void CPWL_Wnd::ReplaceSelection(const WideString& text) {}
373 
SelectAllText()374 bool CPWL_Wnd::SelectAllText() {
375   return false;
376 }
377 
CanUndo()378 bool CPWL_Wnd::CanUndo() {
379   return false;
380 }
381 
CanRedo()382 bool CPWL_Wnd::CanRedo() {
383   return false;
384 }
385 
Undo()386 bool CPWL_Wnd::Undo() {
387   return false;
388 }
389 
Redo()390 bool CPWL_Wnd::Redo() {
391   return false;
392 }
393 
OnMouseWheel(Mask<FWL_EVENTFLAG> nFlag,const CFX_PointF & point,const CFX_Vector & delta)394 bool CPWL_Wnd::OnMouseWheel(Mask<FWL_EVENTFLAG> nFlag,
395                             const CFX_PointF& point,
396                             const CFX_Vector& delta) {
397   if (!IsValid() || !IsVisible())
398     return false;
399 
400   SetCursor();
401   if (!IsWndCaptureKeyboard(this))
402     return false;
403 
404   for (const auto& pChild : m_Children) {
405     if (IsWndCaptureKeyboard(pChild.get()))
406       return pChild->OnMouseWheel(nFlag, point, delta);
407   }
408   return false;
409 }
410 
AddChild(std::unique_ptr<CPWL_Wnd> pWnd)411 void CPWL_Wnd::AddChild(std::unique_ptr<CPWL_Wnd> pWnd) {
412   DCHECK(!pWnd->m_pParent);
413   pWnd->m_pParent = this;
414   m_Children.push_back(std::move(pWnd));
415 }
416 
RemoveChild(CPWL_Wnd * pWnd)417 void CPWL_Wnd::RemoveChild(CPWL_Wnd* pWnd) {
418   DCHECK_EQ(pWnd->m_pParent, this);
419   auto it =
420       std::find(m_Children.begin(), m_Children.end(), MakeFakeUniquePtr(pWnd));
421   if (it == m_Children.end())
422     return;
423 
424   // TODO(tsepez): murky ownership.
425   it->release();
426   m_Children.erase(it);
427 }
428 
SetScrollInfo(const PWL_SCROLL_INFO & info)429 void CPWL_Wnd::SetScrollInfo(const PWL_SCROLL_INFO& info) {}
430 
SetScrollPosition(float pos)431 void CPWL_Wnd::SetScrollPosition(float pos) {}
432 
ScrollWindowVertically(float pos)433 void CPWL_Wnd::ScrollWindowVertically(float pos) {}
434 
NotifyLButtonDown(CPWL_Wnd * child,const CFX_PointF & pos)435 void CPWL_Wnd::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {}
436 
NotifyLButtonUp(CPWL_Wnd * child,const CFX_PointF & pos)437 void CPWL_Wnd::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {}
438 
NotifyMouseMove(CPWL_Wnd * child,const CFX_PointF & pos)439 void CPWL_Wnd::NotifyMouseMove(CPWL_Wnd* child, const CFX_PointF& pos) {}
440 
GetWindowRect() const441 CFX_FloatRect CPWL_Wnd::GetWindowRect() const {
442   return m_rcWindow;
443 }
444 
GetClientRect() const445 CFX_FloatRect CPWL_Wnd::GetClientRect() const {
446   CFX_FloatRect rcWindow = GetWindowRect();
447 
448   float width = static_cast<float>(GetBorderWidth() + GetInnerBorderWidth());
449   CFX_FloatRect rcClient = rcWindow.GetDeflated(width, width);
450   if (CPWL_ScrollBar* pVSB = GetVScrollBar())
451     rcClient.right -= pVSB->GetScrollBarWidth();
452 
453   rcClient.Normalize();
454   return rcWindow.Contains(rcClient) ? rcClient : CFX_FloatRect();
455 }
456 
GetCenterPoint() const457 CFX_PointF CPWL_Wnd::GetCenterPoint() const {
458   CFX_FloatRect rcClient = GetClientRect();
459   return CFX_PointF((rcClient.left + rcClient.right) * 0.5f,
460                     (rcClient.top + rcClient.bottom) * 0.5f);
461 }
462 
HasFlag(uint32_t dwFlags) const463 bool CPWL_Wnd::HasFlag(uint32_t dwFlags) const {
464   return (m_CreationParams.dwFlags & dwFlags) != 0;
465 }
466 
RemoveFlag(uint32_t dwFlags)467 void CPWL_Wnd::RemoveFlag(uint32_t dwFlags) {
468   m_CreationParams.dwFlags &= ~dwFlags;
469 }
470 
GetBackgroundColor() const471 CFX_Color CPWL_Wnd::GetBackgroundColor() const {
472   return m_CreationParams.sBackgroundColor;
473 }
474 
GetTextColor() const475 CFX_Color CPWL_Wnd::GetTextColor() const {
476   return m_CreationParams.sTextColor;
477 }
478 
GetBorderStyle() const479 BorderStyle CPWL_Wnd::GetBorderStyle() const {
480   return m_CreationParams.nBorderStyle;
481 }
482 
GetBorderWidth() const483 int32_t CPWL_Wnd::GetBorderWidth() const {
484   return HasFlag(PWS_BORDER) ? m_CreationParams.dwBorderWidth : 0;
485 }
486 
GetInnerBorderWidth() const487 int32_t CPWL_Wnd::GetInnerBorderWidth() const {
488   return 0;
489 }
490 
GetBorderColor() const491 CFX_Color CPWL_Wnd::GetBorderColor() const {
492   return HasFlag(PWS_BORDER) ? m_CreationParams.sBorderColor : CFX_Color();
493 }
494 
GetBorderDash() const495 const CPWL_Dash& CPWL_Wnd::GetBorderDash() const {
496   return m_CreationParams.sDash;
497 }
498 
GetVScrollBar() const499 CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const {
500   return HasFlag(PWS_VSCROLL) ? m_pVScrollBar : nullptr;
501 }
502 
CreateVScrollBar(const CreateParams & cp)503 void CPWL_Wnd::CreateVScrollBar(const CreateParams& cp) {
504   if (m_pVScrollBar || !HasFlag(PWS_VSCROLL))
505     return;
506 
507   CreateParams scp = cp;
508   scp.dwFlags = PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP;
509   scp.sBackgroundColor = kDefaultWhiteColor;
510   scp.eCursorType = IPWL_FillerNotify::CursorStyle::kArrow;
511   scp.nTransparency = CPWL_ScrollBar::kTransparency;
512 
513   auto pBar = std::make_unique<CPWL_ScrollBar>(scp, CloneAttachedData());
514   m_pVScrollBar = pBar.get();
515   AddChild(std::move(pBar));
516   m_pVScrollBar->Realize();
517 }
518 
SetCapture()519 void CPWL_Wnd::SetCapture() {
520   if (SharedCaptureFocusState* pSharedState = GetSharedCaptureFocusState()) {
521     pSharedState->SetCapture(this);
522   }
523 }
524 
ReleaseCapture()525 void CPWL_Wnd::ReleaseCapture() {
526   for (const auto& pChild : m_Children)
527     pChild->ReleaseCapture();
528 
529   if (SharedCaptureFocusState* pSharedState = GetSharedCaptureFocusState()) {
530     pSharedState->ReleaseCapture();
531   }
532 }
533 
SetFocus()534 void CPWL_Wnd::SetFocus() {
535   if (SharedCaptureFocusState* pSharedState = GetSharedCaptureFocusState()) {
536     if (!pSharedState->IsMainCaptureKeyboard(this)) {
537       pSharedState->ReleaseFocus();
538     }
539     pSharedState->SetFocus(this);
540   }
541 }
542 
KillFocus()543 void CPWL_Wnd::KillFocus() {
544   if (SharedCaptureFocusState* pSharedState = GetSharedCaptureFocusState()) {
545     if (pSharedState->IsWndCaptureKeyboard(this)) {
546       pSharedState->ReleaseFocus();
547     }
548   }
549 }
550 
OnSetFocus()551 void CPWL_Wnd::OnSetFocus() {}
552 
OnKillFocus()553 void CPWL_Wnd::OnKillFocus() {}
554 
CloneAttachedData() const555 std::unique_ptr<IPWL_FillerNotify::PerWindowData> CPWL_Wnd::CloneAttachedData()
556     const {
557   return m_pAttachedData ? m_pAttachedData->Clone() : nullptr;
558 }
559 
GetAncestors()560 std::vector<UnownedPtr<CPWL_Wnd>> CPWL_Wnd::GetAncestors() {
561   std::vector<UnownedPtr<CPWL_Wnd>> results;
562   for (CPWL_Wnd* pWnd = this; pWnd; pWnd = pWnd->GetParentWindow()) {
563     results.emplace_back(pWnd);
564   }
565   return results;
566 }
567 
WndHitTest(const CFX_PointF & point) const568 bool CPWL_Wnd::WndHitTest(const CFX_PointF& point) const {
569   return IsValid() && IsVisible() && GetWindowRect().Contains(point);
570 }
571 
ClientHitTest(const CFX_PointF & point) const572 bool CPWL_Wnd::ClientHitTest(const CFX_PointF& point) const {
573   return IsValid() && IsVisible() && GetClientRect().Contains(point);
574 }
575 
SetVisible(bool bVisible)576 bool CPWL_Wnd::SetVisible(bool bVisible) {
577   ObservedPtr<CPWL_Wnd> this_observed(this);
578   if (!this_observed->IsValid()) {
579     return true;
580   }
581   for (const auto& pChild : this_observed->m_Children) {
582     if (!pChild->SetVisible(bVisible)) {
583       return false;
584     }
585     if (!this_observed) {
586       return false;
587     }
588   }
589   if (bVisible != this_observed->m_bVisible) {
590     this_observed->m_bVisible = bVisible;
591     if (!this_observed->RepositionChildWnd()) {
592       return false;
593     }
594     if (!this_observed->InvalidateRect(nullptr)) {
595       return false;
596     }
597   }
598   return true;
599 }
600 
SetClipRect(const CFX_FloatRect & rect)601 void CPWL_Wnd::SetClipRect(const CFX_FloatRect& rect) {
602   m_rcClip = rect;
603   m_rcClip.Normalize();
604 }
605 
GetClipRect() const606 const CFX_FloatRect& CPWL_Wnd::GetClipRect() const {
607   return m_rcClip;
608 }
609 
IsReadOnly() const610 bool CPWL_Wnd::IsReadOnly() const {
611   return HasFlag(PWS_READONLY);
612 }
613 
RepositionChildWnd()614 bool CPWL_Wnd::RepositionChildWnd() {
615   ObservedPtr<CPWL_Wnd> this_observed(this);
616   CPWL_ScrollBar* pVSB = this_observed->GetVScrollBar();
617   if (!pVSB) {
618     return true;
619   }
620   CFX_FloatRect rcContent = this_observed->GetWindowRect();
621   if (!rcContent.IsEmpty()) {
622     float width = static_cast<float>(this_observed->GetBorderWidth() +
623                                      this_observed->GetInnerBorderWidth());
624     rcContent.Deflate(width, width);
625     rcContent.Normalize();
626   }
627   CFX_FloatRect rcVScroll =
628       CFX_FloatRect(rcContent.right - CPWL_ScrollBar::kWidth, rcContent.bottom,
629                     rcContent.right - 1.0f, rcContent.top);
630 
631   pVSB->Move(rcVScroll, true, false);
632   return !!this_observed;
633 }
634 
CreateChildWnd(const CreateParams & cp)635 void CPWL_Wnd::CreateChildWnd(const CreateParams& cp) {}
636 
SetCursor()637 void CPWL_Wnd::SetCursor() {
638   if (IsValid())
639     GetFillerNotify()->SetCursor(GetCreationParams()->eCursorType);
640 }
641 
CreateSharedCaptureFocusState()642 void CPWL_Wnd::CreateSharedCaptureFocusState() {
643   if (!m_CreationParams.pSharedCaptureFocusState) {
644     m_CreationParams.pSharedCaptureFocusState =
645         new SharedCaptureFocusState(this);
646   }
647 }
648 
DestroySharedCaptureFocusState()649 void CPWL_Wnd::DestroySharedCaptureFocusState() {
650   SharedCaptureFocusState* pSharedCaptureFocusState =
651       GetSharedCaptureFocusState();
652   if (!pSharedCaptureFocusState) {
653     return;
654   }
655   const bool owned = pSharedCaptureFocusState->IsOwnedByWnd(this);
656   pSharedCaptureFocusState->RemoveWnd(this);
657   if (owned) {
658     delete pSharedCaptureFocusState;
659   }
660 }
661 
GetSharedCaptureFocusState() const662 CPWL_Wnd::SharedCaptureFocusState* CPWL_Wnd::GetSharedCaptureFocusState()
663     const {
664   return m_CreationParams.pSharedCaptureFocusState;
665 }
666 
IsCaptureMouse() const667 bool CPWL_Wnd::IsCaptureMouse() const {
668   return IsWndCaptureMouse(this);
669 }
670 
IsWndCaptureMouse(const CPWL_Wnd * pWnd) const671 bool CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
672   SharedCaptureFocusState* pCtrl = GetSharedCaptureFocusState();
673   return pCtrl && pCtrl->IsWndCaptureMouse(pWnd);
674 }
675 
IsWndCaptureKeyboard(const CPWL_Wnd * pWnd) const676 bool CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
677   SharedCaptureFocusState* pCtrl = GetSharedCaptureFocusState();
678   return pCtrl && pCtrl->IsWndCaptureKeyboard(pWnd);
679 }
680 
IsFocused() const681 bool CPWL_Wnd::IsFocused() const {
682   SharedCaptureFocusState* pCtrl = GetSharedCaptureFocusState();
683   return pCtrl && pCtrl->IsMainCaptureKeyboard(this);
684 }
685 
GetFocusRect() const686 CFX_FloatRect CPWL_Wnd::GetFocusRect() const {
687   CFX_FloatRect rect = GetWindowRect();
688   if (!rect.IsEmpty()) {
689     rect.Inflate(1.0f, 1.0f);
690     rect.Normalize();
691   }
692   return rect;
693 }
694 
GetFontSize() const695 float CPWL_Wnd::GetFontSize() const {
696   return m_CreationParams.fFontSize;
697 }
698 
SetFontSize(float fFontSize)699 void CPWL_Wnd::SetFontSize(float fFontSize) {
700   m_CreationParams.fFontSize = fFontSize;
701 }
702 
GetBorderLeftTopColor(BorderStyle nBorderStyle) const703 CFX_Color CPWL_Wnd::GetBorderLeftTopColor(BorderStyle nBorderStyle) const {
704   switch (nBorderStyle) {
705     case BorderStyle::kBeveled:
706       return CFX_Color(CFX_Color::Type::kGray, 1);
707     case BorderStyle::kInset:
708       return CFX_Color(CFX_Color::Type::kGray, 0.5f);
709     default:
710       return CFX_Color();
711   }
712 }
713 
GetBorderRightBottomColor(BorderStyle nBorderStyle) const714 CFX_Color CPWL_Wnd::GetBorderRightBottomColor(BorderStyle nBorderStyle) const {
715   switch (nBorderStyle) {
716     case BorderStyle::kBeveled:
717       return GetBackgroundColor() / 2.0f;
718     case BorderStyle::kInset:
719       return CFX_Color(CFX_Color::Type::kGray, 0.75f);
720     default:
721       return CFX_Color();
722   }
723 }
724 
GetTransparency()725 int32_t CPWL_Wnd::GetTransparency() {
726   return m_CreationParams.nTransparency;
727 }
728 
SetTransparency(int32_t nTransparency)729 void CPWL_Wnd::SetTransparency(int32_t nTransparency) {
730   for (const auto& pChild : m_Children)
731     pChild->SetTransparency(nTransparency);
732 
733   m_CreationParams.nTransparency = nTransparency;
734 }
735 
GetWindowMatrix() const736 CFX_Matrix CPWL_Wnd::GetWindowMatrix() const {
737   CFX_Matrix mt;
738   if (ProviderIface* pProvider = GetProvider())
739     mt.Concat(pProvider->GetWindowMatrix(GetAttachedData()));
740   return mt;
741 }
742 
PWLtoWnd(const CFX_FloatRect & rect) const743 CFX_FloatRect CPWL_Wnd::PWLtoWnd(const CFX_FloatRect& rect) const {
744   CFX_Matrix mt = GetWindowMatrix();
745   return mt.TransformRect(rect);
746 }
747