openMSX
HotKey.hh
Go to the documentation of this file.
1 #ifndef HOTKEY_HH
2 #define HOTKEY_HH
3 
4 #include "RTSchedulable.hh"
5 #include "EventListener.hh"
6 #include "Command.hh"
7 #include "Event.hh"
8 #include "TclObject.hh"
9 #include <map>
10 #include <string_view>
11 #include <vector>
12 #include <string>
13 
14 namespace openmsx {
15 
16 class RTScheduler;
17 class GlobalCommandController;
18 class EventDistributor;
19 
20 class HotKey final : public RTSchedulable, public EventListener
21 {
22 public:
23  struct HotKeyInfo {
24  HotKeyInfo(const Event& event_, std::string command_,
25  bool repeat_ = false, bool passEvent_ = false)
26  : event(event_), command(std::move(command_))
27  , repeat(repeat_)
28  , passEvent(passEvent_) {}
30  std::string command;
31  bool repeat;
32  bool passEvent; // whether to pass event with args back to command
33  };
34  using BindMap = std::vector<HotKeyInfo>; // unsorted
35  using KeySet = std::vector<Event>; // unsorted
36 
37  HotKey(RTScheduler& rtScheduler,
38  GlobalCommandController& commandController,
39  EventDistributor& eventDistributor);
40  ~HotKey();
41 
42  void loadInit();
43  void loadBind(std::string_view key, std::string_view cmd, bool repeat, bool event);
44  void loadUnbind(std::string_view key);
45 
46  template<typename XmlStream>
47  void saveBindings(XmlStream& xml) const
48  {
49  xml.begin("bindings");
50  // add explicit bind's
51  for (const auto& k : boundKeys) {
52  xml.begin("bind");
53  xml.attribute("key", toString(k));
54  const auto& info = *find_unguarded(cmdMap, k, &HotKeyInfo::event);
55  if (info.repeat) {
56  xml.attribute("repeat", "true");
57  }
58  if (info.passEvent) {
59  xml.attribute("event", "true");
60  }
61  xml.data(info.command);
62  xml.end("bind");
63  }
64  // add explicit unbinds
65  for (const auto& k : unboundKeys) {
66  xml.begin("unbind");
67  xml.attribute("key", toString(k));
68  xml.end("unbind");
69  }
70  xml.end("bindings");
71  }
72 
73 private:
74  struct LayerInfo {
75  std::string layer;
76  bool blocking;
77  };
78 
79  void initDefaultBindings();
80  void bind (HotKeyInfo&& info);
81  void unbind (const Event& event);
82  void bindDefault (HotKeyInfo&& info);
83  void unbindDefault(const Event& event);
84  void bindLayer (HotKeyInfo&& info, const std::string& layer);
85  void unbindLayer (const Event& event, const std::string& layer);
86  void unbindFullLayer(const std::string& layer);
87  void activateLayer (std::string layer, bool blocking);
88  void deactivateLayer(std::string_view layer);
89 
90  int executeEvent(const Event& event);
91  void executeBinding(const Event& event, const HotKeyInfo& info);
92  void startRepeat (const Event& event);
93  void stopRepeat();
94 
95  // EventListener
96  int signalEvent(const Event& event) noexcept override;
97  // RTSchedulable
98  void executeRT() override;
99 
100 private:
101  class BindCmd final : public Command {
102  public:
103  BindCmd(CommandController& commandController, HotKey& hotKey,
104  bool defaultCmd);
105  void execute(span<const TclObject> tokens, TclObject& result) override;
106  [[nodiscard]] std::string help(span<const TclObject> tokens) const override;
107  private:
108  HotKey& hotKey;
109  const bool defaultCmd;
110  };
111  BindCmd bindCmd;
112  BindCmd bindDefaultCmd;
113 
114  class UnbindCmd final : public Command {
115  public:
116  UnbindCmd(CommandController& commandController, HotKey& hotKey,
117  bool defaultCmd);
118  void execute(span<const TclObject> tokens, TclObject& result) override;
119  [[nodiscard]] std::string help(span<const TclObject> tokens) const override;
120  private:
121  HotKey& hotKey;
122  const bool defaultCmd;
123  };
124  UnbindCmd unbindCmd;
125  UnbindCmd unbindDefaultCmd;
126 
127  struct ActivateCmd final : Command {
128  explicit ActivateCmd(CommandController& commandController);
129  void execute(span<const TclObject> tokens, TclObject& result) override;
130  [[nodiscard]] std::string help(span<const TclObject> tokens) const override;
131  } activateCmd;
132 
133  struct DeactivateCmd final : Command {
134  explicit DeactivateCmd(CommandController& commandController);
135  void execute(span<const TclObject> tokens, TclObject& result) override;
136  [[nodiscard]] std::string help(span<const TclObject> tokens) const override;
137  } deactivateCmd;
138 
139  BindMap cmdMap;
140  BindMap defaultMap;
141  std::map<std::string, BindMap> layerMap;
142  std::vector<LayerInfo> activeLayers;
143  KeySet boundKeys;
144  KeySet unboundKeys;
145  GlobalCommandController& commandController;
146  EventDistributor& eventDistributor;
147  Event lastEvent;
148 };
149 
150 } // namespace openmsx
151 
152 #endif
HotKey(RTScheduler &rtScheduler, GlobalCommandController &commandController, EventDistributor &eventDistributor)
Definition: HotKey.cc:37
void loadUnbind(std::string_view key)
Definition: HotKey.cc:189
void saveBindings(XmlStream &xml) const
Definition: HotKey.hh:47
std::vector< HotKeyInfo > BindMap
Definition: HotKey.hh:34
void loadBind(std::string_view key, std::string_view cmd, bool repeat, bool event)
Definition: HotKey.cc:183
void loadInit()
Definition: HotKey.cc:175
std::vector< Event > KeySet
Definition: HotKey.hh:35
Definition: span.hh:126
This file implemented 3 utility functions:
Definition: Autofire.cc:9
std::string toString(const Event &event)
Get a string representation of this event.
Definition: Event.cc:176
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
HotKeyInfo(const Event &event_, std::string command_, bool repeat_=false, bool passEvent_=false)
Definition: HotKey.hh:24
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.
Definition: xrange.hh:170