• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "touch_drawing_manager.h"
17 
18 #include "bytrace_adapter.h"
19 #include "parameters.h"
20 #include "setting_datashare.h"
21 
22 #include "i_multimodal_input_connect.h"
23 #include "input_windows_manager.h"
24 #include "table_dump.h"
25 
26 #undef MMI_LOG_DOMAIN
27 #define MMI_LOG_DOMAIN MMI_LOG_CURSOR
28 #undef MMI_LOG_TAG
29 #define MMI_LOG_TAG "TouchDrawingManager"
30 
31 namespace OHOS {
32 namespace MMI {
33 namespace {
34 const static Rosen::Drawing::Color LABELS_DEFAULT_COLOR = Rosen::Drawing::Color::ColorQuadSetARGB(192, 255, 255, 255);
35 const static Rosen::Drawing::Color LABELS_RED_COLOR = Rosen::Drawing::Color::ColorQuadSetARGB(192, 255, 0, 0);
36 const static Rosen::Drawing::Color TRACKER_COLOR = Rosen::Drawing::Color::ColorQuadSetARGB(255, 0, 96, 255);
37 const static Rosen::Drawing::Color POINTER_RED_COLOR = Rosen::Drawing::Color::ColorQuadSetARGB(255, 255, 0, 0);
38 const static Rosen::Drawing::Color CROSS_HAIR_COLOR = Rosen::Drawing::Color::ColorQuadSetARGB(255, 0, 0, 192);
39 constexpr int32_t DENSITY_BASELINE { 160 };
40 constexpr int32_t INDEPENDENT_INNER_PIXELS { 20 };
41 constexpr int32_t INDEPENDENT_OUTER_PIXELS { 21 };
42 constexpr int32_t INDEPENDENT_WIDTH_PIXELS { 2 };
43 constexpr int32_t MULTIPLE_FACTOR { 10 };
44 constexpr int32_t CALCULATE_MIDDLE { 2 };
45 constexpr int32_t DEFAULT_VALUE { -1 };
46 constexpr int32_t RECT_COUNT { 6 };
47 constexpr int32_t PHONE_RECT_TOP { 118 };
48 constexpr int32_t PAD_RECT_TOP { 0 };
49 constexpr int32_t RECT_HEIGHT { 40 };
50 constexpr int32_t TEXT_TOP { 30 };
51 constexpr int32_t PEN_WIDTH { 1 };
52 constexpr int32_t TOUCH_SLOP { 30 };
53 constexpr int32_t RECT_SPACEING { 1 };
54 constexpr int32_t THREE_PRECISION { 3 };
55 constexpr int32_t TWO_PRECISION { 2 };
56 constexpr int32_t ONE_PRECISION { 1 };
57 constexpr int32_t ROTATION_ANGLE_0 { 0 };
58 constexpr int32_t ROTATION_ANGLE_90 { 90 };
59 constexpr int32_t ROTATION_ANGLE_180 { 180 };
60 constexpr int32_t ROTATION_ANGLE_270 { 270 };
61 constexpr uint64_t FOLD_SCREEN_MAIN_ID { 5 };
62 constexpr uint64_t FOLD_SCREEN_FULL_ID { 0 };
63 constexpr float TEXT_SIZE { 28.0f };
64 constexpr float TEXT_SCALE { 1.0f };
65 constexpr float TEXT_SKEW { 0.0f };
66 constexpr float INNER_CIRCLE_TRANSPARENCY { 0.6f };
67 constexpr float OUT_CIRCLE_TRANSPARENCY { 0.1f };
68 const std::string showCursorSwitchName { "settings.input.show_touch_hint" };
69 const std::string pointerPositionSwitchName { "settings.developer.show_touch_track" };
70 const std::string PRODUCT_TYPE = system::GetParameter("const.product.devicetype", "unknown");
71 const int32_t ROTATE_POLICY = system::GetIntParameter("const.window.device.rotate_policy", 0);
72 const std::string FOLDABLE_DEVICE_POLICY = system::GetParameter("const.window.foldabledevice.rotate_policy", "");
73 constexpr int32_t WINDOW_ROTATE { 0 };
74 constexpr char ROTATE_WINDOW_ROTATE { '0' };
75 constexpr int32_t FOLDABLE_DEVICE { 2 };
76 constexpr int32_t ANGLE_90 { 90 };
77 constexpr int32_t ANGLE_360 { 360 };
78 const char* PRODUCT_PHONE { "phone" };
79 const char* PRODUCT_TYPE_PC = { "2in1" };
80 } // namespace
81 
TouchDrawingManager()82 TouchDrawingManager::TouchDrawingManager()
83 {}
84 
~TouchDrawingManager()85 TouchDrawingManager::~TouchDrawingManager() {}
86 
RecordLabelsInfo()87 void TouchDrawingManager::RecordLabelsInfo()
88 {
89     CHKPV(pointerEvent_);
90     PointerEvent::PointerItem pointerItem;
91     if (!pointerEvent_->GetPointerItem(currentPointerId_, pointerItem)) {
92         MMI_HILOGE("Can't find pointer item, pointer:%{public}d", currentPointerId_);
93         return;
94     }
95     auto displayXY = CalcDrawCoordinate(displayInfo_, pointerItem);
96     if (pointerItem.IsPressed()) {
97         currentPt_.SetX(displayXY.first);
98         currentPt_.SetY(displayXY.second);
99         pressure_ = pointerItem.GetPressure();
100     }
101     if (isFirstDownAction_) {
102         firstPt_.SetX(displayXY.first);
103         firstPt_.SetY(displayXY.second);
104         isFirstDownAction_ = false;
105     }
106     int64_t actionTime = pointerEvent_->GetActionTime();
107     if (pointerEvent_->GetPointerId() == currentPointerId_ && !lastPointerItem_.empty()) {
108         double diffTime = static_cast<double>(actionTime - lastActionTime_) / 1000;
109         if (MMI_EQ(diffTime, 0.0)) {
110             xVelocity_ = 0.0;
111             yVelocity_ = 0.0;
112         } else {
113             auto diffX = currentPt_.GetX() - lastPt_.GetX();
114             auto diffY = currentPt_.GetY() - lastPt_.GetY();
115             xVelocity_ = diffX / diffTime;
116             yVelocity_ = diffY / diffTime;
117         }
118         lastActionTime_ = actionTime;
119     }
120 }
121 
TouchDrawHandler(std::shared_ptr<PointerEvent> pointerEvent)122 void TouchDrawingManager::TouchDrawHandler(std::shared_ptr<PointerEvent> pointerEvent)
123 {
124     CALL_DEBUG_ENTER;
125     CHKPV(pointerEvent);
126     pointerEvent_ = pointerEvent;
127     CreateObserver();
128     if (bubbleMode_.isShow) {
129         CreateTouchWindow();
130         AddCanvasNode(bubbleCanvasNode_, false);
131         DrawBubbleHandler();
132     }
133     if (pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_UP
134         && pointerEvent->GetAllPointerItems().size() == 1) {
135         lastPointerItem_.clear();
136     }
137     if (pointerEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_DOWN
138         && pointerEvent->GetAllPointerItems().size() == 1) {
139         stopRecord_ = false;
140     }
141     if (pointerMode_.isShow && !stopRecord_) {
142         CreateTouchWindow();
143         AddCanvasNode(trackerCanvasNode_, true);
144         AddCanvasNode(crosshairCanvasNode_, false);
145         AddCanvasNode(labelsCanvasNode_, false, false);
146         DrawPointerPositionHandler();
147         lastPt_ = currentPt_;
148     }
149 }
150 
UpdateDisplayInfo(const DisplayInfo & displayInfo)151 void TouchDrawingManager::UpdateDisplayInfo(const DisplayInfo& displayInfo)
152 {
153     CALL_DEBUG_ENTER;
154     isChangedRotation_ = displayInfo.direction == displayInfo_.direction ? false : true;
155     isChangedMode_ = displayInfo.displayMode == displayInfo_.displayMode ? false : true;
156     scaleW_ = displayInfo.validWidth > displayInfo.validHeight ? displayInfo.validWidth : displayInfo.validHeight;
157     scaleH_ = displayInfo.validWidth > displayInfo.validHeight ? displayInfo.validWidth : displayInfo.validHeight;
158     displayInfo_ = displayInfo;
159     bubble_.innerCircleRadius = displayInfo.dpi * INDEPENDENT_INNER_PIXELS / DENSITY_BASELINE / CALCULATE_MIDDLE;
160     bubble_.outerCircleRadius = displayInfo.dpi * INDEPENDENT_OUTER_PIXELS / DENSITY_BASELINE / CALCULATE_MIDDLE;
161     bubble_.outerCircleWidth = static_cast<float>(displayInfo.dpi * INDEPENDENT_WIDTH_PIXELS) / DENSITY_BASELINE;
162     itemRectW_ = static_cast<double>(displayInfo_.validWidth) / RECT_COUNT;
163     rectTopPosition_ = 0;
164     if (IsWindowRotation()) {
165         if (displayInfo_.direction == DIRECTION0 || displayInfo_.direction == DIRECTION180) {
166             rectTopPosition_ = PRODUCT_TYPE == PRODUCT_PHONE ? PHONE_RECT_TOP : PAD_RECT_TOP;
167         }
168     } else {
169         if (displayInfo_.direction == DIRECTION90 && PRODUCT_TYPE != PRODUCT_TYPE_PC) {
170             rectTopPosition_ = PHONE_RECT_TOP;
171         }
172     }
173     if (isChangedMode_) {
174         if (trackerCanvasNode_ != nullptr) {
175             trackerCanvasNode_.reset();
176         }
177         if (bubbleCanvasNode_ != nullptr) {
178             bubbleCanvasNode_.reset();
179         }
180         if (crosshairCanvasNode_ != nullptr) {
181             crosshairCanvasNode_.reset();
182         }
183         if (labelsCanvasNode_ != nullptr) {
184             labelsCanvasNode_.reset();
185         }
186         Rosen::RSTransaction::FlushImplicitTransaction();
187     }
188 }
189 
GetOriginalTouchScreenCoordinates(Direction direction,int32_t width,int32_t height,int32_t & physicalX,int32_t & physicalY)190 void TouchDrawingManager::GetOriginalTouchScreenCoordinates(Direction direction, int32_t width, int32_t height,
191     int32_t &physicalX, int32_t &physicalY)
192 {
193     MMI_HILOGD("direction:%{public}d", direction);
194     switch (direction) {
195         case DIRECTION0: {
196             break;
197         }
198         case DIRECTION90: {
199             int32_t temp = physicalY;
200             physicalY = width - physicalX;
201             physicalX = temp;
202             break;
203         }
204         case DIRECTION180: {
205             physicalX = width - physicalX;
206             physicalY = height - physicalY;
207             break;
208         }
209         case DIRECTION270: {
210             int32_t temp = physicalX;
211             physicalX = height - physicalY;
212             physicalY = temp;
213             break;
214         }
215         default: {
216             break;
217         }
218     }
219 }
220 
UpdateLabels()221 int32_t TouchDrawingManager::UpdateLabels()
222 {
223     CALL_DEBUG_ENTER;
224     if (pointerMode_.isShow) {
225         CreateTouchWindow();
226         AddCanvasNode(labelsCanvasNode_, false, false);
227         DrawLabels();
228     } else {
229         RemovePointerPosition();
230         DestoryTouchWindow();
231     }
232     Rosen::RSTransaction::FlushImplicitTransaction();
233     return RET_OK;
234 }
235 
UpdateBubbleData()236 int32_t TouchDrawingManager::UpdateBubbleData()
237 {
238     if (!bubbleMode_.isShow) {
239         CHKPR(surfaceNode_, ERROR_NULL_POINTER);
240         surfaceNode_->RemoveChild(bubbleCanvasNode_);
241         bubbleCanvasNode_.reset();
242         DestoryTouchWindow();
243         Rosen::RSTransaction::FlushImplicitTransaction();
244     }
245     return RET_OK;
246 }
247 
RotationScreen()248 void TouchDrawingManager::RotationScreen()
249 {
250     CALL_DEBUG_ENTER;
251     if (!isChangedRotation_ && !isChangedMode_) {
252         return;
253     }
254 
255     if (pointerMode_.isShow) {
256         RotationCanvasNode(trackerCanvasNode_);
257         RotationCanvasNode(crosshairCanvasNode_);
258     }
259     if (bubbleMode_.isShow) {
260         RotationCanvasNode(bubbleCanvasNode_);
261     }
262 
263     if (pointerMode_.isShow && !isChangedMode_) {
264         if (!lastPointerItem_.empty() || stopRecord_) {
265             Snapshot();
266         } else if (!stopRecord_) {
267             UpdateLabels();
268         }
269     }
270     Rosen::RSTransaction::FlushImplicitTransaction();
271 }
272 
CreateObserver()273 void TouchDrawingManager::CreateObserver()
274 {
275     CALL_DEBUG_ENTER;
276     if (!hasBubbleObserver_) {
277         bubbleMode_.SwitchName = showCursorSwitchName;
278         CreateBubbleObserver(bubbleMode_);
279     }
280     if (!hasPointerObserver_) {
281         pointerMode_.SwitchName = pointerPositionSwitchName;
282         CreatePointerObserver(pointerMode_);
283         SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID).
284             GetBoolValue(pointerPositionSwitchName, pointerMode_.isShow);
285     }
286     MMI_HILOGD("The bubbleMode_:%{public}d, pointerMode_:%{public}d", bubbleMode_.isShow, pointerMode_.isShow);
287 }
288 
289 template <class T>
CreateBubbleObserver(T & item)290 void TouchDrawingManager::CreateBubbleObserver(T &item)
291 {
292     CALL_DEBUG_ENTER;
293     SettingObserver::UpdateFunc updateFunc = [&item, this](const std::string& key) {
294         auto ret = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID)
295             .GetBoolValue(key, item.isShow);
296         if (ret != RET_OK) {
297             MMI_HILOGE("Get value from setting date fail");
298             return;
299         }
300         CHKPV(delegateProxy_);
301         delegateProxy_->OnPostSyncTask(std::bind(&TouchDrawingManager::UpdateBubbleData, this));
302         MMI_HILOGI("The key:%{public}s, statusValue:%{public}d", key.c_str(), item.isShow);
303     };
304     sptr<SettingObserver> statusObserver = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID)
305         .CreateObserver(item.SwitchName, updateFunc);
306     ErrCode ret = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID).
307         RegisterObserver(statusObserver);
308     if (ret != ERR_OK) {
309         MMI_HILOGE("Register setting observer failed, ret:%{public}d", ret);
310         statusObserver = nullptr;
311         return;
312     }
313     hasBubbleObserver_ = true;
314 }
315 
316 template <class T>
CreatePointerObserver(T & item)317 void TouchDrawingManager::CreatePointerObserver(T &item)
318 {
319     CALL_DEBUG_ENTER;
320     SettingObserver::UpdateFunc updateFunc = [&item, this](const std::string& key) {
321         auto ret = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID)
322             .GetBoolValue(key, item.isShow);
323         if (ret != RET_OK) {
324             MMI_HILOGE("Get value from setting date fail");
325             return;
326         }
327         CHKPV(delegateProxy_);
328         delegateProxy_->OnPostSyncTask(std::bind(&TouchDrawingManager::UpdateLabels, this));
329         MMI_HILOGI("The key:%{public}s, statusValue:%{public}d", key.c_str(), item.isShow);
330     };
331     sptr<SettingObserver> statusObserver = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID)
332         .CreateObserver(item.SwitchName, updateFunc);
333     ErrCode ret = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID).RegisterObserver(statusObserver);
334     if (ret != ERR_OK) {
335         MMI_HILOGE("Register setting observer failed, ret:%{public}d", ret);
336         statusObserver = nullptr;
337         return;
338     }
339     hasPointerObserver_ = true;
340 }
341 
342 template <class T>
FormatNumber(T number,int32_t precision)343 std::string TouchDrawingManager::FormatNumber(T number, int32_t precision)
344 {
345     std::string temp(".000");
346     auto str = std::to_string(number);
347     if (str.find(".") == std::string::npos) {
348         str += temp;
349     }
350     return str.substr(0, str.find(".") + precision + 1);
351 }
352 
AddCanvasNode(std::shared_ptr<Rosen::RSCanvasNode> & canvasNode,bool isTrackerNode,bool isNeedRotate)353 void TouchDrawingManager::AddCanvasNode(std::shared_ptr<Rosen::RSCanvasNode>& canvasNode, bool isTrackerNode,
354     bool isNeedRotate)
355 {
356     CALL_DEBUG_ENTER;
357     std::lock_guard<std::mutex> lock(mutex_);
358     CHKPV(surfaceNode_);
359     if (canvasNode != nullptr && screenId_ == static_cast<uint64_t>(displayInfo_.id)) {
360         return;
361     }
362     MMI_HILOGI("Screen from:%{public}" PRIu64 " to :%{public}d", screenId_, displayInfo_.id);
363     screenId_ = static_cast<uint64_t>(displayInfo_.id);
364     canvasNode = isTrackerNode ? Rosen::RSCanvasDrawingNode::Create() : Rosen::RSCanvasNode::Create();
365     canvasNode->SetBounds(0, 0, scaleW_, scaleH_);
366     canvasNode->SetFrame(0, 0, scaleW_, scaleH_);
367     surfaceNode_->SetBounds(0, 0, scaleW_, scaleH_);
368     surfaceNode_->SetFrame(0, 0, scaleW_, scaleH_);
369     if (isNeedRotate) {
370         RotationCanvasNode(canvasNode);
371     }
372 #ifndef USE_ROSEN_DRAWING
373     canvasNode->SetBackgroundColor(SK_ColorTRANSPARENT);
374 #else
375     canvasNode->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
376 #endif
377     canvasNode->SetCornerRadius(1);
378     canvasNode->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
379     surfaceNode_->AddChild(canvasNode, DEFAULT_VALUE);
380 }
381 
RotationCanvasNode(std::shared_ptr<Rosen::RSCanvasNode> canvasNode)382 void TouchDrawingManager::RotationCanvasNode(std::shared_ptr<Rosen::RSCanvasNode> canvasNode)
383 {
384     CALL_DEBUG_ENTER;
385     CHKPV(canvasNode);
386     Direction displayDirection = static_cast<Direction>((
387         ((displayInfo_.direction - displayInfo_.displayDirection) * ANGLE_90 + ANGLE_360) % ANGLE_360) / ANGLE_90);
388     if (displayDirection == Direction::DIRECTION90) {
389         canvasNode->SetRotation(ROTATION_ANGLE_270);
390         canvasNode->SetTranslateX(0);
391     } else if (displayDirection == Direction::DIRECTION270) {
392         canvasNode->SetRotation(ROTATION_ANGLE_90);
393         canvasNode->SetTranslateX(-std::fabs(displayInfo_.validWidth - displayInfo_.validHeight));
394     } else if (displayDirection == Direction::DIRECTION180) {
395         canvasNode->SetRotation(ROTATION_ANGLE_180);
396         canvasNode->SetTranslateX(-std::fabs(displayInfo_.validWidth - displayInfo_.validHeight));
397     } else {
398         canvasNode->SetRotation(ROTATION_ANGLE_0);
399         canvasNode->SetTranslateX(0);
400     }
401     canvasNode->SetTranslateY(0);
402 }
403 
ResetCanvasNode(std::shared_ptr<Rosen::RSCanvasNode> canvasNode)404 void TouchDrawingManager::ResetCanvasNode(std::shared_ptr<Rosen::RSCanvasNode> canvasNode)
405 {
406     CALL_DEBUG_ENTER;
407     CHKPV(canvasNode);
408     canvasNode->SetRotation(ROTATION_ANGLE_0);
409     canvasNode->SetTranslateX(0);
410     canvasNode->SetTranslateY(0);
411 }
412 
RotationCanvas(RosenCanvas * canvas,Direction direction)413 void TouchDrawingManager::RotationCanvas(RosenCanvas *canvas, Direction direction)
414 {
415     CHKPV(canvas);
416     if (direction == Direction::DIRECTION90) {
417         canvas->Translate(0, displayInfo_.validWidth);
418         canvas->Rotate(ROTATION_ANGLE_270, 0, 0);
419     } else if (direction == Direction::DIRECTION180) {
420         canvas->Rotate(ROTATION_ANGLE_180, static_cast<float>(displayInfo_.validWidth) / CALCULATE_MIDDLE,
421             static_cast<float>(displayInfo_.validHeight) / CALCULATE_MIDDLE);
422     } else if (direction == Direction::DIRECTION270) {
423         canvas->Translate(displayInfo_.validHeight, 0);
424         canvas->Rotate(ROTATION_ANGLE_90, 0, 0);
425     }
426 }
CreateTouchWindow()427 void TouchDrawingManager::CreateTouchWindow()
428 {
429     CALL_DEBUG_ENTER;
430     std::lock_guard<std::mutex> lock(mutex_);
431     if (surfaceNode_ != nullptr || scaleW_ == 0 || scaleH_ == 0) {
432         return;
433     }
434     Rosen::RSSurfaceNodeConfig surfaceNodeConfig;
435     surfaceNodeConfig.SurfaceNodeName = "touch window";
436     Rosen::RSSurfaceNodeType surfaceNodeType = Rosen::RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE;
437     surfaceNode_ = Rosen::RSSurfaceNode::Create(surfaceNodeConfig, surfaceNodeType);
438     CHKPV(surfaceNode_);
439     surfaceNode_->SetFrameGravity(Rosen::Gravity::RESIZE_ASPECT_FILL);
440     surfaceNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
441     surfaceNode_->SetBounds(0, 0, scaleW_, scaleH_);
442     surfaceNode_->SetFrame(0, 0, scaleW_, scaleH_);
443 #ifndef USE_ROSEN_DRAWING
444     surfaceNode_->SetBackgroundColor(SK_ColorTRANSPARENT);
445 #else
446     surfaceNode_->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
447 #endif
448     surfaceNode_->SetRotation(0);
449     screenId_ = static_cast<uint64_t>(displayInfo_.id);
450     if (windowScreenId_ == screenId_) {
451         screenId_ = displayNodeScreenId_;
452     }
453     surfaceNode_->AttachToDisplay(screenId_);
454     MMI_HILOGI("Setting screen:%{public}" PRIu64 ", displayNode:%{public}" PRIu64, screenId_, surfaceNode_->GetId());
455 }
456 
DrawBubbleHandler()457 void TouchDrawingManager::DrawBubbleHandler()
458 {
459     CALL_DEBUG_ENTER;
460     CHKPV(pointerEvent_);
461     auto pointerAction = pointerEvent_->GetPointerAction();
462     if (IsValidAction(pointerAction)) {
463         DrawBubble();
464     }
465     Rosen::RSTransaction::FlushImplicitTransaction();
466 }
467 
DrawBubble()468 void TouchDrawingManager::DrawBubble()
469 {
470     CHKPV(pointerEvent_);
471     CHKPV(bubbleCanvasNode_);
472     auto canvas = static_cast<RosenCanvas *>(bubbleCanvasNode_->BeginRecording(scaleW_, scaleH_));
473     CHKPV(canvas);
474     auto pointerIdList = pointerEvent_->GetPointerIds();
475     for (auto pointerId : pointerIdList) {
476         if ((pointerEvent_->GetPointerAction() == PointerEvent::POINTER_ACTION_UP ||
477             pointerEvent_->GetPointerAction() == PointerEvent::POINTER_ACTION_PULL_UP ||
478             pointerEvent_->GetPointerAction() == PointerEvent::POINTER_ACTION_CANCEL) &&
479             pointerEvent_->GetPointerId() == pointerId) {
480             MMI_HILOGI("Continue bubble draw, pointerAction:%{public}d, pointerId:%{public}d",
481                 pointerEvent_->GetPointerAction(), pointerEvent_->GetPointerId());
482             continue;
483         }
484         PointerEvent::PointerItem pointerItem;
485         if (!pointerEvent_->GetPointerItem(pointerId, pointerItem)) {
486             MMI_HILOGE("Can't find pointer item, pointer:%{public}d", pointerId);
487             return;
488         }
489         auto displayXY = CalcDrawCoordinate(displayInfo_, pointerItem);
490         Rosen::Drawing::Point centerPt(displayXY.first, displayXY.second);
491         Rosen::Drawing::Pen pen;
492         pen.SetColor(Rosen::Drawing::Color::COLOR_BLACK);
493         pen.SetAntiAlias(true);
494         pen.SetAlphaF(OUT_CIRCLE_TRANSPARENCY);
495         pen.SetWidth(bubble_.outerCircleWidth);
496         canvas->AttachPen(pen);
497         canvas->DrawCircle(centerPt, bubble_.outerCircleRadius);
498         canvas->DetachPen();
499 
500         Rosen::Drawing::Brush brush;
501         brush.SetColor(Rosen::Drawing::Color::COLOR_WHITE);
502         brush.SetAntiAlias(true);
503         brush.SetAlphaF(INNER_CIRCLE_TRANSPARENCY);
504         canvas->AttachBrush(brush);
505         canvas->DrawCircle(centerPt, bubble_.innerCircleRadius);
506         canvas->DetachBrush();
507         if (pointerEvent_->GetPointerAction() == PointerEvent::POINTER_ACTION_DOWN &&
508             pointerEvent_->GetPointerId() == pointerId) {
509             MMI_HILOGI("Bubble is draw success, pointerAction:%{public}d, pointerId:%{public}d, physicalX:%{private}d,"
510                 " physicalY:%{private}d, width:%{public}d, height:%{public}d", pointerEvent_->GetPointerAction(),
511                 pointerEvent_->GetPointerId(), displayXY.first, displayXY.second, scaleW_, scaleH_);
512         }
513     }
514     bubbleCanvasNode_->FinishRecording();
515 }
516 
DrawPointerPositionHandler()517 void TouchDrawingManager::DrawPointerPositionHandler()
518 {
519     CALL_DEBUG_ENTER;
520     CHKPV(pointerEvent_);
521     UpdatePointerPosition();
522     ClearTracker();
523     RecordLabelsInfo();
524     CHKPV(crosshairCanvasNode_);
525     auto canvas = static_cast<RosenCanvas *>(crosshairCanvasNode_->BeginRecording(scaleW_, scaleH_));
526     CHKPV(canvas);
527     auto pointerIdList = pointerEvent_->GetPointerIds();
528     for (auto pointerId : pointerIdList) {
529         PointerEvent::PointerItem pointerItem;
530         if (!pointerEvent_->GetPointerItem(pointerId, pointerItem)) {
531             MMI_HILOGE("Can't find pointer item, pointer:%{public}d", pointerId);
532             return;
533         }
534         auto displayXY = CalcDrawCoordinate(displayInfo_, pointerItem);
535         DrawTracker(displayXY.first, displayXY.second, pointerId);
536         if (pointerEvent_->GetPointerAction() != PointerEvent::POINTER_ACTION_UP) {
537             DrawCrosshairs(canvas, displayXY.first, displayXY.second);
538             UpdateLastPointerItem(pointerItem);
539         }
540     }
541     DrawLabels();
542     crosshairCanvasNode_->FinishRecording();
543     Rosen::RSTransaction::FlushImplicitTransaction();
544 }
545 
Snapshot()546 void TouchDrawingManager::Snapshot()
547 {
548     CHKPV(labelsCanvasNode_);
549     std::string viewP = "P: 0 / " + std::to_string(maxPointerCount_);
550     auto dx = currentPt_.GetX() - firstPt_.GetX();
551     auto dy = currentPt_.GetY() - firstPt_.GetY();
552     std::string viewDx = "dX: " + FormatNumber(dx, ONE_PRECISION);
553     std::string viewDy = "dY: " + FormatNumber(dy, ONE_PRECISION);
554     std::string viewXv = "Xv: " + FormatNumber(xVelocity_, THREE_PRECISION);
555     std::string viewYv = "Yv: " + FormatNumber(yVelocity_, THREE_PRECISION);
556     std::string viewPrs = "Prs: " + FormatNumber(pressure_, TWO_PRECISION);
557     Rosen::Drawing::Color color = LABELS_DEFAULT_COLOR;
558     auto canvas = static_cast<RosenCanvas *>(labelsCanvasNode_->BeginRecording(scaleW_, scaleH_));
559     Rosen::Drawing::Rect rect;
560     rect.top_ = rectTopPosition_;
561     rect.bottom_ = rectTopPosition_ + RECT_HEIGHT;
562     rect.left_ = 0;
563     rect.right_ = itemRectW_ + rect.left_;
564     Direction displayDirection = static_cast<Direction>((
565         ((displayInfo_.direction - displayInfo_.displayDirection) * ANGLE_90 + ANGLE_360) % ANGLE_360) / ANGLE_90);
566     RotationCanvas(canvas, displayDirection);
567 
568     DrawRectItem(canvas, viewP, rect, color);
569     color = std::abs(dx) < TOUCH_SLOP ? LABELS_DEFAULT_COLOR : LABELS_RED_COLOR;
570     DrawRectItem(canvas, viewDx, rect, color);
571     color = std::abs(dy) < TOUCH_SLOP ? LABELS_DEFAULT_COLOR : LABELS_RED_COLOR;
572     DrawRectItem(canvas, viewDy, rect, color);
573     DrawRectItem(canvas, viewXv, rect, LABELS_DEFAULT_COLOR);
574     DrawRectItem(canvas, viewYv, rect, LABELS_DEFAULT_COLOR);
575     color = isFirstDraw_ ? LABELS_DEFAULT_COLOR : LABELS_RED_COLOR;
576     DrawRectItem(canvas, viewPrs, rect, color);
577     labelsCanvasNode_->FinishRecording();
578     CHKPV(crosshairCanvasNode_);
579     auto crosshairCanvas = static_cast<RosenCanvas *>(crosshairCanvasNode_->BeginRecording(scaleW_, scaleH_));
580     crosshairCanvas->Clear();
581     crosshairCanvasNode_->FinishRecording();
582     stopRecord_ = true;
583 }
584 
IsWindowRotation()585 bool TouchDrawingManager::IsWindowRotation()
586 {
587     MMI_HILOGD("ROTATE_POLICY:%{public}d, FOLDABLE_DEVICE_POLICY:%{public}s",
588         ROTATE_POLICY, FOLDABLE_DEVICE_POLICY.c_str());
589     return (ROTATE_POLICY == WINDOW_ROTATE ||
590         (ROTATE_POLICY == FOLDABLE_DEVICE &&
591         ((displayInfo_.displayMode == DisplayMode::MAIN &&
592         FOLDABLE_DEVICE_POLICY[0] == ROTATE_WINDOW_ROTATE) ||
593         (displayInfo_.displayMode == DisplayMode::FULL &&
594         FOLDABLE_DEVICE_POLICY[FOLDABLE_DEVICE] == ROTATE_WINDOW_ROTATE))));
595 }
596 
DrawTracker(int32_t x,int32_t y,int32_t pointerId)597 void TouchDrawingManager::DrawTracker(int32_t x, int32_t y, int32_t pointerId)
598 {
599     CALL_DEBUG_ENTER;
600     Rosen::Drawing::Point currentPt(x, y);
601     Rosen::Drawing::Point lastPt;
602     bool find = false;
603     for (auto &item : lastPointerItem_) {
604         if (item.GetPointerId() == pointerId) {
605             auto displayXY = CalcDrawCoordinate(displayInfo_, item);
606             lastPt.SetX(displayXY.first);
607             lastPt.SetY(displayXY.second);
608             find = true;
609             break;
610         }
611     }
612     if (currentPt == lastPt) {
613         return;
614     }
615     CHKPV(trackerCanvasNode_);
616     BytraceAdapter::StartHandleTracker(pointerId);
617     auto canvas = static_cast<RosenCanvas *>(trackerCanvasNode_->BeginRecording(scaleW_, scaleH_));
618     CHKPV(canvas);
619     Rosen::Drawing::Pen pen;
620     if (find) {
621         pen.SetColor(TRACKER_COLOR);
622         pen.SetWidth(PEN_WIDTH);
623         canvas->AttachPen(pen);
624         canvas->DrawLine(lastPt, currentPt);
625         canvas->DetachPen();
626         pen.SetColor(POINTER_RED_COLOR);
627         pen.SetWidth(INDEPENDENT_WIDTH_PIXELS);
628         canvas->AttachPen(pen);
629         canvas->DrawPoint(currentPt);
630         canvas->DetachPen();
631     }
632     if (!isDownAction_ && !find) {
633         int32_t futureX = x + xVelocity_ * MULTIPLE_FACTOR;
634         int32_t futureY = y + yVelocity_ * MULTIPLE_FACTOR;
635         Rosen::Drawing::Point futurePt(futureX, futureY);
636         pen.SetColor(POINTER_RED_COLOR);
637         pen.SetWidth(PEN_WIDTH);
638         canvas->AttachPen(pen);
639         canvas->DrawLine(currentPt, futurePt);
640         canvas->DetachPen();
641     }
642     trackerCanvasNode_->FinishRecording();
643     BytraceAdapter::StopHandleTracker();
644 }
645 
DrawCrosshairs(RosenCanvas * canvas,int32_t x,int32_t y)646 void TouchDrawingManager::DrawCrosshairs(RosenCanvas *canvas, int32_t x, int32_t y)
647 {
648     CALL_DEBUG_ENTER;
649     CHKPV(canvas);
650     Rosen::Drawing::Pen pen;
651     pen.SetColor(CROSS_HAIR_COLOR);
652     pen.SetWidth(PEN_WIDTH);
653     canvas->AttachPen(pen);
654     Rosen::Drawing::Point left(0, y);
655     Rosen::Drawing::Point right(scaleH_, y);
656     canvas->DrawLine(left, right);
657     Rosen::Drawing::Point top(x, 0);
658     Rosen::Drawing::Point bottom(x, scaleH_);
659     canvas->DrawLine(top, bottom);
660     canvas->DetachPen();
661 }
662 
DrawLabels()663 void TouchDrawingManager::DrawLabels()
664 {
665     CALL_DEBUG_ENTER;
666     CHKPV(labelsCanvasNode_);
667     std::string viewP = "P: " + std::to_string(currentPointerCount_) + " / " + std::to_string(maxPointerCount_);
668     std::string viewX = "X: " + FormatNumber(currentPt_.GetX(), ONE_PRECISION);
669     std::string viewY = "Y: " + FormatNumber(currentPt_.GetY(), ONE_PRECISION);
670     auto dx = currentPt_.GetX() - firstPt_.GetX();
671     auto dy = currentPt_.GetY() - firstPt_.GetY();
672     std::string viewDx = "dX: " + FormatNumber(dx, ONE_PRECISION);
673     std::string viewDy = "dY: " + FormatNumber(dy, ONE_PRECISION);
674     std::string viewXv = "Xv: " + FormatNumber(xVelocity_, THREE_PRECISION);
675     std::string viewYv = "Yv: " + FormatNumber(yVelocity_, THREE_PRECISION);
676     std::string viewPrs = "Prs: " + FormatNumber(pressure_, TWO_PRECISION);
677     Rosen::Drawing::Color color = LABELS_DEFAULT_COLOR;
678     std::lock_guard<std::mutex> lock(mutex_);
679     auto canvas = static_cast<RosenCanvas *>(labelsCanvasNode_->BeginRecording(scaleW_, scaleH_));
680     CHKPV(canvas);
681     Rosen::Drawing::Rect rect;
682     rect.top_ = rectTopPosition_;
683     rect.bottom_ = rectTopPosition_ + RECT_HEIGHT;
684     rect.left_ = 0;
685     rect.right_ = itemRectW_ + rect.left_;
686     Direction displayDirection = static_cast<Direction>((
687         ((displayInfo_.direction - displayInfo_.displayDirection) * ANGLE_90 + ANGLE_360) % ANGLE_360) / ANGLE_90);
688     RotationCanvas(canvas, displayDirection);
689     DrawRectItem(canvas, viewP, rect, color);
690     if (isDownAction_ || !lastPointerItem_.empty()) {
691         DrawRectItem(canvas, viewX, rect, color);
692         DrawRectItem(canvas, viewY, rect, color);
693     } else {
694         color = std::abs(dx) < TOUCH_SLOP ? LABELS_DEFAULT_COLOR : LABELS_RED_COLOR;
695         DrawRectItem(canvas, viewDx, rect, color);
696         color = std::abs(dy) < TOUCH_SLOP ? LABELS_DEFAULT_COLOR : LABELS_RED_COLOR;
697         DrawRectItem(canvas, viewDy, rect, color);
698     }
699     DrawRectItem(canvas, viewXv, rect, LABELS_DEFAULT_COLOR);
700     DrawRectItem(canvas, viewYv, rect, LABELS_DEFAULT_COLOR);
701     color = isFirstDraw_ ? LABELS_DEFAULT_COLOR : LABELS_RED_COLOR;
702     DrawRectItem(canvas, viewPrs, rect, color);
703     labelsCanvasNode_->FinishRecording();
704     isFirstDraw_ = false;
705 }
706 
DrawRectItem(RosenCanvas * canvas,const std::string & text,Rosen::Drawing::Rect & rect,const Rosen::Drawing::Color & color)707 void TouchDrawingManager::DrawRectItem(RosenCanvas* canvas, const std::string &text,
708     Rosen::Drawing::Rect &rect, const Rosen::Drawing::Color &color)
709 {
710     CHKPV(canvas);
711     Rosen::Drawing::Brush brush;
712     brush.SetColor(color);
713     canvas->AttachBrush(brush);
714     canvas->DrawRect(rect);
715     canvas->DetachBrush();
716 
717     std::shared_ptr<Rosen::Drawing::TextBlob> textBlob = Rosen::Drawing::TextBlob::MakeFromString(text.c_str(),
718         Rosen::Drawing::Font(nullptr, TEXT_SIZE, TEXT_SCALE, TEXT_SKEW), Rosen::Drawing::TextEncoding::UTF8);
719     CHKPV(textBlob);
720     brush.SetColor(Rosen::Drawing::Color::COLOR_BLACK);
721     canvas->AttachBrush(brush);
722     canvas->DrawTextBlob(textBlob.get(), rect.left_, rectTopPosition_ + TEXT_TOP);
723     canvas->DetachBrush();
724     rect.left_ += itemRectW_ + RECT_SPACEING;
725     rect.right_ += itemRectW_ + RECT_SPACEING;
726 }
727 
UpdatePointerPosition()728 void TouchDrawingManager::UpdatePointerPosition()
729 {
730     CALL_DEBUG_ENTER;
731     CHKPV(pointerEvent_);
732     int32_t pointerAction = pointerEvent_->GetPointerAction();
733     int32_t pointerId = pointerEvent_->GetPointerId();
734     if (pointerAction == PointerEvent::POINTER_ACTION_DOWN) {
735         if (lastPointerItem_.empty()) {
736             InitLabels();
737         }
738         maxPointerCount_ = ++currentPointerCount_;
739     } else if (pointerAction == PointerEvent::POINTER_ACTION_UP) {
740         isDownAction_ = false;
741         isFirstDownAction_ = false;
742         for (auto it = lastPointerItem_.begin(); it != lastPointerItem_.end(); it++) {
743             if (it->GetPointerId() == pointerId) {
744                 lastPointerItem_.erase(it);
745                 --currentPointerCount_;
746                 break;
747             }
748         }
749         if (!lastPointerItem_.empty() && (currentPointerId_ == pointerId)) {
750             currentPointerId_ = lastPointerItem_.front().GetPointerId();
751         }
752     }
753 }
754 
UpdateLastPointerItem(PointerEvent::PointerItem & pointerItem)755 void TouchDrawingManager::UpdateLastPointerItem(PointerEvent::PointerItem &pointerItem)
756 {
757     CALL_DEBUG_ENTER;
758     if (!pointerItem.IsPressed()) {
759         return;
760     }
761     for (auto &item : lastPointerItem_) {
762         if (item.GetPointerId() == pointerItem.GetPointerId()) {
763             item = pointerItem;
764             return;
765         }
766     }
767     lastPointerItem_.emplace_back(pointerItem);
768 }
769 
RemovePointerPosition()770 void TouchDrawingManager::RemovePointerPosition()
771 {
772     CALL_DEBUG_ENTER;
773     CHKPV(surfaceNode_);
774     surfaceNode_->RemoveChild(trackerCanvasNode_);
775     trackerCanvasNode_.reset();
776 
777     surfaceNode_->RemoveChild(crosshairCanvasNode_);
778     crosshairCanvasNode_.reset();
779 
780     surfaceNode_->RemoveChild(labelsCanvasNode_);
781     labelsCanvasNode_.reset();
782 
783     pointerEvent_.reset();
784     Rosen::RSTransaction::FlushImplicitTransaction();
785     isFirstDraw_ = true;
786     pressure_ = 0.0;
787 }
788 
DestoryTouchWindow()789 void TouchDrawingManager::DestoryTouchWindow()
790 {
791     if (bubbleMode_.isShow || pointerMode_.isShow) {
792         return;
793     }
794     MMI_HILOGI("Destory touch window success, bubbleMode:%{public}d, pointerMode:%{public}d",
795         bubbleMode_.isShow, pointerMode_.isShow);
796     CHKPV(surfaceNode_);
797     surfaceNode_->ClearChildren();
798     surfaceNode_.reset();
799 }
800 
ClearTracker()801 void TouchDrawingManager::ClearTracker()
802 {
803     CALL_DEBUG_ENTER;
804     CHKPV(trackerCanvasNode_);
805     if (lastPointerItem_.empty() && isDownAction_) {
806         MMI_HILOGD("ClearTracker isDownAction_ and empty");
807         auto canvasNode = static_cast<Rosen::RSCanvasDrawingNode*>(trackerCanvasNode_.get());
808         canvasNode->ResetSurface(scaleW_, scaleH_);
809     }
810 }
811 
InitLabels()812 void TouchDrawingManager::InitLabels()
813 {
814     isFirstDownAction_ = true;
815     isDownAction_ = true;
816     maxPointerCount_ = 0;
817     currentPointerCount_ = 0;
818     currentPointerId_ = 0;
819     xVelocity_ = 0.0;
820     yVelocity_ = 0.0;
821 }
822 
IsValidAction(const int32_t action)823 bool TouchDrawingManager::IsValidAction(const int32_t action)
824 {
825     if (action == PointerEvent::POINTER_ACTION_DOWN || action == PointerEvent::POINTER_ACTION_PULL_DOWN ||
826         action == PointerEvent::POINTER_ACTION_MOVE || action == PointerEvent::POINTER_ACTION_PULL_MOVE ||
827         action == PointerEvent::POINTER_ACTION_UP || action == PointerEvent::POINTER_ACTION_PULL_UP ||
828         action == PointerEvent::POINTER_ACTION_CANCEL) {
829         return true;
830     }
831     return false;
832 }
833 
Dump(int32_t fd,const std::vector<std::string> & args)834 void TouchDrawingManager::Dump(int32_t fd, const std::vector<std::string> &args)
835 {
836     CALL_DEBUG_ENTER;
837     std::ostringstream oss;
838 
839     std::vector<std::string> titles1 = {"currentPointerId", "maxPointerCount", "currentPointerCount",
840                                         "lastActionTime", "xVelocity", "yVelocity"};
841 
842     std::vector<std::vector<std::string>> data1 = {
843         {std::to_string(currentPointerId_), std::to_string(maxPointerCount_), std::to_string(currentPointerCount_),
844          std::to_string(lastActionTime_), std::to_string(xVelocity_), std::to_string(yVelocity_)}
845     };
846 
847     DumpFullTable(oss, "Touch Location Info", titles1, data1);
848     oss << std::endl;
849 
850     std::vector<std::string> titles2 = {"pressure", "itemRectW", "hasBubbleObserver",
851                                         "hasPointerObserver", "isFirstDownAction", "isDownAction", "isFirstDraw"};
852 
853     std::vector<std::vector<std::string>> data2 = {
854         {std::to_string(pressure_), std::to_string(itemRectW_), std::to_string(hasBubbleObserver_),
855          std::to_string(hasPointerObserver_), std::to_string(isFirstDownAction_), std::to_string(isDownAction_),
856          std::to_string(isFirstDraw_)}
857     };
858 
859     DumpFullTable(oss, "Touch Location Info", titles2, data2);
860     oss << std::endl;
861 
862     std::vector<std::string> bubbleTitles = {"innerCircleRadius", "outerCircleRadius", "outerCircleWidth"};
863     std::vector<std::vector<std::string>> bubbleData = {
864         {std::to_string(bubble_.innerCircleRadius), std::to_string(bubble_.outerCircleRadius), std::to_string(bubble_.outerCircleWidth)}
865     };
866 
867     DumpFullTable(oss, "Bubble Info", bubbleTitles, bubbleData);
868     oss << std::endl;
869 
870     std::vector<std::string> devModeTitles = {"Name", "SwitchName", "IsShow"};
871     std::vector<std::vector<std::string>> devModeData = {
872         {"BubbleMode", bubbleMode_.SwitchName, std::to_string(bubbleMode_.isShow)},
873         {"PointerMode", pointerMode_.SwitchName, std::to_string(pointerMode_.isShow)}
874     };
875 
876     DumpFullTable(oss, "DevMode Info", devModeTitles, devModeData);
877     oss << std::endl;
878 
879     std::string dumpInfo = oss.str();
880     dprintf(fd, dumpInfo.c_str());
881 }
882 
CalcDrawCoordinate(const DisplayInfo & displayInfo,PointerEvent::PointerItem pointerItem)883 std::pair<int32_t, int32_t> TouchDrawingManager::CalcDrawCoordinate(const DisplayInfo& displayInfo,
884     PointerEvent::PointerItem pointerItem)
885 {
886     CALL_DEBUG_ENTER;
887     double physicalX = pointerItem.GetRawDisplayX();
888     double physicalY = pointerItem.GetRawDisplayY();
889     if (!displayInfo.transform.empty()) {
890         auto displayXY = WIN_MGR->TransformDisplayXY(displayInfo, physicalX, physicalY);
891         physicalX = displayXY.first;
892         physicalY = displayXY.second;
893     }
894     return {static_cast<int32_t>(physicalX), static_cast<int32_t>(physicalY)};
895 }
896 } // namespace MMI
897 } // namespace OHOS