1 // Copyright 2014 The PDFium Authors
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/fxfa/cxfa_ffwidgethandler.h"
8
9 #include "fxjs/xfa/cjx_object.h"
10 #include "xfa/fxfa/cxfa_ffdoc.h"
11 #include "xfa/fxfa/cxfa_ffdocview.h"
12 #include "xfa/fxfa/cxfa_fffield.h"
13 #include "xfa/fxfa/cxfa_ffwidget.h"
14 #include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
15 #include "xfa/fxfa/layout/cxfa_layoutprocessor.h"
16 #include "xfa/fxfa/parser/cxfa_calculate.h"
17 #include "xfa/fxfa/parser/cxfa_checkbutton.h"
18 #include "xfa/fxfa/parser/cxfa_measurement.h"
19 #include "xfa/fxfa/parser/cxfa_node.h"
20 #include "xfa/fxfa/parser/cxfa_ui.h"
21 #include "xfa/fxfa/parser/cxfa_validate.h"
22
CXFA_FFWidgetHandler(CXFA_FFDocView * pDocView)23 CXFA_FFWidgetHandler::CXFA_FFWidgetHandler(CXFA_FFDocView* pDocView)
24 : m_pDocView(pDocView) {}
25
26 CXFA_FFWidgetHandler::~CXFA_FFWidgetHandler() = default;
27
Trace(cppgc::Visitor * visitor) const28 void CXFA_FFWidgetHandler::Trace(cppgc::Visitor* visitor) const {
29 visitor->Trace(m_pDocView);
30 }
31
OnMouseEnter(CXFA_FFWidget * hWidget)32 bool CXFA_FFWidgetHandler::OnMouseEnter(CXFA_FFWidget* hWidget) {
33 CXFA_FFDocView::UpdateScope scope(m_pDocView);
34 return hWidget->OnMouseEnter();
35 }
36
OnMouseExit(CXFA_FFWidget * hWidget)37 bool CXFA_FFWidgetHandler::OnMouseExit(CXFA_FFWidget* hWidget) {
38 CXFA_FFDocView::UpdateScope scope(m_pDocView);
39 return hWidget->OnMouseExit();
40 }
41
OnLButtonDown(CXFA_FFWidget * hWidget,Mask<XFA_FWL_KeyFlag> dwFlags,const CFX_PointF & point)42 bool CXFA_FFWidgetHandler::OnLButtonDown(CXFA_FFWidget* hWidget,
43 Mask<XFA_FWL_KeyFlag> dwFlags,
44 const CFX_PointF& point) {
45 CXFA_FFDocView::UpdateScope scope(m_pDocView);
46 if (!hWidget->AcceptsFocusOnButtonDown(
47 dwFlags, hWidget->Rotate2Normal(point),
48 CFWL_MessageMouse::MouseCommand::kLeftButtonDown)) {
49 return false;
50 }
51 // May re-enter JS.
52 if (m_pDocView->SetFocus(hWidget))
53 m_pDocView->GetDoc()->SetFocusWidget(hWidget);
54
55 return hWidget->OnLButtonDown(dwFlags, hWidget->Rotate2Normal(point));
56 }
57
OnLButtonUp(CXFA_FFWidget * hWidget,Mask<XFA_FWL_KeyFlag> dwFlags,const CFX_PointF & point)58 bool CXFA_FFWidgetHandler::OnLButtonUp(CXFA_FFWidget* hWidget,
59 Mask<XFA_FWL_KeyFlag> dwFlags,
60 const CFX_PointF& point) {
61 CXFA_FFDocView::UpdateScope scope(m_pDocView);
62 m_pDocView->SetLayoutEvent();
63 return hWidget->OnLButtonUp(dwFlags, hWidget->Rotate2Normal(point));
64 }
65
OnLButtonDblClk(CXFA_FFWidget * hWidget,Mask<XFA_FWL_KeyFlag> dwFlags,const CFX_PointF & point)66 bool CXFA_FFWidgetHandler::OnLButtonDblClk(CXFA_FFWidget* hWidget,
67 Mask<XFA_FWL_KeyFlag> dwFlags,
68 const CFX_PointF& point) {
69 return hWidget->OnLButtonDblClk(dwFlags, hWidget->Rotate2Normal(point));
70 }
71
OnMouseMove(CXFA_FFWidget * hWidget,Mask<XFA_FWL_KeyFlag> dwFlags,const CFX_PointF & point)72 bool CXFA_FFWidgetHandler::OnMouseMove(CXFA_FFWidget* hWidget,
73 Mask<XFA_FWL_KeyFlag> dwFlags,
74 const CFX_PointF& point) {
75 return hWidget->OnMouseMove(dwFlags, hWidget->Rotate2Normal(point));
76 }
77
OnMouseWheel(CXFA_FFWidget * hWidget,Mask<XFA_FWL_KeyFlag> dwFlags,const CFX_PointF & point,const CFX_Vector & delta)78 bool CXFA_FFWidgetHandler::OnMouseWheel(CXFA_FFWidget* hWidget,
79 Mask<XFA_FWL_KeyFlag> dwFlags,
80 const CFX_PointF& point,
81 const CFX_Vector& delta) {
82 return hWidget->OnMouseWheel(dwFlags, hWidget->Rotate2Normal(point), delta);
83 }
84
OnRButtonDown(CXFA_FFWidget * hWidget,Mask<XFA_FWL_KeyFlag> dwFlags,const CFX_PointF & point)85 bool CXFA_FFWidgetHandler::OnRButtonDown(CXFA_FFWidget* hWidget,
86 Mask<XFA_FWL_KeyFlag> dwFlags,
87 const CFX_PointF& point) {
88 if (!hWidget->AcceptsFocusOnButtonDown(
89 dwFlags, hWidget->Rotate2Normal(point),
90 CFWL_MessageMouse::MouseCommand::kRightButtonDown)) {
91 return false;
92 }
93 // May re-enter JS.
94 if (m_pDocView->SetFocus(hWidget)) {
95 m_pDocView->GetDoc()->SetFocusWidget(hWidget);
96 }
97 return hWidget->OnRButtonDown(dwFlags, hWidget->Rotate2Normal(point));
98 }
99
OnRButtonUp(CXFA_FFWidget * hWidget,Mask<XFA_FWL_KeyFlag> dwFlags,const CFX_PointF & point)100 bool CXFA_FFWidgetHandler::OnRButtonUp(CXFA_FFWidget* hWidget,
101 Mask<XFA_FWL_KeyFlag> dwFlags,
102 const CFX_PointF& point) {
103 return hWidget->OnRButtonUp(dwFlags, hWidget->Rotate2Normal(point));
104 }
105
OnRButtonDblClk(CXFA_FFWidget * hWidget,Mask<XFA_FWL_KeyFlag> dwFlags,const CFX_PointF & point)106 bool CXFA_FFWidgetHandler::OnRButtonDblClk(CXFA_FFWidget* hWidget,
107 Mask<XFA_FWL_KeyFlag> dwFlags,
108 const CFX_PointF& point) {
109 return hWidget->OnRButtonDblClk(dwFlags, hWidget->Rotate2Normal(point));
110 }
111
OnKeyDown(CXFA_FFWidget * hWidget,XFA_FWL_VKEYCODE dwKeyCode,Mask<XFA_FWL_KeyFlag> dwFlags)112 bool CXFA_FFWidgetHandler::OnKeyDown(CXFA_FFWidget* hWidget,
113 XFA_FWL_VKEYCODE dwKeyCode,
114 Mask<XFA_FWL_KeyFlag> dwFlags) {
115 bool bRet = hWidget->OnKeyDown(dwKeyCode, dwFlags);
116 m_pDocView->UpdateDocView();
117 return bRet;
118 }
119
OnChar(CXFA_FFWidget * hWidget,uint32_t dwChar,Mask<XFA_FWL_KeyFlag> dwFlags)120 bool CXFA_FFWidgetHandler::OnChar(CXFA_FFWidget* hWidget,
121 uint32_t dwChar,
122 Mask<XFA_FWL_KeyFlag> dwFlags) {
123 return hWidget->OnChar(dwChar, dwFlags);
124 }
125
GetText(CXFA_FFWidget * widget)126 WideString CXFA_FFWidgetHandler::GetText(CXFA_FFWidget* widget) {
127 return widget->GetText();
128 }
129
GetSelectedText(CXFA_FFWidget * widget)130 WideString CXFA_FFWidgetHandler::GetSelectedText(CXFA_FFWidget* widget) {
131 if (!widget->CanCopy())
132 return WideString();
133
134 return widget->Copy().value_or(WideString());
135 }
136
PasteText(CXFA_FFWidget * widget,const WideString & text)137 void CXFA_FFWidgetHandler::PasteText(CXFA_FFWidget* widget,
138 const WideString& text) {
139 if (!widget->CanPaste())
140 return;
141
142 widget->Paste(text);
143 }
144
SelectAllText(CXFA_FFWidget * widget)145 bool CXFA_FFWidgetHandler::SelectAllText(CXFA_FFWidget* widget) {
146 if (!widget->CanSelectAll())
147 return false;
148
149 widget->SelectAll();
150 return true;
151 }
152
CanUndo(CXFA_FFWidget * widget)153 bool CXFA_FFWidgetHandler::CanUndo(CXFA_FFWidget* widget) {
154 return widget->CanUndo();
155 }
156
CanRedo(CXFA_FFWidget * widget)157 bool CXFA_FFWidgetHandler::CanRedo(CXFA_FFWidget* widget) {
158 return widget->CanRedo();
159 }
160
Undo(CXFA_FFWidget * widget)161 bool CXFA_FFWidgetHandler::Undo(CXFA_FFWidget* widget) {
162 return widget->Undo();
163 }
164
Redo(CXFA_FFWidget * widget)165 bool CXFA_FFWidgetHandler::Redo(CXFA_FFWidget* widget) {
166 return widget->Redo();
167 }
168
HitTest(CXFA_FFWidget * pWidget,const CFX_PointF & point)169 FWL_WidgetHit CXFA_FFWidgetHandler::HitTest(CXFA_FFWidget* pWidget,
170 const CFX_PointF& point) {
171 if (!pWidget->GetLayoutItem()->TestStatusBits(XFA_WidgetStatus::kVisible))
172 return FWL_WidgetHit::Unknown;
173 return pWidget->HitTest(pWidget->Rotate2Normal(point));
174 }
175
RenderWidget(CXFA_FFWidget * hWidget,CFGAS_GEGraphics * pGS,const CFX_Matrix & matrix,bool bHighlight)176 void CXFA_FFWidgetHandler::RenderWidget(CXFA_FFWidget* hWidget,
177 CFGAS_GEGraphics* pGS,
178 const CFX_Matrix& matrix,
179 bool bHighlight) {
180 hWidget->RenderWidget(
181 pGS, matrix,
182 bHighlight ? CXFA_FFWidget::kHighlight : CXFA_FFWidget::kNoHighlight);
183 }
184
HasEvent(CXFA_Node * pNode,XFA_EVENTTYPE eEventType)185 bool CXFA_FFWidgetHandler::HasEvent(CXFA_Node* pNode,
186 XFA_EVENTTYPE eEventType) {
187 if (eEventType == XFA_EVENT_Unknown)
188 return false;
189 if (!pNode || pNode->GetElementType() == XFA_Element::Draw)
190 return false;
191
192 switch (eEventType) {
193 case XFA_EVENT_Calculate: {
194 CXFA_Calculate* calc = pNode->GetCalculateIfExists();
195 return calc && calc->GetScriptIfExists();
196 }
197 case XFA_EVENT_Validate: {
198 CXFA_Validate* validate = pNode->GetValidateIfExists();
199 return validate && validate->GetScriptIfExists();
200 }
201 default:
202 break;
203 }
204 return !pNode->GetEventByActivity(kXFAEventActivity[eEventType], false)
205 .empty();
206 }
207
ProcessEvent(CXFA_Node * pNode,CXFA_EventParam * pParam)208 XFA_EventError CXFA_FFWidgetHandler::ProcessEvent(CXFA_Node* pNode,
209 CXFA_EventParam* pParam) {
210 if (!pParam || pParam->m_eType == XFA_EVENT_Unknown)
211 return XFA_EventError::kNotExist;
212 if (!pNode || pNode->GetElementType() == XFA_Element::Draw)
213 return XFA_EventError::kNotExist;
214
215 switch (pParam->m_eType) {
216 case XFA_EVENT_Calculate:
217 return pNode->ProcessCalculate(m_pDocView.Get());
218 case XFA_EVENT_Validate:
219 if (m_pDocView->GetDoc()->IsValidationsEnabled())
220 return pNode->ProcessValidate(m_pDocView.Get(), 0);
221 return XFA_EventError::kDisabled;
222 case XFA_EVENT_InitCalculate: {
223 CXFA_Calculate* calc = pNode->GetCalculateIfExists();
224 if (!calc)
225 return XFA_EventError::kNotExist;
226 if (pNode->IsUserInteractive())
227 return XFA_EventError::kDisabled;
228 return pNode->ExecuteScript(m_pDocView.Get(), calc->GetScriptIfExists(),
229 pParam);
230 }
231 default:
232 break;
233 }
234 return pNode->ProcessEvent(m_pDocView.Get(),
235 kXFAEventActivity[pParam->m_eType], pParam);
236 }
237