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, globalDisplayX, globalDisplayY, verticalAxis, horizontalAxis,
26 pinchAxisScale, rotateAxisAngle, isRotationEvent, action, time, deviceId, sourceType, sourceTool,
27 pointerEvent, pressedCodes, targetDisplayId, originalId, isInjected, scrollStep };
28 }
29 return { id, x / scale, y / scale, screenX / scale, screenY / scale, globalDisplayX / scale, globalDisplayY / scale,
30 verticalAxis, horizontalAxis, pinchAxisScale, rotateAxisAngle, isRotationEvent, action, time, deviceId,
31 sourceType, sourceTool, pointerEvent, pressedCodes, 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
GetGlobalDisplayOffset() const44 Offset AxisEvent::GetGlobalDisplayOffset() const
45 {
46 return Offset(globalDisplayX, globalDisplayY);
47 }
48
GetDirection() const49 AxisDirection AxisEvent::GetDirection() const
50 {
51 uint32_t verticalFlag = 0;
52 uint32_t horizontalFlag = 0;
53 if (LessNotEqual(verticalAxis, 0.0)) {
54 verticalFlag = static_cast<uint32_t>(AxisDirection::UP);
55 } else if (GreatNotEqual(verticalAxis, 0.0)) {
56 verticalFlag = static_cast<uint32_t>(AxisDirection::DOWN);
57 }
58 if (LessNotEqual(horizontalAxis, 0.0)) {
59 horizontalFlag = static_cast<uint32_t>(AxisDirection::LEFT);
60 } else if (GreatNotEqual(horizontalAxis, 0.0)) {
61 horizontalFlag = static_cast<uint32_t>(AxisDirection::RIGHT);
62 }
63 return static_cast<AxisDirection>(verticalFlag | horizontalFlag);
64 }
IsDirectionUp(AxisDirection direction)65 bool AxisEvent::IsDirectionUp(AxisDirection direction)
66 {
67 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::UP));
68 }
IsDirectionDown(AxisDirection direction)69 bool AxisEvent::IsDirectionDown(AxisDirection direction)
70 {
71 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::DOWN));
72 }
IsDirectionLeft(AxisDirection direction)73 bool AxisEvent::IsDirectionLeft(AxisDirection direction)
74 {
75 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::LEFT));
76 }
IsDirectionRight(AxisDirection direction)77 bool AxisEvent::IsDirectionRight(AxisDirection direction)
78 {
79 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::RIGHT));
80 }
81
ConvertToOffset(bool isShiftKeyPressed,bool hasDifferentDirectionGesture) const82 Offset AxisEvent::ConvertToOffset(bool isShiftKeyPressed, bool hasDifferentDirectionGesture) const
83 {
84 Offset result;
85 if (sourceTool == SourceTool::MOUSE) {
86 // Axis event is made by mouse.
87 if (isShiftKeyPressed) {
88 result = Offset(-verticalAxis, -horizontalAxis);
89 } else {
90 if (hasDifferentDirectionGesture) {
91 result = Offset(-horizontalAxis, -verticalAxis);
92 } else {
93 result = Offset(-verticalAxis, -verticalAxis);
94 }
95 }
96 return result * (LINE_HEIGHT_DESKTOP / MOUSE_WHEEL_DEGREES).ConvertToPx();
97 }
98 // Axis event is made by others. Include touch-pad.
99 result = Offset(-horizontalAxis, -verticalAxis);
100 return result;
101 }
102
103 // MMI has the different direction, need to check truth direction.
ConvertToSummationAxisValue(const AxisEvent & event) const104 std::pair<float, float> AxisEvent::ConvertToSummationAxisValue(const AxisEvent& event) const
105 {
106 return std::make_pair(event.horizontalAxis - horizontalAxis, event.verticalAxis - verticalAxis);
107 }
108
HasKey(KeyCode expectCode) const109 bool AxisEvent::HasKey(KeyCode expectCode) const
110 {
111 auto curPressedCode = pressedCodes.rbegin();
112 while (curPressedCode != pressedCodes.rend()) {
113 if (expectCode == *curPressedCode) {
114 return true;
115 }
116 ++curPressedCode;
117 }
118 return false;
119 }
120
GetTargetDisplayId() const121 int32_t AxisEvent::GetTargetDisplayId() const
122 {
123 return targetDisplayId;
124 }
125
AxisInfo(const AxisEvent & event,const Offset & localLocation,const EventTarget & target)126 AxisInfo::AxisInfo(const AxisEvent& event, const Offset& localLocation, const EventTarget& target)
127 : BaseEventInfo("onAxis")
128 {
129 action_ = event.action;
130 scrollStep_ = event.scrollStep;
131 verticalAxis_ = static_cast<float>(event.verticalAxis);
132 horizontalAxis_ = static_cast<float>(event.horizontalAxis);
133 pinchAxisScale_ = static_cast<float>(event.pinchAxisScale);
134 rotateAxisAngle_ = static_cast<float>(event.rotateAxisAngle);
135 isRotationEvent_ = event.isRotationEvent;
136 globalLocation_ = event.GetOffset();
137 localLocation_ = localLocation;
138 screenLocation_ = Offset();
139 SetPressedKeyCodes(event.pressedCodes);
140 SetTimeStamp(event.time);
141 SetDeviceId(event.deviceId);
142 SetSourceDevice(event.sourceType);
143 SetTarget(target);
144 SetTargetDisplayId(event.targetDisplayId);
145 }
146
SetAction(AxisAction action)147 void AxisInfo::SetAction(AxisAction action)
148 {
149 action_ = action;
150 }
151
GetAction() const152 AxisAction AxisInfo::GetAction() const
153 {
154 return action_;
155 }
156
GetScrollStep() const157 int32_t AxisInfo::GetScrollStep() const
158 {
159 return scrollStep_;
160 }
161
SetPinchAxisScale(float scale)162 void AxisInfo::SetPinchAxisScale(float scale)
163 {
164 pinchAxisScale_ = scale;
165 }
166
GetPinchAxisScale() const167 float AxisInfo::GetPinchAxisScale() const
168 {
169 return pinchAxisScale_;
170 }
171
SetRotateAxisAngle(float angle)172 void AxisInfo::SetRotateAxisAngle(float angle)
173 {
174 rotateAxisAngle_ = angle;
175 }
176
GetRotateAxisAngle() const177 float AxisInfo::GetRotateAxisAngle() const
178 {
179 return rotateAxisAngle_;
180 }
181
SetIsRotationEvent(bool rotationFlag)182 void AxisInfo::SetIsRotationEvent(bool rotationFlag)
183 {
184 isRotationEvent_ = rotationFlag;
185 }
186
GetIsRotationEvent() const187 bool AxisInfo::GetIsRotationEvent() const
188 {
189 return isRotationEvent_;
190 }
191
SetGlobalLocation(const Offset & globalLocation)192 AxisInfo& AxisInfo::SetGlobalLocation(const Offset& globalLocation)
193 {
194 globalLocation_ = globalLocation;
195 return *this;
196 }
SetLocalLocation(const Offset & localLocation)197 AxisInfo& AxisInfo::SetLocalLocation(const Offset& localLocation)
198 {
199 localLocation_ = localLocation;
200 return *this;
201 }
202
SetScreenLocation(const Offset & screenLocation)203 AxisInfo& AxisInfo::SetScreenLocation(const Offset& screenLocation)
204 {
205 screenLocation_ = screenLocation;
206 return *this;
207 }
208
GetScreenLocation() const209 const Offset& AxisInfo::GetScreenLocation() const
210 {
211 return screenLocation_;
212 }
213
GetLocalLocation() const214 const Offset& AxisInfo::GetLocalLocation() const
215 {
216 return localLocation_;
217 }
GetGlobalLocation() const218 const Offset& AxisInfo::GetGlobalLocation() const
219 {
220 return globalLocation_;
221 }
222
SetGlobalDisplayLocation(const Offset & globalDisplayLocation)223 AxisInfo& AxisInfo::SetGlobalDisplayLocation(const Offset& globalDisplayLocation)
224 {
225 globalDisplayLocation_ = globalDisplayLocation;
226 return *this;
227 }
GetGlobalDisplayLocation() const228 const Offset& AxisInfo::GetGlobalDisplayLocation() const
229 {
230 return globalDisplayLocation_;
231 }
232
ConvertToAxisEvent() const233 AxisEvent AxisInfo::ConvertToAxisEvent() const
234 {
235 AxisEvent axisEvent;
236 axisEvent.x = static_cast<float>(globalLocation_.GetX());
237 axisEvent.y = static_cast<float>(globalLocation_.GetY());
238 axisEvent.screenX = static_cast<float>(screenLocation_.GetX());
239 axisEvent.screenY = static_cast<float>(screenLocation_.GetY());
240 axisEvent.globalDisplayX = static_cast<float>(globalDisplayLocation_.GetX());
241 axisEvent.globalDisplayY = static_cast<float>(globalDisplayLocation_.GetY());
242 axisEvent.scrollStep = scrollStep_;
243 axisEvent.horizontalAxis = horizontalAxis_;
244 axisEvent.verticalAxis = verticalAxis_;
245 axisEvent.pinchAxisScale = pinchAxisScale_;
246 axisEvent.action = action_;
247 axisEvent.rotateAxisAngle = rotateAxisAngle_;
248 axisEvent.time = timeStamp_;
249 axisEvent.localX = static_cast<float>(localLocation_.GetX());
250 axisEvent.localY = static_cast<float>(localLocation_.GetY());
251 axisEvent.sourceType = deviceType_;
252 axisEvent.sourceTool = sourceTool_;
253 const auto& targetLocalOffset = GetTarget().area.GetOffset();
254 const auto& targetOrigin = GetTarget().origin;
255 // width height x y globalx globaly
256 axisEvent.targetPositionX = targetLocalOffset.GetX().ConvertToPx();
257 axisEvent.targetPositionY = targetLocalOffset.GetY().ConvertToPx();
258 axisEvent.targetGlobalPositionX = targetOrigin.GetX().ConvertToPx() + targetLocalOffset.GetX().ConvertToPx();
259 axisEvent.targetGlobalPositionY = targetOrigin.GetY().ConvertToPx() + targetLocalOffset.GetY().ConvertToPx();
260 axisEvent.width = GetTarget().area.GetWidth().ConvertToPx();
261 axisEvent.height = GetTarget().area.GetHeight().ConvertToPx();
262 // deviceid
263 axisEvent.deviceId = GetDeviceId();
264 // modifierkeystates
265 axisEvent.modifierKeyState = CalculateModifierKeyState(GetPressedKeyCodes());
266 axisEvent.targetDisplayId = GetTargetDisplayId();
267 return axisEvent;
268 }
269
SetOnAxisCallback(const OnAxisEventFunc & onAxisCallback)270 void AxisEventTarget::SetOnAxisCallback(const OnAxisEventFunc& onAxisCallback)
271 {
272 onAxisCallback_ = onAxisCallback;
273 }
274
SetCoordinateOffset(const NG::OffsetF & coordinateOffset)275 void AxisEventTarget::SetCoordinateOffset(const NG::OffsetF& coordinateOffset)
276 {
277 coordinateOffset_ = coordinateOffset;
278 }
279
SetGetEventTargetImpl(const GetEventTargetImpl & getEventTargetImpl)280 void AxisEventTarget::SetGetEventTargetImpl(const GetEventTargetImpl& getEventTargetImpl)
281 {
282 getEventTargetImpl_ = getEventTargetImpl;
283 }
284
GetEventTarget() const285 std::optional<EventTarget> AxisEventTarget::GetEventTarget() const
286 {
287 if (getEventTargetImpl_) {
288 return getEventTargetImpl_();
289 }
290 return std::nullopt;
291 }
292
SetFrameName(const std::string & frameName)293 void AxisEventTarget::SetFrameName(const std::string& frameName)
294 {
295 frameName_ = frameName;
296 }
297
GetFrameName() const298 std::string AxisEventTarget::GetFrameName() const
299 {
300 return frameName_;
301 }
302
HandleAxisEvent(const AxisEvent & event)303 bool AxisEventTarget::HandleAxisEvent(const AxisEvent& event)
304 {
305 if (!onAxisCallback_) {
306 return false;
307 }
308 Offset localLocation = Offset(
309 event.GetOffset().GetX() - coordinateOffset_.GetX(), event.GetOffset().GetY() - coordinateOffset_.GetY());
310 AxisInfo info = AxisInfo(event, localLocation, GetEventTarget().value_or(EventTarget()));
311 info.SetScreenLocation(Offset(event.screenX, event.screenY));
312 info.SetGlobalDisplayLocation(Offset(event.globalDisplayX, event.globalDisplayY));
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