mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
[input] Start work on improved input system
The common input code (input outer loop and event handling) has been moved into libQFinput, and modified to have the concept of input drivers that are registered by the appropriate system-level code (x11, win, etc). As well, my evdev input library code (with hotplug support) has been added, but is not yet fully functional. However, the idea is that it will be available on all systems that support evdev (Linux, and from what I've read, FreeBSD).
This commit is contained in:
parent
8a5c3c1ac1
commit
a91dac60d9
14 changed files with 867 additions and 43 deletions
|
@ -85,6 +85,8 @@ EXTRA_DIST += \
|
|||
include/client/locs.h \
|
||||
include/client/state.h \
|
||||
include/client/view.h \
|
||||
include/evdev/hotplug.h \
|
||||
include/evdev/inputlib.h \
|
||||
include/qw/bothdefs.h \
|
||||
include/qw/msg_backbuf.h \
|
||||
include/qw/msg_ucmd.h \
|
||||
|
|
|
@ -35,12 +35,21 @@ typedef struct {
|
|||
vec3_t position;
|
||||
} viewdelta_t;
|
||||
|
||||
typedef struct {
|
||||
void (*init) (void);
|
||||
void (*shutdown) (void);
|
||||
void (*process_events) (void);
|
||||
void (*clear_states) (void);
|
||||
void (*grab_input) (int grab);
|
||||
} in_driver_t;
|
||||
|
||||
extern viewdelta_t viewdelta;
|
||||
|
||||
#define freelook (in_mlook.state & 1 || in_freelook->int_val)
|
||||
|
||||
struct cvar_s;
|
||||
|
||||
void IN_RegisterDriver (in_driver_t *driver);
|
||||
void IN_Init (struct cbuf_s *cbuf);
|
||||
void IN_Init_Cvars (void);
|
||||
|
||||
|
@ -64,12 +73,6 @@ extern struct cvar_s *lookstrafe;
|
|||
extern qboolean in_mouse_avail;
|
||||
extern float in_mouse_x, in_mouse_y;
|
||||
|
||||
void IN_LL_Init_Cvars (void);
|
||||
void IN_LL_Init (void);
|
||||
void IN_LL_Shutdown (void);
|
||||
void IN_LL_ProcessEvents (void);
|
||||
void IN_LL_ClearStates (void);
|
||||
void IN_LL_Grab_Input (int grab);
|
||||
|
||||
extern kbutton_t in_strafe, in_klook, in_speed, in_mlook;
|
||||
|
||||
|
|
14
include/evdev/hotplug.h
Normal file
14
include/evdev/hotplug.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef evdev_hotplug_h
|
||||
#define evdev_hotplug_h
|
||||
|
||||
int inputlib_hotplug_init(const char *path,
|
||||
void (*created) (const char*),
|
||||
void (*deleted) (const char *));
|
||||
|
||||
void inputlib_hotplug_close (void);
|
||||
|
||||
int inputlib_hotplug_add_select (fd_set *fdset, int *maxfd);
|
||||
|
||||
int inputlib_hotplug_check_select (fd_set *fdset);
|
||||
|
||||
#endif//evdev_hotplug_h
|
46
include/evdev/inputlib.h
Normal file
46
include/evdev/inputlib.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef evdev_inputlib_h
|
||||
#define evdev_inputlib_h
|
||||
|
||||
typedef struct {
|
||||
int num; ///< The high-level index of the button. Always 0-N
|
||||
int evnum; ///< The low-level index of the button. May be sparse
|
||||
int state; ///< Current state of the button.
|
||||
} button_t;
|
||||
|
||||
typedef struct {
|
||||
int num; ///< The high-level index of the axis. Always 0-N
|
||||
int evnum; ///< The low-level index of the axis. May be sparse
|
||||
int value; ///< Current value of the input axis.
|
||||
// relative axes set these to 0
|
||||
int min; ///< Minimum value for the axis (usually constant).
|
||||
int max; ///< Maximum value for the axis (usually constant).
|
||||
} axis_t;
|
||||
|
||||
typedef struct device_s {
|
||||
struct device_s *next;
|
||||
char *path;
|
||||
char *name;
|
||||
char *phys;
|
||||
char *uniq;
|
||||
int fd;
|
||||
int max_button;
|
||||
int *button_map;
|
||||
int num_buttons;
|
||||
button_t *buttons;
|
||||
int max_abs_axis;
|
||||
int *abs_axis_map;
|
||||
int max_rel_axis;
|
||||
int *rel_axis_map;
|
||||
int num_abs_axes;
|
||||
int num_rel_axes;
|
||||
// includes both abs and rel axes, with abs first
|
||||
int num_axes;
|
||||
axis_t *axes;
|
||||
int event_count;
|
||||
} device_t;
|
||||
|
||||
int inputlib_check_input (void);
|
||||
void inputlib_close (void);
|
||||
int inputlib_init (void (*dev_add) (device_t *), void (*dev_rem) (device_t *));
|
||||
|
||||
#endif//evdev_inputlib_h
|
|
@ -1,8 +1,16 @@
|
|||
lib_LTLIBRARIES += libs/input/libQFinput.la
|
||||
|
||||
in_evdev_src= \
|
||||
libs/input/evdev/hotplug.c \
|
||||
libs/input/evdev/inputlib.c \
|
||||
libs/input/in_evdev.c
|
||||
|
||||
libs_input_libQFinput_la_LDFLAGS= $(lib_ldflags)
|
||||
libs_input_libQFinput_la_LIBADD= $(input_deps)
|
||||
libs_input_libQFinput_la_DEPENDENCIES= $(input_deps)
|
||||
libs_input_libQFinput_la_SOURCES= \
|
||||
$(in_evdev_src) \
|
||||
libs/input/keys.c \
|
||||
libs/input/old_keys.c
|
||||
libs/input/old_keys.c \
|
||||
libs/input/in_common.c \
|
||||
libs/input/in_event.c
|
||||
|
|
124
libs/input/evdev/hotplug.c
Normal file
124
libs/input/evdev/hotplug.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
#include <sys/inotify.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/select.h>
|
||||
#include <alloca.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "evdev/hotplug.h"
|
||||
|
||||
static int inotify_fd;
|
||||
static int devinput_wd;
|
||||
static char *devinput_path;
|
||||
static void (*device_deleted) (const char *name);
|
||||
static void (*device_created) (const char *name);
|
||||
|
||||
static unsigned
|
||||
get_queue_size (int fd)
|
||||
{
|
||||
unsigned queue_len;
|
||||
int ret = ioctl (fd, FIONREAD, &queue_len);
|
||||
if (ret < 0) {
|
||||
perror ("ioctl");
|
||||
return 0;
|
||||
}
|
||||
return queue_len;
|
||||
}
|
||||
|
||||
static void
|
||||
parse_inotify_events (int fd)
|
||||
{
|
||||
ssize_t len, i;
|
||||
ssize_t queue_len = get_queue_size (fd);
|
||||
char *buf = alloca (queue_len);
|
||||
struct inotify_event *event;
|
||||
|
||||
len = read (fd, buf, queue_len);
|
||||
for (i = 0; i < len; i += sizeof (struct inotify_event) + event->len) {
|
||||
event = (struct inotify_event *) &buf[i];
|
||||
//printf ("%-3d %08x %5u %4d %s\n", event->wd, event->mask,
|
||||
// event->cookie, event->len,
|
||||
// event->len ? event->name : "<no name>");
|
||||
if ((event->mask & IN_DELETE) && event->len) {
|
||||
if (strncmp (event->name, "event", 5) == 0) {
|
||||
// interested in only evdev devices
|
||||
//printf("deleted device %s\n", event->name);
|
||||
device_deleted (event->name);
|
||||
}
|
||||
}
|
||||
if (((event->mask & IN_ATTRIB) || (event->mask & IN_CREATE))
|
||||
&& event->len) {
|
||||
// done this way because may not have read permission when the
|
||||
// device is created, so try again when (presumabely) permission is
|
||||
// granted
|
||||
if (strncmp (event->name, "event", 5) == 0) {
|
||||
// interested in only evdev devices
|
||||
//printf("created device %s\n", event->name);
|
||||
device_created (event->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
inputlib_hotplug_init(const char *path,
|
||||
void (*created) (const char*),
|
||||
void (*deleted) (const char *))
|
||||
{
|
||||
inotify_fd = inotify_init ();
|
||||
if (inotify_fd == -1) {
|
||||
perror ("inotify_init");
|
||||
return -1;
|
||||
}
|
||||
devinput_wd = inotify_add_watch (inotify_fd, path,
|
||||
IN_CREATE | IN_DELETE | IN_ATTRIB
|
||||
| IN_ONLYDIR);
|
||||
if (devinput_wd == -1) {
|
||||
perror ("inotify_add_watch");
|
||||
close (inotify_fd);
|
||||
return -1;
|
||||
}
|
||||
devinput_path = strdup (path);
|
||||
device_created = created;
|
||||
device_deleted = deleted;
|
||||
//printf ("inputlib_hotplug_init: %s %d %d\n", path, inotify_fd,
|
||||
// devinput_wd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
inputlib_hotplug_close (void)
|
||||
{
|
||||
if (inotify_fd != -1) {
|
||||
close (inotify_fd);
|
||||
free (devinput_path);
|
||||
device_created = 0;
|
||||
device_deleted = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
inputlib_hotplug_add_select (fd_set *fdset, int *maxfd)
|
||||
{
|
||||
if (inotify_fd != -1) {
|
||||
FD_SET (inotify_fd, fdset);
|
||||
if (inotify_fd > *maxfd) {
|
||||
*maxfd = inotify_fd;
|
||||
}
|
||||
}
|
||||
return inotify_fd;
|
||||
}
|
||||
|
||||
int
|
||||
inputlib_hotplug_check_select (fd_set *fdset)
|
||||
{
|
||||
if (inotify_fd != -1) {
|
||||
if (FD_ISSET (inotify_fd, fdset)) {
|
||||
parse_inotify_events (inotify_fd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
479
libs/input/evdev/inputlib.c
Normal file
479
libs/input/evdev/inputlib.c
Normal file
|
@ -0,0 +1,479 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <linux/input.h>
|
||||
#include <linux/joystick.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "QF/dstring.h"
|
||||
|
||||
#include "evdev/hotplug.h"
|
||||
#include "evdev/inputlib.h"
|
||||
|
||||
static const char *devinput_path = "/dev/input";
|
||||
static device_t *devices;
|
||||
void (*device_add) (device_t *);
|
||||
void (*device_remove) (device_t *);
|
||||
|
||||
static void
|
||||
setup_buttons (device_t *dev)
|
||||
{
|
||||
int i, j, len;
|
||||
unsigned char buf[1024];
|
||||
button_t *button;
|
||||
|
||||
dev->max_button = -1;
|
||||
dev->num_buttons = 0;
|
||||
dev->button_map = 0;
|
||||
dev->buttons = 0;
|
||||
len = ioctl (dev->fd, EVIOCGBIT (EV_KEY, sizeof (buf)), buf);
|
||||
for (i = 0; i < len; i++) {
|
||||
//printf("%c%02x", !(i % 16) ? '\n': !(i % 8) ? '-' : ' ', buf[i]);
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (buf[i] & (1 << j)) {
|
||||
dev->num_buttons++;
|
||||
dev->max_button = i * 8 + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
//printf("\n");
|
||||
dev->button_map = malloc ((dev->max_button + 1) * sizeof (int));
|
||||
dev->buttons = malloc (dev->num_buttons * sizeof (button_t));
|
||||
for (i = 0, button = dev->buttons; i < len; i++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
int button_ind = i * 8 + j;
|
||||
if (buf[i] & (1 << j)) {
|
||||
button->num = button - dev->buttons;
|
||||
button->evnum = button_ind;
|
||||
button->state = 0;
|
||||
dev->button_map[button_ind] = button->num;
|
||||
|
||||
button++;
|
||||
} else {
|
||||
if (button_ind <= dev->max_button) {
|
||||
dev->button_map[button_ind] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
len = ioctl (dev->fd, EVIOCGKEY (sizeof (buf)), buf);
|
||||
for (i = 0; i < dev->num_buttons; i++) {
|
||||
int key = dev->buttons[i].evnum;
|
||||
dev->buttons[i].state = !!(buf[key / 8] & (1 << (key % 8)));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
count_axes (const unsigned char *buf, int len, int *max_axis)
|
||||
{
|
||||
int count = 0;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (buf[i] & (1 << j)) {
|
||||
count++;
|
||||
*max_axis = i * 8 + j;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static void
|
||||
abs_info (device_t *dev, int axis_ind, axis_t *axis)
|
||||
{
|
||||
struct input_absinfo absinfo;
|
||||
ioctl (dev->fd, EVIOCGABS(axis_ind), &absinfo);
|
||||
axis->value = absinfo.value;
|
||||
axis->min = absinfo.minimum;
|
||||
axis->max = absinfo.maximum;
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
rel_info (device_t *dev, int axis_ind, axis_t *axis)
|
||||
{
|
||||
// relative axes are marked by having 0 min/max
|
||||
axis->value = 0;
|
||||
axis->min = 0;
|
||||
axis->max = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
map_axes (const unsigned char *buf, int len, device_t *dev,
|
||||
int max_axis, int *axis_map, axis_t *first_axis,
|
||||
void (*info)(device_t*, int, axis_t *))
|
||||
{
|
||||
int i, j;
|
||||
axis_t *axis;
|
||||
|
||||
for (i = 0, axis = first_axis; i < len; i++) {
|
||||
for (j = 0; j < 8; j++) {
|
||||
int axis_ind = i * 8 + j;
|
||||
if (buf[i] & (1 << j)) {
|
||||
axis->num = axis - dev->axes;
|
||||
axis->evnum = axis_ind;
|
||||
axis_map[axis_ind] = axis->num;
|
||||
info (dev, axis_ind, axis);
|
||||
axis++;
|
||||
} else {
|
||||
if (axis_ind <= max_axis) {
|
||||
axis_map[axis_ind] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_axes (device_t *dev)
|
||||
{
|
||||
int alen, rlen;
|
||||
unsigned char abuf[1024];
|
||||
unsigned char rbuf[1024];
|
||||
|
||||
dev->max_abs_axis = -1;
|
||||
dev->max_rel_axis = -1;
|
||||
dev->num_axes = 0;
|
||||
dev->abs_axis_map = 0;
|
||||
dev->rel_axis_map = 0;
|
||||
dev->axes = 0;
|
||||
|
||||
alen = ioctl (dev->fd, EVIOCGBIT (EV_ABS, sizeof (abuf)), abuf);
|
||||
rlen = ioctl (dev->fd, EVIOCGBIT (EV_REL, sizeof (rbuf)), rbuf);
|
||||
|
||||
dev->num_abs_axes = count_axes (abuf, alen, &dev->max_abs_axis);
|
||||
dev->num_rel_axes = count_axes (rbuf, alen, &dev->max_rel_axis);
|
||||
|
||||
dev->num_axes = dev->num_abs_axes + dev->num_rel_axes;
|
||||
|
||||
dev->abs_axis_map = malloc ((dev->max_abs_axis + 1) * sizeof (int));
|
||||
dev->rel_axis_map = malloc ((dev->max_rel_axis + 1) * sizeof (int));
|
||||
|
||||
dev->axes = malloc (dev->num_axes * sizeof (axis_t));
|
||||
map_axes (abuf, alen, dev, dev->max_abs_axis, dev->abs_axis_map,
|
||||
dev->axes, abs_info);
|
||||
map_axes (rbuf, rlen, dev, dev->max_rel_axis, dev->rel_axis_map,
|
||||
dev->axes + dev->num_abs_axes, rel_info);
|
||||
}
|
||||
|
||||
static void device_created (const char *name);
|
||||
static void device_deleted (const char *name);
|
||||
|
||||
#define get_string(fd, ioctlid, dstr) \
|
||||
({ \
|
||||
int size; \
|
||||
while ((size = ioctl (fd, ioctlid (dstr->truesize), dstr->str)) \
|
||||
== (int) dstr->truesize) { \
|
||||
dstr->size = dstr->truesize + 1024; \
|
||||
dstring_adjust (dstr); \
|
||||
} \
|
||||
dstr->size = size <= 0 ? 1 : size; \
|
||||
dstr->str[dstr->size - 1] = 0; \
|
||||
dstr->str; \
|
||||
})
|
||||
|
||||
static int
|
||||
check_device (const char *path)
|
||||
{
|
||||
device_t *dev;
|
||||
int fd;
|
||||
dstring_t *buff = dstring_newstr ();
|
||||
|
||||
fd = open (path, O_RDWR);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
dev = malloc (sizeof (device_t));
|
||||
dev->next = devices;
|
||||
devices = dev;
|
||||
|
||||
dev->path = strdup (path);
|
||||
dev->fd = fd;
|
||||
|
||||
dev->name = strdup (get_string (fd, EVIOCGNAME, buff));
|
||||
dev->phys = strdup (get_string (fd, EVIOCGPHYS, buff));
|
||||
dev->uniq = strdup (get_string (fd, EVIOCGUNIQ, buff));
|
||||
|
||||
setup_buttons(dev);
|
||||
setup_axes(dev);
|
||||
|
||||
dev->event_count = 0;
|
||||
|
||||
printf ("%s:\n", path);
|
||||
printf ("\tname: %s\n", dev->name);
|
||||
printf ("\tbuttons: %d\n", dev->num_buttons);
|
||||
printf ("\taxes: %d\n", dev->num_axes);
|
||||
|
||||
if (device_add) {
|
||||
device_add (dev);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/*static const char *event_codes[] = {
|
||||
"EV_SYN",
|
||||
"EV_KEY",
|
||||
"EV_REL",
|
||||
"EV_ABS",
|
||||
"EV_MSC",
|
||||
"EV_SW",
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
"EV_LED",
|
||||
"EV_SND",
|
||||
"EV_REP",
|
||||
"EV_FF",
|
||||
"EV_PWR",
|
||||
"EV_FF_STATUS",
|
||||
};*/
|
||||
|
||||
static void
|
||||
read_device_input (device_t *dev)
|
||||
{
|
||||
struct input_event event;
|
||||
button_t *button;
|
||||
axis_t *axis;
|
||||
//int i;
|
||||
|
||||
// zero motion counters for relative axes
|
||||
//for (i = dev->num_abs_axes; i < dev->num_axes; i++) {
|
||||
// dev->axes[i].value = 0;
|
||||
//}
|
||||
|
||||
while (1) {
|
||||
if (read (dev->fd, &event, sizeof (event)) < 0) {
|
||||
perror(dev->name);
|
||||
dev->fd = -1;
|
||||
return;
|
||||
}
|
||||
//const char *ev = event_codes[event.type];
|
||||
//printf ("%6d(%s) %6d %6x\n", event.type, ev ? ev : "?", event.code, event.value);
|
||||
switch (event.type) {
|
||||
case EV_SYN:
|
||||
dev->event_count++;
|
||||
return;
|
||||
case EV_KEY:
|
||||
button = &dev->buttons[dev->button_map[event.code]];
|
||||
button->state = event.value;
|
||||
break;
|
||||
case EV_ABS:
|
||||
axis = &dev->axes[dev->abs_axis_map[event.code]];
|
||||
axis->value = event.value;
|
||||
break;
|
||||
case EV_MSC:
|
||||
break;
|
||||
case EV_REL:
|
||||
axis = &dev->axes[dev->rel_axis_map[event.code]];
|
||||
//printf ("EV_REL %6d %6x %6d %p\n", event.code, event.value,
|
||||
// dev->rel_axis_map[event.code], axis);
|
||||
axis->value = event.value;
|
||||
break;
|
||||
case EV_SW:
|
||||
case EV_LED:
|
||||
case EV_SND:
|
||||
case EV_REP:
|
||||
case EV_FF:
|
||||
case EV_PWR:
|
||||
case EV_FF_STATUS:
|
||||
//printf ("%6d %6d %6x\n", event.type, event.code, event.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
inputlib_check_input (void)
|
||||
{
|
||||
fd_set fdset;
|
||||
struct timeval _timeout;
|
||||
struct timeval *timeout = &_timeout;
|
||||
int res;
|
||||
int maxfd = -1;
|
||||
device_t *dev;
|
||||
|
||||
_timeout.tv_sec = 0;
|
||||
_timeout.tv_usec = 0;
|
||||
|
||||
FD_ZERO (&fdset);
|
||||
|
||||
inputlib_hotplug_add_select (&fdset, &maxfd);
|
||||
|
||||
for (dev = devices; dev; dev = dev->next) {
|
||||
if (dev->fd < 0) {
|
||||
continue;
|
||||
}
|
||||
FD_SET (dev->fd, &fdset);
|
||||
if (dev->fd > maxfd) {
|
||||
maxfd = dev->fd;
|
||||
}
|
||||
}
|
||||
if (maxfd < 0) {
|
||||
return 0;
|
||||
}
|
||||
res = select (maxfd + 1, &fdset, NULL, NULL, timeout);
|
||||
if (res <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inputlib_hotplug_check_select (&fdset);
|
||||
|
||||
for (dev = devices; dev; dev = dev->next) {
|
||||
if (dev->fd < 0) {
|
||||
continue;
|
||||
}
|
||||
if (FD_ISSET (dev->fd, &fdset)) {
|
||||
read_device_input (dev);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
close_device (device_t *dev)
|
||||
{
|
||||
if (device_remove) {
|
||||
device_remove (dev);
|
||||
}
|
||||
close (dev->fd);
|
||||
free (dev->button_map);
|
||||
if (dev->buttons) {
|
||||
free (dev->buttons);
|
||||
}
|
||||
free (dev->abs_axis_map);
|
||||
free (dev->rel_axis_map);
|
||||
if (dev->axes) {
|
||||
free (dev->axes);
|
||||
}
|
||||
free (dev->name);
|
||||
free (dev->path);
|
||||
}
|
||||
|
||||
static char *
|
||||
make_devname (const char *path, const char *name)
|
||||
{
|
||||
int plen = strlen (path);
|
||||
int nlen = strlen (name);
|
||||
char *devname = malloc (plen + nlen + 2);
|
||||
|
||||
strcpy (devname, path);
|
||||
devname[plen] = '/';
|
||||
strcpy (devname + plen + 1, name);
|
||||
|
||||
return devname;
|
||||
}
|
||||
|
||||
static int
|
||||
check_input_device (const char *path, const char *name)
|
||||
{
|
||||
int ret;
|
||||
char *devname = make_devname (path, name);
|
||||
|
||||
//puts (devname);
|
||||
ret = check_device (devname);
|
||||
free (devname);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
device_created (const char *name)
|
||||
{
|
||||
char *devname = make_devname (devinput_path, name);
|
||||
device_t *dev;
|
||||
int olddev = 0;
|
||||
|
||||
for (dev = devices; dev; dev = dev->next) {
|
||||
if (strcmp (dev->path, devname) == 0) {
|
||||
// already have this device open
|
||||
olddev = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!olddev && check_device (devname) >= 0) {
|
||||
//printf ("found device %s\n", devname);
|
||||
}
|
||||
free (devname);
|
||||
}
|
||||
|
||||
static void
|
||||
device_deleted (const char *name)
|
||||
{
|
||||
char *devname = make_devname (devinput_path, name);
|
||||
device_t **dev;
|
||||
|
||||
for (dev = &devices; *dev; dev = &(*dev)->next) {
|
||||
if (strcmp ((*dev)->path, devname) == 0) {
|
||||
//printf ("lost device %s\n", (*dev)->path);
|
||||
close_device (*dev);
|
||||
device_t *d = *dev;
|
||||
*dev = (*dev)->next;
|
||||
free (d);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free (devname);
|
||||
}
|
||||
|
||||
static int
|
||||
scan_devices (void)
|
||||
{
|
||||
struct dirent *dirent;
|
||||
DIR *dir;
|
||||
|
||||
dir = opendir (devinput_path);
|
||||
if (!dir) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((dirent = readdir (dir))) {
|
||||
if (dirent->d_type != DT_CHR) {
|
||||
continue;
|
||||
}
|
||||
if (strncmp (dirent->d_name, "event", 5)) {
|
||||
continue;
|
||||
}
|
||||
if (check_input_device (devinput_path, dirent->d_name) < 0) {
|
||||
continue;
|
||||
}
|
||||
//printf("%s\n", dirent->d_name);
|
||||
}
|
||||
closedir (dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
inputlib_init (void (*dev_add) (device_t *), void (*dev_rem) (device_t *))
|
||||
{
|
||||
device_add = dev_add;
|
||||
device_remove = dev_rem;
|
||||
if (scan_devices () != -1) {
|
||||
inputlib_hotplug_init (devinput_path, device_created, device_deleted);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
inputlib_close (void)
|
||||
{
|
||||
inputlib_hotplug_close ();
|
||||
while (devices) {
|
||||
close_device (devices);
|
||||
device_t *dev = devices;
|
||||
devices = devices->next;
|
||||
free (dev);
|
||||
}
|
||||
}
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
#include "QF/cbuf.h"
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/darray.h"
|
||||
#include "QF/in_event.h"
|
||||
#include "QF/input.h"
|
||||
#include "QF/joystick.h"
|
||||
|
@ -57,6 +58,8 @@
|
|||
#include "QF/sys.h"
|
||||
#include "QF/vid.h"
|
||||
|
||||
static struct DARRAY_TYPE (in_driver_t) in_drivers = { .grow = 8, };
|
||||
|
||||
VISIBLE viewdelta_t viewdelta;
|
||||
|
||||
cvar_t *in_grab;
|
||||
|
@ -76,26 +79,36 @@ qboolean in_mouse_avail;
|
|||
float in_mouse_x, in_mouse_y;
|
||||
static float in_old_mouse_x, in_old_mouse_y;
|
||||
|
||||
void
|
||||
IN_RegisterDriver (in_driver_t *driver)
|
||||
{
|
||||
DARRAY_APPEND (&in_drivers, *driver);
|
||||
}
|
||||
|
||||
void
|
||||
IN_UpdateGrab (cvar_t *var) // called from context_*.c
|
||||
{
|
||||
if (var) {
|
||||
IN_LL_Grab_Input (var->int_val);
|
||||
for (size_t i = 0; i < in_drivers.size; i++) {
|
||||
if (in_drivers.a[i].grab_input) {
|
||||
in_drivers.a[i].grab_input (var->int_val);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IN_ProcessEvents (void)
|
||||
{
|
||||
/* Get events from environment. */
|
||||
JOY_Command ();
|
||||
IN_LL_ProcessEvents ();
|
||||
for (size_t i = 0; i < in_drivers.size; i++) {
|
||||
in_drivers.a[i].process_events ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IN_Move (void)
|
||||
{
|
||||
JOY_Move ();
|
||||
//JOY_Move ();
|
||||
|
||||
if (!in_mouse_avail)
|
||||
return;
|
||||
|
@ -131,10 +144,14 @@ IN_Move (void)
|
|||
static void
|
||||
IN_shutdown (void *data)
|
||||
{
|
||||
JOY_Shutdown ();
|
||||
//JOY_Shutdown ();
|
||||
|
||||
Sys_MaskPrintf (SYS_vid, "IN_Shutdown\n");
|
||||
IN_LL_Shutdown ();
|
||||
for (size_t i = in_drivers.size; i-- > 0; ) {
|
||||
if (in_drivers.a[i].shutdown) {
|
||||
in_drivers.a[i].shutdown ();
|
||||
}
|
||||
}
|
||||
|
||||
IE_Shutdown ();
|
||||
}
|
||||
|
@ -145,9 +162,11 @@ IN_Init (cbuf_t *cbuf)
|
|||
Sys_RegisterShutdown (IN_shutdown, 0);
|
||||
|
||||
IE_Init ();
|
||||
IN_LL_Init ();
|
||||
for (size_t i = 0; i < in_drivers.size; i++) {
|
||||
in_drivers.a[i].init ();
|
||||
}
|
||||
Key_Init (cbuf);
|
||||
JOY_Init ();
|
||||
//JOY_Init ();
|
||||
|
||||
in_mouse_x = in_mouse_y = 0.0;
|
||||
}
|
||||
|
@ -157,7 +176,7 @@ IN_Init_Cvars (void)
|
|||
{
|
||||
IE_Init_Cvars ();
|
||||
Key_Init_Cvars ();
|
||||
JOY_Init_Cvars ();
|
||||
//JOY_Init_Cvars ();
|
||||
in_grab = Cvar_Get ("in_grab", "0", CVAR_ARCHIVE, IN_UpdateGrab,
|
||||
"With this set to 1, quake will grab the mouse, "
|
||||
"preventing loss of input focus.");
|
||||
|
@ -175,12 +194,18 @@ IN_Init_Cvars (void)
|
|||
"mouse in_mouse_pre_amp multiplier");
|
||||
lookstrafe = Cvar_Get ("lookstrafe", "0", CVAR_ARCHIVE, NULL,
|
||||
"when mlook/klook on player will strafe");
|
||||
IN_LL_Init_Cvars ();
|
||||
}
|
||||
|
||||
void
|
||||
IN_ClearStates (void)
|
||||
{
|
||||
IN_LL_ClearStates ();
|
||||
for (size_t i = 0; i < in_drivers.size; i++) {
|
||||
if (in_drivers.a[i].clear_states) {
|
||||
in_drivers.a[i].clear_states ();
|
||||
}
|
||||
}
|
||||
Key_ClearStates ();
|
||||
}
|
||||
|
||||
extern int in_evdev_force_link;
|
||||
static __attribute__((used)) int *evdev_force_link = &in_evdev_force_link;
|
100
libs/input/in_evdev.c
Normal file
100
libs/input/in_evdev.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
in_evdev.c
|
||||
|
||||
general evdev input driver
|
||||
|
||||
Copyright (C) 2021 Bill Currie <bill@taniwha.org>
|
||||
Please see the file "AUTHORS" for a list of contributors
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to:
|
||||
|
||||
Free Software Foundation, Inc.
|
||||
59 Temple Place - Suite 330
|
||||
Boston, MA 02111-1307, USA
|
||||
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
# include <string.h>
|
||||
#endif
|
||||
#ifdef HAVE_STRINGS_H
|
||||
# include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "QF/cvar.h"
|
||||
#include "QF/input.h"
|
||||
#include "QF/sys.h"
|
||||
|
||||
#include "compat.h"
|
||||
#include "evdev/inputlib.h"
|
||||
|
||||
static void
|
||||
in_evdev_keydest_callback (keydest_t key_dest, void *data)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
in_evdev_process_events (void)
|
||||
{
|
||||
if (inputlib_check_input ()) {
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
in_evdev_shutdown (void)
|
||||
{
|
||||
inputlib_close ();
|
||||
}
|
||||
|
||||
static void
|
||||
device_add (device_t *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
device_remove (device_t *dev)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
in_evdev_init (void)
|
||||
{
|
||||
Key_KeydestCallback (in_evdev_keydest_callback, 0);
|
||||
|
||||
inputlib_init (device_add, device_remove);
|
||||
}
|
||||
|
||||
static void
|
||||
in_evdev_clear_states (void)
|
||||
{
|
||||
}
|
||||
|
||||
static in_driver_t in_evdev_driver = {
|
||||
.init = in_evdev_init,
|
||||
.shutdown = in_evdev_shutdown,
|
||||
.process_events = in_evdev_process_events,
|
||||
.clear_states = in_evdev_clear_states,
|
||||
};
|
||||
|
||||
static void __attribute__((constructor))
|
||||
in_evdev_register_driver (void)
|
||||
{
|
||||
IN_RegisterDriver (&in_evdev_driver);
|
||||
}
|
||||
|
||||
int in_evdev_force_link;
|
|
@ -56,8 +56,6 @@ libs_video_targets_libQFjs_la_SOURCES= libs/video/targets/joy.c $(joy_src)
|
|||
EXTRA_libs_video_targets_libQFjs_la_SOURCES= $(joy_linux_src) $(joy_win_src) $(joy_null_src)
|
||||
|
||||
libs_video_targets_libvid_common_la_SOURCES = \
|
||||
libs/video/targets/in_common.c \
|
||||
libs/video/targets/in_event.c \
|
||||
libs/video/targets/vid.c
|
||||
libs_video_targets_libvid_common_la_CFLAGS= @PREFER_NON_PIC@
|
||||
libs_video_targets_libvid_common_la_LDFLAGS= @STATIC@
|
||||
|
|
|
@ -685,3 +685,6 @@ X11_RestoreMouseAcceleration (void)
|
|||
accel_denominator, accel_threshold);
|
||||
accel_saved = false;
|
||||
}
|
||||
|
||||
extern int x11_force_link;
|
||||
static __attribute__((used)) int *context_x11_force_link = &x11_force_link;
|
||||
|
|
|
@ -597,7 +597,7 @@ XLateKey (XKeyEvent * ev, int *k, int *u)
|
|||
}
|
||||
|
||||
static void
|
||||
x11_keydest_callback (keydest_t key_dest, void *data)
|
||||
in_x11_keydest_callback (keydest_t key_dest, void *data)
|
||||
{
|
||||
// if (key_dest == key_game) {
|
||||
// XAutoRepeatOff (x_disp);
|
||||
|
@ -742,8 +742,8 @@ grab_error (int code, const char *device)
|
|||
Sys_Printf ("failed to grab %s: %s\n", device, reason);
|
||||
}
|
||||
|
||||
void
|
||||
IN_LL_Grab_Input (int grab)
|
||||
static void
|
||||
in_x11_grab_input (int grab)
|
||||
{
|
||||
if (!x_disp || !x_win)
|
||||
return;
|
||||
|
@ -780,16 +780,16 @@ IN_LL_Grab_Input (int grab)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
IN_LL_ProcessEvents (void)
|
||||
static void
|
||||
in_x11_process_events (void)
|
||||
{
|
||||
X11_ProcessEvents (); // Get events from X server.
|
||||
}
|
||||
|
||||
void
|
||||
IN_LL_Shutdown (void)
|
||||
static void
|
||||
in_x11_shutdown (void)
|
||||
{
|
||||
Sys_MaskPrintf (SYS_vid, "IN_LL_Shutdown\n");
|
||||
Sys_MaskPrintf (SYS_vid, "in_x11_shutdown\n");
|
||||
in_mouse_avail = 0;
|
||||
if (x_disp) {
|
||||
// XAutoRepeatOn (x_disp);
|
||||
|
@ -800,8 +800,20 @@ IN_LL_Shutdown (void)
|
|||
X11_CloseDisplay ();
|
||||
}
|
||||
|
||||
void
|
||||
IN_LL_Init (void)
|
||||
static void
|
||||
in_x11_init_cvars (void)
|
||||
{
|
||||
in_snd_block = Cvar_Get ("in_snd_block", "0", CVAR_ARCHIVE, NULL,
|
||||
"block sound output on window focus loss");
|
||||
in_dga = Cvar_Get ("in_dga", "0", CVAR_ARCHIVE, in_dga_f, //FIXME 0 until X fixed
|
||||
"DGA Input support");
|
||||
in_mouse_accel = Cvar_Get ("in_mouse_accel", "1", CVAR_ARCHIVE,
|
||||
in_mouse_accel_f,
|
||||
"set to 0 to remove mouse acceleration");
|
||||
}
|
||||
|
||||
static void
|
||||
in_x11_init (void)
|
||||
{
|
||||
// open the display
|
||||
if (!x_disp)
|
||||
|
@ -809,6 +821,8 @@ IN_LL_Init (void)
|
|||
if (!x_win)
|
||||
Sys_Error ("IN: No window!!");
|
||||
|
||||
in_x11_init_cvars ();
|
||||
|
||||
X11_OpenDisplay (); // call to increment the reference counter
|
||||
|
||||
{
|
||||
|
@ -842,25 +856,29 @@ IN_LL_Init (void)
|
|||
in_mouse_avail = 1;
|
||||
}
|
||||
|
||||
Key_KeydestCallback (x11_keydest_callback, 0);
|
||||
Key_KeydestCallback (in_x11_keydest_callback, 0);
|
||||
|
||||
Cmd_AddCommand ("in_paste_buffer", in_paste_buffer_f,
|
||||
"Paste the contents of X's C&P buffer to the console");
|
||||
}
|
||||
|
||||
void
|
||||
IN_LL_Init_Cvars (void)
|
||||
static void
|
||||
in_x11_clear_states (void)
|
||||
{
|
||||
in_snd_block = Cvar_Get ("in_snd_block", "0", CVAR_ARCHIVE, NULL,
|
||||
"block sound output on window focus loss");
|
||||
in_dga = Cvar_Get ("in_dga", "0", CVAR_ARCHIVE, in_dga_f, //FIXME 0 until X fixed
|
||||
"DGA Input support");
|
||||
in_mouse_accel = Cvar_Get ("in_mouse_accel", "1", CVAR_ARCHIVE,
|
||||
in_mouse_accel_f,
|
||||
"set to 0 to remove mouse acceleration");
|
||||
}
|
||||
|
||||
void
|
||||
IN_LL_ClearStates (void)
|
||||
static in_driver_t in_x11_driver = {
|
||||
.init = in_x11_init,
|
||||
.shutdown = in_x11_shutdown,
|
||||
.process_events = in_x11_process_events,
|
||||
.clear_states = in_x11_clear_states,
|
||||
.grab_input = in_x11_grab_input,
|
||||
};
|
||||
|
||||
static void __attribute__((constructor))
|
||||
in_x11_register_driver (void)
|
||||
{
|
||||
IN_RegisterDriver (&in_x11_driver);
|
||||
}
|
||||
|
||||
int x11_force_link;
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "QF/cvar.h"
|
||||
#include "QF/gib.h"
|
||||
#include "QF/idparse.h"
|
||||
#include "QF/input.h"
|
||||
#include "QF/keys.h"
|
||||
#include "QF/progs.h"
|
||||
#include "QF/qargs.h"
|
||||
|
@ -74,6 +75,9 @@ qwaq_init_threads (qwaq_thread_set_t *thread_data)
|
|||
{
|
||||
int main_ind = -1;
|
||||
|
||||
IN_Init_Cvars ();
|
||||
IN_Init (qwaq_cbuf);
|
||||
|
||||
for (size_t i = 1, thread_ind = 0; i < thread_data->size; i++) {
|
||||
qwaq_thread_t *thread = thread_data->a[i];
|
||||
progsinit_f *app_funcs = target_app;
|
||||
|
|
Loading…
Reference in a new issue