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#ifndef KEY_SHORTCUT_MANAGER_H
17c29fa5a6Sopenharmony_ci#define KEY_SHORTCUT_MANAGER_H
18c29fa5a6Sopenharmony_ci
19c29fa5a6Sopenharmony_ci#include <functional>
20c29fa5a6Sopenharmony_ci#include <map>
21c29fa5a6Sopenharmony_ci#include <optional>
22c29fa5a6Sopenharmony_ci#include <set>
23c29fa5a6Sopenharmony_ci
24c29fa5a6Sopenharmony_ci#include <cJSON.h>
25c29fa5a6Sopenharmony_ci#include <nocopyable.h>
26c29fa5a6Sopenharmony_ci
27c29fa5a6Sopenharmony_ci#include "key_command_handler.h"
28c29fa5a6Sopenharmony_ci#include "key_event.h"
29c29fa5a6Sopenharmony_ci#include "key_option.h"
30c29fa5a6Sopenharmony_ci
31c29fa5a6Sopenharmony_cinamespace OHOS {
32c29fa5a6Sopenharmony_cinamespace MMI {
33c29fa5a6Sopenharmony_cienum KeyShortcutError : int32_t {
34c29fa5a6Sopenharmony_ci    KEY_SHORTCUT_ERROR_BASE = -1,
35c29fa5a6Sopenharmony_ci    KEY_SHORTCUT_ERROR_CONFIG = (KEY_SHORTCUT_ERROR_BASE - 1),
36c29fa5a6Sopenharmony_ci    KEY_SHORTCUT_ERROR_COMBINATION_KEY = (KEY_SHORTCUT_ERROR_BASE - 2),
37c29fa5a6Sopenharmony_ci    KEY_SHORTCUT_ERROR_TAKEN = (KEY_SHORTCUT_ERROR_BASE - 3),
38c29fa5a6Sopenharmony_ci};
39c29fa5a6Sopenharmony_ci
40c29fa5a6Sopenharmony_ciclass KeyShortcutManager final {
41c29fa5a6Sopenharmony_cipublic:
42c29fa5a6Sopenharmony_ci    static inline constexpr uint32_t SHORTCUT_MODIFIER_ALT { 0x1 };
43c29fa5a6Sopenharmony_ci    static inline constexpr uint32_t SHORTCUT_MODIFIER_SHIFT { SHORTCUT_MODIFIER_ALT << 1U };
44c29fa5a6Sopenharmony_ci    static inline constexpr uint32_t SHORTCUT_MODIFIER_CTRL { SHORTCUT_MODIFIER_ALT << 2U };
45c29fa5a6Sopenharmony_ci    static inline constexpr uint32_t SHORTCUT_MODIFIER_LOGO { SHORTCUT_MODIFIER_ALT << 3U };
46c29fa5a6Sopenharmony_ci    static inline constexpr uint32_t SHORTCUT_MODIFIER_MASK {
47c29fa5a6Sopenharmony_ci        SHORTCUT_MODIFIER_ALT | SHORTCUT_MODIFIER_SHIFT | SHORTCUT_MODIFIER_CTRL | SHORTCUT_MODIFIER_LOGO };
48c29fa5a6Sopenharmony_ci    static inline constexpr int32_t SHORTCUT_PURE_MODIFIERS { -1 };
49c29fa5a6Sopenharmony_ci    static inline constexpr int32_t MOUSE_BUTTON_LEFT { 25001 };
50c29fa5a6Sopenharmony_ci    static inline constexpr int32_t MOUSE_BUTTON_RIGHT { MOUSE_BUTTON_LEFT + 1 };
51c29fa5a6Sopenharmony_ci
52c29fa5a6Sopenharmony_ci    enum ShortcutTriggerType : int32_t {
53c29fa5a6Sopenharmony_ci        SHORTCUT_TRIGGER_TYPE_DOWN = 0,
54c29fa5a6Sopenharmony_ci        SHORTCUT_TRIGGER_TYPE_UP,
55c29fa5a6Sopenharmony_ci    };
56c29fa5a6Sopenharmony_ci
57c29fa5a6Sopenharmony_ci    struct SystemShortcutKey {
58c29fa5a6Sopenharmony_ci        std::set<int32_t> modifiers;
59c29fa5a6Sopenharmony_ci        int32_t finalKey;
60c29fa5a6Sopenharmony_ci        int32_t longPressTime; // ms
61c29fa5a6Sopenharmony_ci        ShortcutTriggerType triggerType;
62c29fa5a6Sopenharmony_ci        int32_t session;
63c29fa5a6Sopenharmony_ci        std::function<void(std::shared_ptr<KeyEvent>)> callback;
64c29fa5a6Sopenharmony_ci    };
65c29fa5a6Sopenharmony_ci
66c29fa5a6Sopenharmony_ci    struct HotKey {
67c29fa5a6Sopenharmony_ci        std::set<int32_t> modifiers;
68c29fa5a6Sopenharmony_ci        int32_t finalKey;
69c29fa5a6Sopenharmony_ci        int32_t longPressTime; // ms
70c29fa5a6Sopenharmony_ci        int32_t session;
71c29fa5a6Sopenharmony_ci        std::function<void(std::shared_ptr<KeyEvent>)> callback;
72c29fa5a6Sopenharmony_ci    };
73c29fa5a6Sopenharmony_ci
74c29fa5a6Sopenharmony_ci    KeyShortcutManager();
75c29fa5a6Sopenharmony_ci    ~KeyShortcutManager() = default;
76c29fa5a6Sopenharmony_ci    DISALLOW_COPY_AND_MOVE(KeyShortcutManager);
77c29fa5a6Sopenharmony_ci
78c29fa5a6Sopenharmony_ci    int32_t RegisterSystemKey(const SystemShortcutKey &key);
79c29fa5a6Sopenharmony_ci    void UnregisterSystemKey(int32_t shortcutId);
80c29fa5a6Sopenharmony_ci    int32_t RegisterHotKey(const HotKey &key);
81c29fa5a6Sopenharmony_ci    void UnregisterHotKey(int32_t shortcutId);
82c29fa5a6Sopenharmony_ci    bool HandleEvent(std::shared_ptr<KeyEvent> keyEvent);
83c29fa5a6Sopenharmony_ci    void ResetAll();
84c29fa5a6Sopenharmony_ci    int32_t GetAllSystemHotkeys(std::vector<std::unique_ptr<KeyOption>> &sysKeys);
85c29fa5a6Sopenharmony_ci    void ResetCheckState();
86c29fa5a6Sopenharmony_ci    bool IsCheckUpShortcut(const std::shared_ptr<KeyEvent> &keyEvent);
87c29fa5a6Sopenharmony_ci
88c29fa5a6Sopenharmony_ci    bool HaveShortcutConsumed(std::shared_ptr<KeyEvent> keyEvent);
89c29fa5a6Sopenharmony_ci    void UpdateShortcutConsumed(std::shared_ptr<KeyEvent> keyEvent);
90c29fa5a6Sopenharmony_ci    void MarkShortcutConsumed(const ShortcutKey &shortcut);
91c29fa5a6Sopenharmony_ci    void MarkShortcutConsumed(const KeyOption &shortcut);
92c29fa5a6Sopenharmony_ci
93c29fa5a6Sopenharmony_ci    static std::shared_ptr<KeyShortcutManager> GetInstance();
94c29fa5a6Sopenharmony_ci
95c29fa5a6Sopenharmony_ciprivate:
96c29fa5a6Sopenharmony_ci    struct SystemKey {
97c29fa5a6Sopenharmony_ci        uint32_t modifiers;
98c29fa5a6Sopenharmony_ci        int32_t finalKey;
99c29fa5a6Sopenharmony_ci
100c29fa5a6Sopenharmony_ci        bool operator<(const SystemKey &other) const;
101c29fa5a6Sopenharmony_ci    };
102c29fa5a6Sopenharmony_ci
103c29fa5a6Sopenharmony_ci    struct ExceptionalSystemKey {
104c29fa5a6Sopenharmony_ci        std::set<int32_t> preKeys;
105c29fa5a6Sopenharmony_ci        int32_t finalKey;
106c29fa5a6Sopenharmony_ci        int32_t longPressTime; // ms
107c29fa5a6Sopenharmony_ci        ShortcutTriggerType triggerType;
108c29fa5a6Sopenharmony_ci
109c29fa5a6Sopenharmony_ci        bool operator<(const ExceptionalSystemKey &other) const;
110c29fa5a6Sopenharmony_ci    };
111c29fa5a6Sopenharmony_ci
112c29fa5a6Sopenharmony_ci    struct KeyShortcut {
113c29fa5a6Sopenharmony_ci        uint32_t modifiers;
114c29fa5a6Sopenharmony_ci        int32_t finalKey;
115c29fa5a6Sopenharmony_ci        int32_t longPressTime; // ms
116c29fa5a6Sopenharmony_ci        ShortcutTriggerType triggerType;
117c29fa5a6Sopenharmony_ci        int32_t session;
118c29fa5a6Sopenharmony_ci        std::function<void(std::shared_ptr<KeyEvent>)> callback;
119c29fa5a6Sopenharmony_ci    };
120c29fa5a6Sopenharmony_ci
121c29fa5a6Sopenharmony_ci    struct SystemHotkey {
122c29fa5a6Sopenharmony_ci        std::set<int32_t> preKeys;
123c29fa5a6Sopenharmony_ci        int32_t finalKey;
124c29fa5a6Sopenharmony_ci
125c29fa5a6Sopenharmony_ci        bool operator<(const SystemHotkey &other) const;
126c29fa5a6Sopenharmony_ci    };
127c29fa5a6Sopenharmony_ci
128c29fa5a6Sopenharmony_ci    void LoadSystemKeys();
129c29fa5a6Sopenharmony_ci    void ReadSystemKeys(const std::string &cfgPath);
130c29fa5a6Sopenharmony_ci    int32_t ReadSystemKey(cJSON *jsonSysKey);
131c29fa5a6Sopenharmony_ci    int32_t AddSystemKey(const std::set<int32_t> &preKeys, int32_t finalKey);
132c29fa5a6Sopenharmony_ci    void LoadExceptionalSystemKeys();
133c29fa5a6Sopenharmony_ci    void ReadExceptionalSystemKeys(const std::string &cfgPath);
134c29fa5a6Sopenharmony_ci    int32_t ReadExceptionalSystemKey(cJSON *jsonSysKey);
135c29fa5a6Sopenharmony_ci    void AddExceptionalSystemKey(const ExceptionalSystemKey &sysKey);
136c29fa5a6Sopenharmony_ci    std::string FormatModifiers(const std::set<int32_t> &modifiers) const;
137c29fa5a6Sopenharmony_ci    int32_t GenerateId() const;
138c29fa5a6Sopenharmony_ci    bool IsExceptionalSystemKey(const ExceptionalSystemKey &sysKey) const;
139c29fa5a6Sopenharmony_ci    bool IsModifier(int32_t keyCode) const;
140c29fa5a6Sopenharmony_ci    bool CheckSystemKey(const SystemShortcutKey &key, KeyShortcut &shortcut) const;
141c29fa5a6Sopenharmony_ci    bool IsValid(const ShortcutTriggerType triggerType) const;
142c29fa5a6Sopenharmony_ci    bool IsReservedSystemKey(const KeyShortcut &shortcut) const;
143c29fa5a6Sopenharmony_ci    bool CheckGlobalKey(const HotKey &key, KeyShortcut &shortcut) const;
144c29fa5a6Sopenharmony_ci    bool HaveRegisteredGlobalKey(const KeyShortcut &key) const;
145c29fa5a6Sopenharmony_ci    std::string FormatPressedKeys(std::shared_ptr<KeyEvent> keyEvent) const;
146c29fa5a6Sopenharmony_ci    std::set<int32_t> GetForegroundPids() const;
147c29fa5a6Sopenharmony_ci    bool HandleKeyDown(std::shared_ptr<KeyEvent> keyEvent);
148c29fa5a6Sopenharmony_ci    bool HandleKeyUp(std::shared_ptr<KeyEvent> keyEvent);
149c29fa5a6Sopenharmony_ci    bool HandleKeyCancel(std::shared_ptr<KeyEvent> keyEvent);
150c29fa5a6Sopenharmony_ci    bool CheckCombination(std::shared_ptr<KeyEvent> keyEvent, const KeyShortcut &shortcut) const;
151c29fa5a6Sopenharmony_ci    bool CheckPureModifiers(std::shared_ptr<KeyEvent> keyEvent, const KeyShortcut &shortcut) const;
152c29fa5a6Sopenharmony_ci    bool CheckModifiers(std::shared_ptr<KeyEvent> keyEvent, const KeyShortcut &shortcut) const;
153c29fa5a6Sopenharmony_ci    void TriggerDown(std::shared_ptr<KeyEvent> keyEvent, int32_t shortcutId, const KeyShortcut &shortcut);
154c29fa5a6Sopenharmony_ci    void RunShortcut(std::shared_ptr<KeyEvent> keyEvent, int32_t shortcutId);
155c29fa5a6Sopenharmony_ci    void TriggerUp(std::shared_ptr<KeyEvent> keyEvent, int32_t shortcutId, const KeyShortcut &shortcut);
156c29fa5a6Sopenharmony_ci    void ResetTriggering(std::shared_ptr<KeyEvent> keyEvent);
157c29fa5a6Sopenharmony_ci    bool WillResetOnKeyDown(int32_t keyCode, const KeyShortcut &shortcut) const;
158c29fa5a6Sopenharmony_ci    bool WillResetOnKeyUp(int32_t keyCode, const KeyShortcut &shortcut) const;
159c29fa5a6Sopenharmony_ci    void ResetTriggering(int32_t shortcutId);
160c29fa5a6Sopenharmony_ci    void LoadHotkeys();
161c29fa5a6Sopenharmony_ci    void ReadHotkeys(const std::string &cfgPath);
162c29fa5a6Sopenharmony_ci    int32_t ReadHotkey(cJSON *jsonSysKey);
163c29fa5a6Sopenharmony_ci    int32_t AddHotkey(const std::set<int32_t> &preKeys, int32_t finalKey);
164c29fa5a6Sopenharmony_ci
165c29fa5a6Sopenharmony_ci    std::set<int32_t> shortcutConsumed_;
166c29fa5a6Sopenharmony_ci    std::set<SystemKey> systemKeys_;
167c29fa5a6Sopenharmony_ci    std::set<ExceptionalSystemKey> exceptSysKeys_;
168c29fa5a6Sopenharmony_ci    std::map<int32_t, KeyShortcut> shortcuts_;
169c29fa5a6Sopenharmony_ci    std::map<int32_t, int32_t> triggering_;
170c29fa5a6Sopenharmony_ci    static const std::map<int32_t, uint32_t> modifiers_;
171c29fa5a6Sopenharmony_ci    static std::mutex mutex_;
172c29fa5a6Sopenharmony_ci    static std::shared_ptr<KeyShortcutManager> instance_;
173c29fa5a6Sopenharmony_ci    std::set<SystemHotkey> hotkeys_;
174c29fa5a6Sopenharmony_ci    bool isCheckShortcut_ { true };
175c29fa5a6Sopenharmony_ci};
176c29fa5a6Sopenharmony_ci
177c29fa5a6Sopenharmony_ci#define KEY_SHORTCUT_MGR KeyShortcutManager::GetInstance()
178c29fa5a6Sopenharmony_ci} // namespace MMI
179c29fa5a6Sopenharmony_ci} // namespace OHOS
180c29fa5a6Sopenharmony_ci#endif // KEY_SHORTCUT_MANAGER_H
181