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_window.h"
18 #include "visibility.h"
19
20 namespace OHOS {
21 namespace Accessibility {
22
23 namespace {
24 const std::string WINDOW_NAME = "magnification_window";
25 }
26
27 static MagnificationWindow instance;
28
29 //common
GetSourceCenter()30 PointerPos MagnificationWindow::GetSourceCenter()
31 {
32 PointerPos point = {0, 0};
33 point.posX = sourceRect_.posX_ + static_cast<int32_t>(sourceRect_.width_ / DIVISOR_TWO);
34 point.posY = sourceRect_.posY_ + static_cast<int32_t>(sourceRect_.height_ / DIVISOR_TWO);
35 return point;
36 }
37
ConvertCoordinates(int32_t posX,int32_t posY)38 PointerPos MagnificationWindow::ConvertCoordinates(int32_t posX, int32_t posY)
39 {
40 PointerPos sourcePoint = {0, 0};
41 if ((abs(scale_) < EPS)) {
42 return sourcePoint;
43 }
44 int32_t windowDeltaX = posX - windowRect_.posX_;
45 int32_t windowDeltaY = posY - windowRect_.posY_;
46 sourcePoint.posX = sourceRect_.posX_ + static_cast<int32_t>(windowDeltaX / scale_);
47 sourcePoint.posY = sourceRect_.posY_ + static_cast<int32_t>(windowDeltaY / scale_);
48 return sourcePoint;
49 }
50
CreateMagnificationWindow()51 void MagnificationWindow::CreateMagnificationWindow()
52 {
53 HILOG_DEBUG();
54 sptr<Rosen::WindowOption> windowOption = new(std::nothrow) Rosen::WindowOption();
55 if (windowOption == nullptr) {
56 HILOG_ERROR("windowOption is null.");
57 return;
58 }
59 windowOption->SetWindowType(Rosen::WindowType::WINDOW_TYPE_MAGNIFICATION);
60 windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING);
61 windowOption->SetWindowRect(windowRect_);
62 windowOption->SetFocusable(false);
63 window_ = OHOS::Rosen::Window::Create(WINDOW_NAME, windowOption);
64 if (window_ == nullptr) {
65 HILOG_ERROR("window create failed.");
66 ExtUtils::RecordMagnificationUnavailableEvent("Create window failed.");
67 return;
68 }
69 window_->SetCornerRadius(CORNER_RADIUS);
70 surfaceNode_ = window_->GetSurfaceNode();
71 if (surfaceNode_ == nullptr) {
72 HILOG_ERROR("get surfaceNode_ failed.");
73 return;
74 }
75 rsUIContext_ = surfaceNode_->GetRSUIContext();
76 canvasNode_ = Rosen::RSCanvasNode::Create(false, false, rsUIContext_);
77 if (canvasNode_ == nullptr) {
78 HILOG_ERROR("canvasNode_ is nullptr.");
79 return;
80 }
81 canvasNode_->SetSkipCheckInMultiInstance(true);
82 }
83
GetWindowParam()84 void MagnificationWindow::GetWindowParam()
85 {
86 HILOG_DEBUG();
87 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
88 screenId_ = Rosen::DisplayManager::GetInstance().GetDefaultDisplayId();
89 sptr<Rosen::Display> display = Rosen::DisplayManager::GetInstance().GetDisplayById(screenId_);
90 if (display == nullptr) {
91 HILOG_ERROR("display is nullptr.");
92 return;
93 }
94 screenWidth_ = static_cast<uint32_t>(display->GetWidth());
95 screenHeight_ = static_cast<uint32_t>(display->GetHeight());
96 screenSpan_ = hypot(screenWidth_, screenHeight_);
97 screenRect_ = {0, 0, screenWidth_, screenHeight_};
98 #else
99 HILOG_INFO("not support");
100 #endif
101 }
102
FlushImplicitTransaction()103 void MagnificationWindow::FlushImplicitTransaction()
104 {
105 if (rsUIContext_ != nullptr) {
106 auto rsTransaction = rsUIContext_->GetRSTransaction();
107 if (rsTransaction != nullptr) {
108 rsTransaction->FlushImplicitTransaction();
109 }
110 } else {
111 Rosen::RSTransaction::FlushImplicitTransaction();
112 }
113 }
114
GetRectCenter(Rosen::Rect rect)115 PointerPos MagnificationWindow::GetRectCenter(Rosen::Rect rect)
116 {
117 PointerPos point = {0, 0};
118 point.posX = rect.posX_ + static_cast<int32_t>(rect.width_ / DIVISOR_TWO);
119 point.posY = rect.posY_ + static_cast<int32_t>(rect.height_ / DIVISOR_TWO);
120 return point;
121 }
122
GetSourceRectFromPointer(int32_t centerX,int32_t centerY)123 Rosen::Rect MagnificationWindow::GetSourceRectFromPointer(int32_t centerX, int32_t centerY)
124 {
125 Rosen::Rect sourceRect = {0, 0, 0, 0};
126 if ((abs(scale_) < EPS)) {
127 return sourceRect;
128 }
129 sourceRect.width_ = static_cast<uint32_t>(static_cast<float>(windowRect_.width_) / scale_);
130 sourceRect.height_ = static_cast<uint32_t>(static_cast<float>(windowRect_.height_) / scale_);
131
132 int32_t x = centerX - static_cast<int32_t>(sourceRect.width_ / DIVISOR_TWO);
133 int32_t y = centerY - static_cast<int32_t>(sourceRect.height_ / DIVISOR_TWO);
134
135 x = (x < 0) ? 0 : x;
136 x = (x + static_cast<int32_t>(sourceRect.width_)) > static_cast<int32_t>(
137 screenWidth_) ? static_cast<int32_t>(screenWidth_ - sourceRect.width_) : x;
138
139 y = (y < 0) ? 0 : y;
140 y = (y + static_cast<int32_t>(sourceRect.height_)) > static_cast<int32_t>(
141 screenHeight_) ? static_cast<int32_t>(screenHeight_ - sourceRect.height_) : y;
142
143 sourceRect.posX_ = x;
144 sourceRect.posY_ = y;
145 HILOG_WARN("sourceRect_ = %{public}s", sourceRect_.ToString().c_str());
146 return sourceRect;
147 }
148
DisableMagnification(bool needClear)149 void MagnificationWindow::DisableMagnification(bool needClear)
150 {
151 HILOG_INFO();
152 if (needClear && surfaceNode_ != nullptr) {
153 HILOG_DEBUG("claer surfaceNode");
154 surfaceNode_->SetVisible(false);
155 surfaceNode_->ClearChildren();
156 FlushImplicitTransaction();
157 }
158
159 if (window_ != nullptr) {
160 window_->Hide();
161 window_->Destroy();
162 window_ = nullptr;
163 }
164 surfaceNode_ = nullptr;
165 canvasNode_ = nullptr;
166 rsUIContext_ = nullptr;
167 }
168
169 // full magnification
ConvertGesture(uint32_t type,PointerPos coordinates)170 PointerPos MagnificationWindow::ConvertGesture(uint32_t type, PointerPos coordinates)
171 {
172 int32_t posX = coordinates.posX;
173 int32_t posY = coordinates.posY;
174 PointerPos point = {posX, posY};
175
176 if (type == BOTTOM_BACK_GESTURE) {
177 int32_t offsetY = static_cast<int32_t>(screenHeight_) -
178 (sourceRect_.posY_ + static_cast<int32_t>(sourceRect_.height_));
179 point.posY = posY + offsetY;
180 return point;
181 }
182 if (type == LEFT_BACK_GESTURE) {
183 int32_t offsetX = sourceRect_.posX_;
184 point.posX = posX - offsetX;
185 return point;
186 }
187
188 if (type == RIGHT_BACK_GESTURE) {
189 int32_t offsetX = static_cast<int32_t>(screenWidth_) -
190 (sourceRect_.posX_ + static_cast<int32_t>(sourceRect_.width_));
191 point.posX = posX + offsetX;
192 return point;
193 }
194
195 return point;
196 }
197
CheckTapOnHotArea(int32_t posX,int32_t posY)198 uint32_t MagnificationWindow::CheckTapOnHotArea(int32_t posX, int32_t posY)
199 {
200 bool isTapOnBottom = posY <= static_cast<int32_t>(screenHeight_) &&
201 posY >= static_cast<int32_t>(screenHeight_) - GESTURE_OFFSET;
202 if (isTapOnBottom) {
203 HILOG_DEBUG("Tap On Bottom");
204 return BOTTOM_BACK_GESTURE;
205 }
206 bool isTapOnLeftSide = posX >= 0 && posX <= GESTURE_OFFSET;
207 if (isTapOnLeftSide) {
208 HILOG_DEBUG("Tap On Left Side");
209 return LEFT_BACK_GESTURE;
210 }
211 bool isTapOnRightSide = posX >= static_cast<int32_t>(screenWidth_) - GESTURE_OFFSET &&
212 posX <= static_cast<int32_t>(screenWidth_);
213 if (isTapOnRightSide) {
214 HILOG_DEBUG("Tap On Right Side");
215 return RIGHT_BACK_GESTURE;
216 }
217 return INVALID_GESTURE_TYPE;
218 }
219
FollowFocuseElementFull(int32_t centerX,int32_t centerY)220 void MagnificationWindow::FollowFocuseElementFull(int32_t centerX, int32_t centerY)
221 {
222 HILOG_DEBUG();
223 if (window_ == nullptr) {
224 HILOG_ERROR("window_ is nullptr.");
225 return;
226 }
227 sourceRect_ = GetSourceRectFromPointer(centerX, centerY);
228 window_->SetFrameRectForPartialZoomIn(sourceRect_);
229 DrawRuoundRectFrameFull();
230 FlushImplicitTransaction();
231 UpdateAnchor();
232 }
233
UpdateAnchor()234 void MagnificationWindow::UpdateAnchor()
235 {
236 centerX_ = static_cast<int32_t>((sourceRect_.posX_ + sourceRect_.posX_ +
237 static_cast<int32_t>(sourceRect_.width_)) / DIVISOR_TWO);
238 centerY_ = static_cast<int32_t>((sourceRect_.posY_ + sourceRect_.posY_ +
239 static_cast<int32_t>(sourceRect_.height_)) / DIVISOR_TWO);
240 }
241
DrawRuoundRectFrameFull()242 void MagnificationWindow::DrawRuoundRectFrameFull()
243 {
244 if (surfaceNode_ == nullptr) {
245 HILOG_ERROR("get surfaceNode_ failed.");
246 return;
247 }
248
249 if (canvasNode_ == nullptr) {
250 HILOG_ERROR("create canvasNode_ fail");
251 return;
252 }
253 surfaceNode_->SetAbilityBGAlpha(BG_ALPHA);
254 surfaceNode_->AddChild(canvasNode_, -1);
255 canvasNode_->SetBounds(0, 0, screenWidth_, screenHeight_);
256 canvasNode_->SetFrame(0, 0, screenWidth_, screenHeight_);
257 canvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
258 canvasNode_->SetRotation(0);
259
260 auto canvas = canvasNode_->BeginRecording(screenWidth_, screenHeight_);
261 if (canvas == nullptr) {
262 HILOG_ERROR("get canvas fail");
263 return;
264 }
265 Rosen::Drawing::Pen pen;
266 pen.SetAntiAlias(true);
267 pen.SetColor(ORANGE_COLOR);
268 pen.SetWidth(PEN_WIDTH);
269 canvas->AttachPen(pen);
270 Rosen::Drawing::Path path;
271 path.AddRoundRect({ROUND_RECT_MARGIN, ROUND_RECT_MARGIN,
272 screenWidth_ - ROUND_RECT_MARGIN, screenHeight_ - ROUND_RECT_MARGIN},
273 CORNER_RADIUS, CORNER_RADIUS, Rosen::Drawing::PathDirection::CW_DIRECTION);
274 canvas->DrawPath(path);
275 canvas->DetachPen();
276 canvasNode_->FinishRecording();
277 }
278
EnableMagnificationFull(int32_t centerX,int32_t centerY)279 void MagnificationWindow::EnableMagnificationFull(int32_t centerX, int32_t centerY)
280 {
281 HILOG_INFO("centerX = %{public}d, centerY = %{public}d.", centerX, centerY);
282 GetWindowParam();
283 if (window_ == nullptr) {
284 HILOG_DEBUG("window is null. need create.");
285 windowRect_ = {0, 0, screenWidth_, screenHeight_};
286 CreateMagnificationWindow();
287 }
288
289 if (window_ == nullptr) {
290 HILOG_ERROR("create window failed.");
291 return;
292 }
293 sourceRect_ = GetSourceRectFromPointer(centerX, centerY);
294 UpdateAnchor();
295 DrawRuoundRectFrameFull();
296 Rosen::WMError ret = window_->SetFrameRectForPartialZoomIn(sourceRect_);
297 if (ret != Rosen::WMError::WM_OK) {
298 HILOG_ERROR("Trigger magnification failed.");
299 ExtUtils::RecordMagnificationUnavailableEvent("Trigger magnification failed.");
300 }
301 window_->Show();
302 FlushImplicitTransaction();
303 isMagnificationShowFull_ = true;
304 }
305
DisableMagnificationFull(bool needClear)306 void MagnificationWindow::DisableMagnificationFull(bool needClear)
307 {
308 HILOG_INFO();
309 DisableMagnification();
310 isMagnificationShowFull_ = false;
311 }
312
SetScaleFull(float scaleSpan)313 void MagnificationWindow::SetScaleFull(float scaleSpan)
314 {
315 HILOG_DEBUG();
316 if (window_ == nullptr) {
317 HILOG_ERROR("window_ is nullptr.");
318 return;
319 }
320 if (screenWidth_ == 0 || screenHeight_ == 0 || abs(screenSpan_) < EPS) {
321 HILOG_ERROR("screen param invalid.");
322 return;
323 }
324
325 float ratio = scaleSpan / screenSpan_;
326 float tmpScale = scale_ + ratio * scale_;
327
328 if (tmpScale > MAX_SCALE) {
329 tmpScale = MAX_SCALE;
330 }
331 if (tmpScale < DEFAULT_SCALE) {
332 tmpScale = DEFAULT_SCALE;
333 }
334
335 uint32_t newWidth = static_cast<uint32_t>(windowRect_.width_ / tmpScale);
336 uint32_t newHeight = static_cast<uint32_t>(windowRect_.height_ / tmpScale);
337 int32_t newPosX = centerX_ - static_cast<int32_t>(newWidth / DIVISOR_TWO);
338 int32_t newPosY = centerY_ - static_cast<int32_t>(newHeight / DIVISOR_TWO);
339
340 if (newPosX < 0) {
341 centerX_ -= newPosX;
342 newPosX = 0;
343 }
344
345 if (newPosY < 0) {
346 centerY_ -= newPosY;
347 newPosY = 0;
348 }
349
350 if (newPosX + static_cast<int32_t>(newWidth) > static_cast<int32_t>(screenWidth_)) {
351 centerX_ -= (newPosX + static_cast<int32_t>(newWidth) - static_cast<int32_t>(screenWidth_));
352 newPosX = static_cast<int32_t>(screenWidth_) - static_cast<int32_t>(newWidth);
353 }
354
355 if (newPosY + static_cast<int32_t>(newHeight) > static_cast<int32_t>(screenHeight_)) {
356 centerY_ -= (newPosY + static_cast<int32_t>(newHeight) - static_cast<int32_t>(screenHeight_));
357 newPosY = static_cast<int32_t>(screenHeight_) - static_cast<int32_t>(newHeight);
358 }
359
360 sourceRect_ = {newPosX, newPosY, newWidth, newHeight};
361 scale_ = tmpScale;
362 window_->SetFrameRectForPartialZoomIn(sourceRect_);
363 DrawRuoundRectFrameFull();
364 FlushImplicitTransaction();
365 UpdateAnchor();
366 }
367
MoveMagnificationFull(int32_t deltaX,int32_t deltaY)368 void MagnificationWindow::MoveMagnificationFull(int32_t deltaX, int32_t deltaY)
369 {
370 HILOG_DEBUG();
371 if (window_ == nullptr) {
372 HILOG_ERROR("window_ is nullptr.");
373 return;
374 }
375 int32_t sourcePosX = sourceRect_.posX_ - deltaX;
376 int32_t sourcePosY = sourceRect_.posY_ - deltaY;
377
378 if (sourcePosX < 0) {
379 sourcePosX = 0;
380 }
381
382 if (sourcePosY < 0) {
383 sourcePosY = 0;
384 }
385
386 if (sourcePosX + static_cast<int32_t>(sourceRect_.width_) > static_cast<int32_t>(screenWidth_)) {
387 sourcePosX = static_cast<int32_t>(screenWidth_) - static_cast<int32_t>(sourceRect_.width_);
388 }
389
390 if (sourcePosY + static_cast<int32_t>(sourceRect_.height_) > static_cast<int32_t>(screenHeight_)) {
391 sourcePosY = static_cast<int32_t>(screenHeight_) - static_cast<int32_t>(sourceRect_.height_);
392 }
393 sourceRect_.posX_ = sourcePosX;
394 sourceRect_.posY_ = sourcePosY;
395 window_->SetFrameRectForPartialZoomIn(sourceRect_);
396 DrawRuoundRectFrameFull();
397 FlushImplicitTransaction();
398 UpdateAnchor();
399 }
400
ShowMagnificationFull()401 void MagnificationWindow::ShowMagnificationFull()
402 {
403 int32_t centerX = static_cast<int32_t>(screenWidth_ / DIVISOR_TWO);
404 int32_t centerY = static_cast<int32_t>(screenHeight_ / DIVISOR_TWO);
405 EnableMagnificationFull(centerX, centerY);
406 }
407
RefreshWindowParamFull(RotationType type)408 void MagnificationWindow::RefreshWindowParamFull(RotationType type)
409 {
410 HILOG_DEBUG();
411 PointerPos center = GetRectCenter(sourceRect_);
412 if (isMagnificationShowFull_) {
413 DisableMagnificationFull(false);
414 center = TransferCenter(type, center);
415 EnableMagnificationFull(center.posX, center.posY);
416 } else {
417 GetWindowParam();
418 }
419 }
420
IsMagnificationShowFull()421 bool MagnificationWindow::IsMagnificationShowFull()
422 {
423 return isMagnificationShowFull_;
424 }
425
426 // window magnification
GetWindowRectFromPointer(int32_t centerX,int32_t centerY)427 Rosen::Rect MagnificationWindow::GetWindowRectFromPointer(int32_t centerX, int32_t centerY)
428 {
429 Rosen::Rect windowRect = {0, 0, windowWidth_, windowHeight_};
430 int32_t x = centerX - static_cast<int32_t>(windowWidth_ / DIVISOR_TWO);
431 int32_t y = centerY - static_cast<int32_t>(windowHeight_ / DIVISOR_TWO);
432
433 x = (x < 0) ? 0 : x;
434 x = (x + static_cast<int32_t>(windowWidth_)) > static_cast<int32_t>(
435 screenWidth_) ? static_cast<int32_t>(screenWidth_ - windowWidth_) : x;
436
437 y = (y < 0) ? 0 : y;
438 y = (y + static_cast<int32_t>(windowHeight_)) > static_cast<int32_t>(
439 screenHeight_) ? static_cast<int32_t>(screenHeight_ - windowHeight_) : y;
440
441 windowRect.posX_ = x;
442 windowRect.posY_ = y;
443 return windowRect;
444 }
445
CalculateAnchorOffset()446 void MagnificationWindow::CalculateAnchorOffset()
447 {
448 int32_t windowCenterX = windowRect_.posX_ + windowRect_.posX_ + static_cast<int32_t>(windowRect_.width_);
449 int32_t sourceCenterX = sourceRect_.posX_ + sourceRect_.posX_ + static_cast<int32_t>(sourceRect_.width_);
450 anchorOffsetX_ = static_cast<int32_t>((windowCenterX - sourceCenterX) * HALF);
451
452 int32_t windowCenterY = windowRect_.posY_ + windowRect_.posY_ + static_cast<int32_t>(windowRect_.height_);
453 int32_t sourceCenterY = sourceRect_.posY_ + sourceRect_.posY_ + static_cast<int32_t>(sourceRect_.height_);
454 anchorOffsetY_ = static_cast<int32_t>((windowCenterY - sourceCenterY) * HALF);
455 }
456
UpdateRelativeRect()457 void MagnificationWindow::UpdateRelativeRect()
458 {
459 int32_t posX = sourceRect_.posX_ - windowRect_.posX_;
460 if (posX < 0) {
461 posX = 0;
462 }
463
464 int32_t deltaX = static_cast<int32_t>(windowRect_.width_) - static_cast<int32_t>(sourceRect_.width_);
465 if (posX > deltaX) {
466 posX = deltaX;
467 }
468 relativeRect_.posX_ = posX;
469
470 int32_t posY = sourceRect_.posY_ - windowRect_.posY_;
471 if (posY < 0) {
472 posY = 0;
473 }
474
475 int32_t deltaY = static_cast<int32_t>(windowRect_.height_) - static_cast<int32_t>(sourceRect_.height_);
476 if (posY > deltaY) {
477 posY = deltaY;
478 }
479 relativeRect_.posY_ = posY;
480 relativeRect_.width_ = sourceRect_.width_;
481 relativeRect_.height_ = sourceRect_.height_;
482 }
483
AdjustMagnificationWindowPosition()484 void MagnificationWindow::AdjustMagnificationWindowPosition()
485 {
486 if (windowRect_.posX_ < 0) {
487 windowRect_.posX_ = 0;
488 }
489
490 if (windowRect_.posY_ < 0) {
491 windowRect_.posY_ = 0;
492 }
493
494 if (windowRect_.posX_ + static_cast<int32_t>(windowRect_.width_) > static_cast<int32_t>(screenWidth_)) {
495 windowRect_.posX_ = static_cast<int32_t>(screenWidth_) - static_cast<int32_t>(windowRect_.width_);
496 }
497
498 if (windowRect_.posY_ + static_cast<int32_t>(windowRect_.height_) > static_cast<int32_t>(screenHeight_)) {
499 windowRect_.posY_ = static_cast<int32_t>(screenHeight_) - static_cast<int32_t>(windowRect_.height_);
500 }
501 }
502
AdjustSourceWindowPosition()503 void MagnificationWindow::AdjustSourceWindowPosition()
504 {
505 if (sourceRect_.posX_ < windowRect_.posX_) {
506 sourceRect_.posX_ = windowRect_.posX_;
507 }
508
509 if (sourceRect_.posY_ < windowRect_.posY_) {
510 sourceRect_.posY_ = windowRect_.posY_;
511 }
512
513 int32_t windowX = windowRect_.posX_ + static_cast<int32_t>(windowRect_.width_);
514 if (sourceRect_.posX_ + static_cast<int32_t>(sourceRect_.width_) > windowX) {
515 sourceRect_.posX_ = windowX - static_cast<int32_t>(sourceRect_.width_);
516 }
517
518 int32_t windowY = windowRect_.posY_ + static_cast<int32_t>(windowRect_.height_);
519 if (sourceRect_.posY_ + static_cast<int32_t>(sourceRect_.height_) > windowY) {
520 sourceRect_.posY_ = windowY - static_cast<int32_t>(sourceRect_.height_);
521 }
522 }
523
IsTapOnHotArea(int32_t posX,int32_t posY)524 bool MagnificationWindow::IsTapOnHotArea(int32_t posX, int32_t posY)
525 {
526 if (!isMagnificationShowPart_) {
527 return false;
528 }
529 Rosen::Rect innerRect = {windowRect_.posX_ + static_cast<int32_t>(hotAreaWidth_),
530 windowRect_.posY_ + static_cast<int32_t>(hotAreaWidth_),
531 windowRect_.width_ - static_cast<uint32_t>(2 * hotAreaWidth_),
532 windowRect_.height_ - static_cast<uint32_t>(2 * hotAreaWidth_)};
533 Rosen::Rect outRect = {windowRect_.posX_ - static_cast<int32_t>(hotAreaWidth_),
534 windowRect_.posY_ - static_cast<int32_t>(hotAreaWidth_),
535 windowRect_.width_ + static_cast<uint32_t>(2 * hotAreaWidth_),
536 windowRect_.height_ + static_cast<uint32_t>(2 * hotAreaWidth_)};
537 return ExtUtils::IsInRect(posX, posY, outRect) && !(ExtUtils::IsInRect(posX, posY, innerRect));
538 }
539
IsTapOnMagnificationWindow(int32_t posX,int32_t posY)540 bool MagnificationWindow::IsTapOnMagnificationWindow(int32_t posX, int32_t posY)
541 {
542 return ExtUtils::IsInRect(posX, posY, windowRect_);
543 }
FixSourceCenter(bool needFix)544 void MagnificationWindow::FixSourceCenter(bool needFix)
545 {
546 HILOG_DEBUG();
547 if (needFix == isFixSourceCenter_) {
548 return;
549 }
550
551 isFixSourceCenter_ = needFix;
552 if (needFix) {
553 isFixSourceCenter_ = needFix;
554 float sourceCenterX = (sourceRect_.posX_ + sourceRect_.posX_ +
555 static_cast<int32_t>(sourceRect_.width_)) / static_cast<float>(DIVISOR_TWO);
556 float sourceCenterY = (sourceRect_.posY_ + sourceRect_.posY_ +
557 static_cast<int32_t>(sourceRect_.height_)) / static_cast<float>(DIVISOR_TWO);
558 fixedSourceCenter_ = {static_cast<int32_t>(sourceCenterX), static_cast<int32_t>(sourceCenterY)};
559 } else {
560 fixedSourceCenter_ = {0, 0};
561 }
562 }
563
DrawRuoundRectFramePart()564 void MagnificationWindow::DrawRuoundRectFramePart()
565 {
566 if (surfaceNode_ == nullptr) {
567 HILOG_ERROR("get surfaceNode_ failed.");
568 return;
569 }
570
571 if (canvasNode_ == nullptr) {
572 HILOG_ERROR("create canvasNode_ fail");
573 return;
574 }
575 surfaceNode_->SetAbilityBGAlpha(BG_ALPHA);
576 surfaceNode_->AddChild(canvasNode_, -1);
577 canvasNode_->SetBounds(0, 0, windowWidth_, windowHeight_);
578 canvasNode_->SetFrame(0, 0, windowWidth_, windowHeight_);
579 canvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
580 canvasNode_->SetRotation(0);
581
582 auto canvas = canvasNode_->BeginRecording(windowWidth_, windowHeight_);
583 if (canvas == nullptr) {
584 HILOG_ERROR("get canvas fail");
585 return;
586 }
587 Rosen::Drawing::Pen pen;
588 pen.SetAntiAlias(true);
589 pen.SetColor(ORANGE_COLOR);
590 pen.SetWidth(PEN_WIDTH);
591 canvas->AttachPen(pen);
592 Rosen::Drawing::Path path;
593 path.AddRoundRect({ROUND_RECT_MARGIN, ROUND_RECT_MARGIN,
594 windowWidth_ - ROUND_RECT_MARGIN, windowHeight_ - ROUND_RECT_MARGIN},
595 CORNER_RADIUS, CORNER_RADIUS, Rosen::Drawing::PathDirection::CW_DIRECTION);
596 canvas->DrawPath(path);
597 canvas->DetachPen();
598
599 Rosen::Drawing::Pen linePen;
600 linePen.SetAntiAlias(true);
601 linePen.SetColor(ORANGE_COLOR);
602 linePen.SetWidth(PEN_WIDTH);
603 canvas->AttachPen(linePen);
604 auto p1 = Rosen::Drawing::Point(BAR_START, windowHeight_ - barMargin_);
605 auto p2 = Rosen::Drawing::Point(BAR_END, windowHeight_ - barMargin_);
606 canvas->DrawLine(p1, p2);
607 canvas->DetachPen();
608
609 Rosen::Drawing::Brush brush;
610 brush.SetAntiAlias(true);
611 brush.SetColor(ORANGE_COLOR);
612 canvas->AttachBrush(brush);
613 canvas->DrawCircle(p1, static_cast<float>(PEN_WIDTH / DIVISOR_TWO));
614 canvas->DrawCircle(p2, static_cast<float>(PEN_WIDTH / DIVISOR_TWO));
615 canvas->DetachBrush();
616 canvasNode_->FinishRecording();
617 }
618
EnableMagnificationPart(int32_t centerX,int32_t centerY)619 void MagnificationWindow::EnableMagnificationPart(int32_t centerX, int32_t centerY)
620 {
621 HILOG_INFO("centerX = %{public}d, centerY = %{public}d.", centerX, centerY);
622 GetWindowParam();
623 if (window_ == nullptr) {
624 HILOG_DEBUG("window is null. need create.");
625 windowRect_ = GetWindowRectFromPointer(centerX, centerY);
626 CreateMagnificationWindow();
627 }
628
629 if (window_ == nullptr) {
630 HILOG_ERROR("create window failed.");
631 return;
632 }
633 sourceRect_ = GetSourceRectFromPointer(centerX, centerY);
634 CalculateAnchorOffset();
635 UpdateRelativeRect();
636 Rosen::WMError ret = window_->SetFrameRectForPartialZoomIn(relativeRect_);
637 if (ret != Rosen::WMError::WM_OK) {
638 HILOG_ERROR("Trigger magnification failed.");
639 ExtUtils::RecordMagnificationUnavailableEvent("Trigger magnification failed.");
640 }
641 DrawRuoundRectFramePart();
642 window_->Show();
643 FlushImplicitTransaction();
644 isMagnificationShowPart_ = true;
645 }
646
DisableMagnificationPart(bool needClear)647 void MagnificationWindow::DisableMagnificationPart(bool needClear)
648 {
649 DisableMagnification(needClear);
650 anchorOffsetX_ = 0;
651 anchorOffsetY_ = 0;
652 isMagnificationShowPart_ = false;
653 }
654
IsMagnificationShowPart()655 bool MagnificationWindow::IsMagnificationShowPart()
656 {
657 return isMagnificationShowPart_;
658 }
659
SetScalePart(float scaleSpan)660 void MagnificationWindow::SetScalePart(float scaleSpan)
661 {
662 HILOG_DEBUG();
663 if (screenWidth_ == 0 || screenHeight_ == 0 || abs(screenSpan_) < EPS) {
664 HILOG_ERROR("screen param invalid.");
665 return;
666 }
667
668 float ratio = scaleSpan / screenSpan_;
669 float tmpScale = scale_ + ratio * scale_;
670 if (tmpScale > MAX_SCALE) {
671 tmpScale = MAX_SCALE;
672 }
673 if (tmpScale < DEFAULT_SCALE) {
674 tmpScale = DEFAULT_SCALE;
675 }
676
677 uint32_t newWidth = static_cast<uint32_t>(windowRect_.width_ / tmpScale);
678 uint32_t newHeight = static_cast<uint32_t>(windowRect_.height_ / tmpScale);
679 int32_t newPosX = fixedSourceCenter_.posX - static_cast<int32_t>(newWidth / DIVISOR_TWO);
680 int32_t newPosY = fixedSourceCenter_.posY - static_cast<int32_t>(newHeight / DIVISOR_TWO);
681
682 Rosen::Rect tmpRect = {newPosX, newPosY, newWidth, newHeight};
683 if (!tmpRect.IsInsideOf(screenRect_)) {
684 HILOG_ERROR("sourceRect out of screenRect.");
685 return;
686 }
687
688 if (window_ == nullptr) {
689 HILOG_ERROR("window_ is nullptr.");
690 return;
691 }
692
693 sourceRect_ = tmpRect;
694 scale_ = tmpScale;
695 UpdateRelativeRect();
696 window_->SetFrameRectForPartialZoomIn(relativeRect_);
697 DrawRuoundRectFramePart();
698 FlushImplicitTransaction();
699 CalculateAnchorOffset();
700 }
701
MoveMagnificationPart(int32_t deltaX,int32_t deltaY)702 void MagnificationWindow::MoveMagnificationPart(int32_t deltaX, int32_t deltaY)
703 {
704 if (window_ == nullptr) {
705 HILOG_ERROR("window is null.");
706 return;
707 }
708
709 int32_t windowPosX = windowRect_.posX_;
710 int32_t sourcePosX = sourceRect_.posX_;
711
712 if (abs(anchorOffsetX_) <= ANCHOR_OFFSET) {
713 windowPosX += deltaX;
714 }
715 sourcePosX += deltaX;
716
717 int32_t windowPosY = windowRect_.posY_;
718 int32_t sourcePosY = sourceRect_.posY_;
719
720 if (abs(anchorOffsetY_) <= ANCHOR_OFFSET) {
721 windowPosY += deltaY;
722 }
723 sourcePosY += deltaY;
724
725 windowRect_.posX_ = windowPosX;
726 windowRect_.posY_ = windowPosY;
727 AdjustMagnificationWindowPosition();
728
729 window_->MoveTo(windowRect_.posX_, windowRect_.posY_);
730
731 sourceRect_.posX_ = sourcePosX;
732 sourceRect_.posY_ = sourcePosY;
733 AdjustSourceWindowPosition();
734 UpdateRelativeRect();
735 window_->SetFrameRectForPartialZoomIn(relativeRect_);
736 DrawRuoundRectFramePart();
737 FlushImplicitTransaction();
738 CalculateAnchorOffset();
739 }
740
ShowMagnificationPart()741 void MagnificationWindow::ShowMagnificationPart()
742 {
743 int32_t centerX = static_cast<int32_t>(screenWidth_ / DIVISOR_TWO);
744 int32_t centerY = static_cast<int32_t>(screenHeight_ / DIVISOR_TWO);
745 EnableMagnificationPart(centerX, centerY);
746 }
747
FollowFocuseElementPart(int32_t centerX,int32_t centerY)748 void MagnificationWindow::FollowFocuseElementPart(int32_t centerX, int32_t centerY)
749 {
750 HILOG_DEBUG();
751 if (window_ == nullptr) {
752 HILOG_ERROR("window_ is nullptr.");
753 return;
754 }
755 windowRect_ = GetWindowRectFromPointer(centerX, centerY);
756 sourceRect_ = GetSourceRectFromPointer(centerX, centerY);
757 window_->MoveTo(windowRect_.posX_, windowRect_.posY_);
758 UpdateRelativeRect();
759 window_->SetFrameRectForPartialZoomIn(relativeRect_);
760 DrawRuoundRectFramePart();
761 FlushImplicitTransaction();
762 CalculateAnchorOffset();
763 }
764
RefreshWindowParamPart(RotationType type)765 void MagnificationWindow::RefreshWindowParamPart(RotationType type)
766 {
767 HILOG_DEBUG();
768 if (isMagnificationShowPart_) {
769 PointerPos center = GetRectCenter(windowRect_);
770 HILOG_INFO("need refresh window param.");
771 DisableMagnificationPart();
772 center = TransferCenter(type, center);
773 EnableMagnificationPart(center.posX, center.posY);
774 } else {
775 GetWindowParam();
776 }
777 }
778
TransferCenter(RotationType type,PointerPos center)779 PointerPos MagnificationWindow::TransferCenter(RotationType type, PointerPos center)
780 {
781 if (type == RotationType::NO_CHANGE || type == RotationType::UNKNOWN) {
782 return center;
783 }
784 GetWindowParam();
785 if (type == RotationType::LEFT_ROTATE) {
786 return {center.posY, static_cast<int32_t>(screenHeight_) - center.posX};
787 }
788 if (type == RotationType::RIGHT_ROTATE) {
789 return {screenWidth_ - center.posY, center.posX};
790 }
791 if (type == RotationType::FLIP_VERTICAL) {
792 return {screenWidth_ - center.posX, screenHeight_ - center.posY};
793 }
794 return center;
795 }
796
EnableMagnification(uint32_t magnificationType,int32_t posX,int32_t posY)797 extern "C" API_EXPORT void EnableMagnification(uint32_t magnificationType, int32_t posX, int32_t posY)
798 {
799 if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
800 instance.EnableMagnificationFull(posX, posY);
801 return;
802 }
803 if (magnificationType == WINDOW_MAGNIFICATION) {
804 instance.EnableMagnificationPart(posX, posY);
805 return;
806 }
807 HILOG_DEBUG("invalid type = %{public}d", magnificationType);
808 }
809
DisableMagnification(uint32_t magnificationType,bool needClear)810 extern "C" API_EXPORT void DisableMagnification(uint32_t magnificationType, bool needClear)
811 {
812 if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
813 instance.DisableMagnificationFull(needClear);
814 return;
815 }
816 if (magnificationType == WINDOW_MAGNIFICATION) {
817 instance.DisableMagnificationPart(needClear);
818 return;
819 }
820 HILOG_DEBUG("invalid type = %{public}d", magnificationType);
821 }
822
SetScale(uint32_t magnificationType,float scaleSpan)823 extern "C" API_EXPORT void SetScale(uint32_t magnificationType, float scaleSpan)
824 {
825 if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
826 instance.SetScaleFull(scaleSpan);
827 return;
828 }
829 if (magnificationType == WINDOW_MAGNIFICATION) {
830 instance.SetScalePart(scaleSpan);
831 return;
832 }
833 HILOG_DEBUG("invalid type = %{public}d", magnificationType);
834 }
835
MoveMagnification(uint32_t magnificationType,int32_t deltaX,int32_t deltaY)836 extern "C" API_EXPORT void MoveMagnification(uint32_t magnificationType, int32_t deltaX, int32_t deltaY)
837 {
838 if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
839 instance.MoveMagnificationFull(deltaX, deltaY);
840 return;
841 }
842 if (magnificationType == WINDOW_MAGNIFICATION) {
843 instance.MoveMagnificationPart(deltaX, deltaY);
844 return;
845 }
846 HILOG_DEBUG("invalid type = %{public}d", magnificationType);
847 }
848
ConvertGesture(uint32_t type,PointerPos coordinates)849 extern "C" API_EXPORT PointerPos ConvertGesture(uint32_t type, PointerPos coordinates)
850 {
851 return instance.ConvertGesture(type, coordinates);
852 }
853
ConvertCoordinates(int32_t posX,int32_t posY)854 extern "C" API_EXPORT PointerPos ConvertCoordinates(int32_t posX, int32_t posY)
855 {
856 return instance.ConvertCoordinates(posX, posY);
857 }
858
CheckTapOnHotArea(int32_t posX,int32_t posY)859 extern "C" API_EXPORT uint32_t CheckTapOnHotArea(int32_t posX, int32_t posY)
860 {
861 return instance.CheckTapOnHotArea(posX, posY);
862 }
863
GetScale()864 extern "C" API_EXPORT float GetScale()
865 {
866 return instance.GetScale();
867 }
868
IsMagnificationWindowShow(uint32_t magnificationType)869 extern "C" API_EXPORT bool IsMagnificationWindowShow(uint32_t magnificationType)
870 {
871 if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
872 return instance.IsMagnificationShowFull();
873 }
874 if (magnificationType == WINDOW_MAGNIFICATION) {
875 return instance.IsMagnificationShowPart();
876 }
877 HILOG_DEBUG("invalid type = %{public}d", magnificationType);
878 return false;
879 }
880
FollowFocuseElement(uint32_t magnificationType,int32_t centerX,int32_t centerY)881 extern "C" API_EXPORT void FollowFocuseElement(uint32_t magnificationType, int32_t centerX, int32_t centerY)
882 {
883 if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
884 instance.FollowFocuseElementFull(centerX, centerY);
885 return;
886 }
887 if (magnificationType == WINDOW_MAGNIFICATION) {
888 instance.FollowFocuseElementPart(centerX, centerY);
889 return;
890 }
891 HILOG_DEBUG("invalid type = %{public}d", magnificationType);
892 }
893
GetSourceCenter()894 extern "C" API_EXPORT PointerPos GetSourceCenter()
895 {
896 return instance.GetSourceCenter();
897 }
898
ShowMagnification(uint32_t magnificationType)899 extern "C" API_EXPORT void ShowMagnification(uint32_t magnificationType)
900 {
901 if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
902 instance.ShowMagnificationFull();
903 return;
904 }
905 if (magnificationType == WINDOW_MAGNIFICATION) {
906 instance.ShowMagnificationPart();
907 return;
908 }
909 HILOG_DEBUG("invalid type = %{public}d", magnificationType);
910 }
911
RefreshWindowParam(uint32_t magnificationType,RotationType type)912 extern "C" API_EXPORT void RefreshWindowParam(uint32_t magnificationType, RotationType type)
913 {
914 if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
915 instance.RefreshWindowParamFull(type);
916 return;
917 }
918 if (magnificationType == WINDOW_MAGNIFICATION) {
919 instance.RefreshWindowParamPart(type);
920 return;
921 }
922 HILOG_DEBUG("invalid type = %{public}d", magnificationType);
923 }
924
IsTapOnHotArea(int32_t posX,int32_t posY)925 extern "C" API_EXPORT bool IsTapOnHotArea(int32_t posX, int32_t posY)
926 {
927 return instance.IsTapOnHotArea(posX, posY);
928 }
929
IsTapOnMagnificationWindow(int32_t posX,int32_t posY)930 extern "C" API_EXPORT bool IsTapOnMagnificationWindow(int32_t posX, int32_t posY)
931 {
932 return instance.IsTapOnMagnificationWindow(posX, posY);
933 }
934
FixSourceCenter(bool needFix)935 extern "C" API_EXPORT void FixSourceCenter(bool needFix)
936 {
937 instance.FixSourceCenter(needFix);
938 }
939
InitMagnificationParam(float scale)940 extern "C" API_EXPORT void InitMagnificationParam(float scale)
941 {
942 instance.InitMagnificationParam(scale);
943 }
944 }
945 }
946 // LCOV_EXCL_STOP