From b51f532f9ea35fa663c73ddd39edece3bc2412e3 Mon Sep 17 00:00:00 2001 From: fanzexuan Date: Fri, 30 May 2025 20:02:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B1=80=E9=83=A8=E6=94=BE=E5=A4=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: fanzexuan --- frameworks/aafwk/test/BUILD.gn | 6 + .../common/include/accessibility_def.h | 2 + services/aams/BUILD.gn | 5 + .../include/accessibility_input_interceptor.h | 13 +- .../include/accessibility_touch_exploration.h | 2 - .../include/accessibility_window_manager.h | 9 + .../aams/include/accessibility_zoom_gesture.h | 14 +- .../accessible_ability_manager_service.h | 13 + .../full_screen_magnification_manager.h | 78 ++ services/aams/include/magnification_def.h | 56 ++ services/aams/include/magnification_manager.h | 45 + .../aams/include/magnification_menu_manager.h | 88 ++ services/aams/include/utils.h | 2 + .../include/window_magnification_gesture.h | 206 ++++ .../include/window_magnification_manager.h | 106 +++ .../src/accessibility_input_interceptor.cpp | 84 +- .../src/accessibility_settings_config.cpp | 5 +- .../aams/src/accessibility_zoom_gesture.cpp | 226 +++-- .../accessible_ability_manager_service.cpp | 140 ++- .../src/full_screen_magnification_manager.cpp | 344 +++++++ services/aams/src/magnification_manager.cpp | 169 ++++ .../aams/src/magnification_menu_manager.cpp | 304 ++++++ services/aams/src/utils.cpp | 6 + .../aams/src/window_magnification_gesture.cpp | 881 ++++++++++++++++++ .../aams/src/window_magnification_manager.cpp | 433 +++++++++ services/aams/test/BUILD.gn | 77 ++ .../mock_accessibility_display_manager.cpp | 1 - .../mock_accessibility_input_interceptor.cpp | 5 + ...ock_accessible_ability_manager_service.cpp | 40 + .../accessibility_zoom_gesture_test.cpp | 4 +- services/test/BUILD.gn | 30 + 31 files changed, 3252 insertions(+), 142 deletions(-) create mode 100644 services/aams/include/full_screen_magnification_manager.h create mode 100644 services/aams/include/magnification_def.h create mode 100644 services/aams/include/magnification_manager.h create mode 100644 services/aams/include/magnification_menu_manager.h create mode 100644 services/aams/include/window_magnification_gesture.h create mode 100644 services/aams/include/window_magnification_manager.h create mode 100644 services/aams/src/full_screen_magnification_manager.cpp create mode 100644 services/aams/src/magnification_manager.cpp create mode 100644 services/aams/src/magnification_menu_manager.cpp create mode 100644 services/aams/src/window_magnification_gesture.cpp create mode 100644 services/aams/src/window_magnification_manager.cpp diff --git a/frameworks/aafwk/test/BUILD.gn b/frameworks/aafwk/test/BUILD.gn index 0275993b..c663d287 100755 --- a/frameworks/aafwk/test/BUILD.gn +++ b/frameworks/aafwk/test/BUILD.gn @@ -125,6 +125,11 @@ ohos_unittest("accessible_ability_test") { "../../../services/aams/src/accessible_ability_manager_service.cpp", "../../../services/aams/src/accessible_ability_manager_service_event_handler.cpp", "../../../services/aams/src/utils.cpp", + "../../../services/aams/src/magnification_manager.cpp", + "../../../services/aams/src/window_magnification_gesture.cpp", + "../../../services/aams/src/magnification_menu_manager.cpp", + "../../../services/aams/src/full_screen_magnification_manager.cpp", + "../../../services/aams/src/window_magnification_manager.cpp", "../../../services/aams/test/mock/src/mock_accessibility_account_data.cpp", "../../../services/aams/test/mock/src/mock_accessibility_common_event.cpp", "../../../services/aams/test/mock/src/mock_accessibility_event_transmission.cpp", @@ -188,6 +193,7 @@ ohos_unittest("accessible_ability_test") { "ffrt:libffrt", "googletest:gmock_main", "googletest:gtest_main", + "graphic_2d:2d_graphics", "graphic_2d:librender_service_client", "graphic_2d:librender_service_base", "hicollie:libhicollie", diff --git a/interfaces/innerkits/common/include/accessibility_def.h b/interfaces/innerkits/common/include/accessibility_def.h index b888313d..8c455b82 100644 --- a/interfaces/innerkits/common/include/accessibility_def.h +++ b/interfaces/innerkits/common/include/accessibility_def.h @@ -390,6 +390,8 @@ constexpr int32_t CODE_SUCCESS = 0; constexpr int32_t CODE_FAILED = -1; constexpr int32_t CHAE_BUFFER_MAX = 1024; constexpr int32_t US_TO_MS = 1000; +constexpr float COMPLEX_UNIT_MM_CONVERSION = 1.0f / 25.4f; +constexpr int32_t MM_PER_CM = 10; enum class NAccessibilityErrorCode : int32_t { ACCESSIBILITY_OK = 0, diff --git a/services/aams/BUILD.gn b/services/aams/BUILD.gn index b966f054..cbc759c5 100644 --- a/services/aams/BUILD.gn +++ b/services/aams/BUILD.gn @@ -74,6 +74,11 @@ accessibleabilityms_files = [ "${services_path}/src/touch_exploration_multi_finger_gesture.cpp", "${services_path}/src/touch_exploration_single_finger_gesture.cpp", "${services_path}/src/utils.cpp", + "${services_path}/src/magnification_manager.cpp", + "${services_path}/src/window_magnification_manager.cpp", + "${services_path}/src/window_magnification_gesture.cpp", + "${services_path}/src/magnification_menu_manager.cpp", + "${services_path}/src/full_screen_magnification_manager.cpp", ] ohos_shared_library("accessibleabilityms") { diff --git a/services/aams/include/accessibility_input_interceptor.h b/services/aams/include/accessibility_input_interceptor.h index b8f421c5..170e88e4 100644 --- a/services/aams/include/accessibility_input_interceptor.h +++ b/services/aams/include/accessibility_input_interceptor.h @@ -29,6 +29,7 @@ #include "input_manager.h" #include "key_event.h" #include "pointer_event.h" +#include "window_magnification_gesture.h" namespace OHOS { namespace Accessibility { @@ -82,13 +83,7 @@ public: // flag = true shield zoom gesture | flag = false restore zoom gesture void ShieldZoomGesture(bool flag); void RefreshDisplayInfo(); - inline ACCESSIBILITY_ZOOM_STATE GetZoomState() - { - if (zoomGesture_) { - return zoomGesture_->GetZoomState(); - } - return READY_STATE; - } + void StartMagnificationInteract(uint32_t mode); private: AccessibilityInputInterceptor(); @@ -101,6 +96,8 @@ private: const sptr &next); void UpdateInterceptor(); void DestroyInterceptor(); + void CreateMagnificationGesture(sptr &header, sptr ¤t); + void ClearMagnificationGesture(); sptr pointerEventTransmitters_ = nullptr; sptr keyEventTransmitters_ = nullptr; @@ -113,6 +110,8 @@ private: ffrt::mutex mutex_; sptr zoomGesture_ = nullptr; + sptr windowMagnificationGesture_ = nullptr; + bool needInteractMagnification_ = false; }; } // namespace Accessibility } // namespace OHOS diff --git a/services/aams/include/accessibility_touch_exploration.h b/services/aams/include/accessibility_touch_exploration.h index 3dbb8cb2..0c6b2c4e 100644 --- a/services/aams/include/accessibility_touch_exploration.h +++ b/services/aams/include/accessibility_touch_exploration.h @@ -46,12 +46,10 @@ const float MULTI_TAP_SLOP = 100.0f; const float MULTI_TAP_SLOP_DELTA = 0.5f; const int32_t SCREEN_AXIS_NUM = 2; const double MAX_DRAG_GESTURE_COSINE = 0.525321989; -const int32_t MM_PER_CM = 10; const double EPSINON = 0.01; const float PIXEL_MULTIPLIER = 0.1f; const int32_t DIVIDE_NUM = 2; const uint32_t FIND_FOCUS_TIMEOUT = 50; -const float COMPLEX_UNIT_MM_CONVERSION = 1.0f / 25.4f; const int32_t SIMULATE_POINTER_ID = 10000; #define BIND(func) [this](MMI::PointerEvent& event) { (func(event)); } diff --git a/services/aams/include/accessibility_window_manager.h b/services/aams/include/accessibility_window_manager.h index b955e676..23676083 100644 --- a/services/aams/include/accessibility_window_manager.h +++ b/services/aams/include/accessibility_window_manager.h @@ -121,6 +121,15 @@ private: AccessibilityWindowManager &windInfoMgr_; }; + class WindowRotationChangeListener : public Rosen::IWindowRotationChangeListener { + public: + explicit WindowRotationChangeListener(); + ~WindowRotationChangeListener() = default; + + virtual void OnRotationChange(const Rosen::RotationChangeInfo& rotationChangeInfo, + Rosen::RotationChangeResult& rotationChangeResult) override; + }; + bool CompareRect(const Rect &rectAccessibility, const Rosen::Rect &rectWindow); bool EqualFocus(const Accessibility::AccessibilityWindowInfo &accWindowInfo, const sptr &windowInfo); diff --git a/services/aams/include/accessibility_zoom_gesture.h b/services/aams/include/accessibility_zoom_gesture.h index 444b2b66..309846a7 100644 --- a/services/aams/include/accessibility_zoom_gesture.h +++ b/services/aams/include/accessibility_zoom_gesture.h @@ -20,13 +20,15 @@ #include "event_handler.h" #include "pointer_event.h" #include "dm_common.h" +#include "full_screen_magnification_manager.h" namespace OHOS { namespace Accessibility { enum ACCESSIBILITY_ZOOM_STATE { READY_STATE, ZOOMIN_STATE, - SLIDING_STATE + SLIDING_STATE, + MENU_SLIDING_STATE }; enum ACCESSIBILITY_ZOOM_GESTURE_MSG : uint32_t { @@ -40,7 +42,7 @@ struct ZOOM_FOCUS_COORDINATE { class AccessibilityZoomGesture : public EventTransmission { public: - AccessibilityZoomGesture(); + AccessibilityZoomGesture(std::shared_ptr fullScreenManager); ~AccessibilityZoomGesture() = default; virtual bool OnPointerEvent(MMI::PointerEvent &event) override; @@ -48,6 +50,7 @@ public: // flag = true shield zoom gesture | flag = false restore zoom gesture void ShieldZoomGesture(bool state); void GetWindowParam(bool needRefresh = false); + void StartMagnificationInteract(); inline ACCESSIBILITY_ZOOM_STATE GetZoomState() { return state_; @@ -73,6 +76,7 @@ private: void RecognizeInZoomStateDownEvent(MMI::PointerEvent &event); void RecognizeInZoomState(MMI::PointerEvent &event); void RecognizeInSlidingState(MMI::PointerEvent &event); + void RecognizeInMenuSlidingState(MMI::PointerEvent &event); void RecognizeScroll(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE &coordinate); void RecognizeScale(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE &coordinate); void CalcFocusCoordinate(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE &coordinate); @@ -109,6 +113,8 @@ private: uint32_t screenHeight_ = 0; float anchorPointX_ = 0.0f; float anchorPointY_ = 0.0f; + int32_t centerX_ = 0; + int32_t centerY_ = 0; float scaleRatio_ = 2.0f; int32_t downPid_ = -1; ACCESSIBILITY_ZOOM_STATE state_ = READY_STATE; @@ -120,10 +126,14 @@ private: std::shared_ptr lastUpEvent_ = nullptr; std::shared_ptr currentMoveEvent_ = nullptr; std::shared_ptr longPressDownEvent_ = nullptr; + std::shared_ptr lastSlidingEvent_ = nullptr; std::shared_ptr zoomGestureEventHandler_ = nullptr; std::vector> cacheEvents_; + std::shared_ptr fullScreenManager_ = nullptr; std::atomic shieldZoomGestureFlag_ = false; + bool isTapOnMenu_ = false; + uint32_t gestureType_ = 0; }; } // namespace Accessibility } // namespace OHOS diff --git a/services/aams/include/accessible_ability_manager_service.h b/services/aams/include/accessible_ability_manager_service.h index 3a28d69e..74701423 100644 --- a/services/aams/include/accessible_ability_manager_service.h +++ b/services/aams/include/accessible_ability_manager_service.h @@ -43,6 +43,7 @@ #include "accessibility_short_key.h" #include "accessibility_resource_bundle_manager.h" #include "refbase.h" +#include "magnification_manager.h" namespace OHOS { namespace Accessibility { @@ -315,6 +316,16 @@ public: void OnDataClone(); bool CheckPermission(const std::string &permission) const; + // for magnification + uint32_t GetMagnificationType(); + uint32_t GetMagnificationMode(); + void SetMagnificationMode(int32_t mode); + float GetMagnificationScale(); + void SetMagnificationScale(float scale); + std::shared_ptr GetMagnificationMgr(); + std::shared_ptr GetWindowMagnificationManager(); + std::shared_ptr GetFullScreenMagnificationManager(); + private: void StopCallbackWait(int32_t windowId); void StopCallbackWait(int32_t windowId, int32_t treeId); @@ -443,6 +454,7 @@ private: int32_t ApplyTreeId(); void RecycleTreeId(int32_t treeId); + std::shared_ptr GetCurrentAcountDatashareHelper(); bool isReady_ = false; bool isPublished_ = false; @@ -500,6 +512,7 @@ private: bool isSubscribeMSDPCallback_ = false; ffrt::mutex subscribeMSDPMutex_; + std::shared_ptr magnificationManager_ = nullptr; }; } // namespace Accessibility } // namespace OHOS diff --git a/services/aams/include/full_screen_magnification_manager.h b/services/aams/include/full_screen_magnification_manager.h new file mode 100644 index 00000000..413a5c95 --- /dev/null +++ b/services/aams/include/full_screen_magnification_manager.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FULL_SCREEN_MAGNIFICATION_MANAGER_H +#define FULL_SCREEN_MAGNIFICATION_MANAGER_H + +#include "window.h" +#include "window_option.h" +#include +#include +#include +#include "ui/rs_ui_director.h" +#include "ui/rs_root_node.h" +#include "recording/recording_canvas.h" +#include "hilog_wrapper.h" +#include "magnification_def.h" + +namespace OHOS { +namespace Accessibility { + +class FullScreenMagnificationManager { +public: + FullScreenMagnificationManager(); + ~FullScreenMagnificationManager() = default; + + void CreateMagnificationWindow(); + void DrawRuoundRectFrame(); + void EnableMagnification(int32_t centerX, int32_t centerY); + void ShowMagnification(); + void DisableMagnification(); + PointerPos ConvertCoordinates(int32_t posX, int32_t posY); + void RefreshWindowParam(); + void SetScale(float scaleSpan); + void MoveMagnification(int32_t deltaX, int32_t deltaY); + void PersistScale(); + PointerPos ConvertGesture(uint32_t type, PointerPos coordinates); + uint32_t CheckTapOnHotArea(int32_t posX, int32_t posY); + inline bool isMagnificationWindowShow() + { + return isMagnificationWindowShow_; + } +private: + void GetWindowParam(); + void InitMagnificationParam(); + Rosen::Rect GetSourceRectFromPointer(int32_t centerX, int32_t centerY); + void UpdateAnchor(); + sptr window_ = nullptr; + std::shared_ptr surfaceNode_; + std::shared_ptr canvasNode_; + bool isMagnificationWindowShow_ = false; + + Rosen::Rect sourceRect_; + Rosen::Rect windowRect_; + Rosen::Rect screenRect_; + uint32_t screenWidth_ = 0; + uint32_t screenHeight_ = 0; + float screenSpan_ = 0.0f; + uint64_t screenId_ = 0; + Rosen::DisplayOrientation orientation_ = Rosen::DisplayOrientation::UNKNOWN; + int32_t centerX_ = 0; + int32_t centerY_ = 0; + float scale_ = 2.0f; +}; +} // namespace Accessibility +} // namespace OHOS +#endif // FULL_SCREEN_MAGNIFICATION_MANAGER_H \ No newline at end of file diff --git a/services/aams/include/magnification_def.h b/services/aams/include/magnification_def.h new file mode 100644 index 00000000..9158ff4c --- /dev/null +++ b/services/aams/include/magnification_def.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MAGNIFICATION_MANAGER_DEF_H +#define MAGNIFICATION_MANAGER_DEF_H + +namespace OHOS { +namespace Accessibility { + +struct PointerPos { + int32_t posX; + int32_t posY; +}; + +constexpr float EPS = 1e-6; +constexpr float DEFAULT_SCALE = 2.0f; +constexpr float MAX_SCALE = 8.0f; +constexpr uint8_t BG_ALPHA = 254; +constexpr float CORNER_RADIUS = 75.0f; +constexpr float MENU_CORNER_RADIUS = 25.0f; +constexpr float PEN_WIDTH = 10.0f; +constexpr int32_t DIVISOR_TWO = 2; +constexpr int32_t ROUND_RECT_MARGIN = 5; +constexpr int32_t ANCHOR_OFFSET = 20; +constexpr float HALF = 0.5f; +constexpr float MIN_SCALE_DISTANCE = 200.0f; + +const std::string WINDOW_NAME = "magnification_window"; +const std::string MENU_NAME = "magnification_menu"; + +constexpr uint32_t FULL_SCREEN_MAGNIFICATION = 1; +constexpr uint32_t WINDOW_MAGNIFICATION = 2; +constexpr uint32_t SWITCH_MAGNIFICATION = 3; +constexpr uint32_t INPUT_METHOD_WINDOW_TYPE = 2105; +constexpr uint32_t ORANGE_COLOR = 0xFFFFA500; + +constexpr uint32_t INVALID_GESTURE_TYPE = 0; +constexpr uint32_t LEFT_BACK_GESTURE = 1; // Swipe from the left side of the screen inward +constexpr uint32_t RIGHT_BACK_GESTURE = 2; // Swipe from the right side of the screen inward +constexpr uint32_t BOTTOM_BACK_GESTURE = 3; // Swipe from the bottom side of the screen inward + +} // namespace Accessibility +} // namespace OHOS +#endif // MAGNIFICATION_MANAGER_DEF_H \ No newline at end of file diff --git a/services/aams/include/magnification_manager.h b/services/aams/include/magnification_manager.h new file mode 100644 index 00000000..7e465370 --- /dev/null +++ b/services/aams/include/magnification_manager.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MAGNIFICATION_MANAGER_H +#define MAGNIFICATION_MANAGER_H + +#include "window_magnification_manager.h" +#include "full_screen_magnification_manager.h" + +namespace OHOS { +namespace Accessibility { +class MagnificationManager { +public: + MagnificationManager(); + ~MagnificationManager() = default; + + std::shared_ptr GetWindowMagnificationManager(); + std::shared_ptr GetFullScreenMagnificationManager(); + void OnMagnificationTypeChanged(uint32_t magnificationType); + void OnModeChanged(uint32_t mode); + void DisableMagnification(); + void SetMagnificationState(bool isEnabled); + bool GetMagnificationState(); + void RefreshWindowParam(); +private: + std::shared_ptr windowMagnificationManager_ = nullptr; + std::shared_ptr fullScreenMagnificationManager_ = nullptr; + uint32_t currentMode_ = 0; + bool isMagnificationEnabled_ = false; +}; +} // namespace Accessibility +} // namespace OHOS +#endif // MAGNIFICATION_MANAGER_H \ No newline at end of file diff --git a/services/aams/include/magnification_menu_manager.h b/services/aams/include/magnification_menu_manager.h new file mode 100644 index 00000000..41268489 --- /dev/null +++ b/services/aams/include/magnification_menu_manager.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MAGNIFICATION_MENU_MANAGER_H +#define MAGNIFICATION_MENU_MANAGER_H + +#include "hilog_wrapper.h" +#include "window.h" +#include "window_option.h" +#include +#include +#include +#include "ui/rs_ui_director.h" +#include "ui/rs_root_node.h" +#include "recording/recording_canvas.h" +#include "image_source.h" +#include "pixel_map.h" +#include "magnification_manager.h" + +namespace OHOS { +namespace Accessibility { + +class MagnificationMenuManager { +public: + static std::shared_ptr menuMgr_; + static std::shared_ptr GetInstance(); + static void DeleteInstance(); + + MagnificationMenuManager(); + DISALLOW_COPY_AND_MOVE(MagnificationMenuManager); + ~MagnificationMenuManager(); + + void ShowMenuWindow(uint32_t mode); + void DisableMenuWindow(); + bool IsTapOnMenu(int32_t posX, int32_t posY); + void SetCurrentType(uint32_t type); + void OnMenuTap(); + void MoveMenuWindow(int32_t deltaX, int32_t deltaY); + void AttachToEdge(); + void RefreshWindowParam(); + +private: + void GetWindowParam(); + void CreateMenuWindow(); + void LoadMenuBgImage(uint32_t mode); + void ChangeMode(); + void AdjustMeunPosition(); + std::shared_ptr DecodePixelMap(const std::string& pathName, + const Media::AllocatorType& allocatorType); + //menu window + sptr menuWindow_ = nullptr; + std::shared_ptr surfaceNode_; + std::shared_ptr canvasNode_; + Media::AllocatorType allocatorType_ = Media::AllocatorType::DMA_ALLOC; + std::shared_ptr bgpixelmap_ = nullptr; + std::shared_ptr rosenImage_ = nullptr; + std::shared_ptr manager_ = nullptr; + + Rosen::Rect menuRect_; + Rosen::Rect screenRect_; + + uint32_t menuSize_ = 150; + int32_t margin_ = 50; + uint64_t screenId_ = 0; + uint32_t screenWidth_ = 0; + uint32_t screenHeight_ = 0; + Rosen::DisplayOrientation orientation_ = Rosen::DisplayOrientation::UNKNOWN; + + uint32_t meunMode_ = 0; + uint32_t currentType_ = 0; + bool isMenuShown_ = false; +}; + +} // namespace Accessibility +} // namespace OHOS +#endif // MAGNIFICATION_MENU_MANAGER_H \ No newline at end of file diff --git a/services/aams/include/utils.h b/services/aams/include/utils.h index db9a013c..1445a54b 100644 --- a/services/aams/include/utils.h +++ b/services/aams/include/utils.h @@ -19,6 +19,7 @@ #include "accessibility_ability_info.h" #include "element_name.h" #include "extension_ability_info.h" +#include "window.h" namespace OHOS { namespace Accessibility { @@ -75,6 +76,7 @@ public: const std::string &bundleName = "", const std::string &abilityName = ""); static bool isWideFold(); static bool isBigFold(); + static bool IsInRect(int32_t posX, int32_t posY, Rosen::Rect rect); private: static std::string TransferUnavailableEventToString(A11yUnavailableEvent type); diff --git a/services/aams/include/window_magnification_gesture.h b/services/aams/include/window_magnification_gesture.h new file mode 100644 index 00000000..855b5bb9 --- /dev/null +++ b/services/aams/include/window_magnification_gesture.h @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MAGNIFICATION_GESTURE_H +#define MAGNIFICATION_GESTURE_H + +#include "accessibility_event_transmission.h" +#include "window_magnification_manager.h" +#include "hilog_wrapper.h" + +namespace OHOS { +namespace Accessibility { +class WindowMagnificationGesture; + +#define BIND(func) [this](MMI::PointerEvent& event) { (func(event)); } + +enum class MagnificationGestureState : uint32_t { + PASSING_THROUGH, + INVALID, + READY_STATE, + READY_STATE_ONE_FINGER_DOWN, + READY_STATE_ONE_FINGER_TAP, + ZOOMIN_STATE, + ZOOMIN_STATE_ONE_FINGER_DOWN, + ZOOMIN_STATE_ONE_FINGER_TAP, + ZOOMIN_STATE_TWO_FINGERS_DOWN, + SLIDING_STATE, + TWO_FINGERS_SLIDING_STATE, + MENU_SLIDING_STATE, +}; + +enum class MagnificationState : uint32_t { + MAGNIFICATION_READY_STATE, + MAGNIFICATION_ZOOMIN_STATE, + MAGNIFICATION_SLIDING_STATE +}; + +enum class PointerCountSize : int32_t { + POINTER_SIZE_1 = 1, + POINTER_SIZE_2 = 2 +}; + +enum class MagnificationGestureMsg : uint32_t { + SINGLE_TAP_FAIL_MSG, + TRIPLE_TAP_FAIL_MSG, + LONG_PRESS_MSG, + WAIT_ANOTHER_FINGER_DOWN_MSG, +}; + +// ms +enum class MagnificationTimeout : uint32_t { + TAP_TIMEOUT = 100, + DOUBLE_TAP_TIMEOUT = 250, + LONG_PRESS_TIMEOUT = 200, +}; + +class MagnificationGestureEventHandler : public AppExecFwk::EventHandler { +public: + MagnificationGestureEventHandler(const std::shared_ptr &runner, + WindowMagnificationGesture &server); + virtual ~MagnificationGestureEventHandler() = default; + /** + * @brief Process the event of install system bundles. + * @param event Indicates the event to be processed. + */ + virtual void ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) override; + +private: + WindowMagnificationGesture &server_; +}; + +class WindowMagnificationGesture : public EventTransmission { +public: + WindowMagnificationGesture(); + explicit WindowMagnificationGesture(std::shared_ptr windowMagnificationManager); + ~WindowMagnificationGesture() = default; + + bool OnPointerEvent(MMI::PointerEvent &event) override; + void DestroyEvents() override; + + void CancelPostEvent(MagnificationGestureMsg msg); + void SendCacheEventsToNext(); + void ShieldZoomGesture(bool state); + void StartMagnificationInteract(); + + /* Set current magnification gesture state */ + inline void SetGestureState(MagnificationGestureState state, int32_t action) + { + HILOG_INFO("gestureState changed: [%{public}d] -> [%{public}d], current action: %{public}d.", + gestureState_, state, action); + gestureState_ = state; + } + + /* Get current magnification gesture state */ + inline MagnificationGestureState GetGestureState() + { + return gestureState_; + } + + inline void AddTapCount() + { + tapCount_++; + HILOG_INFO("add tap count, current count = [%{public}d].", tapCount_); + } + + inline void ResetTapCount() + { + tapCount_ = 0; + HILOG_INFO("reset tap count = 0"); + } + + inline uint32_t GetTapCount() + { + HILOG_INFO("get tap count = [%{public}d].", tapCount_); + return tapCount_; + } + + inline bool GetTapOnMenu() + { + return isTapOnMenu_; + } +private: + bool needBypassPointerEvent(MMI::PointerEvent &event); + + void OnPointerEventExcute(MMI::PointerEvent &event); + + void HandlePassingThroughState(MMI::PointerEvent &event); + + void HandleReadyStateDown(MMI::PointerEvent &event); + void HandleReadyStateUp(MMI::PointerEvent &event); + void HandleReadyStateMove(MMI::PointerEvent &event); + void HandleReadyStateOneFingerDownStateDown(MMI::PointerEvent &event); + void HandleReadyStateOneFingerDownStateUp(MMI::PointerEvent &event); + void HandleReadyStateOneFingerDownStateMove(MMI::PointerEvent &event); + void HandleReadyStateOneFingerTapDown(MMI::PointerEvent &event); + + void HandleZoomInStateDown(MMI::PointerEvent &event); + void HandleZoomInStateUp(MMI::PointerEvent &event); + void HandleZoomInStateMove(MMI::PointerEvent &event); + void HandleZoomInStateOneFingerDownStateDown(MMI::PointerEvent &event); + void HandleZoomInStateOneFingerDownStateUp(MMI::PointerEvent &event); + void HandleZoomInStateOneFingerDownStateMove(MMI::PointerEvent &event); + void HandleZoomInStateOneFingerTapDown(MMI::PointerEvent &event); + + void HandleTwoFingersDownStateUp(MMI::PointerEvent &event); + void HandleTwoFingersDownStateMove(MMI::PointerEvent &event); + + void HandleSlidingStateDown(MMI::PointerEvent &event); + void HandleSlidingStateUp(MMI::PointerEvent &event); + void HandleSlidingStateMove(MMI::PointerEvent &event); + + void HandleMenuSlidingStateUp(MMI::PointerEvent &event); + void HandleMenuSlidingStateMove(MMI::PointerEvent &event); + + void InitGestureFuncMap(); + + bool IsMove(MMI::PointerEvent &startEvent, MMI::PointerEvent &endEvent, float slop); + void Clear(); + void OnTripleTap(int32_t centerX, int32_t centerY); + void SendEventToMultimodal(MMI::PointerEvent event, bool needTransfer, bool needResetTime); + bool IsTapOnInputMethod(MMI::PointerEvent &event); + inline float CalculateMoveThreshold(int dpi) + { + return dpi * COMPLEX_UNIT_MM_CONVERSION * MM_PER_CM; + } + + std::shared_ptr handler_ = nullptr; + std::shared_ptr runner_ = nullptr; + std::shared_ptr windowMagnificationManager_ = nullptr; + MagnificationState magnificationState_ = MagnificationState::MAGNIFICATION_READY_STATE; + MagnificationGestureState gestureState_ = MagnificationGestureState::READY_STATE; + + using HandleEventFunc = std::function; + std::map> handleEventFuncMap_ {}; + std::list receivedPointerEvents_ {}; + std::shared_ptr lastDownEvent_ = nullptr; + std::shared_ptr lastSlidingEvent_ = nullptr; + bool isTapOnHotArea_ = false; + bool isSingleTapOnWindow_ = false; + bool isDoubleFingersValid_ = false; + bool startScale_ = false; + bool isTapOnMenu_ = false; + + float moveThreshold_ = 0.0f; + float tapDistance_ = 0.0f; + float multiTapDistance_ = 0.0f; + + uint32_t tapCount_ = 0; + float distance_ = 0.0f; + bool shieldZoomGestureFlag_ = false; +}; +} // namespace Accessibility +} // namespace OHOS +#endif // MAGNIFICATION_GESTURE_H \ No newline at end of file diff --git a/services/aams/include/window_magnification_manager.h b/services/aams/include/window_magnification_manager.h new file mode 100644 index 00000000..97fdd60d --- /dev/null +++ b/services/aams/include/window_magnification_manager.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINDOW_MAGNIFICATION_MANAGER_H +#define WINDOW_MAGNIFICATION_MANAGER_H + +#include "window.h" +#include "window_option.h" +#include +#include +#include +#include "ui/rs_ui_director.h" +#include "ui/rs_root_node.h" +#include "recording/recording_canvas.h" +#include "hilog_wrapper.h" +#include "magnification_def.h" + +namespace OHOS { +namespace Accessibility { + +struct RectBound { + uint32_t width; + uint32_t height; +}; + +class WindowMagnificationManager { +public: + WindowMagnificationManager(); + ~WindowMagnificationManager() = default; + + void OnMagnificationModeChanged(uint32_t magnificationMode); + + inline bool isMagnificationWindowShow() + { + return isMagnificationWindowShow_; + } + inline float GetScale() + { + return scale_; + } + + void CreateMagnificationWindow(int32_t posX, int32_t posY); + void DrawRuoundRectFrame(); + void EnableWindowMagnification(int32_t centerX, int32_t centerY); + void ShowWindowMagnification(); + void DisableWindowMagnification(); + void SetScale(float deltaSpan); + void MoveMagnificationWindow(int32_t deltaX, int32_t deltaY); + void InitMagnificationParam(); + bool IsTapOnHotArea(int32_t posX, int32_t posY); + bool IsTapOnMagnificationWindow(int32_t posX, int32_t posY); + PointerPos ConvertCoordinates(int32_t posX, int32_t posY); + void FixSourceCenter(bool needFix); + void PersistScale(); + void RefreshWindowParam(); + +private: + PointerPos ConvertCenterToTopLeft(int32_t centerX, int32_t centerY); + RectBound GenRectBound(uint32_t width, uint32_t height); + Rosen::Rect GetSourceRectFromPointer(int32_t centerX, int32_t centerY); + Rosen::Rect GetWindowRectFromPointer(int32_t centerX, int32_t centerY); + void AdjustMagnificationWindowPosition(); + void AdjustSourceWindowPosition(); + void CalculateAnchorOffset(); + void GetWindowParam(); + + Rosen::Rect sourceRect_; + Rosen::Rect windowRect_; + Rosen::Rect screenRect_; + + sptr window_ = nullptr; + std::shared_ptr surfaceNode_; + std::shared_ptr canvasNode_; + bool isMagnificationWindowShow_ = false; + + uint32_t windowWidth_ = 940; + uint32_t windowHeight_ = 550; + uint32_t barMargin_ = 40; + float scale_ = 2.0f; + uint32_t hotAreaWidth_ = 60; + int32_t anchorOffsetX_ = 0; // windowRect_'s centerX - sourceRect_'s centerX + int32_t anchorOffsetY_ = 0; // windowRect_'s centerY - sourceRect_'s centerY + + uint32_t screenWidth_ = 0; + uint32_t screenHeight_ = 0; + float screenSpan_ = 0.0f; + uint64_t screenId_ = 0; + Rosen::DisplayOrientation orientation_ = Rosen::DisplayOrientation::UNKNOWN; + bool isFixSourceCenter_ = false; + PointerPos fixedSourceCenter_ = {0, 0}; +}; +} // namespace Accessibility +} // namespace OHOS +#endif // WINDOW_MAGNIFICATION_MANAGER_H \ No newline at end of file diff --git a/services/aams/src/accessibility_input_interceptor.cpp b/services/aams/src/accessibility_input_interceptor.cpp index 36d68079..b3884197 100644 --- a/services/aams/src/accessibility_input_interceptor.cpp +++ b/services/aams/src/accessibility_input_interceptor.cpp @@ -21,6 +21,7 @@ #include "accessibility_touch_exploration.h" #include "accessibility_touchEvent_injector.h" #include "accessibility_zoom_gesture.h" +#include "window_magnification_gesture.h" #include "accessible_ability_manager_service.h" #include "hilog_wrapper.h" #include "key_event.h" @@ -188,15 +189,9 @@ void AccessibilityInputInterceptor::CreatePointerEventTransmitters() } if (availableFunctions_& FEATURE_SCREEN_MAGNIFICATION) { - sptr zoomGesture = new(std::nothrow) AccessibilityZoomGesture(); - if (!zoomGesture) { - HILOG_ERROR("zoomGesture is null"); - return; - } - zoomGesture_ = zoomGesture; - SetNextEventTransmitter(header, current, zoomGesture); + CreateMagnificationGesture(header, current); } else { - zoomGesture_ = nullptr; + ClearMagnificationGesture(); } if (availableFunctions_& FEATURE_TOUCH_EXPLORATION) { @@ -222,6 +217,64 @@ void AccessibilityInputInterceptor::CreatePointerEventTransmitters() pointerEventTransmitters_ = header; } +void AccessibilityInputInterceptor::CreateMagnificationGesture(sptr &header, + sptr ¤t) +{ + HILOG_DEBUG(); + + uint32_t magnificationMode = Singleton::GetInstance().GetMagnificationMode(); + if (magnificationMode == FULL_SCREEN_MAGNIFICATION) { + std::shared_ptr fullScreenMagnificationManager = + Singleton::GetInstance().GetFullScreenMagnificationManager(); + if (fullScreenMagnificationManager == nullptr) { + HILOG_ERROR("get windowMagnification manager failed."); + return; + } + sptr zoomGesture = + new(std::nothrow) AccessibilityZoomGesture(fullScreenMagnificationManager); + if (!zoomGesture) { + HILOG_ERROR("zoomGesture create error."); + return; + } + zoomGesture_ = zoomGesture; + if (needInteractMagnification_) { + zoomGesture_->StartMagnificationInteract(); + needInteractMagnification_ = false; + } + SetNextEventTransmitter(header, current, zoomGesture); + windowMagnificationGesture_ = nullptr; + } else if (magnificationMode == WINDOW_MAGNIFICATION) { + std::shared_ptr windowMagnificationManager = + Singleton::GetInstance().GetWindowMagnificationManager(); + if (windowMagnificationManager == nullptr) { + HILOG_ERROR("get windowMagnification manager failed."); + return; + } + sptr windowMagnificationGesture = + new(std::nothrow) WindowMagnificationGesture(windowMagnificationManager); + if (!windowMagnificationGesture) { + HILOG_ERROR("windowMagnificationGesture create error."); + return; + } + windowMagnificationGesture_ = windowMagnificationGesture; + if (needInteractMagnification_) { + windowMagnificationGesture_->StartMagnificationInteract(); + needInteractMagnification_ = false; + } + SetNextEventTransmitter(header, current, windowMagnificationGesture); + zoomGesture_ = nullptr; + } else { + HILOG_WARN("invalid magnificationMode"); + ClearMagnificationGesture(); + } +} + +void AccessibilityInputInterceptor::ClearMagnificationGesture() +{ + zoomGesture_ = nullptr; + windowMagnificationGesture_ = nullptr; +} + void AccessibilityInputInterceptor::CreateKeyEventTransmitters() { HILOG_DEBUG(); @@ -366,10 +419,13 @@ void AccessibilityInputInterceptor::SetNextEventTransmitter(sptrShieldZoomGesture(flag); + } + if (windowMagnificationGesture_) { + windowMagnificationGesture_->ShieldZoomGesture(flag); } - zoomGesture_->ShieldZoomGesture(flag); } void AccessibilityInputInterceptor::RefreshDisplayInfo() @@ -380,6 +436,12 @@ void AccessibilityInputInterceptor::RefreshDisplayInfo() zoomGesture_->GetWindowParam(true); } +void AccessibilityInputInterceptor::StartMagnificationInteract(uint32_t mode) +{ + HILOG_DEBUG("mode = %{public}d", mode); + needInteractMagnification_ = true; +} + AccessibilityInputEventConsumer::AccessibilityInputEventConsumer() { HILOG_DEBUG(); diff --git a/services/aams/src/accessibility_settings_config.cpp b/services/aams/src/accessibility_settings_config.cpp index 05d6aed2..09e057da 100644 --- a/services/aams/src/accessibility_settings_config.cpp +++ b/services/aams/src/accessibility_settings_config.cpp @@ -26,7 +26,7 @@ namespace OHOS { namespace Accessibility { namespace { constexpr uint32_t DEFAULT_COLOR = 0xff000000; - const int32_t DEFAULT_SCALE = 100; + const int32_t DEFAULT_FONT_SCALE = 100; const int32_t SHORT_KEY_TIMEOUT_AFTER_USE = 1000; // ms const int32_t SHORT_KEY_TIMEOUT_BEFORE_USE = 3000; // ms const int32_t DEFAULT_ACCOUNT_ID = 100; @@ -87,7 +87,6 @@ namespace { constexpr int INVALID_MASTER_MONO_VALUE = -1; constexpr int AUDIO_BALANCE_STEP = 5; constexpr float INVALID_MASTER_BALANCE_VALUE = 2.0; - constexpr float EPS = 1e-6; constexpr int INVALID_SHORTCUT_ON_LOCK_SCREEN_STATE = 2; } // namespace AccessibilitySettingsConfig::AccessibilitySettingsConfig(int32_t id) @@ -891,7 +890,7 @@ void AccessibilitySettingsConfig::InitCaption() std::string fontFamliy = datashare_->GetStringValue(FONT_FAMILY, "default"); HILOG_DEBUG("fontFamily = %{public}s.", fontFamliy.c_str()); - int32_t fontScale = static_cast(datashare_->GetIntValue(FONT_SCALE, DEFAULT_SCALE)); + int32_t fontScale = static_cast(datashare_->GetIntValue(FONT_SCALE, DEFAULT_FONT_SCALE)); HILOG_DEBUG("fontScale = %{public}d.", fontScale); uint32_t fontColor = static_cast(datashare_->GetIntValue(FONT_COLOR, DEFAULT_COLOR)); diff --git a/services/aams/src/accessibility_zoom_gesture.cpp b/services/aams/src/accessibility_zoom_gesture.cpp index c5739597..18347c37 100755 --- a/services/aams/src/accessibility_zoom_gesture.cpp +++ b/services/aams/src/accessibility_zoom_gesture.cpp @@ -22,6 +22,7 @@ #ifdef OHOS_BUILD_ENABLE_POWER_MANAGER #include "accessibility_power_manager.h" #endif +#include "magnification_menu_manager.h" namespace OHOS { namespace Accessibility { @@ -32,23 +33,18 @@ namespace { constexpr int32_t MULTI_TAP_TIMER = 250; // ms constexpr int32_t LONG_PRESS_TIMER = 300; // ms constexpr float DOUBLE_TAP_SLOP = 100.0f; - constexpr float HALF = 0.5f; constexpr uint32_t DOUBLE = 2; constexpr uint32_t TRIPLE_TAP_COUNT = 3; - constexpr float DEFAULT_SCALE = 2.0f; constexpr float NORMAL_SCALE = 1.0f; - constexpr float MAX_SCALE = 8.0f; - constexpr uint32_t INPUT_METHOD_WINDOW_TYPE = 2105; - constexpr float EPS = 1e-6; constexpr float MIN_SCROLL_SPAN = 2.0f; constexpr float MIN_SCALE_SPAN = 2.0f; constexpr float DEFAULT_ANCHOR = 0.5f; } // namespace -AccessibilityZoomGesture::AccessibilityZoomGesture() +AccessibilityZoomGesture::AccessibilityZoomGesture( + std::shared_ptr fullScreenManager) : fullScreenManager_(fullScreenManager) { HILOG_DEBUG(); - zoomGestureEventHandler_ = std::make_shared( Singleton::GetInstance().GetInputManagerRunner(), *this); @@ -122,11 +118,6 @@ bool AccessibilityZoomGesture::OnPointerEvent(MMI::PointerEvent &event) return false; } - if (IsTapOnInputMethod(event)) { - EventTransmission::OnPointerEvent(event); - return true; - } - switch (state_) { case READY_STATE: CacheEvents(event); @@ -139,6 +130,9 @@ bool AccessibilityZoomGesture::OnPointerEvent(MMI::PointerEvent &event) case SLIDING_STATE: RecognizeInSlidingState(event); break; + case MENU_SLIDING_STATE: + RecognizeInMenuSlidingState(event); + break; default: break; } @@ -201,6 +195,12 @@ void AccessibilityZoomGesture::SendCacheEventsToNext() size_t cacheEventsNum = 0; size_t cacheEventsTotalNum = cacheEventsTmp.size(); + + if (fullScreenManager_ == nullptr) { + HILOG_ERROR("fullScreenManager_ is nullptr."); + return; + } + for (auto &pointerEvent : cacheEventsTmp) { cacheEventsNum++; action = pointerEvent->GetPointerAction(); @@ -212,10 +212,24 @@ void AccessibilityZoomGesture::SendCacheEventsToNext() } if (isStartNewAction) { OnPointerEvent(*pointerEvent); - } else { - pointerEvent->SetActionTime(Utils::GetSystemTime() * US_TO_MS); - EventTransmission::OnPointerEvent(*pointerEvent); + continue; } + if (state_ != READY_STATE) { + MMI::PointerEvent::PointerItem pointer {}; + pointerEvent->GetPointerItem(pointerEvent->GetPointerId(), pointer); + PointerPos coordinates = fullScreenManager_->ConvertCoordinates(pointer.GetDisplayX(), + pointer.GetDisplayY()); + if (gestureType_ != INVALID_GESTURE_TYPE) { + coordinates = fullScreenManager_->ConvertGesture(gestureType_, coordinates); + } + pointer.SetDisplayX(coordinates.posX); + pointer.SetDisplayY(coordinates.posY); + pointerEvent->RemovePointerItem(pointerEvent->GetPointerId()); + pointerEvent->AddPointerItem(pointer); + pointerEvent->SetZOrder(10000); // 10000 is magnification window zorder + } + pointerEvent->SetActionTime(Utils::GetSystemTime() * US_TO_MS); + EventTransmission::OnPointerEvent(*pointerEvent); } } @@ -249,7 +263,7 @@ void AccessibilityZoomGesture::RecognizeInReadyState(MMI::PointerEvent &event) } break; case MMI::PointerEvent::POINTER_ACTION_UP: - if ((pointerCount == POINTER_COUNT_1) && IsUpValid()) { + if ((pointerCount == POINTER_COUNT_1) && IsUpValid() && !(IsTapOnInputMethod(event))) { isTripleTaps = IsTripleTaps(); } else { SendCacheEventsToNext(); @@ -280,20 +294,33 @@ void AccessibilityZoomGesture::RecognizeInZoomStateDownEvent(MMI::PointerEvent & { HILOG_DEBUG(); + if (fullScreenManager_ == nullptr) { + HILOG_ERROR("fullScreenManager_ is nullptr."); + return; + } + gestureType_ = INVALID_GESTURE_TYPE; std::vector pointerIdList = event.GetPointerIds(); size_t pointerCount = pointerIdList.size(); zoomGestureEventHandler_->RemoveEvent(MULTI_TAP_MSG); if (pointerCount == POINTER_COUNT_1) { isLongPress_ = false; + MMI::PointerEvent::PointerItem pointerItem; + event.GetPointerItem(event.GetPointerId(), pointerItem); + gestureType_ = fullScreenManager_->CheckTapOnHotArea(pointerItem.GetDisplayX(), pointerItem.GetDisplayY()); + isTapOnMenu_ = Singleton::GetInstance().IsTapOnMenu(pointerItem.GetDisplayX(), + pointerItem.GetDisplayY()); std::shared_ptr pointerEvent = std::make_shared(event); longPressDownEvent_ = pointerEvent; downPid_ = event.GetPointerId(); if (IsDownValid()) { - zoomGestureEventHandler_->SendEvent(MULTI_TAP_MSG, 0, MULTI_TAP_TIMER); + if (!isTapOnMenu_) { + zoomGestureEventHandler_->SendEvent(MULTI_TAP_MSG, 0, MULTI_TAP_TIMER); + } } else { SendCacheEventsToNext(); } } else if (pointerCount == POINTER_COUNT_2) { + gestureType_ = INVALID_GESTURE_TYPE; if (isLongPress_ || IsKnuckles(event)) { HILOG_INFO("not transferState sliding."); SendCacheEventsToNext(); @@ -330,8 +357,13 @@ void AccessibilityZoomGesture::RecognizeInZoomState(MMI::PointerEvent &event) if (downPid_ == event.GetPointerId()) { isLongPress_ = false; } - if ((pointerCount == POINTER_COUNT_1) && IsUpValid()) { - isTripleTaps = IsTripleTaps(); + if ((pointerCount == POINTER_COUNT_1) && IsUpValid() && !(IsTapOnInputMethod(event))) { + if (isTapOnMenu_) { + Singleton::GetInstance().OnMenuTap(); + ClearCacheEventsAndMsg(); + } else { + isTripleTaps = IsTripleTaps(); + } } else { SendCacheEventsToNext(); } @@ -339,6 +371,9 @@ void AccessibilityZoomGesture::RecognizeInZoomState(MMI::PointerEvent &event) case MMI::PointerEvent::POINTER_ACTION_MOVE: if ((pointerCount == POINTER_COUNT_1) && !IsLongPress() && IsMoveValid()) { HILOG_DEBUG("move valid."); + } else if (isTapOnMenu_ && (!IsMoveValid() || IsLongPress())) { + TransferState(MENU_SLIDING_STATE); + ClearCacheEventsAndMsg(); } else { SendCacheEventsToNext(); HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount); @@ -372,14 +407,62 @@ void AccessibilityZoomGesture::RecognizeInSlidingState(MMI::PointerEvent &event) } HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount); + + if (fullScreenManager_ == nullptr) { + HILOG_ERROR("fullScreenManager_ is nullptr."); + return; + } + switch (action) { case MMI::PointerEvent::POINTER_ACTION_UP: if (pointerCount == POINTER_COUNT_1) { TransferState(ZOOMIN_STATE); + fullScreenManager_->PersistScale(); } break; case MMI::PointerEvent::POINTER_ACTION_CANCEL: TransferState(ZOOMIN_STATE); + fullScreenManager_->PersistScale(); + break; + default: + break; + } +} + +void AccessibilityZoomGesture::RecognizeInMenuSlidingState(MMI::PointerEvent &event) +{ + HILOG_INFO(); + int32_t action = event.GetPointerAction(); + switch (action) { + case MMI::PointerEvent::POINTER_ACTION_MOVE: + if (isTapOnMenu_) { + ClearCacheEventsAndMsg(); + if (lastSlidingEvent_ == nullptr) { + lastSlidingEvent_ = std::make_shared(event); + } + MMI::PointerEvent::PointerItem lastSlidingItem; + lastSlidingEvent_->GetPointerItem(lastSlidingEvent_->GetPointerId(), lastSlidingItem); + + MMI::PointerEvent::PointerItem currentItem; + event.GetPointerItem(event.GetPointerId(), currentItem); + + int32_t deltaX = currentItem.GetDisplayX() - lastSlidingItem.GetDisplayX(); + int32_t deltaY = currentItem.GetDisplayY() - lastSlidingItem.GetDisplayY(); + Singleton::GetInstance().MoveMenuWindow(deltaX, deltaY); + + lastSlidingEvent_ = std::make_shared(event); + } else { + if (lastSlidingEvent_ != nullptr) { + lastSlidingEvent_ = nullptr; + } + } + break; + case MMI::PointerEvent::POINTER_ACTION_UP: + lastSlidingEvent_ = nullptr; + isTapOnMenu_ = false; + Singleton::GetInstance().AttachToEdge(); + TransferState(ZOOMIN_STATE); + ClearCacheEventsAndMsg(); break; default: break; @@ -463,7 +546,7 @@ void AccessibilityZoomGesture::RecognizeScale(MMI::PointerEvent &event, ZOOM_FOC return; } - float scaleSpan = (span - lastSpan_) * scaleRatio_; + float scaleSpan = span - lastSpan_; if (abs(scaleSpan) > EPS) { OnScale(scaleSpan); lastSpan_ = span; @@ -773,115 +856,60 @@ void AccessibilityZoomGesture::GetWindowParam(bool needRefresh) #endif } +void AccessibilityZoomGesture::StartMagnificationInteract() +{ + HILOG_INFO(); + TransferState(ZOOMIN_STATE); +} + void AccessibilityZoomGesture::OnZoom(int32_t anchorX, int32_t anchorY) { HILOG_INFO(); -#ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER - GetWindowParam(); - if (screenWidth_ == 0 || screenHeight_ == 0) { - HILOG_ERROR("screen param invalid."); + centerX_ = anchorX; + centerX_ = anchorY; + if (fullScreenManager_ == nullptr) { + HILOG_ERROR("fullScreenManager_ is nullptr."); return; } - anchorPointX_ = static_cast(anchorX); - anchorPointY_ = static_cast(anchorY); - - float x = anchorPointX_ / screenWidth_; - float y = anchorPointY_ / screenHeight_; - scaleRatio_ = DEFAULT_SCALE; - AccessibilityDisplayManager &displayMgr = Singleton::GetInstance(); - Utils::RecordOnZoomGestureEvent("on"); - displayMgr.SetDisplayScale(screenId_, scaleRatio_, scaleRatio_, x, y); -#else - HILOG_INFO("not support zoom"); - return; -#endif + fullScreenManager_->EnableMagnification(anchorX, anchorY); + Singleton::GetInstance().ShowMenuWindow(1); } void AccessibilityZoomGesture::OffZoom() { HILOG_INFO(); -#ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER - AccessibilityDisplayManager &displayMgr = Singleton::GetInstance(); - uint64_t currentScreen = displayMgr.GetDefaultDisplayId(); - Utils::RecordOnZoomGestureEvent("off"); - displayMgr.SetDisplayScale(currentScreen, NORMAL_SCALE, NORMAL_SCALE, DEFAULT_ANCHOR, DEFAULT_ANCHOR); -#else - HILOG_INFO("not support zoom"); - return; -#endif + Singleton::GetInstance().DisableMenuWindow(); + if (fullScreenManager_ == nullptr) { + HILOG_ERROR("fullScreenManager_ is nullptr."); + return; + } + fullScreenManager_->DisableMagnification(); } void AccessibilityZoomGesture::OnScroll(float offsetX, float offsetY) { HILOG_DEBUG("offsetX:%{public}f, offsetY:%{public}f.", offsetX, offsetY); -#ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER - GetWindowParam(); - if (screenWidth_ == 0 || screenHeight_ == 0) { - HILOG_ERROR("screen param invalid."); - return; - } - if (abs(scaleRatio_) < EPS) { - HILOG_ERROR("scaleRatio_ param invalid."); + if (fullScreenManager_ == nullptr) { + HILOG_ERROR("fullScreenManager_ is nullptr."); return; } - anchorPointX_ -= (offsetX * DOUBLE / scaleRatio_); - anchorPointY_ -= (offsetY * DOUBLE / scaleRatio_); - - if (anchorPointX_ < 0) { - anchorPointX_ = 0; - } - if (anchorPointX_ > screenWidth_) { - anchorPointX_ = screenWidth_; - } - if (anchorPointY_ < 0) { - anchorPointY_ = 0; - } - if (anchorPointY_ > screenHeight_) { - anchorPointY_ = screenHeight_; - } + fullScreenManager_->MoveMagnification(static_cast(offsetX), static_cast(offsetY)); - float x = anchorPointX_ / screenWidth_; - float y = anchorPointY_ / screenHeight_; - AccessibilityDisplayManager &displayMgr = Singleton::GetInstance(); - displayMgr.SetDisplayScale(screenId_, scaleRatio_, scaleRatio_, x, y); #ifdef OHOS_BUILD_ENABLE_POWER_MANAGER AccessibilityPowerManager &powerMgr = Singleton::GetInstance(); powerMgr.RefreshActivity(); #endif -#else - HILOG_INFO("not support zoom"); - return; -#endif } void AccessibilityZoomGesture::OnScale(float scaleSpan) { HILOG_DEBUG(); -#ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER - GetWindowParam(); - if (screenWidth_ == 0 || screenHeight_ == 0 || abs(screenSpan_) < EPS) { - HILOG_ERROR("screen param invalid."); + if (fullScreenManager_ == nullptr) { + HILOG_ERROR("fullScreenManager_ is nullptr."); return; } - - float ratio = scaleSpan / screenSpan_; - scaleRatio_ = scaleRatio_ + ratio; - if (scaleRatio_ > MAX_SCALE) { - scaleRatio_ = MAX_SCALE; - } - if (scaleRatio_ < DEFAULT_SCALE) { - scaleRatio_ = DEFAULT_SCALE; - } - - float x = anchorPointX_ / screenWidth_; - float y = anchorPointY_ / screenHeight_; - AccessibilityDisplayManager &displayMgr = Singleton::GetInstance(); - displayMgr.SetDisplayScale(screenId_, scaleRatio_, scaleRatio_, x, y); -#else - HILOG_INFO("not support zoom"); - return; -#endif + fullScreenManager_->SetScale(scaleSpan); } void AccessibilityZoomGesture::Clear() diff --git a/services/aams/src/accessible_ability_manager_service.cpp b/services/aams/src/accessible_ability_manager_service.cpp index 4a9f2f97..e896fd53 100644 --- a/services/aams/src/accessible_ability_manager_service.cpp +++ b/services/aams/src/accessible_ability_manager_service.cpp @@ -75,6 +75,8 @@ namespace { const std::string DEVICE_PROVISIONED = "device_provisioned"; const std::string SCREEN_MAGNIFICATION_KEY = "accessibility_display_magnification_enabled"; const std::string SCREEN_MAGNIFICATION_TYPE = "accessibility_magnification_capability"; + const std::string SCREEN_MAGNIFICATION_MODE = "accessibility_magnification_mode"; + const std::string SCREEN_MAGNIFICATION_SCALE = "accessibility_display_magnification_scale"; const std::string VOICE_RECOGNITION_KEY = "accessibility_sound_recognition_switch"; const std::string VOICE_RECOGNITION_TYPES = "accessibility_sound_recognition_enabled"; const std::string DELAY_UNLOAD_TASK = "TASK_UNLOAD_ACCESSIBILITY_SA"; @@ -142,6 +144,7 @@ AccessibleAbilityManagerService::AccessibleAbilityManagerService() accessibilitySettings_ = std::make_shared(); accessibilityShortKey_ = std::make_shared(); + magnificationManager_ = std::make_shared(); } AccessibleAbilityManagerService::~AccessibleAbilityManagerService() @@ -1889,10 +1892,7 @@ void AccessibleAbilityManagerService::SwitchedUser(int32_t accountId) HILOG_WARN("The account is current account id."); return; } - if (inputInterceptor_ && inputInterceptor_->GetZoomState() == ACCESSIBILITY_ZOOM_STATE::ZOOMIN_STATE) { - HILOG_INFO("off zoom gesture when switch user"); - OffZoomGesture(); - } + OffZoomGesture(); std::map importantEnabledAbilities; SCREENREADER_STATE screenReaderState = SCREENREADER_STATE::UNINIT; @@ -3317,17 +3317,11 @@ void AccessibleAbilityManagerService::RegisterShortKeyEvent() void AccessibleAbilityManagerService::OffZoomGesture() { HILOG_INFO(); -#ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER - AccessibilityDisplayManager &displayMgr = Singleton::GetInstance(); - uint64_t currentScreen = displayMgr.GetDefaultDisplayId(); - float normalScale = 1.0f; - float defaultAnchor = 0.5f; - displayMgr.SetDisplayScale(currentScreen, normalScale, normalScale, defaultAnchor, defaultAnchor); - return; -#else - HILOG_INFO("not support zoom"); - return; -#endif + if (magnificationManager_ == nullptr) { + HILOG_ERROR("magnificationManager_ is nullptr."); + return; + } + magnificationManager_->DisableMagnification(); } void AccessibleAbilityManagerService::OnScreenMagnificationStateChanged() @@ -3406,7 +3400,9 @@ void AccessibleAbilityManagerService::OnScreenMagnificationTypeChanged() screenMagnificationType = static_cast(config->GetDbHandle()->GetIntValue(SCREEN_MAGNIFICATION_TYPE, 0)); config->SetScreenMagnificationType(screenMagnificationType); - Singleton::GetInstance().UpdateInputFilter(); + if (magnificationManager_ != nullptr) { + magnificationManager_->OnMagnificationTypeChanged(screenMagnificationType); + } } void AccessibleAbilityManagerService::RegisterScreenMagnificationType() @@ -3787,5 +3783,117 @@ RetError AccessibleAbilityManagerService::GetResourceValue(AccessibilityEventInf } return RET_OK; } + +std::shared_ptr AccessibleAbilityManagerService::GetCurrentAcountDatashareHelper() +{ + HILOG_DEBUG(); + sptr accountData = GetCurrentAccountData(); + if (accountData == nullptr) { + HILOG_ERROR("accountData is nullptr"); + return nullptr; + } + + std::shared_ptr config = accountData->GetConfig(); + if (config == nullptr) { + HILOG_ERROR("config is nullptr"); + return nullptr; + } + + return config->GetDbHandle(); +} + +uint32_t AccessibleAbilityManagerService::GetMagnificationType() +{ + HILOG_DEBUG(); + uint32_t magnificationType = FULL_SCREEN_MAGNIFICATION; + shared_ptr helper = GetCurrentAcountDatashareHelper(); + if (helper == nullptr) { + HILOG_ERROR("datashareHelper is nullptr"); + return magnificationType; + } + + magnificationType = + static_cast(helper->GetIntValue(SCREEN_MAGNIFICATION_TYPE, FULL_SCREEN_MAGNIFICATION)); + return magnificationType; +} + +uint32_t AccessibleAbilityManagerService::GetMagnificationMode() +{ + HILOG_DEBUG(); + uint32_t magnificationMode = FULL_SCREEN_MAGNIFICATION; + shared_ptr helper = GetCurrentAcountDatashareHelper(); + if (helper == nullptr) { + HILOG_ERROR("datashareHelper is nullptr"); + return magnificationMode; + } + + magnificationMode = + static_cast(helper->GetIntValue(SCREEN_MAGNIFICATION_MODE, FULL_SCREEN_MAGNIFICATION)); + return magnificationMode; +} + +void AccessibleAbilityManagerService::SetMagnificationMode(int32_t mode) +{ + HILOG_DEBUG(); + shared_ptr helper = GetCurrentAcountDatashareHelper(); + if (helper == nullptr) { + HILOG_ERROR("datashareHelper is nullptr"); + return; + } + + helper->PutIntValue(SCREEN_MAGNIFICATION_MODE, mode, false); +} + +float AccessibleAbilityManagerService::GetMagnificationScale() +{ + HILOG_DEBUG(); + float magnificationScale = DEFAULT_SCALE; + shared_ptr helper = GetCurrentAcountDatashareHelper(); + if (helper == nullptr) { + HILOG_ERROR("datashareHelper is nullptr"); + return magnificationScale; + } + + magnificationScale = + static_cast(helper->GetFloatValue(SCREEN_MAGNIFICATION_SCALE, DEFAULT_SCALE)); + return magnificationScale; +} + +void AccessibleAbilityManagerService::SetMagnificationScale(float scale) +{ + HILOG_DEBUG(); + shared_ptr helper = GetCurrentAcountDatashareHelper(); + if (helper == nullptr) { + HILOG_ERROR("datashareHelper is nullptr"); + return; + } + helper->PutFloatValue(SCREEN_MAGNIFICATION_SCALE, scale, false); +} + +std::shared_ptr AccessibleAbilityManagerService::GetMagnificationMgr() +{ + HILOG_DEBUG(); + return magnificationManager_; +} + +std::shared_ptr AccessibleAbilityManagerService::GetWindowMagnificationManager() +{ + HILOG_DEBUG(); + if (magnificationManager_ == nullptr) { + HILOG_ERROR("magnificationManager_ is nullptr."); + return nullptr; + } + return magnificationManager_->GetWindowMagnificationManager(); +} + +std::shared_ptr AccessibleAbilityManagerService::GetFullScreenMagnificationManager() +{ + HILOG_DEBUG(); + if (magnificationManager_ == nullptr) { + HILOG_ERROR("magnificationManager_ is nullptr."); + return nullptr; + } + return magnificationManager_->GetFullScreenMagnificationManager(); +} } // namespace Accessibility } // namespace OHOS \ No newline at end of file diff --git a/services/aams/src/full_screen_magnification_manager.cpp b/services/aams/src/full_screen_magnification_manager.cpp new file mode 100644 index 00000000..17c63918 --- /dev/null +++ b/services/aams/src/full_screen_magnification_manager.cpp @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// LCOV_EXCL_START +#include "full_screen_magnification_manager.h" +#include "accessibility_display_manager.h" +#include "accessible_ability_manager_service.h" +#include "magnification_menu_manager.h" + +namespace OHOS { +namespace Accessibility { +namespace { + int32_t GESTURE_OFFSET = 100; +} + +FullScreenMagnificationManager::FullScreenMagnificationManager() +{ + GetWindowParam(); + InitMagnificationParam(); +} + +void FullScreenMagnificationManager::CreateMagnificationWindow() +{ + HILOG_ERROR(); + sptr windowOption = new(std::nothrow) Rosen::WindowOption(); + windowOption->SetWindowType(Rosen::WindowType::WINDOW_TYPE_MAGNIFICATION); + windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING); + windowOption->SetWindowRect(windowRect_); + window_ = Rosen::Window::Create(WINDOW_NAME, windowOption); + if (window_ == nullptr) { + HILOG_ERROR("window create failed."); + return; + } + window_->SetCornerRadius(CORNER_RADIUS); + surfaceNode_ = window_->GetSurfaceNode(); + canvasNode_ = Rosen::RSCanvasNode::Create(); +} + +void FullScreenMagnificationManager::DrawRuoundRectFrame() +{ + if (surfaceNode_ == nullptr) { + HILOG_ERROR("get surfaceNode_ failed."); + return; + } + + if (canvasNode_ == nullptr) { + HILOG_ERROR("create canvasNode_ fail"); + return; + } + surfaceNode_->SetAbilityBGAlpha(BG_ALPHA); + surfaceNode_->AddChild(canvasNode_, -1); + canvasNode_->SetBounds(0, 0, screenWidth_, screenHeight_); + canvasNode_->SetFrame(0, 0, screenWidth_, screenHeight_); + canvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z); + canvasNode_->SetRotation(0); + + auto canvas = canvasNode_->BeginRecording(screenWidth_, screenHeight_); + Rosen::Drawing::Pen pen; + pen.SetAntiAlias(true); + pen.SetColor(ORANGE_COLOR); + pen.SetWidth(PEN_WIDTH); + canvas->AttachPen(pen); + Rosen::Drawing::Path path; + path.AddRoundRect({ROUND_RECT_MARGIN, ROUND_RECT_MARGIN, + screenWidth_ - ROUND_RECT_MARGIN, screenHeight_ - ROUND_RECT_MARGIN}, + CORNER_RADIUS, CORNER_RADIUS, Rosen::Drawing::PathDirection::CW_DIRECTION); + canvas->DrawPath(path); + canvas->DetachPen(); + canvasNode_->FinishRecording(); +} + +void FullScreenMagnificationManager::EnableMagnification(int32_t centerX, int32_t centerY) +{ + HILOG_INFO("centerX = %{public}d, centerY = %{public}d.", centerX, centerY); + if (window_ == nullptr) { + HILOG_ERROR("window is null. need create."); + CreateMagnificationWindow(); + } + + if (window_ == nullptr) { + HILOG_ERROR("create window failed."); + return; + } + sourceRect_ = GetSourceRectFromPointer(centerX, centerY); + UpdateAnchor(); + window_->SetFrameRectForParticalZoomIn(sourceRect_); + DrawRuoundRectFrame(); + window_->Show(); + Rosen::RSTransaction::FlushImplicitTransaction(); + isMagnificationWindowShow_ = true; +} + +void FullScreenMagnificationManager::ShowMagnification() +{ + int32_t centerX = static_cast(screenWidth_ / DIVISOR_TWO); + int32_t centerY = static_cast(screenHeight_ / DIVISOR_TWO); + EnableMagnification(centerX, centerY); +} + +void FullScreenMagnificationManager::DisableMagnification() +{ + HILOG_INFO(); + if (window_ != nullptr) { + window_->Hide(); + window_->Destroy(); + window_ = nullptr; + } + surfaceNode_ = nullptr; + canvasNode_ = nullptr; + isMagnificationWindowShow_ = false; +} + +void FullScreenMagnificationManager::SetScale(float scaleSpan) +{ + HILOG_DEBUG(); + if (screenWidth_ == 0 || screenHeight_ == 0 || abs(screenSpan_) < EPS) { + HILOG_ERROR("screen param invalid."); + return; + } + + float ratio = scaleSpan / screenSpan_; + float tmpScale = scale_ + ratio * scale_; + + if (tmpScale > MAX_SCALE) { + tmpScale = MAX_SCALE; + } + if (tmpScale < DEFAULT_SCALE) { + tmpScale = DEFAULT_SCALE; + } + + uint32_t newWidth = static_cast(windowRect_.width_ / tmpScale); + uint32_t newHeight = static_cast(windowRect_.height_ / tmpScale); + int32_t newPosX = centerX_ - static_cast(newWidth / DIVISOR_TWO); + int32_t newPosY = centerY_ - static_cast(newHeight / DIVISOR_TWO); + + if (newPosX < 0) { + centerX_ -= newPosX; + newPosX = 0; + } + + if (newPosY < 0) { + centerY_ -= newPosY; + newPosY = 0; + } + + if (newPosX + static_cast(newWidth) > static_cast(screenWidth_)) { + centerX_ -= (newPosX + static_cast(newWidth) - static_cast(screenWidth_)); + newPosX = static_cast(screenWidth_) - static_cast(newWidth); + } + + if (newPosY + static_cast(newHeight) > static_cast(screenHeight_)) { + centerY_ -= (newPosY + static_cast(newHeight) - static_cast(screenHeight_)); + newPosY = static_cast(screenHeight_) - static_cast(newHeight); + } + + sourceRect_ = {newPosX, newPosY, newWidth, newHeight}; + scale_ = tmpScale; + HILOG_DEBUG("scale_ = %{public}f", scale_); + window_->SetFrameRectForParticalZoomIn(sourceRect_); + Rosen::RSTransaction::FlushImplicitTransaction(); + UpdateAnchor(); +} + +void FullScreenMagnificationManager::MoveMagnification(int32_t deltaX, int32_t deltaY) +{ + int32_t sourcePosX = sourceRect_.posX_ - deltaX; + int32_t sourcePosY = sourceRect_.posY_ - deltaY; + + if (sourcePosX < 0) { + sourcePosX = 0; + } + + if (sourcePosY < 0) { + sourcePosY = 0; + } + + if (sourcePosX + static_cast(sourceRect_.width_) > static_cast(screenWidth_)) { + sourcePosX = static_cast(screenWidth_) - static_cast(sourceRect_.width_); + } + + if (sourcePosY + static_cast(sourceRect_.height_) > static_cast(screenHeight_)) { + sourcePosY = static_cast(screenHeight_) - static_cast(sourceRect_.height_); + } + sourceRect_.posX_ = sourcePosX; + sourceRect_.posY_ = sourcePosY; + window_->SetFrameRectForParticalZoomIn(sourceRect_); + Rosen::RSTransaction::FlushImplicitTransaction(); + UpdateAnchor(); +} + +void FullScreenMagnificationManager::PersistScale() +{ + HILOG_DEBUG("scale_ = %{public}f", scale_); + Singleton::GetInstance().SetMagnificationScale(scale_); +} + +void FullScreenMagnificationManager::GetWindowParam() +{ + HILOG_INFO(); +#ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER + AccessibilityDisplayManager &displayMgr = Singleton::GetInstance(); + screenId_ = displayMgr.GetDefaultDisplayId(); + OHOS::Rosen::DisplayOrientation currentOrientation = displayMgr.GetOrientation(); + orientation_ = currentOrientation; + sptr display = displayMgr.GetDisplay(screenId_); + screenWidth_ = static_cast(display->GetWidth()); + screenHeight_ = static_cast(display->GetHeight()); + HILOG_INFO("screenWidth_ = %{public}d, screenHeight_ = %{public}d.", screenWidth_, screenHeight_); + + screenSpan_ = hypot(screenWidth_, screenHeight_); + screenRect_ = {0, 0, screenWidth_, screenHeight_}; + windowRect_ = {0, 0, screenWidth_, screenHeight_}; +#else + HILOG_INFO("not support"); +#endif +} + +void FullScreenMagnificationManager::RefreshWindowParam() +{ + HILOG_INFO(); + if (orientation_ == Singleton::GetInstance().GetOrientation()) { + HILOG_INFO("no need refresh window param."); + return; + } + int32_t centerX = sourceRect_.posX_; + int32_t centerY = sourceRect_.posY_; + if (isMagnificationWindowShow_) { + DisableMagnification(); + GetWindowParam(); + EnableMagnification(centerX, centerY); + } else { + GetWindowParam(); + } +} + +PointerPos FullScreenMagnificationManager::ConvertCoordinates(int32_t posX, int32_t posY) +{ + PointerPos sourcePoint = {0, 0}; + if ((abs(scale_) < EPS)) { + return sourcePoint; + } + int32_t windowDeltaX = posX - windowRect_.posX_; + int32_t windowDeltaY = posY - windowRect_.posY_; + sourcePoint.posX = sourceRect_.posX_ + static_cast(windowDeltaX / scale_); + sourcePoint.posY = sourceRect_.posY_ + static_cast(windowDeltaY / scale_); + return sourcePoint; +} + +PointerPos FullScreenMagnificationManager::ConvertGesture(uint32_t type, PointerPos coordinates) +{ + int32_t posX = coordinates.posX; + int32_t posY = coordinates.posY; + PointerPos point = {posX, posY}; + + if (type == BOTTOM_BACK_GESTURE) { + int32_t offsetY = screenHeight_ - (sourceRect_.posY_ + static_cast(sourceRect_.height_)); + point.posY = posY + offsetY; + return point; + } + if (type == LEFT_BACK_GESTURE) { + int32_t offsetX = sourceRect_.posX_; + point.posX = posX - offsetX; + return point; + } + + if (type == RIGHT_BACK_GESTURE) { + int32_t offsetX = screenWidth_ - (sourceRect_.posX_ + static_cast(sourceRect_.width_)); + point.posX = posX + offsetX; + return point; + } + + return point; +} + +uint32_t FullScreenMagnificationManager::CheckTapOnHotArea(int32_t posX, int32_t posY) +{ + bool isTapOnBottom = posY <= static_cast(screenHeight_) && + posY >= static_cast(screenHeight_) - GESTURE_OFFSET; + if (isTapOnBottom) { + HILOG_DEBUG("Tap On Bottom"); + return BOTTOM_BACK_GESTURE; + } + bool isTapOnLeftSide = posX >= 0 && posX <= GESTURE_OFFSET; + if (isTapOnLeftSide) { + HILOG_DEBUG("Tap On Left Side"); + return LEFT_BACK_GESTURE; + } + bool isTapOnRightSide = posX >= static_cast(screenWidth_) - GESTURE_OFFSET && + posX <= static_cast(screenWidth_); + if (isTapOnRightSide) { + HILOG_DEBUG("Tap On Right Side"); + return RIGHT_BACK_GESTURE; + } + return INVALID_GESTURE_TYPE; +} + +void FullScreenMagnificationManager::InitMagnificationParam() +{ + scale_ = Singleton::GetInstance().GetMagnificationScale(); +} + +Rosen::Rect FullScreenMagnificationManager::GetSourceRectFromPointer(int32_t centerX, int32_t centerY) +{ + Rosen::Rect sourceRect = {0, 0, 0, 0}; + sourceRect.width_ = static_cast(static_cast(screenWidth_) / scale_); + sourceRect.height_ = static_cast(static_cast(screenHeight_) / scale_); + + int32_t x = centerX - static_cast(sourceRect.width_ / DIVISOR_TWO); + int32_t y = centerY - static_cast(sourceRect.height_ / DIVISOR_TWO); + + x = (x < 0) ? 0 : x; + x = (x + sourceRect.width_) > screenWidth_ ? static_cast(screenWidth_ - sourceRect.width_) : x; + + y = (y < 0) ? 0 : y; + y = (y + sourceRect.height_) > screenHeight_ ? static_cast(screenHeight_ - sourceRect.height_) : y; + + sourceRect.posX_ = x; + sourceRect.posY_ = y; + + return sourceRect; +} + +void FullScreenMagnificationManager::UpdateAnchor() +{ + centerX_ = static_cast((sourceRect_.posX_ + sourceRect_.posX_ + + static_cast(sourceRect_.width_)) / DIVISOR_TWO); + centerY_ = static_cast((sourceRect_.posY_ + sourceRect_.posY_ + + static_cast(sourceRect_.height_)) / DIVISOR_TWO); +} +} // namespace Accessibility +} // namespace OHOS +// LCOV_EXCL_STOP \ No newline at end of file diff --git a/services/aams/src/magnification_manager.cpp b/services/aams/src/magnification_manager.cpp new file mode 100644 index 00000000..8ae0bd74 --- /dev/null +++ b/services/aams/src/magnification_manager.cpp @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// LCOV_EXCL_START +#include "hilog_wrapper.h" +#include "magnification_manager.h" +#include "accessibility_display_manager.h" +#include "accessible_ability_manager_service.h" +#include "magnification_menu_manager.h" + +namespace OHOS { +namespace Accessibility { +MagnificationManager::MagnificationManager() +{ + HILOG_DEBUG(); +} + +std::shared_ptr MagnificationManager::GetWindowMagnificationManager() +{ + HILOG_DEBUG(); + if (windowMagnificationManager_ == nullptr) { + windowMagnificationManager_ = std::make_shared(); + } + return windowMagnificationManager_; +} + +std::shared_ptr MagnificationManager::GetFullScreenMagnificationManager() +{ + HILOG_DEBUG(); + if (fullScreenMagnificationManager_ == nullptr) { + fullScreenMagnificationManager_ = std::make_shared(); + } + return fullScreenMagnificationManager_; +} + +void MagnificationManager::OnMagnificationTypeChanged(uint32_t magnificationType) +{ + if (windowMagnificationManager_ == nullptr) { + HILOG_DEBUG("GetWindowMagnificationManager"); + GetWindowMagnificationManager(); + } + if (fullScreenMagnificationManager_ == nullptr) { + HILOG_DEBUG("GetFullScreenMagnificationManager"); + GetFullScreenMagnificationManager(); + } + + currentMode_ = Singleton::GetInstance().GetMagnificationMode(); + Singleton::GetInstance().SetCurrentType(magnificationType); + if (magnificationType == SWITCH_MAGNIFICATION) { + if (windowMagnificationManager_ != nullptr && windowMagnificationManager_->isMagnificationWindowShow()) { + Singleton::GetInstance().DisableMenuWindow(); + Singleton::GetInstance().ShowMenuWindow(currentMode_); + return; + } + + if (fullScreenMagnificationManager_ != nullptr && + fullScreenMagnificationManager_->isMagnificationWindowShow()) { + Singleton::GetInstance().DisableMenuWindow(); + Singleton::GetInstance().ShowMenuWindow(currentMode_); + return; + } + } + + Singleton::GetInstance().DisableMenuWindow(); + + HILOG_INFO("magnificationType = %{public}d, currentMode_ = %{public}d", magnificationType, currentMode_); + if (currentMode_ == magnificationType) { + return; + } + + OnModeChanged(magnificationType); +} + +void MagnificationManager::OnModeChanged(uint32_t mode) +{ + HILOG_INFO("mode = %{public}d.", mode); + if (windowMagnificationManager_ == nullptr) { + HILOG_DEBUG("GetWindowMagnificationManager"); + GetWindowMagnificationManager(); + } + if (fullScreenMagnificationManager_ == nullptr) { + HILOG_DEBUG("GetFullScreenMagnificationManager"); + GetFullScreenMagnificationManager(); + } + + if (mode != FULL_SCREEN_MAGNIFICATION && mode != WINDOW_MAGNIFICATION) { + HILOG_ERROR("invalid mode = %{public}d.", mode); + return; + } + + auto interceptor = AccessibilityInputInterceptor::GetInstance(); + bool needShow = false; + if (mode == WINDOW_MAGNIFICATION) { + HILOG_INFO("disable full screen magnification."); + if (fullScreenMagnificationManager_ != nullptr) { + needShow = fullScreenMagnificationManager_->isMagnificationWindowShow(); + fullScreenMagnificationManager_->DisableMagnification(); + } + if (windowMagnificationManager_ != nullptr && needShow) { + windowMagnificationManager_->ShowWindowMagnification(); + } + } else { + HILOG_INFO("disable window magnification."); + if (windowMagnificationManager_ != nullptr) { + needShow = windowMagnificationManager_->isMagnificationWindowShow(); + windowMagnificationManager_->DisableWindowMagnification(); + } + if (fullScreenMagnificationManager_ != nullptr && needShow) { + fullScreenMagnificationManager_->ShowMagnification(); + } + } + Singleton::GetInstance().SetMagnificationMode(static_cast(mode)); + currentMode_ = mode; + Singleton::GetInstance().UpdateInputFilter(); + interceptor->StartMagnificationInteract(mode); +} + +void MagnificationManager::DisableMagnification() +{ + HILOG_INFO(); + Singleton::GetInstance().DisableMenuWindow(); + if (windowMagnificationManager_ != nullptr && windowMagnificationManager_->isMagnificationWindowShow()) { + windowMagnificationManager_->DisableWindowMagnification(); + return; + } + if (fullScreenMagnificationManager_ != nullptr && fullScreenMagnificationManager_->isMagnificationWindowShow()) { + fullScreenMagnificationManager_->DisableMagnification(); + return; + } +} + +void MagnificationManager::SetMagnificationState(bool isEnabled) +{ + isMagnificationEnabled_ = isEnabled; +} + +bool MagnificationManager::GetMagnificationState() +{ + return isMagnificationEnabled_; +} + +void MagnificationManager::RefreshWindowParam() +{ + HILOG_DEBUG(); + if (windowMagnificationManager_ != nullptr) { + windowMagnificationManager_->RefreshWindowParam(); + } + + if (fullScreenMagnificationManager_ != nullptr) { + fullScreenMagnificationManager_->RefreshWindowParam(); + } + + Singleton::GetInstance().RefreshWindowParam(); +} +} // namespace Accessibility +} // namespace OHOS +// LCOV_EXCL_STOP \ No newline at end of file diff --git a/services/aams/src/magnification_menu_manager.cpp b/services/aams/src/magnification_menu_manager.cpp new file mode 100644 index 00000000..efb4cd8f --- /dev/null +++ b/services/aams/src/magnification_menu_manager.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// LCOV_EXCL_START +#include "magnification_menu_manager.h" +#include "accessibility_def.h" +#include "accessibility_display_manager.h" +#include "accessible_ability_manager_service.h" +#include "utils.h" + +namespace OHOS { +namespace Accessibility { +namespace { + const std::string FULL_SCREEN_PATH = "/system/etc/accessibility/fullScreen.png"; + const std::string WINDOW_PATH = "/system/etc/accessibility/window.png"; +} + +std::shared_ptr MagnificationMenuManager::menuMgr_ = nullptr; + +std::shared_ptr MagnificationMenuManager::GetInstance() +{ + HILOG_DEBUG(); + if (menuMgr_ == nullptr) { + menuMgr_ = std::make_shared(); + } + return menuMgr_; +} + +void MagnificationMenuManager::DeleteInstance() +{ + HILOG_DEBUG(); + if (menuMgr_ == nullptr) { + HILOG_ERROR("menuMgr_ is nullptr."); + return; + } + menuMgr_ = nullptr; +} + +MagnificationMenuManager::MagnificationMenuManager() +{ + HILOG_DEBUG(); + GetWindowParam(); + manager_ = Singleton::GetInstance().GetMagnificationMgr(); +} + +MagnificationMenuManager::~MagnificationMenuManager() +{ + if (menuWindow_ != nullptr) { + menuWindow_->Hide(); + menuWindow_->Destroy(); + menuWindow_ = nullptr; + } + surfaceNode_ = nullptr; + canvasNode_ = nullptr; + bgpixelmap_ = nullptr; + rosenImage_ = nullptr; +} + +void MagnificationMenuManager::CreateMenuWindow() +{ + HILOG_DEBUG(); + menuRect_ = {(screenWidth_ - menuSize_ - margin_), (screenHeight_ - menuSize_ - margin_), menuSize_, menuSize_}; + sptr windowOption = new(std::nothrow) Rosen::WindowOption(); + windowOption->SetWindowType(Rosen::WindowType::WINDOW_TYPE_MAGNIFICATION_MENU); + windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING); + windowOption->SetWindowRect(menuRect_); + menuWindow_ = Rosen::Window::Create(MENU_NAME, windowOption); + if (menuWindow_ == nullptr) { + HILOG_ERROR("create failed"); + return; + } + menuWindow_->SetCornerRadius(MENU_CORNER_RADIUS); + surfaceNode_ = menuWindow_->GetSurfaceNode(); + canvasNode_ = Rosen::RSCanvasNode::Create(); + surfaceNode_->SetAbilityBGAlpha(BG_ALPHA); + surfaceNode_->AddChild(canvasNode_, -1); + canvasNode_->SetBounds(0, 0, menuSize_, menuSize_); + canvasNode_->SetFrame(0, 0, menuSize_, menuSize_); + canvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z); + canvasNode_->SetRotation(0); + rosenImage_ = std::make_shared(); +} + +void MagnificationMenuManager::LoadMenuBgImage(uint32_t mode) +{ + HILOG_DEBUG(); + std::string path = FULL_SCREEN_PATH; + if (mode == WINDOW_MAGNIFICATION) { + path = WINDOW_PATH; + } + bgpixelmap_ = DecodePixelMap(path, allocatorType_); + if (bgpixelmap_ == nullptr) { + HILOG_ERROR("DecodePixelMap failed."); + return; + } + + canvasNode_->SetBgImageWidth(menuSize_); + canvasNode_->SetBgImageHeight(menuSize_); + canvasNode_->SetBgImagePositionX(0); + canvasNode_->SetBgImagePositionY(0); + + rosenImage_->SetPixelMap(bgpixelmap_); + rosenImage_->SetImageFit(static_cast(Rosen::ImageFit::FILL)); + canvasNode_->SetBgImage(rosenImage_); + menuWindow_->Show(); +} + +void MagnificationMenuManager::ShowMenuWindow(uint32_t mode) +{ + HILOG_DEBUG(); + currentType_ = Singleton::GetInstance().GetMagnificationType(); + meunMode_ = Singleton::GetInstance().GetMagnificationMode(); + if (currentType_ != SWITCH_MAGNIFICATION) { + HILOG_WARN("no need show menu."); + return; + } + + if (menuWindow_ == nullptr) { + HILOG_WARN("window is null. need create."); + CreateMenuWindow(); + } + + if (menuWindow_ == nullptr) { + HILOG_INFO("create window failed."); + return; + } + + LoadMenuBgImage(mode); + Rosen::RSTransaction::FlushImplicitTransaction(); + isMenuShown_ = true; +} + +void MagnificationMenuManager::DisableMenuWindow() +{ + HILOG_DEBUG(); + isMenuShown_ = false; + if (menuWindow_ != nullptr) { + menuWindow_->Hide(); + menuWindow_->Destroy(); + menuWindow_ = nullptr; + } + surfaceNode_ = nullptr; + canvasNode_ = nullptr; + bgpixelmap_ = nullptr; + rosenImage_ = nullptr; +} + +void MagnificationMenuManager::MoveMenuWindow(int32_t deltaX, int32_t deltaY) +{ + HILOG_DEBUG(); + if (menuWindow_ == nullptr) { + HILOG_ERROR("menuWindow_ is null."); + return; + } + int32_t menuPosX = menuRect_.posX_ + deltaX; + int32_t menuPosY = menuRect_.posY_ + deltaY; + + menuRect_.posX_ = menuPosX; + menuRect_.posY_ = menuPosY; + + AdjustMeunPosition(); + menuWindow_->MoveTo(menuRect_.posX_, menuRect_.posY_); +} + +void MagnificationMenuManager::AttachToEdge() +{ + if (menuWindow_ == nullptr) { + HILOG_ERROR("menuWindow_ is null."); + return; + } + + if (menuRect_.posX_ < static_cast(screenWidth_ / DIVISOR_TWO)) { + menuRect_.posX_ = margin_; + } else { + menuRect_.posX_ = screenWidth_ - menuSize_ - margin_; + } + menuWindow_->MoveTo(menuRect_.posX_, menuRect_.posY_); +} + +void MagnificationMenuManager::SetCurrentType(uint32_t type) +{ + currentType_ = type; +} + +bool MagnificationMenuManager::IsTapOnMenu(int32_t posX, int32_t posY) +{ + if (!isMenuShown_) { + return false; + } + return Utils::IsInRect(posX, posY, menuRect_); +} + +void MagnificationMenuManager::OnMenuTap() +{ + if (manager_ == nullptr) { + HILOG_ERROR("manager_ is null."); + return; + } + DisableMenuWindow(); + ChangeMode(); + manager_->OnModeChanged(meunMode_); + ShowMenuWindow(meunMode_); +} + +void MagnificationMenuManager::ChangeMode() +{ + if (meunMode_ == WINDOW_MAGNIFICATION) { + meunMode_ = FULL_SCREEN_MAGNIFICATION; + return; + } + if (meunMode_ == FULL_SCREEN_MAGNIFICATION) { + meunMode_ = WINDOW_MAGNIFICATION; + return; + } +} + +void MagnificationMenuManager::AdjustMeunPosition() +{ + if (menuRect_.posX_ < margin_) { + menuRect_.posX_ = margin_; + } + + if (menuRect_.posY_ < margin_) { + menuRect_.posY_ = margin_; + } + + if (menuRect_.posX_ + static_cast(menuRect_.width_) + margin_ > static_cast(screenWidth_)) { + menuRect_.posX_ = static_cast(screenWidth_) - static_cast(menuRect_.width_) - margin_; + } + + if (menuRect_.posY_ + static_cast(menuRect_.height_) + margin_ > static_cast(screenHeight_)) { + menuRect_.posY_ = static_cast(screenHeight_) - static_cast(menuRect_.height_) - margin_; + } +} + +std::shared_ptr MagnificationMenuManager::DecodePixelMap( + const std::string& pathName, const Media::AllocatorType& allocatorType) +{ + uint32_t errCode = 0; + std::unique_ptr imageSource = + Media::ImageSource::CreateImageSource(pathName, Media::SourceOptions(), errCode); + if (imageSource == nullptr || errCode != 0) { + HILOG_ERROR("CreateImageSource failed."); + return nullptr; + } + + Media::DecodeOptions decodeOpt; + decodeOpt.allocatorType = allocatorType; + std::shared_ptr pixelmap = imageSource->CreatePixelMap(decodeOpt, errCode); + if (pixelmap == nullptr || errCode != 0) { + HILOG_ERROR("CreatePixelMap failed."); + return nullptr; + } + return pixelmap; +} + +void MagnificationMenuManager::GetWindowParam() +{ +#ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER + AccessibilityDisplayManager &displayMgr = Singleton::GetInstance(); + uint64_t screenId_ = displayMgr.GetDefaultDisplayId(); + OHOS::Rosen::DisplayOrientation currentOrientation = displayMgr.GetOrientation(); + orientation_ = currentOrientation; + sptr display = displayMgr.GetDisplay(screenId_); + screenWidth_ = static_cast(display->GetWidth()); + screenHeight_ = static_cast(display->GetHeight()); + screenRect_ = {0, 0, screenWidth_, screenHeight_}; +#else + HILOG_INFO("not support"); +#endif +} + +void MagnificationMenuManager::RefreshWindowParam() +{ + HILOG_DEBUG(); + if (orientation_ == Singleton::GetInstance().GetOrientation()) { + HILOG_INFO("no need refresh window param."); + return; + } + + HILOG_INFO("need refresh window param."); + if (isMenuShown_) { + DisableMenuWindow(); + GetWindowParam(); + ShowMenuWindow(meunMode_); + } else { + GetWindowParam(); + } +} +} // namespace Accessibility +} // namespace OHOS +// LCOV_EXCL_STOP \ No newline at end of file diff --git a/services/aams/src/utils.cpp b/services/aams/src/utils.cpp index 3103f174..80ebff34 100644 --- a/services/aams/src/utils.cpp +++ b/services/aams/src/utils.cpp @@ -540,5 +540,11 @@ bool Utils::GetBundleNameByCallingUid(std::string &bundleName) HILOG_DEBUG("GetCallingUid:%{public}d, getBundleNameByUid:%{public}s", uid, bundleName.c_str()); return true; } + +bool Utils::IsInRect(int32_t posX, int32_t posY, Rosen::Rect rect) +{ + return (posX >= rect.posX_ && posY >= rect.posY_ && posX <= rect.posX_ + static_cast(rect.width_) && + posY <= rect.posY_ + static_cast(rect.height_)); +} } // namespace Accessibility } // namespace OHOS \ No newline at end of file diff --git a/services/aams/src/window_magnification_gesture.cpp b/services/aams/src/window_magnification_gesture.cpp new file mode 100644 index 00000000..b19da4db --- /dev/null +++ b/services/aams/src/window_magnification_gesture.cpp @@ -0,0 +1,881 @@ +/* + * Copyright (C) 2022-2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// LCOV_EXCL_START +#include "window_magnification_gesture.h" +#include "utils.h" +#include "accessible_ability_manager_service.h" +#include "magnification_menu_manager.h" +#include "accessibility_window_manager.h" + +namespace OHOS { +namespace Accessibility { +namespace { + constexpr float TAP_MIN_DISTANCE = 8.0f; + constexpr float DOUBLE_TAP_SLOP = 100.0f; + constexpr int32_t HANDLER = 0; + constexpr int32_t SWITCH_MENU = -1; + constexpr uint32_t TAP_COUNT_THREE = 3; +} // namespace + +void WindowMagnificationGesture::InitGestureFuncMap() +{ + handleEventFuncMap_ = { + {MagnificationGestureState::READY_STATE, { + {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleReadyStateDown)}, + {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleReadyStateUp)}, + {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleReadyStateMove)}, + } + }, + {MagnificationGestureState::READY_STATE_ONE_FINGER_DOWN, { + {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleReadyStateOneFingerDownStateDown)}, + {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleReadyStateOneFingerDownStateUp)}, + {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleReadyStateOneFingerDownStateMove)}, + } + }, + {MagnificationGestureState::READY_STATE_ONE_FINGER_TAP, { + {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleReadyStateOneFingerTapDown)}, + } + }, + {MagnificationGestureState::ZOOMIN_STATE, { + {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleZoomInStateDown)}, + {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleZoomInStateUp)}, + {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleZoomInStateMove)}, + } + }, + {MagnificationGestureState::ZOOMIN_STATE_ONE_FINGER_DOWN, { + {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleZoomInStateOneFingerDownStateDown)}, + {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleZoomInStateOneFingerDownStateUp)}, + {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleZoomInStateOneFingerDownStateMove)}, + } + }, + {MagnificationGestureState::ZOOMIN_STATE_ONE_FINGER_TAP, { + {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleZoomInStateOneFingerTapDown)}, + } + }, + {MagnificationGestureState::ZOOMIN_STATE_TWO_FINGERS_DOWN, { + {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleTwoFingersDownStateUp)}, + {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleTwoFingersDownStateMove)}, + } + }, + {MagnificationGestureState::SLIDING_STATE, { + {MMI::PointerEvent::POINTER_ACTION_DOWN, BIND(HandleSlidingStateDown)}, + {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleSlidingStateUp)}, + {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleSlidingStateMove)}, + } + }, + {MagnificationGestureState::MENU_SLIDING_STATE, { + {MMI::PointerEvent::POINTER_ACTION_UP, BIND(HandleMenuSlidingStateUp)}, + {MMI::PointerEvent::POINTER_ACTION_MOVE, BIND(HandleMenuSlidingStateMove)}, + } + }, + }; +} + +MagnificationGestureEventHandler::MagnificationGestureEventHandler( + const std::shared_ptr &runner, + WindowMagnificationGesture &server) : AppExecFwk::EventHandler(runner), server_(server) +{ +} + +void MagnificationGestureEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event) +{ + HILOG_DEBUG(); + + MagnificationGestureMsg msg = static_cast(event->GetInnerEventId()); + int64_t param = event->GetParam(); + HILOG_DEBUG("handler process event id = %{public}d, GestureState is %{public}d, param = %{public}d", + event->GetInnerEventId(), server_.GetGestureState(), static_cast(param)); + switch (msg) { + case MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG: + if (!server_.GetTapOnMenu()) { + server_.SendCacheEventsToNext(); + server_.ResetTapCount(); + } + // If this event is not canceled within 100ms, it is cleared. + server_.SetGestureState(static_cast(event->GetParam()), HANDLER); + break; + case MagnificationGestureMsg::TRIPLE_TAP_FAIL_MSG: + // If no next up comes in more than 250ms, clear it. + server_.SendCacheEventsToNext(); + server_.ResetTapCount(); + server_.SetGestureState(static_cast(event->GetParam()), HANDLER); + break; + case MagnificationGestureMsg::LONG_PRESS_MSG: + // If it is not cleared within 200ms, it indicates that the current action is a long press. + if (server_.GetTapOnMenu()) { + server_.SetGestureState(MagnificationGestureState::MENU_SLIDING_STATE, HANDLER); + } else { + server_.SetGestureState(MagnificationGestureState::SLIDING_STATE, HANDLER); + } + break; + default: + break; + } +} + +WindowMagnificationGesture::WindowMagnificationGesture( + std::shared_ptr windowMagnificationManager) + : windowMagnificationManager_(windowMagnificationManager) +{ + HILOG_DEBUG(); + runner_ = Singleton::GetInstance().GetInputManagerRunner(); + if (!runner_) { + HILOG_ERROR("get runner failed"); + return; + } + + handler_ = std::make_shared(runner_, *this); + if (!handler_) { + HILOG_ERROR("create event handler failed"); + return; + } + + InitGestureFuncMap(); + +#ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER + AccessibilityDisplayManager &displayMgr = Singleton::GetInstance(); + auto display = displayMgr.GetDefaultDisplay(); + if (display == nullptr) { + HILOG_ERROR("get display is nullptr"); + return; + } + moveThreshold_ = CalculateMoveThreshold(display->GetDpi()); + float densityPixels = display->GetVirtualPixelRatio(); + multiTapDistance_ = densityPixels * DOUBLE_TAP_SLOP + 0.5f; + tapDistance_ = TAP_MIN_DISTANCE; +#else + HILOG_DEBUG("not support display manager"); + moveThreshold_ = 1; + multiTapDistance_ = 1 * DOUBLE_TAP_SLOP + 0.5f; +#endif +} + +bool WindowMagnificationGesture::OnPointerEvent(MMI::PointerEvent &event) +{ + MMI::PointerEvent::PointerItem Item; + event.GetPointerItem(event.GetPointerId(), Item); + + if (needBypassPointerEvent(event)) { + EventTransmission::OnPointerEvent(event); + return false; + } + OnPointerEventExcute(event); + return true; +} + +bool WindowMagnificationGesture::needBypassPointerEvent(MMI::PointerEvent &event) +{ + HILOG_DEBUG("shieldZoomGestureFlag %{public}d.", shieldZoomGestureFlag_); + return shieldZoomGestureFlag_ || + (event.GetSourceType() != MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN); +} + +void WindowMagnificationGesture::OnPointerEventExcute(MMI::PointerEvent &event) +{ + if (GetGestureState() == MagnificationGestureState::PASSING_THROUGH) { + HandlePassingThroughState(event); + return; + } + + auto iter = handleEventFuncMap_.find(GetGestureState()); + if (iter != handleEventFuncMap_.end()) { + auto funcMap = iter->second.find(event.GetPointerAction()); + if (funcMap != iter->second.end()) { + funcMap->second(event); + return; + } + } + HILOG_ERROR("no way to handle this event."); +} + +void WindowMagnificationGesture::DestroyEvents() +{ + HILOG_DEBUG(); + SendCacheEventsToNext(); +} + +void WindowMagnificationGesture::CancelPostEvent(MagnificationGestureMsg msg) +{ + if (handler_->HasInnerEvent(static_cast(msg))) { + handler_->RemoveEvent(static_cast(msg)); + HILOG_DEBUG("innerEventID = %{public}u canceled.", static_cast(msg)); + } +} + +void WindowMagnificationGesture::SendCacheEventsToNext() +{ + HILOG_DEBUG(); + for (auto &receivedEvent : receivedPointerEvents_) { + SendEventToMultimodal(receivedEvent, false, true); + } + Clear(); +} + +void WindowMagnificationGesture::HandlePassingThroughState(MMI::PointerEvent &event) +{ + SendEventToMultimodal(event, false, false); + + MMI::PointerEvent::PointerItem pointerItem; + event.GetPointerItem(event.GetPointerId(), pointerItem); + + // the last finger is lifted + if ((event.GetPointerCount() == static_cast(PointerCountSize::POINTER_SIZE_1)) && + (!pointerItem.IsPressed())) { + if (windowMagnificationManager_ != nullptr && windowMagnificationManager_->isMagnificationWindowShow()) { + SetGestureState(MagnificationGestureState::ZOOMIN_STATE, event.GetPointerAction()); + } else { + SetGestureState(MagnificationGestureState::READY_STATE, event.GetPointerAction()); + } + } +} + +void WindowMagnificationGesture::HandleReadyStateDown(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + int32_t size = event.GetPointerCount(); + lastDownEvent_ = std::make_shared(event); + if (size == static_cast(PointerCountSize::POINTER_SIZE_1)) { + CancelPostEvent(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG); + CancelPostEvent(MagnificationGestureMsg::TRIPLE_TAP_FAIL_MSG); + receivedPointerEvents_.push_back(event); + SetGestureState(MagnificationGestureState::READY_STATE_ONE_FINGER_DOWN, event.GetPointerAction()); + handler_->SendEvent(static_cast(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG), + static_cast(MagnificationGestureState::READY_STATE), + static_cast(MagnificationTimeout::TAP_TIMEOUT)); + return; + } + + receivedPointerEvents_.push_back(event); + SendCacheEventsToNext(); + SetGestureState(MagnificationGestureState::PASSING_THROUGH, event.GetPointerAction()); +} + +void WindowMagnificationGesture::HandleReadyStateUp(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + SendEventToMultimodal(event, false, false); + if (event.GetPointerCount() != static_cast(PointerCountSize::POINTER_SIZE_1)) { + SetGestureState(MagnificationGestureState::PASSING_THROUGH, event.GetPointerAction()); + } +} + +void WindowMagnificationGesture::HandleReadyStateMove(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + SendEventToMultimodal(event, false, false); + SetGestureState(MagnificationGestureState::PASSING_THROUGH, event.GetPointerAction()); +} + +void WindowMagnificationGesture::HandleReadyStateOneFingerDownStateDown(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + int32_t size = event.GetPointerCount(); + if (size == static_cast(PointerCountSize::POINTER_SIZE_1)) { + HILOG_WARN("invalid state."); + } else { + receivedPointerEvents_.push_back(event); + SendCacheEventsToNext(); + SetGestureState(MagnificationGestureState::PASSING_THROUGH, event.GetPointerAction()); + } +} + +void WindowMagnificationGesture::HandleReadyStateOneFingerDownStateUp(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + receivedPointerEvents_.push_back(event); + CancelPostEvent(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG); + CancelPostEvent(MagnificationGestureMsg::TRIPLE_TAP_FAIL_MSG); + + if (lastDownEvent_ == nullptr) { + HILOG_ERROR("lastDownEvent_ is nullptr"); + return; + } + + if (IsMove(event, *lastDownEvent_, tapDistance_)) { + SendCacheEventsToNext(); + SetGestureState(MagnificationGestureState::PASSING_THROUGH, event.GetPointerAction()); + return; + } + if (IsTapOnInputMethod(event)) { + SendCacheEventsToNext(); + SetGestureState(MagnificationGestureState::READY_STATE, event.GetPointerAction()); + return; + } + AddTapCount(); + if (GetTapCount() == TAP_COUNT_THREE) { + MMI::PointerEvent::PointerItem pointerItem; + event.GetPointerItem(event.GetPointerId(), pointerItem); + OnTripleTap(pointerItem.GetDisplayX(), pointerItem.GetDisplayY()); + Clear(); + SetGestureState(MagnificationGestureState::ZOOMIN_STATE, event.GetPointerAction()); + } else { + handler_->SendEvent(static_cast(MagnificationGestureMsg::TRIPLE_TAP_FAIL_MSG), + static_cast(MagnificationGestureState::READY_STATE), + static_cast(MagnificationTimeout::DOUBLE_TAP_TIMEOUT)); + SetGestureState(MagnificationGestureState::READY_STATE_ONE_FINGER_TAP, event.GetPointerAction()); + } +} + +void WindowMagnificationGesture::HandleReadyStateOneFingerDownStateMove(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + receivedPointerEvents_.push_back(event); + + if (lastDownEvent_ == nullptr) { + HILOG_ERROR("lastDownEvent_ is nullptr"); + return; + } + + if (IsMove(event, *lastDownEvent_, tapDistance_)) { + CancelPostEvent(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG); + CancelPostEvent(MagnificationGestureMsg::TRIPLE_TAP_FAIL_MSG); + SendCacheEventsToNext(); + SetGestureState(MagnificationGestureState::PASSING_THROUGH, event.GetPointerAction()); + } +} + +void WindowMagnificationGesture::HandleReadyStateOneFingerTapDown(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + CancelPostEvent(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG); + CancelPostEvent(MagnificationGestureMsg::TRIPLE_TAP_FAIL_MSG); + + if (lastDownEvent_ == nullptr) { + HILOG_ERROR("lastDownEvent_ is nullptr"); + return; + } + + std::shared_ptr preLastEvent = lastDownEvent_; + lastDownEvent_ = std::make_shared(event); + if (IsMove(*preLastEvent, *lastDownEvent_, multiTapDistance_)) { + SendCacheEventsToNext(); + SetGestureState(MagnificationGestureState::PASSING_THROUGH, event.GetPointerAction()); + return; + } + handler_->SendEvent(static_cast(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG), + static_cast(MagnificationGestureState::READY_STATE), + static_cast(MagnificationTimeout::TAP_TIMEOUT)); + SetGestureState(MagnificationGestureState::READY_STATE_ONE_FINGER_DOWN, event.GetPointerAction()); +} + +void WindowMagnificationGesture::HandleZoomInStateDown(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + + if (windowMagnificationManager_ == nullptr) { + HILOG_ERROR("windowMagnificationManager_ is nullptr."); + return; + } + + int32_t size = event.GetPointerCount(); + lastDownEvent_ = std::make_shared(event); + MMI::PointerEvent::PointerItem pointerItem; + event.GetPointerItem(event.GetPointerId(), pointerItem); + + if (size != static_cast(PointerCountSize::POINTER_SIZE_1)) { + return; + } + + isTapOnMenu_ = Singleton::GetInstance().IsTapOnMenu(pointerItem.GetDisplayX(), + pointerItem.GetDisplayY()); + if (isTapOnMenu_) { + isTapOnHotArea_ = false; + isSingleTapOnWindow_ = false; + } else { + isTapOnHotArea_ = windowMagnificationManager_->IsTapOnHotArea(pointerItem.GetDisplayX(), + pointerItem.GetDisplayY()); + isSingleTapOnWindow_ = windowMagnificationManager_->IsTapOnMagnificationWindow(pointerItem.GetDisplayX(), + pointerItem.GetDisplayY()); + if (isTapOnHotArea_) { + handler_->SendEvent(static_cast(MagnificationGestureMsg::LONG_PRESS_MSG), 0, + static_cast(MagnificationTimeout::LONG_PRESS_TIMEOUT)); + } else { + receivedPointerEvents_.push_back(event); + } + } + + SetGestureState(MagnificationGestureState::ZOOMIN_STATE_ONE_FINGER_DOWN, event.GetPointerAction()); + CancelPostEvent(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG); + CancelPostEvent(MagnificationGestureMsg::TRIPLE_TAP_FAIL_MSG); + handler_->SendEvent(static_cast(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG), + static_cast(MagnificationGestureState::ZOOMIN_STATE), + static_cast(MagnificationTimeout::TAP_TIMEOUT)); +} + +void WindowMagnificationGesture::HandleZoomInStateUp(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + SendEventToMultimodal(event, true, true); +} + +void WindowMagnificationGesture::HandleZoomInStateMove(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + SendEventToMultimodal(event, true, true); +} + +void WindowMagnificationGesture::HandleZoomInStateOneFingerDownStateDown(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + if (windowMagnificationManager_ == nullptr) { + HILOG_ERROR("windowMagnificationManager_ is nullptr."); + return; + } + + if (event.GetPointerCount() == static_cast(PointerCountSize::POINTER_SIZE_2)) { + CancelPostEvent(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG); + CancelPostEvent(MagnificationGestureMsg::TRIPLE_TAP_FAIL_MSG); + CancelPostEvent(MagnificationGestureMsg::LONG_PRESS_MSG); + isTapOnMenu_ = false; + isSingleTapOnWindow_ = false; + isTapOnHotArea_ = false; + lastDownEvent_ = std::make_shared(event); + MMI::PointerEvent::PointerItem pointerItemOne; + event.GetPointerItem(0, pointerItemOne); + bool fingerOne = windowMagnificationManager_->IsTapOnMagnificationWindow(pointerItemOne.GetDisplayX(), + pointerItemOne.GetDisplayY()); + + MMI::PointerEvent::PointerItem pointerItemTwo; + event.GetPointerItem(1, pointerItemTwo); + bool fingerTwo = windowMagnificationManager_->IsTapOnMagnificationWindow(pointerItemTwo.GetDisplayX(), + pointerItemTwo.GetDisplayY()); + isDoubleFingersValid_ = fingerOne || fingerTwo; + + if (isDoubleFingersValid_) { + SetGestureState(MagnificationGestureState::ZOOMIN_STATE_TWO_FINGERS_DOWN, event.GetPointerAction()); + } else { + receivedPointerEvents_.push_back(event); + SendCacheEventsToNext(); + SetGestureState(MagnificationGestureState::ZOOMIN_STATE, event.GetPointerAction()); + } + } +} + +void WindowMagnificationGesture::HandleZoomInStateOneFingerDownStateUp(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + if (!isTapOnHotArea_) { + receivedPointerEvents_.push_back(event); + } + CancelPostEvent(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG); + CancelPostEvent(MagnificationGestureMsg::TRIPLE_TAP_FAIL_MSG); + CancelPostEvent(MagnificationGestureMsg::LONG_PRESS_MSG); + + if (lastDownEvent_ == nullptr) { + HILOG_ERROR("lastDownEvent_ is nullptr"); + return; + } + + if (IsMove(event, *lastDownEvent_, tapDistance_)) { + SendCacheEventsToNext(); + SetGestureState(MagnificationGestureState::PASSING_THROUGH, event.GetPointerAction()); + return; + } + if (IsTapOnInputMethod(event)) { + SendCacheEventsToNext(); + SetGestureState(MagnificationGestureState::ZOOMIN_STATE, event.GetPointerAction()); + return; + } + AddTapCount(); + if (GetTapCount() == TAP_COUNT_THREE) { + MMI::PointerEvent::PointerItem pointerItem; + event.GetPointerItem(event.GetPointerId(), pointerItem); + OnTripleTap(pointerItem.GetDisplayX(), pointerItem.GetDisplayY()); + Clear(); + SetGestureState(MagnificationGestureState::READY_STATE, event.GetPointerAction()); + } else { + if (isTapOnMenu_) { + Singleton::GetInstance().OnMenuTap(); + } else { + handler_->SendEvent(static_cast(MagnificationGestureMsg::TRIPLE_TAP_FAIL_MSG), + static_cast(MagnificationGestureState::ZOOMIN_STATE), + static_cast(MagnificationTimeout::DOUBLE_TAP_TIMEOUT)); + SetGestureState(MagnificationGestureState::ZOOMIN_STATE_ONE_FINGER_TAP, event.GetPointerAction()); + } + } +} + +void WindowMagnificationGesture::HandleZoomInStateOneFingerDownStateMove(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + if (event.GetPointerCount() != 1) { + receivedPointerEvents_.push_back(event); + return; + } + + if (isTapOnMenu_ || isTapOnHotArea_) { + CancelPostEvent(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG); + } else { + receivedPointerEvents_.push_back(event); + } + + if (lastDownEvent_ == nullptr) { + HILOG_ERROR("lastDownEvent_ is nullptr"); + return; + } + + if (IsMove(event, *lastDownEvent_, tapDistance_)) { + CancelPostEvent(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG); + CancelPostEvent(MagnificationGestureMsg::TRIPLE_TAP_FAIL_MSG); + CancelPostEvent(MagnificationGestureMsg::LONG_PRESS_MSG); + SendCacheEventsToNext(); + if (isTapOnMenu_) { + SetGestureState(MagnificationGestureState::MENU_SLIDING_STATE, event.GetPointerAction()); + } else if (isTapOnHotArea_) { + SetGestureState(MagnificationGestureState::SLIDING_STATE, event.GetPointerAction()); + } else { + SetGestureState(MagnificationGestureState::PASSING_THROUGH, event.GetPointerAction()); + } + } +} + +void WindowMagnificationGesture::HandleZoomInStateOneFingerTapDown(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + CancelPostEvent(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG); + CancelPostEvent(MagnificationGestureMsg::TRIPLE_TAP_FAIL_MSG); + + if (lastDownEvent_ == nullptr) { + HILOG_ERROR("lastDownEvent_ is nullptr"); + return; + } + + std::shared_ptr preLastEvent = lastDownEvent_; + lastDownEvent_ = std::make_shared(event); + if (IsMove(*preLastEvent, *lastDownEvent_, multiTapDistance_)) { + SendCacheEventsToNext(); + SetGestureState(MagnificationGestureState::PASSING_THROUGH, event.GetPointerAction()); + return; + } + handler_->SendEvent(static_cast(MagnificationGestureMsg::SINGLE_TAP_FAIL_MSG), + static_cast(MagnificationGestureState::ZOOMIN_STATE), + static_cast(MagnificationTimeout::TAP_TIMEOUT)); + SetGestureState(MagnificationGestureState::ZOOMIN_STATE_ONE_FINGER_DOWN, event.GetPointerAction()); +} + +void WindowMagnificationGesture::HandleTwoFingersDownStateUp(MMI::PointerEvent &event) +{ + startScale_ = false; + if (windowMagnificationManager_ != nullptr) { + windowMagnificationManager_->FixSourceCenter(startScale_); + windowMagnificationManager_->PersistScale(); + } + lastSlidingEvent_ = nullptr; + MMI::PointerEvent::PointerItem pointerItem; + event.GetPointerItem(event.GetPointerId(), pointerItem); + if ((event.GetPointerCount() == static_cast(PointerCountSize::POINTER_SIZE_1)) && + (!pointerItem.IsPressed())) { + SetGestureState(MagnificationGestureState::ZOOMIN_STATE, event.GetPointerAction()); + isDoubleFingersValid_ = false; + } +} + +void WindowMagnificationGesture::HandleTwoFingersDownStateMove(MMI::PointerEvent &event) +{ + HILOG_DEBUG(); + if (windowMagnificationManager_ == nullptr) { + HILOG_ERROR("windowMagnificationManager_ is nullptr."); + return; + } + if (!isDoubleFingersValid_) { + HILOG_ERROR("two fingers state is invalid."); + return; + } + + if (event.GetPointerCount() < static_cast(PointerCountSize::POINTER_SIZE_2)) { + SetGestureState(MagnificationGestureState::SLIDING_STATE, event.GetPointerAction()); + return; + } + + if (lastDownEvent_ == nullptr) { + return; + } + + MMI::PointerEvent::PointerItem baseFirstItem; + lastDownEvent_->GetPointerItem(0, baseFirstItem); + + MMI::PointerEvent::PointerItem baseSecondItem; + lastDownEvent_->GetPointerItem(1, baseSecondItem); + + float baseFocusX = (baseFirstItem.GetDisplayX() + baseSecondItem.GetDisplayX()) / DIVISOR_TWO; + float baseFocusY = (baseFirstItem.GetDisplayY() + baseSecondItem.GetDisplayY()) / DIVISOR_TWO; + int32_t baseOffsetX = abs(baseFirstItem.GetDisplayX() - baseSecondItem.GetDisplayX()); + int32_t baseOffsetY = abs(baseFirstItem.GetDisplayY() - baseSecondItem.GetDisplayY()); + float baseDistance = hypot(baseOffsetX, baseOffsetY); + + if (lastSlidingEvent_ == nullptr) { + lastSlidingEvent_ = std::make_shared(event); + } + + MMI::PointerEvent::PointerItem firstItem; + lastSlidingEvent_->GetPointerItem(0, firstItem); + + MMI::PointerEvent::PointerItem secondItem; + lastSlidingEvent_->GetPointerItem(1, secondItem); + + float lastFocusX = (firstItem.GetDisplayX() + secondItem.GetDisplayX()) / DIVISOR_TWO; + float lastFocusY = (firstItem.GetDisplayY() + secondItem.GetDisplayY()) / DIVISOR_TWO; + int32_t offsetX = abs(firstItem.GetDisplayX() - secondItem.GetDisplayX()); + int32_t offsetY = abs(firstItem.GetDisplayY() - secondItem.GetDisplayY()); + float slidingDistance = hypot(offsetX, offsetY); + + MMI::PointerEvent::PointerItem firstCurrentItem; + event.GetPointerItem(0, firstCurrentItem); + + MMI::PointerEvent::PointerItem secondCurrentItem; + event.GetPointerItem(1, secondCurrentItem); + + float currentFocusX = (firstCurrentItem.GetDisplayX() + secondCurrentItem.GetDisplayX()) / DIVISOR_TWO; + float currentFocusY = (firstCurrentItem.GetDisplayY() + secondCurrentItem.GetDisplayY()) / DIVISOR_TWO; + int32_t currentOffsetX = abs(firstCurrentItem.GetDisplayX() - secondCurrentItem.GetDisplayX()); + int32_t currentOffsetY = abs(firstCurrentItem.GetDisplayY() - secondCurrentItem.GetDisplayY()); + float currentDistance = hypot(currentOffsetX, currentOffsetY); + if (abs(baseDistance - currentDistance) > MIN_SCALE_DISTANCE) { + startScale_ = true; + windowMagnificationManager_->FixSourceCenter(startScale_); + } + + if (startScale_) { + float deltaSpan = currentDistance - slidingDistance; + windowMagnificationManager_->SetScale(deltaSpan); + } else { + int32_t deltaX = static_cast(currentFocusX - lastFocusX); + int32_t deltaY = static_cast(currentFocusY - lastFocusY); + windowMagnificationManager_->MoveMagnificationWindow(deltaX, deltaY); + } + + if (abs(windowMagnificationManager_->GetScale() - DEFAULT_SCALE) < EPS) { + startScale_ = false; + windowMagnificationManager_->FixSourceCenter(startScale_); + } + lastSlidingEvent_ = std::make_shared(event); +} + +void WindowMagnificationGesture::HandleSlidingStateDown(MMI::PointerEvent &event) +{ + HILOG_DEBUG("no need process down in this sliding state."); +} + +void WindowMagnificationGesture::HandleSlidingStateUp(MMI::PointerEvent &event) +{ + if (event.GetPointerCount() > static_cast(PointerCountSize::POINTER_SIZE_1) && event.GetPointerId() > 0) { + return; + } + lastSlidingEvent_ = nullptr; + Clear(); + SetGestureState(MagnificationGestureState::ZOOMIN_STATE, event.GetPointerAction()); +} + +void WindowMagnificationGesture::HandleSlidingStateMove(MMI::PointerEvent &event) +{ + if (windowMagnificationManager_ == nullptr) { + HILOG_ERROR("windowMagnificationManager_ is nullptr."); + return; + } + + if (event.GetPointerCount() > static_cast(PointerCountSize::POINTER_SIZE_1) && event.GetPointerId() > 0) { + return; + } + + if (isTapOnHotArea_) { + if (lastSlidingEvent_ == nullptr) { + lastSlidingEvent_ = std::make_shared(event); + } + MMI::PointerEvent::PointerItem lastSlidingItem; + lastSlidingEvent_->GetPointerItem(lastSlidingEvent_->GetPointerId(), lastSlidingItem); + + MMI::PointerEvent::PointerItem currentItem; + event.GetPointerItem(event.GetPointerId(), currentItem); + + int32_t deltaX = currentItem.GetDisplayX() - lastSlidingItem.GetDisplayX(); + int32_t deltaY = currentItem.GetDisplayY() - lastSlidingItem.GetDisplayY(); + windowMagnificationManager_->MoveMagnificationWindow(deltaX, deltaY); + + lastSlidingEvent_ = std::make_shared(event); + } else { + if (lastSlidingEvent_ != nullptr) { + lastSlidingEvent_ = nullptr; + } + } +} + +void WindowMagnificationGesture::HandleMenuSlidingStateMove(MMI::PointerEvent &event) +{ + if (event.GetPointerCount() > static_cast(PointerCountSize::POINTER_SIZE_1) && event.GetPointerId() > 0) { + return; + } + + if (isTapOnMenu_) { + if (lastSlidingEvent_ == nullptr) { + lastSlidingEvent_ = std::make_shared(event); + } + MMI::PointerEvent::PointerItem lastSlidingItem; + lastSlidingEvent_->GetPointerItem(lastSlidingEvent_->GetPointerId(), lastSlidingItem); + + MMI::PointerEvent::PointerItem currentItem; + event.GetPointerItem(event.GetPointerId(), currentItem); + + int32_t deltaX = currentItem.GetDisplayX() - lastSlidingItem.GetDisplayX(); + int32_t deltaY = currentItem.GetDisplayY() - lastSlidingItem.GetDisplayY(); + Singleton::GetInstance().MoveMenuWindow(deltaX, deltaY); + + lastSlidingEvent_ = std::make_shared(event); + } else { + if (lastSlidingEvent_ != nullptr) { + lastSlidingEvent_ = nullptr; + } + } +} + +void WindowMagnificationGesture::HandleMenuSlidingStateUp(MMI::PointerEvent &event) +{ + if (event.GetPointerCount() > static_cast(PointerCountSize::POINTER_SIZE_1) && event.GetPointerId() > 0) { + return; + } + lastSlidingEvent_ = nullptr; + isTapOnMenu_ = false; + Clear(); + Singleton::GetInstance().AttachToEdge(); + SetGestureState(MagnificationGestureState::ZOOMIN_STATE, event.GetPointerAction()); +} + +bool WindowMagnificationGesture::IsMove(MMI::PointerEvent &startEvent, MMI::PointerEvent &endEvent, float slop) +{ + MMI::PointerEvent::PointerItem endItem; + endEvent.GetPointerItem(endEvent.GetPointerId(), endItem); + + MMI::PointerEvent::PointerItem startItem; + startEvent.GetPointerItem(startEvent.GetPointerId(), startItem); + float deltaX = startItem.GetDisplayX() - endItem.GetDisplayX(); + float deltaY = startItem.GetDisplayY() - endItem.GetDisplayY(); + double duration = hypot(deltaX, deltaY); + return duration > slop; +} + +void WindowMagnificationGesture::Clear() +{ + HILOG_DEBUG(); + receivedPointerEvents_.clear(); +} + +void WindowMagnificationGesture::OnTripleTap(int32_t centerX, int32_t centerY) +{ + HILOG_INFO("OnTripleTap"); + ResetTapCount(); + + if (windowMagnificationManager_ == nullptr) { + HILOG_ERROR("windowMagnificationManager_ is nullptr."); + return; + } + + if (windowMagnificationManager_->isMagnificationWindowShow()) { + windowMagnificationManager_->DisableWindowMagnification(); + Singleton::GetInstance().DisableMenuWindow(); + isSingleTapOnWindow_ = false; + isTapOnHotArea_ = false; + } else { + windowMagnificationManager_->EnableWindowMagnification(centerX, centerY); + Singleton::GetInstance().ShowMenuWindow(WINDOW_MAGNIFICATION); + } +} + +void WindowMagnificationGesture::SendEventToMultimodal(MMI::PointerEvent event, bool needTransfer, bool needResetTime) +{ + if (windowMagnificationManager_ == nullptr) { + HILOG_ERROR("windowMagnificationManager_ is nullptr."); + return; + } + + if (isTapOnMenu_) { + HILOG_DEBUG("Tap on menu."); + return; + } + + if (isSingleTapOnWindow_ && !isTapOnHotArea_) { + MMI::PointerEvent::PointerItem pointer {}; + event.GetPointerItem(event.GetPointerId(), pointer); + + PointerPos coordinates = windowMagnificationManager_->ConvertCoordinates(pointer.GetDisplayX(), + pointer.GetDisplayY()); + + pointer.SetDisplayX(coordinates.posX); + pointer.SetDisplayY(coordinates.posY); + event.RemovePointerItem(event.GetPointerId()); + event.AddPointerItem(pointer); + event.SetZOrder(10000); // magnification zlevel is 10000 + } + + if (needResetTime) { + event.SetActionTime(Utils::GetSystemTime() * US_TO_MS); + } + EventTransmission::OnPointerEvent(event); +} + +void WindowMagnificationGesture::ShieldZoomGesture(bool state) +{ + HILOG_INFO("ShieldZoomGesture state = %{public}d", state); + shieldZoomGestureFlag_ = state; + if (state) { + Clear(); + if (windowMagnificationManager_ != nullptr) { + windowMagnificationManager_->DisableWindowMagnification(); + } + Singleton::GetInstance().DisableMenuWindow(); + isSingleTapOnWindow_ = false; + isTapOnHotArea_ = false; + } +} + +void WindowMagnificationGesture::StartMagnificationInteract() +{ + HILOG_DEBUG(); + SetGestureState(MagnificationGestureState::ZOOMIN_STATE, SWITCH_MENU); +} + +bool WindowMagnificationGesture::IsTapOnInputMethod(MMI::PointerEvent &event) +{ + int32_t pointerCount = event.GetPointerCount(); + if (pointerCount != 1) { + HILOG_DEBUG("not single finger."); + return false; + } + std::vector windowInfos = + Singleton::GetInstance().GetAccessibilityWindows(); + for (auto &window : windowInfos) { + if (window.GetWindowType() == INPUT_METHOD_WINDOW_TYPE) { + Rect inputRect = window.GetRectInScreen(); + int32_t leftTopX = inputRect.GetLeftTopXScreenPostion(); + int32_t leftTopY = inputRect.GetLeftTopYScreenPostion(); + int32_t rightBottomX = inputRect.GetRightBottomXScreenPostion(); + int32_t rightBottomY = inputRect.GetRightBottomYScreenPostion(); + + MMI::PointerEvent::PointerItem item; + event.GetPointerItem(event.GetPointerId(), item); + int32_t itemX = item.GetDisplayX(); + int32_t itemY = item.GetDisplayY(); + if ((itemX >= leftTopX) && (itemX <= rightBottomX) && + (itemY >= leftTopY) && (itemY <= rightBottomY)) { + HILOG_INFO("tap on input method window."); + return true; + } + } + } + HILOG_DEBUG("have no input method window."); + return false; +} +} // namespace Accessibility +} // namespace OHOS +// LCOV_EXCL_STOP \ No newline at end of file diff --git a/services/aams/src/window_magnification_manager.cpp b/services/aams/src/window_magnification_manager.cpp new file mode 100644 index 00000000..2c0fd4c6 --- /dev/null +++ b/services/aams/src/window_magnification_manager.cpp @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2025-2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// LCOV_EXCL_START +#include "window_magnification_manager.h" +#include "accessibility_display_manager.h" +#include "accessible_ability_manager_service.h" +#include "magnification_menu_manager.h" +#include "utils.h" + +namespace OHOS { +namespace Accessibility { +namespace { + constexpr int32_t BAR_START = 400; + constexpr int32_t BAR_END = 550; +} + +WindowMagnificationManager::WindowMagnificationManager() +{ + HILOG_INFO(); + GetWindowParam(); + InitMagnificationParam(); +} + +void WindowMagnificationManager::CreateMagnificationWindow(int32_t posX, int32_t posY) +{ + HILOG_DEBUG(); + windowRect_ = GetWindowRectFromPointer(posX, posY); + sptr windowOption = new(std::nothrow) Rosen::WindowOption(); + windowOption->SetWindowType(Rosen::WindowType::WINDOW_TYPE_MAGNIFICATION); + windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING); + windowOption->SetWindowRect(windowRect_); + window_ = Rosen::Window::Create(WINDOW_NAME, windowOption); + if (window_ == nullptr) { + HILOG_ERROR("create failed."); + return; + } + window_->SetCornerRadius(CORNER_RADIUS); + surfaceNode_ = window_->GetSurfaceNode(); + canvasNode_ = Rosen::RSCanvasNode::Create(); +} + +void WindowMagnificationManager::DrawRuoundRectFrame() +{ + if (surfaceNode_ == nullptr) { + HILOG_ERROR("get surfaceNode_ failed."); + return; + } + + if (canvasNode_ == nullptr) { + HILOG_ERROR("create canvasNode_ fail"); + return; + } + surfaceNode_->SetAbilityBGAlpha(BG_ALPHA); + surfaceNode_->AddChild(canvasNode_, -1); + canvasNode_->SetBounds(0, 0, windowWidth_, windowHeight_); + canvasNode_->SetFrame(0, 0, windowWidth_, windowHeight_); + canvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z); + canvasNode_->SetRotation(0); + + auto canvas = canvasNode_->BeginRecording(windowWidth_, windowHeight_); + Rosen::Drawing::Pen pen; + pen.SetAntiAlias(true); + pen.SetColor(ORANGE_COLOR); + pen.SetWidth(10.0f); + canvas->AttachPen(pen); + Rosen::Drawing::Path path; + path.AddRoundRect({ROUND_RECT_MARGIN, ROUND_RECT_MARGIN, + windowWidth_ - ROUND_RECT_MARGIN, windowHeight_ - ROUND_RECT_MARGIN}, + CORNER_RADIUS, CORNER_RADIUS, Rosen::Drawing::PathDirection::CW_DIRECTION); + canvas->DrawPath(path); + canvas->DetachPen(); + + Rosen::Drawing::Pen linePen; + linePen.SetAntiAlias(true); + linePen.SetColor(ORANGE_COLOR); + linePen.SetWidth(PEN_WIDTH); + canvas->AttachPen(linePen); + auto p1 = Rosen::Drawing::Point(BAR_START, windowHeight_ - barMargin_); + auto p2 = Rosen::Drawing::Point(BAR_END, windowHeight_ - barMargin_); + canvas->DrawLine(p1, p2); + canvas->DetachPen(); + canvasNode_->FinishRecording(); +} + +void WindowMagnificationManager::EnableWindowMagnification(int32_t centerX, int32_t centerY) +{ + HILOG_INFO("centerX = %{public}d, centerY = %{public}d.", centerX, centerY); + if (window_ == nullptr) { + HILOG_ERROR("window is null. need create."); + CreateMagnificationWindow(centerX, centerY); + } + + if (window_ == nullptr) { + HILOG_ERROR(" create window failed."); + return; + } + sourceRect_ = GetSourceRectFromPointer(centerX, centerY); + CalculateAnchorOffset(); + window_->SetFrameRectForParticalZoomIn(sourceRect_); + DrawRuoundRectFrame(); + window_->Show(); + Rosen::RSTransaction::FlushImplicitTransaction(); + isMagnificationWindowShow_ = true; +} + +void WindowMagnificationManager::ShowWindowMagnification() +{ + int32_t centerX = static_cast(screenWidth_ / DIVISOR_TWO); + int32_t centerY = static_cast(screenHeight_ / DIVISOR_TWO); + EnableWindowMagnification(centerX, centerY); +} + +void WindowMagnificationManager::DisableWindowMagnification() +{ + HILOG_INFO(); + if (window_ != nullptr) { + window_->Hide(); + window_->Destroy(); + window_ = nullptr; + } + surfaceNode_ = nullptr; + canvasNode_ = nullptr; + isMagnificationWindowShow_ = false; + int32_t anchorOffsetX_ = 0; + int32_t anchorOffsetY_ = 0; +} + +void WindowMagnificationManager::SetScale(float deltaSpan) +{ + HILOG_DEBUG(); + if (screenWidth_ == 0 || screenHeight_ == 0 || abs(screenSpan_) < EPS) { + HILOG_ERROR("screen param invalid."); + return; + } + + float ratio = deltaSpan / screenSpan_; + float tmpScale = scale_ + ratio * scale_; + if (tmpScale > MAX_SCALE) { + tmpScale = MAX_SCALE; + } + if (tmpScale < DEFAULT_SCALE) { + tmpScale = DEFAULT_SCALE; + } + + uint32_t newWidth = static_cast(windowRect_.width_ / tmpScale); + uint32_t newHeight = static_cast(windowRect_.height_ / tmpScale); + int32_t newPosX = fixedSourceCenter_.posX - static_cast(newWidth / DIVISOR_TWO); + int32_t newPosY = fixedSourceCenter_.posY - static_cast(newHeight / DIVISOR_TWO); + + Rosen::Rect tmpRect = {newPosX, newPosY, newWidth, newHeight}; + if (!tmpRect.IsInsideOf(screenRect_)) { + HILOG_ERROR("sourceRect out of screenRect."); + return; + } + + if (window_ == nullptr) { + HILOG_ERROR("window_ is nullptr."); + return; + } + + sourceRect_ = tmpRect; + scale_ = tmpScale; + window_->SetFrameRectForParticalZoomIn(sourceRect_); + DrawRuoundRectFrame(); + Rosen::RSTransaction::FlushImplicitTransaction(); + CalculateAnchorOffset(); +} + +void WindowMagnificationManager::MoveMagnificationWindow(int32_t deltaX, int32_t deltaY) +{ + if (window_ == nullptr) { + HILOG_ERROR("window is null."); + return; + } + + int32_t windowPosX = windowRect_.posX_; + int32_t sourcePosX = sourceRect_.posX_; + + if (abs(anchorOffsetX_) <= ANCHOR_OFFSET) { + windowPosX += deltaX; + } + sourcePosX += deltaX; + + int32_t windowPosY = windowRect_.posY_; + int32_t sourcePosY = sourceRect_.posY_; + + if (abs(anchorOffsetY_) <= ANCHOR_OFFSET) { + windowPosY += deltaY; + } + sourcePosY += deltaY; + + windowRect_.posX_ = windowPosX; + windowRect_.posY_ = windowPosY; + AdjustMagnificationWindowPosition(); + + window_->MoveTo(windowRect_.posX_, windowRect_.posY_); + + sourceRect_.posX_ = sourcePosX; + sourceRect_.posY_ = sourcePosY; + AdjustSourceWindowPosition(); + window_->SetFrameRectForParticalZoomIn(sourceRect_); + DrawRuoundRectFrame(); + Rosen::RSTransaction::FlushImplicitTransaction(); + CalculateAnchorOffset(); +} + +void WindowMagnificationManager::GetWindowParam() +{ + HILOG_INFO(); +#ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER + AccessibilityDisplayManager &displayMgr = Singleton::GetInstance(); + screenId_ = displayMgr.GetDefaultDisplayId(); + orientation_ = displayMgr.GetOrientation(); + + HILOG_INFO("display id or orientation changed."); + sptr display = displayMgr.GetDisplay(screenId_); + screenWidth_ = static_cast(display->GetWidth()); + screenHeight_ = static_cast(display->GetHeight()); + HILOG_INFO("screenWidth_ = %{public}d, screenHeight_ = %{public}d.", screenWidth_, screenHeight_); + + screenSpan_ = hypot(screenWidth_, screenHeight_); + screenRect_ = {0, 0, screenWidth_, screenHeight_}; +#else + HILOG_INFO("not support"); +#endif +} + +void WindowMagnificationManager::InitMagnificationParam() +{ + scale_ = Singleton::GetInstance().GetMagnificationScale(); +} + +bool WindowMagnificationManager::IsTapOnHotArea(int32_t posX, int32_t posY) +{ + Rosen::Rect innerRect = {windowRect_.posX_ + static_cast(hotAreaWidth_), + windowRect_.posY_ + static_cast(hotAreaWidth_), + windowRect_.width_ - static_cast(2 * hotAreaWidth_), + windowRect_.height_ - static_cast(2 * hotAreaWidth_)}; + Rosen::Rect outRect = {windowRect_.posX_ - static_cast(hotAreaWidth_), + windowRect_.posY_ - static_cast(hotAreaWidth_), + windowRect_.width_ + static_cast(2 * hotAreaWidth_), + windowRect_.height_ + static_cast(2 * hotAreaWidth_)}; + return Utils::IsInRect(posX, posY, outRect) && !(Utils::IsInRect(posX, posY, innerRect)); +} + +void WindowMagnificationManager::RefreshWindowParam() +{ + HILOG_DEBUG(); + if (orientation_ == Singleton::GetInstance().GetOrientation()) { + HILOG_INFO("no need refresh window param."); + return; + } + + HILOG_INFO("need refresh window param."); + int32_t centerX = windowRect_.posX_; + int32_t centerY = windowRect_.posY_; + if (isMagnificationWindowShow_) { + HILOG_INFO("need refresh window param."); + DisableWindowMagnification(); + GetWindowParam(); + EnableWindowMagnification(centerX, centerY); + } else { + GetWindowParam(); + } +} + +bool WindowMagnificationManager::IsTapOnMagnificationWindow(int32_t posX, int32_t posY) +{ + return Utils::IsInRect(posX, posY, windowRect_); +} + +PointerPos WindowMagnificationManager::ConvertCoordinates(int32_t posX, int32_t posY) +{ + PointerPos sourcePoint = {0, 0}; + if ((abs(scale_) < EPS)) { + return sourcePoint; + } + int32_t windowDeltaX = posX - windowRect_.posX_; + int32_t windowDeltaY = posY - windowRect_.posY_; + sourcePoint.posX = sourceRect_.posX_ + static_cast(windowDeltaX / scale_); + sourcePoint.posY = sourceRect_.posY_ + static_cast(windowDeltaY / scale_); + return sourcePoint; +} + +void WindowMagnificationManager::FixSourceCenter(bool needFix) +{ + HILOG_DEBUG(); + if (needFix == isFixSourceCenter_) { + return; + } + + isFixSourceCenter_ = needFix; + if (needFix) { + isFixSourceCenter_ = needFix; + float sourceCenterX = (sourceRect_.posX_ + sourceRect_.posX_ + + static_cast(sourceRect_.width_)) / DIVISOR_TWO; + float sourceCenterY = (sourceRect_.posY_ + sourceRect_.posY_ + + static_cast(sourceRect_.height_)) / DIVISOR_TWO; + fixedSourceCenter_ = {static_cast(sourceCenterX), static_cast(sourceCenterY)}; + } else { + fixedSourceCenter_ = {0, 0}; + } +} + +void WindowMagnificationManager::PersistScale() +{ + HILOG_DEBUG(); + Singleton::GetInstance().SetMagnificationScale(scale_); +} + +PointerPos WindowMagnificationManager::ConvertCenterToTopLeft(int32_t centerX, int32_t centerY) +{ + PointerPos point = {0, 0}; + point.posX = centerX - (windowWidth_ / DIVISOR_TWO); + point.posY = centerY - (windowHeight_ / DIVISOR_TWO); + return point; +} + +RectBound WindowMagnificationManager::GenRectBound(uint32_t width, uint32_t height) +{ + RectBound bound = {0, 0}; + if ((abs(scale_) < EPS)) { + return bound; + } + bound.width = static_cast(static_cast(width) / scale_); + bound.height = static_cast(static_cast(height) / scale_); + return bound; +} + +Rosen::Rect WindowMagnificationManager::GetSourceRectFromPointer(int32_t centerX, int32_t centerY) +{ + Rosen::Rect sourceRect = {0, 0, 0, 0}; + RectBound bound = GenRectBound(windowWidth_, windowHeight_); + sourceRect.width_ = bound.width; + sourceRect.height_ = bound.height; + + int32_t x = centerX - static_cast(sourceRect.width_ / DIVISOR_TWO); + int32_t y = centerY - static_cast(sourceRect.height_ / DIVISOR_TWO); + + x = (x < 0) ? 0 : x; + x = (x + bound.width) > screenWidth_ ? static_cast(screenWidth_ - bound.width) : x; + + y = (y < 0) ? 0 : y; + y = (y + bound.height) > screenHeight_ ? static_cast(screenHeight_ - bound.height) : y; + + sourceRect.posX_ = x; + sourceRect.posY_ = y; + return sourceRect; +} + +Rosen::Rect WindowMagnificationManager::GetWindowRectFromPointer(int32_t centerX, int32_t centerY) +{ + Rosen::Rect windowRect = {0, 0, windowWidth_, windowHeight_}; + int32_t x = centerX - static_cast(windowWidth_ / DIVISOR_TWO); + int32_t y = centerY - static_cast(windowHeight_ / DIVISOR_TWO); + + x = (x < 0) ? 0 : x; + x = (x + windowWidth_) > screenWidth_ ? static_cast(screenWidth_ - windowWidth_) : x; + + y = (y < 0) ? 0 : y; + y = (y + windowHeight_) > screenHeight_ ? static_cast(screenHeight_ - windowHeight_) : y; + + windowRect.posX_ = x; + windowRect.posY_ = y; + return windowRect; +} + +void WindowMagnificationManager::AdjustMagnificationWindowPosition() +{ + if (windowRect_.posX_ < 0) { + windowRect_.posX_ = 0; + } + + if (windowRect_.posY_ < 0) { + windowRect_.posY_ = 0; + } + + if (windowRect_.posX_ + static_cast(windowRect_.width_) > static_cast(screenWidth_)) { + windowRect_.posX_ = static_cast(screenWidth_) - static_cast(windowRect_.width_); + } + + if (windowRect_.posY_ + static_cast(windowRect_.height_) > static_cast(screenHeight_)) { + windowRect_.posY_ = static_cast(screenHeight_) - static_cast(windowRect_.height_); + } +} + +void WindowMagnificationManager::AdjustSourceWindowPosition() +{ + if (sourceRect_.posX_ < windowRect_.posX_) { + sourceRect_.posX_ = windowRect_.posX_; + } + + if (sourceRect_.posY_ < windowRect_.posY_) { + sourceRect_.posY_ = windowRect_.posY_; + } + + int32_t windowX = windowRect_.posX_ + static_cast(windowRect_.width_); + if (sourceRect_.posX_ + static_cast(sourceRect_.width_) > windowX) { + sourceRect_.posX_ = windowX - static_cast(sourceRect_.width_); + } + + int32_t windowY = windowRect_.posY_ + static_cast(windowRect_.height_); + if (sourceRect_.posY_ + static_cast(sourceRect_.height_) > windowY) { + sourceRect_.posY_ = windowY - static_cast(sourceRect_.height_); + } +} + +void WindowMagnificationManager::CalculateAnchorOffset() +{ + int32_t windowCenterX = windowRect_.posX_ + windowRect_.posX_ + static_cast(windowRect_.width_); + int32_t sourceCenterX = sourceRect_.posX_ + sourceRect_.posX_ + static_cast(sourceRect_.width_); + anchorOffsetX_ = static_cast((windowCenterX - sourceCenterX) * HALF); + + int32_t windowCenterY = windowRect_.posY_ + windowRect_.posY_ + static_cast(windowRect_.height_); + int32_t sourceCenterY = sourceRect_.posY_ + sourceRect_.posY_ + static_cast(sourceRect_.height_); + anchorOffsetY_ = static_cast((windowCenterY - sourceCenterY) * HALF); +} +} // namespace Accessibility +} // namespace OHOS +// LCOV_EXCL_STOP \ No newline at end of file diff --git a/services/aams/test/BUILD.gn b/services/aams/test/BUILD.gn index 6f4531fe..3323fb77 100644 --- a/services/aams/test/BUILD.gn +++ b/services/aams/test/BUILD.gn @@ -81,6 +81,11 @@ ohos_unittest("accessibility_account_data_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "mock/src/mock_accessibility_setting_provider.cpp", "mock/src/mock_accessibility_settings_config.cpp", "mock/src/mock_accessible_ability_client_stub_impl.cpp", @@ -193,6 +198,11 @@ ohos_unittest("accessible_ability_manager_service_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "mock/src/aafwk/mock_bundle_manager.cpp", "mock/src/mock_accessibility_element_operator_callback_stub.cpp", "mock/src/mock_accessibility_short_key_dialog.cpp", @@ -331,6 +341,9 @@ ohos_unittest("accessibility_touch_exploration_test") { "ffrt:libffrt", "googletest:gmock_main", "googletest:gtest_main", + "graphic_2d:2d_graphics", + "graphic_2d:librender_service_client", + "graphic_2d:librender_service_base", "hicollie:libhicollie", "hilog:libhilog", "hisysevent:libhisysevent", @@ -389,6 +402,11 @@ ohos_unittest("accessibility_common_event_registry_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "mock/src/mock_accessibility_account_data.cpp", "mock/src/mock_accessible_ability_manager_service.cpp", "mock/src/mock_system_ability.cpp", @@ -483,6 +501,11 @@ ohos_unittest("accessibility_input_interceptor_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "mock/src/aafwk/mock_bundle_manager.cpp", "mock/src/mock_accessibility_account_data.cpp", "mock/src/mock_accessibility_keyevent_filter.cpp", @@ -581,6 +604,11 @@ ohos_unittest("accessibility_window_manager_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "mock/src/aafwk/mock_bundle_manager.cpp", "mock/src/mock_accessibility_account_data.cpp", "mock/src/mock_accessibility_common_event.cpp", @@ -669,6 +697,11 @@ ohos_unittest("accessibility_keyevent_filter_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "../src/accessibility_resource_bundle_manager.cpp", "./mock/src/mock_accessibility_account_data.cpp", "./mock/src/mock_accessibility_event_transmission.cpp", @@ -768,6 +801,11 @@ ohos_unittest("accessible_ability_connection_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "mock/src/aafwk/mock_bundle_manager.cpp", "mock/src/mock_accessibility_element_operator_callback_stub.cpp", "mock/src/mock_accessibility_element_operator_stub.cpp", @@ -870,6 +908,9 @@ ohos_unittest("accessibility_display_manager_test") { "ffrt:libffrt", "googletest:gmock_main", "googletest:gtest_main", + "graphic_2d:2d_graphics", + "graphic_2d:librender_service_client", + "graphic_2d:librender_service_base", "hilog:libhilog", "hisysevent:libhisysevent", "i18n:intl_util", @@ -948,6 +989,9 @@ ohos_unittest("accessibility_dumper_test") { "ffrt:libffrt", "googletest:gmock_main", "googletest:gtest_main", + "graphic_2d:2d_graphics", + "graphic_2d:librender_service_client", + "graphic_2d:librender_service_base", "hicollie:libhicollie", "hilog:libhilog", "hisysevent:libhisysevent", @@ -1002,6 +1046,11 @@ ohos_unittest("accessibility_touchevent_injector_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "mock/src/mock_accessibility_common_event.cpp", "mock/src/mock_accessibility_event_transmission.cpp", "mock/src/mock_accessible_ability_client_stub_impl.cpp", @@ -1191,6 +1240,11 @@ ohos_unittest("accessibility_mouse_autoclick_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "mock/src/mock_accessibility_common_event.cpp", "mock/src/mock_accessibility_event_transmission.cpp", "mock/src/mock_accessibility_settings_config.cpp", @@ -1288,6 +1342,11 @@ ohos_unittest("accessibility_screen_touch_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "mock/src/mock_accessibility_account_data.cpp", "mock/src/mock_accessibility_common_event.cpp", "mock/src/mock_accessibility_event_transmission.cpp", @@ -1390,6 +1449,9 @@ ohos_unittest("accessibility_mouse_key_test") { "ffrt:libffrt", "googletest:gmock_main", "googletest:gtest_main", + "graphic_2d:2d_graphics", + "graphic_2d:librender_service_client", + "graphic_2d:librender_service_base", "hilog:libhilog", "hisysevent:libhisysevent", "i18n:intl_util", @@ -1441,6 +1503,11 @@ ohos_unittest("accessibility_short_key_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "mock/src/mock_accessibility_common_event.cpp", "mock/src/mock_accessibility_event_transmission.cpp", "mock/src/mock_accessible_ability_client_stub_impl.cpp", @@ -1628,6 +1695,11 @@ ohos_unittest("accessibility_settings_config_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "unittest/accessibility_settings_config_test.cpp", ] @@ -1723,6 +1795,11 @@ ohos_unittest("accessibility_zoom_gesture_test") { "../src/touch_exploration_multi_finger_gesture.cpp", "../src/touch_exploration_single_finger_gesture.cpp", "../src/utils.cpp", + "../src/magnification_manager.cpp", + "../src/window_magnification_gesture.cpp", + "../src/magnification_menu_manager.cpp", + "../src/full_screen_magnification_manager.cpp", + "../src/window_magnification_manager.cpp", "mock/src/mock_accessibility_common_event.cpp", "mock/src/mock_accessibility_display_manager.cpp", "mock/src/mock_accessibility_event_transmission.cpp", diff --git a/services/aams/test/mock/src/mock_accessibility_display_manager.cpp b/services/aams/test/mock/src/mock_accessibility_display_manager.cpp index 1f4ee800..15e61a6f 100644 --- a/services/aams/test/mock/src/mock_accessibility_display_manager.cpp +++ b/services/aams/test/mock/src/mock_accessibility_display_manager.cpp @@ -24,7 +24,6 @@ namespace Accessibility { constexpr int32_t DEFAULT_DPI = 540; constexpr int32_t DEFAULT_WIDTH = 1260; constexpr int32_t DEFAULT_HEIGHT = 2720; -constexpr float DEFAULT_SCALE = 2.0f; constexpr float NORMAL_SCALE = 1.0f; AccessibilityDisplayManager::AccessibilityDisplayManager() diff --git a/services/aams/test/mock/src/mock_accessibility_input_interceptor.cpp b/services/aams/test/mock/src/mock_accessibility_input_interceptor.cpp index 721a8e03..bbb067d1 100644 --- a/services/aams/test/mock/src/mock_accessibility_input_interceptor.cpp +++ b/services/aams/test/mock/src/mock_accessibility_input_interceptor.cpp @@ -121,5 +121,10 @@ void AccessibilityInputEventConsumer::OnInputEvent(std::shared_ptr AccessibleAbilityManagerService::GetMagnificationMgr() +{ + return nullptr; +} + +std::shared_ptr AccessibleAbilityManagerService::GetWindowMagnificationManager() +{ + return nullptr; +} + +std::shared_ptr AccessibleAbilityManagerService::GetFullScreenMagnificationManager() +{ + return nullptr; +} } // namespace Accessibility } // namespace OHOS \ No newline at end of file diff --git a/services/aams/test/unittest/accessibility_zoom_gesture_test.cpp b/services/aams/test/unittest/accessibility_zoom_gesture_test.cpp index 2542c58b..6052d3a4 100644 --- a/services/aams/test/unittest/accessibility_zoom_gesture_test.cpp +++ b/services/aams/test/unittest/accessibility_zoom_gesture_test.cpp @@ -19,6 +19,7 @@ #include "accessibility_ut_helper.h" #include "accessibility_zoom_gesture.h" #include "accessible_ability_manager_service.h" +#include "full_screen_magnification_manager.h" using namespace testing; using namespace testing::ext; @@ -60,7 +61,8 @@ void AccessibilityZoomGestureUnitTest::TearDownTestCase() void AccessibilityZoomGestureUnitTest::SetUp() { GTEST_LOG_(INFO) << "SetUp"; - zoomGesture_ = std::make_shared(); + std::shared_ptr manager = std::make_shared(); + zoomGesture_ = std::make_shared(manager); } void AccessibilityZoomGestureUnitTest::TearDown() diff --git a/services/test/BUILD.gn b/services/test/BUILD.gn index 89a86f5a..41b1e211 100644 --- a/services/test/BUILD.gn +++ b/services/test/BUILD.gn @@ -83,6 +83,11 @@ ohos_moduletest("aams_accessibility_touch_exploration_test") { "../aams/src/accessibility_window_connection.cpp", "../aams/src/accessibility_window_manager.cpp", "../aams/src/accessibility_zoom_gesture.cpp", + "../aams/src/magnification_manager.cpp", + "../aams/src/window_magnification_gesture.cpp", + "../aams/src/magnification_menu_manager.cpp", + "../aams/src/full_screen_magnification_manager.cpp", + "../aams/src/window_magnification_manager.cpp", "../aams/src/accessible_ability_channel.cpp", "../aams/src/accessible_ability_connection.cpp", "../aams/src/accessible_ability_manager_service.cpp", @@ -194,6 +199,11 @@ ohos_moduletest("aams_accessibility_touchEvent_injector_test") { "../aams/src/accessibility_window_connection.cpp", "../aams/src/accessibility_window_manager.cpp", "../aams/src/accessibility_zoom_gesture.cpp", + "../aams/src/magnification_manager.cpp", + "../aams/src/window_magnification_gesture.cpp", + "../aams/src/magnification_menu_manager.cpp", + "../aams/src/full_screen_magnification_manager.cpp", + "../aams/src/window_magnification_manager.cpp", "../aams/src/accessible_ability_channel.cpp", "../aams/src/accessible_ability_connection.cpp", "../aams/src/accessible_ability_manager_service.cpp", @@ -306,6 +316,11 @@ ohos_moduletest("aams_accessible_ability_channel_test") { "../aams/src/accessibility_window_connection.cpp", "../aams/src/accessibility_window_manager.cpp", "../aams/src/accessibility_zoom_gesture.cpp", + "../aams/src/magnification_manager.cpp", + "../aams/src/window_magnification_gesture.cpp", + "../aams/src/magnification_menu_manager.cpp", + "../aams/src/full_screen_magnification_manager.cpp", + "../aams/src/window_magnification_manager.cpp", "../aams/src/accessible_ability_channel.cpp", "../aams/src/accessible_ability_connection.cpp", "../aams/src/accessible_ability_manager_service.cpp", @@ -417,6 +432,11 @@ ohos_moduletest("aams_server_test") { "../aams/src/accessibility_window_connection.cpp", "../aams/src/accessibility_window_manager.cpp", "../aams/src/accessibility_zoom_gesture.cpp", + "../aams/src/magnification_manager.cpp", + "../aams/src/window_magnification_gesture.cpp", + "../aams/src/magnification_menu_manager.cpp", + "../aams/src/full_screen_magnification_manager.cpp", + "../aams/src/window_magnification_manager.cpp", "../aams/src/accessible_ability_channel.cpp", "../aams/src/accessible_ability_connection.cpp", "../aams/src/accessible_ability_manager_service.cpp", @@ -526,6 +546,11 @@ ohos_moduletest("aams_accessibility_keyevent_filter_test") { "../aams/src/accessibility_window_connection.cpp", "../aams/src/accessibility_window_manager.cpp", "../aams/src/accessibility_zoom_gesture.cpp", + "../aams/src/magnification_manager.cpp", + "../aams/src/window_magnification_gesture.cpp", + "../aams/src/magnification_menu_manager.cpp", + "../aams/src/full_screen_magnification_manager.cpp", + "../aams/src/window_magnification_manager.cpp", "../aams/src/accessible_ability_channel.cpp", "../aams/src/accessible_ability_connection.cpp", "../aams/src/accessible_ability_manager_service.cpp", @@ -636,6 +661,11 @@ ohos_moduletest("aams_common_event_registry_test") { "../aams/src/accessibility_window_connection.cpp", "../aams/src/accessibility_window_manager.cpp", "../aams/src/accessibility_zoom_gesture.cpp", + "../aams/src/magnification_manager.cpp", + "../aams/src/window_magnification_gesture.cpp", + "../aams/src/magnification_menu_manager.cpp", + "../aams/src/full_screen_magnification_manager.cpp", + "../aams/src/window_magnification_manager.cpp", "../aams/src/accessible_ability_channel.cpp", "../aams/src/accessible_ability_connection.cpp", "../aams/src/accessible_ability_manager_service.cpp", -- Gitee