[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.
This commit is contained in:
Bill Currie 2021-08-30 14:40:19 +09:00
parent 065d0f3818
commit 70812b3c49
7 changed files with 211 additions and 64 deletions

View file

@ -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);

View file

@ -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 *);

View file

@ -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);

View file

@ -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:

View file

@ -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,

View file

@ -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;

View file

@ -39,72 +39,56 @@
#endif
#include <stdlib.h>
#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);