• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 "libinput_adapter.h"
17 
18 #include <regex>
19 #ifdef OHOS_BUILD_ENABLE_VKEYBOARD
20 #include <common_event_manager.h>
21 #endif // OHOS_BUILD_ENABLE_VKEYBOARD
22 
23 #include "param_wrapper.h"
24 #include "property_reader.h"
25 #include "input_device_manager.h"
26 #include "input_windows_manager.h"
27 #include "key_event_normalize.h"
28 #ifdef OHOS_BUILD_ENABLE_VKEYBOARD
29 #include "key_event_value_transformation.h"
30 #include "timer_manager.h"
31 #include <shared_mutex>
32 #include "common_event_manager.h"
33 #include "common_event_support.h"
34 #endif // OHOS_BUILD_ENABLE_VKEYBOARD
35 #include "multimodal_input_plugin_manager.h"
36 
37 #undef MMI_LOG_DOMAIN
38 #define MMI_LOG_DOMAIN MMI_LOG_SERVER
39 #undef MMI_LOG_TAG
40 #define MMI_LOG_TAG "LibinputAdapter"
41 
42 namespace OHOS {
43 namespace MMI {
44 namespace {
45 constexpr int32_t WAIT_TIME_FOR_INPUT { 10 };
46 constexpr int32_t MAX_RETRY_COUNT { 5 };
47 constexpr int32_t MIN_RIGHT_BTN_AREA_PERCENT { 0 };
48 constexpr int32_t MAX_RIGHT_BTN_AREA_PERCENT { 100 };
49 constexpr int32_t INVALID_RIGHT_BTN_AREA { -1 };
50 #ifdef OHOS_BUILD_ENABLE_VKEYBOARD
51 constexpr uint32_t KEY_CAPSLOCK { 58 };
52 constexpr uint32_t LIBINPUT_KEY_VOLUME_DOWN { 114 };
53 constexpr uint32_t LIBINPUT_KEY_VOLUME_UP { 115 };
54 constexpr uint32_t LIBINPUT_KEY_POWER { 116 };
55 constexpr uint32_t LIBINPUT_KEY_FN { 240 };
56 constexpr float SCREEN_CAPTURE_WINDOW_ZORDER { 8000.0 };
57 constexpr double VTP_LEFT_BUTTON_DELTA_X { 0.0 };
58 constexpr double VTP_LEFT_BUTTON_DELTA_Y { -1.0 };
59 constexpr uint32_t VKEY_PINCH_FIRST_FINGER_ID { 0 };
60 constexpr uint32_t VKEY_PINCH_SECOND_FINGER_ID { 1 };
61 constexpr float VKEY_RAW_COORDINATE_RATIO { 8.0 };
62 constexpr uint32_t VKEY_PINCH_CURSOR_FAKE_DX { 1 };
63 constexpr uint32_t WINDOW_NAME_TYPE_SCHREENSHOT { 1 };
64 enum class VKeyboardTouchEventType : int32_t {
65     TOUCH_DOWN = 0,
66     TOUCH_UP = 1,
67     TOUCH_MOVE = 2,
68     TOUCH_FRAME = 3,
69 };
70 #define SCREEN_RECORD_WINDOW_WIDTH 400
71 #define SCREEN_RECORD_WINDOW_HEIGHT 200
72 #else // OHOS_BUILD_ENABLE_VKEYBOARD
73 constexpr uint32_t KEY_CAPSLOCK { 58 };
74 #endif // OHOS_BUILD_ENABLE_VKEYBOARD
75 
HiLogFunc(struct libinput * input,libinput_log_priority priority,const char * fmt,va_list args)76 void HiLogFunc(struct libinput* input, libinput_log_priority priority, const char* fmt, va_list args)
77 {
78     CHKPV(input);
79     CHKPV(fmt);
80     char buffer[256] = {};
81     if (vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, fmt, args) == -1) {
82         MMI_HILOGE("Call vsnprintf_s failed");
83         va_end(args);
84         return;
85     }
86     if (strstr(buffer, "LOG_LEVEL_I") != nullptr) {
87         MMI_HILOGI("PrintLog_Info:%{public}s", buffer);
88     } else if (strstr(buffer, "LOG_LEVEL_D") != nullptr) {
89         MMI_HILOGD("PrintLog_Info:%{public}s", buffer);
90     } else if (strstr(buffer, "LOG_LEVEL_E") != nullptr) {
91         MMI_HILOGE("PrintLog_Info:%{public}s", buffer);
92     } else {
93         MMI_HILOGD("PrintLog_Info:%{public}s", buffer);
94     }
95     va_end(args);
96 }
97 } // namespace
98 
DeviceLedUpdate(struct libinput_device * device,int32_t funcKey,bool enable)99 int32_t LibinputAdapter::DeviceLedUpdate(struct libinput_device *device, int32_t funcKey, bool enable)
100 {
101     CHKPR(device, RET_ERR);
102     return libinput_set_led_state(device, funcKey, enable);
103 }
104 
InitRightButtonAreaConfig()105 void LibinputAdapter::InitRightButtonAreaConfig()
106 {
107     CHKPV(input_);
108 
109     int32_t height_percent = OHOS::system::GetIntParameter("const.multimodalinput.rightclick_y_percentage",
110                                                            INVALID_RIGHT_BTN_AREA);
111     if ((height_percent <= MIN_RIGHT_BTN_AREA_PERCENT) || (height_percent > MAX_RIGHT_BTN_AREA_PERCENT)) {
112         MMI_HILOGE("Right button area height percent param is invalid");
113         return;
114     }
115 
116     int32_t width_percent = OHOS::system::GetIntParameter("const.multimodalinput.rightclick_x_percentage",
117                                                           INVALID_RIGHT_BTN_AREA);
118     if ((width_percent <= MIN_RIGHT_BTN_AREA_PERCENT) || (width_percent > MAX_RIGHT_BTN_AREA_PERCENT)) {
119         MMI_HILOGE("Right button area width percent param is invalid");
120         return;
121     }
122 
123     auto status = libinput_config_rightbutton_area(input_, height_percent, width_percent);
124     if (status != LIBINPUT_CONFIG_STATUS_SUCCESS) {
125         MMI_HILOGE("Config the touchpad right button area failed");
126     }
127 }
128 
129 constexpr static libinput_interface LIBINPUT_INTERFACE = {
__anon7795070c0202()130     .open_restricted = [](const char *path, int32_t flags, void *user_data)->int32_t {
131         if (path == nullptr) {
132             MMI_HILOGWK("Input device path is nullptr");
133             return RET_ERR;
134         }
135         char realPath[PATH_MAX] = {};
136         if (realpath(path, realPath) == nullptr) {
137             std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME_FOR_INPUT));
138             MMI_HILOGWK("The error path is %{private}s", path);
139             return RET_ERR;
140         }
141         int32_t fd = 0;
142         for (int32_t i = 0; i < MAX_RETRY_COUNT; i++) {
143             fd = open(realPath, flags);
144             if (fd >= 0) {
145                 break;
146             }
147             std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME_FOR_INPUT));
148         }
149         int32_t errNo = errno;
150         std::regex re("(\\d+)");
151         std::string str_path(path);
152         std::smatch match;
153         int32_t id;
154         bool isPath = std::regex_search(str_path, match, re);
155         if (!isPath) {
156             id = -1;
157         } else {
158             id = std::stoi(match[0]);
159         }
160         MMI_HILOGWK("Libinput .open_restricted id:%{public}d, fd:%{public}d, errno:%{public}d", id, fd, errNo);
161         return fd < 0 ? RET_ERR : fd;
162     },
163     .close_restricted = [](int32_t fd, void *user_data)
__anon7795070c0302() 164     {
165         if (fd < 0) {
166             return;
167         }
168         MMI_HILOGI("Libinput .close_restricted fd:%{public}d", fd);
169         close(fd);
170     },
171 };
172 
173 #ifdef OHOS_BUILD_ENABLE_VKEYBOARD
174 class BootStatusReceiver : public EventFwk::CommonEventSubscriber {
175 public:
BootStatusReceiver(const OHOS::EventFwk::CommonEventSubscribeInfo & subscribeInfo)176     explicit BootStatusReceiver(const OHOS::EventFwk::CommonEventSubscribeInfo& subscribeInfo)
177         : OHOS::EventFwk::CommonEventSubscriber(subscribeInfo)
178     {
179     }
180 
181     virtual ~BootStatusReceiver() = default;
182 
OnReceiveEvent(const EventFwk::CommonEventData & eventData)183     void OnReceiveEvent(const EventFwk::CommonEventData &eventData)
184     {
185         LibinputAdapter::SetBootCompleted();
186         std::string action = eventData.GetWant().GetAction();
187         if (action.empty()) {
188             MMI_HILOGE("The action is empty");
189             return;
190         }
191         MMI_HILOGI("Received boot status:%{public}s", action.c_str());
192     }
193 };
194 
195 std::atomic_bool LibinputAdapter::isBootCompleted_ = false;
196 
SetBootCompleted()197 void LibinputAdapter::SetBootCompleted()
198 {
199     isBootCompleted_ = true;
200 }
201 
RegisterBootStatusReceiver()202 void LibinputAdapter::RegisterBootStatusReceiver()
203 {
204     if (hasInitSubscriber_) {
205         MMI_HILOGE("Current common event has subscribered");
206         return;
207     }
208     MMI_HILOGI("Subscribe Boot Events");
209     EventFwk::MatchingSkills matchingSkills;
210     matchingSkills.AddEvent(EventFwk::CommonEventSupport::COMMON_EVENT_BOOT_COMPLETED);
211     EventFwk::CommonEventSubscribeInfo commonEventSubscribeInfo(matchingSkills);
212     hasInitSubscriber_ = OHOS::EventFwk::CommonEventManager::SubscribeCommonEvent(
213         std::make_shared<BootStatusReceiver>(commonEventSubscribeInfo));
214 }
215 #endif // OHOS_BUILD_ENABLE_VKEYBOARD
216 
Init(FunInputEvent funInputEvent)217 bool LibinputAdapter::Init(FunInputEvent funInputEvent)
218 {
219     CALL_DEBUG_ENTER;
220     CHKPF(funInputEvent);
221 
222     auto callback = [funInputEvent](libinput_event *event, int64_t frameTime) {
223         funInputEvent(static_cast<void *>(event), frameTime);
224     };
225     auto manager = InputPluginManager::GetInstance();
226     if (manager != nullptr) {
227         manager->PluginAssignmentCallBack(callback, InputPluginStage::INPUT_BEFORE_LIBINPUT_ADAPTER_ON_EVENT);
228     }
229     funInputEvent_ = [manager, callback](void *event, int64_t frameTime) {
230         if (manager != nullptr) {
231             int32_t result = manager->HandleEvent(static_cast<libinput_event *>(event),
232                 frameTime,
233                 InputPluginStage::INPUT_BEFORE_LIBINPUT_ADAPTER_ON_EVENT);
234             if (result != RET_NOTDO) {
235                 return;
236             }
237         }
238         callback(static_cast<libinput_event *>(event), frameTime);
239     };
240 
241     input_ = libinput_path_create_context(&LIBINPUT_INTERFACE, nullptr);
242     CHKPF(input_);
243     libinput_log_set_handler(input_, &HiLogFunc);
244     fd_ = libinput_get_fd(input_);
245     if (fd_ < 0) {
246         libinput_unref(input_);
247         fd_ = -1;
248         MMI_HILOGE("The fd_ is less than 0");
249         return false;
250     }
251     InitRightButtonAreaConfig();
252     return hotplugDetector_.Init([this](std::string path) { OnDeviceAdded(std::move(path)); },
253         [this](std::string path) { OnDeviceRemoved(std::move(path)); });
254 }
255 
EventDispatch(int32_t fd)256 void LibinputAdapter::EventDispatch(int32_t fd)
257 {
258     CALL_DEBUG_ENTER;
259     if (fd == fd_) {
260         MMI_HILOGD("Start to libinput_dispatch");
261         if (libinput_dispatch(input_) != 0) {
262             MMI_HILOGE("Failed to dispatch libinput");
263             return;
264         }
265         OnEventHandler();
266         MMI_HILOGD("End to OnEventHandler");
267     } else if (fd == hotplugDetector_.GetFd()) {
268         hotplugDetector_.OnEvent();
269     } else {
270         MMI_HILOGE("EventDispatch() called with unknown fd:%{public}d", fd);
271     }
272 }
273 
Stop()274 void LibinputAdapter::Stop()
275 {
276     CALL_DEBUG_ENTER;
277     hotplugDetector_.Stop();
278     if (fd_ >= 0) {
279         close(fd_);
280         fd_ = -1;
281     }
282     if (input_ != nullptr) {
283         libinput_unref(input_);
284         input_ = nullptr;
285     }
286 }
287 
ProcessPendingEvents()288 void LibinputAdapter::ProcessPendingEvents()
289 {
290     OnEventHandler();
291 }
292 
InitVKeyboard(HandleTouchPoint handleTouchPoint,HardwareKeyEventDetected hardwareKeyEventDetected,GetKeyboardActivationState getKeyboardActivationState,IsFloatingKeyboard isFloatingKeyboard,IsVKeyboardShown isVKeyboardShown,GetLibinputEventForVKeyboard getLibinputEventForVKeyboard,GetLibinputEventForVTrackpad getLibinputEventForVTrackpad)293 void LibinputAdapter::InitVKeyboard(HandleTouchPoint handleTouchPoint,
294     HardwareKeyEventDetected hardwareKeyEventDetected,
295     GetKeyboardActivationState getKeyboardActivationState,
296     IsFloatingKeyboard isFloatingKeyboard,
297     IsVKeyboardShown isVKeyboardShown,
298     GetLibinputEventForVKeyboard getLibinputEventForVKeyboard,
299     GetLibinputEventForVTrackpad getLibinputEventForVTrackpad)
300 {
301     handleTouchPoint_ = handleTouchPoint;
302     hardwareKeyEventDetected_ = hardwareKeyEventDetected;
303     getKeyboardActivationState_ = getKeyboardActivationState;
304     isFloatingKeyboard_ = isFloatingKeyboard;
305     isVKeyboardShown_ = isVKeyboardShown;
306     getLibinputEventForVKeyboard_ = getLibinputEventForVKeyboard;
307     getLibinputEventForVTrackpad_ = getLibinputEventForVTrackpad;
308 
309     // init touch device Id.
310     deviceId = -1;
311 }
312 
313 #ifdef OHOS_BUILD_ENABLE_VKEYBOARD
DelayInjectKeyEventCallback()314 void LibinputAdapter::DelayInjectKeyEventCallback()
315 {
316     MMI_HILOGI("Delayed done for kc:%{private}d.", vkbDelayedKeyCode_);
317     CHKPV(vkbDelayedEvent_);
318     libinput_event_touch *touch = libinput_event_get_touch_event(vkbDelayedEvent_);
319     CHKPV(touch);
320     CHKPV(funInputEvent_);
321     int64_t frameTime = GetSysClockTime();
322     funInputEvent_(vkbDelayedKeyEvent_, frameTime);
323     free(vkbDelayedKeyEvent_);
324     vkbDelayedKeyEvent_ = nullptr;
325     libinput_event_destroy(vkbDelayedEvent_);
326     vkbDelayedEvent_ = nullptr;
327 }
328 
329 // return true if timer has started successfully.
CreateVKeyboardDelayTimer(libinput_event * event,int32_t delayMs,libinput_event * keyEvent)330 bool LibinputAdapter::CreateVKeyboardDelayTimer(libinput_event *event, int32_t delayMs, libinput_event *keyEvent)
331 {
332     if (vkbDelayedEvent_ != nullptr) {
333         MMI_HILOGI("A delayed event is pending, skip delay msg, Delay=%{public}d", delayMs);
334         return false;
335     }
336 
337     vkbDelayedEvent_ = event;
338     vkbDelayedKeyEvent_ = keyEvent;
339     MMI_HILOGD("Create the delayed event Delay=%{public}d", delayMs);
340     return true;
341 }
342 
StartVKeyboardDelayTimer(int32_t delayMs)343 void LibinputAdapter::StartVKeyboardDelayTimer(int32_t delayMs)
344 {
345     TimerMgr->AddTimer(delayMs, 1, [this]() {
346         DelayInjectKeyEventCallback();
347     }, "LibinputAdapter-StartVKeyboardDelayTimer");
348 }
349 
GetIsCaptureMode()350 bool LibinputAdapter::GetIsCaptureMode()
351 {
352     bool isCaptureMode = false;
353     bool isFloating = (isFloatingKeyboard_ != nullptr) ? isFloatingKeyboard_() : false;
354 
355     InputWindowsManager* inputWindowsManager = static_cast<InputWindowsManager *>(WIN_MGR.get());
356     if (inputWindowsManager == nullptr) {
357         return false;
358     }
359 
360     isCaptureMode = inputWindowsManager->IsCaptureMode() && isFloating;
361     MMI_HILOGD("Currently keyboard will %s consume touch points", (isCaptureMode ? "not" : ""));
362     return isCaptureMode;
363 }
364 #endif // OHOS_BUILD_ENABLE_VKEYBOARD
365 
366 #ifdef OHOS_BUILD_ENABLE_VKEYBOARD
HandleVFullKeyboardMessages(libinput_event * event,int64_t frameTime,libinput_event_type eventType,libinput_event_touch * touch)367 void LibinputAdapter::HandleVFullKeyboardMessages(
368     libinput_event *event, int64_t frameTime, libinput_event_type eventType, libinput_event_touch *touch)
369 {
370     // delay the event destroy.
371     bool delayDestroy = false;
372     int32_t confirmedDelayMs(0);
373 
374     if (getLibinputEventForVKeyboard_ == nullptr || getLibinputEventForVTrackpad_ == nullptr) {
375         return;
376     }
377 
378     // handle keyboard messages.
379     while (true) {
380         int32_t delayMs(0);
381         std::vector<libinput_event*> keyEvents;
382         VKeyboardEventType eventType = (VKeyboardEventType)getLibinputEventForVKeyboard_(touch, delayMs, keyEvents);
383         if (eventType == VKeyboardEventType::NoKeyboardEvent || keyEvents.size() == 0) {
384             break;
385         }
386 
387          // if need to delay, not injecting but store them. Limit to up event.
388         if (delayMs > 0 && eventType == VKeyboardEventType::StopLongpress && !delayDestroy) {
389             // start delaying.
390             delayDestroy = CreateVKeyboardDelayTimer(event, delayMs, *keyEvents.begin());
391             if (delayDestroy) {
392                 // create and delay this event.
393                 confirmedDelayMs = delayMs;
394                 continue;
395             }
396         }
397         HandleVKeyboardMessage(eventType, keyEvents, frameTime);
398     }
399 
400 	// handle trackpad messages.
401     while (true) {
402         std::vector<libinput_event*> events;
403         VTrackpadEventType eventType = (VTrackpadEventType)getLibinputEventForVTrackpad_(touch, events);
404         if (eventType == VTrackpadEventType::NoTrackpadEvent) {
405             break;
406         }
407 
408         HandleVTrackpadMessage(eventType, events, frameTime, touch);
409     }
410 
411     if (eventType == LIBINPUT_EVENT_TOUCH_FRAME) {
412         // still let frame info go through.
413         funInputEvent_(event, frameTime);
414     }
415     if (delayDestroy) {
416         StartVKeyboardDelayTimer(confirmedDelayMs);
417     } else {
418         libinput_event_destroy(event);
419     }
420 }
421 
HandleVKeyboardMessage(VKeyboardEventType eventType,std::vector<libinput_event * > keyEvents,int64_t frameTime)422 void LibinputAdapter::HandleVKeyboardMessage(VKeyboardEventType eventType,
423                                              std::vector<libinput_event*> keyEvents, int64_t frameTime)
424 {
425     bool isCapsLockOn = false;
426     bool libinputCapsLockOn = false;
427     if ((eventType == VKeyboardEventType::NormalKeyboardEvent || eventType == VKeyboardEventType::UpdateCaps) &&
428         !keyEvents.empty()) {
429         // check current caps state.
430         std::shared_ptr<KeyEvent> sharedKeyEvent = KeyEventHdr->GetKeyEvent();
431         auto device = libinput_event_get_device(keyEvents.front());
432         if (sharedKeyEvent != nullptr && device != nullptr) {
433             isCapsLockOn = sharedKeyEvent->GetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY);
434             libinputCapsLockOn =
435                 static_cast<bool>(libinput_get_funckey_state(device, MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY));
436         } else {
437             MMI_HILOGW("Failed to sync virtual keyboard's Caps state given nullptr of keyEvent/device.");
438         }
439     }
440     switch (eventType) {
441         case VKeyboardEventType::NormalKeyboardEvent: {
442             for (auto event : keyEvents) {
443                 funInputEvent_(event, frameTime);
444                 free(event);
445                 event = nullptr;
446             }
447 
448             if (libinputCapsLockOn != isCapsLockOn) {
449                 // non-caps scenario, if a mismatch is found, sync it now.
450                 libinput_toggle_caps_key();
451             }
452             break;
453         }
454         case VKeyboardEventType::UpdateCaps: {
455             for (auto event : keyEvents) {
456                 funInputEvent_(event, frameTime);
457                 free(event);
458                 event = nullptr;
459             }
460 
461             std::shared_ptr<KeyEvent> keyEvent = KeyEventHdr->GetKeyEvent();
462             if (keyEvent != nullptr) {
463                 keyEvent->SetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY, !isCapsLockOn);
464             }
465             MultiKeyboardSetLedState(isCapsLockOn);
466             if (libinputCapsLockOn == isCapsLockOn) {
467                 libinput_toggle_caps_key();
468             } // no need to flip virtual keyboard's caps if it is already flipped.
469             break;
470         }
471         case VKeyboardEventType::HideCursor: {
472             HideMouseCursorTemporary();
473             break;
474         }
475         default:
476             break;
477     }
478 }
479 
HandleVTrackpadMessage(VTrackpadEventType eventType,std::vector<libinput_event * > events,int64_t frameTime,libinput_event_touch * touch)480 void LibinputAdapter::HandleVTrackpadMessage(VTrackpadEventType eventType, std::vector<libinput_event*> events,
481                                              int64_t frameTime,  libinput_event_touch *touch)
482 {
483     if (eventType != VTrackpadEventType::NormalTrackpadEvent) {
484         return;
485     }
486 
487     for (auto event : events) {
488         libinput_event_type injectEventType = libinput_event_get_type(event);
489         funInputEvent_(event, frameTime);
490         free(event);
491         event = nullptr;
492 
493         if (injectEventType == libinput_event_type::LIBINPUT_EVENT_GESTURE_PINCH_BEGIN) {
494             InjectEventForTwoFingerOnTouchpad(touch, libinput_event_type::LIBINPUT_EVENT_TOUCHPAD_DOWN,
495                                               frameTime);
496         } else if (injectEventType == libinput_event_type::LIBINPUT_EVENT_GESTURE_PINCH_UPDATE) {
497             InjectEventForTwoFingerOnTouchpad(touch, libinput_event_type::LIBINPUT_EVENT_TOUCHPAD_MOTION,
498                                               frameTime);
499         } else if (injectEventType == libinput_event_type::LIBINPUT_EVENT_GESTURE_PINCH_END) {
500             if (IsCursorInCastWindow()) {
501                 InjectEventForCastWindow(touch);
502             } else {
503                 InjectEventForTwoFingerOnTouchpad(touch, libinput_event_type::LIBINPUT_EVENT_TOUCHPAD_UP,
504                                                   frameTime);
505             }
506         }
507     }
508 }
509 
InjectEventForCastWindow(libinput_event_touch * touch)510 void LibinputAdapter::InjectEventForCastWindow(libinput_event_touch* touch)
511 {
512     int64_t frameTime = GetSysClockTime();
513     InjectEventForTwoFingerOnTouchpad(touch, libinput_event_type::LIBINPUT_EVENT_TOUCHPAD_UP, frameTime);
514 
515     event_touch tEvent;
516     tEvent.seat_slot = VKEY_PINCH_FIRST_FINGER_ID;
517 
518     auto mouseInfo = WIN_MGR->GetMouseInfo();
519     tEvent.event_type = libinput_event_type::LIBINPUT_EVENT_TOUCH_DOWN;
520     tEvent.x = mouseInfo.physicalX * VKEY_RAW_COORDINATE_RATIO;
521     tEvent.y = mouseInfo.physicalY * VKEY_RAW_COORDINATE_RATIO;
522     tEvent.seat_slot = 0;
523     tEvent.slot = 0;
524     ltEvent = libinput_create_touch_event(touch, tEvent);
525     funInputEvent_((libinput_event*)ltEvent, frameTime);
526     free(ltEvent);
527     ltEvent = nullptr;
528 
529     tEvent.event_type = libinput_event_type::LIBINPUT_EVENT_TOUCH_UP;
530     ltEvent = libinput_create_touch_event(touch, tEvent);
531     funInputEvent_((libinput_event*)ltEvent, frameTime);
532     free(ltEvent);
533     ltEvent = nullptr;
534 
535     event_pointer pEvent;
536     pEvent.event_type = libinput_event_type::LIBINPUT_EVENT_POINTER_MOTION_TOUCHPAD;
537     pEvent.delta_raw_x = VKEY_PINCH_CURSOR_FAKE_DX;
538     pEvent.delta_raw_y = 0;
539     libinput_event_pointer* lpEvent = libinput_create_pointer_event(touch, pEvent);
540     funInputEvent_((libinput_event*)lpEvent, frameTime);
541     free(lpEvent);
542     lpEvent = nullptr;
543 }
544 
IsCursorInCastWindow()545 bool LibinputAdapter::IsCursorInCastWindow()
546 {
547     InputWindowsManager* inputWindowsManager = static_cast<InputWindowsManager *>(WIN_MGR.get());
548     if (inputWindowsManager == nullptr) {
549         return false;
550     }
551     return inputWindowsManager->IsMouseInCastWindow();
552 }
553 
ConvertToTouchEventType(libinput_event_type eventType)554 int32_t LibinputAdapter::ConvertToTouchEventType(
555     libinput_event_type eventType)
556 {
557     if (eventType == LIBINPUT_EVENT_TOUCH_DOWN) {
558         return static_cast<int32_t>(VKeyboardTouchEventType::TOUCH_DOWN);
559     } else if (eventType == LIBINPUT_EVENT_TOUCH_UP) {
560         return static_cast<int32_t>(VKeyboardTouchEventType::TOUCH_UP);
561     } else if (eventType == LIBINPUT_EVENT_TOUCH_FRAME) {
562         return static_cast<int32_t>(VKeyboardTouchEventType::TOUCH_FRAME);
563     } else {
564         return static_cast<int32_t>(VKeyboardTouchEventType::TOUCH_MOVE);
565     }
566 }
567 
HandleHWKeyEventForVKeyboard(libinput_event * event)568 void LibinputAdapter::HandleHWKeyEventForVKeyboard(libinput_event* event)
569 {
570     MMI_HILOGD("Hardware keyboard key event detected");
571     if (hardwareKeyEventDetected_ == nullptr) {
572         return;
573     }
574     if (event == nullptr) {
575         MMI_HILOGD("libinput event is nullptr");
576         return;
577     }
578     libinput_event_type eventType = libinput_event_get_type(event);
579     if (eventType == LIBINPUT_EVENT_KEYBOARD_KEY) {
580         libinput_event_keyboard* keyboardEvent = libinput_event_get_keyboard_event(event);
581         if (keyboardEvent == nullptr) {
582             MMI_HILOGD("keyboardEvent is nullptr");
583             return;
584         }
585         libinput_device* device = libinput_event_get_device(event);
586         if (device == nullptr) {
587             MMI_HILOGD("keyboard device is nullptr");
588             return;
589         }
590         uint32_t keyCode = libinput_event_keyboard_get_key(keyboardEvent);
591         auto keyValueInfo = TransferKeyValue(static_cast<int32_t>(keyCode));
592         int32_t hasFnKey = libinput_device_has_key(device, LIBINPUT_KEY_FN);
593         MMI_HILOGD("The current keyCode:%{private}u, hasFnKey:%{private}d, keyName:%{private}s",
594             keyCode, hasFnKey, keyValueInfo.keyEvent.c_str());
595         if ((keyCode == LIBINPUT_KEY_VOLUME_DOWN || keyCode == LIBINPUT_KEY_VOLUME_UP ||
596             keyCode == LIBINPUT_KEY_POWER) && !hasFnKey) {
597             MMI_HILOGD("Skip device local button keyCode:%{private}u", keyCode);
598             return;
599         }
600         hardwareKeyEventDetected_(keyValueInfo.keyEvent);
601     }
602 }
603 
ShowMouseCursor()604 void LibinputAdapter::ShowMouseCursor()
605 {
606     if (!CursorDrawingComponent::GetInstance().GetMouseDisplayState()) {
607         MMI_HILOGI("Found hidden mouse cursor during trackpad operation, show it.");
608         CursorDrawingComponent::GetInstance().SetMouseDisplayState(true);
609     }
610 }
611 
HideMouseCursorTemporary()612 void LibinputAdapter::HideMouseCursorTemporary()
613 {
614     MMI_HILOGI("VKeyboard hide mouse.");
615     if (CursorDrawingComponent::GetInstance().GetMouseDisplayState()) {
616         CursorDrawingComponent::GetInstance().SetMouseDisplayState(false);
617     }
618 }
619 
GetAccumulatedPressure(int touchId,int32_t eventType,double touchPressure)620 double LibinputAdapter::GetAccumulatedPressure(int touchId, int32_t eventType, double touchPressure)
621 {
622     auto pos = touchPointPressureCache_.find(touchId);
623     double accumulatedPressure = 0.0;
624     if (pos != touchPointPressureCache_.end()) {
625         accumulatedPressure = pos->second;
626     }
627 
628     accumulatedPressure += touchPressure;
629     touchPointPressureCache_[touchId] = accumulatedPressure;
630 
631     if (eventType == LIBINPUT_EVENT_TOUCH_UP) {
632         pos = touchPointPressureCache_.find(touchId);
633         if (pos != touchPointPressureCache_.end()) {
634             touchPointPressureCache_.erase(pos);
635         }
636     }
637 
638     return accumulatedPressure;
639 }
640 
IsVKeyboardActivationDropEvent(libinput_event_touch * touch,libinput_event_type eventType)641 bool LibinputAdapter::IsVKeyboardActivationDropEvent(libinput_event_touch* touch, libinput_event_type eventType)
642 {
643     bool bDropEventFlag = false;
644     if (getKeyboardActivationState_ != nullptr) {
645         VKeyboardActivation activateState = (VKeyboardActivation)getKeyboardActivationState_();
646         switch (activateState) {
647             case VKeyboardActivation::INACTIVE: {
648                 break;
649             }
650             case VKeyboardActivation::ACTIVATED: {
651                 MMI_HILOGI("activation state: %{public}d", static_cast<int32_t>(activateState));
652                 break;
653             }
654             case VKeyboardActivation::TOUCH_CANCEL: {
655                 MMI_HILOGI(
656                     "activation state: %{public}d, sending touch cancel event", static_cast<int32_t>(activateState));
657                 if (eventType == LIBINPUT_EVENT_TOUCH_MOTION) {
658                     libinput_set_touch_event_type(touch, LIBINPUT_EVENT_TOUCH_CANCEL);
659                 }
660                 if (eventType == LIBINPUT_EVENT_TOUCH_DOWN) {
661                     bDropEventFlag = true;
662                 }
663                 break;
664             }
665             case VKeyboardActivation::TOUCH_DROP: {
666                 MMI_HILOGI("activation state: %{public}d, dropping event", static_cast<int32_t>(activateState));
667                 if (eventType != LIBINPUT_EVENT_TOUCH_UP) {
668                     bDropEventFlag = true;
669                 }
670                 break;
671             }
672             case VKeyboardActivation::EIGHT_FINGERS_UP: {
673                 MMI_HILOGI("activation state: %{public}d", static_cast<int32_t>(activateState));
674                 break;
675             }
676             default:
677                 break;
678         }
679     }
680     return bDropEventFlag;
681 }
682 
UpdateBootFlag()683 void LibinputAdapter::UpdateBootFlag()
684 {
685     if (!isBootCompleted_ && isVKeyboardShown_ != nullptr) {
686         isBootCompleted_ = isVKeyboardShown_();
687         if (isBootCompleted_) {
688             MMI_HILOGI("backend booted from outside (mainly due to process restart)=%{public}d",
689                 static_cast<int32_t>(isBootCompleted_));
690         }
691     }
692     // could also check SA status here.
693 }
694 #endif // OHOS_BUILD_ENABLE_VKEYBOARD
695 
MultiKeyboardSetLedState(bool oldCapsLockState)696 void LibinputAdapter::MultiKeyboardSetLedState(bool oldCapsLockState)
697 {
698     std::vector<struct libinput_device*> input_device;
699     INPUT_DEV_MGR->GetMultiKeyboardDevice(input_device);
700     for (auto it = input_device.begin(); it != input_device.end(); ++it) {
701         auto setDevice = (*it);
702         CHKPV(setDevice);
703         DeviceLedUpdate(setDevice, KeyEvent::CAPS_LOCK_FUNCTION_KEY, !oldCapsLockState);
704     }
705 }
706 
MultiKeyboardSetFuncState(libinput_event * event)707 void LibinputAdapter::MultiKeyboardSetFuncState(libinput_event* event)
708 {
709     libinput_event_type eventType = libinput_event_get_type(event);
710     if (eventType == LIBINPUT_EVENT_KEYBOARD_KEY) {
711             struct libinput_event_keyboard* keyboardEvent = libinput_event_get_keyboard_event(event);
712             CHKPV(keyboardEvent);
713             std::shared_ptr<KeyEvent> keyEvent = KeyEventHdr->GetKeyEvent();
714             if (libinput_event_keyboard_get_key_state(keyboardEvent) == LIBINPUT_KEY_STATE_PRESSED
715 			   && libinput_event_keyboard_get_key(keyboardEvent) == KEY_CAPSLOCK
716 			   && keyEvent != nullptr) {
717                 bool oldCapsLockOn = keyEvent->GetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY);
718                 MultiKeyboardSetLedState(oldCapsLockOn);
719                 keyEvent->SetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY, !oldCapsLockOn);
720                 libinput_toggle_caps_key();
721             }
722     }
723 }
724 
OnEventHandler()725 void LibinputAdapter::OnEventHandler()
726 {
727     CALL_DEBUG_ENTER;
728     CHKPV(funInputEvent_);
729     libinput_event *event = nullptr;
730     int64_t frameTime = GetSysClockTime();
731     while ((event = libinput_get_event(input_))) {
732 #ifdef OHOS_BUILD_ENABLE_VKEYBOARD
733         foldingAreaToast_.FoldingAreaProcess(event);
734         libinput_event_type eventType = libinput_event_get_type(event);
735         int32_t touchId = 0;
736         libinput_event_touch* touch = nullptr;
737         static int32_t downCount = 0;
738         bool isInsideWindow = false;
739 
740         // confirm boot completed msg in case of mmi restart.
741         UpdateBootFlag();
742 
743         // add the logic of screen capture window conuming touch point in high priority
744         bool isCaptureMode = GetIsCaptureMode();
745         if (((eventType == LIBINPUT_EVENT_TOUCH_DOWN && !isCaptureMode)
746             || eventType == LIBINPUT_EVENT_TOUCH_UP
747             || eventType == LIBINPUT_EVENT_TOUCH_MOTION
748             || eventType == LIBINPUT_EVENT_TOUCH_CANCEL
749             || eventType == LIBINPUT_EVENT_TOUCH_FRAME) && isBootCompleted_) {
750             touch = libinput_event_get_touch_event(event);
751             double touchPressure = 0.0;
752             double accumulatedPressure = 0.0;
753             if (eventType != LIBINPUT_EVENT_TOUCH_FRAME) {
754                 touchId = libinput_event_touch_get_slot(touch);
755                 touchPressure = libinput_event_touch_get_pressure(touch);
756                 accumulatedPressure = GetAccumulatedPressure(touchId, eventType, touchPressure);
757             }
758 
759             if (deviceId == -1) {
760                 // initialize touch device ID.
761                 libinput_device* device = libinput_event_get_device(event);
762                 deviceId = INPUT_DEV_MGR->FindInputDeviceId(device);
763             }
764 
765             EventTouch touchInfo;
766             int32_t logicalDisplayId = -1;
767             double x = 0.0;
768             double y = 0.0;
769             int32_t touchEventType = ConvertToTouchEventType(eventType);
770             // touch up event has no coordinates information, skip coordinate calculation.
771             if (eventType == LIBINPUT_EVENT_TOUCH_DOWN || eventType == LIBINPUT_EVENT_TOUCH_MOTION) {
772                 if (!WIN_MGR->TouchPointToDisplayPoint(deviceId, touch, touchInfo, logicalDisplayId)) {
773                     MMI_HILOGE("Map touch point to display point failed");
774                 } else {
775                     x = touchInfo.point.x;
776                     y = touchInfo.point.y;
777 
778                     touchPoints_[touchId] = std::pair<double, double>(x, y);
779 
780                     InputWindowsManager* inputWindowsManager = static_cast<InputWindowsManager *>(WIN_MGR.get());
781                     isInsideWindow = inputWindowsManager->IsPointInsideSpecialWindow(x, y);
782                 }
783             } else if (eventType == LIBINPUT_EVENT_TOUCH_UP) {
784                 auto pos = touchPoints_.find(touchId);
785                 if (pos != touchPoints_.end()) {
786                     x = (pos->second).first;
787                     y = (pos->second).second;
788                     touchPoints_.erase(pos);
789                 }
790             }
791 
792             int32_t longAxis = libinput_event_get_touch_contact_long_axis(touch);
793             int32_t shortAxis = libinput_event_get_touch_contact_short_axis(touch);
794             MMI_HILOGD("touch event. deviceId:%{private}d, touchId:%{private}d, x:%{private}d, y:%{private}d, \
795 type:%{private}d, accPressure:%{private}f, longAxis:%{private}d, shortAxis:%{private}d",
796                 deviceId,
797                 touchId,
798                 static_cast<int32_t>(x),
799                 static_cast<int32_t>(y),
800                 static_cast<int32_t>(eventType),
801                 accumulatedPressure,
802                 longAxis,
803                 shortAxis);
804 
805             if (!isInsideWindow && handleTouchPoint_ != nullptr &&
806                 handleTouchPoint_(x, y, touchId, touchEventType, accumulatedPressure, longAxis, shortAxis) == 0) {
807                 MMI_HILOGD("Inside vkeyboard area");
808                 HandleVFullKeyboardMessages(event, frameTime, eventType, touch);
809             } else {
810                 bool bDropEventFlag = IsVKeyboardActivationDropEvent(touch, eventType);
811                 if (!bDropEventFlag) {
812                     funInputEvent_(event, frameTime);
813                 }
814                 libinput_event_destroy(event);
815             }
816         } else if (eventType == LIBINPUT_EVENT_KEYBOARD_KEY) {
817             struct libinput_event_keyboard* keyboardEvent = libinput_event_get_keyboard_event(event);
818             std::shared_ptr<KeyEvent> keyEvent = KeyEventHdr->GetKeyEvent();
819 
820             if (libinput_event_keyboard_get_key_state(keyboardEvent) == LIBINPUT_KEY_STATE_PRESSED
821 			   && libinput_event_keyboard_get_key(keyboardEvent) == KEY_CAPSLOCK
822 			   && keyEvent != nullptr) {
823                 bool oldCapsLockOn = keyEvent->GetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY);
824                 libinput_device* device = libinput_event_get_device(event);
825 
826                 HandleHWKeyEventForVKeyboard(event);
827                 funInputEvent_(event, frameTime);
828                 libinput_event_destroy(event);
829 
830                 MultiKeyboardSetLedState(oldCapsLockOn);
831                 keyEvent->SetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY, !oldCapsLockOn);
832                 libinput_toggle_caps_key();
833             } else {
834                 HandleHWKeyEventForVKeyboard(event);
835                 funInputEvent_(event, frameTime);
836                 libinput_event_destroy(event);
837             }
838         } else {
839             funInputEvent_(event, frameTime);
840             libinput_event_destroy(event);
841         }
842 #else // OHOS_BUILD_ENABLE_VKEYBOARD
843         MultiKeyboardSetFuncState(event);
844         funInputEvent_(event, frameTime);
845         libinput_event_destroy(event);
846 #endif // OHOS_BUILD_ENABLE_VKEYBOARD
847     }
848     if (event == nullptr) {
849         funInputEvent_(nullptr, 0);
850     }
851 }
852 
ReloadDevice()853 void LibinputAdapter::ReloadDevice()
854 {
855     CALL_DEBUG_ENTER;
856     CHKPV(input_);
857     libinput_suspend(input_);
858     libinput_resume(input_);
859 }
860 
OnDeviceAdded(std::string path)861 void LibinputAdapter::OnDeviceAdded(std::string path)
862 {
863     std::regex re("(\\d+)");
864     std::string str_path(path);
865     std::smatch match;
866     int32_t id;
867     bool isPath = std::regex_search(str_path, match, re);
868     if (!isPath) {
869         id = -1;
870     } else {
871         id = std::stoi(match[0]);
872     }
873     MMI_HILOGI("OnDeviceAdded id:%{public}d", id);
874     auto pos = devices_.find(path);
875     if (pos != devices_.end()) {
876         MMI_HILOGD("Path is found");
877         return;
878     }
879 
880     DTaskCallback cb = [this, path] {
881         MMI_HILOGI("OnDeviceAdded, path:%{private}s", path.c_str());
882         udev_device_record_devnode(path.c_str());
883         libinput_device* device = libinput_path_add_device(input_, path.c_str());
884         if (device != nullptr) {
885             devices_[std::move(path)] = libinput_device_ref(device);
886             // Libinput doesn't signal device adding event in path mode. Process manually.
887             OnEventHandler();
888         }
889         udev_device_property_remove(path.c_str());
890         return 0;
891     };
892     PropReader->ReadPropertys(path, cb);
893 }
894 
OnDeviceRemoved(std::string path)895 void LibinputAdapter::OnDeviceRemoved(std::string path)
896 {
897     std::regex re("(\\d+)");
898     std::string str_path(path);
899     std::smatch match;
900     int32_t id;
901     bool isPath = std::regex_search(str_path, match, re);
902     if (!isPath) {
903         id = -1;
904     } else {
905         id = std::stoi(match[0]);
906     }
907     MMI_HILOGI("OnDeviceRemoved id:%{public}d", id);
908     auto pos = devices_.find(path);
909     if (pos != devices_.end()) {
910         libinput_path_remove_device(pos->second);
911         libinput_device_unref(pos->second);
912         devices_.erase(pos);
913         // Libinput doesn't signal device removing event in path mode. Process manually.
914         OnEventHandler();
915     }
916 }
917 } // namespace MMI
918 } // namespace OHOS
919