#define KEYBITS_WORD_BITS (sizeof(keybits_t) * 8)
struct in_sdl_state {
+ const in_drv_t *drv;
SDL_Joystick *joy;
int joy_id;
int axis_keydown[2];
keybits_t keystate[SDLK_LAST / KEYBITS_WORD_BITS + 1];
+ // emulator keys should always be processed immediately lest one is lost
+ keybits_t emu_keys[SDLK_LAST / KEYBITS_WORD_BITS + 1];
};
static void (*ext_event_handler)(void *event);
[SDLK_8] = "8",
[SDLK_9] = "9",
[SDLK_COLON] = ":",
- [SDLK_SEMICOLON] = ",",
+ [SDLK_SEMICOLON] = ";",
[SDLK_LESS] = "<",
[SDLK_EQUALS] = "=",
[SDLK_GREATER] = ">",
[SDLK_DOWN] = "down",
[SDLK_RIGHT] = "right",
[SDLK_LEFT] = "left",
- [SDLK_DOWN] = "down",
[SDLK_INSERT] = "insert",
[SDLK_HOME] = "home",
[SDLK_END] = "end",
[SDLK_COMPOSE] = "compose",
};
-static void in_sdl_probe(void)
+static void in_sdl_probe(const in_drv_t *drv)
{
+ const struct in_pdata *pdata = drv->pdata;
+ const char * const * key_names = in_sdl_keys;
struct in_sdl_state *state;
SDL_Joystick *joy;
int i, joycount;
char name[256];
+ if (pdata->key_names)
+ key_names = pdata->key_names;
+
state = calloc(1, sizeof(*state));
if (state == NULL) {
fprintf(stderr, "in_sdl: OOM\n");
return;
}
+ state->drv = drv;
in_register(IN_SDL_PREFIX "keys", -1, state, SDLK_LAST,
- in_sdl_keys, 0);
+ key_names, 0);
/* joysticks go here too */
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
}
state->joy = joy;
state->joy_id = i;
+ state->drv = drv;
snprintf(name, sizeof(name), IN_SDL_PREFIX "%s", SDL_JoystickName(i));
- in_register(name, -1, state, SDLK_LAST, in_sdl_keys, 0);
+ in_register(name, -1, state, SDLK_LAST, key_names, 0);
}
if (joycount > 0)
}
static const char * const *
-in_sdl_get_key_names(int *count)
+in_sdl_get_key_names(const in_drv_t *drv, int *count)
{
+ const struct in_pdata *pdata = drv->pdata;
*count = SDLK_LAST;
+
+ if (pdata->key_names)
+ return pdata->key_names;
return in_sdl_keys;
}
*ks_word &= ~mask;
}
+static int get_keystate(keybits_t *keystate, int sym)
+{
+ keybits_t *ks_word, mask;
+
+ mask = 1;
+ mask <<= sym & (KEYBITS_WORD_BITS - 1);
+ ks_word = keystate + sym / KEYBITS_WORD_BITS;
+ return !!(*ks_word & mask);
+}
+
static int handle_event(struct in_sdl_state *state, SDL_Event *event,
- int *kc_out, int *down_out)
+ int *kc_out, int *down_out, int *emu_out)
{
+ int emu;
+
if (event->type != SDL_KEYDOWN && event->type != SDL_KEYUP)
return -1;
+ emu = get_keystate(state->emu_keys, event->key.keysym.sym);
update_keystate(state->keystate, event->key.keysym.sym,
event->type == SDL_KEYDOWN);
if (kc_out != NULL)
*kc_out = event->key.keysym.sym;
if (down_out != NULL)
*down_out = event->type == SDL_KEYDOWN;
+ if (emu_out != 0)
+ *emu_out = emu;
return 1;
}
static int handle_joy_event(struct in_sdl_state *state, SDL_Event *event,
- int *kc_out, int *down_out)
+ int *kc_out, int *down_out, int *emu_out)
{
- int kc = -1, down = 0, ret = 0;
+ int kc = -1, down = 0, emu = 0, ret = 0;
- /* FIXME: should ckeck .which */
/* TODO: remaining axis */
switch (event->type) {
case SDL_JOYAXISMOTION:
+ if (event->jaxis.which != state->joy_id)
+ return -2;
if (event->jaxis.axis > 1)
break;
if (-16384 <= event->jaxis.value && event->jaxis.value <= 16384) {
}
else if (event->jaxis.value < -16384) {
kc = state->axis_keydown[event->jaxis.axis];
- if (kc)
+ if (kc) {
+ emu |= get_keystate(state->emu_keys, kc);
update_keystate(state->keystate, kc, 0);
+ }
kc = event->jaxis.axis ? SDLK_UP : SDLK_LEFT;
state->axis_keydown[event->jaxis.axis] = kc;
down = 1;
}
else if (event->jaxis.value > 16384) {
kc = state->axis_keydown[event->jaxis.axis];
- if (kc)
+ if (kc) {
+ emu |= get_keystate(state->emu_keys, kc);
update_keystate(state->keystate, kc, 0);
+ }
kc = event->jaxis.axis ? SDLK_DOWN : SDLK_RIGHT;
state->axis_keydown[event->jaxis.axis] = kc;
down = 1;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
+ if (event->jbutton.which != state->joy_id)
+ return -2;
kc = (int)event->jbutton.button + SDLK_WORLD_0;
down = event->jbutton.state == SDL_PRESSED;
ret = 1;
return -1;
}
- if (ret)
+ if (ret) {
+ emu |= get_keystate(state->emu_keys, kc);
update_keystate(state->keystate, kc, down);
+ }
if (kc_out != NULL)
*kc_out = kc;
if (down_out != NULL)
*down_out = down;
+ if (emu_out != 0)
+ *emu_out = emu;
return ret;
}
{
SDL_Event events[4];
Uint32 mask = state->joy ? JOY_EVENTS : (SDL_ALLEVENTS & ~JOY_EVENTS);
- int count, maxcount;
+ int count, maxcount, is_emukey;
int i, ret, retval = 0;
+ int num_events, num_peeped_events;
+ SDL_Event *event;
maxcount = (one_kc != NULL) ? 1 : sizeof(events) / sizeof(events[0]);
SDL_PumpEvents();
- while (1) {
+
+ num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, mask);
+
+ for (num_peeped_events = 0; num_peeped_events < num_events; num_peeped_events += count) {
count = SDL_PeepEvents(events, maxcount, SDL_GETEVENT, mask);
if (count <= 0)
break;
for (i = 0; i < count; i++) {
- if (state->joy)
+ event = &events[i];
+ if (state->joy) {
ret = handle_joy_event(state,
- &events[i], one_kc, one_down);
- else
+ event, one_kc, one_down, &is_emukey);
+ } else {
ret = handle_event(state,
- &events[i], one_kc, one_down);
- if (ret == -1) {
- if (ext_event_handler != NULL)
- ext_event_handler(&events[i]);
+ event, one_kc, one_down, &is_emukey);
+ }
+ if (ret < 0) {
+ switch (ret) {
+ case -2:
+ SDL_PushEvent(event);
+ break;
+ default:
+ if (ext_event_handler != NULL)
+ ext_event_handler(event);
+ break;
+ }
continue;
}
retval |= ret;
- if (one_kc != NULL && ret)
+ if ((is_emukey || one_kc != NULL) && ret)
+ {
+ // don't lose events other devices might want to handle
+ if (++i < count)
+ SDL_PeepEvents(events+i, count-i, SDL_ADDEVENT, mask);
goto out;
+ }
}
}
return ret_kc;
}
-struct menu_keymap {
- short key;
- short pbtn;
-};
-
-static const struct menu_keymap key_pbtn_map[] =
-{
- { SDLK_UP, PBTN_UP },
- { SDLK_DOWN, PBTN_DOWN },
- { SDLK_LEFT, PBTN_LEFT },
- { SDLK_RIGHT, PBTN_RIGHT },
- /* XXX: maybe better set this from it's plat code somehow */
- { SDLK_RETURN, PBTN_MOK },
- { SDLK_ESCAPE, PBTN_MBACK },
- { SDLK_a, PBTN_MA2 },
- { SDLK_s, PBTN_MA3 },
- { SDLK_BACKSLASH, PBTN_MENU },
- { SDLK_LEFTBRACKET, PBTN_L },
- { SDLK_RIGHTBRACKET, PBTN_R },
-};
-#define KEY_PBTN_MAP_SIZE (sizeof(key_pbtn_map) / sizeof(key_pbtn_map[0]))
-
-static const struct menu_keymap joybtn_pbtn_map[] =
-{
- { SDLK_UP, PBTN_UP },
- { SDLK_DOWN, PBTN_DOWN },
- { SDLK_LEFT, PBTN_LEFT },
- { SDLK_RIGHT, PBTN_RIGHT },
- /* joystick */
- { SDLK_WORLD_0, PBTN_MOK },
- { SDLK_WORLD_1, PBTN_MBACK },
- { SDLK_WORLD_2, PBTN_MA2 },
- { SDLK_WORLD_3, PBTN_MA3 },
-};
-#define JOYBTN_PBTN_MAP_SIZE (sizeof(joybtn_pbtn_map) / sizeof(joybtn_pbtn_map[0]))
-
static int in_sdl_menu_translate(void *drv_data, int keycode, char *charcode)
{
struct in_sdl_state *state = drv_data;
+ const struct in_pdata *pdata = state->drv->pdata;
+ const char * const * key_names = in_sdl_keys;
const struct menu_keymap *map;
int map_len;
int ret = 0;
int i;
- map = state->joy ? joybtn_pbtn_map : key_pbtn_map;
- map_len = state->joy ? JOYBTN_PBTN_MAP_SIZE : KEY_PBTN_MAP_SIZE;
+ if (pdata->key_names)
+ key_names = pdata->key_names;
+
+ if (state->joy) {
+ map = pdata->joy_map;
+ map_len = pdata->jmap_size;
+ } else {
+ map = pdata->key_map;
+ map_len = pdata->kmap_size;
+ }
if (keycode < 0)
{
}
if (charcode != NULL && (unsigned int)keycode < SDLK_LAST &&
- in_sdl_keys[keycode] != NULL && in_sdl_keys[keycode][1] == 0)
+ key_names[keycode] != NULL && key_names[keycode][1] == 0)
{
ret |= PBTN_CHAR;
- *charcode = in_sdl_keys[keycode][0];
+ *charcode = key_names[keycode][0];
}
}
return ret;
}
+static int in_sdl_clean_binds(void *drv_data, int *binds, int *def_finds)
+{
+ struct in_sdl_state *state = drv_data;
+ int i, t, cnt = 0;
+
+ memset(state->emu_keys, 0, sizeof(state->emu_keys));
+ for (t = 0; t < IN_BINDTYPE_COUNT; t++)
+ for (i = 0; i < SDLK_LAST; i++)
+ if (binds[IN_BIND_OFFS(i, t)]) {
+ if (t == IN_BINDTYPE_EMU)
+ update_keystate(state->emu_keys, i, 1);
+ cnt ++;
+ }
+
+ return cnt;
+}
+
static const in_drv_t in_sdl_drv = {
.prefix = IN_SDL_PREFIX,
.probe = in_sdl_probe,
.update = in_sdl_update,
.update_keycode = in_sdl_update_keycode,
.menu_translate = in_sdl_menu_translate,
+ .clean_binds = in_sdl_clean_binds,
};
-void in_sdl_init(const struct in_default_bind *defbinds,
- void (*handler)(void *event))
+int in_sdl_init(const struct in_pdata *pdata, void (*handler)(void *event))
{
- in_register_driver(&in_sdl_drv, defbinds);
+ if (!pdata) {
+ fprintf(stderr, "in_sdl: Missing input platform data\n");
+ return -1;
+ }
+
+ in_register_driver(&in_sdl_drv, pdata->defbinds, pdata);
ext_event_handler = handler;
+ return 0;
}