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 "input_event_handler.h"
17
18 #include <cinttypes>
19 #include <cstdio>
20 #include <cstring>
21 #include <functional>
22 #include <vector>
23
24 #include <sys/stat.h>
25 #include <unistd.h>
26
27 #include "libinput.h"
28 #include "key_command_handler.h"
29 #include "timer_manager.h"
30 #include "util.h"
31
32 #undef MMI_LOG_DOMAIN
33 #define MMI_LOG_DOMAIN MMI_LOG_HANDLER
34 #undef MMI_LOG_TAG
35 #define MMI_LOG_TAG "InputEventHandler"
36
37 namespace OHOS {
38 namespace MMI {
39 namespace {
40 constexpr int32_t MT_TOOL_PALM { 2 };
41 constexpr int32_t TIMEOUT_MS { 1500 };
42 constexpr uint32_t KEY_ESC { 1 };
43 constexpr uint32_t KEY_KPASTERISK { 55 };
44 constexpr uint32_t KEY_F1 { 59 };
45 constexpr uint32_t KEY_LEFTCTRL { 29 };
46 constexpr uint32_t KEY_RIGHTCTRL { 97 };
47 constexpr uint32_t KEY_LEFTALT { 56 };
48 constexpr uint32_t KEY_RIGHTALT { 100 };
49 constexpr uint32_t KEY_LEFTSHIFT { 42 };
50 constexpr uint32_t KEY_RIGHTSHIFT { 54 };
51 constexpr uint32_t KEY_FN { 0x1d0 };
52 constexpr uint32_t KEY_CAPSLOCK { 58 };
53 constexpr uint32_t KEY_TAB { 15 };
54 constexpr uint32_t KEY_COMPOSE { 127 };
55 constexpr uint32_t KEY_RIGHTMETA { 126 };
56 constexpr uint32_t KEY_LEFTMETA { 125 };
57 } // namespace
58
InputEventHandler()59 InputEventHandler::InputEventHandler()
60 {
61 lastEventBeginTime_ = GetSysClockTime();
62 udsServer_ = nullptr;
63 }
64
~InputEventHandler()65 InputEventHandler::~InputEventHandler() {}
66
Init(UDSServer & udsServer)67 void InputEventHandler::Init(UDSServer& udsServer)
68 {
69 udsServer_ = &udsServer;
70 BuildInputHandlerChain();
71 }
72
OnEvent(void * event,int64_t frameTime)73 void InputEventHandler::OnEvent(void *event, int64_t frameTime)
74 {
75 CHKPV(eventNormalizeHandler_);
76 if (event == nullptr) {
77 eventNormalizeHandler_->HandleEvent(nullptr, frameTime);
78 return;
79 }
80
81 idSeed_ += 1;
82 const uint64_t maxUInt64 = (std::numeric_limits<uint64_t>::max)() - 1;
83 if (idSeed_ >= maxUInt64) {
84 MMI_HILOGE("The value is flipped. id:%{public}" PRId64, idSeed_);
85 idSeed_ = 1;
86 }
87
88 auto *lpEvent = static_cast<libinput_event *>(event);
89 CHKPV(lpEvent);
90 int32_t eventType = libinput_event_get_type(lpEvent);
91 int64_t beginTime = GetSysClockTime();
92 lastEventBeginTime_ = beginTime;
93 MMI_HILOGD("Event reporting. id:%{public}" PRId64 ",tid:%{public}" PRId64 ",eventType:%{public}d,"
94 "beginTime:%{public}" PRId64, idSeed_, GetThisThreadId(), eventType, beginTime);
95
96 UpdateDwtRecord(lpEvent);
97 if (IsTouchpadMistouch(lpEvent)) {
98 return;
99 }
100
101 ResetLogTrace();
102 eventNormalizeHandler_->HandleEvent(lpEvent, frameTime);
103 int64_t endTime = GetSysClockTime();
104 int64_t lostTime = endTime - beginTime;
105 if (lostTime >= TIMEOUT_MS) {
106 MMI_HILOGE("Event handling completed. id:%{public}" PRId64 ",endTime:%{public}" PRId64
107 ",lostTime:%{public}" PRId64, idSeed_, endTime, lostTime);
108 }
109 MMI_HILOGD("Event handling completed. id:%{public}" PRId64 ",endTime:%{public}" PRId64
110 ",lostTime:%{public}" PRId64, idSeed_, endTime, lostTime);
111 }
112
UpdateDwtRecord(libinput_event * event)113 void InputEventHandler::UpdateDwtRecord(libinput_event *event)
114 {
115 CHKPV(event);
116 auto type = libinput_event_get_type(event);
117 if (type == LIBINPUT_EVENT_TOUCHPAD_DOWN || type == LIBINPUT_EVENT_TOUCHPAD_MOTION) {
118 UpdateDwtTouchpadRecord(event);
119 }
120 if (type == LIBINPUT_EVENT_KEYBOARD_KEY) {
121 UpdateDwtKeyboardRecord(event);
122 }
123 }
124
UpdateDwtTouchpadRecord(libinput_event * event)125 void InputEventHandler::UpdateDwtTouchpadRecord(libinput_event *event)
126 {
127 auto touchpadEvent = libinput_event_get_touchpad_event(event);
128 CHKPV(touchpadEvent);
129 auto type = libinput_event_get_type(event);
130 auto touchpadDevice = libinput_event_get_device(event); // guaranteed valid during event lifetime
131 CHKPV(touchpadDevice);
132 double touchpadSizeX;
133 double touchpadSizeY;
134 if (libinput_device_get_size(touchpadDevice, &touchpadSizeX, &touchpadSizeY) != 0) {
135 MMI_HILOGW("Failed to get touchpad device size");
136 return;
137 }
138 if (type == LIBINPUT_EVENT_TOUCHPAD_DOWN) {
139 touchpadEventDownAbsX_ = libinput_event_touchpad_get_x(touchpadEvent);
140 touchpadEventDownAbsY_ = libinput_event_touchpad_get_y(touchpadEvent);
141 touchpadEventAbsX_ = touchpadEventDownAbsX_;
142 touchpadEventAbsY_ = touchpadEventDownAbsY_;
143 if (touchpadEventDownAbsX_ > TOUCHPAD_EDGE_WIDTH &&
144 touchpadEventDownAbsX_ < touchpadSizeX - TOUCHPAD_EDGE_WIDTH) {
145 isDwtEdgeAreaForTouchpadMotionActing_ = false;
146 MMI_HILOGD("Pointer edge dwt unlocked, coordX = %{public}f", touchpadEventDownAbsX_);
147 }
148 if (touchpadEventDownAbsX_ > TOUCHPAD_EDGE_WIDTH_FOR_BUTTON &&
149 touchpadEventDownAbsX_ < touchpadSizeX - TOUCHPAD_EDGE_WIDTH_FOR_BUTTON) {
150 isDwtEdgeAreaForTouchpadButtonActing_ = false;
151 MMI_HILOGD("Button edge dwt unlocked, coordX = %{public}f", touchpadEventDownAbsX_);
152 }
153 if (touchpadEventDownAbsX_ > TOUCHPAD_EDGE_WIDTH_FOR_TAP &&
154 touchpadEventDownAbsX_ < touchpadSizeX - TOUCHPAD_EDGE_WIDTH_FOR_TAP) {
155 isDwtEdgeAreaForTouchpadTapActing_ = false;
156 MMI_HILOGD("Tap edge dwt unlocked, coordX = %{public}f", touchpadEventDownAbsX_);
157 }
158 }
159 if (type == LIBINPUT_EVENT_TOUCHPAD_MOTION) {
160 touchpadEventAbsX_ = libinput_event_touchpad_get_x(touchpadEvent);
161 touchpadEventAbsY_ = libinput_event_touchpad_get_y(touchpadEvent);
162 int32_t toolType = libinput_event_touchpad_get_tool_type(touchpadEvent);
163 if (touchpadEventAbsX_ > TOUCHPAD_EDGE_WIDTH_RELEASE &&
164 touchpadEventAbsX_ < touchpadSizeX - TOUCHPAD_EDGE_WIDTH_RELEASE &&
165 toolType != MT_TOOL_PALM) {
166 isDwtEdgeAreaForTouchpadMotionActing_ = false;
167 MMI_HILOGD("Pointer edge dwt unlocked, coordX = %{public}f", touchpadEventDownAbsX_);
168 }
169 }
170 }
171
UpdateDwtKeyboardRecord(libinput_event * event)172 void InputEventHandler::UpdateDwtKeyboardRecord(libinput_event *event)
173 {
174 auto keyboardEvent = libinput_event_get_keyboard_event(event);
175 CHKPV(keyboardEvent);
176 uint32_t key = libinput_event_keyboard_get_key(keyboardEvent);
177 if (IsStandaloneFunctionKey(key)) {
178 return;
179 }
180
181 auto keyState = libinput_event_keyboard_get_key_state(keyboardEvent);
182 if (IsModifierKey(key)) {
183 modifierPressedCount_ += (keyState == LIBINPUT_KEY_STATE_PRESSED) ? 1 : -1;
184 }
185 if (keyState == LIBINPUT_KEY_STATE_PRESSED && modifierPressedCount_ > 0) {
186 isKeyPressedWithAnyModifiers_[key] = true; // set flag when key is pressed with modifiers
187 }
188 if (!IsModifierKey(key) && !isKeyPressedWithAnyModifiers_[key]) {
189 RefreshDwtActingState();
190 }
191 if (keyState == LIBINPUT_KEY_STATE_RELEASED) {
192 isKeyPressedWithAnyModifiers_[key] = false; // always reset flag when key is released
193 }
194 }
195
IsStandaloneFunctionKey(uint32_t keycode)196 bool InputEventHandler::IsStandaloneFunctionKey(uint32_t keycode)
197 {
198 if (IsModifierKey(keycode)) {
199 return false;
200 }
201 switch (keycode) {
202 case KEY_ESC:
203 case KEY_KPASTERISK:
204 return true;
205 default:
206 return keycode >= KEY_F1;
207 }
208 }
209
IsModifierKey(uint32_t keycode)210 bool InputEventHandler::IsModifierKey(uint32_t keycode)
211 {
212 switch (keycode) {
213 case KEY_LEFTCTRL:
214 case KEY_RIGHTCTRL:
215 case KEY_LEFTALT:
216 case KEY_RIGHTALT:
217 case KEY_LEFTSHIFT:
218 case KEY_RIGHTSHIFT:
219 case KEY_FN:
220 case KEY_CAPSLOCK:
221 case KEY_TAB:
222 case KEY_COMPOSE:
223 case KEY_RIGHTMETA:
224 case KEY_LEFTMETA:
225 return true;
226 default:
227 return false;
228 }
229 }
230
RefreshDwtActingState()231 void InputEventHandler::RefreshDwtActingState()
232 {
233 isDwtEdgeAreaForTouchpadMotionActing_ = true;
234 isDwtEdgeAreaForTouchpadButtonActing_ = true;
235 isDwtEdgeAreaForTouchpadTapActing_ = true;
236 }
237
IsTouchpadMistouch(libinput_event * event)238 bool InputEventHandler::IsTouchpadMistouch(libinput_event *event)
239 {
240 CHKPF(event);
241 auto type = libinput_event_get_type(event);
242 if (type >= LIBINPUT_EVENT_TOUCHPAD_DOWN && type <= LIBINPUT_EVENT_TOUCHPAD_MOTION) {
243 auto touchpadEvent = libinput_event_get_touchpad_event(event);
244 CHKPF(touchpadEvent);
245 int32_t toolType = libinput_event_touchpad_get_tool_type(touchpadEvent);
246 if (toolType == MT_TOOL_PALM) {
247 MMI_HILOGD("Touchpad event is palm");
248 return false;
249 }
250 }
251
252 if (type == LIBINPUT_EVENT_POINTER_BUTTON_TOUCHPAD) {
253 return IsTouchpadButtonMistouch(event);
254 }
255 if (type == LIBINPUT_EVENT_POINTER_TAP) {
256 return IsTouchpadTapMistouch(event);
257 }
258 if (type == LIBINPUT_EVENT_TOUCHPAD_MOTION) {
259 return IsTouchpadMotionMistouch(event);
260 }
261 if (type == LIBINPUT_EVENT_POINTER_MOTION_TOUCHPAD) {
262 return IsTouchpadPointerMotionMistouch(event);
263 }
264
265 return false;
266 }
267
IsTouchpadButtonMistouch(libinput_event * event)268 bool InputEventHandler::IsTouchpadButtonMistouch(libinput_event* event)
269 {
270 CHKPF(event);
271 auto touchpadButtonEvent = libinput_event_get_pointer_event(event);
272 CHKPF(touchpadButtonEvent);
273 auto buttonState = libinput_event_pointer_get_button_state(touchpadButtonEvent);
274 if (buttonState == LIBINPUT_BUTTON_STATE_PRESSED) {
275 auto touchpadDevice = libinput_event_get_device(event); // guaranteed valid during event lifetime
276 CHKPF(touchpadDevice);
277 double touchpadSizeX;
278 double touchpadSizeY;
279 if (libinput_device_get_size(touchpadDevice, &touchpadSizeX, &touchpadSizeY) != 0) {
280 return false;
281 }
282 double coordX = touchpadEventAbsX_;
283 if (isDwtEdgeAreaForTouchpadButtonActing_ &&
284 (coordX <= TOUCHPAD_EDGE_WIDTH_FOR_BUTTON || coordX >= touchpadSizeX - TOUCHPAD_EDGE_WIDTH_FOR_BUTTON)) {
285 isButtonMistouch_ = true;
286 MMI_HILOGD("The buttonPressed event is mistouch");
287 return true;
288 }
289 }
290 if (buttonState == LIBINPUT_BUTTON_STATE_RELEASED) {
291 if (isButtonMistouch_) {
292 isButtonMistouch_ = false;
293 MMI_HILOGD("The buttonReleased event is mistouch");
294 return true;
295 }
296 }
297 return false;
298 }
299
IsTouchpadTapMistouch(libinput_event * event)300 bool InputEventHandler::IsTouchpadTapMistouch(libinput_event* event)
301 {
302 CHKPF(event);
303 auto data = libinput_event_get_pointer_event(event);
304 CHKPF(data);
305 auto state = libinput_event_pointer_get_button_state(data);
306 if (state == LIBINPUT_BUTTON_STATE_PRESSED) {
307 auto touchpadDevice = libinput_event_get_device(event); // guaranteed valid during event lifetime
308 CHKPF(touchpadDevice);
309 double touchpadSizeX;
310 double touchpadSizeY;
311 if (libinput_device_get_size(touchpadDevice, &touchpadSizeX, &touchpadSizeY) != 0) {
312 return false;
313 }
314 double coordX = touchpadEventDownAbsX_;
315 if (isDwtEdgeAreaForTouchpadTapActing_ &&
316 (coordX <= TOUCHPAD_EDGE_WIDTH_FOR_TAP || coordX >= touchpadSizeX - TOUCHPAD_EDGE_WIDTH_FOR_TAP)) {
317 isTapMistouch_ = true;
318 MMI_HILOGD("Touchpad tap presse event is mistouch");
319 return true;
320 }
321 }
322 if (state == LIBINPUT_BUTTON_STATE_RELEASED) {
323 if (isTapMistouch_) {
324 isTapMistouch_ = false;
325 MMI_HILOGD("Touchpad tap release event is mistouch");
326 return true;
327 }
328 }
329 return false;
330 }
331
IsTouchpadMotionMistouch(libinput_event * event)332 bool InputEventHandler::IsTouchpadMotionMistouch(libinput_event *event)
333 {
334 if (!isDwtEdgeAreaForTouchpadMotionActing_) {
335 return false;
336 }
337
338 CHKPF(event);
339 auto touchpadEvent = libinput_event_get_touchpad_event(event);
340 CHKPF(touchpadEvent);
341 auto touchpadDevice = libinput_event_get_device(event); // guaranteed valid during event lifetime
342 CHKPF(touchpadDevice);
343 double touchpadSizeX;
344 double touchpadSizeY;
345 if (libinput_device_get_size(touchpadDevice, &touchpadSizeX, &touchpadSizeY) != 0) {
346 return false;
347 }
348 auto coordX = touchpadEventDownAbsX_;
349 if (coordX <= TOUCHPAD_EDGE_WIDTH || coordX >= touchpadSizeX - TOUCHPAD_EDGE_WIDTH) {
350 MMI_HILOGD("Touchpad event is edge mistouch");
351 return true;
352 }
353 return false;
354 }
355
IsTouchpadPointerMotionMistouch(libinput_event * event)356 bool InputEventHandler::IsTouchpadPointerMotionMistouch(libinput_event *event)
357 {
358 if (!isDwtEdgeAreaForTouchpadMotionActing_) {
359 return false;
360 }
361
362 CHKPF(event);
363 auto pointerEvent = libinput_event_get_pointer_event(event);
364 CHKPF(pointerEvent);
365 auto touchpadDevice = libinput_event_get_device(event); // guaranteed valid during event lifetime
366 CHKPF(touchpadDevice);
367 double touchpadSizeX;
368 double touchpadSizeY;
369 if (libinput_device_get_size(touchpadDevice, &touchpadSizeX, &touchpadSizeY) != 0) {
370 return false;
371 }
372 double coordX = touchpadEventDownAbsX_;
373 if (coordX <= TOUCHPAD_EDGE_WIDTH || coordX >= touchpadSizeX - TOUCHPAD_EDGE_WIDTH) {
374 MMI_HILOGD("Touchpad pointer motion event is edge mistouch");
375 return true;
376 }
377 return false;
378 }
379
BuildInputHandlerChain()380 int32_t InputEventHandler::BuildInputHandlerChain()
381 {
382 eventNormalizeHandler_ = std::make_shared<EventNormalizeHandler>();
383 #if !defined(OHOS_BUILD_ENABLE_KEYBOARD) && !defined(OHOS_BUILD_ENABLE_POINTER) && !defined(OHOS_BUILD_ENABLE_TOUCH)
384 return RET_OK;
385 #endif // !OHOS_BUILD_ENABLE_KEYBOARD && !OHOS_BUILD_ENABLE_POINTER && !OHOS_BUILD_ENABLE_TOUCH
386
387 std::shared_ptr<IInputEventHandler> handler = eventNormalizeHandler_;
388 #if defined(OHOS_BUILD_ENABLE_POINTER) || defined(OHOS_BUILD_ENABLE_TOUCH)
389 eventFilterHandler_ = std::make_shared<EventFilterHandler>();
390 handler->SetNext(eventFilterHandler_);
391 handler = eventFilterHandler_;
392 #endif // OHOS_BUILD_ENABLE_POINTER || OHOS_BUILD_ENABLE_TOUCH
393
394 #ifdef OHOS_BUILD_ENABLE_INTERCEPTOR
395 eventInterceptorHandler_ = std::make_shared<EventInterceptorHandler>();
396 handler->SetNext(eventInterceptorHandler_);
397 handler = eventInterceptorHandler_;
398 #endif // OHOS_BUILD_ENABLE_INTERCEPTOR
399
400 #ifdef OHOS_BUILD_ENABLE_KEYBOARD
401 #ifdef OHOS_BUILD_ENABLE_COMBINATION_KEY
402 eventPreMonitorHandler_ = std::make_shared<EventPreMonitorHandler>();
403 handler->SetNext(eventPreMonitorHandler_);
404 handler = eventPreMonitorHandler_;
405 eventKeyCommandHandler_ = std::make_shared<KeyCommandHandler>();
406 handler->SetNext(eventKeyCommandHandler_);
407 handler = eventKeyCommandHandler_;
408 #endif // OHOS_BUILD_ENABLE_COMBINATION_KEY
409 eventSubscriberHandler_ = std::make_shared<KeySubscriberHandler>();
410 handler->SetNext(eventSubscriberHandler_);
411 handler = eventSubscriberHandler_;
412 #endif // OHOS_BUILD_ENABLE_KEYBOARD
413 #ifdef OHOS_BUILD_ENABLE_SWITCH
414 switchEventSubscriberHandler_ = std::make_shared<SwitchSubscriberHandler>();
415 handler->SetNext(switchEventSubscriberHandler_);
416 handler = switchEventSubscriberHandler_;
417 #endif // OHOS_BUILD_ENABLE_SWITCH
418 #ifdef OHOS_BUILD_ENABLE_MONITOR
419 eventMonitorHandler_ = std::make_shared<EventMonitorHandler>();
420 handler->SetNext(eventMonitorHandler_);
421 handler = eventMonitorHandler_;
422 #endif // OHOS_BUILD_ENABLE_MONITOR
423 eventDispatchHandler_ = std::make_shared<EventDispatchHandler>();
424 handler->SetNext(eventDispatchHandler_);
425 return RET_OK;
426 }
427
GetIntervalSinceLastInput(int64_t & timeInterval)428 int32_t InputEventHandler::GetIntervalSinceLastInput(int64_t &timeInterval)
429 {
430 int64_t currentSystemTime = GetSysClockTime();
431 timeInterval = currentSystemTime - lastEventBeginTime_;
432 return RET_OK;
433 }
434
GetUDSServer() const435 UDSServer* InputEventHandler::GetUDSServer() const
436 {
437 return udsServer_;
438 }
439
GetEventNormalizeHandler() const440 std::shared_ptr<EventNormalizeHandler> InputEventHandler::GetEventNormalizeHandler() const
441 {
442 return eventNormalizeHandler_;
443 }
444
GetInterceptorHandler() const445 std::shared_ptr<EventInterceptorHandler> InputEventHandler::GetInterceptorHandler() const
446 {
447 return eventInterceptorHandler_;
448 }
449
GetSubscriberHandler() const450 std::shared_ptr<KeySubscriberHandler> InputEventHandler::GetSubscriberHandler() const
451 {
452 return eventSubscriberHandler_;
453 }
454
GetSwitchSubscriberHandler() const455 std::shared_ptr<SwitchSubscriberHandler> InputEventHandler::GetSwitchSubscriberHandler() const
456 {
457 return switchEventSubscriberHandler_;
458 }
459
GetKeyCommandHandler() const460 std::shared_ptr<KeyCommandHandler> InputEventHandler::GetKeyCommandHandler() const
461 {
462 return eventKeyCommandHandler_;
463 }
464
GetMonitorHandler() const465 std::shared_ptr<EventMonitorHandler> InputEventHandler::GetMonitorHandler() const
466 {
467 return eventMonitorHandler_;
468 }
469
GetFilterHandler() const470 std::shared_ptr<EventFilterHandler> InputEventHandler::GetFilterHandler() const
471 {
472 return eventFilterHandler_;
473 }
474
GetEventDispatchHandler() const475 std::shared_ptr<EventDispatchHandler> InputEventHandler::GetEventDispatchHandler() const
476 {
477 return eventDispatchHandler_;
478 }
479
GetEventPreMonitorHandler() const480 std::shared_ptr<EventPreMonitorHandler> InputEventHandler::GetEventPreMonitorHandler() const
481 {
482 return eventPreMonitorHandler_;
483 }
484
SetMoveEventFilters(bool flag)485 int32_t InputEventHandler::SetMoveEventFilters(bool flag)
486 {
487 CALL_INFO_TRACE;
488 #ifdef OHOS_BUILD_ENABLE_MOVE_EVENT_FILTERS
489 CHKPR(eventNormalizeHandler_, INVALID_HANDLER_ID);
490 return eventNormalizeHandler_->SetMoveEventFilters(flag);
491 #else
492 MMI_HILOGW("Set move event filters does not support");
493 return ERROR_UNSUPPORT;
494 #endif // OHOS_BUILD_ENABLE_MOVE_EVENT_FILTERS
495 }
496 } // namespace MMI
497 } // namespace OHOS