1 /* 2 * Copyright (c) 2022 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_AXIS_EVENT_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_AXIS_EVENT_H 18 19 #include <list> 20 #include <utility> 21 22 #include "base/geometry/offset.h" 23 #include "base/memory/ace_type.h" 24 #include "core/event/ace_events.h" 25 #include "core/event/key_event.h" 26 27 namespace OHOS::MMI { 28 class PointerEvent; 29 } // namespace OHOS::MMI 30 31 namespace OHOS::Ace { 32 33 constexpr double MOUSE_WHEEL_DEGREES = 15.0; 34 constexpr double DP_PER_LINE_DESKTOP = 40.0; 35 constexpr Dimension LINE_HEIGHT_DESKTOP = 21.0_vp; 36 constexpr int32_t LINE_NUMBER_DESKTOP = 3; 37 constexpr int32_t DP_PER_LINE_PHONE = 64; 38 constexpr int32_t LINE_NUMBER_PHONE = 1; 39 40 enum class AxisDirection : int32_t { 41 NONE = 0, 42 UP = 1, 43 DOWN = 2, 44 LEFT = 4, 45 RIGHT = 8, 46 UP_LEFT = 5, 47 UP_RIGHT = 9, 48 DOWN_LEFT = 6, 49 DOWN_RIGHT = 10, 50 }; 51 52 enum class AxisAction : int32_t { 53 NONE = 0, 54 BEGIN, 55 UPDATE, 56 END, 57 CANCEL, 58 }; 59 struct UIInputEvent { 60 virtual ~UIInputEvent() = default; 61 TimeStamp time; 62 }; 63 64 struct AxisEvent final : public UIInputEvent { 65 ~AxisEvent() = default; 66 int32_t id = 0; 67 float x = 0.0; 68 float y = 0.0; 69 float screenX = 0.0; 70 float screenY = 0.0; 71 double verticalAxis = 0.0; 72 double horizontalAxis = 0.0; 73 double pinchAxisScale = 0.0; 74 double rotateAxisAngle = 0.0; 75 bool isRotationEvent = false; 76 AxisAction action = AxisAction::NONE; 77 int64_t deviceId = 0; 78 SourceType sourceType = SourceType::NONE; 79 SourceTool sourceTool = SourceTool::UNKNOWN; 80 std::shared_ptr<MMI::PointerEvent> pointerEvent; 81 int32_t touchEventId = 0; 82 std::vector<KeyCode> pressedCodes; 83 84 // Coordinates relative to the upper-left corner of the current component 85 float localX = 0.0; 86 float localY = 0.0; 87 88 int32_t targetDisplayId = 0; 89 int32_t originalId = 0; 90 bool isInjected = false; 91 AxisEventfinal92 AxisEvent() {} 93 AxisEventfinal94 AxisEvent(int32_t id, float x, float y, float screenX, float screenY, double verticalAxis, double horizontalAxis, 95 double pinchAxisScale, double rotateAxisAngle, bool isRotationEvent, AxisAction action, TimeStamp timestamp, 96 int64_t deviceId, SourceType sourceType, SourceTool sourceTool, std::shared_ptr<MMI::PointerEvent> pointerEvent, 97 std::vector<KeyCode> pressedCodes, int32_t targetDisplayId, int32_t originalId, bool isInjected) 98 : id(id), x(x), y(y), screenX(screenX), screenY(screenY), verticalAxis(verticalAxis), 99 horizontalAxis(horizontalAxis), pinchAxisScale(pinchAxisScale), rotateAxisAngle(rotateAxisAngle), 100 isRotationEvent(isRotationEvent), action(action), deviceId(deviceId), sourceType(sourceType), 101 sourceTool(sourceTool), pointerEvent(std::move(pointerEvent)), pressedCodes(pressedCodes), 102 targetDisplayId(targetDisplayId), originalId(originalId), isInjected(isInjected) 103 { 104 time = timestamp; 105 } 106 CreateScaleEventfinal107 AxisEvent CreateScaleEvent(float scale) const 108 { 109 if (NearZero(scale)) { 110 return { id, x, y, screenX, screenY, verticalAxis, horizontalAxis, pinchAxisScale, rotateAxisAngle, 111 isRotationEvent, action, time, deviceId, sourceType, sourceTool, pointerEvent, pressedCodes, 112 targetDisplayId, originalId, isInjected }; 113 } 114 return { id, x / scale, y / scale, screenX / scale, screenY / scale, verticalAxis, horizontalAxis, 115 pinchAxisScale, rotateAxisAngle, isRotationEvent, action, time, deviceId, sourceType, sourceTool, 116 pointerEvent, pressedCodes, targetDisplayId, originalId, isInjected }; 117 } 118 GetOffsetfinal119 Offset GetOffset() const 120 { 121 return Offset(x, y); 122 } 123 GetScreenOffsetfinal124 Offset GetScreenOffset() const 125 { 126 return Offset(screenX, screenY); 127 } 128 GetDirectionfinal129 AxisDirection GetDirection() const 130 { 131 uint32_t verticalFlag = 0; 132 uint32_t horizontalFlag = 0; 133 if (LessNotEqual(verticalAxis, 0.0)) { 134 verticalFlag = static_cast<uint32_t>(AxisDirection::UP); 135 } else if (GreatNotEqual(verticalAxis, 0.0)) { 136 verticalFlag = static_cast<uint32_t>(AxisDirection::DOWN); 137 } 138 if (LessNotEqual(horizontalAxis, 0.0)) { 139 horizontalFlag = static_cast<uint32_t>(AxisDirection::LEFT); 140 } else if (GreatNotEqual(horizontalAxis, 0.0)) { 141 horizontalFlag = static_cast<uint32_t>(AxisDirection::RIGHT); 142 } 143 return static_cast<AxisDirection>(verticalFlag | horizontalFlag); 144 } IsDirectionUpfinal145 static bool IsDirectionUp(AxisDirection direction) 146 { 147 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::UP)); 148 } IsDirectionDownfinal149 static bool IsDirectionDown(AxisDirection direction) 150 { 151 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::DOWN)); 152 } IsDirectionLeftfinal153 static bool IsDirectionLeft(AxisDirection direction) 154 { 155 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::LEFT)); 156 } IsDirectionRightfinal157 static bool IsDirectionRight(AxisDirection direction) 158 { 159 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::RIGHT)); 160 } 161 162 Offset ConvertToOffset(bool isShiftKeyPressed = false, bool hasDifferentDirectionGesture = false) const 163 { 164 Offset result; 165 if (sourceTool == SourceTool::MOUSE) { 166 // Axis event is made by mouse. 167 if (isShiftKeyPressed) { 168 result = Offset(-verticalAxis, -horizontalAxis); 169 } else { 170 if (hasDifferentDirectionGesture) { 171 result = Offset(-horizontalAxis, -verticalAxis); 172 } else { 173 result = Offset(-verticalAxis, -verticalAxis); 174 } 175 } 176 return result * (LINE_HEIGHT_DESKTOP / MOUSE_WHEEL_DEGREES).ConvertToPx(); 177 } 178 // Axis event is made by others. Include touch-pad. 179 result = Offset(-horizontalAxis, -verticalAxis); 180 return result; 181 } 182 183 // MMI has the different direction, need to check truth direction. ConvertToSummationAxisValuefinal184 std::pair<float, float> ConvertToSummationAxisValue(const AxisEvent& event) const 185 { 186 return std::make_pair(event.horizontalAxis - horizontalAxis, event.verticalAxis - verticalAxis); 187 } 188 }; 189 190 class AxisInfo : public BaseEventInfo { 191 DECLARE_RELATIONSHIP_OF_CLASSES(AxisInfo, BaseEventInfo); 192 193 public: AxisInfo()194 AxisInfo() : BaseEventInfo("onAxis") {} AxisInfo(const AxisEvent & event,const Offset & localLocation,const EventTarget & target)195 AxisInfo(const AxisEvent& event, const Offset& localLocation, const EventTarget& target) : BaseEventInfo("onAxis") 196 { 197 action_ = event.action; 198 verticalAxis_ = static_cast<float>(event.verticalAxis); 199 horizontalAxis_ = static_cast<float>(event.horizontalAxis); 200 pinchAxisScale_ = static_cast<float>(event.pinchAxisScale); 201 rotateAxisAngle_ = static_cast<float>(event.rotateAxisAngle); 202 isRotationEvent_ = event.isRotationEvent; 203 globalLocation_ = event.GetOffset(); 204 localLocation_ = localLocation; 205 screenLocation_ = Offset(); 206 SetTimeStamp(event.time); 207 SetDeviceId(event.deviceId); 208 SetSourceDevice(event.sourceType); 209 SetTarget(target); 210 } 211 ~AxisInfo() override = default; 212 SetAction(AxisAction action)213 void SetAction(AxisAction action) 214 { 215 action_ = action; 216 } 217 GetAction()218 AxisAction GetAction() const 219 { 220 return action_; 221 } 222 SetVerticalAxis(float axis)223 void SetVerticalAxis(float axis) 224 { 225 verticalAxis_ = axis; 226 } 227 GetVerticalAxis()228 float GetVerticalAxis() const 229 { 230 return verticalAxis_; 231 } 232 SetHorizontalAxis(float axis)233 void SetHorizontalAxis(float axis) 234 { 235 horizontalAxis_ = axis; 236 } 237 GetHorizontalAxis()238 float GetHorizontalAxis() const 239 { 240 return horizontalAxis_; 241 } 242 SetPinchAxisScale(float scale)243 void SetPinchAxisScale(float scale) 244 { 245 pinchAxisScale_ = scale; 246 } 247 GetPinchAxisScale()248 float GetPinchAxisScale() const 249 { 250 return pinchAxisScale_; 251 } 252 SetRotateAxisAngle(float angle)253 void SetRotateAxisAngle(float angle) 254 { 255 rotateAxisAngle_ = angle; 256 } 257 GetRotateAxisAngle()258 float GetRotateAxisAngle() const 259 { 260 return rotateAxisAngle_; 261 } 262 SetIsRotationEvent(bool rotationFlag)263 void SetIsRotationEvent(bool rotationFlag) 264 { 265 isRotationEvent_ = rotationFlag; 266 } 267 GetIsRotationEvent()268 bool GetIsRotationEvent() const 269 { 270 return isRotationEvent_; 271 } 272 SetGlobalLocation(const Offset & globalLocation)273 AxisInfo& SetGlobalLocation(const Offset& globalLocation) 274 { 275 globalLocation_ = globalLocation; 276 return *this; 277 } SetLocalLocation(const Offset & localLocation)278 AxisInfo& SetLocalLocation(const Offset& localLocation) 279 { 280 localLocation_ = localLocation; 281 return *this; 282 } 283 SetScreenLocation(const Offset & screenLocation)284 AxisInfo& SetScreenLocation(const Offset& screenLocation) 285 { 286 screenLocation_ = screenLocation; 287 return *this; 288 } 289 GetScreenLocation()290 const Offset& GetScreenLocation() const 291 { 292 return screenLocation_; 293 } 294 GetLocalLocation()295 const Offset& GetLocalLocation() const 296 { 297 return localLocation_; 298 } GetGlobalLocation()299 const Offset& GetGlobalLocation() const 300 { 301 return globalLocation_; 302 } 303 ConvertToAxisEvent()304 AxisEvent ConvertToAxisEvent() const 305 { 306 AxisEvent axisEvent; 307 axisEvent.x = static_cast<float>(globalLocation_.GetX()); 308 axisEvent.y = static_cast<float>(globalLocation_.GetY()); 309 axisEvent.screenX = static_cast<float>(screenLocation_.GetX()); 310 axisEvent.screenY = static_cast<float>(screenLocation_.GetY()); 311 axisEvent.horizontalAxis = horizontalAxis_; 312 axisEvent.verticalAxis = verticalAxis_; 313 axisEvent.pinchAxisScale = pinchAxisScale_; 314 axisEvent.rotateAxisAngle = rotateAxisAngle_; 315 axisEvent.time = timeStamp_; 316 axisEvent.localX = static_cast<float>(localLocation_.GetX()); 317 axisEvent.localY = static_cast<float>(localLocation_.GetY()); 318 return axisEvent; 319 } 320 321 private: 322 AxisAction action_ = AxisAction::NONE; 323 float verticalAxis_ = 0.0; 324 float horizontalAxis_ = 0.0; 325 float pinchAxisScale_ = 0.0; 326 float rotateAxisAngle_ = 0.0; 327 bool isRotationEvent_ = false; 328 // global position at which the touch point contacts the screen. 329 Offset globalLocation_; 330 // Different from global location, The local location refers to the location of the contact point relative to the 331 // current node which has the recognizer. 332 Offset localLocation_; 333 Offset screenLocation_; 334 }; 335 336 using OnAxisEventFunc = std::function<void(AxisInfo&)>; 337 using GetEventTargetImpl = std::function<std::optional<EventTarget>()>; 338 339 class AxisEventTarget : public virtual AceType { 340 DECLARE_ACE_TYPE(AxisEventTarget, AceType); 341 342 public: 343 AxisEventTarget() = default; AxisEventTarget(std::string frameName)344 AxisEventTarget(std::string frameName) : frameName_(std::move(frameName)) {} 345 ~AxisEventTarget() override = default; 346 SetOnAxisCallback(const OnAxisEventFunc & onAxisCallback)347 void SetOnAxisCallback(const OnAxisEventFunc& onAxisCallback) 348 { 349 onAxisCallback_ = onAxisCallback; 350 } 351 SetCoordinateOffset(const NG::OffsetF & coordinateOffset)352 void SetCoordinateOffset(const NG::OffsetF& coordinateOffset) 353 { 354 coordinateOffset_ = coordinateOffset; 355 } 356 SetGetEventTargetImpl(const GetEventTargetImpl & getEventTargetImpl)357 void SetGetEventTargetImpl(const GetEventTargetImpl& getEventTargetImpl) 358 { 359 getEventTargetImpl_ = getEventTargetImpl; 360 } 361 GetEventTarget()362 std::optional<EventTarget> GetEventTarget() const 363 { 364 if (getEventTargetImpl_) { 365 return getEventTargetImpl_(); 366 } 367 return std::nullopt; 368 } 369 SetFrameName(const std::string & frameName)370 void SetFrameName(const std::string& frameName) 371 { 372 frameName_ = frameName; 373 } 374 GetFrameName()375 std::string GetFrameName() const 376 { 377 return frameName_; 378 } 379 HandleAxisEvent(const AxisEvent & event)380 bool HandleAxisEvent(const AxisEvent& event) 381 { 382 if (!onAxisCallback_) { 383 return false; 384 } 385 Offset localLocation = Offset( 386 event.GetOffset().GetX() - coordinateOffset_.GetX(), event.GetOffset().GetY() - coordinateOffset_.GetY()); 387 AxisInfo info = AxisInfo(event, localLocation, GetEventTarget().value_or(EventTarget())); 388 info.SetScreenLocation(Offset(event.screenX, event.screenY)); 389 onAxisCallback_(info); 390 return true; 391 } 392 HandleEvent(const AxisEvent & event)393 virtual void HandleEvent(const AxisEvent& event) {} 394 395 private: 396 OnAxisEventFunc onAxisCallback_; 397 NG::OffsetF coordinateOffset_; 398 GetEventTargetImpl getEventTargetImpl_; 399 std::string frameName_ = "Unknown"; 400 }; 401 402 using AxisTestResult = std::list<RefPtr<AxisEventTarget>>; 403 404 } // namespace OHOS::Ace 405 406 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_AXIS_EVENT_H