• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025-2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 // LCOV_EXCL_START
17 #include "magnification_menu.h"
18 #include "visibility.h"
19 
20 namespace OHOS {
21 namespace Accessibility {
22 namespace {
23     const std::string FULL_SCREEN_PATH = "/system/etc/accessibility/fullScreen.png";
24     const std::string WINDOW_PATH = "/system/etc/accessibility/window.png";
25     const std::string MENU_NAME = "magnification_menu";
26 }
27 static MagnificationMenu instance;
28 
CreateMenuWindow()29 void MagnificationMenu::CreateMenuWindow()
30 {
31     HILOG_DEBUG();
32     GetWindowParam();
33     menuRect_ = {(static_cast<int32_t>(screenWidth_ - menuSize_) - margin_), (
34         static_cast<int32_t>(screenHeight_ - menuSize_) - margin_), menuSize_, menuSize_};
35     sptr<Rosen::WindowOption> windowOption = new(std::nothrow) Rosen::WindowOption();
36     if (windowOption == nullptr) {
37         HILOG_ERROR("windowOption is null");
38         return;
39     }
40     windowOption->SetWindowType(Rosen::WindowType::WINDOW_TYPE_MAGNIFICATION_MENU);
41     windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING);
42     windowOption->SetWindowRect(menuRect_);
43     menuWindow_ = Rosen::Window::Create(MENU_NAME, windowOption);
44     if (menuWindow_ == nullptr) {
45         HILOG_ERROR("create failed");
46         ExtUtils::RecordMagnificationUnavailableEvent("Create menu failed.");
47         return;
48     }
49     menuWindow_->SetCornerRadius(MENU_CORNER_RADIUS);
50     surfaceNode_ = menuWindow_->GetSurfaceNode();
51     if (surfaceNode_ == nullptr) {
52         HILOG_ERROR("surfaceNode_ is nullptr.");
53         return;
54     }
55     rsUIContext_ = surfaceNode_->GetRSUIContext();
56     canvasNode_ = Rosen::RSCanvasNode::Create(false, false, rsUIContext_);
57     if (canvasNode_ == nullptr) {
58         HILOG_ERROR("create canvasNode_ fail.");
59         return;
60     }
61     canvasNode_->SetSkipCheckInMultiInstance(true);
62     surfaceNode_->SetAbilityBGAlpha(BG_ALPHA);
63     surfaceNode_->AddChild(canvasNode_, -1);
64     canvasNode_->SetBounds(0, 0, menuSize_, menuSize_);
65     canvasNode_->SetFrame(0, 0, menuSize_, menuSize_);
66     canvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
67     canvasNode_->SetRotation(0);
68     rosenImage_ = std::make_shared<Rosen::RSImage>();
69 }
70 
LoadMenuBgImage(uint32_t mode)71 void MagnificationMenu::LoadMenuBgImage(uint32_t mode)
72 {
73     HILOG_DEBUG();
74     std::string path = FULL_SCREEN_PATH;
75     if (mode == WINDOW_MAGNIFICATION) {
76         path = WINDOW_PATH;
77     }
78     bgpixelmap_ = DecodePixelMap(path, allocatorType_);
79     if (bgpixelmap_ == nullptr) {
80         HILOG_ERROR("DecodePixelMap failed.");
81         return;
82     }
83     if (canvasNode_ == nullptr) {
84         HILOG_ERROR("canvasNode_ is nullptr.");
85         return;
86     }
87     canvasNode_->SetBgImageWidth(menuSize_);
88     canvasNode_->SetBgImageHeight(menuSize_);
89     canvasNode_->SetBgImagePositionX(0);
90     canvasNode_->SetBgImagePositionY(0);
91     if (rosenImage_ == nullptr) {
92         HILOG_ERROR("rosenImage_ is nullptr.");
93         return;
94     }
95     rosenImage_->SetPixelMap(bgpixelmap_);
96     rosenImage_->SetImageFit(static_cast<int>(Rosen::ImageFit::FILL));
97     canvasNode_->SetBgImage(rosenImage_);
98     if (menuWindow_ == nullptr) {
99         HILOG_ERROR("create failed");
100         return;
101     }
102     menuWindow_->Show();
103 }
104 
ShowMenuWindow(uint32_t mode)105 void MagnificationMenu::ShowMenuWindow(uint32_t mode)
106 {
107     HILOG_INFO();
108     menuMode_ = mode;
109     if (currentType_ != SWITCH_MAGNIFICATION) {
110         HILOG_WARN("no need show menu.");
111         return;
112     }
113 
114     if (menuWindow_ == nullptr) {
115         HILOG_ERROR("window is null. need create.");
116         CreateMenuWindow();
117     }
118 
119     if (menuWindow_ == nullptr) {
120         HILOG_ERROR("create window failed.");
121         return;
122     }
123 
124     LoadMenuBgImage(mode);
125     FlushImplicitTransaction();
126     isMenuShown_ = true;
127 }
128 
DisableMenuWindow()129 void MagnificationMenu::DisableMenuWindow()
130 {
131     HILOG_INFO();
132     if (!isMenuShown_) {
133         HILOG_INFO("menu not shown.");
134         return;
135     }
136     if (surfaceNode_ != nullptr) {
137         surfaceNode_->SetVisible(false);
138         surfaceNode_->ClearChildren();
139         FlushImplicitTransaction();
140     }
141 
142     isMenuShown_ = false;
143     if (menuWindow_ != nullptr) {
144         menuWindow_->Hide();
145         menuWindow_->Destroy();
146         menuWindow_ = nullptr;
147     }
148     surfaceNode_ = nullptr;
149     canvasNode_ = nullptr;
150     rsUIContext_ = nullptr;
151     bgpixelmap_ = nullptr;
152     rosenImage_ = nullptr;
153 }
154 
MoveMenuWindow(int32_t deltaX,int32_t deltaY)155 void MagnificationMenu::MoveMenuWindow(int32_t deltaX, int32_t deltaY)
156 {
157     HILOG_DEBUG();
158     if (menuWindow_ == nullptr) {
159         HILOG_ERROR("menuWindow_ is null.");
160         return;
161     }
162     int32_t menuPosX = menuRect_.posX_ + deltaX;
163     int32_t menuPosY = menuRect_.posY_ + deltaY;
164 
165     menuRect_.posX_ = menuPosX;
166     menuRect_.posY_ = menuPosY;
167 
168     AdjustMenuPosition();
169     menuWindow_->MoveTo(menuRect_.posX_, menuRect_.posY_);
170 }
171 
AttachToEdge()172 void MagnificationMenu::AttachToEdge()
173 {
174     if (menuWindow_ == nullptr) {
175         HILOG_ERROR("menuWindow_ is null.");
176         return;
177     }
178 
179     if (menuRect_.posX_ < static_cast<int32_t>(screenWidth_ / DIVISOR_TWO)) {
180         menuRect_.posX_ = margin_;
181     } else {
182         menuRect_.posX_ = static_cast<int32_t>(screenWidth_ - menuSize_) - margin_;
183     }
184     menuWindow_->MoveTo(menuRect_.posX_, menuRect_.posY_);
185 }
186 
SetCurrentType(uint32_t type)187 void MagnificationMenu::SetCurrentType(uint32_t type)
188 {
189     currentType_ = type;
190 }
191 
IsTapOnMenu(int32_t posX,int32_t posY)192 bool MagnificationMenu::IsTapOnMenu(int32_t posX, int32_t posY)
193 {
194     if (!isMenuShown_) {
195         return false;
196     }
197     return ExtUtils::IsInRect(posX, posY, menuRect_);
198 }
199 
ChangeMode()200 uint32_t MagnificationMenu::ChangeMode()
201 {
202     if (menuMode_ == WINDOW_MAGNIFICATION) {
203         menuMode_ = FULL_SCREEN_MAGNIFICATION;
204         return menuMode_;
205     }
206     if (menuMode_ == FULL_SCREEN_MAGNIFICATION) {
207         menuMode_ = WINDOW_MAGNIFICATION;
208         return menuMode_;
209     }
210     return 0;
211 }
212 
AdjustMenuPosition()213 void MagnificationMenu::AdjustMenuPosition()
214 {
215     if (menuRect_.posX_ < margin_) {
216         menuRect_.posX_ = margin_;
217     }
218 
219     if (menuRect_.posY_ < margin_) {
220         menuRect_.posY_ = margin_;
221     }
222 
223     if (menuRect_.posX_ + static_cast<int32_t>(menuRect_.width_) + margin_ > static_cast<int32_t>(screenWidth_)) {
224         menuRect_.posX_ = static_cast<int32_t>(screenWidth_) - static_cast<int32_t>(menuRect_.width_) - margin_;
225     }
226 
227     if (menuRect_.posY_ + static_cast<int32_t>(menuRect_.height_) + margin_ > static_cast<int32_t>(screenHeight_)) {
228         menuRect_.posY_ = static_cast<int32_t>(screenHeight_) - static_cast<int32_t>(menuRect_.height_) - margin_;
229     }
230 }
231 
DecodePixelMap(const std::string & pathName,const Media::AllocatorType & allocatorType)232 std::shared_ptr<Media::PixelMap> MagnificationMenu::DecodePixelMap(
233     const std::string& pathName, const Media::AllocatorType& allocatorType)
234 {
235     uint32_t errCode = 0;
236     std::unique_ptr<Media::ImageSource> imageSource =
237         Media::ImageSource::CreateImageSource(pathName, Media::SourceOptions(), errCode);
238     if (imageSource == nullptr || errCode != 0) {
239         HILOG_ERROR("CreateImageSource failed.");
240         return nullptr;
241     }
242 
243     Media::DecodeOptions decodeOpt;
244     decodeOpt.allocatorType = allocatorType;
245     std::shared_ptr<Media::PixelMap> pixelmap = imageSource->CreatePixelMap(decodeOpt, errCode);
246     if (pixelmap == nullptr || errCode != 0) {
247         HILOG_ERROR("CreatePixelMap failed.");
248         return nullptr;
249     }
250     return pixelmap;
251 }
252 
GetWindowParam()253 void MagnificationMenu::GetWindowParam()
254 {
255     HILOG_DEBUG();
256 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
257     screenId_ = Rosen::DisplayManager::GetInstance().GetDefaultDisplayId();
258     sptr<Rosen::Display> display = Rosen::DisplayManager::GetInstance().GetDisplayById(screenId_);
259     if (display == nullptr) {
260         HILOG_ERROR("display is nullptr.");
261         return;
262     }
263     screenWidth_ = static_cast<uint32_t>(display->GetWidth());
264     screenHeight_ = static_cast<uint32_t>(display->GetHeight());
265     screenRect_ = {0, 0, screenWidth_, screenHeight_};
266 #else
267     HILOG_INFO("not support");
268 #endif
269 }
270 
RefreshWindowParam()271 void MagnificationMenu::RefreshWindowParam()
272 {
273     HILOG_DEBUG();
274     if (isMenuShown_) {
275         DisableMenuWindow();
276         ShowMenuWindow(menuMode_);
277     } else {
278         GetWindowParam();
279     }
280 }
281 
FlushImplicitTransaction()282 void MagnificationMenu::FlushImplicitTransaction()
283 {
284     if (rsUIContext_ != nullptr) {
285         auto rsTransaction = rsUIContext_->GetRSTransaction();
286         if (rsTransaction != nullptr) {
287             rsTransaction->FlushImplicitTransaction();
288         }
289     } else {
290         Rosen::RSTransaction::FlushImplicitTransaction();
291     }
292 }
293 
IsMenuShown()294 bool MagnificationMenu::IsMenuShown()
295 {
296     return isMenuShown_;
297 }
298 
ShowMenuWindow(uint32_t mode)299 extern "C" API_EXPORT void ShowMenuWindow(uint32_t mode)
300 {
301     instance.ShowMenuWindow(mode);
302 }
303 
DisableMenuWindow()304 extern "C" API_EXPORT void DisableMenuWindow()
305 {
306     instance.DisableMenuWindow();
307 }
308 
MoveMenuWindow(int32_t deltaX,int32_t deltaY)309 extern "C" API_EXPORT void MoveMenuWindow(int32_t deltaX, int32_t deltaY)
310 {
311     instance.MoveMenuWindow(deltaX, deltaY);
312 }
313 
IsTapOnMenu(int32_t posX,int32_t posY)314 extern "C" API_EXPORT bool IsTapOnMenu(int32_t posX, int32_t posY)
315 {
316     return instance.IsTapOnMenu(posX, posY);
317 }
318 
AttachToEdge()319 extern "C" API_EXPORT void AttachToEdge()
320 {
321     instance.AttachToEdge();
322 }
323 
RefreshWindowParamMenu()324 extern "C" API_EXPORT void RefreshWindowParamMenu()
325 {
326     instance.RefreshWindowParam();
327 }
328 
SetCurrentType(uint32_t type)329 extern "C" API_EXPORT void SetCurrentType(uint32_t type)
330 {
331     instance.SetCurrentType(type);
332 }
333 
ChangeMode()334 extern "C" API_EXPORT uint32_t ChangeMode()
335 {
336     return instance.ChangeMode();
337 }
338 
IsMenuShown()339 extern "C" API_EXPORT bool IsMenuShown()
340 {
341     return instance.IsMenuShown();
342 }
343 }
344 }
345 // LCOV_EXCL_STOP