diff --git a/service/BUILD.gn b/service/BUILD.gn index c243474dfee6ea9e784549608cd0885735c66c44..bbdb2829a4ebc4d112bedd1ea87ab51dfa4846af 100644 --- a/service/BUILD.gn +++ b/service/BUILD.gn @@ -2063,12 +2063,14 @@ ohos_unittest("KeyEventNormalizeTest") { "${mmi_path}/service:libmmi-server", "${mmi_path}/test/facility/libinput_wrapper:libinput_wrapper_sources", "${mmi_path}/test/facility/virtual_device:virtual_device_sources", + "${mmi_path}/test/facility/mock:mmi_mock_sources", "${mmi_path}/util:libmmi-util", ] external_deps = [ "cJSON:cjson", "c_utils:utilsbase", + "googletest:gmock_main", "googletest:gtest_main", "graphic_2d:2d_graphics", "graphic_2d:librender_service_client", diff --git a/service/key_event_normalize/src/key_event_normalize.cpp b/service/key_event_normalize/src/key_event_normalize.cpp index 6ce27f8a082bad0c457fb5ed73f0e52350d9d623..ffe931e791a642c6e922521a99337e8f6584e0df 100644 --- a/service/key_event_normalize/src/key_event_normalize.cpp +++ b/service/key_event_normalize/src/key_event_normalize.cpp @@ -17,7 +17,6 @@ #include #include - #include "display_manager.h" #include "key_map_manager.h" #include "key_command_handler_util.h" @@ -166,20 +165,41 @@ void KeyEventNormalize::HandleKeyAction(struct libinput_device* device, KeyEvent void KeyEventNormalize::ResetKeyEvent(struct libinput_device* device) { if (INPUT_DEV_MGR->IsKeyboardDevice(device) || INPUT_DEV_MGR->IsPointerDevice(device)) { + bool newKeyEventJustCreated = false; if (keyEvent_ == nullptr) { keyEvent_ = KeyEvent::Create(); + newKeyEventJustCreated = true; + } + CHKPV(keyEvent_); + + if (!libinput_has_event_led_type(device)) { + // skip if this device does not have led lights. + return; } - if (libinput_has_event_led_type(device)) { - CHKPV(keyEvent_); - const std::vector funcKeys = { - KeyEvent::NUM_LOCK_FUNCTION_KEY, - KeyEvent::CAPS_LOCK_FUNCTION_KEY, - KeyEvent::SCROLL_LOCK_FUNCTION_KEY - }; + + const std::vector funcKeys = { + KeyEvent::NUM_LOCK_FUNCTION_KEY, + KeyEvent::CAPS_LOCK_FUNCTION_KEY, + KeyEvent::SCROLL_LOCK_FUNCTION_KEY + }; +#ifdef OHOS_BUILD_ENABLE_VKEYBOARD + if (newKeyEventJustCreated) { + // if key event just created, set keyevent from this new device. + MMI_HILOGI("Reset key event function key state based on the new added device's led"); for (const auto &funcKey : funcKeys) { keyEvent_->SetFunctionKey(funcKey, libinput_get_funckey_state(device, funcKey)); } + } else { + // otherwise, set this new device's function key state based on the key event. + for (const auto &funcKey : funcKeys) { + LibinputAdapter::DeviceLedUpdate(device, funcKey, keyEvent_->GetFunctionKey(funcKey)); + } + } +#else // OHOS_BUILD_ENABLE_VKEYBOARD + for (const auto &funcKey : funcKeys) { + keyEvent_->SetFunctionKey(funcKey, libinput_get_funckey_state(device, funcKey)); } +#endif // OHOS_BUILD_ENABLE_VKEYBOARD } } diff --git a/service/key_event_normalize/test/key_event_normalize_test.cpp b/service/key_event_normalize/test/key_event_normalize_test.cpp index d467a58da7a2b33d060e5d9f0c1cfb70cc1f1abd..830dda9df5a21f14137928a88b2ddc8334a97066 100644 --- a/service/key_event_normalize/test/key_event_normalize_test.cpp +++ b/service/key_event_normalize/test/key_event_normalize_test.cpp @@ -23,6 +23,7 @@ #include "i_input_windows_manager.h" #include "key_event_normalize.h" #include "libinput_wrapper.h" +#include "libinput_mock.h" #include "pointer_event.h" #undef MMI_LOG_TAG @@ -258,51 +259,126 @@ HWTEST_F(KeyEventNormalizeTest, KeyEventNormalizeTest_HandleKeyAction_003, TestS /** * @tc.name: KeyEventNormalizeTest_ResetKeyEvent_001 - * @tc.desc: Test ResetKeyEvent + * @tc.desc: Test ResetKeyEvent with a device without led and null keyEvent. * @tc.type: FUNC * @tc.require: */ -HWTEST_F(KeyEventNormalizeTest, KeyEventNormalizeTest_ResetKeyEvent_001, TestSize.Level1) +HWTEST_F(KeyEventNormalizeTest, KeyEventNormalizeTest_ResetKeyEvent_LedOff_001, TestSize.Level1) { CALL_TEST_DEBUG; - vKeyboard_.SendEvent(EV_KEY, 29, 1); - vKeyboard_.SendEvent(EV_KEY, KEY_C, 1); - vKeyboard_.SendEvent(EV_SYN, SYN_REPORT, 0); - vKeyboard_.SendEvent(EV_KEY, KEY_C, 0); - vKeyboard_.SendEvent(EV_KEY, 29, 0); - vKeyboard_.SendEvent(EV_SYN, SYN_REPORT, 0); - libinput_event *event = libinput_.Dispatch(); - ASSERT_TRUE(event != nullptr); - struct libinput_device *dev = libinput_event_get_device(event); - ASSERT_TRUE(dev != nullptr); - std::cout << "keyboard device: " << libinput_device_get_name(dev) << std::endl; - std::shared_ptr keyEvent = nullptr; - EXPECT_NO_FATAL_FAILURE(KeyEventHdr->ResetKeyEvent(dev)); + testing::NiceMock libinputMock; + // create a node for keyboard. + struct libinput_device libDev { + .udevDev { 2 }, + .busType = 1, + .version = 1, + .product = 1, + .vendor = 1, + .name = "test", + }; + std::cout << "keyboard device: " << libinput_device_get_name(&libDev) << std::endl; + EXPECT_EQ(INPUT_DEV_MGR->IsKeyboardDevice(&libDev), true); + KeyEventHdr->keyEvent_ = nullptr; + EXPECT_CALL(libinputMock, HasEventLedType).WillOnce(testing::Return(0)); + EXPECT_NO_FATAL_FAILURE(KeyEventHdr->ResetKeyEvent(&libDev)); } /** * @tc.name: KeyEventNormalizeTest_ResetKeyEvent_002 - * @tc.desc: Test ResetKeyEvent + * @tc.desc: Test ResetKeyEvent with a device without led and valid keyEvent. * @tc.type: FUNC * @tc.require: */ -HWTEST_F(KeyEventNormalizeTest, KeyEventNormalizeTest_ResetKeyEvent_002, TestSize.Level1) +HWTEST_F(KeyEventNormalizeTest, KeyEventNormalizeTest_ResetKeyEvent_LedOff_002, TestSize.Level1) { CALL_TEST_DEBUG; - vKeyboard_.SendEvent(EV_KEY, 29, 1); - vKeyboard_.SendEvent(EV_KEY, KEY_C, 1); - vKeyboard_.SendEvent(EV_SYN, SYN_REPORT, 0); - vKeyboard_.SendEvent(EV_KEY, KEY_C, 0); - vKeyboard_.SendEvent(EV_KEY, 29, 0); - vKeyboard_.SendEvent(EV_SYN, SYN_REPORT, 0); - libinput_event *event = libinput_.Dispatch(); - ASSERT_TRUE(event != nullptr); - struct libinput_device *dev = libinput_event_get_device(event); - ASSERT_TRUE(dev != nullptr); - std::cout << "keyboard device: " << libinput_device_get_name(dev) << std::endl; - std::shared_ptr keyEvent = KeyEvent::Create(); - ASSERT_TRUE(keyEvent != nullptr); - EXPECT_NO_FATAL_FAILURE(KeyEventHdr->ResetKeyEvent(dev)); + testing::NiceMock libinputMock; + // create a node for keyboard. + struct libinput_device libDev { + .udevDev { 2 }, + .busType = 1, + .version = 1, + .product = 1, + .vendor = 1, + .name = "test", + }; + std::cout << "keyboard device: " << libinput_device_get_name(&libDev) << std::endl; + EXPECT_EQ(INPUT_DEV_MGR->IsKeyboardDevice(&libDev), true); + KeyEventHdr->keyEvent_ = KeyEvent::Create(); + ASSERT_TRUE(KeyEventHdr->keyEvent_ != nullptr); + EXPECT_CALL(libinputMock, HasEventLedType).WillOnce(testing::Return(0)); + EXPECT_NO_FATAL_FAILURE(KeyEventHdr->ResetKeyEvent(&libDev)); +} + +/** + * @tc.name: KeyEventNormalizeTest_ResetKeyEvent_003 + * @tc.desc: Test ResetKeyEvent with a device with led and null keyEvent. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(KeyEventNormalizeTest, KeyEventNormalizeTest_ResetKeyEvent_LedOn_003, TestSize.Level1) +{ + CALL_TEST_DEBUG; + testing::NiceMock libinputMock; + // create a node for keyboard. + struct libinput_device libDev { + .udevDev { 2 }, + .busType = 1, + .version = 1, + .product = 1, + .vendor = 1, + .name = "test", + }; + std::cout << "keyboard device: " << libinput_device_get_name(&libDev) << std::endl; + EXPECT_EQ(INPUT_DEV_MGR->IsKeyboardDevice(&libDev), true); + KeyEventHdr->keyEvent_ = nullptr; + EXPECT_CALL(libinputMock, HasEventLedType).WillOnce(testing::Return(1)); + // mock: all lights on. + EXPECT_CALL(libinputMock, GetFuncKeyState).WillRepeatedly(testing::Return(1)); + EXPECT_NO_FATAL_FAILURE(KeyEventHdr->ResetKeyEvent(&libDev)); + ASSERT_TRUE(KeyEventHdr->keyEvent_ != nullptr); + EXPECT_EQ(KeyEventHdr->keyEvent_->GetFunctionKey(KeyEvent::NUM_LOCK_FUNCTION_KEY), true); + EXPECT_EQ(KeyEventHdr->keyEvent_->GetFunctionKey(KeyEvent::CAPS_LOCK_FUNCTION_KEY), true); + EXPECT_EQ(KeyEventHdr->keyEvent_->GetFunctionKey(KeyEvent::SCROLL_LOCK_FUNCTION_KEY), true); +} + +/** + * @tc.name: KeyEventNormalizeTest_ResetKeyEvent_004 + * @tc.desc: Test ResetKeyEvent with a device with led and valid keyEvent. + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(KeyEventNormalizeTest, KeyEventNormalizeTest_ResetKeyEvent_LedOn_004, TestSize.Level1) +{ + CALL_TEST_DEBUG; + testing::NiceMock libinputMock; + // create a node for keyboard. + struct libinput_device libDev { + .udevDev { 2 }, + .busType = 1, + .version = 1, + .product = 1, + .vendor = 1, + .name = "test", + }; + std::cout << "keyboard device: " << libinput_device_get_name(&libDev) << std::endl; + EXPECT_EQ(INPUT_DEV_MGR->IsKeyboardDevice(&libDev), true); + KeyEventHdr->keyEvent_ = KeyEvent::Create(); + ASSERT_TRUE(KeyEventHdr->keyEvent_ != nullptr); + // original: 0, 1, 0. + KeyEventHdr->keyEvent_->SetFunctionKey(KeyEvent::NUM_LOCK_FUNCTION_KEY, 0); + KeyEventHdr->keyEvent_->SetFunctionKey(KeyEvent::CAPS_LOCK_FUNCTION_KEY, 1); + KeyEventHdr->keyEvent_->SetFunctionKey(KeyEvent::SCROLL_LOCK_FUNCTION_KEY, 0); + EXPECT_CALL(libinputMock, HasEventLedType).WillOnce(testing::Return(1)); + // mock: all lights on. + EXPECT_CALL(libinputMock, GetFuncKeyState).WillRepeatedly(testing::Return(1)); + EXPECT_NO_FATAL_FAILURE(KeyEventHdr->ResetKeyEvent(&libDev)); +#ifdef OHOS_BUILD_ENABLE_VKEYBOARD + // keyEvent unchanged: 0, 1, 0 + EXPECT_EQ(KeyEventHdr->keyEvent_->GetFunctionKey(KeyEvent::NUM_LOCK_FUNCTION_KEY), false); + EXPECT_EQ(KeyEventHdr->keyEvent_->GetFunctionKey(KeyEvent::CAPS_LOCK_FUNCTION_KEY), true); + EXPECT_EQ(KeyEventHdr->keyEvent_->GetFunctionKey(KeyEvent::SCROLL_LOCK_FUNCTION_KEY), false); +#endif // OHOS_BUILD_ENABLE_VKEYBOARD } /** diff --git a/service/libinput_adapter/src/libinput_adapter.cpp b/service/libinput_adapter/src/libinput_adapter.cpp index ed331b74404c8ba091ea1854591881d15e6219c4..38f0be7a90ddb4c02a3ab02eb78e9447e02b631e 100644 --- a/service/libinput_adapter/src/libinput_adapter.cpp +++ b/service/libinput_adapter/src/libinput_adapter.cpp @@ -421,12 +421,32 @@ void LibinputAdapter::HandleVFullKeyboardMessages( void LibinputAdapter::HandleVKeyboardMessage(VKeyboardEventType eventType, std::vector keyEvents, int64_t frameTime) { + bool isCapsLockOn = false; + bool libinputCapsLockOn = false; + if ((eventType == VKeyboardEventType::NormalKeyboardEvent || eventType == VKeyboardEventType::UpdateCaps) && + !keyEvents.empty()) { + // check current caps state. + std::shared_ptr sharedKeyEvent = KeyEventHdr->GetKeyEvent(); + auto device = libinput_event_get_device(keyEvents.front()); + if (sharedKeyEvent != nullptr && device != nullptr) { + isCapsLockOn = sharedKeyEvent->GetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY); + libinputCapsLockOn = + static_cast(libinput_get_funckey_state(device, MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY)); + } else { + MMI_HILOGW("Failed to sync virtual keyboard's Caps state given nullptr of keyEvent/device."); + } + } switch (eventType) { case VKeyboardEventType::NormalKeyboardEvent: { for (auto event : keyEvents) { funInputEvent_(event, frameTime); free(event); } + + if (libinputCapsLockOn != isCapsLockOn) { + // non-caps scenario, if a mismatch is found, sync it now. + libinput_toggle_caps_key(); + } break; } case VKeyboardEventType::UpdateCaps: { @@ -434,16 +454,15 @@ void LibinputAdapter::HandleVKeyboardMessage(VKeyboardEventType eventType, funInputEvent_(event, frameTime); free(event); } - struct libinput_device* device = INPUT_DEV_MGR->GetKeyboardDevice(); - if (device != nullptr) { - std::shared_ptr keyEvent = KeyEventHdr->GetKeyEvent(); - if (keyEvent != nullptr) { - bool isCapsLockOn = keyEvent->GetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY); - - DeviceLedUpdate(device, KeyEvent::CAPS_LOCK_FUNCTION_KEY, !isCapsLockOn); - keyEvent->SetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY, !isCapsLockOn); - } + + std::shared_ptr keyEvent = KeyEventHdr->GetKeyEvent(); + if (keyEvent != nullptr) { + keyEvent->SetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY, !isCapsLockOn); } + MultiKeyboardSetLedState(isCapsLockOn); + if (libinputCapsLockOn == isCapsLockOn) { + libinput_toggle_caps_key(); + } // no need to flip virtual keyboard's caps if it is already flipped. break; } case VKeyboardEventType::HideCursor: { @@ -796,7 +815,6 @@ type:%{private}d, accPressure:%{private}f, longAxis:%{private}d, shortAxis:%{pri && keyEvent != nullptr) { bool oldCapsLockOn = keyEvent->GetFunctionKey(MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY); libinput_device* device = libinput_event_get_device(event); - int libinputCaps = libinput_get_funckey_state(device, MMI::KeyEvent::CAPS_LOCK_FUNCTION_KEY); HandleHWKeyEventForVKeyboard(event); funInputEvent_(event, frameTime); diff --git a/test/facility/libinput_interface/include/libinput.h b/test/facility/libinput_interface/include/libinput.h index 225130143e3638474c9234d536b88611a5890546..f1a9da8654a6be23a6e67d978cadbae356643b53 100644 --- a/test/facility/libinput_interface/include/libinput.h +++ b/test/facility/libinput_interface/include/libinput.h @@ -60,6 +60,7 @@ struct libinput_event_joystick_axis_abs_info { enum libinput_event_type { LIBINPUT_EVENT_NONE = 0, + LIBINPUT_EVENT_DEVICE_ADDED, LIBINPUT_EVENT_KEYBOARD_KEY = 300, diff --git a/test/facility/libinput_interface/include/libinput_interface.h b/test/facility/libinput_interface/include/libinput_interface.h index 6e189605c05d93a6c7b6543e35bbe5c0f3978d4f..979911bd67e8d29b3f304caee32f63e2b068bcbd 100644 --- a/test/facility/libinput_interface/include/libinput_interface.h +++ b/test/facility/libinput_interface/include/libinput_interface.h @@ -143,6 +143,8 @@ public: virtual struct libinput_event_keyboard* LibinputEventGetKeyboardEvent (struct libinput_event *event) = 0; virtual uint32_t LibinputEventKeyboardGetKey (struct libinput_event_keyboard *event) = 0; virtual enum libinput_key_state LibinputEventKeyboardGetKeyState (struct libinput_event_keyboard *event) = 0; + virtual int HasEventLedType (struct libinput_device *device) = 0; + virtual int GetFuncKeyState (struct libinput_device *device, unsigned int code) = 0; }; } // namespace MMI } // namespace OHOS diff --git a/test/facility/libinput_interface/src/libinput_interface.cpp b/test/facility/libinput_interface/src/libinput_interface.cpp index bec5f07bc31e57c4a4e5e4592b650717b644467f..90b95cc13afc81d05dcb02f0c8eb7530af1931bb 100644 --- a/test/facility/libinput_interface/src/libinput_interface.cpp +++ b/test/facility/libinput_interface/src/libinput_interface.cpp @@ -338,7 +338,12 @@ int libinput_event_gesture_get_device_coords_y(struct libinput_event_gesture *ev int libinput_has_event_led_type(struct libinput_device *device) { - return 0; + return g_instance->HasEventLedType(device); +} + +int libinput_set_led_state(struct libinput_device *device, unsigned int code, unsigned int state) +{ + return 1; } const char* libinput_device_get_name(struct libinput_device *device) @@ -388,7 +393,11 @@ struct udev_device* libinput_device_get_udev_device(struct libinput_device *devi enum evdev_device_udev_tags libinput_device_get_tags(struct libinput_device* device) { - return EVDEV_UDEV_TAG_INPUT; + if (device == nullptr) { + return EVDEV_UDEV_TAG_INPUT; + } + enum evdev_device_udev_tags tag = static_cast(device->udevDev.tags); + return tag; } int libinput_device_has_capability(struct libinput_device *device, enum libinput_device_capability capability) @@ -433,7 +442,7 @@ int libinput_device_get_size(struct libinput_device *device, double *width, doub int libinput_get_funckey_state(struct libinput_device *device, unsigned int code) { - return 0; + return g_instance->GetFuncKeyState(device, code); } uint32_t libinput_event_pointer_get_finger_count(struct libinput_event_pointer *event) diff --git a/test/facility/mock/include/libinput_mock.h b/test/facility/mock/include/libinput_mock.h index 231b3f341f32f7c682da3563a22fe08d4666a5d8..149e1cbfc4868cc70a7127f945fa5a6f9741598c 100644 --- a/test/facility/mock/include/libinput_mock.h +++ b/test/facility/mock/include/libinput_mock.h @@ -71,6 +71,8 @@ public: MOCK_METHOD(struct libinput_event_keyboard*, LibinputEventGetKeyboardEvent, (struct libinput_event *)); MOCK_METHOD(uint32_t, LibinputEventKeyboardGetKey, (struct libinput_event_keyboard *)); MOCK_METHOD(enum libinput_key_state, LibinputEventKeyboardGetKeyState, (struct libinput_event_keyboard *)); + MOCK_METHOD(int, HasEventLedType, (struct libinput_device *)); + MOCK_METHOD(int, GetFuncKeyState, (struct libinput_device *, unsigned int)); }; } // namespace MMI } // namespace OHOS