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