1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "accessibility_zoom_gesture.h"
17 #include "accessible_ability_manager_service.h"
18 #include "hilog_wrapper.h"
19 #include "window_accessibility_controller.h"
20
21 namespace OHOS {
22 namespace Accessibility {
23 namespace {
24 constexpr size_t POINTER_COUNT_1 = 1;
25 constexpr float TAP_MIN_DISTANCE = 8.0f;
26 constexpr int32_t MULTI_TAP_TIMER = 300; // ms
27 constexpr int32_t LONG_PRESS_TIMER = 500; // ms
28 constexpr int64_t US_TO_MS = 1000;
29 constexpr float MIN_SCALE_SPAN = 26.0f;
30 constexpr float DOUBLE_TAP_SLOP = 100.0f;
31 constexpr float HALF = 0.5f;
32 constexpr uint32_t TRIPLE_TAP_COUNT = 3;
33 constexpr float DEFAULT_SCALE = 2.0f;
34 } // namespace
35
AccessibilityZoomGesture()36 AccessibilityZoomGesture::AccessibilityZoomGesture()
37 {
38 HILOG_DEBUG();
39
40 zoomGestureEventHandler_ = std::make_shared<ZoomGestureEventHandler>(
41 Singleton<AccessibleAbilityManagerService>::GetInstance().GetMainRunner(), *this);
42
43 tapDistance_ = TAP_MIN_DISTANCE;
44
45 AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
46 auto display = displayMgr.GetDefaultDisplay();
47 if (!display) {
48 HILOG_ERROR("get display is nullptr");
49 return;
50 }
51
52 float densityPixels = display->GetVirtualPixelRatio();
53 multiTapDistance_ = densityPixels * DOUBLE_TAP_SLOP + 0.5f;
54 }
55
OnPointerEvent(MMI::PointerEvent & event)56 bool AccessibilityZoomGesture::OnPointerEvent(MMI::PointerEvent &event)
57 {
58 HILOG_DEBUG("state_ is %{public}d.", state_);
59
60 int32_t sourceType = event.GetSourceType();
61 if (sourceType != MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN) {
62 EventTransmission::OnPointerEvent(event);
63 return false;
64 }
65
66 switch (state_) {
67 case READY_STATE:
68 CacheEvents(event);
69 RecognizeInReadyState(event);
70 break;
71 case ZOOMIN_STATE:
72 CacheEvents(event);
73 RecognizeInZoomState(event);
74 break;
75 case SLIDING_STATE:
76 RecognizeInSlidingState(event);
77 break;
78 default:
79 break;
80 }
81 return true;
82 }
83
TransferState(ACCESSIBILITY_ZOOM_STATE state)84 void AccessibilityZoomGesture::TransferState(ACCESSIBILITY_ZOOM_STATE state)
85 {
86 HILOG_DEBUG("state:%{public}d.", state);
87
88 state_ = state;
89 }
90
CacheEvents(MMI::PointerEvent & event)91 void AccessibilityZoomGesture::CacheEvents(MMI::PointerEvent &event)
92 {
93 HILOG_DEBUG();
94
95 int32_t action = event.GetPointerAction();
96 size_t pointerCount = event.GetPointerIds().size();
97 std::shared_ptr<MMI::PointerEvent> pointerEvent = std::make_shared<MMI::PointerEvent>(event);
98
99 switch (action) {
100 case MMI::PointerEvent::POINTER_ACTION_DOWN:
101 if (pointerCount == POINTER_COUNT_1) {
102 HILOG_DEBUG("Cache pointer down");
103 preLastDownEvent_ = lastDownEvent_;
104 lastDownEvent_ = pointerEvent;
105 }
106 break;
107 case MMI::PointerEvent::POINTER_ACTION_UP:
108 if (pointerCount == POINTER_COUNT_1) {
109 HILOG_DEBUG("Cache pointer up");
110 preLastUpEvent_ = lastUpEvent_;
111 lastUpEvent_ = pointerEvent;
112 }
113 break;
114 default:
115 HILOG_DEBUG("Action is %{public}d", action);
116 break;
117 }
118 cacheEvents_.emplace_back(pointerEvent);
119 }
120
SendCacheEventsToNext()121 void AccessibilityZoomGesture::SendCacheEventsToNext()
122 {
123 HILOG_DEBUG();
124
125 bool isStartNewAction = false;
126 int32_t action = MMI::PointerEvent::POINTER_ACTION_UNKNOWN;
127 std::vector<std::shared_ptr<MMI::PointerEvent>> cacheEventsTmp;
128 std::copy(cacheEvents_.begin(), cacheEvents_.end(), std::back_inserter(cacheEventsTmp));
129
130 ClearCacheEventsAndMsg();
131
132 size_t cacheEventsNum = 0;
133 size_t cacheEventsTotalNum = cacheEventsTmp.size();
134 for (auto &pointerEvent : cacheEventsTmp) {
135 cacheEventsNum++;
136 action = pointerEvent->GetPointerAction();
137 if ((cacheEventsNum > 1) &&
138 (cacheEventsNum == cacheEventsTotalNum) &&
139 (action == MMI::PointerEvent::POINTER_ACTION_DOWN)) {
140 HILOG_DEBUG("The down event needs to be parsed again");
141 isStartNewAction = true;
142 }
143 if (isStartNewAction) {
144 OnPointerEvent(*pointerEvent);
145 } else {
146 EventTransmission::OnPointerEvent(*pointerEvent);
147 }
148 }
149 }
150
ClearCacheEventsAndMsg()151 void AccessibilityZoomGesture::ClearCacheEventsAndMsg()
152 {
153 HILOG_DEBUG();
154
155 cacheEvents_.clear();
156 preLastDownEvent_ = nullptr;
157 lastDownEvent_ = nullptr;
158 preLastUpEvent_ = nullptr;
159 lastUpEvent_ = nullptr;
160 zoomGestureEventHandler_->RemoveEvent(MULTI_TAP_MSG);
161 }
162
RecognizeInReadyState(MMI::PointerEvent & event)163 void AccessibilityZoomGesture::RecognizeInReadyState(MMI::PointerEvent &event)
164 {
165 HILOG_DEBUG();
166
167 int32_t action = event.GetPointerAction();
168 size_t pointerCount = event.GetPointerIds().size();
169 bool isTripleTaps = false;
170
171 HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
172 switch (action) {
173 case MMI::PointerEvent::POINTER_ACTION_DOWN:
174 zoomGestureEventHandler_->RemoveEvent(MULTI_TAP_MSG);
175 if ((pointerCount == POINTER_COUNT_1) && IsDownValid()) {
176 zoomGestureEventHandler_->SendEvent(MULTI_TAP_MSG, 0, MULTI_TAP_TIMER);
177 } else {
178 SendCacheEventsToNext();
179 }
180 break;
181 case MMI::PointerEvent::POINTER_ACTION_UP:
182 if ((pointerCount == POINTER_COUNT_1) && IsUpValid()) {
183 isTripleTaps = IsTripleTaps();
184 } else {
185 SendCacheEventsToNext();
186 }
187 break;
188 case MMI::PointerEvent::POINTER_ACTION_CANCEL:
189 SendCacheEventsToNext();
190 break;
191 default:
192 break;
193 }
194
195 if (isTripleTaps) {
196 OnTripleTaps(event);
197 }
198 }
199
RecognizeInZoomState(MMI::PointerEvent & event)200 void AccessibilityZoomGesture::RecognizeInZoomState(MMI::PointerEvent &event)
201 {
202 HILOG_DEBUG();
203
204 int32_t action = event.GetPointerAction();
205 size_t pointerCount = event.GetPointerIds().size();
206 bool isTripleTaps = false;
207
208 HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
209 switch (action) {
210 case MMI::PointerEvent::POINTER_ACTION_DOWN:
211 zoomGestureEventHandler_->RemoveEvent(MULTI_TAP_MSG);
212 if (pointerCount == POINTER_COUNT_1) {
213 if (IsDownValid()) {
214 zoomGestureEventHandler_->SendEvent(MULTI_TAP_MSG, 0, MULTI_TAP_TIMER);
215 } else {
216 SendCacheEventsToNext();
217 }
218 } else if (pointerCount > POINTER_COUNT_1) {
219 TransferState(SLIDING_STATE);
220 ClearCacheEventsAndMsg();
221 ZOOM_FOCUS_COORDINATE focusXY = {0.0f, 0.0f};
222 CalcFocusCoordinate(event, focusXY);
223 // Used for scroll algorithm.
224 lastScrollFocusX_ = focusXY.centerX;
225 lastScrollFocusY_ = focusXY.centerY;
226
227 // Used for scale algorithm.
228 float span = CalcScaleSpan(event, focusXY);
229 if (span >= MIN_SCALE_SPAN) {
230 startScaling_ = true;
231 preSpan_ = lastSpan_ = span;
232 }
233 }
234 break;
235 case MMI::PointerEvent::POINTER_ACTION_UP:
236 if ((pointerCount == POINTER_COUNT_1) && IsUpValid()) {
237 isTripleTaps = IsTripleTaps();
238 } else {
239 SendCacheEventsToNext();
240 }
241 break;
242 case MMI::PointerEvent::POINTER_ACTION_CANCEL:
243 SendCacheEventsToNext();
244 break;
245 default:
246 break;
247 }
248
249 if (isTripleTaps) {
250 OnTripleTaps(event);
251 }
252 }
253
RecognizeInSlidingState(MMI::PointerEvent & event)254 void AccessibilityZoomGesture::RecognizeInSlidingState(MMI::PointerEvent &event)
255 {
256 HILOG_DEBUG();
257
258 int32_t action = event.GetPointerAction();
259 size_t pointerCount = event.GetPointerIds().size();
260
261 // Recognize scroll and zoom gestures.
262 RecognizeScroll(event);
263 RecognizeScale(event);
264
265 HILOG_DEBUG("action:%{public}d, pointerCount:%{public}zu", action, pointerCount);
266 switch (action) {
267 case MMI::PointerEvent::POINTER_ACTION_UP:
268 if (pointerCount == POINTER_COUNT_1) {
269 TransferState(ZOOMIN_STATE);
270 }
271 break;
272 case MMI::PointerEvent::POINTER_ACTION_CANCEL:
273 TransferState(ZOOMIN_STATE);
274 break;
275 default:
276 break;
277 }
278 }
279
RecognizeScroll(MMI::PointerEvent & event)280 void AccessibilityZoomGesture::RecognizeScroll(MMI::PointerEvent &event)
281 {
282 HILOG_DEBUG();
283
284 int32_t action = event.GetPointerAction();
285 ZOOM_FOCUS_COORDINATE coordinate = {0.0f, 0.0f};
286 CalcFocusCoordinate(event, coordinate);
287
288 switch (action) {
289 case MMI::PointerEvent::POINTER_ACTION_DOWN:
290 case MMI::PointerEvent::POINTER_ACTION_UP:
291 lastScrollFocusX_ = coordinate.centerX;
292 lastScrollFocusY_ = coordinate.centerY;
293 break;
294 case MMI::PointerEvent::POINTER_ACTION_MOVE: {
295 float offsetX = coordinate.centerX - lastScrollFocusX_;
296 float offsetY = coordinate.centerY - lastScrollFocusY_;
297 if ((abs(offsetX) > 1) || (abs(offsetY) > 1)) {
298 lastScrollFocusX_ = coordinate.centerX;
299 lastScrollFocusY_ = coordinate.centerY;
300 OnScroll(offsetX, offsetY);
301 }
302 break;
303 }
304 default:
305 break;
306 }
307 }
308
RecognizeScale(MMI::PointerEvent & event)309 void AccessibilityZoomGesture::RecognizeScale(MMI::PointerEvent &event)
310 {
311 HILOG_DEBUG();
312
313 int32_t action = event.GetPointerAction();
314 size_t pointerCount = event.GetPointerIds().size();
315 if (((action == MMI::PointerEvent::POINTER_ACTION_UP) && (pointerCount == POINTER_COUNT_1)) ||
316 (action == MMI::PointerEvent::POINTER_ACTION_CANCEL)) {
317 HILOG_DEBUG("Scaling is end");
318 startScaling_ = false;
319 preSpan_ = lastSpan_ = 0;
320 return;
321 }
322
323 ZOOM_FOCUS_COORDINATE focusXY = {0.0f, 0.0f};
324 CalcFocusCoordinate(event, focusXY);
325 float span = CalcScaleSpan(event, focusXY);
326 if (!startScaling_) {
327 // When the span is greater than or equal to MIN_SCALE_SPAN, start scaling.
328 if (span >= MIN_SCALE_SPAN) {
329 startScaling_ = true;
330 preSpan_ = lastSpan_ = span;
331 }
332 } else {
333 // When the span is smaller than the MIN_SCALE_SPAN,
334 // the scale recognition will be restarted.
335 if (span < MIN_SCALE_SPAN) {
336 startScaling_ = false;
337 preSpan_ = lastSpan_ = span;
338 }
339 if ((action == MMI::PointerEvent::POINTER_ACTION_UP) ||
340 (action == MMI::PointerEvent::POINTER_ACTION_DOWN)) {
341 preSpan_ = lastSpan_ = span;
342 }
343 }
344
345 if (!startScaling_) {
346 HILOG_DEBUG("Current is not scaling");
347 return;
348 }
349
350 if (action != MMI::PointerEvent::POINTER_ACTION_MOVE) {
351 HILOG_DEBUG("Action(%{public}d) is not move", action);
352 return;
353 }
354
355 lastSpan_ = span;
356 float ratio = lastSpan_ / preSpan_;
357 if (ratio != 1) {
358 OnScale(ratio, focusXY.centerX, focusXY.centerY);
359 preSpan_ = lastSpan_;
360 }
361 }
362
CalcFocusCoordinate(MMI::PointerEvent & event,ZOOM_FOCUS_COORDINATE & coordinate)363 void AccessibilityZoomGesture::CalcFocusCoordinate(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE &coordinate)
364 {
365 HILOG_DEBUG();
366
367 float sumX = 0.0f;
368 float sumY = 0.0f;
369 int32_t upPointerId = -1;
370 int32_t action = event.GetPointerAction();
371 std::vector<int32_t> pointerIdList = event.GetPointerIds();
372 size_t count = pointerIdList.size();
373 if (!count) {
374 HILOG_DEBUG("The size of PointerIds is 0");
375 return;
376 }
377
378 if (action == MMI::PointerEvent::POINTER_ACTION_UP) {
379 upPointerId = event.GetPointerId();
380 HILOG_DEBUG("The pointer id of up is %{public}d", upPointerId);
381 count--;
382 }
383
384 if (!count) {
385 HILOG_DEBUG("The size of PointerIds(down) is invalid");
386 return;
387 }
388
389 for (int32_t pointerId : pointerIdList) {
390 if (pointerId == upPointerId) {
391 continue;
392 }
393 MMI::PointerEvent::PointerItem item;
394 event.GetPointerItem(pointerId, item);
395 sumX += static_cast<float>(item.GetDisplayX());
396 sumY += static_cast<float>(item.GetDisplayY());
397 }
398
399 coordinate.centerX = sumX / count;
400 coordinate.centerY = sumY / count;
401 HILOG_DEBUG("centerX:%{public}f, centerY:%{public}f", coordinate.centerX, coordinate.centerY);
402 }
403
CalcScaleSpan(MMI::PointerEvent & event,ZOOM_FOCUS_COORDINATE coordinate)404 float AccessibilityZoomGesture::CalcScaleSpan(MMI::PointerEvent &event, ZOOM_FOCUS_COORDINATE coordinate)
405 {
406 HILOG_DEBUG();
407
408 float span = 0.0f;
409 float sumSpanX = 0.0f;
410 float sumSpanY = 0.0f;
411 int32_t upPointerId = -1;
412 int32_t action = event.GetPointerAction();
413 std::vector<int32_t> pointerIdList = event.GetPointerIds();
414 size_t count = pointerIdList.size();
415 if (!count) {
416 HILOG_DEBUG("The size of PointerIds is 0");
417 return span;
418 }
419
420 if (action == MMI::PointerEvent::POINTER_ACTION_UP) {
421 upPointerId = event.GetPointerId();
422 HILOG_DEBUG("The pointer id of up is %{public}d", upPointerId);
423 count--;
424 }
425
426 if (!count) {
427 HILOG_DEBUG("The size of PointerIds(down) is invalid");
428 return span;
429 }
430
431 for (int32_t pointerId : pointerIdList) {
432 if (pointerId == upPointerId) {
433 continue;
434 }
435 MMI::PointerEvent::PointerItem item;
436 event.GetPointerItem(pointerId, item);
437 sumSpanX += static_cast<float>(abs(item.GetDisplayX() - coordinate.centerX));
438 sumSpanY += static_cast<float>(abs(item.GetDisplayY() - coordinate.centerY));
439 }
440
441 float spanX = sumSpanX / count;
442 float spanY = sumSpanY / count;
443 span = hypot(spanX, spanY) / HALF;
444 HILOG_DEBUG("The span is %{public}f", span);
445 return span;
446 }
447
IsDownValid()448 bool AccessibilityZoomGesture::IsDownValid()
449 {
450 HILOG_DEBUG();
451
452 if (!preLastDownEvent_) {
453 HILOG_DEBUG("This is the first down event");
454 return true;
455 }
456
457 if (CalcSeparationDistance(preLastDownEvent_, lastDownEvent_) >= multiTapDistance_) {
458 HILOG_DEBUG("The down event is vailid");
459 return false;
460 }
461 return true;
462 }
463
IsUpValid()464 bool AccessibilityZoomGesture::IsUpValid()
465 {
466 HILOG_DEBUG();
467
468 if (!lastDownEvent_) {
469 HILOG_DEBUG("The up event is invailid");
470 return false;
471 }
472
473 if (CalcIntervalTime(lastDownEvent_, lastUpEvent_) >= LONG_PRESS_TIMER) {
474 HILOG_DEBUG("The time has exceeded the long press time");
475 return false;
476 }
477
478 if (CalcSeparationDistance(lastDownEvent_, lastUpEvent_) >= tapDistance_) {
479 HILOG_DEBUG("The distance has exceeded the threshold");
480 return false;
481 }
482 return true;
483 }
484
IsTripleTaps()485 bool AccessibilityZoomGesture::IsTripleTaps()
486 {
487 HILOG_DEBUG();
488
489 uint32_t upEventCount = 0;
490 int32_t action = MMI::PointerEvent::POINTER_ACTION_UNKNOWN;
491 for (auto &pointerEvent : cacheEvents_) {
492 action = pointerEvent->GetPointerAction();
493 if (action == MMI::PointerEvent::POINTER_ACTION_UP) {
494 upEventCount++;
495 }
496 }
497
498 if (upEventCount >= TRIPLE_TAP_COUNT) {
499 HILOG_DEBUG("Triple tap detected");
500 return true;
501 }
502
503 return false;
504 }
505
CalcIntervalTime(std::shared_ptr<MMI::PointerEvent> firstEvent,std::shared_ptr<MMI::PointerEvent> secondEvent)506 int64_t AccessibilityZoomGesture::CalcIntervalTime(std::shared_ptr<MMI::PointerEvent> firstEvent,
507 std::shared_ptr<MMI::PointerEvent> secondEvent)
508 {
509 HILOG_DEBUG();
510
511 if (!firstEvent || !secondEvent) {
512 HILOG_DEBUG("The event is null");
513 return 0;
514 }
515
516 int64_t firstTime = firstEvent->GetActionTime();
517 int64_t secondTime = secondEvent->GetActionTime();
518 int64_t intervalTime = (secondTime - firstTime) / US_TO_MS;
519
520 return intervalTime;
521 }
522
CalcSeparationDistance(std::shared_ptr<MMI::PointerEvent> firstEvent,std::shared_ptr<MMI::PointerEvent> secondEvent)523 float AccessibilityZoomGesture::CalcSeparationDistance(std::shared_ptr<MMI::PointerEvent> firstEvent,
524 std::shared_ptr<MMI::PointerEvent> secondEvent)
525 {
526 HILOG_DEBUG();
527
528 if (!firstEvent || !secondEvent) {
529 HILOG_DEBUG("The event is null");
530 return 0;
531 }
532
533 MMI::PointerEvent::PointerItem firstItem;
534 MMI::PointerEvent::PointerItem secondItem;
535 firstEvent->GetPointerItem(firstEvent->GetPointerId(), firstItem);
536 secondEvent->GetPointerItem(secondEvent->GetPointerId(), secondItem);
537 int32_t durationX = secondItem.GetDisplayX() - firstItem.GetDisplayX();
538 int32_t durationY = secondItem.GetDisplayY() - firstItem.GetDisplayY();
539 float distance = static_cast<float>(hypot(durationX, durationY));
540
541 return distance;
542 }
543
OnTripleTaps(MMI::PointerEvent & event)544 void AccessibilityZoomGesture::OnTripleTaps(MMI::PointerEvent &event)
545 {
546 HILOG_DEBUG("state_ is %{public}d.", state_);
547
548 switch (state_) {
549 case READY_STATE: {
550 TransferState(ZOOMIN_STATE);
551 int32_t pointerId = event.GetPointerId();
552 MMI::PointerEvent::PointerItem item;
553 event.GetPointerItem(pointerId, item);
554 int32_t anchorX = item.GetDisplayX();
555 int32_t anchorY = item.GetDisplayY();
556 OnZoom(anchorX, anchorY);
557 break;
558 }
559 case ZOOMIN_STATE:
560 TransferState(READY_STATE);
561 OffZoom();
562 break;
563 default:
564 break;
565 }
566
567 ClearCacheEventsAndMsg();
568 }
569
ZoomGestureEventHandler(const std::shared_ptr<AppExecFwk::EventRunner> & runner,AccessibilityZoomGesture & zoomGesture)570 AccessibilityZoomGesture::ZoomGestureEventHandler::ZoomGestureEventHandler(
571 const std::shared_ptr<AppExecFwk::EventRunner> &runner,
572 AccessibilityZoomGesture &zoomGesture): AppExecFwk::EventHandler(runner), zoomGesture_(zoomGesture)
573 {
574 HILOG_DEBUG();
575 }
576
ProcessEvent(const AppExecFwk::InnerEvent::Pointer & event)577 void AccessibilityZoomGesture::ZoomGestureEventHandler::ProcessEvent(const AppExecFwk::InnerEvent::Pointer &event)
578 {
579 HILOG_DEBUG();
580
581 uint32_t eventId = event->GetInnerEventId();
582
583 switch (eventId) {
584 case MULTI_TAP_MSG:
585 zoomGesture_.SendCacheEventsToNext();
586 break;
587 default:
588 break;
589 }
590 }
591
OnZoom(int32_t anchorX,int32_t anchorY)592 void AccessibilityZoomGesture::OnZoom(int32_t anchorX, int32_t anchorY)
593 {
594 HILOG_DEBUG("anchorX:%{public}d, anchorY:%{public}d.", anchorX, anchorY);
595
596 OHOS::Rosen::WindowAccessibilityController::GetInstance().SetAnchorAndScale(anchorX, anchorY, DEFAULT_SCALE);
597 }
598
OffZoom()599 void AccessibilityZoomGesture::OffZoom()
600 {
601 HILOG_DEBUG();
602
603 OHOS::Rosen::WindowAccessibilityController::GetInstance().OffWindowZoom();
604 }
605
OnScroll(float offsetX,float offsetY)606 void AccessibilityZoomGesture::OnScroll(float offsetX, float offsetY)
607 {
608 HILOG_DEBUG("offsetX:%{public}f, offsetY:%{public}f.", offsetX, offsetY);
609
610 OHOS::Rosen::WindowAccessibilityController::GetInstance().SetAnchorOffset(
611 static_cast<int32_t>(offsetX), static_cast<int32_t>(offsetY));
612 }
613
OnScale(float scaleRatio,float focusX,float focusY)614 void AccessibilityZoomGesture::OnScale(float scaleRatio, float focusX, float focusY)
615 {
616 HILOG_DEBUG("scaleRatio:%{public}f, focusX:%{public}f, focusY:%{public}f.", scaleRatio, focusX, focusY);
617
618 OHOS::Rosen::WindowAccessibilityController::GetInstance().SetAnchorAndScale(
619 static_cast<int32_t>(focusX), static_cast<int32_t>(focusY), scaleRatio);
620 }
621 } // namespace Accessibility
622 } // namespace OHOS
623