Pyrogenesis  trunk
Hotkey.h
Go to the documentation of this file.
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;
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  bool operator<(const SKey& o) const { return code < o.code; }
58  bool operator==(const SKey& o) const { return code == o.code; }
59 };
60 
61 // Hotkey data associated with an externally-specified 'primary' keycode
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  */
90 /**
91  * Actually fires hotkeys.
92  */
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
Definition: Hotkey.h:62
InReaction HotkeyStateChange(const SDL_Event_ *ev)
Updates g_HotkeyMap.
Definition: Hotkey.cpp:164
InReaction HotkeyInputPrepHandler(const SDL_Event_ *ev)
Detects hotkeys that should fire.
Definition: Hotkey.cpp:173
const uint SDL_HOTKEYPRESS_SILENT
Definition: Hotkey.h:49
void LoadHotkeys(CConfigDB &configDB)
Definition: Hotkey.cpp:135
const uint SDL_USEREVENT_
Definition: Hotkey.h:45
Definition: Hotkey.h:54
Definition: libsdl.h:52
bool operator<(const SKey &o) const
Definition: Hotkey.h:57
CStr name
Definition: Hotkey.h:64
bool operator==(const SKey &o) const
Definition: Hotkey.h:58
InReaction
Definition: input.h:34
SKey primary
Definition: Hotkey.h:65
const uint SDL_HOTKEYPRESS
Definition: Hotkey.h:46
void ResetActiveHotkeys()
Resets all currently active hotkeys (and clears in-flight hotkeys).
Definition: Hotkey.cpp:463
std::vector< SHotkeyMapping > KeyMapping
Definition: Hotkey.h:69
void UnloadHotkeys()
Definition: Hotkey.cpp:141
const uint SDL_HOTKEYUP_SILENT
Definition: Hotkey.h:50
int SDL_Scancode_
Definition: Hotkey.h:41
const uint SDL_HOTKEYUP
Definition: Hotkey.h:48
InReaction HotkeyInputActualHandler(const SDL_Event_ *ev)
Actually fires hotkeys.
Definition: Hotkey.cpp:349
bool HotkeyIsPressed(const CStr &keyname)
Definition: Hotkey.cpp:478
unsigned int uint
Definition: types.h:42
bool EventWillFireHotkey(const SDL_Event_ *ev, const CStr &keyname)
Definition: Hotkey.cpp:453
const uint SDL_HOTKEYDOWN
Definition: Hotkey.h:47
std::unordered_map< SDL_Scancode_, KeyMapping > g_HotkeyMap
Definition: Hotkey.cpp:33
Definition: ConfigDB.h:66
std::vector< SKey > requires
Definition: Hotkey.h:66
constexpr SDL_Scancode_ UNUSED_HOTKEY_CODE
Definition: Hotkey.h:52
SDL_Scancode_ code
Definition: Hotkey.h:56