X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?p=libpicofe.git;a=blobdiff_plain;f=input.c;h=d0e4a4e691668a2ccb9806be7499a666a0717a79;hp=8030e1f944dc9fa5572d571c3b6431b3ac71960c;hb=HEAD;hpb=afdbb7c87325a4a6280943564da2e9e19cefc55b diff --git a/input.c b/input.c index 8030e1f..92b47a2 100644 --- a/input.c +++ b/input.c @@ -17,11 +17,6 @@ #include "plat.h" #include "lprintf.h" -#ifdef IN_VK -#error needs update: in_vk_init in_vk_update -#include "../win32/in_vk.h" -#endif - typedef struct { int drv_id; @@ -30,6 +25,7 @@ typedef struct char *name; int key_count; int *binds; /* total = key_count * bindtypes * 2 */ + int *kbd_binds; /* total = key_count */ const char * const *key_names; unsigned int probed:1; unsigned int does_combos:1; @@ -43,6 +39,8 @@ static int in_have_async_devs = 0; static int in_probe_dev_id; static int menu_key_state = 0; static int menu_last_used_dev = 0; +static int menu_key_prev = 0; +static int menu_key_repeat = 0; #define DRV(id) in_drivers[id] @@ -50,25 +48,51 @@ static int menu_last_used_dev = 0; static int *in_alloc_binds(int drv_id, int key_count) { const struct in_default_bind *defbinds; - int *binds; + int *binds, *binds_d; int i; binds = calloc(key_count * IN_BINDTYPE_COUNT * 2, sizeof(binds[0])); if (binds == NULL) return NULL; + binds_d = binds + key_count * IN_BINDTYPE_COUNT; + + /* always have a copy of defbinds */ defbinds = DRV(drv_id).defbinds; if (defbinds != NULL) { for (i = 0; ; i++) { - if (defbinds[i].bit == 0 && defbinds[i].code == 0) + if (defbinds[i].code == 0 && defbinds[i].btype == 0 + && defbinds[i].bit == 0) break; - binds[IN_BIND_OFFS(defbinds[i].code, defbinds[i].btype)] = + + binds_d[IN_BIND_OFFS(defbinds[i].code, defbinds[i].btype)] |= 1 << defbinds[i].bit; } + } - /* always have a copy of defbinds */ - memcpy(binds + key_count * IN_BINDTYPE_COUNT, binds, - sizeof(binds[0]) * key_count * IN_BINDTYPE_COUNT); + return binds; +} + +static int *in_alloc_kbd_binds(int drv_id, int key_count) +{ + const struct in_default_bind *defbinds; + int *binds; + int i; + + binds = calloc(key_count * 2, sizeof(binds[0])); + if (binds == NULL) + return NULL; + + /* always have a copy of defbinds */ + defbinds = DRV(drv_id).kbd_binds; + if (defbinds != NULL) { + for (i = 0; ; i++) { + if (defbinds[i].code == 0 && defbinds[i].btype == 0 + && defbinds[i].bit == 0) + break; + + binds[defbinds[i].code] = defbinds[i].bit; + } } return binds; @@ -96,7 +120,7 @@ static void in_free(in_dev_t *dev) void in_register(const char *nname, int drv_fd_hnd, void *drv_data, int key_count, const char * const *key_names, int combos) { - int i, ret, dupe_count = 0, *binds; + int i, ret, dupe_count = 0, *binds, *kbd_binds; char name[256], *name_end, *tmp; strncpy(name, nname, sizeof(name)); @@ -139,9 +163,18 @@ void in_register(const char *nname, int drv_fd_hnd, void *drv_data, free(tmp); return; } + kbd_binds = in_alloc_kbd_binds(in_probe_dev_id, key_count); + if (kbd_binds == NULL) { + free(tmp); + return; + } + + memcpy(binds, binds + key_count * IN_BINDTYPE_COUNT, + sizeof(binds[0]) * key_count * IN_BINDTYPE_COUNT); in_devices[i].name = tmp; in_devices[i].binds = binds; + in_devices[i].kbd_binds = kbd_binds; in_devices[i].key_count = key_count; if (i + 1 > in_dev_count) in_dev_count = i + 1; @@ -246,7 +279,7 @@ void in_probe(void) for (i = 0; i < in_driver_count; i++) { in_probe_dev_id = i; - in_drivers[i].probe(); + in_drivers[i].probe(&DRV(i)); } /* get rid of devs without binds and probes */ @@ -286,6 +319,19 @@ int in_update(int *result) return ret; } +int in_update_kbd(int *result) +{ + int i, ret = 0; + + for (i = 0; i < in_dev_count; i++) { + in_dev_t *dev = &in_devices[i]; + if (dev->probed && dev->binds != NULL) + ret += DRV(dev->drv_id).update_kbd(dev->drv_data, dev->kbd_binds, result+ret); + } + + return ret; +} + static in_dev_t *get_dev(int dev_id) { if (dev_id < 0 || dev_id >= IN_MAX_DEVS) @@ -304,6 +350,16 @@ int in_update_analog(int dev_id, int axis_id, int *result) return DRV(dev->drv_id).update_analog(dev->drv_data, axis_id, result); } +int in_update_pointer(int dev_id, int id, int *result) +{ + in_dev_t *dev = get_dev(dev_id); + + if (dev == NULL || !dev->probed) + return -1; + + return DRV(dev->drv_id).update_pointer(dev->drv_data, id, result); +} + static int in_update_kc_async(int *dev_id_out, int *is_down_out, int timeout_ms) { int i, is_down, result; @@ -351,8 +407,11 @@ int in_update_keycode(int *dev_id_out, int *is_down_out, char *charcode, int tim if (in_have_async_devs) { result = in_update_kc_async(&dev_id, &is_down, timeout_ms); - if (result == -1) + if (result == -1) { + // no key up event for RDRAW, clear to avoid key repeat + menu_key_state &= ~PBTN_RDRAW; return -1; + } drv = &DRV(in_devices[dev_id].drv_id); goto finish; } @@ -427,53 +486,44 @@ finish: int in_menu_wait_any(char *charcode, int timeout_ms) { int keys_old = menu_key_state; + int ret; + int dev_id = 0; - while (1) - { - int code, is_down = 0, dev_id = 0; + menu_key_prev = menu_key_state; - code = in_update_keycode(&dev_id, &is_down, charcode, timeout_ms); - if (code < 0) - break; + in_update_keycode(&dev_id, NULL, charcode, timeout_ms); - if (keys_old != menu_key_state) { - menu_last_used_dev = dev_id; - break; - } - } + if (keys_old != menu_key_state) + menu_last_used_dev = dev_id; + + ret = menu_key_state; + if (ret == 0) + menu_key_prev = 0; - return menu_key_state; + return ret; } /* wait for menu input, do autorepeat */ int in_menu_wait(int interesting, char *charcode, int autorep_delay_ms) { - static int inp_prev = 0; - static int repeats = 0; - int ret, release = 0, wait = 450; + int ret, wait = 450; - if (repeats) + if (menu_key_repeat) wait = autorep_delay_ms; - ret = in_menu_wait_any(charcode, wait); - if (ret == inp_prev) - repeats++; - - while (!(ret & interesting)) { - ret = in_menu_wait_any(charcode, -1); - release = 1; - } - - if (release || ret != inp_prev) - repeats = 0; - - inp_prev = ret; + /* wait until either key repeat or a new key has been pressed */ + interesting |= PBTN_RDRAW; + do { + ret = in_menu_wait_any(charcode, wait); + if (ret == 0 || ret != menu_key_prev) + menu_key_repeat = 0; + else + menu_key_repeat++; + wait = -1; + } while (!(ret & interesting)); /* we don't need diagonals in menus */ - if ((ret & PBTN_UP) && (ret & PBTN_LEFT)) ret &= ~PBTN_LEFT; - if ((ret & PBTN_UP) && (ret & PBTN_RIGHT)) ret &= ~PBTN_RIGHT; - if ((ret & PBTN_DOWN) && (ret & PBTN_LEFT)) ret &= ~PBTN_LEFT; - if ((ret & PBTN_DOWN) && (ret & PBTN_RIGHT)) ret &= ~PBTN_RIGHT; + if (ret & (PBTN_UP|PBTN_DOWN)) ret &= ~(PBTN_LEFT|PBTN_RIGHT); return ret; } @@ -485,16 +535,36 @@ const int *in_get_dev_binds(int dev_id) return dev ? dev->binds : NULL; } +const int *in_get_dev_kbd_binds(int dev_id) +{ + in_dev_t *dev = get_dev(dev_id); + + return dev ? dev->kbd_binds : NULL; +} + const int *in_get_dev_def_binds(int dev_id) { in_dev_t *dev = get_dev(dev_id); if (dev == NULL) return NULL; + if (dev->binds == NULL) + return NULL; return dev->binds + dev->key_count * IN_BINDTYPE_COUNT; } -int in_get_config(int dev_id, int what, void *val) +const int *in_get_dev_kbd_def_binds(int dev_id) +{ + in_dev_t *dev = get_dev(dev_id); + if (dev == NULL) + return NULL; + if (dev->binds == NULL) + return NULL; + + return dev->kbd_binds; +} + +int in_get_config(int dev_id, enum in_cfg_opt what, void *val) { int *ival = val; in_dev_t *dev; @@ -514,6 +584,9 @@ int in_get_config(int dev_id, int what, void *val) case IN_CFG_KEY_NAMES: return -1; /* not implemented */ default: + if (!dev->probed) + return -1; + return DRV(dev->drv_id).get_config(dev->drv_data, what, ival); } @@ -527,23 +600,26 @@ static int in_set_blocking(int is_blocking) /* have_async_devs means we will have to do all reads async anyway.. */ if (!in_have_async_devs) { for (i = 0; i < in_dev_count; i++) { - if (in_devices[i].probed) - DRV(in_devices[i].drv_id).set_config(in_devices[i].drv_data, - IN_CFG_BLOCKING, is_blocking); + if (!in_devices[i].probed) + continue; + + DRV(in_devices[i].drv_id).set_config( + in_devices[i].drv_data, IN_CFG_BLOCKING, + is_blocking); } } - menu_key_state = 0; - /* flush events */ do { ret = in_update_keycode(NULL, NULL, NULL, 0); } while (ret >= 0); + menu_key_state = 0; + return 0; } -int in_set_config(int dev_id, int what, const void *val, int size) +int in_set_config(int dev_id, enum in_cfg_opt what, const void *val, size_t size) { const char * const *names; const int *ival = val; @@ -720,6 +796,30 @@ int in_bind_key(int dev_id, int keycode, int mask, int bind_type, int force_unbi return 0; } +int in_bind_kbd_key(int dev_id, int keycode, int kbd_key) +{ + int count; + in_dev_t *dev; + + dev = get_dev(dev_id); + if (dev == NULL) + return -1; + + count = dev->key_count; + + if (dev->kbd_binds == NULL) { + dev->kbd_binds = in_alloc_kbd_binds(dev->drv_id, count); + if (dev->kbd_binds == NULL) + return -1; + } + + if (keycode < 0 || keycode >= count) + return -1; + + dev->kbd_binds[keycode] = (kbd_key == -1 ? 0 : kbd_key); + return 0; +} + /* * Unbind act_mask on binds with type bind_type * - if dev_id_ < 0, affects all devices @@ -749,9 +849,11 @@ void in_unbind_all(int dev_id_, int act_mask, int bind_type) if (act_mask != -1) { for (i = 0; i < count; i++) dev->binds[IN_BIND_OFFS(i, bind_type)] &= ~act_mask; - } - else + } else { memset(dev->binds, 0, sizeof(dev->binds[0]) * count * IN_BINDTYPE_COUNT); + if (dev->kbd_binds) + memset(dev->kbd_binds, 0, sizeof(dev->kbd_binds[0]) * count); + } } } @@ -769,7 +871,7 @@ int in_config_parse_dev(const char *name) } if (drv_id < 0) { - lprintf("input: missing driver for %s\n", name); + lprintf("input: missing driver for '%s'\n", name); return -1; } @@ -787,7 +889,8 @@ int in_config_parse_dev(const char *name) for (i = 0; i < IN_MAX_DEVS; i++) if (in_devices[i].name == NULL) break; if (i >= IN_MAX_DEVS) { - lprintf("input: too many devices, can't add %s\n", name); + lprintf("input: too many devices, can't add '%s'\n", + name); return -1; } } @@ -798,7 +901,8 @@ int in_config_parse_dev(const char *name) if (in_devices[i].name == NULL) return -1; - in_devices[i].key_names = DRV(drv_id).get_key_names(&in_devices[i].key_count); + in_devices[i].key_names = DRV(drv_id).get_key_names(&DRV(drv_id), + &in_devices[i].key_count); in_devices[i].drv_id = drv_id; if (i + 1 > in_dev_count) @@ -807,14 +911,9 @@ int in_config_parse_dev(const char *name) return i; } -int in_config_bind_key(int dev_id, const char *key, int acts, int bind_type) +static int parse_key(in_dev_t *dev, const char *key) { - in_dev_t *dev; - int i, offs, kc; - - dev = get_dev(dev_id); - if (dev == NULL || bind_type >= IN_BINDTYPE_COUNT) - return -1; + int kc, i; /* maybe a raw code? */ if (key[0] == '\\' && key[1] == 'x') { @@ -850,8 +949,23 @@ int in_config_bind_key(int dev_id, const char *key, int acts, int bind_type) } } + return kc; +} + +int in_config_bind_key(int dev_id, const char *key, int acts, int bind_type) +{ + in_dev_t *dev; + int i, offs, kc; + + dev = get_dev(dev_id); + if (dev == NULL || bind_type >= IN_BINDTYPE_COUNT) + return -1; + + kc = parse_key(dev, key); + if (kc < 0 || kc >= dev->key_count) { - lprintf("input: bad key: %s\n", key); + lprintf("input: bad key: '%s' for device '%s'\n", + key, dev->name); return -1; } @@ -868,6 +982,28 @@ int in_config_bind_key(int dev_id, const char *key, int acts, int bind_type) return 0; } +int in_config_bind_kbd_key(int dev_id, const char *key, int kbd_key) +{ + in_dev_t *dev; + int kc; + + dev = get_dev(dev_id); + if (dev == NULL) + return -1; + + kc = parse_key(dev, key); + + if (kc < 0 || kc >= dev->key_count) { + lprintf("input: bad key: '%s' for device '%s'\n", + key, dev->name); + return -1; + } + + dev->kbd_binds[kc] = kbd_key; + + return 0; +} + void in_clean_binds(void) { int i; @@ -876,7 +1012,7 @@ void in_clean_binds(void) int ret, count, *binds, *def_binds; in_dev_t *dev = &in_devices[i]; - if (dev->binds == NULL || dev->drv_data == NULL) + if (dev->binds == NULL || !dev->probed) continue; count = dev->key_count; @@ -901,8 +1037,25 @@ void in_debug_dump(void) in_dev_t *d = &in_devices[i]; if (!d->probed && d->name == NULL && d->binds == NULL) continue; - lprintf("%d %3d %6c %5c %s\n", i, d->drv_id, d->probed ? 'y' : 'n', + lprintf("%d %3d %6c %5c %s\n", i, d->drv_id, + d->probed ? 'y' : 'n', d->binds ? 'y' : 'n', d->name); +#if 0 + if (d->binds) { + int kc, o, t, h; + for (kc = 0; kc < d->key_count; kc++) { + o = IN_BIND_OFFS(kc, 0); + for (t = h = 0; t < IN_BINDTYPE_COUNT; t++) + h |= d->binds[o + t]; + if (h == 0) + continue; + lprintf(" [%3d] =", kc); + for (t = 0; t < IN_BINDTYPE_COUNT; t++) + printf(" %x", d->binds[o + t]); + printf("\n"); + } + } +#endif } } @@ -910,9 +1063,10 @@ void in_debug_dump(void) static void in_def_free(void *drv_data) {} static int in_def_clean_binds(void *drv_data, int *b, int *db) { return 1; } -static int in_def_get_config(void *drv_data, int what, int *val) { return -1; } -static int in_def_set_config(void *drv_data, int what, int val) { return -1; } +static int in_def_get_config(void *drv_data, enum in_cfg_opt what, int *val) { return -1; } +static int in_def_set_config(void *drv_data, enum in_cfg_opt what, int val) { return -1; } static int in_def_update_analog(void *drv_data, int axis_id, int *result) { return -1; } +static int in_def_update_pointer(void *drv_data, int id, int *result) { return -1; } static int in_def_update_keycode(void *drv_data, int *is_down) { return 0; } static int in_def_menu_translate(void *drv_data, int keycode, char *ccode) { return 0; } static int in_def_get_key_code(const char *key_name) { return -1; } @@ -922,7 +1076,10 @@ static const char *in_def_get_key_name(int keycode) { return NULL; } if (d.f == NULL) d.f = in_def_##f /* to be called by drivers */ -int in_register_driver(const in_drv_t *drv, const struct in_default_bind *defbinds) +int in_register_driver(const in_drv_t *drv, + const struct in_default_bind *defbinds, + const struct in_default_bind *kbd_map, + const void *pdata) { int count_new = in_driver_count + 1; in_drv_t *new_drivers; @@ -940,12 +1097,17 @@ int in_register_driver(const in_drv_t *drv, const struct in_default_bind *defbin CHECK_ADD_STUB(new_drivers[in_driver_count], get_config); CHECK_ADD_STUB(new_drivers[in_driver_count], set_config); CHECK_ADD_STUB(new_drivers[in_driver_count], update_analog); + CHECK_ADD_STUB(new_drivers[in_driver_count], update_pointer); CHECK_ADD_STUB(new_drivers[in_driver_count], update_keycode); CHECK_ADD_STUB(new_drivers[in_driver_count], menu_translate); CHECK_ADD_STUB(new_drivers[in_driver_count], get_key_code); CHECK_ADD_STUB(new_drivers[in_driver_count], get_key_name); - if (defbinds != NULL) + if (pdata) + new_drivers[in_driver_count].pdata = pdata; + if (defbinds) new_drivers[in_driver_count].defbinds = defbinds; + if (kbd_map) + new_drivers[in_driver_count].kbd_binds = kbd_map; in_drivers = new_drivers; in_driver_count = count_new;