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