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 <map>
8 #include <vector>
9
10 #include "fpdfsdk/pdfwindow/PWL_ScrollBar.h"
11 #include "fpdfsdk/pdfwindow/PWL_Utils.h"
12 #include "fpdfsdk/pdfwindow/PWL_Wnd.h"
13 #include "third_party/base/ptr_util.h"
14 #include "third_party/base/stl_util.h"
15
GetPWLTimeMap()16 static std::map<int32_t, CPWL_Timer*>& GetPWLTimeMap() {
17 // Leak the object at shutdown.
18 static auto timeMap = new std::map<int32_t, CPWL_Timer*>;
19 return *timeMap;
20 }
21
PWL_CREATEPARAM()22 PWL_CREATEPARAM::PWL_CREATEPARAM()
23 : rcRectWnd(0, 0, 0, 0),
24 pSystemHandler(nullptr),
25 pFontMap(nullptr),
26 pProvider(nullptr),
27 pFocusHandler(nullptr),
28 dwFlags(0),
29 sBackgroundColor(),
30 pAttachedWidget(nullptr),
31 nBorderStyle(BorderStyle::SOLID),
32 dwBorderWidth(1),
33 sBorderColor(),
34 sTextColor(),
35 nTransparency(255),
36 fFontSize(PWL_DEFAULT_FONTSIZE),
37 sDash(3, 0, 0),
38 pAttachedData(nullptr),
39 pParentWnd(nullptr),
40 pMsgControl(nullptr),
41 eCursorType(FXCT_ARROW),
42 mtChild(1, 0, 0, 1, 0, 0) {}
43
44 PWL_CREATEPARAM::PWL_CREATEPARAM(const PWL_CREATEPARAM& other) = default;
45
CPWL_Timer(CPWL_TimerHandler * pAttached,CFX_SystemHandler * pSystemHandler)46 CPWL_Timer::CPWL_Timer(CPWL_TimerHandler* pAttached,
47 CFX_SystemHandler* pSystemHandler)
48 : m_nTimerID(0), m_pAttached(pAttached), m_pSystemHandler(pSystemHandler) {
49 ASSERT(m_pAttached);
50 ASSERT(m_pSystemHandler);
51 }
52
~CPWL_Timer()53 CPWL_Timer::~CPWL_Timer() {
54 KillPWLTimer();
55 }
56
SetPWLTimer(int32_t nElapse)57 int32_t CPWL_Timer::SetPWLTimer(int32_t nElapse) {
58 if (m_nTimerID != 0)
59 KillPWLTimer();
60 m_nTimerID = m_pSystemHandler->SetTimer(nElapse, TimerProc);
61
62 GetPWLTimeMap()[m_nTimerID] = this;
63 return m_nTimerID;
64 }
65
KillPWLTimer()66 void CPWL_Timer::KillPWLTimer() {
67 if (m_nTimerID == 0)
68 return;
69
70 m_pSystemHandler->KillTimer(m_nTimerID);
71 GetPWLTimeMap().erase(m_nTimerID);
72 m_nTimerID = 0;
73 }
74
TimerProc(int32_t idEvent)75 void CPWL_Timer::TimerProc(int32_t idEvent) {
76 auto it = GetPWLTimeMap().find(idEvent);
77 if (it == GetPWLTimeMap().end())
78 return;
79
80 CPWL_Timer* pTimer = it->second;
81 if (pTimer->m_pAttached)
82 pTimer->m_pAttached->TimerProc();
83 }
84
CPWL_TimerHandler()85 CPWL_TimerHandler::CPWL_TimerHandler() {}
86
~CPWL_TimerHandler()87 CPWL_TimerHandler::~CPWL_TimerHandler() {}
88
BeginTimer(int32_t nElapse)89 void CPWL_TimerHandler::BeginTimer(int32_t nElapse) {
90 if (!m_pTimer)
91 m_pTimer = pdfium::MakeUnique<CPWL_Timer>(this, GetSystemHandler());
92
93 m_pTimer->SetPWLTimer(nElapse);
94 }
95
EndTimer()96 void CPWL_TimerHandler::EndTimer() {
97 if (m_pTimer)
98 m_pTimer->KillPWLTimer();
99 }
100
TimerProc()101 void CPWL_TimerHandler::TimerProc() {}
102
103 class CPWL_MsgControl {
104 friend class CPWL_Wnd;
105
106 public:
CPWL_MsgControl(CPWL_Wnd * pWnd)107 explicit CPWL_MsgControl(CPWL_Wnd* pWnd) {
108 m_pCreatedWnd = pWnd;
109 Default();
110 }
111
~CPWL_MsgControl()112 ~CPWL_MsgControl() { Default(); }
113
Default()114 void Default() {
115 m_aMousePath.clear();
116 m_aKeyboardPath.clear();
117 m_pMainMouseWnd = nullptr;
118 m_pMainKeyboardWnd = nullptr;
119 }
120
IsWndCreated(const CPWL_Wnd * pWnd) const121 bool IsWndCreated(const CPWL_Wnd* pWnd) const {
122 return m_pCreatedWnd == pWnd;
123 }
124
IsMainCaptureMouse(const CPWL_Wnd * pWnd) const125 bool IsMainCaptureMouse(const CPWL_Wnd* pWnd) const {
126 return pWnd == m_pMainMouseWnd;
127 }
128
IsWndCaptureMouse(const CPWL_Wnd * pWnd) const129 bool IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
130 return pWnd && pdfium::ContainsValue(m_aMousePath, pWnd);
131 }
132
IsMainCaptureKeyboard(const CPWL_Wnd * pWnd) const133 bool IsMainCaptureKeyboard(const CPWL_Wnd* pWnd) const {
134 return pWnd == m_pMainKeyboardWnd;
135 }
136
IsWndCaptureKeyboard(const CPWL_Wnd * pWnd) const137 bool IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
138 return pWnd && pdfium::ContainsValue(m_aKeyboardPath, pWnd);
139 }
140
SetFocus(CPWL_Wnd * pWnd)141 void SetFocus(CPWL_Wnd* pWnd) {
142 m_aKeyboardPath.clear();
143 if (pWnd) {
144 m_pMainKeyboardWnd = pWnd;
145 CPWL_Wnd* pParent = pWnd;
146 while (pParent) {
147 m_aKeyboardPath.push_back(pParent);
148 pParent = pParent->GetParentWindow();
149 }
150 pWnd->OnSetFocus();
151 }
152 }
153
KillFocus()154 void KillFocus() {
155 if (!m_aKeyboardPath.empty())
156 if (CPWL_Wnd* pWnd = m_aKeyboardPath[0])
157 pWnd->OnKillFocus();
158
159 m_pMainKeyboardWnd = nullptr;
160 m_aKeyboardPath.clear();
161 }
162
SetCapture(CPWL_Wnd * pWnd)163 void SetCapture(CPWL_Wnd* pWnd) {
164 m_aMousePath.clear();
165 if (pWnd) {
166 m_pMainMouseWnd = pWnd;
167 CPWL_Wnd* pParent = pWnd;
168 while (pParent) {
169 m_aMousePath.push_back(pParent);
170 pParent = pParent->GetParentWindow();
171 }
172 }
173 }
174
ReleaseCapture()175 void ReleaseCapture() {
176 m_pMainMouseWnd = nullptr;
177 m_aMousePath.clear();
178 }
179
180 private:
181 std::vector<CPWL_Wnd*> m_aMousePath;
182 std::vector<CPWL_Wnd*> m_aKeyboardPath;
183 CPWL_Wnd* m_pCreatedWnd;
184 CPWL_Wnd* m_pMainMouseWnd;
185 CPWL_Wnd* m_pMainKeyboardWnd;
186 };
187
CPWL_Wnd()188 CPWL_Wnd::CPWL_Wnd()
189 : m_pVScrollBar(nullptr),
190 m_rcWindow(),
191 m_rcClip(),
192 m_bCreated(false),
193 m_bVisible(false),
194 m_bNotifying(false),
195 m_bEnabled(true) {}
196
~CPWL_Wnd()197 CPWL_Wnd::~CPWL_Wnd() {
198 ASSERT(m_bCreated == false);
199 }
200
GetClassName() const201 CFX_ByteString CPWL_Wnd::GetClassName() const {
202 return "CPWL_Wnd";
203 }
204
Create(const PWL_CREATEPARAM & cp)205 void CPWL_Wnd::Create(const PWL_CREATEPARAM& cp) {
206 if (!IsValid()) {
207 m_sPrivateParam = cp;
208
209 OnCreate(m_sPrivateParam);
210
211 m_sPrivateParam.rcRectWnd.Normalize();
212 m_rcWindow = m_sPrivateParam.rcRectWnd;
213 m_rcClip = CPWL_Utils::InflateRect(m_rcWindow, 1.0f);
214
215 CreateMsgControl();
216
217 if (m_sPrivateParam.pParentWnd)
218 m_sPrivateParam.pParentWnd->OnNotify(this, PNM_ADDCHILD);
219
220 PWL_CREATEPARAM ccp = m_sPrivateParam;
221
222 ccp.dwFlags &= 0xFFFF0000L; // remove sub styles
223 ccp.mtChild = CFX_Matrix(1, 0, 0, 1, 0, 0);
224
225 CreateScrollBar(ccp);
226 CreateChildWnd(ccp);
227
228 m_bVisible = HasFlag(PWS_VISIBLE);
229
230 OnCreated();
231
232 RePosChildWnd();
233 m_bCreated = true;
234 }
235 }
236
OnCreate(PWL_CREATEPARAM & cp)237 void CPWL_Wnd::OnCreate(PWL_CREATEPARAM& cp) {}
238
OnCreated()239 void CPWL_Wnd::OnCreated() {}
240
OnDestroy()241 void CPWL_Wnd::OnDestroy() {}
242
InvalidateFocusHandler(IPWL_FocusHandler * handler)243 void CPWL_Wnd::InvalidateFocusHandler(IPWL_FocusHandler* handler) {
244 if (m_sPrivateParam.pFocusHandler == handler)
245 m_sPrivateParam.pFocusHandler = nullptr;
246 }
247
InvalidateProvider(IPWL_Provider * provider)248 void CPWL_Wnd::InvalidateProvider(IPWL_Provider* provider) {
249 if (m_sPrivateParam.pProvider.Get() == provider)
250 m_sPrivateParam.pProvider.Reset();
251 }
252
Destroy()253 void CPWL_Wnd::Destroy() {
254 KillFocus();
255 OnDestroy();
256 if (m_bCreated) {
257 for (auto it = m_Children.rbegin(); it != m_Children.rend(); ++it) {
258 if (CPWL_Wnd* pChild = *it) {
259 *it = nullptr;
260 pChild->Destroy();
261 delete pChild;
262 }
263 }
264 if (m_sPrivateParam.pParentWnd)
265 m_sPrivateParam.pParentWnd->OnNotify(this, PNM_REMOVECHILD);
266
267 m_bCreated = false;
268 }
269 DestroyMsgControl();
270 m_sPrivateParam.Reset();
271 m_Children.clear();
272 m_pVScrollBar = nullptr;
273 }
274
Move(const CFX_FloatRect & rcNew,bool bReset,bool bRefresh)275 void CPWL_Wnd::Move(const CFX_FloatRect& rcNew, bool bReset, bool bRefresh) {
276 if (IsValid()) {
277 CFX_FloatRect rcOld = GetWindowRect();
278
279 m_rcWindow = rcNew;
280 m_rcWindow.Normalize();
281
282 if (rcOld.left != rcNew.left || rcOld.right != rcNew.right ||
283 rcOld.top != rcNew.top || rcOld.bottom != rcNew.bottom) {
284 if (bReset) {
285 RePosChildWnd();
286 }
287 }
288 if (bRefresh) {
289 InvalidateRectMove(rcOld, rcNew);
290 }
291
292 m_sPrivateParam.rcRectWnd = m_rcWindow;
293 }
294 }
295
InvalidateRectMove(const CFX_FloatRect & rcOld,const CFX_FloatRect & rcNew)296 void CPWL_Wnd::InvalidateRectMove(const CFX_FloatRect& rcOld,
297 const CFX_FloatRect& rcNew) {
298 CFX_FloatRect rcUnion = rcOld;
299 rcUnion.Union(rcNew);
300
301 InvalidateRect(&rcUnion);
302 }
303
GetAppearanceStream(CFX_ByteTextBuf & sAppStream)304 void CPWL_Wnd::GetAppearanceStream(CFX_ByteTextBuf& sAppStream) {
305 if (IsValid() && IsVisible()) {
306 GetThisAppearanceStream(sAppStream);
307 GetChildAppearanceStream(sAppStream);
308 }
309 }
310
311 // if don't set,Get default apperance stream
GetThisAppearanceStream(CFX_ByteTextBuf & sAppStream)312 void CPWL_Wnd::GetThisAppearanceStream(CFX_ByteTextBuf& sAppStream) {
313 CFX_FloatRect rectWnd = GetWindowRect();
314 if (!rectWnd.IsEmpty()) {
315 CFX_ByteTextBuf sThis;
316
317 if (HasFlag(PWS_BACKGROUND))
318 sThis << CPWL_Utils::GetRectFillAppStream(rectWnd, GetBackgroundColor());
319
320 if (HasFlag(PWS_BORDER)) {
321 sThis << CPWL_Utils::GetBorderAppStream(
322 rectWnd, (FX_FLOAT)GetBorderWidth(), GetBorderColor(),
323 GetBorderLeftTopColor(GetBorderStyle()),
324 GetBorderRightBottomColor(GetBorderStyle()), GetBorderStyle(),
325 GetBorderDash());
326 }
327
328 sAppStream << sThis;
329 }
330 }
331
GetChildAppearanceStream(CFX_ByteTextBuf & sAppStream)332 void CPWL_Wnd::GetChildAppearanceStream(CFX_ByteTextBuf& sAppStream) {
333 for (CPWL_Wnd* pChild : m_Children) {
334 if (pChild)
335 pChild->GetAppearanceStream(sAppStream);
336 }
337 }
338
DrawAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)339 void CPWL_Wnd::DrawAppearance(CFX_RenderDevice* pDevice,
340 CFX_Matrix* pUser2Device) {
341 if (IsValid() && IsVisible()) {
342 DrawThisAppearance(pDevice, pUser2Device);
343 DrawChildAppearance(pDevice, pUser2Device);
344 }
345 }
346
DrawThisAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)347 void CPWL_Wnd::DrawThisAppearance(CFX_RenderDevice* pDevice,
348 CFX_Matrix* pUser2Device) {
349 CFX_FloatRect rectWnd = GetWindowRect();
350 if (!rectWnd.IsEmpty()) {
351 if (HasFlag(PWS_BACKGROUND)) {
352 CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(
353 rectWnd, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
354 CPWL_Utils::DrawFillRect(pDevice, pUser2Device, rcClient,
355 GetBackgroundColor(), GetTransparency());
356 }
357
358 if (HasFlag(PWS_BORDER))
359 CPWL_Utils::DrawBorder(pDevice, pUser2Device, rectWnd,
360 (FX_FLOAT)GetBorderWidth(), GetBorderColor(),
361 GetBorderLeftTopColor(GetBorderStyle()),
362 GetBorderRightBottomColor(GetBorderStyle()),
363 GetBorderStyle(), GetTransparency());
364 }
365 }
366
DrawChildAppearance(CFX_RenderDevice * pDevice,CFX_Matrix * pUser2Device)367 void CPWL_Wnd::DrawChildAppearance(CFX_RenderDevice* pDevice,
368 CFX_Matrix* pUser2Device) {
369 for (CPWL_Wnd* pChild : m_Children) {
370 if (!pChild)
371 continue;
372
373 CFX_Matrix mt = pChild->GetChildMatrix();
374 if (mt.IsIdentity()) {
375 pChild->DrawAppearance(pDevice, pUser2Device);
376 } else {
377 mt.Concat(*pUser2Device);
378 pChild->DrawAppearance(pDevice, &mt);
379 }
380 }
381 }
382
InvalidateRect(CFX_FloatRect * pRect)383 void CPWL_Wnd::InvalidateRect(CFX_FloatRect* pRect) {
384 if (IsValid()) {
385 CFX_FloatRect rcRefresh = pRect ? *pRect : GetWindowRect();
386
387 if (!HasFlag(PWS_NOREFRESHCLIP)) {
388 CFX_FloatRect rcClip = GetClipRect();
389 if (!rcClip.IsEmpty()) {
390 rcRefresh.Intersect(rcClip);
391 }
392 }
393
394 FX_RECT rcWin = PWLtoWnd(rcRefresh);
395 rcWin.left -= PWL_INVALIDATE_INFLATE;
396 rcWin.top -= PWL_INVALIDATE_INFLATE;
397 rcWin.right += PWL_INVALIDATE_INFLATE;
398 rcWin.bottom += PWL_INVALIDATE_INFLATE;
399
400 if (CFX_SystemHandler* pSH = GetSystemHandler()) {
401 if (CPDFSDK_Widget* widget = static_cast<CPDFSDK_Widget*>(
402 m_sPrivateParam.pAttachedWidget.Get())) {
403 pSH->InvalidateRect(widget, rcWin);
404 }
405 }
406 }
407 }
408
409 #define PWL_IMPLEMENT_KEY_METHOD(key_method_name) \
410 bool CPWL_Wnd::key_method_name(uint16_t nChar, uint32_t nFlag) { \
411 if (!IsValid() || !IsVisible() || !IsEnabled()) \
412 return false; \
413 if (!IsWndCaptureKeyboard(this)) \
414 return false; \
415 for (const auto& pChild : m_Children) { \
416 if (pChild && IsWndCaptureKeyboard(pChild)) \
417 return pChild->key_method_name(nChar, nFlag); \
418 } \
419 return false; \
420 }
421
422 PWL_IMPLEMENT_KEY_METHOD(OnKeyDown)
PWL_IMPLEMENT_KEY_METHOD(OnChar)423 PWL_IMPLEMENT_KEY_METHOD(OnChar)
424 #undef PWL_IMPLEMENT_KEY_METHOD
425
426 #define PWL_IMPLEMENT_MOUSE_METHOD(mouse_method_name) \
427 bool CPWL_Wnd::mouse_method_name(const CFX_PointF& point, uint32_t nFlag) { \
428 if (!IsValid() || !IsVisible() || !IsEnabled()) \
429 return false; \
430 if (IsWndCaptureMouse(this)) { \
431 for (const auto& pChild : m_Children) { \
432 if (pChild && IsWndCaptureMouse(pChild)) { \
433 return pChild->mouse_method_name(pChild->ParentToChild(point), \
434 nFlag); \
435 } \
436 } \
437 SetCursor(); \
438 return false; \
439 } \
440 for (const auto& pChild : m_Children) { \
441 if (pChild && pChild->WndHitTest(pChild->ParentToChild(point))) { \
442 return pChild->mouse_method_name(pChild->ParentToChild(point), nFlag); \
443 } \
444 } \
445 if (WndHitTest(point)) \
446 SetCursor(); \
447 return false; \
448 }
449
450 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDblClk)
451 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonDown)
452 PWL_IMPLEMENT_MOUSE_METHOD(OnLButtonUp)
453 PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonDown)
454 PWL_IMPLEMENT_MOUSE_METHOD(OnRButtonUp)
455 PWL_IMPLEMENT_MOUSE_METHOD(OnMouseMove)
456 #undef PWL_IMPLEMENT_MOUSE_METHOD
457
458 bool CPWL_Wnd::OnMouseWheel(short zDelta,
459 const CFX_PointF& point,
460 uint32_t nFlag) {
461 if (!IsValid() || !IsVisible() || !IsEnabled())
462 return false;
463
464 SetCursor();
465 if (!IsWndCaptureKeyboard(this))
466 return false;
467
468 for (const auto& pChild : m_Children) {
469 if (pChild && IsWndCaptureKeyboard(pChild))
470 return pChild->OnMouseWheel(zDelta, pChild->ParentToChild(point), nFlag);
471 }
472 return false;
473 }
474
AddChild(CPWL_Wnd * pWnd)475 void CPWL_Wnd::AddChild(CPWL_Wnd* pWnd) {
476 m_Children.push_back(pWnd);
477 }
478
RemoveChild(CPWL_Wnd * pWnd)479 void CPWL_Wnd::RemoveChild(CPWL_Wnd* pWnd) {
480 for (auto it = m_Children.rbegin(); it != m_Children.rend(); ++it) {
481 if (*it && *it == pWnd) {
482 m_Children.erase(std::next(it).base());
483 break;
484 }
485 }
486 }
487
OnNotify(CPWL_Wnd * pWnd,uint32_t msg,intptr_t wParam,intptr_t lParam)488 void CPWL_Wnd::OnNotify(CPWL_Wnd* pWnd,
489 uint32_t msg,
490 intptr_t wParam,
491 intptr_t lParam) {
492 switch (msg) {
493 case PNM_ADDCHILD:
494 AddChild(pWnd);
495 break;
496 case PNM_REMOVECHILD:
497 RemoveChild(pWnd);
498 break;
499 default:
500 break;
501 }
502 }
503
IsValid() const504 bool CPWL_Wnd::IsValid() const {
505 return m_bCreated;
506 }
507
GetCreationParam() const508 const PWL_CREATEPARAM& CPWL_Wnd::GetCreationParam() const {
509 return m_sPrivateParam;
510 }
511
GetParentWindow() const512 CPWL_Wnd* CPWL_Wnd::GetParentWindow() const {
513 return m_sPrivateParam.pParentWnd;
514 }
515
GetWindowRect() const516 CFX_FloatRect CPWL_Wnd::GetWindowRect() const {
517 return m_rcWindow;
518 }
519
GetClientRect() const520 CFX_FloatRect CPWL_Wnd::GetClientRect() const {
521 CFX_FloatRect rcWindow = GetWindowRect();
522 CFX_FloatRect rcClient = CPWL_Utils::DeflateRect(
523 rcWindow, (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
524 if (CPWL_ScrollBar* pVSB = GetVScrollBar())
525 rcClient.right -= pVSB->GetScrollBarWidth();
526
527 rcClient.Normalize();
528 return rcWindow.Contains(rcClient) ? rcClient : CFX_FloatRect();
529 }
530
GetCenterPoint() const531 CFX_PointF CPWL_Wnd::GetCenterPoint() const {
532 CFX_FloatRect rcClient = GetClientRect();
533 return CFX_PointF((rcClient.left + rcClient.right) * 0.5f,
534 (rcClient.top + rcClient.bottom) * 0.5f);
535 }
536
HasFlag(uint32_t dwFlags) const537 bool CPWL_Wnd::HasFlag(uint32_t dwFlags) const {
538 return (m_sPrivateParam.dwFlags & dwFlags) != 0;
539 }
540
RemoveFlag(uint32_t dwFlags)541 void CPWL_Wnd::RemoveFlag(uint32_t dwFlags) {
542 m_sPrivateParam.dwFlags &= ~dwFlags;
543 }
544
AddFlag(uint32_t dwFlags)545 void CPWL_Wnd::AddFlag(uint32_t dwFlags) {
546 m_sPrivateParam.dwFlags |= dwFlags;
547 }
548
GetBackgroundColor() const549 CPWL_Color CPWL_Wnd::GetBackgroundColor() const {
550 return m_sPrivateParam.sBackgroundColor;
551 }
552
SetBackgroundColor(const CPWL_Color & color)553 void CPWL_Wnd::SetBackgroundColor(const CPWL_Color& color) {
554 m_sPrivateParam.sBackgroundColor = color;
555 }
556
GetTextColor() const557 CPWL_Color CPWL_Wnd::GetTextColor() const {
558 return m_sPrivateParam.sTextColor;
559 }
560
GetBorderStyle() const561 BorderStyle CPWL_Wnd::GetBorderStyle() const {
562 return m_sPrivateParam.nBorderStyle;
563 }
564
SetBorderStyle(BorderStyle nBorderStyle)565 void CPWL_Wnd::SetBorderStyle(BorderStyle nBorderStyle) {
566 if (HasFlag(PWS_BORDER))
567 m_sPrivateParam.nBorderStyle = nBorderStyle;
568 }
569
GetBorderWidth() const570 int32_t CPWL_Wnd::GetBorderWidth() const {
571 if (HasFlag(PWS_BORDER))
572 return m_sPrivateParam.dwBorderWidth;
573
574 return 0;
575 }
576
GetInnerBorderWidth() const577 int32_t CPWL_Wnd::GetInnerBorderWidth() const {
578 return 0;
579 }
580
GetBorderColor() const581 CPWL_Color CPWL_Wnd::GetBorderColor() const {
582 if (HasFlag(PWS_BORDER))
583 return m_sPrivateParam.sBorderColor;
584
585 return CPWL_Color();
586 }
587
GetBorderDash() const588 const CPWL_Dash& CPWL_Wnd::GetBorderDash() const {
589 return m_sPrivateParam.sDash;
590 }
591
GetAttachedData() const592 void* CPWL_Wnd::GetAttachedData() const {
593 return m_sPrivateParam.pAttachedData;
594 }
595
GetVScrollBar() const596 CPWL_ScrollBar* CPWL_Wnd::GetVScrollBar() const {
597 if (HasFlag(PWS_VSCROLL))
598 return m_pVScrollBar;
599
600 return nullptr;
601 }
602
CreateScrollBar(const PWL_CREATEPARAM & cp)603 void CPWL_Wnd::CreateScrollBar(const PWL_CREATEPARAM& cp) {
604 CreateVScrollBar(cp);
605 }
606
CreateVScrollBar(const PWL_CREATEPARAM & cp)607 void CPWL_Wnd::CreateVScrollBar(const PWL_CREATEPARAM& cp) {
608 if (!m_pVScrollBar && HasFlag(PWS_VSCROLL)) {
609 PWL_CREATEPARAM scp = cp;
610
611 // flags
612 scp.dwFlags =
613 PWS_CHILD | PWS_BACKGROUND | PWS_AUTOTRANSPARENT | PWS_NOREFRESHCLIP;
614
615 scp.pParentWnd = this;
616 scp.sBackgroundColor = PWL_DEFAULT_WHITECOLOR;
617 scp.eCursorType = FXCT_ARROW;
618 scp.nTransparency = PWL_SCROLLBAR_TRANSPARENCY;
619
620 m_pVScrollBar = new CPWL_ScrollBar(SBT_VSCROLL);
621 m_pVScrollBar->Create(scp);
622 }
623 }
624
SetCapture()625 void CPWL_Wnd::SetCapture() {
626 if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
627 pMsgCtrl->SetCapture(this);
628 }
629
ReleaseCapture()630 void CPWL_Wnd::ReleaseCapture() {
631 for (const auto& pChild : m_Children) {
632 if (pChild)
633 pChild->ReleaseCapture();
634 }
635 if (CPWL_MsgControl* pMsgCtrl = GetMsgControl())
636 pMsgCtrl->ReleaseCapture();
637 }
638
SetFocus()639 void CPWL_Wnd::SetFocus() {
640 if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
641 if (!pMsgCtrl->IsMainCaptureKeyboard(this))
642 pMsgCtrl->KillFocus();
643 pMsgCtrl->SetFocus(this);
644 }
645 }
646
KillFocus()647 void CPWL_Wnd::KillFocus() {
648 if (CPWL_MsgControl* pMsgCtrl = GetMsgControl()) {
649 if (pMsgCtrl->IsWndCaptureKeyboard(this))
650 pMsgCtrl->KillFocus();
651 }
652 }
653
OnSetFocus()654 void CPWL_Wnd::OnSetFocus() {}
655
OnKillFocus()656 void CPWL_Wnd::OnKillFocus() {}
657
WndHitTest(const CFX_PointF & point) const658 bool CPWL_Wnd::WndHitTest(const CFX_PointF& point) const {
659 return IsValid() && IsVisible() && GetWindowRect().Contains(point);
660 }
661
ClientHitTest(const CFX_PointF & point) const662 bool CPWL_Wnd::ClientHitTest(const CFX_PointF& point) const {
663 return IsValid() && IsVisible() && GetClientRect().Contains(point);
664 }
665
GetRootWnd() const666 const CPWL_Wnd* CPWL_Wnd::GetRootWnd() const {
667 if (m_sPrivateParam.pParentWnd)
668 return m_sPrivateParam.pParentWnd->GetRootWnd();
669
670 return this;
671 }
672
SetVisible(bool bVisible)673 void CPWL_Wnd::SetVisible(bool bVisible) {
674 if (!IsValid())
675 return;
676
677 for (const auto& pChild : m_Children) {
678 if (pChild)
679 pChild->SetVisible(bVisible);
680 }
681 if (bVisible != m_bVisible) {
682 m_bVisible = bVisible;
683 RePosChildWnd();
684 InvalidateRect();
685 }
686 }
687
SetClipRect(const CFX_FloatRect & rect)688 void CPWL_Wnd::SetClipRect(const CFX_FloatRect& rect) {
689 m_rcClip = rect;
690 m_rcClip.Normalize();
691 }
692
GetClipRect() const693 const CFX_FloatRect& CPWL_Wnd::GetClipRect() const {
694 return m_rcClip;
695 }
696
IsReadOnly() const697 bool CPWL_Wnd::IsReadOnly() const {
698 return HasFlag(PWS_READONLY);
699 }
700
RePosChildWnd()701 void CPWL_Wnd::RePosChildWnd() {
702 CFX_FloatRect rcContent = CPWL_Utils::DeflateRect(
703 GetWindowRect(), (FX_FLOAT)(GetBorderWidth() + GetInnerBorderWidth()));
704
705 CPWL_ScrollBar* pVSB = GetVScrollBar();
706
707 CFX_FloatRect rcVScroll =
708 CFX_FloatRect(rcContent.right - PWL_SCROLLBAR_WIDTH, rcContent.bottom,
709 rcContent.right - 1.0f, rcContent.top);
710
711 if (pVSB)
712 pVSB->Move(rcVScroll, true, false);
713 }
714
CreateChildWnd(const PWL_CREATEPARAM & cp)715 void CPWL_Wnd::CreateChildWnd(const PWL_CREATEPARAM& cp) {}
716
SetCursor()717 void CPWL_Wnd::SetCursor() {
718 if (IsValid()) {
719 if (CFX_SystemHandler* pSH = GetSystemHandler()) {
720 int32_t nCursorType = GetCreationParam().eCursorType;
721 pSH->SetCursor(nCursorType);
722 }
723 }
724 }
725
CreateMsgControl()726 void CPWL_Wnd::CreateMsgControl() {
727 if (!m_sPrivateParam.pMsgControl)
728 m_sPrivateParam.pMsgControl = new CPWL_MsgControl(this);
729 }
730
DestroyMsgControl()731 void CPWL_Wnd::DestroyMsgControl() {
732 if (CPWL_MsgControl* pMsgControl = GetMsgControl())
733 if (pMsgControl->IsWndCreated(this))
734 delete pMsgControl;
735 }
736
GetMsgControl() const737 CPWL_MsgControl* CPWL_Wnd::GetMsgControl() const {
738 return m_sPrivateParam.pMsgControl;
739 }
740
IsCaptureMouse() const741 bool CPWL_Wnd::IsCaptureMouse() const {
742 return IsWndCaptureMouse(this);
743 }
744
IsWndCaptureMouse(const CPWL_Wnd * pWnd) const745 bool CPWL_Wnd::IsWndCaptureMouse(const CPWL_Wnd* pWnd) const {
746 if (CPWL_MsgControl* pCtrl = GetMsgControl())
747 return pCtrl->IsWndCaptureMouse(pWnd);
748
749 return false;
750 }
751
IsWndCaptureKeyboard(const CPWL_Wnd * pWnd) const752 bool CPWL_Wnd::IsWndCaptureKeyboard(const CPWL_Wnd* pWnd) const {
753 if (CPWL_MsgControl* pCtrl = GetMsgControl())
754 return pCtrl->IsWndCaptureKeyboard(pWnd);
755
756 return false;
757 }
758
IsFocused() const759 bool CPWL_Wnd::IsFocused() const {
760 if (CPWL_MsgControl* pCtrl = GetMsgControl())
761 return pCtrl->IsMainCaptureKeyboard(this);
762
763 return false;
764 }
765
GetFocusRect() const766 CFX_FloatRect CPWL_Wnd::GetFocusRect() const {
767 return CPWL_Utils::InflateRect(GetWindowRect(), 1);
768 }
769
GetFontSize() const770 FX_FLOAT CPWL_Wnd::GetFontSize() const {
771 return m_sPrivateParam.fFontSize;
772 }
773
SetFontSize(FX_FLOAT fFontSize)774 void CPWL_Wnd::SetFontSize(FX_FLOAT fFontSize) {
775 m_sPrivateParam.fFontSize = fFontSize;
776 }
777
GetSystemHandler() const778 CFX_SystemHandler* CPWL_Wnd::GetSystemHandler() const {
779 return m_sPrivateParam.pSystemHandler;
780 }
781
GetFocusHandler() const782 IPWL_FocusHandler* CPWL_Wnd::GetFocusHandler() const {
783 return m_sPrivateParam.pFocusHandler;
784 }
785
GetProvider() const786 IPWL_Provider* CPWL_Wnd::GetProvider() const {
787 return m_sPrivateParam.pProvider.Get();
788 }
789
GetFontMap() const790 IPVT_FontMap* CPWL_Wnd::GetFontMap() const {
791 return m_sPrivateParam.pFontMap;
792 }
793
GetBorderLeftTopColor(BorderStyle nBorderStyle) const794 CPWL_Color CPWL_Wnd::GetBorderLeftTopColor(BorderStyle nBorderStyle) const {
795 switch (nBorderStyle) {
796 case BorderStyle::BEVELED:
797 return CPWL_Color(COLORTYPE_GRAY, 1);
798 case BorderStyle::INSET:
799 return CPWL_Color(COLORTYPE_GRAY, 0.5f);
800 default:
801 return CPWL_Color();
802 }
803 }
804
GetBorderRightBottomColor(BorderStyle nBorderStyle) const805 CPWL_Color CPWL_Wnd::GetBorderRightBottomColor(BorderStyle nBorderStyle) const {
806 switch (nBorderStyle) {
807 case BorderStyle::BEVELED:
808 return GetBackgroundColor() / 2.0f;
809 case BorderStyle::INSET:
810 return CPWL_Color(COLORTYPE_GRAY, 0.75f);
811 default:
812 return CPWL_Color();
813 }
814 }
815
GetTransparency()816 int32_t CPWL_Wnd::GetTransparency() {
817 return m_sPrivateParam.nTransparency;
818 }
819
SetTransparency(int32_t nTransparency)820 void CPWL_Wnd::SetTransparency(int32_t nTransparency) {
821 for (const auto& pChild : m_Children) {
822 if (pChild)
823 pChild->SetTransparency(nTransparency);
824 }
825 m_sPrivateParam.nTransparency = nTransparency;
826 }
827
GetWindowMatrix() const828 CFX_Matrix CPWL_Wnd::GetWindowMatrix() const {
829 CFX_Matrix mt = GetChildToRoot();
830 if (IPWL_Provider* pProvider = GetProvider())
831 mt.Concat(pProvider->GetWindowMatrix(GetAttachedData()));
832 return mt;
833 }
834
PWLtoWnd(const CFX_FloatRect & rect) const835 FX_RECT CPWL_Wnd::PWLtoWnd(const CFX_FloatRect& rect) const {
836 CFX_FloatRect rcTemp = rect;
837 CFX_Matrix mt = GetWindowMatrix();
838 mt.TransformRect(rcTemp);
839 return FX_RECT((int32_t)(rcTemp.left + 0.5), (int32_t)(rcTemp.bottom + 0.5),
840 (int32_t)(rcTemp.right + 0.5), (int32_t)(rcTemp.top + 0.5));
841 }
842
ParentToChild(const CFX_PointF & point) const843 CFX_PointF CPWL_Wnd::ParentToChild(const CFX_PointF& point) const {
844 CFX_Matrix mt = GetChildMatrix();
845 if (mt.IsIdentity())
846 return point;
847
848 mt.SetReverse(mt);
849 return mt.Transform(point);
850 }
851
ParentToChild(const CFX_FloatRect & rect) const852 CFX_FloatRect CPWL_Wnd::ParentToChild(const CFX_FloatRect& rect) const {
853 CFX_Matrix mt = GetChildMatrix();
854 if (mt.IsIdentity())
855 return rect;
856
857 mt.SetReverse(mt);
858 CFX_FloatRect rc = rect;
859 mt.TransformRect(rc);
860 return rc;
861 }
862
GetChildToRoot() const863 CFX_Matrix CPWL_Wnd::GetChildToRoot() const {
864 CFX_Matrix mt(1, 0, 0, 1, 0, 0);
865 if (HasFlag(PWS_CHILD)) {
866 const CPWL_Wnd* pParent = this;
867 while (pParent) {
868 mt.Concat(pParent->GetChildMatrix());
869 pParent = pParent->GetParentWindow();
870 }
871 }
872 return mt;
873 }
874
GetChildMatrix() const875 CFX_Matrix CPWL_Wnd::GetChildMatrix() const {
876 if (HasFlag(PWS_CHILD))
877 return m_sPrivateParam.mtChild;
878
879 return CFX_Matrix(1, 0, 0, 1, 0, 0);
880 }
881
SetChildMatrix(const CFX_Matrix & mt)882 void CPWL_Wnd::SetChildMatrix(const CFX_Matrix& mt) {
883 m_sPrivateParam.mtChild = mt;
884 }
885
GetFocused() const886 const CPWL_Wnd* CPWL_Wnd::GetFocused() const {
887 CPWL_MsgControl* pMsgCtrl = GetMsgControl();
888 return pMsgCtrl ? pMsgCtrl->m_pMainKeyboardWnd : nullptr;
889 }
890
EnableWindow(bool bEnable)891 void CPWL_Wnd::EnableWindow(bool bEnable) {
892 if (m_bEnabled == bEnable)
893 return;
894
895 for (const auto& pChild : m_Children) {
896 if (pChild)
897 pChild->EnableWindow(bEnable);
898 }
899 m_bEnabled = bEnable;
900 }
901
IsCTRLpressed(uint32_t nFlag) const902 bool CPWL_Wnd::IsCTRLpressed(uint32_t nFlag) const {
903 CFX_SystemHandler* pSystemHandler = GetSystemHandler();
904 return pSystemHandler && pSystemHandler->IsCTRLKeyDown(nFlag);
905 }
906
IsSHIFTpressed(uint32_t nFlag) const907 bool CPWL_Wnd::IsSHIFTpressed(uint32_t nFlag) const {
908 CFX_SystemHandler* pSystemHandler = GetSystemHandler();
909 return pSystemHandler && pSystemHandler->IsSHIFTKeyDown(nFlag);
910 }
911
IsALTpressed(uint32_t nFlag) const912 bool CPWL_Wnd::IsALTpressed(uint32_t nFlag) const {
913 CFX_SystemHandler* pSystemHandler = GetSystemHandler();
914 return pSystemHandler && pSystemHandler->IsALTKeyDown(nFlag);
915 }
916