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);
104 if (curr->type == SDL_KEYDOWN) {
116void InputEventGenerator::setNewOsdControlButtonState(
117 unsigned newState,
const Event& origEvent)
119 unsigned deltaState = osdControlButtonsState ^ newState;
122 if (deltaState & (1 << i)) {
123 if (newState & (1 << i)) {
125 Event::create<OsdControlReleaseEvent>(
129 Event::create<OsdControlPressEvent>(
134 osdControlButtonsState = newState;
137void InputEventGenerator::triggerOsdControlEventsFromJoystickAxisMotion(
138 unsigned axis,
int value,
const Event& origEvent)
140 auto [neg_button, pos_button] = [&] {
151 return std::pair{0u, 0u};
157 setNewOsdControlButtonState(
158 (osdControlButtonsState | neg_button) & ~pos_button,
160 }
else if (value < 0) {
162 setNewOsdControlButtonState(
163 (osdControlButtonsState | pos_button) & ~neg_button,
167 setNewOsdControlButtonState(
168 osdControlButtonsState | neg_button | pos_button,
173void InputEventGenerator::triggerOsdControlEventsFromJoystickHat(
174 int value,
const Event& origEvent)
183 setNewOsdControlButtonState(ab | dir, origEvent);
186void InputEventGenerator::osdControlChangeButton(
187 bool up,
unsigned changedButtonMask,
const Event& origEvent)
189 auto newButtonState = up
190 ? osdControlButtonsState | changedButtonMask
191 : osdControlButtonsState & ~changedButtonMask;
192 setNewOsdControlButtonState(newButtonState, origEvent);
195void InputEventGenerator::triggerOsdControlEventsFromJoystickButtonEvent(
196 unsigned button,
bool up,
const Event& origEvent)
198 osdControlChangeButton(
205void InputEventGenerator::triggerOsdControlEventsFromKeyEvent(
208 unsigned buttonMask = [&] {
222 osdControlChangeButton(!up, buttonMask, origEvent);
224 osdControlChangeButton(up, buttonMask, origEvent);
228static constexpr Uint16 normalizeModifier(SDL_Keycode sym, Uint16 mod)
235 return (sym ==
one_of(SDLK_LCTRL, SDLK_LSHIFT, SDLK_LALT, SDLK_LGUI,
236 SDLK_RCTRL, SDLK_RSHIFT, SDLK_RALT, SDLK_RGUI,
242void InputEventGenerator::handleKeyDown(
const SDL_KeyboardEvent& key, uint32_t unicode)
256 auto mod = normalizeModifier(key.keysym.sym, key.keysym.mod);
258 key.keysym.sym, mod, key.keysym.scancode,
false);
259 event = Event::create<KeyDownEvent>(keyCode, scanCode, unicode);
260 triggerOsdControlEventsFromKeyEvent(keyCode,
false, key.repeat, event);
265void InputEventGenerator::handleText(
const char*
utf8)
269 if (unicode == 0)
return;
275void InputEventGenerator::handle(
const SDL_Event& evt)
298 auto mod = normalizeModifier(evt.key.keysym.sym, evt.key.keysym.mod);
300 evt.key.keysym.sym, mod, evt.key.keysym.scancode,
true);
301 event = Event::create<KeyUpEvent>(keyCode, scanCode);
303 triggerOsdControlEventsFromKeyEvent(keyCode,
true,
repeat, event);
307 handleKeyDown(evt.key, 0);
310 case SDL_MOUSEBUTTONUP:
311 event = Event::create<MouseButtonUpEvent>(evt.button.button);
313 case SDL_MOUSEBUTTONDOWN:
314 event = Event::create<MouseButtonDownEvent>(evt.button.button);
316 case SDL_MOUSEWHEEL: {
319 if (evt.wheel.direction == SDL_MOUSEWHEEL_FLIPPED) {
323 event = Event::create<MouseWheelEvent>(x, y);
326 case SDL_MOUSEMOTION:
327 event = Event::create<MouseMotionEvent>(
328 evt.motion.xrel, evt.motion.yrel,
329 evt.motion.x, evt.motion.y);
332 case SDL_JOYBUTTONUP:
333 event = Event::create<JoystickButtonUpEvent>(
334 evt.jbutton.which, evt.jbutton.button);
335 triggerOsdControlEventsFromJoystickButtonEvent(
336 evt.jbutton.button,
true, event);
338 case SDL_JOYBUTTONDOWN:
339 event = Event::create<JoystickButtonDownEvent>(
340 evt.jbutton.which, evt.jbutton.button);
341 triggerOsdControlEventsFromJoystickButtonEvent(
342 evt.jbutton.button,
false, event);
344 case SDL_JOYAXISMOTION: {
346 int threshold = (
setting.getInt() * 32768) / 100;
347 auto value = (evt.jaxis.value < -threshold) ? evt.jaxis.value
348 : (evt.jaxis.value > threshold) ? evt.jaxis.value
350 event = Event::create<JoystickAxisMotionEvent>(
351 evt.jaxis.which, evt.jaxis.axis, value);
352 triggerOsdControlEventsFromJoystickAxisMotion(
353 evt.jaxis.axis, value, event);
356 case SDL_JOYHATMOTION:
357 event = Event::create<JoystickHatEvent>(
358 evt.jhat.which, evt.jhat.hat, evt.jhat.value);
359 triggerOsdControlEventsFromJoystickHat(evt.jhat.value, event);
363 handleText(evt.text.text);
366 case SDL_WINDOWEVENT:
367 switch (evt.window.event) {
368 case SDL_WINDOWEVENT_FOCUS_GAINED:
369 event = Event::create<FocusEvent>(
true);
371 case SDL_WINDOWEVENT_FOCUS_LOST:
372 event = Event::create<FocusEvent>(
false);
374 case SDL_WINDOWEVENT_RESIZED:
375 event = Event::create<ResizeEvent>(
376 evt.window.data1, evt.window.data2);
378 case SDL_WINDOWEVENT_EXPOSED:
379 event = Event::create<ExposeEvent>();
387 event = Event::create<FileDropEvent>(
389 SDL_free(evt.drop.file);
393 event = Event::create<QuitEvent>();
402 std::cerr <<
"SDL event converted to: " <<
toString(event) <<
'\n';
404 std::cerr <<
"SDL event was of unknown type, not converted to an openMSX event\n";
414 escapeGrabState = ESCAPE_GRAB_WAIT_CMD;
418int InputEventGenerator::signalEvent(
const Event& event)
422 switch (escapeGrabState) {
423 case ESCAPE_GRAB_WAIT_CMD:
426 case ESCAPE_GRAB_WAIT_LOST:
428 escapeGrabState = ESCAPE_GRAB_WAIT_GAIN;
431 case ESCAPE_GRAB_WAIT_GAIN:
433 escapeGrabState = ESCAPE_GRAB_WAIT_CMD;
446void InputEventGenerator::setGrabInput(
bool grab)
448 SDL_SetRelativeMouseMode(grab ? SDL_TRUE : SDL_FALSE);
466 return SDL_JoystickNumButtons(joystick);
473 case 0:
return androidButtonA;
474 case 1:
return androidButtonB;
478 return SDL_JoystickGetButton(joystick, button) != 0;
485InputEventGenerator::EscapeGrabCmd::EscapeGrabCmd(
487 :
Command(commandController_,
"escape_grab")
491void InputEventGenerator::EscapeGrabCmd::execute(
492 std::span<const TclObject> , TclObject& )
494 auto& inputEventGenerator =
OUTER(InputEventGenerator, escapeGrabCmd);
495 if (inputEventGenerator.grabInput.getBoolean()) {
496 inputEventGenerator.escapeGrabState =
497 InputEventGenerator::ESCAPE_GRAB_WAIT_LOST;
498 inputEventGenerator.setGrabInput(
false);
502std::string InputEventGenerator::EscapeGrabCmd::help(
503 std::span<const TclObject> )
const
505 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.
KeyCode
Constants that identify keys and key modifiers.
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.
This file implemented 3 utility functions:
auto visit(Visitor &&visitor, const Event &event)
std::string toString(const Event &event)
Get a string representation of this event.
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.