aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2019-01-18 10:24:19 +0100
committerGerd Hoffmann <kraxel@redhat.com>2019-01-18 12:27:47 +0100
commit1eeeaefecb634ea734059685648c058dd600bcae (patch)
treec03f7dab7aa64179f295ebb83e0d4bdbdb7b5e67
parent1e49f9371f39475be7d2a3a9be2994ce5d27870b (diff)
downloadfbida-1eeeaefecb634ea734059685648c058dd600bcae.tar.gz
kbd: experimental libinput support
-rw-r--r--GNUmakefile8
-rw-r--r--drmtools.c5
-rw-r--r--fbi.c8
-rw-r--r--fbiconfig.c10
-rw-r--r--fbiconfig.h4
-rw-r--r--fbida.spec1
-rw-r--r--fbpdf.c4
-rw-r--r--fbtools.c5
-rw-r--r--gfx.h2
-rw-r--r--kbd.c105
-rw-r--r--kbd.h2
-rw-r--r--kbdtest.c2
-rw-r--r--meson.build11
13 files changed, 148 insertions, 19 deletions
diff --git a/GNUmakefile b/GNUmakefile
index 40e733a..de30fda 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -13,8 +13,9 @@ CFLAGS += -Wno-pointer-sign
# hard build deps
PKG_CONFIG = pkg-config
PKGS_IDA := libexif libpng libtiff-4 pixman-1
-PKGS_FBI := freetype2 fontconfig libdrm libexif libpng libtiff-4 pixman-1
-PKGS_FBPDF := libdrm poppler-glib gbm egl epoxy pixman-1
+PKGS_FBI := freetype2 fontconfig libdrm libexif libpng libtiff-4 pixman-1 libudev libinput
+PKGS_FBPDF := libdrm poppler-glib gbm egl epoxy pixman-1 libudev libinput
+PKGS_KTEST := libudev libinput
HAVE_DEPS := $(shell $(PKG_CONFIG) $(PKGS_FBI) $(PKGS_FBPDF) && echo yes)
# map pkg-config names to debian packages using apt-file
@@ -201,6 +202,9 @@ fbpdf: $(OBJS_FBPDF)
########################################################################
# rules for kbdtest
+kbdtest : CFLAGS += $(shell $(PKG_CONFIG) --cflags $(PKGS_KTEST))
+kbdtest : LDLIBS += $(shell $(PKG_CONFIG) --libs $(PKGS_KTEST))
+
kbdtest : kbdtest.o kbd.o
########################################################################
diff --git a/drmtools.c b/drmtools.c
index b1eae37..f731a92 100644
--- a/drmtools.c
+++ b/drmtools.c
@@ -10,6 +10,7 @@
#include <sys/ioctl.h>
#include <sys/mman.h>
+#include <sys/stat.h>
#include "gfx.h"
#include "drmtools.h"
@@ -226,6 +227,7 @@ static void drm_flush_display(bool second)
gfxstate *drm_init(const char *device, const char *output,
const char *mode, bool pageflip)
{
+ struct stat st;
gfxstate *gfx;
char dev[64];
@@ -266,6 +268,9 @@ gfxstate *drm_init(const char *device, const char *output,
gfx->cleanup_display = drm_cleanup_display;
gfx->flush_display = drm_flush_display;
+ fstat(drm_fd, &st);
+ gfx->devnum = st.st_rdev;
+
if (pageflip) {
if (drm_init_fb(&fb2) == 0) {
gfx->mem2 = fb2.mem;
diff --git a/fbi.c b/fbi.c
index 3eb9099..2d76f9c 100644
--- a/fbi.c
+++ b/fbi.c
@@ -950,7 +950,11 @@ svga_show(struct flist *f, struct flist *prev,
case KEY_D:
/* need shift state for this one */
return KEY_D | (keymod << 16);
+
+ case KEY_RESERVED:
+ /* ignored event */
break;
+
default:
return keycode;
}
@@ -1322,6 +1326,7 @@ int main(int argc, char *argv[])
int once;
int i, arg, key;
bool framebuffer = false;
+ bool use_libinput;
char *info, *desc, *device, *output, *mode;
char linebuffer[128];
struct flist *fprev = NULL;
@@ -1376,6 +1381,7 @@ int main(int argc, char *argv[])
timeout = GET_TIMEOUT();
pcd_res = GET_PCD_RES();
interactive = GET_INTERACTIVE();
+ use_libinput = GET_LIBINPUT();
fontname = cfg_get_str(O_FONT);
filelist = cfg_get_str(O_FILE_LIST);
@@ -1442,7 +1448,7 @@ int main(int argc, char *argv[])
shadow_init(gfx);
/* svga main loop */
- kbd_init();
+ kbd_init(use_libinput, gfx->devnum);
desc = NULL;
info = NULL;
for (;;) {
diff --git a/fbiconfig.c b/fbiconfig.c
index 44e2321..48c0fca 100644
--- a/fbiconfig.c
+++ b/fbiconfig.c
@@ -182,6 +182,11 @@ struct cfg_cmdline fbi_cfg[] = {
.option = { O_VIDEO_MODE },
.needsarg = 1,
.desc = "use video mode <arg> (from /etc/fb.modes)",
+ },{
+ .cmdline = "libinput",
+ .option = { O_LIBINPUT },
+ .yesno = 1,
+ .desc = "use libinput (experimental)",
},{
/* end of list */
@@ -250,6 +255,11 @@ struct cfg_cmdline fbpdf_cfg[] = {
.needsarg = 1,
.desc = "use video mode <arg> (from /etc/fb.modes)",
},{
+ .cmdline = "libinput",
+ .option = { O_LIBINPUT },
+ .yesno = 1,
+ .desc = "use libinput (experimental)",
+ },{
/* end of list */
}
};
diff --git a/fbiconfig.h b/fbiconfig.h
index d0b4d32..3fdc2f0 100644
--- a/fbiconfig.h
+++ b/fbiconfig.h
@@ -30,7 +30,8 @@
#define O_SCROLL O_OPTIONS, "scroll"
#define O_TIMEOUT O_OPTIONS, "timeout"
#define O_PCD_RES O_OPTIONS, "photocd-res"
-#define O_INTERACTIVE O_OPTIONS, "interactive"
+#define O_INTERACTIVE O_OPTIONS, "interactive"
+#define O_LIBINPUT O_OPTIONS, "libinput"
#define O_DEVICE O_OPTIONS, "device"
#define O_OUTPUT O_OPTIONS, "output"
@@ -65,6 +66,7 @@
#define GET_TIMEOUT() cfg_get_int(O_TIMEOUT, 0)
#define GET_PCD_RES() cfg_get_int(O_PCD_RES, 3)
#define GET_INTERACTIVE() cfg_get_bool(O_INTERACTIVE, 1)
+#define GET_LIBINPUT() cfg_get_bool(O_LIBINPUT, 0)
#define GET_OPENGL() cfg_get_bool(O_OPENGL, 0)
#define GET_PAGEFLIP() cfg_get_bool(O_PAGEFLIP, 1)
diff --git a/fbida.spec b/fbida.spec
index 517228c..665b6be 100644
--- a/fbida.spec
+++ b/fbida.spec
@@ -35,6 +35,7 @@ BuildRequires: pkgconfig(gbm)
BuildRequires: pkgconfig(egl)
BuildRequires: pkgconfig(epoxy)
BuildRequires: pkgconfig(cairo)
+BuildRequires: pkgconfig(libudev)
%description
fbida
diff --git a/fbpdf.c b/fbpdf.c
index 2c2b10f..91ccecd 100644
--- a/fbpdf.c
+++ b/fbpdf.c
@@ -237,6 +237,7 @@ int main(int argc, char *argv[])
{
GError *err = NULL;
bool framebuffer = false;
+ bool use_libinput;
bool quit, newpage, pageflip;
char cwd[1024];
char uri[1024];
@@ -294,6 +295,7 @@ int main(int argc, char *argv[])
mode = cfg_get_str(O_VIDEO_MODE);
fitwidth = GET_FIT_WIDTH();
pageflip = GET_PAGEFLIP();
+ use_libinput = GET_LIBINPUT();
if (device) {
/* device specified */
@@ -340,7 +342,7 @@ int main(int argc, char *argv[])
gfx->stride);
}
- kbd_init();
+ kbd_init(use_libinput, gfx->devnum);
index = 0;
newpage = true;
diff --git a/fbtools.c b/fbtools.c
index 1ee8639..a429775 100644
--- a/fbtools.c
+++ b/fbtools.c
@@ -224,6 +224,7 @@ static void fb_cleanup_display(void)
gfxstate* fb_init(char *device, char *mode, int vt)
{
unsigned long page_mask;
+ struct stat st;
gfxstate *gfx;
if (vt != 0)
@@ -334,6 +335,10 @@ gfxstate* fb_init(char *device, char *mode, int vt)
gfx->restore_display = fb_restore_display;
gfx->cleanup_display = fb_cleanup_display;
+
+ fstat(fb, &st);
+ gfx->devnum = st.st_rdev;
+
return gfx;
err:
diff --git a/gfx.h b/gfx.h
index f3602c6..9b2e52f 100644
--- a/gfx.h
+++ b/gfx.h
@@ -17,6 +17,8 @@ struct gfxstate {
uint32_t rlen, glen, blen, tlen;
uint32_t roff, goff, boff, toff;
+ dev_t devnum;
+
/* egl */
EGLDisplay dpy;
EGLContext ctx;
diff --git a/kbd.c b/kbd.c
index 6a30ca6..9ef8d3e 100644
--- a/kbd.c
+++ b/kbd.c
@@ -9,6 +9,9 @@
#include <errno.h>
#include <termios.h>
+#include <libudev.h>
+#include <libinput.h>
+
#include "kbd.h"
/* ---------------------------------------------------------------------- */
@@ -192,34 +195,118 @@ static int file_wait(int fd, int timeout)
/* ---------------------------------------------------------------------- */
-void kbd_init(void)
+static int devcount;
+
+static int open_restricted(const char *path, int flags, void *user_data)
+{
+ int fd;
+
+ fd = open(path, flags);
+ if (fd < 0) {
+ fprintf(stderr, "open %s: %s\n", path, strerror(errno));
+ return fd;
+ }
+
+ fprintf(stderr, "using %s\n", path);
+ ioctl(fd, EVIOCGRAB, 1);
+ devcount++;
+ return fd;
+}
+
+static void close_restricted(int fd, void *user_data)
+{
+ ioctl(fd, EVIOCGRAB, 0);
+ close(fd);
+}
+
+static const struct libinput_interface interface = {
+ .open_restricted = open_restricted,
+ .close_restricted = close_restricted,
+};
+
+static struct libinput *ctx;
+
+void kbd_init(int use_libinput, dev_t gfx)
{
- tty_raw();
+ struct udev *udev;
+ struct udev_device *ugfx;
+ const char *seat = NULL;
+
+ if (use_libinput) {
+ udev = udev_new();
+ ugfx = udev_device_new_from_devnum(udev, 'c', gfx);
+ if (ugfx)
+ seat = udev_device_get_property_value(ugfx, "ID_SEAT");
+ if (!seat)
+ seat = "seat0";
+ ctx = libinput_udev_create_context(&interface, NULL, udev);
+ libinput_udev_assign_seat(ctx, seat);
+ if (devcount == 0) {
+ fprintf(stderr, "WARNING: no input devices available\n");
+ }
+ fprintf(stderr, "kbd: using libinput (%d devices, %s)\n",
+ devcount, seat);
+ } else {
+ fprintf(stderr, "kbd: using stdin from terminal\n");
+ tty_raw();
+ }
}
void kbd_fini(void)
{
- tty_restore();
+ if (ctx) {
+ libinput_unref(ctx);
+ } else {
+ tty_restore();
+ }
}
int kbd_wait(int timeout)
{
- return file_wait(STDIN_FILENO, timeout);
+ if (ctx) {
+ return file_wait(libinput_get_fd(ctx), timeout);
+ } else {
+ return file_wait(STDIN_FILENO, timeout);
+ }
}
int kbd_read(char *buf, uint32_t len,
uint32_t *keycode, uint32_t *modifier)
{
+ struct libinput_event *evt;
+ struct libinput_event_keyboard *kbd;
int rc;
memset(buf, 0, len);
*keycode = KEY_RESERVED;
*modifier = 0;
- rc = read(STDIN_FILENO, buf, len-1);
- if (rc < 1)
- return -1;
+ if (ctx) {
+ rc = libinput_dispatch(ctx);
+ if (rc < 0)
+ return -1;
+ while ((evt = libinput_get_event(ctx)) != NULL) {
+ switch (libinput_event_get_type(evt)) {
+ case LIBINPUT_EVENT_KEYBOARD_KEY:
+ kbd = libinput_event_get_keyboard_event(evt);
+ if (libinput_event_keyboard_get_key_state(kbd))
+ *keycode = libinput_event_keyboard_get_key(kbd);
+ /* TODO: track modifier state */
+ /* TODO: fill buf with typed chars */
+ break;
+ default:
+ /* ignore event */
+ break;
+ }
+ libinput_event_destroy(evt);
+ }
+ return 0;
+ } else {
+ rc = read(STDIN_FILENO, buf, len-1);
+ if (rc < 1)
+ return -1;
- *keycode = tty_parse(buf, modifier);
- return rc;
+ *keycode = tty_parse(buf, modifier);
+ return rc;
+ }
}
diff --git a/kbd.h b/kbd.h
index 10d09f9..e9ed50b 100644
--- a/kbd.h
+++ b/kbd.h
@@ -3,7 +3,7 @@
#define KEY_MOD_SHIFT (1 << 0)
#define KEY_MOD_CTRL (1 << 1)
-void kbd_init(void);
+void kbd_init(int use_libinput, dev_t gfx);
int kbd_wait(int timeout);
int kbd_read(char *buf, uint32_t len,
uint32_t *keycode, uint32_t *modifier);
diff --git a/kbdtest.c b/kbdtest.c
index 866b6df..d1768c2 100644
--- a/kbdtest.c
+++ b/kbdtest.c
@@ -23,7 +23,7 @@ int main(int argc, char *argv[])
char key[32];
int rc,i;
- kbd_init();
+ kbd_init(0, 0);
for (;;) {
kbd_wait(10);
diff --git a/meson.build b/meson.build
index 3639b97..cbed982 100644
--- a/meson.build
+++ b/meson.build
@@ -24,6 +24,8 @@ exif_dep = dependency('libexif')
png_dep = dependency('libpng')
tiff_dep = dependency('libtiff-4')
webp_dep = dependency('libwebp', required : false)
+udev_dep = dependency('libudev')
+input_dep = dependency('libinput')
# other library deps
cc = meson.get_compiler('c')
@@ -84,7 +86,7 @@ fbi_srcs = [ 'fbi.c', 'fb-gui.c', 'desktop.c',
fbi_deps = [ freetype_dep, fontconf_dep,
drm_dep, pixman_dep,
exif_dep, image_deps,
- math_dep ]
+ math_dep, udev_dep, input_dep ]
executable('fbi',
sources : fbi_srcs,
@@ -115,7 +117,8 @@ executable('thumbnail.cgi',
fbpdf_srcs = [ 'fbpdf.c', 'parseconfig.c', 'fbiconfig.c',
'vt.c', 'kbd.c', 'fbtools.c', 'drmtools.c', 'drmtools-egl.c' ]
fbpdf_deps = [ drm_dep, gbm_dep, epoxy_dep,
- pixman_dep, poppler_dep, cairo_dep ]
+ pixman_dep, poppler_dep, cairo_dep,
+ udev_dep, input_dep ]
executable('fbpdf',
sources : fbpdf_srcs,
@@ -123,7 +126,9 @@ executable('fbpdf',
install : true)
# build kbdtest
-executable('kbdtest', [ 'kbdtest.c', 'kbd.c' ])
+executable('kbdtest',
+ sources : [ 'kbdtest.c', 'kbd.c' ],
+ dependencies : [ udev_dep, input_dep ] )
# build ida
mkfallback = find_program('scripts/fallback.pl')