openMSX
Event.cc
Go to the documentation of this file.
1#include "Event.hh"
2#include "stl.hh"
3#include "strCat.hh"
4#include <tuple>
5#include <SDL.h>
6
7using namespace std::literals;
8
9namespace openmsx {
10
11[[nodiscard]] static constexpr uint16_t normalizeKeyMod(uint16_t m)
12{
13 // when either left or right modifier is pressed, add the other one as well
14 if (m & KMOD_SHIFT) m |= KMOD_SHIFT;
15 if (m & KMOD_CTRL) m |= KMOD_CTRL;
16 if (m & KMOD_ALT) m |= KMOD_ALT;
17 if (m & KMOD_GUI) m |= KMOD_GUI;
18 // ignore stuff like: KMOD_NUM, KMOD_CAPS, KMOD_SCROLL
19 m &= (KMOD_SHIFT | KMOD_CTRL | KMOD_ALT | KMOD_GUI | KMOD_MODE);
20 return m;
21}
22
23bool operator==(const Event& x, const Event& y)
24{
25 return std::visit(overloaded{
26 [](const KeyUpEvent& a, const KeyUpEvent& b) {
27 // note: don't compare scancode, unicode
28 return std::tuple(a.getKeyCode(), normalizeKeyMod(a.getModifiers())) ==
29 std::tuple(b.getKeyCode(), normalizeKeyMod(b.getModifiers()));
30 },
31 [](const KeyDownEvent& a, const KeyDownEvent& b) {
32 // note: don't compare scancode, unicode
33 return std::tuple(a.getKeyCode(), normalizeKeyMod(a.getModifiers())) ==
34 std::tuple(b.getKeyCode(), normalizeKeyMod(b.getModifiers()));
35 },
36 [](const MouseMotionEvent& a, const MouseMotionEvent& b) {
37 return std::tuple(a.getX(), a.getY(), a.getAbsX(), a.getAbsY()) ==
38 std::tuple(b.getX(), b.getY(), b.getAbsX(), b.getAbsY());
39 },
40 [](const MouseButtonUpEvent& a, const MouseButtonUpEvent& b) {
41 return a.getButton() == b.getButton();
42 },
43 [](const MouseButtonDownEvent& a, const MouseButtonDownEvent& b) {
44 return a.getButton() == b.getButton();
45 },
46 [](const MouseWheelEvent& a, const MouseWheelEvent& b) {
47 return std::tuple(a.getX(), a.getY()) ==
48 std::tuple(b.getX(), b.getY());
49 },
51 return std::tuple(a.getJoystick(), a.getAxis(), a.getValue()) ==
52 std::tuple(b.getJoystick(), b.getAxis(), b.getValue());
53 },
54 [](const JoystickHatEvent& a, const JoystickHatEvent& b) {
55 return std::tuple(a.getJoystick(), a.getHat(), a.getValue()) ==
56 std::tuple(b.getJoystick(), b.getHat(), b.getValue());
57 },
58 [](const JoystickButtonUpEvent& a, const JoystickButtonUpEvent& b) {
59 return std::tuple(a.getJoystick(), a.getButton()) ==
60 std::tuple(b.getJoystick(), b.getButton());
61 },
63 return std::tuple(a.getJoystick(), a.getButton()) ==
64 std::tuple(b.getJoystick(), b.getButton());
65 },
66 [](const OsdControlReleaseEvent& a, const OsdControlReleaseEvent& b) {
67 return a.getButton() == b.getButton();
68 },
69 [](const OsdControlPressEvent& a, const OsdControlPressEvent& b) {
70 return a.getButton() == b.getButton();
71 },
72 [](const WindowEvent& a_, const WindowEvent& b_) {
73 const auto& a = a_.getSdlWindowEvent();
74 const auto& b = b_.getSdlWindowEvent();
75 // don't compare timestamp
76 if (a.event != b.event) return false;
77 if (a.windowID != b.windowID) return false;
78 // TODO for specific events, compare data1 and data2
79 return true;
80 },
81 [](const FileDropEvent& a, const FileDropEvent& b) {
82 return a.getFileName() == b.getFileName();
83 },
84 [](const FinishFrameEvent& a, const FinishFrameEvent& b) {
85 return std::tuple(a.getSource(), a.getSelectedSource(), a.isSkipped()) ==
86 std::tuple(b.getSource(), b.getSelectedSource(), b.isSkipped());
87 },
88 [](const CliCommandEvent& a, const CliCommandEvent& b) {
89 return a.getCommand() == b.getCommand();
90 },
91 [](const GroupEvent& a, const GroupEvent& b) {
92 return a.getTclListComponents() ==
93 b.getTclListComponents();
94 },
95 [&](const EventBase& /*a*/, const EventBase& /*b*/) {
96 return getType(x) == getType(y);
97 }
98 }, x, y);
99}
100
102{
103 static constexpr std::array osdControlNames = {
104 "LEFT"sv, "RIGHT"sv, "UP"sv, "DOWN"sv, "A"sv, "B"sv
105 };
106
107 return std::visit(overloaded{
108 [](const KeyEvent& e) {
109 // Note: 'scanCode' is not included (also not in operator==()).
110 //
111 // At the moment 'scanCode' is only used in the MSX Keyboard code when
112 // the POSITIONAL mapping mode is active. It is not used for key
113 // bindings (the 'bind' or the 'after' commands) or for the openMSX
114 // console. KeyEvents also don't end up in 'reverse replay' files
115 // (instead those files contain more low level MSX keyboard matrix
116 // changes).
117 //
118 // Within these constraints it's fine to ignore 'scanCode' in this
119 // method.
120 auto result = makeTclList("keyb", e.getKey().toString());
121 if (e.getUnicode() != 0) {
122 result.addListElement(tmpStrCat("unicode", e.getUnicode()));
123 }
124 return result;
125 },
126 [](const MouseMotionEvent& e) {
127 return makeTclList("mouse", "motion", e.getX(), e.getY(), e.getAbsX(), e.getAbsY());
128 },
129 [](const MouseButtonUpEvent& e) {
130 return makeTclList("mouse", tmpStrCat("button", e.getButton()), "up");
131 },
132 [](const MouseButtonDownEvent& e) {
133 return makeTclList("mouse", tmpStrCat("button", e.getButton()), "down");
134 },
135 [](const MouseWheelEvent& e) {
136 return makeTclList("mouse", "wheel", e.getX(), e.getY());
137 },
138 [](const JoystickAxisMotionEvent& e) {
139 return makeTclList(e.getJoystick().str(), tmpStrCat("axis", e.getAxis()), e.getValue());
140 },
141 [](const JoystickHatEvent& e) {
142 const char* str = [&] {
143 switch (e.getValue()) {
144 case SDL_HAT_UP: return "up";
145 case SDL_HAT_RIGHT: return "right";
146 case SDL_HAT_DOWN: return "down";
147 case SDL_HAT_LEFT: return "left";
148 case SDL_HAT_RIGHTUP: return "rightup";
149 case SDL_HAT_RIGHTDOWN: return "rightdown";
150 case SDL_HAT_LEFTUP: return "leftup";
151 case SDL_HAT_LEFTDOWN: return "leftdown";
152 default: return "center";
153 }
154 }();
155 return makeTclList(e.getJoystick().str(), tmpStrCat("hat", e.getHat()), str);
156 },
157 [](const JoystickButtonUpEvent& e) {
158 return makeTclList(e.getJoystick().str(), tmpStrCat("button", e.getButton()), "up");
159 },
160 [](const JoystickButtonDownEvent& e) {
161 return makeTclList(e.getJoystick().str(), tmpStrCat("button", e.getButton()), "down");
162 },
163 [](const OsdControlReleaseEvent& e) {
164 return makeTclList("OSDcontrol", osdControlNames[e.getButton()], "RELEASE");
165 },
166 [](const OsdControlPressEvent& e) {
167 return makeTclList("OSDcontrol", osdControlNames[e.getButton()], "PRESS");
168 },
169 [](const WindowEvent& e_) {
170 const auto& e = e_.getSdlWindowEvent();
171 if (e.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
172 return makeTclList("focus", true);
173 } else if (e.event == SDL_WINDOWEVENT_FOCUS_LOST) {
174 return makeTclList("focus", false);
175 }
176 return makeTclList(); // other events don't need a textual representation (yet)
177 },
178 [](const TextEvent&) {
179 return makeTclList(); // doesn't need a textual representation (yet)
180 },
181 [](const FileDropEvent& e) {
182 return makeTclList("filedrop", e.getFileName());
183 },
184 [](const QuitEvent& /*e*/) {
185 return makeTclList("quit");
186 },
187 [](const FinishFrameEvent& e) {
188 return makeTclList("finishframe", int(e.getSource()), int(e.getSelectedSource()), e.isSkipped());
189 },
190 [](const CliCommandEvent& e) {
191 return makeTclList("CliCmd", e.getCommand());
192 },
193 [](const GroupEvent& e) {
194 return e.getTclListComponents();
195 },
196 [&](const SimpleEvent& /*e*/) {
197 return makeTclList("simple", int(getType(event)));
198 },
199 [](const ImGuiActiveEvent& e) {
200 return makeTclList("imgui", e.getActive());
201 }
202 }, event);
203}
204
205std::string toString(const Event& event)
206{
207 return std::string(toTclList(event).getString());
208}
209
210bool matches(const Event& self, const Event& other)
211{
212 return std::visit(overloaded{
213 [&](const GroupEvent& e) {
214 return contains(e.getTypesToMatch(), getType(other));
215 },
216 [&](const EventBase&) {
217 return self == other;
218 }
219 }, self);
220}
221
222} // namespace openmsx
Command received on CliComm connection.
Definition Event.hh:346
This event is send when a device (v99x8, v9990, video9000, laserdisc) reaches the end of a frame.
Definition Event.hh:324
SDL_Keycode getKeyCode() const
Definition Event.hh:45
uint16_t getModifiers() const
Definition Event.hh:47
const SDL_WindowEvent & getSdlWindowEvent() const
Definition Event.hh:222
This file implemented 3 utility functions:
Definition Autofire.cc:9
bool operator==(const BooleanInput &x, const BooleanInput &y)
bool matches(const Event &self, const Event &other)
Does this event 'match' the given event.
Definition Event.cc:210
TclObject toTclList(const Event &event)
Similar to toString(), but retains the structure of the event.
Definition Event.cc:101
EventType getType(const Event &event)
Definition Event.hh:526
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:454
TclObject makeTclList(Args &&... args)
Definition TclObject.hh:289
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
Definition stl.hh:32
TemporaryString tmpStrCat(Ts &&... ts)
Definition strCat.hh:742