aboutsummaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
authorBastien Bouclet2017-11-24 19:37:58 +0100
committerGitHub2017-11-24 19:37:58 +0100
commit5ed745f5329a54d33f1b1551569cf9856990bea1 (patch)
treee444facb6330945c3ee03c6252b386dc8e70acad /backends
parentc5caf9825e0d02036795afa87f49b7aa274cc983 (diff)
parentacf87add2751ae68298f4d5b5480635d06b0ec5e (diff)
downloadscummvm-rg350-5ed745f5329a54d33f1b1551569cf9856990bea1.tar.gz
scummvm-rg350-5ed745f5329a54d33f1b1551569cf9856990bea1.tar.bz2
scummvm-rg350-5ed745f5329a54d33f1b1551569cf9856990bea1.zip
Merge pull request #1063 from bgK/keyboard-repeat
SDL2: Improve handling of keyboard repeat events
Diffstat (limited to 'backends')
-rw-r--r--backends/events/default/default-events.cpp289
-rw-r--r--backends/events/default/default-events.h20
-rw-r--r--backends/events/sdl/sdl-events.cpp4
-rw-r--r--backends/platform/android/events.cpp2
-rw-r--r--backends/platform/sdl/sdl.cpp11
-rw-r--r--backends/platform/tizen/form.cpp1
-rw-r--r--backends/vkeybd/virtual-keyboard.cpp1
7 files changed, 183 insertions, 145 deletions
diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp
index 667914b023..8dd9599d20 100644
--- a/backends/events/default/default-events.cpp
+++ b/backends/events/default/default-events.cpp
@@ -40,7 +40,8 @@ DefaultEventManager::DefaultEventManager(Common::EventSource *boss) :
_modifierState(0),
_shouldQuit(false),
_shouldRTL(false),
- _confirmExitDialogActive(false) {
+ _confirmExitDialogActive(false),
+ _shouldGenerateKeyRepeatEvents(true) {
assert(boss);
@@ -50,10 +51,6 @@ DefaultEventManager::DefaultEventManager(Common::EventSource *boss) :
_dispatcher.registerObserver(this, kEventManPriority, false);
// Reset key repeat
- _currentKeyDown.keycode = 0;
- _currentKeyDown.ascii = 0;
- _currentKeyDown.flags = 0;
-
_keyRepeatTime = 0;
#ifdef ENABLE_VKEYBD
@@ -86,163 +83,181 @@ void DefaultEventManager::init() {
}
bool DefaultEventManager::pollEvent(Common::Event &event) {
- // Skip recording of these events
- uint32 time = g_system->getMillis(true);
- bool result = false;
-
_dispatcher.dispatch();
- if (!_eventQueue.empty()) {
- event = _eventQueue.pop();
- result = true;
+
+ if (_shouldGenerateKeyRepeatEvents) {
+ handleKeyRepeat();
}
- if (result) {
- event.synthetic = false;
- switch (event.type) {
- case Common::EVENT_KEYDOWN:
- _modifierState = event.kbd.flags;
- // init continuous event stream
- _currentKeyDown.ascii = event.kbd.ascii;
- _currentKeyDown.keycode = event.kbd.keycode;
- _currentKeyDown.flags = event.kbd.flags;
- _keyRepeatTime = time + kKeyRepeatInitialDelay;
+ if (_eventQueue.empty()) {
+ return false;
+ }
- if (event.kbd.keycode == Common::KEYCODE_BACKSPACE) {
- // WORKAROUND: Some engines incorrectly attempt to use the
- // ascii value instead of the keycode to detect the backspace
- // key (a non-portable behavior). This fails at least on
- // Mac OS X, possibly also on other systems.
- // As a workaround, we force the ascii value for backspace
- // key pressed. A better fix would be for engines to stop
- // making invalid assumptions about ascii values.
- event.kbd.ascii = Common::KEYCODE_BACKSPACE;
- _currentKeyDown.ascii = Common::KEYCODE_BACKSPACE;
+ event = _eventQueue.pop();
+ bool forwardEvent = true;
+
+ switch (event.type) {
+ case Common::EVENT_KEYDOWN:
+ _modifierState = event.kbd.flags;
+
+ if (event.kbd.keycode == Common::KEYCODE_BACKSPACE) {
+ // WORKAROUND: Some engines incorrectly attempt to use the
+ // ascii value instead of the keycode to detect the backspace
+ // key (a non-portable behavior). This fails at least on
+ // Mac OS X, possibly also on other systems.
+ // As a workaround, we force the ascii value for backspace
+ // key pressed. A better fix would be for engines to stop
+ // making invalid assumptions about ascii values.
+ event.kbd.ascii = Common::KEYCODE_BACKSPACE;
+ _currentKeyDown.ascii = Common::KEYCODE_BACKSPACE;
+ }
+ break;
+
+ case Common::EVENT_KEYUP:
+ _modifierState = event.kbd.flags;
+ break;
+
+ case Common::EVENT_MOUSEMOVE:
+ _mousePos = event.mouse;
+ break;
+
+ case Common::EVENT_LBUTTONDOWN:
+ _mousePos = event.mouse;
+ _buttonState |= LBUTTON;
+ break;
+
+ case Common::EVENT_LBUTTONUP:
+ _mousePos = event.mouse;
+ _buttonState &= ~LBUTTON;
+ break;
+
+ case Common::EVENT_RBUTTONDOWN:
+ _mousePos = event.mouse;
+ _buttonState |= RBUTTON;
+ break;
+
+ case Common::EVENT_RBUTTONUP:
+ _mousePos = event.mouse;
+ _buttonState &= ~RBUTTON;
+ break;
+
+ case Common::EVENT_MAINMENU:
+ if (g_engine && !g_engine->isPaused())
+ g_engine->openMainMenuDialog();
+
+ if (_shouldQuit)
+ event.type = Common::EVENT_QUIT;
+ else if (_shouldRTL)
+ event.type = Common::EVENT_RTL;
+ break;
+#ifdef ENABLE_VKEYBD
+ case Common::EVENT_VIRTUAL_KEYBOARD:
+ if (_vk->isDisplaying()) {
+ _vk->close(true);
+ } else {
+ if (g_engine)
+ g_engine->pauseEngine(true);
+ _vk->show();
+ if (g_engine)
+ g_engine->pauseEngine(false);
+ forwardEvent = false;
+ }
+ break;
+#endif
+#ifdef ENABLE_KEYMAPPER
+ case Common::EVENT_KEYMAPPER_REMAP:
+ if (!_remap) {
+ _remap = true;
+ Common::RemapDialog _remapDialog;
+ if (g_engine)
+ g_engine->pauseEngine(true);
+ _remapDialog.runModal();
+ if (g_engine)
+ g_engine->pauseEngine(false);
+ _remap = false;
+ }
+ break;
+#endif
+ case Common::EVENT_RTL:
+ if (ConfMan.getBool("confirm_exit")) {
+ if (g_engine)
+ g_engine->pauseEngine(true);
+ GUI::MessageDialog alert(_("Do you really want to return to the Launcher?"), _("Launcher"), _("Cancel"));
+ forwardEvent = _shouldRTL = (alert.runModal() == GUI::kMessageOK);
+ if (g_engine)
+ g_engine->pauseEngine(false);
+ } else
+ _shouldRTL = true;
+ break;
+
+ case Common::EVENT_MUTE:
+ if (g_engine)
+ g_engine->flipMute();
+ break;
+
+ case Common::EVENT_QUIT:
+ if (ConfMan.getBool("confirm_exit")) {
+ if (_confirmExitDialogActive) {
+ forwardEvent = false;
+ break;
}
- break;
+ _confirmExitDialogActive = true;
+ if (g_engine)
+ g_engine->pauseEngine(true);
+ GUI::MessageDialog alert(_("Do you really want to quit?"), _("Quit"), _("Cancel"));
+ forwardEvent = _shouldQuit = (alert.runModal() == GUI::kMessageOK);
+ if (g_engine)
+ g_engine->pauseEngine(false);
+ _confirmExitDialogActive = false;
+ } else
+ _shouldQuit = true;
- case Common::EVENT_KEYUP:
- _modifierState = event.kbd.flags;
- if (event.kbd.keycode == _currentKeyDown.keycode) {
- // Only stop firing events if it's the current key
- _currentKeyDown.keycode = 0;
- }
- break;
+ break;
- case Common::EVENT_MOUSEMOVE:
- _mousePos = event.mouse;
- break;
+ default:
+ break;
+ }
- case Common::EVENT_LBUTTONDOWN:
- _mousePos = event.mouse;
- _buttonState |= LBUTTON;
- break;
+ return forwardEvent;
+}
- case Common::EVENT_LBUTTONUP:
- _mousePos = event.mouse;
- _buttonState &= ~LBUTTON;
- break;
+void DefaultEventManager::handleKeyRepeat() {
+ uint32 time = g_system->getMillis(true);
- case Common::EVENT_RBUTTONDOWN:
- _mousePos = event.mouse;
- _buttonState |= RBUTTON;
- break;
+ if (!_eventQueue.empty()) {
+ // Peek in the event queue
+ const Common::Event &nextEvent = _eventQueue.front();
- case Common::EVENT_RBUTTONUP:
- _mousePos = event.mouse;
- _buttonState &= ~RBUTTON;
+ switch (nextEvent.type) {
+ case Common::EVENT_KEYDOWN:
+ // init continuous event stream
+ _currentKeyDown = nextEvent.kbd;
+ _keyRepeatTime = time + kKeyRepeatInitialDelay;
break;
- case Common::EVENT_MAINMENU:
- if (g_engine && !g_engine->isPaused())
- g_engine->openMainMenuDialog();
-
- if (_shouldQuit)
- event.type = Common::EVENT_QUIT;
- else if (_shouldRTL)
- event.type = Common::EVENT_RTL;
- break;
-#ifdef ENABLE_VKEYBD
- case Common::EVENT_VIRTUAL_KEYBOARD:
- if (_vk->isDisplaying()) {
- _vk->close(true);
- } else {
- if (g_engine)
- g_engine->pauseEngine(true);
- _vk->show();
- if (g_engine)
- g_engine->pauseEngine(false);
- result = false;
- }
- break;
-#endif
-#ifdef ENABLE_KEYMAPPER
- case Common::EVENT_KEYMAPPER_REMAP:
- if (!_remap) {
- _remap = true;
- Common::RemapDialog _remapDialog;
- if (g_engine)
- g_engine->pauseEngine(true);
- _remapDialog.runModal();
- if (g_engine)
- g_engine->pauseEngine(false);
- _remap = false;
+ case Common::EVENT_KEYUP:
+ if (nextEvent.kbd.keycode == _currentKeyDown.keycode) {
+ // Only stop firing events if it's the current key
+ _currentKeyDown.keycode = Common::KEYCODE_INVALID;
}
break;
-#endif
- case Common::EVENT_RTL:
- if (ConfMan.getBool("confirm_exit")) {
- if (g_engine)
- g_engine->pauseEngine(true);
- GUI::MessageDialog alert(_("Do you really want to return to the Launcher?"), _("Launcher"), _("Cancel"));
- result = _shouldRTL = (alert.runModal() == GUI::kMessageOK);
- if (g_engine)
- g_engine->pauseEngine(false);
- } else
- _shouldRTL = true;
- break;
-
- case Common::EVENT_MUTE:
- if (g_engine)
- g_engine->flipMute();
- break;
-
- case Common::EVENT_QUIT:
- if (ConfMan.getBool("confirm_exit")) {
- if (_confirmExitDialogActive) {
- result = false;
- break;
- }
- _confirmExitDialogActive = true;
- if (g_engine)
- g_engine->pauseEngine(true);
- GUI::MessageDialog alert(_("Do you really want to quit?"), _("Quit"), _("Cancel"));
- result = _shouldQuit = (alert.runModal() == GUI::kMessageOK);
- if (g_engine)
- g_engine->pauseEngine(false);
- _confirmExitDialogActive = false;
- } else
- _shouldQuit = true;
-
- break;
default:
break;
}
} else {
// Check if event should be sent again (keydown)
- if (_currentKeyDown.keycode != 0 && _keyRepeatTime < time) {
+ if (_currentKeyDown.keycode != Common::KEYCODE_INVALID && _keyRepeatTime <= time) {
// fire event
- event.type = Common::EVENT_KEYDOWN;
- event.synthetic = true;
- event.kbd.ascii = _currentKeyDown.ascii;
- event.kbd.keycode = (Common::KeyCode)_currentKeyDown.keycode;
- event.kbd.flags = _currentKeyDown.flags;
+ Common::Event repeatEvent;
+ repeatEvent.type = Common::EVENT_KEYDOWN;
+ repeatEvent.kbdRepeat = true;
+ repeatEvent.kbd = _currentKeyDown;
_keyRepeatTime = time + kKeyRepeatSustainDelay;
- result = true;
+
+ _eventQueue.push(repeatEvent);
}
}
-
- return result;
}
void DefaultEventManager::pushEvent(const Common::Event &event) {
diff --git a/backends/events/default/default-events.h b/backends/events/default/default-events.h
index 38406c25aa..df6ebd2f14 100644
--- a/backends/events/default/default-events.h
+++ b/backends/events/default/default-events.h
@@ -67,12 +67,11 @@ class DefaultEventManager : public Common::EventManager, Common::EventObserver {
kKeyRepeatSustainDelay = 100
};
- struct {
- uint16 ascii;
- byte flags;
- int keycode;
- } _currentKeyDown;
+ bool _shouldGenerateKeyRepeatEvents;
+ Common::KeyState _currentKeyDown;
uint32 _keyRepeatTime;
+
+ void handleKeyRepeat();
public:
DefaultEventManager(Common::EventSource *boss);
~DefaultEventManager();
@@ -97,6 +96,17 @@ public:
// this, please talk to tsoliman and/or LordHoto.
virtual Common::Keymapper *getKeymapper() { return _keymapper; }
#endif
+
+ /**
+ * Controls whether repeated key down events are generated while a key is pressed
+ *
+ * Backends that generate their own keyboard repeat events should disable this.
+ *
+ * @param generateKeyRepeatEvents
+ */
+ void setGenerateKeyRepeatEvents(bool generateKeyRepeatEvents) {
+ _shouldGenerateKeyRepeatEvents = generateKeyRepeatEvents;
+ }
};
#endif
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp
index 91ca0f5df6..d01d9c6c4a 100644
--- a/backends/events/sdl/sdl-events.cpp
+++ b/backends/events/sdl/sdl-events.cpp
@@ -696,6 +696,10 @@ bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) {
event.kbd.keycode = SDLToOSystemKeycode(sdlKeycode);
event.kbd.ascii = mapKey(sdlKeycode, (SDLMod)ev.key.keysym.mod, obtainUnicode(ev.key.keysym));
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ event.kbdRepeat = ev.key.repeat;
+#endif
+
return true;
}
diff --git a/backends/platform/android/events.cpp b/backends/platform/android/events.cpp
index b146945a01..d13d381f95 100644
--- a/backends/platform/android/events.cpp
+++ b/backends/platform/android/events.cpp
@@ -443,7 +443,7 @@ void OSystem_Android::pushEvent(int type, int arg1, int arg2, int arg3,
}
if (arg5 > 0)
- e.synthetic = true;
+ e.kbdRepeat = true;
// map special keys to 'our' ascii codes
switch (e.kbd.keycode) {
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index f2bf9590c5..68a987bc61 100644
--- a/backends/platform/sdl/sdl.cpp
+++ b/backends/platform/sdl/sdl.cpp
@@ -43,6 +43,7 @@
#include "backends/audiocd/sdl/sdl-audiocd.h"
#endif
+#include "backends/events/default/default-events.h"
#include "backends/events/sdl/sdl-events.h"
#include "backends/mutex/sdl/sdl-mutex.h"
#include "backends/timer/sdl/sdl-timer.h"
@@ -207,6 +208,16 @@ void OSystem_SDL::initBackend() {
if (_eventSource == 0)
_eventSource = new SdlEventSource();
+ if (_eventManager == nullptr) {
+ DefaultEventManager *eventManager = new DefaultEventManager(_eventSource);
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ // SDL 2 generates its own keyboard repeat events.
+ eventManager->setGenerateKeyRepeatEvents(false);
+#endif
+ _eventManager = eventManager;
+ }
+
+
#ifdef USE_OPENGL
#if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_DisplayMode displayMode;
diff --git a/backends/platform/tizen/form.cpp b/backends/platform/tizen/form.cpp
index 2a9a3967cc..22e15f61c4 100644
--- a/backends/platform/tizen/form.cpp
+++ b/backends/platform/tizen/form.cpp
@@ -243,7 +243,6 @@ void TizenAppForm::pushEvent(Common::EventType type, const Point &currentPositio
void TizenAppForm::pushKey(Common::KeyCode keycode) {
if (_eventQueueLock) {
Common::Event e;
- e.synthetic = false;
e.kbd.keycode = keycode;
e.kbd.ascii = keycode;
e.kbd.flags = 0;
diff --git a/backends/vkeybd/virtual-keyboard.cpp b/backends/vkeybd/virtual-keyboard.cpp
index ce19e9d462..80d7313a8c 100644
--- a/backends/vkeybd/virtual-keyboard.cpp
+++ b/backends/vkeybd/virtual-keyboard.cpp
@@ -242,7 +242,6 @@ void VirtualKeyboard::show() {
// push keydown & keyup events into the event manager
Event evt;
- evt.synthetic = false;
while (!_keyQueue.empty()) {
evt.kbd = _keyQueue.pop();
evt.type = EVENT_KEYDOWN;