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