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