1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/event/axis_event.h"
17
18 #include "base/input_manager/input_manager.h"
19 #include "core/event/key_event.h"
20
21 namespace OHOS::Ace {
CreateScaleEvent(float scale) const22 AxisEvent AxisEvent::CreateScaleEvent(float scale) const
23 {
24 if (NearZero(scale)) {
25 return { id, x, y, screenX, screenY, verticalAxis, horizontalAxis, pinchAxisScale, rotateAxisAngle,
26 isRotationEvent, action, time, deviceId, sourceType, sourceTool, pointerEvent, pressedCodes,
27 targetDisplayId, originalId, isInjected, scrollStep };
28 }
29 return { id, x / scale, y / scale, screenX / scale, screenY / scale, verticalAxis, horizontalAxis, pinchAxisScale,
30 rotateAxisAngle, isRotationEvent, action, time, deviceId, sourceType, sourceTool, pointerEvent, pressedCodes,
31 targetDisplayId, originalId, isInjected, scrollStep };
32 }
33
GetOffset() const34 Offset AxisEvent::GetOffset() const
35 {
36 return Offset(x, y);
37 }
38
GetScreenOffset() const39 Offset AxisEvent::GetScreenOffset() const
40 {
41 return Offset(screenX, screenY);
42 }
43
GetDirection() const44 AxisDirection AxisEvent::GetDirection() const
45 {
46 uint32_t verticalFlag = 0;
47 uint32_t horizontalFlag = 0;
48 if (LessNotEqual(verticalAxis, 0.0)) {
49 verticalFlag = static_cast<uint32_t>(AxisDirection::UP);
50 } else if (GreatNotEqual(verticalAxis, 0.0)) {
51 verticalFlag = static_cast<uint32_t>(AxisDirection::DOWN);
52 }
53 if (LessNotEqual(horizontalAxis, 0.0)) {
54 horizontalFlag = static_cast<uint32_t>(AxisDirection::LEFT);
55 } else if (GreatNotEqual(horizontalAxis, 0.0)) {
56 horizontalFlag = static_cast<uint32_t>(AxisDirection::RIGHT);
57 }
58 return static_cast<AxisDirection>(verticalFlag | horizontalFlag);
59 }
IsDirectionUp(AxisDirection direction)60 bool AxisEvent::IsDirectionUp(AxisDirection direction)
61 {
62 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::UP));
63 }
IsDirectionDown(AxisDirection direction)64 bool AxisEvent::IsDirectionDown(AxisDirection direction)
65 {
66 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::DOWN));
67 }
IsDirectionLeft(AxisDirection direction)68 bool AxisEvent::IsDirectionLeft(AxisDirection direction)
69 {
70 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::LEFT));
71 }
IsDirectionRight(AxisDirection direction)72 bool AxisEvent::IsDirectionRight(AxisDirection direction)
73 {
74 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::RIGHT));
75 }
76
ConvertToOffset(bool isShiftKeyPressed,bool hasDifferentDirectionGesture) const77 Offset AxisEvent::ConvertToOffset(bool isShiftKeyPressed, bool hasDifferentDirectionGesture) const
78 {
79 Offset result;
80 if (sourceTool == SourceTool::MOUSE) {
81 // Axis event is made by mouse.
82 if (isShiftKeyPressed) {
83 result = Offset(-verticalAxis, -horizontalAxis);
84 } else {
85 if (hasDifferentDirectionGesture) {
86 result = Offset(-horizontalAxis, -verticalAxis);
87 } else {
88 result = Offset(-verticalAxis, -verticalAxis);
89 }
90 }
91 return result * (LINE_HEIGHT_DESKTOP / MOUSE_WHEEL_DEGREES).ConvertToPx();
92 }
93 // Axis event is made by others. Include touch-pad.
94 result = Offset(-horizontalAxis, -verticalAxis);
95 return result;
96 }
97
98 // MMI has the different direction, need to check truth direction.
ConvertToSummationAxisValue(const AxisEvent & event) const99 std::pair<float, float> AxisEvent::ConvertToSummationAxisValue(const AxisEvent& event) const
100 {
101 return std::make_pair(event.horizontalAxis - horizontalAxis, event.verticalAxis - verticalAxis);
102 }
103
HasKey(KeyCode expectCode) const104 bool AxisEvent::HasKey(KeyCode expectCode) const
105 {
106 auto curPressedCode = pressedCodes.rbegin();
107 while (curPressedCode != pressedCodes.rend()) {
108 if (expectCode == *curPressedCode) {
109 return true;
110 }
111 ++curPressedCode;
112 }
113 return false;
114 }
115
GetTargetDisplayId() const116 int32_t AxisEvent::GetTargetDisplayId() const
117 {
118 return targetDisplayId;
119 }
120
AxisInfo(const AxisEvent & event,const Offset & localLocation,const EventTarget & target)121 AxisInfo::AxisInfo(const AxisEvent& event, const Offset& localLocation, const EventTarget& target)
122 : BaseEventInfo("onAxis")
123 {
124 action_ = event.action;
125 scrollStep_ = event.scrollStep;
126 verticalAxis_ = static_cast<float>(event.verticalAxis);
127 horizontalAxis_ = static_cast<float>(event.horizontalAxis);
128 pinchAxisScale_ = static_cast<float>(event.pinchAxisScale);
129 rotateAxisAngle_ = static_cast<float>(event.rotateAxisAngle);
130 isRotationEvent_ = event.isRotationEvent;
131 globalLocation_ = event.GetOffset();
132 localLocation_ = localLocation;
133 screenLocation_ = Offset();
134 SetPressedKeyCodes(event.pressedCodes);
135 SetTimeStamp(event.time);
136 SetDeviceId(event.deviceId);
137 SetSourceDevice(event.sourceType);
138 SetTarget(target);
139 }
140
SetAction(AxisAction action)141 void AxisInfo::SetAction(AxisAction action)
142 {
143 action_ = action;
144 }
145
GetAction() const146 AxisAction AxisInfo::GetAction() const
147 {
148 return action_;
149 }
150
GetScrollStep() const151 int32_t AxisInfo::GetScrollStep() const
152 {
153 return scrollStep_;
154 }
155
SetVerticalAxis(float axis)156 void AxisInfo::SetVerticalAxis(float axis)
157 {
158 verticalAxis_ = axis;
159 }
160
GetVerticalAxis() const161 float AxisInfo::GetVerticalAxis() const
162 {
163 return verticalAxis_;
164 }
165
SetHorizontalAxis(float axis)166 void AxisInfo::SetHorizontalAxis(float axis)
167 {
168 horizontalAxis_ = axis;
169 }
170
GetHorizontalAxis() const171 float AxisInfo::GetHorizontalAxis() const
172 {
173 return horizontalAxis_;
174 }
175
SetPinchAxisScale(float scale)176 void AxisInfo::SetPinchAxisScale(float scale)
177 {
178 pinchAxisScale_ = scale;
179 }
180
GetPinchAxisScale() const181 float AxisInfo::GetPinchAxisScale() const
182 {
183 return pinchAxisScale_;
184 }
185
SetRotateAxisAngle(float angle)186 void AxisInfo::SetRotateAxisAngle(float angle)
187 {
188 rotateAxisAngle_ = angle;
189 }
190
GetRotateAxisAngle() const191 float AxisInfo::GetRotateAxisAngle() const
192 {
193 return rotateAxisAngle_;
194 }
195
SetIsRotationEvent(bool rotationFlag)196 void AxisInfo::SetIsRotationEvent(bool rotationFlag)
197 {
198 isRotationEvent_ = rotationFlag;
199 }
200
GetIsRotationEvent() const201 bool AxisInfo::GetIsRotationEvent() const
202 {
203 return isRotationEvent_;
204 }
205
SetGlobalLocation(const Offset & globalLocation)206 AxisInfo& AxisInfo::SetGlobalLocation(const Offset& globalLocation)
207 {
208 globalLocation_ = globalLocation;
209 return *this;
210 }
SetLocalLocation(const Offset & localLocation)211 AxisInfo& AxisInfo::SetLocalLocation(const Offset& localLocation)
212 {
213 localLocation_ = localLocation;
214 return *this;
215 }
216
SetScreenLocation(const Offset & screenLocation)217 AxisInfo& AxisInfo::SetScreenLocation(const Offset& screenLocation)
218 {
219 screenLocation_ = screenLocation;
220 return *this;
221 }
222
GetScreenLocation() const223 const Offset& AxisInfo::GetScreenLocation() const
224 {
225 return screenLocation_;
226 }
227
GetLocalLocation() const228 const Offset& AxisInfo::GetLocalLocation() const
229 {
230 return localLocation_;
231 }
GetGlobalLocation() const232 const Offset& AxisInfo::GetGlobalLocation() const
233 {
234 return globalLocation_;
235 }
236
ConvertToAxisEvent() const237 AxisEvent AxisInfo::ConvertToAxisEvent() const
238 {
239 AxisEvent axisEvent;
240 axisEvent.x = static_cast<float>(globalLocation_.GetX());
241 axisEvent.y = static_cast<float>(globalLocation_.GetY());
242 axisEvent.screenX = static_cast<float>(screenLocation_.GetX());
243 axisEvent.screenY = static_cast<float>(screenLocation_.GetY());
244 axisEvent.scrollStep = scrollStep_;
245 axisEvent.horizontalAxis = horizontalAxis_;
246 axisEvent.verticalAxis = verticalAxis_;
247 axisEvent.pinchAxisScale = pinchAxisScale_;
248 axisEvent.action = action_;
249 axisEvent.rotateAxisAngle = rotateAxisAngle_;
250 axisEvent.time = timeStamp_;
251 axisEvent.localX = static_cast<float>(localLocation_.GetX());
252 axisEvent.localY = static_cast<float>(localLocation_.GetY());
253 axisEvent.sourceType = deviceType_;
254 axisEvent.sourceTool = sourceTool_;
255 const auto& targetLocalOffset = GetTarget().area.GetOffset();
256 const auto& targetOrigin = GetTarget().origin;
257 // width height x y globalx globaly
258 axisEvent.targetPositionX = targetLocalOffset.GetX().ConvertToPx();
259 axisEvent.targetPositionY = targetLocalOffset.GetY().ConvertToPx();
260 axisEvent.targetGlobalPositionX = targetOrigin.GetX().ConvertToPx() + targetLocalOffset.GetX().ConvertToPx();
261 axisEvent.targetGlobalPositionY = targetOrigin.GetY().ConvertToPx() + targetLocalOffset.GetY().ConvertToPx();
262 axisEvent.width = GetTarget().area.GetWidth().ConvertToPx();
263 axisEvent.height = GetTarget().area.GetHeight().ConvertToPx();
264 // deviceid
265 axisEvent.deviceId = GetDeviceId();
266 // modifierkeystates
267 axisEvent.modifierKeyState = CalculateModifierKeyState(GetPressedKeyCodes());
268 return axisEvent;
269 }
270
SetOnAxisCallback(const OnAxisEventFunc & onAxisCallback)271 void AxisEventTarget::SetOnAxisCallback(const OnAxisEventFunc& onAxisCallback)
272 {
273 onAxisCallback_ = onAxisCallback;
274 }
275
SetCoordinateOffset(const NG::OffsetF & coordinateOffset)276 void AxisEventTarget::SetCoordinateOffset(const NG::OffsetF& coordinateOffset)
277 {
278 coordinateOffset_ = coordinateOffset;
279 }
280
SetGetEventTargetImpl(const GetEventTargetImpl & getEventTargetImpl)281 void AxisEventTarget::SetGetEventTargetImpl(const GetEventTargetImpl& getEventTargetImpl)
282 {
283 getEventTargetImpl_ = getEventTargetImpl;
284 }
285
GetEventTarget() const286 std::optional<EventTarget> AxisEventTarget::GetEventTarget() const
287 {
288 if (getEventTargetImpl_) {
289 return getEventTargetImpl_();
290 }
291 return std::nullopt;
292 }
293
SetFrameName(const std::string & frameName)294 void AxisEventTarget::SetFrameName(const std::string& frameName)
295 {
296 frameName_ = frameName;
297 }
298
GetFrameName() const299 std::string AxisEventTarget::GetFrameName() const
300 {
301 return frameName_;
302 }
303
HandleAxisEvent(const AxisEvent & event)304 bool AxisEventTarget::HandleAxisEvent(const AxisEvent& event)
305 {
306 if (!onAxisCallback_) {
307 return false;
308 }
309 Offset localLocation = Offset(
310 event.GetOffset().GetX() - coordinateOffset_.GetX(), event.GetOffset().GetY() - coordinateOffset_.GetY());
311 AxisInfo info = AxisInfo(event, localLocation, GetEventTarget().value_or(EventTarget()));
312 info.SetScreenLocation(Offset(event.screenX, event.screenY));
313 info.SetSourceTool(event.sourceTool);
314 info.SetStopPropagation(true);
315 onAxisCallback_(info);
316 return info.IsStopPropagation();
317 }
318
IsAxisEventSequenceCorrect(const AxisEvent & event)319 bool AxisEventChecker::IsAxisEventSequenceCorrect(const AxisEvent& event)
320 {
321 if (event.sourceType == SourceType::MOUSE) { // wheel on mouse or touch pad
322 return IsGenericAxisEventSequenceCorrect(event);
323 }
324
325 // no check for other axis event, for example the axis event generated by joystick
326 return true;
327 }
328
GetPreAction() const329 AxisAction AxisEventChecker::GetPreAction() const
330 {
331 return preActionOld_;
332 }
333
IsGenericAxisEventSequenceCorrect(const AxisEvent & event)334 bool AxisEventChecker::IsGenericAxisEventSequenceCorrect(const AxisEvent& event)
335 {
336 preActionOld_ = preActionNew_;
337 preActionNew_ = event.action;
338
339 switch (event.action) {
340 case AxisAction::BEGIN:
341 // received begin but have not received end or cancel for pre event
342 return preActionOld_ == AxisAction::NONE;
343 case AxisAction::UPDATE:
344 // received update but have not received
345 return preActionOld_ == AxisAction::BEGIN || preActionOld_ == AxisAction::UPDATE;
346 case AxisAction::END:
347 case AxisAction::CANCEL:
348 // received end or cancel
349 preActionNew_ = AxisAction::NONE;
350 return preActionOld_ == AxisAction::BEGIN || preActionOld_ == AxisAction::UPDATE;
351 default:
352 return false;
353 }
354 }
355
356 } // namespace OHOS::Ace