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(¶m); 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(¶m); 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