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