1 /*
2 * Copyright (c) 2021-2022 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 "touchpad_transform_processor.h"
17
18 #include <linux/input.h>
19
20 #include "dfx_hisysevent.h"
21 #include "event_log_helper.h"
22 #include "i_input_windows_manager.h"
23 #include "i_preference_manager.h"
24 #include "mouse_device_state.h"
25
26 #undef MMI_LOG_DOMAIN
27 #define MMI_LOG_DOMAIN MMI_LOG_DISPATCH
28 #undef MMI_LOG_TAG
29 #define MMI_LOG_TAG "TouchPadTransformProcessor"
30
31 namespace OHOS {
32 namespace MMI {
33 namespace {
34 constexpr int32_t MT_TOOL_NONE { -1 };
35 constexpr int32_t BTN_DOWN { 1 };
36 constexpr int32_t FINGER_COUNT_MAX { 5 };
37 constexpr int32_t FINGER_TAP_MIN { 3 };
38 constexpr int32_t FINGER_TAP_THREE { 3 };
39 constexpr int32_t TP_SYSTEM_PINCH_FINGER_CNT { 2 };
40 constexpr int32_t DEFAULT_POINTER_ID { 0 };
41 constexpr int32_t MIN_ROWS { 1 };
42 constexpr int32_t MAX_ROWS { 100 };
43 constexpr int32_t DEFAULT_ROWS { 3 };
44 constexpr int32_t MAX_N_POINTER_ITEMS { 10 };
45
46 const char* TOUCHPAD_FILE_NAME = "touchpad_settings.xml";
47 std::string g_threeFingerTapKey = "touchpadThreeFingerTap";
48 } // namespace
49
TouchPadTransformProcessor(int32_t deviceId)50 TouchPadTransformProcessor::TouchPadTransformProcessor(int32_t deviceId)
51 : deviceId_(deviceId)
52 {
53 InitToolType();
54 }
55
OnEventTouchPadDown(struct libinput_event * event)56 int32_t TouchPadTransformProcessor::OnEventTouchPadDown(struct libinput_event *event)
57 {
58 CALL_INFO_TRACE;
59 CHKPR(event, RET_ERR);
60 auto touchpad = libinput_event_get_touchpad_event(event);
61 CHKPR(touchpad, RET_ERR);
62 auto device = libinput_event_get_device(event);
63 CHKPR(device, RET_ERR);
64
65 uint64_t time = libinput_event_touchpad_get_time_usec(touchpad);
66 auto pointIds = pointerEvent_->GetPointerIds();
67 if (pointIds.empty()) {
68 pointerEvent_->SetActionStartTime(time);
69 }
70 pointerEvent_->SetActionTime(time);
71 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_DOWN);
72 PointerEvent::PointerItem item;
73 int32_t longAxis = libinput_event_touchpad_get_touch_contact_long_axis(touchpad);
74 int32_t shortAxis = libinput_event_touchpad_get_touch_contact_short_axis(touchpad);
75 double pressure = libinput_event_touchpad_get_pressure(touchpad);
76 int32_t seatSlot = libinput_event_touchpad_get_seat_slot(touchpad);
77 double logicalX = libinput_event_touchpad_get_x(touchpad);
78 double logicalY = libinput_event_touchpad_get_y(touchpad);
79 double toolPhysicalX = libinput_event_touchpad_get_tool_x(touchpad);
80 double toolPhysicalY = libinput_event_touchpad_get_tool_y(touchpad);
81 double toolWidth = libinput_event_touchpad_get_tool_width(touchpad);
82 double toolHeight = libinput_event_touchpad_get_tool_height(touchpad);
83 int32_t toolType = GetTouchPadToolType(touchpad, device);
84 if (toolType == PointerEvent::TOOL_TYPE_PALM) {
85 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_CANCEL);
86 }
87
88 item.SetLongAxis(longAxis);
89 item.SetShortAxis(shortAxis);
90 item.SetPressure(pressure);
91 item.SetToolType(toolType);
92 item.SetPointerId(seatSlot);
93 item.SetDownTime(time);
94 item.SetPressed(true);
95 item.SetDisplayX(static_cast<int32_t>(logicalX));
96 item.SetDisplayY(static_cast<int32_t>(logicalY));
97 item.SetToolDisplayX(static_cast<int32_t>(toolPhysicalX));
98 item.SetToolDisplayY(static_cast<int32_t>(toolPhysicalY));
99 item.SetToolWidth(static_cast<int32_t>(toolWidth));
100 item.SetToolHeight(static_cast<int32_t>(toolHeight));
101 item.SetDeviceId(deviceId_);
102 pointerEvent_->SetDeviceId(deviceId_);
103 RemoveSurplusPointerItem();
104 pointerEvent_->AddPointerItem(item);
105 pointerEvent_->SetPointerId(seatSlot);
106
107 return RET_OK;
108 }
109
OnEventTouchPadMotion(struct libinput_event * event)110 int32_t TouchPadTransformProcessor::OnEventTouchPadMotion(struct libinput_event *event)
111 {
112 CALL_DEBUG_ENTER;
113 CHKPR(event, RET_ERR);
114 auto touchpad = libinput_event_get_touchpad_event(event);
115 CHKPR(touchpad, RET_ERR);
116 int32_t seatSlot = libinput_event_touchpad_get_seat_slot(touchpad);
117 auto device = libinput_event_get_device(event);
118 CHKPR(device, RET_ERR);
119
120 uint64_t time = libinput_event_touchpad_get_time_usec(touchpad);
121 pointerEvent_->SetActionTime(time);
122 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_MOVE);
123 PointerEvent::PointerItem item;
124 if (!pointerEvent_->GetPointerItem(seatSlot, item)) {
125 MMI_HILOGD("Can't find the pointer item data, seatSlot:%{public}d, errCode:%{public}d",
126 seatSlot, PARAM_INPUT_FAIL);
127 return RET_ERR;
128 }
129 int32_t longAxis = libinput_event_touchpad_get_touch_contact_long_axis(touchpad);
130 int32_t shortAxis = libinput_event_touchpad_get_touch_contact_short_axis(touchpad);
131 double pressure = libinput_event_touchpad_get_pressure(touchpad);
132 double logicalX = libinput_event_touchpad_get_x(touchpad);
133 double logicalY = libinput_event_touchpad_get_y(touchpad);
134 double toolPhysicalX = libinput_event_touchpad_get_tool_x(touchpad);
135 double toolPhysicalY = libinput_event_touchpad_get_tool_y(touchpad);
136 double toolWidth = libinput_event_touchpad_get_tool_width(touchpad);
137 double toolHeight = libinput_event_touchpad_get_tool_height(touchpad);
138 int32_t toolType = GetTouchPadToolType(touchpad, device);
139 if (toolType == PointerEvent::TOOL_TYPE_PALM) {
140 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_CANCEL);
141 }
142
143 item.SetLongAxis(longAxis);
144 item.SetShortAxis(shortAxis);
145 item.SetPressure(pressure);
146 item.SetDisplayX(static_cast<int32_t>(logicalX));
147 item.SetDisplayY(static_cast<int32_t>(logicalY));
148 item.SetToolDisplayX(static_cast<int32_t>(toolPhysicalX));
149 item.SetToolDisplayY(static_cast<int32_t>(toolPhysicalY));
150 item.SetToolWidth(static_cast<int32_t>(toolWidth));
151 item.SetToolHeight(static_cast<int32_t>(toolHeight));
152 pointerEvent_->UpdatePointerItem(seatSlot, item);
153 pointerEvent_->SetPointerId(seatSlot);
154
155 return RET_OK;
156 }
157
OnEventTouchPadUp(struct libinput_event * event)158 int32_t TouchPadTransformProcessor::OnEventTouchPadUp(struct libinput_event *event)
159 {
160 CALL_DEBUG_ENTER;
161 CHKPR(event, RET_ERR);
162 auto touchpad = libinput_event_get_touchpad_event(event);
163 CHKPR(touchpad, RET_ERR);
164 int32_t seatSlot = libinput_event_touchpad_get_seat_slot(touchpad);
165
166 uint64_t time = libinput_event_touchpad_get_time_usec(touchpad);
167 pointerEvent_->SetActionTime(time);
168 if (MULTI_FINGERTAP_HDR->GetMultiFingersState() == MulFingersTap::TRIPLE_TAP) {
169 SetTouchPadMultiTapData();
170 } else {
171 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_UP);
172 }
173 PointerEvent::PointerItem item;
174 if (!pointerEvent_->GetPointerItem(seatSlot, item)) {
175 MMI_HILOGE("Can't find the pointer item data, seatSlot:%{public}d, errCode:%{public}d",
176 seatSlot, PARAM_INPUT_FAIL);
177 return RET_ERR;
178 }
179 item.SetPressed(false);
180 pointerEvent_->UpdatePointerItem(seatSlot, item);
181 pointerEvent_->SetPointerId(seatSlot);
182
183 return RET_OK;
184 }
185
OnEvent(struct libinput_event * event)186 std::shared_ptr<PointerEvent> TouchPadTransformProcessor::OnEvent(struct libinput_event *event)
187 {
188 CALL_DEBUG_ENTER;
189 CHKPP(event);
190 if (pointerEvent_ == nullptr) {
191 pointerEvent_ = PointerEvent::Create();
192 CHKPP(pointerEvent_);
193 }
194
195 int32_t ret = RET_OK;
196 int32_t type = libinput_event_get_type(event);
197 switch (type) {
198 case LIBINPUT_EVENT_TOUCHPAD_DOWN: {
199 ret = OnEventTouchPadDown(event);
200 break;
201 }
202 case LIBINPUT_EVENT_TOUCHPAD_UP: {
203 ret = OnEventTouchPadUp(event);
204 break;
205 }
206 case LIBINPUT_EVENT_TOUCHPAD_MOTION: {
207 ret = OnEventTouchPadMotion(event);
208 break;
209 }
210 case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN: {
211 ret = OnEventTouchPadSwipeBegin(event);
212 break;
213 }
214 case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE: {
215 ret = OnEventTouchPadSwipeUpdate(event);
216 break;
217 }
218 case LIBINPUT_EVENT_GESTURE_SWIPE_END: {
219 ret = OnEventTouchPadSwipeEnd(event);
220 break;
221 }
222 case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
223 case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
224 case LIBINPUT_EVENT_GESTURE_PINCH_END:
225 OnEventTouchPadPinchGesture(event);
226 break;
227 default: {
228 MMI_HILOGW("Touch pad action is not found");
229 return nullptr;
230 }
231 }
232
233 if (ret != RET_OK) {
234 return nullptr;
235 }
236
237 pointerEvent_->UpdateId();
238 StartLogTraceId(pointerEvent_->GetId(), pointerEvent_->GetEventType(), pointerEvent_->GetPointerAction());
239 MMI_HILOGD("Pointer event dispatcher of server:");
240 EventLogHelper::PrintEventData(pointerEvent_, pointerEvent_->GetPointerAction(),
241 pointerEvent_->GetPointerIds().size(), MMI_LOG_FREEZE);
242 auto device = INPUT_DEV_MGR->GetInputDevice(pointerEvent_->GetDeviceId());
243 CHKPP(device);
244 if (pointerEvent_->GetPointerAction() != PointerEvent::POINTER_ACTION_MOVE &&
245 pointerEvent_->GetPointerAction() != PointerEvent::POINTER_ACTION_SWIPE_UPDATE) {
246 aggregator_.Record(MMI_LOG_FREEZE, device->GetName() + ", TW: " +
247 std::to_string(pointerEvent_->GetTargetWindowId()), std::to_string(pointerEvent_->GetId()));
248 }
249
250 return pointerEvent_;
251 }
252
GetTouchPadToolType(struct libinput_event_touch * touchpad,struct libinput_device * device)253 int32_t TouchPadTransformProcessor::GetTouchPadToolType(
254 struct libinput_event_touch *touchpad, struct libinput_device *device)
255 {
256 int32_t toolType = libinput_event_touchpad_get_tool_type(touchpad);
257 switch (toolType) {
258 case MT_TOOL_NONE: {
259 return GetTouchPadToolType(device);
260 }
261 case MT_TOOL_FINGER: {
262 return PointerEvent::TOOL_TYPE_FINGER;
263 }
264 case MT_TOOL_PEN: {
265 return PointerEvent::TOOL_TYPE_PEN;
266 }
267 case MT_TOOL_PALM: {
268 MMI_HILOGD("toolType is MT_TOOL_PALM");
269 return PointerEvent::TOOL_TYPE_PALM;
270 }
271 default : {
272 MMI_HILOGW("Unknown tool type, identified as finger, toolType:%{public}d", toolType);
273 return PointerEvent::TOOL_TYPE_FINGER;
274 }
275 }
276 }
277
GetTouchPadToolType(struct libinput_device * device)278 int32_t TouchPadTransformProcessor::GetTouchPadToolType(struct libinput_device *device)
279 {
280 for (const auto &item : vecToolType_) {
281 if (libinput_device_touchpad_btn_tool_type_down(device, item.first) == BTN_DOWN) {
282 return item.second;
283 }
284 }
285 MMI_HILOGD("Unknown Btn tool type, identified as finger");
286 return PointerEvent::TOOL_TYPE_FINGER;
287 }
288
SetTouchPadSwipeData(struct libinput_event * event,int32_t action)289 int32_t TouchPadTransformProcessor::SetTouchPadSwipeData(struct libinput_event *event, int32_t action)
290 {
291 CALL_DEBUG_ENTER;
292
293 bool tpSwipeSwitch = true;
294 GetTouchpadSwipeSwitch(tpSwipeSwitch);
295
296 if (!tpSwipeSwitch) {
297 MMI_HILOGD("Touchpad swipe switch is false");
298 return RET_ERR;
299 }
300
301 CHKPR(event, RET_ERR);
302 struct libinput_event_gesture *gesture = libinput_event_get_gesture_event(event);
303 CHKPR(gesture, RET_ERR);
304
305 int64_t time = static_cast<int64_t>(libinput_event_gesture_get_time(gesture));
306 pointerEvent_->SetActionTime(GetSysClockTime());
307 pointerEvent_->SetActionStartTime(time);
308 pointerEvent_->SetPointerAction(action);
309 pointerEvent_->SetDeviceId(deviceId_);
310
311 int32_t fingerCount = libinput_event_gesture_get_finger_count(gesture);
312 if (fingerCount < 0 || fingerCount > FINGER_COUNT_MAX) {
313 MMI_HILOGE("Finger count is invalid");
314 return RET_ERR;
315 }
316 if (fingerCount == FINGER_TAP_THREE) {
317 GetTouchpadThreeFingersTapSwitch(tpSwipeSwitch);
318 if (!tpSwipeSwitch) {
319 return RET_OK;
320 }
321 }
322 pointerEvent_->SetFingerCount(fingerCount);
323
324 if (fingerCount == 0) {
325 MMI_HILOGD("There is no finger in swipe action:%{public}d", action);
326 return RET_ERR;
327 }
328
329 AddItemForEventWhileSetSwipeData(time, gesture, fingerCount);
330
331 if (action == PointerEvent::POINTER_ACTION_SWIPE_BEGIN) {
332 MMI_HILOGE("Start report for POINTER_ACTION_SWIPE_BEGIN");
333 swipeHistory_.clear();
334 DfxHisysevent::StatisticTouchpadGesture(pointerEvent_);
335 }
336
337 return RET_OK;
338 }
339
AddItemForEventWhileSetSwipeData(int64_t time,libinput_event_gesture * gesture,int32_t fingerCount)340 int32_t TouchPadTransformProcessor::AddItemForEventWhileSetSwipeData(int64_t time, libinput_event_gesture *gesture,
341 int32_t fingerCount)
342 {
343 if (fingerCount == 0 || fingerCount > FINGER_COUNT_MAX) {
344 MMI_HILOGD("There are wrong finger counts in swipe action");
345 return RET_ERR;
346 }
347 Coords avgCoord {0, 0};
348 std::vector<Coords> fingerCoords(FINGER_COUNT_MAX, avgCoord);
349 int32_t action = pointerEvent_->GetPointerAction();
350 for (int32_t i = 0; i < fingerCount; ++i) {
351 fingerCoords[i].x = libinput_event_gesture_get_device_coords_x(gesture, i);
352 fingerCoords[i].y = libinput_event_gesture_get_device_coords_y(gesture, i);
353 }
354 if (action == PointerEvent::POINTER_ACTION_SWIPE_UPDATE) {
355 SmoothMultifingerSwipeData(fingerCoords, fingerCount);
356 }
357 for (int32_t i = 0; i < fingerCount; ++i) {
358 avgCoord += fingerCoords[i];
359 }
360 avgCoord /= fingerCount;
361 PointerEvent::PointerItem pointerItem;
362 pointerEvent_->GetPointerItem(DEFAULT_POINTER_ID, pointerItem);
363 pointerItem.SetPressed(MouseState->IsLeftBtnPressed());
364 pointerItem.SetDownTime(time);
365 pointerItem.SetDisplayX(avgCoord.x);
366 pointerItem.SetDisplayY(avgCoord.y);
367 pointerItem.SetDeviceId(deviceId_);
368 pointerItem.SetPointerId(DEFAULT_POINTER_ID);
369 pointerEvent_->SetPointerId(DEFAULT_POINTER_ID);
370 RemoveSurplusPointerItem();
371 pointerEvent_->UpdatePointerItem(DEFAULT_POINTER_ID, pointerItem);
372 pointerEvent_->SetSourceType(PointerEvent::SOURCE_TYPE_TOUCHPAD);
373 if ((pointerEvent_->GetPointerAction() == PointerEvent::POINTER_ACTION_SWIPE_BEGIN ||
374 pointerEvent_->GetPointerAction() == PointerEvent::POINTER_ACTION_SWIPE_UPDATE ||
375 pointerEvent_->GetPointerAction() == PointerEvent::POINTER_ACTION_SWIPE_END) &&
376 (pointerEvent_->GetTargetWindowId() > 0)) {
377 pointerEvent_->SetTargetWindowId(-1);
378 pointerEvent_->SetAgentWindowId(-1);
379 pointerItem.SetTargetWindowId(-1);
380 }
381 return RET_OK;
382 }
383
SmoothMultifingerSwipeData(std::vector<Coords> & fingerCoords,const int32_t fingerCount)384 void TouchPadTransformProcessor::SmoothMultifingerSwipeData(std::vector<Coords>& fingerCoords,
385 const int32_t fingerCount)
386 {
387 bool isMissing = false;
388 Coords coordDelta {0, 0};
389 int32_t historyFingerCount = 0;
390 for (int32_t i = 0; i < fingerCount; ++i) {
391 if (static_cast<int32_t>(swipeHistory_.size()) <= i) {
392 swipeHistory_.emplace_back(std::deque<Coords>());
393 }
394 if (fingerCoords[i].x == 0 && fingerCoords[i].y == 0) {
395 isMissing = true;
396 continue;
397 }
398 swipeHistory_[i].push_back(fingerCoords[i]);
399 if (static_cast<int32_t>(swipeHistory_[i].size()) > fingerCount) {
400 swipeHistory_[i].pop_front();
401 }
402 }
403 if (!isMissing) {
404 return;
405 }
406 for (int32_t i = 0; i < fingerCount; ++i) {
407 int32_t historySize = static_cast<int32_t>(swipeHistory_[i].size()) - 1;
408 if (historySize > 0) {
409 coordDelta += swipeHistory_[i][historySize] - swipeHistory_[i][0];
410 historyFingerCount += historySize;
411 }
412 }
413 if (historyFingerCount > 0) {
414 coordDelta /= historyFingerCount;
415 }
416 for (int32_t i = 0; i < fingerCount; ++i) {
417 if (fingerCoords[i].x == 0 && fingerCoords[i].y == 0) {
418 fingerCoords[i] = swipeHistory_[i].back() + coordDelta;
419 swipeHistory_[i].push_back(fingerCoords[i]);
420 }
421 if (static_cast<int32_t>(swipeHistory_[i].size()) > fingerCount) {
422 swipeHistory_[i].pop_front();
423 }
424 }
425 }
426
OnEventTouchPadSwipeBegin(struct libinput_event * event)427 int32_t TouchPadTransformProcessor::OnEventTouchPadSwipeBegin(struct libinput_event *event)
428 {
429 CALL_DEBUG_ENTER;
430 return SetTouchPadSwipeData(event, PointerEvent::POINTER_ACTION_SWIPE_BEGIN);
431 }
432
OnEventTouchPadSwipeUpdate(struct libinput_event * event)433 int32_t TouchPadTransformProcessor::OnEventTouchPadSwipeUpdate(struct libinput_event *event)
434 {
435 CALL_DEBUG_ENTER;
436 return SetTouchPadSwipeData(event, PointerEvent::POINTER_ACTION_SWIPE_UPDATE);
437 }
438
OnEventTouchPadSwipeEnd(struct libinput_event * event)439 int32_t TouchPadTransformProcessor::OnEventTouchPadSwipeEnd(struct libinput_event *event)
440 {
441 CALL_DEBUG_ENTER;
442 return SetTouchPadSwipeData(event, PointerEvent::POINTER_ACTION_SWIPE_END);
443 }
444
SetTouchPadMultiTapData()445 void TouchPadTransformProcessor::SetTouchPadMultiTapData()
446 {
447 pointerEvent_->SetSourceType(PointerEvent::SOURCE_TYPE_TOUCHPAD);
448 pointerEvent_->SetPointerAction(PointerEvent::POINTER_ACTION_TRIPTAP);
449 auto state = MULTI_FINGERTAP_HDR->GetMultiFingersState();
450 pointerEvent_->SetFingerCount(static_cast<int32_t>(state));
451 }
452
SetPinchPointerItem(int64_t time)453 void TouchPadTransformProcessor::SetPinchPointerItem(int64_t time)
454 {
455 PointerEvent::PointerItem pointerItem;
456 pointerItem.SetDownTime(time);
457 pointerItem.SetPressed(MouseState->IsLeftBtnPressed());
458 pointerItem.SetDeviceId(deviceId_);
459 pointerItem.SetPointerId(DEFAULT_POINTER_ID);
460 pointerItem.SetWindowX(0);
461 pointerItem.SetWindowY(0);
462 auto mouseInfo = WIN_MGR->GetMouseInfo();
463 pointerItem.SetDisplayX(mouseInfo.physicalX);
464 pointerItem.SetDisplayY(mouseInfo.physicalY);
465 pointerItem.SetToolType(PointerEvent::TOOL_TYPE_TOUCHPAD);
466 RemoveSurplusPointerItem();
467 pointerEvent_->UpdatePointerItem(DEFAULT_POINTER_ID, pointerItem);
468 }
469
ProcessTouchPadPinchDataEvent(int32_t fingerCount,int32_t action,double scale,double angle)470 void TouchPadTransformProcessor::ProcessTouchPadPinchDataEvent
471 (int32_t fingerCount, int32_t action, double scale, double angle)
472 {
473 CALL_DEBUG_ENTER;
474 pointerEvent_->ClearButtonPressed();
475 std::vector<int32_t> pressedButtons;
476 MouseState->GetPressedButtons(pressedButtons);
477 for (const auto &item : pressedButtons) {
478 pointerEvent_->SetButtonPressed(item);
479 }
480
481 pointerEvent_->SetFingerCount(fingerCount);
482 pointerEvent_->SetDeviceId(deviceId_);
483 auto mouseInfo = WIN_MGR->GetMouseInfo();
484 pointerEvent_->SetTargetDisplayId(mouseInfo.displayId);
485 pointerEvent_->SetTargetWindowId(-1);
486 pointerEvent_->SetPointerId(DEFAULT_POINTER_ID);
487 pointerEvent_->SetPointerAction(action);
488 if (!MMI_EQ(scale, 0.0)) {
489 pointerEvent_->SetAxisValue(PointerEvent::AXIS_TYPE_PINCH, scale);
490 }
491 if (!MMI_EQ(angle, 0.0)) {
492 rotateAngle_ += angle;
493 MMI_HILOGD("The rotate angle is %{public}f", rotateAngle_);
494 pointerEvent_->SetAxisValue(PointerEvent::AXIS_TYPE_ROTATE, rotateAngle_);
495 }
496
497 if (fingerCount == TP_SYSTEM_PINCH_FINGER_CNT) {
498 pointerEvent_->SetSourceType(PointerEvent::SOURCE_TYPE_MOUSE);
499 pointerEvent_->SetAxisEventType(PointerEvent::AXIS_EVENT_TYPE_PINCH);
500 } else {
501 pointerEvent_->SetSourceType(PointerEvent::SOURCE_TYPE_TOUCHPAD);
502 }
503
504 if (pointerEvent_->GetFingerCount() == TP_SYSTEM_PINCH_FINGER_CNT) {
505 WIN_MGR->UpdateTargetPointer(pointerEvent_);
506 }
507
508 // only three or four finger pinch need to statistic
509 if (action == PointerEvent::POINTER_ACTION_AXIS_BEGIN && fingerCount > TP_SYSTEM_PINCH_FINGER_CNT) {
510 DfxHisysevent::StatisticTouchpadGesture(pointerEvent_);
511 }
512 }
513
OnEventTouchPadPinchGesture(libinput_event * event)514 int32_t TouchPadTransformProcessor::OnEventTouchPadPinchGesture(libinput_event *event)
515 {
516 CALL_DEBUG_ENTER;
517 CHKPR(event, RET_ERR);
518 auto type = libinput_event_get_type(event);
519 auto gesture = libinput_event_get_gesture_event(event);
520 CHKPR(gesture, RET_ERR);
521 double scale = libinput_event_gesture_get_scale(gesture);
522 double angle = libinput_event_gesture_get_angle_delta(gesture);
523 auto action = GetPinchGestureType(type, angle);
524 MMI_HILOGD("The action is %{public}d, scale is %{public}f, angle is %{public}f", action, scale, angle);
525 int32_t fingerCount = libinput_event_gesture_get_finger_count(gesture);
526 MMI_HILOGD("The finger count is %{public}d", fingerCount);
527 if (fingerCount <= 0 || fingerCount > FINGER_COUNT_MAX) {
528 MMI_HILOGE("Finger count is invalid");
529 return RET_ERR;
530 }
531 bool tpPinchSwitch = false;
532 GetTouchpadPinchSwitch(tpPinchSwitch);
533 if (!tpPinchSwitch && fingerCount == TP_SYSTEM_PINCH_FINGER_CNT &&
534 (action == PointerEvent::POINTER_ACTION_AXIS_BEGIN ||
535 action == PointerEvent::POINTER_ACTION_AXIS_UPDATE ||
536 action == PointerEvent::POINTER_ACTION_AXIS_END)) {
537 MMI_HILOGD("Touchpad pinch switch is false");
538 return RET_ERR;
539 }
540 bool tpRotateSwitch = false;
541 GetTouchpadPinchSwitch(tpRotateSwitch);
542 if (!tpRotateSwitch && fingerCount == TP_SYSTEM_PINCH_FINGER_CNT &&
543 (action == PointerEvent::POINTER_ACTION_ROTATE_BEGIN ||
544 action == PointerEvent::POINTER_ACTION_ROTATE_UPDATE ||
545 action == PointerEvent::POINTER_ACTION_ROTATE_END)) {
546 MMI_HILOGD("Touchpad rotate switch is false");
547 return RET_ERR;
548 }
549 int64_t time = static_cast<int64_t>(libinput_event_gesture_get_time(gesture));
550 pointerEvent_->SetActionTime(GetSysClockTime());
551 pointerEvent_->SetActionStartTime(time);
552 SetPinchPointerItem(time);
553 ProcessTouchPadPinchDataEvent(fingerCount, action, scale, angle);
554 return RET_OK;
555 }
556
GetPinchGestureType(int32_t type,double angle)557 int32_t TouchPadTransformProcessor::GetPinchGestureType(int32_t type, double angle)
558 {
559 switch (type) {
560 case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN: {
561 rotateAngle_ = 0.0;
562 isRotateGesture_ = MMI_EQ(angle, 0.0) ? false : true;
563 return MMI_EQ(angle, 0.0) ? PointerEvent::POINTER_ACTION_AXIS_BEGIN :
564 PointerEvent::POINTER_ACTION_ROTATE_BEGIN;
565 }
566 case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE: {
567 return isRotateGesture_ ? PointerEvent::POINTER_ACTION_ROTATE_UPDATE :
568 PointerEvent::POINTER_ACTION_AXIS_UPDATE;
569 }
570 case LIBINPUT_EVENT_GESTURE_PINCH_END: {
571 return isRotateGesture_ ? PointerEvent::POINTER_ACTION_ROTATE_END :
572 PointerEvent::POINTER_ACTION_AXIS_END;
573 }
574 default:
575 break;
576 }
577 MMI_HILOGE("Check pinch gesture failed. type:%{public}d", type);
578 return RET_ERR;
579 }
580
InitToolType()581 void TouchPadTransformProcessor::InitToolType()
582 {
583 vecToolType_.push_back(std::make_pair(BTN_TOOL_PEN, PointerEvent::TOOL_TYPE_PEN));
584 vecToolType_.push_back(std::make_pair(BTN_TOOL_RUBBER, PointerEvent::TOOL_TYPE_RUBBER));
585 vecToolType_.push_back(std::make_pair(BTN_TOOL_BRUSH, PointerEvent::TOOL_TYPE_BRUSH));
586 vecToolType_.push_back(std::make_pair(BTN_TOOL_PENCIL, PointerEvent::TOOL_TYPE_PENCIL));
587 vecToolType_.push_back(std::make_pair(BTN_TOOL_AIRBRUSH, PointerEvent::TOOL_TYPE_AIRBRUSH));
588 vecToolType_.push_back(std::make_pair(BTN_TOOL_FINGER, PointerEvent::TOOL_TYPE_FINGER));
589 vecToolType_.push_back(std::make_pair(BTN_TOOL_MOUSE, PointerEvent::TOOL_TYPE_MOUSE));
590 vecToolType_.push_back(std::make_pair(BTN_TOOL_LENS, PointerEvent::TOOL_TYPE_LENS));
591 }
592
SetTouchpadSwipeSwitch(bool switchFlag)593 int32_t TouchPadTransformProcessor::SetTouchpadSwipeSwitch(bool switchFlag)
594 {
595 std::string name = "touchpadSwipe";
596 if (PutConfigDataToDatabase(name, switchFlag) != RET_OK) {
597 MMI_HILOGE("Failed to set touchpad swpie switch flag to mem");
598 return RET_ERR;
599 }
600
601 DfxHisysevent::ReportTouchpadSettingState(DfxHisysevent::TOUCHPAD_SETTING_CODE::TOUCHPAD_SWIPE_SETTING,
602 switchFlag);
603 return RET_OK;
604 }
605
GetTouchpadSwipeSwitch(bool & switchFlag)606 void TouchPadTransformProcessor::GetTouchpadSwipeSwitch(bool &switchFlag)
607 {
608 std::string name = "touchpadSwipe";
609 GetConfigDataFromDatabase(name, switchFlag);
610 }
611
SetTouchpadPinchSwitch(bool switchFlag)612 int32_t TouchPadTransformProcessor::SetTouchpadPinchSwitch(bool switchFlag)
613 {
614 std::string name = "touchpadPinch";
615 if (PutConfigDataToDatabase(name, switchFlag) != RET_OK) {
616 MMI_HILOGE("Failed to set touchpad pinch switch flag to mem");
617 return RET_ERR;
618 }
619
620 DfxHisysevent::ReportTouchpadSettingState(DfxHisysevent::TOUCHPAD_SETTING_CODE::TOUCHPAD_PINCH_SETTING,
621 switchFlag);
622 return RET_OK;
623 }
624
GetTouchpadPinchSwitch(bool & switchFlag)625 void TouchPadTransformProcessor::GetTouchpadPinchSwitch(bool &switchFlag)
626 {
627 std::string name = "touchpadPinch";
628 GetConfigDataFromDatabase(name, switchFlag);
629 }
630
SetTouchpadRotateSwitch(bool rotateSwitch)631 int32_t TouchPadTransformProcessor::SetTouchpadRotateSwitch(bool rotateSwitch)
632 {
633 std::string name = "touchpadRotate";
634 if (PutConfigDataToDatabase(name, rotateSwitch) != RET_OK) {
635 MMI_HILOGE("PutConfigDataToDatabase failed");
636 return RET_ERR;
637 }
638
639 DfxHisysevent::ReportTouchpadSettingState(DfxHisysevent::TOUCHPAD_SETTING_CODE::TOUCHPAD_ROTATE_SETTING,
640 rotateSwitch);
641 return RET_OK;
642 }
643
GetTouchpadRotateSwitch(bool & rotateSwitch)644 void TouchPadTransformProcessor::GetTouchpadRotateSwitch(bool &rotateSwitch)
645 {
646 std::string name = "touchpadRotate";
647 GetConfigDataFromDatabase(name, rotateSwitch);
648 }
649
SetTouchpadDoubleTapAndDragState(bool switchFlag)650 int32_t TouchPadTransformProcessor::SetTouchpadDoubleTapAndDragState(bool switchFlag)
651 {
652 std::string name = "touchpadDoubleTapAndDrag";
653 if (PutConfigDataToDatabase(name, switchFlag) != RET_OK) {
654 MMI_HILOGE("PutConfigDataToDatabase failed");
655 return RET_ERR;
656 }
657
658 auto originDevice = INPUT_DEV_MGR->GetTouchPadDeviceOrigin();
659 if (originDevice == nullptr) {
660 MMI_HILOGW("Not touchpad device");
661 return RET_OK;
662 }
663
664 auto state = LIBINPUT_CONFIG_DRAG_DISABLED;
665 if (switchFlag) {
666 state = LIBINPUT_CONFIG_DRAG_ENABLED;
667 }
668 auto ret = libinput_device_config_tap_set_drag_enabled(originDevice, state);
669 if (ret != LIBINPUT_CONFIG_STATUS_SUCCESS) {
670 MMI_HILOGE("Set drag failed");
671 return RET_ERR;
672 }
673 MMI_HILOGI("Touchpad set double tap and drag state successfully, state:%{public}d", state);
674
675 DfxHisysevent::ReportTouchpadSettingState(DfxHisysevent::TOUCHPAD_SETTING_CODE::TOUCHPAD_DOUBLE_TAP_DRAG_SETTING,
676 switchFlag);
677 return RET_OK;
678 }
679
GetTouchpadDoubleTapAndDragState(bool & switchFlag)680 void TouchPadTransformProcessor::GetTouchpadDoubleTapAndDragState(bool &switchFlag)
681 {
682 std::string name = "touchpadDoubleTapAndDrag";
683 GetConfigDataFromDatabase(name, switchFlag);
684 }
685
SetTouchpadScrollRows(int32_t rows)686 int32_t TouchPadTransformProcessor::SetTouchpadScrollRows(int32_t rows)
687 {
688 CALL_DEBUG_ENTER;
689 int32_t newRows = std::clamp(rows, MIN_ROWS, MAX_ROWS);
690 std::string name = "touchpadScrollRows";
691 int32_t ret = PREFERENCES_MGR->SetIntValue(name, TOUCHPAD_FILE_NAME, newRows);
692 MMI_HILOGD("Set touchpad scroll rows successfully, rows:%{public}d", newRows);
693 return ret;
694 }
695
GetTouchpadScrollRows()696 int32_t TouchPadTransformProcessor::GetTouchpadScrollRows()
697 {
698 CALL_DEBUG_ENTER;
699 std::string name = "touchpadScrollRows";
700 int32_t rows = PREFERENCES_MGR->GetIntValue(name, DEFAULT_ROWS);
701 MMI_HILOGD("Get touchpad scroll rows successfully, rows:%{public}d", rows);
702 return rows;
703 }
704
PutConfigDataToDatabase(std::string & key,bool value)705 int32_t TouchPadTransformProcessor::PutConfigDataToDatabase(std::string &key, bool value)
706 {
707 return PREFERENCES_MGR->SetBoolValue(key, TOUCHPAD_FILE_NAME, value);
708 }
709
GetConfigDataFromDatabase(std::string & key,bool & value)710 void TouchPadTransformProcessor::GetConfigDataFromDatabase(std::string &key, bool &value)
711 {
712 value = PREFERENCES_MGR->GetBoolValue(key, true);
713 }
714
GetPointerEvent()715 std::shared_ptr<PointerEvent> TouchPadTransformProcessor::GetPointerEvent()
716 {
717 return pointerEvent_;
718 }
719
RemoveSurplusPointerItem()720 void TouchPadTransformProcessor::RemoveSurplusPointerItem()
721 {
722 std::list<PointerEvent::PointerItem> pointerItems = pointerEvent_->GetAllPointerItems();
723 if (pointerItems.size() >= MAX_N_POINTER_ITEMS) {
724 MMI_HILOGW("Exceed maximum allowed number of pointer items");
725 pointerEvent_->RemovePointerItem(pointerItems.begin()->GetPointerId());
726 }
727 }
728
MultiFingersTapHandler()729 MultiFingersTapHandler::MultiFingersTapHandler() {}
730
~MultiFingersTapHandler()731 MultiFingersTapHandler::~MultiFingersTapHandler() {}
732
HandleMulFingersTap(struct libinput_event_touch * event,int32_t type)733 int32_t MultiFingersTapHandler::HandleMulFingersTap(struct libinput_event_touch *event, int32_t type)
734 {
735 CALL_DEBUG_ENTER;
736 CHKPR(event, RET_ERR);
737 // if is not multifigners tap, return.
738 if (tapTrends_ == TapTrends::NO_MULTAP) {
739 return RET_OK;
740 }
741 // calculator delta time, if is larger than threshold, return.
742 auto time = libinput_event_touchpad_get_time_usec(event);
743 uint64_t deltaTime = 0;
744 if (tapTrends_ != TapTrends::BEGIN) {
745 deltaTime = time - lastTime;
746 } else {
747 beginTime = time;
748 }
749 lastTime = time;
750 if ((deltaTime > perTimeThreshold) || ((lastTime - beginTime) > totalTimeThreshold)) {
751 MMI_HILOGD("Not multitap, single time interval or total time interval is out of range."
752 "single:%{public}" PRId64 ", total:%{public}" PRId64, deltaTime, (lastTime - beginTime));
753 SetMultiFingersTapHdrDefault();
754 return RET_OK;
755 }
756 if (type == LIBINPUT_EVENT_TOUCHPAD_DOWN) {
757 // if trends is up, is not multifigners tap, return.
758 if ((tapTrends_ == TapTrends::UPING) || !CanAddToPointerMaps(event)) {
759 MMI_HILOGD("The trends is up, is not a multifigners tap event");
760 SetMultiFingersTapHdrDefault();
761 return RET_OK;
762 } else {
763 downCnt++;
764 tapTrends_ = TapTrends::DOWNING;
765 }
766 } else if ((type == LIBINPUT_EVENT_TOUCHPAD_UP) && !CanUnsetPointerItem(event)) {
767 upCnt++;
768 tapTrends_ = TapTrends::UPING;
769 }
770
771 if ((upCnt == downCnt) && (upCnt >= FINGER_TAP_MIN) && (upCnt <= FINGER_COUNT_MAX)) {
772 multiFingersState_ = static_cast<MulFingersTap>(upCnt);
773 MMI_HILOGD("This is multifinger tap event, finger count:%{public}d", upCnt);
774 }
775 return RET_OK;
776 }
777
SetMultiFingersTapHdrDefault(bool isAllDefault)778 void MultiFingersTapHandler::SetMultiFingersTapHdrDefault(bool isAllDefault)
779 {
780 downCnt = 0;
781 upCnt = 0;
782 tapTrends_ = TapTrends::BEGIN;
783 beginTime = 0;
784 lastTime = 0;
785 if (isAllDefault) {
786 multiFingersState_ = MulFingersTap::NO_TAP;
787 }
788 pointerMaps.clear();
789 }
790
ClearPointerItems(std::shared_ptr<PointerEvent> pointer)791 bool MultiFingersTapHandler::ClearPointerItems(std::shared_ptr<PointerEvent> pointer)
792 {
793 CHKPR(pointer, ERROR_NULL_POINTER);
794 auto ids_ = pointer->GetPointerIds();
795 for (const auto &id : ids_) {
796 pointer->RemovePointerItem(id);
797 }
798 return true;
799 }
800
GetMultiFingersState()801 MulFingersTap MultiFingersTapHandler::GetMultiFingersState()
802 {
803 return multiFingersState_;
804 }
805
CanAddToPointerMaps(struct libinput_event_touch * event)806 bool MultiFingersTapHandler::CanAddToPointerMaps(struct libinput_event_touch *event)
807 {
808 CHKPR(event, RET_ERR);
809 int32_t seatSlot = libinput_event_touchpad_get_seat_slot(event);
810 if (pointerMaps.find(seatSlot) != pointerMaps.end()) {
811 return false;
812 }
813 auto currentX = libinput_event_touchpad_get_x(event);
814 auto currentY = libinput_event_touchpad_get_y(event);
815 pointerMaps[seatSlot] = {currentX, currentY};
816 return true;
817 }
818
CanUnsetPointerItem(struct libinput_event_touch * event)819 bool MultiFingersTapHandler::CanUnsetPointerItem(struct libinput_event_touch *event)
820 {
821 CHKPR(event, RET_ERR);
822 int32_t seatSlot = libinput_event_touchpad_get_seat_slot(event);
823 if (pointerMaps.find(seatSlot) != pointerMaps.end()) {
824 return false;
825 } else {
826 pointerMaps[seatSlot] = {-1.0F, -1.0F};
827 return true;
828 }
829 }
830
SetTouchpadThreeFingersTapSwitch(bool switchFlag)831 int32_t TouchPadTransformProcessor::SetTouchpadThreeFingersTapSwitch(bool switchFlag)
832 {
833 if (PutConfigDataToDatabase(g_threeFingerTapKey, switchFlag) != RET_OK) {
834 MMI_HILOGE("Failed to set touchpad three fingers switch flag to mem");
835 return RET_ERR;
836 }
837 DfxHisysevent::ReportTouchpadSettingState(DfxHisysevent::TOUCHPAD_SETTING_CODE::TOUCHPAD_PINCH_SETTING,
838 switchFlag);
839 return RET_OK;
840 }
841
GetTouchpadThreeFingersTapSwitch(bool & switchFlag)842 int32_t TouchPadTransformProcessor::GetTouchpadThreeFingersTapSwitch(bool &switchFlag)
843 {
844 GetConfigDataFromDatabase(g_threeFingerTapKey, switchFlag);
845 return RET_OK;
846 }
847 } // namespace MMI
848 } // namespace OHOS
849