From 7777b9edde60902d6d6f590eb827e723f1dd59fc Mon Sep 17 00:00:00 2001 From: Paul Cercueil Date: Sun, 23 Feb 2014 17:00:12 +0100 Subject: [PATCH] Added key repeat on analog sticks and hats --- src/gmenu2x.cpp | 6 +-- src/gmenu2x.h | 2 - src/inputmanager.cpp | 92 ++++++++++++++++++++++++++++++++++++-------- src/inputmanager.h | 24 ++++++++---- 4 files changed, 93 insertions(+), 31 deletions(-) diff --git a/src/gmenu2x.cpp b/src/gmenu2x.cpp index 846e80b..b75ed5e 100644 --- a/src/gmenu2x.cpp +++ b/src/gmenu2x.cpp @@ -257,7 +257,7 @@ GMenu2X::GMenu2X() if (confInt["backlightTimeout"] > 0) PowerSaver::getInstance()->setScreenTimeout( confInt["backlightTimeout"] ); - setInputSpeed(); + SDL_EnableKeyRepeat(INPUT_KEY_REPEAT_DELAY, INPUT_KEY_REPEAT_RATE); #ifdef ENABLE_CPUFREQ setClock(confInt["menuClock"]); #endif @@ -1038,10 +1038,6 @@ typedef struct { unsigned short remocon; } MMSP2ADC; -void GMenu2X::setInputSpeed() { - SDL_EnableKeyRepeat(250, 150); -} - #ifdef ENABLE_CPUFREQ void GMenu2X::setClock(unsigned mhz) { mhz = constrain(mhz, cpuFreqMin, confInt["maxClock"]); diff --git a/src/gmenu2x.h b/src/gmenu2x.h index 50a8e95..ab4aea7 100644 --- a/src/gmenu2x.h +++ b/src/gmenu2x.h @@ -182,8 +182,6 @@ public: unsigned getDefaultAppClock() { return cpuFreqAppDefault; } #endif - void setInputSpeed(); - /** * Requests that the given application be launched. * The launch won't happen immediately; it will happen after control diff --git a/src/inputmanager.cpp b/src/inputmanager.cpp index 8994847..65b96d2 100644 --- a/src/inputmanager.cpp +++ b/src/inputmanager.cpp @@ -51,6 +51,7 @@ InputManager::InputManager() for (i = 0; i < SDL_NumJoysticks(); i++) { struct Joystick joystick = { SDL_JoystickOpen(i), false, false, false, false, + SDL_HAT_CENTERED, nullptr, }; joysticks.push_back(joystick); } @@ -151,22 +152,28 @@ bool InputManager::getButton(Button *button, bool wait) { source = KEYBOARD; break; #ifndef SDL_JOYSTICK_DISABLED - case SDL_JOYHATMOTION: - switch (event.jhat.value) { - case SDL_HAT_CENTERED: - return false; - case SDL_HAT_UP: - *button = UP; - break; - case SDL_HAT_DOWN: - *button = DOWN; - break; - case SDL_HAT_LEFT: - *button = LEFT; - break; - case SDL_HAT_RIGHT: - *button = RIGHT; - break; + case SDL_JOYHATMOTION: { + Joystick *joystick = &joysticks[event.jaxis.which]; + joystick->hatState = event.jhat.value; + + switch (event.jhat.value) { + case SDL_HAT_CENTERED: + stopTimer(joystick); + return false; + case SDL_HAT_UP: + *button = UP; + break; + case SDL_HAT_DOWN: + *button = DOWN; + break; + case SDL_HAT_LEFT: + *button = LEFT; + break; + case SDL_HAT_RIGHT: + *button = RIGHT; + break; + } + startTimer(joystick); } case SDL_JOYBUTTONDOWN: source = JOYSTICK; @@ -179,7 +186,8 @@ bool InputManager::getButton(Button *button, bool wait) { if (axis > 1) return false; - bool *axisState = joysticks[event.jaxis.which].axisState[axis]; + Joystick *joystick = &joysticks[event.jaxis.which]; + bool *axisState = joystick->axisState[axis]; if (event.jaxis.value < -20000) { if (axisState[AXIS_STATE_NEGATIVE]) @@ -194,9 +202,17 @@ bool InputManager::getButton(Button *button, bool wait) { axisState[AXIS_STATE_POSITIVE] = true; *button = axis ? DOWN : RIGHT; } else { + bool *otherAxisState = joystick->axisState[!axis]; + if (!otherAxisState[AXIS_STATE_NEGATIVE] && + !otherAxisState[AXIS_STATE_POSITIVE] && ( + axisState[AXIS_STATE_NEGATIVE] || + axisState[AXIS_STATE_POSITIVE])) + stopTimer(joystick); + axisState[0] = axisState[1] = false; return false; } + startTimer(joystick); break; } #endif @@ -259,3 +275,45 @@ bool InputManager::getButton(Button *button, bool wait) { return true; } + +Uint32 keyRepeatCallback(Uint32 timeout __attribute__((unused)), void *d) +{ + struct Joystick *joystick = (struct Joystick *) d; + Uint8 hatState = joystick->hatState; + + if (joystick->axisState[1][AXIS_STATE_NEGATIVE]) + hatState |= SDL_HAT_UP; + else if (joystick->axisState[1][AXIS_STATE_POSITIVE]) + hatState |= SDL_HAT_DOWN; + if (joystick->axisState[0][AXIS_STATE_NEGATIVE]) + hatState |= SDL_HAT_LEFT; + else if (joystick->axisState[0][AXIS_STATE_POSITIVE]) + hatState |= SDL_HAT_RIGHT; + + SDL_JoyHatEvent e = { + .type = SDL_JOYHATMOTION, + .which = (Uint8) SDL_JoystickIndex(joystick->joystick), + .hat = 0, + .value = hatState, + }; + SDL_PushEvent((SDL_Event *) &e); + + return INPUT_KEY_REPEAT_RATE; +} + +void InputManager::startTimer(Joystick *joystick) +{ + if (joystick->timer) + return; + + joystick->timer = SDL_AddTimer(INPUT_KEY_REPEAT_DELAY, + keyRepeatCallback, joystick); +} + +void InputManager::stopTimer(Joystick *joystick) +{ + if (joystick->timer) { + SDL_RemoveTimer(joystick->timer); + joystick->timer = nullptr; + } +} diff --git a/src/inputmanager.h b/src/inputmanager.h index d2cc649..317f79a 100644 --- a/src/inputmanager.h +++ b/src/inputmanager.h @@ -25,6 +25,9 @@ #include #include +#define INPUT_KEY_REPEAT_DELAY 250 +#define INPUT_KEY_REPEAT_RATE 150 + class Menu; enum EventCode { @@ -34,6 +37,17 @@ enum EventCode { REPAINT_MENU, }; +#ifndef SDL_JOYSTICK_DISABLED +#define AXIS_STATE_POSITIVE 0 +#define AXIS_STATE_NEGATIVE 1 +struct Joystick { + SDL_Joystick *joystick; + bool axisState[2][2]; + Uint8 hatState; + SDL_TimerID timer; +}; +#endif + class InputManager { public: enum Button { @@ -66,14 +80,10 @@ private: ButtonMapEntry buttonMap[BUTTON_TYPE_SIZE]; #ifndef SDL_JOYSTICK_DISABLED -#define AXIS_STATE_POSITIVE 0 -#define AXIS_STATE_NEGATIVE 1 - struct Joystick { - SDL_Joystick *joystick; - bool axisState[2][2]; - }; - std::vector joysticks; + + void startTimer(Joystick *joystick); + void stopTimer(Joystick *joystick); #endif };