1c29fa5a6Sopenharmony_ci/* 2c29fa5a6Sopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 3c29fa5a6Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4c29fa5a6Sopenharmony_ci * you may not use this file except in compliance with the License. 5c29fa5a6Sopenharmony_ci * You may obtain a copy of the License at 6c29fa5a6Sopenharmony_ci * 7c29fa5a6Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8c29fa5a6Sopenharmony_ci * 9c29fa5a6Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10c29fa5a6Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11c29fa5a6Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12c29fa5a6Sopenharmony_ci * See the License for the specific language governing permissions and 13c29fa5a6Sopenharmony_ci * limitations under the License. 14c29fa5a6Sopenharmony_ci */ 15c29fa5a6Sopenharmony_ci 16c29fa5a6Sopenharmony_ci#include "key_shortcut_manager.h" 17c29fa5a6Sopenharmony_ci 18c29fa5a6Sopenharmony_ci#include <config_policy_utils.h> 19c29fa5a6Sopenharmony_ci 20c29fa5a6Sopenharmony_ci#include "app_state_observer.h" 21c29fa5a6Sopenharmony_ci#include "define_multimodal.h" 22c29fa5a6Sopenharmony_ci#include "key_command_handler_util.h" 23c29fa5a6Sopenharmony_ci 24c29fa5a6Sopenharmony_ci#undef MMI_LOG_DOMAIN 25c29fa5a6Sopenharmony_ci#define MMI_LOG_DOMAIN MMI_LOG_HANDLER 26c29fa5a6Sopenharmony_ci#undef MMI_LOG_TAG 27c29fa5a6Sopenharmony_ci#define MMI_LOG_TAG "KeyShortcutManager" 28c29fa5a6Sopenharmony_ci 29c29fa5a6Sopenharmony_cinamespace OHOS { 30c29fa5a6Sopenharmony_cinamespace MMI { 31c29fa5a6Sopenharmony_cinamespace { 32c29fa5a6Sopenharmony_ciconstexpr size_t SINGLE_MODIFIER { 1 }; 33c29fa5a6Sopenharmony_ciconstexpr size_t MAX_N_PRINTABLE_ITEMS { 3 }; 34c29fa5a6Sopenharmony_ciconstexpr int32_t MAXIMUM_LONG_PRESS_TIME { 60000 }; // 60s 35c29fa5a6Sopenharmony_ciconstexpr int32_t REPEAT_ONCE { 1 }; 36c29fa5a6Sopenharmony_ci} 37c29fa5a6Sopenharmony_ci 38c29fa5a6Sopenharmony_cistd::mutex KeyShortcutManager::mutex_; 39c29fa5a6Sopenharmony_cistd::shared_ptr<KeyShortcutManager> KeyShortcutManager::instance_; 40c29fa5a6Sopenharmony_ci 41c29fa5a6Sopenharmony_ciconst std::map<int32_t, uint32_t> KeyShortcutManager::modifiers_ { 42c29fa5a6Sopenharmony_ci { KeyEvent::KEYCODE_ALT_LEFT, SHORTCUT_MODIFIER_ALT }, 43c29fa5a6Sopenharmony_ci { KeyEvent::KEYCODE_ALT_RIGHT, SHORTCUT_MODIFIER_ALT }, 44c29fa5a6Sopenharmony_ci { KeyEvent::KEYCODE_SHIFT_LEFT, SHORTCUT_MODIFIER_SHIFT }, 45c29fa5a6Sopenharmony_ci { KeyEvent::KEYCODE_SHIFT_RIGHT, SHORTCUT_MODIFIER_SHIFT }, 46c29fa5a6Sopenharmony_ci { KeyEvent::KEYCODE_CTRL_LEFT, SHORTCUT_MODIFIER_CTRL }, 47c29fa5a6Sopenharmony_ci { KeyEvent::KEYCODE_CTRL_RIGHT, SHORTCUT_MODIFIER_CTRL }, 48c29fa5a6Sopenharmony_ci { KeyEvent::KEYCODE_META_LEFT, SHORTCUT_MODIFIER_LOGO }, 49c29fa5a6Sopenharmony_ci { KeyEvent::KEYCODE_META_RIGHT, SHORTCUT_MODIFIER_LOGO } 50c29fa5a6Sopenharmony_ci}; 51c29fa5a6Sopenharmony_ci 52c29fa5a6Sopenharmony_cibool KeyShortcutManager::SystemKey::operator<(const SystemKey &other) const 53c29fa5a6Sopenharmony_ci{ 54c29fa5a6Sopenharmony_ci uint32_t modifier1 = (modifiers & SHORTCUT_MODIFIER_MASK); 55c29fa5a6Sopenharmony_ci uint32_t modifier2 = (other.modifiers & SHORTCUT_MODIFIER_MASK); 56c29fa5a6Sopenharmony_ci if (modifier1 != modifier2) { 57c29fa5a6Sopenharmony_ci return (modifier1 < modifier2); 58c29fa5a6Sopenharmony_ci } 59c29fa5a6Sopenharmony_ci return (finalKey < other.finalKey); 60c29fa5a6Sopenharmony_ci} 61c29fa5a6Sopenharmony_ci 62c29fa5a6Sopenharmony_cibool KeyShortcutManager::ExceptionalSystemKey::operator<(const ExceptionalSystemKey &other) const 63c29fa5a6Sopenharmony_ci{ 64c29fa5a6Sopenharmony_ci if (finalKey != other.finalKey) { 65c29fa5a6Sopenharmony_ci return (finalKey < other.finalKey); 66c29fa5a6Sopenharmony_ci } 67c29fa5a6Sopenharmony_ci if (longPressTime != other.longPressTime) { 68c29fa5a6Sopenharmony_ci return (longPressTime < other.longPressTime); 69c29fa5a6Sopenharmony_ci } 70c29fa5a6Sopenharmony_ci if (triggerType != other.triggerType) { 71c29fa5a6Sopenharmony_ci return (triggerType < other.triggerType); 72c29fa5a6Sopenharmony_ci } 73c29fa5a6Sopenharmony_ci return (preKeys < other.preKeys); 74c29fa5a6Sopenharmony_ci} 75c29fa5a6Sopenharmony_ci 76c29fa5a6Sopenharmony_cibool KeyShortcutManager::SystemHotkey::operator<(const SystemHotkey &other) const 77c29fa5a6Sopenharmony_ci{ 78c29fa5a6Sopenharmony_ci if (finalKey != other.finalKey) { 79c29fa5a6Sopenharmony_ci return (finalKey < other.finalKey); 80c29fa5a6Sopenharmony_ci } 81c29fa5a6Sopenharmony_ci return (preKeys < other.preKeys); 82c29fa5a6Sopenharmony_ci} 83c29fa5a6Sopenharmony_ci 84c29fa5a6Sopenharmony_cistd::shared_ptr<KeyShortcutManager> KeyShortcutManager::GetInstance() 85c29fa5a6Sopenharmony_ci{ 86c29fa5a6Sopenharmony_ci if (instance_ == nullptr) { 87c29fa5a6Sopenharmony_ci std::lock_guard<std::mutex> guard(mutex_); 88c29fa5a6Sopenharmony_ci if (instance_ == nullptr) { 89c29fa5a6Sopenharmony_ci instance_ = std::make_shared<KeyShortcutManager>(); 90c29fa5a6Sopenharmony_ci } 91c29fa5a6Sopenharmony_ci } 92c29fa5a6Sopenharmony_ci return instance_; 93c29fa5a6Sopenharmony_ci} 94c29fa5a6Sopenharmony_ci 95c29fa5a6Sopenharmony_ciKeyShortcutManager::KeyShortcutManager() 96c29fa5a6Sopenharmony_ci{ 97c29fa5a6Sopenharmony_ci LoadSystemKeys(); 98c29fa5a6Sopenharmony_ci LoadExceptionalSystemKeys(); 99c29fa5a6Sopenharmony_ci LoadHotkeys(); 100c29fa5a6Sopenharmony_ci} 101c29fa5a6Sopenharmony_ci 102c29fa5a6Sopenharmony_ciint32_t KeyShortcutManager::RegisterSystemKey(const SystemShortcutKey &key) 103c29fa5a6Sopenharmony_ci{ 104c29fa5a6Sopenharmony_ci KeyShortcut shortcut {}; 105c29fa5a6Sopenharmony_ci ExceptionalSystemKey eSysKey { 106c29fa5a6Sopenharmony_ci .preKeys = key.modifiers, 107c29fa5a6Sopenharmony_ci .finalKey = key.finalKey, 108c29fa5a6Sopenharmony_ci .longPressTime = key.longPressTime, 109c29fa5a6Sopenharmony_ci .triggerType = key.triggerType, 110c29fa5a6Sopenharmony_ci }; 111c29fa5a6Sopenharmony_ci 112c29fa5a6Sopenharmony_ci if (!CheckSystemKey(key, shortcut)) { 113c29fa5a6Sopenharmony_ci MMI_HILOGE("Not system key ([%{public}s],FinalKey:%{public}d,PressTime:%{public}d,TriggerType:%{public}d)", 114c29fa5a6Sopenharmony_ci FormatModifiers(key.modifiers).c_str(), key.finalKey, key.longPressTime, key.triggerType); 115c29fa5a6Sopenharmony_ci if (IsExceptionalSystemKey(eSysKey)) { 116c29fa5a6Sopenharmony_ci auto shortcutId = GenerateId(); 117c29fa5a6Sopenharmony_ci MMI_HILOGI("Register exceptional system key [No.%{public}d]" 118c29fa5a6Sopenharmony_ci "([%{public}s],FinalKey:%{public}d,PressTime:%{public}d,TriggerType:%{public}d)", 119c29fa5a6Sopenharmony_ci shortcutId, FormatModifiers(key.modifiers).c_str(), key.finalKey, key.longPressTime, key.triggerType); 120c29fa5a6Sopenharmony_ci return shortcutId; 121c29fa5a6Sopenharmony_ci } 122c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_COMBINATION_KEY; 123c29fa5a6Sopenharmony_ci } 124c29fa5a6Sopenharmony_ci if (!IsReservedSystemKey(shortcut)) { 125c29fa5a6Sopenharmony_ci if (IsExceptionalSystemKey(eSysKey)) { 126c29fa5a6Sopenharmony_ci auto shortcutId = GenerateId(); 127c29fa5a6Sopenharmony_ci MMI_HILOGI("Register exceptional system key [No.%{public}d]" 128c29fa5a6Sopenharmony_ci "([%{public}s],FinalKey:%{public}d,PressTime:%{public}d,TriggerType:%{public}d)", 129c29fa5a6Sopenharmony_ci shortcutId, FormatModifiers(key.modifiers).c_str(), key.finalKey, key.longPressTime, key.triggerType); 130c29fa5a6Sopenharmony_ci return shortcutId; 131c29fa5a6Sopenharmony_ci } 132c29fa5a6Sopenharmony_ci MMI_HILOGE("The system application can only subscribe to reserved shortcuts"); 133c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_COMBINATION_KEY; 134c29fa5a6Sopenharmony_ci } 135c29fa5a6Sopenharmony_ci auto [iter, _] = shortcuts_.emplace(GenerateId(), shortcut); 136c29fa5a6Sopenharmony_ci MMI_HILOGI("Register system key [No.%{public}d](0x%{public}x,%{public}d,%{public}d,%{public}d,%{public}d)", 137c29fa5a6Sopenharmony_ci iter->first, shortcut.modifiers, shortcut.finalKey, shortcut.longPressTime, 138c29fa5a6Sopenharmony_ci shortcut.triggerType, shortcut.session); 139c29fa5a6Sopenharmony_ci return iter->first; 140c29fa5a6Sopenharmony_ci} 141c29fa5a6Sopenharmony_ci 142c29fa5a6Sopenharmony_civoid KeyShortcutManager::UnregisterSystemKey(int32_t shortcutId) 143c29fa5a6Sopenharmony_ci{ 144c29fa5a6Sopenharmony_ci auto iter = shortcuts_.find(shortcutId); 145c29fa5a6Sopenharmony_ci if (iter == shortcuts_.end()) { 146c29fa5a6Sopenharmony_ci MMI_HILOGI("There is no system key(%{public}d)", shortcutId); 147c29fa5a6Sopenharmony_ci return; 148c29fa5a6Sopenharmony_ci } 149c29fa5a6Sopenharmony_ci const KeyShortcut &key = iter->second; 150c29fa5a6Sopenharmony_ci MMI_HILOGI("Unregister system key(0x%{public}x,%{public}d,%{public}d,%{public}d,SESSION:%{public}d)", 151c29fa5a6Sopenharmony_ci key.modifiers, key.finalKey, key.longPressTime, key.triggerType, key.session); 152c29fa5a6Sopenharmony_ci ResetTriggering(shortcutId); 153c29fa5a6Sopenharmony_ci shortcuts_.erase(iter); 154c29fa5a6Sopenharmony_ci} 155c29fa5a6Sopenharmony_ci 156c29fa5a6Sopenharmony_ciint32_t KeyShortcutManager::RegisterHotKey(const HotKey &key) 157c29fa5a6Sopenharmony_ci{ 158c29fa5a6Sopenharmony_ci KeyShortcut globalKey {}; 159c29fa5a6Sopenharmony_ci 160c29fa5a6Sopenharmony_ci if (!CheckGlobalKey(key, globalKey)) { 161c29fa5a6Sopenharmony_ci MMI_HILOGE("Not global shortcut key"); 162c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_COMBINATION_KEY; 163c29fa5a6Sopenharmony_ci } 164c29fa5a6Sopenharmony_ci if (HaveRegisteredGlobalKey(globalKey)) { 165c29fa5a6Sopenharmony_ci MMI_HILOGE("Global key (0x%{public}x, %{public}d) has been taken", globalKey.modifiers, globalKey.finalKey); 166c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_TAKEN; 167c29fa5a6Sopenharmony_ci } 168c29fa5a6Sopenharmony_ci if (IsReservedSystemKey(globalKey)) { 169c29fa5a6Sopenharmony_ci MMI_HILOGE("Can not register reserved system key ([%{public}s],%{public}d)", 170c29fa5a6Sopenharmony_ci FormatModifiers(key.modifiers).c_str(), key.finalKey); 171c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_COMBINATION_KEY; 172c29fa5a6Sopenharmony_ci } 173c29fa5a6Sopenharmony_ci auto [iter, _] = shortcuts_.emplace(GenerateId(), globalKey); 174c29fa5a6Sopenharmony_ci MMI_HILOGI("Register global key [No.%{public}d](0x%{public}x,%{public}d,SESSION:%{public}d)", 175c29fa5a6Sopenharmony_ci iter->first, globalKey.modifiers, globalKey.finalKey, globalKey.session); 176c29fa5a6Sopenharmony_ci return iter->first; 177c29fa5a6Sopenharmony_ci} 178c29fa5a6Sopenharmony_ci 179c29fa5a6Sopenharmony_civoid KeyShortcutManager::UnregisterHotKey(int32_t shortcutId) 180c29fa5a6Sopenharmony_ci{ 181c29fa5a6Sopenharmony_ci auto iter = shortcuts_.find(shortcutId); 182c29fa5a6Sopenharmony_ci if (iter == shortcuts_.end()) { 183c29fa5a6Sopenharmony_ci MMI_HILOGI("There is no global key(%{public}d)", shortcutId); 184c29fa5a6Sopenharmony_ci return; 185c29fa5a6Sopenharmony_ci } 186c29fa5a6Sopenharmony_ci const KeyShortcut &key = iter->second; 187c29fa5a6Sopenharmony_ci MMI_HILOGI("Unregister global key(0x%{public}x,%{public}d,SESSION:%{public}d)", 188c29fa5a6Sopenharmony_ci key.modifiers, key.finalKey, key.session); 189c29fa5a6Sopenharmony_ci shortcuts_.erase(iter); 190c29fa5a6Sopenharmony_ci} 191c29fa5a6Sopenharmony_ci 192c29fa5a6Sopenharmony_cibool KeyShortcutManager::HandleEvent(std::shared_ptr<KeyEvent> keyEvent) 193c29fa5a6Sopenharmony_ci{ 194c29fa5a6Sopenharmony_ci CHKPF(keyEvent); 195c29fa5a6Sopenharmony_ci MMI_HILOGI("Handle key event(No.%{public}d,KC:%{public}d,KA:%{public}d,PressedKeys:[%{public}s])", 196c29fa5a6Sopenharmony_ci keyEvent->GetId(), keyEvent->GetKeyCode(), keyEvent->GetKeyAction(), FormatPressedKeys(keyEvent).c_str()); 197c29fa5a6Sopenharmony_ci ResetTriggering(keyEvent); 198c29fa5a6Sopenharmony_ci if (keyEvent->GetKeyAction() == KeyEvent::KEY_ACTION_DOWN) { 199c29fa5a6Sopenharmony_ci return HandleKeyDown(keyEvent); 200c29fa5a6Sopenharmony_ci } else if (keyEvent->GetKeyAction() == KeyEvent::KEY_ACTION_UP) { 201c29fa5a6Sopenharmony_ci return HandleKeyUp(keyEvent); 202c29fa5a6Sopenharmony_ci } else if (keyEvent->GetKeyAction() == KeyEvent::KEY_ACTION_CANCEL) { 203c29fa5a6Sopenharmony_ci return HandleKeyCancel(keyEvent); 204c29fa5a6Sopenharmony_ci } 205c29fa5a6Sopenharmony_ci return false; 206c29fa5a6Sopenharmony_ci} 207c29fa5a6Sopenharmony_ci 208c29fa5a6Sopenharmony_civoid KeyShortcutManager::LoadSystemKeys() 209c29fa5a6Sopenharmony_ci{ 210c29fa5a6Sopenharmony_ci char cfgName[] { "etc/multimodalinput/system_keys_config.json" }; 211c29fa5a6Sopenharmony_ci char buf[MAX_PATH_LEN] {}; 212c29fa5a6Sopenharmony_ci char *cfgPath = ::GetOneCfgFile(cfgName, buf, sizeof(buf)); 213c29fa5a6Sopenharmony_ci 214c29fa5a6Sopenharmony_ci if (cfgPath == nullptr) { 215c29fa5a6Sopenharmony_ci MMI_HILOGE("No '%{public}s' was found", cfgPath); 216c29fa5a6Sopenharmony_ci return; 217c29fa5a6Sopenharmony_ci } 218c29fa5a6Sopenharmony_ci MMI_HILOGI("Config of system keys:%{public}s", cfgPath); 219c29fa5a6Sopenharmony_ci ReadSystemKeys(std::string(cfgPath)); 220c29fa5a6Sopenharmony_ci} 221c29fa5a6Sopenharmony_ci 222c29fa5a6Sopenharmony_civoid KeyShortcutManager::ReadSystemKeys(const std::string &cfgPath) 223c29fa5a6Sopenharmony_ci{ 224c29fa5a6Sopenharmony_ci std::string cfg = ReadJsonFile(cfgPath); 225c29fa5a6Sopenharmony_ci JsonParser parser; 226c29fa5a6Sopenharmony_ci parser.json_ = cJSON_Parse(cfg.c_str()); 227c29fa5a6Sopenharmony_ci if (!cJSON_IsObject(parser.json_)) { 228c29fa5a6Sopenharmony_ci MMI_HILOGE("Not json format"); 229c29fa5a6Sopenharmony_ci return; 230c29fa5a6Sopenharmony_ci } 231c29fa5a6Sopenharmony_ci cJSON* jsonSysKeys = cJSON_GetObjectItemCaseSensitive(parser.json_, "SystemKeys"); 232c29fa5a6Sopenharmony_ci if (!cJSON_IsArray(jsonSysKeys)) { 233c29fa5a6Sopenharmony_ci MMI_HILOGE("jsonSysKeys is not array"); 234c29fa5a6Sopenharmony_ci return; 235c29fa5a6Sopenharmony_ci } 236c29fa5a6Sopenharmony_ci int32_t nSysKeys = cJSON_GetArraySize(jsonSysKeys); 237c29fa5a6Sopenharmony_ci for (int32_t index = 0; index < nSysKeys; ++index) { 238c29fa5a6Sopenharmony_ci cJSON *jsonSysKey = cJSON_GetArrayItem(jsonSysKeys, index); 239c29fa5a6Sopenharmony_ci ReadSystemKey(jsonSysKey); 240c29fa5a6Sopenharmony_ci } 241c29fa5a6Sopenharmony_ci} 242c29fa5a6Sopenharmony_ci 243c29fa5a6Sopenharmony_ciint32_t KeyShortcutManager::ReadSystemKey(cJSON *jsonSysKey) 244c29fa5a6Sopenharmony_ci{ 245c29fa5a6Sopenharmony_ci if (!cJSON_IsObject(jsonSysKey)) { 246c29fa5a6Sopenharmony_ci MMI_HILOGE("Not json object"); 247c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_CONFIG; 248c29fa5a6Sopenharmony_ci } 249c29fa5a6Sopenharmony_ci cJSON *jsonPreKeys = cJSON_GetObjectItem(jsonSysKey, "preKeys"); 250c29fa5a6Sopenharmony_ci if (!cJSON_IsArray(jsonPreKeys)) { 251c29fa5a6Sopenharmony_ci MMI_HILOGE("Expect array for PreKeys"); 252c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_CONFIG; 253c29fa5a6Sopenharmony_ci } 254c29fa5a6Sopenharmony_ci std::set<int32_t> preKeys; 255c29fa5a6Sopenharmony_ci int32_t nPreKeys = cJSON_GetArraySize(jsonPreKeys); 256c29fa5a6Sopenharmony_ci 257c29fa5a6Sopenharmony_ci for (int32_t index = 0; index < nPreKeys; ++index) { 258c29fa5a6Sopenharmony_ci cJSON *jsonPreKey = cJSON_GetArrayItem(jsonPreKeys, index); 259c29fa5a6Sopenharmony_ci if (!cJSON_IsNumber(jsonPreKey)) { 260c29fa5a6Sopenharmony_ci MMI_HILOGE("Expect number for PreKey"); 261c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_CONFIG; 262c29fa5a6Sopenharmony_ci } 263c29fa5a6Sopenharmony_ci preKeys.insert(static_cast<int32_t>(cJSON_GetNumberValue(jsonPreKey))); 264c29fa5a6Sopenharmony_ci } 265c29fa5a6Sopenharmony_ci cJSON *jsonFinalKey = cJSON_GetObjectItem(jsonSysKey, "finalKey"); 266c29fa5a6Sopenharmony_ci if (!cJSON_IsNumber(jsonFinalKey)) { 267c29fa5a6Sopenharmony_ci MMI_HILOGE("Expect number for FinalKey"); 268c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_CONFIG; 269c29fa5a6Sopenharmony_ci } 270c29fa5a6Sopenharmony_ci int32_t finalKey = static_cast<int32_t>(cJSON_GetNumberValue(jsonFinalKey)); 271c29fa5a6Sopenharmony_ci return AddSystemKey(preKeys, finalKey); 272c29fa5a6Sopenharmony_ci} 273c29fa5a6Sopenharmony_ci 274c29fa5a6Sopenharmony_ciint32_t KeyShortcutManager::AddSystemKey(const std::set<int32_t> &preKeys, int32_t finalKey) 275c29fa5a6Sopenharmony_ci{ 276c29fa5a6Sopenharmony_ci SystemShortcutKey sysKey { 277c29fa5a6Sopenharmony_ci .modifiers = preKeys, 278c29fa5a6Sopenharmony_ci .finalKey = finalKey, 279c29fa5a6Sopenharmony_ci }; 280c29fa5a6Sopenharmony_ci KeyShortcut shortcut {}; 281c29fa5a6Sopenharmony_ci 282c29fa5a6Sopenharmony_ci if (!CheckSystemKey(sysKey, shortcut)) { 283c29fa5a6Sopenharmony_ci MMI_HILOGE("Not system key ([%{public}s],%{public}d)", FormatModifiers(preKeys).c_str(), finalKey); 284c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_COMBINATION_KEY; 285c29fa5a6Sopenharmony_ci } 286c29fa5a6Sopenharmony_ci systemKeys_.emplace(SystemKey { 287c29fa5a6Sopenharmony_ci .modifiers = shortcut.modifiers, 288c29fa5a6Sopenharmony_ci .finalKey = shortcut.finalKey, 289c29fa5a6Sopenharmony_ci }); 290c29fa5a6Sopenharmony_ci return RET_OK; 291c29fa5a6Sopenharmony_ci} 292c29fa5a6Sopenharmony_ci 293c29fa5a6Sopenharmony_civoid KeyShortcutManager::LoadExceptionalSystemKeys() 294c29fa5a6Sopenharmony_ci{ 295c29fa5a6Sopenharmony_ci char cfgName[] { "etc/multimodalinput/exceptional_system_keys_config.json" }; 296c29fa5a6Sopenharmony_ci char buf[MAX_PATH_LEN] {}; 297c29fa5a6Sopenharmony_ci char *cfgPath = ::GetOneCfgFile(cfgName, buf, sizeof(buf)); 298c29fa5a6Sopenharmony_ci 299c29fa5a6Sopenharmony_ci if (cfgPath == nullptr) { 300c29fa5a6Sopenharmony_ci MMI_HILOGE("No '%{public}s' was found", cfgPath); 301c29fa5a6Sopenharmony_ci return; 302c29fa5a6Sopenharmony_ci } 303c29fa5a6Sopenharmony_ci MMI_HILOGI("Config of exceptional system keys:%{public}s", cfgPath); 304c29fa5a6Sopenharmony_ci ReadExceptionalSystemKeys(std::string(cfgPath)); 305c29fa5a6Sopenharmony_ci} 306c29fa5a6Sopenharmony_ci 307c29fa5a6Sopenharmony_civoid KeyShortcutManager::ReadExceptionalSystemKeys(const std::string &cfgPath) 308c29fa5a6Sopenharmony_ci{ 309c29fa5a6Sopenharmony_ci std::string cfg = ReadJsonFile(cfgPath); 310c29fa5a6Sopenharmony_ci JsonParser parser; 311c29fa5a6Sopenharmony_ci parser.json_ = cJSON_Parse(cfg.c_str()); 312c29fa5a6Sopenharmony_ci if (!cJSON_IsObject(parser.json_)) { 313c29fa5a6Sopenharmony_ci MMI_HILOGE("Not json format"); 314c29fa5a6Sopenharmony_ci return; 315c29fa5a6Sopenharmony_ci } 316c29fa5a6Sopenharmony_ci cJSON* jsonSysKeys = cJSON_GetObjectItemCaseSensitive(parser.json_, "ExceptionalSystemKeys"); 317c29fa5a6Sopenharmony_ci if (!cJSON_IsArray(jsonSysKeys)) { 318c29fa5a6Sopenharmony_ci MMI_HILOGE("jsonSysKeys is not array"); 319c29fa5a6Sopenharmony_ci return; 320c29fa5a6Sopenharmony_ci } 321c29fa5a6Sopenharmony_ci int32_t nSysKeys = cJSON_GetArraySize(jsonSysKeys); 322c29fa5a6Sopenharmony_ci for (int32_t index = 0; index < nSysKeys; ++index) { 323c29fa5a6Sopenharmony_ci cJSON *jsonSysKey = cJSON_GetArrayItem(jsonSysKeys, index); 324c29fa5a6Sopenharmony_ci ReadExceptionalSystemKey(jsonSysKey); 325c29fa5a6Sopenharmony_ci } 326c29fa5a6Sopenharmony_ci} 327c29fa5a6Sopenharmony_ci 328c29fa5a6Sopenharmony_ciint32_t KeyShortcutManager::ReadExceptionalSystemKey(cJSON *jsonSysKey) 329c29fa5a6Sopenharmony_ci{ 330c29fa5a6Sopenharmony_ci if (!cJSON_IsObject(jsonSysKey)) { 331c29fa5a6Sopenharmony_ci MMI_HILOGE("Not json object"); 332c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_CONFIG; 333c29fa5a6Sopenharmony_ci } 334c29fa5a6Sopenharmony_ci ExceptionalSystemKey sysKey {}; 335c29fa5a6Sopenharmony_ci cJSON *jsonPreKeys = cJSON_GetObjectItem(jsonSysKey, "preKeys"); 336c29fa5a6Sopenharmony_ci if (!cJSON_IsArray(jsonPreKeys)) { 337c29fa5a6Sopenharmony_ci MMI_HILOGE("Expect array for PreKeys"); 338c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_CONFIG; 339c29fa5a6Sopenharmony_ci } 340c29fa5a6Sopenharmony_ci int32_t nPreKeys = cJSON_GetArraySize(jsonPreKeys); 341c29fa5a6Sopenharmony_ci 342c29fa5a6Sopenharmony_ci for (int32_t index = 0; index < nPreKeys; ++index) { 343c29fa5a6Sopenharmony_ci cJSON *jsonPreKey = cJSON_GetArrayItem(jsonPreKeys, index); 344c29fa5a6Sopenharmony_ci if (!cJSON_IsNumber(jsonPreKey)) { 345c29fa5a6Sopenharmony_ci MMI_HILOGE("Expect number for PreKey"); 346c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_CONFIG; 347c29fa5a6Sopenharmony_ci } 348c29fa5a6Sopenharmony_ci sysKey.preKeys.insert(static_cast<int32_t>(cJSON_GetNumberValue(jsonPreKey))); 349c29fa5a6Sopenharmony_ci } 350c29fa5a6Sopenharmony_ci cJSON *jsonFinalKey = cJSON_GetObjectItem(jsonSysKey, "finalKey"); 351c29fa5a6Sopenharmony_ci if (!cJSON_IsNumber(jsonFinalKey)) { 352c29fa5a6Sopenharmony_ci MMI_HILOGE("Expect number for FinalKey"); 353c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_CONFIG; 354c29fa5a6Sopenharmony_ci } 355c29fa5a6Sopenharmony_ci sysKey.finalKey = static_cast<int32_t>(cJSON_GetNumberValue(jsonFinalKey)); 356c29fa5a6Sopenharmony_ci 357c29fa5a6Sopenharmony_ci cJSON *jsonPressTime = cJSON_GetObjectItem(jsonSysKey, "longPressTime"); 358c29fa5a6Sopenharmony_ci if (!cJSON_IsNumber(jsonPressTime)) { 359c29fa5a6Sopenharmony_ci MMI_HILOGE("Expect number for LongPressTime"); 360c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_CONFIG; 361c29fa5a6Sopenharmony_ci } 362c29fa5a6Sopenharmony_ci sysKey.longPressTime = static_cast<int32_t>(cJSON_GetNumberValue(jsonPressTime)); 363c29fa5a6Sopenharmony_ci 364c29fa5a6Sopenharmony_ci cJSON *jsonTriggerType = cJSON_GetObjectItem(jsonSysKey, "triggerType"); 365c29fa5a6Sopenharmony_ci char *triggerType = cJSON_GetStringValue(jsonTriggerType); 366c29fa5a6Sopenharmony_ci if ((triggerType == nullptr) || 367c29fa5a6Sopenharmony_ci ((std::strcmp(triggerType, "down") != 0) && (std::strcmp(triggerType, "up") != 0))) { 368c29fa5a6Sopenharmony_ci MMI_HILOGE("Expect down/up for TriggerType"); 369c29fa5a6Sopenharmony_ci return KEY_SHORTCUT_ERROR_CONFIG; 370c29fa5a6Sopenharmony_ci } 371c29fa5a6Sopenharmony_ci sysKey.triggerType = (std::strcmp(triggerType, "down") == 0 ? 372c29fa5a6Sopenharmony_ci SHORTCUT_TRIGGER_TYPE_DOWN : SHORTCUT_TRIGGER_TYPE_UP); 373c29fa5a6Sopenharmony_ci 374c29fa5a6Sopenharmony_ci AddExceptionalSystemKey(sysKey); 375c29fa5a6Sopenharmony_ci return RET_OK; 376c29fa5a6Sopenharmony_ci} 377c29fa5a6Sopenharmony_ci 378c29fa5a6Sopenharmony_civoid KeyShortcutManager::AddExceptionalSystemKey(const ExceptionalSystemKey &sysKey) 379c29fa5a6Sopenharmony_ci{ 380c29fa5a6Sopenharmony_ci MMI_HILOGI("Add exceptional system key ([%{public}s],FinalKey:%{public}d,PressTime:%{public}d,%{public}s)", 381c29fa5a6Sopenharmony_ci FormatModifiers(sysKey.preKeys).c_str(), sysKey.finalKey, sysKey.longPressTime, 382c29fa5a6Sopenharmony_ci (sysKey.triggerType == SHORTCUT_TRIGGER_TYPE_DOWN ? "down" : "up")); 383c29fa5a6Sopenharmony_ci exceptSysKeys_.emplace(sysKey); 384c29fa5a6Sopenharmony_ci} 385c29fa5a6Sopenharmony_ci 386c29fa5a6Sopenharmony_cistd::string KeyShortcutManager::FormatModifiers(const std::set<int32_t> &modifiers) const 387c29fa5a6Sopenharmony_ci{ 388c29fa5a6Sopenharmony_ci std::ostringstream sModifiers; 389c29fa5a6Sopenharmony_ci size_t nModifiers = 0; 390c29fa5a6Sopenharmony_ci 391c29fa5a6Sopenharmony_ci if (auto iter = modifiers.cbegin(); iter != modifiers.cend()) { 392c29fa5a6Sopenharmony_ci sModifiers << *iter; 393c29fa5a6Sopenharmony_ci ++nModifiers; 394c29fa5a6Sopenharmony_ci 395c29fa5a6Sopenharmony_ci for (++iter; iter != modifiers.cend(); ++iter) { 396c29fa5a6Sopenharmony_ci if (nModifiers > MAX_N_PRINTABLE_ITEMS) { 397c29fa5a6Sopenharmony_ci sModifiers << ",..."; 398c29fa5a6Sopenharmony_ci break; 399c29fa5a6Sopenharmony_ci } 400c29fa5a6Sopenharmony_ci sModifiers << "," << *iter; 401c29fa5a6Sopenharmony_ci ++nModifiers; 402c29fa5a6Sopenharmony_ci } 403c29fa5a6Sopenharmony_ci } 404c29fa5a6Sopenharmony_ci return sModifiers.str(); 405c29fa5a6Sopenharmony_ci} 406c29fa5a6Sopenharmony_ci 407c29fa5a6Sopenharmony_ciint32_t KeyShortcutManager::GenerateId() const 408c29fa5a6Sopenharmony_ci{ 409c29fa5a6Sopenharmony_ci static int32_t baseId {}; 410c29fa5a6Sopenharmony_ci return ++baseId; 411c29fa5a6Sopenharmony_ci} 412c29fa5a6Sopenharmony_ci 413c29fa5a6Sopenharmony_cibool KeyShortcutManager::IsExceptionalSystemKey(const ExceptionalSystemKey &sysKey) const 414c29fa5a6Sopenharmony_ci{ 415c29fa5a6Sopenharmony_ci return (exceptSysKeys_.find(sysKey) != exceptSysKeys_.cend()); 416c29fa5a6Sopenharmony_ci} 417c29fa5a6Sopenharmony_ci 418c29fa5a6Sopenharmony_cibool KeyShortcutManager::IsModifier(int32_t keyCode) const 419c29fa5a6Sopenharmony_ci{ 420c29fa5a6Sopenharmony_ci return (modifiers_.find(keyCode) != modifiers_.cend()); 421c29fa5a6Sopenharmony_ci} 422c29fa5a6Sopenharmony_ci 423c29fa5a6Sopenharmony_cibool KeyShortcutManager::IsValid(const ShortcutTriggerType triggerType) const 424c29fa5a6Sopenharmony_ci{ 425c29fa5a6Sopenharmony_ci return ((triggerType == SHORTCUT_TRIGGER_TYPE_DOWN) || 426c29fa5a6Sopenharmony_ci (triggerType == SHORTCUT_TRIGGER_TYPE_UP)); 427c29fa5a6Sopenharmony_ci} 428c29fa5a6Sopenharmony_ci 429c29fa5a6Sopenharmony_cibool KeyShortcutManager::IsReservedSystemKey(const KeyShortcut &shortcut) const 430c29fa5a6Sopenharmony_ci{ 431c29fa5a6Sopenharmony_ci return (systemKeys_.find(SystemKey { 432c29fa5a6Sopenharmony_ci .modifiers = shortcut.modifiers, 433c29fa5a6Sopenharmony_ci .finalKey = shortcut.finalKey, 434c29fa5a6Sopenharmony_ci }) != systemKeys_.cend()); 435c29fa5a6Sopenharmony_ci} 436c29fa5a6Sopenharmony_ci 437c29fa5a6Sopenharmony_cibool KeyShortcutManager::CheckSystemKey(const SystemShortcutKey &key, KeyShortcut &shortcut) const 438c29fa5a6Sopenharmony_ci{ 439c29fa5a6Sopenharmony_ci size_t nModifiers = 0; 440c29fa5a6Sopenharmony_ci uint32_t modifiers = 0U; 441c29fa5a6Sopenharmony_ci 442c29fa5a6Sopenharmony_ci for (auto keyCode : key.modifiers) { 443c29fa5a6Sopenharmony_ci auto iter = modifiers_.find(keyCode); 444c29fa5a6Sopenharmony_ci if (iter == modifiers_.end()) { 445c29fa5a6Sopenharmony_ci MMI_HILOGE("Key code (%{public}d) is not modifier", keyCode); 446c29fa5a6Sopenharmony_ci return false; 447c29fa5a6Sopenharmony_ci } 448c29fa5a6Sopenharmony_ci if ((modifiers & iter->second) != iter->second) { 449c29fa5a6Sopenharmony_ci modifiers |= iter->second; 450c29fa5a6Sopenharmony_ci ++nModifiers; 451c29fa5a6Sopenharmony_ci } 452c29fa5a6Sopenharmony_ci } 453c29fa5a6Sopenharmony_ci if (nModifiers < SINGLE_MODIFIER) { 454c29fa5a6Sopenharmony_ci MMI_HILOGE("Require modifier(s)"); 455c29fa5a6Sopenharmony_ci return false; 456c29fa5a6Sopenharmony_ci } 457c29fa5a6Sopenharmony_ci if (key.finalKey == SHORTCUT_PURE_MODIFIERS) { 458c29fa5a6Sopenharmony_ci if ((nModifiers == SINGLE_MODIFIER) && (modifiers != SHORTCUT_MODIFIER_LOGO)) { 459c29fa5a6Sopenharmony_ci MMI_HILOGE("Only 'Logo' can be one-key shortcut"); 460c29fa5a6Sopenharmony_ci return false; 461c29fa5a6Sopenharmony_ci } 462c29fa5a6Sopenharmony_ci } else if (IsModifier(key.finalKey)) { 463c29fa5a6Sopenharmony_ci MMI_HILOGE("Modifier as final key"); 464c29fa5a6Sopenharmony_ci return false; 465c29fa5a6Sopenharmony_ci } 466c29fa5a6Sopenharmony_ci if (!IsValid(key.triggerType)) { 467c29fa5a6Sopenharmony_ci MMI_HILOGE("Invalid trigger type(%{public}d)", key.triggerType); 468c29fa5a6Sopenharmony_ci return false; 469c29fa5a6Sopenharmony_ci } 470c29fa5a6Sopenharmony_ci if ((key.longPressTime < 0) || (key.longPressTime > MAXIMUM_LONG_PRESS_TIME)) { 471c29fa5a6Sopenharmony_ci MMI_HILOGE("Long-press time(%{public}d) is out of range [0,%{public}d]", 472c29fa5a6Sopenharmony_ci key.longPressTime, MAXIMUM_LONG_PRESS_TIME); 473c29fa5a6Sopenharmony_ci return false; 474c29fa5a6Sopenharmony_ci } 475c29fa5a6Sopenharmony_ci shortcut = KeyShortcut { 476c29fa5a6Sopenharmony_ci .modifiers = modifiers, 477c29fa5a6Sopenharmony_ci .finalKey = key.finalKey, 478c29fa5a6Sopenharmony_ci .longPressTime = key.longPressTime, 479c29fa5a6Sopenharmony_ci .triggerType = key.triggerType, 480c29fa5a6Sopenharmony_ci .session = key.session, 481c29fa5a6Sopenharmony_ci .callback = key.callback, 482c29fa5a6Sopenharmony_ci }; 483c29fa5a6Sopenharmony_ci return true; 484c29fa5a6Sopenharmony_ci} 485c29fa5a6Sopenharmony_ci 486c29fa5a6Sopenharmony_cibool KeyShortcutManager::CheckGlobalKey(const HotKey &key, KeyShortcut &shortcut) const 487c29fa5a6Sopenharmony_ci{ 488c29fa5a6Sopenharmony_ci size_t nModifiers = 0; 489c29fa5a6Sopenharmony_ci uint32_t modifiers = 0U; 490c29fa5a6Sopenharmony_ci 491c29fa5a6Sopenharmony_ci for (auto keyCode : key.modifiers) { 492c29fa5a6Sopenharmony_ci auto iter = modifiers_.find(keyCode); 493c29fa5a6Sopenharmony_ci if (iter == modifiers_.end()) { 494c29fa5a6Sopenharmony_ci MMI_HILOGE("Key code (%{public}d) is not modifier", keyCode); 495c29fa5a6Sopenharmony_ci return false; 496c29fa5a6Sopenharmony_ci } 497c29fa5a6Sopenharmony_ci if ((modifiers & iter->second) != iter->second) { 498c29fa5a6Sopenharmony_ci modifiers |= iter->second; 499c29fa5a6Sopenharmony_ci ++nModifiers; 500c29fa5a6Sopenharmony_ci } 501c29fa5a6Sopenharmony_ci } 502c29fa5a6Sopenharmony_ci if (IsModifier(key.finalKey)) { 503c29fa5a6Sopenharmony_ci MMI_HILOGE("FinalKey(%{public}d) should not be modifier", key.finalKey); 504c29fa5a6Sopenharmony_ci return false; 505c29fa5a6Sopenharmony_ci } 506c29fa5a6Sopenharmony_ci if (key.finalKey == SHORTCUT_PURE_MODIFIERS) { 507c29fa5a6Sopenharmony_ci MMI_HILOGE("Expect FinalKey"); 508c29fa5a6Sopenharmony_ci return false; 509c29fa5a6Sopenharmony_ci } 510c29fa5a6Sopenharmony_ci if (modifiers & SHORTCUT_MODIFIER_LOGO) { 511c29fa5a6Sopenharmony_ci MMI_HILOGE("'LOGO' is not allowed for GlobalKey"); 512c29fa5a6Sopenharmony_ci return false; 513c29fa5a6Sopenharmony_ci } 514c29fa5a6Sopenharmony_ci if (nModifiers < SINGLE_MODIFIER) { 515c29fa5a6Sopenharmony_ci MMI_HILOGE("Require modifier(s)"); 516c29fa5a6Sopenharmony_ci return false; 517c29fa5a6Sopenharmony_ci } 518c29fa5a6Sopenharmony_ci shortcut = KeyShortcut { 519c29fa5a6Sopenharmony_ci .modifiers = modifiers, 520c29fa5a6Sopenharmony_ci .finalKey = key.finalKey, 521c29fa5a6Sopenharmony_ci .triggerType = SHORTCUT_TRIGGER_TYPE_DOWN, 522c29fa5a6Sopenharmony_ci .session = key.session, 523c29fa5a6Sopenharmony_ci .callback = key.callback, 524c29fa5a6Sopenharmony_ci }; 525c29fa5a6Sopenharmony_ci return true; 526c29fa5a6Sopenharmony_ci} 527c29fa5a6Sopenharmony_ci 528c29fa5a6Sopenharmony_cibool KeyShortcutManager::HaveRegisteredGlobalKey(const KeyShortcut &key) const 529c29fa5a6Sopenharmony_ci{ 530c29fa5a6Sopenharmony_ci auto iter = std::find_if(shortcuts_.cbegin(), shortcuts_.cend(), 531c29fa5a6Sopenharmony_ci [&key](const auto &item) { 532c29fa5a6Sopenharmony_ci return ((item.second.modifiers == key.modifiers) && 533c29fa5a6Sopenharmony_ci (item.second.finalKey == key.finalKey)); 534c29fa5a6Sopenharmony_ci }); 535c29fa5a6Sopenharmony_ci // We met the problem: key-shortcut does not differentiate left/right CTRL/SHIFT/ALT/LOGO. 536c29fa5a6Sopenharmony_ci // but the implementation of key-shortcut reuse the logic of key-subscription, which 537c29fa5a6Sopenharmony_ci // treat left/right CTRL/SHIFT/ALT/LOGO as different keys. That means, for 'CTRL+A' etc 538c29fa5a6Sopenharmony_ci // to work as expected, we have to subscribe both 'LEFT-CTRL+A' and 'RIGHT-CTRL+A'. 539c29fa5a6Sopenharmony_ci // But duplicate global key registration will fail according to key-shortcut rules. 540c29fa5a6Sopenharmony_ci // We relax this retriction here to allow duplicate global key registration from same application. 541c29fa5a6Sopenharmony_ci return (iter != shortcuts_.cend() ? (iter->second.session != key.session) : false); 542c29fa5a6Sopenharmony_ci} 543c29fa5a6Sopenharmony_ci 544c29fa5a6Sopenharmony_cistd::string KeyShortcutManager::FormatPressedKeys(std::shared_ptr<KeyEvent> keyEvent) const 545c29fa5a6Sopenharmony_ci{ 546c29fa5a6Sopenharmony_ci auto pressedKeys = keyEvent->GetPressedKeys(); 547c29fa5a6Sopenharmony_ci std::ostringstream sPressedKeys; 548c29fa5a6Sopenharmony_ci size_t nPressedKeys = 0; 549c29fa5a6Sopenharmony_ci 550c29fa5a6Sopenharmony_ci if (auto iter = pressedKeys.cbegin(); iter != pressedKeys.cend()) { 551c29fa5a6Sopenharmony_ci sPressedKeys << *iter; 552c29fa5a6Sopenharmony_ci ++nPressedKeys; 553c29fa5a6Sopenharmony_ci 554c29fa5a6Sopenharmony_ci for (++iter; iter != pressedKeys.cend(); ++iter) { 555c29fa5a6Sopenharmony_ci if (nPressedKeys > MAX_N_PRINTABLE_ITEMS) { 556c29fa5a6Sopenharmony_ci sPressedKeys << ",..."; 557c29fa5a6Sopenharmony_ci break; 558c29fa5a6Sopenharmony_ci } 559c29fa5a6Sopenharmony_ci sPressedKeys << "," << *iter; 560c29fa5a6Sopenharmony_ci ++nPressedKeys; 561c29fa5a6Sopenharmony_ci } 562c29fa5a6Sopenharmony_ci } 563c29fa5a6Sopenharmony_ci return sPressedKeys.str(); 564c29fa5a6Sopenharmony_ci} 565c29fa5a6Sopenharmony_ci 566c29fa5a6Sopenharmony_cistd::set<int32_t> KeyShortcutManager::GetForegroundPids() const 567c29fa5a6Sopenharmony_ci{ 568c29fa5a6Sopenharmony_ci std::vector<AppExecFwk::AppStateData> foregroundApps = APP_OBSERVER_MGR->GetForegroundAppData(); 569c29fa5a6Sopenharmony_ci std::set<int32_t> foregroundPids; 570c29fa5a6Sopenharmony_ci 571c29fa5a6Sopenharmony_ci for (auto &item : foregroundApps) { 572c29fa5a6Sopenharmony_ci foregroundPids.insert(item.pid); 573c29fa5a6Sopenharmony_ci } 574c29fa5a6Sopenharmony_ci std::set<int32_t> tForegroundPids; 575c29fa5a6Sopenharmony_ci 576c29fa5a6Sopenharmony_ci for (const auto &shortcut : shortcuts_) { 577c29fa5a6Sopenharmony_ci if (foregroundPids.find(shortcut.second.session) != foregroundPids.cend()) { 578c29fa5a6Sopenharmony_ci tForegroundPids.insert(shortcut.second.session); 579c29fa5a6Sopenharmony_ci } 580c29fa5a6Sopenharmony_ci } 581c29fa5a6Sopenharmony_ci std::ostringstream sPids; 582c29fa5a6Sopenharmony_ci 583c29fa5a6Sopenharmony_ci if (auto iter = tForegroundPids.cbegin(); iter != tForegroundPids.cend()) { 584c29fa5a6Sopenharmony_ci sPids << *iter; 585c29fa5a6Sopenharmony_ci for (++iter; iter != tForegroundPids.cend(); ++iter) { 586c29fa5a6Sopenharmony_ci sPids << "," << *iter; 587c29fa5a6Sopenharmony_ci } 588c29fa5a6Sopenharmony_ci } 589c29fa5a6Sopenharmony_ci MMI_HILOGI("Foreground pids: [%{public}s]", sPids.str().c_str()); 590c29fa5a6Sopenharmony_ci return tForegroundPids; 591c29fa5a6Sopenharmony_ci} 592c29fa5a6Sopenharmony_ci 593c29fa5a6Sopenharmony_cibool KeyShortcutManager::HandleKeyDown(std::shared_ptr<KeyEvent> keyEvent) 594c29fa5a6Sopenharmony_ci{ 595c29fa5a6Sopenharmony_ci bool handled = false; 596c29fa5a6Sopenharmony_ci std::set<int32_t> foregroundPids = GetForegroundPids(); 597c29fa5a6Sopenharmony_ci 598c29fa5a6Sopenharmony_ci for (auto &item : shortcuts_) { 599c29fa5a6Sopenharmony_ci KeyShortcut &shortcut = item.second; 600c29fa5a6Sopenharmony_ci if (shortcut.triggerType != SHORTCUT_TRIGGER_TYPE_DOWN) { 601c29fa5a6Sopenharmony_ci continue; 602c29fa5a6Sopenharmony_ci } 603c29fa5a6Sopenharmony_ci if (!foregroundPids.empty() && 604c29fa5a6Sopenharmony_ci (foregroundPids.find(shortcut.session) == foregroundPids.cend())) { 605c29fa5a6Sopenharmony_ci continue; 606c29fa5a6Sopenharmony_ci } 607c29fa5a6Sopenharmony_ci if (!CheckCombination(keyEvent, shortcut)) { 608c29fa5a6Sopenharmony_ci continue; 609c29fa5a6Sopenharmony_ci } 610c29fa5a6Sopenharmony_ci MMI_HILOGI("Matched shortcut[No.%{public}d]" 611c29fa5a6Sopenharmony_ci "(0x%{public}x,%{public}d,%{public}d,%{public}d,SESSION:%{public}d)", 612c29fa5a6Sopenharmony_ci item.first, shortcut.modifiers, shortcut.finalKey, shortcut.longPressTime, 613c29fa5a6Sopenharmony_ci shortcut.triggerType, shortcut.session); 614c29fa5a6Sopenharmony_ci TriggerDown(keyEvent, item.first, shortcut); 615c29fa5a6Sopenharmony_ci handled = true; 616c29fa5a6Sopenharmony_ci } 617c29fa5a6Sopenharmony_ci return handled; 618c29fa5a6Sopenharmony_ci} 619c29fa5a6Sopenharmony_ci 620c29fa5a6Sopenharmony_cibool KeyShortcutManager::HandleKeyUp(std::shared_ptr<KeyEvent> keyEvent) 621c29fa5a6Sopenharmony_ci{ 622c29fa5a6Sopenharmony_ci bool handled = false; 623c29fa5a6Sopenharmony_ci std::set<int32_t> foregroundPids = GetForegroundPids(); 624c29fa5a6Sopenharmony_ci 625c29fa5a6Sopenharmony_ci for (auto &item : shortcuts_) { 626c29fa5a6Sopenharmony_ci KeyShortcut &shortcut = item.second; 627c29fa5a6Sopenharmony_ci if (shortcut.triggerType != SHORTCUT_TRIGGER_TYPE_UP) { 628c29fa5a6Sopenharmony_ci continue; 629c29fa5a6Sopenharmony_ci } 630c29fa5a6Sopenharmony_ci if (!foregroundPids.empty() && 631c29fa5a6Sopenharmony_ci (foregroundPids.find(shortcut.session) == foregroundPids.cend())) { 632c29fa5a6Sopenharmony_ci continue; 633c29fa5a6Sopenharmony_ci } 634c29fa5a6Sopenharmony_ci if (!CheckCombination(keyEvent, shortcut)) { 635c29fa5a6Sopenharmony_ci continue; 636c29fa5a6Sopenharmony_ci } 637c29fa5a6Sopenharmony_ci MMI_HILOGI("Matched shortcut(0x%{public}x,%{public}d,%{public}d,%{public}d,SESSION:%{public}d)", 638c29fa5a6Sopenharmony_ci shortcut.modifiers, shortcut.finalKey, shortcut.longPressTime, shortcut.triggerType, shortcut.session); 639c29fa5a6Sopenharmony_ci TriggerUp(keyEvent, item.first, shortcut); 640c29fa5a6Sopenharmony_ci handled = true; 641c29fa5a6Sopenharmony_ci } 642c29fa5a6Sopenharmony_ci return handled; 643c29fa5a6Sopenharmony_ci} 644c29fa5a6Sopenharmony_ci 645c29fa5a6Sopenharmony_cibool KeyShortcutManager::HandleKeyCancel(std::shared_ptr<KeyEvent> keyEvent) 646c29fa5a6Sopenharmony_ci{ 647c29fa5a6Sopenharmony_ci ResetAll(); 648c29fa5a6Sopenharmony_ci return false; 649c29fa5a6Sopenharmony_ci} 650c29fa5a6Sopenharmony_ci 651c29fa5a6Sopenharmony_cibool KeyShortcutManager::CheckCombination(std::shared_ptr<KeyEvent> keyEvent, const KeyShortcut &shortcut) const 652c29fa5a6Sopenharmony_ci{ 653c29fa5a6Sopenharmony_ci return (((shortcut.finalKey == SHORTCUT_PURE_MODIFIERS) && CheckPureModifiers(keyEvent, shortcut)) || 654c29fa5a6Sopenharmony_ci ((shortcut.finalKey == keyEvent->GetKeyCode()) && CheckModifiers(keyEvent, shortcut))); 655c29fa5a6Sopenharmony_ci} 656c29fa5a6Sopenharmony_ci 657c29fa5a6Sopenharmony_cibool KeyShortcutManager::CheckPureModifiers(std::shared_ptr<KeyEvent> keyEvent, const KeyShortcut &shortcut) const 658c29fa5a6Sopenharmony_ci{ 659c29fa5a6Sopenharmony_ci auto iter = modifiers_.find(keyEvent->GetKeyCode()); 660c29fa5a6Sopenharmony_ci if (iter == modifiers_.cend()) { 661c29fa5a6Sopenharmony_ci return false; 662c29fa5a6Sopenharmony_ci } 663c29fa5a6Sopenharmony_ci uint32_t modifiers = (shortcut.modifiers & ~iter->second); 664c29fa5a6Sopenharmony_ci auto pressedKeys = keyEvent->GetPressedKeys(); 665c29fa5a6Sopenharmony_ci 666c29fa5a6Sopenharmony_ci for (auto keyCode : pressedKeys) { 667c29fa5a6Sopenharmony_ci if (auto iter = modifiers_.find(keyCode); iter != modifiers_.cend()) { 668c29fa5a6Sopenharmony_ci modifiers &= ~iter->second; 669c29fa5a6Sopenharmony_ci } 670c29fa5a6Sopenharmony_ci } 671c29fa5a6Sopenharmony_ci return (modifiers == 0U); 672c29fa5a6Sopenharmony_ci} 673c29fa5a6Sopenharmony_ci 674c29fa5a6Sopenharmony_cibool KeyShortcutManager::CheckModifiers(std::shared_ptr<KeyEvent> keyEvent, const KeyShortcut &shortcut) const 675c29fa5a6Sopenharmony_ci{ 676c29fa5a6Sopenharmony_ci uint32_t modifiers = shortcut.modifiers; 677c29fa5a6Sopenharmony_ci auto pressedKeys = keyEvent->GetPressedKeys(); 678c29fa5a6Sopenharmony_ci 679c29fa5a6Sopenharmony_ci for (auto keyCode : pressedKeys) { 680c29fa5a6Sopenharmony_ci if (auto iter = modifiers_.find(keyCode); iter != modifiers_.cend()) { 681c29fa5a6Sopenharmony_ci modifiers &= ~iter->second; 682c29fa5a6Sopenharmony_ci } 683c29fa5a6Sopenharmony_ci } 684c29fa5a6Sopenharmony_ci return (modifiers == 0U); 685c29fa5a6Sopenharmony_ci} 686c29fa5a6Sopenharmony_ci 687c29fa5a6Sopenharmony_civoid KeyShortcutManager::TriggerDown( 688c29fa5a6Sopenharmony_ci std::shared_ptr<KeyEvent> keyEvent, int32_t shortcutId, const KeyShortcut &shortcut) 689c29fa5a6Sopenharmony_ci{ 690c29fa5a6Sopenharmony_ci if (shortcut.longPressTime <= 0) { 691c29fa5a6Sopenharmony_ci MMI_HILOGI("Run shortcut[No.%{public}d]", shortcutId); 692c29fa5a6Sopenharmony_ci if (shortcut.callback != nullptr) { 693c29fa5a6Sopenharmony_ci shortcut.callback(keyEvent); 694c29fa5a6Sopenharmony_ci } 695c29fa5a6Sopenharmony_ci } else { 696c29fa5a6Sopenharmony_ci if (triggering_.find(shortcutId) != triggering_.cend()) { 697c29fa5a6Sopenharmony_ci MMI_HILOGI("Shortcut[No.%{public}d]" 698c29fa5a6Sopenharmony_ci "(0x%{public}x,%{public}d,%{public}d,%{public}d,SESSION:%{public}d) is pending", 699c29fa5a6Sopenharmony_ci shortcutId, shortcut.modifiers, shortcut.finalKey, shortcut.longPressTime, 700c29fa5a6Sopenharmony_ci shortcut.triggerType, shortcut.session); 701c29fa5a6Sopenharmony_ci return; 702c29fa5a6Sopenharmony_ci } 703c29fa5a6Sopenharmony_ci auto timerId = TimerMgr->AddTimer(shortcut.longPressTime, REPEAT_ONCE, 704c29fa5a6Sopenharmony_ci [this, tKeyEvent = KeyEvent::Clone(keyEvent), shortcutId]() { 705c29fa5a6Sopenharmony_ci triggering_.erase(shortcutId); 706c29fa5a6Sopenharmony_ci RunShortcut(tKeyEvent, shortcutId); 707c29fa5a6Sopenharmony_ci }); 708c29fa5a6Sopenharmony_ci if (timerId < 0) { 709c29fa5a6Sopenharmony_ci MMI_HILOGE("AddTimer fail"); 710c29fa5a6Sopenharmony_ci return; 711c29fa5a6Sopenharmony_ci } 712c29fa5a6Sopenharmony_ci triggering_.emplace(shortcutId, timerId); 713c29fa5a6Sopenharmony_ci } 714c29fa5a6Sopenharmony_ci} 715c29fa5a6Sopenharmony_ci 716c29fa5a6Sopenharmony_civoid KeyShortcutManager::RunShortcut(std::shared_ptr<KeyEvent> keyEvent, int32_t shortcutId) 717c29fa5a6Sopenharmony_ci{ 718c29fa5a6Sopenharmony_ci if (auto iter = shortcuts_.find(shortcutId); iter != shortcuts_.end()) { 719c29fa5a6Sopenharmony_ci std::set<int32_t> foregroundPids = GetForegroundPids(); 720c29fa5a6Sopenharmony_ci if (!foregroundPids.empty() && 721c29fa5a6Sopenharmony_ci (foregroundPids.find(iter->second.session) == foregroundPids.cend())) { 722c29fa5a6Sopenharmony_ci MMI_HILOGI("Session(%{public}d) is not foreground, skip running shortcut[%{public}d]", 723c29fa5a6Sopenharmony_ci iter->second.session, shortcutId); 724c29fa5a6Sopenharmony_ci return; 725c29fa5a6Sopenharmony_ci } 726c29fa5a6Sopenharmony_ci MMI_HILOGI("Run shortcut[No.%{public}d]", shortcutId); 727c29fa5a6Sopenharmony_ci if (iter->second.callback != nullptr) { 728c29fa5a6Sopenharmony_ci iter->second.callback(keyEvent); 729c29fa5a6Sopenharmony_ci } 730c29fa5a6Sopenharmony_ci } 731c29fa5a6Sopenharmony_ci} 732c29fa5a6Sopenharmony_ci 733c29fa5a6Sopenharmony_civoid KeyShortcutManager::TriggerUp( 734c29fa5a6Sopenharmony_ci std::shared_ptr<KeyEvent> keyEvent, int32_t shortcutId, const KeyShortcut &shortcut) 735c29fa5a6Sopenharmony_ci{ 736c29fa5a6Sopenharmony_ci if (shortcut.longPressTime > 0) { 737c29fa5a6Sopenharmony_ci std::optional<KeyEvent::KeyItem> keyItem = keyEvent->GetKeyItem(); 738c29fa5a6Sopenharmony_ci if (!keyItem) { 739c29fa5a6Sopenharmony_ci MMI_HILOGE("Corrupted key event"); 740c29fa5a6Sopenharmony_ci return; 741c29fa5a6Sopenharmony_ci } 742c29fa5a6Sopenharmony_ci auto upTime = keyEvent->GetActionTime(); 743c29fa5a6Sopenharmony_ci auto downTime = keyItem->GetDownTime(); 744c29fa5a6Sopenharmony_ci if (upTime - downTime < MS2US(shortcut.longPressTime)) { 745c29fa5a6Sopenharmony_ci MMI_HILOGE("upTime - downTime < duration"); 746c29fa5a6Sopenharmony_ci return; 747c29fa5a6Sopenharmony_ci } 748c29fa5a6Sopenharmony_ci } 749c29fa5a6Sopenharmony_ci if (shortcut.callback != nullptr) { 750c29fa5a6Sopenharmony_ci shortcut.callback(keyEvent); 751c29fa5a6Sopenharmony_ci } 752c29fa5a6Sopenharmony_ci} 753c29fa5a6Sopenharmony_ci 754c29fa5a6Sopenharmony_civoid KeyShortcutManager::ResetAll() 755c29fa5a6Sopenharmony_ci{ 756c29fa5a6Sopenharmony_ci for (auto &item : triggering_) { 757c29fa5a6Sopenharmony_ci TimerMgr->RemoveTimer(item.second); 758c29fa5a6Sopenharmony_ci } 759c29fa5a6Sopenharmony_ci triggering_.clear(); 760c29fa5a6Sopenharmony_ci} 761c29fa5a6Sopenharmony_ci 762c29fa5a6Sopenharmony_civoid KeyShortcutManager::ResetCheckState() 763c29fa5a6Sopenharmony_ci{ 764c29fa5a6Sopenharmony_ci isCheckShortcut_ = true; 765c29fa5a6Sopenharmony_ci} 766c29fa5a6Sopenharmony_ci 767c29fa5a6Sopenharmony_cistatic const std::vector<int32_t> specialKeyCodes = { 768c29fa5a6Sopenharmony_ci KeyEvent::KEYCODE_ALT_LEFT, 769c29fa5a6Sopenharmony_ci KeyEvent::KEYCODE_ALT_RIGHT, 770c29fa5a6Sopenharmony_ci KeyEvent::KEYCODE_TAB, 771c29fa5a6Sopenharmony_ci KeyEvent::KEYCODE_VOLUME_UP, 772c29fa5a6Sopenharmony_ci KeyEvent::KEYCODE_VOLUME_DOWN, 773c29fa5a6Sopenharmony_ci KeyEvent::KEYCODE_POWER 774c29fa5a6Sopenharmony_ci}; 775c29fa5a6Sopenharmony_ci 776c29fa5a6Sopenharmony_cibool KeyShortcutManager::IsCheckUpShortcut(const std::shared_ptr<KeyEvent> &keyEvent) 777c29fa5a6Sopenharmony_ci{ 778c29fa5a6Sopenharmony_ci auto it = std::find(specialKeyCodes.begin(), specialKeyCodes.end(), keyEvent->GetKeyCode()); 779c29fa5a6Sopenharmony_ci if (it != specialKeyCodes.end() && keyEvent->GetKeyAction() == KeyEvent::KEY_ACTION_UP) { 780c29fa5a6Sopenharmony_ci return true; 781c29fa5a6Sopenharmony_ci } 782c29fa5a6Sopenharmony_ci if (isCheckShortcut_) { 783c29fa5a6Sopenharmony_ci isCheckShortcut_ = false; 784c29fa5a6Sopenharmony_ci return true; 785c29fa5a6Sopenharmony_ci } 786c29fa5a6Sopenharmony_ci return false; 787c29fa5a6Sopenharmony_ci} 788c29fa5a6Sopenharmony_ci 789c29fa5a6Sopenharmony_ciint32_t KeyShortcutManager::GetAllSystemHotkeys(std::vector<std::unique_ptr<KeyOption>> &sysKeys) 790c29fa5a6Sopenharmony_ci{ 791c29fa5a6Sopenharmony_ci CALL_DEBUG_ENTER; 792c29fa5a6Sopenharmony_ci for (const auto &item : hotkeys_) { 793c29fa5a6Sopenharmony_ci std::unique_ptr<KeyOption> keyOptionPtr = std::make_unique<KeyOption>(); 794c29fa5a6Sopenharmony_ci keyOptionPtr->SetPreKeys(item.preKeys); 795c29fa5a6Sopenharmony_ci keyOptionPtr->SetFinalKey(item.finalKey); 796c29fa5a6Sopenharmony_ci sysKeys.push_back(std::move(keyOptionPtr)); 797c29fa5a6Sopenharmony_ci } 798c29fa5a6Sopenharmony_ci return RET_OK; 799c29fa5a6Sopenharmony_ci} 800c29fa5a6Sopenharmony_ci 801c29fa5a6Sopenharmony_cibool KeyShortcutManager::HaveShortcutConsumed(std::shared_ptr<KeyEvent> keyEvent) 802c29fa5a6Sopenharmony_ci{ 803c29fa5a6Sopenharmony_ci auto it = std::find(specialKeyCodes.begin(), specialKeyCodes.end(), keyEvent->GetKeyCode()); 804c29fa5a6Sopenharmony_ci if (it != specialKeyCodes.end() && keyEvent->GetKeyAction() == KeyEvent::KEY_ACTION_UP) { 805c29fa5a6Sopenharmony_ci return false; 806c29fa5a6Sopenharmony_ci } 807c29fa5a6Sopenharmony_ci return (shortcutConsumed_.find(keyEvent->GetKeyCode()) != shortcutConsumed_.cend()); 808c29fa5a6Sopenharmony_ci} 809c29fa5a6Sopenharmony_ci 810c29fa5a6Sopenharmony_civoid KeyShortcutManager::UpdateShortcutConsumed(std::shared_ptr<KeyEvent> keyEvent) 811c29fa5a6Sopenharmony_ci{ 812c29fa5a6Sopenharmony_ci if (keyEvent->GetKeyAction() == KeyEvent::KEY_ACTION_UP) { 813c29fa5a6Sopenharmony_ci shortcutConsumed_.erase(keyEvent->GetKeyCode()); 814c29fa5a6Sopenharmony_ci } 815c29fa5a6Sopenharmony_ci} 816c29fa5a6Sopenharmony_ci 817c29fa5a6Sopenharmony_civoid KeyShortcutManager::MarkShortcutConsumed(const ShortcutKey &shortcut) 818c29fa5a6Sopenharmony_ci{ 819c29fa5a6Sopenharmony_ci std::for_each(shortcut.preKeys.cbegin(), shortcut.preKeys.cend(), 820c29fa5a6Sopenharmony_ci [this](auto keyCode) { 821c29fa5a6Sopenharmony_ci shortcutConsumed_.emplace(keyCode); 822c29fa5a6Sopenharmony_ci }); 823c29fa5a6Sopenharmony_ci if (shortcut.triggerType == KeyEvent::KEY_ACTION_DOWN) { 824c29fa5a6Sopenharmony_ci shortcutConsumed_.emplace(shortcut.finalKey); 825c29fa5a6Sopenharmony_ci } 826c29fa5a6Sopenharmony_ci isCheckShortcut_ = false; 827c29fa5a6Sopenharmony_ci} 828c29fa5a6Sopenharmony_ci 829c29fa5a6Sopenharmony_civoid KeyShortcutManager::MarkShortcutConsumed(const KeyOption &shortcut) 830c29fa5a6Sopenharmony_ci{ 831c29fa5a6Sopenharmony_ci auto preKeys = shortcut.GetPreKeys(); 832c29fa5a6Sopenharmony_ci 833c29fa5a6Sopenharmony_ci std::for_each(preKeys.cbegin(), preKeys.cend(), 834c29fa5a6Sopenharmony_ci [this](auto keyCode) { 835c29fa5a6Sopenharmony_ci shortcutConsumed_.emplace(keyCode); 836c29fa5a6Sopenharmony_ci }); 837c29fa5a6Sopenharmony_ci if (shortcut.IsFinalKeyDown()) { 838c29fa5a6Sopenharmony_ci shortcutConsumed_.emplace(shortcut.GetFinalKey()); 839c29fa5a6Sopenharmony_ci } 840c29fa5a6Sopenharmony_ci shortcutConsumed_.erase(KeyEvent::KEYCODE_VOLUME_UP); 841c29fa5a6Sopenharmony_ci shortcutConsumed_.erase(KeyEvent::KEYCODE_VOLUME_DOWN); 842c29fa5a6Sopenharmony_ci shortcutConsumed_.erase(KeyEvent::KEYCODE_POWER); 843c29fa5a6Sopenharmony_ci isCheckShortcut_ = false; 844c29fa5a6Sopenharmony_ci} 845c29fa5a6Sopenharmony_ci 846c29fa5a6Sopenharmony_civoid KeyShortcutManager::ResetTriggering(std::shared_ptr<KeyEvent> keyEvent) 847c29fa5a6Sopenharmony_ci{ 848c29fa5a6Sopenharmony_ci if (keyEvent->GetKeyAction() == KeyEvent::KEY_ACTION_DOWN) { 849c29fa5a6Sopenharmony_ci for (auto iter = triggering_.cbegin(); iter != triggering_.cend();) { 850c29fa5a6Sopenharmony_ci auto shortcutIter = shortcuts_.find(iter->first); 851c29fa5a6Sopenharmony_ci if ((shortcutIter != shortcuts_.cend()) && 852c29fa5a6Sopenharmony_ci WillResetOnKeyDown(keyEvent->GetKeyCode(), shortcutIter->second)) { 853c29fa5a6Sopenharmony_ci MMI_HILOGI("Reset triggering shortcut[%{public}d]", iter->first); 854c29fa5a6Sopenharmony_ci TimerMgr->RemoveTimer(iter->second); 855c29fa5a6Sopenharmony_ci iter = triggering_.erase(iter); 856c29fa5a6Sopenharmony_ci } else { 857c29fa5a6Sopenharmony_ci ++iter; 858c29fa5a6Sopenharmony_ci } 859c29fa5a6Sopenharmony_ci } 860c29fa5a6Sopenharmony_ci } else { 861c29fa5a6Sopenharmony_ci for (auto iter = triggering_.cbegin(); iter != triggering_.cend();) { 862c29fa5a6Sopenharmony_ci auto shortcutIter = shortcuts_.find(iter->first); 863c29fa5a6Sopenharmony_ci if ((shortcutIter != shortcuts_.cend()) && 864c29fa5a6Sopenharmony_ci WillResetOnKeyUp(keyEvent->GetKeyCode(), shortcutIter->second)) { 865c29fa5a6Sopenharmony_ci MMI_HILOGI("Reset triggering shortcut[%{public}d]", iter->first); 866c29fa5a6Sopenharmony_ci TimerMgr->RemoveTimer(iter->second); 867c29fa5a6Sopenharmony_ci iter = triggering_.erase(iter); 868c29fa5a6Sopenharmony_ci } else { 869c29fa5a6Sopenharmony_ci ++iter; 870c29fa5a6Sopenharmony_ci } 871c29fa5a6Sopenharmony_ci } 872c29fa5a6Sopenharmony_ci } 873c29fa5a6Sopenharmony_ci} 874c29fa5a6Sopenharmony_ci 875c29fa5a6Sopenharmony_cibool KeyShortcutManager::WillResetOnKeyDown(int32_t keyCode, const KeyShortcut &shortcut) const 876c29fa5a6Sopenharmony_ci{ 877c29fa5a6Sopenharmony_ci if (keyCode == shortcut.finalKey) { 878c29fa5a6Sopenharmony_ci return false; 879c29fa5a6Sopenharmony_ci } 880c29fa5a6Sopenharmony_ci auto modIter = modifiers_.find(keyCode); 881c29fa5a6Sopenharmony_ci return ((modIter == modifiers_.cend()) || ((modIter->second & shortcut.modifiers) == 0U)); 882c29fa5a6Sopenharmony_ci} 883c29fa5a6Sopenharmony_ci 884c29fa5a6Sopenharmony_cibool KeyShortcutManager::WillResetOnKeyUp(int32_t keyCode, const KeyShortcut &shortcut) const 885c29fa5a6Sopenharmony_ci{ 886c29fa5a6Sopenharmony_ci if (keyCode == shortcut.finalKey) { 887c29fa5a6Sopenharmony_ci return true; 888c29fa5a6Sopenharmony_ci } 889c29fa5a6Sopenharmony_ci auto modIter = modifiers_.find(keyCode); 890c29fa5a6Sopenharmony_ci return ((modIter != modifiers_.cend()) && ((modIter->second & shortcut.modifiers) != 0U)); 891c29fa5a6Sopenharmony_ci} 892c29fa5a6Sopenharmony_ci 893c29fa5a6Sopenharmony_civoid KeyShortcutManager::ResetTriggering(int32_t shortcutId) 894c29fa5a6Sopenharmony_ci{ 895c29fa5a6Sopenharmony_ci if (auto iter = triggering_.find(shortcutId); iter != triggering_.cend()) { 896c29fa5a6Sopenharmony_ci TimerMgr->RemoveTimer(iter->second); 897c29fa5a6Sopenharmony_ci triggering_.erase(iter); 898c29fa5a6Sopenharmony_ci } 899c29fa5a6Sopenharmony_ci} 900c29fa5a6Sopenharmony_ci 901c29fa5a6Sopenharmony_civoid KeyShortcutManager::LoadHotkeys() 902c29fa5a6Sopenharmony_ci{ 903c29fa5a6Sopenharmony_ci char cfgName[] { "etc/multimodalinput/system_hotkeys_config.json" }; 904c29fa5a6Sopenharmony_ci char buf[MAX_PATH_LEN] {}; 905c29fa5a6Sopenharmony_ci char *cfgPath = ::GetOneCfgFile(cfgName, buf, sizeof(buf)); 906c29fa5a6Sopenharmony_ci 907c29fa5a6Sopenharmony_ci if ((cfgPath == nullptr) || (cfgPath[0] == '\0') || (strlen(cfgPath) > MAX_PATH_LEN)) { 908c29fa5a6Sopenharmony_ci MMI_HILOGE("No '%{public}s' was found", cfgPath); 909c29fa5a6Sopenharmony_ci return; 910c29fa5a6Sopenharmony_ci } 911c29fa5a6Sopenharmony_ci MMI_HILOGI("Config of hotkey:%{public}s", cfgPath); 912c29fa5a6Sopenharmony_ci ReadHotkeys(std::string(cfgPath)); 913c29fa5a6Sopenharmony_ci} 914c29fa5a6Sopenharmony_ci 915c29fa5a6Sopenharmony_civoid KeyShortcutManager::ReadHotkeys(const std::string &cfgPath) 916c29fa5a6Sopenharmony_ci{ 917c29fa5a6Sopenharmony_ci std::string cfg = ReadJsonFile(cfgPath); 918c29fa5a6Sopenharmony_ci JsonParser parser; 919c29fa5a6Sopenharmony_ci parser.json_ = cJSON_Parse(cfg.c_str()); 920c29fa5a6Sopenharmony_ci if (!cJSON_IsObject(parser.json_)) { 921c29fa5a6Sopenharmony_ci MMI_HILOGE("Not json format"); 922c29fa5a6Sopenharmony_ci return; 923c29fa5a6Sopenharmony_ci } 924c29fa5a6Sopenharmony_ci cJSON* jsonHotkeys = cJSON_GetObjectItemCaseSensitive(parser.json_, "Hotkeys"); 925c29fa5a6Sopenharmony_ci if (!cJSON_IsArray(jsonHotkeys)) { 926c29fa5a6Sopenharmony_ci MMI_HILOGE("JsonHotkeys is not array"); 927c29fa5a6Sopenharmony_ci return; 928c29fa5a6Sopenharmony_ci } 929c29fa5a6Sopenharmony_ci int32_t nSysKeys = cJSON_GetArraySize(jsonHotkeys); 930c29fa5a6Sopenharmony_ci for (int32_t index = 0; index < nSysKeys; ++index) { 931c29fa5a6Sopenharmony_ci cJSON *jsonHotkey = cJSON_GetArrayItem(jsonHotkeys, index); 932c29fa5a6Sopenharmony_ci if (ReadHotkey(jsonHotkey) != RET_OK) { 933c29fa5a6Sopenharmony_ci MMI_HILOGE("Read hotkey failed"); 934c29fa5a6Sopenharmony_ci return; 935c29fa5a6Sopenharmony_ci } 936c29fa5a6Sopenharmony_ci } 937c29fa5a6Sopenharmony_ci} 938c29fa5a6Sopenharmony_ci 939c29fa5a6Sopenharmony_ciint32_t KeyShortcutManager::ReadHotkey(cJSON *jsonHotkey) 940c29fa5a6Sopenharmony_ci{ 941c29fa5a6Sopenharmony_ci if (!cJSON_IsObject(jsonHotkey)) { 942c29fa5a6Sopenharmony_ci MMI_HILOGE("Not json object"); 943c29fa5a6Sopenharmony_ci return RET_ERR; 944c29fa5a6Sopenharmony_ci } 945c29fa5a6Sopenharmony_ci cJSON *jsonPreKeys = cJSON_GetObjectItem(jsonHotkey, "preKeys"); 946c29fa5a6Sopenharmony_ci if (!cJSON_IsArray(jsonPreKeys)) { 947c29fa5a6Sopenharmony_ci MMI_HILOGE("Expect array for PreKeys"); 948c29fa5a6Sopenharmony_ci return RET_ERR; 949c29fa5a6Sopenharmony_ci } 950c29fa5a6Sopenharmony_ci std::set<int32_t> preKeys; 951c29fa5a6Sopenharmony_ci int32_t nPreKeys = cJSON_GetArraySize(jsonPreKeys); 952c29fa5a6Sopenharmony_ci 953c29fa5a6Sopenharmony_ci for (int32_t index = 0; index < nPreKeys; ++index) { 954c29fa5a6Sopenharmony_ci cJSON *jsonPreKey = cJSON_GetArrayItem(jsonPreKeys, index); 955c29fa5a6Sopenharmony_ci if (!cJSON_IsNumber(jsonPreKey)) { 956c29fa5a6Sopenharmony_ci MMI_HILOGE("Expect number for PreKey"); 957c29fa5a6Sopenharmony_ci return RET_ERR; 958c29fa5a6Sopenharmony_ci } 959c29fa5a6Sopenharmony_ci preKeys.insert(static_cast<int32_t>(cJSON_GetNumberValue(jsonPreKey))); 960c29fa5a6Sopenharmony_ci } 961c29fa5a6Sopenharmony_ci cJSON *jsonFinalKey = cJSON_GetObjectItem(jsonHotkey, "finalKey"); 962c29fa5a6Sopenharmony_ci if (!cJSON_IsNumber(jsonFinalKey)) { 963c29fa5a6Sopenharmony_ci MMI_HILOGE("Expect number for FinalKey"); 964c29fa5a6Sopenharmony_ci return RET_ERR; 965c29fa5a6Sopenharmony_ci } 966c29fa5a6Sopenharmony_ci int32_t finalKey = static_cast<int32_t>(cJSON_GetNumberValue(jsonFinalKey)); 967c29fa5a6Sopenharmony_ci return AddHotkey(preKeys, finalKey); 968c29fa5a6Sopenharmony_ci} 969c29fa5a6Sopenharmony_ci 970c29fa5a6Sopenharmony_ciint32_t KeyShortcutManager::AddHotkey(const std::set<int32_t> &preKeys, int32_t finalKey) 971c29fa5a6Sopenharmony_ci{ 972c29fa5a6Sopenharmony_ci SystemHotkey hotkey { 973c29fa5a6Sopenharmony_ci .preKeys = preKeys, 974c29fa5a6Sopenharmony_ci .finalKey = finalKey, 975c29fa5a6Sopenharmony_ci }; 976c29fa5a6Sopenharmony_ci for (const auto &item : hotkey.preKeys) { 977c29fa5a6Sopenharmony_ci if ((modifiers_.find(item) == modifiers_.cend()) && (item != KeyEvent::KEYCODE_SYSRQ)) { 978c29fa5a6Sopenharmony_ci MMI_HILOGE("Not hotkeys"); 979c29fa5a6Sopenharmony_ci return RET_ERR; 980c29fa5a6Sopenharmony_ci } 981c29fa5a6Sopenharmony_ci } 982c29fa5a6Sopenharmony_ci 983c29fa5a6Sopenharmony_ci if (IsModifier(hotkey.finalKey)) { 984c29fa5a6Sopenharmony_ci MMI_HILOGE("FinalKey is modifier"); 985c29fa5a6Sopenharmony_ci return RET_ERR; 986c29fa5a6Sopenharmony_ci } 987c29fa5a6Sopenharmony_ci hotkeys_.emplace(hotkey); 988c29fa5a6Sopenharmony_ci return RET_OK; 989c29fa5a6Sopenharmony_ci} 990c29fa5a6Sopenharmony_ci} // namespace MMI 991c29fa5a6Sopenharmony_ci} // namespace OHOS 992