diff options
Diffstat (limited to 'backends/events/sdl')
-rw-r--r-- | backends/events/sdl/sdl-events.cpp | 75 | ||||
-rw-r--r-- | backends/events/sdl/sdl-events.h | 9 |
2 files changed, 65 insertions, 19 deletions
diff --git a/backends/events/sdl/sdl-events.cpp b/backends/events/sdl/sdl-events.cpp index 1ab230141c..5fb66a7ec4 100644 --- a/backends/events/sdl/sdl-events.cpp +++ b/backends/events/sdl/sdl-events.cpp @@ -555,15 +555,17 @@ bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) { SDLModToOSystemKeyFlags(SDL_GetModState(), event); + SDLKey sdlKeycode = obtainKeycode(ev.key.keysym); + // Handle scroll lock as a key modifier - if (ev.key.keysym.sym == SDLK_SCROLLOCK) + if (sdlKeycode == SDLK_SCROLLOCK) _scrollLock = !_scrollLock; if (_scrollLock) event.kbd.flags |= Common::KBD_SCRL; // Ctrl-m toggles mouse capture - if (event.kbd.hasFlags(Common::KBD_CTRL) && ev.key.keysym.sym == 'm') { + if (event.kbd.hasFlags(Common::KBD_CTRL) && sdlKeycode == 'm') { if (_graphicsManager) { _graphicsManager->getWindow()->toggleMouseGrab(); } @@ -572,26 +574,26 @@ bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) { #if defined(MACOSX) // On Macintosh, Cmd-Q quits - if ((ev.key.keysym.mod & KMOD_META) && ev.key.keysym.sym == 'q') { + if ((ev.key.keysym.mod & KMOD_META) && sdlKeycode == 'q') { event.type = Common::EVENT_QUIT; return true; } #elif defined(POSIX) // On other *nix systems, Control-Q quits - if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'q') { + if ((ev.key.keysym.mod & KMOD_CTRL) && sdlKeycode == 'q') { event.type = Common::EVENT_QUIT; return true; } #else // Ctrl-z quits - if ((event.kbd.hasFlags(Common::KBD_CTRL) && ev.key.keysym.sym == 'z')) { + if ((event.kbd.hasFlags(Common::KBD_CTRL) && sdlKeycode == 'z')) { event.type = Common::EVENT_QUIT; return true; } #ifdef WIN32 // On Windows, also use the default Alt-F4 quit combination - if ((ev.key.keysym.mod & KMOD_ALT) && ev.key.keysym.sym == SDLK_F4) { + if ((ev.key.keysym.mod & KMOD_ALT) && sdlKeycode == SDLK_F4) { event.type = Common::EVENT_QUIT; return true; } @@ -599,7 +601,7 @@ bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) { #endif // Ctrl-u toggles mute - if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'u') { + if ((ev.key.keysym.mod & KMOD_CTRL) && sdlKeycode == 'u') { event.type = Common::EVENT_MUTE; return true; } @@ -608,8 +610,8 @@ bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) { return true; event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = SDLToOSystemKeycode(ev.key.keysym.sym); - event.kbd.ascii = mapKey(ev.key.keysym.sym, (SDLMod)ev.key.keysym.mod, obtainUnicode(ev.key.keysym)); + event.kbd.keycode = SDLToOSystemKeycode(sdlKeycode); + event.kbd.ascii = mapKey(sdlKeycode, (SDLMod)ev.key.keysym.mod, obtainUnicode(ev.key.keysym)); return true; } @@ -618,6 +620,7 @@ bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) { if (remapKey(ev, event)) return true; + SDLKey sdlKeycode = obtainKeycode(ev.key.keysym); SDLMod mod = SDL_GetModState(); // Check if this is an event handled by handleKeyDown(), and stop if it is @@ -625,21 +628,21 @@ bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) { // Check if the Ctrl key is down, so that we can trap cases where the // user has the Ctrl key down, and has just released a special key if (mod & KMOD_CTRL) { - if (ev.key.keysym.sym == 'm' || // Ctrl-m toggles mouse capture + if (sdlKeycode == 'm' || // Ctrl-m toggles mouse capture #if defined(MACOSX) // Meta - Q, handled below #elif defined(POSIX) - ev.key.keysym.sym == 'q' || // On other *nix systems, Control-Q quits + sdlKeycode == 'q' || // On other *nix systems, Control-Q quits #else - ev.key.keysym.sym == 'z' || // Ctrl-z quit + sdlKeycode == 'z' || // Ctrl-z quit #endif - ev.key.keysym.sym == 'u') // Ctrl-u toggles mute + sdlKeycode == 'u') // Ctrl-u toggles mute return false; } // Same for other keys (Meta and Alt) #if defined(MACOSX) - if ((mod & KMOD_META) && ev.key.keysym.sym == 'q') + if ((mod & KMOD_META) && sdlKeycode == 'q') return false; // On Macintosh, Cmd-Q quits #endif @@ -647,8 +650,8 @@ bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) { // continue normally event.type = Common::EVENT_KEYUP; - event.kbd.keycode = SDLToOSystemKeycode(ev.key.keysym.sym); - event.kbd.ascii = mapKey(ev.key.keysym.sym, (SDLMod)ev.key.keysym.mod, 0); + event.kbd.keycode = SDLToOSystemKeycode(sdlKeycode); + event.kbd.ascii = mapKey(sdlKeycode, (SDLMod)ev.key.keysym.mod, 0); // Ctrl-Alt-<key> will change the GFX mode SDLModToOSystemKeyFlags(mod, event); @@ -883,7 +886,7 @@ bool SdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) { return false; } -void SdlEventSource::resetKeyboadEmulation(int16 x_max, int16 y_max) { +void SdlEventSource::resetKeyboardEmulation(int16 x_max, int16 y_max) { _km.x_max = x_max; _km.y_max = y_max; _km.delay_time = 25; @@ -906,6 +909,44 @@ bool SdlEventSource::handleResizeEvent(Common::Event &event, int w, int h) { return false; } +SDLKey SdlEventSource::obtainKeycode(const SDL_keysym keySym) { +#if !SDL_VERSION_ATLEAST(2, 0, 0) && defined(WIN32) && !defined(_WIN32_WCE) + // WORKAROUND: SDL 1.2 on Windows does not use the user configured keyboard layout, + // resulting in "keySym.sym" values to always be those expected for an US keyboard. + // For example, SDL returns SDLK_Q when pressing the 'A' key on an AZERTY keyboard. + // This defeats the purpose of keycodes which is to be able to refer to a key without + // knowing where it is physically located. + // We work around this issue by querying the currently active Windows keyboard layout + // using the scancode provided by SDL. + + if (keySym.sym >= SDLK_0 && keySym.sym <= SDLK_9) { + // The keycode returned by SDL is kept for the number keys. + // Querying the keyboard layout for those would return the base key values + // for AZERTY keyboards, which are not numbers. For example, SDLK_1 would + // map to SDLK_AMPERSAND. This is theoretically correct but practically unhelpful, + // because it makes it impossible to handle key combinations such as "ctrl-1". + return keySym.sym; + } + + int vk = MapVirtualKey(keySym.scancode, MAPVK_VSC_TO_VK); + if (vk) { + int ch = (MapVirtualKey(vk, MAPVK_VK_TO_CHAR) & 0x7FFF); + // The top bit of the result of MapVirtualKey with MAPVK_VSC_TO_VK signals + // a dead key was pressed. In that case we keep the value of the accent alone. + if (ch) { + if (ch >= 'A' && ch <= 'Z') { + // Windows returns uppercase ASCII whereas SDL expects lowercase + return (SDLKey)(SDLK_a + (ch - 'A')); + } else { + return (SDLKey)ch; + } + } + } +#endif + + return keySym.sym; +} + uint32 SdlEventSource::obtainUnicode(const SDL_keysym keySym) { #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_Event events[2]; diff --git a/backends/events/sdl/sdl-events.h b/backends/events/sdl/sdl-events.h index caa60c1354..c43699420b 100644 --- a/backends/events/sdl/sdl-events.h +++ b/backends/events/sdl/sdl-events.h @@ -47,7 +47,7 @@ public: /** * Resets keyboard emulation after a video screen change */ - virtual void resetKeyboadEmulation(int16 x_max, int16 y_max); + virtual void resetKeyboardEmulation(int16 x_max, int16 y_max); protected: /** @name Keyboard mouse emulation @@ -125,7 +125,7 @@ protected: /** * Maps the ASCII value of key */ - int mapKey(SDLKey key, SDLMod mod, Uint16 unicode); + virtual int mapKey(SDLKey key, SDLMod mod, Uint16 unicode); /** * Configures the key modifiers flags status @@ -148,6 +148,11 @@ protected: */ uint32 obtainUnicode(const SDL_keysym keySym); + /** + * Extracts the keycode for the specified key sym. + */ + SDLKey obtainKeycode(const SDL_keysym keySym); + #if SDL_VERSION_ATLEAST(2, 0, 0) /** * Whether _fakeKeyUp contains an event we need to send. |