swc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/swc
Log | Files | Refs | README | LICENSE

commit acec51090e74b672ed4489ad1bcaa6ba6264eae6
parent bba112e9c73e713d938cf512fa7a7232650df24a
Author: Michael Forney <mforney@mforney.org>
Date:   Sat, 11 Mar 2017 14:42:29 -0800

Make libinput a hard dependency

I am not interested in maintaining the direct evdev device handling, nor
implementing touchpad support. However, libinput has a hard libudev
dependency, even with the path-seat.

To resolve this, I branched libinput to remove the libinput dependency,
and made libinput a hard dependency in swc. Now, ENABLE_LIBINPUT
controls whether or not device hotplugging should be supported,
otherwise path-seat is used.

Diffstat:
MREADME.md | 6+++---
Mconfig.mk | 2+-
Dlibswc/evdev_device.c | 355-------------------------------------------------------------------------------
Dlibswc/evdev_device.h | 78------------------------------------------------------------------------------
Mlibswc/local.mk | 11++++-------
Mlibswc/seat.c | 230++++++++++++++++++++++++++++++-------------------------------------------------
6 files changed, 95 insertions(+), 587 deletions(-)

diff --git a/README.md b/README.md @@ -14,14 +14,14 @@ Dependencies * wayland * wayland-protocols * libdrm -* libevdev +* libinput (see my [libinput repository](https://github.com/michaelforney/libinput) + if you don't want the libudev dependency) * libxkbcommon * pixman * [wld](http://github.com/michaelforney/wld) * linux\[>=3.12\] (for EVIOCREVOKE) -For input hotplugging and touchpad support, the following is also required: -* libinput +For input hotplugging, the following is also required: * libudev For XWayland support, the following are also required: diff --git a/config.mk b/config.mk @@ -18,6 +18,6 @@ CFLAGS = -pipe ENABLE_DEBUG = 1 ENABLE_STATIC = 1 ENABLE_SHARED = 1 -ENABLE_LIBINPUT = 1 +ENABLE_LIBUDEV = 1 ENABLE_XWAYLAND = 1 diff --git a/libswc/evdev_device.c b/libswc/evdev_device.c @@ -1,355 +0,0 @@ -/* swc: libswc/evdev_device.c - * - * Copyright (c) 2013, 2014 Michael Forney - * - * Based in part upon evdev.c from weston, which is: - * - * Copyright © 2010 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "evdev_device.h" -#include "event.h" -#include "internal.h" -#include "launch.h" -#include "seat.h" -#include "util.h" - -#include <errno.h> -#include <fcntl.h> -#include <libevdev/libevdev.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <unistd.h> - -#define AXIS_STEP_DISTANCE 10 -#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) - -static inline uint32_t -timeval_to_msec(struct timeval *time) -{ - return time->tv_sec * 1000 + time->tv_usec / 1000; -} - -static void -handle_key_event(struct evdev_device *device, struct input_event *ev) -{ - uint32_t time = timeval_to_msec(&ev->time); - uint32_t state; - - if ((ev->code >= BTN_MISC && ev->code <= BTN_GEAR_UP) || ev->code >= BTN_TRIGGER_HAPPY) { - state = ev->value ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED; - device->handler->button(time, ev->code, state); - if (state == WL_POINTER_BUTTON_STATE_PRESSED) { - /* qemu generates GEAR_UP/GEAR_DOWN events on scroll, so - * pass those through as axis events. */ - switch (ev->code) { - case BTN_GEAR_DOWN: - device->handler->axis(time, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(AXIS_STEP_DISTANCE)); - break; - case BTN_GEAR_UP: - device->handler->axis(time, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(-AXIS_STEP_DISTANCE)); - break; - } - } - } else { - state = ev->value ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED; - device->handler->key(time, ev->code, state); - } -} - -static void -handle_rel_event(struct evdev_device *device, struct input_event *ev) -{ - uint32_t time = timeval_to_msec(&ev->time); - uint32_t axis, amount; - - if (!(device->capabilities & WL_SEAT_CAPABILITY_POINTER)) - return; - - switch (ev->code) { - case REL_X: - device->rel.dx += ev->value; - device->rel.pending = true; - return; - case REL_Y: - device->rel.dy += ev->value; - device->rel.pending = true; - return; - case REL_WHEEL: - axis = WL_POINTER_AXIS_VERTICAL_SCROLL; - amount = -AXIS_STEP_DISTANCE * wl_fixed_from_int(ev->value); - break; - case REL_HWHEEL: - axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL; - amount = AXIS_STEP_DISTANCE * wl_fixed_from_int(ev->value); - break; - default: - return; - } - - device->handler->axis(time, axis, amount); -} - -static void -handle_abs_event(struct evdev_device *device, struct input_event *ev) -{ - if (!(device->capabilities & WL_SEAT_CAPABILITY_POINTER)) - return; - - switch (ev->code) { - case ABS_X: - device->abs.x = ev->value; - device->abs.pending = true; - break; - case ABS_Y: - device->abs.y = ev->value; - device->abs.pending = true; - break; - } -} - -static void (*event_handlers[])(struct evdev_device *device, struct input_event *ev) = { - [EV_KEY] = handle_key_event, - [EV_REL] = handle_rel_event, - [EV_ABS] = handle_abs_event, -}; - -static bool -is_motion_event(struct input_event *ev) -{ - return (ev->type == EV_REL && (ev->code == REL_X || ev->code == REL_Y)) - || (ev->type == EV_ABS && (ev->code == ABS_X || ev->code == ABS_Y)); -} - -static void -handle_motion_events(struct evdev_device *device, uint32_t time) -{ - if (device->abs.pending) { - int32_t x = device->abs.x - device->abs.info.x->minimum; - int32_t max_x = device->abs.info.x->maximum - device->abs.info.x->minimum; - int32_t y = device->abs.y - device->abs.info.y->minimum; - int32_t max_y = device->abs.info.y->maximum - device->abs.info.y->minimum; - - device->handler->absolute_motion(time, x, max_x, y, max_y); - device->abs.pending = false; - } - if (device->rel.pending) { - wl_fixed_t dx = wl_fixed_from_int(device->rel.dx); - wl_fixed_t dy = wl_fixed_from_int(device->rel.dy); - - device->handler->relative_motion(time, dx, dy); - device->rel.pending = false; - device->rel.dx = 0; - device->rel.dy = 0; - } -} - -static void -handle_event(struct evdev_device *device, struct input_event *ev) -{ - if (!is_motion_event(ev)) - handle_motion_events(device, timeval_to_msec(&ev->time)); - - if (ev->type < ARRAY_SIZE(event_handlers) && event_handlers[ev->type]) - event_handlers[ev->type](device, ev); -} - -static void -close_device(struct evdev_device *device) -{ - wl_event_source_remove(device->source); - close(device->fd); - device->source = NULL; - device->fd = -1; -} - -static int -handle_data(int fd, uint32_t mask, void *data) -{ - struct evdev_device *device = data; - struct input_event event; - unsigned flags = device->needs_sync ? LIBEVDEV_READ_FLAG_FORCE_SYNC : LIBEVDEV_READ_FLAG_NORMAL; - int ret; - - device->needs_sync = false; - - for (;;) { - ret = libevdev_next_event(device->dev, flags, &event); - - switch (ret) { - case LIBEVDEV_READ_STATUS_SUCCESS: - handle_event(device, &event); - break; - case LIBEVDEV_READ_STATUS_SYNC: - while (ret == LIBEVDEV_READ_STATUS_SYNC) { - ret = libevdev_next_event(device->dev, LIBEVDEV_READ_FLAG_SYNC, &event); - - if (ret < 0) - goto done; - - handle_event(device, &event); - } - break; - default: - goto done; - } - } - -done: - if (ret == -ENODEV) - close_device(device); - - handle_motion_events(device, timeval_to_msec(&event.time)); - - return 1; -} - -struct evdev_device * -evdev_device_new(const char *path, const struct evdev_device_handler *handler) -{ - struct evdev_device *device; - - if (!(device = malloc(sizeof *device))) - goto error0; - - device->fd = launch_open_device(path, O_RDWR | O_NONBLOCK | O_CLOEXEC); - - if (device->fd == -1) { - ERROR("Failed to open input device at %s\n", path); - goto error1; - } - - if (!(device->path = strdup(path))) - goto error2; - - if (libevdev_new_from_fd(device->fd, &device->dev) != 0) { - ERROR("Failed to create libevdev device\n"); - goto error3; - } - - if (libevdev_set_clock_id(device->dev, CLOCK_MONOTONIC) != 0) { - ERROR("Failed to set libevdev device to monotonic clock\n"); - goto error4; - } - - device->source = wl_event_loop_add_fd(swc.event_loop, device->fd, WL_EVENT_READABLE, handle_data, device); - - if (!device->source) { - ERROR("Failed to add event source\n"); - goto error4; - } - - DEBUG("Adding device %s\n", libevdev_get_name(device->dev)); - - device->needs_sync = false; - device->handler = handler; - device->capabilities = 0; - device->abs.info.x = libevdev_get_abs_info(device->dev, ABS_X); - device->abs.info.y = libevdev_get_abs_info(device->dev, ABS_Y); - device->abs.pending = false; - memset(&device->rel, 0, sizeof(device->rel)); - - if (libevdev_has_event_code(device->dev, EV_KEY, KEY_ENTER)) { - device->capabilities |= WL_SEAT_CAPABILITY_KEYBOARD; - DEBUG("\tThis device is a keyboard\n"); - } - - if (libevdev_has_event_code(device->dev, EV_REL, REL_X) - && libevdev_has_event_code(device->dev, EV_REL, REL_Y) - && libevdev_has_event_code(device->dev, EV_KEY, BTN_MOUSE)) - { - device->capabilities |= WL_SEAT_CAPABILITY_POINTER; - DEBUG("\tThis device is a pointer\n"); - } - - if (libevdev_has_event_code(device->dev, EV_ABS, ABS_X) - && libevdev_has_event_code(device->dev, EV_ABS, ABS_Y) - && libevdev_has_event_code(device->dev, EV_KEY, BTN_MOUSE) - && !libevdev_has_event_code(device->dev, EV_KEY, BTN_TOOL_FINGER)) - { - device->capabilities |= WL_SEAT_CAPABILITY_POINTER; - } - - /* XXX: touch devices */ - - return device; - -error4: - libevdev_free(device->dev); -error3: - free(device->path); -error2: - close(device->fd); -error1: - free(device); -error0: - return NULL; -} - -void -evdev_device_destroy(struct evdev_device *device) -{ - if (device->source) - close_device(device); - - libevdev_free(device->dev); - free(device->path); - free(device); -} - -bool -evdev_device_reopen(struct evdev_device *device) -{ - if (device->source) - close_device(device); - - device->fd = launch_open_device(device->path, O_RDWR | O_NONBLOCK | O_CLOEXEC); - - if (device->fd == -1) { - WARNING("Failed to reopen input device at %s: %s\n", device->path, strerror(errno)); - goto error0; - } - - if (libevdev_change_fd(device->dev, device->fd) == -1) { - ERROR("Failed to update libevdev fd\n"); - goto error1; - } - - /* According to libevdev documentation, after changing the fd for the device, - * you should force a sync to bring it's state up to date. */ - device->needs_sync = true; - device->source = wl_event_loop_add_fd(swc.event_loop, device->fd, WL_EVENT_READABLE, handle_data, device); - - if (!device->source) { - ERROR("Failed to create event source\n"); - goto error1; - } - - return true; - -error1: - close(device->fd); - device->fd = -1; -error0: - return false; -} diff --git a/libswc/evdev_device.h b/libswc/evdev_device.h @@ -1,78 +0,0 @@ -/* swc: libswc/evdev_device.h - * - * Copyright (c) 2013 Michael Forney - * - * Based in part upon evdev.h from weston, which is: - * - * Copyright © 2011, 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef SWC_EVDEV_DEVICE_H -#define SWC_EVDEV_DEVICE_H - -#include <stdbool.h> -#include <linux/input.h> -#include <wayland-util.h> - -struct evdev_device; -struct wl_event_loop; - -struct evdev_device_handler { - void (*key)(uint32_t time, uint32_t key, uint32_t state); - void (*button)(uint32_t time, uint32_t key, uint32_t state); - void (*axis)(uint32_t time, uint32_t axis, wl_fixed_t amount); - void (*relative_motion)(uint32_t time, wl_fixed_t dx, wl_fixed_t dy); - void (*absolute_motion)(uint32_t time, int32_t x, int32_t y, int32_t max_x, int32_t max_y); -}; - -struct evdev_device { - char *path; - int fd; - struct libevdev *dev; - bool needs_sync; - - const struct evdev_device_handler *handler; - - struct { - struct { - const struct input_absinfo *x, *y; - } info; - - int32_t x, y; - bool pending; - } abs; - - struct { - int32_t dx, dy; - bool pending; - } rel; - - uint32_t capabilities; - - struct wl_event_source *source; - struct wl_list link; -}; - -struct evdev_device *evdev_device_new(const char *path, const struct evdev_device_handler *handler); -void evdev_device_destroy(struct evdev_device *device); -bool evdev_device_reopen(struct evdev_device *device); - -#endif diff --git a/libswc/local.mk b/libswc/local.mk @@ -17,7 +17,7 @@ $(dir)_TARGETS += \ $(dir)/$(LIBSWC_LINK) endif -$(dir)_PACKAGES := libdrm libevdev pixman-1 wayland-server wld xkbcommon +$(dir)_PACKAGES := libdrm libinput pixman-1 wayland-server wld xkbcommon $(dir)_CFLAGS += -Iprotocol SWC_SOURCES = \ @@ -59,11 +59,9 @@ SWC_SOURCES = \ protocol/wayland-drm-protocol.c \ protocol/xdg-shell-unstable-v5-protocol.c -ifeq ($(ENABLE_LIBINPUT),1) -$(dir)_CFLAGS += -DENABLE_LIBINPUT -$(dir)_PACKAGES += libinput libudev -else -SWC_SOURCES += libswc/evdev_device.c +ifeq ($(ENABLE_LIBUDEV),1) +$(dir)_CFLAGS += -DENABLE_LIBUDEV +$(dir)_PACKAGES += libudev endif ifeq ($(ENABLE_XWAYLAND),1) @@ -121,4 +119,3 @@ install-$(dir): $($(dir)_TARGETS:$(dir)/%=install-%) | $(DESTDIR)$(INCLUDEDIR) CLEAN_FILES += $(SWC_SHARED_OBJECTS) $(SWC_STATIC_OBJECTS) include common.mk - diff --git a/libswc/seat.c b/libswc/seat.c @@ -24,7 +24,6 @@ #include "seat.h" #include "compositor.h" #include "data_device.h" -#include "evdev_device.h" #include "event.h" #include "internal.h" #include "keyboard.h" @@ -34,27 +33,28 @@ #include "surface.h" #include "util.h" -#include <errno.h> #include <dirent.h> -#include <stdlib.h> +#include <errno.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> -#ifdef ENABLE_LIBINPUT + +#include <libinput.h> +#include <linux/input.h> +#ifdef ENABLE_LIBUDEV # include <libudev.h> -# include <libinput.h> #endif static struct { char *name; uint32_t capabilities; -#ifdef ENABLE_LIBINPUT - struct udev *udev; struct libinput *libinput; struct wl_event_source *libinput_source; -#else - struct wl_list devices; + +#ifdef ENABLE_LIBUDEV + struct udev *udev; #endif struct wl_listener swc_listener; @@ -74,41 +74,6 @@ const struct swc_seat swc_seat = { }; static void -handle_key(uint32_t time, uint32_t key, uint32_t state) -{ - keyboard_handle_key(&seat.keyboard, time, key, state); -} - -static void -handle_button(uint32_t time, uint32_t button, uint32_t state) -{ - pointer_handle_button(&seat.pointer, time, button, state); -} - -static void -handle_axis(uint32_t time, uint32_t axis, wl_fixed_t amount) -{ - pointer_handle_axis(&seat.pointer, time, axis, amount); -} - -static void -handle_relative_motion(uint32_t time, wl_fixed_t dx, wl_fixed_t dy) -{ - pointer_handle_relative_motion(&seat.pointer, time, dx, dy); -} - -static void -handle_absolute_motion(uint32_t time, int32_t x, int32_t max_x, int32_t y, int32_t max_y) -{ - struct screen *screen = wl_container_of(swc.screens.next, screen, link); - struct swc_rectangle *rect = &screen->base.geometry; - wl_fixed_t fx = wl_fixed_from_int(x * rect->width / max_x + rect->x); - wl_fixed_t fy = wl_fixed_from_int(y * rect->height / max_y + rect->y); - - pointer_handle_absolute_motion(&seat.pointer, time, fx, fy); -} - -static void handle_keyboard_focus_event(struct wl_listener *listener, void *data) { struct event *ev = data; @@ -151,30 +116,15 @@ static void handle_swc_event(struct wl_listener *listener, void *data) { struct event *ev = data; -#ifndef ENABLE_LIBINPUT - struct evdev_device *device, *next; -#endif switch (ev->type) { case SWC_EVENT_DEACTIVATED: -#ifdef ENABLE_LIBINPUT libinput_suspend(seat.libinput); -#endif keyboard_reset(&seat.keyboard); break; case SWC_EVENT_ACTIVATED: -#ifdef ENABLE_LIBINPUT if (libinput_resume(seat.libinput) != 0) WARNING("Failed to resume libinput context\n"); -#else - /* Re-open all input devices */ - wl_list_for_each_safe (device, next, &seat.devices, link) { - if (!evdev_device_reopen(device)) { - wl_list_remove(&device->link); - evdev_device_destroy(device); - } - } -#endif break; } } @@ -235,7 +185,6 @@ update_capabilities(uint32_t capabilities) wl_seat_send_capabilities(resource, seat.capabilities); } -#ifdef ENABLE_LIBINPUT static int open_restricted(const char *path, int flags, void *user_data) { @@ -273,19 +222,28 @@ device_capabilities(struct libinput_device *device) static void handle_libinput_axis_event(struct libinput_event_pointer *event, enum libinput_pointer_axis axis) { - double amount; + wl_fixed_t amount; if (!libinput_event_pointer_has_axis(event, axis)) return; - amount = libinput_event_pointer_get_axis_value(event, axis); - handle_axis(libinput_event_pointer_get_time(event), axis, wl_fixed_from_double(amount)); + amount = wl_fixed_from_double(libinput_event_pointer_get_axis_value(event, axis)); + pointer_handle_axis(&seat.pointer, libinput_event_pointer_get_time(event), axis, amount); } static int handle_libinput_data(int fd, uint32_t mask, void *data) { + struct screen *screen; + struct swc_rectangle *rect; struct libinput_event *generic_event; + struct libinput_device *device; + union { + struct libinput_event_keyboard *k; + struct libinput_event_pointer *p; + } event; + wl_fixed_t x, y; + uint32_t time, key, state; if (libinput_dispatch(seat.libinput) != 0) { WARNING("libinput_dispatch failed: %s\n", strerror(errno)); @@ -294,49 +252,57 @@ handle_libinput_data(int fd, uint32_t mask, void *data) while ((generic_event = libinput_get_event(seat.libinput))) { switch (libinput_event_get_type(generic_event)) { - case LIBINPUT_EVENT_DEVICE_ADDED: { - struct libinput_device *device; - + case LIBINPUT_EVENT_DEVICE_ADDED: device = libinput_event_get_device(generic_event); update_capabilities(device_capabilities(device)); break; - } - case LIBINPUT_EVENT_KEYBOARD_KEY: { - struct libinput_event_keyboard *event; - - event = libinput_event_get_keyboard_event(generic_event); - handle_key(libinput_event_keyboard_get_time(event), - libinput_event_keyboard_get_key(event), - libinput_event_keyboard_get_key_state(event)); + case LIBINPUT_EVENT_KEYBOARD_KEY: + event.k = libinput_event_get_keyboard_event(generic_event); + time = libinput_event_keyboard_get_time(event.k); + key = libinput_event_keyboard_get_key(event.k); + state = libinput_event_keyboard_get_key_state(event.k); + keyboard_handle_key(&seat.keyboard, time, key, state); break; - } - case LIBINPUT_EVENT_POINTER_MOTION: { - struct libinput_event_pointer *event; - wl_fixed_t dx, dy; - - event = libinput_event_get_pointer_event(generic_event); - dx = wl_fixed_from_double(libinput_event_pointer_get_dx(event)); - dy = wl_fixed_from_double(libinput_event_pointer_get_dy(event)); - handle_relative_motion(libinput_event_pointer_get_time(event), dx, dy); + case LIBINPUT_EVENT_POINTER_MOTION: + event.p = libinput_event_get_pointer_event(generic_event); + time = libinput_event_pointer_get_time(event.p); + x = wl_fixed_from_double(libinput_event_pointer_get_dx(event.p)); + y = wl_fixed_from_double(libinput_event_pointer_get_dy(event.p)); + pointer_handle_relative_motion(&seat.pointer, time, x, y); break; - } - case LIBINPUT_EVENT_POINTER_BUTTON: { - struct libinput_event_pointer *event; - - event = libinput_event_get_pointer_event(generic_event); - handle_button(libinput_event_pointer_get_time(event), - libinput_event_pointer_get_button(event), - libinput_event_pointer_get_button_state(event)); + case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE: + screen = wl_container_of(swc.screens.next, screen, link); + rect = &screen->base.geometry; + event.p = libinput_event_get_pointer_event(generic_event); + time = libinput_event_pointer_get_time(event.p); + x = wl_fixed_from_double(libinput_event_pointer_get_absolute_x_transformed(event.p, rect->width)); + y = wl_fixed_from_double(libinput_event_pointer_get_absolute_y_transformed(event.p, rect->height)); + pointer_handle_absolute_motion(&seat.pointer, time, x, y); break; - } - case LIBINPUT_EVENT_POINTER_AXIS: { - struct libinput_event_pointer *event; - - event = libinput_event_get_pointer_event(generic_event); - handle_libinput_axis_event(event, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); - handle_libinput_axis_event(event, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); + case LIBINPUT_EVENT_POINTER_BUTTON: + event.p = libinput_event_get_pointer_event(generic_event); + time = libinput_event_pointer_get_time(event.p); + key = libinput_event_pointer_get_button(event.p); + state = libinput_event_pointer_get_button_state(event.p); + pointer_handle_button(&seat.pointer, time, key, state); + if (state == LIBINPUT_BUTTON_STATE_PRESSED) { + /* qemu generates GEAR_UP/GEAR_DOWN events on scroll, so pass + * those through as axis events. */ + switch (key) { + case BTN_GEAR_DOWN: + pointer_handle_axis(&seat.pointer, time, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(10)); + break; + case BTN_GEAR_UP: + pointer_handle_axis(&seat.pointer, time, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(-10)); + break; + } + } + break; + case LIBINPUT_EVENT_POINTER_AXIS: + event.p = libinput_event_get_pointer_event(generic_event); + handle_libinput_axis_event(event.p, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL); + handle_libinput_axis_event(event.p, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL); break; - } default: break; } @@ -350,22 +316,28 @@ handle_libinput_data(int fd, uint32_t mask, void *data) bool initialize_libinput(const char *seat_name) { +#ifdef ENABLE_LIBUDEV if (!(seat.udev = udev_new())) { ERROR("Could not create udev context\n"); goto error0; } seat.libinput = libinput_udev_create_context(&libinput_interface, NULL, seat.udev); +#else + seat.libinput = libinput_path_create_context(&libinput_interface, NULL); +#endif if (!seat.libinput) { ERROR("Could not create libinput context\n"); goto error1; } +#ifdef ENABLE_LIBUDEV if (libinput_udev_assign_seat(seat.libinput, seat_name) != 0) { ERROR("Failed to assign seat to libinput context\n"); goto error2; } +#endif seat.libinput_source = wl_event_loop_add_fd (swc.event_loop, libinput_get_fd(seat.libinput), WL_EVENT_READABLE, @@ -384,41 +356,14 @@ initialize_libinput(const char *seat_name) error2: libinput_unref(seat.libinput); error1: +#ifdef ENABLE_LIBUDEV udev_unref(seat.udev); error0: +#endif return false; } -void -finalize_libinput(void) -{ - wl_event_source_remove(seat.libinput_source); - libinput_unref(seat.libinput); - udev_unref(seat.udev); -} -#else -const static struct evdev_device_handler evdev_handler = { - .key = handle_key, - .button = handle_button, - .axis = handle_axis, - .relative_motion = handle_relative_motion, - .absolute_motion = handle_absolute_motion, -}; - -static void -add_device(const char *path) -{ - struct evdev_device *device; - - if (!(device = evdev_device_new(path, &evdev_handler))) { - ERROR("Could not create evdev device\n"); - return; - } - - update_capabilities(device->capabilities); - wl_list_insert(&seat.devices, &device->link); -} - +#ifndef ENABLE_LIBUDEV static int select_device(const struct dirent *entry) { @@ -430,20 +375,23 @@ static bool add_devices(void) { struct dirent **devices; - int i, num_devices; + int i, n; char path[64]; + struct libinput_device *device; - num_devices = scandir("/dev/input", &devices, &select_device, &alphasort); + n = scandir("/dev/input", &devices, &select_device, &alphasort); - if (num_devices == -1) { + if (n == -1) { ERROR("Failed to scan /dev/input for event devices\n"); return false; } - for (i = 0; i < num_devices; ++i) { + for (i = 0; i < n; ++i) { snprintf(path, sizeof path, "/dev/input/%s", devices[i]->d_name); free(devices[i]); - add_device(path); + device = libinput_path_add_device(seat.libinput, path); + if (device) + update_capabilities(device_capabilities(device)); } free(devices); @@ -489,12 +437,10 @@ seat_initialize(const char *seat_name) goto error4; } -#ifdef ENABLE_LIBINPUT if (!initialize_libinput(seat.name)) goto error5; -#else - wl_list_init(&seat.devices); +#ifndef ENABLE_LIBUDEV if (!add_devices()) goto error5; #endif @@ -518,12 +464,10 @@ error0: void seat_finalize(void) { -#ifdef ENABLE_LIBINPUT - finalize_libinput(); -#else - struct evdev_device *device, *tmp; - wl_list_for_each_safe (device, tmp, &seat.devices, link) - evdev_device_destroy(device); + wl_event_source_remove(seat.libinput_source); + libinput_unref(seat.libinput); +#ifdef ENABLE_LIBUDEV + udev_unref(seat.udev); #endif pointer_finalize(&seat.pointer);