Line data Source code
1 : /* Copyright (C) 2021 Wildfire Games.
2 : * This file is part of 0 A.D.
3 : *
4 : * 0 A.D. is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 2 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * 0 A.D. is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #ifndef INCLUDED_HOTKEY
19 : #define INCLUDED_HOTKEY
20 :
21 : /**
22 : * @file
23 : * Hotkey system.
24 : *
25 : * Hotkeys consist of a name (an arbitrary string), and a key mapping.
26 : * The names and mappings are loaded from the config system (any
27 : * config setting with the name prefix "hotkey.").
28 : * When a hotkey is pressed one SDL_HOTKEYPRESS is triggered. While the key is
29 : * kept down repeated SDL_HOTKEYDOWN events are triggered at an interval
30 : * determined by the OS. When a hotkey is released an SDL_HOTKEYUP event is
31 : * triggered. All with the hotkey name stored in ev.user.data1 as a const char*.
32 : */
33 :
34 : #include "CStr.h"
35 : #include "lib/input.h"
36 :
37 : #include <unordered_map>
38 : #include <vector>
39 :
40 : // SDL_Scancode is an enum, we'll use an explicit int to avoid including SDL in this header.
41 : using SDL_Scancode_ = int;
42 :
43 : // 0x8000 is SDL_USEREVENT, this is static_asserted in Hotkey.cpp
44 : // We do this to avoid including SDL in this header.
45 : const uint SDL_USEREVENT_ = 0x8000;
46 : const uint SDL_HOTKEYPRESS = SDL_USEREVENT_;
47 : const uint SDL_HOTKEYDOWN = SDL_USEREVENT_ + 1;
48 : const uint SDL_HOTKEYUP = SDL_USEREVENT_ + 2;
49 : const uint SDL_HOTKEYPRESS_SILENT = SDL_USEREVENT_ + 3;
50 : const uint SDL_HOTKEYUP_SILENT = SDL_USEREVENT_ + 4;
51 :
52 : constexpr SDL_Scancode_ UNUSED_HOTKEY_CODE = 0; // == SDL_SCANCODE_UNKNOWN
53 :
54 : struct SKey
55 : {
56 : SDL_Scancode_ code; // scancode or MOUSE_ or UNIFIED_ value
57 0 : bool operator<(const SKey& o) const { return code < o.code; }
58 0 : bool operator==(const SKey& o) const { return code == o.code; }
59 : };
60 :
61 : // Hotkey data associated with an externally-specified 'primary' keycode
62 124 : struct SHotkeyMapping
63 : {
64 : CStr name; // name of the hotkey
65 : SKey primary; // the primary key
66 : std::vector<SKey> requires; // list of non-primary keys that must also be active
67 : };
68 :
69 : typedef std::vector<SHotkeyMapping> KeyMapping;
70 :
71 : // A mapping of scancodes onto the hotkeys that are associated with that key.
72 : // (A hotkey triggered by a combination of multiple keys will be in this map
73 : // multiple times.)
74 : extern std::unordered_map<SDL_Scancode_, KeyMapping> g_HotkeyMap;
75 :
76 : class CConfigDB;
77 : extern void LoadHotkeys(CConfigDB& configDB);
78 : extern void UnloadHotkeys();
79 :
80 : /**
81 : * Updates g_HotkeyMap.
82 : */
83 : extern InReaction HotkeyStateChange(const SDL_Event_* ev);
84 :
85 : /**
86 : * Detects hotkeys that should fire. This allows using EventWillFireHotkey,
87 : * (and then possibly preventing those hotkeys from firing by handling the event).
88 : */
89 : extern InReaction HotkeyInputPrepHandler(const SDL_Event_* ev);
90 : /**
91 : * Actually fires hotkeys.
92 : */
93 : extern InReaction HotkeyInputActualHandler(const SDL_Event_* ev);
94 :
95 : /**
96 : * @return whether the event @param ev will fire the hotkey @param keyname.
97 : */
98 : extern bool EventWillFireHotkey(const SDL_Event_* ev, const CStr& keyname);
99 :
100 : /**
101 : * Resets all currently active hotkeys (and clears in-flight hotkeys).
102 : * You should call this when something grabs key input, e.g. an input box,
103 : * as those prevent keydown/keyup messages from reaching the hotkey system,
104 : * and can lead to hotkeys being stuck active.
105 : * NB: active hotkeys are released immediately and "HotkeyUp" message sent.
106 : */
107 : extern void ResetActiveHotkeys();
108 :
109 : /**
110 : * @return whether the hotkey is currently pressed (i.e. active).
111 : */
112 : extern bool HotkeyIsPressed(const CStr& keyname);
113 :
114 : #endif // INCLUDED_HOTKEY
|