cfwl_widget.cpp revision 33357cad1fd1321a2b38d2963e2585f27ce980a2
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/tto/fde_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/xfa_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
38CFWL_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
61CFWL_Widget::~CFWL_Widget() {
62  NotifyDriver();
63  m_pWidgetMgr->RemoveWidget(this);
64}
65
66bool CFWL_Widget::IsInstance(const CFX_WideStringC& wsClass) const {
67  return false;
68}
69
70CFX_RectF CFWL_Widget::GetAutosizedWidgetRect() {
71  return CFX_RectF();
72}
73
74CFX_RectF CFWL_Widget::GetWidgetRect() {
75  return m_pProperties->m_rtWidget;
76}
77
78void CFWL_Widget::InflateWidgetRect(CFX_RectF& rect) {
79  if (HasBorder()) {
80    FX_FLOAT fBorder = GetBorderSize(true);
81    rect.Inflate(fBorder, fBorder);
82  }
83}
84
85void CFWL_Widget::SetWidgetRect(const CFX_RectF& rect) {
86  m_pProperties->m_rtWidget = rect;
87}
88
89CFX_RectF CFWL_Widget::GetClientRect() {
90  return GetEdgeRect();
91}
92
93void CFWL_Widget::SetParent(CFWL_Widget* pParent) {
94  m_pProperties->m_pParent = pParent;
95  m_pWidgetMgr->SetParent(pParent, this);
96}
97
98uint32_t CFWL_Widget::GetStyles() const {
99  return m_pProperties->m_dwStyles;
100}
101
102void CFWL_Widget::ModifyStyles(uint32_t dwStylesAdded,
103                               uint32_t dwStylesRemoved) {
104  m_pProperties->m_dwStyles =
105      (m_pProperties->m_dwStyles & ~dwStylesRemoved) | dwStylesAdded;
106}
107
108uint32_t CFWL_Widget::GetStylesEx() const {
109  return m_pProperties->m_dwStyleExes;
110}
111uint32_t CFWL_Widget::GetStates() const {
112  return m_pProperties->m_dwStates;
113}
114
115void CFWL_Widget::ModifyStylesEx(uint32_t dwStylesExAdded,
116                                 uint32_t dwStylesExRemoved) {
117  m_pProperties->m_dwStyleExes =
118      (m_pProperties->m_dwStyleExes & ~dwStylesExRemoved) | dwStylesExAdded;
119}
120
121static 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
132void 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
150void CFWL_Widget::RemoveStates(uint32_t dwStates) {
151  m_pProperties->m_dwStates &= ~dwStates;
152}
153
154FWL_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
162CFX_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  CFX_Matrix m;
201  m.SetReverse(pWidget->GetMatrix());
202  return m.Transform(ret) - pWidget->GetWidgetRect().TopLeft();
203}
204
205CFX_Matrix CFWL_Widget::GetMatrix() {
206  if (!m_pProperties)
207    return CFX_Matrix();
208
209  CFWL_Widget* parent = GetParent();
210  std::vector<CFWL_Widget*> parents;
211  while (parent) {
212    parents.push_back(parent);
213    parent = parent->GetParent();
214  }
215
216  CFX_Matrix matrix;
217  CFX_Matrix ctmOnParent;
218  CFX_RectF rect;
219  int32_t count = pdfium::CollectionSize<int32_t>(parents);
220  for (int32_t i = count - 2; i >= 0; i--) {
221    parent = parents[i];
222    if (parent->m_pProperties)
223      ctmOnParent.SetIdentity();
224    rect = parent->GetWidgetRect();
225    matrix.Concat(ctmOnParent, true);
226    matrix.Translate(rect.left, rect.top, true);
227  }
228  CFX_Matrix m;
229  m.SetIdentity();
230  matrix.Concat(m, true);
231  parents.clear();
232  return matrix;
233}
234
235IFWL_ThemeProvider* CFWL_Widget::GetThemeProvider() const {
236  return m_pProperties->m_pThemeProvider;
237}
238
239void CFWL_Widget::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
240  m_pProperties->m_pThemeProvider = pThemeProvider;
241}
242
243bool CFWL_Widget::IsEnabled() const {
244  return (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == 0;
245}
246
247bool CFWL_Widget::HasBorder() const {
248  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Border);
249}
250
251bool CFWL_Widget::IsVisible() const {
252  return (m_pProperties->m_dwStates & FWL_WGTSTATE_Invisible) == 0;
253}
254
255bool CFWL_Widget::IsOverLapper() const {
256  return (m_pProperties->m_dwStyles & FWL_WGTSTYLE_WindowTypeMask) ==
257         FWL_WGTSTYLE_OverLapper;
258}
259
260bool CFWL_Widget::IsPopup() const {
261  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Popup);
262}
263
264bool CFWL_Widget::IsChild() const {
265  return !!(m_pProperties->m_dwStyles & FWL_WGTSTYLE_Child);
266}
267
268CFX_RectF CFWL_Widget::GetEdgeRect() {
269  CFX_RectF rtEdge(0, 0, m_pProperties->m_rtWidget.width,
270                   m_pProperties->m_rtWidget.height);
271  if (HasBorder()) {
272    FX_FLOAT fCX = GetBorderSize(true);
273    FX_FLOAT fCY = GetBorderSize(false);
274    rtEdge.Deflate(fCX, fCY);
275  }
276  return rtEdge;
277}
278
279FX_FLOAT CFWL_Widget::GetBorderSize(bool bCX) {
280  IFWL_ThemeProvider* theme = GetAvailableTheme();
281  if (!theme)
282    return 0.0f;
283  return bCX ? theme->GetCXBorderSize() : theme->GetCYBorderSize();
284}
285
286CFX_RectF CFWL_Widget::GetRelativeRect() {
287  return CFX_RectF(0, 0, m_pProperties->m_rtWidget.width,
288                   m_pProperties->m_rtWidget.height);
289}
290
291IFWL_ThemeProvider* CFWL_Widget::GetAvailableTheme() {
292  if (m_pProperties->m_pThemeProvider)
293    return m_pProperties->m_pThemeProvider;
294
295  CFWL_Widget* pUp = this;
296  do {
297    pUp = (pUp->GetStyles() & FWL_WGTSTYLE_Popup)
298              ? m_pWidgetMgr->GetOwnerWidget(pUp)
299              : m_pWidgetMgr->GetParentWidget(pUp);
300    if (pUp) {
301      IFWL_ThemeProvider* pRet = pUp->GetThemeProvider();
302      if (pRet)
303        return pRet;
304    }
305  } while (pUp);
306  return nullptr;
307}
308
309CFWL_Widget* CFWL_Widget::GetRootOuter() {
310  CFWL_Widget* pRet = m_pOuter;
311  if (!pRet)
312    return nullptr;
313
314  while (CFWL_Widget* pOuter = pRet->GetOuter())
315    pRet = pOuter;
316  return pRet;
317}
318
319CFX_SizeF CFWL_Widget::CalcTextSize(const CFX_WideString& wsText,
320                                    IFWL_ThemeProvider* pTheme,
321                                    bool bMultiLine) {
322  if (!pTheme)
323    return CFX_SizeF();
324
325  CFWL_ThemeText calPart;
326  calPart.m_pWidget = this;
327  calPart.m_wsText = wsText;
328  calPart.m_dwTTOStyles =
329      bMultiLine ? FDE_TTOSTYLE_LineWrap : FDE_TTOSTYLE_SingleLine;
330  calPart.m_iTTOAlign = FDE_TTOALIGNMENT_TopLeft;
331  FX_FLOAT fWidth =
332      bMultiLine ? FWL_WGT_CalcMultiLineDefWidth : FWL_WGT_CalcWidth;
333  CFX_RectF rect(0, 0, fWidth, FWL_WGT_CalcHeight);
334  pTheme->CalcTextRect(&calPart, rect);
335  return CFX_SizeF(rect.width, rect.height);
336}
337
338void CFWL_Widget::CalcTextRect(const CFX_WideString& wsText,
339                               IFWL_ThemeProvider* pTheme,
340                               uint32_t dwTTOStyles,
341                               int32_t iTTOAlign,
342                               CFX_RectF& rect) {
343  CFWL_ThemeText calPart;
344  calPart.m_pWidget = this;
345  calPart.m_wsText = wsText;
346  calPart.m_dwTTOStyles = dwTTOStyles;
347  calPart.m_iTTOAlign = iTTOAlign;
348  pTheme->CalcTextRect(&calPart, rect);
349}
350
351void CFWL_Widget::SetFocus(bool bFocus) {
352  if (m_pWidgetMgr->IsFormDisabled())
353    return;
354
355  const CFWL_App* pApp = GetOwnerApp();
356  if (!pApp)
357    return;
358
359  CFWL_NoteDriver* pDriver =
360      static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
361  if (!pDriver)
362    return;
363
364  CFWL_Widget* curFocus = pDriver->GetFocus();
365  if (bFocus && curFocus != this)
366    pDriver->SetFocus(this);
367  else if (!bFocus && curFocus == this)
368    pDriver->SetFocus(nullptr);
369}
370
371void CFWL_Widget::SetGrab(bool bSet) {
372  const CFWL_App* pApp = GetOwnerApp();
373  if (!pApp)
374    return;
375
376  CFWL_NoteDriver* pDriver =
377      static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver());
378  pDriver->SetGrab(this, bSet);
379}
380
381void CFWL_Widget::GetPopupPos(FX_FLOAT fMinHeight,
382                              FX_FLOAT fMaxHeight,
383                              const CFX_RectF& rtAnchor,
384                              CFX_RectF& rtPopup) {
385  if (GetClassID() == FWL_Type::ComboBox) {
386    if (m_pWidgetMgr->IsFormDisabled()) {
387      m_pWidgetMgr->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor,
388                                       rtPopup);
389      return;
390    }
391    GetPopupPosComboBox(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
392    return;
393  }
394  if (GetClassID() == FWL_Type::DateTimePicker &&
395      m_pWidgetMgr->IsFormDisabled()) {
396    m_pWidgetMgr->GetAdapterPopupPos(this, fMinHeight, fMaxHeight, rtAnchor,
397                                     rtPopup);
398    return;
399  }
400  GetPopupPosGeneral(fMinHeight, fMaxHeight, rtAnchor, rtPopup);
401}
402
403bool CFWL_Widget::GetPopupPosMenu(FX_FLOAT fMinHeight,
404                                  FX_FLOAT fMaxHeight,
405                                  const CFX_RectF& rtAnchor,
406                                  CFX_RectF& rtPopup) {
407  if (GetStylesEx() & FWL_STYLEEXT_MNU_Vert) {
408    bool bLeft = m_pProperties->m_rtWidget.left < 0;
409    FX_FLOAT fRight = rtAnchor.right() + rtPopup.width;
410    CFX_PointF point = TransformTo(nullptr, CFX_PointF());
411    if (fRight + point.x > 0.0f || bLeft) {
412      rtPopup = CFX_RectF(rtAnchor.left - rtPopup.width, rtAnchor.top,
413                          rtPopup.width, rtPopup.height);
414    } else {
415      rtPopup = CFX_RectF(rtAnchor.right(), rtAnchor.top, rtPopup.width,
416                          rtPopup.height);
417    }
418    rtPopup.Offset(point.x, point.y);
419    return true;
420  }
421
422  FX_FLOAT fBottom = rtAnchor.bottom() + rtPopup.height;
423  CFX_PointF point = TransformTo(nullptr, point);
424  if (fBottom + point.y > 0.0f) {
425    rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.top - rtPopup.height,
426                        rtPopup.width, rtPopup.height);
427  } else {
428    rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.bottom(), rtPopup.width,
429                        rtPopup.height);
430  }
431  rtPopup.Offset(point.x, point.y);
432  return true;
433}
434
435bool CFWL_Widget::GetPopupPosComboBox(FX_FLOAT fMinHeight,
436                                      FX_FLOAT fMaxHeight,
437                                      const CFX_RectF& rtAnchor,
438                                      CFX_RectF& rtPopup) {
439  FX_FLOAT fPopHeight = rtPopup.height;
440  if (rtPopup.height > fMaxHeight)
441    fPopHeight = fMaxHeight;
442  else if (rtPopup.height < fMinHeight)
443    fPopHeight = fMinHeight;
444
445  FX_FLOAT fWidth = std::max(rtAnchor.width, rtPopup.width);
446  FX_FLOAT fBottom = rtAnchor.bottom() + fPopHeight;
447  CFX_PointF point = TransformTo(nullptr, CFX_PointF());
448  if (fBottom + point.y > 0.0f) {
449    rtPopup =
450        CFX_RectF(rtAnchor.left, rtAnchor.top - fPopHeight, fWidth, fPopHeight);
451  } else {
452    rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.bottom(), fWidth, fPopHeight);
453  }
454
455  rtPopup.Offset(point.x, point.y);
456  return true;
457}
458
459bool CFWL_Widget::GetPopupPosGeneral(FX_FLOAT fMinHeight,
460                                     FX_FLOAT fMaxHeight,
461                                     const CFX_RectF& rtAnchor,
462                                     CFX_RectF& rtPopup) {
463  CFX_PointF point = TransformTo(nullptr, CFX_PointF());
464  if (rtAnchor.bottom() + point.y > 0.0f) {
465    rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.top - rtPopup.height,
466                        rtPopup.width, rtPopup.height);
467  } else {
468    rtPopup = CFX_RectF(rtAnchor.left, rtAnchor.bottom(), rtPopup.width,
469                        rtPopup.height);
470  }
471  rtPopup.Offset(point.x, point.y);
472  return true;
473}
474
475void CFWL_Widget::RegisterEventTarget(CFWL_Widget* pEventSource) {
476  const CFWL_App* pApp = GetOwnerApp();
477  if (!pApp)
478    return;
479
480  CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
481  if (!pNoteDriver)
482    return;
483
484  pNoteDriver->RegisterEventTarget(this, pEventSource);
485}
486
487void CFWL_Widget::UnregisterEventTarget() {
488  const CFWL_App* pApp = GetOwnerApp();
489  if (!pApp)
490    return;
491
492  CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
493  if (!pNoteDriver)
494    return;
495
496  pNoteDriver->UnregisterEventTarget(this);
497}
498
499void CFWL_Widget::DispatchEvent(CFWL_Event* pEvent) {
500  if (m_pOuter) {
501    m_pOuter->GetDelegate()->OnProcessEvent(pEvent);
502    return;
503  }
504  const CFWL_App* pApp = GetOwnerApp();
505  if (!pApp)
506    return;
507
508  CFWL_NoteDriver* pNoteDriver = pApp->GetNoteDriver();
509  if (!pNoteDriver)
510    return;
511  pNoteDriver->SendEvent(pEvent);
512}
513
514void CFWL_Widget::Repaint() {
515  RepaintRect(CFX_RectF(0, 0, m_pProperties->m_rtWidget.width,
516                        m_pProperties->m_rtWidget.height));
517}
518
519void CFWL_Widget::RepaintRect(const CFX_RectF& pRect) {
520  m_pWidgetMgr->RepaintWidget(this, pRect);
521}
522
523void CFWL_Widget::DrawBackground(CFX_Graphics* pGraphics,
524                                 CFWL_Part iPartBk,
525                                 IFWL_ThemeProvider* pTheme,
526                                 const CFX_Matrix* pMatrix) {
527  CFWL_ThemeBackground param;
528  param.m_pWidget = this;
529  param.m_iPart = iPartBk;
530  param.m_pGraphics = pGraphics;
531  if (pMatrix)
532    param.m_matrix.Concat(*pMatrix, true);
533  param.m_rtPart = GetRelativeRect();
534  pTheme->DrawBackground(&param);
535}
536
537void CFWL_Widget::DrawBorder(CFX_Graphics* pGraphics,
538                             CFWL_Part iPartBorder,
539                             IFWL_ThemeProvider* pTheme,
540                             const CFX_Matrix* pMatrix) {
541  CFWL_ThemeBackground param;
542  param.m_pWidget = this;
543  param.m_iPart = iPartBorder;
544  param.m_pGraphics = pGraphics;
545  if (pMatrix)
546    param.m_matrix.Concat(*pMatrix, true);
547  param.m_rtPart = GetRelativeRect();
548  pTheme->DrawBackground(&param);
549}
550
551void 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
564CFX_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
584bool 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
594void 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
613void CFWL_Widget::OnProcessEvent(CFWL_Event* pEvent) {}
614
615void CFWL_Widget::OnDrawWidget(CFX_Graphics* pGraphics,
616                               const CFX_Matrix* pMatrix) {}
617