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