From 70812b3c497b3c37cca98ef657e9205f51fde2f6 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 30 Aug 2021 14:40:19 +0900 Subject: [PATCH] [input] Hook up low level input to events This includes device add and remove events, and axis and buttons for evdev. Will need to sort out X11 input later, but next is getting qwaq responding. --- include/QF/in_event.h | 44 +++++++++++++------- include/QF/input.h | 12 +++++- include/evdev/inputlib.h | 4 ++ libs/input/evdev/inputlib.c | 9 +++++ libs/input/in_common.c | 59 ++++++++++++++++++++++++--- libs/input/in_evdev.c | 81 +++++++++++++++++++++++++++++++++++-- libs/input/in_event.c | 66 ++++++++++++------------------ 7 files changed, 211 insertions(+), 64 deletions(-) diff --git a/include/QF/in_event.h b/include/QF/in_event.h index dd1f148cf..31ec88f46 100644 --- a/include/QF/in_event.h +++ b/include/QF/in_event.h @@ -35,7 +35,7 @@ #include "QF/joystick.h" // needed for JOY_MAX_AXES typedef struct { - float x, y; + int x, y; unsigned int buttons; } IE_mouse_event_t; @@ -45,33 +45,49 @@ typedef struct { } IE_key_event_t; typedef struct { - float axis[JOY_MAX_AXES]; - unsigned int buttons; -} IE_joystick_event_t; + int devid; + int axis; + int value; +} IE_axis_event_t; + +typedef struct { + int devid; + int button; + int state; +} IE_button_event_t; + +typedef struct { + int devid; +} IE_device_event_t; typedef enum { ie_none, ie_gain_focus, ie_lose_focus, + ie_add_device, + ie_remove_device, ie_mouse, ie_key, - ie_joystick, + ie_axis, + ie_button, } IE_event_type; typedef struct { - IE_event_type type; + IE_event_type type; + uint64_t when; union { - IE_mouse_event_t mouse; - IE_key_event_t key; - IE_joystick_event_t joystick; - } e; + IE_mouse_event_t mouse; + IE_key_event_t key; + IE_axis_event_t axis; + IE_button_event_t button; + IE_device_event_t device; + }; } IE_event_t; -void IE_Init (void); -void IE_Init_Cvars (void); -void IE_Shutdown (void); +typedef int ie_handler_t (const IE_event_t *, void *data); + int IE_Send_Event (const IE_event_t *event); -int IE_Add_Handler (int (*event_handler)(const IE_event_t*)); +int IE_Add_Handler (ie_handler_t *event_handler, void *data); void IE_Remove_Handler (int handle); void IE_Set_Focus (int handle); diff --git a/include/QF/input.h b/include/QF/input.h index e09ac6c3c..e91014b4e 100644 --- a/include/QF/input.h +++ b/include/QF/input.h @@ -35,7 +35,7 @@ typedef struct { vec3_t position; } viewdelta_t; -typedef struct { +typedef struct in_driver_s { void (*init) (void *data); void (*shutdown) (void *data); void (*process_events) (void *data); @@ -43,6 +43,13 @@ typedef struct { void (*grab_input) (void *data, int grab); } in_driver_t; +typedef struct in_device_s { + int driverid; + void *device; + const char *name; + const char *path; +} in_device_t; + extern viewdelta_t viewdelta; #define freelook (in_mlook.state & 1 || in_freelook->int_val) @@ -54,6 +61,9 @@ void IN_DriverData (int handlle, void *data); void IN_Init (struct cbuf_s *cbuf); void IN_Init_Cvars (void); +int IN_AddDevice (in_device_t *device); +void IN_RemoveDevice (int devid); + void IN_ProcessEvents (void); void IN_UpdateGrab (struct cvar_s *); diff --git a/include/evdev/inputlib.h b/include/evdev/inputlib.h index de3e61caf..9d8c931e5 100644 --- a/include/evdev/inputlib.h +++ b/include/evdev/inputlib.h @@ -37,6 +37,10 @@ typedef struct device_s { int num_axes; axis_t *axes; int event_count; + + void *data; + void (*axis_event) (axis_t *axis, void *data); + void (*button_event) (button_t *button, void *data); } device_t; int inputlib_check_input (void); diff --git a/libs/input/evdev/inputlib.c b/libs/input/evdev/inputlib.c index 065c57dc0..9fd854be4 100644 --- a/libs/input/evdev/inputlib.c +++ b/libs/input/evdev/inputlib.c @@ -270,10 +270,16 @@ read_device_input (device_t *dev) case EV_KEY: button = &dev->buttons[dev->button_map[event.code]]; button->state = event.value; + if (dev->button_event) { + dev->button_event (button, dev->data); + } break; case EV_ABS: axis = &dev->axes[dev->abs_axis_map[event.code]]; axis->value = event.value; + if (dev->axis_event) { + dev->axis_event (axis, dev->data); + } break; case EV_MSC: break; @@ -282,6 +288,9 @@ read_device_input (device_t *dev) //Sys_Printf ("EV_REL %6d %6x %6d %p\n", event.code, event.value, // dev->rel_axis_map[event.code], axis); axis->value = event.value; + if (dev->axis_event) { + dev->axis_event (axis, dev->data); + } break; case EV_SW: case EV_LED: diff --git a/libs/input/in_common.c b/libs/input/in_common.c index 609bb0344..aa49f1331 100644 --- a/libs/input/in_common.c +++ b/libs/input/in_common.c @@ -63,7 +63,8 @@ typedef struct { void *data; } in_regdriver_t; -static struct DARRAY_TYPE (in_regdriver_t) in_drivers = { .grow = 8, }; +static struct DARRAY_TYPE (in_regdriver_t) in_drivers = { .grow = 8 }; +static struct DARRAY_TYPE (in_device_t *) in_devices = { .grow = 8 }; VISIBLE viewdelta_t viewdelta; @@ -98,6 +99,58 @@ IN_DriverData (int handle, void *data) in_drivers.a[handle].data = data; } +static int +in_add_device (in_device_t *device) +{ + size_t devid; + + for (devid = 0; devid < in_devices.size; devid++) { + if (!in_devices.a[devid]) { + in_devices.a[devid] = device; + return devid; + } + } + DARRAY_APPEND (&in_devices, device); + return devid; +} + +int +IN_AddDevice (in_device_t *device) +{ + int devid = in_add_device (device); + + IE_event_t event = { + .type = ie_add_device, + .when = Sys_LongTime (), + .device = { + .devid = devid, + }, + }; + IE_Send_Event (&event); + return devid; +} + +void +IN_RemoveDevice (int devid) +{ + size_t d = devid; + + if (d >= in_devices.size) { + Sys_Error ("IN_RemoveDevice: invalid devid: %d", devid); + } + + IE_event_t event = { + .type = ie_remove_device, + .when = Sys_LongTime (), + .device = { + .devid = devid, + }, + }; + IE_Send_Event (&event); + + in_devices.a[devid] = 0; +} + void IN_UpdateGrab (cvar_t *var) // called from context_*.c { @@ -168,8 +221,6 @@ IN_shutdown (void *data) rd->driver.shutdown (rd->data); } } - - IE_Shutdown (); } void @@ -177,7 +228,6 @@ IN_Init (cbuf_t *cbuf) { Sys_RegisterShutdown (IN_shutdown, 0); - IE_Init (); for (size_t i = 0; i < in_drivers.size; i++) { in_regdriver_t *rd = &in_drivers.a[i]; rd->driver.init (rd->data); @@ -191,7 +241,6 @@ IN_Init (cbuf_t *cbuf) void IN_Init_Cvars (void) { - IE_Init_Cvars (); Key_Init_Cvars (); //JOY_Init_Cvars (); in_grab = Cvar_Get ("in_grab", "0", CVAR_ARCHIVE, IN_UpdateGrab, diff --git a/libs/input/in_evdev.c b/libs/input/in_evdev.c index 125d12e64..cfd9aa221 100644 --- a/libs/input/in_evdev.c +++ b/libs/input/in_evdev.c @@ -37,12 +37,22 @@ #endif #include "QF/cvar.h" +#include "QF/in_event.h" #include "QF/input.h" +#include "QF/progs.h" // for PR_RESMAP #include "QF/sys.h" #include "compat.h" #include "evdev/inputlib.h" +typedef struct { + in_device_t in_dev; + int devid; +} devmap_t; + +static int evdev_driver_handle = -1; +static PR_RESMAP (devmap_t) devmap; + static void in_evdev_keydest_callback (keydest_t key_dest, void *data) { @@ -61,19 +71,84 @@ in_evdev_shutdown (void *data) inputlib_close (); } +static void +in_evdev_axis_event (axis_t *axis, void *_dm) +{ + devmap_t *dm = _dm; + //Sys_Printf ("in_evdev_axis_event: %d %d\n", axis->num, axis->value); + + IE_event_t event = { + .type = ie_axis, + .when = Sys_LongTime (), + .axis = { + .devid = dm->devid, + .axis = axis->num, + .value = axis->value, + }, + }; + IE_Send_Event (&event); +} + +static void +in_evdev_button_event (button_t *button, void *_dm) +{ + devmap_t *dm = _dm; + //Sys_Printf ("in_evdev_button_event: %d %d\n", button->num, button->state); + + IE_event_t event = { + .type = ie_button, + .when = Sys_LongTime (), + .button = { + .devid = dm->devid, + .button = button->num, + .state = button->state, + }, + }; + IE_Send_Event (&event); +} + static void device_add (device_t *dev) { + devmap_t *dm = PR_RESNEW (devmap); + dm->in_dev.driverid = evdev_driver_handle; + dm->in_dev.device = dev; + dm->in_dev.name = dev->name; + dm->in_dev.path = dev->phys; + dm->devid = IN_AddDevice (&dm->in_dev); + + dev->data = dm; + dev->axis_event = in_evdev_axis_event; + dev->button_event = in_evdev_button_event; + +#if 0 Sys_Printf ("in_evdev: add %s\n", dev->path); Sys_Printf (" %s\n", dev->name); Sys_Printf (" %s\n", dev->phys); - Sys_Printf (" %s\n", dev->uniq); + for (int i = 0; i < dev->num_axes; i++) { + axis_t *axis = dev->axes + i; + Sys_Printf ("axis: %d %d\n", axis->num, axis->value); + } + for (int i = 0; i < dev->num_buttons; i++) { + button_t *button = dev->buttons + i; + Sys_Printf ("button: %d %d\n", button->num, button->state); + } +#endif } static void device_remove (device_t *dev) { - Sys_Printf ("in_evdev: remove %s\n", dev->path); + //Sys_Printf ("in_evdev: remove %s\n", dev->path); + for (unsigned i = 0; i < devmap._size; i++) { + devmap_t *dm = PR_RESGET (devmap, ~i); + if (dm->in_dev.device == dev) { + IN_RemoveDevice (dm->devid); + memset (dm, 0, sizeof (*dm)); + PR_RESFREE (devmap, dm); + break; + } + } } static void @@ -99,7 +174,7 @@ static in_driver_t in_evdev_driver = { static void __attribute__((constructor)) in_evdev_register_driver (void) { - IN_RegisterDriver (&in_evdev_driver, 0); + evdev_driver_handle = IN_RegisterDriver (&in_evdev_driver, 0); } int in_evdev_force_link; diff --git a/libs/input/in_event.c b/libs/input/in_event.c index 28ee17c98..6f74ae4bc 100644 --- a/libs/input/in_event.c +++ b/libs/input/in_event.c @@ -39,72 +39,56 @@ #endif #include +#include "QF/darray.h" #include "QF/in_event.h" -static int (**event_handler_list)(const IE_event_t*); -static int eh_list_size; -static int focus; +typedef struct { + ie_handler_t *handler; + void *data; +} ie_reghandler_t; -void -IE_Init (void) -{ - eh_list_size = 8; // start with 8 slots. will grow dynamicly if needed - event_handler_list = calloc (eh_list_size, sizeof (event_handler_list[0])); -} - -void -IE_Init_Cvars (void) -{ -} - -void -IE_Shutdown (void) -{ -} +static struct DARRAY_TYPE (ie_reghandler_t) ie_handlers = { .grow = 8, }; +static unsigned focus; int IE_Send_Event (const IE_event_t *event) { - if (event_handler_list[focus]) - return event_handler_list[focus](event); + if (focus < ie_handlers.size && ie_handlers.a[focus].handler) { + ie_reghandler_t *reg = &ie_handlers.a[focus]; + return reg->handler (event, reg->data); + } return 0; } int -IE_Add_Handler (int (*event_handler)(const IE_event_t*)) +IE_Add_Handler (ie_handler_t *event_handler, void *data) { - int i; + size_t handle; + ie_reghandler_t reg = { event_handler, data }; - while (1) { - int (**t)(const IE_event_t*); - for (i = 0; i < eh_list_size; i++) { - if (!event_handler_list[i]) { - event_handler_list[i] = event_handler; - return i; - } + for (handle = 0; handle < ie_handlers.size; handle++) { + if (!ie_handlers.a[handle].handler) { + ie_handlers.a[handle] = reg; + return handle; } - if (!(t = realloc (event_handler_list, eh_list_size + 8))) - return -1; - event_handler_list = t; - memset (event_handler_list + eh_list_size, 0, - 8 * sizeof (event_handler_list[0])); - eh_list_size += 8; } + DARRAY_APPEND (&ie_handlers, reg); + return handle; } void IE_Remove_Handler (int handle) { - if (handle >= 0 && handle < eh_list_size) - event_handler_list[handle] = 0; + if ((size_t) (ssize_t) handle < ie_handlers.size) { + ie_handlers.a[handle].handler = 0; + } } void IE_Set_Focus (int handle) { - if (handle >= 0 && handle < eh_list_size - && event_handler_list[handle] - && focus != handle) { + unsigned h = handle; + if (h < ie_handlers.size && ie_handlers.a[handle].handler && focus != h) { IE_event_t event; event.type = ie_lose_focus; IE_Send_Event (&event);