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