• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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