ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

sdl-events.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "common/scummsys.h"
00024 
00025 #if defined(SDL_BACKEND)
00026 
00027 #include "backends/events/sdl/sdl-events.h"
00028 #include "backends/platform/sdl/sdl.h"
00029 #include "backends/graphics/graphics.h"
00030 #include "common/config-manager.h"
00031 #include "common/textconsole.h"
00032 #include "common/fs.h"
00033 
00034 //ResidualVM specific:
00035 #if defined(__amigaos4__)
00036 // KEYCODE_LESS and KEYCODE_GREATER are already defined in AmigaOS, inside
00037 // include/include_h/intuition/intuition.h (bug #3121350)
00038 #if defined(KEYCODE_LESS) && defined(KEYCODE_GREATER)
00039 #undef KEYCODE_LESS
00040 #undef KEYCODE_GREATER
00041 #endif
00042 #endif
00043 
00044 // FIXME move joystick defines out and replace with confile file options
00045 // we should really allow users to map any key to a joystick button
00046 
00047 // #define JOY_INVERT_Y
00048 #define JOY_XAXIS 0
00049 #define JOY_YAXIS 1
00050 // buttons
00051 #define JOY_BUT_LMOUSE 0
00052 #define JOY_BUT_RMOUSE 2
00053 #define JOY_BUT_ESCAPE 3
00054 #define JOY_BUT_PERIOD 1
00055 #define JOY_BUT_SPACE 4
00056 #define JOY_BUT_F5 5
00057 #ifdef ENABLE_VKEYBD
00058 #define JOY_BUT_VKEYBOARD 7
00059 #endif
00060 
00061 
00062 #if SDL_VERSION_ATLEAST(2, 0, 0)
00063 #define GAMECONTROLLERDB_FILE "gamecontrollerdb.txt"
00064 
00065 static uint32 convUTF8ToUTF32(const char *src) {
00066     uint32 utf32 = 0;
00067 
00068     char *dst = SDL_iconv_string(
00069 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
00070                                  "UTF-32BE",
00071 #else
00072                                  "UTF-32LE",
00073 #endif
00074                                  "UTF-8", src, SDL_strlen(src) + 1);
00075 
00076     if (dst) {
00077         utf32 = *((uint32 *)dst);
00078         SDL_free(dst);
00079     }
00080 
00081     return utf32;
00082 }
00083 
00084 void SdlEventSource::loadGameControllerMappingFile() {
00085     bool loaded = false;
00086     if (ConfMan.hasKey("controller_map_db")) {
00087         Common::FSNode file = Common::FSNode(ConfMan.get("controller_map_db"));
00088         if (file.exists()) {
00089             if (SDL_GameControllerAddMappingsFromFile(file.getPath().c_str()) < 0)
00090                 error("File %s not valid: %s", file.getPath().c_str(), SDL_GetError()); 
00091             else {
00092                 loaded = true;
00093                 debug("Game controller DB file loaded: %s", file.getPath().c_str());
00094             }
00095         } else
00096             warning("Game controller DB file not found: %s", file.getPath().c_str());
00097     }
00098     if (!loaded && ConfMan.hasKey("extrapath")) {
00099         Common::FSNode dir = Common::FSNode(ConfMan.get("extrapath"));
00100         Common::FSNode file = dir.getChild(GAMECONTROLLERDB_FILE);
00101         if (file.exists()) {
00102             if (SDL_GameControllerAddMappingsFromFile(file.getPath().c_str()) < 0)
00103                 error("File %s not valid: %s", file.getPath().c_str(), SDL_GetError()); 
00104             else
00105                 debug("Game controller DB file loaded: %s", file.getPath().c_str());
00106         }
00107     }
00108 }
00109 #endif
00110 
00111 SdlEventSource::SdlEventSource()
00112     : EventSource(), _scrollLock(false), _joystick(0), _lastScreenID(0), _graphicsManager(0), _queuedFakeMouseMove(false)
00113 #if SDL_VERSION_ATLEAST(2, 0, 0)
00114       , _queuedFakeKeyUp(false), _fakeKeyUp(), _controller(nullptr)
00115 #endif
00116       {
00117     // Reset mouse state
00118     memset(&_km, 0, sizeof(_km));
00119 
00120     int joystick_num = ConfMan.getInt("joystick_num");
00121     if (joystick_num >= 0) {
00122         // Initialize SDL joystick subsystem
00123         if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) {
00124             error("Could not initialize SDL: %s", SDL_GetError());
00125         }
00126 
00127 #if SDL_VERSION_ATLEAST(2, 0, 0)
00128         if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) == -1) {
00129             error("Could not initialize SDL: %s", SDL_GetError());
00130         }
00131         loadGameControllerMappingFile();
00132 #endif
00133 
00134         openJoystick(joystick_num);
00135     }
00136 }
00137 
00138 SdlEventSource::~SdlEventSource() {
00139     closeJoystick();
00140 }
00141 
00142 int SdlEventSource::mapKey(SDLKey sdlKey, SDLMod mod, Uint16 unicode) {
00143     Common::KeyCode key = SDLToOSystemKeycode(sdlKey);
00144 
00145     // Keep unicode in case it's regular ASCII text or in case we didn't get a valid keycode
00146     //
00147     // We need to use unicode in those cases, simply because SDL1.x passes us non-layout-adjusted keycodes.
00148     // So unicode is the only way to get layout-adjusted keys.
00149     if (unicode < 0x20) {
00150         // don't use unicode, in case it's control characters
00151         unicode = 0;
00152     } else {
00153         // Use unicode, in case keycode is invalid.
00154         // Umlauts and others will set KEYCODE_INVALID on SDL2, so in such a case always keep unicode.
00155         if (key != Common::KEYCODE_INVALID) {
00156             // keycode is valid, check further also depending on modifiers
00157             if (mod & (KMOD_CTRL | KMOD_ALT)) {
00158                 // Ctrl and/or Alt is active
00159                 //
00160                 // We need to restrict unicode to only up to 0x7E, because on macOS the option/alt key will switch to
00161                 // an alternate keyboard, which will cause us to receive Unicode characters for some keys, which are outside
00162                 // of the ASCII range (e.g. alt-x will get us U+2248). We need to return 'x' for alt-x, so using unicode
00163                 // in that case would break alt-shortcuts.
00164                 if (unicode > 0x7E)
00165                     unicode = 0; // do not allow any characters above 0x7E
00166             } else {
00167                 // We must not restrict as much as when Ctrl/Alt-modifiers are active, otherwise
00168                 // we wouldn't let umlauts through for SDL1. For SDL1 umlauts may set for example KEYCODE_QUOTE, KEYCODE_MINUS, etc.
00169                 if (unicode > 0xFF)
00170                     unicode = 0; // do not allow any characters above 0xFF
00171             }
00172         }
00173     }
00174 
00175     // Attention:
00176     // When using SDL1.x, we will get scancodes via sdlKey, that are raw scancodes, so NOT adjusted to keyboard layout/
00177     // mapping. So for example for certain locales, we will get KEYCODE_y, when 'z' is pressed and so on.
00178     // When using SDL2.x however, we will get scancodes based on the keyboard layout.
00179 
00180     if (key >= Common::KEYCODE_F1 && key <= Common::KEYCODE_F9) {
00181         return key - Common::KEYCODE_F1 + Common::ASCII_F1;
00182     } else if (key >= Common::KEYCODE_KP0 && key <= Common::KEYCODE_KP9) {
00183         // WORKAROUND:  Disable this change for AmigaOS4 as it is breaking numpad usage ("fighting") on that platform.
00184         // This fixes bug #10558.
00185         // The actual issue here is that the SCUMM engine uses ASCII codes instead of keycodes for input.
00186         // See also the relevant FIXME in SCUMM's input.cpp.
00187         #ifndef __amigaos4__
00188             if ((mod & KMOD_NUM) == 0)
00189                 return 0; // In case Num-Lock is NOT enabled, return 0 for ascii, so that directional keys on numpad work
00190         #endif
00191         return key - Common::KEYCODE_KP0 + '0';
00192     } else if (key >= Common::KEYCODE_UP && key <= Common::KEYCODE_PAGEDOWN) {
00193         return key;
00194     } else if (unicode) {
00195         // Return unicode in case it's still set and wasn't filtered.
00196         return unicode;
00197     } else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) {
00198         return key & ~0x20;
00199     } else if (key >= Common::KEYCODE_NUMLOCK && key <= Common::KEYCODE_EURO) {
00200         return 0;
00201     } else {
00202         return key;
00203     }
00204 }
00205 
00206 // ResidualVM specific relMouse x,y
00207 bool SdlEventSource::processMouseEvent(Common::Event &event, int x, int y, int relx, int rely) {
00208     event.mouse.x = x;
00209     event.mouse.y = y;
00210     event.relMouse.x = relx;
00211     event.relMouse.y = rely;
00212 
00213     if (_graphicsManager) {
00214         return _graphicsManager->notifyMousePosition(event.mouse);
00215     }
00216 
00217     return true;
00218 }
00219 
00220 void SdlEventSource::updateKbdMouse() {
00221     uint32 curTime = g_system->getMillis(true);
00222     if (curTime < _km.last_time + _km.delay_time) {
00223         return;
00224     }
00225 
00226     _km.last_time = curTime;
00227     if (_km.x_down_count == 1) {
00228         _km.x_down_time = curTime;
00229         _km.x_down_count = 2;
00230     }
00231     if (_km.y_down_count == 1) {
00232         _km.y_down_time = curTime;
00233         _km.y_down_count = 2;
00234     }
00235 
00236     if (_km.x_vel || _km.y_vel) {
00237         if (_km.x_down_count) {
00238             if (curTime > _km.x_down_time + 300) {
00239                 if (_km.x_vel > 0)
00240                     _km.x_vel += MULTIPLIER;
00241                 else
00242                     _km.x_vel -= MULTIPLIER;
00243             } else if (curTime > _km.x_down_time + 200) {
00244                 if (_km.x_vel > 0)
00245                     _km.x_vel = 5 * MULTIPLIER;
00246                 else
00247                     _km.x_vel = -5 * MULTIPLIER;
00248             }
00249         }
00250         if (_km.y_down_count) {
00251             if (curTime > _km.y_down_time + 300) {
00252                 if (_km.y_vel > 0)
00253                     _km.y_vel += MULTIPLIER;
00254                 else
00255                     _km.y_vel -= MULTIPLIER;
00256             } else if (curTime > _km.y_down_time + 200) {
00257                 if (_km.y_vel > 0)
00258                     _km.y_vel = 5 * MULTIPLIER;
00259                 else
00260                     _km.y_vel = -5 * MULTIPLIER;
00261             }
00262         }
00263 
00264         int16 speedFactor = computeJoystickMouseSpeedFactor();
00265 
00266         // - The modifier key makes the mouse movement slower
00267         // - The extra factor "delay/speedFactor" ensures velocities
00268         // are independent of the kbdMouse update rate
00269         // - all velocities were originally chosen
00270         // at a delay of 25, so that is the reference used here
00271         // - note: operator order is important to avoid overflow
00272         if (_km.modifier) {
00273             _km.x += ((_km.x_vel / 10) * ((int16)_km.delay_time)) / speedFactor;
00274             _km.y += ((_km.y_vel / 10) * ((int16)_km.delay_time)) / speedFactor;
00275         } else {
00276             _km.x += (_km.x_vel * ((int16)_km.delay_time)) / speedFactor;
00277             _km.y += (_km.y_vel * ((int16)_km.delay_time)) / speedFactor;
00278         }
00279 
00280         if (_km.x < 0) {
00281             _km.x = 0;
00282             _km.x_vel = -1 * MULTIPLIER;
00283             _km.x_down_count = 1;
00284         } else if (_km.x > _km.x_max * MULTIPLIER) {
00285             _km.x = _km.x_max * MULTIPLIER;
00286             _km.x_vel = 1 * MULTIPLIER;
00287             _km.x_down_count = 1;
00288         }
00289 
00290         if (_km.y < 0) {
00291             _km.y = 0;
00292             _km.y_vel = -1 * MULTIPLIER;
00293             _km.y_down_count = 1;
00294         } else if (_km.y > _km.y_max * MULTIPLIER) {
00295             _km.y = _km.y_max * MULTIPLIER;
00296             _km.y_vel = 1 * MULTIPLIER;
00297             _km.y_down_count = 1;
00298         }
00299     }
00300 }
00301 
00302 bool SdlEventSource::handleKbdMouse(Common::Event &event) {
00303     int16 oldKmX = _km.x;
00304     int16 oldKmY = _km.y;
00305 
00306     updateKbdMouse();
00307 
00308     if (_km.x != oldKmX || _km.y != oldKmY) {
00309         if (_graphicsManager) {
00310             _graphicsManager->getWindow()->warpMouseInWindow((Uint16)(_km.x / MULTIPLIER), (Uint16)(_km.y / MULTIPLIER));
00311         }
00312 
00313         event.type = Common::EVENT_MOUSEMOVE;
00314         return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
00315     }
00316 
00317     return false;
00318 }
00319 
00320 int16 SdlEventSource::computeJoystickMouseSpeedFactor() const {
00321     int16 speedFactor;
00322 
00323     switch (ConfMan.getInt("kbdmouse_speed")) {
00324     // 0.25 keyboard pointer speed
00325     case 0:
00326         speedFactor = 100;
00327         break;
00328     // 0.5 speed
00329     case 1:
00330         speedFactor = 50;
00331         break;
00332     // 0.75 speed
00333     case 2:
00334         speedFactor = 33;
00335         break;
00336     // 1.0 speed
00337     case 3:
00338         speedFactor = 25;
00339         break;
00340     // 1.25 speed
00341     case 4:
00342         speedFactor = 20;
00343         break;
00344     // 1.5 speed
00345     case 5:
00346         speedFactor = 17;
00347         break;
00348     // 1.75 speed
00349     case 6:
00350         speedFactor = 14;
00351         break;
00352     // 2.0 speed
00353     case 7:
00354         speedFactor = 12;
00355         break;
00356     default:
00357         speedFactor = 25;
00358     }
00359 
00360     // Scale the mouse cursor speed with the display size so moving across
00361     // the screen takes a reasonable amount of time at higher resolutions.
00362     return speedFactor * 480 / _km.y_max;
00363 }
00364 
00365 void SdlEventSource::SDLModToOSystemKeyFlags(SDLMod mod, Common::Event &event) {
00366 
00367     event.kbd.flags = 0;
00368 
00369     if (mod & KMOD_SHIFT)
00370         event.kbd.flags |= Common::KBD_SHIFT;
00371     if (mod & KMOD_ALT)
00372         event.kbd.flags |= Common::KBD_ALT;
00373     if (mod & KMOD_CTRL)
00374         event.kbd.flags |= Common::KBD_CTRL;
00375     if (mod & KMOD_META)
00376         event.kbd.flags |= Common::KBD_META;
00377 
00378     // Sticky flags
00379     if (mod & KMOD_NUM)
00380         event.kbd.flags |= Common::KBD_NUM;
00381     if (mod & KMOD_CAPS)
00382         event.kbd.flags |= Common::KBD_CAPS;
00383 }
00384 
00385 Common::KeyCode SdlEventSource::SDLToOSystemKeycode(const SDLKey key) {
00386     switch (key) {
00387     case SDLK_BACKSPACE: return Common::KEYCODE_BACKSPACE;
00388     case SDLK_TAB: return Common::KEYCODE_TAB;
00389     case SDLK_CLEAR: return Common::KEYCODE_CLEAR;
00390     case SDLK_RETURN: return Common::KEYCODE_RETURN;
00391     case SDLK_PAUSE: return Common::KEYCODE_PAUSE;
00392     case SDLK_ESCAPE: return Common::KEYCODE_ESCAPE;
00393     case SDLK_SPACE: return Common::KEYCODE_SPACE;
00394     case SDLK_EXCLAIM: return Common::KEYCODE_EXCLAIM;
00395     case SDLK_QUOTEDBL: return Common::KEYCODE_QUOTEDBL;
00396     case SDLK_HASH: return Common::KEYCODE_HASH;
00397     case SDLK_DOLLAR: return Common::KEYCODE_DOLLAR;
00398     case SDLK_AMPERSAND: return Common::KEYCODE_AMPERSAND;
00399     case SDLK_QUOTE: return Common::KEYCODE_QUOTE;
00400     case SDLK_LEFTPAREN: return Common::KEYCODE_LEFTPAREN;
00401     case SDLK_RIGHTPAREN: return Common::KEYCODE_RIGHTPAREN;
00402     case SDLK_ASTERISK: return Common::KEYCODE_ASTERISK;
00403     case SDLK_PLUS: return Common::KEYCODE_PLUS;
00404     case SDLK_COMMA: return Common::KEYCODE_COMMA;
00405     case SDLK_MINUS: return Common::KEYCODE_MINUS;
00406     case SDLK_PERIOD: return Common::KEYCODE_PERIOD;
00407     case SDLK_SLASH: return Common::KEYCODE_SLASH;
00408     case SDLK_0: return Common::KEYCODE_0;
00409     case SDLK_1: return Common::KEYCODE_1;
00410     case SDLK_2: return Common::KEYCODE_2;
00411     case SDLK_3: return Common::KEYCODE_3;
00412     case SDLK_4: return Common::KEYCODE_4;
00413     case SDLK_5: return Common::KEYCODE_5;
00414     case SDLK_6: return Common::KEYCODE_6;
00415     case SDLK_7: return Common::KEYCODE_7;
00416     case SDLK_8: return Common::KEYCODE_8;
00417     case SDLK_9: return Common::KEYCODE_9;
00418     case SDLK_COLON: return Common::KEYCODE_COLON;
00419     case SDLK_SEMICOLON: return Common::KEYCODE_SEMICOLON;
00420     case SDLK_LESS: return Common::KEYCODE_LESS;
00421     case SDLK_EQUALS: return Common::KEYCODE_EQUALS;
00422     case SDLK_GREATER: return Common::KEYCODE_GREATER;
00423     case SDLK_QUESTION: return Common::KEYCODE_QUESTION;
00424     case SDLK_AT: return Common::KEYCODE_AT;
00425     case SDLK_LEFTBRACKET: return Common::KEYCODE_LEFTBRACKET;
00426     case SDLK_BACKSLASH: return Common::KEYCODE_BACKSLASH;
00427     case SDLK_RIGHTBRACKET: return Common::KEYCODE_RIGHTBRACKET;
00428     case SDLK_CARET: return Common::KEYCODE_CARET;
00429     case SDLK_UNDERSCORE: return Common::KEYCODE_UNDERSCORE;
00430     case SDLK_BACKQUOTE: return Common::KEYCODE_BACKQUOTE;
00431     case SDLK_a: return Common::KEYCODE_a;
00432     case SDLK_b: return Common::KEYCODE_b;
00433     case SDLK_c: return Common::KEYCODE_c;
00434     case SDLK_d: return Common::KEYCODE_d;
00435     case SDLK_e: return Common::KEYCODE_e;
00436     case SDLK_f: return Common::KEYCODE_f;
00437     case SDLK_g: return Common::KEYCODE_g;
00438     case SDLK_h: return Common::KEYCODE_h;
00439     case SDLK_i: return Common::KEYCODE_i;
00440     case SDLK_j: return Common::KEYCODE_j;
00441     case SDLK_k: return Common::KEYCODE_k;
00442     case SDLK_l: return Common::KEYCODE_l;
00443     case SDLK_m: return Common::KEYCODE_m;
00444     case SDLK_n: return Common::KEYCODE_n;
00445     case SDLK_o: return Common::KEYCODE_o;
00446     case SDLK_p: return Common::KEYCODE_p;
00447     case SDLK_q: return Common::KEYCODE_q;
00448     case SDLK_r: return Common::KEYCODE_r;
00449     case SDLK_s: return Common::KEYCODE_s;
00450     case SDLK_t: return Common::KEYCODE_t;
00451     case SDLK_u: return Common::KEYCODE_u;
00452     case SDLK_v: return Common::KEYCODE_v;
00453     case SDLK_w: return Common::KEYCODE_w;
00454     case SDLK_x: return Common::KEYCODE_x;
00455     case SDLK_y: return Common::KEYCODE_y;
00456     case SDLK_z: return Common::KEYCODE_z;
00457     case SDLK_DELETE: return Common::KEYCODE_DELETE;
00458 #if SDL_VERSION_ATLEAST(2, 0, 0)
00459     case SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_GRAVE): return Common::KEYCODE_TILDE;
00460 #else
00461     case SDLK_WORLD_16: return Common::KEYCODE_TILDE;
00462 #endif
00463     case SDLK_KP0: return Common::KEYCODE_KP0;
00464     case SDLK_KP1: return Common::KEYCODE_KP1;
00465     case SDLK_KP2: return Common::KEYCODE_KP2;
00466     case SDLK_KP3: return Common::KEYCODE_KP3;
00467     case SDLK_KP4: return Common::KEYCODE_KP4;
00468     case SDLK_KP5: return Common::KEYCODE_KP5;
00469     case SDLK_KP6: return Common::KEYCODE_KP6;
00470     case SDLK_KP7: return Common::KEYCODE_KP7;
00471     case SDLK_KP8: return Common::KEYCODE_KP8;
00472     case SDLK_KP9: return Common::KEYCODE_KP9;
00473     case SDLK_KP_PERIOD: return Common::KEYCODE_KP_PERIOD;
00474     case SDLK_KP_DIVIDE: return Common::KEYCODE_KP_DIVIDE;
00475     case SDLK_KP_MULTIPLY: return Common::KEYCODE_KP_MULTIPLY;
00476     case SDLK_KP_MINUS: return Common::KEYCODE_KP_MINUS;
00477     case SDLK_KP_PLUS: return Common::KEYCODE_KP_PLUS;
00478     case SDLK_KP_ENTER: return Common::KEYCODE_KP_ENTER;
00479     case SDLK_KP_EQUALS: return Common::KEYCODE_KP_EQUALS;
00480     case SDLK_UP: return Common::KEYCODE_UP;
00481     case SDLK_DOWN: return Common::KEYCODE_DOWN;
00482     case SDLK_RIGHT: return Common::KEYCODE_RIGHT;
00483     case SDLK_LEFT: return Common::KEYCODE_LEFT;
00484     case SDLK_INSERT: return Common::KEYCODE_INSERT;
00485     case SDLK_HOME: return Common::KEYCODE_HOME;
00486     case SDLK_END: return Common::KEYCODE_END;
00487     case SDLK_PAGEUP: return Common::KEYCODE_PAGEUP;
00488     case SDLK_PAGEDOWN: return Common::KEYCODE_PAGEDOWN;
00489     case SDLK_F1: return Common::KEYCODE_F1;
00490     case SDLK_F2: return Common::KEYCODE_F2;
00491     case SDLK_F3: return Common::KEYCODE_F3;
00492     case SDLK_F4: return Common::KEYCODE_F4;
00493     case SDLK_F5: return Common::KEYCODE_F5;
00494     case SDLK_F6: return Common::KEYCODE_F6;
00495     case SDLK_F7: return Common::KEYCODE_F7;
00496     case SDLK_F8: return Common::KEYCODE_F8;
00497     case SDLK_F9: return Common::KEYCODE_F9;
00498     case SDLK_F10: return Common::KEYCODE_F10;
00499     case SDLK_F11: return Common::KEYCODE_F11;
00500     case SDLK_F12: return Common::KEYCODE_F12;
00501     case SDLK_F13: return Common::KEYCODE_F13;
00502     case SDLK_F14: return Common::KEYCODE_F14;
00503     case SDLK_F15: return Common::KEYCODE_F15;
00504     case SDLK_NUMLOCK: return Common::KEYCODE_NUMLOCK;
00505     case SDLK_CAPSLOCK: return Common::KEYCODE_CAPSLOCK;
00506     case SDLK_SCROLLOCK: return Common::KEYCODE_SCROLLOCK;
00507     case SDLK_RSHIFT: return Common::KEYCODE_RSHIFT;
00508     case SDLK_LSHIFT: return Common::KEYCODE_LSHIFT;
00509     case SDLK_RCTRL: return Common::KEYCODE_RCTRL;
00510     case SDLK_LCTRL: return Common::KEYCODE_LCTRL;
00511     case SDLK_RALT: return Common::KEYCODE_RALT;
00512     case SDLK_LALT: return Common::KEYCODE_LALT;
00513     case SDLK_LSUPER: return Common::KEYCODE_LSUPER;
00514     case SDLK_RSUPER: return Common::KEYCODE_RSUPER;
00515     case SDLK_MODE: return Common::KEYCODE_MODE;
00516     case SDLK_COMPOSE: return Common::KEYCODE_COMPOSE;
00517     case SDLK_HELP: return Common::KEYCODE_HELP;
00518     case SDLK_PRINT: return Common::KEYCODE_PRINT;
00519     case SDLK_SYSREQ: return Common::KEYCODE_SYSREQ;
00520 #if !SDL_VERSION_ATLEAST(2, 0, 0)
00521     case SDLK_BREAK: return Common::KEYCODE_BREAK;
00522 #endif
00523     case SDLK_MENU: return Common::KEYCODE_MENU;
00524     case SDLK_POWER: return Common::KEYCODE_POWER;
00525     case SDLK_UNDO: return Common::KEYCODE_UNDO;
00526     default: return Common::KEYCODE_INVALID;
00527     }
00528 }
00529 
00530 bool SdlEventSource::pollEvent(Common::Event &event) {
00531 
00532 #if SDL_VERSION_ATLEAST(2, 0, 0)
00533     // In case we still need to send a key up event for a key down from a
00534     // TEXTINPUT event we do this immediately.
00535     if (_queuedFakeKeyUp) {
00536         event = _fakeKeyUp;
00537         _queuedFakeKeyUp = false;
00538         return true;
00539     }
00540 #endif
00541 
00542     // If the screen changed, send an Common::EVENT_SCREEN_CHANGED
00543     int screenID = ((OSystem_SDL *)g_system)->getGraphicsManager()->getScreenChangeID();
00544     if (screenID != _lastScreenID) {
00545         _lastScreenID = screenID;
00546         event.type = Common::EVENT_SCREEN_CHANGED;
00547         return true;
00548     }
00549 
00550     if (_queuedFakeMouseMove) {
00551         event = _fakeMouseMove;
00552         _queuedFakeMouseMove = false;
00553         return true;
00554     }
00555 
00556     SDL_Event ev;
00557     while (SDL_PollEvent(&ev)) {
00558         preprocessEvents(&ev);
00559         if (dispatchSDLEvent(ev, event))
00560             return true;
00561     }
00562 
00563     // Handle mouse control via analog joystick and keyboard
00564     if (handleKbdMouse(event)) {
00565         return true;
00566     }
00567 
00568     return false;
00569 }
00570 
00571 bool SdlEventSource::dispatchSDLEvent(SDL_Event &ev, Common::Event &event) {
00572     switch (ev.type) {
00573     case SDL_KEYDOWN:
00574         return handleKeyDown(ev, event);
00575     case SDL_KEYUP:
00576         return handleKeyUp(ev, event);
00577     case SDL_MOUSEMOTION:
00578         return handleMouseMotion(ev, event);
00579     case SDL_MOUSEBUTTONDOWN:
00580         return handleMouseButtonDown(ev, event);
00581     case SDL_MOUSEBUTTONUP:
00582         return handleMouseButtonUp(ev, event);
00583     case SDL_SYSWMEVENT:
00584         return handleSysWMEvent(ev, event);
00585 
00586 #if SDL_VERSION_ATLEAST(2, 0, 0)
00587     case SDL_MOUSEWHEEL: {
00588         Sint32 yDir = ev.wheel.y;
00589         // HACK: It seems we want the mouse coordinates supplied
00590         // with a mouse wheel event. However, SDL2 does not supply
00591         // these, thus we use whatever we got last time. It seems
00592         // these are always stored in _km.x, _km.y.
00593         if (!processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER)) {
00594             return false;
00595         }
00596         if (yDir < 0) {
00597             event.type = Common::EVENT_WHEELDOWN;
00598             return true;
00599         } else if (yDir > 0) {
00600             event.type = Common::EVENT_WHEELUP;
00601             return true;
00602         } else {
00603             return false;
00604         }
00605         }
00606 
00607     case SDL_TEXTINPUT: {
00608         // When we get a TEXTINPUT event it means we got some user input for
00609         // which no KEYDOWN exists. SDL 1.2 introduces a "fake" key down+up
00610         // in such cases. We will do the same to mimic it's behavior.
00611         event.type = Common::EVENT_KEYDOWN;
00612 
00613         event.kbd = Common::KeyState(Common::KEYCODE_INVALID, convUTF8ToUTF32(ev.text.text), 0);
00614 
00615         SDLModToOSystemKeyFlags(SDL_GetModState(), event);
00616         // Set the scroll lock sticky flag
00617         if (_scrollLock)
00618             event.kbd.flags |= Common::KBD_SCRL;
00619 
00620         // Fake a key up when we have a proper ascii value.
00621         _queuedFakeKeyUp = (event.kbd.ascii != 0);
00622         _fakeKeyUp = event;
00623         _fakeKeyUp.type = Common::EVENT_KEYUP;
00624 
00625         return _queuedFakeKeyUp;
00626         }
00627 
00628     case SDL_WINDOWEVENT:
00629         switch (ev.window.event) {
00630         case SDL_WINDOWEVENT_EXPOSED:
00631             if (_graphicsManager)
00632                 _graphicsManager->notifyVideoExpose();
00633             return false;
00634 
00635         // SDL2 documentation indicate that SDL_WINDOWEVENT_SIZE_CHANGED is sent either as a result
00636         // of the size being changed by an external event (for example the user resizing the window
00637         // or going fullscreen) or a call to the SDL API (for example SDL_SetWindowSize). On the
00638         // other hand SDL_WINDOWEVENT_RESIZED is only sent for resize resulting from an external event,
00639         // and is always preceded by a SDL_WINDOWEVENT_SIZE_CHANGED event.
00640         // We need to handle the programmatic resize as well so that the graphics manager always know
00641         // the current size. See comments in SdlWindow::createOrUpdateWindow for details of one case
00642         // where we need to call SDL_SetWindowSize and we need the resulting event to be processed.
00643         // However if the documentation is correct we can ignore SDL_WINDOWEVENT_RESIZED since when we
00644         // get one we should always get a SDL_WINDOWEVENT_SIZE_CHANGED as well.
00645         case SDL_WINDOWEVENT_SIZE_CHANGED:
00646         //case SDL_WINDOWEVENT_RESIZED:
00647             return handleResizeEvent(event, ev.window.data1, ev.window.data2);
00648 
00649         default:
00650             return false;
00651         }
00652 
00653     case SDL_JOYDEVICEADDED:
00654         return handleJoystickAdded(ev.jdevice);
00655 
00656     case SDL_JOYDEVICEREMOVED:
00657         return handleJoystickRemoved(ev.jdevice);
00658 
00659     case SDL_DROPFILE:
00660         event.type = Common::EVENT_DROP_FILE;
00661         event.path = Common::String(ev.drop.file);
00662         SDL_free(ev.drop.file);
00663         return true;
00664 
00665     case SDL_CLIPBOARDUPDATE:
00666         event.type = Common::EVENT_CLIPBOARD_UPDATE;
00667         return true;
00668 #else
00669     case SDL_VIDEOEXPOSE:
00670         if (_graphicsManager)
00671             _graphicsManager->notifyVideoExpose();
00672         return false;
00673 
00674     case SDL_VIDEORESIZE:
00675         return handleResizeEvent(event, ev.resize.w, ev.resize.h);
00676 #endif
00677 
00678     case SDL_QUIT:
00679         event.type = Common::EVENT_QUIT;
00680         return true;
00681 
00682     }
00683 
00684     if (_joystick) {
00685         switch (ev.type) {
00686         case SDL_JOYBUTTONDOWN:
00687             return handleJoyButtonDown(ev, event);
00688         case SDL_JOYBUTTONUP:
00689             return handleJoyButtonUp(ev, event);
00690         case SDL_JOYAXISMOTION:
00691             return handleJoyAxisMotion(ev, event);
00692         }
00693     }
00694 
00695 #if SDL_VERSION_ATLEAST(2, 0, 0)
00696     if (_controller) {
00697         switch (ev.type) {
00698         case SDL_CONTROLLERBUTTONDOWN:
00699             return handleControllerButton(ev, event, false);
00700         case SDL_CONTROLLERBUTTONUP:
00701             return handleControllerButton(ev, event, true);
00702         case SDL_CONTROLLERAXISMOTION:
00703             return handleControllerAxisMotion(ev, event);
00704         }
00705     }
00706 #endif
00707 
00708     return false;
00709 }
00710 
00711 
00712 bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) {
00713 
00714     SDLModToOSystemKeyFlags(SDL_GetModState(), event);
00715 
00716     SDLKey sdlKeycode = obtainKeycode(ev.key.keysym);
00717 
00718     // Handle scroll lock as a key modifier
00719     if (sdlKeycode == SDLK_SCROLLOCK)
00720         _scrollLock = !_scrollLock;
00721 
00722     if (_scrollLock)
00723         event.kbd.flags |= Common::KBD_SCRL;
00724 
00725     // Ctrl-m toggles mouse capture
00726     if (event.kbd.hasFlags(Common::KBD_CTRL) && sdlKeycode == 'm') {
00727         if (_graphicsManager) {
00728             _graphicsManager->getWindow()->toggleMouseGrab();
00729         }
00730         return false;
00731     }
00732 
00733 #if defined(MACOSX)
00734     // On Macintosh, Cmd-Q quits
00735     if ((ev.key.keysym.mod & KMOD_META) && sdlKeycode == 'q') {
00736         event.type = Common::EVENT_QUIT;
00737         return true;
00738     }
00739 #elif defined(POSIX)
00740     // On other *nix systems, Control-Q quits
00741     if ((ev.key.keysym.mod & KMOD_CTRL) && sdlKeycode == 'q') {
00742         event.type = Common::EVENT_QUIT;
00743         return true;
00744     }
00745 #else
00746     // Ctrl-z quits
00747     if ((event.kbd.hasFlags(Common::KBD_CTRL) && sdlKeycode == 'z')) {
00748         event.type = Common::EVENT_QUIT;
00749         return true;
00750     }
00751 
00752     #ifdef WIN32
00753     // On Windows, also use the default Alt-F4 quit combination
00754     if ((ev.key.keysym.mod & KMOD_ALT) && sdlKeycode == SDLK_F4) {
00755         event.type = Common::EVENT_QUIT;
00756         return true;
00757     }
00758     #endif
00759 #endif
00760 
00761     // Ctrl-u toggles mute
00762     if ((ev.key.keysym.mod & KMOD_CTRL) && sdlKeycode == 'u') {
00763         event.type = Common::EVENT_MUTE;
00764         return true;
00765     }
00766 
00767     if (remapKey(ev, event))
00768         return true;
00769 
00770     event.type = Common::EVENT_KEYDOWN;
00771     event.kbd.keycode = SDLToOSystemKeycode(sdlKeycode);
00772     event.kbd.ascii = mapKey(sdlKeycode, (SDLMod)ev.key.keysym.mod, obtainUnicode(ev.key.keysym));
00773 
00774 #if SDL_VERSION_ATLEAST(2, 0, 0)
00775     event.kbdRepeat = ev.key.repeat;
00776 #endif
00777 
00778     return true;
00779 }
00780 
00781 bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) {
00782     if (remapKey(ev, event))
00783         return true;
00784 
00785     SDLKey sdlKeycode = obtainKeycode(ev.key.keysym);
00786     SDLMod mod = SDL_GetModState();
00787 
00788     // Check if this is an event handled by handleKeyDown(), and stop if it is
00789 
00790     // Check if the Ctrl key is down, so that we can trap cases where the
00791     // user has the Ctrl key down, and has just released a special key
00792     if (mod & KMOD_CTRL) {
00793         if (sdlKeycode == 'm' ||    // Ctrl-m toggles mouse capture
00794 #if defined(MACOSX)
00795             // Meta - Q, handled below
00796 #elif defined(POSIX)
00797             sdlKeycode == 'q' ||    // On other *nix systems, Control-Q quits
00798 #else
00799             sdlKeycode == 'z' ||    // Ctrl-z quit
00800 #endif
00801             sdlKeycode == 'u')  // Ctrl-u toggles mute
00802             return false;
00803     }
00804 
00805     // Same for other keys (Meta and Alt)
00806 #if defined(MACOSX)
00807     if ((mod & KMOD_META) && sdlKeycode == 'q')
00808         return false;   // On Macintosh, Cmd-Q quits
00809 #endif
00810 
00811     // If we reached here, this isn't an event handled by handleKeyDown(), thus
00812     // continue normally
00813 
00814     event.type = Common::EVENT_KEYUP;
00815     event.kbd.keycode = SDLToOSystemKeycode(sdlKeycode);
00816     event.kbd.ascii = mapKey(sdlKeycode, (SDLMod)ev.key.keysym.mod, 0);
00817 
00818     // Ctrl-Alt-<key> will change the GFX mode
00819     SDLModToOSystemKeyFlags(mod, event);
00820 
00821     // Set the scroll lock sticky flag
00822     if (_scrollLock)
00823         event.kbd.flags |= Common::KBD_SCRL;
00824 
00825     return true;
00826 }
00827 
00828 bool SdlEventSource::handleMouseMotion(SDL_Event &ev, Common::Event &event) {
00829     event.type = Common::EVENT_MOUSEMOVE;
00830 
00831     // update KbdMouse
00832     _km.x = ev.motion.x * MULTIPLIER;
00833     _km.y = ev.motion.y * MULTIPLIER;
00834 
00835     return processMouseEvent(event, ev.motion.x, ev.motion.y, ev.motion.xrel, ev.motion.yrel); // ResidualVM xrel,yrel
00836 }
00837 
00838 bool SdlEventSource::handleMouseButtonDown(SDL_Event &ev, Common::Event &event) {
00839     if (ev.button.button == SDL_BUTTON_LEFT)
00840         event.type = Common::EVENT_LBUTTONDOWN;
00841     else if (ev.button.button == SDL_BUTTON_RIGHT)
00842         event.type = Common::EVENT_RBUTTONDOWN;
00843 #if defined(SDL_BUTTON_WHEELUP) && defined(SDL_BUTTON_WHEELDOWN)
00844     else if (ev.button.button == SDL_BUTTON_WHEELUP)
00845         event.type = Common::EVENT_WHEELUP;
00846     else if (ev.button.button == SDL_BUTTON_WHEELDOWN)
00847         event.type = Common::EVENT_WHEELDOWN;
00848 #endif
00849 #if defined(SDL_BUTTON_MIDDLE)
00850     else if (ev.button.button == SDL_BUTTON_MIDDLE)
00851         event.type = Common::EVENT_MBUTTONDOWN;
00852 #endif
00853     else
00854         return false;
00855 
00856     // update KbdMouse
00857     _km.x = ev.button.x * MULTIPLIER;
00858     _km.y = ev.button.y * MULTIPLIER;
00859 
00860     return processMouseEvent(event, ev.button.x, ev.button.y);
00861 }
00862 
00863 bool SdlEventSource::handleMouseButtonUp(SDL_Event &ev, Common::Event &event) {
00864     if (ev.button.button == SDL_BUTTON_LEFT)
00865         event.type = Common::EVENT_LBUTTONUP;
00866     else if (ev.button.button == SDL_BUTTON_RIGHT)
00867         event.type = Common::EVENT_RBUTTONUP;
00868 #if defined(SDL_BUTTON_MIDDLE)
00869     else if (ev.button.button == SDL_BUTTON_MIDDLE)
00870         event.type = Common::EVENT_MBUTTONUP;
00871 #endif
00872     else
00873         return false;
00874 
00875     // update KbdMouse
00876     _km.x = ev.button.x * MULTIPLIER;
00877     _km.y = ev.button.y * MULTIPLIER;
00878 
00879     return processMouseEvent(event, ev.button.x, ev.button.y);
00880 }
00881 
00882 bool SdlEventSource::handleSysWMEvent(SDL_Event &ev, Common::Event &event) {
00883     return false;
00884 }
00885 
00886 void SdlEventSource::openJoystick(int joystickIndex) {
00887     if (SDL_NumJoysticks() > joystickIndex) {
00888 #if SDL_VERSION_ATLEAST(2, 0, 0)
00889         if (SDL_IsGameController(joystickIndex)) {
00890             _controller = SDL_GameControllerOpen(joystickIndex);
00891             debug("Using game controller: %s", SDL_GameControllerName(_controller));
00892         } else
00893 #endif
00894         {
00895             _joystick = SDL_JoystickOpen(joystickIndex);
00896             debug("Using joystick: %s",
00897 #if SDL_VERSION_ATLEAST(2, 0, 0)
00898                   SDL_JoystickName(_joystick)
00899 #else
00900                   SDL_JoystickName(joystickIndex)
00901 #endif
00902             );
00903         }
00904     } else {
00905         warning("Invalid joystick: %d", joystickIndex);
00906     }
00907 }
00908 
00909 void SdlEventSource::closeJoystick() {
00910 #if SDL_VERSION_ATLEAST(2, 0, 0)
00911     if (_controller) {
00912         SDL_GameControllerClose(_controller);
00913         _controller = nullptr;
00914     }
00915 #endif
00916     if (_joystick) {
00917         SDL_JoystickClose(_joystick);
00918         _joystick = nullptr;
00919     }
00920 }
00921 
00922 bool SdlEventSource::handleJoyButtonDown(SDL_Event &ev, Common::Event &event) {
00923     if (ev.jbutton.button == JOY_BUT_LMOUSE) {
00924         event.type = Common::EVENT_LBUTTONDOWN;
00925         return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
00926     } else if (ev.jbutton.button == JOY_BUT_RMOUSE) {
00927         event.type = Common::EVENT_RBUTTONDOWN;
00928         return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
00929     } else {
00930         event.type = Common::EVENT_KEYDOWN;
00931         switch (ev.jbutton.button) {
00932         case JOY_BUT_ESCAPE:
00933             event.kbd.keycode = Common::KEYCODE_ESCAPE;
00934             event.kbd.ascii = mapKey(SDLK_ESCAPE, (SDLMod)ev.key.keysym.mod, 0);
00935             break;
00936         case JOY_BUT_PERIOD:
00937             event.kbd.keycode = Common::KEYCODE_PERIOD;
00938             event.kbd.ascii = mapKey(SDLK_PERIOD, (SDLMod)ev.key.keysym.mod, 0);
00939             break;
00940         case JOY_BUT_SPACE:
00941             event.kbd.keycode = Common::KEYCODE_SPACE;
00942             event.kbd.ascii = mapKey(SDLK_SPACE, (SDLMod)ev.key.keysym.mod, 0);
00943             break;
00944         case JOY_BUT_F5:
00945             event.kbd.keycode = Common::KEYCODE_F5;
00946             event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0);
00947             break;
00948 #ifdef ENABLE_VKEYBD
00949         case JOY_BUT_VKEYBOARD: // Toggles virtual keyboard
00950             event.type = Common::EVENT_VIRTUAL_KEYBOARD;
00951             break;
00952 #endif
00953         }
00954         return true;
00955     }
00956 }
00957 
00958 bool SdlEventSource::handleJoyButtonUp(SDL_Event &ev, Common::Event &event) {
00959     if (ev.jbutton.button == JOY_BUT_LMOUSE) {
00960         event.type = Common::EVENT_LBUTTONUP;
00961         return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
00962     } else if (ev.jbutton.button == JOY_BUT_RMOUSE) {
00963         event.type = Common::EVENT_RBUTTONUP;
00964         return processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
00965     } else {
00966         event.type = Common::EVENT_KEYUP;
00967         switch (ev.jbutton.button) {
00968         case JOY_BUT_ESCAPE:
00969             event.kbd.keycode = Common::KEYCODE_ESCAPE;
00970             event.kbd.ascii = mapKey(SDLK_ESCAPE, (SDLMod)ev.key.keysym.mod, 0);
00971             break;
00972         case JOY_BUT_PERIOD:
00973             event.kbd.keycode = Common::KEYCODE_PERIOD;
00974             event.kbd.ascii = mapKey(SDLK_PERIOD, (SDLMod)ev.key.keysym.mod, 0);
00975             break;
00976         case JOY_BUT_SPACE:
00977             event.kbd.keycode = Common::KEYCODE_SPACE;
00978             event.kbd.ascii = mapKey(SDLK_SPACE, (SDLMod)ev.key.keysym.mod, 0);
00979             break;
00980         case JOY_BUT_F5:
00981             event.kbd.keycode = Common::KEYCODE_F5;
00982             event.kbd.ascii = mapKey(SDLK_F5, (SDLMod)ev.key.keysym.mod, 0);
00983             break;
00984 #ifdef ENABLE_VKEYBD
00985         case JOY_BUT_VKEYBOARD: // Toggles virtual keyboard
00986             // Handled in key down
00987             break;
00988 #endif
00989         }
00990         return true;
00991     }
00992 }
00993 
00994 bool SdlEventSource::handleJoyAxisMotion(SDL_Event &ev, Common::Event &event) {
00995     if (ev.jaxis.axis == JOY_XAXIS) {
00996         _km.joy_x = ev.jaxis.value;
00997         return handleAxisToMouseMotion(_km.joy_x, _km.joy_y);
00998     } else if (ev.jaxis.axis == JOY_YAXIS) {
00999         _km.joy_y = ev.jaxis.value;
01000         return handleAxisToMouseMotion(_km.joy_x, _km.joy_y);
01001     }
01002 
01003     return false;
01004 }
01005 
01006 #if SDL_VERSION_ATLEAST(2, 0, 0)
01007 bool SdlEventSource::handleJoystickAdded(const SDL_JoyDeviceEvent &device) {
01008     debug(5, "SdlEventSource: Received joystick added event for index '%d'", device.which);
01009 
01010     int joystick_num = ConfMan.getInt("joystick_num");
01011     if (joystick_num == device.which) {
01012         debug(5, "SdlEventSource: Newly added joystick with index '%d' matches 'joysticky_num', trying to use it", device.which);
01013 
01014         closeJoystick();
01015         openJoystick(joystick_num);
01016     }
01017 
01018     return false;
01019 }
01020 
01021 bool SdlEventSource::handleJoystickRemoved(const SDL_JoyDeviceEvent &device) {
01022     debug(5, "SdlEventSource: Received joystick removed event for instance id '%d'", device.which);
01023 
01024     SDL_Joystick *joystick;
01025     if (_controller) {
01026         joystick = SDL_GameControllerGetJoystick(_controller);
01027     } else {
01028         joystick = _joystick;
01029     }
01030 
01031     if (!joystick) {
01032         return false;
01033     }
01034 
01035     if (SDL_JoystickInstanceID(joystick) == device.which) {
01036         debug(5, "SdlEventSource: Newly removed joystick with instance id '%d' matches currently used joystick, closing current joystick", device.which);
01037 
01038         closeJoystick();
01039     }
01040 
01041     return false;
01042 }
01043 
01044 bool SdlEventSource::handleControllerButton(const SDL_Event &ev, Common::Event &event, bool buttonUp) {
01045     using namespace Common;
01046 
01047     struct ControllerEventMapping {
01048         EventType normalType;
01049         KeyState normalKeystate;
01050         EventType modifierType;
01051         KeyState modifierKeystate;
01052     };
01053 
01054     static const ControllerEventMapping mapping[] = {
01055             // SDL_CONTROLLER_BUTTON_A: Left mouse button
01056             { EVENT_LBUTTONDOWN, KeyState(), EVENT_LBUTTONDOWN, KeyState() },
01057             // SDL_CONTROLLER_BUTTON_B: Right mouse button
01058             { EVENT_RBUTTONDOWN, KeyState(), EVENT_RBUTTONDOWN, KeyState() },
01059             // SDL_CONTROLLER_BUTTON_X: Period (+R_trigger: Space)
01060             { EVENT_KEYDOWN, KeyState(KEYCODE_PERIOD, '.'), EVENT_KEYDOWN, KeyState(KEYCODE_SPACE, ASCII_SPACE) },
01061             // SDL_CONTROLLER_BUTTON_Y: Escape (+R_trigger: Return)
01062             { EVENT_KEYDOWN, KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE), EVENT_KEYDOWN, KeyState(KEYCODE_RETURN, ASCII_RETURN) },
01063             // SDL_CONTROLLER_BUTTON_BACK: Virtual keyboard (+R_trigger: Predictive Input Dialog)
01064 #ifdef ENABLE_VKEYBD
01065             { EVENT_VIRTUAL_KEYBOARD, KeyState(), EVENT_PREDICTIVE_DIALOG, KeyState() },
01066 #else
01067             { EVENT_INVALID, KeyState(), EVENT_PREDICTIVE_DIALOG, KeyState() },
01068 #endif
01069             // SDL_CONTROLLER_BUTTON_GUIDE: Unmapped
01070             { EVENT_INVALID, KeyState(), EVENT_INVALID, KeyState() },
01071             // SDL_CONTROLLER_BUTTON_START: ScummVM in game menu
01072             { EVENT_MAINMENU, KeyState(), EVENT_MAINMENU, KeyState() },
01073             // SDL_CONTROLLER_BUTTON_LEFTSTICK: Unmapped
01074             { EVENT_INVALID, KeyState(), EVENT_INVALID, KeyState() },
01075             // SDL_CONTROLLER_BUTTON_RIGHTSTICK: Unmapped
01076             { EVENT_INVALID, KeyState(), EVENT_INVALID, KeyState() },
01077             // SDL_CONTROLLER_BUTTON_LEFTSHOULDER: Game menu
01078             { EVENT_KEYDOWN, KeyState(KEYCODE_F5, ASCII_F5), EVENT_KEYDOWN, KeyState(KEYCODE_F5, ASCII_F5) },
01079             // SDL_CONTROLLER_BUTTON_RIGHTSHOULDER: Modifier + Shift
01080             { EVENT_KEYDOWN, KeyState(KEYCODE_INVALID, 0, KBD_SHIFT), EVENT_KEYDOWN, KeyState(KEYCODE_INVALID, 0, 0) },
01081             // SDL_CONTROLLER_BUTTON_DPAD_UP: Up (+R_trigger: Up+Right)
01082             { EVENT_KEYDOWN, KeyState(KEYCODE_KP8, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP9, 0) },
01083             // SDL_CONTROLLER_BUTTON_DPAD_DOWN: Down (+R_trigger: Down+Left)
01084             { EVENT_KEYDOWN, KeyState(KEYCODE_KP2, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP1, 0) },
01085             // SDL_CONTROLLER_BUTTON_DPAD_LEFT: Left (+R_trigger: Up+Left)
01086             { EVENT_KEYDOWN, KeyState(KEYCODE_KP4, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP7, 0) },
01087             // SDL_CONTROLLER_BUTTON_DPAD_RIGHT: Right (+R_trigger: Down+Right)
01088             { EVENT_KEYDOWN, KeyState(KEYCODE_KP6, 0), EVENT_KEYDOWN, KeyState(KEYCODE_KP3, 0) }
01089     };
01090 
01091     if (ev.cbutton.button > SDL_CONTROLLER_BUTTON_DPAD_RIGHT) {
01092         warning("Unknown SDL controller button: '%d'", ev.cbutton.button);
01093         return false;
01094     }
01095 
01096     if (!_km.modifier) {
01097         event.type = mapping[ev.cbutton.button].normalType;
01098         event.kbd = mapping[ev.cbutton.button].normalKeystate;
01099     } else {
01100         event.type = mapping[ev.cbutton.button].modifierType;
01101         event.kbd = mapping[ev.cbutton.button].modifierKeystate;
01102     }
01103 
01104     // Setting the mouse speed modifier after filling the event structure above
01105     // ensures that the shift key events are correctly handled
01106     if (ev.cbutton.button == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER) {
01107         // Right shoulder is the modifier button that makes the mouse go slower
01108         // and allows access to an extended layout while pressed.
01109         _km.modifier = !buttonUp;
01110     }
01111 
01112     if (event.type == EVENT_LBUTTONDOWN || event.type == EVENT_RBUTTONDOWN) {
01113         processMouseEvent(event, _km.x / MULTIPLIER, _km.y / MULTIPLIER);
01114     }
01115 
01116     if (buttonUp) {
01117         // The event mapping table is for button down events. If we received a button up event,
01118         // transform the event type to the corresponding up type.
01119         if (event.type == EVENT_KEYDOWN) {
01120             event.type = EVENT_KEYUP;
01121         } else if (event.type == EVENT_LBUTTONDOWN) {
01122             event.type = EVENT_LBUTTONUP;
01123         } else if (event.type == EVENT_RBUTTONDOWN) {
01124             event.type = EVENT_RBUTTONUP;
01125         } else {
01126             // Handled in key down
01127             event.type = EVENT_INVALID;
01128         }
01129     }
01130 
01131     return event.type != EVENT_INVALID;
01132 }
01133 
01134 bool SdlEventSource::handleControllerAxisMotion(const SDL_Event &ev, Common::Event &event) {
01135     if (ev.caxis.axis == SDL_CONTROLLER_AXIS_LEFTX) {
01136         _km.joy_x = ev.caxis.value;
01137         return handleAxisToMouseMotion(_km.joy_x, _km.joy_y);
01138     } else if (ev.caxis.axis == SDL_CONTROLLER_AXIS_LEFTY) {
01139         _km.joy_y = ev.caxis.value;
01140         return handleAxisToMouseMotion(_km.joy_x, _km.joy_y);
01141     }
01142 
01143     return false;
01144 }
01145 #endif
01146 
01147 bool SdlEventSource::handleAxisToMouseMotion(int16 xAxis, int16 yAxis) {
01148 #ifdef JOY_INVERT_Y
01149     yAxis = -yAxis;
01150 #endif
01151 
01152     // conversion factor between keyboard mouse and joy axis value
01153     int vel_to_axis = (1500 / MULTIPLIER);
01154 
01155     // radial and scaled deadzone
01156 
01157     float analogX = (float)xAxis;
01158     float analogY = (float)yAxis;
01159     float deadZone = (float)ConfMan.getInt("joystick_deadzone") * 1000.0f;
01160 
01161     float magnitude = sqrt(analogX * analogX + analogY * analogY);
01162 
01163     if (magnitude >= deadZone) {
01164         _km.x_down_count = 0;
01165         _km.y_down_count = 0;
01166         float scalingFactor = 1.0f / magnitude * (magnitude - deadZone) / (32769.0f - deadZone);
01167         _km.x_vel = (int16)(analogX * scalingFactor * 32768.0f / vel_to_axis);
01168         _km.y_vel = (int16)(analogY * scalingFactor * 32768.0f / vel_to_axis);
01169     } else {
01170         _km.x_vel = 0;
01171         _km.y_vel = 0;
01172     }
01173 
01174     return false;
01175 }
01176 
01177 bool SdlEventSource::remapKey(SDL_Event &ev, Common::Event &event) {
01178     return false;
01179 }
01180 
01181 void SdlEventSource::resetKeyboardEmulation(int16 x_max, int16 y_max) {
01182     _km.x_max = x_max;
01183     _km.y_max = y_max;
01184     _km.delay_time = 12;
01185     _km.last_time = 0;
01186     _km.modifier = false;
01187     _km.joy_x = 0;
01188     _km.joy_y = 0;
01189 }
01190 
01191 void SdlEventSource::fakeWarpMouse(const int x, const int y) {
01192     _queuedFakeMouseMove = true;
01193     _fakeMouseMove.type = Common::EVENT_MOUSEMOVE;
01194     _fakeMouseMove.mouse = Common::Point(x, y);
01195 }
01196 
01197 bool SdlEventSource::handleResizeEvent(Common::Event &event, int w, int h) {
01198     if (_graphicsManager) {
01199         _graphicsManager->notifyResize(w, h);
01200 
01201         // If the screen changed, send an Common::EVENT_SCREEN_CHANGED
01202         int screenID = ((OSystem_SDL *)g_system)->getGraphicsManager()->getScreenChangeID();
01203         if (screenID != _lastScreenID) {
01204             _lastScreenID = screenID;
01205             event.type = Common::EVENT_SCREEN_CHANGED;
01206             return true;
01207         }
01208     }
01209 
01210     return false;
01211 }
01212 
01213 SDLKey SdlEventSource::obtainKeycode(const SDL_keysym keySym) {
01214 #if !SDL_VERSION_ATLEAST(2, 0, 0) && defined(WIN32) && !defined(_WIN32_WCE)
01215     // WORKAROUND: SDL 1.2 on Windows does not use the user configured keyboard layout,
01216     // resulting in "keySym.sym" values to always be those expected for an US keyboard.
01217     // For example, SDL returns SDLK_Q when pressing the 'A' key on an AZERTY keyboard.
01218     // This defeats the purpose of keycodes which is to be able to refer to a key without
01219     // knowing where it is physically located.
01220     // We work around this issue by querying the currently active Windows keyboard layout
01221     // using the scancode provided by SDL.
01222 
01223     if (keySym.sym >= SDLK_0 && keySym.sym <= SDLK_9) {
01224         // The keycode returned by SDL is kept for the number keys.
01225         // Querying the keyboard layout for those would return the base key values
01226         // for AZERTY keyboards, which are not numbers. For example, SDLK_1 would
01227         // map to SDLK_AMPERSAND. This is theoretically correct but practically unhelpful,
01228         // because it makes it impossible to handle key combinations such as "ctrl-1".
01229         return keySym.sym;
01230     }
01231 
01232     int vk = MapVirtualKey(keySym.scancode, MAPVK_VSC_TO_VK);
01233     if (vk) {
01234         int ch = (MapVirtualKey(vk, MAPVK_VK_TO_CHAR) & 0x7FFF);
01235         // The top bit of the result of MapVirtualKey with MAPVK_VSC_TO_VK signals
01236         // a dead key was pressed. In that case we keep the value of the accent alone.
01237         if (ch) {
01238             if (ch >= 'A' && ch <= 'Z') {
01239                 // Windows returns uppercase ASCII whereas SDL expects lowercase
01240                 return (SDLKey)(SDLK_a + (ch - 'A'));
01241             } else {
01242                 return (SDLKey)ch;
01243             }
01244         }
01245     }
01246 #endif
01247 
01248     return keySym.sym;
01249 }
01250 
01251 uint32 SdlEventSource::obtainUnicode(const SDL_keysym keySym) {
01252 #if SDL_VERSION_ATLEAST(2, 0, 0)
01253     SDL_Event events[2];
01254 
01255     // Update the event queue here to give SDL a chance to insert TEXTINPUT
01256     // events for KEYDOWN events. Otherwise we have a high chance that on
01257     // Windows the TEXTINPUT event is not in the event queue at this point.
01258     // In this case we will get two events with ascii values due to mapKey
01259     // and dispatchSDLEvent. This results in nasty double input of characters
01260     // in the GUI.
01261     //
01262     // FIXME: This is all a bit fragile because in mapKey we derive the ascii
01263     // value from the key code if no unicode value is given. This is legacy
01264     // behavior and should be removed anyway. If that is removed, we might not
01265     // even need to do this peeking here but instead can rely on the
01266     // SDL_TEXTINPUT case in dispatchSDLEvent to introduce keydown/keyup with
01267     // proper ASCII values (but with KEYCODE_INVALID as keycode).
01268     SDL_PumpEvents();
01269 
01270     // In SDL2, the unicode field has been removed from the keysym struct.
01271     // Instead a SDL_TEXTINPUT event is generated on key combinations that
01272     // generates unicode.
01273     // Here we peek into the event queue for the event to see if it exists.
01274     int n = SDL_PeepEvents(events, 2, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_TEXTINPUT);
01275     // Make sure that the TEXTINPUT event belongs to this KEYDOWN
01276     // event and not another pending one.
01277     if ((n > 0 && events[0].type == SDL_TEXTINPUT)
01278         || (n > 1 && events[0].type != SDL_KEYDOWN && events[1].type == SDL_TEXTINPUT)) {
01279         // Remove the text input event we associate with the key press. This
01280         // makes sure we never get any SDL_TEXTINPUT events which do "belong"
01281         // to SDL_KEYDOWN events.
01282         n = SDL_PeepEvents(events, 1, SDL_GETEVENT, SDL_TEXTINPUT, SDL_TEXTINPUT);
01283         // This is basically a paranoia safety check because we know there
01284         // must be a text input event in the queue.
01285         if (n > 0) {
01286             return convUTF8ToUTF32(events[0].text.text);
01287         } else {
01288             return 0;
01289         }
01290     } else {
01291         return 0;
01292     }
01293 #else
01294     return keySym.unicode;
01295 #endif
01296 }
01297 
01298 #endif


Generated on Sat Apr 4 2020 05:00:25 for ResidualVM by doxygen 1.7.1
curved edge   curved edge