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_widget.h"
      8 
      9 #include <algorithm>
     10 #include <utility>
     11 #include <vector>
     12 
     13 #include "third_party/base/stl_util.h"
     14 #include "xfa/fde/cfde_textout.h"
     15 #include "xfa/fwl/cfwl_app.h"
     16 #include "xfa/fwl/cfwl_combobox.h"
     17 #include "xfa/fwl/cfwl_event.h"
     18 #include "xfa/fwl/cfwl_eventmouse.h"
     19 #include "xfa/fwl/cfwl_form.h"
     20 #include "xfa/fwl/cfwl_messagekey.h"
     21 #include "xfa/fwl/cfwl_messagekillfocus.h"
     22 #include "xfa/fwl/cfwl_messagemouse.h"
     23 #include "xfa/fwl/cfwl_messagemousewheel.h"
     24 #include "xfa/fwl/cfwl_messagesetfocus.h"
     25 #include "xfa/fwl/cfwl_notedriver.h"
     26 #include "xfa/fwl/cfwl_themebackground.h"
     27 #include "xfa/fwl/cfwl_themepart.h"
     28 #include "xfa/fwl/cfwl_themetext.h"
     29 #include "xfa/fwl/cfwl_widgetmgr.h"
     30 #include "xfa/fwl/ifwl_themeprovider.h"
     31 #include "xfa/fxfa/cxfa_ffapp.h"
     32 
     33 #define FWL_STYLEEXT_MNU_Vert (1L << 0)
     34 #define FWL_WGT_CalcHeight 2048
     35 #define FWL_WGT_CalcWidth 2048
     36 #define FWL_WGT_CalcMultiLineDefWidth 120.0f
     37 
     38 CFWL_Widget::CFWL_Widget(const CFWL_App* app,
     39                          std::unique_ptr<CFWL_WidgetProperties> properties,
     40                          CFWL_Widget* pOuter)
     41     : m_pOwnerApp(app),
     42       m_pWidgetMgr(app->GetWidgetMgr()),
     43       m_pProperties(std::move(properties)),
     44       m_pOuter(pOuter),
     45       m_iLock(0),
     46       m_pLayoutItem(nullptr),
     47       m_nEventKey(0),
     48       m_pDelegate(nullptr) {
     49   ASSERT(m_pWidgetMgr);
     50 
     51   CFWL_Widget* pParent = m_pProperties->m_pParent;
     52   m_pWidgetMgr->InsertWidget(pParent, this);
     53   if (IsChild())
     54     return;
     55 
     56   CFWL_Widget* pOwner = m_pProperties->m_pOwner;
     57   if (pOwner)
     58     m_pWidgetMgr->SetOwner(pOwner, this);
     59 }
     60 
     61 CFWL_Widget::~CFWL_Widget() {
     62   NotifyDriver();
     63   m_pWidgetMgr->RemoveWidget(this);
     64 }
     65 
     66 bool CFWL_Widget::IsInstance(const WideStringView& wsClass) const {
     67   return false;
     68 }
     69 
     70 CFX_RectF CFWL_Widget::GetAutosizedWidgetRect() {
     71   return CFX_RectF();
     72 }
     73 
     74 CFX_RectF CFWL_Widget::GetWidgetRect() {
     75   return m_pProperties->m_rtWidget;
     76 }
     77 
     78 void CFWL_Widget::InflateWidgetRect(CFX_RectF& rect) {
     79   if (HasBorder()) {
     80     float fBorder = GetBorderSize(true);
     81     rect.Inflate(fBorder, fBorder);
     82   }
     83 }
     84 
     85 void CFWL_Widget::SetWidgetRect(const CFX_RectF& rect) {
     86   m_pProperties->m_rtWidget = rect;
     87 }
     88 
     89 CFX_RectF CFWL_Widget::GetClientRect() {
     90   return GetEdgeRect();
     91 }
     92 
     93 void CFWL_Widget::SetParent(CFWL_Widget* pParent) {
     94   m_pProperties->m_pParent = pParent;
     95   m_pWidgetMgr->SetParent(pParent, this);
     96 }
     97 
     98 uint32_t CFWL_Widget::GetStyles() const {
     99   return m_pProperties->m_dwStyles;
    100 }
    101 
    102 void CFWL_Widget::ModifyStyles(uint32_t dwStylesAdded,
    103                                uint32_t dwStylesRemoved) {
    104   m_pProperties->m_dwStyles =
    105       (m_pProperties->m_dwStyles & ~dwStylesRemoved) | dwStylesAdded;
    106 }
    107 
    108 uint32_t CFWL_Widget::GetStylesEx() const {
    109   return m_pProperties->m_dwStyleExes;
    110 }
    111 uint32_t CFWL_Widget::GetStates() const {
    112   return m_pProperties->m_dwStates;
    113 }
    114 
    115 void CFWL_Widget::ModifyStylesEx(uint32_t dwStylesExAdded,
    116                                  uint32_t dwStylesExRemoved) {
    117   m_pProperties->m_dwStyleExes =
    118       (m_pProperties->m_dwStyleExes & ~dwStylesExRemoved) | dwStylesExAdded;
    119 }
    120 
    121 static void NotifyHideChildWidget(CFWL_WidgetMgr* widgetMgr,
    122                                   CFWL_Widget* widget,
    123                                   CFWL_NoteDriver* noteDriver) {
    124   CFWL_Widget* child = widgetMgr->GetFirstChildWidget(widget);
    125   while (child) {
    126     noteDriver->NotifyTargetHide(child);
    127     NotifyHideChildWidget(widgetMgr, child, noteDriver);
    128     child = widgetMgr->GetNextSiblingWidget(child);
    129   }
    130 }
    131 
    132 void CFWL_Widget::SetStates(uint32_t dwStates) {
    133   m_pProperties->m_dwStates |= dwStates;
    134   if (!(dwStates & FWL_WGTSTATE_Invisible))
    135     return;
    136 
    137   CFWL_NoteDriver* noteDriver =
    138       static_cast<CFWL_NoteDriver*>(GetOwnerApp()->GetNoteDriver());
    139   CFWL_WidgetMgr* widgetMgr = GetOwnerApp()->GetWidgetMgr();
    140   noteDriver->NotifyTargetHide(this);
    141   CFWL_Widget* child = widgetMgr->GetFirstChildWidget(this);
    142   while (child) {
    143     noteDriver->NotifyTargetHide(child);
    144     NotifyHideChildWidget(widgetMgr, child, noteDriver);
    145     child = widgetMgr->GetNextSiblingWidget(child);
    146   }
    147   return;
    148 }
    149 
    150 void CFWL_Widget::RemoveStates(uint32_t dwStates) {
    151   m_pProperties->m_dwStates &= ~dwStates;
    152 }
    153 
    154 FWL_WidgetHit CFWL_Widget::HitTest(const CFX_PointF& point) {
    155   if (GetClientRect().Contains(point))
    156     return FWL_WidgetHit::Client;
    157   if (HasBorder() && GetRelativeRect().Contains(point))
    158     return FWL_WidgetHit::Border;
    159   return FWL_WidgetHit::Unknown;
    160 }
    161 
    162 CFX_PointF CFWL_Widget::TransformTo(CFWL_Widget* pWidget,
    163                                     const CFX_PointF& point) {
    164   if (m_pWidgetMgr->IsFormDisabled()) {
    165     CFX_SizeF szOffset;
    166     if (IsParent(pWidget)) {
    167       szOffset = GetOffsetFromParent(pWidget);
    168     } else {
    169       szOffset = pWidget->GetOffsetFromParent(this);
    170       szOffset.width = -szOffset.width;
    171       szOffset.height = -szOffset.height;
    172     }
    173     return point + CFX_PointF(szOffset.width, szOffset.height);
    174   }
    175 
    176   CFX_PointF ret = point;
    177   CFWL_Widget* parent = GetParent();
    178   if (parent)
    179     ret = GetMatrix().Transform(ret + GetWidgetRect().TopLeft());
    180 
    181   CFWL_Widget* form1 = m_pWidgetMgr->GetSystemFormWidget(this);
    182   if (!form1)
    183     return ret;
    184 
    185   if (!pWidget)
    186     return ret + form1->GetWidgetRect().TopLeft();
    187 
    188   CFWL_Widget* form2 = m_pWidgetMgr->GetSystemFormWidget(pWidget);
    189   if (!form2)
    190     return ret;
    191   if (form1 != form2) {
    192     ret += form1->GetWidgetRect().TopLeft();
    193     ret -= form2->GetWidgetRect().TopLeft();
    194   }
    195 
    196   parent = pWidget->GetParent();
    197   if (!parent)
    198     return ret;
    199 
    200   return pWidget->GetMatrix().GetInverse().Transform(ret) -
    201          pWidget->GetWidgetRect().TopLeft();
    202 }
    203 
    204 CFX_Matrix CFWL_Widget::GetMatrix() {
    205   if (!m_pProperties)
    206     return CFX_Matrix();
    207 
    208   CFWL_Widget* parent = GetParent();
    209   std::vector<CFWL_Widget*> parents;
    210   while (parent) {
    211     parents.push_back(parent);
    212     parent = parent->GetParent();
    213   }
    214 
    215   CFX_Matrix matrix;
    216   CFX_Matrix ctmOnParent;
    217   CFX_RectF rect;
    218   int32_t count = pdfium::CollectionSize<int32_t>(parents);
    219   for (int32_t i = count - 2; i >= 0; i--) {
    220     parent = parents[i];
    221     if (parent->m_pProperties)
    222       ctmOnParent.SetIdentity();
    223     rect = parent->GetWidgetRect();
    224     matrix.Concat(ctmOnParent, true);
    225     matrix.Translate(rect.left, rect.top, true);
    226   }
    227   CFX_Matrix m;
    228   m.SetIdentity();
    229   matrix.Concat(m, true);
    230   parents.clear();
    231   return matrix;
    232 }
    233 
    234 IFWL_ThemeProvider* CFWL_Widget::GetThemeProvider() const {
    235   return m_pProperties->m_pThemeProvider;
    236 }
    237 
    238 void CFWL_Widget::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
    239   m_pProperties->m_pThemeProvider = pThemeProvider;
    240 }
    241 
    242 bool CFWL_Widget::IsEnabled() const {
    243   return (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == 0;
    244 }
    245 
    246 bool CFWL_Widget::HasBorder() const {
    247   return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border);
    248 }
    249 
    250 bool CFWL_Widget::IsVisible() const {
    251   return (m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) == 0;
    252 }
    253 
    254 bool CFWL_Widget::IsOverLapper() const {
    255   return (m_pProperties->m_dwStyles & FWL_WGTSTYLE_WindowTypeMask) ==
    256          FWL_WGTSTYLE_OverLapper;
    257 }
    258 
    259 bool CFWL_Widget::IsPopup() const {
    260   return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Popup);
    261 }
    262 
    263 bool CFWL_Widget::IsChild() const {
    264   return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Child);
    265 }
    266 
    267 CFX_RectF CFWL_Widget::GetEdgeRect() {
    268   CFX_RectF rtEdge(0, 0, m_pProperties->m_rtWidget.width,
    269                    m_pProperties->m_rtWidget.height);
    270   if (HasBorder()) {
    271     float fCX = GetBorderSize(true);
    272     float fCY = GetBorderSize(false);
    273     rtEdge.Deflate(fCX, fCY);
    274   }
    275   return rtEdge;
    276 }
    277 
    278 float CFWL_Widget::GetBorderSize(bool bCX) {
    279   IFWL_ThemeProvider* theme = GetAvailableTheme();
    280   if (!theme)
    281     return 0.0f;
    282   return bCX ? theme->GetCXBorderSize() : theme->GetCYBorderSize();
    283 }
    284 
    285 CFX_RectF CFWL_Widget::GetRelativeRect() {
    286   return CFX_RectF(0, 0, m_pProperties->m_rtWidget.width,
    287                    m_pProperties->m_rtWidget.height);
    288 }
    289 
    290 IFWL_ThemeProvider* CFWL_Widget::GetAvailableTheme() {
    291   if (m_pProperties->m_pThemeProvider)
    292     return m_pProperties->m_pThemeProvider;
    293 
    294   CFWL_Widget* pUp = this;
    295   do {
    296     pUp = (pUp->GetStyles() & FWL_WGTSTYLE_Popup)
    297               ? m_pWidgetMgr->GetOwnerWidget(pUp)
    298               : m_pWidgetMgr->GetParentWidget(pUp);
    299     if (pUp) {
    300       IFWL_ThemeProvider* pRet = pUp->GetThemeProvider();
    301       if (pRet)
    302         return pRet;
    303     }
    304   } while (pUp);
    305   return nullptr;
    306 }
    307 
    308 CFWL_Widget* CFWL_Widget::GetRootOuter() {
    309   CFWL_Widget* pRet = m_pOuter;
    310   if (!pRet)
    311     return nullptr;
    312 
    313   while (CFWL_Widget* pOuter = pRet->GetOuter())
    314     pRet = pOuter;
    315   return pRet;
    316 }
    317 
    318 CFX_SizeF CFWL_Widget::CalcTextSize(const WideString& wsText,
    319                                     IFWL_ThemeProvider* pTheme,
    320                                     bool bMultiLine) {
    321   if (!pTheme)
    322     return CFX_SizeF();
    323 
    324   CFWL_ThemeText calPart;
    325   calPart.m_pWidget = this;
    326   calPart.m_wsText = wsText;
    327   if (bMultiLine)
    328     calPart.m_dwTTOStyles.line_wrap_ = true;
    329   else
    330     calPart.m_dwTTOStyles.single_line_ = true;
    331 
    332   calPart.m_iTTOAlign = FDE_TextAlignment::kTopLeft;
    333   float fWidth = bMultiLine ? FWL_WGT_CalcMultiLineDefWidth : FWL_WGT_CalcWidth;
    334   CFX_RectF rect(0, 0, fWidth, FWL_WGT_CalcHeight);
    335   pTheme->CalcTextRect(&calPart, rect);
    336   return CFX_SizeF(rect.width, rect.height);
    337 }
    338 
    339 void CFWL_Widget::CalcTextRect(const WideString& wsText,
    340                                IFWL_ThemeProvider* pTheme,
    341                                const FDE_TextStyle& dwTTOStyles,
    342                                FDE_TextAlignment iTTOAlign,
    343                                CFX_RectF& rect) {
    344   CFWL_ThemeText calPart;
    345   calPart.m_pWidget = this;
    346   calPart.m_wsText = wsText;
    347   calPart.m_dwTTOStyles = dwTTOStyles;
    348   calPart.m_iTTOAlign = iTTOAlign;
    349   pTheme->CalcTextRect(&calPart, rect);
    350 }
    351 
    352 void CFWL_Widget::SetFocus(bool bFocus) {
    353   if (m_pWidgetMgr->IsFormDisabled())
    354     return;
    355 
    356   const CFWL_App* pApp = GetOwnerApp();
    357   if (!pApp)
    358     return;
    359 
    360   CFWL_NoteDriver* pDriver =
    361       static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
    362   if (!pDriver)
    363     return;
    364 
    365   CFWL_Widget* curFocus = pDriver->GetFocus();
    366   if (bFocus && curFocus != this)
    367     pDriver->SetFocus(this);
    368   else if (!bFocus && curFocus == this)
    369     pDriver->SetFocus(nullptr);
    370 }
    371 
    372 void CFWL_Widget::SetGrab(bool bSet) {
    373   const CFWL_App* pApp = GetOwnerApp();
    374   if (!pApp)
    375     return;
    376 
    377   CFWL_NoteDriver* pDriver =
    378       static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
    379   pDriver->SetGrab(this, bSet);
    380 }
    381 
    382 void CFWL_Widget::GetPopupPos(float fMinHeight,
    383                               float fMaxHeight,
    384                               const CFX_RectF& rtAnchor,
    385                               CFX_RectF& rtPopup) {
    386   if (GetClassID() == FWL_Type::ComboBox) {
    387     if (m_pWidgetMgr->IsFormDisabled()) {
    388       m_pWidgetMgr->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor,
    389                                        rtPopup);
    390       return;
    391     }
    392     GetPopupPosComboBox(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
    393     return;
    394   }
    395   if (GetClassID() == FWL_Type::DateTimePicker &&
    396       m_pWidgetMgr->IsFormDisabled()) {
    397     m_pWidgetMgr->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor,
    398                                      rtPopup);
    399     return;
    400   }
    401   GetPopupPosGeneral(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
    402 }
    403 
    404 bool CFWL_Widget::GetPopupPosMenu(float fMinHeight,
    405                                   float fMaxHeight,
    406                                   const CFX_RectF& rtAnchor,
    407                                   CFX_RectF& rtPopup) {
    408   if (GetStylesEx() & FWL_STYLEEXT_MNU_Vert) {
    409     bool bLeft = m_pProperties->m_rtWidget.left < 0;
    410     float fRight = rtAnchor.right() + rtPopup.width;
    411     CFX_PointF point = TransformTo(nullptr, CFX_PointF());
    412     if (fRight + point.x > 0.0f || bLeft) {
    413       rtPopup = CFX_RectF(rtAnchor.left - rtPopup.width, rtAnchor.top,
    414                           rtPopup.width, rtPopup.height);
    415     } else {
    416       rtPopup = CFX_RectF(rtAnchor.right(), rtAnchor.top, rtPopup.width,
    417                           rtPopup.height);
    418     }
    419     rtPopup.Offset(point.x, point.y);
    420     return true;
    421   }
    422 
    423   float fBottom = rtAnchor.bottom() + rtPopup.height;
    424   CFX_PointF point = TransformTo(nullptr, point);
    425   if (fBottom + point.y > 0.0f) {
    426     rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.top - rtPopup.height,
    427                         rtPopup.width, rtPopup.height);
    428   } else {
    429     rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.bottom(), rtPopup.width,
    430                         rtPopup.height);
    431   }
    432   rtPopup.Offset(point.x, point.y);
    433   return true;
    434 }
    435 
    436 bool CFWL_Widget::GetPopupPosComboBox(float fMinHeight,
    437                                       float fMaxHeight,
    438                                       const CFX_RectF& rtAnchor,
    439                                       CFX_RectF& rtPopup) {
    440   float fPopHeight = rtPopup.height;
    441   if (rtPopup.height > fMaxHeight)
    442     fPopHeight = fMaxHeight;
    443   else if (rtPopup.height < fMinHeight)
    444     fPopHeight = fMinHeight;
    445 
    446   float fWidth = std::max(rtAnchor.width, rtPopup.width);
    447   float fBottom = rtAnchor.bottom() + fPopHeight;
    448   CFX_PointF point = TransformTo(nullptr, CFX_PointF());
    449   if (fBottom + point.y > 0.0f) {
    450     rtPopup =
    451         CFX_RectF(rtAnchor.left, rtAnchor.top - fPopHeight, fWidth, fPopHeight);
    452   } else {
    453     rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.bottom(), fWidth, fPopHeight);
    454   }
    455 
    456   rtPopup.Offset(point.x, point.y);
    457   return true;
    458 }
    459 
    460 bool CFWL_Widget::GetPopupPosGeneral(float fMinHeight,
    461                                      float fMaxHeight,
    462                                      const CFX_RectF& rtAnchor,
    463                                      CFX_RectF& rtPopup) {
    464   CFX_PointF point = TransformTo(nullptr, CFX_PointF());
    465   if (rtAnchor.bottom() + point.y > 0.0f) {
    466     rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.top - rtPopup.height,
    467                         rtPopup.width, rtPopup.height);
    468   } else {
    469     rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.bottom(), rtPopup.width,
    470                         rtPopup.height);
    471   }
    472   rtPopup.Offset(point.x, point.y);
    473   return true;
    474 }
    475 
    476 void CFWL_Widget::RegisterEventTarget(CFWL_Widget* pEventSource) {
    477   const CFWL_App* pApp = GetOwnerApp();
    478   if (!pApp)
    479     return;
    480 
    481   CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
    482   if (!pNoteDriver)
    483     return;
    484 
    485   pNoteDriver->RegisterEventTarget(this, pEventSource);
    486 }
    487 
    488 void CFWL_Widget::UnregisterEventTarget() {
    489   const CFWL_App* pApp = GetOwnerApp();
    490   if (!pApp)
    491     return;
    492 
    493   CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
    494   if (!pNoteDriver)
    495     return;
    496 
    497   pNoteDriver->UnregisterEventTarget(this);
    498 }
    499 
    500 void CFWL_Widget::DispatchEvent(CFWL_Event* pEvent) {
    501   if (m_pOuter) {
    502     m_pOuter->GetDelegate()->OnProcessEvent(pEvent);
    503     return;
    504   }
    505   const CFWL_App* pApp = GetOwnerApp();
    506   if (!pApp)
    507     return;
    508 
    509   CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
    510   if (!pNoteDriver)
    511     return;
    512   pNoteDriver->SendEvent(pEvent);
    513 }
    514 
    515 void CFWL_Widget::Repaint() {
    516   RepaintRect(CFX_RectF(0, 0, m_pProperties->m_rtWidget.width,
    517                         m_pProperties->m_rtWidget.height));
    518 }
    519 
    520 void CFWL_Widget::RepaintRect(const CFX_RectF& pRect) {
    521   m_pWidgetMgr->RepaintWidget(this, pRect);
    522 }
    523 
    524 void CFWL_Widget::DrawBackground(CXFA_Graphics* pGraphics,
    525                                  CFWL_Part iPartBk,
    526                                  IFWL_ThemeProvider* pTheme,
    527                                  const CFX_Matrix* pMatrix) {
    528   CFWL_ThemeBackground param;
    529   param.m_pWidget = this;
    530   param.m_iPart = iPartBk;
    531   param.m_pGraphics = pGraphics;
    532   if (pMatrix)
    533     param.m_matrix.Concat(*pMatrix, true);
    534   param.m_rtPart = GetRelativeRect();
    535   pTheme->DrawBackground(&param);
    536 }
    537 
    538 void CFWL_Widget::DrawBorder(CXFA_Graphics* pGraphics,
    539                              CFWL_Part iPartBorder,
    540                              IFWL_ThemeProvider* pTheme,
    541                              const CFX_Matrix& matrix) {
    542   CFWL_ThemeBackground param;
    543   param.m_pWidget = this;
    544   param.m_iPart = iPartBorder;
    545   param.m_pGraphics = pGraphics;
    546   param.m_matrix.Concat(matrix, true);
    547   param.m_rtPart = GetRelativeRect();
    548   pTheme->DrawBackground(&param);
    549 }
    550 
    551 void CFWL_Widget::NotifyDriver() {
    552   const CFWL_App* pApp = GetOwnerApp();
    553   if (!pApp)
    554     return;
    555 
    556   CFWL_NoteDriver* pDriver =
    557       static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
    558   if (!pDriver)
    559     return;
    560 
    561   pDriver->NotifyTargetDestroy(this);
    562 }
    563 
    564 CFX_SizeF CFWL_Widget::GetOffsetFromParent(CFWL_Widget* pParent) {
    565   if (pParent == this)
    566     return CFX_SizeF();
    567 
    568   CFWL_WidgetMgr* pWidgetMgr = GetOwnerApp()->GetWidgetMgr();
    569   if (!pWidgetMgr)
    570     return CFX_SizeF();
    571 
    572   CFX_SizeF szRet(m_pProperties->m_rtWidget.left,
    573                   m_pProperties->m_rtWidget.top);
    574 
    575   CFWL_Widget* pDstWidget = GetParent();
    576   while (pDstWidget && pDstWidget != pParent) {
    577     CFX_RectF rtDst = pDstWidget->GetWidgetRect();
    578     szRet += CFX_SizeF(rtDst.left, rtDst.top);
    579     pDstWidget = pWidgetMgr->GetParentWidget(pDstWidget);
    580   }
    581   return szRet;
    582 }
    583 
    584 bool CFWL_Widget::IsParent(CFWL_Widget* pParent) {
    585   CFWL_Widget* pUpWidget = GetParent();
    586   while (pUpWidget) {
    587     if (pUpWidget == pParent)
    588       return true;
    589     pUpWidget = pUpWidget->GetParent();
    590   }
    591   return false;
    592 }
    593 
    594 void CFWL_Widget::OnProcessMessage(CFWL_Message* pMessage) {
    595   if (!pMessage->m_pDstTarget)
    596     return;
    597 
    598   CFWL_Widget* pWidget = pMessage->m_pDstTarget;
    599   switch (pMessage->GetType()) {
    600     case CFWL_Message::Type::Mouse: {
    601       CFWL_MessageMouse* pMsgMouse = static_cast<CFWL_MessageMouse*>(pMessage);
    602 
    603       CFWL_EventMouse evt(pWidget, pWidget);
    604       evt.m_dwCmd = pMsgMouse->m_dwCmd;
    605       pWidget->DispatchEvent(&evt);
    606       break;
    607     }
    608     default:
    609       break;
    610   }
    611 }
    612 
    613 void CFWL_Widget::OnProcessEvent(CFWL_Event* pEvent) {}
    614 
    615 void CFWL_Widget::OnDrawWidget(CXFA_Graphics* pGraphics,
    616                                const CFX_Matrix& matrix) {}
    617