20 : eventDistributor(eventDistributor_)
21 , globalSettings(globalSettings_)
23 commandController,
"grabinput",
24 "This setting controls if openMSX takes over mouse and keyboard input",
26 , escapeGrabCmd(commandController)
27 , escapeGrabState(ESCAPE_GRAB_WAIT_CMD)
28 , osdControlButtonsState(unsigned(~0))
33 #ifndef SDL_JOYSTICK_DISABLED
34 SDL_JoystickEventState(SDL_ENABLE);
46 if (!SDL_WasInit(SDL_INIT_VIDEO)) {
50 if (SDL_WaitEvent(
nullptr)) {
86 SDL_Event event1, event2;
91 while (SDL_PollEvent(curr)) {
94 if ((prev->type == SDL_KEYDOWN) && (curr->type == SDL_TEXTINPUT)) {
95 const char*
utf8 = curr->text.text;
97 handleKeyDown(prev->key, unicode);
106 if (curr->type == SDL_KEYDOWN) {
108 std::swap(curr, prev);
118 void InputEventGenerator::setNewOsdControlButtonState(
119 unsigned newState,
const Event& origEvent)
121 unsigned deltaState = osdControlButtonsState ^ newState;
124 if (deltaState & (1 << i)) {
125 if (newState & (1 << i)) {
127 Event::create<OsdControlReleaseEvent>(
131 Event::create<OsdControlPressEvent>(
136 osdControlButtonsState = newState;
139 void InputEventGenerator::triggerOsdControlEventsFromJoystickAxisMotion(
140 unsigned axis,
int value,
const Event& origEvent)
142 auto [neg_button, pos_button] = [&] {
153 return std::pair{0u, 0u};
159 setNewOsdControlButtonState(
160 (osdControlButtonsState | neg_button) & ~pos_button,
162 }
else if (value < 0) {
164 setNewOsdControlButtonState(
165 (osdControlButtonsState | pos_button) & ~neg_button,
169 setNewOsdControlButtonState(
170 osdControlButtonsState | neg_button | pos_button,
175 void InputEventGenerator::triggerOsdControlEventsFromJoystickHat(
176 int value,
const Event& origEvent)
185 setNewOsdControlButtonState(ab | dir, origEvent);
188 void InputEventGenerator::osdControlChangeButton(
189 bool up,
unsigned changedButtonMask,
const Event& origEvent)
191 auto newButtonState = up
192 ? osdControlButtonsState | changedButtonMask
193 : osdControlButtonsState & ~changedButtonMask;
194 setNewOsdControlButtonState(newButtonState, origEvent);
197 void InputEventGenerator::triggerOsdControlEventsFromJoystickButtonEvent(
198 unsigned button,
bool up,
const Event& origEvent)
200 osdControlChangeButton(
207 void InputEventGenerator::triggerOsdControlEventsFromKeyEvent(
210 unsigned buttonMask = [&] {
224 osdControlChangeButton(!up, buttonMask, origEvent);
226 osdControlChangeButton(up, buttonMask, origEvent);
230 static constexpr Uint16 normalizeModifier(SDL_Keycode sym, Uint16 mod)
237 return (sym ==
one_of(SDLK_LCTRL, SDLK_LSHIFT, SDLK_LALT, SDLK_LGUI,
238 SDLK_RCTRL, SDLK_RSHIFT, SDLK_RALT, SDLK_RGUI,
244 void InputEventGenerator::handleKeyDown(
const SDL_KeyboardEvent& key, uint32_t unicode)
258 auto mod = normalizeModifier(key.keysym.sym, key.keysym.mod);
260 key.keysym.sym, mod, key.keysym.scancode,
false);
261 event = Event::create<KeyDownEvent>(keyCode, scanCode, unicode);
262 triggerOsdControlEventsFromKeyEvent(keyCode,
false, key.repeat, event);
267 void InputEventGenerator::handleText(
const char*
utf8)
271 if (unicode == 0)
return;
277 void InputEventGenerator::handle(
const SDL_Event& evt)
300 auto mod = normalizeModifier(evt.key.keysym.sym, evt.key.keysym.mod);
302 evt.key.keysym.sym, mod, evt.key.keysym.scancode,
true);
303 event = Event::create<KeyUpEvent>(keyCode, scanCode);
305 triggerOsdControlEventsFromKeyEvent(keyCode,
true,
repeat, event);
309 handleKeyDown(evt.key, 0);
312 case SDL_MOUSEBUTTONUP:
313 event = Event::create<MouseButtonUpEvent>(evt.button.button);
315 case SDL_MOUSEBUTTONDOWN:
316 event = Event::create<MouseButtonDownEvent>(evt.button.button);
318 case SDL_MOUSEWHEEL: {
321 if (evt.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) {
325 event = Event::create<MouseWheelEvent>(
x, y);
328 case SDL_MOUSEMOTION:
329 event = Event::create<MouseMotionEvent>(
330 evt.motion.xrel, evt.motion.yrel,
331 evt.motion.x, evt.motion.y);
334 case SDL_JOYBUTTONUP:
335 event = Event::create<JoystickButtonUpEvent>(
336 evt.jbutton.which, evt.jbutton.button);
337 triggerOsdControlEventsFromJoystickButtonEvent(
338 evt.jbutton.button,
true, event);
340 case SDL_JOYBUTTONDOWN:
341 event = Event::create<JoystickButtonDownEvent>(
342 evt.jbutton.which, evt.jbutton.button);
343 triggerOsdControlEventsFromJoystickButtonEvent(
344 evt.jbutton.button,
false, event);
346 case SDL_JOYAXISMOTION: {
348 int threshold = (
setting.getInt() * 32768) / 100;
349 auto value = (evt.jaxis.value < -threshold) ? evt.jaxis.value
350 : (evt.jaxis.value > threshold) ? evt.jaxis.value
352 event = Event::create<JoystickAxisMotionEvent>(
353 evt.jaxis.which, evt.jaxis.axis, value);
354 triggerOsdControlEventsFromJoystickAxisMotion(
355 evt.jaxis.axis, value, event);
358 case SDL_JOYHATMOTION:
359 event = Event::create<JoystickHatEvent>(
360 evt.jhat.which, evt.jhat.hat, evt.jhat.value);
361 triggerOsdControlEventsFromJoystickHat(evt.jhat.value, event);
365 handleText(evt.text.text);
368 case SDL_WINDOWEVENT:
369 switch (evt.window.event) {
370 case SDL_WINDOWEVENT_FOCUS_GAINED:
371 event = Event::create<FocusEvent>(
true);
373 case SDL_WINDOWEVENT_FOCUS_LOST:
374 event = Event::create<FocusEvent>(
false);
376 case SDL_WINDOWEVENT_RESIZED:
377 event = Event::create<ResizeEvent>(
378 evt.window.data1, evt.window.data2);
380 case SDL_WINDOWEVENT_EXPOSED:
381 event = Event::create<ExposeEvent>();
389 event = Event::create<FileDropEvent>(
391 SDL_free(evt.drop.file);
395 event = Event::create<QuitEvent>();
404 std::cerr <<
"SDL event converted to: " <<
toString(event) <<
'\n';
406 std::cerr <<
"SDL event was of unknown type, not converted to an openMSX event\n";
416 escapeGrabState = ESCAPE_GRAB_WAIT_CMD;
420 int InputEventGenerator::signalEvent(
const Event& event) noexcept
424 switch (escapeGrabState) {
425 case ESCAPE_GRAB_WAIT_CMD:
428 case ESCAPE_GRAB_WAIT_LOST:
430 escapeGrabState = ESCAPE_GRAB_WAIT_GAIN;
433 case ESCAPE_GRAB_WAIT_GAIN:
435 escapeGrabState = ESCAPE_GRAB_WAIT_CMD;
448 void InputEventGenerator::setGrabInput(
bool grab)
450 SDL_SetRelativeMouseMode(grab ? SDL_TRUE : SDL_FALSE);
468 return SDL_JoystickNumButtons(joystick);
475 case 0:
return androidButtonA;
476 case 1:
return androidButtonB;
480 return SDL_JoystickGetButton(joystick, button) != 0;
487 InputEventGenerator::EscapeGrabCmd::EscapeGrabCmd(
489 :
Command(commandController_,
"escape_grab")
493 void InputEventGenerator::EscapeGrabCmd::execute(
494 std::span<const TclObject> , TclObject& )
496 auto& inputEventGenerator =
OUTER(InputEventGenerator, escapeGrabCmd);
497 if (inputEventGenerator.grabInput.getBoolean()) {
498 inputEventGenerator.escapeGrabState =
499 InputEventGenerator::ESCAPE_GRAB_WAIT_LOST;
500 inputEventGenerator.setGrabInput(
false);
504 std::string InputEventGenerator::EscapeGrabCmd::help(
505 std::span<const TclObject> )
const
507 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)
const std::string & getConventionalPath(const std::string &path)
Returns the path in conventional path-delimiter.
std::pair< KeyCode, KeyCode > getCodes(SDL_Keycode sdlkeycode, Uint16 mod, SDL_Scancode sdlscancode, bool release)
Translate SDL_Keycode/SDL_Scancode into openMSX key/scan Keycode's.
KeyCode
Constants that identify keys and key modifiers.
This file implemented 3 utility functions:
auto visit(Visitor &&visitor, const Event &event)
constexpr KeyMatrixPosition x
Keyboard bindings.
std::string toString(const Event &event)
Get a string representation of this 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.