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;
123 if (deltaState & (1 << i)) {
124 if (newState & (1 << i)) {
131 osdControlButtonsState = newState;
134void InputEventGenerator::triggerOsdControlEventsFromJoystickAxisMotion(
135 unsigned axis,
int value)
137 auto [neg_button, pos_button] = [&] {
148 return std::pair{0u, 0u};
154 setNewOsdControlButtonState(
155 (osdControlButtonsState | neg_button) & ~pos_button);
156 }
else if (value < 0) {
158 setNewOsdControlButtonState(
159 (osdControlButtonsState | pos_button) & ~neg_button);
162 setNewOsdControlButtonState(
163 osdControlButtonsState | neg_button | pos_button);
167void InputEventGenerator::triggerOsdControlEventsFromJoystickHat(
int value)
176 setNewOsdControlButtonState(ab | dir);
179void InputEventGenerator::osdControlChangeButton(
bool down,
unsigned changedButtonMask)
181 auto newButtonState = down
182 ? osdControlButtonsState & ~changedButtonMask
183 : osdControlButtonsState | changedButtonMask;
184 setNewOsdControlButtonState(newButtonState);
187void InputEventGenerator::triggerOsdControlEventsFromJoystickButtonEvent(
unsigned button,
bool down)
189 osdControlChangeButton(
192 : (1 << OsdControlEvent::A_BUTTON)));
195void InputEventGenerator::triggerOsdControlEventsFromKeyEvent(SDLKey key,
bool repeat)
197 unsigned buttonMask = [&] {
198 switch (key.sym.sym) {
211 osdControlChangeButton(!key.down, buttonMask);
213 osdControlChangeButton(key.down, buttonMask);
217static constexpr Uint16 normalizeModifier(SDL_Keycode sym, Uint16 mod)
224 return (sym ==
one_of(SDLK_LCTRL, SDLK_LSHIFT, SDLK_LALT, SDLK_LGUI,
225 SDLK_RCTRL, SDLK_RSHIFT, SDLK_RALT, SDLK_RGUI,
231void InputEventGenerator::handleKeyDown(
const SDL_KeyboardEvent& key, uint32_t unicode)
245 evt.key = SDL_KeyboardEvent{};
246 memcpy(&evt.key, &key,
sizeof(key));
247 evt.key.keysym.mod = normalizeModifier(key.keysym.sym, key.keysym.mod);
248 evt.key.keysym.unused = unicode;
249 Event event = KeyDownEvent(evt);
250 triggerOsdControlEventsFromKeyEvent(SDLKey{key.keysym,
true}, key.repeat);
255void InputEventGenerator::splitText(uint32_t timestamp,
const char*
utf8)
259 if (unicode == 0)
return;
265void InputEventGenerator::handle(
const SDL_Event& evt)
267 std::optional<Event> event;
287 e.key = SDL_KeyboardEvent{};
288 memcpy(&
e.key, &evt.key,
sizeof(evt.key));
289 e.key.keysym.mod = normalizeModifier(evt.key.keysym.sym, evt.key.keysym.mod);
290 event = KeyUpEvent(e);
293 triggerOsdControlEventsFromKeyEvent(SDLKey{
e.key.keysym, down},
repeat);
297 handleKeyDown(evt.key, 0);
300 case SDL_MOUSEBUTTONUP:
301 event = MouseButtonUpEvent(evt);
303 case SDL_MOUSEBUTTONDOWN:
304 event = MouseButtonDownEvent(evt);
307 event = MouseWheelEvent(evt);
309 case SDL_MOUSEMOTION:
310 event = MouseMotionEvent(evt);
313 case SDL_JOYBUTTONUP:
315 event = JoystickButtonUpEvent(evt);
316 triggerOsdControlEventsFromJoystickButtonEvent(
317 evt.jbutton.button,
false);
320 case SDL_JOYBUTTONDOWN:
322 event = JoystickButtonDownEvent(evt);
323 triggerOsdControlEventsFromJoystickButtonEvent(
324 evt.jbutton.button,
true);
327 case SDL_JOYAXISMOTION: {
331 int deadZone =
setting->getInt();
332 int threshold = (deadZone * 32768) / 100;
333 auto value = (evt.jaxis.value < -threshold) ? evt.jaxis.value
334 : (evt.jaxis.value > threshold) ? evt.jaxis.value
336 event = JoystickAxisMotionEvent(evt);
337 triggerOsdControlEventsFromJoystickAxisMotion(
338 evt.jaxis.axis, value);
342 case SDL_JOYHATMOTION:
344 event = JoystickHatEvent(evt);
345 triggerOsdControlEventsFromJoystickHat(evt.jhat.value);
349 case SDL_JOYDEVICEADDED:
350 joystickManager.
add(evt.jdevice.which);
353 case SDL_JOYDEVICEREMOVED:
354 joystickManager.
remove(evt.jdevice.which);
358 splitText(evt.text.timestamp, evt.text.text);
359 event = TextEvent(evt);
362 case SDL_WINDOWEVENT:
363 switch (evt.window.event) {
364 case SDL_WINDOWEVENT_CLOSE:
371 event = WindowEvent(evt);
377 event = FileDropEvent(
379 SDL_free(evt.drop.file);
392 std::cerr <<
"SDL event converted to: " <<
toString(event) <<
'\n';
394 std::cerr <<
"SDL event was of unknown type, not converted to an openMSX event\n";
404 escapeGrabState = ESCAPE_GRAB_WAIT_CMD;
408int InputEventGenerator::signalEvent(
const Event& event)
412 const auto& evt = e.getSdlWindowEvent();
413 if (e.isMainWindow() &&
414 evt.event ==
one_of(SDL_WINDOWEVENT_FOCUS_GAINED, SDL_WINDOWEVENT_FOCUS_LOST)) {
415 switch (escapeGrabState) {
416 case ESCAPE_GRAB_WAIT_CMD:
419 case ESCAPE_GRAB_WAIT_LOST:
420 if (evt.event == SDL_WINDOWEVENT_FOCUS_LOST) {
421 escapeGrabState = ESCAPE_GRAB_WAIT_GAIN;
424 case ESCAPE_GRAB_WAIT_GAIN:
425 if (evt.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
426 escapeGrabState = ESCAPE_GRAB_WAIT_CMD;
440void InputEventGenerator::setGrabInput(
bool grab)
const
442 SDL_SetRelativeMouseMode(grab ? SDL_TRUE : SDL_FALSE);
453InputEventGenerator::EscapeGrabCmd::EscapeGrabCmd(
454 CommandController& commandController_)
455 : Command(commandController_,
"escape_grab")
459void InputEventGenerator::EscapeGrabCmd::execute(
460 std::span<const TclObject> , TclObject& )
462 auto& inputEventGenerator =
OUTER(InputEventGenerator, escapeGrabCmd);
463 if (inputEventGenerator.grabInput.getBoolean()) {
464 inputEventGenerator.escapeGrabState =
465 InputEventGenerator::ESCAPE_GRAB_WAIT_LOST;
466 inputEventGenerator.setGrabInput(
false);
470std::string InputEventGenerator::EscapeGrabCmd::help(
471 std::span<const TclObject> )
const
473 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=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
uint32_t next(octet_iterator &it)
#define OUTER(type, member)
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.