* Copyright (C) 2025-2026 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.
*/
#include "hilog_wrapper.h"
#include "magnification_manager.h"
#include "accessibility_display_manager.h"
#include "magnification_menu_manager.h"
#include "magnification_window.h"
#include "extend_service_manager.h"
namespace OHOS {
namespace Accessibility {
std::shared_ptr<MagnificationManager> MagnificationManager::instance_ = nullptr;
ffrt::mutex MagnificationManager::instanceMutex_;
std::shared_ptr<MagnificationManager> MagnificationManager::GetInstance()
{
if (!instance_) {
std::lock_guard<ffrt::mutex> lock(instanceMutex_);
if (!instance_) {
HILOG_INFO("Create MagnificationManager instance.");
instance_ = std::make_shared<MagnificationManager>();
}
}
return instance_;
}
MagnificationManager::MagnificationManager()
{
EventFwk::MatchingSkills matchingSkills;
matchingSkills.AddEvent("usual.event.SCREEN_OFF");
EventFwk::CommonEventSubscribeInfo subscribeInfo(matchingSkills);
subscriber_ = std::make_shared<SystemEventSubscriber>(
subscribeInfo, std::bind(&MagnificationManager::OnReceiveEvent, this, std::placeholders::_1));
}
void MagnificationManager::SubscribeCommonEvent()
{
if (subscriber_ != nullptr) {
HILOG_INFO("subscribe screen off event");
EventFwk::CommonEventManager::SubscribeCommonEvent(subscriber_);
}
}
void MagnificationManager::UnSubscribeCommonEvent()
{
if (subscriber_ != nullptr) {
bool unSubscribeResult = EventFwk::CommonEventManager::UnSubscribeCommonEvent(subscriber_);
HILOG_INFO("unSubscribeResult = %{public}d", unSubscribeResult);
}
}
void MagnificationManager::OnReceiveEvent(const EventFwk::CommonEventData &data)
{
std::string action = data.GetWant().GetAction();
if (action == "usual.event.SCREEN_OFF") {
HILOG_INFO("screen off received");
DisableMagnification();
}
}
std::shared_ptr<WindowMagnificationManager> MagnificationManager::GetWindowMagnificationManager()
{
HILOG_DEBUG();
currentMode_ = Singleton<ExtendServiceManager>::GetInstance().getMagnificationModeCallback();
if (windowMagnificationManager_ == nullptr) {
windowMagnificationManager_ = std::make_shared<WindowMagnificationManager>();
}
return windowMagnificationManager_;
}
std::shared_ptr<FullScreenMagnificationManager> MagnificationManager::GetFullScreenMagnificationManager()
{
HILOG_DEBUG();
currentMode_ = Singleton<ExtendServiceManager>::GetInstance().getMagnificationModeCallback();
if (fullScreenMagnificationManager_ == nullptr) {
fullScreenMagnificationManager_ = std::make_shared<FullScreenMagnificationManager>();
}
return fullScreenMagnificationManager_;
}
std::shared_ptr<MagnificationMenuManager> MagnificationManager::GetMenuManager()
{
HILOG_DEBUG();
if (menuManager_ == nullptr) {
menuManager_ = std::make_shared<MagnificationMenuManager>();
}
return menuManager_;
}
void MagnificationManager::OnMagnificationTypeChanged(uint32_t magnificationType)
{
HILOG_INFO("magnificationType = %{public}d, currentMode_ = %{public}d", magnificationType, currentMode_);
if (windowMagnificationManager_ == nullptr) {
HILOG_DEBUG("GetWindowMagnificationManager");
GetWindowMagnificationManager();
}
if (fullScreenMagnificationManager_ == nullptr) {
HILOG_DEBUG("GetFullScreenMagnificationManager");
GetFullScreenMagnificationManager();
}
currentMode_ = Singleton<ExtendServiceManager>::GetInstance().getMagnificationModeCallback();
Singleton<MagnificationMenuManager>::GetInstance().SetCurrentType(magnificationType);
if (magnificationType == SWITCH_MAGNIFICATION) {
if (windowMagnificationManager_ != nullptr && windowMagnificationManager_->IsMagnificationWindowShow()) {
Singleton<MagnificationMenuManager>::GetInstance().DisableMenuWindow();
Singleton<MagnificationMenuManager>::GetInstance().ShowMenuWindow(currentMode_);
return;
}
if (fullScreenMagnificationManager_ != nullptr &&
fullScreenMagnificationManager_->IsMagnificationWindowShow()) {
Singleton<MagnificationMenuManager>::GetInstance().DisableMenuWindow();
Singleton<MagnificationMenuManager>::GetInstance().ShowMenuWindow(currentMode_);
return;
}
}
Singleton<MagnificationMenuManager>::GetInstance().DisableMenuWindow();
HILOG_INFO("magnificationType = %{public}d, currentMode_ = %{public}d", magnificationType, currentMode_);
if (currentMode_ == magnificationType) {
return;
}
bool state = Singleton<ExtendServiceManager>::GetInstance().getMagnificationState();
if (!state) {
currentMode_ = magnificationType;
Singleton<ExtendServiceManager>::GetInstance().magnificationModeCallback(
static_cast<int32_t>(magnificationType));
return;
}
OnModeChanged(magnificationType);
}
void MagnificationManager::OnModeChanged(uint32_t mode)
{
HILOG_INFO("mode = %{public}d.", mode);
if (windowMagnificationManager_ == nullptr) {
GetWindowMagnificationManager();
}
if (fullScreenMagnificationManager_ == nullptr) {
GetFullScreenMagnificationManager();
}
if (mode != FULL_SCREEN_MAGNIFICATION && mode != WINDOW_MAGNIFICATION) {
HILOG_ERROR("invalid mode = %{public}d.", mode);
return;
}
auto interceptor = AccessibilityInputInterceptor::GetInstance();
if (interceptor == nullptr) {
HILOG_ERROR("interceptor is nullptr.");
return;
}
bool needShow = false;
PointerPos pos = {0, 0};
if (mode == WINDOW_MAGNIFICATION) {
HILOG_INFO("disable full screen magnification.");
if (fullScreenMagnificationManager_ != nullptr) {
needShow = fullScreenMagnificationManager_->IsMagnificationWindowShow();
pos = fullScreenMagnificationManager_->GetSourceCenter();
fullScreenMagnificationManager_->DisableMagnification();
}
if (windowMagnificationManager_ != nullptr && needShow) {
windowMagnificationManager_->ShowWindowMagnificationWithPosition(pos);
Singleton<ExtendServiceManager>::GetInstance().announcedForMagnificationCallback(
AnnounceType::ANNOUNCE_SWITCH_WINDOW);
}
} else {
HILOG_INFO("disable window magnification.");
if (windowMagnificationManager_ != nullptr) {
needShow = windowMagnificationManager_->IsMagnificationWindowShow();
pos = windowMagnificationManager_->GetSourceCenter();
windowMagnificationManager_->DisableWindowMagnification();
}
if (fullScreenMagnificationManager_ != nullptr && needShow) {
fullScreenMagnificationManager_->ShowMagnificationWithPosition(pos);
Singleton<ExtendServiceManager>::GetInstance().announcedForMagnificationCallback(
AnnounceType::ANNOUNCE_SWITCH_FULL_SCREEN);
}
}
Singleton<ExtendServiceManager>::GetInstance().magnificationModeCallback(static_cast<int32_t>(mode));
currentMode_ = mode;
interceptor->SetMagnificationMode(mode);
}
void MagnificationManager::DisableMagnification()
{
HILOG_INFO();
auto interceptor = AccessibilityInputInterceptor::GetInstance();
if (interceptor == nullptr) {
HILOG_ERROR("interceptor is nullptr.");
return;
}
if (menuManager_ != nullptr) {
menuManager_->DisableMenuWindow();
}
if (windowMagnificationManager_ != nullptr && windowMagnificationManager_->IsMagnificationWindowShow()) {
HILOG_INFO("disable window");
windowMagnificationManager_->DisableWindowMagnification();
interceptor->DisableGesture(WINDOW_MAGNIFICATION);
}
if (fullScreenMagnificationManager_ != nullptr && fullScreenMagnificationManager_->IsMagnificationWindowShow()) {
HILOG_INFO("disable full");
fullScreenMagnificationManager_->DisableMagnification();
interceptor->DisableGesture(FULL_SCREEN_MAGNIFICATION);
}
}
void MagnificationManager::TriggerMagnification(uint32_t type, uint32_t mode)
{
HILOG_INFO("type = %{public}d, mode = %{public}d", type, mode);
if (mode == WINDOW_MAGNIFICATION) {
if (windowMagnificationManager_ != nullptr) {
windowMagnificationManager_->ShowWindowMagnification();
}
}
if (mode == FULL_SCREEN_MAGNIFICATION) {
if (fullScreenMagnificationManager_ != nullptr) {
fullScreenMagnificationManager_->ShowMagnification();
}
}
if (type == SWITCH_MAGNIFICATION && menuManager_ != nullptr) {
menuManager_->ShowMenuWindow(mode);
}
auto interceptor = AccessibilityInputInterceptor::GetInstance();
if (interceptor == nullptr) {
HILOG_ERROR("interceptor is nullptr.");
return;
}
interceptor->EnableGesture(mode);
}
bool MagnificationManager::GetMagnificationState()
{
if (currentMode_ == WINDOW_MAGNIFICATION && windowMagnificationManager_ != nullptr) {
return windowMagnificationManager_->IsMagnificationWindowShow();
}
if (currentMode_ == FULL_SCREEN_MAGNIFICATION && fullScreenMagnificationManager_ != nullptr) {
return fullScreenMagnificationManager_->IsMagnificationWindowShow();
}
return false;
}
void MagnificationManager::RefreshWindowParam(RotationType type)
{
HILOG_DEBUG();
if (currentMode_ == WINDOW_MAGNIFICATION && windowMagnificationManager_ != nullptr) {
windowMagnificationManager_->RefreshWindowParam(type);
}
if (currentMode_ == FULL_SCREEN_MAGNIFICATION && fullScreenMagnificationManager_ != nullptr) {
fullScreenMagnificationManager_->RefreshWindowParam(type);
}
if (menuManager_ != nullptr) {
menuManager_->RefreshWindowParam();
}
}
void MagnificationManager::FollowFocuseElement(int32_t centerX, int32_t centerY)
{
currentMode_ = Singleton<ExtendServiceManager>::GetInstance().getMagnificationModeCallback();
HILOG_INFO("currentMode_ is %{public}d", currentMode_);
if (windowMagnificationManager_ == nullptr) {
windowMagnificationManager_ = std::make_shared<WindowMagnificationManager>();
}
if (fullScreenMagnificationManager_ == nullptr) {
fullScreenMagnificationManager_ = std::make_shared<FullScreenMagnificationManager>();
}
if (currentMode_ == WINDOW_MAGNIFICATION && windowMagnificationManager_ != nullptr) {
if (windowMagnificationManager_->IsMagnificationWindowShow()) {
windowMagnificationManager_->FollowFocuseElement(centerX, centerY);
}
}
if (currentMode_ == FULL_SCREEN_MAGNIFICATION && fullScreenMagnificationManager_ != nullptr) {
if (fullScreenMagnificationManager_->IsMagnificationWindowShow()) {
fullScreenMagnificationManager_->FollowFocuseElement(centerX, centerY);
}
}
}
}
}