From 7ba7a3dfb7cb31051d789935794e0fcfc247b51b Mon Sep 17 00:00:00 2001 From: zhaolinglan Date: Sat, 7 Jan 2023 17:00:39 +0800 Subject: [PATCH] fix combination mechanics Signed-off-by: zhaolinglan --- .../keyboard/include/combination_key.h | 32 +++++++++++++ .../keyboard/include/input_event_callback.h | 1 + .../adapter/keyboard/include/keyboard_event.h | 7 +-- .../adapter/keyboard/src/combination_key.cpp | 47 +++++++++++++++++++ .../keyboard/src/input_event_callback.cpp | 16 ++++++- .../include/input_method_system_ability.h | 4 +- services/src/input_method_system_ability.cpp | 22 ++++----- 7 files changed, 106 insertions(+), 23 deletions(-) create mode 100644 services/adapter/keyboard/include/combination_key.h create mode 100644 services/adapter/keyboard/src/combination_key.cpp diff --git a/services/adapter/keyboard/include/combination_key.h b/services/adapter/keyboard/include/combination_key.h new file mode 100644 index 00000000..2d867194 --- /dev/null +++ b/services/adapter/keyboard/include/combination_key.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INPUTMETHOD_IMF_COMBINATION_KEY_H +#define INPUTMETHOD_IMF_COMBINATION_KEY_H + +#include + + +namespace OHOS { +namespace MiscServices { +enum class CombinationKeyFunction : uint32_t { SWITCH_LANGUAGE = 0, SWITCH_MODE, SWITCH_IME }; +class CombinationKey { +public: + static bool IsMatch(CombinationKeyFunction combinationKey, uint32_t state, uint8_t lastPressedKey); +}; +} +} // namespace OHOS + +#endif //INPUTMETHOD_IMF_COMBINATION_KEY_H diff --git a/services/adapter/keyboard/include/input_event_callback.h b/services/adapter/keyboard/include/input_event_callback.h index 1612fbe3..7179099f 100644 --- a/services/adapter/keyboard/include/input_event_callback.h +++ b/services/adapter/keyboard/include/input_event_callback.h @@ -36,6 +36,7 @@ public: private: KeyHandle keyHandler_ = nullptr; static uint32_t keyState_; + static int32_t lastPressedKey_; }; } // namespace MiscServices } // namespace OHOS diff --git a/services/adapter/keyboard/include/keyboard_event.h b/services/adapter/keyboard/include/keyboard_event.h index 2ad7df15..1c6faadf 100644 --- a/services/adapter/keyboard/include/keyboard_event.h +++ b/services/adapter/keyboard/include/keyboard_event.h @@ -18,14 +18,13 @@ #include #include -#include #include "global.h" #include "key_event.h" namespace OHOS { namespace MiscServices { -using KeyHandle = std::function; +using KeyHandle = std::function; class KeyboardEvent { public: @@ -36,10 +35,6 @@ public: static constexpr uint8_t CTRL_LEFT_MASK = 0X1 << 2; static constexpr uint8_t CTRL_RIGHT_MASK = 0X1 << 3; static constexpr uint8_t CAPS_MASK = 0X1 << 4; - static constexpr bool IS_KEYS_DOWN(uint32_t state, uint8_t mask) - { - return state == mask; - } private: static constexpr int32_t PRESS_KEY_DELAY_MS = 200; diff --git a/services/adapter/keyboard/src/combination_key.cpp b/services/adapter/keyboard/src/combination_key.cpp new file mode 100644 index 00000000..f3ef6702 --- /dev/null +++ b/services/adapter/keyboard/src/combination_key.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "combination_key.h" + +#include +#include + +#include "keyboard_event.h" + +namespace OHOS { +namespace MiscServices { +const std::map> COMBINATION_KEY_MAP{ + { CombinationKeyFunction::SWITCH_LANGUAGE, { KeyboardEvent::SHIFT_LEFT_MASK | KeyboardEvent::SHIFT_RIGHT_MASK } }, + { CombinationKeyFunction::SWITCH_IME, { KeyboardEvent::SHIFT_LEFT_MASK | KeyboardEvent::SHIFT_RIGHT_MASK, + KeyboardEvent::CTRL_LEFT_MASK | KeyboardEvent::CTRL_RIGHT_MASK } }, + { CombinationKeyFunction::SWITCH_MODE, { KeyboardEvent::CAPS_MASK } }, +}; + +bool CombinationKey::IsMatch(CombinationKeyFunction combinationKey, uint32_t state, uint8_t lastPressedKey) +{ + auto keys = COMBINATION_KEY_MAP.find(combinationKey); + bool isLastKeyMatch = false; + for (const auto &key : keys->second) { + if ((state & key) == 0) { + return false; + } + if ((lastPressedKey & key) != 0) { + isLastKeyMatch = true; + } + } + return isLastKeyMatch; +} +} // namespace MiscServices +} // namespace OHOS \ No newline at end of file diff --git a/services/adapter/keyboard/src/input_event_callback.cpp b/services/adapter/keyboard/src/input_event_callback.cpp index 3d213405..1e7ea7aa 100644 --- a/services/adapter/keyboard/src/input_event_callback.cpp +++ b/services/adapter/keyboard/src/input_event_callback.cpp @@ -20,6 +20,7 @@ namespace OHOS { namespace MiscServices { uint32_t InputEventCallback::keyState_ = static_cast(0); +int32_t InputEventCallback::lastPressedKey_ = MMI::KeyEvent::KEYCODE_UNKNOWN; const std::map MASK_MAP{ { MMI::KeyEvent::KEYCODE_SHIFT_LEFT, KeyboardEvent::SHIFT_LEFT_MASK }, { MMI::KeyEvent::KEYCODE_SHIFT_RIGHT, KeyboardEvent::SHIFT_RIGHT_MASK }, @@ -35,6 +36,9 @@ void InputEventCallback::OnInputEvent(std::shared_ptr keyEvent) c auto currKey = MASK_MAP.find(keyCode); if (currKey == MASK_MAP.end()) { IMSA_HILOGD("key code unknown"); + if (keyAction == MMI::KeyEvent::KEY_ACTION_DOWN) { + lastPressedKey_ = MMI::KeyEvent::KEYCODE_UNKNOWN; + } return; } IMSA_HILOGD("keyCode: %{public}d, keyAction: %{public}d", keyCode, keyAction); @@ -42,12 +46,20 @@ void InputEventCallback::OnInputEvent(std::shared_ptr keyEvent) c if (keyAction == MMI::KeyEvent::KEY_ACTION_DOWN) { IMSA_HILOGD("key %{public}d pressed down", keyCode); keyState_ = static_cast(keyState_ | currKey->second); + lastPressedKey_ = keyCode; + if (keyCode == MMI::KeyEvent::KEYCODE_CAPS_LOCK) { + if (keyHandler_ != nullptr) { + int32_t ret = keyHandler_(keyState_, KeyboardEvent::CAPS_MASK); + IMSA_HILOGI("handle key event ret: %{public}d", ret); + } + } return; } if (keyAction == MMI::KeyEvent::KEY_ACTION_UP) { - if (keyHandler_ != nullptr) { - int32_t ret = keyHandler_(keyState_); + auto lastPressedKey = MASK_MAP.find(lastPressedKey_); + if (keyHandler_ != nullptr && lastPressedKey != MASK_MAP.end()) { + int32_t ret = keyHandler_(keyState_, lastPressedKey->second); IMSA_HILOGI("handle key event ret: %{public}d", ret); } keyState_ = static_cast(keyState_ & ~currKey->second); diff --git a/services/include/input_method_system_ability.h b/services/include/input_method_system_ability.h index 657ac53e..482b4496 100644 --- a/services/include/input_method_system_ability.h +++ b/services/include/input_method_system_ability.h @@ -23,12 +23,12 @@ #include "ability_manager_interface.h" #include "application_info.h" #include "bundle_mgr_proxy.h" +#include "combination_key.h" #include "event_handler.h" #include "input_method_status.h" #include "input_method_system_ability_stub.h" #include "inputmethod_dump.h" #include "inputmethod_trace.h" -#include "keyboard_event.h" #include "peruser_session.h" #include "system_ability.h" @@ -124,7 +124,7 @@ private: using CompareHandler = std::function; SubProperty FindSubPropertyByCompare(const std::string &bundleName, CompareHandler compare); SubProperty GetExtends(const std::vector &metaData); - int32_t SwitchByCombinationKey(uint32_t state); + int32_t SwitchByCombinationKey(uint32_t state, uint8_t lastPressedKey); int32_t QueryImeInfos(int32_t userId, std::vector &infos); }; diff --git a/services/src/input_method_system_ability.cpp b/services/src/input_method_system_ability.cpp index f31c1480..0157933a 100644 --- a/services/src/input_method_system_ability.cpp +++ b/services/src/input_method_system_ability.cpp @@ -431,7 +431,7 @@ int32_t InputMethodSystemAbility::ListDisabledInputMethod(int32_t userId, std::v return ErrorCode::ERROR_NULL_POINTER; } for (auto iter = props.begin(); iter != props.end();) { - if (iter->name == filter->name && iter->id == filter->id) { + if (iter->name == filter->name) { iter = props.erase(iter); continue; } @@ -988,7 +988,7 @@ SubProperty InputMethodSystemAbility::FindSubPropertyByCompare(const std::string return {}; } -int32_t InputMethodSystemAbility::SwitchByCombinationKey(uint32_t state) +int32_t InputMethodSystemAbility::SwitchByCombinationKey(uint32_t state, uint8_t lastPressedKey) { IMSA_HILOGI("InputMethodSystemAbility::SwitchByCombinationKey"); auto current = GetCurrentInputMethodSubtype(); @@ -996,8 +996,8 @@ int32_t InputMethodSystemAbility::SwitchByCombinationKey(uint32_t state) IMSA_HILOGE("GetCurrentInputMethodSubtype failed"); return ErrorCode::ERROR_EX_NULL_POINTER; } - if (KeyboardEvent::IS_KEYS_DOWN(state, KeyboardEvent::CAPS_MASK)) { - IMSA_HILOGI("CAPS press"); + if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_MODE, state, lastPressedKey)) { + IMSA_HILOGI("switch mode"); auto target = current->mode == "upper" ? FindSubPropertyByCompare(current->id, [¤t](const SubProperty &property) { return property.mode == "lower"; }) : @@ -1005,9 +1005,8 @@ int32_t InputMethodSystemAbility::SwitchByCombinationKey(uint32_t state) [¤t](const SubProperty &property) { return property.mode == "upper"; }); return SwitchInputMethod(target.id, target.label); } - if (KeyboardEvent::IS_KEYS_DOWN(state, KeyboardEvent::SHIFT_LEFT_MASK) || - KeyboardEvent::IS_KEYS_DOWN(state, KeyboardEvent::SHIFT_RIGHT_MASK)) { - IMSA_HILOGI("SHIFT press"); + if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_LANGUAGE, state, lastPressedKey)) { + IMSA_HILOGI("switch language"); auto target = current->language == "chinese" ? FindSubPropertyByCompare(current->id, [¤t](const SubProperty &property) { return property.language == "english"; }) : @@ -1015,11 +1014,8 @@ int32_t InputMethodSystemAbility::SwitchByCombinationKey(uint32_t state) [¤t](const SubProperty &property) { return property.language == "chinese"; }); return SwitchInputMethod(target.id, target.label); } - if (KeyboardEvent::IS_KEYS_DOWN(state, KeyboardEvent::CTRL_LEFT_MASK | KeyboardEvent::SHIFT_LEFT_MASK) || - KeyboardEvent::IS_KEYS_DOWN(state, KeyboardEvent::CTRL_LEFT_MASK | KeyboardEvent::SHIFT_RIGHT_MASK) || - KeyboardEvent::IS_KEYS_DOWN(state, KeyboardEvent::CTRL_RIGHT_MASK | KeyboardEvent::SHIFT_LEFT_MASK) || - KeyboardEvent::IS_KEYS_DOWN(state, KeyboardEvent::CTRL_RIGHT_MASK | KeyboardEvent::SHIFT_RIGHT_MASK)) { - IMSA_HILOGI("CTRL_SHIFT press"); + if (CombinationKey::IsMatch(CombinationKeyFunction::SWITCH_IME, state, lastPressedKey)) { + IMSA_HILOGI("switch ime"); std::vector props = {}; auto ret = ListProperty(MAIN_USER_ID, props); if (ret != ErrorCode::NO_ERROR) { @@ -1040,7 +1036,7 @@ int32_t InputMethodSystemAbility::InitKeyEventMonitor() { IMSA_HILOGI("InputMethodSystemAbility::InitKeyEventMonitor"); bool ret = ImCommonEventManager::GetInstance()->SubscribeKeyboardEvent( - [this](uint32_t keyCode) { return SwitchByCombinationKey(keyCode); }); + [this](uint32_t keyCode, uint8_t lastPressedKey) { return SwitchByCombinationKey(keyCode, lastPressedKey); }); return ret ? ErrorCode::NO_ERROR : ErrorCode::ERROR_SERVICE_START_FAILED; } } // namespace MiscServices