openMSX
HotKey.hh
Go to the documentation of this file.
1#ifndef HOTKEY_HH
2#define HOTKEY_HH
3
4#include "Command.hh"
5#include "Event.hh"
6#include "EventListener.hh"
7#include "EventDistributor.hh"
8#include "RTSchedulable.hh"
9
10#include "TclObject.hh"
11
12#include <map>
13#include <optional>
14#include <string>
15#include <string_view>
16#include <vector>
17
18namespace openmsx {
19
20class GlobalCommandController;
21class RTScheduler;
22
23class HotKey final : public RTSchedulable
24{
25public:
26 struct Data {
27 std::string_view key;
28 std::string_view cmd;
29 bool repeat = false;
30 bool event = false;
31 bool msx = false;
32 };
33
34 struct HotKeyInfo {
35 HotKeyInfo(Event event_, std::string command_,
36 bool repeat_ = false, bool passEvent_ = false, bool msx_ = false)
37 : event(std::move(event_)), command(std::move(command_))
38 , repeat(repeat_), passEvent(passEvent_), msx(msx_) {}
40 std::string command;
41 bool repeat;
42 bool passEvent; // whether to pass event with args back to command
43 bool msx; // false->global binding, true->only active when msx window has focus
44 };
45 using BindMap = std::vector<HotKeyInfo>; // unsorted
46 using KeySet = std::vector<Event>; // unsorted
47
48 HotKey(RTScheduler& rtScheduler,
49 GlobalCommandController& commandController,
50 EventDistributor& eventDistributor);
51
52 void loadInit();
53 void loadBind(const Data& data);
54 void loadUnbind(std::string_view key);
55
56 template<typename XmlStream>
57 void saveBindings(XmlStream& xml) const
58 {
59 xml.begin("bindings");
60 // add explicit binds
61 for (const auto& k : boundKeys) {
62 xml.begin("bind");
63 xml.attribute("key", toString(k));
64 const auto& info = *find_unguarded(cmdMap, k, &HotKeyInfo::event);
65 if (info.repeat) {
66 xml.attribute("repeat", "true");
67 }
68 if (info.passEvent) {
69 xml.attribute("event", "true");
70 }
71 if (info.msx) {
72 xml.attribute("msx", "true");
73 }
74 xml.data(info.command);
75 xml.end("bind");
76 }
77 // add explicit unbinds
78 for (const auto& k : unboundKeys) {
79 xml.begin("unbind");
80 xml.attribute("key", toString(k));
81 xml.end("unbind");
82 }
83 xml.end("bindings");
84 }
85
86 const auto& getGlobalBindings() const { return cmdMap; }
87
88private:
89 struct LayerInfo {
90 LayerInfo(std::string l, bool b)
91 : layer(std::move(l)), blocking(b) {} // clang-15 workaround
92
93 std::string layer;
94 bool blocking;
95 };
96
97 void initDefaultBindings();
98 void bind (HotKeyInfo&& info);
99 void unbind (const Event& event);
100 void bindDefault (HotKeyInfo&& info);
101 void unbindDefault(const Event& event);
102 void bindLayer (HotKeyInfo&& info, const std::string& layer);
103 void unbindLayer (const Event& event, const std::string& layer);
104 void unbindFullLayer(const std::string& layer);
105 void activateLayer (std::string layer, bool blocking);
106 void deactivateLayer(std::string_view layer);
107
108 bool executeEvent(const Event& event, EventDistributor::Priority priority);
109 void executeBinding(const Event& event, const HotKeyInfo& info);
110 void startRepeat (const Event& event);
111 void stopRepeat();
112
113 bool signalEvent(const Event& event, EventDistributor::Priority priority);
114
115 // RTSchedulable
116 void executeRT() override;
117
118private:
119 class BindCmd final : public Command {
120 public:
121 BindCmd(CommandController& commandController, HotKey& hotKey,
122 bool defaultCmd);
123 void execute(std::span<const TclObject> tokens, TclObject& result) override;
124 [[nodiscard]] std::string help(std::span<const TclObject> tokens) const override;
125 private:
126 HotKey& hotKey;
127 const bool defaultCmd;
128 };
129 BindCmd bindCmd;
130 BindCmd bindDefaultCmd;
131
132 class UnbindCmd final : public Command {
133 public:
134 UnbindCmd(CommandController& commandController, HotKey& hotKey,
135 bool defaultCmd);
136 void execute(std::span<const TclObject> tokens, TclObject& result) override;
137 [[nodiscard]] std::string help(std::span<const TclObject> tokens) const override;
138 private:
139 HotKey& hotKey;
140 const bool defaultCmd;
141 };
142 UnbindCmd unbindCmd;
143 UnbindCmd unbindDefaultCmd;
144
145 struct ActivateCmd final : Command {
146 explicit ActivateCmd(CommandController& commandController);
147 void execute(std::span<const TclObject> tokens, TclObject& result) override;
148 [[nodiscard]] std::string help(std::span<const TclObject> tokens) const override;
149 } activateCmd;
150
151 struct DeactivateCmd final : Command {
152 explicit DeactivateCmd(CommandController& commandController);
153 void execute(std::span<const TclObject> tokens, TclObject& result) override;
154 [[nodiscard]] std::string help(std::span<const TclObject> tokens) const override;
155 } deactivateCmd;
156
157 BindMap cmdMap;
158 BindMap defaultMap;
159 std::map<std::string, BindMap, std::less<>> layerMap;
160 std::vector<LayerInfo> activeLayers;
161 KeySet boundKeys;
162 KeySet unboundKeys;
163 GlobalCommandController& commandController;
164 EventDistributor& eventDistributor;
165 std::optional<Event> lastEvent;
166
167 class Listener : public EventListener {
168 public:
169 Listener(HotKey& hotKey, EventDistributor::Priority priority);
170 ~Listener();
171 bool signalEvent(const Event& event) override;
172 private:
173 HotKey& hotKey;
175 };
176 Listener listenerHigh;
177 Listener listenerLow;
178};
179
180} // namespace openmsx
181
182#endif
Priority
Priorities from high to low, higher priority listeners can block events for lower priority listeners.
void loadUnbind(std::string_view key)
Definition HotKey.cc:155
void saveBindings(XmlStream &xml) const
Definition HotKey.hh:57
std::vector< HotKeyInfo > BindMap
Definition HotKey.hh:45
void loadBind(const Data &data)
Definition HotKey.cc:149
const auto & getGlobalBindings() const
Definition HotKey.hh:86
void loadInit()
Definition HotKey.cc:141
std::vector< Event > KeySet
Definition HotKey.hh:46
This file implemented 3 utility functions:
Definition Autofire.cc:11
std::string toString(const BooleanInput &input)
std::variant< KeyUpEvent, KeyDownEvent, MouseMotionEvent, MouseButtonUpEvent, MouseButtonDownEvent, MouseWheelEvent, JoystickAxisMotionEvent, JoystickHatEvent, JoystickButtonUpEvent, JoystickButtonDownEvent, OsdControlReleaseEvent, OsdControlPressEvent, WindowEvent, TextEvent, FileDropEvent, QuitEvent, FinishFrameEvent, CliCommandEvent, GroupEvent, BootEvent, FrameDrawnEvent, BreakEvent, SwitchRendererEvent, TakeReverseSnapshotEvent, AfterTimedEvent, MachineLoadedEvent, MachineActivatedEvent, MachineDeactivatedEvent, MidiInReaderEvent, MidiInWindowsEvent, MidiInCoreMidiEvent, MidiInCoreMidiVirtualEvent, MidiInALSAEvent, Rs232TesterEvent, Rs232NetEvent, ImGuiDelayedActionEvent, ImGuiActiveEvent > Event
Definition Event.hh:445
STL namespace.
ITER find_unguarded(ITER first, ITER last, const VAL &val, Proj proj={})
Faster alternative to 'find' when it's guaranteed that the value will be found (if not the behavior i...
Definition stl.hh:72
std::string_view key
Definition HotKey.hh:27
std::string_view cmd
Definition HotKey.hh:28
HotKeyInfo(Event event_, std::string command_, bool repeat_=false, bool passEvent_=false, bool msx_=false)
Definition HotKey.hh:35