Generalize VControl to work with SDL1 and SDL2.

SDL2's keycodes do not form a contiguous range the way SDL1's do,
so we need to perform separate chaining of bindings.
This commit is contained in:
Michael Martin
2019-08-11 20:14:11 -07:00
parent 00365dd5b7
commit 40c60bc08a
3 changed files with 94 additions and 76 deletions
+16 -1
View File
@@ -109,6 +109,7 @@ static keyname keynames[] = {
{"y", SDLK_y},
{"z", SDLK_z},
{"Delete", SDLK_DELETE},
#if SDL_MAJOR_VERSION == 1
{"Keypad-0", SDLK_KP0},
{"Keypad-1", SDLK_KP1},
{"Keypad-2", SDLK_KP2},
@@ -119,6 +120,18 @@ static keyname keynames[] = {
{"Keypad-7", SDLK_KP7},
{"Keypad-8", SDLK_KP8},
{"Keypad-9", SDLK_KP9},
#else
{"Keypad-0", SDLK_KP_0},
{"Keypad-1", SDLK_KP_1},
{"Keypad-2", SDLK_KP_2},
{"Keypad-3", SDLK_KP_3},
{"Keypad-4", SDLK_KP_4},
{"Keypad-5", SDLK_KP_5},
{"Keypad-6", SDLK_KP_6},
{"Keypad-7", SDLK_KP_7},
{"Keypad-8", SDLK_KP_8},
{"Keypad-9", SDLK_KP_9},
#endif
{"Keypad-.", SDLK_KP_PERIOD},
{"Keypad-/", SDLK_KP_DIVIDE},
{"Keypad-*", SDLK_KP_MULTIPLY},
@@ -156,6 +169,7 @@ static keyname keynames[] = {
{"LeftControl", SDLK_LCTRL},
{"RightAlt", SDLK_RALT},
{"LeftAlt", SDLK_LALT},
#if SDL_MAJOR_VERSION == 1
{"RightMeta", SDLK_RMETA},
{"LeftMeta", SDLK_LMETA},
{"RightSuper", SDLK_RSUPER},
@@ -177,7 +191,8 @@ static keyname keynames[] = {
{"App4", SDLK_APP4},
{"App5", SDLK_APP5},
{"App6", SDLK_APP6},
#endif
#endif /* _WIN32_WCE */
#endif /* SDL_MAJOR_VERSION == 1 */
{"Unknown", 0}};
/* Last element must have code zero */
+66 -69
View File
@@ -28,8 +28,15 @@
/* How many binding slots are allocated at once. */
#define POOL_CHUNK_SIZE 64
/* Total number of key input buckets. SDL1 keys are a simple enum,
* but SDL2 scatters key symbols through the entire 32-bit space,
* so we do not rely on being able to declare an array with one
* entry per key. */
#define KEYBOARD_INPUT_BUCKETS 512
typedef struct vcontrol_keybinding {
int *target;
sdl_key_t keycode;
struct vcontrol_keypool *parent;
struct vcontrol_keybinding *next;
} keybinding;
@@ -67,8 +74,7 @@ static joystick *joysticks;
#endif /* HAVE_JOYSTICK */
static unsigned int joycount;
static unsigned int num_sdl_keys = 0;
static keybinding **bindings = NULL;
static keybinding *bindings[KEYBOARD_INPUT_BUCKETS];
static keypool *pool;
@@ -88,6 +94,7 @@ allocate_key_chunk (void)
for (i = 0; i < POOL_CHUNK_SIZE; i++)
{
x->pool[i].target = NULL;
x->pool[i].keycode = SDLK_UNKNOWN;
x->pool[i].next = NULL;
x->pool[i].parent = x;
}
@@ -127,7 +134,11 @@ create_joystick (int index)
{
joystick *x = &joysticks[index];
int j;
#if SDL_MAJOR_VERSION == 1
log_add (log_Info, "VControl opened joystick: %s", SDL_JoystickName (index));
#else
log_add (log_Info, "VControl opened joystick: %s", SDL_JoystickName (stick));
#endif
axes = SDL_JoystickNumAxes (stick);
buttons = SDL_JoystickNumButtons (stick);
hats = SDL_JoystickNumHats (stick);
@@ -185,9 +196,7 @@ key_init (void)
{
unsigned int i;
pool = allocate_key_chunk ();
(void)SDL_GetKeyState (&num_sdl_keys);
bindings = (keybinding **) HMalloc (sizeof (keybinding *) * num_sdl_keys);
for (i = 0; i < num_sdl_keys; i++)
for (i = 0; i < KEYBOARD_INPUT_BUCKETS; i++)
bindings[i] = NULL;
#ifdef HAVE_JOYSTICK
@@ -221,10 +230,8 @@ key_uninit (void)
{
unsigned int i;
free_key_pool (pool);
for (i = 0; i < num_sdl_keys; i++)
for (i = 0; i < KEYBOARD_INPUT_BUCKETS; i++)
bindings[i] = NULL;
HFree (bindings);
bindings = NULL;
pool = NULL;
#ifdef HAVE_JOYSTICK
@@ -268,7 +275,7 @@ VControl_SetJoyThreshold (int port, int threshold)
static void
add_binding (keybinding **newptr, int *target)
add_binding (keybinding **newptr, int *target, sdl_key_t keycode)
{
keybinding *newbinding;
keypool *searchbase;
@@ -279,7 +286,7 @@ add_binding (keybinding **newptr, int *target)
* bound this symbol to this target. If we have, return.*/
while (*newptr != NULL)
{
if ((*newptr)->target == target)
if (((*newptr)->target == target) && ((*newptr)->keycode == keycode))
{
return;
}
@@ -321,24 +328,26 @@ add_binding (keybinding **newptr, int *target)
}
newbinding->target = target;
newbinding->keycode = keycode;
newbinding->next = NULL;
*newptr = newbinding;
searchbase->remaining--;
}
static void
remove_binding (keybinding **ptr, int *target)
remove_binding (keybinding **ptr, int *target, sdl_key_t keycode)
{
if (!(*ptr))
{
/* Nothing bound to symbol; return. */
return;
}
else if ((*ptr)->target == target)
else if (((*ptr)->target == target) && ((*ptr)->keycode == keycode))
{
keybinding *todel = *ptr;
*ptr = todel->next;
todel->target = NULL;
todel->keycode = SDLK_UNKNOWN;
todel->next = NULL;
todel->parent->remaining++;
}
@@ -352,6 +361,7 @@ remove_binding (keybinding **ptr, int *target)
keybinding *todel = prev->next;
prev->next = todel->next;
todel->target = NULL;
todel->keycode = SDLK_UNKNOWN;
todel->next = NULL;
todel->parent->remaining++;
}
@@ -361,22 +371,25 @@ remove_binding (keybinding **ptr, int *target)
}
static void
activate (keybinding *i)
activate (keybinding *i, sdl_key_t keycode)
{
while (i != NULL)
{
if (i->keycode == keycode)
{
*(i->target) = (*(i->target)+1) | VCONTROL_STARTBIT;
}
i = i->next;
}
}
static void
deactivate (keybinding *i)
deactivate (keybinding *i, sdl_key_t keycode)
{
while (i != NULL)
{
int v = *(i->target) & VCONTROL_MASK;
if (v > 0)
if ((i->keycode == keycode) && (v > 0))
{
*(i->target) = (v-1) | (*(i->target) & VCONTROL_STARTBIT);
}
@@ -487,24 +500,16 @@ VControl_RemoveGestureBinding (VCONTROL_GESTURE *g, int *target)
}
int
VControl_AddKeyBinding (SDLKey symbol, int *target)
VControl_AddKeyBinding (sdl_key_t symbol, int *target)
{
if ((unsigned int) symbol >= num_sdl_keys) {
log_add (log_Warning, "VControl: Illegal key index %d", symbol);
return -1;
}
add_binding(&bindings[symbol], target);
add_binding(&bindings[symbol % KEYBOARD_INPUT_BUCKETS], target, symbol);
return 0;
}
void
VControl_RemoveKeyBinding (SDLKey symbol, int *target)
VControl_RemoveKeyBinding (sdl_key_t symbol, int *target)
{
if ((unsigned int) symbol >= num_sdl_keys) {
log_add (log_Warning, "VControl: Illegal key index %d", symbol);
return;
}
remove_binding (&bindings[symbol], target);
remove_binding (&bindings[symbol % KEYBOARD_INPUT_BUCKETS], target, symbol);
}
int
@@ -520,11 +525,11 @@ VControl_AddJoyAxisBinding (int port, int axis, int polarity, int *target)
{
if (polarity < 0)
{
add_binding(&joysticks[port].axes[axis].neg, target);
add_binding(&joysticks[port].axes[axis].neg, target, SDLK_UNKNOWN);
}
else if (polarity > 0)
{
add_binding(&joysticks[port].axes[axis].pos, target);
add_binding(&joysticks[port].axes[axis].pos, target, SDLK_UNKNOWN);
}
else
{
@@ -565,11 +570,11 @@ VControl_RemoveJoyAxisBinding (int port, int axis, int polarity, int *target)
{
if (polarity < 0)
{
remove_binding(&joysticks[port].axes[axis].neg, target);
remove_binding(&joysticks[port].axes[axis].neg, target, SDLK_UNKNOWN);
}
else if (polarity > 0)
{
remove_binding(&joysticks[port].axes[axis].pos, target);
remove_binding(&joysticks[port].axes[axis].pos, target, SDLK_UNKNOWN);
}
else
{
@@ -604,7 +609,7 @@ VControl_AddJoyButtonBinding (int port, int button, int *target)
create_joystick (port);
if ((button >= 0) && (button < j->numbuttons))
{
add_binding(&joysticks[port].buttons[button], target);
add_binding(&joysticks[port].buttons[button], target, SDLK_UNKNOWN);
return 0;
}
else
@@ -636,7 +641,7 @@ VControl_RemoveJoyButtonBinding (int port, int button, int *target)
create_joystick (port);
if ((button >= 0) && (button < j->numbuttons))
{
remove_binding (&joysticks[port].buttons[button], target);
remove_binding (&joysticks[port].buttons[button], target, SDLK_UNKNOWN);
}
else
{
@@ -667,19 +672,19 @@ VControl_AddJoyHatBinding (int port, int which, Uint8 dir, int *target)
{
if (dir == SDL_HAT_LEFT)
{
add_binding(&joysticks[port].hats[which].left, target);
add_binding(&joysticks[port].hats[which].left, target, SDLK_UNKNOWN);
}
else if (dir == SDL_HAT_RIGHT)
{
add_binding(&joysticks[port].hats[which].right, target);
add_binding(&joysticks[port].hats[which].right, target, SDLK_UNKNOWN);
}
else if (dir == SDL_HAT_UP)
{
add_binding(&joysticks[port].hats[which].up, target);
add_binding(&joysticks[port].hats[which].up, target, SDLK_UNKNOWN);
}
else if (dir == SDL_HAT_DOWN)
{
add_binding(&joysticks[port].hats[which].down, target);
add_binding(&joysticks[port].hats[which].down, target, SDLK_UNKNOWN);
}
else
{
@@ -720,19 +725,19 @@ VControl_RemoveJoyHatBinding (int port, int which, Uint8 dir, int *target)
{
if (dir == SDL_HAT_LEFT)
{
remove_binding(&joysticks[port].hats[which].left, target);
remove_binding(&joysticks[port].hats[which].left, target, SDLK_UNKNOWN);
}
else if (dir == SDL_HAT_RIGHT)
{
remove_binding(&joysticks[port].hats[which].right, target);
remove_binding(&joysticks[port].hats[which].right, target, SDLK_UNKNOWN);
}
else if (dir == SDL_HAT_UP)
{
remove_binding(&joysticks[port].hats[which].up, target);
remove_binding(&joysticks[port].hats[which].up, target, SDLK_UNKNOWN);
}
else if (dir == SDL_HAT_DOWN)
{
remove_binding(&joysticks[port].hats[which].down, target);
remove_binding(&joysticks[port].hats[which].down, target, SDLK_UNKNOWN);
}
else
{
@@ -764,23 +769,15 @@ VControl_RemoveAllBindings (void)
}
void
VControl_ProcessKeyDown (SDLKey symbol)
VControl_ProcessKeyDown (sdl_key_t symbol)
{
if (symbol >= num_sdl_keys) {
log_add (log_Warning, "VControl: Got unknown key index %d", symbol);
return;
}
activate (bindings[symbol]);
activate (bindings[symbol % KEYBOARD_INPUT_BUCKETS], symbol);
}
void
VControl_ProcessKeyUp (SDLKey symbol)
VControl_ProcessKeyUp (sdl_key_t symbol)
{
if (symbol >= num_sdl_keys)
return;
deactivate (bindings[symbol]);
deactivate (bindings[symbol % KEYBOARD_INPUT_BUCKETS], symbol);
}
void
@@ -789,7 +786,7 @@ VControl_ProcessJoyButtonDown (int port, int button)
#ifdef HAVE_JOYSTICK
if (!joysticks[port].stick)
return;
activate (joysticks[port].buttons[button]);
activate (joysticks[port].buttons[button], SDLK_UNKNOWN);
#else
(void) port;
(void) button;
@@ -802,7 +799,7 @@ VControl_ProcessJoyButtonUp (int port, int button)
#ifdef HAVE_JOYSTICK
if (!joysticks[port].stick)
return;
deactivate (joysticks[port].buttons[button]);
deactivate (joysticks[port].buttons[button], SDLK_UNKNOWN);
#else
(void) port;
(void) button;
@@ -823,10 +820,10 @@ VControl_ProcessJoyAxis (int port, int axis, int value)
{
if (joysticks[port].axes[axis].polarity == -1)
{
deactivate (joysticks[port].axes[axis].neg);
deactivate (joysticks[port].axes[axis].neg, SDLK_UNKNOWN);
}
joysticks[port].axes[axis].polarity = 1;
activate (joysticks[port].axes[axis].pos);
activate (joysticks[port].axes[axis].pos, SDLK_UNKNOWN);
}
}
else if (value < -t)
@@ -835,21 +832,21 @@ VControl_ProcessJoyAxis (int port, int axis, int value)
{
if (joysticks[port].axes[axis].polarity == 1)
{
deactivate (joysticks[port].axes[axis].pos);
deactivate (joysticks[port].axes[axis].pos, SDLK_UNKNOWN);
}
joysticks[port].axes[axis].polarity = -1;
activate (joysticks[port].axes[axis].neg);
activate (joysticks[port].axes[axis].neg, SDLK_UNKNOWN);
}
}
else
{
if (joysticks[port].axes[axis].polarity == -1)
{
deactivate (joysticks[port].axes[axis].neg);
deactivate (joysticks[port].axes[axis].neg, SDLK_UNKNOWN);
}
else if (joysticks[port].axes[axis].polarity == 1)
{
deactivate (joysticks[port].axes[axis].pos);
deactivate (joysticks[port].axes[axis].pos, SDLK_UNKNOWN);
}
joysticks[port].axes[axis].polarity = 0;
}
@@ -869,21 +866,21 @@ VControl_ProcessJoyHat (int port, int which, Uint8 value)
return;
old = joysticks[port].hats[which].last;
if (!(old & SDL_HAT_LEFT) && (value & SDL_HAT_LEFT))
activate (joysticks[port].hats[which].left);
activate (joysticks[port].hats[which].left, SDLK_UNKNOWN);
if (!(old & SDL_HAT_RIGHT) && (value & SDL_HAT_RIGHT))
activate (joysticks[port].hats[which].right);
activate (joysticks[port].hats[which].right, SDLK_UNKNOWN);
if (!(old & SDL_HAT_UP) && (value & SDL_HAT_UP))
activate (joysticks[port].hats[which].up);
activate (joysticks[port].hats[which].up, SDLK_UNKNOWN);
if (!(old & SDL_HAT_DOWN) && (value & SDL_HAT_DOWN))
activate (joysticks[port].hats[which].down);
activate (joysticks[port].hats[which].down, SDLK_UNKNOWN);
if ((old & SDL_HAT_LEFT) && !(value & SDL_HAT_LEFT))
deactivate (joysticks[port].hats[which].left);
deactivate (joysticks[port].hats[which].left, SDLK_UNKNOWN);
if ((old & SDL_HAT_RIGHT) && !(value & SDL_HAT_RIGHT))
deactivate (joysticks[port].hats[which].right);
deactivate (joysticks[port].hats[which].right, SDLK_UNKNOWN);
if ((old & SDL_HAT_UP) && !(value & SDL_HAT_UP))
deactivate (joysticks[port].hats[which].up);
deactivate (joysticks[port].hats[which].up, SDLK_UNKNOWN);
if ((old & SDL_HAT_DOWN) && !(value & SDL_HAT_DOWN))
deactivate (joysticks[port].hats[which].down);
deactivate (joysticks[port].hats[which].down, SDLK_UNKNOWN);
joysticks[port].hats[which].last = value;
#else
(void) port;
+11 -5
View File
@@ -20,6 +20,12 @@
#include "port.h"
#include SDL_INCLUDE(SDL.h)
#if SDL_MAJOR_VERSION == 1
typedef SDLKey sdl_key_t;
#else
typedef SDL_Keycode sdl_key_t;
#endif
/* Initialization routines */
void VControl_Init (void);
void VControl_Uninit (void);
@@ -39,7 +45,7 @@ typedef enum {
typedef struct {
VCONTROL_GESTURE_TYPE type;
union {
SDLKey key;
sdl_key_t key;
struct { int port, index, polarity; } axis;
struct { int port, index; } button;
struct { int port, index; Uint8 dir; } hat;
@@ -50,8 +56,8 @@ typedef struct {
int VControl_AddGestureBinding (VCONTROL_GESTURE *g, int *target);
void VControl_RemoveGestureBinding (VCONTROL_GESTURE *g, int *target);
int VControl_AddKeyBinding (SDLKey symbol, int *target);
void VControl_RemoveKeyBinding (SDLKey symbol, int *target);
int VControl_AddKeyBinding (sdl_key_t symbol, int *target);
void VControl_RemoveKeyBinding (sdl_key_t symbol, int *target);
int VControl_AddJoyAxisBinding (int port, int axis, int polarity, int *target);
void VControl_RemoveJoyAxisBinding (int port, int axis, int polarity, int *target);
int VControl_SetJoyThreshold (int port, int threshold);
@@ -69,8 +75,8 @@ void VControl_BeginFrame (void);
* fabricating an SDL_Event.
*/
void VControl_HandleEvent (const SDL_Event *e);
void VControl_ProcessKeyDown (SDLKey symbol);
void VControl_ProcessKeyUp (SDLKey symbol);
void VControl_ProcessKeyDown (sdl_key_t symbol);
void VControl_ProcessKeyUp (sdl_key_t symbol);
void VControl_ProcessJoyButtonDown (int port, int button);
void VControl_ProcessJoyButtonUp (int port, int button);
void VControl_ProcessJoyAxis (int port, int axis, int value);