20 : eventDistributor(eventDistributor_)
21 , globalSettings(globalSettings_)
23 commandController,
"grabinput",
24 "This setting controls if openMSX takes over mouse and keyboard input",
26 , escapeGrabCmd(commandController)
31#ifndef SDL_JOYSTICK_DISABLED
32 SDL_JoystickEventState(SDL_ENABLE);
44 if (!SDL_WasInit(SDL_INIT_VIDEO)) {
48 if (SDL_WaitEvent(
nullptr)) {
84 SDL_Event event1, event2;
89 while (SDL_PollEvent(curr)) {
92 if ((prev->type == SDL_KEYDOWN) && (curr->type == SDL_TEXTINPUT)) {
93 const char*
utf8 = curr->text.text;
95 handleKeyDown(prev->key, unicode);
97 splitText(curr->text.timestamp,
utf8);
105 if (curr->type == SDL_KEYDOWN) {
117void InputEventGenerator::setNewOsdControlButtonState(
unsigned newState)
119 unsigned deltaState = osdControlButtonsState ^ newState;
122 if (deltaState & (1 << i)) {
123 if (newState & (1 << i)) {
130 osdControlButtonsState = newState;
133void InputEventGenerator::triggerOsdControlEventsFromJoystickAxisMotion(
134 unsigned axis,
int value)
136 auto [neg_button, pos_button] = [&] {
147 return std::pair{0u, 0u};
153 setNewOsdControlButtonState(
154 (osdControlButtonsState | neg_button) & ~pos_button);
155 }
else if (value < 0) {
157 setNewOsdControlButtonState(
158 (osdControlButtonsState | pos_button) & ~neg_button);
161 setNewOsdControlButtonState(
162 osdControlButtonsState | neg_button | pos_button);
166void InputEventGenerator::triggerOsdControlEventsFromJoystickHat(
int value)
175 setNewOsdControlButtonState(ab | dir);
178void InputEventGenerator::osdControlChangeButton(
bool down,
unsigned changedButtonMask)
180 auto newButtonState = down
181 ? osdControlButtonsState & ~changedButtonMask
182 : osdControlButtonsState | changedButtonMask;
183 setNewOsdControlButtonState(newButtonState);
186void InputEventGenerator::triggerOsdControlEventsFromJoystickButtonEvent(
unsigned button,
bool down)
188 osdControlChangeButton(
194void InputEventGenerator::triggerOsdControlEventsFromKeyEvent(SDLKey key,
bool repeat)
196 unsigned buttonMask = [&] {
197 switch (key.sym.sym) {
210 osdControlChangeButton(!key.down, buttonMask);
212 osdControlChangeButton(key.down, buttonMask);
216static constexpr Uint16 normalizeModifier(SDL_Keycode sym, Uint16 mod)
223 return (sym ==
one_of(SDLK_LCTRL, SDLK_LSHIFT, SDLK_LALT, SDLK_LGUI,
224 SDLK_RCTRL, SDLK_RSHIFT, SDLK_RALT, SDLK_RGUI,
230void InputEventGenerator::handleKeyDown(
const SDL_KeyboardEvent& key, uint32_t unicode)
244 memcpy(&evt, &key,
sizeof(key));
245 evt.key.keysym.mod = normalizeModifier(key.keysym.sym, key.keysym.mod);
246 evt.key.keysym.unused = unicode;
247 Event event = KeyDownEvent(evt);
248 triggerOsdControlEventsFromKeyEvent(SDLKey{key.keysym,
true}, key.repeat);
253void InputEventGenerator::splitText(uint32_t timestamp,
const char*
utf8)
257 if (unicode == 0)
return;
263void InputEventGenerator::handle(
const SDL_Event& evt)
265 std::optional<Event> event;
285 memcpy(&
e, &evt,
sizeof(evt));
286 e.key.keysym.mod = normalizeModifier(evt.key.keysym.sym, evt.key.keysym.mod);
287 event = KeyUpEvent(
e);
290 triggerOsdControlEventsFromKeyEvent(SDLKey{
e.key.keysym, down},
repeat);
294 handleKeyDown(evt.key, 0);
297 case SDL_MOUSEBUTTONUP:
298 event = MouseButtonUpEvent(evt);
300 case SDL_MOUSEBUTTONDOWN:
301 event = MouseButtonDownEvent(evt);
304 event = MouseWheelEvent(evt);
306 case SDL_MOUSEMOTION:
307 event = MouseMotionEvent(evt);
310 case SDL_JOYBUTTONUP:
311 event = JoystickButtonUpEvent(evt);
312 triggerOsdControlEventsFromJoystickButtonEvent(
313 evt.jbutton.button,
false);
315 case SDL_JOYBUTTONDOWN:
316 event = JoystickButtonDownEvent(evt);
317 triggerOsdControlEventsFromJoystickButtonEvent(
318 evt.jbutton.button,
true);
320 case SDL_JOYAXISMOTION: {
322 int threshold = (
setting.getInt() * 32768) / 100;
323 auto value = (evt.jaxis.value < -threshold) ? evt.jaxis.value
324 : (evt.jaxis.value > threshold) ? evt.jaxis.value
326 event = JoystickAxisMotionEvent(evt);
327 triggerOsdControlEventsFromJoystickAxisMotion(
328 evt.jaxis.axis, value);
331 case SDL_JOYHATMOTION:
332 event = JoystickHatEvent(evt);
333 triggerOsdControlEventsFromJoystickHat(evt.jhat.value);
337 splitText(evt.text.timestamp, evt.text.text);
338 event = TextEvent(evt);
341 case SDL_WINDOWEVENT:
342 switch (evt.window.event) {
343 case SDL_WINDOWEVENT_CLOSE:
350 event = WindowEvent(evt);
356 event = FileDropEvent(
358 SDL_free(evt.drop.file);
371 std::cerr <<
"SDL event converted to: " <<
toString(event) <<
'\n';
373 std::cerr <<
"SDL event was of unknown type, not converted to an openMSX event\n";
383 escapeGrabState = ESCAPE_GRAB_WAIT_CMD;
387int InputEventGenerator::signalEvent(
const Event& event)
391 const auto& evt =
e.getSdlWindowEvent();
392 if (
e.isMainWindow() &&
393 evt.event ==
one_of(SDL_WINDOWEVENT_FOCUS_GAINED, SDL_WINDOWEVENT_FOCUS_LOST)) {
394 switch (escapeGrabState) {
395 case ESCAPE_GRAB_WAIT_CMD:
398 case ESCAPE_GRAB_WAIT_LOST:
399 if (evt.event == SDL_WINDOWEVENT_FOCUS_LOST) {
400 escapeGrabState = ESCAPE_GRAB_WAIT_GAIN;
403 case ESCAPE_GRAB_WAIT_GAIN:
404 if (evt.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
405 escapeGrabState = ESCAPE_GRAB_WAIT_CMD;
419void InputEventGenerator::setGrabInput(
bool grab)
421 SDL_SetRelativeMouseMode(grab ? SDL_TRUE : SDL_FALSE);
439 return SDL_JoystickNumButtons(joystick);
446 case 0:
return androidButtonA;
447 case 1:
return androidButtonB;
451 return SDL_JoystickGetButton(joystick, button) != 0;
458InputEventGenerator::EscapeGrabCmd::EscapeGrabCmd(
460 :
Command(commandController_,
"escape_grab")
464void InputEventGenerator::EscapeGrabCmd::execute(
465 std::span<const TclObject> , TclObject& )
467 auto& inputEventGenerator =
OUTER(InputEventGenerator, escapeGrabCmd);
468 if (inputEventGenerator.grabInput.getBoolean()) {
469 inputEventGenerator.escapeGrabState =
470 InputEventGenerator::ESCAPE_GRAB_WAIT_LOST;
471 inputEventGenerator.setGrabInput(
false);
475std::string InputEventGenerator::EscapeGrabCmd::help(
476 std::span<const TclObject> )
const
478 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).
IntegerSetting & getJoyDeadZoneSetting(int i)
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::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, ImGuiDelayedActionEvent, ImGuiActiveEvent > Event
std::string toString(const BooleanInput &input)
void swap(openmsx::MemBuffer< T > &l, openmsx::MemBuffer< T > &r) noexcept
uint32_t next(octet_iterator &it)
#define OUTER(type, member)
constexpr void repeat(T n, Op op)
Repeat the given operation 'op' 'n' times.