24 : eventDistributor(eventDistributor_)
25 , globalSettings(globalSettings_)
26 , joystickManager(commandController)
28 commandController,
"grabinput",
29 "This setting controls if openMSX takes over mouse and keyboard input",
31 , escapeGrabCmd(commandController)
45 if (!SDL_WasInit(SDL_INIT_VIDEO)) {
49 if (SDL_WaitEvent(
nullptr)) {
85 SDL_Event event1, event2;
90 while (SDL_PollEvent(curr)) {
93 if ((prev->type == SDL_KEYDOWN) && (curr->type == SDL_TEXTINPUT)) {
94 const char*
utf8 = curr->text.text;
96 handleKeyDown(prev->key, unicode);
98 splitText(curr->text.timestamp,
utf8);
106 if (curr->type == SDL_KEYDOWN) {
108 std::swap(curr, prev);
118void InputEventGenerator::setNewOsdControlButtonState(
unsigned newState)
120 unsigned deltaState = osdControlButtonsState ^ newState;
122 for (
auto b : {LEFT, RIGHT, UP, DOWN,
A,
B}) {
131 osdControlButtonsState = newState;
134void InputEventGenerator::triggerOsdControlEventsFromJoystickAxisMotion(
135 unsigned axis,
int value)
137 auto [neg_button, pos_button] = [&] {
149 return std::pair{0u, 0u};
155 setNewOsdControlButtonState(
156 (osdControlButtonsState | neg_button) & ~pos_button);
157 }
else if (value < 0) {
159 setNewOsdControlButtonState(
160 (osdControlButtonsState | pos_button) & ~neg_button);
163 setNewOsdControlButtonState(
164 osdControlButtonsState | neg_button | pos_button);
168void InputEventGenerator::triggerOsdControlEventsFromJoystickHat(
int value)
173 if (!(value & SDL_HAT_DOWN )) dir |= 1 <<
to_underlying(DOWN);
174 if (!(value & SDL_HAT_LEFT )) dir |= 1 <<
to_underlying(LEFT);
175 if (!(value & SDL_HAT_RIGHT)) dir |= 1 <<
to_underlying(RIGHT);
178 setNewOsdControlButtonState(ab | dir);
181void InputEventGenerator::osdControlChangeButton(
bool down,
unsigned changedButtonMask)
183 auto newButtonState = down
184 ? osdControlButtonsState & ~changedButtonMask
185 : osdControlButtonsState | changedButtonMask;
186 setNewOsdControlButtonState(newButtonState);
189void InputEventGenerator::triggerOsdControlEventsFromJoystickButtonEvent(
unsigned button,
bool down)
192 osdControlChangeButton(
198void InputEventGenerator::triggerOsdControlEventsFromKeyEvent(SDLKey key,
bool repeat)
200 unsigned buttonMask = [&] {
201 switch (key.sym.sym) {
215 osdControlChangeButton(!key.down, buttonMask);
217 osdControlChangeButton(key.down, buttonMask);
221static constexpr Uint16 normalizeModifier(SDL_Keycode sym, Uint16 mod)
228 return (sym ==
one_of(SDLK_LCTRL, SDLK_LSHIFT, SDLK_LALT, SDLK_LGUI,
229 SDLK_RCTRL, SDLK_RSHIFT, SDLK_RALT, SDLK_RGUI,
235void InputEventGenerator::handleKeyDown(
const SDL_KeyboardEvent& key, uint32_t unicode)
249 evt.key = SDL_KeyboardEvent{};
250 memcpy(&evt.key, &key,
sizeof(key));
251 evt.key.keysym.mod = normalizeModifier(key.keysym.sym, key.keysym.mod);
252 evt.key.keysym.unused = unicode;
253 Event event = KeyDownEvent(evt);
254 triggerOsdControlEventsFromKeyEvent(SDLKey{key.keysym,
true}, key.repeat);
259void InputEventGenerator::splitText(uint32_t timestamp,
const char*
utf8)
263 if (unicode == 0)
return;
269void InputEventGenerator::handle(
const SDL_Event& evt)
271 std::optional<Event> event;
291 e.key = SDL_KeyboardEvent{};
292 memcpy(&
e.key, &evt.key,
sizeof(evt.key));
293 e.key.keysym.mod = normalizeModifier(evt.key.keysym.sym, evt.key.keysym.mod);
294 event = KeyUpEvent(e);
297 triggerOsdControlEventsFromKeyEvent(SDLKey{
e.key.keysym, down},
repeat);
301 handleKeyDown(evt.key, 0);
304 case SDL_MOUSEBUTTONUP:
305 event = MouseButtonUpEvent(evt);
307 case SDL_MOUSEBUTTONDOWN:
308 event = MouseButtonDownEvent(evt);
311 event = MouseWheelEvent(evt);
313 case SDL_MOUSEMOTION:
314 event = MouseMotionEvent(evt);
317 case SDL_JOYBUTTONUP:
319 event = JoystickButtonUpEvent(evt);
320 triggerOsdControlEventsFromJoystickButtonEvent(
321 evt.jbutton.button,
false);
324 case SDL_JOYBUTTONDOWN:
326 event = JoystickButtonDownEvent(evt);
327 triggerOsdControlEventsFromJoystickButtonEvent(
328 evt.jbutton.button,
true);
331 case SDL_JOYAXISMOTION: {
335 int deadZone =
setting->getInt();
336 int threshold = (deadZone * 32768) / 100;
337 auto value = (evt.jaxis.value < -threshold) ? evt.jaxis.value
338 : (evt.jaxis.value > threshold) ? evt.jaxis.value
340 event = JoystickAxisMotionEvent(evt);
341 triggerOsdControlEventsFromJoystickAxisMotion(
342 evt.jaxis.axis, value);
346 case SDL_JOYHATMOTION:
348 event = JoystickHatEvent(evt);
349 triggerOsdControlEventsFromJoystickHat(evt.jhat.value);
353 case SDL_JOYDEVICEADDED:
354 joystickManager.
add(evt.jdevice.which);
357 case SDL_JOYDEVICEREMOVED:
358 joystickManager.
remove(evt.jdevice.which);
362 splitText(evt.text.timestamp, evt.text.text);
363 event = TextEvent(evt);
366 case SDL_WINDOWEVENT:
367 switch (evt.window.event) {
368 case SDL_WINDOWEVENT_CLOSE:
375 event = WindowEvent(evt);
381 event = FileDropEvent(
383 SDL_free(evt.drop.file);
396 std::cerr <<
"SDL event converted to: " <<
toString(event) <<
'\n';
398 std::cerr <<
"SDL event was of unknown type, not converted to an openMSX event\n";
408 escapeGrabState = ESCAPE_GRAB_WAIT_CMD;
412bool InputEventGenerator::signalEvent(
const Event& event)
416 const auto& evt = e.getSdlWindowEvent();
417 if (e.isMainWindow() &&
418 evt.event ==
one_of(SDL_WINDOWEVENT_FOCUS_GAINED, SDL_WINDOWEVENT_FOCUS_LOST)) {
419 switch (escapeGrabState) {
420 case ESCAPE_GRAB_WAIT_CMD:
423 case ESCAPE_GRAB_WAIT_LOST:
424 if (evt.event == SDL_WINDOWEVENT_FOCUS_LOST) {
425 escapeGrabState = ESCAPE_GRAB_WAIT_GAIN;
428 case ESCAPE_GRAB_WAIT_GAIN:
429 if (evt.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
430 escapeGrabState = ESCAPE_GRAB_WAIT_CMD;
444void InputEventGenerator::setGrabInput(
bool grab)
const
446 SDL_SetRelativeMouseMode(grab ? SDL_TRUE : SDL_FALSE);
457InputEventGenerator::EscapeGrabCmd::EscapeGrabCmd(
458 CommandController& commandController_)
459 : Command(commandController_,
"escape_grab")
463void InputEventGenerator::EscapeGrabCmd::execute(
464 std::span<const TclObject> , TclObject& )
466 auto& inputEventGenerator =
OUTER(InputEventGenerator, escapeGrabCmd);
467 if (inputEventGenerator.grabInput.getBoolean()) {
468 inputEventGenerator.escapeGrabState =
469 InputEventGenerator::ESCAPE_GRAB_WAIT_LOST;
470 inputEventGenerator.setGrabInput(
false);
474std::string InputEventGenerator::EscapeGrabCmd::help(
475 std::span<const TclObject> )
const
477 return "Temporarily release input grab.";
bool getBoolean() const noexcept
void unregisterEventListener(EventType type, EventListener &listener)
Unregisters a previously registered event listener.
void distributeEvent(Event &&event)
Schedule the given event for delivery.
void registerEventListener(EventType type, EventListener &listener, Priority priority=Priority::OTHER)
Registers a given object to receive certain events.
This class contains settings that are used by several other class (including some singletons).
void add(int deviceIndex)
IntegerSetting * getJoyDeadZoneSetting(JoystickId joyId) const
void remove(int instanceId)
std::optional< JoystickId > translateSdlInstanceId(SDL_Event &evt) const
static KeyDownEvent create(SDL_Keycode code, SDL_Keymod mod=KMOD_NONE)
bool isMainWindow() const
const std::string & getConventionalPath(const std::string &path)
Returns the path in conventional path-delimiter.
This file implemented 3 utility functions:
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
std::array< const EDStorage, 4 > A
uint32_t next(octet_iterator &it)
#define OUTER(type, member)
constexpr auto to_underlying(E e) noexcept
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.