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
11bool operator==(const Event& x, const Event& y)
12{
13 return visit(overloaded{
14 [](const KeyUpEvent& a, const KeyUpEvent& b) {
15 // note: don't compare scancode, unicode
16 return a.getKeyCode() == b.getKeyCode();
17 },
18 [](const KeyDownEvent& a, const KeyDownEvent& b) {
19 // note: don't compare scancode, unicode
20 return a.getKeyCode() == b.getKeyCode();
21 },
22 [](const MouseMotionEvent& a, const MouseMotionEvent& b) {
23 return std::tuple(a.getX(), a.getY(), a.getAbsX(), a.getAbsY()) ==
24 std::tuple(b.getX(), b.getY(), b.getAbsX(), b.getAbsY());
25 },
26 [](const MouseButtonUpEvent& a, const MouseButtonUpEvent& b) {
27 return a.getButton() == b.getButton();
28 },
29 [](const MouseButtonDownEvent& a, const MouseButtonDownEvent& b) {
30 return a.getButton() == b.getButton();
31 },
32 [](const MouseWheelEvent& a, const MouseWheelEvent& b) {
33 return std::tuple(a.getX(), a.getY()) ==
34 std::tuple(b.getX(), b.getY());
35 },
37 return std::tuple(a.getJoystick(), a.getAxis(), a.getValue()) ==
38 std::tuple(b.getJoystick(), b.getAxis(), b.getValue());
39 },
40 [](const JoystickHatEvent& a, const JoystickHatEvent& b) {
41 return std::tuple(a.getJoystick(), a.getHat(), a.getValue()) ==
42 std::tuple(b.getJoystick(), b.getHat(), b.getValue());
43 },
44 [](const JoystickButtonUpEvent& a, const JoystickButtonUpEvent& b) {
45 return std::tuple(a.getJoystick(), a.getButton()) ==
46 std::tuple(b.getJoystick(), b.getButton());
47 },
49 return std::tuple(a.getJoystick(), a.getButton()) ==
50 std::tuple(b.getJoystick(), b.getButton());
51 },
52 [](const OsdControlReleaseEvent& a, const OsdControlReleaseEvent& b) {
53 return a.getButton() == b.getButton();
54 },
55 [](const OsdControlPressEvent& a, const OsdControlPressEvent& b) {
56 return a.getButton() == b.getButton();
57 },
58 [](const FocusEvent& a, const FocusEvent& b) {
59 return a.getGain() == b.getGain();
60 },
61 [](const ResizeEvent& a, const ResizeEvent& b) {
62 return std::tuple(a.getX(), a.getY()) ==
63 std::tuple(b.getX(), b.getY());
64 },
65 [](const FileDropEvent& a, const FileDropEvent& b) {
66 return a.getFileName() == b.getFileName();
67 },
68 [](const FinishFrameEvent& a, const FinishFrameEvent& b) {
69 return std::tuple(a.getSource(), a.getSelectedSource(), a.isSkipped()) ==
70 std::tuple(b.getSource(), b.getSelectedSource(), b.isSkipped());
71 },
72 [](const CliCommandEvent& a, const CliCommandEvent& b) {
73 return a.getCommand() == b.getCommand();
74 },
75 [](const GroupEvent& a, const GroupEvent& b) {
76 return a.getTclListComponents() ==
77 b.getTclListComponents();
78 },
79 [&](const EventBase& /*a*/, const EventBase& /*b*/) {
80 return getType(x) == getType(y);
81 }
82 }, x, y);
83}
84
86{
87 static constexpr std::array osdControlNames = {
88 "LEFT"sv, "RIGHT"sv, "UP"sv, "DOWN"sv, "A"sv, "B"sv
89 };
90
91 return visit(overloaded{
92 [](const KeyEvent& e) {
93 // Note: 'scanCode' is not included (also not in operator==()).
94 //
95 // At the moment 'scanCode' is only used in the MSX Keyboard code when
96 // the POSITIONAL mapping mode is active. It is not used for key
97 // bindings (the 'bind' or the 'after' commands) or for the openMSX
98 // console. KeyEvents also don't end up in 'reverse replay' files
99 // (instead those files contain more low level MSX keyboard matrix
100 // changes).
101 //
102 // Within these constraints it's fine to ignore 'scanCode' in this
103 // method.
104 auto result = makeTclList("keyb", Keys::getName(e.getKeyCode()));
105 if (e.getUnicode() != 0) {
106 result.addListElement(tmpStrCat("unicode", e.getUnicode()));
107 }
108 return result;
109 },
110 [](const MouseMotionEvent& e) {
111 return makeTclList("mouse", "motion", e.getX(), e.getY(), e.getAbsX(), e.getAbsY());
112 },
113 [](const MouseButtonUpEvent& e) {
114 return makeTclList("mouse", tmpStrCat("button", e.getButton()), "up");
115 },
116 [](const MouseButtonDownEvent& e) {
117 return makeTclList("mouse", tmpStrCat("button", e.getButton()), "down");
118 },
119 [](const MouseWheelEvent& e) {
120 return makeTclList("mouse", "wheel", e.getX(), e.getY());
121 },
122 [](const JoystickAxisMotionEvent& e) {
123 return makeTclList(tmpStrCat("joy", e.getJoystick() + 1), tmpStrCat("axis", e.getAxis()), e.getValue());
124 },
125 [](const JoystickHatEvent& e) {
126 const char* str = [&] {
127 switch (e.getValue()) {
128 case SDL_HAT_UP: return "up";
129 case SDL_HAT_RIGHT: return "right";
130 case SDL_HAT_DOWN: return "down";
131 case SDL_HAT_LEFT: return "left";
132 case SDL_HAT_RIGHTUP: return "rightup";
133 case SDL_HAT_RIGHTDOWN: return "rightdown";
134 case SDL_HAT_LEFTUP: return "leftup";
135 case SDL_HAT_LEFTDOWN: return "leftdown";
136 default: return "center";
137 }
138 }();
139 return makeTclList(tmpStrCat("joy", e.getJoystick() + 1), tmpStrCat("hat", e.getHat()), str);
140 },
141 [](const JoystickButtonUpEvent& e) {
142 return makeTclList(tmpStrCat("joy", e.getJoystick() + 1), tmpStrCat("button", e.getButton()), "up");
143 },
144 [](const JoystickButtonDownEvent& e) {
145 return makeTclList(tmpStrCat("joy", e.getJoystick() + 1), tmpStrCat("button", e.getButton()), "down");
146 },
147 [](const OsdControlReleaseEvent& e) {
148 return makeTclList("OSDcontrol", osdControlNames[e.getButton()], "RELEASE");
149 },
150 [](const OsdControlPressEvent& e) {
151 return makeTclList("OSDcontrol", osdControlNames[e.getButton()], "PRESS");
152 },
153 [](const FocusEvent& e) {
154 return makeTclList("focus", e.getGain());
155 },
156 [](const ResizeEvent& e) {
157 return makeTclList("resize", int(e.getX()), int(e.getY()));
158 },
159 [](const FileDropEvent& e) {
160 return makeTclList("filedrop", e.getFileName());
161 },
162 [](const QuitEvent& /*e*/) {
163 return makeTclList("quit");
164 },
165 [](const FinishFrameEvent& e) {
166 return makeTclList("finishframe", int(e.getSource()), int(e.getSelectedSource()), e.isSkipped());
167 },
168 [](const CliCommandEvent& e) {
169 return makeTclList("CliCmd", e.getCommand());
170 },
171 [](const GroupEvent& e) {
172 return e.getTclListComponents();
173 },
174 [&](const SimpleEvent& /*e*/) {
175 return makeTclList("simple", int(getType(event)));
176 }
177 }, event);
178}
179
180std::string toString(const Event& event)
181{
182 return std::string(toTclList(event).getString());
183}
184
185bool isRepeatStopper(const Event& self, const Event& other)
186{
187 assert(self && other);
188 return visit(overloaded{
189 // Normally all events should stop the repeat process in 'bind -repeat',
190 // but in case of OsdControlEvent there are two exceptions:
191 // - we should not stop because of the original host event that
192 // actually generated this 'artificial' OsdControlEvent.
193 // - if the original host event is a joystick motion event, we
194 // should not stop repeat for 'small' relative new joystick events.
195 [&](const OsdControlEvent& e) {
196 // If this OsdControlEvent was generated by the other event, then
197 // repeat should not be stopped.
198 if (!e.getOrigEvent()) return true;
199 if (e.getOrigEvent() == other) return false;
200
201 // If this OsdControlEvent event was generated by a joystick motion
202 // event and the new event is also a joystick motion event then don't
203 // stop repeat. We don't need to check the actual values of the events
204 // (it also isn't trivial), because when the values differ by enough,
205 // a new OsdControlEvent will be generated and that one will stop
206 // repeat.
207 return (getType(e.getOrigEvent()) != EventType::JOY_AXIS_MOTION) ||
209 },
210 [](const EventBase& /*e*/) {
211 return true;
212 }
213 }, self);
214}
215
216bool matches(const Event& self, const Event& other)
217{
218 assert(self && other);
219 return visit(overloaded{
220 [&](const GroupEvent& e) {
221 return contains(e.getTypesToMatch(), getType(other));
222 },
223 [&](const EventBase&) {
224 return self == other;
225 }
226 }, self);
227}
228
229} // namespace openmsx
Command received on CliComm connection.
Definition: Event.hh:406
This event is send when a device (v99x8, v9990, video9000, laserdisc) reaches the end of a frame.
Definition: Event.hh:384
Keys::KeyCode getKeyCode() const
Definition: Event.hh:93
OSD events are triggered by other events.
Definition: Event.hh:320
constexpr double e
Definition: Math.hh:20
std::string getName(KeyCode keyCode)
Translate key code to key name.
Definition: Keys.cc:730
This file implemented 3 utility functions:
Definition: Autofire.cc:9
bool operator==(const Event &x, const Event &y)
Definition: Event.cc:11
bool isRepeatStopper(const Event &self, const Event &other)
Should 'bind -repeat' be stopped by 'other' event.
Definition: Event.cc:185
bool matches(const Event &self, const Event &other)
Does this event 'match' the given event.
Definition: Event.cc:216
auto visit(Visitor &&visitor, const Event &event)
Definition: Event.hh:652
TclObject toTclList(const Event &event)
Similar to toString(), but retains the structure of the event.
Definition: Event.cc:85
EventType getType(const Event &event)
Definition: Event.hh:644
TclObject makeTclList(Args &&... args)
Definition: TclObject.hh:283
std::string toString(const Event &event)
Get a string representation of this event.
Definition: Event.cc:180
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
Definition: stl.hh:23
TemporaryString tmpStrCat(Ts &&... ts)
Definition: strCat.hh:610