[RFC/PATCH weston 3/3] Use libinput for handling evdev input devices
Jonas Ådahl
jadahl at gmail.com
Tue Nov 12 13:55:07 PST 2013
Instead of having all the input device processing in weston, use
libinput to handle the evdev devices and all the processing.
Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
---
configure.ac | 6 +-
src/Makefile.am | 5 +-
src/compositor-rpi.c | 4 +-
src/evdev-touchpad.c | 800 ---------------------------------------------------
src/evdev.c | 727 +++++++++++++---------------------------------
src/evdev.h | 82 +-----
src/udev-seat.c | 37 ++-
7 files changed, 221 insertions(+), 1440 deletions(-)
delete mode 100644 src/evdev-touchpad.c
diff --git a/configure.ac b/configure.ac
index 41ce9ad..e87638f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -144,7 +144,7 @@ AC_ARG_ENABLE(drm-compositor, [ --enable-drm-compositor],,
AM_CONDITIONAL(ENABLE_DRM_COMPOSITOR, test x$enable_drm_compositor = xyes -a x$enable_egl = xyes)
if test x$enable_drm_compositor = xyes -a x$enable_egl = xyes; then
AC_DEFINE([BUILD_DRM_COMPOSITOR], [1], [Build the DRM compositor])
- PKG_CHECK_MODULES(DRM_COMPOSITOR, [libudev >= 136 libdrm >= 2.4.30 gbm mtdev >= 1.1.0])
+ PKG_CHECK_MODULES(DRM_COMPOSITOR, [libudev >= 136 libdrm >= 2.4.30 gbm libinput >= 0.0.90])
# For libdrm usage in launcher-util.c
COMPOSITOR_MODULES="$COMPOSITOR_MODULES libdrm"
@@ -177,7 +177,7 @@ AM_CONDITIONAL(ENABLE_RPI_COMPOSITOR, test "x$enable_rpi_compositor" = "xyes")
have_bcm_host="no"
if test "x$enable_rpi_compositor" = "xyes"; then
AC_DEFINE([BUILD_RPI_COMPOSITOR], [1], [Build the compositor for Raspberry Pi])
- PKG_CHECK_MODULES(RPI_COMPOSITOR, [libudev >= 136 mtdev >= 1.1.0])
+ PKG_CHECK_MODULES(RPI_COMPOSITOR, [libudev >= 136 libinput >= 0.0.90])
PKG_CHECK_MODULES(RPI_BCM_HOST, [bcm_host],
[have_bcm_host="yes"
AC_DEFINE([HAVE_BCM_HOST], [1], [have Raspberry Pi BCM headers])],
@@ -192,7 +192,7 @@ AM_CONDITIONAL([ENABLE_FBDEV_COMPOSITOR],
[test x$enable_fbdev_compositor = xyes])
AS_IF([test x$enable_fbdev_compositor = xyes], [
AC_DEFINE([BUILD_FBDEV_COMPOSITOR], [1], [Build the fbdev compositor])
- PKG_CHECK_MODULES([FBDEV_COMPOSITOR], [libudev >= 136 mtdev >= 1.1.0])
+ PKG_CHECK_MODULES([FBDEV_COMPOSITOR], [libudev >= 136 libinput >= 0.0.90])
])
AC_ARG_ENABLE([rdp-compositor], [ --enable-rdp-compositor],,
diff --git a/src/Makefile.am b/src/Makefile.am
index 9925129..8dcba63 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -174,7 +174,6 @@ drm_backend_la_SOURCES = \
udev-seat.h \
evdev.c \
evdev.h \
- evdev-touchpad.c \
launcher-util.c \
launcher-util.h \
libbacklight.c \
@@ -222,8 +221,7 @@ rpi_backend_la_SOURCES = \
launcher-util.c \
launcher-util.h \
evdev.c \
- evdev.h \
- evdev-touchpad.c
+ evdev.h
if ENABLE_EGL
rpi_backend_la_LIBADD += $(EGL_LIBS)
@@ -262,7 +260,6 @@ fbdev_backend_la_SOURCES = \
udev-seat.h \
evdev.c \
evdev.h \
- evdev-touchpad.c \
launcher-util.c \
launcher-util.h
endif
diff --git a/src/compositor-rpi.c b/src/compositor-rpi.c
index f163e01..d714b18 100644
--- a/src/compositor-rpi.c
+++ b/src/compositor-rpi.c
@@ -530,8 +530,8 @@ evdev_udev_handler(int fd, uint32_t mask, void *data)
devnode = udev_device_get_devnode(udev_device);
wl_list_for_each_safe(device, next, &seat->devices_list, link)
if (!strcmp(device->devnode, devnode)) {
- weston_log("input device %s, %s removed\n",
- device->devname, device->devnode);
+ weston_log("input device %s removed\n",
+ device->devnode);
evdev_device_destroy(device);
break;
}
diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c
deleted file mode 100644
index 69f913a..0000000
--- a/src/evdev-touchpad.c
+++ /dev/null
@@ -1,800 +0,0 @@
-/*
- * Copyright © 2012 Jonas Ådahl
- *
- * Permission to use, copy, modify, distribute, and sell this software and
- * its documentation for any purpose is hereby granted without fee, provided
- * that the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of the copyright holders not be used in
- * advertising or publicity pertaining to distribution of the software
- * without specific, written prior permission. The copyright holders make
- * no representations about the suitability of this software for any
- * purpose. It is provided "as is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
- * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
- * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
- * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
- * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <linux/input.h>
-
-#include "filter.h"
-#include "evdev.h"
-#include "../shared/config-parser.h"
-
-/* Default values */
-#define DEFAULT_CONSTANT_ACCEL_NUMERATOR 50
-#define DEFAULT_MIN_ACCEL_FACTOR 0.16
-#define DEFAULT_MAX_ACCEL_FACTOR 1.0
-#define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
-
-#define DEFAULT_TOUCHPAD_SINGLE_TAP_BUTTON BTN_LEFT
-#define DEFAULT_TOUCHPAD_SINGLE_TAP_TIMEOUT 100
-
-enum touchpad_model {
- TOUCHPAD_MODEL_UNKNOWN = 0,
- TOUCHPAD_MODEL_SYNAPTICS,
- TOUCHPAD_MODEL_ALPS,
- TOUCHPAD_MODEL_APPLETOUCH,
- TOUCHPAD_MODEL_ELANTECH
-};
-
-enum touchpad_event {
- TOUCHPAD_EVENT_NONE = 0,
- TOUCHPAD_EVENT_ABSOLUTE_ANY = (1 << 0),
- TOUCHPAD_EVENT_ABSOLUTE_X = (1 << 1),
- TOUCHPAD_EVENT_ABSOLUTE_Y = (1 << 2),
- TOUCHPAD_EVENT_REPORT = (1 << 3)
-};
-
-struct touchpad_model_spec {
- short vendor;
- short product;
- enum touchpad_model model;
-};
-
-static struct touchpad_model_spec touchpad_spec_table[] = {
- {0x0002, 0x0007, TOUCHPAD_MODEL_SYNAPTICS},
- {0x0002, 0x0008, TOUCHPAD_MODEL_ALPS},
- {0x05ac, 0x0000, TOUCHPAD_MODEL_APPLETOUCH},
- {0x0002, 0x000e, TOUCHPAD_MODEL_ELANTECH},
- {0x0000, 0x0000, TOUCHPAD_MODEL_UNKNOWN}
-};
-
-enum touchpad_state {
- TOUCHPAD_STATE_NONE = 0,
- TOUCHPAD_STATE_TOUCH = (1 << 0),
- TOUCHPAD_STATE_MOVE = (1 << 1)
-};
-
-#define TOUCHPAD_HISTORY_LENGTH 4
-
-struct touchpad_motion {
- int32_t x;
- int32_t y;
-};
-
-enum touchpad_fingers_state {
- TOUCHPAD_FINGERS_ONE = (1 << 0),
- TOUCHPAD_FINGERS_TWO = (1 << 1),
- TOUCHPAD_FINGERS_THREE = (1 << 2)
-};
-
-enum fsm_event {
- FSM_EVENT_TOUCH,
- FSM_EVENT_RELEASE,
- FSM_EVENT_MOTION,
- FSM_EVENT_TIMEOUT
-};
-
-enum fsm_state {
- FSM_IDLE,
- FSM_TOUCH,
- FSM_TAP,
- FSM_TAP_2,
- FSM_DRAG
-};
-
-struct touchpad_dispatch {
- struct evdev_dispatch base;
- struct evdev_device *device;
-
- enum touchpad_model model;
- unsigned int state;
- int finger_state;
- int last_finger_state;
-
- double constant_accel_factor;
- double min_accel_factor;
- double max_accel_factor;
-
- unsigned int event_mask;
- unsigned int event_mask_filter;
-
- int reset;
-
- struct {
- bool enable;
-
- struct wl_array events;
- enum fsm_state state;
- struct wl_event_source *timer_source;
- } fsm;
-
- struct {
- int32_t x;
- int32_t y;
- } hw_abs;
-
- int has_pressure;
- struct {
- int32_t touch_low;
- int32_t touch_high;
- } pressure;
-
- struct {
- int32_t margin_x;
- int32_t margin_y;
- int32_t center_x;
- int32_t center_y;
- } hysteresis;
-
- struct touchpad_motion motion_history[TOUCHPAD_HISTORY_LENGTH];
- int motion_index;
- unsigned int motion_count;
-
- struct weston_motion_filter *filter;
-};
-
-static enum touchpad_model
-get_touchpad_model(struct evdev_device *device)
-{
- struct input_id id;
- unsigned int i;
-
- if (ioctl(device->fd, EVIOCGID, &id) < 0)
- return TOUCHPAD_MODEL_UNKNOWN;
-
- for (i = 0; i < ARRAY_LENGTH(touchpad_spec_table); i++)
- if (touchpad_spec_table[i].vendor == id.vendor &&
- (!touchpad_spec_table[i].product ||
- touchpad_spec_table[i].product == id.product))
- return touchpad_spec_table[i].model;
-
- return TOUCHPAD_MODEL_UNKNOWN;
-}
-
-static void
-configure_touchpad_pressure(struct touchpad_dispatch *touchpad,
- int32_t pressure_min, int32_t pressure_max)
-{
- int32_t range = pressure_max - pressure_min + 1;
-
- touchpad->has_pressure = 1;
-
- /* Magic numbers from xf86-input-synaptics */
- switch (touchpad->model) {
- case TOUCHPAD_MODEL_ELANTECH:
- touchpad->pressure.touch_low = pressure_min + 1;
- touchpad->pressure.touch_high = pressure_min + 1;
- break;
- default:
- touchpad->pressure.touch_low =
- pressure_min + range * (25.0/256.0);
- touchpad->pressure.touch_high =
- pressure_min + range * (30.0/256.0);
- }
-}
-
-static double
-touchpad_profile(struct weston_motion_filter *filter,
- void *data,
- double velocity,
- uint32_t time)
-{
- struct touchpad_dispatch *touchpad =
- (struct touchpad_dispatch *) data;
-
- double accel_factor;
-
- accel_factor = velocity * touchpad->constant_accel_factor;
-
- if (accel_factor > touchpad->max_accel_factor)
- accel_factor = touchpad->max_accel_factor;
- else if (accel_factor < touchpad->min_accel_factor)
- accel_factor = touchpad->min_accel_factor;
-
- return accel_factor;
-}
-
-static inline struct touchpad_motion *
-motion_history_offset(struct touchpad_dispatch *touchpad, int offset)
-{
- int offset_index =
- (touchpad->motion_index - offset + TOUCHPAD_HISTORY_LENGTH) %
- TOUCHPAD_HISTORY_LENGTH;
-
- return &touchpad->motion_history[offset_index];
-}
-
-static double
-estimate_delta(int x0, int x1, int x2, int x3)
-{
- return (x0 + x1 - x2 - x3) / 4;
-}
-
-static int
-hysteresis(int in, int center, int margin)
-{
- int diff = in - center;
- if (abs(diff) <= margin)
- return center;
-
- if (diff > margin)
- return center + diff - margin;
- else if (diff < -margin)
- return center + diff + margin;
- return center + diff;
-}
-
-static void
-touchpad_get_delta(struct touchpad_dispatch *touchpad, double *dx, double *dy)
-{
- *dx = estimate_delta(motion_history_offset(touchpad, 0)->x,
- motion_history_offset(touchpad, 1)->x,
- motion_history_offset(touchpad, 2)->x,
- motion_history_offset(touchpad, 3)->x);
- *dy = estimate_delta(motion_history_offset(touchpad, 0)->y,
- motion_history_offset(touchpad, 1)->y,
- motion_history_offset(touchpad, 2)->y,
- motion_history_offset(touchpad, 3)->y);
-}
-
-static void
-filter_motion(struct touchpad_dispatch *touchpad,
- double *dx, double *dy, uint32_t time)
-{
- struct weston_motion_params motion;
-
- motion.dx = *dx;
- motion.dy = *dy;
-
- weston_filter_dispatch(touchpad->filter, &motion, touchpad, time);
-
- *dx = motion.dx;
- *dy = motion.dy;
-}
-
-static void
-notify_button_pressed(struct touchpad_dispatch *touchpad, uint32_t time)
-{
- notify_button(touchpad->device->seat, time,
- DEFAULT_TOUCHPAD_SINGLE_TAP_BUTTON,
- WL_POINTER_BUTTON_STATE_PRESSED);
-}
-
-static void
-notify_button_released(struct touchpad_dispatch *touchpad, uint32_t time)
-{
- notify_button(touchpad->device->seat, time,
- DEFAULT_TOUCHPAD_SINGLE_TAP_BUTTON,
- WL_POINTER_BUTTON_STATE_RELEASED);
-}
-
-static void
-notify_tap(struct touchpad_dispatch *touchpad, uint32_t time)
-{
- notify_button_pressed(touchpad, time);
- notify_button_released(touchpad, time);
-}
-
-static void
-process_fsm_events(struct touchpad_dispatch *touchpad, uint32_t time)
-{
- uint32_t timeout = UINT32_MAX;
- enum fsm_event *pevent;
- enum fsm_event event;
-
- if (!touchpad->fsm.enable)
- return;
-
- if (touchpad->fsm.events.size == 0)
- return;
-
- wl_array_for_each(pevent, &touchpad->fsm.events) {
- event = *pevent;
- timeout = 0;
-
- switch (touchpad->fsm.state) {
- case FSM_IDLE:
- switch (event) {
- case FSM_EVENT_TOUCH:
- touchpad->fsm.state = FSM_TOUCH;
- break;
- default:
- break;
- }
- break;
- case FSM_TOUCH:
- switch (event) {
- case FSM_EVENT_RELEASE:
- timeout = DEFAULT_TOUCHPAD_SINGLE_TAP_TIMEOUT;
- touchpad->fsm.state = FSM_TAP;
- break;
- default:
- touchpad->fsm.state = FSM_IDLE;
- break;
- }
- break;
- case FSM_TAP:
- switch (event) {
- case FSM_EVENT_TIMEOUT:
- notify_tap(touchpad, time);
- touchpad->fsm.state = FSM_IDLE;
- break;
- case FSM_EVENT_TOUCH:
- notify_button_pressed(touchpad, time);
- touchpad->fsm.state = FSM_TAP_2;
- break;
- default:
- touchpad->fsm.state = FSM_IDLE;
- break;
- }
- break;
- case FSM_TAP_2:
- switch (event) {
- case FSM_EVENT_MOTION:
- touchpad->fsm.state = FSM_DRAG;
- break;
- case FSM_EVENT_RELEASE:
- notify_button_released(touchpad, time);
- notify_tap(touchpad, time);
- touchpad->fsm.state = FSM_IDLE;
- break;
- default:
- touchpad->fsm.state = FSM_IDLE;
- break;
- }
- break;
- case FSM_DRAG:
- switch (event) {
- case FSM_EVENT_RELEASE:
- notify_button_released(touchpad, time);
- touchpad->fsm.state = FSM_IDLE;
- break;
- default:
- touchpad->fsm.state = FSM_IDLE;
- break;
- }
- break;
- default:
- weston_log("evdev-touchpad: Unknown state %d",
- touchpad->fsm.state);
- touchpad->fsm.state = FSM_IDLE;
- break;
- }
- }
-
- if (timeout != UINT32_MAX)
- wl_event_source_timer_update(touchpad->fsm.timer_source,
- timeout);
-
- wl_array_release(&touchpad->fsm.events);
- wl_array_init(&touchpad->fsm.events);
-}
-
-static void
-push_fsm_event(struct touchpad_dispatch *touchpad,
- enum fsm_event event)
-{
- enum fsm_event *pevent;
-
- if (!touchpad->fsm.enable)
- return;
-
- pevent = wl_array_add(&touchpad->fsm.events, sizeof event);
- if (pevent)
- *pevent = event;
- else
- touchpad->fsm.state = FSM_IDLE;
-}
-
-static int
-fsm_timout_handler(void *data)
-{
- struct touchpad_dispatch *touchpad = data;
-
- if (touchpad->fsm.events.size == 0) {
- push_fsm_event(touchpad, FSM_EVENT_TIMEOUT);
- process_fsm_events(touchpad, weston_compositor_get_time());
- }
-
- return 1;
-}
-
-static void
-touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time)
-{
- int motion_index;
- int center_x, center_y;
- double dx = 0.0, dy = 0.0;
-
- if (touchpad->reset ||
- touchpad->last_finger_state != touchpad->finger_state) {
- touchpad->reset = 0;
- touchpad->motion_count = 0;
- touchpad->event_mask = TOUCHPAD_EVENT_NONE;
- touchpad->event_mask_filter =
- TOUCHPAD_EVENT_ABSOLUTE_X | TOUCHPAD_EVENT_ABSOLUTE_Y;
-
- touchpad->last_finger_state = touchpad->finger_state;
-
- process_fsm_events(touchpad, time);
-
- return;
- }
- touchpad->last_finger_state = touchpad->finger_state;
-
- if (!(touchpad->event_mask & TOUCHPAD_EVENT_REPORT))
- return;
- else
- touchpad->event_mask &= ~TOUCHPAD_EVENT_REPORT;
-
- if ((touchpad->event_mask & touchpad->event_mask_filter) !=
- touchpad->event_mask_filter)
- return;
-
- touchpad->event_mask_filter = TOUCHPAD_EVENT_ABSOLUTE_ANY;
- touchpad->event_mask = 0;
-
- /* Avoid noice by moving center only when delta reaches a threshold
- * distance from the old center. */
- if (touchpad->motion_count > 0) {
- center_x = hysteresis(touchpad->hw_abs.x,
- touchpad->hysteresis.center_x,
- touchpad->hysteresis.margin_x);
- center_y = hysteresis(touchpad->hw_abs.y,
- touchpad->hysteresis.center_y,
- touchpad->hysteresis.margin_y);
- } else {
- center_x = touchpad->hw_abs.x;
- center_y = touchpad->hw_abs.y;
- }
- touchpad->hysteresis.center_x = center_x;
- touchpad->hysteresis.center_y = center_y;
- touchpad->hw_abs.x = center_x;
- touchpad->hw_abs.y = center_y;
-
- /* Update motion history tracker */
- motion_index = (touchpad->motion_index + 1) % TOUCHPAD_HISTORY_LENGTH;
- touchpad->motion_index = motion_index;
- touchpad->motion_history[motion_index].x = touchpad->hw_abs.x;
- touchpad->motion_history[motion_index].y = touchpad->hw_abs.y;
- if (touchpad->motion_count < 4)
- touchpad->motion_count++;
-
- if (touchpad->motion_count >= 4) {
- touchpad_get_delta(touchpad, &dx, &dy);
-
- filter_motion(touchpad, &dx, &dy, time);
-
- if (touchpad->finger_state == TOUCHPAD_FINGERS_ONE) {
- notify_motion(touchpad->device->seat, time,
- wl_fixed_from_double(dx),
- wl_fixed_from_double(dy));
- } else if (touchpad->finger_state == TOUCHPAD_FINGERS_TWO) {
- if (dx != 0.0)
- notify_axis(touchpad->device->seat,
- time,
- WL_POINTER_AXIS_HORIZONTAL_SCROLL,
- wl_fixed_from_double(dx));
- if (dy != 0.0)
- notify_axis(touchpad->device->seat,
- time,
- WL_POINTER_AXIS_VERTICAL_SCROLL,
- wl_fixed_from_double(dy));
- }
- }
-
- if (!(touchpad->state & TOUCHPAD_STATE_MOVE) &&
- ((int)dx || (int)dy)) {
- touchpad->state |= TOUCHPAD_STATE_MOVE;
- push_fsm_event(touchpad, FSM_EVENT_MOTION);
- }
-
- process_fsm_events(touchpad, time);
-}
-
-static void
-on_touch(struct touchpad_dispatch *touchpad)
-{
- touchpad->state |= TOUCHPAD_STATE_TOUCH;
-
- push_fsm_event(touchpad, FSM_EVENT_TOUCH);
-}
-
-static void
-on_release(struct touchpad_dispatch *touchpad)
-{
-
- touchpad->reset = 1;
- touchpad->state &= ~(TOUCHPAD_STATE_MOVE | TOUCHPAD_STATE_TOUCH);
-
- push_fsm_event(touchpad, FSM_EVENT_RELEASE);
-}
-
-static inline void
-process_absolute(struct touchpad_dispatch *touchpad,
- struct evdev_device *device,
- struct input_event *e)
-{
- switch (e->code) {
- case ABS_PRESSURE:
- if (e->value > touchpad->pressure.touch_high &&
- !(touchpad->state & TOUCHPAD_STATE_TOUCH))
- on_touch(touchpad);
- else if (e->value < touchpad->pressure.touch_low &&
- touchpad->state & TOUCHPAD_STATE_TOUCH)
- on_release(touchpad);
-
- break;
- case ABS_X:
- if (touchpad->state & TOUCHPAD_STATE_TOUCH) {
- touchpad->hw_abs.x = e->value;
- touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY;
- touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_X;
- }
- break;
- case ABS_Y:
- if (touchpad->state & TOUCHPAD_STATE_TOUCH) {
- touchpad->hw_abs.y = e->value;
- touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_ANY;
- touchpad->event_mask |= TOUCHPAD_EVENT_ABSOLUTE_Y;
- }
- break;
- }
-}
-
-static inline void
-process_key(struct touchpad_dispatch *touchpad,
- struct evdev_device *device,
- struct input_event *e,
- uint32_t time)
-{
- uint32_t code;
-
- switch (e->code) {
- case BTN_TOUCH:
- if (!touchpad->has_pressure) {
- if (e->value && !(touchpad->state & TOUCHPAD_STATE_TOUCH))
- on_touch(touchpad);
- else if (!e->value)
- on_release(touchpad);
- }
- break;
- case BTN_LEFT:
- case BTN_RIGHT:
- case BTN_MIDDLE:
- case BTN_SIDE:
- case BTN_EXTRA:
- case BTN_FORWARD:
- case BTN_BACK:
- case BTN_TASK:
- if (!touchpad->fsm.enable && e->code == BTN_LEFT &&
- touchpad->finger_state == TOUCHPAD_FINGERS_TWO)
- code = BTN_RIGHT;
- else
- code = e->code;
- notify_button(device->seat, time, code,
- e->value ? WL_POINTER_BUTTON_STATE_PRESSED :
- WL_POINTER_BUTTON_STATE_RELEASED);
- break;
- case BTN_TOOL_PEN:
- case BTN_TOOL_RUBBER:
- case BTN_TOOL_BRUSH:
- case BTN_TOOL_PENCIL:
- case BTN_TOOL_AIRBRUSH:
- case BTN_TOOL_MOUSE:
- case BTN_TOOL_LENS:
- touchpad->reset = 1;
- break;
- case BTN_TOOL_FINGER:
- if (e->value)
- touchpad->finger_state |= TOUCHPAD_FINGERS_ONE;
- else
- touchpad->finger_state &= ~TOUCHPAD_FINGERS_ONE;
- break;
- case BTN_TOOL_DOUBLETAP:
- if (e->value)
- touchpad->finger_state |= TOUCHPAD_FINGERS_TWO;
- else
- touchpad->finger_state &= ~TOUCHPAD_FINGERS_TWO;
- break;
- case BTN_TOOL_TRIPLETAP:
- if (e->value)
- touchpad->finger_state |= TOUCHPAD_FINGERS_THREE;
- else
- touchpad->finger_state &= ~TOUCHPAD_FINGERS_THREE;
- break;
- }
-}
-
-static void
-touchpad_process(struct evdev_dispatch *dispatch,
- struct evdev_device *device,
- struct input_event *e,
- uint32_t time)
-{
- struct touchpad_dispatch *touchpad =
- (struct touchpad_dispatch *) dispatch;
-
- switch (e->type) {
- case EV_SYN:
- if (e->code == SYN_REPORT)
- touchpad->event_mask |= TOUCHPAD_EVENT_REPORT;
- break;
- case EV_ABS:
- process_absolute(touchpad, device, e);
- break;
- case EV_KEY:
- process_key(touchpad, device, e, time);
- break;
- }
-
- touchpad_update_state(touchpad, time);
-}
-
-static void
-touchpad_destroy(struct evdev_dispatch *dispatch)
-{
- struct touchpad_dispatch *touchpad =
- (struct touchpad_dispatch *) dispatch;
-
- touchpad->filter->interface->destroy(touchpad->filter);
- wl_event_source_remove(touchpad->fsm.timer_source);
- free(dispatch);
-}
-
-struct evdev_dispatch_interface touchpad_interface = {
- touchpad_process,
- touchpad_destroy
-};
-
-static void
-touchpad_parse_config(struct touchpad_dispatch *touchpad, double diagonal)
-{
- struct weston_compositor *compositor =
- touchpad->device->seat->compositor;
- struct weston_config_section *s;
- double constant_accel_factor;
- double min_accel_factor;
- double max_accel_factor;
-
- s = weston_config_get_section(compositor->config,
- "touchpad", NULL, NULL);
- weston_config_section_get_double(s, "constant_accel_factor",
- &constant_accel_factor,
- DEFAULT_CONSTANT_ACCEL_NUMERATOR);
- weston_config_section_get_double(s, "min_accel_factor",
- &min_accel_factor,
- DEFAULT_MIN_ACCEL_FACTOR);
- weston_config_section_get_double(s, "max_accel_factor",
- &max_accel_factor,
- DEFAULT_MAX_ACCEL_FACTOR);
-
- touchpad->constant_accel_factor =
- constant_accel_factor / diagonal;
- touchpad->min_accel_factor = min_accel_factor;
- touchpad->max_accel_factor = max_accel_factor;
-}
-
-static int
-touchpad_init(struct touchpad_dispatch *touchpad,
- struct evdev_device *device)
-{
- struct weston_motion_filter *accel;
- struct wl_event_loop *loop;
-
- unsigned long prop_bits[INPUT_PROP_MAX];
- struct input_absinfo absinfo;
- unsigned long abs_bits[NBITS(ABS_MAX)];
-
- bool has_buttonpad;
-
- double width;
- double height;
- double diagonal;
-
- touchpad->base.interface = &touchpad_interface;
- touchpad->device = device;
-
- /* Detect model */
- touchpad->model = get_touchpad_model(device);
-
- ioctl(device->fd, EVIOCGPROP(sizeof(prop_bits)), prop_bits);
- has_buttonpad = TEST_BIT(prop_bits, INPUT_PROP_BUTTONPAD);
-
- /* Configure pressure */
- ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits);
- if (TEST_BIT(abs_bits, ABS_PRESSURE)) {
- ioctl(device->fd, EVIOCGABS(ABS_PRESSURE), &absinfo);
- configure_touchpad_pressure(touchpad,
- absinfo.minimum,
- absinfo.maximum);
- }
-
- /* Configure acceleration factor */
- width = abs(device->abs.max_x - device->abs.min_x);
- height = abs(device->abs.max_y - device->abs.min_y);
- diagonal = sqrt(width*width + height*height);
-
- touchpad_parse_config(touchpad, diagonal);
-
- touchpad->hysteresis.margin_x =
- diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
- touchpad->hysteresis.margin_y =
- diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
- touchpad->hysteresis.center_x = 0;
- touchpad->hysteresis.center_y = 0;
-
- /* Configure acceleration profile */
- accel = create_pointer_accelator_filter(touchpad_profile);
- if (accel == NULL)
- return -1;
- touchpad->filter = accel;
-
- /* Setup initial state */
- touchpad->reset = 1;
-
- memset(touchpad->motion_history, 0, sizeof touchpad->motion_history);
- touchpad->motion_index = 0;
- touchpad->motion_count = 0;
-
- touchpad->state = TOUCHPAD_STATE_NONE;
- touchpad->last_finger_state = 0;
- touchpad->finger_state = 0;
-
- wl_array_init(&touchpad->fsm.events);
- touchpad->fsm.state = FSM_IDLE;
-
- loop = wl_display_get_event_loop(device->seat->compositor->wl_display);
- touchpad->fsm.timer_source =
- wl_event_loop_add_timer(loop, fsm_timout_handler, touchpad);
- if (touchpad->fsm.timer_source == NULL) {
- accel->interface->destroy(accel);
- return -1;
- }
-
- /* Configure */
- touchpad->fsm.enable = !has_buttonpad;
-
- return 0;
-}
-
-struct evdev_dispatch *
-evdev_touchpad_create(struct evdev_device *device)
-{
- struct touchpad_dispatch *touchpad;
-
- touchpad = malloc(sizeof *touchpad);
- if (touchpad == NULL)
- return NULL;
-
- if (touchpad_init(touchpad, device) != 0) {
- free(touchpad);
- return NULL;
- }
-
- return &touchpad->base;
-}
diff --git a/src/evdev.c b/src/evdev.c
index ec18d99..5edb4fc 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -1,5 +1,6 @@
/*
* Copyright © 2010 Intel Corporation
+ * Copyright © 2013 Jonas Ådahl
*
* Permission to use, copy, modify, distribute, and sell this software and
* its documentation for any purpose is hereby granted without fee, provided
@@ -30,6 +31,7 @@
#include <fcntl.h>
#include <mtdev.h>
#include <assert.h>
+#include <libinput.h>
#include "compositor.h"
#include "evdev.h"
@@ -37,607 +39,283 @@
#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10)
void
-evdev_led_update(struct evdev_device *device, enum weston_led leds)
+evdev_led_update(struct evdev_device *device, enum weston_led weston_leds)
{
- static const struct {
- enum weston_led weston;
- int evdev;
- } map[] = {
- { LED_NUM_LOCK, LED_NUML },
- { LED_CAPS_LOCK, LED_CAPSL },
- { LED_SCROLL_LOCK, LED_SCROLLL },
- };
- struct input_event ev[ARRAY_LENGTH(map) + 1];
- unsigned int i;
+ enum libinput_led leds = 0;
- if (!device->caps & EVDEV_KEYBOARD)
- return;
+ if (weston_leds & LED_NUM_LOCK)
+ leds |= LIBINPUT_LED_NUM_LOCK;
+ if (weston_leds & LED_CAPS_LOCK)
+ leds |= LIBINPUT_LED_CAPS_LOCK;
+ if (weston_leds & LED_SCROLL_LOCK)
+ leds |= LIBINPUT_LED_SCROLL_LOCK;
- memset(ev, 0, sizeof(ev));
- for (i = 0; i < ARRAY_LENGTH(map); i++) {
- ev[i].type = EV_LED;
- ev[i].code = map[i].evdev;
- ev[i].value = !!(leds & map[i].weston);
- }
- ev[i].type = EV_SYN;
- ev[i].code = SYN_REPORT;
-
- i = write(device->fd, ev, sizeof ev);
- (void)i; /* no, we really don't care about the return value */
+ libinput_device_led_update(device->device, leds);
}
-static void
-transform_absolute(struct evdev_device *device, int32_t *x, int32_t *y)
-{
- if (!device->abs.apply_calibration) {
- *x = device->abs.x;
- *y = device->abs.y;
- return;
- } else {
- *x = device->abs.x * device->abs.calibration[0] +
- device->abs.y * device->abs.calibration[1] +
- device->abs.calibration[2];
-
- *y = device->abs.x * device->abs.calibration[3] +
- device->abs.y * device->abs.calibration[4] +
- device->abs.calibration[5];
- }
-}
-
-static void
-evdev_flush_pending_event(struct evdev_device *device, uint32_t time)
+static int
+evdev_device_data(int fd, uint32_t mask, void *data)
{
- struct weston_seat *master = device->seat;
- wl_fixed_t x, y;
- int32_t cx, cy;
- int slot;
-
- slot = device->mt.slot;
+ struct weston_compositor *ec;
+ struct evdev_device *device = data;
- switch (device->pending_event) {
- case EVDEV_NONE:
- return;
- case EVDEV_RELATIVE_MOTION:
- notify_motion(master, time, device->rel.dx, device->rel.dy);
- device->rel.dx = 0;
- device->rel.dy = 0;
- goto handled;
- case EVDEV_ABSOLUTE_MT_DOWN:
- weston_output_transform_coordinate(device->output,
- wl_fixed_from_int(device->mt.slots[slot].x),
- wl_fixed_from_int(device->mt.slots[slot].y),
- &x, &y);
- notify_touch(master, time,
- slot, x, y, WL_TOUCH_DOWN);
- goto handled;
- case EVDEV_ABSOLUTE_MT_MOTION:
- weston_output_transform_coordinate(device->output,
- wl_fixed_from_int(device->mt.slots[slot].x),
- wl_fixed_from_int(device->mt.slots[slot].y),
- &x, &y);
- notify_touch(master, time,
- slot, x, y, WL_TOUCH_MOTION);
- goto handled;
- case EVDEV_ABSOLUTE_MT_UP:
- notify_touch(master, time, slot, 0, 0,
- WL_TOUCH_UP);
- goto handled;
- case EVDEV_ABSOLUTE_TOUCH_DOWN:
- transform_absolute(device, &cx, &cy);
- weston_output_transform_coordinate(device->output,
- wl_fixed_from_int(cx),
- wl_fixed_from_int(cy),
- &x, &y);
- notify_touch(master, time, 0, x, y, WL_TOUCH_DOWN);
- goto handled;
- case EVDEV_ABSOLUTE_MOTION:
- transform_absolute(device, &cx, &cy);
- weston_output_transform_coordinate(device->output,
- wl_fixed_from_int(cx),
- wl_fixed_from_int(cy),
- &x, &y);
-
- if (device->caps & EVDEV_TOUCH)
- notify_touch(master, time, 0, x, y, WL_TOUCH_MOTION);
- else
- notify_motion_absolute(master, time, x, y);
- goto handled;
- case EVDEV_ABSOLUTE_TOUCH_UP:
- notify_touch(master, time, 0, 0, 0, WL_TOUCH_UP);
- goto handled;
- }
+ ec = device->seat->compositor;
+ if (!ec->session_active)
+ return 1;
- assert(0 && "Unknown pending event type");
+ libinput_device_dispatch(device->device);
-handled:
- device->pending_event = EVDEV_NONE;
+ return 0;
}
static void
-evdev_process_touch_button(struct evdev_device *device, int time, int value)
+register_capability(enum libinput_seat_capability capability,
+ void *data)
{
- if (device->pending_event != EVDEV_NONE &&
- device->pending_event != EVDEV_ABSOLUTE_MOTION)
- evdev_flush_pending_event(device, time);
-
- device->pending_event = (value ?
- EVDEV_ABSOLUTE_TOUCH_DOWN :
- EVDEV_ABSOLUTE_TOUCH_UP);
-}
-
-static inline void
-evdev_process_key(struct evdev_device *device, struct input_event *e, int time)
-{
- /* ignore kernel key repeat */
- if (e->value == 2)
- return;
-
- if (e->code == BTN_TOUCH) {
- if (!device->is_mt)
- evdev_process_touch_button(device, time, e->value);
- return;
- }
+ struct evdev_device *device = data;
+ struct weston_seat *seat = device->seat;
- evdev_flush_pending_event(device, time);
-
- switch (e->code) {
- case BTN_LEFT:
- case BTN_RIGHT:
- case BTN_MIDDLE:
- case BTN_SIDE:
- case BTN_EXTRA:
- case BTN_FORWARD:
- case BTN_BACK:
- case BTN_TASK:
- notify_button(device->seat,
- time, e->code,
- e->value ? WL_POINTER_BUTTON_STATE_PRESSED :
- WL_POINTER_BUTTON_STATE_RELEASED);
+ switch (capability) {
+ case LIBINPUT_SEAT_CAP_KEYBOARD:
+ weston_seat_init_keyboard(seat, NULL);
break;
-
- default:
- notify_key(device->seat,
- time, e->code,
- e->value ? WL_KEYBOARD_KEY_STATE_PRESSED :
- WL_KEYBOARD_KEY_STATE_RELEASED,
- STATE_UPDATE_AUTOMATIC);
+ case LIBINPUT_SEAT_CAP_POINTER:
+ weston_seat_init_pointer(seat);
break;
- }
+ case LIBINPUT_SEAT_CAP_TOUCH:
+ weston_seat_init_touch(seat);
+ break;
+ };
}
static void
-evdev_process_touch(struct evdev_device *device,
- struct input_event *e,
- uint32_t time)
+unregister_capability(enum libinput_seat_capability capability,
+ void *data)
{
- const int screen_width = device->output->current_mode->width;
- const int screen_height = device->output->current_mode->height;
+ struct evdev_device *device = data;
+ struct weston_seat *seat = device->seat;
- switch (e->code) {
- case ABS_MT_SLOT:
- evdev_flush_pending_event(device, time);
- device->mt.slot = e->value;
+ switch (capability) {
+ case LIBINPUT_SEAT_CAP_KEYBOARD:
+ weston_seat_release_keyboard(seat);
break;
- case ABS_MT_TRACKING_ID:
- if (device->pending_event != EVDEV_NONE &&
- device->pending_event != EVDEV_ABSOLUTE_MT_MOTION)
- evdev_flush_pending_event(device, time);
- if (e->value >= 0)
- device->pending_event = EVDEV_ABSOLUTE_MT_DOWN;
- else
- device->pending_event = EVDEV_ABSOLUTE_MT_UP;
+ case LIBINPUT_SEAT_CAP_POINTER:
+ weston_seat_release_pointer(seat);
break;
- case ABS_MT_POSITION_X:
- device->mt.slots[device->mt.slot].x =
- (e->value - device->abs.min_x) * screen_width /
- (device->abs.max_x - device->abs.min_x);
- if (device->pending_event == EVDEV_NONE)
- device->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
+ case LIBINPUT_SEAT_CAP_TOUCH:
+ weston_seat_release_touch(seat);
break;
- case ABS_MT_POSITION_Y:
- device->mt.slots[device->mt.slot].y =
- (e->value - device->abs.min_y) * screen_height /
- (device->abs.max_y - device->abs.min_y);
- if (device->pending_event == EVDEV_NONE)
- device->pending_event = EVDEV_ABSOLUTE_MT_MOTION;
- break;
- }
+ };
}
-static inline void
-evdev_process_absolute_motion(struct evdev_device *device,
- struct input_event *e)
+static void
+get_current_screen_dimensions(int *width,
+ int *height,
+ void *data)
{
- const int screen_width = device->output->current_mode->width;
- const int screen_height = device->output->current_mode->height;
-
- switch (e->code) {
- case ABS_X:
- device->abs.x =
- (e->value - device->abs.min_x) * screen_width /
- (device->abs.max_x - device->abs.min_x);
- if (device->pending_event == EVDEV_NONE)
- device->pending_event = EVDEV_ABSOLUTE_MOTION;
- break;
- case ABS_Y:
- device->abs.y =
- (e->value - device->abs.min_y) * screen_height /
- (device->abs.max_y - device->abs.min_y);
- if (device->pending_event == EVDEV_NONE)
- device->pending_event = EVDEV_ABSOLUTE_MOTION;
- break;
- }
+ struct evdev_device *device = data;
+
+ *width = device->output->current_mode->width;
+ *height = device->output->current_mode->height;
}
-static inline void
-evdev_process_relative(struct evdev_device *device,
- struct input_event *e, uint32_t time)
+struct libinput_fd_handle {
+ struct wl_event_source *source;
+ libinput_fd_callback callback;
+ struct evdev_device *device;
+};
+
+static int
+dispatch_libinput_callback(int fd, uint32_t mask, void *data)
{
- switch (e->code) {
- case REL_X:
- if (device->pending_event != EVDEV_RELATIVE_MOTION)
- evdev_flush_pending_event(device, time);
- device->rel.dx += wl_fixed_from_int(e->value);
- device->pending_event = EVDEV_RELATIVE_MOTION;
- break;
- case REL_Y:
- if (device->pending_event != EVDEV_RELATIVE_MOTION)
- evdev_flush_pending_event(device, time);
- device->rel.dy += wl_fixed_from_int(e->value);
- device->pending_event = EVDEV_RELATIVE_MOTION;
- break;
- case REL_WHEEL:
- evdev_flush_pending_event(device, time);
- switch (e->value) {
- case -1:
- /* Scroll down */
- case 1:
- /* Scroll up */
- notify_axis(device->seat,
- time,
- WL_POINTER_AXIS_VERTICAL_SCROLL,
- -1 * e->value * DEFAULT_AXIS_STEP_DISTANCE);
- break;
- default:
- break;
- }
- break;
- case REL_HWHEEL:
- evdev_flush_pending_event(device, time);
- switch (e->value) {
- case -1:
- /* Scroll left */
- case 1:
- /* Scroll right */
- notify_axis(device->seat,
- time,
- WL_POINTER_AXIS_HORIZONTAL_SCROLL,
- e->value * DEFAULT_AXIS_STEP_DISTANCE);
- break;
- default:
- break;
+ struct libinput_fd_handle *handle = data;
- }
- }
+ handle->callback(fd, handle->device->device);
+
+ return 1;
}
-static inline void
-evdev_process_absolute(struct evdev_device *device,
- struct input_event *e,
- uint32_t time)
+static struct libinput_fd_handle *
+add_fd(int fd, libinput_fd_callback callback, void *data)
{
- if (device->is_mt) {
- evdev_process_touch(device, e, time);
- } else {
- evdev_process_absolute_motion(device, e);
+ struct evdev_device *device = data;
+ struct libinput_fd_handle *handle;
+ struct wl_event_loop *loop =
+ wl_display_get_event_loop(device->seat->compositor->wl_display);
+
+ handle = malloc(sizeof *handle);
+ if (!handle)
+ return NULL;
+
+ handle->callback = callback;
+ handle->device = device;
+ handle->source = wl_event_loop_add_fd(loop,
+ fd,
+ WL_EVENT_READABLE,
+ dispatch_libinput_callback,
+ handle);
+ if (!handle->source) {
+ free(handle);
+ return NULL;
}
+
+ return handle;
}
static void
-fallback_process(struct evdev_dispatch *dispatch,
- struct evdev_device *device,
- struct input_event *event,
- uint32_t time)
+remove_fd(struct libinput_fd_handle *handle, void *data)
{
- switch (event->type) {
- case EV_REL:
- evdev_process_relative(device, event, time);
- break;
- case EV_ABS:
- evdev_process_absolute(device, event, time);
- break;
- case EV_KEY:
- evdev_process_key(device, event, time);
- break;
- case EV_SYN:
- evdev_flush_pending_event(device, time);
- break;
- }
+ wl_event_source_remove(handle->source);
+ free(handle);
}
static void
-fallback_destroy(struct evdev_dispatch *dispatch)
+device_lost(void *data)
{
- free(dispatch);
+ struct evdev_device *device = data;
+
+ wl_event_source_remove(device->source);
+ device->source = NULL;
}
-struct evdev_dispatch_interface fallback_interface = {
- fallback_process,
- fallback_destroy
-};
+static const struct libinput_device_interface device_interface = {
+ register_capability,
+ unregister_capability,
-static struct evdev_dispatch *
-fallback_dispatch_create(void)
-{
- struct evdev_dispatch *dispatch = malloc(sizeof *dispatch);
- if (dispatch == NULL)
- return NULL;
+ get_current_screen_dimensions,
- dispatch->interface = &fallback_interface;
+ add_fd,
+ remove_fd,
- return dispatch;
-}
+ device_lost,
+};
static void
-evdev_process_events(struct evdev_device *device,
- struct input_event *ev, int count)
+keyboard_notify_key(uint32_t time,
+ uint32_t key,
+ enum libinput_keyboard_key_state state,
+ void *data)
{
- struct evdev_dispatch *dispatch = device->dispatch;
- struct input_event *e, *end;
- uint32_t time = 0;
-
- e = ev;
- end = e + count;
- for (e = ev; e < end; e++) {
- time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
+ struct evdev_device *device = data;
+ enum wl_keyboard_key_state key_state =
+ (enum wl_keyboard_key_state) state;
- dispatch->interface->process(dispatch, device, e, time);
- }
+ notify_key(device->seat, time, key, key_state, STATE_UPDATE_AUTOMATIC);
}
-static int
-evdev_device_data(int fd, uint32_t mask, void *data)
+static const struct libinput_keyboard_listener keyboard_listener = {
+ keyboard_notify_key,
+};
+
+static void
+pointer_notify_motion(uint32_t time,
+ li_fixed_t dx,
+ li_fixed_t dy,
+ void *data)
{
- struct weston_compositor *ec;
struct evdev_device *device = data;
- struct input_event ev[32];
- int len;
-
- ec = device->seat->compositor;
- if (!ec->session_active)
- return 1;
-
- /* If the compositor is repainting, this function is called only once
- * per frame and we have to process all the events available on the
- * fd, otherwise there will be input lag. */
- do {
- if (device->mtdev)
- len = mtdev_get(device->mtdev, fd, ev,
- ARRAY_LENGTH(ev)) *
- sizeof (struct input_event);
- else
- len = read(fd, &ev, sizeof ev);
-
- if (len < 0 || len % sizeof ev[0] != 0) {
- if (len < 0 && errno != EAGAIN && errno != EINTR) {
- weston_log("device %s died\n",
- device->devnode);
- wl_event_source_remove(device->source);
- device->source = NULL;
- }
-
- return 1;
- }
- evdev_process_events(device, ev, len / sizeof ev[0]);
+ notify_motion(device->seat, time, dx, dy);
+}
- } while (len > 0);
+static void
+pointer_notify_motion_absolute(uint32_t time,
+ li_fixed_t x,
+ li_fixed_t y,
+ void *data)
+{
+ struct evdev_device *device = data;
- return 1;
+ weston_output_transform_coordinate(device->output, x, y, &x, &y);
+ notify_motion_absolute(device->seat, time, x, y);
}
-static int
-evdev_handle_device(struct evdev_device *device)
+static void
+pointer_notify_button(uint32_t time,
+ int32_t button,
+ enum libinput_pointer_button_state state,
+ void *data)
{
- struct input_absinfo absinfo;
- unsigned long ev_bits[NBITS(EV_MAX)];
- unsigned long abs_bits[NBITS(ABS_MAX)];
- unsigned long rel_bits[NBITS(REL_MAX)];
- unsigned long key_bits[NBITS(KEY_MAX)];
- int has_key, has_abs;
- unsigned int i;
-
- has_key = 0;
- has_abs = 0;
- device->caps = 0;
-
- ioctl(device->fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits);
- if (TEST_BIT(ev_bits, EV_ABS)) {
- has_abs = 1;
-
- ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)),
- abs_bits);
-
- if (TEST_BIT(abs_bits, ABS_WHEEL) ||
- TEST_BIT(abs_bits, ABS_GAS) ||
- TEST_BIT(abs_bits, ABS_BRAKE) ||
- TEST_BIT(abs_bits, ABS_HAT0X)) {
- weston_log("device %s is a joystick, ignoring\n",
- device->devnode);
- return 0;
- }
+ struct evdev_device *device = data;
+ enum wl_pointer_button_state button_state =
+ (enum wl_pointer_button_state) state;
- if (TEST_BIT(abs_bits, ABS_X)) {
- ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo);
- device->abs.min_x = absinfo.minimum;
- device->abs.max_x = absinfo.maximum;
- device->caps |= EVDEV_MOTION_ABS;
- }
- if (TEST_BIT(abs_bits, ABS_Y)) {
- ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo);
- device->abs.min_y = absinfo.minimum;
- device->abs.max_y = absinfo.maximum;
- device->caps |= EVDEV_MOTION_ABS;
- }
- /* We only handle the slotted Protocol B in weston.
- Devices with ABS_MT_POSITION_* but not ABS_MT_SLOT
- require mtdev for conversion. */
- if (TEST_BIT(abs_bits, ABS_MT_POSITION_X) &&
- TEST_BIT(abs_bits, ABS_MT_POSITION_Y)) {
- ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_X),
- &absinfo);
- device->abs.min_x = absinfo.minimum;
- device->abs.max_x = absinfo.maximum;
- ioctl(device->fd, EVIOCGABS(ABS_MT_POSITION_Y),
- &absinfo);
- device->abs.min_y = absinfo.minimum;
- device->abs.max_y = absinfo.maximum;
- device->is_mt = 1;
- device->caps |= EVDEV_TOUCH;
-
- if (!TEST_BIT(abs_bits, ABS_MT_SLOT)) {
- device->mtdev = mtdev_new_open(device->fd);
- if (!device->mtdev) {
- weston_log("mtdev required but failed to open for %s\n",
- device->devnode);
- return 0;
- }
- device->mt.slot = device->mtdev->caps.slot.value;
- } else {
- ioctl(device->fd, EVIOCGABS(ABS_MT_SLOT),
- &absinfo);
- device->mt.slot = absinfo.value;
- }
- }
- }
- if (TEST_BIT(ev_bits, EV_REL)) {
- ioctl(device->fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)),
- rel_bits);
- if (TEST_BIT(rel_bits, REL_X) || TEST_BIT(rel_bits, REL_Y))
- device->caps |= EVDEV_MOTION_REL;
- }
- if (TEST_BIT(ev_bits, EV_KEY)) {
- has_key = 1;
- ioctl(device->fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)),
- key_bits);
- if (TEST_BIT(key_bits, BTN_TOOL_FINGER) &&
- !TEST_BIT(key_bits, BTN_TOOL_PEN) &&
- has_abs) {
- device->dispatch = evdev_touchpad_create(device);
- weston_log("input device %s, %s is a touchpad\n",
- device->devname, device->devnode);
- }
- for (i = KEY_ESC; i < KEY_MAX; i++) {
- if (i >= BTN_MISC && i < KEY_OK)
- continue;
- if (TEST_BIT(key_bits, i)) {
- device->caps |= EVDEV_KEYBOARD;
- break;
- }
- }
- if (TEST_BIT(key_bits, BTN_TOUCH)) {
- device->caps |= EVDEV_TOUCH;
- }
- for (i = BTN_MISC; i < BTN_JOYSTICK; i++) {
- if (TEST_BIT(key_bits, i)) {
- device->caps |= EVDEV_BUTTON;
- device->caps &= ~EVDEV_TOUCH;
- break;
- }
- }
- }
- if (TEST_BIT(ev_bits, EV_LED)) {
- device->caps |= EVDEV_KEYBOARD;
- }
+ notify_button(device->seat, time, button, button_state);
+}
- /* This rule tries to catch accelerometer devices and opt out. We may
- * want to adjust the protocol later adding a proper event for dealing
- * with accelerometers and implement here accordingly */
- if (has_abs && !has_key && !device->is_mt) {
- weston_log("input device %s, %s "
- "ignored: unsupported device type\n",
- device->devname, device->devnode);
- return 0;
- }
+static void
+pointer_notify_axis(uint32_t time,
+ enum libinput_pointer_axis axis,
+ li_fixed_t value,
+ void *data)
+{
+ struct evdev_device *device = data;
- return 1;
+ notify_axis(device->seat, time, (uint32_t) axis, value);
}
-static int
-evdev_configure_device(struct evdev_device *device)
+static const struct libinput_pointer_listener pointer_listener = {
+ pointer_notify_motion,
+ pointer_notify_motion_absolute,
+ pointer_notify_button,
+ pointer_notify_axis,
+};
+
+static void
+touch_notify_touch(uint32_t time,
+ int32_t slot,
+ li_fixed_t x,
+ li_fixed_t y,
+ enum libinput_touch_type touch_type,
+ void *data)
{
- if ((device->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL)) &&
- (device->caps & EVDEV_BUTTON)) {
- weston_seat_init_pointer(device->seat);
- device->seat_caps |= EVDEV_SEAT_POINTER;
- weston_log("input device %s, %s is a pointer caps =%s%s%s\n",
- device->devname, device->devnode,
- device->caps & EVDEV_MOTION_ABS ? " absolute-motion" : "",
- device->caps & EVDEV_MOTION_REL ? " relative-motion": "",
- device->caps & EVDEV_BUTTON ? " button" : "");
- }
- if ((device->caps & EVDEV_KEYBOARD)) {
- if (weston_seat_init_keyboard(device->seat, NULL) < 0)
- return -1;
- device->seat_caps |= EVDEV_SEAT_KEYBOARD;
- weston_log("input device %s, %s is a keyboard\n",
- device->devname, device->devnode);
- }
- if ((device->caps & EVDEV_TOUCH)) {
- weston_seat_init_touch(device->seat);
- device->seat_caps |= EVDEV_SEAT_TOUCH;
- weston_log("input device %s, %s is a touch device\n",
- device->devname, device->devnode);
- }
+ struct evdev_device *device = data;
- return 0;
+ weston_output_transform_coordinate(device->output,
+ x, y, &x, &y);
+ notify_touch(device->seat, time, slot, x, y, (int) touch_type);
}
+static const struct libinput_touch_listener touch_listener = {
+ touch_notify_touch,
+};
+
struct evdev_device *
evdev_device_create(struct weston_seat *seat, const char *path, int device_fd)
{
struct evdev_device *device;
struct weston_compositor *ec;
- char devname[256] = "unknown";
device = zalloc(sizeof *device);
if (device == NULL)
return NULL;
+ device->devnode = strdup(path);
+ device->fd = device_fd;
ec = seat->compositor;
device->output =
container_of(ec->output_list.next, struct weston_output, link);
-
device->seat = seat;
- device->seat_caps = 0;
- device->is_mt = 0;
- device->mtdev = NULL;
- device->devnode = strdup(path);
- device->mt.slot = -1;
- device->rel.dx = 0;
- device->rel.dy = 0;
- device->dispatch = NULL;
- device->fd = device_fd;
- device->pending_event = EVDEV_NONE;
wl_list_init(&device->link);
- ioctl(device->fd, EVIOCGNAME(sizeof(devname)), devname);
- devname[sizeof(devname) - 1] = '\0';
- device->devname = strdup(devname);
-
- if (!evdev_handle_device(device)) {
- evdev_device_destroy(device);
- return EVDEV_UNHANDLED_DEVICE;
+ device->device = libinput_device_create_evdev(path,
+ device_fd,
+ &device_interface,
+ device);
+ if (device->device == NULL) {
+ free(device);
+ return NULL;
}
- if (evdev_configure_device(device) == -1)
- goto err;
-
- /* If the dispatch was not set up use the fallback. */
- if (device->dispatch == NULL)
- device->dispatch = fallback_dispatch_create();
- if (device->dispatch == NULL)
- goto err;
+ libinput_device_set_keyboard_listener(device->device,
+ &keyboard_listener,
+ device);
+ libinput_device_set_pointer_listener(device->device,
+ &pointer_listener,
+ device);
+ libinput_device_set_touch_listener(device->device,
+ &touch_listener,
+ device);
device->source = wl_event_loop_add_fd(ec->input_loop, device->fd,
WL_EVENT_READABLE,
@@ -655,26 +333,12 @@ err:
void
evdev_device_destroy(struct evdev_device *device)
{
- struct evdev_dispatch *dispatch;
-
- if (device->seat_caps & EVDEV_SEAT_POINTER)
- weston_seat_release_pointer(device->seat);
- if (device->seat_caps & EVDEV_SEAT_KEYBOARD)
- weston_seat_release_keyboard(device->seat);
- if (device->seat_caps & EVDEV_SEAT_TOUCH)
- weston_seat_release_touch(device->seat);
-
- dispatch = device->dispatch;
- if (dispatch)
- dispatch->interface->destroy(dispatch);
-
if (device->source)
wl_event_source_remove(device->source);
wl_list_remove(&device->link);
- if (device->mtdev)
- mtdev_close_delete(device->mtdev);
- close(device->fd);
- free(device->devname);
+
+ libinput_device_destroy(device->device);
+
free(device->devnode);
free(device);
}
@@ -697,8 +361,9 @@ evdev_notify_keyboard_focus(struct weston_seat *seat,
memset(all_keys, 0, sizeof all_keys);
wl_list_for_each(device, evdev_devices, link) {
memset(evdev_keys, 0, sizeof evdev_keys);
- ret = ioctl(device->fd,
- EVIOCGKEY(sizeof evdev_keys), evdev_keys);
+ ret = libinput_device_get_keys(device->device,
+ evdev_keys,
+ sizeof evdev_keys);
if (ret < 0) {
weston_log("failed to get keys for device %s\n",
device->devnode);
diff --git a/src/evdev.h b/src/evdev.h
index e146d1a..a9e7049 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -27,27 +27,7 @@
#include <linux/input.h>
#include <wayland-util.h>
-
-#define MAX_SLOTS 16
-
-enum evdev_event_type {
- EVDEV_NONE,
- EVDEV_ABSOLUTE_TOUCH_DOWN,
- EVDEV_ABSOLUTE_MOTION,
- EVDEV_ABSOLUTE_TOUCH_UP,
- EVDEV_ABSOLUTE_MT_DOWN,
- EVDEV_ABSOLUTE_MT_MOTION,
- EVDEV_ABSOLUTE_MT_UP,
- EVDEV_RELATIVE_MOTION,
-};
-
-enum evdev_device_capability {
- EVDEV_KEYBOARD = (1 << 0),
- EVDEV_BUTTON = (1 << 1),
- EVDEV_MOTION_ABS = (1 << 2),
- EVDEV_MOTION_REL = (1 << 3),
- EVDEV_TOUCH = (1 << 4),
-};
+#include <libinput.h>
enum evdev_device_seat_capability {
EVDEV_SEAT_POINTER = (1 << 0),
@@ -57,72 +37,14 @@ enum evdev_device_seat_capability {
struct evdev_device {
struct weston_seat *seat;
+ struct libinput_device *device;
struct wl_list link;
struct wl_event_source *source;
struct weston_output *output;
- struct evdev_dispatch *dispatch;
char *devnode;
- char *devname;
int fd;
- struct {
- int min_x, max_x, min_y, max_y;
- int32_t x, y;
-
- int apply_calibration;
- float calibration[6];
- } abs;
-
- struct {
- int slot;
- struct {
- int32_t x, y;
- } slots[MAX_SLOTS];
- } mt;
- struct mtdev *mtdev;
-
- struct {
- wl_fixed_t dx, dy;
- } rel;
-
- enum evdev_event_type pending_event;
- enum evdev_device_capability caps;
- enum evdev_device_seat_capability seat_caps;
-
- int is_mt;
};
-/* copied from udev/extras/input_id/input_id.c */
-/* we must use this kernel-compatible implementation */
-#define BITS_PER_LONG (sizeof(unsigned long) * 8)
-#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
-#define OFF(x) ((x)%BITS_PER_LONG)
-#define BIT(x) (1UL<<OFF(x))
-#define LONG(x) ((x)/BITS_PER_LONG)
-#define TEST_BIT(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1)
-/* end copied */
-
-#define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1)
-
-struct evdev_dispatch;
-
-struct evdev_dispatch_interface {
- /* Process an evdev input event. */
- void (*process)(struct evdev_dispatch *dispatch,
- struct evdev_device *device,
- struct input_event *event,
- uint32_t time);
-
- /* Destroy an event dispatch handler and free all its resources. */
- void (*destroy)(struct evdev_dispatch *dispatch);
-};
-
-struct evdev_dispatch {
- struct evdev_dispatch_interface *interface;
-};
-
-struct evdev_dispatch *
-evdev_touchpad_create(struct evdev_device *device);
-
void
evdev_led_update(struct evdev_device *device, enum weston_led leds);
diff --git a/src/udev-seat.c b/src/udev-seat.c
index deceb50..7638d16 100644
--- a/src/udev-seat.c
+++ b/src/udev-seat.c
@@ -51,6 +51,7 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
const char *calibration_values;
int fd;
struct udev_seat *seat;
+ float calibration[6];
device_seat = udev_device_get_property_value(udev_device, "ID_SEAT");
if (!device_seat)
@@ -82,14 +83,10 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
}
device = evdev_device_create(&seat->base, devnode, fd);
- if (device == EVDEV_UNHANDLED_DEVICE) {
+ if (device == NULL) {
weston_launcher_close(c->launcher, fd);
weston_log("not using input device '%s'.\n", devnode);
return 0;
- } else if (device == NULL) {
- weston_launcher_close(c->launcher, fd);
- weston_log("failed to create input device '%s'.\n", devnode);
- return 0;
}
calibration_values =
@@ -98,20 +95,20 @@ device_added(struct udev_device *udev_device, struct udev_input *input)
if (calibration_values && sscanf(calibration_values,
"%f %f %f %f %f %f",
- &device->abs.calibration[0],
- &device->abs.calibration[1],
- &device->abs.calibration[2],
- &device->abs.calibration[3],
- &device->abs.calibration[4],
- &device->abs.calibration[5]) == 6) {
- device->abs.apply_calibration = 1;
+ &calibration[0],
+ &calibration[1],
+ &calibration[2],
+ &calibration[3],
+ &calibration[4],
+ &calibration[5]) == 6) {
weston_log ("Applying calibration: %f %f %f %f %f %f\n",
- device->abs.calibration[0],
- device->abs.calibration[1],
- device->abs.calibration[2],
- device->abs.calibration[3],
- device->abs.calibration[4],
- device->abs.calibration[5]);
+ calibration[0],
+ calibration[1],
+ calibration[2],
+ calibration[3],
+ calibration[4],
+ calibration[5]);
+ libinput_device_calibrate(device->device, calibration);
}
wl_list_insert(seat->devices_list.prev, &device->link);
@@ -217,8 +214,8 @@ evdev_udev_handler(int fd, uint32_t mask, void *data)
wl_list_for_each(seat, &input->compositor->seat_list, base.link) {
wl_list_for_each_safe(device, next, &seat->devices_list, link)
if (!strcmp(device->devnode, devnode)) {
- weston_log("input device %s, %s removed\n",
- device->devname, device->devnode);
+ weston_log("input device %s removed\n",
+ device->devnode);
weston_launcher_close(input->compositor->launcher,
device->fd);
evdev_device_destroy(device);
--
1.8.1.2
More information about the wayland-devel
mailing list