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/components_ng/event/event_constants.h" 25 #include "core/event/ace_events.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 60 struct UIInputEvent { 61 virtual ~UIInputEvent() = default; 62 TimeStamp time; 63 UIInputEventType eventType = UIInputEventType::NONE; 64 }; 65 66 67 struct PointerEvent : public UIInputEvent { 68 virtual ~PointerEvent() = default; 69 explicit PointerEvent(float x = {}, float y = {}, float screenX = {}, 70 float screenY = {}, TimeStamp time = {}) xPointerEvent71 :x(x), y(y), screenX(screenX), screenY(screenY) 72 { 73 this->time = time; 74 } 75 float x = {}; 76 float y = {}; 77 float screenX = {}; 78 float screenY = {}; 79 }; 80 81 struct AxisEvent final : public PointerEvent { 82 ~AxisEvent() = default; 83 int32_t id = 0; 84 85 double verticalAxis = 0.0; 86 double horizontalAxis = 0.0; 87 double pinchAxisScale = 0.0; 88 double rotateAxisAngle = 0.0; 89 bool isRotationEvent = false; 90 AxisAction action = AxisAction::NONE; 91 int64_t deviceId = 0; 92 SourceType sourceType = SourceType::NONE; 93 SourceTool sourceTool = SourceTool::UNKNOWN; 94 std::shared_ptr<MMI::PointerEvent> pointerEvent; 95 int32_t touchEventId = 0; 96 std::vector<KeyCode> pressedCodes; 97 98 // Coordinates relative to the upper-left corner of the current component 99 float localX = 0.0; 100 float localY = 0.0; 101 102 int32_t targetDisplayId = 0; 103 int32_t originalId = 0; 104 bool isInjected = false; 105 AxisEventfinal106 AxisEvent() 107 { 108 eventType = UIInputEventType::AXIS; 109 } 110 AxisEventfinal111 AxisEvent(int32_t id, float x, float y, float screenX, float screenY, double verticalAxis, double horizontalAxis, 112 double pinchAxisScale, double rotateAxisAngle, bool isRotationEvent, AxisAction action, TimeStamp timestamp, 113 int64_t deviceId, SourceType sourceType, SourceTool sourceTool, std::shared_ptr<MMI::PointerEvent> pointerEvent, 114 std::vector<KeyCode> pressedCodes, int32_t targetDisplayId, int32_t originalId, bool isInjected) 115 : PointerEvent(x, y, screenX, screenY, timestamp), id(id), verticalAxis(verticalAxis), 116 horizontalAxis(horizontalAxis), pinchAxisScale(pinchAxisScale), rotateAxisAngle(rotateAxisAngle), 117 isRotationEvent(isRotationEvent), action(action), deviceId(deviceId), sourceType(sourceType), 118 sourceTool(sourceTool), pointerEvent(std::move(pointerEvent)), pressedCodes(pressedCodes), 119 targetDisplayId(targetDisplayId), originalId(originalId), isInjected(isInjected) 120 { 121 eventType = UIInputEventType::AXIS; 122 } 123 CreateScaleEventfinal124 AxisEvent CreateScaleEvent(float scale) const 125 { 126 if (NearZero(scale)) { 127 return { id, x, y, screenX, screenY, verticalAxis, horizontalAxis, pinchAxisScale, rotateAxisAngle, 128 isRotationEvent, action, time, deviceId, sourceType, sourceTool, pointerEvent, pressedCodes, 129 targetDisplayId, originalId, isInjected }; 130 } 131 return { id, x / scale, y / scale, screenX / scale, screenY / scale, verticalAxis, horizontalAxis, 132 pinchAxisScale, rotateAxisAngle, isRotationEvent, action, time, deviceId, sourceType, sourceTool, 133 pointerEvent, pressedCodes, targetDisplayId, originalId, isInjected }; 134 } 135 GetOffsetfinal136 Offset GetOffset() const 137 { 138 return Offset(x, y); 139 } 140 GetScreenOffsetfinal141 Offset GetScreenOffset() const 142 { 143 return Offset(screenX, screenY); 144 } 145 GetDirectionfinal146 AxisDirection GetDirection() const 147 { 148 uint32_t verticalFlag = 0; 149 uint32_t horizontalFlag = 0; 150 if (LessNotEqual(verticalAxis, 0.0)) { 151 verticalFlag = static_cast<uint32_t>(AxisDirection::UP); 152 } else if (GreatNotEqual(verticalAxis, 0.0)) { 153 verticalFlag = static_cast<uint32_t>(AxisDirection::DOWN); 154 } 155 if (LessNotEqual(horizontalAxis, 0.0)) { 156 horizontalFlag = static_cast<uint32_t>(AxisDirection::LEFT); 157 } else if (GreatNotEqual(horizontalAxis, 0.0)) { 158 horizontalFlag = static_cast<uint32_t>(AxisDirection::RIGHT); 159 } 160 return static_cast<AxisDirection>(verticalFlag | horizontalFlag); 161 } IsDirectionUpfinal162 static bool IsDirectionUp(AxisDirection direction) 163 { 164 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::UP)); 165 } IsDirectionDownfinal166 static bool IsDirectionDown(AxisDirection direction) 167 { 168 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::DOWN)); 169 } IsDirectionLeftfinal170 static bool IsDirectionLeft(AxisDirection direction) 171 { 172 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::LEFT)); 173 } IsDirectionRightfinal174 static bool IsDirectionRight(AxisDirection direction) 175 { 176 return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::RIGHT)); 177 } 178 179 Offset ConvertToOffset(bool isShiftKeyPressed = false, bool hasDifferentDirectionGesture = false) const 180 { 181 Offset result; 182 if (sourceTool == SourceTool::MOUSE) { 183 // Axis event is made by mouse. 184 if (isShiftKeyPressed) { 185 result = Offset(-verticalAxis, -horizontalAxis); 186 } else { 187 if (hasDifferentDirectionGesture) { 188 result = Offset(-horizontalAxis, -verticalAxis); 189 } else { 190 result = Offset(-verticalAxis, -verticalAxis); 191 } 192 } 193 return result * (LINE_HEIGHT_DESKTOP / MOUSE_WHEEL_DEGREES).ConvertToPx(); 194 } 195 // Axis event is made by others. Include touch-pad. 196 result = Offset(-horizontalAxis, -verticalAxis); 197 return result; 198 } 199 200 // MMI has the different direction, need to check truth direction. ConvertToSummationAxisValuefinal201 std::pair<float, float> ConvertToSummationAxisValue(const AxisEvent& event) const 202 { 203 return std::make_pair(event.horizontalAxis - horizontalAxis, event.verticalAxis - verticalAxis); 204 } 205 }; 206 207 class AxisInfo : public BaseEventInfo { 208 DECLARE_RELATIONSHIP_OF_CLASSES(AxisInfo, BaseEventInfo); 209 210 public: AxisInfo()211 AxisInfo() : BaseEventInfo("onAxis") {} AxisInfo(const AxisEvent & event,const Offset & localLocation,const EventTarget & target)212 AxisInfo(const AxisEvent& event, const Offset& localLocation, const EventTarget& target) : BaseEventInfo("onAxis") 213 { 214 action_ = event.action; 215 verticalAxis_ = static_cast<float>(event.verticalAxis); 216 horizontalAxis_ = static_cast<float>(event.horizontalAxis); 217 pinchAxisScale_ = static_cast<float>(event.pinchAxisScale); 218 rotateAxisAngle_ = static_cast<float>(event.rotateAxisAngle); 219 isRotationEvent_ = event.isRotationEvent; 220 globalLocation_ = event.GetOffset(); 221 localLocation_ = localLocation; 222 screenLocation_ = Offset(); 223 SetTimeStamp(event.time); 224 SetDeviceId(event.deviceId); 225 SetSourceDevice(event.sourceType); 226 SetTarget(target); 227 } 228 ~AxisInfo() override = default; 229 SetAction(AxisAction action)230 void SetAction(AxisAction action) 231 { 232 action_ = action; 233 } 234 GetAction()235 AxisAction GetAction() const 236 { 237 return action_; 238 } 239 SetVerticalAxis(float axis)240 void SetVerticalAxis(float axis) 241 { 242 verticalAxis_ = axis; 243 } 244 GetVerticalAxis()245 float GetVerticalAxis() const 246 { 247 return verticalAxis_; 248 } 249 SetHorizontalAxis(float axis)250 void SetHorizontalAxis(float axis) 251 { 252 horizontalAxis_ = axis; 253 } 254 GetHorizontalAxis()255 float GetHorizontalAxis() const 256 { 257 return horizontalAxis_; 258 } 259 SetPinchAxisScale(float scale)260 void SetPinchAxisScale(float scale) 261 { 262 pinchAxisScale_ = scale; 263 } 264 GetPinchAxisScale()265 float GetPinchAxisScale() const 266 { 267 return pinchAxisScale_; 268 } 269 SetRotateAxisAngle(float angle)270 void SetRotateAxisAngle(float angle) 271 { 272 rotateAxisAngle_ = angle; 273 } 274 GetRotateAxisAngle()275 float GetRotateAxisAngle() const 276 { 277 return rotateAxisAngle_; 278 } 279 SetIsRotationEvent(bool rotationFlag)280 void SetIsRotationEvent(bool rotationFlag) 281 { 282 isRotationEvent_ = rotationFlag; 283 } 284 GetIsRotationEvent()285 bool GetIsRotationEvent() const 286 { 287 return isRotationEvent_; 288 } 289 SetGlobalLocation(const Offset & globalLocation)290 AxisInfo& SetGlobalLocation(const Offset& globalLocation) 291 { 292 globalLocation_ = globalLocation; 293 return *this; 294 } SetLocalLocation(const Offset & localLocation)295 AxisInfo& SetLocalLocation(const Offset& localLocation) 296 { 297 localLocation_ = localLocation; 298 return *this; 299 } 300 SetScreenLocation(const Offset & screenLocation)301 AxisInfo& SetScreenLocation(const Offset& screenLocation) 302 { 303 screenLocation_ = screenLocation; 304 return *this; 305 } 306 GetScreenLocation()307 const Offset& GetScreenLocation() const 308 { 309 return screenLocation_; 310 } 311 GetLocalLocation()312 const Offset& GetLocalLocation() const 313 { 314 return localLocation_; 315 } GetGlobalLocation()316 const Offset& GetGlobalLocation() const 317 { 318 return globalLocation_; 319 } 320 ConvertToAxisEvent()321 AxisEvent ConvertToAxisEvent() const 322 { 323 AxisEvent axisEvent; 324 axisEvent.x = static_cast<float>(globalLocation_.GetX()); 325 axisEvent.y = static_cast<float>(globalLocation_.GetY()); 326 axisEvent.screenX = static_cast<float>(screenLocation_.GetX()); 327 axisEvent.screenY = static_cast<float>(screenLocation_.GetY()); 328 axisEvent.horizontalAxis = horizontalAxis_; 329 axisEvent.verticalAxis = verticalAxis_; 330 axisEvent.pinchAxisScale = pinchAxisScale_; 331 axisEvent.action = action_; 332 axisEvent.rotateAxisAngle = rotateAxisAngle_; 333 axisEvent.time = timeStamp_; 334 axisEvent.localX = static_cast<float>(localLocation_.GetX()); 335 axisEvent.localY = static_cast<float>(localLocation_.GetY()); 336 axisEvent.sourceType = deviceType_; 337 axisEvent.sourceTool = sourceTool_; 338 return axisEvent; 339 } 340 341 private: 342 AxisAction action_ = AxisAction::NONE; 343 float verticalAxis_ = 0.0; 344 float horizontalAxis_ = 0.0; 345 float pinchAxisScale_ = 0.0; 346 float rotateAxisAngle_ = 0.0; 347 bool isRotationEvent_ = false; 348 // global position at which the touch point contacts the screen. 349 Offset globalLocation_; 350 // Different from global location, The local location refers to the location of the contact point relative to the 351 // current node which has the recognizer. 352 Offset localLocation_; 353 Offset screenLocation_; 354 }; 355 356 using OnAxisEventFunc = std::function<void(AxisInfo&)>; 357 using GetEventTargetImpl = std::function<std::optional<EventTarget>()>; 358 359 class AxisEventTarget : public virtual AceType { 360 DECLARE_ACE_TYPE(AxisEventTarget, AceType); 361 362 public: 363 AxisEventTarget() = default; AxisEventTarget(std::string frameName)364 AxisEventTarget(std::string frameName) : frameName_(std::move(frameName)) {} 365 ~AxisEventTarget() override = default; 366 SetOnAxisCallback(const OnAxisEventFunc & onAxisCallback)367 void SetOnAxisCallback(const OnAxisEventFunc& onAxisCallback) 368 { 369 onAxisCallback_ = onAxisCallback; 370 } 371 SetCoordinateOffset(const NG::OffsetF & coordinateOffset)372 void SetCoordinateOffset(const NG::OffsetF& coordinateOffset) 373 { 374 coordinateOffset_ = coordinateOffset; 375 } 376 SetGetEventTargetImpl(const GetEventTargetImpl & getEventTargetImpl)377 void SetGetEventTargetImpl(const GetEventTargetImpl& getEventTargetImpl) 378 { 379 getEventTargetImpl_ = getEventTargetImpl; 380 } 381 GetEventTarget()382 std::optional<EventTarget> GetEventTarget() const 383 { 384 if (getEventTargetImpl_) { 385 return getEventTargetImpl_(); 386 } 387 return std::nullopt; 388 } 389 SetFrameName(const std::string & frameName)390 void SetFrameName(const std::string& frameName) 391 { 392 frameName_ = frameName; 393 } 394 GetFrameName()395 std::string GetFrameName() const 396 { 397 return frameName_; 398 } 399 HandleAxisEvent(const AxisEvent & event)400 bool HandleAxisEvent(const AxisEvent& event) 401 { 402 if (!onAxisCallback_) { 403 return false; 404 } 405 Offset localLocation = Offset( 406 event.GetOffset().GetX() - coordinateOffset_.GetX(), event.GetOffset().GetY() - coordinateOffset_.GetY()); 407 AxisInfo info = AxisInfo(event, localLocation, GetEventTarget().value_or(EventTarget())); 408 info.SetScreenLocation(Offset(event.screenX, event.screenY)); 409 info.SetSourceTool(event.sourceTool); 410 onAxisCallback_(info); 411 return true; 412 } 413 HandleEvent(const AxisEvent & event)414 virtual void HandleEvent(const AxisEvent& event) {} 415 416 private: 417 OnAxisEventFunc onAxisCallback_; 418 NG::OffsetF coordinateOffset_; 419 GetEventTargetImpl getEventTargetImpl_; 420 std::string frameName_ = "Unknown"; 421 }; 422 423 using AxisTestResult = std::list<RefPtr<AxisEventTarget>>; 424 425 } // namespace OHOS::Ace 426 427 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_AXIS_EVENT_H