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 "xfa/fwl/cfwl_widgetmgr.h"
8 
9 #include <utility>
10 
11 #include "third_party/base/ptr_util.h"
12 #include "xfa/fwl/cfwl_app.h"
13 #include "xfa/fwl/cfwl_form.h"
14 #include "xfa/fwl/cfwl_notedriver.h"
15 #include "xfa/fxfa/app/xfa_fwladapter.h"
16 #include "xfa/fxfa/xfa_ffapp.h"
17 
18 namespace {
19 
20 const int kNeedRepaintHitPoints = 12;
21 const int kNeedRepaintHitPiece = 3;
22 
23 struct FWL_NEEDREPAINTHITDATA {
24   CFX_PointF hitPoint;
25   bool bNotNeedRepaint;
26   bool bNotContainByDirty;
27 };
28 
29 }  // namespace
30 
CFWL_WidgetMgr(CXFA_FFApp * pAdapterNative)31 CFWL_WidgetMgr::CFWL_WidgetMgr(CXFA_FFApp* pAdapterNative)
32     : m_dwCapability(0), m_pAdapter(pAdapterNative->GetWidgetMgr(this)) {
33   ASSERT(m_pAdapter);
34   m_mapWidgetItem[nullptr] = pdfium::MakeUnique<Item>();
35 #if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
36   m_rtScreen.Reset();
37 #endif
38 }
39 
~CFWL_WidgetMgr()40 CFWL_WidgetMgr::~CFWL_WidgetMgr() {}
41 
GetParentWidget(CFWL_Widget * pWidget) const42 CFWL_Widget* CFWL_WidgetMgr::GetParentWidget(CFWL_Widget* pWidget) const {
43   Item* pItem = GetWidgetMgrItem(pWidget);
44   return pItem && pItem->pParent ? pItem->pParent->pWidget : nullptr;
45 }
46 
GetOwnerWidget(CFWL_Widget * pWidget) const47 CFWL_Widget* CFWL_WidgetMgr::GetOwnerWidget(CFWL_Widget* pWidget) const {
48   Item* pItem = GetWidgetMgrItem(pWidget);
49   return pItem && pItem->pOwner ? pItem->pOwner->pWidget : nullptr;
50 }
51 
GetFirstSiblingWidget(CFWL_Widget * pWidget) const52 CFWL_Widget* CFWL_WidgetMgr::GetFirstSiblingWidget(CFWL_Widget* pWidget) const {
53   Item* pItem = GetWidgetMgrItem(pWidget);
54   if (!pItem)
55     return nullptr;
56 
57   pItem = pItem->pPrevious;
58   while (pItem && pItem->pPrevious)
59     pItem = pItem->pPrevious;
60   return pItem ? pItem->pWidget : nullptr;
61 }
62 
GetPriorSiblingWidget(CFWL_Widget * pWidget) const63 CFWL_Widget* CFWL_WidgetMgr::GetPriorSiblingWidget(CFWL_Widget* pWidget) const {
64   Item* pItem = GetWidgetMgrItem(pWidget);
65   return pItem && pItem->pPrevious ? pItem->pPrevious->pWidget : nullptr;
66 }
67 
GetNextSiblingWidget(CFWL_Widget * pWidget) const68 CFWL_Widget* CFWL_WidgetMgr::GetNextSiblingWidget(CFWL_Widget* pWidget) const {
69   Item* pItem = GetWidgetMgrItem(pWidget);
70   return pItem && pItem->pNext ? pItem->pNext->pWidget : nullptr;
71 }
72 
GetFirstChildWidget(CFWL_Widget * pWidget) const73 CFWL_Widget* CFWL_WidgetMgr::GetFirstChildWidget(CFWL_Widget* pWidget) const {
74   Item* pItem = GetWidgetMgrItem(pWidget);
75   return pItem && pItem->pChild ? pItem->pChild->pWidget : nullptr;
76 }
77 
GetLastChildWidget(CFWL_Widget * pWidget) const78 CFWL_Widget* CFWL_WidgetMgr::GetLastChildWidget(CFWL_Widget* pWidget) const {
79   Item* pItem = GetWidgetMgrItem(pWidget);
80   if (!pItem)
81     return nullptr;
82 
83   pItem = pItem->pChild;
84   while (pItem && pItem->pNext)
85     pItem = pItem->pNext;
86   return pItem ? pItem->pWidget : nullptr;
87 }
88 
GetSystemFormWidget(CFWL_Widget * pWidget) const89 CFWL_Widget* CFWL_WidgetMgr::GetSystemFormWidget(CFWL_Widget* pWidget) const {
90   Item* pItem = GetWidgetMgrItem(pWidget);
91   while (pItem) {
92     if (IsAbleNative(pItem->pWidget))
93       return pItem->pWidget;
94     pItem = pItem->pParent;
95   }
96   return nullptr;
97 }
98 
AppendWidget(CFWL_Widget * pWidget)99 void CFWL_WidgetMgr::AppendWidget(CFWL_Widget* pWidget) {
100   Item* pItem = GetWidgetMgrItem(pWidget);
101   if (!pItem)
102     return;
103   if (!pItem->pParent)
104     return;
105 
106   Item* pChild = pItem->pParent->pChild;
107   int32_t i = 0;
108   while (pChild) {
109     if (pChild == pItem) {
110       if (pChild->pPrevious)
111         pChild->pPrevious->pNext = pChild->pNext;
112       if (pChild->pNext)
113         pChild->pNext->pPrevious = pChild->pPrevious;
114       if (pItem->pParent->pChild == pItem)
115         pItem->pParent->pChild = pItem->pNext;
116 
117       pItem->pNext = nullptr;
118       pItem->pPrevious = nullptr;
119       break;
120     }
121     if (!pChild->pNext)
122       break;
123 
124     pChild = pChild->pNext;
125     ++i;
126   }
127 
128   pChild = pItem->pParent->pChild;
129   if (pChild) {
130     while (pChild->pNext)
131       pChild = pChild->pNext;
132 
133     pChild->pNext = pItem;
134     pItem->pPrevious = pChild;
135   } else {
136     pItem->pParent->pChild = pItem;
137     pItem->pPrevious = nullptr;
138   }
139   pItem->pNext = nullptr;
140 }
141 
RepaintWidget(CFWL_Widget * pWidget,const CFX_RectF & rect)142 void CFWL_WidgetMgr::RepaintWidget(CFWL_Widget* pWidget,
143                                    const CFX_RectF& rect) {
144   if (!m_pAdapter)
145     return;
146 
147   CFWL_Widget* pNative = pWidget;
148   CFX_RectF transformedRect = rect;
149   if (IsFormDisabled()) {
150     CFWL_Widget* pOuter = pWidget->GetOuter();
151     while (pOuter) {
152       CFX_RectF rtTemp = pNative->GetWidgetRect();
153       transformedRect.left += rtTemp.left;
154       transformedRect.top += rtTemp.top;
155       pNative = pOuter;
156       pOuter = pOuter->GetOuter();
157     }
158   } else if (!IsAbleNative(pWidget)) {
159     pNative = GetSystemFormWidget(pWidget);
160     if (!pNative)
161       return;
162 
163     CFX_PointF pos = pWidget->TransformTo(
164         pNative, CFX_PointF(transformedRect.left, transformedRect.top));
165     transformedRect.left = pos.x;
166     transformedRect.top = pos.y;
167   }
168   AddRedrawCounts(pNative);
169   m_pAdapter->RepaintWidget(pNative);
170 }
171 
InsertWidget(CFWL_Widget * pParent,CFWL_Widget * pChild)172 void CFWL_WidgetMgr::InsertWidget(CFWL_Widget* pParent, CFWL_Widget* pChild) {
173   Item* pParentItem = GetWidgetMgrItem(pParent);
174   if (!pParentItem) {
175     auto item = pdfium::MakeUnique<Item>(pParent);
176     pParentItem = item.get();
177     m_mapWidgetItem[pParent] = std::move(item);
178 
179     pParentItem->pParent = GetWidgetMgrItem(nullptr);
180     AppendWidget(pParent);
181   }
182 
183   Item* pItem = GetWidgetMgrItem(pChild);
184   if (!pItem) {
185     auto item = pdfium::MakeUnique<Item>(pChild);
186     pItem = item.get();
187     m_mapWidgetItem[pChild] = std::move(item);
188   }
189   if (pItem->pParent && pItem->pParent != pParentItem) {
190     if (pItem->pPrevious)
191       pItem->pPrevious->pNext = pItem->pNext;
192     if (pItem->pNext)
193       pItem->pNext->pPrevious = pItem->pPrevious;
194     if (pItem->pParent->pChild == pItem)
195       pItem->pParent->pChild = pItem->pNext;
196   }
197   pItem->pParent = pParentItem;
198   AppendWidget(pChild);
199 }
200 
RemoveWidget(CFWL_Widget * pWidget)201 void CFWL_WidgetMgr::RemoveWidget(CFWL_Widget* pWidget) {
202   Item* pItem = GetWidgetMgrItem(pWidget);
203   if (!pItem)
204     return;
205   if (pItem->pPrevious)
206     pItem->pPrevious->pNext = pItem->pNext;
207   if (pItem->pNext)
208     pItem->pNext->pPrevious = pItem->pPrevious;
209   if (pItem->pParent && pItem->pParent->pChild == pItem)
210     pItem->pParent->pChild = pItem->pNext;
211 
212   Item* pChild = pItem->pChild;
213   while (pChild) {
214     Item* pNext = pChild->pNext;
215     RemoveWidget(pChild->pWidget);
216     pChild = pNext;
217   }
218   m_mapWidgetItem.erase(pWidget);
219 }
220 
SetOwner(CFWL_Widget * pOwner,CFWL_Widget * pOwned)221 void CFWL_WidgetMgr::SetOwner(CFWL_Widget* pOwner, CFWL_Widget* pOwned) {
222   Item* pParentItem = GetWidgetMgrItem(pOwner);
223   if (!pParentItem) {
224     auto item = pdfium::MakeUnique<Item>(pOwner);
225     pParentItem = item.get();
226     m_mapWidgetItem[pOwner] = std::move(item);
227 
228     pParentItem->pParent = GetWidgetMgrItem(nullptr);
229     AppendWidget(pOwner);
230   }
231 
232   Item* pItem = GetWidgetMgrItem(pOwned);
233   if (!pItem) {
234     auto item = pdfium::MakeUnique<Item>(pOwned);
235     pItem = item.get();
236     m_mapWidgetItem[pOwned] = std::move(item);
237   }
238   pItem->pOwner = pParentItem;
239 }
SetParent(CFWL_Widget * pParent,CFWL_Widget * pChild)240 void CFWL_WidgetMgr::SetParent(CFWL_Widget* pParent, CFWL_Widget* pChild) {
241   Item* pParentItem = GetWidgetMgrItem(pParent);
242   Item* pItem = GetWidgetMgrItem(pChild);
243   if (!pItem)
244     return;
245   if (pItem->pParent && pItem->pParent != pParentItem) {
246     if (pItem->pPrevious)
247       pItem->pPrevious->pNext = pItem->pNext;
248     if (pItem->pNext)
249       pItem->pNext->pPrevious = pItem->pPrevious;
250     if (pItem->pParent->pChild == pItem)
251       pItem->pParent->pChild = pItem->pNext;
252 
253     pItem->pNext = nullptr;
254     pItem->pPrevious = nullptr;
255   }
256   pItem->pParent = pParentItem;
257   AppendWidget(pChild);
258 }
259 
GetWidgetAtPoint(CFWL_Widget * parent,const CFX_PointF & point) const260 CFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(CFWL_Widget* parent,
261                                               const CFX_PointF& point) const {
262   if (!parent)
263     return nullptr;
264 
265   CFX_PointF pos;
266   CFWL_Widget* child = GetLastChildWidget(parent);
267   while (child) {
268     if ((child->GetStates() & FWL_WGTSTATE_Invisible) == 0) {
269       CFX_Matrix m;
270       m.SetIdentity();
271 
272       CFX_Matrix matrixOnParent;
273       m.SetReverse(matrixOnParent);
274       pos = m.Transform(point);
275 
276       CFX_RectF bounds = child->GetWidgetRect();
277       if (bounds.Contains(pos)) {
278         pos -= bounds.TopLeft();
279         return GetWidgetAtPoint(child, pos);
280       }
281     }
282     child = GetPriorSiblingWidget(child);
283   }
284   return parent;
285 }
286 
NextTab(CFWL_Widget * parent,CFWL_Widget * focus,bool & bFind)287 CFWL_Widget* CFWL_WidgetMgr::NextTab(CFWL_Widget* parent,
288                                      CFWL_Widget* focus,
289                                      bool& bFind) {
290   CFWL_WidgetMgr* pMgr = parent->GetOwnerApp()->GetWidgetMgr();
291   CFWL_Widget* child = pMgr->GetFirstChildWidget(parent);
292   while (child) {
293     if (focus == child)
294       bFind = true;
295 
296     CFWL_Widget* bRet = NextTab(child, focus, bFind);
297     if (bRet)
298       return bRet;
299 
300     child = pMgr->GetNextSiblingWidget(child);
301   }
302   return nullptr;
303 }
304 
CountRadioButtonGroup(CFWL_Widget * pFirst) const305 int32_t CFWL_WidgetMgr::CountRadioButtonGroup(CFWL_Widget* pFirst) const {
306   int32_t iRet = 0;
307   CFWL_Widget* pChild = pFirst;
308   while (pChild) {
309     pChild = GetNextSiblingWidget(pChild);
310     ++iRet;
311   }
312   return iRet;
313 }
314 
GetRadioButtonGroupHeader(CFWL_Widget * pRadioButton) const315 CFWL_Widget* CFWL_WidgetMgr::GetRadioButtonGroupHeader(
316     CFWL_Widget* pRadioButton) const {
317   CFWL_Widget* pNext = pRadioButton;
318   if (pNext && (pNext->GetStyles() & FWL_WGTSTYLE_Group))
319     return pNext;
320   return nullptr;
321 }
322 
GetSameGroupRadioButton(CFWL_Widget * pRadioButton) const323 std::vector<CFWL_Widget*> CFWL_WidgetMgr::GetSameGroupRadioButton(
324     CFWL_Widget* pRadioButton) const {
325   CFWL_Widget* pFirst = GetFirstSiblingWidget(pRadioButton);
326   if (!pFirst)
327     pFirst = pRadioButton;
328 
329   if (CountRadioButtonGroup(pFirst) < 2)
330     return std::vector<CFWL_Widget*>();
331 
332   std::vector<CFWL_Widget*> group;
333   group.push_back(GetRadioButtonGroupHeader(pRadioButton));
334   return group;
335 }
336 
GetDefaultButton(CFWL_Widget * pParent) const337 CFWL_Widget* CFWL_WidgetMgr::GetDefaultButton(CFWL_Widget* pParent) const {
338   if ((pParent->GetClassID() == FWL_Type::PushButton) &&
339       (pParent->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) {
340     return pParent;
341   }
342 
343   CFWL_Widget* child =
344       pParent->GetOwnerApp()->GetWidgetMgr()->GetFirstChildWidget(pParent);
345   while (child) {
346     if ((child->GetClassID() == FWL_Type::PushButton) &&
347         (child->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) {
348       return child;
349     }
350     if (CFWL_Widget* find = GetDefaultButton(child))
351       return find;
352 
353     child = child->GetOwnerApp()->GetWidgetMgr()->GetNextSiblingWidget(child);
354   }
355   return nullptr;
356 }
357 
AddRedrawCounts(CFWL_Widget * pWidget)358 void CFWL_WidgetMgr::AddRedrawCounts(CFWL_Widget* pWidget) {
359   GetWidgetMgrItem(pWidget)->iRedrawCounter++;
360 }
361 
ResetRedrawCounts(CFWL_Widget * pWidget)362 void CFWL_WidgetMgr::ResetRedrawCounts(CFWL_Widget* pWidget) {
363   GetWidgetMgrItem(pWidget)->iRedrawCounter = 0;
364 }
365 
GetWidgetMgrItem(CFWL_Widget * pWidget) const366 CFWL_WidgetMgr::Item* CFWL_WidgetMgr::GetWidgetMgrItem(
367     CFWL_Widget* pWidget) const {
368   auto it = m_mapWidgetItem.find(pWidget);
369   return it != m_mapWidgetItem.end() ? static_cast<Item*>(it->second.get())
370                                      : nullptr;
371 }
372 
IsAbleNative(CFWL_Widget * pWidget) const373 bool CFWL_WidgetMgr::IsAbleNative(CFWL_Widget* pWidget) const {
374   if (!pWidget)
375     return false;
376   if (!pWidget->IsInstance(FWL_CLASS_Form))
377     return false;
378 
379   uint32_t dwStyles = pWidget->GetStyles();
380   return ((dwStyles & FWL_WGTSTYLE_WindowTypeMask) ==
381           FWL_WGTSTYLE_OverLapper) ||
382          (dwStyles & FWL_WGTSTYLE_Popup);
383 }
384 
GetAdapterPopupPos(CFWL_Widget * pWidget,FX_FLOAT fMinHeight,FX_FLOAT fMaxHeight,const CFX_RectF & rtAnchor,CFX_RectF & rtPopup) const385 void CFWL_WidgetMgr::GetAdapterPopupPos(CFWL_Widget* pWidget,
386                                         FX_FLOAT fMinHeight,
387                                         FX_FLOAT fMaxHeight,
388                                         const CFX_RectF& rtAnchor,
389                                         CFX_RectF& rtPopup) const {
390   m_pAdapter->GetPopupPos(pWidget, fMinHeight, fMaxHeight, rtAnchor, rtPopup);
391 }
392 
OnSetCapability(uint32_t dwCapability)393 void CFWL_WidgetMgr::OnSetCapability(uint32_t dwCapability) {
394   m_dwCapability = dwCapability;
395 }
396 
OnProcessMessageToForm(CFWL_Message * pMessage)397 void CFWL_WidgetMgr::OnProcessMessageToForm(CFWL_Message* pMessage) {
398   if (!pMessage)
399     return;
400   if (!pMessage->m_pDstTarget)
401     return;
402 
403   CFWL_Widget* pDstWidget = pMessage->m_pDstTarget;
404   const CFWL_App* pApp = pDstWidget->GetOwnerApp();
405   if (!pApp)
406     return;
407 
408   CFWL_NoteDriver* pNoteDriver =
409       static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
410   if (!pNoteDriver)
411     return;
412 
413   if (IsFormDisabled())
414     pNoteDriver->ProcessMessage(pMessage->Clone());
415   else
416     pNoteDriver->QueueMessage(pMessage->Clone());
417 
418 #if (_FX_OS_ == _FX_MACOSX_)
419   CFWL_NoteLoop* pTopLoop = pNoteDriver->GetTopLoop();
420   if (pTopLoop)
421     pNoteDriver->UnqueueMessageAndProcess(pTopLoop);
422 #endif
423 }
424 
OnDrawWidget(CFWL_Widget * pWidget,CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)425 void CFWL_WidgetMgr::OnDrawWidget(CFWL_Widget* pWidget,
426                                   CFX_Graphics* pGraphics,
427                                   const CFX_Matrix* pMatrix) {
428   if (!pWidget || !pGraphics)
429     return;
430 
431   CFX_RectF clipCopy(0, 0, pWidget->GetWidgetRect().Size());
432   CFX_RectF clipBounds;
433 
434 #if _FX_OS_ == _FX_MACOSX_
435   if (IsFormDisabled()) {
436 #endif  // _FX_OS_ == _FX_MACOSX_
437 
438     pWidget->GetDelegate()->OnDrawWidget(pGraphics, pMatrix);
439     clipBounds = pGraphics->GetClipRect();
440     clipCopy = clipBounds;
441 
442 #if _FX_OS_ == _FX_MACOSX_
443   } else {
444     clipBounds = CFX_RectF(pMatrix->a, pMatrix->b, pMatrix->c, pMatrix->d);
445     const_cast<CFX_Matrix*>(pMatrix)->SetIdentity();  // FIXME: const cast.
446     pWidget->GetDelegate()->OnDrawWidget(pGraphics, pMatrix);
447   }
448 #endif  // _FX_OS_ == _FX_MACOSX_
449 
450   if (!IsFormDisabled())
451     clipBounds.Intersect(pWidget->GetClientRect());
452   if (!clipBounds.IsEmpty())
453     DrawChild(pWidget, clipBounds, pGraphics, pMatrix);
454 
455   GetWidgetMgrItem(pWidget)->iRedrawCounter = 0;
456   ResetRedrawCounts(pWidget);
457 }
458 
DrawChild(CFWL_Widget * parent,const CFX_RectF & rtClip,CFX_Graphics * pGraphics,const CFX_Matrix * pMatrix)459 void CFWL_WidgetMgr::DrawChild(CFWL_Widget* parent,
460                                const CFX_RectF& rtClip,
461                                CFX_Graphics* pGraphics,
462                                const CFX_Matrix* pMatrix) {
463   if (!parent)
464     return;
465 
466   bool bFormDisable = IsFormDisabled();
467   CFWL_Widget* pNextChild = GetFirstChildWidget(parent);
468   while (pNextChild) {
469     CFWL_Widget* child = pNextChild;
470     pNextChild = GetNextSiblingWidget(child);
471     if (child->GetStates() & FWL_WGTSTATE_Invisible)
472       continue;
473 
474     CFX_RectF rtWidget = child->GetWidgetRect();
475     if (rtWidget.IsEmpty())
476       continue;
477 
478     CFX_Matrix widgetMatrix;
479     CFX_RectF clipBounds(rtWidget);
480     if (!bFormDisable)
481       widgetMatrix = child->GetMatrix();
482     if (pMatrix)
483       widgetMatrix.Concat(*pMatrix);
484 
485     if (!bFormDisable) {
486       CFX_PointF pos = widgetMatrix.Transform(clipBounds.TopLeft());
487       clipBounds.left = pos.x;
488       clipBounds.top = pos.y;
489       clipBounds.Intersect(rtClip);
490       if (clipBounds.IsEmpty())
491         continue;
492 
493       pGraphics->SaveGraphState();
494       pGraphics->SetClipRect(clipBounds);
495     }
496     widgetMatrix.Translate(rtWidget.left, rtWidget.top, true);
497 
498     if (IFWL_WidgetDelegate* pDelegate = child->GetDelegate()) {
499       if (IsFormDisabled() || IsNeedRepaint(child, &widgetMatrix, rtClip))
500         pDelegate->OnDrawWidget(pGraphics, &widgetMatrix);
501     }
502     if (!bFormDisable)
503       pGraphics->RestoreGraphState();
504 
505     DrawChild(child, clipBounds, pGraphics,
506               bFormDisable ? &widgetMatrix : pMatrix);
507     child = GetNextSiblingWidget(child);
508   }
509 }
510 
IsNeedRepaint(CFWL_Widget * pWidget,CFX_Matrix * pMatrix,const CFX_RectF & rtDirty)511 bool CFWL_WidgetMgr::IsNeedRepaint(CFWL_Widget* pWidget,
512                                    CFX_Matrix* pMatrix,
513                                    const CFX_RectF& rtDirty) {
514   Item* pItem = GetWidgetMgrItem(pWidget);
515   if (pItem && pItem->iRedrawCounter > 0) {
516     pItem->iRedrawCounter = 0;
517     return true;
518   }
519 
520   CFX_RectF rtWidget(0, 0, pWidget->GetWidgetRect().Size());
521   pMatrix->TransformRect(rtWidget);
522   if (!rtWidget.IntersectWith(rtDirty))
523     return false;
524 
525   CFWL_Widget* pChild =
526       pWidget->GetOwnerApp()->GetWidgetMgr()->GetFirstChildWidget(pWidget);
527   if (!pChild)
528     return true;
529 
530   CFX_RectF rtChilds;
531   bool bChildIntersectWithDirty = false;
532   bool bOrginPtIntersectWidthChild = false;
533   bool bOrginPtIntersectWidthDirty = rtDirty.Contains(rtWidget.TopLeft());
534   static FWL_NEEDREPAINTHITDATA hitPoint[kNeedRepaintHitPoints];
535   FXSYS_memset(hitPoint, 0, sizeof(hitPoint));
536   FX_FLOAT fxPiece = rtWidget.width / kNeedRepaintHitPiece;
537   FX_FLOAT fyPiece = rtWidget.height / kNeedRepaintHitPiece;
538   hitPoint[2].hitPoint.x = hitPoint[6].hitPoint.x = rtWidget.left;
539   hitPoint[0].hitPoint.x = hitPoint[3].hitPoint.x = hitPoint[7].hitPoint.x =
540       hitPoint[10].hitPoint.x = fxPiece + rtWidget.left;
541   hitPoint[1].hitPoint.x = hitPoint[4].hitPoint.x = hitPoint[8].hitPoint.x =
542       hitPoint[11].hitPoint.x = fxPiece * 2 + rtWidget.left;
543   hitPoint[5].hitPoint.x = hitPoint[9].hitPoint.x =
544       rtWidget.width + rtWidget.left;
545   hitPoint[0].hitPoint.y = hitPoint[1].hitPoint.y = rtWidget.top;
546   hitPoint[2].hitPoint.y = hitPoint[3].hitPoint.y = hitPoint[4].hitPoint.y =
547       hitPoint[5].hitPoint.y = fyPiece + rtWidget.top;
548   hitPoint[6].hitPoint.y = hitPoint[7].hitPoint.y = hitPoint[8].hitPoint.y =
549       hitPoint[9].hitPoint.y = fyPiece * 2 + rtWidget.top;
550   hitPoint[10].hitPoint.y = hitPoint[11].hitPoint.y =
551       rtWidget.height + rtWidget.top;
552   do {
553     CFX_RectF rect = pChild->GetWidgetRect();
554     CFX_RectF r(rect.left + rtWidget.left, rect.top + rtWidget.top, rect.width,
555                 rect.height);
556     if (r.IsEmpty())
557       continue;
558     if (r.Contains(rtDirty))
559       return false;
560     if (!bChildIntersectWithDirty && r.IntersectWith(rtDirty))
561       bChildIntersectWithDirty = true;
562     if (bOrginPtIntersectWidthDirty && !bOrginPtIntersectWidthChild)
563       bOrginPtIntersectWidthChild = rect.Contains(CFX_PointF(0, 0));
564 
565     if (rtChilds.IsEmpty())
566       rtChilds = rect;
567     else if (!(pChild->GetStates() & FWL_WGTSTATE_Invisible))
568       rtChilds.Union(rect);
569 
570     for (int32_t i = 0; i < kNeedRepaintHitPoints; i++) {
571       if (hitPoint[i].bNotContainByDirty || hitPoint[i].bNotNeedRepaint)
572         continue;
573       if (!rtDirty.Contains(hitPoint[i].hitPoint)) {
574         hitPoint[i].bNotContainByDirty = true;
575         continue;
576       }
577       if (r.Contains(hitPoint[i].hitPoint))
578         hitPoint[i].bNotNeedRepaint = true;
579     }
580     pChild =
581         pChild->GetOwnerApp()->GetWidgetMgr()->GetNextSiblingWidget(pChild);
582   } while (pChild);
583 
584   if (!bChildIntersectWithDirty)
585     return true;
586   if (bOrginPtIntersectWidthDirty && !bOrginPtIntersectWidthChild)
587     return true;
588   if (rtChilds.IsEmpty())
589     return true;
590 
591   int32_t repaintPoint = kNeedRepaintHitPoints;
592   for (int32_t i = 0; i < kNeedRepaintHitPoints; i++) {
593     if (hitPoint[i].bNotNeedRepaint)
594       repaintPoint--;
595   }
596   if (repaintPoint > 0)
597     return true;
598 
599   pMatrix->TransformRect(rtChilds);
600   if (rtChilds.Contains(rtDirty) || rtChilds.Contains(rtWidget))
601     return false;
602   return true;
603 }
604 
Item()605 CFWL_WidgetMgr::Item::Item() : CFWL_WidgetMgr::Item(nullptr) {}
606 
Item(CFWL_Widget * widget)607 CFWL_WidgetMgr::Item::Item(CFWL_Widget* widget)
608     : pParent(nullptr),
609       pOwner(nullptr),
610       pChild(nullptr),
611       pPrevious(nullptr),
612       pNext(nullptr),
613       pWidget(widget),
614       iRedrawCounter(0)
615 #if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_)
616       ,
617       bOutsideChanged(false)
618 #endif
619 {
620 }
621 
~Item()622 CFWL_WidgetMgr::Item::~Item() {}
623