fix combination mechanics

Signed-off-by: zhaolinglan <zhaolinglan@huawei.com>
This commit is contained in:
zhaolinglan 2023-01-07 17:00:39 +08:00
parent 6208a4d728
commit 7ba7a3dfb7
7 changed files with 106 additions and 23 deletions

View File

@ -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 <cstdint>
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

View File

@ -36,6 +36,7 @@ public:
private:
KeyHandle keyHandler_ = nullptr;
static uint32_t keyState_;
static int32_t lastPressedKey_;
};
} // namespace MiscServices
} // namespace OHOS

View File

@ -18,14 +18,13 @@
#include <cstdint>
#include <functional>
#include <set>
#include "global.h"
#include "key_event.h"
namespace OHOS {
namespace MiscServices {
using KeyHandle = std::function<int32_t(uint32_t)>;
using KeyHandle = std::function<int32_t(uint32_t, uint8_t lastDownKey)>;
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;

View File

@ -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 <list>
#include <map>
#include "keyboard_event.h"
namespace OHOS {
namespace MiscServices {
const std::map<CombinationKeyFunction, std::list<uint8_t>> 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

View File

@ -20,6 +20,7 @@
namespace OHOS {
namespace MiscServices {
uint32_t InputEventCallback::keyState_ = static_cast<uint32_t>(0);
int32_t InputEventCallback::lastPressedKey_ = MMI::KeyEvent::KEYCODE_UNKNOWN;
const std::map<int32_t, uint8_t> 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<MMI::KeyEvent> 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<MMI::KeyEvent> keyEvent) c
if (keyAction == MMI::KeyEvent::KEY_ACTION_DOWN) {
IMSA_HILOGD("key %{public}d pressed down", keyCode);
keyState_ = static_cast<uint32_t>(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<uint32_t>(keyState_ & ~currKey->second);

View File

@ -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<bool(const SubProperty &)>;
SubProperty FindSubPropertyByCompare(const std::string &bundleName, CompareHandler compare);
SubProperty GetExtends(const std::vector<Metadata> &metaData);
int32_t SwitchByCombinationKey(uint32_t state);
int32_t SwitchByCombinationKey(uint32_t state, uint8_t lastPressedKey);
int32_t QueryImeInfos(int32_t userId, std::vector<AppExecFwk::ExtensionAbilityInfo> &infos);
};

View File

@ -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,
[&current](const SubProperty &property) { return property.mode == "lower"; }) :
@ -1005,9 +1005,8 @@ int32_t InputMethodSystemAbility::SwitchByCombinationKey(uint32_t state)
[&current](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,
[&current](const SubProperty &property) { return property.language == "english"; }) :
@ -1015,11 +1014,8 @@ int32_t InputMethodSystemAbility::SwitchByCombinationKey(uint32_t state)
[&current](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<Property> 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