Home | History | Annotate | Download | only in fwl
      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 
     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 
     40 CFWL_WidgetMgr::~CFWL_WidgetMgr() {}
     41 
     42 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 
     47 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 
     52 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 
     63 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 
     68 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 
     73 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 
     78 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 
     89 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 
     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 
    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 
    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 
    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 
    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 }
    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 
    260 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 
    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 
    305 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 
    315 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 
    323 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 
    337 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 
    358 void CFWL_WidgetMgr::AddRedrawCounts(CFWL_Widget* pWidget) {
    359   GetWidgetMgrItem(pWidget)->iRedrawCounter++;
    360 }
    361 
    362 void CFWL_WidgetMgr::ResetRedrawCounts(CFWL_Widget* pWidget) {
    363   GetWidgetMgrItem(pWidget)->iRedrawCounter = 0;
    364 }
    365 
    366 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 
    373 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 
    385 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 
    393 void CFWL_WidgetMgr::OnSetCapability(uint32_t dwCapability) {
    394   m_dwCapability = dwCapability;
    395 }
    396 
    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 
    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 
    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 
    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 
    605 CFWL_WidgetMgr::Item::Item() : CFWL_WidgetMgr::Item(nullptr) {}
    606 
    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 
    622 CFWL_WidgetMgr::Item::~Item() {}
    623