mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-21 09:51:41 +00:00
[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:
parent
065d0f3818
commit
70812b3c49
7 changed files with 211 additions and 64 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue