tools: add keymap handling to the socket demos

Client sets layout fr, server accepts it and prints azerty for the keys
pressed.

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2020-08-21 16:57:41 +10:00
parent 2a619fd4b4
commit 4af29d930a
6 changed files with 154 additions and 11 deletions

View file

@ -32,14 +32,14 @@ variables:
# See the documentation here: #
# https://wayland.freedesktop.org/libinput/doc/latest/building_libinput.html #
###############################################################################
FEDORA_PACKAGES: 'git diffutils gcc gcc-c++ pkgconf-pkg-config meson systemd-devel protobuf-c-devel'
FEDORA_PACKAGES: 'git diffutils gcc gcc-c++ pkgconf-pkg-config meson systemd-devel protobuf-c-devel libxkbcommon-devel'
############################ end of package lists #############################
# these tags should be updated each time the list of packages is updated
# changing these will force rebuilding the associated image
# Note: these tags have no meaning and are not tied to a particular
# libinput version
FEDORA_TAG: '2020-08-20.1'
FEDORA_TAG: '2020-08-21.1'
FDO_UPSTREAM_REPO: whot/libei
@ -226,6 +226,12 @@ default-build-release@fedora:32:
MESON_ARGS: "-Dbuildtype=release"
CFLAGS: "-Werror"
build-no-libxkcommon-nodeps@fedora:32:
extends:
- .fedora-build@template
before_script:
- dnf remove -y libxkcommon-devel
valgrind@fedora:32:
extends:
- .fedora-build@template

View file

@ -38,7 +38,7 @@ variables:
# See the documentation here: #
# https://wayland.freedesktop.org/libinput/doc/latest/building_libinput.html #
###############################################################################
FEDORA_PACKAGES: 'git diffutils gcc gcc-c++ pkgconf-pkg-config meson systemd-devel protobuf-c-devel'
FEDORA_PACKAGES: 'git diffutils gcc gcc-c++ pkgconf-pkg-config meson systemd-devel protobuf-c-devel libxkbcommon-devel'
############################ end of package lists #############################
# these tags should be updated each time the list of packages is updated
@ -247,6 +247,12 @@ default-build-release@{{distro.name}}:{{version}}:
MESON_ARGS: "-Dbuildtype=release"
CFLAGS: "-Werror"
build-no-libxkcommon-nodeps@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template
before_script:
- dnf remove -y libxkcommon-devel
valgrind@{{distro.name}}:{{version}}:
extends:
- .{{distro.name}}-build@template

View file

@ -3,7 +3,7 @@
#
# We're happy to rebuild all containers when one changes.
.default_tag: &default_tag '2020-08-20.1'
.default_tag: &default_tag '2020-08-21.1'
distributions:
- name: fedora

View file

@ -123,13 +123,15 @@ pkgconfig.generate(lib_libreis,
libraries: lib_libreis,
)
dep_libxkbcommon = dependency('xkbcommon', required: false)
config_h.set10('HAVE_LIBXKBCOMMON', dep_libxkbcommon.found())
executable('eis-socket-server',
'tools/eis-socket-server.c',
dependencies: [dep_libeis])
dependencies: [dep_libutil, dep_libeis, dep_libxkbcommon])
executable('ei-socket-client',
'tools/ei-socket-client.c',
dependencies: [dep_libei])
dependencies: [dep_libutil, dep_libei, dep_libxkbcommon])
# tests
subproject('munit')

View file

@ -31,10 +31,15 @@
#include <string.h>
#include <stdarg.h>
#if HAVE_LIBXKBCOMMON
#include <xkbcommon/xkbcommon.h>
#endif
#include "libei.h"
#include "src/util-macros.h"
#include "src/util-mem.h"
#include "src/util-memfile.h"
#include "src/util-color.h"
#include "src/util-strings.h"
@ -60,6 +65,48 @@ colorprint(const char *format, ...)
va_end(args);
}
#if HAVE_LIBXKBCOMMON
DEFINE_TRIVIAL_CLEANUP_FUNC(struct xkb_context*, xkb_context_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct xkb_keymap*, xkb_keymap_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct xkb_state*, xkb_state_unref);
#define _cleanup_xkb_context_ _cleanup_(xkb_context_unrefp)
#define _cleanup_xkb_keymap_ _cleanup_(xkb_keymap_unrefp)
#define _cleanup_xkb_state_ _cleanup_(xkb_state_unrefp)
#endif
static void
setup_keymap(struct ei_device *kbd)
{
#if HAVE_LIBXKBCOMMON
_cleanup_xkb_context_ struct xkb_context *ctx =
xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!ctx)
return;
struct xkb_rule_names names = {
.rules = "evdev",
.model = "pc105",
.layout = "fr",
};
_cleanup_xkb_keymap_ struct xkb_keymap *keymap =
xkb_keymap_new_from_names(ctx, &names, 0);
if (!keymap)
return;
const char *str = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
size_t len = strlen(str) - 1;
struct memfile *f = memfile_new(str, len);
if (!f)
return;
ei_device_configure_keymap(kbd, EI_KEYMAP_TYPE_XKB,
memfile_get_fd(f), memfile_get_size(f));
memfile_unref(f);
#endif
}
int main(int argc, char **argv)
{
const char SOCKETNAME[] = "eis-0";
@ -90,6 +137,7 @@ int main(int argc, char **argv)
_cleanup_(ei_device_unrefp) struct ei_device *kbd = ei_device_new(ei);
ei_device_configure_capability(kbd, EI_DEVICE_CAP_KEYBOARD);
setup_keymap(kbd);
bool stop = false;
bool have_ptr = false;
@ -156,9 +204,11 @@ int main(int argc, char **argv)
}
if (have_kbd) {
static int key = 0;
colorprint("sending key event\n");
ei_device_keyboard_key(kbd, 57, true); /* KEY_SPACE */
ei_device_keyboard_key(kbd, 57, false); /* KEY_SPACE */
ei_device_keyboard_key(kbd, 16 + key, true); /* KEY_Q */
ei_device_keyboard_key(kbd, 16 + key, false); /* KEY_Q */
key = (key + 1) % 6;
}
}

View file

@ -29,13 +29,28 @@
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <sys/mman.h>
#if HAVE_LIBXKBCOMMON
#include <xkbcommon/xkbcommon.h>
#endif
#include "libeis.h"
#include "src/util-color.h"
#include "src/util-mem.h"
#include "src/util-memfile.h"
#include "src/util-strings.h"
struct eis_server {
uint32_t pad; /* avoid warning with missing libxkbcommon */
#if HAVE_LIBXKBCOMMON
struct xkb_context *ctx;
struct xkb_keymap *keymap;
struct xkb_state *state;
#endif
};
static bool stop = false;
static void sighandler(int signal) {
@ -71,8 +86,71 @@ colorprint(const char *format, ...)
va_end(args);
}
#if HAVE_LIBXKBCOMMON
DEFINE_TRIVIAL_CLEANUP_FUNC(struct xkb_context*, xkb_context_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct xkb_keymap*, xkb_keymap_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct xkb_state*, xkb_state_unref);
#define _cleanup_xkb_context_ _cleanup_(xkb_context_unrefp)
#define _cleanup_xkb_keymap_ _cleanup_(xkb_keymap_unrefp)
#define _cleanup_xkb_state_ _cleanup_(xkb_state_unrefp)
#endif
static void
setup_keymap(struct eis_server *server, struct eis_device *device)
{
#if HAVE_LIBXKBCOMMON
if (eis_device_get_keymap_type(device) == EIS_KEYMAP_TYPE_NONE)
return;
colorprint("Using client keymap\n");
int fd = eis_device_get_keymap(device);
size_t size = eis_device_get_keymap_size(device);
char *str = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
if (str == MAP_FAILED)
return;
_cleanup_xkb_context_ struct xkb_context *ctx =
xkb_context_new(XKB_CONTEXT_NO_FLAGS);
if (!ctx)
return;
_cleanup_xkb_keymap_ struct xkb_keymap *keymap =
xkb_keymap_new_from_string(ctx, str,
XKB_KEYMAP_FORMAT_TEXT_V1, 0);
if (!keymap)
return;
_cleanup_xkb_state_ struct xkb_state *state = xkb_state_new(keymap);
if (!state)
return;
server->ctx = steal(&ctx);
server->keymap = steal(&keymap);
server->state = steal(&state);
#endif
}
static void
handle_key(struct eis_server *server, uint32_t keycode, bool is_press)
{
char keysym_name[64] = {0};
#if HAVE_LIBXKBCOMMON
if (server->state) {
uint32_t xkbkc = keycode + 8;
xkb_state_update_key(server->state, xkbkc, is_press ? XKB_KEY_DOWN : XKB_KEY_UP);
xkb_state_key_get_utf8(server->state, xkbkc, keysym_name, sizeof(keysym_name));
}
#endif
colorprint("key %d (%s) [%s]\n",
keycode, is_press ? "press" : "release",
keysym_name);
}
int main(int argc, char **argv)
{
struct eis_server server = {0};
_cleanup_(eis_unrefp) struct eis *eis = eis_new(NULL);
assert(eis);
@ -137,6 +215,7 @@ int main(int argc, char **argv)
eis_device_has_capability(device, EIS_DEVICE_CAP_KEYBOARD) ? " kbd" : "",
eis_device_has_capability(device, EIS_DEVICE_CAP_POINTER_ABSOLUTE) ? " abs" : "",
eis_device_has_capability(device, EIS_DEVICE_CAP_TOUCH) ? " touch" : "");
setup_keymap(&server, device);
/* insert sophisticated device checks here */
eis_device_connect(device);
eis_device_resume(device);
@ -163,9 +242,9 @@ int main(int argc, char **argv)
break;
case EIS_EVENT_KEYBOARD_KEY:
{
colorprint("key %d (%s)\n",
eis_event_keyboard_get_key(e),
eis_event_keyboard_get_key_is_press(e) ? "press" : "release");
handle_key(&server,
eis_event_keyboard_get_key(e),
eis_event_keyboard_get_key_is_press(e));
}
break;
default: