#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;
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;
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]
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;
+}
+
static void in_unprobe(in_dev_t *dev)
{
if (dev->probed)
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));
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;
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)
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;
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;
}
{
int keys_old = menu_key_state;
int ret;
- int is_down = 0, dev_id = 0;
+ int dev_id = 0;
+
+ menu_key_prev = menu_key_state;
- in_update_keycode(&dev_id, &is_down, charcode, timeout_ms);
+ in_update_keycode(&dev_id, NULL, charcode, timeout_ms);
if (keys_old != menu_key_state)
menu_last_used_dev = dev_id;
ret = menu_key_state;
- menu_key_state &= ~PBTN_CHAR;
+ if (ret == 0)
+ menu_key_prev = 0;
+
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;
}
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);
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;
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;
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
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);
+ }
}
}
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') {
}
}
+ 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' for device '%s'\n",
key, dev->name);
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;
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; }
/* to be called by drivers */
int in_register_driver(const in_drv_t *drv,
- const struct in_default_bind *defbinds, const void *pdata)
+ 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;
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);
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;