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