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