1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef KEY_SHORTCUT_MANAGER_H
17 #define KEY_SHORTCUT_MANAGER_H
18 
19 #include <functional>
20 #include <map>
21 #include <optional>
22 #include <set>
23 
24 #include <cJSON.h>
25 #include <nocopyable.h>
26 
27 #include "key_command_handler.h"
28 #include "key_event.h"
29 #include "key_option.h"
30 
31 namespace OHOS {
32 namespace MMI {
33 enum KeyShortcutError : int32_t {
34     KEY_SHORTCUT_ERROR_BASE = -1,
35     KEY_SHORTCUT_ERROR_CONFIG = (KEY_SHORTCUT_ERROR_BASE - 1),
36     KEY_SHORTCUT_ERROR_COMBINATION_KEY = (KEY_SHORTCUT_ERROR_BASE - 2),
37     KEY_SHORTCUT_ERROR_TAKEN = (KEY_SHORTCUT_ERROR_BASE - 3),
38 };
39 
40 class KeyShortcutManager final {
41 public:
42     static inline constexpr uint32_t SHORTCUT_MODIFIER_ALT { 0x1 };
43     static inline constexpr uint32_t SHORTCUT_MODIFIER_SHIFT { SHORTCUT_MODIFIER_ALT << 1U };
44     static inline constexpr uint32_t SHORTCUT_MODIFIER_CTRL { SHORTCUT_MODIFIER_ALT << 2U };
45     static inline constexpr uint32_t SHORTCUT_MODIFIER_LOGO { SHORTCUT_MODIFIER_ALT << 3U };
46     static inline constexpr uint32_t SHORTCUT_MODIFIER_MASK {
47         SHORTCUT_MODIFIER_ALT | SHORTCUT_MODIFIER_SHIFT | SHORTCUT_MODIFIER_CTRL | SHORTCUT_MODIFIER_LOGO };
48     static inline constexpr int32_t SHORTCUT_PURE_MODIFIERS { -1 };
49     static inline constexpr int32_t MOUSE_BUTTON_LEFT { 25001 };
50     static inline constexpr int32_t MOUSE_BUTTON_RIGHT { MOUSE_BUTTON_LEFT + 1 };
51 
52     enum ShortcutTriggerType : int32_t {
53         SHORTCUT_TRIGGER_TYPE_DOWN = 0,
54         SHORTCUT_TRIGGER_TYPE_UP,
55     };
56 
57     struct SystemShortcutKey {
58         std::set<int32_t> modifiers;
59         int32_t finalKey;
60         int32_t longPressTime; // ms
61         ShortcutTriggerType triggerType;
62         int32_t session;
63         std::function<void(std::shared_ptr<KeyEvent>)> callback;
64     };
65 
66     struct HotKey {
67         std::set<int32_t> modifiers;
68         int32_t finalKey;
69         int32_t longPressTime; // ms
70         int32_t session;
71         std::function<void(std::shared_ptr<KeyEvent>)> callback;
72     };
73 
74     KeyShortcutManager();
75     ~KeyShortcutManager() = default;
76     DISALLOW_COPY_AND_MOVE(KeyShortcutManager);
77 
78     int32_t RegisterSystemKey(const SystemShortcutKey &key);
79     void UnregisterSystemKey(int32_t shortcutId);
80     int32_t RegisterHotKey(const HotKey &key);
81     void UnregisterHotKey(int32_t shortcutId);
82     bool HandleEvent(std::shared_ptr<KeyEvent> keyEvent);
83     void ResetAll();
84     int32_t GetAllSystemHotkeys(std::vector<std::unique_ptr<KeyOption>> &sysKeys);
85     void ResetCheckState();
86     bool IsCheckUpShortcut(const std::shared_ptr<KeyEvent> &keyEvent);
87 
88     bool HaveShortcutConsumed(std::shared_ptr<KeyEvent> keyEvent);
89     void UpdateShortcutConsumed(std::shared_ptr<KeyEvent> keyEvent);
90     void MarkShortcutConsumed(const ShortcutKey &shortcut);
91     void MarkShortcutConsumed(const KeyOption &shortcut);
92 
93     static std::shared_ptr<KeyShortcutManager> GetInstance();
94 
95 private:
96     struct SystemKey {
97         uint32_t modifiers;
98         int32_t finalKey;
99 
100         bool operator<(const SystemKey &other) const;
101     };
102 
103     struct ExceptionalSystemKey {
104         std::set<int32_t> preKeys;
105         int32_t finalKey;
106         int32_t longPressTime; // ms
107         ShortcutTriggerType triggerType;
108 
109         bool operator<(const ExceptionalSystemKey &other) const;
110     };
111 
112     struct KeyShortcut {
113         uint32_t modifiers;
114         int32_t finalKey;
115         int32_t longPressTime; // ms
116         ShortcutTriggerType triggerType;
117         int32_t session;
118         std::function<void(std::shared_ptr<KeyEvent>)> callback;
119     };
120 
121     struct SystemHotkey {
122         std::set<int32_t> preKeys;
123         int32_t finalKey;
124 
125         bool operator<(const SystemHotkey &other) const;
126     };
127 
128     void LoadSystemKeys();
129     void ReadSystemKeys(const std::string &cfgPath);
130     int32_t ReadSystemKey(cJSON *jsonSysKey);
131     int32_t AddSystemKey(const std::set<int32_t> &preKeys, int32_t finalKey);
132     void LoadExceptionalSystemKeys();
133     void ReadExceptionalSystemKeys(const std::string &cfgPath);
134     int32_t ReadExceptionalSystemKey(cJSON *jsonSysKey);
135     void AddExceptionalSystemKey(const ExceptionalSystemKey &sysKey);
136     std::string FormatModifiers(const std::set<int32_t> &modifiers) const;
137     int32_t GenerateId() const;
138     bool IsExceptionalSystemKey(const ExceptionalSystemKey &sysKey) const;
139     bool IsModifier(int32_t keyCode) const;
140     bool CheckSystemKey(const SystemShortcutKey &key, KeyShortcut &shortcut) const;
141     bool IsValid(const ShortcutTriggerType triggerType) const;
142     bool IsReservedSystemKey(const KeyShortcut &shortcut) const;
143     bool CheckGlobalKey(const HotKey &key, KeyShortcut &shortcut) const;
144     bool HaveRegisteredGlobalKey(const KeyShortcut &key) const;
145     std::string FormatPressedKeys(std::shared_ptr<KeyEvent> keyEvent) const;
146     std::set<int32_t> GetForegroundPids() const;
147     bool HandleKeyDown(std::shared_ptr<KeyEvent> keyEvent);
148     bool HandleKeyUp(std::shared_ptr<KeyEvent> keyEvent);
149     bool HandleKeyCancel(std::shared_ptr<KeyEvent> keyEvent);
150     bool CheckCombination(std::shared_ptr<KeyEvent> keyEvent, const KeyShortcut &shortcut) const;
151     bool CheckPureModifiers(std::shared_ptr<KeyEvent> keyEvent, const KeyShortcut &shortcut) const;
152     bool CheckModifiers(std::shared_ptr<KeyEvent> keyEvent, const KeyShortcut &shortcut) const;
153     void TriggerDown(std::shared_ptr<KeyEvent> keyEvent, int32_t shortcutId, const KeyShortcut &shortcut);
154     void RunShortcut(std::shared_ptr<KeyEvent> keyEvent, int32_t shortcutId);
155     void TriggerUp(std::shared_ptr<KeyEvent> keyEvent, int32_t shortcutId, const KeyShortcut &shortcut);
156     void ResetTriggering(std::shared_ptr<KeyEvent> keyEvent);
157     bool WillResetOnKeyDown(int32_t keyCode, const KeyShortcut &shortcut) const;
158     bool WillResetOnKeyUp(int32_t keyCode, const KeyShortcut &shortcut) const;
159     void ResetTriggering(int32_t shortcutId);
160     void LoadHotkeys();
161     void ReadHotkeys(const std::string &cfgPath);
162     int32_t ReadHotkey(cJSON *jsonSysKey);
163     int32_t AddHotkey(const std::set<int32_t> &preKeys, int32_t finalKey);
164 
165     std::set<int32_t> shortcutConsumed_;
166     std::set<SystemKey> systemKeys_;
167     std::set<ExceptionalSystemKey> exceptSysKeys_;
168     std::map<int32_t, KeyShortcut> shortcuts_;
169     std::map<int32_t, int32_t> triggering_;
170     static const std::map<int32_t, uint32_t> modifiers_;
171     static std::mutex mutex_;
172     static std::shared_ptr<KeyShortcutManager> instance_;
173     std::set<SystemHotkey> hotkeys_;
174     bool isCheckShortcut_ { true };
175 };
176 
177 #define KEY_SHORTCUT_MGR KeyShortcutManager::GetInstance()
178 } // namespace MMI
179 } // namespace OHOS
180 #endif // KEY_SHORTCUT_MANAGER_H
181