[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:
Bill Currie 2021-08-27 09:10:21 +09:00
parent 8a5c3c1ac1
commit a91dac60d9
14 changed files with 867 additions and 43 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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