From ec11ec9c7c2656fa2ea1b6eb5f0175e4e3f94f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 24 Nov 2008 00:12:20 -0500 Subject: [PATCH 001/162] Rename input.c to evdev.c. --- evdev.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 evdev.c diff --git a/evdev.c b/evdev.c new file mode 100644 index 00000000..f91b6859 --- /dev/null +++ b/evdev.c @@ -0,0 +1,151 @@ +#include +#include +#include +#include +#include + +#include + +#include "wayland.h" + +struct wl_input_device { + struct wl_object base; + struct wl_event_source *source; + struct wl_display *display; + int fd; + int tool; + int32_t x, y; +}; + +static const struct wl_method input_device_methods[] = { +}; + +static const struct wl_interface input_device_interface = { + "input_device", 1, + ARRAY_LENGTH(input_device_methods), + input_device_methods, +}; + +static void wl_input_device_data(int fd, uint32_t mask, void *data) +{ + struct wl_input_device *device = data; + struct input_event ev[8], *e, *end; + int len, value, dx, dy, absolute_event; + + dx = 0; + dy = 0; + absolute_event = 0; + + len = read(fd, &ev, sizeof ev); + if (len < 0 || len % sizeof e[0] != 0) { + /* FIXME: handle error... reopen device? */; + return; + } + + e = ev; + end = (void *) ev + len; + for (e = ev; e < end; e++) { + /* Get the signed value, earlier kernels had this as unsigned */ + value = e->value; + + switch (e->type) { + case EV_REL: + switch (e->code) { + case REL_X: + dx += value; + break; + + case REL_Y: + dy += value; + break; + } + + case EV_ABS: + absolute_event = 1; + switch (e->code) { + case ABS_X: + device->x = value; + break; + case ABS_Y: + device->y = value; + break; + } + + case EV_KEY: + if (value == 2) + break; + + switch (e->code) { + case BTN_TOUCH: + case BTN_TOOL_PEN: + case BTN_TOOL_RUBBER: + case BTN_TOOL_BRUSH: + case BTN_TOOL_PENCIL: + case BTN_TOOL_AIRBRUSH: + case BTN_TOOL_FINGER: + case BTN_TOOL_MOUSE: + case BTN_TOOL_LENS: + device->tool = value ? e->code : 0; + break; + + case BTN_LEFT: + wl_display_post_button_event(device->display, + &device->base, 0, value); + break; + + case BTN_RIGHT: + wl_display_post_button_event(device->display, + &device->base, 2, value); + break; + + case BTN_MIDDLE: + wl_display_post_button_event(device->display, + &device->base, 1, value); + break; + } + } + } + + if (dx != 0 || dy != 0) + wl_display_post_relative_event(device->display, + &device->base, dx, dy); + if (absolute_event && device->tool) + wl_display_post_absolute_event(device->display, + &device->base, + device->x, device->y); +} + +struct wl_object * +wl_input_device_create(struct wl_display *display, + const char *path, uint32_t id) +{ + struct wl_input_device *device; + struct wl_event_loop *loop; + + device = malloc(sizeof *device); + if (device == NULL) + return NULL; + + device->base.interface = &input_device_interface; + device->display = display; + device->tool = 1; + + device->fd = open(path, O_RDONLY); + if (device->fd < 0) { + free(device); + fprintf(stderr, "couldn't create pointer for %s: %m\n", path); + return NULL; + } + + loop = wl_display_get_event_loop(display); + device->source = wl_event_loop_add_fd(loop, device->fd, + WL_EVENT_READABLE, + wl_input_device_data, device); + if (device->source == NULL) { + close(device->fd); + free(device); + return NULL; + } + + return &device->base; +} From e3ceb1c060f032b9199ab36eab5cb0fde6abd005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 24 Nov 2008 00:13:13 -0500 Subject: [PATCH 002/162] Add missing breaks in evdev switch. --- evdev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/evdev.c b/evdev.c index f91b6859..ee51e0ef 100644 --- a/evdev.c +++ b/evdev.c @@ -59,6 +59,7 @@ static void wl_input_device_data(int fd, uint32_t mask, void *data) dy += value; break; } + break; case EV_ABS: absolute_event = 1; @@ -70,6 +71,7 @@ static void wl_input_device_data(int fd, uint32_t mask, void *data) device->y = value; break; } + break; case EV_KEY: if (value == 2) From 12787f22f9fce4676cb2529f200302b512ebd11a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 24 Nov 2008 00:31:49 -0500 Subject: [PATCH 003/162] Add keyboard input, move input device creation to compositor. --- evdev.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/evdev.c b/evdev.c index ee51e0ef..36823213 100644 --- a/evdev.c +++ b/evdev.c @@ -104,6 +104,11 @@ static void wl_input_device_data(int fd, uint32_t mask, void *data) wl_display_post_button_event(device->display, &device->base, 1, value); break; + + default: + wl_display_post_key_event(device->display, + &device->base, e->code, value); + break; } } } @@ -117,9 +122,8 @@ static void wl_input_device_data(int fd, uint32_t mask, void *data) device->x, device->y); } -struct wl_object * -wl_input_device_create(struct wl_display *display, - const char *path, uint32_t id) +WL_EXPORT struct wl_object * +wl_input_device_create(struct wl_display *display, const char *path) { struct wl_input_device *device; struct wl_event_loop *loop; From 3666c9b27ff3183feb3bd61d0663122706e41657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 25 Nov 2008 23:16:31 -0500 Subject: [PATCH 004/162] Convert touchpad absolute events to relative. --- evdev.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/evdev.c b/evdev.c index 36823213..713670a8 100644 --- a/evdev.c +++ b/evdev.c @@ -13,8 +13,8 @@ struct wl_input_device { struct wl_event_source *source; struct wl_display *display; int fd; - int tool; - int32_t x, y; + int tool, new_x, new_y; + int32_t x, y, base_x, base_y; }; static const struct wl_method input_device_methods[] = { @@ -65,10 +65,18 @@ static void wl_input_device_data(int fd, uint32_t mask, void *data) absolute_event = 1; switch (e->code) { case ABS_X: - device->x = value; + if (device->new_x) { + device->base_x = device->x - value; + device->new_x = 0; + } + device->x = device->base_x + value; break; case ABS_Y: - device->y = value; + if (device->new_y) { + device->base_y = device->y - value; + device->new_y = 0; + } + device->y = device->base_y + value; break; } break; @@ -87,6 +95,10 @@ static void wl_input_device_data(int fd, uint32_t mask, void *data) case BTN_TOOL_FINGER: case BTN_TOOL_MOUSE: case BTN_TOOL_LENS: + if (device->tool == 0 && value) { + device->new_x = 1; + device->new_y = 1; + } device->tool = value ? e->code : 0; break; @@ -135,6 +147,10 @@ wl_input_device_create(struct wl_display *display, const char *path) device->base.interface = &input_device_interface; device->display = display; device->tool = 1; + device->x = 100; + device->y = 100; + device->new_x = 1; + device->new_y = 1; device->fd = open(path, O_RDONLY); if (device->fd < 0) { From 9a0f4ebce6023b8805eed8579113588863c062b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 2 Dec 2008 15:15:01 -0500 Subject: [PATCH 005/162] Put Wayland under the MIT license. --- evdev.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/evdev.c b/evdev.c index 713670a8..beba634b 100644 --- a/evdev.c +++ b/evdev.c @@ -1,3 +1,25 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * + * 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 #include #include From 800cdae9af7551c0550d2def26ce1697acf42dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 10 Dec 2008 13:16:50 -0500 Subject: [PATCH 006/162] Feed button events through compositor. This also generalizes the code to send events to a surface a bit. --- evdev.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/evdev.c b/evdev.c index beba634b..beeca29e 100644 --- a/evdev.c +++ b/evdev.c @@ -42,10 +42,18 @@ struct wl_input_device { static const struct wl_method input_device_methods[] = { }; +static const struct wl_event input_device_events[] = { + { "motion", "ii" }, + { "button", "uu" }, + { "key", "uu" }, +}; + static const struct wl_interface input_device_interface = { "input_device", 1, ARRAY_LENGTH(input_device_methods), input_device_methods, + ARRAY_LENGTH(input_device_events), + input_device_events, }; static void wl_input_device_data(int fd, uint32_t mask, void *data) From 3aa850dd903e21b90e0e4afd8eb5cc7fbbc5c615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 10 Dec 2008 17:31:44 -0500 Subject: [PATCH 007/162] Fix signature for pointer motion event. --- evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evdev.c b/evdev.c index beeca29e..b73ca9d7 100644 --- a/evdev.c +++ b/evdev.c @@ -43,7 +43,7 @@ static const struct wl_method input_device_methods[] = { }; static const struct wl_event input_device_events[] = { - { "motion", "ii" }, + { "motion", "iiii" }, { "button", "uu" }, { "key", "uu" }, }; From 8027cba2f1143f96556e4d056f10bee4554957b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 11 Dec 2008 23:18:45 -0500 Subject: [PATCH 008/162] Rewrite input event delivery path. Instead of having the input driver push the events into the core server, only to have the server call back out to the compositor hooks, the driver now just calls the compositor directly. The input drivers are always dependent on the type of compositor anyway so there was no point in passing the events through the server. Now the server is only involved when it's time to actually send the events to the clients. --- evdev.c | 84 +++++++++++++++++++++------------------------------------ 1 file changed, 30 insertions(+), 54 deletions(-) diff --git a/evdev.c b/evdev.c index b73ca9d7..77f82fd0 100644 --- a/evdev.c +++ b/evdev.c @@ -29,42 +29,28 @@ #include #include "wayland.h" +#include "egl-compositor.h" -struct wl_input_device { - struct wl_object base; +struct evdev_input_device { + struct egl_input_device *device; struct wl_event_source *source; - struct wl_display *display; - int fd; int tool, new_x, new_y; - int32_t x, y, base_x, base_y; + int base_x, base_y; + int fd; }; -static const struct wl_method input_device_methods[] = { -}; - -static const struct wl_event input_device_events[] = { - { "motion", "iiii" }, - { "button", "uu" }, - { "key", "uu" }, -}; - -static const struct wl_interface input_device_interface = { - "input_device", 1, - ARRAY_LENGTH(input_device_methods), - input_device_methods, - ARRAY_LENGTH(input_device_events), - input_device_events, -}; - -static void wl_input_device_data(int fd, uint32_t mask, void *data) +static void evdev_input_device_data(int fd, uint32_t mask, void *data) { - struct wl_input_device *device = data; + struct evdev_input_device *device = data; struct input_event ev[8], *e, *end; int len, value, dx, dy, absolute_event; + int x, y; dx = 0; dy = 0; absolute_event = 0; + egl_device_get_position(device->device, &x, &y); + len = read(fd, &ev, sizeof ev); if (len < 0 || len % sizeof e[0] != 0) { @@ -96,17 +82,17 @@ static void wl_input_device_data(int fd, uint32_t mask, void *data) switch (e->code) { case ABS_X: if (device->new_x) { - device->base_x = device->x - value; + device->base_x = x - value; device->new_x = 0; } - device->x = device->base_x + value; + x = device->base_x + value; break; case ABS_Y: if (device->new_y) { - device->base_y = device->y - value; + device->base_y = y - value; device->new_y = 0; } - device->y = device->base_y + value; + y = device->base_y + value; break; } break; @@ -133,54 +119,44 @@ static void wl_input_device_data(int fd, uint32_t mask, void *data) break; case BTN_LEFT: - wl_display_post_button_event(device->display, - &device->base, 0, value); - break; - case BTN_RIGHT: - wl_display_post_button_event(device->display, - &device->base, 2, value); - break; - case BTN_MIDDLE: - wl_display_post_button_event(device->display, - &device->base, 1, value); + case BTN_SIDE: + case BTN_EXTRA: + case BTN_FORWARD: + case BTN_BACK: + case BTN_TASK: + notify_button(device->device, e->code, value); break; default: - wl_display_post_key_event(device->display, - &device->base, e->code, value); + notify_key(device->device, e->code, value); break; } } } if (dx != 0 || dy != 0) - wl_display_post_relative_event(device->display, - &device->base, dx, dy); + notify_motion(device->device, x + dx, y + dy); if (absolute_event && device->tool) - wl_display_post_absolute_event(device->display, - &device->base, - device->x, device->y); + notify_motion(device->device, x, y); } -WL_EXPORT struct wl_object * -wl_input_device_create(struct wl_display *display, const char *path) +struct evdev_input_device * +evdev_input_device_create(struct egl_input_device *master, + struct wl_display *display, const char *path) { - struct wl_input_device *device; + struct evdev_input_device *device; struct wl_event_loop *loop; device = malloc(sizeof *device); if (device == NULL) return NULL; - device->base.interface = &input_device_interface; - device->display = display; device->tool = 1; - device->x = 100; - device->y = 100; device->new_x = 1; device->new_y = 1; + device->device = master; device->fd = open(path, O_RDONLY); if (device->fd < 0) { @@ -192,12 +168,12 @@ wl_input_device_create(struct wl_display *display, const char *path) loop = wl_display_get_event_loop(display); device->source = wl_event_loop_add_fd(loop, device->fd, WL_EVENT_READABLE, - wl_input_device_data, device); + evdev_input_device_data, device); if (device->source == NULL) { close(device->fd); free(device); return NULL; } - return &device->base; + return device; } From 566e81ccee1def495a28b7c1a72a7c94d1d048cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 19 Dec 2008 13:47:53 -0500 Subject: [PATCH 009/162] Rename egl-compositor to wayland-system-compositor. The wayland-system-compositor is the top-level compositor. X sessions or nested Wayland sessions will run as clients of the system compositor. The system compositor is licensed under the GPL. --- evdev.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/evdev.c b/evdev.c index 77f82fd0..d79db8fa 100644 --- a/evdev.c +++ b/evdev.c @@ -1,23 +1,19 @@ /* * Copyright © 2008 Kristian Høgsberg * - * 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. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * 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. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include @@ -29,10 +25,10 @@ #include #include "wayland.h" -#include "egl-compositor.h" +#include "wayland-system-compositor.h" struct evdev_input_device { - struct egl_input_device *device; + struct wlsc_input_device *device; struct wl_event_source *source; int tool, new_x, new_y; int base_x, base_y; @@ -49,8 +45,7 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data) dx = 0; dy = 0; absolute_event = 0; - egl_device_get_position(device->device, &x, &y); - + wlsc_device_get_position(device->device, &x, &y); len = read(fd, &ev, sizeof ev); if (len < 0 || len % sizeof e[0] != 0) { @@ -143,7 +138,7 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data) } struct evdev_input_device * -evdev_input_device_create(struct egl_input_device *master, +evdev_input_device_create(struct wlsc_input_device *master, struct wl_display *display, const char *path) { struct evdev_input_device *device; From b44f9173f939e473c2a46623310b662fc1cd4ff7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 4 Jun 2010 21:52:02 -0400 Subject: [PATCH 010/162] Rename wayland-system-compositor back to just compositor --- evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evdev.c b/evdev.c index d79db8fa..d934aa6c 100644 --- a/evdev.c +++ b/evdev.c @@ -25,7 +25,7 @@ #include #include "wayland.h" -#include "wayland-system-compositor.h" +#include "compositor.h" struct evdev_input_device { struct wlsc_input_device *device; From b98d9e87ae2ad3c8e4180ee967af888620ec9fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 11 Jun 2010 12:56:24 -0400 Subject: [PATCH 011/162] Split native drm part of compositor out --- evdev.c | 174 -------------------------------------------------------- 1 file changed, 174 deletions(-) delete mode 100644 evdev.c diff --git a/evdev.c b/evdev.c deleted file mode 100644 index d934aa6c..00000000 --- a/evdev.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright © 2008 Kristian Høgsberg - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include - -#include - -#include "wayland.h" -#include "compositor.h" - -struct evdev_input_device { - struct wlsc_input_device *device; - struct wl_event_source *source; - int tool, new_x, new_y; - int base_x, base_y; - int fd; -}; - -static void evdev_input_device_data(int fd, uint32_t mask, void *data) -{ - struct evdev_input_device *device = data; - struct input_event ev[8], *e, *end; - int len, value, dx, dy, absolute_event; - int x, y; - - dx = 0; - dy = 0; - absolute_event = 0; - wlsc_device_get_position(device->device, &x, &y); - - len = read(fd, &ev, sizeof ev); - if (len < 0 || len % sizeof e[0] != 0) { - /* FIXME: handle error... reopen device? */; - return; - } - - e = ev; - end = (void *) ev + len; - for (e = ev; e < end; e++) { - /* Get the signed value, earlier kernels had this as unsigned */ - value = e->value; - - switch (e->type) { - case EV_REL: - switch (e->code) { - case REL_X: - dx += value; - break; - - case REL_Y: - dy += value; - break; - } - break; - - case EV_ABS: - absolute_event = 1; - switch (e->code) { - case ABS_X: - if (device->new_x) { - device->base_x = x - value; - device->new_x = 0; - } - x = device->base_x + value; - break; - case ABS_Y: - if (device->new_y) { - device->base_y = y - value; - device->new_y = 0; - } - y = device->base_y + value; - break; - } - break; - - case EV_KEY: - if (value == 2) - break; - - switch (e->code) { - case BTN_TOUCH: - case BTN_TOOL_PEN: - case BTN_TOOL_RUBBER: - case BTN_TOOL_BRUSH: - case BTN_TOOL_PENCIL: - case BTN_TOOL_AIRBRUSH: - case BTN_TOOL_FINGER: - case BTN_TOOL_MOUSE: - case BTN_TOOL_LENS: - if (device->tool == 0 && value) { - device->new_x = 1; - device->new_y = 1; - } - device->tool = value ? e->code : 0; - 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: - notify_button(device->device, e->code, value); - break; - - default: - notify_key(device->device, e->code, value); - break; - } - } - } - - if (dx != 0 || dy != 0) - notify_motion(device->device, x + dx, y + dy); - if (absolute_event && device->tool) - notify_motion(device->device, x, y); -} - -struct evdev_input_device * -evdev_input_device_create(struct wlsc_input_device *master, - struct wl_display *display, const char *path) -{ - struct evdev_input_device *device; - struct wl_event_loop *loop; - - device = malloc(sizeof *device); - if (device == NULL) - return NULL; - - device->tool = 1; - device->new_x = 1; - device->new_y = 1; - device->device = master; - - device->fd = open(path, O_RDONLY); - if (device->fd < 0) { - free(device); - fprintf(stderr, "couldn't create pointer for %s: %m\n", path); - return NULL; - } - - loop = wl_display_get_event_loop(display); - device->source = wl_event_loop_add_fd(loop, device->fd, - WL_EVENT_READABLE, - evdev_input_device_data, device); - if (device->source == NULL) { - close(device->fd); - free(device); - return NULL; - } - - return device; -} From 3b3c0013815e0e3896f308d5973ccefce43c24a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 14 Jan 2011 14:45:42 -0500 Subject: [PATCH 012/162] Split out evdev handling to its own file --- compositor/evdev.c | 223 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 223 insertions(+) create mode 100644 compositor/evdev.c diff --git a/compositor/evdev.c b/compositor/evdev.c new file mode 100644 index 00000000..2b5ab6bf --- /dev/null +++ b/compositor/evdev.c @@ -0,0 +1,223 @@ +/* + * Copyright © 2010 Intel Corporation + * + * 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 +#include +#include +#include +#include +#include + +#include "compositor.h" + +struct evdev_input { + struct wlsc_input_device base; +}; + +struct evdev_input_device { + struct evdev_input *master; + struct wl_event_source *source; + int tool, new_x, new_y; + int base_x, base_y; + int fd; +}; + +static void evdev_input_device_data(int fd, uint32_t mask, void *data) +{ + struct wlsc_compositor *ec; + struct evdev_input_device *device = data; + struct input_event ev[8], *e, *end; + int len, value, dx, dy, absolute_event; + int x, y; + uint32_t time; + + ec = (struct wlsc_compositor *) + device->master->base.input_device.compositor; + if (!ec->focus) + return; + + dx = 0; + dy = 0; + absolute_event = 0; + x = device->master->base.input_device.x; + y = device->master->base.input_device.y; + + len = read(fd, &ev, sizeof ev); + if (len < 0 || len % sizeof e[0] != 0) { + /* FIXME: handle error... reopen device? */; + return; + } + + e = ev; + end = (void *) ev + len; + for (e = ev; e < end; e++) { + /* Get the signed value, earlier kernels had this as unsigned */ + value = e->value; + time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000; + + switch (e->type) { + case EV_REL: + switch (e->code) { + case REL_X: + dx += value; + break; + + case REL_Y: + dy += value; + break; + } + break; + + case EV_ABS: + absolute_event = 1; + switch (e->code) { + case ABS_X: + if (device->new_x) { + device->base_x = x - value; + device->new_x = 0; + } + x = device->base_x + value; + break; + case ABS_Y: + if (device->new_y) { + device->base_y = y - value; + device->new_y = 0; + } + y = device->base_y + value; + break; + } + break; + + case EV_KEY: + if (value == 2) + break; + + switch (e->code) { + case BTN_TOUCH: + case BTN_TOOL_PEN: + case BTN_TOOL_RUBBER: + case BTN_TOOL_BRUSH: + case BTN_TOOL_PENCIL: + case BTN_TOOL_AIRBRUSH: + case BTN_TOOL_FINGER: + case BTN_TOOL_MOUSE: + case BTN_TOOL_LENS: + if (device->tool == 0 && value) { + device->new_x = 1; + device->new_y = 1; + } + device->tool = value ? e->code : 0; + 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: + notify_button(&device->master->base.input_device, + time, e->code, value); + break; + + default: + notify_key(&device->master->base.input_device, + time, e->code, value); + break; + } + } + } + + if (dx != 0 || dy != 0) + notify_motion(&device->master->base.input_device, + time, x + dx, y + dy); + if (absolute_event && device->tool) + notify_motion(&device->master->base.input_device, time, x, y); +} + +static struct evdev_input_device * +evdev_input_device_create(struct evdev_input *master, + struct wl_display *display, const char *path) +{ + struct evdev_input_device *device; + struct wl_event_loop *loop; + + device = malloc(sizeof *device); + if (device == NULL) + return NULL; + + device->tool = 1; + device->new_x = 1; + device->new_y = 1; + device->master = master; + + device->fd = open(path, O_RDONLY); + if (device->fd < 0) { + free(device); + fprintf(stderr, "couldn't create pointer for %s: %m\n", path); + return NULL; + } + + loop = wl_display_get_event_loop(display); + device->source = wl_event_loop_add_fd(loop, device->fd, + WL_EVENT_READABLE, + evdev_input_device_data, device); + if (device->source == NULL) { + close(device->fd); + free(device); + return NULL; + } + + return device; +} + +void +evdev_input_add_devices(struct wlsc_compositor *c, struct udev *udev) +{ + struct evdev_input *input; + struct udev_enumerate *e; + struct udev_list_entry *entry; + struct udev_device *device; + const char *path; + + input = malloc(sizeof *input); + if (input == NULL) + return; + + memset(input, 0, sizeof *input); + wlsc_input_device_init(&input->base, c); + + e = udev_enumerate_new(udev); + udev_enumerate_add_match_subsystem(e, "input"); + udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1"); + udev_enumerate_scan_devices(e); + udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { + path = udev_list_entry_get_name(entry); + device = udev_device_new_from_syspath(udev, path); + evdev_input_device_create(input, c->wl_display, + udev_device_get_devnode(device)); + } + udev_enumerate_unref(e); + + c->input_device = &input->base.input_device; +} From 1a75173a73dfde8d70f5d649c37d4a2fc8d49678 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 14 Jan 2011 14:49:46 -0500 Subject: [PATCH 013/162] Some kind of support for touchscreen --- compositor/evdev.c | 48 ++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 2b5ab6bf..6ff7b699 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -39,6 +39,7 @@ struct evdev_input_device { int tool, new_x, new_y; int base_x, base_y; int fd; + int min_x, max_x, min_y, max_y; }; static void evdev_input_device_data(int fd, uint32_t mask, void *data) @@ -50,6 +51,10 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data) int x, y; uint32_t time; + /* FIXME: Obviously we need to not hardcode these here, but + * instead get the values from the output it's associated with. */ + const int screen_width = 1024, screen_height = 600; + ec = (struct wlsc_compositor *) device->master->base.input_device.compositor; if (!ec->focus) @@ -88,21 +93,16 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data) break; case EV_ABS: - absolute_event = 1; switch (e->code) { case ABS_X: - if (device->new_x) { - device->base_x = x - value; - device->new_x = 0; - } - x = device->base_x + value; + absolute_event = device->tool; + x = (value - device->min_x) * screen_width / + (device->max_x - device->min_x); break; case ABS_Y: - if (device->new_y) { - device->base_y = y - value; - device->new_y = 0; - } - y = device->base_y + value; + absolute_event = device->tool; + y = (value - device->min_y) * screen_height / + (device->max_y - device->min_y); break; } break; @@ -121,10 +121,6 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data) case BTN_TOOL_FINGER: case BTN_TOOL_MOUSE: case BTN_TOOL_LENS: - if (device->tool == 0 && value) { - device->new_x = 1; - device->new_y = 1; - } device->tool = value ? e->code : 0; break; @@ -151,16 +147,21 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data) if (dx != 0 || dy != 0) notify_motion(&device->master->base.input_device, time, x + dx, y + dy); - if (absolute_event && device->tool) + if (absolute_event) notify_motion(&device->master->base.input_device, time, x, y); } +#define TEST_BIT(b, i) (b[(i) / 32] & (1 << (i & 31))) + static struct evdev_input_device * evdev_input_device_create(struct evdev_input *master, struct wl_display *display, const char *path) { struct evdev_input_device *device; struct wl_event_loop *loop; + struct input_absinfo absinfo; + uint32_t ev_bits[EV_MAX]; + uint32_t key_bits[KEY_MAX]; device = malloc(sizeof *device); if (device == NULL) @@ -178,6 +179,21 @@ evdev_input_device_create(struct evdev_input *master, return NULL; } + ioctl(device->fd, EVIOCGBIT(0, EV_MAX), ev_bits); + if (TEST_BIT(ev_bits, EV_ABS)) { + ioctl(device->fd, EVIOCGBIT(EV_ABS, EV_MAX), key_bits); + if (TEST_BIT(key_bits, ABS_X)) { + ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo); + device->min_x = absinfo.minimum; + device->max_x = absinfo.maximum; + } + if (TEST_BIT(key_bits, ABS_Y)) { + ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo); + device->min_y = absinfo.minimum; + device->max_y = absinfo.maximum; + } + } + loop = wl_display_get_event_loop(display); device->source = wl_event_loop_add_fd(loop, device->fd, WL_EVENT_READABLE, From 0e0776fb62aedac115a460232da7abc6f5a02836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 22 Apr 2011 12:27:57 -0400 Subject: [PATCH 014/162] Update return types of event handler functions Missed this in previous commit. --- compositor/evdev.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 6ff7b699..de482257 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -42,7 +42,8 @@ struct evdev_input_device { int min_x, max_x, min_y, max_y; }; -static void evdev_input_device_data(int fd, uint32_t mask, void *data) +static int +evdev_input_device_data(int fd, uint32_t mask, void *data) { struct wlsc_compositor *ec; struct evdev_input_device *device = data; @@ -58,7 +59,7 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data) ec = (struct wlsc_compositor *) device->master->base.input_device.compositor; if (!ec->focus) - return; + return 1; dx = 0; dy = 0; @@ -69,7 +70,7 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data) len = read(fd, &ev, sizeof ev); if (len < 0 || len % sizeof e[0] != 0) { /* FIXME: handle error... reopen device? */; - return; + return 1; } e = ev; @@ -149,6 +150,8 @@ static void evdev_input_device_data(int fd, uint32_t mask, void *data) time, x + dx, y + dy); if (absolute_event) notify_motion(&device->master->base.input_device, time, x, y); + + return 1; } #define TEST_BIT(b, i) (b[(i) / 32] & (1 << (i & 31))) From 1ba7295e44850549ccc1471c8355cc7b1d7df9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 19 Jul 2011 16:10:11 -0700 Subject: [PATCH 015/162] compositor: Use systemd seats for input devices as well --- compositor/evdev.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index de482257..def22b9d 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -210,13 +210,17 @@ evdev_input_device_create(struct evdev_input *master, return device; } +static const char default_seat[] = "seat0"; + void -evdev_input_add_devices(struct wlsc_compositor *c, struct udev *udev) +evdev_input_add_devices(struct wlsc_compositor *c, + struct udev *udev, const char *seat) { struct evdev_input *input; struct udev_enumerate *e; struct udev_list_entry *entry; struct udev_device *device; + const char *device_seat; const char *path; input = malloc(sizeof *input); @@ -228,13 +232,22 @@ evdev_input_add_devices(struct wlsc_compositor *c, struct udev *udev) e = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(e, "input"); - udev_enumerate_add_match_property(e, "WAYLAND_SEAT", "1"); udev_enumerate_scan_devices(e); udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { path = udev_list_entry_get_name(entry); device = udev_device_new_from_syspath(udev, path); - evdev_input_device_create(input, c->wl_display, - udev_device_get_devnode(device)); + + device_seat = + udev_device_get_property_value(device, "ID_SEAT"); + if (!device_seat) + device_seat = default_seat; + + if (strcmp(device_seat, seat) == 0) { + evdev_input_device_create(input, c->wl_display, + udev_device_get_devnode(device)); + } + + udev_device_unref(device); } udev_enumerate_unref(e); From bdf74308e3debd3d7657896e80d5a88a4aa6e13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 21 Jul 2011 06:46:26 -0700 Subject: [PATCH 016/162] evdev: Only add event devices --- compositor/evdev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compositor/evdev.c b/compositor/evdev.c index def22b9d..9a9a3100 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -237,6 +237,9 @@ evdev_input_add_devices(struct wlsc_compositor *c, path = udev_list_entry_get_name(entry); device = udev_device_new_from_syspath(udev, path); + if (strncmp("event", udev_device_get_sysname(device), 5) != 0) + continue; + device_seat = udev_device_get_property_value(device, "ID_SEAT"); if (!device_seat) From 0ced95682dac7461ff95ef9d067f58f8b9496e0c Mon Sep 17 00:00:00 2001 From: Matt Peterson Date: Mon, 1 Aug 2011 13:46:29 -0600 Subject: [PATCH 017/162] Relative movement with a touchpad and other misc fixes for events --- compositor/evdev.c | 87 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 9a9a3100..ff1cdaa9 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -40,6 +40,7 @@ struct evdev_input_device { int base_x, base_y; int fd; int min_x, max_x, min_y, max_y; + int is_touchpad, old_x_value, old_y_value, reset_x_value, reset_y_value; }; static int @@ -55,6 +56,9 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) /* FIXME: Obviously we need to not hardcode these here, but * instead get the values from the output it's associated with. */ const int screen_width = 1024, screen_height = 600; + + /* FIXME: Make this configurable somehow. */ + const int touchpad_speed = 700; ec = (struct wlsc_compositor *) device->master->base.input_device.compositor; @@ -94,17 +98,43 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) break; case EV_ABS: - switch (e->code) { - case ABS_X: - absolute_event = device->tool; - x = (value - device->min_x) * screen_width / - (device->max_x - device->min_x); - break; - case ABS_Y: - absolute_event = device->tool; - y = (value - device->min_y) * screen_height / - (device->max_y - device->min_y); - break; + if (device->is_touchpad) { + switch (e->code) { + case ABS_X: + value -= device->min_x; + if (device->reset_x_value) + device->reset_x_value = 0; + else { + dx = (value - device->old_x_value) * touchpad_speed / + (device->max_x - device->min_x); + } + device->old_x_value = value; + break; + case ABS_Y: + value -= device->min_y; + if (device->reset_y_value) + device->reset_y_value = 0; + else { + dy = (value - device->old_y_value) * touchpad_speed / + /* maybe use x size here to have the same scale? */ + (device->max_y - device->min_y); + } + device->old_y_value = value; + break; + } + } else { + switch (e->code) { + case ABS_X: + absolute_event = device->tool; + x = (value - device->min_x) * screen_width / + (device->max_x - device->min_x); + break; + case ABS_Y: + absolute_event = device->tool; + y = (value - device->min_y) * screen_height / + (device->max_y - device->min_y); + break; + } } break; @@ -123,6 +153,11 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) case BTN_TOOL_MOUSE: case BTN_TOOL_LENS: device->tool = value ? e->code : 0; + if (device->is_touchpad) + { + device->reset_x_value = 1; + device->reset_y_value = 1; + } break; case BTN_LEFT: @@ -154,7 +189,16 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) return 1; } -#define TEST_BIT(b, i) (b[(i) / 32] & (1 << (i & 31))) + +/* 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(bit)) & 1) +/* end copied */ static struct evdev_input_device * evdev_input_device_create(struct evdev_input *master, @@ -163,8 +207,9 @@ evdev_input_device_create(struct evdev_input *master, struct evdev_input_device *device; struct wl_event_loop *loop; struct input_absinfo absinfo; - uint32_t ev_bits[EV_MAX]; - uint32_t key_bits[KEY_MAX]; + unsigned long ev_bits[NBITS(EV_MAX)]; + unsigned long abs_bits[NBITS(ABS_MAX)]; + unsigned long key_bits[NBITS(KEY_MAX)]; device = malloc(sizeof *device); if (device == NULL) @@ -174,6 +219,7 @@ evdev_input_device_create(struct evdev_input *master, device->new_x = 1; device->new_y = 1; device->master = master; + device->is_touchpad = 0; device->fd = open(path, O_RDONLY); if (device->fd < 0) { @@ -182,20 +228,25 @@ evdev_input_device_create(struct evdev_input *master, return NULL; } - ioctl(device->fd, EVIOCGBIT(0, EV_MAX), ev_bits); + ioctl(device->fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits); if (TEST_BIT(ev_bits, EV_ABS)) { - ioctl(device->fd, EVIOCGBIT(EV_ABS, EV_MAX), key_bits); - if (TEST_BIT(key_bits, ABS_X)) { + ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits); + if (TEST_BIT(abs_bits, ABS_X)) { ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo); device->min_x = absinfo.minimum; device->max_x = absinfo.maximum; } - if (TEST_BIT(key_bits, ABS_Y)) { + if (TEST_BIT(abs_bits, ABS_Y)) { ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo); device->min_y = absinfo.minimum; device->max_y = absinfo.maximum; } } + if (TEST_BIT(ev_bits, EV_KEY)) { + 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)) + device->is_touchpad = 1; + } loop = wl_display_get_event_loop(display); device->source = wl_event_loop_add_fd(loop, device->fd, From 8355f0670a892e0005ba2f92d32124b969ebb862 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Fri, 19 Aug 2011 15:06:20 +0300 Subject: [PATCH 018/162] evdev: use a separate function for configuring devices No semantical changes. Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 56 +++++++++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index ff1cdaa9..150ca04c 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -200,16 +200,44 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) #define TEST_BIT(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1) /* end copied */ +static void +evdev_configure_device(struct evdev_input_device *device) +{ + struct input_absinfo absinfo; + unsigned long ev_bits[NBITS(EV_MAX)]; + unsigned long abs_bits[NBITS(ABS_MAX)]; + unsigned long key_bits[NBITS(KEY_MAX)]; + + ioctl(device->fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits); + if (TEST_BIT(ev_bits, EV_ABS)) { + ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), + abs_bits); + if (TEST_BIT(abs_bits, ABS_X)) { + ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo); + device->min_x = absinfo.minimum; + device->max_x = absinfo.maximum; + } + if (TEST_BIT(abs_bits, ABS_Y)) { + ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo); + device->min_y = absinfo.minimum; + device->max_y = absinfo.maximum; + } + } + if (TEST_BIT(ev_bits, EV_KEY)) { + 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)) + device->is_touchpad = 1; + } +} + static struct evdev_input_device * evdev_input_device_create(struct evdev_input *master, struct wl_display *display, const char *path) { struct evdev_input_device *device; struct wl_event_loop *loop; - struct input_absinfo absinfo; - unsigned long ev_bits[NBITS(EV_MAX)]; - unsigned long abs_bits[NBITS(ABS_MAX)]; - unsigned long key_bits[NBITS(KEY_MAX)]; device = malloc(sizeof *device); if (device == NULL) @@ -228,25 +256,7 @@ evdev_input_device_create(struct evdev_input *master, return NULL; } - ioctl(device->fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits); - if (TEST_BIT(ev_bits, EV_ABS)) { - ioctl(device->fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits); - if (TEST_BIT(abs_bits, ABS_X)) { - ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo); - device->min_x = absinfo.minimum; - device->max_x = absinfo.maximum; - } - if (TEST_BIT(abs_bits, ABS_Y)) { - ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo); - device->min_y = absinfo.minimum; - device->max_y = absinfo.maximum; - } - } - if (TEST_BIT(ev_bits, EV_KEY)) { - 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)) - device->is_touchpad = 1; - } + evdev_configure_device(device); loop = wl_display_get_event_loop(display); device->source = wl_event_loop_add_fd(loop, device->fd, From 99476b1a6945290ec2dc02eb1b4af846d6532eef Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Fri, 19 Aug 2011 17:07:40 +0300 Subject: [PATCH 019/162] evdev: opt out accelerometer type of devices We may want to adjust the protocol later for clients that care for these devices only, generating a special event. Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 150ca04c..03dbac31 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -200,16 +200,21 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) #define TEST_BIT(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1) /* end copied */ -static void +static int evdev_configure_device(struct evdev_input_device *device) { struct input_absinfo absinfo; unsigned long ev_bits[NBITS(EV_MAX)]; unsigned long abs_bits[NBITS(ABS_MAX)]; unsigned long key_bits[NBITS(KEY_MAX)]; + int has_key, has_abs; + + has_key = 0; + has_abs = 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_X)) { @@ -224,12 +229,21 @@ evdev_configure_device(struct evdev_input_device *device) } } 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)) device->is_touchpad = 1; } + + /* 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) + return -1; + + return 0; } static struct evdev_input_device * @@ -256,7 +270,11 @@ evdev_input_device_create(struct evdev_input *master, return NULL; } - evdev_configure_device(device); + if (evdev_configure_device(device) == -1) { + close(device->fd); + free(device); + return NULL; + } loop = wl_display_get_event_loop(display); device->source = wl_event_loop_add_fd(loop, device->fd, From 76dc338535c6e7f86ae2669384244c2babe430ae Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Thu, 1 Sep 2011 19:00:03 +0300 Subject: [PATCH 020/162] evdev: organize the code for processing events Nothing was touched, just code moved around. Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 210 +++++++++++++++++++++++++-------------------- 1 file changed, 118 insertions(+), 92 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 03dbac31..edb65750 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -43,6 +43,116 @@ struct evdev_input_device { int is_touchpad, old_x_value, old_y_value, reset_x_value, reset_y_value; }; +static inline void +evdev_process_key(struct evdev_input_device *device, + struct input_event *e, int value, int time) +{ + switch (e->code) { + case BTN_TOUCH: + case BTN_TOOL_PEN: + case BTN_TOOL_RUBBER: + case BTN_TOOL_BRUSH: + case BTN_TOOL_PENCIL: + case BTN_TOOL_AIRBRUSH: + case BTN_TOOL_FINGER: + case BTN_TOOL_MOUSE: + case BTN_TOOL_LENS: + device->tool = value ? e->code : 0; + if (device->is_touchpad) + { + device->reset_x_value = 1; + device->reset_y_value = 1; + } + 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: + notify_button(&device->master->base.input_device, + time, e->code, value); + break; + + default: + notify_key(&device->master->base.input_device, + time, e->code, value); + break; + } +} + +static inline void +evdev_process_absolute_motion(struct evdev_input_device *device, + struct input_event *e, int value, int *x, int *y, + int *absolute_event) +{ + /* FIXME: Obviously we need to not hardcode these here, but + * instead get the values from the output it's associated with. */ + const int screen_width = 1024, screen_height = 600; + + switch (e->code) { + case ABS_X: + *absolute_event = device->tool; + *x = (value - device->min_x) * screen_width / + (device->max_x - device->min_x); + break; + case ABS_Y: + *absolute_event = device->tool; + *y = (value - device->min_y) * screen_height / + (device->max_y - device->min_y); + break; + } +} + +static inline void +evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, + struct input_event *e, int value, int *dx, int *dy) +{ + /* FIXME: Make this configurable somehow. */ + const int touchpad_speed = 700; + + switch (e->code) { + case ABS_X: + value -= device->min_x; + if (device->reset_x_value) + device->reset_x_value = 0; + else { + *dx = (value - device->old_x_value) * touchpad_speed / + (device->max_x - device->min_x); + } + device->old_x_value = value; + break; + case ABS_Y: + value -= device->min_y; + if (device->reset_y_value) + device->reset_y_value = 0; + else { + *dy = (value - device->old_y_value) * touchpad_speed / + /* maybe use x size here to have the same scale? */ + (device->max_y - device->min_y); + } + device->old_y_value = value; + break; + } +} + +static inline void +evdev_process_relative_motion(struct input_event *e, int value, int *dx, + int *dy) +{ + switch (e->code) { + case REL_X: + *dx += value; + break; + case REL_Y: + *dy += value; + break; + } +} + static int evdev_input_device_data(int fd, uint32_t mask, void *data) { @@ -53,13 +163,6 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) int x, y; uint32_t time; - /* FIXME: Obviously we need to not hardcode these here, but - * instead get the values from the output it's associated with. */ - const int screen_width = 1024, screen_height = 600; - - /* FIXME: Make this configurable somehow. */ - const int touchpad_speed = 700; - ec = (struct wlsc_compositor *) device->master->base.input_device.compositor; if (!ec->focus) @@ -86,97 +189,20 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) switch (e->type) { case EV_REL: - switch (e->code) { - case REL_X: - dx += value; - break; - - case REL_Y: - dy += value; - break; - } + evdev_process_relative_motion(e, value, &dx, &dy); break; - case EV_ABS: - if (device->is_touchpad) { - switch (e->code) { - case ABS_X: - value -= device->min_x; - if (device->reset_x_value) - device->reset_x_value = 0; - else { - dx = (value - device->old_x_value) * touchpad_speed / - (device->max_x - device->min_x); - } - device->old_x_value = value; - break; - case ABS_Y: - value -= device->min_y; - if (device->reset_y_value) - device->reset_y_value = 0; - else { - dy = (value - device->old_y_value) * touchpad_speed / - /* maybe use x size here to have the same scale? */ - (device->max_y - device->min_y); - } - device->old_y_value = value; - break; - } - } else { - switch (e->code) { - case ABS_X: - absolute_event = device->tool; - x = (value - device->min_x) * screen_width / - (device->max_x - device->min_x); - break; - case ABS_Y: - absolute_event = device->tool; - y = (value - device->min_y) * screen_height / - (device->max_y - device->min_y); - break; - } - } + if (device->is_touchpad) + evdev_process_absolute_motion_touchpad(device, + e, value, &dx, &dy); + else + evdev_process_absolute_motion(device, e, value, + &x, &y, &absolute_event); break; - case EV_KEY: if (value == 2) break; - - switch (e->code) { - case BTN_TOUCH: - case BTN_TOOL_PEN: - case BTN_TOOL_RUBBER: - case BTN_TOOL_BRUSH: - case BTN_TOOL_PENCIL: - case BTN_TOOL_AIRBRUSH: - case BTN_TOOL_FINGER: - case BTN_TOOL_MOUSE: - case BTN_TOOL_LENS: - device->tool = value ? e->code : 0; - if (device->is_touchpad) - { - device->reset_x_value = 1; - device->reset_y_value = 1; - } - 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: - notify_button(&device->master->base.input_device, - time, e->code, value); - break; - - default: - notify_key(&device->master->base.input_device, - time, e->code, value); - break; - } + evdev_process_key(device, e, value, time); } } From b5b8c0e807248de0edec6802fdf63ac9a49ec941 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Thu, 1 Sep 2011 19:00:04 +0300 Subject: [PATCH 021/162] evdev: use last output from compositor to get the screen geometries Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index edb65750..662a61c0 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -87,11 +87,12 @@ evdev_process_key(struct evdev_input_device *device, static inline void evdev_process_absolute_motion(struct evdev_input_device *device, struct input_event *e, int value, int *x, int *y, - int *absolute_event) + int *absolute_event, struct wlsc_compositor *ec) { - /* FIXME: Obviously we need to not hardcode these here, but - * instead get the values from the output it's associated with. */ - const int screen_width = 1024, screen_height = 600; + const int screen_width = container_of(ec->output_list.prev, + struct wlsc_output, link)->current->width; + const int screen_height = container_of(ec->output_list.prev, + struct wlsc_output, link)->current->height; switch (e->code) { case ABS_X: @@ -197,7 +198,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) e, value, &dx, &dy); else evdev_process_absolute_motion(device, e, value, - &x, &y, &absolute_event); + &x, &y, &absolute_event, ec); break; case EV_KEY: if (value == 2) From 728a38301f817657ff37d6b5f6e81e41f1779e51 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Thu, 1 Sep 2011 19:00:05 +0300 Subject: [PATCH 022/162] evdev: treat BTN_TOUCH as BTN_LEFT idea stolen from xorg evdev. Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 662a61c0..113eded9 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -48,7 +48,6 @@ evdev_process_key(struct evdev_input_device *device, struct input_event *e, int value, int time) { switch (e->code) { - case BTN_TOUCH: case BTN_TOOL_PEN: case BTN_TOOL_RUBBER: case BTN_TOOL_BRUSH: @@ -65,6 +64,11 @@ evdev_process_key(struct evdev_input_device *device, } break; + case BTN_TOUCH: + /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as + * BTN_LEFT */ + e->code = BTN_LEFT; + /* Intentional fallthrough! */ case BTN_LEFT: case BTN_RIGHT: case BTN_MIDDLE: From 771c31005d8f3faada1da2b3ff593a58f7360364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 1 Sep 2011 13:25:50 -0400 Subject: [PATCH 023/162] evdev: Associate touchscreen devices with output up front This isn't going to change over time, so just tracking it in the evdev device is a little easier. Also, we need to adjust for the output position when transforming the device events to screen space. --- compositor/evdev.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 113eded9..f0cdf30b 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -36,6 +36,7 @@ struct evdev_input { struct evdev_input_device { struct evdev_input *master; struct wl_event_source *source; + struct wlsc_output *output; int tool, new_x, new_y; int base_x, base_y; int fd; @@ -91,23 +92,21 @@ evdev_process_key(struct evdev_input_device *device, static inline void evdev_process_absolute_motion(struct evdev_input_device *device, struct input_event *e, int value, int *x, int *y, - int *absolute_event, struct wlsc_compositor *ec) + int *absolute_event) { - const int screen_width = container_of(ec->output_list.prev, - struct wlsc_output, link)->current->width; - const int screen_height = container_of(ec->output_list.prev, - struct wlsc_output, link)->current->height; + const int screen_width = device->output->current->width; + const int screen_height = device->output->current->height; switch (e->code) { case ABS_X: *absolute_event = device->tool; *x = (value - device->min_x) * screen_width / - (device->max_x - device->min_x); + (device->max_x - device->min_x) + device->output->x; break; case ABS_Y: *absolute_event = device->tool; *y = (value - device->min_y) * screen_height / - (device->max_y - device->min_y); + (device->max_y - device->min_y) + device->output->y; break; } } @@ -202,7 +201,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) e, value, &dx, &dy); else evdev_process_absolute_motion(device, e, value, - &x, &y, &absolute_event, ec); + &x, &y, &absolute_event); break; case EV_KEY: if (value == 2) @@ -283,11 +282,16 @@ evdev_input_device_create(struct evdev_input *master, { struct evdev_input_device *device; struct wl_event_loop *loop; + struct wlsc_compositor *ec; device = malloc(sizeof *device); if (device == NULL) return NULL; + ec = (struct wlsc_compositor *) master->base.input_device.compositor; + device->output = + container_of(ec->output_list.next, struct wlsc_output, link); + device->tool = 1; device->new_x = 1; device->new_y = 1; From 6ee755d0db1a956e8eaf7c5a69ff125f3259d4c7 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Fri, 28 Oct 2011 13:05:06 -0400 Subject: [PATCH 024/162] evdev: Add hotplug support Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 123 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 112 insertions(+), 11 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index f0cdf30b..2f1b1423 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -31,12 +31,17 @@ struct evdev_input { struct wlsc_input_device base; + struct wl_list devices_list; + struct udev_monitor *udev_monitor; + char *seat_id; }; struct evdev_input_device { struct evdev_input *master; + struct wl_list link; struct wl_event_source *source; struct wlsc_output *output; + char *devnode; int tool, new_x, new_y; int base_x, base_y; int fd; @@ -180,7 +185,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) len = read(fd, &ev, sizeof ev); if (len < 0 || len % sizeof e[0] != 0) { - /* FIXME: handle error... reopen device? */; + /* FIXME: call device_removed when errno is ENODEV. */; return 1; } @@ -297,9 +302,11 @@ evdev_input_device_create(struct evdev_input *master, device->new_y = 1; device->master = master; device->is_touchpad = 0; + device->devnode = strdup(path); device->fd = open(path, O_RDONLY); if (device->fd < 0) { + free(device->devnode); free(device); fprintf(stderr, "couldn't create pointer for %s: %m\n", path); return NULL; @@ -307,6 +314,7 @@ evdev_input_device_create(struct evdev_input *master, if (evdev_configure_device(device) == -1) { close(device->fd); + free(device->devnode); free(device); return NULL; } @@ -317,15 +325,109 @@ evdev_input_device_create(struct evdev_input *master, evdev_input_device_data, device); if (device->source == NULL) { close(device->fd); + free(device->devnode); free(device); return NULL; } + wl_list_insert(master->devices_list.prev, &device->link); return device; } static const char default_seat[] = "seat0"; +static void +device_added(struct udev_device *udev_device, struct evdev_input *master) +{ + struct wlsc_compositor *c; + const char *devnode; + const char *device_seat; + + device_seat = udev_device_get_property_value(udev_device, "ID_SEAT"); + if (!device_seat) + device_seat = default_seat; + + if (strcmp(device_seat, master->seat_id)) + return; + + c = (struct wlsc_compositor *) master->base.input_device.compositor; + devnode = udev_device_get_devnode(udev_device); + if (evdev_input_device_create(master, c->wl_display, devnode)) + fprintf(stderr, "evdev input device: added: %s\n", devnode); +} + +static void +device_removed(struct udev_device *udev_device, struct evdev_input *master) +{ + const char *devnode = udev_device_get_devnode(udev_device); + struct evdev_input_device *device, *next; + + wl_list_for_each_safe(device, next, &master->devices_list, link) { + if (!strcmp(device->devnode, devnode)) { + wl_event_source_remove(device->source); + wl_list_remove(&device->link); + close(device->fd); + free(device->devnode); + free(device); + break; + } + } + fprintf(stderr, "evdev input device: removed: %s\n", devnode); +} + +static int +evdev_udev_handler(int fd, uint32_t mask, void *data) +{ + struct evdev_input *master = data; + struct udev_device *udev_device; + const char *action; + + udev_device = udev_monitor_receive_device(master->udev_monitor); + if (!udev_device) + return 1; + + action = udev_device_get_action(udev_device); + if (action) { + if (strncmp("event", udev_device_get_sysname(udev_device), 5) != 0) + return 0; + + if (!strcmp(action, "add")) { + device_added(udev_device, master); + } + else if (!strcmp(action, "remove")) + device_removed(udev_device, master); + } + udev_device_unref(udev_device); + + return 0; +} + +static int +evdev_config_udev_monitor(struct udev *udev, struct evdev_input *master) +{ + struct wl_event_loop *loop; + struct wlsc_compositor *c = + (struct wlsc_compositor *) master->base.input_device.compositor; + + master->udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); + if (!master->udev_monitor) + return 0; + + udev_monitor_filter_add_match_subsystem_devtype(master->udev_monitor, + "input", NULL); + + if (udev_monitor_enable_receiving(master->udev_monitor)) { + fprintf(stderr, "udev: failed to bind the udev monitor\n"); + return 0; + } + + loop = wl_display_get_event_loop(c->wl_display); + wl_event_loop_add_fd(loop, udev_monitor_get_fd(master->udev_monitor), + WL_EVENT_READABLE, evdev_udev_handler, master); + + return 1; +} + void evdev_input_add_devices(struct wlsc_compositor *c, struct udev *udev, const char *seat) @@ -334,7 +436,6 @@ evdev_input_add_devices(struct wlsc_compositor *c, struct udev_enumerate *e; struct udev_list_entry *entry; struct udev_device *device; - const char *device_seat; const char *path; input = malloc(sizeof *input); @@ -344,6 +445,14 @@ evdev_input_add_devices(struct wlsc_compositor *c, memset(input, 0, sizeof *input); wlsc_input_device_init(&input->base, c); + wl_list_init(&input->devices_list); + input->seat_id = strdup(seat); + if (!evdev_config_udev_monitor(udev, input)) { + free(input->seat_id); + free(input); + return; + } + e = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(e, "input"); udev_enumerate_scan_devices(e); @@ -354,15 +463,7 @@ evdev_input_add_devices(struct wlsc_compositor *c, if (strncmp("event", udev_device_get_sysname(device), 5) != 0) continue; - device_seat = - udev_device_get_property_value(device, "ID_SEAT"); - if (!device_seat) - device_seat = default_seat; - - if (strcmp(device_seat, seat) == 0) { - evdev_input_device_create(input, c->wl_display, - udev_device_get_devnode(device)); - } + device_added(device, input); udev_device_unref(device); } From 3b6274e10cce1dd91a404ce170e59eac0f318e9e Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Fri, 28 Oct 2011 13:09:42 -0400 Subject: [PATCH 025/162] evdev: Delete unused fields from evdev_input_device Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 2f1b1423..b63500e3 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -42,8 +42,7 @@ struct evdev_input_device { struct wl_event_source *source; struct wlsc_output *output; char *devnode; - int tool, new_x, new_y; - int base_x, base_y; + int tool; int fd; int min_x, max_x, min_y, max_y; int is_touchpad, old_x_value, old_y_value, reset_x_value, reset_y_value; @@ -298,8 +297,6 @@ evdev_input_device_create(struct evdev_input *master, container_of(ec->output_list.next, struct wlsc_output, link); device->tool = 1; - device->new_x = 1; - device->new_y = 1; device->master = master; device->is_touchpad = 0; device->devnode = strdup(path); From f9abe44b984a4edc1fce89b851fcbed6425243a0 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Fri, 28 Oct 2011 13:15:25 -0400 Subject: [PATCH 026/162] evdev: Simplify error path for device creation Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index b63500e3..a432204a 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -293,7 +293,7 @@ evdev_input_device_create(struct evdev_input *master, return NULL; ec = (struct wlsc_compositor *) master->base.input_device.compositor; - device->output = + device->output = container_of(ec->output_list.next, struct wlsc_output, link); device->tool = 1; @@ -302,33 +302,29 @@ evdev_input_device_create(struct evdev_input *master, device->devnode = strdup(path); device->fd = open(path, O_RDONLY); - if (device->fd < 0) { - free(device->devnode); - free(device); - fprintf(stderr, "couldn't create pointer for %s: %m\n", path); - return NULL; - } + if (device->fd < 0) + goto err0; - if (evdev_configure_device(device) == -1) { - close(device->fd); - free(device->devnode); - free(device); - return NULL; - } + if (evdev_configure_device(device) == -1) + goto err1; loop = wl_display_get_event_loop(display); device->source = wl_event_loop_add_fd(loop, device->fd, WL_EVENT_READABLE, evdev_input_device_data, device); - if (device->source == NULL) { - close(device->fd); - free(device->devnode); - free(device); - return NULL; - } + if (device->source == NULL) + goto err1; wl_list_insert(master->devices_list.prev, &device->link); + return device; + +err1: + close(device->fd); +err0: + free(device->devnode); + free(device); + return NULL; } static const char default_seat[] = "seat0"; From 11bf9d088c93b124ba58e9c18476c9ae1d3d0c5b Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Thu, 10 Nov 2011 14:47:30 +0200 Subject: [PATCH 027/162] evdev: remove signed value checks Very likely that 2.4 kernels won't be used with Wayland compositor so the check for signal value is pretty much useless. It's okay to change e->value inside evdev_process_absolute_motion_touchpad given it's not used later on, and I also rather not touch this snip because it will be changed when multi-touch support arrives. Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 53 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index a432204a..2b87084a 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -50,8 +50,11 @@ struct evdev_input_device { static inline void evdev_process_key(struct evdev_input_device *device, - struct input_event *e, int value, int time) + struct input_event *e, int time) { + if (e->value == 2) + return; + switch (e->code) { case BTN_TOOL_PEN: case BTN_TOOL_RUBBER: @@ -61,7 +64,7 @@ evdev_process_key(struct evdev_input_device *device, case BTN_TOOL_FINGER: case BTN_TOOL_MOUSE: case BTN_TOOL_LENS: - device->tool = value ? e->code : 0; + device->tool = e->value ? e->code : 0; if (device->is_touchpad) { device->reset_x_value = 1; @@ -83,19 +86,19 @@ evdev_process_key(struct evdev_input_device *device, case BTN_BACK: case BTN_TASK: notify_button(&device->master->base.input_device, - time, e->code, value); + time, e->code, e->value); break; default: notify_key(&device->master->base.input_device, - time, e->code, value); + time, e->code, e->value); break; } } static inline void evdev_process_absolute_motion(struct evdev_input_device *device, - struct input_event *e, int value, int *x, int *y, + struct input_event *e, int *x, int *y, int *absolute_event) { const int screen_width = device->output->current->width; @@ -104,12 +107,12 @@ evdev_process_absolute_motion(struct evdev_input_device *device, switch (e->code) { case ABS_X: *absolute_event = device->tool; - *x = (value - device->min_x) * screen_width / + *x = (e->value - device->min_x) * screen_width / (device->max_x - device->min_x) + device->output->x; break; case ABS_Y: *absolute_event = device->tool; - *y = (value - device->min_y) * screen_height / + *y = (e->value - device->min_y) * screen_height / (device->max_y - device->min_y) + device->output->y; break; } @@ -117,46 +120,45 @@ evdev_process_absolute_motion(struct evdev_input_device *device, static inline void evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, - struct input_event *e, int value, int *dx, int *dy) + struct input_event *e, int *dx, int *dy) { /* FIXME: Make this configurable somehow. */ const int touchpad_speed = 700; switch (e->code) { case ABS_X: - value -= device->min_x; + e->value -= device->min_x; if (device->reset_x_value) device->reset_x_value = 0; else { - *dx = (value - device->old_x_value) * touchpad_speed / + *dx = (e->value - device->old_x_value) * touchpad_speed / (device->max_x - device->min_x); } - device->old_x_value = value; + device->old_x_value = e->value; break; case ABS_Y: - value -= device->min_y; + e->value -= device->min_y; if (device->reset_y_value) device->reset_y_value = 0; else { - *dy = (value - device->old_y_value) * touchpad_speed / + *dy = (e->value - device->old_y_value) * touchpad_speed / /* maybe use x size here to have the same scale? */ (device->max_y - device->min_y); } - device->old_y_value = value; + device->old_y_value = e->value; break; } } static inline void -evdev_process_relative_motion(struct input_event *e, int value, int *dx, - int *dy) +evdev_process_relative_motion(struct input_event *e, int *dx, int *dy) { switch (e->code) { case REL_X: - *dx += value; + *dx += e->value; break; case REL_Y: - *dy += value; + *dy += e->value; break; } } @@ -167,7 +169,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) struct wlsc_compositor *ec; struct evdev_input_device *device = data; struct input_event ev[8], *e, *end; - int len, value, dx, dy, absolute_event; + int len, dx, dy, absolute_event; int x, y; uint32_t time; @@ -191,26 +193,23 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) e = ev; end = (void *) ev + len; for (e = ev; e < end; e++) { - /* Get the signed value, earlier kernels had this as unsigned */ - value = e->value; time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000; switch (e->type) { case EV_REL: - evdev_process_relative_motion(e, value, &dx, &dy); + evdev_process_relative_motion(e, &dx, &dy); break; case EV_ABS: if (device->is_touchpad) evdev_process_absolute_motion_touchpad(device, - e, value, &dx, &dy); + e, &dx, &dy); else - evdev_process_absolute_motion(device, e, value, + evdev_process_absolute_motion(device, e, &x, &y, &absolute_event); break; case EV_KEY: - if (value == 2) - break; - evdev_process_key(device, e, value, time); + evdev_process_key(device, e, time); + break; } } From c6fc7c3d218a136cac5976b1fcf35a94a364533a Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Fri, 18 Nov 2011 14:56:58 +0200 Subject: [PATCH 028/162] evdev: fix order of events being sent to the compositor Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 2b87084a..784fa4c5 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -163,6 +163,37 @@ evdev_process_relative_motion(struct input_event *e, int *dx, int *dy) } } +static int +is_motion_event(struct input_event *e) +{ + switch (e->type) { + case EV_REL: + switch (e->code) { + case REL_X: + case REL_Y: + return 1; + } + case EV_ABS: + switch (e->code) { + case ABS_X: + case ABS_Y: + return 1; + } + } + + return 0; +} + +static void +evdev_flush_motion(struct wl_input_device *device, uint32_t time, int x, int y, + int dx, int dy, int absolute_event) +{ + if (dx != 0 || dy != 0) + notify_motion(device, time, x + dx, y + dy); + if (absolute_event) + notify_motion(device, time, x, y); +} + static int evdev_input_device_data(int fd, uint32_t mask, void *data) { @@ -195,6 +226,12 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) for (e = ev; e < end; e++) { time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000; + /* we try to minimize the amount of notifications to be + * forwarded to the compositor, so we accumulate motion + * events and send as a bunch */ + if (!is_motion_event(e)) + evdev_flush_motion(&device->master->base.input_device, + time, x, y, dx, dy, absolute_event); switch (e->type) { case EV_REL: evdev_process_relative_motion(e, &dx, &dy); @@ -213,11 +250,8 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) } } - if (dx != 0 || dy != 0) - notify_motion(&device->master->base.input_device, - time, x + dx, y + dy); - if (absolute_event) - notify_motion(&device->master->base.input_device, time, x, y); + evdev_flush_motion(&device->master->base.input_device, time, x, y, dx, + dy, absolute_event); return 1; } From 0090c3b29ea6e82324b5d41b11e634d56c7b74ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 18 Nov 2011 10:42:34 -0500 Subject: [PATCH 029/162] evdev: Reset accumulate values when we flush motion events Otherwise we end up reporting all motion events twice. --- compositor/evdev.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 784fa4c5..5138c09b 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -229,9 +229,14 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) /* we try to minimize the amount of notifications to be * forwarded to the compositor, so we accumulate motion * events and send as a bunch */ - if (!is_motion_event(e)) + if (!is_motion_event(e)) { evdev_flush_motion(&device->master->base.input_device, time, x, y, dx, dy, absolute_event); + dx = 0; + dy = 0; + absolute_event = 0; + } + switch (e->type) { case EV_REL: evdev_process_relative_motion(e, &dx, &dy); From 1e0dfd820c0d869d15aa736af3ca80baa4e7c199 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Mon, 21 Nov 2011 16:39:55 +0200 Subject: [PATCH 030/162] evdev: use a separate struct for abs information Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 52 +++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 5138c09b..48e8d7cc 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -44,8 +44,11 @@ struct evdev_input_device { char *devnode; int tool; int fd; - int min_x, max_x, min_y, max_y; - int is_touchpad, old_x_value, old_y_value, reset_x_value, reset_y_value; + struct { + int min_x, max_x, min_y, max_y; + int old_x, old_y, reset_x, reset_y; + } abs; + int is_touchpad; }; static inline void @@ -67,8 +70,8 @@ evdev_process_key(struct evdev_input_device *device, device->tool = e->value ? e->code : 0; if (device->is_touchpad) { - device->reset_x_value = 1; - device->reset_y_value = 1; + device->abs.reset_x = 1; + device->abs.reset_y = 1; } break; @@ -107,13 +110,13 @@ evdev_process_absolute_motion(struct evdev_input_device *device, switch (e->code) { case ABS_X: *absolute_event = device->tool; - *x = (e->value - device->min_x) * screen_width / - (device->max_x - device->min_x) + device->output->x; + *x = (e->value - device->abs.min_x) * screen_width / + (device->abs.max_x - device->abs.min_x) + device->output->x; break; case ABS_Y: *absolute_event = device->tool; - *y = (e->value - device->min_y) * screen_height / - (device->max_y - device->min_y) + device->output->y; + *y = (e->value - device->abs.min_y) * screen_height / + (device->abs.max_y - device->abs.min_y) + device->output->y; break; } } @@ -127,25 +130,25 @@ evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, switch (e->code) { case ABS_X: - e->value -= device->min_x; - if (device->reset_x_value) - device->reset_x_value = 0; + e->value -= device->abs.min_x; + if (device->abs.reset_x) + device->abs.reset_x = 0; else { - *dx = (e->value - device->old_x_value) * touchpad_speed / - (device->max_x - device->min_x); + *dx = (e->value - device->abs.old_x) * touchpad_speed / + (device->abs.max_x - device->abs.min_x); } - device->old_x_value = e->value; + device->abs.old_x = e->value; break; case ABS_Y: - e->value -= device->min_y; - if (device->reset_y_value) - device->reset_y_value = 0; + e->value -= device->abs.min_y; + if (device->abs.reset_y) + device->abs.reset_y = 0; else { - *dy = (e->value - device->old_y_value) * touchpad_speed / + *dy = (e->value - device->abs.old_y) * touchpad_speed / /* maybe use x size here to have the same scale? */ - (device->max_y - device->min_y); + (device->abs.max_y - device->abs.min_y); } - device->old_y_value = e->value; + device->abs.old_y = e->value; break; } } @@ -287,17 +290,18 @@ evdev_configure_device(struct evdev_input_device *device) 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_X)) { ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo); - device->min_x = absinfo.minimum; - device->max_x = absinfo.maximum; + device->abs.min_x = absinfo.minimum; + device->abs.max_x = absinfo.maximum; } if (TEST_BIT(abs_bits, ABS_Y)) { ioctl(device->fd, EVIOCGABS(ABS_Y), &absinfo); - device->min_y = absinfo.minimum; - device->max_y = absinfo.maximum; + device->abs.min_y = absinfo.minimum; + device->abs.max_y = absinfo.maximum; } } if (TEST_BIT(ev_bits, EV_KEY)) { From 2b56d6131eba862683b999a25698177c5a574f39 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Mon, 21 Nov 2011 17:40:30 +0200 Subject: [PATCH 031/162] evdev: use a separate structure to denote accumulated motion events Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 93 ++++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 48e8d7cc..2dcfd5ed 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -51,6 +51,16 @@ struct evdev_input_device { int is_touchpad; }; +/* event type flags */ +#define EVDEV_ABSOLUTE_MOTION (1 << 0) +#define EVDEV_RELATIVE_MOTION (1 << 1) + +struct evdev_motion_accumulator { + int x, y; + int dx, dy; + int type; /* event type flags */ +}; + static inline void evdev_process_key(struct evdev_input_device *device, struct input_event *e, int time) @@ -101,29 +111,30 @@ evdev_process_key(struct evdev_input_device *device, static inline void evdev_process_absolute_motion(struct evdev_input_device *device, - struct input_event *e, int *x, int *y, - int *absolute_event) + struct input_event *e, struct evdev_motion_accumulator *accum) { const int screen_width = device->output->current->width; const int screen_height = device->output->current->height; switch (e->code) { case ABS_X: - *absolute_event = device->tool; - *x = (e->value - device->abs.min_x) * screen_width / - (device->abs.max_x - device->abs.min_x) + device->output->x; + accum->x = (e->value - device->abs.min_x) * screen_width / + (device->abs.max_x - device->abs.min_x) + + device->output->x; + accum->type = EVDEV_ABSOLUTE_MOTION; break; case ABS_Y: - *absolute_event = device->tool; - *y = (e->value - device->abs.min_y) * screen_height / - (device->abs.max_y - device->abs.min_y) + device->output->y; + accum->y = (e->value - device->abs.min_y) * screen_height / + (device->abs.max_y - device->abs.min_y) + + device->output->y; + accum->type = EVDEV_ABSOLUTE_MOTION; break; } } static inline void evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, - struct input_event *e, int *dx, int *dy) + struct input_event *e, struct evdev_motion_accumulator *accum) { /* FIXME: Make this configurable somehow. */ const int touchpad_speed = 700; @@ -134,34 +145,41 @@ evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, if (device->abs.reset_x) device->abs.reset_x = 0; else { - *dx = (e->value - device->abs.old_x) * touchpad_speed / + accum->dx = (e->value - device->abs.old_x) * + touchpad_speed / (device->abs.max_x - device->abs.min_x); } device->abs.old_x = e->value; + accum->type = EVDEV_RELATIVE_MOTION; break; case ABS_Y: e->value -= device->abs.min_y; if (device->abs.reset_y) device->abs.reset_y = 0; else { - *dy = (e->value - device->abs.old_y) * touchpad_speed / + accum->dy = (e->value - device->abs.old_y) * + touchpad_speed / /* maybe use x size here to have the same scale? */ (device->abs.max_y - device->abs.min_y); } device->abs.old_y = e->value; + accum->type = EVDEV_RELATIVE_MOTION; break; } } static inline void -evdev_process_relative_motion(struct input_event *e, int *dx, int *dy) +evdev_process_relative_motion(struct input_event *e, + struct evdev_motion_accumulator *accum) { switch (e->code) { case REL_X: - *dx += e->value; + accum->dx += e->value; + accum->type = EVDEV_RELATIVE_MOTION; break; case REL_Y: - *dy += e->value; + accum->dy += e->value; + accum->type = EVDEV_RELATIVE_MOTION; break; } } @@ -188,13 +206,14 @@ is_motion_event(struct input_event *e) } static void -evdev_flush_motion(struct wl_input_device *device, uint32_t time, int x, int y, - int dx, int dy, int absolute_event) +evdev_flush_motion(struct wl_input_device *device, uint32_t time, + struct evdev_motion_accumulator accum) { - if (dx != 0 || dy != 0) - notify_motion(device, time, x + dx, y + dy); - if (absolute_event) - notify_motion(device, time, x, y); + if (accum.type == EVDEV_RELATIVE_MOTION) + notify_motion(device, time, accum.x + accum.dx, + accum.y + accum.dy); + if (accum.type == EVDEV_ABSOLUTE_MOTION) + notify_motion(device, time, accum.x, accum.y); } static int @@ -203,8 +222,8 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) struct wlsc_compositor *ec; struct evdev_input_device *device = data; struct input_event ev[8], *e, *end; - int len, dx, dy, absolute_event; - int x, y; + int len; + struct evdev_motion_accumulator accumulator; uint32_t time; ec = (struct wlsc_compositor *) @@ -212,11 +231,11 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) if (!ec->focus) return 1; - dx = 0; - dy = 0; - absolute_event = 0; - x = device->master->base.input_device.x; - y = device->master->base.input_device.y; + accumulator.dx = 0; + accumulator.dy = 0; + accumulator.type = 0; + accumulator.x = device->master->base.input_device.x; + accumulator.y = device->master->base.input_device.y; len = read(fd, &ev, sizeof ev); if (len < 0 || len % sizeof e[0] != 0) { @@ -234,23 +253,23 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) * events and send as a bunch */ if (!is_motion_event(e)) { evdev_flush_motion(&device->master->base.input_device, - time, x, y, dx, dy, absolute_event); - dx = 0; - dy = 0; - absolute_event = 0; + time, accumulator); + accumulator.dx = 0; + accumulator.dy = 0; + accumulator.type = 0; } - + switch (e->type) { case EV_REL: - evdev_process_relative_motion(e, &dx, &dy); + evdev_process_relative_motion(e, &accumulator); break; case EV_ABS: if (device->is_touchpad) evdev_process_absolute_motion_touchpad(device, - e, &dx, &dy); + e, &accumulator); else evdev_process_absolute_motion(device, e, - &x, &y, &absolute_event); + &accumulator); break; case EV_KEY: evdev_process_key(device, e, time); @@ -258,8 +277,8 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) } } - evdev_flush_motion(&device->master->base.input_device, time, x, y, dx, - dy, absolute_event); + evdev_flush_motion(&device->master->base.input_device, time, + accumulator); return 1; } From 70ca695e9a5269a496f2af08c379ff784067e1ec Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Mon, 21 Nov 2011 17:59:31 +0200 Subject: [PATCH 032/162] evdev: reset accumulator inside evdev_flush_motion Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 2dcfd5ed..e557abba 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -207,13 +207,17 @@ is_motion_event(struct input_event *e) static void evdev_flush_motion(struct wl_input_device *device, uint32_t time, - struct evdev_motion_accumulator accum) + struct evdev_motion_accumulator *accum) { - if (accum.type == EVDEV_RELATIVE_MOTION) - notify_motion(device, time, accum.x + accum.dx, - accum.y + accum.dy); - if (accum.type == EVDEV_ABSOLUTE_MOTION) - notify_motion(device, time, accum.x, accum.y); + if (accum->type == EVDEV_RELATIVE_MOTION) { + notify_motion(device, time, accum->x + accum->dx, + accum->y + accum->dy); + accum->dx = accum->dy = 0; + } + if (accum->type == EVDEV_ABSOLUTE_MOTION) + notify_motion(device, time, accum->x, accum->y); + + accum->type = 0; } static int @@ -231,9 +235,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) if (!ec->focus) return 1; - accumulator.dx = 0; - accumulator.dy = 0; - accumulator.type = 0; + memset(&accumulator, 0, sizeof accumulator); accumulator.x = device->master->base.input_device.x; accumulator.y = device->master->base.input_device.y; @@ -251,14 +253,9 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) /* we try to minimize the amount of notifications to be * forwarded to the compositor, so we accumulate motion * events and send as a bunch */ - if (!is_motion_event(e)) { + if (!is_motion_event(e)) evdev_flush_motion(&device->master->base.input_device, - time, accumulator); - accumulator.dx = 0; - accumulator.dy = 0; - accumulator.type = 0; - } - + time, &accumulator); switch (e->type) { case EV_REL: evdev_process_relative_motion(e, &accumulator); @@ -278,7 +275,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) } evdev_flush_motion(&device->master->base.input_device, time, - accumulator); + &accumulator); return 1; } From f93e815e71c1f008eb8fd9c5bc8776052338ad33 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Mon, 21 Nov 2011 18:29:40 +0200 Subject: [PATCH 033/162] evdev: remove useless field from device structure We'll want to enhance later the driver regarding the tool being used, but for now just remove unused bits. Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index e557abba..96fb0cd9 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -42,7 +42,6 @@ struct evdev_input_device { struct wl_event_source *source; struct wlsc_output *output; char *devnode; - int tool; int fd; struct { int min_x, max_x, min_y, max_y; @@ -77,7 +76,6 @@ evdev_process_key(struct evdev_input_device *device, case BTN_TOOL_FINGER: case BTN_TOOL_MOUSE: case BTN_TOOL_LENS: - device->tool = e->value ? e->code : 0; if (device->is_touchpad) { device->abs.reset_x = 1; @@ -354,7 +352,6 @@ evdev_input_device_create(struct evdev_input *master, device->output = container_of(ec->output_list.next, struct wlsc_output, link); - device->tool = 1; device->master = master; device->is_touchpad = 0; device->devnode = strdup(path); From 2a3c15ab50681dfad9cb7eb2061578f046fd8999 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Tue, 22 Nov 2011 12:05:22 +0200 Subject: [PATCH 034/162] evdev: fetch absolute coordinates inside flush_motion only Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 96fb0cd9..06913cf4 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -208,8 +208,9 @@ evdev_flush_motion(struct wl_input_device *device, uint32_t time, struct evdev_motion_accumulator *accum) { if (accum->type == EVDEV_RELATIVE_MOTION) { - notify_motion(device, time, accum->x + accum->dx, - accum->y + accum->dy); + accum->dx += device->x; + accum->dy += device->y; + notify_motion(device, time, accum->dx, accum->dy); accum->dx = accum->dy = 0; } if (accum->type == EVDEV_ABSOLUTE_MOTION) @@ -233,16 +234,14 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) if (!ec->focus) return 1; - memset(&accumulator, 0, sizeof accumulator); - accumulator.x = device->master->base.input_device.x; - accumulator.y = device->master->base.input_device.y; - len = read(fd, &ev, sizeof ev); if (len < 0 || len % sizeof e[0] != 0) { /* FIXME: call device_removed when errno is ENODEV. */; return 1; } + memset(&accumulator, 0, sizeof accumulator); + e = ev; end = (void *) ev + len; for (e = ev; e < end; e++) { From 32a940e01a82fdf884e418cc50fdd4e007534d43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 22 Nov 2011 19:24:25 -0500 Subject: [PATCH 035/162] Simplify evdev_flush_motion() a tiny bit --- compositor/evdev.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 06913cf4..d36c9b4e 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -207,16 +207,13 @@ static void evdev_flush_motion(struct wl_input_device *device, uint32_t time, struct evdev_motion_accumulator *accum) { - if (accum->type == EVDEV_RELATIVE_MOTION) { - accum->dx += device->x; - accum->dy += device->y; - notify_motion(device, time, accum->dx, accum->dy); - accum->dx = accum->dy = 0; - } + if (accum->type == EVDEV_RELATIVE_MOTION) + notify_motion(device, time, + device->x + accum->dx, device->y + accum->dy); if (accum->type == EVDEV_ABSOLUTE_MOTION) notify_motion(device, time, accum->x, accum->y); - accum->type = 0; + memset(accum, 0, sizeof *accum); } static int From fb0da2d026b904f40bd3c7de6a3eaa0172ba819f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 23 Nov 2011 10:39:34 -0500 Subject: [PATCH 036/162] compositor: The compositor is now jiust a regular global object We have to provide our own bind callback and add a wlsc_compositor pointer to wlsc_input_device, but on the whole it's nice cleanup. --- compositor/evdev.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index d36c9b4e..8233f05a 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -226,8 +226,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) struct evdev_motion_accumulator accumulator; uint32_t time; - ec = (struct wlsc_compositor *) - device->master->base.input_device.compositor; + ec = device->master->base.compositor; if (!ec->focus) return 1; @@ -344,7 +343,7 @@ evdev_input_device_create(struct evdev_input *master, if (device == NULL) return NULL; - ec = (struct wlsc_compositor *) master->base.input_device.compositor; + ec = master->base.compositor; device->output = container_of(ec->output_list.next, struct wlsc_output, link); @@ -394,7 +393,7 @@ device_added(struct udev_device *udev_device, struct evdev_input *master) if (strcmp(device_seat, master->seat_id)) return; - c = (struct wlsc_compositor *) master->base.input_device.compositor; + c = master->base.compositor; devnode = udev_device_get_devnode(udev_device); if (evdev_input_device_create(master, c->wl_display, devnode)) fprintf(stderr, "evdev input device: added: %s\n", devnode); @@ -450,8 +449,7 @@ static int evdev_config_udev_monitor(struct udev *udev, struct evdev_input *master) { struct wl_event_loop *loop; - struct wlsc_compositor *c = - (struct wlsc_compositor *) master->base.input_device.compositor; + struct wlsc_compositor *c = master->base.compositor; master->udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); if (!master->udev_monitor) From cb3c6ad5c6156887990e07e30bcee919e12faa43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 2 Dec 2011 06:39:02 -0500 Subject: [PATCH 037/162] evdev: Silence warning --- compositor/evdev.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 8233f05a..1755a95e 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -224,7 +224,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) struct input_event ev[8], *e, *end; int len; struct evdev_motion_accumulator accumulator; - uint32_t time; + uint32_t time = 0; ec = device->master->base.compositor; if (!ec->focus) @@ -267,8 +267,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) } } - evdev_flush_motion(&device->master->base.input_device, time, - &accumulator); + evdev_flush_motion(&device->master->base.input_device, time, &accumulator); return 1; } From 75953314cf970067f8d3109fc895a657045b347e Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Thu, 8 Dec 2011 12:18:16 +0200 Subject: [PATCH 038/162] evdev: send old valuator inside event frame when the other is missing when a motion is being performed on ts device, only one axis can be sent through the evdev bytestream whereas the other could be omitted. For instance: -------------- SYN_REPORT ------------ type 3 (EV_ABS), code 53 (ABS_MT_POSITION_X), value 22208 type 3 (EV_ABS), code 58 (ABS_MT_PRESSURE), value 631 type 3 (EV_ABS), code 0 (ABS_X), value 22208 -------------- SYN_REPORT ------------ on such case we'd have to send the compositor the old value of Y. Commit f547bd36 introduced this bug cause it was sending zeroed coordinate and not the old one. Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 1755a95e..c4a861fc 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -203,6 +203,20 @@ is_motion_event(struct input_event *e) return 0; } +static void +evdev_reset_accum(struct wl_input_device *device, + struct evdev_motion_accumulator *accum) +{ + memset(accum, 0, sizeof *accum); + + /* There are cases where only one axis on ts devices can be sent + * through the bytestream whereas the other could be omitted. For + * this, we have to save the old value that will be forwarded without + * modifications to the compositor. */ + accum->x = device->x; + accum->y = device->y; +} + static void evdev_flush_motion(struct wl_input_device *device, uint32_t time, struct evdev_motion_accumulator *accum) @@ -213,7 +227,7 @@ evdev_flush_motion(struct wl_input_device *device, uint32_t time, if (accum->type == EVDEV_ABSOLUTE_MOTION) notify_motion(device, time, accum->x, accum->y); - memset(accum, 0, sizeof *accum); + evdev_reset_accum(device, accum); } static int @@ -236,7 +250,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) return 1; } - memset(&accumulator, 0, sizeof accumulator); + evdev_reset_accum(&device->master->base.input_device, &accumulator); e = ev; end = (void *) ev + len; From 47dfaffa0e83f7b1c25405014cb496689c9a9096 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Thu, 8 Dec 2011 13:20:46 +0200 Subject: [PATCH 039/162] evdev: run flush_motion only when needed Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compositor/evdev.c b/compositor/evdev.c index c4a861fc..83812bf7 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -221,6 +221,9 @@ static void evdev_flush_motion(struct wl_input_device *device, uint32_t time, struct evdev_motion_accumulator *accum) { + if (!accum->type) + return; + if (accum->type == EVDEV_RELATIVE_MOTION) notify_motion(device, time, device->x + accum->dx, device->y + accum->dy); From 0b85ddac4cd9ae2eb8209bc506158bd8ce105822 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Sun, 18 Dec 2011 16:47:15 +0200 Subject: [PATCH 040/162] evdev: use a separate function for adding devices Adds new function evdev_add_devices for adding udev devices. No functional changes. Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 46 +++++++++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 83812bf7..43776c8a 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -434,6 +434,32 @@ device_removed(struct udev_device *udev_device, struct evdev_input *master) fprintf(stderr, "evdev input device: removed: %s\n", devnode); } +static void +evdev_add_devices(struct udev *udev, struct wlsc_input_device *input_base) +{ + struct evdev_input *input = (struct evdev_input *) input_base; + struct udev_enumerate *e; + struct udev_list_entry *entry; + struct udev_device *device; + const char *path; + + e = udev_enumerate_new(udev); + udev_enumerate_add_match_subsystem(e, "input"); + udev_enumerate_scan_devices(e); + udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { + path = udev_list_entry_get_name(entry); + device = udev_device_new_from_syspath(udev, path); + + if (strncmp("event", udev_device_get_sysname(device), 5) != 0) + continue; + + device_added(device, input); + + udev_device_unref(device); + } + udev_enumerate_unref(e); +} + static int evdev_udev_handler(int fd, uint32_t mask, void *data) { @@ -491,10 +517,6 @@ evdev_input_add_devices(struct wlsc_compositor *c, struct udev *udev, const char *seat) { struct evdev_input *input; - struct udev_enumerate *e; - struct udev_list_entry *entry; - struct udev_device *device; - const char *path; input = malloc(sizeof *input); if (input == NULL) @@ -511,21 +533,7 @@ evdev_input_add_devices(struct wlsc_compositor *c, return; } - e = udev_enumerate_new(udev); - udev_enumerate_add_match_subsystem(e, "input"); - udev_enumerate_scan_devices(e); - udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { - path = udev_list_entry_get_name(entry); - device = udev_device_new_from_syspath(udev, path); - - if (strncmp("event", udev_device_get_sysname(device), 5) != 0) - continue; - - device_added(device, input); - - udev_device_unref(device); - } - udev_enumerate_unref(e); + evdev_add_devices(udev, &input->base); c->input_device = &input->base.input_device; } From aa5b46b20f9664471ea9cf45aa5835878e7e0f6e Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Sun, 18 Dec 2011 23:52:18 +0200 Subject: [PATCH 041/162] compositor-drm: destroy evdev driver properly when finishing compositor Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/compositor/evdev.c b/compositor/evdev.c index 43776c8a..25784506 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -537,3 +537,30 @@ evdev_input_add_devices(struct wlsc_compositor *c, c->input_device = &input->base.input_device; } + +static void +evdev_remove_devices(struct wlsc_input_device *input_base) +{ + struct evdev_input *input = (struct evdev_input *) input_base; + struct evdev_input_device *device, *next; + + wl_list_for_each_safe(device, next, &input->devices_list, link) { + fprintf(stderr, "evdev input device: removed: %s\n", device->devnode); + wl_event_source_remove(device->source); + wl_list_remove(&device->link); + close(device->fd); + free(device->devnode); + free(device); + } +} + +void +evdev_input_destroy(struct wlsc_input_device *input_base) +{ + struct evdev_input *input = (struct evdev_input *) input_base; + + evdev_remove_devices(input_base); + wl_list_remove(&input->base.link); + free(input->seat_id); + free(input); +} From fa1924097fb8c695222de326a05eeede60348487 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Mon, 19 Dec 2011 00:32:48 +0200 Subject: [PATCH 042/162] compositor-drm: remove/add evdev devices when vt switches Reported-by: Ran Benite Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 25784506..d33c6055 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -434,7 +434,7 @@ device_removed(struct udev_device *udev_device, struct evdev_input *master) fprintf(stderr, "evdev input device: removed: %s\n", devnode); } -static void +void evdev_add_devices(struct udev *udev, struct wlsc_input_device *input_base) { struct evdev_input *input = (struct evdev_input *) input_base; @@ -538,7 +538,7 @@ evdev_input_add_devices(struct wlsc_compositor *c, c->input_device = &input->base.input_device; } -static void +void evdev_remove_devices(struct wlsc_input_device *input_base) { struct evdev_input *input = (struct evdev_input *) input_base; From 0fc65324a7ec0cfeface2ab5ebc7c14996875163 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Mon, 19 Dec 2011 01:14:03 +0200 Subject: [PATCH 043/162] evdev: new header file for the driver Besides the new header file, there's also a change in the main evdev creation procedure for a more suggestive name (evdev_input_add_devices -> evdev_input_create). There's no real functional changes in this commit. Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 5 +++-- compositor/evdev.h | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 compositor/evdev.h diff --git a/compositor/evdev.c b/compositor/evdev.c index d33c6055..13832dc4 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -28,6 +28,7 @@ #include #include "compositor.h" +#include "evdev.h" struct evdev_input { struct wlsc_input_device base; @@ -513,8 +514,8 @@ evdev_config_udev_monitor(struct udev *udev, struct evdev_input *master) } void -evdev_input_add_devices(struct wlsc_compositor *c, - struct udev *udev, const char *seat) +evdev_input_create(struct wlsc_compositor *c, struct udev *udev, + const char *seat) { struct evdev_input *input; diff --git a/compositor/evdev.h b/compositor/evdev.h new file mode 100644 index 00000000..22878938 --- /dev/null +++ b/compositor/evdev.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2011 Intel Corporation + * + * 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. + */ + +void +evdev_add_devices(struct udev *udev, struct wlsc_input_device + *input_base); + +void +evdev_remove_devices(struct wlsc_input_device *input_base); + +void +evdev_input_create(struct wlsc_compositor *c, struct udev *udev, + const char *seat); + +void +evdev_input_destroy(struct wlsc_input_device *input_base); From 8687708937062395e5b657a36a89d7606d31067d Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Wed, 21 Dec 2011 19:34:09 +0200 Subject: [PATCH 044/162] evdev: Add ABS_MT_* support for direct touch devices This adds ABS_MT_* support for direct touch devices and notifies the compositor. The compositor has a stub for now. Signed-off-by: Tiago Vignatti --- compositor/evdev.c | 148 +++++++++++++++++++++++++++++++++------------ 1 file changed, 110 insertions(+), 38 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 13832dc4..11f7f5e4 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -47,17 +47,22 @@ struct evdev_input_device { struct { int min_x, max_x, min_y, max_y; int old_x, old_y, reset_x, reset_y; + int slot_mt; } abs; - int is_touchpad; + int is_touchpad, is_mt; }; /* event type flags */ -#define EVDEV_ABSOLUTE_MOTION (1 << 0) -#define EVDEV_RELATIVE_MOTION (1 << 1) +#define EVDEV_ABSOLUTE_MOTION (1 << 0) +#define EVDEV_ABSOLUTE_MT_DOWN (1 << 1) +#define EVDEV_ABSOLUTE_MT_MOTION (1 << 2) +#define EVDEV_ABSOLUTE_MT_UP (1 << 3) +#define EVDEV_RELATIVE_MOTION (1 << 4) struct evdev_motion_accumulator { int x, y; int dx, dy; + int mt_x, mt_y; int type; /* event type flags */ }; @@ -83,8 +88,14 @@ evdev_process_key(struct evdev_input_device *device, device->abs.reset_y = 1; } break; - case BTN_TOUCH: + /* Multitouch touchscreen devices might not send individually + * button events each time a new finger is down. So we don't + * send notification for such devices and we solve the button + * case emulating on compositor side. */ + if (device->is_mt) + break; + /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as * BTN_LEFT */ e->code = BTN_LEFT; @@ -108,6 +119,39 @@ evdev_process_key(struct evdev_input_device *device, } } +static void +evdev_process_touch(struct evdev_input_device *device, + struct input_event *e, int time, + struct evdev_motion_accumulator *accum) +{ + const int screen_width = device->output->current->width; + const int screen_height = device->output->current->height; + + switch (e->code) { + case ABS_MT_SLOT: + device->abs.slot_mt = e->value; + break; + case ABS_MT_TRACKING_ID: + if (e->value >= 0) + accum->type |= EVDEV_ABSOLUTE_MT_DOWN; + else + accum->type |= EVDEV_ABSOLUTE_MT_UP; + break; + case ABS_MT_POSITION_X: + accum->mt_x = (e->value - device->abs.min_x) * screen_width / + (device->abs.max_x - device->abs.min_x) + + device->output->x; + accum->type |= EVDEV_ABSOLUTE_MT_MOTION; + break; + case ABS_MT_POSITION_Y: + accum->mt_y = (e->value - device->abs.min_y) * screen_height / + (device->abs.max_y - device->abs.min_y) + + device->output->y; + accum->type |= EVDEV_ABSOLUTE_MT_MOTION; + break; + } +} + static inline void evdev_process_absolute_motion(struct evdev_input_device *device, struct input_event *e, struct evdev_motion_accumulator *accum) @@ -120,13 +164,13 @@ evdev_process_absolute_motion(struct evdev_input_device *device, accum->x = (e->value - device->abs.min_x) * screen_width / (device->abs.max_x - device->abs.min_x) + device->output->x; - accum->type = EVDEV_ABSOLUTE_MOTION; + accum->type |= EVDEV_ABSOLUTE_MOTION; break; case ABS_Y: accum->y = (e->value - device->abs.min_y) * screen_height / (device->abs.max_y - device->abs.min_y) + device->output->y; - accum->type = EVDEV_ABSOLUTE_MOTION; + accum->type |= EVDEV_ABSOLUTE_MOTION; break; } } @@ -149,7 +193,7 @@ evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, (device->abs.max_x - device->abs.min_x); } device->abs.old_x = e->value; - accum->type = EVDEV_RELATIVE_MOTION; + accum->type |= EVDEV_RELATIVE_MOTION; break; case ABS_Y: e->value -= device->abs.min_y; @@ -162,7 +206,7 @@ evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, (device->abs.max_y - device->abs.min_y); } device->abs.old_y = e->value; - accum->type = EVDEV_RELATIVE_MOTION; + accum->type |= EVDEV_RELATIVE_MOTION; break; } } @@ -174,15 +218,29 @@ evdev_process_relative_motion(struct input_event *e, switch (e->code) { case REL_X: accum->dx += e->value; - accum->type = EVDEV_RELATIVE_MOTION; + accum->type |= EVDEV_RELATIVE_MOTION; break; case REL_Y: accum->dy += e->value; - accum->type = EVDEV_RELATIVE_MOTION; + accum->type |= EVDEV_RELATIVE_MOTION; break; } } +static inline void +evdev_process_absolute(struct evdev_input_device *device, + struct input_event *e, int time, + struct evdev_motion_accumulator *accum) +{ + if (device->is_touchpad) { + evdev_process_absolute_motion_touchpad(device, e, accum); + } else if (device->is_mt) { + evdev_process_touch(device, e, time, accum); + } else { + evdev_process_absolute_motion(device, e, accum); + } +} + static int is_motion_event(struct input_event *e) { @@ -197,6 +255,8 @@ is_motion_event(struct input_event *e) switch (e->code) { case ABS_X: case ABS_Y: + case ABS_MT_POSITION_X: + case ABS_MT_POSITION_Y: return 1; } } @@ -204,34 +264,41 @@ is_motion_event(struct input_event *e) return 0; } -static void -evdev_reset_accum(struct wl_input_device *device, - struct evdev_motion_accumulator *accum) -{ - memset(accum, 0, sizeof *accum); - - /* There are cases where only one axis on ts devices can be sent - * through the bytestream whereas the other could be omitted. For - * this, we have to save the old value that will be forwarded without - * modifications to the compositor. */ - accum->x = device->x; - accum->y = device->y; -} - static void evdev_flush_motion(struct wl_input_device *device, uint32_t time, - struct evdev_motion_accumulator *accum) + struct evdev_motion_accumulator *accum, int slot_mt) { if (!accum->type) return; - if (accum->type == EVDEV_RELATIVE_MOTION) + if (accum->type & EVDEV_RELATIVE_MOTION) { notify_motion(device, time, device->x + accum->dx, device->y + accum->dy); - if (accum->type == EVDEV_ABSOLUTE_MOTION) + accum->type &= ~EVDEV_RELATIVE_MOTION; + accum->dx = 0; + accum->dy = 0; + } + if (accum->type & EVDEV_ABSOLUTE_MT_DOWN) { + notify_touch(device, time, slot_mt, accum->mt_x, accum->mt_y, + WL_INPUT_DEVICE_TOUCH_DOWN); + accum->type &= ~EVDEV_ABSOLUTE_MT_DOWN; + accum->type &= ~EVDEV_ABSOLUTE_MT_MOTION; + } + if (accum->type & EVDEV_ABSOLUTE_MT_MOTION) { + notify_touch(device, time, slot_mt, accum->mt_x, accum->mt_y, + WL_INPUT_DEVICE_TOUCH_MOTION); + accum->type &= ~EVDEV_ABSOLUTE_MT_DOWN; + accum->type &= ~EVDEV_ABSOLUTE_MT_MOTION; + } + if (accum->type & EVDEV_ABSOLUTE_MT_UP) { + notify_touch(device, time, slot_mt, 0, 0, + WL_INPUT_DEVICE_TOUCH_UP); + accum->type &= ~EVDEV_ABSOLUTE_MT_UP; + } + if (accum->type & EVDEV_ABSOLUTE_MOTION) { notify_motion(device, time, accum->x, accum->y); - - evdev_reset_accum(device, accum); + accum->type &= ~EVDEV_ABSOLUTE_MOTION; + } } static int @@ -254,7 +321,9 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) return 1; } - evdev_reset_accum(&device->master->base.input_device, &accumulator); + accumulator.type = 0; + accumulator.mt_x = accumulator.x = device->master->base.input_device.x; + accumulator.mt_y = accumulator.y = device->master->base.input_device.y; e = ev; end = (void *) ev + len; @@ -266,18 +335,14 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) * events and send as a bunch */ if (!is_motion_event(e)) evdev_flush_motion(&device->master->base.input_device, - time, &accumulator); + time, &accumulator, + device->abs.slot_mt); switch (e->type) { case EV_REL: evdev_process_relative_motion(e, &accumulator); break; case EV_ABS: - if (device->is_touchpad) - evdev_process_absolute_motion_touchpad(device, - e, &accumulator); - else - evdev_process_absolute_motion(device, e, - &accumulator); + evdev_process_absolute(device, e, time, &accumulator); break; case EV_KEY: evdev_process_key(device, e, time); @@ -285,7 +350,8 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) } } - evdev_flush_motion(&device->master->base.input_device, time, &accumulator); + evdev_flush_motion(&device->master->base.input_device, time, + &accumulator, device->abs.slot_mt); return 1; } @@ -329,6 +395,10 @@ evdev_configure_device(struct evdev_input_device *device) device->abs.min_y = absinfo.minimum; device->abs.max_y = absinfo.maximum; } + if (TEST_BIT(abs_bits, ABS_MT_SLOT)) { + device->is_mt = 1; + device->abs.slot_mt = 0; + } } if (TEST_BIT(ev_bits, EV_KEY)) { has_key = 1; @@ -366,7 +436,9 @@ evdev_input_device_create(struct evdev_input *master, device->master = master; device->is_touchpad = 0; + device->is_mt = 0; device->devnode = strdup(path); + device->abs.slot_mt = -1; device->fd = open(path, O_RDONLY); if (device->fd < 0) From 267e7fc4e7d780ada740588c87996b53f6c22dd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 21 Dec 2011 22:18:36 -0500 Subject: [PATCH 045/162] evdev: Store positions for all touch points in the evdev device We need to store all touchpoint positions so that if we just get an ABS_MT_POSITION_X or Y event, we can pull the other coordinate from the cache. And we need this across invocations of evdev_input_device_data(), so the accumulator approach doesn't work. Instead, we go back to the approach of storing all this state in the evdev device struct and we might as well just move the rel and abs state there too. --- compositor/evdev.c | 167 ++++++++++++++++++++++++--------------------- 1 file changed, 91 insertions(+), 76 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index 11f7f5e4..c065b33c 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -37,6 +37,8 @@ struct evdev_input { char *seat_id; }; +#define MAX_SLOTS 10 + struct evdev_input_device { struct evdev_input *master; struct wl_list link; @@ -47,8 +49,21 @@ struct evdev_input_device { struct { int min_x, max_x, min_y, max_y; int old_x, old_y, reset_x, reset_y; - int slot_mt; + int32_t x, y; } abs; + + struct { + int slot; + int32_t x[MAX_SLOTS]; + int32_t y[MAX_SLOTS]; + } mt; + + struct { + int dx, dy; + } rel; + + int type; /* event type flags */ + int is_touchpad, is_mt; }; @@ -59,13 +74,6 @@ struct evdev_input_device { #define EVDEV_ABSOLUTE_MT_UP (1 << 3) #define EVDEV_RELATIVE_MOTION (1 << 4) -struct evdev_motion_accumulator { - int x, y; - int dx, dy; - int mt_x, mt_y; - int type; /* event type flags */ -}; - static inline void evdev_process_key(struct evdev_input_device *device, struct input_event *e, int time) @@ -121,63 +129,66 @@ evdev_process_key(struct evdev_input_device *device, static void evdev_process_touch(struct evdev_input_device *device, - struct input_event *e, int time, - struct evdev_motion_accumulator *accum) + struct input_event *e) { const int screen_width = device->output->current->width; const int screen_height = device->output->current->height; switch (e->code) { case ABS_MT_SLOT: - device->abs.slot_mt = e->value; + device->mt.slot = e->value; break; case ABS_MT_TRACKING_ID: if (e->value >= 0) - accum->type |= EVDEV_ABSOLUTE_MT_DOWN; + device->type |= EVDEV_ABSOLUTE_MT_DOWN; else - accum->type |= EVDEV_ABSOLUTE_MT_UP; + device->type |= EVDEV_ABSOLUTE_MT_UP; break; case ABS_MT_POSITION_X: - accum->mt_x = (e->value - device->abs.min_x) * screen_width / + device->mt.x[device->mt.slot] = + (e->value - device->abs.min_x) * screen_width / (device->abs.max_x - device->abs.min_x) + device->output->x; - accum->type |= EVDEV_ABSOLUTE_MT_MOTION; + device->type |= EVDEV_ABSOLUTE_MT_MOTION; break; case ABS_MT_POSITION_Y: - accum->mt_y = (e->value - device->abs.min_y) * screen_height / + device->mt.y[device->mt.slot] = + (e->value - device->abs.min_y) * screen_height / (device->abs.max_y - device->abs.min_y) + device->output->y; - accum->type |= EVDEV_ABSOLUTE_MT_MOTION; + device->type |= EVDEV_ABSOLUTE_MT_MOTION; break; } } static inline void evdev_process_absolute_motion(struct evdev_input_device *device, - struct input_event *e, struct evdev_motion_accumulator *accum) + struct input_event *e) { const int screen_width = device->output->current->width; const int screen_height = device->output->current->height; switch (e->code) { case ABS_X: - accum->x = (e->value - device->abs.min_x) * screen_width / + device->abs.x = + (e->value - device->abs.min_x) * screen_width / (device->abs.max_x - device->abs.min_x) + device->output->x; - accum->type |= EVDEV_ABSOLUTE_MOTION; + device->type |= EVDEV_ABSOLUTE_MOTION; break; case ABS_Y: - accum->y = (e->value - device->abs.min_y) * screen_height / + device->abs.y = + (e->value - device->abs.min_y) * screen_height / (device->abs.max_y - device->abs.min_y) + device->output->y; - accum->type |= EVDEV_ABSOLUTE_MOTION; + device->type |= EVDEV_ABSOLUTE_MOTION; break; } } static inline void evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, - struct input_event *e, struct evdev_motion_accumulator *accum) + struct input_event *e) { /* FIXME: Make this configurable somehow. */ const int touchpad_speed = 700; @@ -188,56 +199,57 @@ evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, if (device->abs.reset_x) device->abs.reset_x = 0; else { - accum->dx = (e->value - device->abs.old_x) * + device->rel.dx = + (e->value - device->abs.old_x) * touchpad_speed / (device->abs.max_x - device->abs.min_x); } device->abs.old_x = e->value; - accum->type |= EVDEV_RELATIVE_MOTION; + device->type |= EVDEV_RELATIVE_MOTION; break; case ABS_Y: e->value -= device->abs.min_y; if (device->abs.reset_y) device->abs.reset_y = 0; else { - accum->dy = (e->value - device->abs.old_y) * + device->rel.dy = + (e->value - device->abs.old_y) * touchpad_speed / /* maybe use x size here to have the same scale? */ (device->abs.max_y - device->abs.min_y); } device->abs.old_y = e->value; - accum->type |= EVDEV_RELATIVE_MOTION; + device->type |= EVDEV_RELATIVE_MOTION; break; } } static inline void -evdev_process_relative_motion(struct input_event *e, - struct evdev_motion_accumulator *accum) +evdev_process_relative_motion(struct evdev_input_device *device, + struct input_event *e) { switch (e->code) { case REL_X: - accum->dx += e->value; - accum->type |= EVDEV_RELATIVE_MOTION; + device->rel.dx += e->value; + device->type |= EVDEV_RELATIVE_MOTION; break; case REL_Y: - accum->dy += e->value; - accum->type |= EVDEV_RELATIVE_MOTION; + device->rel.dy += e->value; + device->type |= EVDEV_RELATIVE_MOTION; break; } } static inline void evdev_process_absolute(struct evdev_input_device *device, - struct input_event *e, int time, - struct evdev_motion_accumulator *accum) + struct input_event *e) { if (device->is_touchpad) { - evdev_process_absolute_motion_touchpad(device, e, accum); + evdev_process_absolute_motion_touchpad(device, e); } else if (device->is_mt) { - evdev_process_touch(device, e, time, accum); + evdev_process_touch(device, e); } else { - evdev_process_absolute_motion(device, e, accum); + evdev_process_absolute_motion(device, e); } } @@ -265,39 +277,48 @@ is_motion_event(struct input_event *e) } static void -evdev_flush_motion(struct wl_input_device *device, uint32_t time, - struct evdev_motion_accumulator *accum, int slot_mt) +evdev_flush_motion(struct evdev_input_device *device, uint32_t time) { - if (!accum->type) + struct wl_input_device *master = + &device->master->base.input_device; + + if (!device->type) return; - if (accum->type & EVDEV_RELATIVE_MOTION) { - notify_motion(device, time, - device->x + accum->dx, device->y + accum->dy); - accum->type &= ~EVDEV_RELATIVE_MOTION; - accum->dx = 0; - accum->dy = 0; + if (device->type & EVDEV_RELATIVE_MOTION) { + notify_motion(master, time, + master->x + device->rel.dx, + master->y + device->rel.dy); + device->type &= ~EVDEV_RELATIVE_MOTION; + device->rel.dx = 0; + device->rel.dy = 0; } - if (accum->type & EVDEV_ABSOLUTE_MT_DOWN) { - notify_touch(device, time, slot_mt, accum->mt_x, accum->mt_y, + if (device->type & EVDEV_ABSOLUTE_MT_DOWN) { + notify_touch(master, time, + device->mt.slot, + device->mt.x[device->mt.slot], + device->mt.y[device->mt.slot], WL_INPUT_DEVICE_TOUCH_DOWN); - accum->type &= ~EVDEV_ABSOLUTE_MT_DOWN; - accum->type &= ~EVDEV_ABSOLUTE_MT_MOTION; + device->type &= ~EVDEV_ABSOLUTE_MT_DOWN; + device->type &= ~EVDEV_ABSOLUTE_MT_MOTION; } - if (accum->type & EVDEV_ABSOLUTE_MT_MOTION) { - notify_touch(device, time, slot_mt, accum->mt_x, accum->mt_y, - WL_INPUT_DEVICE_TOUCH_MOTION); - accum->type &= ~EVDEV_ABSOLUTE_MT_DOWN; - accum->type &= ~EVDEV_ABSOLUTE_MT_MOTION; + if (device->type & EVDEV_ABSOLUTE_MT_MOTION) { + notify_touch(master, time, + device->mt.slot, + device->mt.x[device->mt.slot], + device->mt.y[device->mt.slot], + WL_INPUT_DEVICE_TOUCH_MOTION); + device->type &= ~EVDEV_ABSOLUTE_MT_DOWN; + device->type &= ~EVDEV_ABSOLUTE_MT_MOTION; } - if (accum->type & EVDEV_ABSOLUTE_MT_UP) { - notify_touch(device, time, slot_mt, 0, 0, + if (device->type & EVDEV_ABSOLUTE_MT_UP) { + notify_touch(master, time, device->mt.slot, 0, 0, WL_INPUT_DEVICE_TOUCH_UP); - accum->type &= ~EVDEV_ABSOLUTE_MT_UP; + device->type &= ~EVDEV_ABSOLUTE_MT_UP; } - if (accum->type & EVDEV_ABSOLUTE_MOTION) { - notify_motion(device, time, accum->x, accum->y); - accum->type &= ~EVDEV_ABSOLUTE_MOTION; + if (device->type & EVDEV_ABSOLUTE_MOTION) { + notify_motion(master, time, device->abs.x, device->abs.y); + device->type &= ~EVDEV_ABSOLUTE_MOTION; } } @@ -308,7 +329,6 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) struct evdev_input_device *device = data; struct input_event ev[8], *e, *end; int len; - struct evdev_motion_accumulator accumulator; uint32_t time = 0; ec = device->master->base.compositor; @@ -321,10 +341,6 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) return 1; } - accumulator.type = 0; - accumulator.mt_x = accumulator.x = device->master->base.input_device.x; - accumulator.mt_y = accumulator.y = device->master->base.input_device.y; - e = ev; end = (void *) ev + len; for (e = ev; e < end; e++) { @@ -334,15 +350,13 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) * forwarded to the compositor, so we accumulate motion * events and send as a bunch */ if (!is_motion_event(e)) - evdev_flush_motion(&device->master->base.input_device, - time, &accumulator, - device->abs.slot_mt); + evdev_flush_motion(device, time); switch (e->type) { case EV_REL: - evdev_process_relative_motion(e, &accumulator); + evdev_process_relative_motion(device, e); break; case EV_ABS: - evdev_process_absolute(device, e, time, &accumulator); + evdev_process_absolute(device, e); break; case EV_KEY: evdev_process_key(device, e, time); @@ -350,8 +364,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) } } - evdev_flush_motion(&device->master->base.input_device, time, - &accumulator, device->abs.slot_mt); + evdev_flush_motion(device, time); return 1; } @@ -397,7 +410,7 @@ evdev_configure_device(struct evdev_input_device *device) } if (TEST_BIT(abs_bits, ABS_MT_SLOT)) { device->is_mt = 1; - device->abs.slot_mt = 0; + device->mt.slot = 0; } } if (TEST_BIT(ev_bits, EV_KEY)) { @@ -438,7 +451,9 @@ evdev_input_device_create(struct evdev_input *master, device->is_touchpad = 0; device->is_mt = 0; device->devnode = strdup(path); - device->abs.slot_mt = -1; + device->mt.slot = -1; + device->rel.dx = 0; + device->rel.dy = 0; device->fd = open(path, O_RDONLY); if (device->fd < 0) From b9016b667dbf2003e81fede52b19527be8fc51d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 21 Dec 2011 22:54:49 -0500 Subject: [PATCH 046/162] clients: Add simple-touch client for testing touch events. --- compositor/evdev.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compositor/evdev.c b/compositor/evdev.c index c065b33c..08fef660 100644 --- a/compositor/evdev.c +++ b/compositor/evdev.c @@ -37,7 +37,7 @@ struct evdev_input { char *seat_id; }; -#define MAX_SLOTS 10 +#define MAX_SLOTS 16 struct evdev_input_device { struct evdev_input *master; @@ -279,8 +279,7 @@ is_motion_event(struct input_event *e) static void evdev_flush_motion(struct evdev_input_device *device, uint32_t time) { - struct wl_input_device *master = - &device->master->base.input_device; + struct wl_input_device *master = &device->master->base.input_device; if (!device->type) return; From 837e433973276408da0f135003de168eedd9eb3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 3 Jan 2012 10:29:47 -0500 Subject: [PATCH 047/162] Rename wayland-compositor to weston This rename addresses a few problems around the split between core Wayland and the wayland-demos repository. 1) Initially, we had one big repository with protocol code, sample compositor and sample clients. We split that repository to make it possible to implement the protocol without pulling in the sample/demo code. At this point, the compositor is more than just a "demo" and wayland-demos doesn't send the right message. The sample compositor is a useful, self-contained project in it's own right, and we want to move away from the "demos" label. 2) Another problem is that the wayland-demos compositor is often called "the wayland compsitor", but it's really just one possible compositor. Existing X11 compositors are expected to add Wayland support and then gradually phase out/modularize the X11 support, for example. Conversely, it's hard to talk about the wayland-demos compositor specifically as opposed to, eg, the wayland protocol or a wayland compositor in general. We are also renaming the repo to weston, and the compositor subdirectory to src/, to emphasize that the main "output" is the compositor. --- {compositor => src}/evdev.c | 24 ++++++++++++------------ {compositor => src}/evdev.h | 8 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) rename {compositor => src}/evdev.c (96%) rename {compositor => src}/evdev.h (83%) diff --git a/compositor/evdev.c b/src/evdev.c similarity index 96% rename from compositor/evdev.c rename to src/evdev.c index 08fef660..0b2fdfa9 100644 --- a/compositor/evdev.c +++ b/src/evdev.c @@ -31,7 +31,7 @@ #include "evdev.h" struct evdev_input { - struct wlsc_input_device base; + struct weston_input_device base; struct wl_list devices_list; struct udev_monitor *udev_monitor; char *seat_id; @@ -43,7 +43,7 @@ struct evdev_input_device { struct evdev_input *master; struct wl_list link; struct wl_event_source *source; - struct wlsc_output *output; + struct weston_output *output; char *devnode; int fd; struct { @@ -324,7 +324,7 @@ evdev_flush_motion(struct evdev_input_device *device, uint32_t time) static int evdev_input_device_data(int fd, uint32_t mask, void *data) { - struct wlsc_compositor *ec; + struct weston_compositor *ec; struct evdev_input_device *device = data; struct input_event ev[8], *e, *end; int len; @@ -436,7 +436,7 @@ evdev_input_device_create(struct evdev_input *master, { struct evdev_input_device *device; struct wl_event_loop *loop; - struct wlsc_compositor *ec; + struct weston_compositor *ec; device = malloc(sizeof *device); if (device == NULL) @@ -444,7 +444,7 @@ evdev_input_device_create(struct evdev_input *master, ec = master->base.compositor; device->output = - container_of(ec->output_list.next, struct wlsc_output, link); + container_of(ec->output_list.next, struct weston_output, link); device->master = master; device->is_touchpad = 0; @@ -485,7 +485,7 @@ static const char default_seat[] = "seat0"; static void device_added(struct udev_device *udev_device, struct evdev_input *master) { - struct wlsc_compositor *c; + struct weston_compositor *c; const char *devnode; const char *device_seat; @@ -522,7 +522,7 @@ device_removed(struct udev_device *udev_device, struct evdev_input *master) } void -evdev_add_devices(struct udev *udev, struct wlsc_input_device *input_base) +evdev_add_devices(struct udev *udev, struct weston_input_device *input_base) { struct evdev_input *input = (struct evdev_input *) input_base; struct udev_enumerate *e; @@ -578,7 +578,7 @@ static int evdev_config_udev_monitor(struct udev *udev, struct evdev_input *master) { struct wl_event_loop *loop; - struct wlsc_compositor *c = master->base.compositor; + struct weston_compositor *c = master->base.compositor; master->udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); if (!master->udev_monitor) @@ -600,7 +600,7 @@ evdev_config_udev_monitor(struct udev *udev, struct evdev_input *master) } void -evdev_input_create(struct wlsc_compositor *c, struct udev *udev, +evdev_input_create(struct weston_compositor *c, struct udev *udev, const char *seat) { struct evdev_input *input; @@ -610,7 +610,7 @@ evdev_input_create(struct wlsc_compositor *c, struct udev *udev, return; memset(input, 0, sizeof *input); - wlsc_input_device_init(&input->base, c); + weston_input_device_init(&input->base, c); wl_list_init(&input->devices_list); input->seat_id = strdup(seat); @@ -626,7 +626,7 @@ evdev_input_create(struct wlsc_compositor *c, struct udev *udev, } void -evdev_remove_devices(struct wlsc_input_device *input_base) +evdev_remove_devices(struct weston_input_device *input_base) { struct evdev_input *input = (struct evdev_input *) input_base; struct evdev_input_device *device, *next; @@ -642,7 +642,7 @@ evdev_remove_devices(struct wlsc_input_device *input_base) } void -evdev_input_destroy(struct wlsc_input_device *input_base) +evdev_input_destroy(struct weston_input_device *input_base) { struct evdev_input *input = (struct evdev_input *) input_base; diff --git a/compositor/evdev.h b/src/evdev.h similarity index 83% rename from compositor/evdev.h rename to src/evdev.h index 22878938..af5f6d9a 100644 --- a/compositor/evdev.h +++ b/src/evdev.h @@ -21,15 +21,15 @@ */ void -evdev_add_devices(struct udev *udev, struct wlsc_input_device +evdev_add_devices(struct udev *udev, struct weston_input_device *input_base); void -evdev_remove_devices(struct wlsc_input_device *input_base); +evdev_remove_devices(struct weston_input_device *input_base); void -evdev_input_create(struct wlsc_compositor *c, struct udev *udev, +evdev_input_create(struct weston_compositor *c, struct udev *udev, const char *seat); void -evdev_input_destroy(struct wlsc_input_device *input_base); +evdev_input_destroy(struct weston_input_device *input_base); From 36392fbd24e738c1535cb6bf2dcb68828ff2f7ca Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Thu, 5 Jan 2012 16:41:21 +0200 Subject: [PATCH 048/162] evdev: warn about missing input devices Usually there should be at least one input device, when Weston starts up, or is reactivated by a VT switch. Add a nice warning, in case there are no input devices. This is to give a clue to users who happen to try Weston on DRM, and do not get any response. Add also a message to another failure case, that may lead to missing input devices. Signed-off-by: Pekka Paalanen --- src/evdev.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 0b2fdfa9..39e04d8e 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -545,6 +545,16 @@ evdev_add_devices(struct udev *udev, struct weston_input_device *input_base) udev_device_unref(device); } udev_enumerate_unref(e); + + if (wl_list_empty(&input->devices_list)) { + fprintf(stderr, + "warning: no input devices on entering Weston. " + "Possible causes:\n" + "\t- no permissions to read /dev/input/evdev*\n" + "\t- seats misconfigured " + "(Weston backend option 'seat', " + "udev device property ID_SEAT)\n"); + } } static int @@ -581,8 +591,10 @@ evdev_config_udev_monitor(struct udev *udev, struct evdev_input *master) struct weston_compositor *c = master->base.compositor; master->udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); - if (!master->udev_monitor) + if (!master->udev_monitor) { + fprintf(stderr, "udev: failed to create the udev monitor\n"); return 0; + } udev_monitor_filter_add_match_subsystem_devtype(master->udev_monitor, "input", NULL); From cbba717b201c11068a885ea6dede410e5ffccce4 Mon Sep 17 00:00:00 2001 From: Olivier Le Thanh Duong Date: Sat, 14 Jan 2012 15:57:34 +0100 Subject: [PATCH 049/162] evdev: Correct warning on missing input device --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 39e04d8e..d614e255 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -550,7 +550,7 @@ evdev_add_devices(struct udev *udev, struct weston_input_device *input_base) fprintf(stderr, "warning: no input devices on entering Weston. " "Possible causes:\n" - "\t- no permissions to read /dev/input/evdev*\n" + "\t- no permissions to read /dev/input/event*\n" "\t- seats misconfigured " "(Weston backend option 'seat', " "udev device property ID_SEAT)\n"); From bcac853c5321dc9279f2737386f621279ac7ff01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 16 Jan 2012 10:54:07 -0500 Subject: [PATCH 050/162] evdev: Drop noisy debug messages on vt swtich --- src/evdev.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index d614e255..32d73679 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -498,8 +498,7 @@ device_added(struct udev_device *udev_device, struct evdev_input *master) c = master->base.compositor; devnode = udev_device_get_devnode(udev_device); - if (evdev_input_device_create(master, c->wl_display, devnode)) - fprintf(stderr, "evdev input device: added: %s\n", devnode); + evdev_input_device_create(master, c->wl_display, devnode); } static void @@ -518,7 +517,6 @@ device_removed(struct udev_device *udev_device, struct evdev_input *master) break; } } - fprintf(stderr, "evdev input device: removed: %s\n", devnode); } void @@ -644,7 +642,6 @@ evdev_remove_devices(struct weston_input_device *input_base) struct evdev_input_device *device, *next; wl_list_for_each_safe(device, next, &input->devices_list, link) { - fprintf(stderr, "evdev input device: removed: %s\n", device->devnode); wl_event_source_remove(device->source); wl_list_remove(&device->link); close(device->fd); From 67b11f7a8d5835ce22f0f349ede774f9dcbce0fd Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Fri, 20 Jan 2012 18:47:46 +0200 Subject: [PATCH 051/162] evdev: fix uninitialised pointer value ==30224== Conditional jump or move depends on uninitialised value(s) ==30224== at 0x40EE3A0: evdev_flush_motion (evdev.c:284) ==30224== by 0x40EE6DC: evdev_input_device_data (evdev.c:352) ==30224== by 0x4034710: wl_event_source_fd_dispatch (event-loop.c:76) ==30224== by 0x4035171: wl_event_loop_dispatch (event-loop.c:462) ==30224== by 0x4032F76: wl_display_run (wayland-server.c:785) ==30224== by 0x8050972: main (compositor.c:2183) Signed-off-by: Tiago Vignatti --- src/evdev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index 32d73679..f489ede0 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -340,6 +340,8 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) return 1; } + device->type = 0; + e = ev; end = (void *) ev + len; for (e = ev; e < end; e++) { From f7968296c621ddcaeb637dde3ce24452ab20a958 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 24 Jan 2012 16:37:15 +0100 Subject: [PATCH 052/162] weston: Drop priviledges early, and seteuid when needed --- src/evdev.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index f489ede0..101b63f9 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -20,6 +20,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#define _GNU_SOURCE + #include #include #include @@ -439,6 +441,7 @@ evdev_input_device_create(struct evdev_input *master, struct evdev_input_device *device; struct wl_event_loop *loop; struct weston_compositor *ec; + uid_t saved_uid, uid, euid; device = malloc(sizeof *device); if (device == NULL) @@ -456,7 +459,10 @@ evdev_input_device_create(struct evdev_input *master, device->rel.dx = 0; device->rel.dy = 0; + getresuid(&uid, &euid, &saved_uid); + seteuid(saved_uid); device->fd = open(path, O_RDONLY); + seteuid(euid); if (device->fd < 0) goto err0; From 0f0dd81107ffd1d86cd10a9ce395b3ffbc40c503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 24 Jan 2012 12:37:17 -0500 Subject: [PATCH 053/162] Revert "weston: Drop priviledges early, and seteuid when needed" This reverts commit fc6ccb868fa735ee9c6592806f381aa1262bf0b2. We still need root permissions for drmDrop/SetMaster. Without integration with ConsoleKit or systemd we also don't have access to /dev/dri/cardX in the case where we open a new VT. --- src/evdev.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 101b63f9..f489ede0 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -20,8 +20,6 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#define _GNU_SOURCE - #include #include #include @@ -441,7 +439,6 @@ evdev_input_device_create(struct evdev_input *master, struct evdev_input_device *device; struct wl_event_loop *loop; struct weston_compositor *ec; - uid_t saved_uid, uid, euid; device = malloc(sizeof *device); if (device == NULL) @@ -459,10 +456,7 @@ evdev_input_device_create(struct evdev_input *master, device->rel.dx = 0; device->rel.dy = 0; - getresuid(&uid, &euid, &saved_uid); - seteuid(saved_uid); device->fd = open(path, O_RDONLY); - seteuid(euid); if (device->fd < 0) goto err0; From dfc66d4662011a3930cb794bb41489167253c188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 5 Mar 2012 17:49:30 -0500 Subject: [PATCH 054/162] compositor: Move input devices to their own event loop First step towards only handling input at repaint time. --- src/evdev.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index f489ede0..530eb6b6 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -437,7 +437,6 @@ evdev_input_device_create(struct evdev_input *master, struct wl_display *display, const char *path) { struct evdev_input_device *device; - struct wl_event_loop *loop; struct weston_compositor *ec; device = malloc(sizeof *device); @@ -463,8 +462,7 @@ evdev_input_device_create(struct evdev_input *master, if (evdev_configure_device(device) == -1) goto err1; - loop = wl_display_get_event_loop(display); - device->source = wl_event_loop_add_fd(loop, device->fd, + device->source = wl_event_loop_add_fd(ec->input_loop, device->fd, WL_EVENT_READABLE, evdev_input_device_data, device); if (device->source == NULL) From bdb628857bb9b7705838b83a230c14c12411f15b Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Fri, 16 Mar 2012 17:33:03 -0300 Subject: [PATCH 055/162] evdev: use mtdev for multitouch devices mtdev library translates all multitouch based devices to the slotted evdev protocol. It provides an uniform interface for Weston, which eases mt implementation when dealing with a big variety of devices. Weston on drm now directly depends on such library. Signed-off-by: Tiago Vignatti Reviewed-by: Peter Hutterer --- src/evdev.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 530eb6b6..9b8d756a 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "compositor.h" #include "evdev.h" @@ -57,6 +58,7 @@ struct evdev_input_device { int32_t x[MAX_SLOTS]; int32_t y[MAX_SLOTS]; } mt; + struct mtdev *mtdev; struct { int dx, dy; @@ -320,13 +322,14 @@ evdev_flush_motion(struct evdev_input_device *device, uint32_t time) device->type &= ~EVDEV_ABSOLUTE_MOTION; } } +#define NUM_EVENTS 8 static int evdev_input_device_data(int fd, uint32_t mask, void *data) { struct weston_compositor *ec; struct evdev_input_device *device = data; - struct input_event ev[8], *e, *end; + struct input_event ev[NUM_EVENTS], *e, *end; int len; uint32_t time = 0; @@ -334,7 +337,11 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) if (!ec->focus) return 1; - len = read(fd, &ev, sizeof ev); + if (device->mtdev) + len = mtdev_get(device->mtdev, fd, ev, NUM_EVENTS) * + sizeof (struct input_event); + else + len = read(fd, &ev, sizeof ev); if (len < 0 || len % sizeof e[0] != 0) { /* FIXME: call device_removed when errno is ENODEV. */; return 1; @@ -450,18 +457,26 @@ evdev_input_device_create(struct evdev_input *master, device->master = master; device->is_touchpad = 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->fd = open(path, O_RDONLY); + /* if O_NONBLOCK is not set, mtdev_get() blocks */ + device->fd = open(path, O_RDONLY | O_NONBLOCK); if (device->fd < 0) goto err0; if (evdev_configure_device(device) == -1) goto err1; + if (device->is_mt) { + device->mtdev = mtdev_new_open(device->fd); + if (!device->mtdev) + fprintf(stderr, "mtdev failed to open for %s\n", path); + } + device->source = wl_event_loop_add_fd(ec->input_loop, device->fd, WL_EVENT_READABLE, evdev_input_device_data, device); @@ -511,6 +526,8 @@ device_removed(struct udev_device *udev_device, struct evdev_input *master) if (!strcmp(device->devnode, devnode)) { wl_event_source_remove(device->source); wl_list_remove(&device->link); + if (device->mtdev) + mtdev_close_delete(device->mtdev); close(device->fd); free(device->devnode); free(device); From 8046633edf176435f127a82ea14bfe369cdeef8b Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Tue, 20 Mar 2012 19:52:57 -0400 Subject: [PATCH 056/162] evdev: fix input lag when processing input from output repaint When the compositor is in a repaint cycle, input is processed only once per frame. However, a call to evdev_input_device_data() would handle at most 8 events at time. When there was more than 8 events pending for a given frame, input lag would occur. This was most visible with multi touch input. This patch changes the evdev_input_device_data() so that it will handle all the events available in the fd. In order to do that, the fd is put in non-blocking mode, so that it is possible to loop on read and stop on EAGAIN instead of blocking. --- src/evdev.c | 65 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 9b8d756a..e0a59668 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -322,35 +322,18 @@ evdev_flush_motion(struct evdev_input_device *device, uint32_t time) device->type &= ~EVDEV_ABSOLUTE_MOTION; } } -#define NUM_EVENTS 8 -static int -evdev_input_device_data(int fd, uint32_t mask, void *data) +static void +evdev_process_events(struct evdev_input_device *device, + struct input_event *ev, int count) { - struct weston_compositor *ec; - struct evdev_input_device *device = data; - struct input_event ev[NUM_EVENTS], *e, *end; - int len; + struct input_event *e, *end; uint32_t time = 0; - ec = device->master->base.compositor; - if (!ec->focus) - return 1; - - if (device->mtdev) - len = mtdev_get(device->mtdev, fd, ev, NUM_EVENTS) * - sizeof (struct input_event); - else - len = read(fd, &ev, sizeof ev); - if (len < 0 || len % sizeof e[0] != 0) { - /* FIXME: call device_removed when errno is ENODEV. */; - return 1; - } - device->type = 0; e = ev; - end = (void *) ev + len; + end = e + count; for (e = ev; e < end; e++) { time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000; @@ -373,11 +356,43 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) } evdev_flush_motion(device, time); +} + +static int +evdev_input_device_data(int fd, uint32_t mask, void *data) +{ + struct weston_compositor *ec; + struct evdev_input_device *device = data; + struct input_event ev[32]; + int len; + + ec = device->master->base.compositor; + if (!ec->focus) + 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) { + /* FIXME: call device_removed when errno is ENODEV. */ + return 1; + } + + evdev_process_events(device, ev, len / sizeof ev[0]); + + } while (len > 0); return 1; } - /* copied from udev/extras/input_id/input_id.c */ /* we must use this kernel-compatible implementation */ #define BITS_PER_LONG (sizeof(unsigned long) * 8) @@ -463,7 +478,9 @@ evdev_input_device_create(struct evdev_input *master, device->rel.dx = 0; device->rel.dy = 0; - /* if O_NONBLOCK is not set, mtdev_get() blocks */ + /* Use non-blocking mode so that we can loop on read on + * evdev_input_device_data() until all events on the fd are + * read. mtdev_get() also expects this. */ device->fd = open(path, O_RDONLY | O_NONBLOCK); if (device->fd < 0) goto err0; From 8fb6507f549c387e381073b616314fbefb565c0c Mon Sep 17 00:00:00 2001 From: Scott Moreau Date: Thu, 22 Mar 2012 10:47:01 -0600 Subject: [PATCH 057/162] Hook up axis events. --- src/evdev.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index e0a59668..8642f515 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -227,8 +227,8 @@ evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, } static inline void -evdev_process_relative_motion(struct evdev_input_device *device, - struct input_event *e) +evdev_process_relative(struct evdev_input_device *device, + struct input_event *e, uint32_t time) { switch (e->code) { case REL_X: @@ -239,6 +239,16 @@ evdev_process_relative_motion(struct evdev_input_device *device, device->rel.dy += e->value; device->type |= EVDEV_RELATIVE_MOTION; break; + case REL_WHEEL: + notify_axis(&device->master->base.input_device, + time, + WL_INPUT_DEVICE_AXIS_VERTICAL_SCROLL, e->value); + break; + case REL_HWHEEL: + notify_axis(&device->master->base.input_device, + time, + WL_INPUT_DEVICE_AXIS_HORIZONTAL_SCROLL, e->value); + break; } } @@ -344,7 +354,7 @@ evdev_process_events(struct evdev_input_device *device, evdev_flush_motion(device, time); switch (e->type) { case EV_REL: - evdev_process_relative_motion(device, e); + evdev_process_relative(device, e, time); break; case EV_ABS: evdev_process_absolute(device, e); From 9dae61964679ee8b4e12031e6bffe2fd4908b977 Mon Sep 17 00:00:00 2001 From: Tiago Vignatti Date: Tue, 27 Mar 2012 21:26:01 +0300 Subject: [PATCH 058/162] evdev: reuse code for device removal Just like device_added, now the routines to close the compositor and vt switch leave are using the same code to remove a device. This patch also closes properly a mtdev device, bug spotted by Christopher Michael. Signed-off-by: Tiago Vignatti --- src/evdev.c | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 8642f515..5dbe6ac2 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -544,23 +544,15 @@ device_added(struct udev_device *udev_device, struct evdev_input *master) } static void -device_removed(struct udev_device *udev_device, struct evdev_input *master) +device_removed(struct evdev_input_device *device) { - const char *devnode = udev_device_get_devnode(udev_device); - struct evdev_input_device *device, *next; - - wl_list_for_each_safe(device, next, &master->devices_list, link) { - if (!strcmp(device->devnode, devnode)) { - wl_event_source_remove(device->source); - wl_list_remove(&device->link); - if (device->mtdev) - mtdev_close_delete(device->mtdev); - close(device->fd); - free(device->devnode); - free(device); - break; - } - } + wl_event_source_remove(device->source); + wl_list_remove(&device->link); + if (device->mtdev) + mtdev_close_delete(device->mtdev); + close(device->fd); + free(device->devnode); + free(device); } void @@ -604,7 +596,9 @@ evdev_udev_handler(int fd, uint32_t mask, void *data) { struct evdev_input *master = data; struct udev_device *udev_device; + struct evdev_input_device *device, *next; const char *action; + const char *devnode; udev_device = udev_monitor_receive_device(master->udev_monitor); if (!udev_device) @@ -618,8 +612,15 @@ evdev_udev_handler(int fd, uint32_t mask, void *data) if (!strcmp(action, "add")) { device_added(udev_device, master); } - else if (!strcmp(action, "remove")) - device_removed(udev_device, master); + else if (!strcmp(action, "remove")) { + devnode = udev_device_get_devnode(udev_device); + wl_list_for_each_safe(device, next, + &master->devices_list, link) + if (!strcmp(device->devnode, devnode)) { + device_removed(device); + break; + } + } } udev_device_unref(udev_device); @@ -685,13 +686,8 @@ evdev_remove_devices(struct weston_input_device *input_base) struct evdev_input *input = (struct evdev_input *) input_base; struct evdev_input_device *device, *next; - wl_list_for_each_safe(device, next, &input->devices_list, link) { - wl_event_source_remove(device->source); - wl_list_remove(&device->link); - close(device->fd); - free(device->devnode); - free(device); - } + wl_list_for_each_safe(device, next, &input->devices_list, link) + device_removed(device); } void From bab10c08127239d067a18f7023b808e63ad6d8bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 28 Mar 2012 22:36:09 +0200 Subject: [PATCH 059/162] Properly dispose event sources and event loops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl --- src/evdev.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 5dbe6ac2..16f0e935 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -35,6 +35,7 @@ struct evdev_input { struct weston_input_device base; struct wl_list devices_list; struct udev_monitor *udev_monitor; + struct wl_event_source *udev_monitor_source; char *seat_id; }; @@ -562,7 +563,7 @@ evdev_add_devices(struct udev *udev, struct weston_input_device *input_base) struct udev_enumerate *e; struct udev_list_entry *entry; struct udev_device *device; - const char *path; + const char *path, *sysname; e = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(e, "input"); @@ -571,8 +572,11 @@ evdev_add_devices(struct udev *udev, struct weston_input_device *input_base) path = udev_list_entry_get_name(entry); device = udev_device_new_from_syspath(udev, path); - if (strncmp("event", udev_device_get_sysname(device), 5) != 0) + sysname = udev_device_get_sysname(device); + if (strncmp("event", sysname, 5) != 0) { + udev_device_unref(device); continue; + } device_added(device, input); @@ -632,6 +636,7 @@ evdev_config_udev_monitor(struct udev *udev, struct evdev_input *master) { struct wl_event_loop *loop; struct weston_compositor *c = master->base.compositor; + int fd; master->udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); if (!master->udev_monitor) { @@ -644,12 +649,19 @@ evdev_config_udev_monitor(struct udev *udev, struct evdev_input *master) if (udev_monitor_enable_receiving(master->udev_monitor)) { fprintf(stderr, "udev: failed to bind the udev monitor\n"); + udev_monitor_unref(master->udev_monitor); return 0; } loop = wl_display_get_event_loop(c->wl_display); - wl_event_loop_add_fd(loop, udev_monitor_get_fd(master->udev_monitor), - WL_EVENT_READABLE, evdev_udev_handler, master); + fd = udev_monitor_get_fd(master->udev_monitor); + master->udev_monitor_source = + wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, + evdev_udev_handler, master); + if (!master->udev_monitor_source) { + udev_monitor_unref(master->udev_monitor); + return 0; + } return 1; } @@ -696,6 +708,10 @@ evdev_input_destroy(struct weston_input_device *input_base) struct evdev_input *input = (struct evdev_input *) input_base; evdev_remove_devices(input_base); + + udev_monitor_unref(input->udev_monitor); + wl_event_source_remove(input->udev_monitor_source); + wl_list_remove(&input->base.link); free(input->seat_id); free(input); From 5cc1e3263a5190928234285a74db4f3953a930fa Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Mon, 30 Jan 2012 14:04:04 +0100 Subject: [PATCH 060/162] Introduce weston-launch weston-launch starts weston and provides mechanism for weston to set/drop drm master, open a tty, and read input devices without being root. Execution is allowed for local-active sessions or users in the group weston-launch. --- src/evdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 16f0e935..9967e525 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -30,6 +30,7 @@ #include "compositor.h" #include "evdev.h" +#include "launcher-util.h" struct evdev_input { struct weston_input_device base; @@ -492,7 +493,7 @@ evdev_input_device_create(struct evdev_input *master, /* Use non-blocking mode so that we can loop on read on * evdev_input_device_data() until all events on the fd are * read. mtdev_get() also expects this. */ - device->fd = open(path, O_RDONLY | O_NONBLOCK); + device->fd = weston_launcher_open(ec, path, O_RDONLY | O_NONBLOCK); if (device->fd < 0) goto err0; From 38bb7a001bdbf5f8c6256e75cbe7dd479a80d0a2 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Mon, 9 Apr 2012 18:14:58 +0200 Subject: [PATCH 061/162] evdev: Disable the udev monitor when another vt becomes active We dont want to receive hotplug events while being inactive. When getting back active we enumerate all devices and would end up with two sources for one device that may be hotplugged in the mean time. --- src/evdev.c | 25 +++++++++++++++++++------ src/evdev.h | 6 ++++++ 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 9967e525..d328264b 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -632,9 +632,10 @@ evdev_udev_handler(int fd, uint32_t mask, void *data) return 0; } -static int -evdev_config_udev_monitor(struct udev *udev, struct evdev_input *master) +int +evdev_enable_udev_monitor(struct udev *udev, struct weston_input_device *input_base) { + struct evdev_input *master = (struct evdev_input *) input_base; struct wl_event_loop *loop; struct weston_compositor *c = master->base.compositor; int fd; @@ -667,6 +668,20 @@ evdev_config_udev_monitor(struct udev *udev, struct evdev_input *master) return 1; } +void +evdev_disable_udev_monitor(struct weston_input_device *input_base) +{ + struct evdev_input *input = (struct evdev_input *) input_base; + + if (!input->udev_monitor) + return; + + udev_monitor_unref(input->udev_monitor); + input->udev_monitor = NULL; + wl_event_source_remove(input->udev_monitor_source); + input->udev_monitor_source = NULL; +} + void evdev_input_create(struct weston_compositor *c, struct udev *udev, const char *seat) @@ -682,7 +697,7 @@ evdev_input_create(struct weston_compositor *c, struct udev *udev, wl_list_init(&input->devices_list); input->seat_id = strdup(seat); - if (!evdev_config_udev_monitor(udev, input)) { + if (!evdev_enable_udev_monitor(udev, &input->base)) { free(input->seat_id); free(input); return; @@ -709,9 +724,7 @@ evdev_input_destroy(struct weston_input_device *input_base) struct evdev_input *input = (struct evdev_input *) input_base; evdev_remove_devices(input_base); - - udev_monitor_unref(input->udev_monitor); - wl_event_source_remove(input->udev_monitor_source); + evdev_disable_udev_monitor(&input->base); wl_list_remove(&input->base.link); free(input->seat_id); diff --git a/src/evdev.h b/src/evdev.h index af5f6d9a..4e298149 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -33,3 +33,9 @@ evdev_input_create(struct weston_compositor *c, struct udev *udev, void evdev_input_destroy(struct weston_input_device *input_base); + +int +evdev_enable_udev_monitor(struct udev *udev, struct weston_input_device *input_base); + +void +evdev_disable_udev_monitor(struct weston_input_device *input_base); From b5e48ee43f6ed0c0a79bea3a2075004627b0130f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 10 Apr 2012 00:03:30 -0400 Subject: [PATCH 062/162] evdev: Get key state from kernel on vt enter We need this to correctly initialize compositor key state, modifier state and to send the right keys in the key enter event. --- src/evdev.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index d328264b..9cb13cce 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -557,6 +557,45 @@ device_removed(struct evdev_input_device *device) free(device); } +static void +evdev_notify_keyboard_focus(struct evdev_input *input) +{ + struct evdev_input_device *device; + struct wl_array keys; + unsigned int i, set; + char evdev_keys[(KEY_CNT + 7) / 8], all_keys[(KEY_CNT + 7) / 8]; + uint32_t *k; + int ret; + + memset(all_keys, 0, sizeof all_keys); + wl_list_for_each(device, &input->devices_list, link) { + memset(evdev_keys, 0, sizeof evdev_keys); + ret = ioctl(device->fd, + EVIOCGKEY(sizeof evdev_keys), evdev_keys); + if (ret < 0) { + fprintf(stderr, "failed to get keys for device %s\n", + device->devnode); + continue; + } + for (i = 0; i < ARRAY_LENGTH(evdev_keys); i++) + all_keys[i] |= evdev_keys[i]; + } + + wl_array_init(&keys); + for (i = 0; i < KEY_CNT; i++) { + set = all_keys[i >> 3] & (1 << (i & 7)); + if (set) { + k = wl_array_add(&keys, sizeof *k); + *k = i; + } + } + + notify_keyboard_focus(&input->base.input_device, + weston_compositor_get_time(), &keys); + + wl_array_release(&keys); +} + void evdev_add_devices(struct udev *udev, struct weston_input_device *input_base) { @@ -585,6 +624,8 @@ evdev_add_devices(struct udev *udev, struct weston_input_device *input_base) } udev_enumerate_unref(e); + evdev_notify_keyboard_focus(input); + if (wl_list_empty(&input->devices_list)) { fprintf(stderr, "warning: no input devices on entering Weston. " @@ -716,6 +757,9 @@ evdev_remove_devices(struct weston_input_device *input_base) wl_list_for_each_safe(device, next, &input->devices_list, link) device_removed(device); + + notify_keyboard_focus(&input->base.input_device, + weston_compositor_get_time(), NULL); } void From 46b3b7e0fce948ce302a105b07912f6cdb930679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 11 Apr 2012 22:42:15 -0400 Subject: [PATCH 063/162] Follow wayland change to serial numbers --- src/evdev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 9cb13cce..c65b82f7 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -590,8 +590,7 @@ evdev_notify_keyboard_focus(struct evdev_input *input) } } - notify_keyboard_focus(&input->base.input_device, - weston_compositor_get_time(), &keys); + notify_keyboard_focus(&input->base.input_device, &keys); wl_array_release(&keys); } @@ -758,8 +757,7 @@ evdev_remove_devices(struct weston_input_device *input_base) wl_list_for_each_safe(device, next, &input->devices_list, link) device_removed(device); - notify_keyboard_focus(&input->base.input_device, - weston_compositor_get_time(), NULL); + notify_keyboard_focus(&input->base.input_device, NULL); } void From c28389d199466b354f59cde9520cc5e2c9df1d1f Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 30 Mar 2012 15:20:23 +0300 Subject: [PATCH 064/162] compositor: move libudev.h to evdev.h Compositor core does not do anything with udev, so the header is not needed there. Move the #include into evdev.h, from where it gets used by compositor-drm.c, too. Also fix the fallout: tty.c: In function 'tty_create': tty.c:143:2: warning: implicit declaration of function 'fstat' Signed-off-by: Pekka Paalanen --- src/evdev.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/evdev.h b/src/evdev.h index 4e298149..b05c855c 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -20,6 +20,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include + void evdev_add_devices(struct udev *udev, struct weston_input_device *input_base); From d9f387fdf7bf91f1cdb9b5b45e65a59f9e356feb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 9 May 2012 08:46:44 +0200 Subject: [PATCH 065/162] evdev: Convert wl_fixed_t to int before using internally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl --- src/evdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index c65b82f7..5fa7ae69 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -300,8 +300,8 @@ evdev_flush_motion(struct evdev_input_device *device, uint32_t time) if (device->type & EVDEV_RELATIVE_MOTION) { notify_motion(master, time, - master->x + device->rel.dx, - master->y + device->rel.dy); + wl_fixed_to_int(master->x) + device->rel.dx, + wl_fixed_to_int(master->y) + device->rel.dy); device->type &= ~EVDEV_RELATIVE_MOTION; device->rel.dx = 0; device->rel.dy = 0; From 3ffaf3d79bddab73bd001ee6e27bbbebadd4c9b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 9 May 2012 12:19:04 -0400 Subject: [PATCH 066/162] compositor: Use wl_fixed_t for incoming input events This changes notify_motion, notify_pointer_focus and notify_touch to take wl_fixed_t types for input coordinates. --- src/evdev.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 5fa7ae69..4dbf5750 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -300,8 +300,8 @@ evdev_flush_motion(struct evdev_input_device *device, uint32_t time) if (device->type & EVDEV_RELATIVE_MOTION) { notify_motion(master, time, - wl_fixed_to_int(master->x) + device->rel.dx, - wl_fixed_to_int(master->y) + device->rel.dy); + master->x + wl_fixed_from_int(device->rel.dx), + master->y + wl_fixed_from_int(device->rel.dy)); device->type &= ~EVDEV_RELATIVE_MOTION; device->rel.dx = 0; device->rel.dy = 0; @@ -309,8 +309,8 @@ evdev_flush_motion(struct evdev_input_device *device, uint32_t time) if (device->type & EVDEV_ABSOLUTE_MT_DOWN) { notify_touch(master, time, device->mt.slot, - device->mt.x[device->mt.slot], - device->mt.y[device->mt.slot], + wl_fixed_from_int(device->mt.x[device->mt.slot]), + wl_fixed_from_int(device->mt.y[device->mt.slot]), WL_INPUT_DEVICE_TOUCH_DOWN); device->type &= ~EVDEV_ABSOLUTE_MT_DOWN; device->type &= ~EVDEV_ABSOLUTE_MT_MOTION; @@ -318,8 +318,8 @@ evdev_flush_motion(struct evdev_input_device *device, uint32_t time) if (device->type & EVDEV_ABSOLUTE_MT_MOTION) { notify_touch(master, time, device->mt.slot, - device->mt.x[device->mt.slot], - device->mt.y[device->mt.slot], + wl_fixed_from_int(device->mt.x[device->mt.slot]), + wl_fixed_from_int(device->mt.y[device->mt.slot]), WL_INPUT_DEVICE_TOUCH_MOTION); device->type &= ~EVDEV_ABSOLUTE_MT_DOWN; device->type &= ~EVDEV_ABSOLUTE_MT_MOTION; @@ -330,7 +330,9 @@ evdev_flush_motion(struct evdev_input_device *device, uint32_t time) device->type &= ~EVDEV_ABSOLUTE_MT_UP; } if (device->type & EVDEV_ABSOLUTE_MOTION) { - notify_motion(master, time, device->abs.x, device->abs.y); + notify_motion(master, time, + wl_fixed_from_int(device->abs.x), + wl_fixed_from_int(device->abs.y)); device->type &= ~EVDEV_ABSOLUTE_MOTION; } } From def34d026d4ceea37d58da50d71d783d7f7de66b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 10 May 2012 16:46:48 -0400 Subject: [PATCH 067/162] evdev: Use wl_fixed_t for relative motions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl --- src/evdev.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 4dbf5750..22634aa1 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -63,7 +63,7 @@ struct evdev_input_device { struct mtdev *mtdev; struct { - int dx, dy; + wl_fixed_t dx, dy; } rel; int type; /* event type flags */ @@ -196,6 +196,7 @@ evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, { /* FIXME: Make this configurable somehow. */ const int touchpad_speed = 700; + int dx, dy; switch (e->code) { case ABS_X: @@ -203,10 +204,11 @@ evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, if (device->abs.reset_x) device->abs.reset_x = 0; else { - device->rel.dx = + dx = (e->value - device->abs.old_x) * touchpad_speed / (device->abs.max_x - device->abs.min_x); + device->rel.dx = wl_fixed_from_int(dx); } device->abs.old_x = e->value; device->type |= EVDEV_RELATIVE_MOTION; @@ -216,11 +218,12 @@ evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, if (device->abs.reset_y) device->abs.reset_y = 0; else { - device->rel.dy = + dy = (e->value - device->abs.old_y) * touchpad_speed / /* maybe use x size here to have the same scale? */ (device->abs.max_y - device->abs.min_y); + device->rel.dy = wl_fixed_from_int(dy); } device->abs.old_y = e->value; device->type |= EVDEV_RELATIVE_MOTION; @@ -234,11 +237,11 @@ evdev_process_relative(struct evdev_input_device *device, { switch (e->code) { case REL_X: - device->rel.dx += e->value; + device->rel.dx += wl_fixed_from_int(e->value); device->type |= EVDEV_RELATIVE_MOTION; break; case REL_Y: - device->rel.dy += e->value; + device->rel.dy += wl_fixed_from_int(e->value); device->type |= EVDEV_RELATIVE_MOTION; break; case REL_WHEEL: @@ -300,8 +303,8 @@ evdev_flush_motion(struct evdev_input_device *device, uint32_t time) if (device->type & EVDEV_RELATIVE_MOTION) { notify_motion(master, time, - master->x + wl_fixed_from_int(device->rel.dx), - master->y + wl_fixed_from_int(device->rel.dy)); + master->x + device->rel.dx, + master->y + device->rel.dy); device->type &= ~EVDEV_RELATIVE_MOTION; device->rel.dx = 0; device->rel.dy = 0; From 93c5aa06d5981545f86d0f119165ea72a0bb5984 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 16 May 2012 18:45:18 +0100 Subject: [PATCH 068/162] Convert wl_input_device to wl_seat (and friends) wl_input_device has been both renamed and split. wl_seat is now a virtual object representing a group of logically related input devices with related focus. It now only generates one event: to let clients know that it has new capabilities. It takes requests which hand back objects for the wl_pointer, wl_keyboard and wl_touch interfaces it exposes which all provide the old input interface, just under different names. This commit tracks these changes in weston and the clients, as well as similar renames (e.g. weston_input_device -> weston_seat). Some other changes were necessary, e.g. renaming the name for the visible mouse sprite from 'pointer' to 'cursor' so as to not conflict. For simplicity, every seat is always exposed with all three interfaces, although this will change as time goes on. Signed-off-by: Daniel Stone --- src/evdev.c | 128 ++++++++++++++++++++++++++-------------------------- src/evdev.h | 11 ++--- 2 files changed, 69 insertions(+), 70 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 22634aa1..26002b42 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -32,8 +32,8 @@ #include "evdev.h" #include "launcher-util.h" -struct evdev_input { - struct weston_input_device base; +struct evdev_seat { + struct weston_seat base; struct wl_list devices_list; struct udev_monitor *udev_monitor; struct wl_event_source *udev_monitor_source; @@ -43,7 +43,7 @@ struct evdev_input { #define MAX_SLOTS 16 struct evdev_input_device { - struct evdev_input *master; + struct evdev_seat *master; struct wl_list link; struct wl_event_source *source; struct weston_output *output; @@ -120,12 +120,12 @@ evdev_process_key(struct evdev_input_device *device, case BTN_FORWARD: case BTN_BACK: case BTN_TASK: - notify_button(&device->master->base.input_device, + notify_button(&device->master->base.seat, time, e->code, e->value); break; default: - notify_key(&device->master->base.input_device, + notify_key(&device->master->base.seat, time, e->code, e->value); break; } @@ -245,14 +245,14 @@ evdev_process_relative(struct evdev_input_device *device, device->type |= EVDEV_RELATIVE_MOTION; break; case REL_WHEEL: - notify_axis(&device->master->base.input_device, + notify_axis(&device->master->base.seat, time, - WL_INPUT_DEVICE_AXIS_VERTICAL_SCROLL, e->value); + WL_POINTER_AXIS_VERTICAL_SCROLL, e->value); break; case REL_HWHEEL: - notify_axis(&device->master->base.input_device, + notify_axis(&device->master->base.seat, time, - WL_INPUT_DEVICE_AXIS_HORIZONTAL_SCROLL, e->value); + WL_POINTER_AXIS_HORIZONTAL_SCROLL, e->value); break; } } @@ -296,44 +296,44 @@ is_motion_event(struct input_event *e) static void evdev_flush_motion(struct evdev_input_device *device, uint32_t time) { - struct wl_input_device *master = &device->master->base.input_device; + struct weston_seat *master = &device->master->base; if (!device->type) return; if (device->type & EVDEV_RELATIVE_MOTION) { - notify_motion(master, time, - master->x + device->rel.dx, - master->y + device->rel.dy); + notify_motion(&master->seat, time, + master->seat.pointer->x + device->rel.dx, + master->seat.pointer->y + device->rel.dy); device->type &= ~EVDEV_RELATIVE_MOTION; device->rel.dx = 0; device->rel.dy = 0; } if (device->type & EVDEV_ABSOLUTE_MT_DOWN) { - notify_touch(master, time, + notify_touch(&master->seat, time, device->mt.slot, wl_fixed_from_int(device->mt.x[device->mt.slot]), wl_fixed_from_int(device->mt.y[device->mt.slot]), - WL_INPUT_DEVICE_TOUCH_DOWN); + WL_TOUCH_DOWN); device->type &= ~EVDEV_ABSOLUTE_MT_DOWN; device->type &= ~EVDEV_ABSOLUTE_MT_MOTION; } if (device->type & EVDEV_ABSOLUTE_MT_MOTION) { - notify_touch(master, time, + notify_touch(&master->seat, time, device->mt.slot, wl_fixed_from_int(device->mt.x[device->mt.slot]), wl_fixed_from_int(device->mt.y[device->mt.slot]), - WL_INPUT_DEVICE_TOUCH_MOTION); + WL_TOUCH_MOTION); device->type &= ~EVDEV_ABSOLUTE_MT_DOWN; device->type &= ~EVDEV_ABSOLUTE_MT_MOTION; } if (device->type & EVDEV_ABSOLUTE_MT_UP) { - notify_touch(master, time, device->mt.slot, 0, 0, - WL_INPUT_DEVICE_TOUCH_UP); + notify_touch(&master->seat, time, device->mt.slot, 0, 0, + WL_TOUCH_UP); device->type &= ~EVDEV_ABSOLUTE_MT_UP; } if (device->type & EVDEV_ABSOLUTE_MOTION) { - notify_motion(master, time, + notify_motion(&master->seat, time, wl_fixed_from_int(device->abs.x), wl_fixed_from_int(device->abs.y)); device->type &= ~EVDEV_ABSOLUTE_MOTION; @@ -472,7 +472,7 @@ evdev_configure_device(struct evdev_input_device *device) } static struct evdev_input_device * -evdev_input_device_create(struct evdev_input *master, +evdev_input_device_create(struct evdev_seat *master, struct wl_display *display, const char *path) { struct evdev_input_device *device; @@ -532,7 +532,7 @@ err0: static const char default_seat[] = "seat0"; static void -device_added(struct udev_device *udev_device, struct evdev_input *master) +device_added(struct udev_device *udev_device, struct evdev_seat *master) { struct weston_compositor *c; const char *devnode; @@ -563,7 +563,7 @@ device_removed(struct evdev_input_device *device) } static void -evdev_notify_keyboard_focus(struct evdev_input *input) +evdev_notify_keyboard_focus(struct evdev_seat *seat) { struct evdev_input_device *device; struct wl_array keys; @@ -573,7 +573,7 @@ evdev_notify_keyboard_focus(struct evdev_input *input) int ret; memset(all_keys, 0, sizeof all_keys); - wl_list_for_each(device, &input->devices_list, link) { + wl_list_for_each(device, &seat->devices_list, link) { memset(evdev_keys, 0, sizeof evdev_keys); ret = ioctl(device->fd, EVIOCGKEY(sizeof evdev_keys), evdev_keys); @@ -595,15 +595,15 @@ evdev_notify_keyboard_focus(struct evdev_input *input) } } - notify_keyboard_focus(&input->base.input_device, &keys); + notify_keyboard_focus(&seat->base.seat, &keys); wl_array_release(&keys); } void -evdev_add_devices(struct udev *udev, struct weston_input_device *input_base) +evdev_add_devices(struct udev *udev, struct weston_seat *seat_base) { - struct evdev_input *input = (struct evdev_input *) input_base; + struct evdev_seat *seat = (struct evdev_seat *) seat_base; struct udev_enumerate *e; struct udev_list_entry *entry; struct udev_device *device; @@ -622,15 +622,15 @@ evdev_add_devices(struct udev *udev, struct weston_input_device *input_base) continue; } - device_added(device, input); + device_added(device, seat); udev_device_unref(device); } udev_enumerate_unref(e); - evdev_notify_keyboard_focus(input); + evdev_notify_keyboard_focus(seat); - if (wl_list_empty(&input->devices_list)) { + if (wl_list_empty(&seat->devices_list)) { fprintf(stderr, "warning: no input devices on entering Weston. " "Possible causes:\n" @@ -644,7 +644,7 @@ evdev_add_devices(struct udev *udev, struct weston_input_device *input_base) static int evdev_udev_handler(int fd, uint32_t mask, void *data) { - struct evdev_input *master = data; + struct evdev_seat *master = data; struct udev_device *udev_device; struct evdev_input_device *device, *next; const char *action; @@ -678,9 +678,9 @@ evdev_udev_handler(int fd, uint32_t mask, void *data) } int -evdev_enable_udev_monitor(struct udev *udev, struct weston_input_device *input_base) +evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base) { - struct evdev_input *master = (struct evdev_input *) input_base; + struct evdev_seat *master = (struct evdev_seat *) seat_base; struct wl_event_loop *loop; struct weston_compositor *c = master->base.compositor; int fd; @@ -714,66 +714,66 @@ evdev_enable_udev_monitor(struct udev *udev, struct weston_input_device *input_b } void -evdev_disable_udev_monitor(struct weston_input_device *input_base) +evdev_disable_udev_monitor(struct weston_seat *seat_base) { - struct evdev_input *input = (struct evdev_input *) input_base; + struct evdev_seat *seat = (struct evdev_seat *) seat_base; - if (!input->udev_monitor) + if (!seat->udev_monitor) return; - udev_monitor_unref(input->udev_monitor); - input->udev_monitor = NULL; - wl_event_source_remove(input->udev_monitor_source); - input->udev_monitor_source = NULL; + udev_monitor_unref(seat->udev_monitor); + seat->udev_monitor = NULL; + wl_event_source_remove(seat->udev_monitor_source); + seat->udev_monitor_source = NULL; } void evdev_input_create(struct weston_compositor *c, struct udev *udev, - const char *seat) + const char *seat_id) { - struct evdev_input *input; + struct evdev_seat *seat; - input = malloc(sizeof *input); - if (input == NULL) + seat = malloc(sizeof *seat); + if (seat == NULL) return; - memset(input, 0, sizeof *input); - weston_input_device_init(&input->base, c); + memset(seat, 0, sizeof *seat); + weston_seat_init(&seat->base, c); - wl_list_init(&input->devices_list); - input->seat_id = strdup(seat); - if (!evdev_enable_udev_monitor(udev, &input->base)) { - free(input->seat_id); - free(input); + wl_list_init(&seat->devices_list); + seat->seat_id = strdup(seat_id); + if (!evdev_enable_udev_monitor(udev, &seat->base)) { + free(seat->seat_id); + free(seat); return; } - evdev_add_devices(udev, &input->base); + evdev_add_devices(udev, &seat->base); - c->input_device = &input->base.input_device; + c->seat = &seat->base; } void -evdev_remove_devices(struct weston_input_device *input_base) +evdev_remove_devices(struct weston_seat *seat_base) { - struct evdev_input *input = (struct evdev_input *) input_base; + struct evdev_seat *seat = (struct evdev_seat *) seat_base; struct evdev_input_device *device, *next; - wl_list_for_each_safe(device, next, &input->devices_list, link) + wl_list_for_each_safe(device, next, &seat->devices_list, link) device_removed(device); - notify_keyboard_focus(&input->base.input_device, NULL); + notify_keyboard_focus(&seat->base.seat, NULL); } void -evdev_input_destroy(struct weston_input_device *input_base) +evdev_input_destroy(struct weston_seat *seat_base) { - struct evdev_input *input = (struct evdev_input *) input_base; + struct evdev_seat *seat = (struct evdev_seat *) seat_base; - evdev_remove_devices(input_base); - evdev_disable_udev_monitor(&input->base); + evdev_remove_devices(seat_base); + evdev_disable_udev_monitor(&seat->base); - wl_list_remove(&input->base.link); - free(input->seat_id); - free(input); + wl_list_remove(&seat->base.link); + free(seat->seat_id); + free(seat); } diff --git a/src/evdev.h b/src/evdev.h index b05c855c..8e3214dd 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -23,21 +23,20 @@ #include void -evdev_add_devices(struct udev *udev, struct weston_input_device - *input_base); +evdev_add_devices(struct udev *udev, struct weston_seat *seat_base); void -evdev_remove_devices(struct weston_input_device *input_base); +evdev_remove_devices(struct weston_seat *seat_base); void evdev_input_create(struct weston_compositor *c, struct udev *udev, const char *seat); void -evdev_input_destroy(struct weston_input_device *input_base); +evdev_input_destroy(struct weston_seat *seat); int -evdev_enable_udev_monitor(struct udev *udev, struct weston_input_device *input_base); +evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base); void -evdev_disable_udev_monitor(struct weston_input_device *input_base); +evdev_disable_udev_monitor(struct weston_seat *seat_base); From 812e1e2bdc5cfd4daf49ca739e7222563cbe6ac0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 17 May 2012 12:18:16 +0200 Subject: [PATCH 069/162] evdev: Add event process dispatching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By setting an 'evdev_dispatch' struct in 'evdev_input_device' during device configuration the 'process' function in the associated interface will be called with received input events. If none is set, a fallback handler will be set instead that handle generic input functionality. Signed-off-by: Jonas Ådahl --- src/evdev-private.h | 103 ++++++++++++++++++++++++++++++++++ src/evdev.c | 131 +++++++++++++++++++++----------------------- 2 files changed, 166 insertions(+), 68 deletions(-) create mode 100644 src/evdev-private.h diff --git a/src/evdev-private.h b/src/evdev-private.h new file mode 100644 index 00000000..dd724306 --- /dev/null +++ b/src/evdev-private.h @@ -0,0 +1,103 @@ +/* + * Copyright © 2012 Intel Corporation + * + * 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. + */ + +#ifndef EVDEV_PRIVATE_H +#define EVDEV_PRIVATE_H + +#include +#include + +struct evdev_seat { + struct weston_seat base; + struct wl_list devices_list; + struct udev_monitor *udev_monitor; + struct wl_event_source *udev_monitor_source; + char *seat_id; +}; + +#define MAX_SLOTS 16 + +struct evdev_input_device { + struct evdev_seat *master; + struct wl_list link; + struct wl_event_source *source; + struct weston_output *output; + struct evdev_dispatch *dispatch; + char *devnode; + int fd; + struct { + int min_x, max_x, min_y, max_y; + int old_x, old_y, reset_x, reset_y; + int32_t x, y; + } abs; + + struct { + int slot; + int32_t x[MAX_SLOTS]; + int32_t y[MAX_SLOTS]; + } mt; + struct mtdev *mtdev; + + struct { + wl_fixed_t dx, dy; + } rel; + + int type; /* event type flags */ + + int is_touchpad, is_mt; +}; + +/* event type flags */ +#define EVDEV_ABSOLUTE_MOTION (1 << 0) +#define EVDEV_ABSOLUTE_MT_DOWN (1 << 1) +#define EVDEV_ABSOLUTE_MT_MOTION (1 << 2) +#define EVDEV_ABSOLUTE_MT_UP (1 << 3) +#define EVDEV_RELATIVE_MOTION (1 << 4) + +/* 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(bit)) & 1) +/* end copied */ + +struct evdev_dispatch; + +struct evdev_dispatch_interface { + /* Process an evdev input event. */ + void (*process)(struct evdev_dispatch *dispatch, + struct evdev_input_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; +}; + +#endif /* EVDEV_PRIVATE_H */ diff --git a/src/evdev.c b/src/evdev.c index 26002b42..d020187d 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -30,54 +30,9 @@ #include "compositor.h" #include "evdev.h" +#include "evdev-private.h" #include "launcher-util.h" -struct evdev_seat { - struct weston_seat base; - struct wl_list devices_list; - struct udev_monitor *udev_monitor; - struct wl_event_source *udev_monitor_source; - char *seat_id; -}; - -#define MAX_SLOTS 16 - -struct evdev_input_device { - struct evdev_seat *master; - struct wl_list link; - struct wl_event_source *source; - struct weston_output *output; - char *devnode; - int fd; - struct { - int min_x, max_x, min_y, max_y; - int old_x, old_y, reset_x, reset_y; - int32_t x, y; - } abs; - - struct { - int slot; - int32_t x[MAX_SLOTS]; - int32_t y[MAX_SLOTS]; - } mt; - struct mtdev *mtdev; - - struct { - wl_fixed_t dx, dy; - } rel; - - int type; /* event type flags */ - - int is_touchpad, is_mt; -}; - -/* event type flags */ -#define EVDEV_ABSOLUTE_MOTION (1 << 0) -#define EVDEV_ABSOLUTE_MT_DOWN (1 << 1) -#define EVDEV_ABSOLUTE_MT_MOTION (1 << 2) -#define EVDEV_ABSOLUTE_MT_UP (1 << 3) -#define EVDEV_RELATIVE_MOTION (1 << 4) - static inline void evdev_process_key(struct evdev_input_device *device, struct input_event *e, int time) @@ -340,10 +295,53 @@ evdev_flush_motion(struct evdev_input_device *device, uint32_t time) } } +static void +fallback_process(struct evdev_dispatch *dispatch, + struct evdev_input_device *device, + struct input_event *event, + uint32_t time) +{ + switch (event->type) { + case EV_REL: + evdev_process_relative(device, event, time); + break; + case EV_ABS: + evdev_process_absolute(device, event); + break; + case EV_KEY: + evdev_process_key(device, event, time); + break; + } +} + +static void +fallback_destroy(struct evdev_dispatch *dispatch) +{ + free(dispatch); +} + +struct evdev_dispatch_interface fallback_interface = { + fallback_process, + fallback_destroy +}; + +static struct evdev_dispatch * +fallback_dispatch_create(void) +{ + struct evdev_dispatch *dispatch = malloc(sizeof *dispatch); + if (dispatch == NULL) + return NULL; + + dispatch->interface = &fallback_interface; + + return dispatch; +} + static void evdev_process_events(struct evdev_input_device *device, struct input_event *ev, int count) { + struct evdev_dispatch *dispatch = device->dispatch; struct input_event *e, *end; uint32_t time = 0; @@ -359,17 +357,8 @@ evdev_process_events(struct evdev_input_device *device, * events and send as a bunch */ if (!is_motion_event(e)) evdev_flush_motion(device, time); - switch (e->type) { - case EV_REL: - evdev_process_relative(device, e, time); - break; - case EV_ABS: - evdev_process_absolute(device, e); - break; - case EV_KEY: - evdev_process_key(device, e, time); - break; - } + + dispatch->interface->process(dispatch, device, e, time); } evdev_flush_motion(device, time); @@ -410,16 +399,6 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) return 1; } -/* 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(bit)) & 1) -/* end copied */ - static int evdev_configure_device(struct evdev_input_device *device) { @@ -494,6 +473,7 @@ evdev_input_device_create(struct evdev_seat *master, device->mt.slot = -1; device->rel.dx = 0; device->rel.dy = 0; + device->dispatch = NULL; /* Use non-blocking mode so that we can loop on read on * evdev_input_device_data() until all events on the fd are @@ -505,6 +485,13 @@ evdev_input_device_create(struct evdev_seat *master, if (evdev_configure_device(device) == -1) goto err1; + /* If the dispatch was not set up use the fallback. */ + if (device->dispatch == NULL) + device->dispatch = fallback_dispatch_create(); + if (device->dispatch == NULL) + goto err1; + + if (device->is_mt) { device->mtdev = mtdev_new_open(device->fd); if (!device->mtdev) @@ -515,12 +502,14 @@ evdev_input_device_create(struct evdev_seat *master, WL_EVENT_READABLE, evdev_input_device_data, device); if (device->source == NULL) - goto err1; + goto err2; wl_list_insert(master->devices_list.prev, &device->link); return device; +err2: + device->dispatch->interface->destroy(device->dispatch); err1: close(device->fd); err0: @@ -553,6 +542,12 @@ device_added(struct udev_device *udev_device, struct evdev_seat *master) static void device_removed(struct evdev_input_device *device) { + struct evdev_dispatch *dispatch; + + dispatch = device->dispatch; + if (dispatch) + dispatch->interface->destroy(dispatch); + wl_event_source_remove(device->source); wl_list_remove(&device->link); if (device->mtdev) From bb25b2ad297891430606c367bfabc5a032f0359d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 17 May 2012 12:18:17 +0200 Subject: [PATCH 070/162] evdev: Improve touchpad support and add motion filters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Touchpad related code has been rewritten and moved to its own file accessed by evdev via the dispatch interface. The various functionality implemented are anti-jitter (don't jumping around), smoother motions, touch detection, pointer acceleration and some more. Pointer acceleration is implemented as one generic part, and one touch specific part (a profile). Some ideas and magic numbers comes from xserver and xf86-input-synaptics. Signed-off-by: Jonas Ådahl --- src/evdev-private.h | 6 +- src/evdev-touchpad.c | 537 +++++++++++++++++++++++++++++++++++++++++++ src/evdev.c | 79 +------ src/filter.c | 337 +++++++++++++++++++++++++++ src/filter.h | 65 ++++++ 5 files changed, 948 insertions(+), 76 deletions(-) create mode 100644 src/evdev-touchpad.c create mode 100644 src/filter.c create mode 100644 src/filter.h diff --git a/src/evdev-private.h b/src/evdev-private.h index dd724306..c11c9b68 100644 --- a/src/evdev-private.h +++ b/src/evdev-private.h @@ -46,7 +46,6 @@ struct evdev_input_device { int fd; struct { int min_x, max_x, min_y, max_y; - int old_x, old_y, reset_x, reset_y; int32_t x, y; } abs; @@ -63,7 +62,7 @@ struct evdev_input_device { int type; /* event type flags */ - int is_touchpad, is_mt; + int is_mt; }; /* event type flags */ @@ -100,4 +99,7 @@ struct evdev_dispatch { struct evdev_dispatch_interface *interface; }; +struct evdev_dispatch * +evdev_touchpad_create(struct evdev_input_device *device); + #endif /* EVDEV_PRIVATE_H */ diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c new file mode 100644 index 00000000..dd7ab1c9 --- /dev/null +++ b/src/evdev-touchpad.c @@ -0,0 +1,537 @@ +/* + * 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 +#include +#include +#include +#include + +#include "filter.h" +#include "evdev-private.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 + +enum touchpad_model { + TOUCHPAD_MODEL_UNKNOWN = 0, + TOUCHPAD_MODEL_SYNAPTICS, + TOUCHPAD_MODEL_ALPS, + TOUCHPAD_MODEL_APPLETOUCH, + TOUCHPAD_MODEL_ELANTECH +}; + +#define TOUCHPAD_EVENT_NONE 0 +#define TOUCHPAD_EVENT_ABSOLUTE_ANY (1 << 0) +#define TOUCHPAD_EVENT_ABSOLUTE_X (1 << 1) +#define TOUCHPAD_EVENT_ABSOLUTE_Y (1 << 2) +#define 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, + TOUCHPAD_STATE_PRESS +}; + +#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) +}; + +struct touchpad_dispatch { + struct evdev_dispatch base; + struct evdev_input_device *device; + + enum touchpad_model model; + enum touchpad_state 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 { + int32_t x; + int32_t y; + } hw_abs; + + int has_pressure; + struct { + int32_t touch_low; + int32_t touch_high; + int32_t press; + } 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 wl_list motion_filters; +}; + +static enum touchpad_model +get_touchpad_model(struct evdev_input_device *device) +{ + struct input_id id; + unsigned int i; + + if (ioctl(device->fd, EVIOCGID, &id) < 0) + return TOUCHPAD_MODEL_UNKNOWN; + + for (i = 0; i < sizeof 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); + } + + touchpad->pressure.press = pressure_min + range; +} + +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 void +configure_touchpad(struct touchpad_dispatch *touchpad, + struct evdev_input_device *device) +{ + struct weston_motion_filter *accel; + + struct input_absinfo absinfo; + unsigned long abs_bits[NBITS(ABS_MAX)]; + + double width; + double height; + double diagonal; + + /* Detect model */ + touchpad->model = get_touchpad_model(device); + + /* 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->constant_accel_factor = + DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal; + + touchpad->min_accel_factor = DEFAULT_MIN_ACCEL_FACTOR; + touchpad->max_accel_factor = DEFAULT_MAX_ACCEL_FACTOR; + + 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); + wl_list_insert(&touchpad->motion_filters, &accel->link); + + /* 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; +} + +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_filter *filter; + struct weston_motion_params motion; + + motion.dx = *dx; + motion.dy = *dy; + + wl_list_for_each(filter, &touchpad->motion_filters, link) + weston_filter_dispatch(filter, &motion, touchpad, time); + + *dx = motion.dx; + *dy = motion.dy; +} + +static void +touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) +{ + int motion_index; + int center_x, center_y; + double dx, dy; + + 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; + + 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); + + touchpad->device->rel.dx = wl_fixed_from_double(dx); + touchpad->device->rel.dy = wl_fixed_from_double(dy); + touchpad->device->type |= EVDEV_RELATIVE_MOTION; + } +} + +static inline void +process_absolute(struct touchpad_dispatch *touchpad, + struct evdev_input_device *device, + struct input_event *e) +{ + switch (e->code) { + case ABS_PRESSURE: + if (e->value > touchpad->pressure.press) + touchpad->state = TOUCHPAD_STATE_PRESS; + else if (e->value > touchpad->pressure.touch_high) + touchpad->state = TOUCHPAD_STATE_TOUCH; + else if (e->value < touchpad->pressure.touch_low) { + if (touchpad->state > TOUCHPAD_STATE_NONE) + touchpad->reset = 1; + + touchpad->state = TOUCHPAD_STATE_NONE; + } + + 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_input_device *device, + struct input_event *e, + uint32_t time) +{ + switch (e->code) { + case BTN_TOUCH: + if (!touchpad->has_pressure) { + if (!e->value) { + touchpad->state = TOUCHPAD_STATE_NONE; + touchpad->reset = 1; + } else { + touchpad->state = + e->value ? + TOUCHPAD_STATE_TOUCH : + TOUCHPAD_STATE_NONE; + } + } + 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: + notify_button(&device->master->base.seat, + time, e->code, e->value); + 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: + touchpad->finger_state = + ~TOUCHPAD_FINGERS_ONE | e->value ? + TOUCHPAD_FINGERS_ONE : 0; + break; + case BTN_TOOL_DOUBLETAP: + touchpad->finger_state = + ~TOUCHPAD_FINGERS_TWO | e->value ? + TOUCHPAD_FINGERS_TWO : 0; + break; + case BTN_TOOL_TRIPLETAP: + touchpad->finger_state = + ~TOUCHPAD_FINGERS_THREE | e->value ? + TOUCHPAD_FINGERS_THREE : 0; + break; + } +} + +static void +touchpad_process(struct evdev_dispatch *dispatch, + struct evdev_input_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; + struct weston_motion_filter *filter; + struct weston_motion_filter *next; + + wl_list_for_each_safe(filter, next, &touchpad->motion_filters, link) + filter->interface->destroy(filter); + + free(dispatch); +} + +struct evdev_dispatch_interface touchpad_interface = { + touchpad_process, + touchpad_destroy +}; + +struct evdev_dispatch * +evdev_touchpad_create(struct evdev_input_device *device) +{ + struct touchpad_dispatch *touchpad; + + touchpad = malloc(sizeof *touchpad); + if (touchpad == NULL) + return NULL; + + touchpad->base.interface = &touchpad_interface; + + touchpad->device = device; + wl_list_init(&touchpad->motion_filters); + + configure_touchpad(touchpad, device); + + return &touchpad->base; +} diff --git a/src/evdev.c b/src/evdev.c index d020187d..73b012b3 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -41,32 +41,6 @@ evdev_process_key(struct evdev_input_device *device, return; switch (e->code) { - case BTN_TOOL_PEN: - case BTN_TOOL_RUBBER: - case BTN_TOOL_BRUSH: - case BTN_TOOL_PENCIL: - case BTN_TOOL_AIRBRUSH: - case BTN_TOOL_FINGER: - case BTN_TOOL_MOUSE: - case BTN_TOOL_LENS: - if (device->is_touchpad) - { - device->abs.reset_x = 1; - device->abs.reset_y = 1; - } - break; - case BTN_TOUCH: - /* Multitouch touchscreen devices might not send individually - * button events each time a new finger is down. So we don't - * send notification for such devices and we solve the button - * case emulating on compositor side. */ - if (device->is_mt) - break; - - /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as - * BTN_LEFT */ - e->code = BTN_LEFT; - /* Intentional fallthrough! */ case BTN_LEFT: case BTN_RIGHT: case BTN_MIDDLE: @@ -145,50 +119,9 @@ evdev_process_absolute_motion(struct evdev_input_device *device, } } -static inline void -evdev_process_absolute_motion_touchpad(struct evdev_input_device *device, - struct input_event *e) -{ - /* FIXME: Make this configurable somehow. */ - const int touchpad_speed = 700; - int dx, dy; - - switch (e->code) { - case ABS_X: - e->value -= device->abs.min_x; - if (device->abs.reset_x) - device->abs.reset_x = 0; - else { - dx = - (e->value - device->abs.old_x) * - touchpad_speed / - (device->abs.max_x - device->abs.min_x); - device->rel.dx = wl_fixed_from_int(dx); - } - device->abs.old_x = e->value; - device->type |= EVDEV_RELATIVE_MOTION; - break; - case ABS_Y: - e->value -= device->abs.min_y; - if (device->abs.reset_y) - device->abs.reset_y = 0; - else { - dy = - (e->value - device->abs.old_y) * - touchpad_speed / - /* maybe use x size here to have the same scale? */ - (device->abs.max_y - device->abs.min_y); - device->rel.dy = wl_fixed_from_int(dy); - } - device->abs.old_y = e->value; - device->type |= EVDEV_RELATIVE_MOTION; - break; - } -} - static inline void evdev_process_relative(struct evdev_input_device *device, - struct input_event *e, uint32_t time) + struct input_event *e, uint32_t time) { switch (e->code) { case REL_X: @@ -216,9 +149,7 @@ static inline void evdev_process_absolute(struct evdev_input_device *device, struct input_event *e) { - if (device->is_touchpad) { - evdev_process_absolute_motion_touchpad(device, e); - } else if (device->is_mt) { + if (device->is_mt) { evdev_process_touch(device, e); } else { evdev_process_absolute_motion(device, e); @@ -437,8 +368,9 @@ evdev_configure_device(struct evdev_input_device *device) 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)) - device->is_touchpad = 1; + !TEST_BIT(key_bits, BTN_TOOL_PEN) && + has_abs) + device->dispatch = evdev_touchpad_create(device); } /* This rule tries to catch accelerometer devices and opt out. We may @@ -466,7 +398,6 @@ evdev_input_device_create(struct evdev_seat *master, container_of(ec->output_list.next, struct weston_output, link); device->master = master; - device->is_touchpad = 0; device->is_mt = 0; device->mtdev = NULL; device->devnode = strdup(path); diff --git a/src/filter.c b/src/filter.c new file mode 100644 index 00000000..72ef9be9 --- /dev/null +++ b/src/filter.c @@ -0,0 +1,337 @@ +/* + * 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 +#include +#include +#include +#include + +#include + +#include "compositor.h" +#include "filter.h" + +void +weston_filter_dispatch(struct weston_motion_filter *filter, + struct weston_motion_params *motion, + void *data, uint32_t time) +{ + filter->interface->filter(filter, motion, data, time); +} + +/* + * Pointer acceleration filter + */ + +#define MAX_VELOCITY_DIFF 1.0 +#define MOTION_TIMEOUT 300 /* (ms) */ +#define NUM_POINTER_TRACKERS 16 + +struct pointer_tracker { + double dx; + double dy; + uint32_t time; + int dir; +}; + +struct pointer_accelerator; +struct pointer_accelerator { + struct weston_motion_filter base; + + accel_profile_func_t profile; + + double velocity; + double last_velocity; + int last_dx; + int last_dy; + + struct pointer_tracker *trackers; + int cur_tracker; +}; + +enum directions { + N = 1 << 0, + NE = 1 << 1, + E = 1 << 2, + SE = 1 << 3, + S = 1 << 4, + SW = 1 << 5, + W = 1 << 6, + NW = 1 << 7, + UNDEFINED_DIRECTION = 0xff +}; + +static int +get_direction(int dx, int dy) +{ + int dir = UNDEFINED_DIRECTION; + int d1, d2; + double r; + + if (abs(dx) < 2 && abs(dy) < 2) { + if (dx > 0 && dy > 0) + dir = S | SE | E; + else if (dx > 0 && dy < 0) + dir = N | NE | E; + else if (dx < 0 && dy > 0) + dir = S | SW | W; + else if (dx < 0 && dy < 0) + dir = N | NW | W; + else if (dx > 0) + dir = NW | W | SW; + else if (dx < 0) + dir = NE | E | SE; + else if (dy > 0) + dir = SE | S | SW; + else if (dy < 0) + dir = NE | N | NW; + } + else { + /* Calculate r within the interval [0 to 8) + * + * r = [0 .. 2π] where 0 is North + * d_f = r / 2π ([0 .. 1)) + * d_8 = 8 * d_f + */ + r = atan2(dy, dx); + r = fmod(r + 2.5*M_PI, 2*M_PI); + r *= 4*M_1_PI; + + /* Mark one or two close enough octants */ + d1 = (int)(r + 0.9) % 8; + d2 = (int)(r + 0.1) % 8; + + dir = (1 << d1) | (1 << d2); + } + + return dir; +} + +static void +feed_trackers(struct pointer_accelerator *accel, + double dx, double dy, + uint32_t time) +{ + int i, current; + struct pointer_tracker *trackers = accel->trackers; + + for (i = 0; i < NUM_POINTER_TRACKERS; i++) { + trackers[i].dx += dx; + trackers[i].dy += dy; + } + + current = (accel->cur_tracker + 1) % NUM_POINTER_TRACKERS; + accel->cur_tracker = current; + + trackers[current].dx = 0.0; + trackers[current].dy = 0.0; + trackers[current].time = time; + trackers[current].dir = get_direction(dx, dy); +} + +static struct pointer_tracker * +tracker_by_offset(struct pointer_accelerator *accel, unsigned int offset) +{ + unsigned int index = + (accel->cur_tracker + NUM_POINTER_TRACKERS - offset) + % NUM_POINTER_TRACKERS; + return &accel->trackers[index]; +} + +static double +calculate_tracker_velocity(struct pointer_tracker *tracker, uint32_t time) +{ + int dx; + int dy; + double distance; + + dx = tracker->dx; + dy = tracker->dy; + distance = sqrt(dx*dx + dy*dy); + return distance / (double)(time - tracker->time); +} + +static double +calculate_velocity(struct pointer_accelerator *accel, uint32_t time) +{ + struct pointer_tracker *tracker; + double velocity; + double result = 0.0; + double initial_velocity; + double velocity_diff; + unsigned int offset; + + unsigned int dir = tracker_by_offset(accel, 0)->dir; + + /* Find first velocity */ + for (offset = 1; offset < NUM_POINTER_TRACKERS; offset++) { + tracker = tracker_by_offset(accel, offset); + + if (time <= tracker->time) + continue; + + result = initial_velocity = + calculate_tracker_velocity(tracker, time); + if (initial_velocity > 0.0) + break; + } + + /* Find least recent vector within a timelimit, maximum velocity diff + * and direction threshold. */ + for (; offset < NUM_POINTER_TRACKERS; offset++) { + tracker = tracker_by_offset(accel, offset); + + /* Stop if too far away in time */ + if (time - tracker->time > MOTION_TIMEOUT || + tracker->time > time) + break; + + /* Stop if direction changed */ + dir &= tracker->dir; + if (dir == 0) + break; + + velocity = calculate_tracker_velocity(tracker, time); + + /* Stop if velocity differs too much from initial */ + velocity_diff = fabs(initial_velocity - velocity); + if (velocity_diff > MAX_VELOCITY_DIFF) + break; + + result = velocity; + } + + return result; +} + +static double +acceleration_profile(struct pointer_accelerator *accel, + void *data, double velocity, uint32_t time) +{ + return accel->profile(&accel->base, data, velocity, time); +} + +static double +calculate_acceleration(struct pointer_accelerator *accel, + void *data, double velocity, uint32_t time) +{ + double factor; + + /* Use Simpson's rule to calculate the avarage acceleration between + * the previous motion and the most recent. */ + factor = acceleration_profile(accel, data, velocity, time); + factor += acceleration_profile(accel, data, accel->last_velocity, time); + factor += 4.0 * + acceleration_profile(accel, data, + (accel->last_velocity + velocity) / 2, + time); + + factor = factor / 6.0; + + return factor; +} + +static double +soften_delta(double last_delta, double delta) +{ + if (delta < -1.0 || delta > 1.0) { + if (delta > last_delta) + return delta - 0.5; + else if (delta < last_delta) + return delta + 0.5; + } + + return delta; +} + +static void +apply_softening(struct pointer_accelerator *accel, + struct weston_motion_params *motion) +{ + motion->dx = soften_delta(accel->last_dx, motion->dx); + motion->dy = soften_delta(accel->last_dy, motion->dy); +} + +static void +accelerator_filter(struct weston_motion_filter *filter, + struct weston_motion_params *motion, + void *data, uint32_t time) +{ + struct pointer_accelerator *accel = + (struct pointer_accelerator *) filter; + double velocity; + double accel_value; + + feed_trackers(accel, motion->dx, motion->dy, time); + velocity = calculate_velocity(accel, time); + accel_value = calculate_acceleration(accel, data, velocity, time); + + motion->dx = accel_value * motion->dx; + motion->dy = accel_value * motion->dy; + + apply_softening(accel, motion); + + accel->last_dx = motion->dx; + accel->last_dy = motion->dy; + + accel->last_velocity = velocity; +} + +static void +accelerator_destroy(struct weston_motion_filter *filter) +{ + struct pointer_accelerator *accel = + (struct pointer_accelerator *) filter; + + free(accel->trackers); + free(accel); +} + +struct weston_motion_filter_interface accelerator_interface = { + accelerator_filter, + accelerator_destroy +}; + +struct weston_motion_filter * +create_pointer_accelator_filter(accel_profile_func_t profile) +{ + struct pointer_accelerator *filter; + + filter = malloc(sizeof *filter); + if (filter == NULL) + return NULL; + + filter->base.interface = &accelerator_interface; + wl_list_init(&filter->base.link); + + filter->profile = profile; + filter->last_velocity = 0.0; + filter->last_dx = 0; + filter->last_dy = 0; + + filter->trackers = + calloc(NUM_POINTER_TRACKERS, sizeof *filter->trackers); + filter->cur_tracker = 0; + + return &filter->base; +} diff --git a/src/filter.h b/src/filter.h new file mode 100644 index 00000000..ff8e579f --- /dev/null +++ b/src/filter.h @@ -0,0 +1,65 @@ +/* + * 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. + */ + +#ifndef _FILTER_H_ +#define _FILTER_H_ + +#include + +#include "compositor.h" + +struct weston_motion_params { + double dx, dy; +}; + +struct weston_motion_filter; + +WL_EXPORT void +weston_filter_dispatch(struct weston_motion_filter *filter, + struct weston_motion_params *motion, + void *data, uint32_t time); + + +struct weston_motion_filter_interface { + void (*filter)(struct weston_motion_filter *filter, + struct weston_motion_params *motion, + void *data, uint32_t time); + void (*destroy)(struct weston_motion_filter *filter); +}; + +struct weston_motion_filter { + struct weston_motion_filter_interface *interface; + struct wl_list link; +}; + +WL_EXPORT struct weston_motion_filter * +create_linear_acceleration_filter(double speed); + +typedef double (*accel_profile_func_t)(struct weston_motion_filter *filter, + void *data, + double velocity, + uint32_t time); + +WL_EXPORT struct weston_motion_filter * +create_pointer_accelator_filter(accel_profile_func_t filter); + +#endif // _FILTER_H_ From 4594e9904bad64293fcd9c9a8ff93aa3a0d4ca84 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 30 May 2012 16:31:46 +0100 Subject: [PATCH 071/162] evdev: Convert device type to an enum Rather than using #defines. Signed-off-by: Daniel Stone --- src/evdev-private.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/evdev-private.h b/src/evdev-private.h index c11c9b68..43143f25 100644 --- a/src/evdev-private.h +++ b/src/evdev-private.h @@ -36,6 +36,14 @@ struct evdev_seat { #define MAX_SLOTS 16 +enum evdev_event_type { + EVDEV_ABSOLUTE_MOTION = (1 << 0), + EVDEV_ABSOLUTE_MT_DOWN = (1 << 1), + EVDEV_ABSOLUTE_MT_MOTION = (1 << 2), + EVDEV_ABSOLUTE_MT_UP = (1 << 3), + EVDEV_RELATIVE_MOTION = (1 << 4), +}; + struct evdev_input_device { struct evdev_seat *master; struct wl_list link; @@ -60,18 +68,11 @@ struct evdev_input_device { wl_fixed_t dx, dy; } rel; - int type; /* event type flags */ + enum evdev_event_type type; int is_mt; }; -/* event type flags */ -#define EVDEV_ABSOLUTE_MOTION (1 << 0) -#define EVDEV_ABSOLUTE_MT_DOWN (1 << 1) -#define EVDEV_ABSOLUTE_MT_MOTION (1 << 2) -#define EVDEV_ABSOLUTE_MT_UP (1 << 3) -#define EVDEV_RELATIVE_MOTION (1 << 4) - /* copied from udev/extras/input_id/input_id.c */ /* we must use this kernel-compatible implementation */ #define BITS_PER_LONG (sizeof(unsigned long) * 8) From b48e8a51cb9d1fd116e01ecdb0c2534438f9f792 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 30 May 2012 16:31:47 +0100 Subject: [PATCH 072/162] Rename evdev_input_device::type to pending_events Since that's what it actually is, rather than a description of the device as such. Signed-off-by: Daniel Stone --- src/evdev-private.h | 2 +- src/evdev-touchpad.c | 2 +- src/evdev.c | 44 ++++++++++++++++++++++---------------------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/evdev-private.h b/src/evdev-private.h index 43143f25..e4bcf138 100644 --- a/src/evdev-private.h +++ b/src/evdev-private.h @@ -68,7 +68,7 @@ struct evdev_input_device { wl_fixed_t dx, dy; } rel; - enum evdev_event_type type; + enum evdev_event_type pending_events; int is_mt; }; diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index dd7ab1c9..f6580810 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -375,7 +375,7 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) touchpad->device->rel.dx = wl_fixed_from_double(dx); touchpad->device->rel.dy = wl_fixed_from_double(dy); - touchpad->device->type |= EVDEV_RELATIVE_MOTION; + touchpad->device->pending_events |= EVDEV_RELATIVE_MOTION; } } diff --git a/src/evdev.c b/src/evdev.c index 73b012b3..6adf10ab 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -73,23 +73,23 @@ evdev_process_touch(struct evdev_input_device *device, break; case ABS_MT_TRACKING_ID: if (e->value >= 0) - device->type |= EVDEV_ABSOLUTE_MT_DOWN; + device->pending_events |= EVDEV_ABSOLUTE_MT_DOWN; else - device->type |= EVDEV_ABSOLUTE_MT_UP; + device->pending_events |= EVDEV_ABSOLUTE_MT_UP; break; case ABS_MT_POSITION_X: device->mt.x[device->mt.slot] = (e->value - device->abs.min_x) * screen_width / (device->abs.max_x - device->abs.min_x) + device->output->x; - device->type |= EVDEV_ABSOLUTE_MT_MOTION; + device->pending_events |= EVDEV_ABSOLUTE_MT_MOTION; break; case ABS_MT_POSITION_Y: device->mt.y[device->mt.slot] = (e->value - device->abs.min_y) * screen_height / (device->abs.max_y - device->abs.min_y) + device->output->y; - device->type |= EVDEV_ABSOLUTE_MT_MOTION; + device->pending_events |= EVDEV_ABSOLUTE_MT_MOTION; break; } } @@ -107,14 +107,14 @@ evdev_process_absolute_motion(struct evdev_input_device *device, (e->value - device->abs.min_x) * screen_width / (device->abs.max_x - device->abs.min_x) + device->output->x; - device->type |= EVDEV_ABSOLUTE_MOTION; + device->pending_events |= 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) + device->output->y; - device->type |= EVDEV_ABSOLUTE_MOTION; + device->pending_events |= EVDEV_ABSOLUTE_MOTION; break; } } @@ -126,11 +126,11 @@ evdev_process_relative(struct evdev_input_device *device, switch (e->code) { case REL_X: device->rel.dx += wl_fixed_from_int(e->value); - device->type |= EVDEV_RELATIVE_MOTION; + device->pending_events |= EVDEV_RELATIVE_MOTION; break; case REL_Y: device->rel.dy += wl_fixed_from_int(e->value); - device->type |= EVDEV_RELATIVE_MOTION; + device->pending_events |= EVDEV_RELATIVE_MOTION; break; case REL_WHEEL: notify_axis(&device->master->base.seat, @@ -184,45 +184,45 @@ evdev_flush_motion(struct evdev_input_device *device, uint32_t time) { struct weston_seat *master = &device->master->base; - if (!device->type) + if (!device->pending_events) return; - if (device->type & EVDEV_RELATIVE_MOTION) { + if (device->pending_events & EVDEV_RELATIVE_MOTION) { notify_motion(&master->seat, time, master->seat.pointer->x + device->rel.dx, master->seat.pointer->y + device->rel.dy); - device->type &= ~EVDEV_RELATIVE_MOTION; + device->pending_events &= ~EVDEV_RELATIVE_MOTION; device->rel.dx = 0; device->rel.dy = 0; } - if (device->type & EVDEV_ABSOLUTE_MT_DOWN) { + if (device->pending_events & EVDEV_ABSOLUTE_MT_DOWN) { notify_touch(&master->seat, time, device->mt.slot, wl_fixed_from_int(device->mt.x[device->mt.slot]), wl_fixed_from_int(device->mt.y[device->mt.slot]), WL_TOUCH_DOWN); - device->type &= ~EVDEV_ABSOLUTE_MT_DOWN; - device->type &= ~EVDEV_ABSOLUTE_MT_MOTION; + device->pending_events &= ~EVDEV_ABSOLUTE_MT_DOWN; + device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION; } - if (device->type & EVDEV_ABSOLUTE_MT_MOTION) { + if (device->pending_events & EVDEV_ABSOLUTE_MT_MOTION) { notify_touch(&master->seat, time, device->mt.slot, wl_fixed_from_int(device->mt.x[device->mt.slot]), wl_fixed_from_int(device->mt.y[device->mt.slot]), WL_TOUCH_MOTION); - device->type &= ~EVDEV_ABSOLUTE_MT_DOWN; - device->type &= ~EVDEV_ABSOLUTE_MT_MOTION; + device->pending_events &= ~EVDEV_ABSOLUTE_MT_DOWN; + device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION; } - if (device->type & EVDEV_ABSOLUTE_MT_UP) { + if (device->pending_events & EVDEV_ABSOLUTE_MT_UP) { notify_touch(&master->seat, time, device->mt.slot, 0, 0, WL_TOUCH_UP); - device->type &= ~EVDEV_ABSOLUTE_MT_UP; + device->pending_events &= ~EVDEV_ABSOLUTE_MT_UP; } - if (device->type & EVDEV_ABSOLUTE_MOTION) { + if (device->pending_events & EVDEV_ABSOLUTE_MOTION) { notify_motion(&master->seat, time, wl_fixed_from_int(device->abs.x), wl_fixed_from_int(device->abs.y)); - device->type &= ~EVDEV_ABSOLUTE_MOTION; + device->pending_events &= ~EVDEV_ABSOLUTE_MOTION; } } @@ -276,7 +276,7 @@ evdev_process_events(struct evdev_input_device *device, struct input_event *e, *end; uint32_t time = 0; - device->type = 0; + device->pending_events = 0; e = ev; end = e + count; From 63f2af557491b909825eb2e73f47b8dc6c12fc01 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 30 May 2012 16:31:48 +0100 Subject: [PATCH 073/162] evdev: Add device capabilities Does what it says on the box: lists whether or not the device supports key, absolute, relative or touch classes. Signed-off-by: Daniel Stone --- src/evdev-private.h | 9 +++++++++ src/evdev.c | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/evdev-private.h b/src/evdev-private.h index e4bcf138..7b56b542 100644 --- a/src/evdev-private.h +++ b/src/evdev-private.h @@ -44,6 +44,14 @@ enum evdev_event_type { EVDEV_RELATIVE_MOTION = (1 << 4), }; +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), +}; + struct evdev_input_device { struct evdev_seat *master; struct wl_list link; @@ -69,6 +77,7 @@ struct evdev_input_device { } rel; enum evdev_event_type pending_events; + enum evdev_device_capability caps; int is_mt; }; diff --git a/src/evdev.c b/src/evdev.c index 6adf10ab..a34aa43e 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -336,11 +336,14 @@ evdev_configure_device(struct evdev_input_device *device) 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)) { @@ -352,17 +355,26 @@ evdev_configure_device(struct evdev_input_device *device) 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; } if (TEST_BIT(abs_bits, ABS_MT_SLOT)) { device->is_mt = 1; device->mt.slot = 0; + device->caps |= EVDEV_TOUCH; } } + 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)), @@ -371,6 +383,20 @@ evdev_configure_device(struct evdev_input_device *device) !TEST_BIT(key_bits, BTN_TOOL_PEN) && has_abs) device->dispatch = evdev_touchpad_create(device); + 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; + } + } + for (i = BTN_MISC; i < KEY_OK; i++) { + if (TEST_BIT(key_bits, i)) { + device->caps |= EVDEV_BUTTON; + break; + } + } } /* This rule tries to catch accelerometer devices and opt out. We may From a6cd4965e992d6fc3f4526013fdfc07a01338fa0 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 30 May 2012 16:31:49 +0100 Subject: [PATCH 074/162] evdev: Add LED update hook Simply pushes the updated LEDs through to all keyboard attached to the seat. Signed-off-by: Daniel Stone --- src/evdev.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index a34aa43e..e73f343c 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -33,6 +33,35 @@ #include "evdev-private.h" #include "launcher-util.h" +static void +evdev_led_update(struct weston_seat *seat_base, enum weston_led 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 evdev_seat *seat = (struct evdev_seat *) seat_base; + struct evdev_input_device *device; + struct input_event ev[ARRAY_LENGTH(map)]; + unsigned int i; + + 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); + } + + wl_list_for_each(device, &seat->devices_list, link) { + if (device->caps & EVDEV_KEYBOARD) + write(device->fd, ev, sizeof *ev); + } +} + static inline void evdev_process_key(struct evdev_input_device *device, struct input_event *e, int time) @@ -691,6 +720,7 @@ evdev_input_create(struct weston_compositor *c, struct udev *udev, memset(seat, 0, sizeof *seat); weston_seat_init(&seat->base, c); + seat->base.led_update = evdev_led_update; wl_list_init(&seat->devices_list); seat->seat_id = strdup(seat_id); From 95b8738f31bef538457a2a64a1feb028d618babc Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 30 May 2012 16:31:51 +0100 Subject: [PATCH 075/162] Use enum wl_pointer_button_state instead of integer Instead of using a uint32_t for state everywhere (except on the wire, where that's still the call signature), use the new wl_pointer_button_state enum, and explicit comparisons. Signed-off-by: Daniel Stone --- src/evdev-touchpad.c | 4 +++- src/evdev.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index f6580810..d371a659 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -444,7 +444,9 @@ process_key(struct touchpad_dispatch *touchpad, case BTN_BACK: case BTN_TASK: notify_button(&device->master->base.seat, - time, e->code, e->value); + time, e->code, + e->value ? WL_POINTER_BUTTON_STATE_PRESSED : + WL_POINTER_BUTTON_STATE_RELEASED); break; case BTN_TOOL_PEN: case BTN_TOOL_RUBBER: diff --git a/src/evdev.c b/src/evdev.c index e73f343c..a7162fcc 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -79,7 +79,9 @@ evdev_process_key(struct evdev_input_device *device, case BTN_BACK: case BTN_TASK: notify_button(&device->master->base.seat, - time, e->code, e->value); + time, e->code, + e->value ? WL_POINTER_BUTTON_STATE_PRESSED : + WL_POINTER_BUTTON_STATE_RELEASED); break; default: From 5e29a127883f7ddc946a81d514e53741317fec3d Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 30 May 2012 16:31:52 +0100 Subject: [PATCH 076/162] Use enum wl_keyboard_key_state instead of integer Instead of using a uint32_t for state everywhere (except on the wire, where that's still the call signature), use the new wl_keyboard_key_state enum, and explicit comparisons. Signed-off-by: Daniel Stone --- src/evdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index a7162fcc..0a5ec91f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -86,7 +86,9 @@ evdev_process_key(struct evdev_input_device *device, default: notify_key(&device->master->base.seat, - time, e->code, e->value); + time, e->code, + e->value ? WL_KEYBOARD_KEY_STATE_PRESSED : + WL_KEYBOARD_KEY_STATE_RELEASED); break; } } From 36dbbb086c9a0f4cc0fa105cd4e60c300a1c8d9e Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 30 May 2012 16:31:57 +0100 Subject: [PATCH 077/162] Convert notify_axis to wl_fixed_t In preparation for the rest of the axis code changing. Signed-off-by: Daniel Stone --- src/evdev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 0a5ec91f..a9c132c2 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -168,12 +168,14 @@ evdev_process_relative(struct evdev_input_device *device, case REL_WHEEL: notify_axis(&device->master->base.seat, time, - WL_POINTER_AXIS_VERTICAL_SCROLL, e->value); + WL_POINTER_AXIS_VERTICAL_SCROLL, + wl_fixed_from_int(e->value)); break; case REL_HWHEEL: notify_axis(&device->master->base.seat, time, - WL_POINTER_AXIS_HORIZONTAL_SCROLL, e->value); + WL_POINTER_AXIS_HORIZONTAL_SCROLL, + wl_fixed_from_int(e->value)); break; } } From 619215f6ce325a4f0a4de6cb63c7d640c36bc99c Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 30 May 2012 16:32:02 +0100 Subject: [PATCH 078/162] Split weston_seat_init up into pointer/keyboard/touch So we don't unnecessarily advertise interfaces the seat doesn't support. Signed-off-by: Daniel Stone --- src/evdev.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index a9c132c2..23faaa68 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -440,6 +440,14 @@ evdev_configure_device(struct evdev_input_device *device) if (has_abs && !has_key) return -1; + if ((device->caps & + (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | EVDEV_BUTTON))) + weston_seat_init_pointer(&device->master->base); + if ((device->caps & EVDEV_KEYBOARD)) + weston_seat_init_keyboard(&device->master->base); + if ((device->caps & EVDEV_TOUCH)) + weston_seat_init_touch(&device->master->base); + return 0; } From 37f83e26663a18d0bdd8fe0ac0e6a8ca0126f467 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 30 May 2012 16:32:06 +0100 Subject: [PATCH 079/162] Add keymap argument to weston_seat_init_keyboard This allows backends to generate their own keymaps and pass them in for use rather than always forcing a single global keymap, which is particularly useful for nested compositors. Signed-off-by: Daniel Stone --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 23faaa68..8439eda7 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -444,7 +444,7 @@ evdev_configure_device(struct evdev_input_device *device) (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | EVDEV_BUTTON))) weston_seat_init_pointer(&device->master->base); if ((device->caps & EVDEV_KEYBOARD)) - weston_seat_init_keyboard(&device->master->base); + weston_seat_init_keyboard(&device->master->base, NULL); if ((device->caps & EVDEV_TOUCH)) weston_seat_init_touch(&device->master->base); From 404488e8bd648710ba44442c6b165a4c70fd0c09 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Fri, 1 Jun 2012 12:13:59 +0100 Subject: [PATCH 080/162] Brown-paper bag fix for LED The O_RDWR change got lost in a rebase, and as Peter suggested as well, make sure to set EVDEV_KEYBOARD if the device has EV_LED. Signed-off-by: Daniel Stone --- src/evdev.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 8439eda7..23d22d7c 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -58,7 +58,7 @@ evdev_led_update(struct weston_seat *seat_base, enum weston_led leds) wl_list_for_each(device, &seat->devices_list, link) { if (device->caps & EVDEV_KEYBOARD) - write(device->fd, ev, sizeof *ev); + write(device->fd, ev, sizeof ev); } } @@ -433,6 +433,9 @@ evdev_configure_device(struct evdev_input_device *device) } } } + if (TEST_BIT(ev_bits, EV_LED)) { + device->caps |= EVDEV_KEYBOARD; + } /* This rule tries to catch accelerometer devices and opt out. We may * want to adjust the protocol later adding a proper event for dealing @@ -478,7 +481,7 @@ evdev_input_device_create(struct evdev_seat *master, /* Use non-blocking mode so that we can loop on read on * evdev_input_device_data() until all events on the fd are * read. mtdev_get() also expects this. */ - device->fd = weston_launcher_open(ec, path, O_RDONLY | O_NONBLOCK); + device->fd = weston_launcher_open(ec, path, O_RDWR | O_NONBLOCK); if (device->fd < 0) goto err0; From 07a21a261d32e8043709293265d3f772abf122ab Mon Sep 17 00:00:00 2001 From: Martin Minarik Date: Thu, 7 Jun 2012 18:01:59 +0200 Subject: [PATCH 081/162] Replace fprintf() by weston_log() --- src/evdev-touchpad.c | 1 - src/evdev.c | 12 ++++++------ src/filter.c | 1 - 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index d371a659..7e167d12 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -20,7 +20,6 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include #include #include diff --git a/src/evdev.c b/src/evdev.c index 23d22d7c..9660996f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -20,7 +20,6 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include #include #include #include @@ -32,6 +31,7 @@ #include "evdev.h" #include "evdev-private.h" #include "launcher-util.h" +#include "log.h" static void evdev_led_update(struct weston_seat *seat_base, enum weston_led leds) @@ -498,7 +498,7 @@ evdev_input_device_create(struct evdev_seat *master, if (device->is_mt) { device->mtdev = mtdev_new_open(device->fd); if (!device->mtdev) - fprintf(stderr, "mtdev failed to open for %s\n", path); + weston_log("mtdev failed to open for %s\n", path); } device->source = wl_event_loop_add_fd(ec->input_loop, device->fd, @@ -576,7 +576,7 @@ evdev_notify_keyboard_focus(struct evdev_seat *seat) ret = ioctl(device->fd, EVIOCGKEY(sizeof evdev_keys), evdev_keys); if (ret < 0) { - fprintf(stderr, "failed to get keys for device %s\n", + weston_log("failed to get keys for device %s\n", device->devnode); continue; } @@ -629,7 +629,7 @@ evdev_add_devices(struct udev *udev, struct weston_seat *seat_base) evdev_notify_keyboard_focus(seat); if (wl_list_empty(&seat->devices_list)) { - fprintf(stderr, + weston_log( "warning: no input devices on entering Weston. " "Possible causes:\n" "\t- no permissions to read /dev/input/event*\n" @@ -685,7 +685,7 @@ evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base) master->udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); if (!master->udev_monitor) { - fprintf(stderr, "udev: failed to create the udev monitor\n"); + weston_log("udev: failed to create the udev monitor\n"); return 0; } @@ -693,7 +693,7 @@ evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base) "input", NULL); if (udev_monitor_enable_receiving(master->udev_monitor)) { - fprintf(stderr, "udev: failed to bind the udev monitor\n"); + weston_log("udev: failed to bind the udev monitor\n"); udev_monitor_unref(master->udev_monitor); return 0; } diff --git a/src/filter.c b/src/filter.c index 72ef9be9..91e588d2 100644 --- a/src/filter.c +++ b/src/filter.c @@ -21,7 +21,6 @@ */ #include -#include #include #include #include From 8e3bdd91bf2af1536899466a35d618e02fb573b5 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Fri, 22 Jun 2012 13:21:29 +0100 Subject: [PATCH 082/162] Split notify_keyboard_focus into in/out variants Since the two functions had nothing in common but the local variables. Signed-off-by: Daniel Stone --- src/evdev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 9660996f..05d1ebe6 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -593,7 +593,8 @@ evdev_notify_keyboard_focus(struct evdev_seat *seat) } } - notify_keyboard_focus(&seat->base.seat, &keys); + notify_keyboard_focus_in(&seat->base.seat, &keys, + STATE_UPDATE_AUTOMATIC); wl_array_release(&keys); } @@ -761,7 +762,7 @@ evdev_remove_devices(struct weston_seat *seat_base) wl_list_for_each_safe(device, next, &seat->devices_list, link) device_removed(device); - notify_keyboard_focus(&seat->base.seat, NULL); + notify_keyboard_focus_out(&seat->base.seat); } void From f749baab42bf22e0ee00cae43742b7d0b2d4c354 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Fri, 22 Jun 2012 13:21:37 +0100 Subject: [PATCH 083/162] notify_key: Add update_state argument If update_state is true, then notify_key will continue to call xkb_key_update_state to update the local state mask, as before this commit. Otherwise, it will rely on the compositor to manually update the state itself, for nested compositors. Signed-off-by: Daniel Stone --- src/evdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 05d1ebe6..3355192f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -88,7 +88,8 @@ evdev_process_key(struct evdev_input_device *device, notify_key(&device->master->base.seat, time, e->code, e->value ? WL_KEYBOARD_KEY_STATE_PRESSED : - WL_KEYBOARD_KEY_STATE_RELEASED); + WL_KEYBOARD_KEY_STATE_RELEASED, + STATE_UPDATE_AUTOMATIC); break; } } From 9d67bb202aa51cc95477d1bde6f165d5bc793f3b Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Mon, 23 Jul 2012 19:54:57 +0100 Subject: [PATCH 084/162] evdev: Don't ignore multitouch touchscreens Most touchscreen drivers provide ABS_X and BTN_TOUCH for legacy single-touch emulation modes, but this isn't mandatory. Make sure we don't ignore touchscreens with provide multitouch events with the new API only. Signed-off-by: Daniel Stone --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 3355192f..74662b26 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -441,7 +441,7 @@ evdev_configure_device(struct evdev_input_device *device) /* 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) + if (has_abs && !has_key && !device->is_mt) return -1; if ((device->caps & From 19b5a3707aa9b4d41ecfb9555ebb677f8b8e6cc8 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Mon, 23 Jul 2012 19:54:59 +0100 Subject: [PATCH 085/162] evdev: Release weston_seat with underlying evdev device Signed-off-by: Daniel Stone --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 74662b26..62f1bc1f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -774,7 +774,7 @@ evdev_input_destroy(struct weston_seat *seat_base) evdev_remove_devices(seat_base); evdev_disable_udev_monitor(&seat->base); - wl_list_remove(&seat->base.link); + weston_seat_release(seat_base); free(seat->seat_id); free(seat); } From 701024fd909a24e5ee779769f0b2d1d124ee71cd Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Tue, 31 Jul 2012 13:21:07 +0300 Subject: [PATCH 086/162] evdev: query position ranges for MT, too For a true multi-touch input device, the code ended up using uninitialised fields of evdev_input_device::abs. Fix it by querying the corresponding MT ranges. Signed-off-by: Pekka Paalanen --- src/evdev.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index 62f1bc1f..c294a3ae 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -400,6 +400,14 @@ evdev_configure_device(struct evdev_input_device *device) device->caps |= EVDEV_MOTION_ABS; } if (TEST_BIT(abs_bits, ABS_MT_SLOT)) { + 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->mt.slot = 0; device->caps |= EVDEV_TOUCH; From ca9ef609b653b48edc96b23d8b2612656e49c14b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 1 Aug 2012 00:00:57 -0400 Subject: [PATCH 087/162] compositor: Fold the log prototypes into compositor.h and drop log.h We're trying to keep the API exposed by the core compositor in compositor.h --- src/evdev.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index c294a3ae..6141bca3 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -31,7 +31,6 @@ #include "evdev.h" #include "evdev-private.h" #include "launcher-util.h" -#include "log.h" static void evdev_led_update(struct weston_seat *seat_base, enum weston_led leds) From cac530ebaebfc324a24a2d54fb013eb3885d3639 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 14:38:57 +0300 Subject: [PATCH 088/162] evdev: rename device_removed() to evdev_input_device_destroy() evdev_input_device_destroy() will completement the API of evdev_input_device_create(), both being independent from udev. Since the udev-specific device_removed() would only call evdev_input_device_destroy() and do nothing else, device_remove() calls are simply replaced with evdev_input_device_destroy(). Signed-off-by: Pekka Paalanen --- src/evdev.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 6141bca3..9b1a7e69 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -354,7 +354,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) len = read(fd, &ev, sizeof ev); if (len < 0 || len % sizeof ev[0] != 0) { - /* FIXME: call device_removed when errno is ENODEV. */ + /* FIXME: call evdev_input_device_destroy when errno is ENODEV. */ return 1; } @@ -529,6 +529,24 @@ err0: return NULL; } +static void +evdev_input_device_destroy(struct evdev_input_device *device) +{ + struct evdev_dispatch *dispatch; + + dispatch = device->dispatch; + if (dispatch) + dispatch->interface->destroy(dispatch); + + wl_event_source_remove(device->source); + wl_list_remove(&device->link); + if (device->mtdev) + mtdev_close_delete(device->mtdev); + close(device->fd); + free(device->devnode); + free(device); +} + static const char default_seat[] = "seat0"; static void @@ -550,24 +568,6 @@ device_added(struct udev_device *udev_device, struct evdev_seat *master) evdev_input_device_create(master, c->wl_display, devnode); } -static void -device_removed(struct evdev_input_device *device) -{ - struct evdev_dispatch *dispatch; - - dispatch = device->dispatch; - if (dispatch) - dispatch->interface->destroy(dispatch); - - wl_event_source_remove(device->source); - wl_list_remove(&device->link); - if (device->mtdev) - mtdev_close_delete(device->mtdev); - close(device->fd); - free(device->devnode); - free(device); -} - static void evdev_notify_keyboard_focus(struct evdev_seat *seat) { @@ -674,7 +674,7 @@ evdev_udev_handler(int fd, uint32_t mask, void *data) wl_list_for_each_safe(device, next, &master->devices_list, link) if (!strcmp(device->devnode, devnode)) { - device_removed(device); + evdev_input_device_destroy(device); break; } } @@ -768,7 +768,7 @@ evdev_remove_devices(struct weston_seat *seat_base) struct evdev_input_device *device, *next; wl_list_for_each_safe(device, next, &seat->devices_list, link) - device_removed(device); + evdev_input_device_destroy(device); notify_keyboard_focus_out(&seat->base.seat); } From 42a42240c95375ef17d713408c33b5472205531f Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 14:38:58 +0300 Subject: [PATCH 089/162] evdev: move device opening out from evdev_input_device_create This makes the generic evdev code (i.e. the functions not relying on udev) independent of launcher-util too. The aim is to allow re-using the generic evdev code in the Android backend, where neither udev nor launcher-util are available. evdev_input_device_create() signature is changed: - add the opened device file descriptor - remove wl_display as unused Also add a bit of failure logging. Signed-off-by: Pekka Paalanen --- src/evdev.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 9b1a7e69..7e142a42 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -464,7 +464,7 @@ evdev_configure_device(struct evdev_input_device *device) static struct evdev_input_device * evdev_input_device_create(struct evdev_seat *master, - struct wl_display *display, const char *path) + const char *path, int device_fd) { struct evdev_input_device *device; struct weston_compositor *ec; @@ -485,13 +485,7 @@ evdev_input_device_create(struct evdev_seat *master, device->rel.dx = 0; device->rel.dy = 0; device->dispatch = NULL; - - /* Use non-blocking mode so that we can loop on read on - * evdev_input_device_data() until all events on the fd are - * read. mtdev_get() also expects this. */ - device->fd = weston_launcher_open(ec, path, O_RDWR | O_NONBLOCK); - if (device->fd < 0) - goto err0; + device->fd = device_fd; if (evdev_configure_device(device) == -1) goto err1; @@ -522,8 +516,6 @@ evdev_input_device_create(struct evdev_seat *master, err2: device->dispatch->interface->destroy(device->dispatch); err1: - close(device->fd); -err0: free(device->devnode); free(device); return NULL; @@ -553,8 +545,10 @@ static void device_added(struct udev_device *udev_device, struct evdev_seat *master) { struct weston_compositor *c; + struct evdev_input_device *device; const char *devnode; const char *device_seat; + int fd; device_seat = udev_device_get_property_value(udev_device, "ID_SEAT"); if (!device_seat) @@ -565,7 +559,21 @@ device_added(struct udev_device *udev_device, struct evdev_seat *master) c = master->base.compositor; devnode = udev_device_get_devnode(udev_device); - evdev_input_device_create(master, c->wl_display, devnode); + + /* Use non-blocking mode so that we can loop on read on + * evdev_input_device_data() until all events on the fd are + * read. mtdev_get() also expects this. */ + fd = weston_launcher_open(c, devnode, O_RDWR | O_NONBLOCK); + if (fd < 0) { + weston_log("opening input device '%s' failed.\n", devnode); + return; + } + + device = evdev_input_device_create(master, devnode, fd); + if (!device) { + close(fd); + weston_log("not using input device '%s'.\n", devnode); + } } static void From 216d16bece6d0c4d91fe6c9d9fbecc7a039f5678 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 14:38:59 +0300 Subject: [PATCH 090/162] evdev: merge evdev-private.h into evdev.h Signed-off-by: Pekka Paalanen --- src/evdev-private.h | 115 ------------------------------------------- src/evdev-touchpad.c | 2 +- src/evdev.c | 1 - src/evdev.h | 95 ++++++++++++++++++++++++++++++++++- 4 files changed, 95 insertions(+), 118 deletions(-) delete mode 100644 src/evdev-private.h diff --git a/src/evdev-private.h b/src/evdev-private.h deleted file mode 100644 index 7b56b542..00000000 --- a/src/evdev-private.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * 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. - */ - -#ifndef EVDEV_PRIVATE_H -#define EVDEV_PRIVATE_H - -#include -#include - -struct evdev_seat { - struct weston_seat base; - struct wl_list devices_list; - struct udev_monitor *udev_monitor; - struct wl_event_source *udev_monitor_source; - char *seat_id; -}; - -#define MAX_SLOTS 16 - -enum evdev_event_type { - EVDEV_ABSOLUTE_MOTION = (1 << 0), - EVDEV_ABSOLUTE_MT_DOWN = (1 << 1), - EVDEV_ABSOLUTE_MT_MOTION = (1 << 2), - EVDEV_ABSOLUTE_MT_UP = (1 << 3), - EVDEV_RELATIVE_MOTION = (1 << 4), -}; - -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), -}; - -struct evdev_input_device { - struct evdev_seat *master; - struct wl_list link; - struct wl_event_source *source; - struct weston_output *output; - struct evdev_dispatch *dispatch; - char *devnode; - int fd; - struct { - int min_x, max_x, min_y, max_y; - int32_t x, y; - } abs; - - struct { - int slot; - int32_t x[MAX_SLOTS]; - int32_t y[MAX_SLOTS]; - } mt; - struct mtdev *mtdev; - - struct { - wl_fixed_t dx, dy; - } rel; - - enum evdev_event_type pending_events; - enum evdev_device_capability 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(bit)) & 1) -/* end copied */ - -struct evdev_dispatch; - -struct evdev_dispatch_interface { - /* Process an evdev input event. */ - void (*process)(struct evdev_dispatch *dispatch, - struct evdev_input_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_input_device *device); - -#endif /* EVDEV_PRIVATE_H */ diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 7e167d12..45c00cb1 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -26,7 +26,7 @@ #include #include "filter.h" -#include "evdev-private.h" +#include "evdev.h" /* Default values */ #define DEFAULT_CONSTANT_ACCEL_NUMERATOR 50 diff --git a/src/evdev.c b/src/evdev.c index 7e142a42..08d2c992 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -29,7 +29,6 @@ #include "compositor.h" #include "evdev.h" -#include "evdev-private.h" #include "launcher-util.h" static void diff --git a/src/evdev.h b/src/evdev.h index 8e3214dd..5775e2a3 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -1,5 +1,5 @@ /* - * Copyright © 2011 Intel Corporation + * Copyright © 2011, 2012 Intel Corporation * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided @@ -20,8 +20,99 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifndef EVDEV_H +#define EVDEV_H + +#include +#include #include +struct evdev_seat { + struct weston_seat base; + struct wl_list devices_list; + struct udev_monitor *udev_monitor; + struct wl_event_source *udev_monitor_source; + char *seat_id; +}; + +#define MAX_SLOTS 16 + +enum evdev_event_type { + EVDEV_ABSOLUTE_MOTION = (1 << 0), + EVDEV_ABSOLUTE_MT_DOWN = (1 << 1), + EVDEV_ABSOLUTE_MT_MOTION = (1 << 2), + EVDEV_ABSOLUTE_MT_UP = (1 << 3), + EVDEV_RELATIVE_MOTION = (1 << 4), +}; + +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), +}; + +struct evdev_input_device { + struct evdev_seat *master; + struct wl_list link; + struct wl_event_source *source; + struct weston_output *output; + struct evdev_dispatch *dispatch; + char *devnode; + int fd; + struct { + int min_x, max_x, min_y, max_y; + int32_t x, y; + } abs; + + struct { + int slot; + int32_t x[MAX_SLOTS]; + int32_t y[MAX_SLOTS]; + } mt; + struct mtdev *mtdev; + + struct { + wl_fixed_t dx, dy; + } rel; + + enum evdev_event_type pending_events; + enum evdev_device_capability 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(bit)) & 1) +/* end copied */ + +struct evdev_dispatch; + +struct evdev_dispatch_interface { + /* Process an evdev input event. */ + void (*process)(struct evdev_dispatch *dispatch, + struct evdev_input_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_input_device *device); + void evdev_add_devices(struct udev *udev, struct weston_seat *seat_base); @@ -40,3 +131,5 @@ evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base); void evdev_disable_udev_monitor(struct weston_seat *seat_base); + +#endif /* EVDEV_H */ From 0e9fd6fa0a585c73d9a7fb5cea425a5933bf180e Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 14:39:00 +0300 Subject: [PATCH 091/162] evdev: change evdev_seat into weston_seat in struct evdev_input_device We are phasing out struct evdev_seat. Signed-off-by: Pekka Paalanen --- src/evdev-touchpad.c | 2 +- src/evdev.c | 20 ++++++++++---------- src/evdev.h | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 45c00cb1..f613fb90 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -442,7 +442,7 @@ process_key(struct touchpad_dispatch *touchpad, case BTN_FORWARD: case BTN_BACK: case BTN_TASK: - notify_button(&device->master->base.seat, + notify_button(&device->seat->seat, time, e->code, e->value ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED); diff --git a/src/evdev.c b/src/evdev.c index 08d2c992..3ea50e51 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -76,14 +76,14 @@ evdev_process_key(struct evdev_input_device *device, case BTN_FORWARD: case BTN_BACK: case BTN_TASK: - notify_button(&device->master->base.seat, + notify_button(&device->seat->seat, time, e->code, e->value ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED); break; default: - notify_key(&device->master->base.seat, + notify_key(&device->seat->seat, time, e->code, e->value ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED, @@ -165,13 +165,13 @@ evdev_process_relative(struct evdev_input_device *device, device->pending_events |= EVDEV_RELATIVE_MOTION; break; case REL_WHEEL: - notify_axis(&device->master->base.seat, + notify_axis(&device->seat->seat, time, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(e->value)); break; case REL_HWHEEL: - notify_axis(&device->master->base.seat, + notify_axis(&device->seat->seat, time, WL_POINTER_AXIS_HORIZONTAL_SCROLL, wl_fixed_from_int(e->value)); @@ -216,7 +216,7 @@ is_motion_event(struct input_event *e) static void evdev_flush_motion(struct evdev_input_device *device, uint32_t time) { - struct weston_seat *master = &device->master->base; + struct weston_seat *master = device->seat; if (!device->pending_events) return; @@ -337,7 +337,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) struct input_event ev[32]; int len; - ec = device->master->base.compositor; + ec = device->seat->compositor; if (!ec->focus) return 1; @@ -452,11 +452,11 @@ evdev_configure_device(struct evdev_input_device *device) if ((device->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | EVDEV_BUTTON))) - weston_seat_init_pointer(&device->master->base); + weston_seat_init_pointer(device->seat); if ((device->caps & EVDEV_KEYBOARD)) - weston_seat_init_keyboard(&device->master->base, NULL); + weston_seat_init_keyboard(device->seat, NULL); if ((device->caps & EVDEV_TOUCH)) - weston_seat_init_touch(&device->master->base); + weston_seat_init_touch(device->seat); return 0; } @@ -476,7 +476,7 @@ evdev_input_device_create(struct evdev_seat *master, device->output = container_of(ec->output_list.next, struct weston_output, link); - device->master = master; + device->seat = &master->base; device->is_mt = 0; device->mtdev = NULL; device->devnode = strdup(path); diff --git a/src/evdev.h b/src/evdev.h index 5775e2a3..e4da3a52 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -54,7 +54,7 @@ enum evdev_device_capability { }; struct evdev_input_device { - struct evdev_seat *master; + struct weston_seat *seat; struct wl_list link; struct wl_event_source *source; struct weston_output *output; From 83d7662cbb6eec8ff27d4ec14bd137bf9d561cb6 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 14:39:01 +0300 Subject: [PATCH 092/162] evdev: make evdev_led_update independent from struct evdev_seat in preparation of removing evdev_seat Signed-off-by: Pekka Paalanen --- src/evdev.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 3ea50e51..bd14f146 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -32,7 +32,7 @@ #include "launcher-util.h" static void -evdev_led_update(struct weston_seat *seat_base, enum weston_led leds) +evdev_led_update(struct wl_list *evdev_devices, enum weston_led leds) { static const struct { enum weston_led weston; @@ -42,7 +42,6 @@ evdev_led_update(struct weston_seat *seat_base, enum weston_led leds) { LED_CAPS_LOCK, LED_CAPSL }, { LED_SCROLL_LOCK, LED_SCROLLL }, }; - struct evdev_seat *seat = (struct evdev_seat *) seat_base; struct evdev_input_device *device; struct input_event ev[ARRAY_LENGTH(map)]; unsigned int i; @@ -54,12 +53,20 @@ evdev_led_update(struct weston_seat *seat_base, enum weston_led leds) ev[i].value = !!(leds & map[i].weston); } - wl_list_for_each(device, &seat->devices_list, link) { + wl_list_for_each(device, evdev_devices, link) { if (device->caps & EVDEV_KEYBOARD) write(device->fd, ev, sizeof ev); } } +static void +drm_led_update(struct weston_seat *seat_base, enum weston_led leds) +{ + struct evdev_seat *seat = (struct evdev_seat *) seat_base; + + evdev_led_update(&seat->devices_list, leds); +} + static inline void evdev_process_key(struct evdev_input_device *device, struct input_event *e, int time) @@ -753,7 +760,7 @@ evdev_input_create(struct weston_compositor *c, struct udev *udev, memset(seat, 0, sizeof *seat); weston_seat_init(&seat->base, c); - seat->base.led_update = evdev_led_update; + seat->base.led_update = drm_led_update; wl_list_init(&seat->devices_list); seat->seat_id = strdup(seat_id); From 1f6acefd70350a659e08c21979ac028031aafc36 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 14:39:02 +0300 Subject: [PATCH 093/162] evdev: make evdev_notify_keyboard_focus() independent of evdev_seat in preparation of removing evdev_seat Signed-off-by: Pekka Paalanen --- src/evdev.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index bd14f146..40f60800 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -583,7 +583,8 @@ device_added(struct udev_device *udev_device, struct evdev_seat *master) } static void -evdev_notify_keyboard_focus(struct evdev_seat *seat) +evdev_notify_keyboard_focus(struct weston_seat *seat, + struct wl_list *evdev_devices) { struct evdev_input_device *device; struct wl_array keys; @@ -593,7 +594,7 @@ evdev_notify_keyboard_focus(struct evdev_seat *seat) int ret; memset(all_keys, 0, sizeof all_keys); - wl_list_for_each(device, &seat->devices_list, link) { + 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); @@ -615,8 +616,7 @@ evdev_notify_keyboard_focus(struct evdev_seat *seat) } } - notify_keyboard_focus_in(&seat->base.seat, &keys, - STATE_UPDATE_AUTOMATIC); + notify_keyboard_focus_in(&seat->seat, &keys, STATE_UPDATE_AUTOMATIC); wl_array_release(&keys); } @@ -649,7 +649,7 @@ evdev_add_devices(struct udev *udev, struct weston_seat *seat_base) } udev_enumerate_unref(e); - evdev_notify_keyboard_focus(seat); + evdev_notify_keyboard_focus(&seat->base, &seat->devices_list); if (wl_list_empty(&seat->devices_list)) { weston_log( From 8e02ad4efe6cc54a0b5ec81a5b120d2c125c9c48 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 14:39:03 +0300 Subject: [PATCH 094/162] evdev: pass weston_seat to evdev_input_device_create() in preparation of removing evdev_seat Signed-off-by: Pekka Paalanen --- src/evdev.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 40f60800..7a46a5c7 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -469,7 +469,7 @@ evdev_configure_device(struct evdev_input_device *device) } static struct evdev_input_device * -evdev_input_device_create(struct evdev_seat *master, +evdev_input_device_create(struct weston_seat *seat, const char *path, int device_fd) { struct evdev_input_device *device; @@ -478,12 +478,13 @@ evdev_input_device_create(struct evdev_seat *master, device = malloc(sizeof *device); if (device == NULL) return NULL; + memset(device, 0, sizeof *device); - ec = master->base.compositor; + ec = seat->compositor; device->output = container_of(ec->output_list.next, struct weston_output, link); - device->seat = &master->base; + device->seat = seat; device->is_mt = 0; device->mtdev = NULL; device->devnode = strdup(path); @@ -515,8 +516,6 @@ evdev_input_device_create(struct evdev_seat *master, if (device->source == NULL) goto err2; - wl_list_insert(master->devices_list.prev, &device->link); - return device; err2: @@ -575,11 +574,14 @@ device_added(struct udev_device *udev_device, struct evdev_seat *master) return; } - device = evdev_input_device_create(master, devnode, fd); + device = evdev_input_device_create(&master->base, devnode, fd); if (!device) { close(fd); weston_log("not using input device '%s'.\n", devnode); + return; } + + wl_list_insert(master->devices_list.prev, &device->link); } static void From d950781445ea95790d0110a2a55a6f56fcbaf0ea Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 14:39:04 +0300 Subject: [PATCH 095/162] evdev: rename evdev_seat to drm_seat Signed-off-by: Pekka Paalanen --- src/evdev.c | 18 +++++++++--------- src/evdev.h | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 7a46a5c7..896702d2 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -62,7 +62,7 @@ evdev_led_update(struct wl_list *evdev_devices, enum weston_led leds) static void drm_led_update(struct weston_seat *seat_base, enum weston_led leds) { - struct evdev_seat *seat = (struct evdev_seat *) seat_base; + struct drm_seat *seat = (struct drm_seat *) seat_base; evdev_led_update(&seat->devices_list, leds); } @@ -547,7 +547,7 @@ evdev_input_device_destroy(struct evdev_input_device *device) static const char default_seat[] = "seat0"; static void -device_added(struct udev_device *udev_device, struct evdev_seat *master) +device_added(struct udev_device *udev_device, struct drm_seat *master) { struct weston_compositor *c; struct evdev_input_device *device; @@ -626,7 +626,7 @@ evdev_notify_keyboard_focus(struct weston_seat *seat, void evdev_add_devices(struct udev *udev, struct weston_seat *seat_base) { - struct evdev_seat *seat = (struct evdev_seat *) seat_base; + struct drm_seat *seat = (struct drm_seat *) seat_base; struct udev_enumerate *e; struct udev_list_entry *entry; struct udev_device *device; @@ -667,7 +667,7 @@ evdev_add_devices(struct udev *udev, struct weston_seat *seat_base) static int evdev_udev_handler(int fd, uint32_t mask, void *data) { - struct evdev_seat *master = data; + struct drm_seat *master = data; struct udev_device *udev_device; struct evdev_input_device *device, *next; const char *action; @@ -703,7 +703,7 @@ evdev_udev_handler(int fd, uint32_t mask, void *data) int evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base) { - struct evdev_seat *master = (struct evdev_seat *) seat_base; + struct drm_seat *master = (struct drm_seat *) seat_base; struct wl_event_loop *loop; struct weston_compositor *c = master->base.compositor; int fd; @@ -739,7 +739,7 @@ evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base) void evdev_disable_udev_monitor(struct weston_seat *seat_base) { - struct evdev_seat *seat = (struct evdev_seat *) seat_base; + struct drm_seat *seat = (struct drm_seat *) seat_base; if (!seat->udev_monitor) return; @@ -754,7 +754,7 @@ void evdev_input_create(struct weston_compositor *c, struct udev *udev, const char *seat_id) { - struct evdev_seat *seat; + struct drm_seat *seat; seat = malloc(sizeof *seat); if (seat == NULL) @@ -780,7 +780,7 @@ evdev_input_create(struct weston_compositor *c, struct udev *udev, void evdev_remove_devices(struct weston_seat *seat_base) { - struct evdev_seat *seat = (struct evdev_seat *) seat_base; + struct drm_seat *seat = (struct drm_seat *) seat_base; struct evdev_input_device *device, *next; wl_list_for_each_safe(device, next, &seat->devices_list, link) @@ -792,7 +792,7 @@ evdev_remove_devices(struct weston_seat *seat_base) void evdev_input_destroy(struct weston_seat *seat_base) { - struct evdev_seat *seat = (struct evdev_seat *) seat_base; + struct drm_seat *seat = (struct drm_seat *) seat_base; evdev_remove_devices(seat_base); evdev_disable_udev_monitor(&seat->base); diff --git a/src/evdev.h b/src/evdev.h index e4da3a52..24557705 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -27,7 +27,7 @@ #include #include -struct evdev_seat { +struct drm_seat { struct weston_seat base; struct wl_list devices_list; struct udev_monitor *udev_monitor; From 921c8f4f336be0c55c67593bf2a35bfddf4ce8c2 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 14:39:05 +0300 Subject: [PATCH 096/162] evdev: expose the generic evdev API This API does not depend on udev or launcher-util. Signed-off-by: Pekka Paalanen --- src/evdev.c | 8 ++++---- src/evdev.h | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 896702d2..92ac9345 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -31,7 +31,7 @@ #include "evdev.h" #include "launcher-util.h" -static void +void evdev_led_update(struct wl_list *evdev_devices, enum weston_led leds) { static const struct { @@ -468,7 +468,7 @@ evdev_configure_device(struct evdev_input_device *device) return 0; } -static struct evdev_input_device * +struct evdev_input_device * evdev_input_device_create(struct weston_seat *seat, const char *path, int device_fd) { @@ -526,7 +526,7 @@ err1: return NULL; } -static void +void evdev_input_device_destroy(struct evdev_input_device *device) { struct evdev_dispatch *dispatch; @@ -584,7 +584,7 @@ device_added(struct udev_device *udev_device, struct drm_seat *master) wl_list_insert(master->devices_list.prev, &device->link); } -static void +void evdev_notify_keyboard_focus(struct weston_seat *seat, struct wl_list *evdev_devices) { diff --git a/src/evdev.h b/src/evdev.h index 24557705..66773e76 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -132,4 +132,18 @@ evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base); void evdev_disable_udev_monitor(struct weston_seat *seat_base); +void +evdev_led_update(struct wl_list *evdev_devices, enum weston_led leds); + +struct evdev_input_device * +evdev_input_device_create(struct weston_seat *seat, + const char *path, int device_fd); + +void +evdev_input_device_destroy(struct evdev_input_device *device); + +void +evdev_notify_keyboard_focus(struct weston_seat *seat, + struct wl_list *evdev_devices); + #endif /* EVDEV_H */ From 50052b1d3c00cb2c061cb40eb71f77fb4c973cd5 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 13:30:30 -0400 Subject: [PATCH 097/162] evdev: move udev code into compositor-drm.c Move all udev-related and now drm backend specific code into compositor-drm.c. This makes evdev.c free of udev and launcher-util, and allows it to be used on Android. Signed-off-by: Pekka Paalanen --- src/evdev.c | 228 ---------------------------------------------------- src/evdev.h | 28 ------- 2 files changed, 256 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 92ac9345..8f57c421 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -29,7 +29,6 @@ #include "compositor.h" #include "evdev.h" -#include "launcher-util.h" void evdev_led_update(struct wl_list *evdev_devices, enum weston_led leds) @@ -59,14 +58,6 @@ evdev_led_update(struct wl_list *evdev_devices, enum weston_led leds) } } -static void -drm_led_update(struct weston_seat *seat_base, enum weston_led leds) -{ - struct drm_seat *seat = (struct drm_seat *) seat_base; - - evdev_led_update(&seat->devices_list, leds); -} - static inline void evdev_process_key(struct evdev_input_device *device, struct input_event *e, int time) @@ -544,46 +535,6 @@ evdev_input_device_destroy(struct evdev_input_device *device) free(device); } -static const char default_seat[] = "seat0"; - -static void -device_added(struct udev_device *udev_device, struct drm_seat *master) -{ - struct weston_compositor *c; - struct evdev_input_device *device; - const char *devnode; - const char *device_seat; - int fd; - - device_seat = udev_device_get_property_value(udev_device, "ID_SEAT"); - if (!device_seat) - device_seat = default_seat; - - if (strcmp(device_seat, master->seat_id)) - return; - - c = master->base.compositor; - devnode = udev_device_get_devnode(udev_device); - - /* Use non-blocking mode so that we can loop on read on - * evdev_input_device_data() until all events on the fd are - * read. mtdev_get() also expects this. */ - fd = weston_launcher_open(c, devnode, O_RDWR | O_NONBLOCK); - if (fd < 0) { - weston_log("opening input device '%s' failed.\n", devnode); - return; - } - - device = evdev_input_device_create(&master->base, devnode, fd); - if (!device) { - close(fd); - weston_log("not using input device '%s'.\n", devnode); - return; - } - - wl_list_insert(master->devices_list.prev, &device->link); -} - void evdev_notify_keyboard_focus(struct weston_seat *seat, struct wl_list *evdev_devices) @@ -622,182 +573,3 @@ evdev_notify_keyboard_focus(struct weston_seat *seat, wl_array_release(&keys); } - -void -evdev_add_devices(struct udev *udev, struct weston_seat *seat_base) -{ - struct drm_seat *seat = (struct drm_seat *) seat_base; - struct udev_enumerate *e; - struct udev_list_entry *entry; - struct udev_device *device; - const char *path, *sysname; - - e = udev_enumerate_new(udev); - udev_enumerate_add_match_subsystem(e, "input"); - udev_enumerate_scan_devices(e); - udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { - path = udev_list_entry_get_name(entry); - device = udev_device_new_from_syspath(udev, path); - - sysname = udev_device_get_sysname(device); - if (strncmp("event", sysname, 5) != 0) { - udev_device_unref(device); - continue; - } - - device_added(device, seat); - - udev_device_unref(device); - } - udev_enumerate_unref(e); - - evdev_notify_keyboard_focus(&seat->base, &seat->devices_list); - - if (wl_list_empty(&seat->devices_list)) { - weston_log( - "warning: no input devices on entering Weston. " - "Possible causes:\n" - "\t- no permissions to read /dev/input/event*\n" - "\t- seats misconfigured " - "(Weston backend option 'seat', " - "udev device property ID_SEAT)\n"); - } -} - -static int -evdev_udev_handler(int fd, uint32_t mask, void *data) -{ - struct drm_seat *master = data; - struct udev_device *udev_device; - struct evdev_input_device *device, *next; - const char *action; - const char *devnode; - - udev_device = udev_monitor_receive_device(master->udev_monitor); - if (!udev_device) - return 1; - - action = udev_device_get_action(udev_device); - if (action) { - if (strncmp("event", udev_device_get_sysname(udev_device), 5) != 0) - return 0; - - if (!strcmp(action, "add")) { - device_added(udev_device, master); - } - else if (!strcmp(action, "remove")) { - devnode = udev_device_get_devnode(udev_device); - wl_list_for_each_safe(device, next, - &master->devices_list, link) - if (!strcmp(device->devnode, devnode)) { - evdev_input_device_destroy(device); - break; - } - } - } - udev_device_unref(udev_device); - - return 0; -} - -int -evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base) -{ - struct drm_seat *master = (struct drm_seat *) seat_base; - struct wl_event_loop *loop; - struct weston_compositor *c = master->base.compositor; - int fd; - - master->udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); - if (!master->udev_monitor) { - weston_log("udev: failed to create the udev monitor\n"); - return 0; - } - - udev_monitor_filter_add_match_subsystem_devtype(master->udev_monitor, - "input", NULL); - - if (udev_monitor_enable_receiving(master->udev_monitor)) { - weston_log("udev: failed to bind the udev monitor\n"); - udev_monitor_unref(master->udev_monitor); - return 0; - } - - loop = wl_display_get_event_loop(c->wl_display); - fd = udev_monitor_get_fd(master->udev_monitor); - master->udev_monitor_source = - wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, - evdev_udev_handler, master); - if (!master->udev_monitor_source) { - udev_monitor_unref(master->udev_monitor); - return 0; - } - - return 1; -} - -void -evdev_disable_udev_monitor(struct weston_seat *seat_base) -{ - struct drm_seat *seat = (struct drm_seat *) seat_base; - - if (!seat->udev_monitor) - return; - - udev_monitor_unref(seat->udev_monitor); - seat->udev_monitor = NULL; - wl_event_source_remove(seat->udev_monitor_source); - seat->udev_monitor_source = NULL; -} - -void -evdev_input_create(struct weston_compositor *c, struct udev *udev, - const char *seat_id) -{ - struct drm_seat *seat; - - seat = malloc(sizeof *seat); - if (seat == NULL) - return; - - memset(seat, 0, sizeof *seat); - weston_seat_init(&seat->base, c); - seat->base.led_update = drm_led_update; - - wl_list_init(&seat->devices_list); - seat->seat_id = strdup(seat_id); - if (!evdev_enable_udev_monitor(udev, &seat->base)) { - free(seat->seat_id); - free(seat); - return; - } - - evdev_add_devices(udev, &seat->base); - - c->seat = &seat->base; -} - -void -evdev_remove_devices(struct weston_seat *seat_base) -{ - struct drm_seat *seat = (struct drm_seat *) seat_base; - struct evdev_input_device *device, *next; - - wl_list_for_each_safe(device, next, &seat->devices_list, link) - evdev_input_device_destroy(device); - - notify_keyboard_focus_out(&seat->base.seat); -} - -void -evdev_input_destroy(struct weston_seat *seat_base) -{ - struct drm_seat *seat = (struct drm_seat *) seat_base; - - evdev_remove_devices(seat_base); - evdev_disable_udev_monitor(&seat->base); - - weston_seat_release(seat_base); - free(seat->seat_id); - free(seat); -} diff --git a/src/evdev.h b/src/evdev.h index 66773e76..6556df0e 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -25,15 +25,6 @@ #include #include -#include - -struct drm_seat { - struct weston_seat base; - struct wl_list devices_list; - struct udev_monitor *udev_monitor; - struct wl_event_source *udev_monitor_source; - char *seat_id; -}; #define MAX_SLOTS 16 @@ -113,25 +104,6 @@ struct evdev_dispatch { struct evdev_dispatch * evdev_touchpad_create(struct evdev_input_device *device); -void -evdev_add_devices(struct udev *udev, struct weston_seat *seat_base); - -void -evdev_remove_devices(struct weston_seat *seat_base); - -void -evdev_input_create(struct weston_compositor *c, struct udev *udev, - const char *seat); - -void -evdev_input_destroy(struct weston_seat *seat); - -int -evdev_enable_udev_monitor(struct udev *udev, struct weston_seat *seat_base); - -void -evdev_disable_udev_monitor(struct weston_seat *seat_base); - void evdev_led_update(struct wl_list *evdev_devices, enum weston_led leds); From b2d021b95ec157b16d65a709d79d817106640778 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 14:39:07 +0300 Subject: [PATCH 098/162] evdev: log input devices Write information about found input devices into the log. Also fetch and record the device name. Signed-off-by: Pekka Paalanen --- src/evdev.c | 27 +++++++++++++++++++++++---- src/evdev.h | 1 + 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 8f57c421..7efbc7da 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -445,16 +445,29 @@ evdev_configure_device(struct evdev_input_device *device) /* 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) + if (has_abs && !has_key && !device->is_mt) { + weston_log("input device %s, %s " + "ignored: unsupported device type\n", + device->devname, device->devnode); return -1; + } if ((device->caps & - (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | EVDEV_BUTTON))) + (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | EVDEV_BUTTON))) { weston_seat_init_pointer(device->seat); - if ((device->caps & EVDEV_KEYBOARD)) + weston_log("input device %s, %s is a pointer\n", + device->devname, device->devnode); + } + if ((device->caps & EVDEV_KEYBOARD)) { weston_seat_init_keyboard(device->seat, NULL); - if ((device->caps & EVDEV_TOUCH)) + 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); + weston_log("input device %s, %s is a touch device\n", + device->devname, device->devnode); + } return 0; } @@ -465,6 +478,7 @@ evdev_input_device_create(struct weston_seat *seat, { struct evdev_input_device *device; struct weston_compositor *ec; + char devname[256] = "unknown"; device = malloc(sizeof *device); if (device == NULL) @@ -485,6 +499,9 @@ evdev_input_device_create(struct weston_seat *seat, device->dispatch = NULL; device->fd = device_fd; + ioctl(device->fd, EVIOCGNAME(sizeof(devname)), devname); + device->devname = strdup(devname); + if (evdev_configure_device(device) == -1) goto err1; @@ -512,6 +529,7 @@ evdev_input_device_create(struct weston_seat *seat, err2: device->dispatch->interface->destroy(device->dispatch); err1: + free(device->devname); free(device->devnode); free(device); return NULL; @@ -531,6 +549,7 @@ evdev_input_device_destroy(struct evdev_input_device *device) if (device->mtdev) mtdev_close_delete(device->mtdev); close(device->fd); + free(device->devname); free(device->devnode); free(device); } diff --git a/src/evdev.h b/src/evdev.h index 6556df0e..379838a3 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -51,6 +51,7 @@ struct evdev_input_device { struct weston_output *output; struct evdev_dispatch *dispatch; char *devnode; + char *devname; int fd; struct { int min_x, max_x, min_y, max_y; From e427ef8cb70fdef565fba899230cd41eba694ebc Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 14:39:11 +0300 Subject: [PATCH 099/162] compositor-drm, evdev: don't crash on missing keyboard Weston's notify_keyboard_focus_*() assume that a keyboard is present, if they are called. With evdev, there might not always be a keyboard. Also clean up the variable definition in evdev_notify_keyborad_focus(). I read that function through many times and finally had to grep where does 'all_keys' come from. Signed-off-by: Pekka Paalanen --- src/evdev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 7efbc7da..09275f44 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -561,10 +561,14 @@ evdev_notify_keyboard_focus(struct weston_seat *seat, struct evdev_input_device *device; struct wl_array keys; unsigned int i, set; - char evdev_keys[(KEY_CNT + 7) / 8], all_keys[(KEY_CNT + 7) / 8]; + char evdev_keys[(KEY_CNT + 7) / 8]; + char all_keys[(KEY_CNT + 7) / 8]; uint32_t *k; int ret; + if (!seat->seat.keyboard) + return; + memset(all_keys, 0, sizeof all_keys); wl_list_for_each(device, evdev_devices, link) { memset(evdev_keys, 0, sizeof evdev_keys); From 7ef5852dff8b1eb3e1c3cb291b16a10212c335d1 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Fri, 3 Aug 2012 14:39:14 +0300 Subject: [PATCH 100/162] evdev: kill a warning in evdev_led_update() evdev.c: In function 'evdev_led_update': evdev.c:57:9: warning: ignoring return value of 'write', declared with attribute warn_unused_result Useless in this case. Signed-off-by: Pekka Paalanen --- src/evdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 09275f44..7d935642 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -54,7 +54,8 @@ evdev_led_update(struct wl_list *evdev_devices, enum weston_led leds) wl_list_for_each(device, evdev_devices, link) { if (device->caps & EVDEV_KEYBOARD) - write(device->fd, ev, sizeof ev); + i = write(device->fd, ev, sizeof ev); + (void)i; /* no, we really don't care about the return value */ } } From 4a75370823d9d63f6aa8a3dd783268f911ce2958 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Mon, 6 Aug 2012 14:57:07 +0300 Subject: [PATCH 101/162] evdev: do not pass a list to evdev_led_update() evdev_led_update() does not really need the whole list of device at once, it can be called one device at a time. Signed-off-by: Pekka Paalanen --- src/evdev.c | 13 ++++++------- src/evdev.h | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 7d935642..dba33bab 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -31,7 +31,7 @@ #include "evdev.h" void -evdev_led_update(struct wl_list *evdev_devices, enum weston_led leds) +evdev_led_update(struct evdev_input_device *device, enum weston_led leds) { static const struct { enum weston_led weston; @@ -41,10 +41,12 @@ evdev_led_update(struct wl_list *evdev_devices, enum weston_led leds) { LED_CAPS_LOCK, LED_CAPSL }, { LED_SCROLL_LOCK, LED_SCROLLL }, }; - struct evdev_input_device *device; struct input_event ev[ARRAY_LENGTH(map)]; unsigned int i; + if (!device->caps & EVDEV_KEYBOARD) + return; + memset(ev, 0, sizeof(ev)); for (i = 0; i < ARRAY_LENGTH(map); i++) { ev[i].type = EV_LED; @@ -52,11 +54,8 @@ evdev_led_update(struct wl_list *evdev_devices, enum weston_led leds) ev[i].value = !!(leds & map[i].weston); } - wl_list_for_each(device, evdev_devices, link) { - if (device->caps & EVDEV_KEYBOARD) - i = write(device->fd, ev, sizeof ev); - (void)i; /* no, we really don't care about the return value */ - } + i = write(device->fd, ev, sizeof ev); + (void)i; /* no, we really don't care about the return value */ } static inline void diff --git a/src/evdev.h b/src/evdev.h index 379838a3..003b3626 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -106,7 +106,7 @@ struct evdev_dispatch * evdev_touchpad_create(struct evdev_input_device *device); void -evdev_led_update(struct wl_list *evdev_devices, enum weston_led leds); +evdev_led_update(struct evdev_input_device *device, enum weston_led leds); struct evdev_input_device * evdev_input_device_create(struct weston_seat *seat, From 1bf81b0c5b6c54d735979adba97a59330e0b9a46 Mon Sep 17 00:00:00 2001 From: Pekka Paalanen Date: Mon, 6 Aug 2012 14:57:08 +0300 Subject: [PATCH 102/162] evdev: rename evdev_input_device to evdev_device As said by krh: "Maybe we should also just call it an evdev_device instead, shorter [and] not really ambiguous." [krh: if my typo filled irc is going in a commit message, I'm at least going to insert the missing words.] Signed-off-by: Pekka Paalanen --- src/evdev-touchpad.c | 14 +++++++------- src/evdev.c | 42 +++++++++++++++++++----------------------- src/evdev.h | 15 +++++++-------- 3 files changed, 33 insertions(+), 38 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index f613fb90..16478b8b 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -83,7 +83,7 @@ enum touchpad_fingers_state { struct touchpad_dispatch { struct evdev_dispatch base; - struct evdev_input_device *device; + struct evdev_device *device; enum touchpad_model model; enum touchpad_state state; @@ -126,7 +126,7 @@ struct touchpad_dispatch { }; static enum touchpad_model -get_touchpad_model(struct evdev_input_device *device) +get_touchpad_model(struct evdev_device *device) { struct input_id id; unsigned int i; @@ -190,7 +190,7 @@ touchpad_profile(struct weston_motion_filter *filter, static void configure_touchpad(struct touchpad_dispatch *touchpad, - struct evdev_input_device *device) + struct evdev_device *device) { struct weston_motion_filter *accel; @@ -380,7 +380,7 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) static inline void process_absolute(struct touchpad_dispatch *touchpad, - struct evdev_input_device *device, + struct evdev_device *device, struct input_event *e) { switch (e->code) { @@ -416,7 +416,7 @@ process_absolute(struct touchpad_dispatch *touchpad, static inline void process_key(struct touchpad_dispatch *touchpad, - struct evdev_input_device *device, + struct evdev_device *device, struct input_event *e, uint32_t time) { @@ -476,7 +476,7 @@ process_key(struct touchpad_dispatch *touchpad, static void touchpad_process(struct evdev_dispatch *dispatch, - struct evdev_input_device *device, + struct evdev_device *device, struct input_event *e, uint32_t time) { @@ -519,7 +519,7 @@ struct evdev_dispatch_interface touchpad_interface = { }; struct evdev_dispatch * -evdev_touchpad_create(struct evdev_input_device *device) +evdev_touchpad_create(struct evdev_device *device) { struct touchpad_dispatch *touchpad; diff --git a/src/evdev.c b/src/evdev.c index dba33bab..3c7b2f47 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -31,7 +31,7 @@ #include "evdev.h" void -evdev_led_update(struct evdev_input_device *device, enum weston_led leds) +evdev_led_update(struct evdev_device *device, enum weston_led leds) { static const struct { enum weston_led weston; @@ -59,8 +59,7 @@ evdev_led_update(struct evdev_input_device *device, enum weston_led leds) } static inline void -evdev_process_key(struct evdev_input_device *device, - struct input_event *e, int time) +evdev_process_key(struct evdev_device *device, struct input_event *e, int time) { if (e->value == 2) return; @@ -91,8 +90,7 @@ evdev_process_key(struct evdev_input_device *device, } static void -evdev_process_touch(struct evdev_input_device *device, - struct input_event *e) +evdev_process_touch(struct evdev_device *device, struct input_event *e) { const int screen_width = device->output->current->width; const int screen_height = device->output->current->height; @@ -125,7 +123,7 @@ evdev_process_touch(struct evdev_input_device *device, } static inline void -evdev_process_absolute_motion(struct evdev_input_device *device, +evdev_process_absolute_motion(struct evdev_device *device, struct input_event *e) { const int screen_width = device->output->current->width; @@ -150,7 +148,7 @@ evdev_process_absolute_motion(struct evdev_input_device *device, } static inline void -evdev_process_relative(struct evdev_input_device *device, +evdev_process_relative(struct evdev_device *device, struct input_event *e, uint32_t time) { switch (e->code) { @@ -178,8 +176,7 @@ evdev_process_relative(struct evdev_input_device *device, } static inline void -evdev_process_absolute(struct evdev_input_device *device, - struct input_event *e) +evdev_process_absolute(struct evdev_device *device, struct input_event *e) { if (device->is_mt) { evdev_process_touch(device, e); @@ -212,7 +209,7 @@ is_motion_event(struct input_event *e) } static void -evdev_flush_motion(struct evdev_input_device *device, uint32_t time) +evdev_flush_motion(struct evdev_device *device, uint32_t time) { struct weston_seat *master = device->seat; @@ -260,7 +257,7 @@ evdev_flush_motion(struct evdev_input_device *device, uint32_t time) static void fallback_process(struct evdev_dispatch *dispatch, - struct evdev_input_device *device, + struct evdev_device *device, struct input_event *event, uint32_t time) { @@ -301,7 +298,7 @@ fallback_dispatch_create(void) } static void -evdev_process_events(struct evdev_input_device *device, +evdev_process_events(struct evdev_device *device, struct input_event *ev, int count) { struct evdev_dispatch *dispatch = device->dispatch; @@ -328,10 +325,10 @@ evdev_process_events(struct evdev_input_device *device, } static int -evdev_input_device_data(int fd, uint32_t mask, void *data) +evdev_device_data(int fd, uint32_t mask, void *data) { struct weston_compositor *ec; - struct evdev_input_device *device = data; + struct evdev_device *device = data; struct input_event ev[32]; int len; @@ -351,7 +348,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) len = read(fd, &ev, sizeof ev); if (len < 0 || len % sizeof ev[0] != 0) { - /* FIXME: call evdev_input_device_destroy when errno is ENODEV. */ + /* FIXME: call evdev_device_destroy when errno is ENODEV. */ return 1; } @@ -363,7 +360,7 @@ evdev_input_device_data(int fd, uint32_t mask, void *data) } static int -evdev_configure_device(struct evdev_input_device *device) +evdev_configure_device(struct evdev_device *device) { struct input_absinfo absinfo; unsigned long ev_bits[NBITS(EV_MAX)]; @@ -472,11 +469,10 @@ evdev_configure_device(struct evdev_input_device *device) return 0; } -struct evdev_input_device * -evdev_input_device_create(struct weston_seat *seat, - const char *path, int device_fd) +struct evdev_device * +evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) { - struct evdev_input_device *device; + struct evdev_device *device; struct weston_compositor *ec; char devname[256] = "unknown"; @@ -520,7 +516,7 @@ evdev_input_device_create(struct weston_seat *seat, device->source = wl_event_loop_add_fd(ec->input_loop, device->fd, WL_EVENT_READABLE, - evdev_input_device_data, device); + evdev_device_data, device); if (device->source == NULL) goto err2; @@ -536,7 +532,7 @@ err1: } void -evdev_input_device_destroy(struct evdev_input_device *device) +evdev_device_destroy(struct evdev_device *device) { struct evdev_dispatch *dispatch; @@ -558,7 +554,7 @@ void evdev_notify_keyboard_focus(struct weston_seat *seat, struct wl_list *evdev_devices) { - struct evdev_input_device *device; + struct evdev_device *device; struct wl_array keys; unsigned int i, set; char evdev_keys[(KEY_CNT + 7) / 8]; diff --git a/src/evdev.h b/src/evdev.h index 003b3626..85c4739b 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -44,7 +44,7 @@ enum evdev_device_capability { EVDEV_TOUCH = (1 << 4), }; -struct evdev_input_device { +struct evdev_device { struct weston_seat *seat; struct wl_list link; struct wl_event_source *source; @@ -90,7 +90,7 @@ struct evdev_dispatch; struct evdev_dispatch_interface { /* Process an evdev input event. */ void (*process)(struct evdev_dispatch *dispatch, - struct evdev_input_device *device, + struct evdev_device *device, struct input_event *event, uint32_t time); @@ -103,17 +103,16 @@ struct evdev_dispatch { }; struct evdev_dispatch * -evdev_touchpad_create(struct evdev_input_device *device); +evdev_touchpad_create(struct evdev_device *device); void -evdev_led_update(struct evdev_input_device *device, enum weston_led leds); +evdev_led_update(struct evdev_device *device, enum weston_led leds); -struct evdev_input_device * -evdev_input_device_create(struct weston_seat *seat, - const char *path, int device_fd); +struct evdev_device * +evdev_device_create(struct weston_seat *seat, const char *path, int device_fd); void -evdev_input_device_destroy(struct evdev_input_device *device); +evdev_device_destroy(struct evdev_device *device); void evdev_notify_keyboard_focus(struct weston_seat *seat, From c69e1fbe27518df34e761775461bfd39365a701c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 10 Aug 2012 09:50:11 -0400 Subject: [PATCH 103/162] compositor: Change notify_* function to take a weston_seat Fewer indirections and derefs, and it's also more appropriate for a backend calling into weston core to pass a weston_seat. --- src/evdev-touchpad.c | 2 +- src/evdev.c | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 16478b8b..e453f9d2 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -442,7 +442,7 @@ process_key(struct touchpad_dispatch *touchpad, case BTN_FORWARD: case BTN_BACK: case BTN_TASK: - notify_button(&device->seat->seat, + notify_button(device->seat, time, e->code, e->value ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED); diff --git a/src/evdev.c b/src/evdev.c index 3c7b2f47..88487365 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -73,14 +73,14 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time) case BTN_FORWARD: case BTN_BACK: case BTN_TASK: - notify_button(&device->seat->seat, + notify_button(device->seat, time, e->code, e->value ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED); break; default: - notify_key(&device->seat->seat, + notify_key(device->seat, time, e->code, e->value ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED, @@ -161,13 +161,13 @@ evdev_process_relative(struct evdev_device *device, device->pending_events |= EVDEV_RELATIVE_MOTION; break; case REL_WHEEL: - notify_axis(&device->seat->seat, + notify_axis(device->seat, time, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(e->value)); break; case REL_HWHEEL: - notify_axis(&device->seat->seat, + notify_axis(device->seat, time, WL_POINTER_AXIS_HORIZONTAL_SCROLL, wl_fixed_from_int(e->value)); @@ -217,7 +217,7 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) return; if (device->pending_events & EVDEV_RELATIVE_MOTION) { - notify_motion(&master->seat, time, + notify_motion(master, time, master->seat.pointer->x + device->rel.dx, master->seat.pointer->y + device->rel.dy); device->pending_events &= ~EVDEV_RELATIVE_MOTION; @@ -225,7 +225,7 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) device->rel.dy = 0; } if (device->pending_events & EVDEV_ABSOLUTE_MT_DOWN) { - notify_touch(&master->seat, time, + notify_touch(master, time, device->mt.slot, wl_fixed_from_int(device->mt.x[device->mt.slot]), wl_fixed_from_int(device->mt.y[device->mt.slot]), @@ -234,7 +234,7 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION; } if (device->pending_events & EVDEV_ABSOLUTE_MT_MOTION) { - notify_touch(&master->seat, time, + notify_touch(master, time, device->mt.slot, wl_fixed_from_int(device->mt.x[device->mt.slot]), wl_fixed_from_int(device->mt.y[device->mt.slot]), @@ -243,12 +243,12 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION; } if (device->pending_events & EVDEV_ABSOLUTE_MT_UP) { - notify_touch(&master->seat, time, device->mt.slot, 0, 0, + notify_touch(master, time, device->mt.slot, 0, 0, WL_TOUCH_UP); device->pending_events &= ~EVDEV_ABSOLUTE_MT_UP; } if (device->pending_events & EVDEV_ABSOLUTE_MOTION) { - notify_motion(&master->seat, time, + notify_motion(master, time, wl_fixed_from_int(device->abs.x), wl_fixed_from_int(device->abs.y)); device->pending_events &= ~EVDEV_ABSOLUTE_MOTION; @@ -588,7 +588,7 @@ evdev_notify_keyboard_focus(struct weston_seat *seat, } } - notify_keyboard_focus_in(&seat->seat, &keys, STATE_UPDATE_AUTOMATIC); + notify_keyboard_focus_in(seat, &keys, STATE_UPDATE_AUTOMATIC); wl_array_release(&keys); } From 56b178cc00691e3a831b6f4828378a6a4def993b Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 9 Oct 2012 18:44:29 +0100 Subject: [PATCH 104/162] evdev-touchpad: Twiddle finger_state correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original code always set the finger_state to the appropriate bitmask irrespective of whether the event was a press or a release. It would also blat all members of the bitmask rather than ORing in the new bit for the event. Cc:Jonas Ådahl Signed-off-by: Rob Bradford --- src/evdev-touchpad.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index e453f9d2..4da37a51 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -457,19 +457,19 @@ process_key(struct touchpad_dispatch *touchpad, touchpad->reset = 1; break; case BTN_TOOL_FINGER: - touchpad->finger_state = - ~TOUCHPAD_FINGERS_ONE | e->value ? - TOUCHPAD_FINGERS_ONE : 0; + touchpad->finger_state &= ~TOUCHPAD_FINGERS_ONE; + if (e->value) + touchpad->finger_state |= TOUCHPAD_FINGERS_ONE; break; case BTN_TOOL_DOUBLETAP: - touchpad->finger_state = - ~TOUCHPAD_FINGERS_TWO | e->value ? - TOUCHPAD_FINGERS_TWO : 0; + touchpad->finger_state &= ~TOUCHPAD_FINGERS_TWO; + if (e->value) + touchpad->finger_state |= TOUCHPAD_FINGERS_TWO; break; case BTN_TOOL_TRIPLETAP: - touchpad->finger_state = - ~TOUCHPAD_FINGERS_THREE | e->value ? - TOUCHPAD_FINGERS_THREE : 0; + touchpad->finger_state &= ~TOUCHPAD_FINGERS_THREE; + if (e->value) + touchpad->finger_state |= TOUCHPAD_FINGERS_THREE; break; } } From 7e10eff8f3e7855bc63279c52e1f8074767b209d Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 9 Oct 2012 18:44:31 +0100 Subject: [PATCH 105/162] evdev: Avoid unintended case drop through e->code is in the same range for ABS_ and for REL_. As the code currently stands and for the current values in Linux's input.h there is no risk of a problem. However just in case it would be wise to break after evaluating the relative events. Signed-off-by: Rob Bradford --- src/evdev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/evdev.c b/src/evdev.c index 88487365..cc5af917 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -195,6 +195,7 @@ is_motion_event(struct input_event *e) case REL_Y: return 1; } + break; case EV_ABS: switch (e->code) { case ABS_X: From 28833e880f5d269cbc9bb06a6f5764ac34cc11f5 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Tue, 9 Oct 2012 18:44:32 +0100 Subject: [PATCH 106/162] evdev-touchpad: Iterate over the touchpad spec table correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The original code would overrun since the calculation of the range did not take into consideration the size of the entries in the table. Cc:Jonas Ådahl Signed-off-by: Rob Bradford --- src/evdev-touchpad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 4da37a51..8827b8b4 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -134,7 +134,7 @@ get_touchpad_model(struct evdev_device *device) if (ioctl(device->fd, EVIOCGID, &id) < 0) return TOUCHPAD_MODEL_UNKNOWN; - for (i = 0; i < sizeof touchpad_spec_table; i++) + for (i = 0; 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)) From f4706c67794b99f0aa29950baf3428642736c8c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 27 Sep 2012 18:40:39 +0200 Subject: [PATCH 107/162] evdev-touchpad: Cleanup and refactoring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl --- src/evdev-touchpad.c | 227 ++++++++++++++++++++++--------------------- 1 file changed, 117 insertions(+), 110 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 8827b8b4..32a22cb5 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -42,11 +42,13 @@ enum touchpad_model { TOUCHPAD_MODEL_ELANTECH }; -#define TOUCHPAD_EVENT_NONE 0 -#define TOUCHPAD_EVENT_ABSOLUTE_ANY (1 << 0) -#define TOUCHPAD_EVENT_ABSOLUTE_X (1 << 1) -#define TOUCHPAD_EVENT_ABSOLUTE_Y (1 << 2) -#define TOUCHPAD_EVENT_REPORT (1 << 3) +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; @@ -63,9 +65,9 @@ static struct touchpad_model_spec touchpad_spec_table[] = { }; enum touchpad_state { - TOUCHPAD_STATE_NONE = 0, - TOUCHPAD_STATE_TOUCH, - TOUCHPAD_STATE_PRESS + TOUCHPAD_STATE_NONE = 0, + TOUCHPAD_STATE_TOUCH = (1 << 0), + TOUCHPAD_STATE_MOVE = (1 << 1) }; #define TOUCHPAD_HISTORY_LENGTH 4 @@ -86,7 +88,7 @@ struct touchpad_dispatch { struct evdev_device *device; enum touchpad_model model; - enum touchpad_state state; + unsigned int state; int finger_state; int last_finger_state; @@ -108,7 +110,6 @@ struct touchpad_dispatch { struct { int32_t touch_low; int32_t touch_high; - int32_t press; } pressure; struct { @@ -122,7 +123,7 @@ struct touchpad_dispatch { int motion_index; unsigned int motion_count; - struct wl_list motion_filters; + struct weston_motion_filter *filter; }; static enum touchpad_model @@ -163,8 +164,6 @@ configure_touchpad_pressure(struct touchpad_dispatch *touchpad, touchpad->pressure.touch_high = pressure_min + range * (30.0/256.0); } - - touchpad->pressure.press = pressure_min + range; } static double @@ -188,65 +187,6 @@ touchpad_profile(struct weston_motion_filter *filter, return accel_factor; } -static void -configure_touchpad(struct touchpad_dispatch *touchpad, - struct evdev_device *device) -{ - struct weston_motion_filter *accel; - - struct input_absinfo absinfo; - unsigned long abs_bits[NBITS(ABS_MAX)]; - - double width; - double height; - double diagonal; - - /* Detect model */ - touchpad->model = get_touchpad_model(device); - - /* 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->constant_accel_factor = - DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal; - - touchpad->min_accel_factor = DEFAULT_MIN_ACCEL_FACTOR; - touchpad->max_accel_factor = DEFAULT_MAX_ACCEL_FACTOR; - - 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); - wl_list_insert(&touchpad->motion_filters, &accel->link); - - /* 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; -} - static inline struct touchpad_motion * motion_history_offset(struct touchpad_dispatch *touchpad, int offset) { @@ -294,14 +234,12 @@ static void filter_motion(struct touchpad_dispatch *touchpad, double *dx, double *dy, uint32_t time) { - struct weston_motion_filter *filter; struct weston_motion_params motion; motion.dx = *dx; motion.dy = *dy; - wl_list_for_each(filter, &touchpad->motion_filters, link) - weston_filter_dispatch(filter, &motion, touchpad, time); + weston_filter_dispatch(touchpad->filter, &motion, touchpad, time); *dx = motion.dx; *dy = motion.dy; @@ -312,7 +250,7 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) { int motion_index; int center_x, center_y; - double dx, dy; + double dx = 0.0, dy = 0.0; if (touchpad->reset || touchpad->last_finger_state != touchpad->finger_state) { @@ -349,8 +287,7 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) center_y = hysteresis(touchpad->hw_abs.y, touchpad->hysteresis.center_y, touchpad->hysteresis.margin_y); - } - else { + } else { center_x = touchpad->hw_abs.x; center_y = touchpad->hw_abs.y; } @@ -376,6 +313,25 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) touchpad->device->rel.dy = wl_fixed_from_double(dy); touchpad->device->pending_events |= EVDEV_RELATIVE_MOTION; } + + if (!(touchpad->state & TOUCHPAD_STATE_MOVE) && + ((int)dx || (int)dy)) { + touchpad->state |= TOUCHPAD_STATE_MOVE; + } +} + +static void +on_touch(struct touchpad_dispatch *touchpad) +{ + touchpad->state |= TOUCHPAD_STATE_TOUCH; +} + +static void +on_release(struct touchpad_dispatch *touchpad) +{ + + touchpad->reset = 1; + touchpad->state &= ~(TOUCHPAD_STATE_MOVE | TOUCHPAD_STATE_TOUCH); } static inline void @@ -385,27 +341,23 @@ process_absolute(struct touchpad_dispatch *touchpad, { switch (e->code) { case ABS_PRESSURE: - if (e->value > touchpad->pressure.press) - touchpad->state = TOUCHPAD_STATE_PRESS; - else if (e->value > touchpad->pressure.touch_high) - touchpad->state = TOUCHPAD_STATE_TOUCH; - else if (e->value < touchpad->pressure.touch_low) { - if (touchpad->state > TOUCHPAD_STATE_NONE) - touchpad->reset = 1; - - touchpad->state = TOUCHPAD_STATE_NONE; - } + 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) { + 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) { + 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; @@ -423,15 +375,10 @@ process_key(struct touchpad_dispatch *touchpad, switch (e->code) { case BTN_TOUCH: if (!touchpad->has_pressure) { - if (!e->value) { - touchpad->state = TOUCHPAD_STATE_NONE; - touchpad->reset = 1; - } else { - touchpad->state = - e->value ? - TOUCHPAD_STATE_TOUCH : - TOUCHPAD_STATE_NONE; - } + if (e->value && !(touchpad->state & TOUCHPAD_STATE_TOUCH)) + on_touch(touchpad); + else if (!e->value) + on_release(touchpad); } break; case BTN_LEFT: @@ -504,12 +451,8 @@ touchpad_destroy(struct evdev_dispatch *dispatch) { struct touchpad_dispatch *touchpad = (struct touchpad_dispatch *) dispatch; - struct weston_motion_filter *filter; - struct weston_motion_filter *next; - - wl_list_for_each_safe(filter, next, &touchpad->motion_filters, link) - filter->interface->destroy(filter); + touchpad->filter->interface->destroy(touchpad->filter); free(dispatch); } @@ -518,6 +461,72 @@ struct evdev_dispatch_interface touchpad_interface = { touchpad_destroy }; +static int +touchpad_init(struct touchpad_dispatch *touchpad, + struct evdev_device *device) +{ + struct weston_motion_filter *accel; + + struct input_absinfo absinfo; + unsigned long abs_bits[NBITS(ABS_MAX)]; + + double width; + double height; + double diagonal; + + touchpad->base.interface = &touchpad_interface; + touchpad->device = device; + + /* Detect model */ + touchpad->model = get_touchpad_model(device); + + /* 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->constant_accel_factor = + DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal; + + touchpad->min_accel_factor = DEFAULT_MIN_ACCEL_FACTOR; + touchpad->max_accel_factor = DEFAULT_MAX_ACCEL_FACTOR; + + 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; + + return 0; +} + struct evdev_dispatch * evdev_touchpad_create(struct evdev_device *device) { @@ -527,12 +536,10 @@ evdev_touchpad_create(struct evdev_device *device) if (touchpad == NULL) return NULL; - touchpad->base.interface = &touchpad_interface; - - touchpad->device = device; - wl_list_init(&touchpad->motion_filters); - - configure_touchpad(touchpad, device); + if (touchpad_init(touchpad, device) != 0) { + free(touchpad); + return NULL; + } return &touchpad->base; } From 68449fc8e889a549bea6efbdc02d3b50f1214663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 27 Sep 2012 18:40:40 +0200 Subject: [PATCH 108/162] evdev-touchpad: Add a finite-state machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The finite-state machine is so far used to implement support for tapping and dragging. Signed-off-by: Jonas Ådahl --- src/evdev-touchpad.c | 188 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 32a22cb5..9c028deb 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "filter.h" @@ -34,6 +35,9 @@ #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, @@ -83,6 +87,21 @@ enum touchpad_fingers_state { 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; @@ -101,6 +120,12 @@ struct touchpad_dispatch { int reset; + struct { + struct wl_array events; + enum fsm_state state; + struct wl_event_source *timer_source; + } fsm; + struct { int32_t x; int32_t y; @@ -245,6 +270,147 @@ filter_motion(struct touchpad_dispatch *touchpad, *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.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; + + 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) { @@ -262,6 +428,8 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) touchpad->last_finger_state = touchpad->finger_state; + process_fsm_events(touchpad, time); + return; } touchpad->last_finger_state = touchpad->finger_state; @@ -317,13 +485,18 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) 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 @@ -332,6 +505,8 @@ 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 @@ -453,6 +628,7 @@ touchpad_destroy(struct evdev_dispatch *dispatch) (struct touchpad_dispatch *) dispatch; touchpad->filter->interface->destroy(touchpad->filter); + wl_event_source_remove(touchpad->fsm.timer_source); free(dispatch); } @@ -466,6 +642,7 @@ touchpad_init(struct touchpad_dispatch *touchpad, struct evdev_device *device) { struct weston_motion_filter *accel; + struct wl_event_loop *loop; struct input_absinfo absinfo; unsigned long abs_bits[NBITS(ABS_MAX)]; @@ -524,6 +701,17 @@ touchpad_init(struct touchpad_dispatch *touchpad, 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; + } + return 0; } From 64545a2977ae73a975648afc3eaa80caf747d9a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 27 Sep 2012 18:40:43 +0200 Subject: [PATCH 109/162] evdev-touchpad: Implement two finger scroll MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl --- src/evdev-touchpad.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 9c028deb..6a3217bd 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -477,9 +477,23 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) filter_motion(touchpad, &dx, &dy, time); - touchpad->device->rel.dx = wl_fixed_from_double(dx); - touchpad->device->rel.dy = wl_fixed_from_double(dy); - touchpad->device->pending_events |= EVDEV_RELATIVE_MOTION; + if (touchpad->finger_state == TOUCHPAD_FINGERS_ONE) { + touchpad->device->rel.dx = wl_fixed_from_double(dx); + touchpad->device->rel.dy = wl_fixed_from_double(dy); + touchpad->device->pending_events |= + EVDEV_RELATIVE_MOTION; + } 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) && @@ -579,19 +593,22 @@ process_key(struct touchpad_dispatch *touchpad, touchpad->reset = 1; break; case BTN_TOOL_FINGER: - touchpad->finger_state &= ~TOUCHPAD_FINGERS_ONE; if (e->value) touchpad->finger_state |= TOUCHPAD_FINGERS_ONE; + else + touchpad->finger_state &= ~TOUCHPAD_FINGERS_ONE; break; case BTN_TOOL_DOUBLETAP: - touchpad->finger_state &= ~TOUCHPAD_FINGERS_TWO; if (e->value) touchpad->finger_state |= TOUCHPAD_FINGERS_TWO; + else + touchpad->finger_state &= ~TOUCHPAD_FINGERS_TWO; break; case BTN_TOOL_TRIPLETAP: - touchpad->finger_state &= ~TOUCHPAD_FINGERS_THREE; if (e->value) touchpad->finger_state |= TOUCHPAD_FINGERS_THREE; + else + touchpad->finger_state &= ~TOUCHPAD_FINGERS_THREE; break; } } From 62f978664697fbd261de6c992656da538eb260ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 3 Oct 2012 22:56:58 +0200 Subject: [PATCH 110/162] evdev: Update axis notifications to follow protocol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl --- src/evdev.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index cc5af917..1c65b7bd 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -30,6 +30,8 @@ #include "compositor.h" #include "evdev.h" +#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10) + void evdev_led_update(struct evdev_device *device, enum weston_led leds) { @@ -161,17 +163,35 @@ evdev_process_relative(struct evdev_device *device, device->pending_events |= EVDEV_RELATIVE_MOTION; break; case REL_WHEEL: - notify_axis(device->seat, - time, - WL_POINTER_AXIS_VERTICAL_SCROLL, - wl_fixed_from_int(e->value)); + 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: - notify_axis(device->seat, - time, - WL_POINTER_AXIS_HORIZONTAL_SCROLL, - wl_fixed_from_int(e->value)); - break; + 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; + + } } } From 4135ccf315555e5885807f84c9369ae75633d892 Mon Sep 17 00:00:00 2001 From: Dima Ryazanov Date: Sun, 11 Nov 2012 00:29:01 -0800 Subject: [PATCH 111/162] Fix a typo. --- src/evdev-touchpad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 6a3217bd..73c04eba 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -160,7 +160,7 @@ get_touchpad_model(struct evdev_device *device) if (ioctl(device->fd, EVIOCGID, &id) < 0) return TOUCHPAD_MODEL_UNKNOWN; - for (i = 0; ARRAY_LENGTH(touchpad_spec_table); i++) + 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)) From 24eabf8bb1964821f620bfa753f7b96b482bff7c Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Mon, 3 Dec 2012 19:44:13 +0000 Subject: [PATCH 112/162] evdev: Include the device capabilities in the debugging --- src/evdev.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 1c65b7bd..fa2c740c 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -473,8 +473,11 @@ evdev_configure_device(struct evdev_device *device) if ((device->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | EVDEV_BUTTON))) { weston_seat_init_pointer(device->seat); - weston_log("input device %s, %s is a pointer\n", - device->devname, device->devnode); + 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)) { weston_seat_init_keyboard(device->seat, NULL); From 60bc3610f3881d04ea3ea184688095034b6c9be9 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Mon, 3 Dec 2012 19:44:16 +0000 Subject: [PATCH 113/162] evdev: Apply calibration values to absolute events Store a set of calibration values per device - these calibration values are just applied to the absolute motion events. --- src/evdev.c | 16 ++++++++++++++++ src/evdev.h | 3 +++ 2 files changed, 19 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index fa2c740c..0b99c436 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -229,6 +229,21 @@ is_motion_event(struct input_event *e) return 0; } +static void +transform_absolute(struct evdev_device *device) +{ + if (!device->abs.apply_calibration) + return; + + device->abs.x = device->abs.x * device->abs.calibration[0] + + device->abs.y * device->abs.calibration[1] + + device->abs.calibration[2]; + + device->abs.y = device->abs.x * device->abs.calibration[3] + + device->abs.y * device->abs.calibration[4] + + device->abs.calibration[5]; +} + static void evdev_flush_motion(struct evdev_device *device, uint32_t time) { @@ -269,6 +284,7 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) device->pending_events &= ~EVDEV_ABSOLUTE_MT_UP; } if (device->pending_events & EVDEV_ABSOLUTE_MOTION) { + transform_absolute(device); notify_motion(master, time, wl_fixed_from_int(device->abs.x), wl_fixed_from_int(device->abs.y)); diff --git a/src/evdev.h b/src/evdev.h index 85c4739b..a90f90cd 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -56,6 +56,9 @@ struct evdev_device { struct { int min_x, max_x, min_y, max_y; int32_t x, y; + + int apply_calibration; + float calibration[6]; } abs; struct { From a74a37275368cea3e417a2d8d0dede06002c5dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Sat, 16 Feb 2013 14:29:24 -0500 Subject: [PATCH 114/162] xkb: Don't call exit on failure in weston_compositor_xkb_init() This will exit without cleaning vt modes and leave the system stuck. https://bugs.freedesktop.org/show_bug.cgi?id=60817 --- src/evdev.c | 20 +++++++++++++++++--- src/evdev.h | 2 ++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 0b99c436..286543a0 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -397,7 +397,7 @@ evdev_device_data(int fd, uint32_t mask, void *data) } static int -evdev_configure_device(struct evdev_device *device) +evdev_handle_device(struct evdev_device *device) { struct input_absinfo absinfo; unsigned long ev_bits[NBITS(EV_MAX)]; @@ -483,9 +483,15 @@ evdev_configure_device(struct evdev_device *device) weston_log("input device %s, %s " "ignored: unsupported device type\n", device->devname, device->devnode); - return -1; + return 0; } + return 1; +} + +static int +evdev_configure_device(struct evdev_device *device) +{ if ((device->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | EVDEV_BUTTON))) { weston_seat_init_pointer(device->seat); @@ -496,7 +502,8 @@ evdev_configure_device(struct evdev_device *device) device->caps & EVDEV_BUTTON ? " button" : ""); } if ((device->caps & EVDEV_KEYBOARD)) { - weston_seat_init_keyboard(device->seat, NULL); + if (weston_seat_init_keyboard(device->seat, NULL) < 0) + return -1; weston_log("input device %s, %s is a keyboard\n", device->devname, device->devnode); } @@ -538,6 +545,13 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) ioctl(device->fd, EVIOCGNAME(sizeof(devname)), devname); device->devname = strdup(devname); + if (!evdev_handle_device(device)) { + free(device->devnode); + free(device->devname); + free(device); + return EVDEV_UNHANDLED_DEVICE; + } + if (evdev_configure_device(device) == -1) goto err1; diff --git a/src/evdev.h b/src/evdev.h index a90f90cd..ccbb2224 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -88,6 +88,8 @@ struct evdev_device { #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 { From b3e195bd271eba7064eba4a1e5b04edcc34390c5 Mon Sep 17 00:00:00 2001 From: Satyeshwar Singh Date: Wed, 27 Feb 2013 15:26:23 -0500 Subject: [PATCH 115/162] evdev: Wait for SYN event before sending events over to the client The issue was that touch::down event from the compositor to client apps would send the previous motion events coordinates and this obviously made the client do the wrong thing. This happened because we were not waiting for a SYN event to come from evdev before sending down, motion or up events. https://bugs.freedesktop.org/show_bug.cgi?id=51909 --- src/evdev-touchpad.c | 2 +- src/evdev.c | 6 +++++- src/evdev.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 73c04eba..c25a199c 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -481,7 +481,7 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) touchpad->device->rel.dx = wl_fixed_from_double(dx); touchpad->device->rel.dy = wl_fixed_from_double(dy); touchpad->device->pending_events |= - EVDEV_RELATIVE_MOTION; + EVDEV_RELATIVE_MOTION | EVDEV_SYN; } else if (touchpad->finger_state == TOUCHPAD_FINGERS_TWO) { if (dx != 0.0) notify_axis(touchpad->device->seat, diff --git a/src/evdev.c b/src/evdev.c index 286543a0..a1fa01f0 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -249,9 +249,10 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) { struct weston_seat *master = device->seat; - if (!device->pending_events) + if (!(device->pending_events & EVDEV_SYN)) return; + device->pending_events &= ~EVDEV_SYN; if (device->pending_events & EVDEV_RELATIVE_MOTION) { notify_motion(master, time, master->seat.pointer->x + device->rel.dx, @@ -308,6 +309,9 @@ fallback_process(struct evdev_dispatch *dispatch, case EV_KEY: evdev_process_key(device, event, time); break; + case EV_SYN: + device->pending_events |= EVDEV_SYN; + break; } } diff --git a/src/evdev.h b/src/evdev.h index ccbb2224..eb5c8682 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -34,6 +34,7 @@ enum evdev_event_type { EVDEV_ABSOLUTE_MT_MOTION = (1 << 2), EVDEV_ABSOLUTE_MT_UP = (1 << 3), EVDEV_RELATIVE_MOTION = (1 << 4), + EVDEV_SYN = (1 << 5), }; enum evdev_device_capability { From 9d92a079964a4845c452b5f0a049941e398345e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 25 Feb 2013 17:04:47 -0500 Subject: [PATCH 116/162] compositor: Change notify_motion to take relative motion events --- src/evdev.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index a1fa01f0..d2954b57 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -254,9 +254,7 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) device->pending_events &= ~EVDEV_SYN; if (device->pending_events & EVDEV_RELATIVE_MOTION) { - notify_motion(master, time, - master->seat.pointer->x + device->rel.dx, - master->seat.pointer->y + device->rel.dy); + notify_motion(master, time, device->rel.dx, device->rel.dy); device->pending_events &= ~EVDEV_RELATIVE_MOTION; device->rel.dx = 0; device->rel.dy = 0; From 23b92d9dc68f297388070393e641fda389174dee Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Wed, 27 Mar 2013 15:59:43 +0000 Subject: [PATCH 117/162] compositor: Support notifying with absolute position too With evdev input devices that generate absolute positions we need to provide an infrastructure in the compositor for supporting those. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=61997 --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index d2954b57..2c81d2b1 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -284,7 +284,7 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) } if (device->pending_events & EVDEV_ABSOLUTE_MOTION) { transform_absolute(device); - notify_motion(master, time, + notify_motion_absolute(master, time, wl_fixed_from_int(device->abs.x), wl_fixed_from_int(device->abs.y)); device->pending_events &= ~EVDEV_ABSOLUTE_MOTION; From 049a7492dc404b7d74e4fbd670af5aa1732af914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 22 Mar 2013 08:41:42 +0100 Subject: [PATCH 118/162] evdev-touchpad: Disable tap FSM by default on touchpads with button pads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl --- src/evdev-touchpad.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index c25a199c..4f9bb033 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -121,6 +121,8 @@ struct touchpad_dispatch { int reset; struct { + bool enable; + struct wl_array events; enum fsm_state state; struct wl_event_source *timer_source; @@ -300,6 +302,9 @@ process_fsm_events(struct touchpad_dispatch *touchpad, uint32_t time) enum fsm_event *pevent; enum fsm_event event; + if (!touchpad->fsm.enable) + return; + if (touchpad->fsm.events.size == 0) return; @@ -391,6 +396,9 @@ push_fsm_event(struct touchpad_dispatch *touchpad, { enum fsm_event *pevent; + if (!touchpad->fsm.enable) + return; + pevent = wl_array_add(&touchpad->fsm.events, sizeof event); if (pevent) *pevent = event; @@ -661,9 +669,12 @@ touchpad_init(struct touchpad_dispatch *touchpad, 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; @@ -674,6 +685,9 @@ touchpad_init(struct touchpad_dispatch *touchpad, /* 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)) { @@ -729,6 +743,9 @@ touchpad_init(struct touchpad_dispatch *touchpad, return -1; } + /* Configure */ + touchpad->fsm.enable = !has_buttonpad; + return 0; } From 6e5928ab4186dc4ebe06291b3c066e8880ead3e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 6 May 2013 23:19:49 -0400 Subject: [PATCH 119/162] input: Merge wl_seat into weston_seat --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 2c81d2b1..9289b1cd 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -618,7 +618,7 @@ evdev_notify_keyboard_focus(struct weston_seat *seat, uint32_t *k; int ret; - if (!seat->seat.keyboard) + if (!seat->keyboard) return; memset(all_keys, 0, sizeof all_keys); From 17ea8f9e505ed0435f9300aedb980740b7d21301 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 22 May 2013 18:03:19 +0300 Subject: [PATCH 120/162] configure.ac: Enable AC_USE_SYSTEM_EXTENSIONS AC_USE_SYSTEM_EXTENSIONS enables _XOPEN_SOURCE, _GNU_SOURCE and similar macros to expose the largest extent of functionality supported by the underlying system. This is required since these macros are often limiting rather than merely additive, e.g. _XOPEN_SOURCE will actually on some systems hide declarations which are not part of the X/Open spec. Since this goes into config.h rather than the command line, ensure all source is consistently including config.h before anything else, including system libraries. This doesn't need to be guarded by a HAVE_CONFIG_H ifdef, which was only ever a hangover from the X.Org modular transition. Signed-off-by: Daniel Stone [pq: rebased and converted more files] --- src/evdev-touchpad.c | 2 ++ src/evdev.c | 2 ++ src/filter.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 4f9bb033..a21ae0b2 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -20,6 +20,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "config.h" + #include #include #include diff --git a/src/evdev.c b/src/evdev.c index 9289b1cd..122a2d9b 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -20,6 +20,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "config.h" + #include #include #include diff --git a/src/filter.c b/src/filter.c index 91e588d2..a55ebf27 100644 --- a/src/filter.c +++ b/src/filter.c @@ -20,6 +20,8 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "config.h" + #include #include #include From 57334b7088b38560050ca40235f0acf688abfc38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 1 Jul 2013 12:48:55 -0400 Subject: [PATCH 121/162] touchpad: Handle two-finger click as right click for button pads --- src/evdev-touchpad.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index a21ae0b2..53300ce8 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -571,6 +571,8 @@ process_key(struct touchpad_dispatch *touchpad, struct input_event *e, uint32_t time) { + uint32_t code; + switch (e->code) { case BTN_TOUCH: if (!touchpad->has_pressure) { @@ -588,8 +590,12 @@ process_key(struct touchpad_dispatch *touchpad, case BTN_FORWARD: case BTN_BACK: case BTN_TASK: - notify_button(device->seat, - time, e->code, + 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; From 23e4ec3e23847089b34977a2a5edacb2fdae6b27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 22 Jul 2013 15:09:30 -0700 Subject: [PATCH 122/162] evdev: Use weston_output_transform_coordinate for evdev touch screens --- src/evdev.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 122a2d9b..08aa7276 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -112,15 +112,13 @@ evdev_process_touch(struct evdev_device *device, struct input_event *e) case ABS_MT_POSITION_X: device->mt.x[device->mt.slot] = (e->value - device->abs.min_x) * screen_width / - (device->abs.max_x - device->abs.min_x) + - device->output->x; + (device->abs.max_x - device->abs.min_x); device->pending_events |= EVDEV_ABSOLUTE_MT_MOTION; break; case ABS_MT_POSITION_Y: device->mt.y[device->mt.slot] = (e->value - device->abs.min_y) * screen_height / - (device->abs.max_y - device->abs.min_y) + - device->output->y; + (device->abs.max_y - device->abs.min_y); device->pending_events |= EVDEV_ABSOLUTE_MT_MOTION; break; } @@ -250,10 +248,13 @@ static void evdev_flush_motion(struct evdev_device *device, uint32_t time) { struct weston_seat *master = device->seat; + wl_fixed_t x, y; + int slot; if (!(device->pending_events & EVDEV_SYN)) return; + slot = device->mt.slot; device->pending_events &= ~EVDEV_SYN; if (device->pending_events & EVDEV_RELATIVE_MOTION) { notify_motion(master, time, device->rel.dx, device->rel.dy); @@ -262,20 +263,22 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) device->rel.dy = 0; } if (device->pending_events & EVDEV_ABSOLUTE_MT_DOWN) { + weston_output_transform_coordinate(device->output, + device->mt.x[slot], + device->mt.y[slot], + &x, &y); notify_touch(master, time, - device->mt.slot, - wl_fixed_from_int(device->mt.x[device->mt.slot]), - wl_fixed_from_int(device->mt.y[device->mt.slot]), - WL_TOUCH_DOWN); + device->mt.slot, x, y, WL_TOUCH_DOWN); device->pending_events &= ~EVDEV_ABSOLUTE_MT_DOWN; device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION; } if (device->pending_events & EVDEV_ABSOLUTE_MT_MOTION) { + weston_output_transform_coordinate(device->output, + device->mt.x[slot], + device->mt.y[slot], + &x, &y); notify_touch(master, time, - device->mt.slot, - wl_fixed_from_int(device->mt.x[device->mt.slot]), - wl_fixed_from_int(device->mt.y[device->mt.slot]), - WL_TOUCH_MOTION); + device->mt.slot, x, y, WL_TOUCH_MOTION); device->pending_events &= ~EVDEV_ABSOLUTE_MT_DOWN; device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION; } @@ -286,9 +289,10 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) } if (device->pending_events & EVDEV_ABSOLUTE_MOTION) { transform_absolute(device); - notify_motion_absolute(master, time, - wl_fixed_from_int(device->abs.x), - wl_fixed_from_int(device->abs.y)); + weston_output_transform_coordinate(device->output, + device->abs.x, + device->abs.y, &x, &y); + notify_motion_absolute(master, time, x, y); device->pending_events &= ~EVDEV_ABSOLUTE_MOTION; } } From 95e1abf104e8aea7108fc55441dff3509babecde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 26 Jul 2013 10:40:32 -0700 Subject: [PATCH 123/162] evdev: Don't add output offset in evdev_process_absolute_motion() We do that in weston_output_transform_coordinate() now. --- src/evdev.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 08aa7276..a5543023 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -135,15 +135,13 @@ evdev_process_absolute_motion(struct evdev_device *device, case ABS_X: device->abs.x = (e->value - device->abs.min_x) * screen_width / - (device->abs.max_x - device->abs.min_x) + - device->output->x; + (device->abs.max_x - device->abs.min_x); device->pending_events |= 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) + - device->output->y; + (device->abs.max_y - device->abs.min_y); device->pending_events |= EVDEV_ABSOLUTE_MOTION; break; } From 7ff70db86d76f15bfb0b15845e98d2b6a083f1b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 26 Jul 2013 10:41:43 -0700 Subject: [PATCH 124/162] evdev: Use temporary x and y coordinates when applying calibration Don't overwrite device->abs.x halfway through the matrix multiplication. --- src/evdev.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index a5543023..dd3e2c9f 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -230,16 +230,21 @@ is_motion_event(struct input_event *e) static void transform_absolute(struct evdev_device *device) { + int32_t x, y; + if (!device->abs.apply_calibration) return; - device->abs.x = device->abs.x * device->abs.calibration[0] + - device->abs.y * device->abs.calibration[1] + - device->abs.calibration[2]; + x = device->abs.x * device->abs.calibration[0] + + device->abs.y * device->abs.calibration[1] + + device->abs.calibration[2]; - device->abs.y = device->abs.x * device->abs.calibration[3] + - device->abs.y * device->abs.calibration[4] + - device->abs.calibration[5]; + y = device->abs.x * device->abs.calibration[3] + + device->abs.y * device->abs.calibration[4] + + device->abs.calibration[5]; + + device->abs.x = x; + device->abs.y = y; } static void From c1bb30da2f965244677776ee7f7cf89fd4f176c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Fri, 26 Jul 2013 10:43:26 -0700 Subject: [PATCH 125/162] evdev: Suport old-style single-touch touch screens These screens send only BTN_TOUCH and ABS_X/Y. --- src/evdev.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index dd3e2c9f..5ad4d6b1 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -83,6 +83,11 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time) WL_POINTER_BUTTON_STATE_RELEASED); break; + case BTN_TOUCH: + if (e->value == 0 && !device->is_mt) + notify_touch(device->seat, time, device->mt.slot, 0, 0, + WL_TOUCH_UP); + break; default: notify_key(device->seat, time, e->code, @@ -295,7 +300,16 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) weston_output_transform_coordinate(device->output, device->abs.x, device->abs.y, &x, &y); - notify_motion_absolute(master, time, x, y); + + if (device->caps & EVDEV_TOUCH) { + if (master->num_tp == 0) + notify_touch(master, time, 0, + x, y, WL_TOUCH_DOWN); + else + notify_touch(master, time, 0, + x, y, WL_TOUCH_MOTION); + } else + notify_motion_absolute(master, time, x, y); device->pending_events &= ~EVDEV_ABSOLUTE_MOTION; } } @@ -482,6 +496,10 @@ evdev_handle_device(struct evdev_device *device) break; } } + if (TEST_BIT(key_bits, BTN_TOUCH)) { + device->caps |= EVDEV_TOUCH; + } + } if (TEST_BIT(ev_bits, EV_LED)) { device->caps |= EVDEV_KEYBOARD; From 420fbad8bb72cb5ad48bde5a73edca1debdd764e Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 8 Aug 2013 11:57:05 +1000 Subject: [PATCH 126/162] malloc + memset -> zalloc And for clients using the xmalloc helper, use xzalloc. Signed-off-by: Peter Hutterer --- src/evdev.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 5ad4d6b1..e9fd8091 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -552,10 +552,9 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) struct weston_compositor *ec; char devname[256] = "unknown"; - device = malloc(sizeof *device); + device = zalloc(sizeof *device); if (device == NULL) return NULL; - memset(device, 0, sizeof *device); ec = seat->compositor; device->output = From 297bac98026a630f789b923aab1be8eba89ccd09 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Thu, 8 Aug 2013 12:03:08 +1000 Subject: [PATCH 127/162] evdev: check for ABS_MT_POSITION_X/Y to determine mt devices mtdev as currently used in weston is a noop. mtdev's purpose is to convert Protocol A devices (without ABS_MT_SLOT) to Protocol B devices (slots). For Protocol B devices mtdev merely routes the events, so checking for slots and then using mtdev based on that adds no functionality. Check for ABS_MT_POSITION_X/Y instead and use that to categorise a device as MT device. mtdev will provide us with a slotted protocol for all devices. https://bugs.freedesktop.org/show_bug.cgi?id=54428 --- src/evdev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index e9fd8091..fc5004c2 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -454,7 +454,11 @@ evdev_handle_device(struct evdev_device *device) device->abs.max_y = absinfo.maximum; device->caps |= EVDEV_MOTION_ABS; } - if (TEST_BIT(abs_bits, ABS_MT_SLOT)) { + /* 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; From 756785ec3eb5643a73fc9556eb67227b4e4623e4 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 7 Aug 2013 11:04:41 +1000 Subject: [PATCH 128/162] evdev: prevent unterminated device name The kernel copies up to sizeof(devname) bytes but doesn't null-terminate the string if the device name exceeds the size of the supplied buffer. --- src/evdev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/evdev.c b/src/evdev.c index fc5004c2..27296f8d 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -575,6 +575,7 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) device->fd = device_fd; ioctl(device->fd, EVIOCGNAME(sizeof(devname)), devname); + devname[sizeof(devname) - 1] = '\0'; device->devname = strdup(devname); if (!evdev_handle_device(device)) { From 3f0ee131e1f0e291b0ce606dbea56c5584cf57d2 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 7 Aug 2013 11:04:42 +1000 Subject: [PATCH 129/162] evdev: add comment why we're ignoring key value 2 --- src/evdev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/evdev.c b/src/evdev.c index 27296f8d..c05bb788 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -65,6 +65,7 @@ evdev_led_update(struct evdev_device *device, enum weston_led leds) 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; From fe57a4e5fae8aa28b2ed3238ef89487087ecb282 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 7 Aug 2013 11:04:45 +1000 Subject: [PATCH 130/162] evdev: only use mtdev for Protocol A devices For Protocol B devices, mtdev merely routes the events and is not needed. For Protocol A devices, mtdev is needed, so fail for those devices now if we mtdev fails. --- src/evdev.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index c05bb788..0cf5aa2e 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -471,6 +471,15 @@ evdev_handle_device(struct evdev_device *device) device->is_mt = 1; device->mt.slot = 0; 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; + } + } } } if (TEST_BIT(ev_bits, EV_REL)) { @@ -580,6 +589,8 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) device->devname = strdup(devname); if (!evdev_handle_device(device)) { + if (device->mtdev) + mtdev_close_delete(device->mtdev); free(device->devnode); free(device->devname); free(device); @@ -595,13 +606,6 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) if (device->dispatch == NULL) goto err1; - - if (device->is_mt) { - device->mtdev = mtdev_new_open(device->fd); - if (!device->mtdev) - weston_log("mtdev failed to open for %s\n", path); - } - device->source = wl_event_loop_add_fd(ec->input_loop, device->fd, WL_EVENT_READABLE, evdev_device_data, device); @@ -613,6 +617,8 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) err2: device->dispatch->interface->destroy(device->dispatch); err1: + if (device->mtdev) + mtdev_close_delete(device->mtdev); free(device->devname); free(device->devnode); free(device); From 3fe16ee03b549e8be063714ed951bef4dd0bfc63 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 7 Aug 2013 11:04:46 +1000 Subject: [PATCH 131/162] evdev: get the current slot value from the absinfo struct or mtdev If touches are already present on the device, absinfo has the currently active touch slot. There's a race condition where the slot may change before we enable the fd and we thus miss out on the ABS_MT_SLOT event. It's still slightly more correct than assuming whatever comes next is slot 0. --- src/evdev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 0cf5aa2e..24f52ca6 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -469,7 +469,6 @@ evdev_handle_device(struct evdev_device *device) device->abs.min_y = absinfo.minimum; device->abs.max_y = absinfo.maximum; device->is_mt = 1; - device->mt.slot = 0; device->caps |= EVDEV_TOUCH; if (!TEST_BIT(abs_bits, ABS_MT_SLOT)) { @@ -479,6 +478,11 @@ evdev_handle_device(struct evdev_device *device) 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; } } } From b23c3273bc9b64cb95156a8a1e4b5acfd3f2135d Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 7 Aug 2013 11:04:47 +1000 Subject: [PATCH 132/162] evdev: plug a potential memleak For touchpads, device->dispatch is set up when exiting evdev_handle_device() and a potential source for a memleak. This can't actually happen at the moment, as evdev_handle_device() won't fail for touchpads after setting up the dispatch but prevent this from happening in the future. --- src/evdev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index 24f52ca6..f3483c67 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -593,6 +593,8 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) device->devname = strdup(devname); if (!evdev_handle_device(device)) { + if (device->dispatch) + device->dispatch->interface->destroy(dispatch); if (device->mtdev) mtdev_close_delete(device->mtdev); free(device->devnode); From 786bf52f8f14a1445146b5c78afaf9dc7b28bc34 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 7 Aug 2013 11:04:48 +1000 Subject: [PATCH 133/162] evdev: call evdev_device_destroy on failure Avoid keeping keeping what needs to be freed in sync in multiple places, make evdev_device_destroy do the right thing instead. --- src/evdev.c | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index f3483c67..af60dbc4 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -593,41 +593,29 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) device->devname = strdup(devname); if (!evdev_handle_device(device)) { - if (device->dispatch) - device->dispatch->interface->destroy(dispatch); - if (device->mtdev) - mtdev_close_delete(device->mtdev); - free(device->devnode); - free(device->devname); - free(device); + evdev_device_destroy(device); return EVDEV_UNHANDLED_DEVICE; } if (evdev_configure_device(device) == -1) - goto err1; + 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 err1; + goto err; device->source = wl_event_loop_add_fd(ec->input_loop, device->fd, WL_EVENT_READABLE, evdev_device_data, device); if (device->source == NULL) - goto err2; + goto err; return device; -err2: - device->dispatch->interface->destroy(device->dispatch); -err1: - if (device->mtdev) - mtdev_close_delete(device->mtdev); - free(device->devname); - free(device->devnode); - free(device); +err: + evdev_device_destroy(device); return NULL; } @@ -640,8 +628,10 @@ evdev_device_destroy(struct evdev_device *device) if (dispatch) dispatch->interface->destroy(dispatch); - wl_event_source_remove(device->source); - wl_list_remove(&device->link); + if (device->source) + wl_event_source_remove(device->source); + if (!wl_list_empty(&device->link)) + wl_list_remove(&device->link); if (device->mtdev) mtdev_close_delete(device->mtdev); close(device->fd); From f22edd89cbb1a1150cbcda420535484a2f9cea40 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 7 Aug 2013 11:04:49 +1000 Subject: [PATCH 134/162] evdev: log when a device is used as touchpad --- src/evdev.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index af60dbc4..342cb9ba 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -498,8 +498,11 @@ evdev_handle_device(struct evdev_device *device) key_bits); if (TEST_BIT(key_bits, BTN_TOOL_FINGER) && !TEST_BIT(key_bits, BTN_TOOL_PEN) && - has_abs) + 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; From 3a65d85ad02c460154807356e4c40e717d4d23cf Mon Sep 17 00:00:00 2001 From: Rusty Lynch Date: Thu, 8 Aug 2013 21:08:17 -0700 Subject: [PATCH 135/162] evdev: Use touch ID 0 when generating touch up event device->mt.slot is uninitialized when we're not receiving the evdev slot events. Always use ID 0 as we do when we generate the touch down and motion events. --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 342cb9ba..2018e2ac 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -86,7 +86,7 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time) case BTN_TOUCH: if (e->value == 0 && !device->is_mt) - notify_touch(device->seat, time, device->mt.slot, 0, 0, + notify_touch(device->seat, time, 0, 0, 0, WL_TOUCH_UP); break; default: From 5a49ec0e83d7433548a027dbcc2e5f2f3cbe1de2 Mon Sep 17 00:00:00 2001 From: Rolf Morel Date: Fri, 9 Aug 2013 16:32:17 +0200 Subject: [PATCH 136/162] evdev: write EV_SYN input_event along with led events to device Other clients of an evdev device need to have the events they receive be separated, in moment in time, from other events by an EV_SYN/ SYN_REPORT. This is the responsibility of the client who writes events into the stream. --- src/evdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 2018e2ac..2966b612 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -45,7 +45,7 @@ evdev_led_update(struct evdev_device *device, enum weston_led leds) { LED_CAPS_LOCK, LED_CAPSL }, { LED_SCROLL_LOCK, LED_SCROLLL }, }; - struct input_event ev[ARRAY_LENGTH(map)]; + struct input_event ev[ARRAY_LENGTH(map) + 1]; unsigned int i; if (!device->caps & EVDEV_KEYBOARD) @@ -57,6 +57,8 @@ evdev_led_update(struct evdev_device *device, enum weston_led leds) 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 */ From b0044ab4e2d0540deb7348b1c6e59ca9e9d51cb5 Mon Sep 17 00:00:00 2001 From: Armin K Date: Wed, 31 Jul 2013 01:41:03 +0200 Subject: [PATCH 137/162] evdev-touchpad: Set some options using weston.ini This patch adds 3 new options to weston.ini to allow the user to change default constant_accel_factor, min_accel_factor and max_accel_factor. If no options are set, it falls back using defaults as it did before. v2: create weston_config_section_get_double and use it instead of manualy converting string to double. v3: add default values in weston_config_get_double instead of using conditionals. v4: don't pass diagonal as pointer. --- src/evdev-touchpad.c | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 53300ce8..81acbd04 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -26,10 +26,12 @@ #include #include #include +#include #include #include "filter.h" #include "evdev.h" +#include "../shared/config-parser.h" /* Default values */ #define DEFAULT_CONSTANT_ACCEL_NUMERATOR 50 @@ -670,6 +672,38 @@ struct evdev_dispatch_interface touchpad_interface = { touchpad_destroy }; +static void +touchpad_parse_config(struct touchpad_dispatch *touchpad, double diagonal) +{ + struct weston_config *config; + struct weston_config_section *s; + int config_fd; + + double constant_accel_factor; + double min_accel_factor; + double max_accel_factor; + + config_fd = open_config_file("weston.ini"); + config = weston_config_parse(config_fd); + close(config_fd); + + s = weston_config_get_section(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) @@ -710,11 +744,7 @@ touchpad_init(struct touchpad_dispatch *touchpad, height = abs(device->abs.max_y - device->abs.min_y); diagonal = sqrt(width*width + height*height); - touchpad->constant_accel_factor = - DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal; - - touchpad->min_accel_factor = DEFAULT_MIN_ACCEL_FACTOR; - touchpad->max_accel_factor = DEFAULT_MAX_ACCEL_FACTOR; + touchpad_parse_config(touchpad, diagonal); touchpad->hysteresis.margin_x = diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR; From 6dc5a8e95dceded41174de9ea175473f40fe542c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 13 Aug 2013 14:55:39 -0700 Subject: [PATCH 138/162] evdev: Ignore joystick devices We don't handle them in any way now and having your steering wheel move the cursor isn't useful. Applications can still open evdev devices and access them directly like they already do. --- src/evdev.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index 2966b612..26fe8665 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -445,6 +445,16 @@ evdev_handle_device(struct evdev_device *device) 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; + } + if (TEST_BIT(abs_bits, ABS_X)) { ioctl(device->fd, EVIOCGABS(ABS_X), &absinfo); device->abs.min_x = absinfo.minimum; From ef1f81dae7a480c3b2666ff798c6dfaaa9f94c0c Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Thu, 15 Aug 2013 01:10:24 +0100 Subject: [PATCH 139/162] Add more missing config.h includes config.h includes were missing in a few files, including input.c, the lack of which caused the X11 backend to segfault instantly due to not having an xkbcommon context. Signed-off-by: Daniel Stone --- src/evdev.h | 2 ++ src/filter.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/evdev.h b/src/evdev.h index eb5c8682..524fa229 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -23,6 +23,8 @@ #ifndef EVDEV_H #define EVDEV_H +#include "config.h" + #include #include diff --git a/src/filter.h b/src/filter.h index ff8e579f..850ce8df 100644 --- a/src/filter.h +++ b/src/filter.h @@ -23,6 +23,8 @@ #ifndef _FILTER_H_ #define _FILTER_H_ +#include "config.h" + #include #include "compositor.h" From 1625aa0fc2e6aaf0bb1fd53a1f3f39f3f11ab9ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 26 Aug 2013 14:35:32 -0700 Subject: [PATCH 140/162] evdev: Initliaze device->link so we can wl_list_remove() without crashing We were testing for wl_list_empty() on a { NULL, NULL } list (which returns false) and then wl_list_remove()ing the device (which crashes). --- src/evdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 26fe8665..29e32136 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -602,6 +602,7 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) device->rel.dy = 0; device->dispatch = NULL; device->fd = device_fd; + wl_list_init(&device->link); ioctl(device->fd, EVIOCGNAME(sizeof(devname)), devname); devname[sizeof(devname) - 1] = '\0'; @@ -645,8 +646,7 @@ evdev_device_destroy(struct evdev_device *device) if (device->source) wl_event_source_remove(device->source); - if (!wl_list_empty(&device->link)) - wl_list_remove(&device->link); + wl_list_remove(&device->link); if (device->mtdev) mtdev_close_delete(device->mtdev); close(device->fd); From 51e2c3f40e9e59ccfcd21386858fb3e877b26a4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Wed, 28 Aug 2013 22:12:24 -0700 Subject: [PATCH 141/162] evdev: Don't transform device->abs.x/y in place We don't always get both an X and an Y event in a SYN report, so we end up transforming the coordinate we don't get twice. For example, if we only receive an ABS_X event, we transform the already transformed device->abs.y again in transform_absolute() when applying the calibration. --- src/evdev.c | 54 ++++++++++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 29e32136..a3d274a0 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -236,33 +236,32 @@ is_motion_event(struct input_event *e) } static void -transform_absolute(struct evdev_device *device) +transform_absolute(struct evdev_device *device, int32_t *x, int32_t *y) { - int32_t x, 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]; - if (!device->abs.apply_calibration) - return; - - 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]; - - device->abs.x = x; - device->abs.y = y; + *y = device->abs.x * device->abs.calibration[3] + + device->abs.y * device->abs.calibration[4] + + device->abs.calibration[5]; + } } static void evdev_flush_motion(struct evdev_device *device, uint32_t time) { - struct weston_seat *master = device->seat; - wl_fixed_t x, y; - int slot; + struct weston_seat *master = device->seat; + wl_fixed_t x, y; + int32_t cx, cy; + int slot; - if (!(device->pending_events & EVDEV_SYN)) + if (!(device->pending_events & EVDEV_SYN)) return; slot = device->mt.slot; @@ -296,16 +295,15 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) if (device->pending_events & EVDEV_ABSOLUTE_MT_UP) { notify_touch(master, time, device->mt.slot, 0, 0, WL_TOUCH_UP); - device->pending_events &= ~EVDEV_ABSOLUTE_MT_UP; - } - if (device->pending_events & EVDEV_ABSOLUTE_MOTION) { - transform_absolute(device); - weston_output_transform_coordinate(device->output, - device->abs.x, - device->abs.y, &x, &y); + device->pending_events &= ~EVDEV_ABSOLUTE_MT_UP; + } + if (device->pending_events & EVDEV_ABSOLUTE_MOTION) { + transform_absolute(device, &cx, &cy); + weston_output_transform_coordinate(device->output, + cx, cy, &x, &y); - if (device->caps & EVDEV_TOUCH) { - if (master->num_tp == 0) + if (device->caps & EVDEV_TOUCH) { + if (master->num_tp == 0) notify_touch(master, time, 0, x, y, WL_TOUCH_DOWN); else From 2f9f6b257a7676e9b10349383fde69bf19476123 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Thu, 29 Aug 2013 13:49:35 -0700 Subject: [PATCH 142/162] evdev: Don't parse config file again, use compositor->config --- src/evdev-touchpad.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 81acbd04..600df073 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -675,19 +675,15 @@ struct evdev_dispatch_interface touchpad_interface = { static void touchpad_parse_config(struct touchpad_dispatch *touchpad, double diagonal) { - struct weston_config *config; + struct weston_compositor *compositor = + touchpad->device->seat->compositor; struct weston_config_section *s; - int config_fd; - double constant_accel_factor; double min_accel_factor; double max_accel_factor; - config_fd = open_config_file("weston.ini"); - config = weston_config_parse(config_fd); - close(config_fd); - - s = weston_config_get_section(config, "touchpad", NULL, NULL); + 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); From 6f96846e0a33eb3eccb58e62b782200a1e959b74 Mon Sep 17 00:00:00 2001 From: Hardening Date: Wed, 18 Sep 2013 23:56:35 +0200 Subject: [PATCH 143/162] Rename current, origin, scale, origin_scale This patch renames that fields to have consistent names. --- src/evdev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index a3d274a0..2367d56b 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -104,8 +104,8 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time) static void evdev_process_touch(struct evdev_device *device, struct input_event *e) { - const int screen_width = device->output->current->width; - const int screen_height = device->output->current->height; + const int screen_width = device->output->current_mode->width; + const int screen_height = device->output->current_mode->height; switch (e->code) { case ABS_MT_SLOT: @@ -136,8 +136,8 @@ static inline void evdev_process_absolute_motion(struct evdev_device *device, struct input_event *e) { - const int screen_width = device->output->current->width; - const int screen_height = device->output->current->height; + const int screen_width = device->output->current_mode->width; + const int screen_height = device->output->current_mode->height; switch (e->code) { case ABS_X: From b3023f5d0ac71798d83fc9f6755c88e40abbb9dc Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 20 Sep 2013 15:03:29 +0100 Subject: [PATCH 144/162] evdev: Flush motion events when the slot changes, not just after sync If two fingers are released almost simultaneously then evdev can send the touch up events in one bunch without sending a sync event in-between. However, the evdev_device struct only keeps track of one pending touch up event so in this case the second touch up event would override the first and it would be lost. This patch changes it to also flush the events whenever the slot changes so that it will flush the previous touch up event before trying to queue the next one. https://bugs.freedesktop.org/show_bug.cgi?id=67563 --- src/evdev-touchpad.c | 2 +- src/evdev.c | 7 ++++--- src/evdev.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 600df073..aa9df62c 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -493,7 +493,7 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) touchpad->device->rel.dx = wl_fixed_from_double(dx); touchpad->device->rel.dy = wl_fixed_from_double(dy); touchpad->device->pending_events |= - EVDEV_RELATIVE_MOTION | EVDEV_SYN; + EVDEV_RELATIVE_MOTION | EVDEV_SYN_OR_SLOT; } else if (touchpad->finger_state == TOUCHPAD_FINGERS_TWO) { if (dx != 0.0) notify_axis(touchpad->device->seat, diff --git a/src/evdev.c b/src/evdev.c index 2367d56b..3ccdd3ca 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -110,6 +110,7 @@ evdev_process_touch(struct evdev_device *device, struct input_event *e) switch (e->code) { case ABS_MT_SLOT: device->mt.slot = e->value; + device->pending_events |= EVDEV_SYN_OR_SLOT; break; case ABS_MT_TRACKING_ID: if (e->value >= 0) @@ -261,11 +262,11 @@ evdev_flush_motion(struct evdev_device *device, uint32_t time) int32_t cx, cy; int slot; - if (!(device->pending_events & EVDEV_SYN)) + if (!(device->pending_events & EVDEV_SYN_OR_SLOT)) return; slot = device->mt.slot; - device->pending_events &= ~EVDEV_SYN; + device->pending_events &= ~EVDEV_SYN_OR_SLOT; if (device->pending_events & EVDEV_RELATIVE_MOTION) { notify_motion(master, time, device->rel.dx, device->rel.dy); device->pending_events &= ~EVDEV_RELATIVE_MOTION; @@ -332,7 +333,7 @@ fallback_process(struct evdev_dispatch *dispatch, evdev_process_key(device, event, time); break; case EV_SYN: - device->pending_events |= EVDEV_SYN; + device->pending_events |= EVDEV_SYN_OR_SLOT; break; } } diff --git a/src/evdev.h b/src/evdev.h index 524fa229..7edcce6e 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -36,7 +36,7 @@ enum evdev_event_type { EVDEV_ABSOLUTE_MT_MOTION = (1 << 2), EVDEV_ABSOLUTE_MT_UP = (1 << 3), EVDEV_RELATIVE_MOTION = (1 << 4), - EVDEV_SYN = (1 << 5), + EVDEV_SYN_OR_SLOT = (1 << 5), }; enum evdev_device_capability { From 96ec0936ca96943a18377410b7b81f7043fc74fd Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 24 Sep 2013 12:09:03 +0100 Subject: [PATCH 145/162] evdev: Only track one pending event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of having a mask of pending events there is now an enum with a single value to represent the one pending event. The event gets flushed explicitly as part of the handling code for each event type rather than in the outer event reading loop. The pending event is used so that we can combine multiple motion events into one and to make sure that we have recieved the latest position before sending a touch up or down event. This should fix the following problems with the old approach: • If you release a finger and press it down again quickly you could get the up and down events in the same batch. However the pending events were always processed in the order down then up so it would end up notifying two down events and then an up. The pending event is now always flushed when there is a new up or down event so they will always be in the right order. • When it got a slot event it would immediately change the slot number and then set the pending event. Then when it flushed the events it would use the new slot number to flush the old pending event so the events could have the wrong finger. The pending event is now immediately flushed when a slot event is received so it will have the right finger. • If you get more than 32 events in one read then it was resetting the pending events before processing the next batch in evdev_process_events. If four fingers were pressed down at once then it ended up with more than 32 events and the sync message would be in the second batch. The pending flag for the last finger was getting cleared so it never got emitted. In this patch the pending event is no longer reset after reading nor is it explicitly flushed. Instead it is flushed when we receive a EV_SYN event or a different pending event needs to replace it. The touchpad handling code was trying to use the pending event mechanism to notify the relative motion events. I'm not sure why it was doing this because it looks the event would effectively get emitted as soon as the touchpad_process function is finished anyway and it wasn't accumulating the values. Instead I've just changed it to emit the event directly. https://bugs.freedesktop.org/show_bug.cgi?id=67563 --- src/evdev-touchpad.c | 7 +- src/evdev.c | 246 ++++++++++++++++++++----------------------- src/evdev.h | 19 ++-- 3 files changed, 129 insertions(+), 143 deletions(-) diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index aa9df62c..69f913ac 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -490,10 +490,9 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) filter_motion(touchpad, &dx, &dy, time); if (touchpad->finger_state == TOUCHPAD_FINGERS_ONE) { - touchpad->device->rel.dx = wl_fixed_from_double(dx); - touchpad->device->rel.dy = wl_fixed_from_double(dy); - touchpad->device->pending_events |= - EVDEV_RELATIVE_MOTION | EVDEV_SYN_OR_SLOT; + 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, diff --git a/src/evdev.c b/src/evdev.c index 3ccdd3ca..c1e11d38 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "compositor.h" #include "evdev.h" @@ -64,6 +65,85 @@ evdev_led_update(struct evdev_device *device, enum weston_led leds) (void)i; /* no, we really don't care about the return value */ } +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) +{ + struct weston_seat *master = device->seat; + wl_fixed_t x, y; + int32_t cx, cy; + int slot; + + slot = device->mt.slot; + + 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, + device->mt.slots[slot].x, + 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, + device->mt.slots[slot].x, + 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_MOTION: + transform_absolute(device, &cx, &cy); + weston_output_transform_coordinate(device->output, + cx, cy, &x, &y); + + if (device->caps & EVDEV_TOUCH) { + if (master->num_tp == 0) + notify_touch(master, time, 0, + x, y, WL_TOUCH_DOWN); + else + notify_touch(master, time, 0, + x, y, WL_TOUCH_MOTION); + } else + notify_motion_absolute(master, time, x, y); + goto handled; + } + + assert(0 && "Unknown pending event type"); + +handled: + device->pending_event = EVDEV_NONE; +} + static inline void evdev_process_key(struct evdev_device *device, struct input_event *e, int time) { @@ -71,6 +151,8 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time) if (e->value == 2) return; + evdev_flush_pending_event(device, time); + switch (e->code) { case BTN_LEFT: case BTN_RIGHT: @@ -102,33 +184,40 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time) } static void -evdev_process_touch(struct evdev_device *device, struct input_event *e) +evdev_process_touch(struct evdev_device *device, + struct input_event *e, + uint32_t time) { const int screen_width = device->output->current_mode->width; const int screen_height = device->output->current_mode->height; switch (e->code) { case ABS_MT_SLOT: + evdev_flush_pending_event(device, time); device->mt.slot = e->value; - device->pending_events |= EVDEV_SYN_OR_SLOT; 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_events |= EVDEV_ABSOLUTE_MT_DOWN; + device->pending_event = EVDEV_ABSOLUTE_MT_DOWN; else - device->pending_events |= EVDEV_ABSOLUTE_MT_UP; + device->pending_event = EVDEV_ABSOLUTE_MT_UP; break; case ABS_MT_POSITION_X: - device->mt.x[device->mt.slot] = + device->mt.slots[device->mt.slot].x = (e->value - device->abs.min_x) * screen_width / (device->abs.max_x - device->abs.min_x); - device->pending_events |= EVDEV_ABSOLUTE_MT_MOTION; + if (device->pending_event == EVDEV_NONE) + device->pending_event = EVDEV_ABSOLUTE_MT_MOTION; break; case ABS_MT_POSITION_Y: - device->mt.y[device->mt.slot] = + device->mt.slots[device->mt.slot].y = (e->value - device->abs.min_y) * screen_height / (device->abs.max_y - device->abs.min_y); - device->pending_events |= EVDEV_ABSOLUTE_MT_MOTION; + if (device->pending_event == EVDEV_NONE) + device->pending_event = EVDEV_ABSOLUTE_MT_MOTION; break; } } @@ -145,13 +234,15 @@ evdev_process_absolute_motion(struct evdev_device *device, device->abs.x = (e->value - device->abs.min_x) * screen_width / (device->abs.max_x - device->abs.min_x); - device->pending_events |= EVDEV_ABSOLUTE_MOTION; + 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); - device->pending_events |= EVDEV_ABSOLUTE_MOTION; + if (device->pending_event == EVDEV_NONE) + device->pending_event = EVDEV_ABSOLUTE_MOTION; break; } } @@ -162,14 +253,19 @@ evdev_process_relative(struct evdev_device *device, { 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_events |= EVDEV_RELATIVE_MOTION; + 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_events |= EVDEV_RELATIVE_MOTION; + device->pending_event = EVDEV_RELATIVE_MOTION; break; case REL_WHEEL: + evdev_flush_pending_event(device, time); switch (e->value) { case -1: /* Scroll down */ @@ -185,6 +281,7 @@ evdev_process_relative(struct evdev_device *device, } break; case REL_HWHEEL: + evdev_flush_pending_event(device, time); switch (e->value) { case -1: /* Scroll left */ @@ -203,119 +300,17 @@ evdev_process_relative(struct evdev_device *device, } static inline void -evdev_process_absolute(struct evdev_device *device, struct input_event *e) +evdev_process_absolute(struct evdev_device *device, + struct input_event *e, + uint32_t time) { if (device->is_mt) { - evdev_process_touch(device, e); + evdev_process_touch(device, e, time); } else { evdev_process_absolute_motion(device, e); } } -static int -is_motion_event(struct input_event *e) -{ - switch (e->type) { - case EV_REL: - switch (e->code) { - case REL_X: - case REL_Y: - return 1; - } - break; - case EV_ABS: - switch (e->code) { - case ABS_X: - case ABS_Y: - case ABS_MT_POSITION_X: - case ABS_MT_POSITION_Y: - return 1; - } - } - - return 0; -} - -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_motion(struct evdev_device *device, uint32_t time) -{ - struct weston_seat *master = device->seat; - wl_fixed_t x, y; - int32_t cx, cy; - int slot; - - if (!(device->pending_events & EVDEV_SYN_OR_SLOT)) - return; - - slot = device->mt.slot; - device->pending_events &= ~EVDEV_SYN_OR_SLOT; - if (device->pending_events & EVDEV_RELATIVE_MOTION) { - notify_motion(master, time, device->rel.dx, device->rel.dy); - device->pending_events &= ~EVDEV_RELATIVE_MOTION; - device->rel.dx = 0; - device->rel.dy = 0; - } - if (device->pending_events & EVDEV_ABSOLUTE_MT_DOWN) { - weston_output_transform_coordinate(device->output, - device->mt.x[slot], - device->mt.y[slot], - &x, &y); - notify_touch(master, time, - device->mt.slot, x, y, WL_TOUCH_DOWN); - device->pending_events &= ~EVDEV_ABSOLUTE_MT_DOWN; - device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION; - } - if (device->pending_events & EVDEV_ABSOLUTE_MT_MOTION) { - weston_output_transform_coordinate(device->output, - device->mt.x[slot], - device->mt.y[slot], - &x, &y); - notify_touch(master, time, - device->mt.slot, x, y, WL_TOUCH_MOTION); - device->pending_events &= ~EVDEV_ABSOLUTE_MT_DOWN; - device->pending_events &= ~EVDEV_ABSOLUTE_MT_MOTION; - } - if (device->pending_events & EVDEV_ABSOLUTE_MT_UP) { - notify_touch(master, time, device->mt.slot, 0, 0, - WL_TOUCH_UP); - device->pending_events &= ~EVDEV_ABSOLUTE_MT_UP; - } - if (device->pending_events & EVDEV_ABSOLUTE_MOTION) { - transform_absolute(device, &cx, &cy); - weston_output_transform_coordinate(device->output, - cx, cy, &x, &y); - - if (device->caps & EVDEV_TOUCH) { - if (master->num_tp == 0) - notify_touch(master, time, 0, - x, y, WL_TOUCH_DOWN); - else - notify_touch(master, time, 0, - x, y, WL_TOUCH_MOTION); - } else - notify_motion_absolute(master, time, x, y); - device->pending_events &= ~EVDEV_ABSOLUTE_MOTION; - } -} - static void fallback_process(struct evdev_dispatch *dispatch, struct evdev_device *device, @@ -327,13 +322,13 @@ fallback_process(struct evdev_dispatch *dispatch, evdev_process_relative(device, event, time); break; case EV_ABS: - evdev_process_absolute(device, event); + evdev_process_absolute(device, event, time); break; case EV_KEY: evdev_process_key(device, event, time); break; case EV_SYN: - device->pending_events |= EVDEV_SYN_OR_SLOT; + evdev_flush_pending_event(device, time); break; } } @@ -369,23 +364,13 @@ evdev_process_events(struct evdev_device *device, struct input_event *e, *end; uint32_t time = 0; - device->pending_events = 0; - e = ev; end = e + count; for (e = ev; e < end; e++) { time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000; - /* we try to minimize the amount of notifications to be - * forwarded to the compositor, so we accumulate motion - * events and send as a bunch */ - if (!is_motion_event(e)) - evdev_flush_motion(device, time); - dispatch->interface->process(dispatch, device, e, time); } - - evdev_flush_motion(device, time); } static int @@ -601,6 +586,7 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) 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); diff --git a/src/evdev.h b/src/evdev.h index 7edcce6e..6d916202 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -31,12 +31,12 @@ #define MAX_SLOTS 16 enum evdev_event_type { - EVDEV_ABSOLUTE_MOTION = (1 << 0), - EVDEV_ABSOLUTE_MT_DOWN = (1 << 1), - EVDEV_ABSOLUTE_MT_MOTION = (1 << 2), - EVDEV_ABSOLUTE_MT_UP = (1 << 3), - EVDEV_RELATIVE_MOTION = (1 << 4), - EVDEV_SYN_OR_SLOT = (1 << 5), + EVDEV_NONE, + EVDEV_ABSOLUTE_MOTION, + EVDEV_ABSOLUTE_MT_DOWN, + EVDEV_ABSOLUTE_MT_MOTION, + EVDEV_ABSOLUTE_MT_UP, + EVDEV_RELATIVE_MOTION, }; enum evdev_device_capability { @@ -66,8 +66,9 @@ struct evdev_device { struct { int slot; - int32_t x[MAX_SLOTS]; - int32_t y[MAX_SLOTS]; + struct { + int32_t x, y; + } slots[MAX_SLOTS]; } mt; struct mtdev *mtdev; @@ -75,7 +76,7 @@ struct evdev_device { wl_fixed_t dx, dy; } rel; - enum evdev_event_type pending_events; + enum evdev_event_type pending_event; enum evdev_device_capability caps; int is_mt; From ee5f763fc81bd1eddd2963392ea92e3c1c0f724a Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Tue, 24 Sep 2013 20:05:07 +0100 Subject: [PATCH 146/162] evdev: Process touch up events of single-touch devices Previously only the touch up key event was used for single-touch devices and the touch down event was generated on the first motion event. This was breaking if the touch up and down events were sent without a motion in-between because the evdev driver wouldn't generate a touch down event and Weston would lose track of the number of touch points that are down. This patch changes it to track the up and down key events as pending events similar to how it does for multi-touch devices. https://bugs.freedesktop.org/show_bug.cgi?id=69759 --- src/evdev.c | 43 ++++++++++++++++++++++++++++++------------- src/evdev.h | 2 ++ 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index c1e11d38..48e5470d 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -121,21 +121,25 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) 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, + cx, 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, cx, cy, &x, &y); - if (device->caps & EVDEV_TOUCH) { - if (master->num_tp == 0) - notify_touch(master, time, 0, - x, y, WL_TOUCH_DOWN); - else - notify_touch(master, time, 0, - x, y, WL_TOUCH_MOTION); - } else + 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; } assert(0 && "Unknown pending event type"); @@ -144,6 +148,18 @@ handled: device->pending_event = EVDEV_NONE; } +static void +evdev_process_touch_button(struct evdev_device *device, int time, int value) +{ + 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) { @@ -151,6 +167,12 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time) if (e->value == 2) return; + if (e->code == BTN_TOUCH) { + if (!device->is_mt) + evdev_process_touch_button(device, time, e->value); + return; + } + evdev_flush_pending_event(device, time); switch (e->code) { @@ -168,11 +190,6 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time) WL_POINTER_BUTTON_STATE_RELEASED); break; - case BTN_TOUCH: - if (e->value == 0 && !device->is_mt) - notify_touch(device->seat, time, 0, 0, 0, - WL_TOUCH_UP); - break; default: notify_key(device->seat, time, e->code, diff --git a/src/evdev.h b/src/evdev.h index 6d916202..5e4d11ac 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -32,7 +32,9 @@ 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, From 5d493ad6f452bcfd46270cdfe3b906cf4ffe9aca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 14 Oct 2013 15:28:01 -0700 Subject: [PATCH 147/162] evdev: Stop looking for pointer buttons when we get to BTN_JOYSTICK We don't want to mark a touchscreen as a button device just because it exposes the BTN_TOUCH and BTN_TOOL buttons. --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 48e5470d..e9235d9b 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -524,7 +524,7 @@ evdev_handle_device(struct evdev_device *device) break; } } - for (i = BTN_MISC; i < KEY_OK; i++) { + for (i = BTN_MISC; i < BTN_JOYSTICK; i++) { if (TEST_BIT(key_bits, i)) { device->caps |= EVDEV_BUTTON; break; From 3fc0ec1bc3694dabb70713d7c133659e0d0f7992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 14 Oct 2013 15:32:08 -0700 Subject: [PATCH 148/162] evdev: Only init a pointer if the evdev device has a button We used to test for abs | rel | button, which inits a pointer device for a device with just rel or abs capabilities. We now make sure we have either rel or abs as well as button. --- src/evdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index e9235d9b..0bfe94d6 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -555,8 +555,8 @@ evdev_handle_device(struct evdev_device *device) static int evdev_configure_device(struct evdev_device *device) { - if ((device->caps & - (EVDEV_MOTION_ABS | EVDEV_MOTION_REL | EVDEV_BUTTON))) { + if ((device->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL)) && + (device->caps & EVDEV_BUTTON)) { weston_seat_init_pointer(device->seat); weston_log("input device %s, %s is a pointer caps =%s%s%s\n", device->devname, device->devnode, From d4c9c6b83b916d48e2517c87be20bd3c00f513bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Mon, 14 Oct 2013 15:46:13 -0700 Subject: [PATCH 149/162] evdev: Clear touch capability if we see a mouse-type button If an input device has BTN_LEFT (typically) it's not a touch screen but a touch pad. --- src/evdev.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 0bfe94d6..edea3968 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -524,16 +524,16 @@ evdev_handle_device(struct evdev_device *device) break; } } - for (i = BTN_MISC; i < BTN_JOYSTICK; i++) { - if (TEST_BIT(key_bits, i)) { - device->caps |= EVDEV_BUTTON; - 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; From b98d0b9d89dd73e98599f1f796eec97f6ce6a3ef Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 15 Oct 2013 14:29:56 +0200 Subject: [PATCH 150/162] evdev: release devices on read() error If read() fails without EAGAIN/EINTR, the device is very likely dead. However, we must not remove the device as it might be muted/revoked. So we simply remove the event-source to avoid polling the device and simply wait for the udev-remove signal now. Note that we cannot call evdev_device_destroy() as the caller created the FD and might need custom code to close it (like weston_launcher_close()). --- src/evdev.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index edea3968..7397ea1d 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -22,6 +22,7 @@ #include "config.h" +#include #include #include #include @@ -414,7 +415,13 @@ evdev_device_data(int fd, uint32_t mask, void *data) len = read(fd, &ev, sizeof ev); if (len < 0 || len % sizeof ev[0] != 0) { - /* FIXME: call evdev_device_destroy when errno is ENODEV. */ + 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; } From c442b9fd608cd92dc14e97bc9351e5e214feb6db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 17 Oct 2013 23:04:05 +0200 Subject: [PATCH 151/162] evdev: Reference count input device's seat capabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the only input device of a certain seat capability is unplugged, stop advertising the capability. Signed-off-by: Jonas Ådahl --- src/evdev.c | 11 +++++++++++ src/evdev.h | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/src/evdev.c b/src/evdev.c index 7397ea1d..eb7631a7 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -565,6 +565,7 @@ evdev_configure_device(struct evdev_device *device) 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" : "", @@ -574,11 +575,13 @@ evdev_configure_device(struct evdev_device *device) 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); } @@ -602,6 +605,7 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) 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); @@ -649,6 +653,13 @@ 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); diff --git a/src/evdev.h b/src/evdev.h index 5e4d11ac..e146d1a4 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -49,6 +49,12 @@ enum evdev_device_capability { EVDEV_TOUCH = (1 << 4), }; +enum evdev_device_seat_capability { + EVDEV_SEAT_POINTER = (1 << 0), + EVDEV_SEAT_KEYBOARD = (1 << 1), + EVDEV_SEAT_TOUCH = (1 << 2) +}; + struct evdev_device { struct weston_seat *seat; struct wl_list link; @@ -80,6 +86,7 @@ struct evdev_device { enum evdev_event_type pending_event; enum evdev_device_capability caps; + enum evdev_device_seat_capability seat_caps; int is_mt; }; From 077e0c937a555f865d38158ec61a8cb55d92e977 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 22 Oct 2013 12:40:54 -0700 Subject: [PATCH 152/162] compositor: Remove redundant and not well-defined focus field It was never clear what this field really did. --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index eb7631a7..ad7a3f6b 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -400,7 +400,7 @@ evdev_device_data(int fd, uint32_t mask, void *data) int len; ec = device->seat->compositor; - if (!ec->focus) + if (!ec->session_active) return 1; /* If the compositor is repainting, this function is called only once From 098ca89e1744ddf540fef18135bbf43140d8ccb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sun, 10 Nov 2013 00:30:10 +0100 Subject: [PATCH 153/162] Make weston_output_transform_coordinate() take wl_fixed_t coordinates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is to make it possible for future API to have non-integer coordinates as input. Signed-off-by: Jonas Ådahl --- src/evdev.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index ad7a3f6b..50ce8713 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -103,18 +103,18 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) device->rel.dy = 0; goto handled; case EVDEV_ABSOLUTE_MT_DOWN: + x = wl_fixed_from_int(device->mt.slots[slot].x); + y = wl_fixed_from_int(device->mt.slots[slot].y); weston_output_transform_coordinate(device->output, - device->mt.slots[slot].x, - device->mt.slots[slot].y, - &x, &y); + x, y, &x, &y); notify_touch(master, time, slot, x, y, WL_TOUCH_DOWN); goto handled; case EVDEV_ABSOLUTE_MT_MOTION: + x = wl_fixed_from_int(device->mt.slots[slot].x); + y = wl_fixed_from_int(device->mt.slots[slot].y); weston_output_transform_coordinate(device->output, - device->mt.slots[slot].x, - device->mt.slots[slot].y, - &x, &y); + x, y, &x, &y); notify_touch(master, time, slot, x, y, WL_TOUCH_MOTION); goto handled; @@ -124,14 +124,18 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) goto handled; case EVDEV_ABSOLUTE_TOUCH_DOWN: transform_absolute(device, &cx, &cy); + x = wl_fixed_from_int(cx); + y = wl_fixed_from_int(cy); weston_output_transform_coordinate(device->output, - cx, cy, &x, &y); + x, y, &x, &y); notify_touch(master, time, 0, x, y, WL_TOUCH_DOWN); goto handled; case EVDEV_ABSOLUTE_MOTION: transform_absolute(device, &cx, &cy); + x = wl_fixed_from_int(cx); + y = wl_fixed_from_int(cy); weston_output_transform_coordinate(device->output, - cx, cy, &x, &y); + x, y, &x, &y); if (device->caps & EVDEV_TOUCH) notify_touch(master, time, 0, x, y, WL_TOUCH_MOTION); From 75f453df6a4c5f358f9bcb91a0cb8ab08593896e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sun, 10 Nov 2013 16:35:32 +0100 Subject: [PATCH 154/162] evdev: Synchronize keys only if seat is keyboard capable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl --- src/evdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/evdev.c b/src/evdev.c index 50ce8713..327a93fa 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -691,7 +691,7 @@ evdev_notify_keyboard_focus(struct weston_seat *seat, uint32_t *k; int ret; - if (!seat->keyboard) + if (!seat->keyboard_device_count > 0) return; memset(all_keys, 0, sizeof all_keys); From fdf50bc34bb150bc1cf04f37ad6d8bc1e708c7bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Tue, 12 Nov 2013 21:52:03 +0100 Subject: [PATCH 155/162] filter: Remove unused variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl --- src/filter.c | 1 - src/filter.h | 1 - 2 files changed, 2 deletions(-) diff --git a/src/filter.c b/src/filter.c index a55ebf27..89237bf8 100644 --- a/src/filter.c +++ b/src/filter.c @@ -323,7 +323,6 @@ create_pointer_accelator_filter(accel_profile_func_t profile) return NULL; filter->base.interface = &accelerator_interface; - wl_list_init(&filter->base.link); filter->profile = profile; filter->last_velocity = 0.0; diff --git a/src/filter.h b/src/filter.h index 850ce8df..dad538b2 100644 --- a/src/filter.h +++ b/src/filter.h @@ -50,7 +50,6 @@ struct weston_motion_filter_interface { struct weston_motion_filter { struct weston_motion_filter_interface *interface; - struct wl_list link; }; WL_EXPORT struct weston_motion_filter * From bd4db1c2a21fddd9b1135a41c5adaff3db0f8b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sun, 10 Nov 2013 17:55:40 +0100 Subject: [PATCH 156/162] Port evdev code to be used as a shared library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit introduces build script configuration for building a shared library 'libinput.so' containing the evdev input device functionality from weston. evdev.c, evdev.h and evdev-touchpad.c are ported to not use the data structures and API in weston and libwayland-server in order to minimize dependencies. The API of filter.c and filter.h are renamed to not include the 'weston_' prefix. Signed-off-by: Jonas Ådahl --- .gitignore | 26 +++ Makefile.am | 3 + README | 9 + autogen.sh | 9 + configure.ac | 53 ++++++ m4/.gitignore | 5 + src/Makefile.am | 26 +++ src/evdev-touchpad.c | 221 ++++++++++++++----------- src/evdev.c | 340 ++++++++++++++++++-------------------- src/evdev.h | 37 +++-- src/filter.c | 23 ++- src/filter.h | 44 +++-- src/libinput-private.h | 102 ++++++++++++ src/libinput-version.h.in | 31 ++++ src/libinput.c | 168 +++++++++++++++++++ src/libinput.h | 173 +++++++++++++++++++ src/libinput.pc.in | 12 ++ 17 files changed, 961 insertions(+), 321 deletions(-) create mode 100644 .gitignore create mode 100644 Makefile.am create mode 100644 README create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 m4/.gitignore create mode 100644 src/Makefile.am create mode 100644 src/libinput-private.h create mode 100644 src/libinput-version.h.in create mode 100644 src/libinput.c create mode 100644 src/libinput.h create mode 100644 src/libinput.pc.in diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..30a27dc1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +*.o +*.pc +*.la +*.lo +Makefile +Makefile.in +aclocal.m4 +autom4te.cache/ +config.guess +config.h +config.h.in +config.log +config.status +config.sub +configure +depcomp +install-sh +libtool +ltmain.sh +missing +stamp-h1 +src/.libs/ +src/.deps/ +src/Makefile +src/Makefile.in +src/libinput-version.h diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..3a7ce7e8 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,3 @@ +SUBDIRS = src + +ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} diff --git a/README b/README new file mode 100644 index 00000000..06c30923 --- /dev/null +++ b/README @@ -0,0 +1,9 @@ +This library does processing on input device events while providing an API +to the the user used for delegating more useful input events. + +Input event processing includes scaling touch coordinates, generating +pointer events from touchpads, pointer acceleration, etc. + +It is based on the input code from the weston Wayland reference compositor. + +It has no other dependencies than libmtdev and supports only evdev devices. diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..b08bc831 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +test -n "$srcdir" || srcdir=`dirname "$0"` +test -n "$srcdir" || srcdir=. +( + cd "$srcdir" && + autoreconf --force -v --install +) || exit +test -n "$NOCONFIGURE" || "$srcdir/configure" "$@" diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..8e0f1c93 --- /dev/null +++ b/configure.ac @@ -0,0 +1,53 @@ +AC_PREREQ([2.64]) + +m4_define([libinput_major_version], [0]) +m4_define([libinput_minor_version], [0]) +m4_define([libinput_micro_version], [90]) +m4_define([libinput_version], + [libinput_major_version.libinput_minor_version.libinput_micro_version]) + +AC_INIT([libinput], + [libinput_version], + [http://nobugtracker], + [libinput], + [http://nohomepage]) + +AC_SUBST([LIBINPUT_VERSION_MAJOR], [libinput_major_version]) +AC_SUBST([LIBINPUT_VERSION_MINOR], [libinput_minor_version]) +AC_SUBST([LIBINPUT_VERSION_MICRO], [libinput_micro_version]) +AC_SUBST([LIBINPUT_VERSION], [libinput_version]) + +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_MACRO_DIR([m4]) + +AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz]) + +AM_SILENT_RULES([yes]) + +# Check for programs +AC_PROG_CC + +# Initialize libtool +LT_PREREQ([2.2]) +LT_INIT + +AC_CHECK_DECL(TFD_CLOEXEC,[], + [AC_MSG_ERROR("TFD_CLOEXEC is needed to compile libinput")], + [[#include ]]) +AC_CHECK_DECL(CLOCK_MONOTONIC,[], + [AC_MSG_ERROR("CLOCK_MONOTONIC is needed to compile libinput")], + [[#include ]]) + +PKG_PROG_PKG_CONFIG() +PKG_CHECK_MODULES(MTDEV, [mtdev >= 1.1.0]) + +if test "x$GCC" = "xyes"; then + GCC_CFLAGS="-Wall -Wextra -Wno-unused-parameter -g -Wstrict-prototypes -Wmissing-prototypes -fvisibility=hidden" +fi +AC_SUBST(GCC_CFLAGS) + +AC_CONFIG_FILES([Makefile + src/Makefile + src/libinput.pc + src/libinput-version.h]) +AC_OUTPUT diff --git a/m4/.gitignore b/m4/.gitignore new file mode 100644 index 00000000..38066ddf --- /dev/null +++ b/m4/.gitignore @@ -0,0 +1,5 @@ +libtool.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 +lt~obsolete.m4 diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 00000000..00b052e2 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,26 @@ +lib_LTLIBRARIES = libinput.la + +include_HEADERS = \ + libinput.h + +libinput_la_SOURCES = \ + libinput.c \ + libinput.h \ + evdev.c \ + evdev.h \ + evdev-touchpad.c \ + filter.c \ + filter.h + +libinput_la_LIBADD = $(MTDEV_LIBS) +libinput_la_CFLAGS = $(MTDEV_CFLAGS) \ + $(GCC_CFLAGS) + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libinput.pc + +AM_CPPFLAGS = $(FFI_CFLAGS) +AM_CFLAGS = $(GCC_CFLAGS) + +DISTCLEANFILES = libinput-version.h +EXTRA_DIST = libinput-version.h.in diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 69f913ac..6268dffa 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -22,16 +22,19 @@ #include "config.h" +#include #include #include #include #include +#include #include #include +#include -#include "filter.h" #include "evdev.h" -#include "../shared/config-parser.h" +#include "filter.h" +#include "libinput-private.h" /* Default values */ #define DEFAULT_CONSTANT_ACCEL_NUMERATOR 50 @@ -127,9 +130,15 @@ struct touchpad_dispatch { struct { bool enable; - struct wl_array events; + + enum fsm_event *events; + size_t events_len; + size_t events_count; enum fsm_state state; - struct wl_event_source *timer_source; + struct { + int fd; + struct libinput_fd_handle *fd_handle; + } timer; } fsm; struct { @@ -154,7 +163,7 @@ struct touchpad_dispatch { int motion_index; unsigned int motion_count; - struct weston_motion_filter *filter; + struct motion_filter *filter; }; static enum touchpad_model @@ -198,7 +207,7 @@ configure_touchpad_pressure(struct touchpad_dispatch *touchpad, } static double -touchpad_profile(struct weston_motion_filter *filter, +touchpad_profile(struct motion_filter *filter, void *data, double velocity, uint32_t time) @@ -265,12 +274,12 @@ static void filter_motion(struct touchpad_dispatch *touchpad, double *dx, double *dy, uint32_t time) { - struct weston_motion_params motion; + struct motion_params motion; motion.dx = *dx; motion.dy = *dy; - weston_filter_dispatch(touchpad->filter, &motion, touchpad, time); + filter_dispatch(touchpad->filter, &motion, touchpad, time); *dx = motion.dx; *dy = motion.dy; @@ -279,17 +288,21 @@ filter_motion(struct touchpad_dispatch *touchpad, 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); + pointer_notify_button( + &touchpad->device->base, + time, + DEFAULT_TOUCHPAD_SINGLE_TAP_BUTTON, + LIBINPUT_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); + pointer_notify_button( + &touchpad->device->base, + time, + DEFAULT_TOUCHPAD_SINGLE_TAP_BUTTON, + LIBINPUT_POINTER_BUTTON_STATE_RELEASED); } static void @@ -303,17 +316,17 @@ 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; + unsigned int i; if (!touchpad->fsm.enable) return; - if (touchpad->fsm.events.size == 0) + if (touchpad->fsm.events_count == 0) return; - wl_array_for_each(pevent, &touchpad->fsm.events) { - event = *pevent; + for (i = 0; i < touchpad->fsm.events_count; ++i) { + event = touchpad->fsm.events[i]; timeout = 0; switch (touchpad->fsm.state) { @@ -379,48 +392,78 @@ process_fsm_events(struct touchpad_dispatch *touchpad, uint32_t time) } 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); + if (timeout != UINT32_MAX) { + struct itimerspec its; - wl_array_release(&touchpad->fsm.events); - wl_array_init(&touchpad->fsm.events); + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + its.it_value.tv_sec = timeout / 1000; + its.it_value.tv_nsec = (timeout % 1000) * 1000 * 1000; + timerfd_settime(touchpad->fsm.timer.fd, 0, &its, NULL); + } + + touchpad->fsm.events_count = 0; } static void push_fsm_event(struct touchpad_dispatch *touchpad, enum fsm_event event) { - enum fsm_event *pevent; + enum fsm_event *events; + size_t new_len = touchpad->fsm.events_len; if (!touchpad->fsm.enable) return; - pevent = wl_array_add(&touchpad->fsm.events, sizeof event); - if (pevent) - *pevent = event; - else - touchpad->fsm.state = FSM_IDLE; -} + if (touchpad->fsm.events_count + 1 >= touchpad->fsm.events_len) { + if (new_len == 0) + new_len = 4; + else + new_len *= 2; + events = realloc(touchpad->fsm.events, + sizeof(enum fsm_event) * new_len); + if (!events) { + touchpad->fsm.state = FSM_IDLE; + return; + } -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()); + touchpad->fsm.events = events; + touchpad->fsm.events_len = new_len; } - return 1; + touchpad->fsm.events[touchpad->fsm.events_count++] = event; +} + +static void +fsm_timeout_handler(int fd, void *data) +{ + struct evdev_device *device = data; + struct touchpad_dispatch *touchpad = + (struct touchpad_dispatch *) device->dispatch; + uint64_t expires; + int len; + struct timespec ts; + uint32_t now; + + len = read(fd, &expires, sizeof expires); + if (len != sizeof expires) + /* This will only happen if the application made the fd + * non-blocking, but this function should only be called + * upon the timeout, so lets continue anyway. */ + fprintf(stderr, "timerfd read error: %m\n"); + + if (touchpad->fsm.events_count == 0) { + clock_gettime(CLOCK_MONOTONIC, &ts); + now = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; + + push_fsm_event(touchpad, FSM_EVENT_TIMEOUT); + process_fsm_events(touchpad, now); + } } static void @@ -429,6 +472,7 @@ 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; + struct libinput_device *base = &touchpad->device->base; if (touchpad->reset || touchpad->last_finger_state != touchpad->finger_state) { @@ -490,20 +534,24 @@ touchpad_update_state(struct touchpad_dispatch *touchpad, uint32_t time) 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)); + pointer_notify_motion( + base, + time, + li_fixed_from_double(dx), + li_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)); + pointer_notify_axis( + base, + time, + LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL, + li_fixed_from_double(dx)); if (dy != 0.0) - notify_axis(touchpad->device->seat, - time, - WL_POINTER_AXIS_VERTICAL_SCROLL, - wl_fixed_from_double(dy)); + pointer_notify_axis( + base, + time, + LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL, + li_fixed_from_double(dy)); } } @@ -596,9 +644,12 @@ process_key(struct touchpad_dispatch *touchpad, 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); + pointer_notify_button( + &touchpad->device->base, + time, + code, + e->value ? LIBINPUT_POINTER_BUTTON_STATE_PRESSED : + LIBINPUT_POINTER_BUTTON_STATE_RELEASED); break; case BTN_TOOL_PEN: case BTN_TOOL_RUBBER: @@ -662,7 +713,11 @@ touchpad_destroy(struct evdev_dispatch *dispatch) (struct touchpad_dispatch *) dispatch; touchpad->filter->interface->destroy(touchpad->filter); - wl_event_source_remove(touchpad->fsm.timer_source); + touchpad->device->base.device_interface->remove_fd( + touchpad->fsm.timer.fd_handle, + touchpad->device->base.device_interface_data); + close(touchpad->fsm.timer.fd); + free(touchpad->fsm.events); free(dispatch); } @@ -671,40 +726,11 @@ struct evdev_dispatch_interface touchpad_interface = { 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; + struct motion_filter *accel; unsigned long prop_bits[INPUT_PROP_MAX]; struct input_absinfo absinfo; @@ -739,7 +765,11 @@ touchpad_init(struct touchpad_dispatch *touchpad, height = abs(device->abs.max_y - device->abs.min_y); diagonal = sqrt(width*width + height*height); - touchpad_parse_config(touchpad, diagonal); + /* Set default parameters */ + touchpad->constant_accel_factor = + DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal; + touchpad->min_accel_factor = DEFAULT_MIN_ACCEL_FACTOR; + touchpad->max_accel_factor = DEFAULT_MAX_ACCEL_FACTOR; touchpad->hysteresis.margin_x = diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR; @@ -765,13 +795,20 @@ touchpad_init(struct touchpad_dispatch *touchpad, touchpad->last_finger_state = 0; touchpad->finger_state = 0; - wl_array_init(&touchpad->fsm.events); + touchpad->fsm.events = NULL; + touchpad->fsm.events_count = 0; + touchpad->fsm.events_len = 0; 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) { + touchpad->fsm.timer.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); + touchpad->fsm.timer.fd_handle = + touchpad->device->base.device_interface->add_fd( + touchpad->fsm.timer.fd, + fsm_timeout_handler, + touchpad->device->base.device_interface_data); + + if (touchpad->fsm.timer.fd_handle == NULL) { + close(touchpad->fsm.timer.fd); accel->interface->destroy(accel); return -1; } diff --git a/src/evdev.c b/src/evdev.c index 327a93fa..aa2ffa99 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 @@ -31,21 +32,22 @@ #include #include -#include "compositor.h" +#include "libinput.h" #include "evdev.h" +#include "libinput-private.h" -#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10) +#define DEFAULT_AXIS_STEP_DISTANCE li_fixed_from_int(10) void -evdev_led_update(struct evdev_device *device, enum weston_led leds) +evdev_device_led_update(struct evdev_device *device, enum libinput_led leds) { static const struct { - enum weston_led weston; + enum libinput_led weston; int evdev; } map[] = { - { LED_NUM_LOCK, LED_NUML }, - { LED_CAPS_LOCK, LED_CAPSL }, - { LED_SCROLL_LOCK, LED_SCROLLL }, + { LIBINPUT_LED_NUM_LOCK, LED_NUML }, + { LIBINPUT_LED_CAPS_LOCK, LED_CAPSL }, + { LIBINPUT_LED_SCROLL_LOCK, LED_SCROLLL }, }; struct input_event ev[ARRAY_LENGTH(map) + 1]; unsigned int i; @@ -69,28 +71,27 @@ evdev_led_update(struct evdev_device *device, enum weston_led 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]; + 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]; - } + *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) { - struct weston_seat *master = device->seat; - wl_fixed_t x, y; int32_t cx, cy; int slot; + struct libinput_device *base = &device->base; slot = device->mt.slot; @@ -98,52 +99,65 @@ evdev_flush_pending_event(struct evdev_device *device, uint32_t time) case EVDEV_NONE: return; case EVDEV_RELATIVE_MOTION: - notify_motion(master, time, device->rel.dx, device->rel.dy); + pointer_notify_motion(base, + time, + device->rel.dx, + device->rel.dy); device->rel.dx = 0; device->rel.dy = 0; goto handled; case EVDEV_ABSOLUTE_MT_DOWN: - x = wl_fixed_from_int(device->mt.slots[slot].x); - y = wl_fixed_from_int(device->mt.slots[slot].y); - weston_output_transform_coordinate(device->output, - x, y, &x, &y); - notify_touch(master, time, - slot, x, y, WL_TOUCH_DOWN); + touch_notify_touch(base, + time, + slot, + li_fixed_from_int(device->mt.slots[slot].x), + li_fixed_from_int(device->mt.slots[slot].y), + LIBINPUT_TOUCH_TYPE_DOWN); goto handled; case EVDEV_ABSOLUTE_MT_MOTION: - x = wl_fixed_from_int(device->mt.slots[slot].x); - y = wl_fixed_from_int(device->mt.slots[slot].y); - weston_output_transform_coordinate(device->output, - x, y, &x, &y); - notify_touch(master, time, - slot, x, y, WL_TOUCH_MOTION); + touch_notify_touch(base, + time, + slot, + li_fixed_from_int(device->mt.slots[slot].x), + li_fixed_from_int(device->mt.slots[slot].y), + LIBINPUT_TOUCH_TYPE_MOTION); goto handled; case EVDEV_ABSOLUTE_MT_UP: - notify_touch(master, time, slot, 0, 0, - WL_TOUCH_UP); + touch_notify_touch(base, + time, + slot, + 0, 0, + LIBINPUT_TOUCH_TYPE_UP); goto handled; case EVDEV_ABSOLUTE_TOUCH_DOWN: transform_absolute(device, &cx, &cy); - x = wl_fixed_from_int(cx); - y = wl_fixed_from_int(cy); - weston_output_transform_coordinate(device->output, - x, y, &x, &y); - notify_touch(master, time, 0, x, y, WL_TOUCH_DOWN); + touch_notify_touch(base, + time, + slot, + li_fixed_from_int(cx), + li_fixed_from_int(cy), + LIBINPUT_TOUCH_TYPE_DOWN); goto handled; case EVDEV_ABSOLUTE_MOTION: transform_absolute(device, &cx, &cy); - x = wl_fixed_from_int(cx); - y = wl_fixed_from_int(cy); - weston_output_transform_coordinate(device->output, - x, y, &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); + if (device->caps & EVDEV_TOUCH) { + touch_notify_touch(base, + time, + slot, + li_fixed_from_int(cx), + li_fixed_from_int(cy), + LIBINPUT_TOUCH_TYPE_DOWN); + } else { + pointer_notify_motion_absolute(base, + time, + li_fixed_from_int(cx), + li_fixed_from_int(cy)); + } goto handled; case EVDEV_ABSOLUTE_TOUCH_UP: - notify_touch(master, time, 0, 0, 0, WL_TOUCH_UP); + touch_notify_touch(base, + time, + 0, 0, 0, LIBINPUT_TOUCH_TYPE_UP); goto handled; } @@ -189,18 +203,21 @@ evdev_process_key(struct evdev_device *device, struct input_event *e, int time) 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); + pointer_notify_button( + &device->base, + time, + e->code, + e->value ? LIBINPUT_POINTER_BUTTON_STATE_PRESSED : + LIBINPUT_POINTER_BUTTON_STATE_RELEASED); break; default: - notify_key(device->seat, - time, e->code, - e->value ? WL_KEYBOARD_KEY_STATE_PRESSED : - WL_KEYBOARD_KEY_STATE_RELEASED, - STATE_UPDATE_AUTOMATIC); + keyboard_notify_key( + &device->base, + time, + e->code, + e->value ? LIBINPUT_KEYBOARD_KEY_STATE_PRESSED : + LIBINPUT_KEYBOARD_KEY_STATE_RELEASED); break; } } @@ -210,8 +227,13 @@ evdev_process_touch(struct evdev_device *device, struct input_event *e, uint32_t time) { - const int screen_width = device->output->current_mode->width; - const int screen_height = device->output->current_mode->height; + int screen_width; + int screen_height; + + device->base.device_interface->get_current_screen_dimensions( + &screen_width, + &screen_height, + device->base.device_interface_data); switch (e->code) { case ABS_MT_SLOT: @@ -248,8 +270,13 @@ static inline void evdev_process_absolute_motion(struct evdev_device *device, struct input_event *e) { - const int screen_width = device->output->current_mode->width; - const int screen_height = device->output->current_mode->height; + int screen_width; + int screen_height; + + device->base.device_interface->get_current_screen_dimensions( + &screen_width, + &screen_height, + device->base.device_interface_data); switch (e->code) { case ABS_X: @@ -273,17 +300,19 @@ static inline void evdev_process_relative(struct evdev_device *device, struct input_event *e, uint32_t time) { + struct libinput_device *base = &device->base; + 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->rel.dx += li_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->rel.dy += li_fixed_from_int(e->value); device->pending_event = EVDEV_RELATIVE_MOTION; break; case REL_WHEEL: @@ -293,10 +322,11 @@ evdev_process_relative(struct evdev_device *device, /* Scroll down */ case 1: /* Scroll up */ - notify_axis(device->seat, - time, - WL_POINTER_AXIS_VERTICAL_SCROLL, - -1 * e->value * DEFAULT_AXIS_STEP_DISTANCE); + pointer_notify_axis( + base, + time, + LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL, + -1 * e->value * DEFAULT_AXIS_STEP_DISTANCE); break; default: break; @@ -309,10 +339,11 @@ evdev_process_relative(struct evdev_device *device, /* Scroll left */ case 1: /* Scroll right */ - notify_axis(device->seat, - time, - WL_POINTER_AXIS_HORIZONTAL_SCROLL, - e->value * DEFAULT_AXIS_STEP_DISTANCE); + pointer_notify_axis( + base, + time, + LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL, + e->value * DEFAULT_AXIS_STEP_DISTANCE); break; default: break; @@ -395,18 +426,13 @@ evdev_process_events(struct evdev_device *device, } } -static int -evdev_device_data(int fd, uint32_t mask, void *data) +int +evdev_device_dispatch(struct evdev_device *device) { - struct weston_compositor *ec; - struct evdev_device *device = data; + int fd = device->fd; 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. */ @@ -420,10 +446,8 @@ evdev_device_data(int fd, uint32_t mask, void *data) 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; + device->base.device_interface->device_lost( + device->base.device_interface_data); } return 1; @@ -462,8 +486,7 @@ evdev_handle_device(struct evdev_device *device) 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); + /* Device %s is a joystick, ignoring. */ return 0; } @@ -498,8 +521,7 @@ evdev_handle_device(struct evdev_device *device) 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); + /* mtdev required but failed to open. */ return 0; } device->mt.slot = device->mtdev->caps.slot.value; @@ -524,8 +546,6 @@ evdev_handle_device(struct evdev_device *device) !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) @@ -554,9 +574,6 @@ evdev_handle_device(struct evdev_device *device) * 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; } @@ -568,58 +585,54 @@ evdev_configure_device(struct evdev_device *device) { if ((device->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL)) && (device->caps & EVDEV_BUTTON)) { - weston_seat_init_pointer(device->seat); + device->base.device_interface->register_capability( + LIBINPUT_SEAT_CAP_POINTER, + device->base.device_interface_data); 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->base.device_interface->register_capability( + LIBINPUT_SEAT_CAP_KEYBOARD, + device->base.device_interface_data); 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->base.device_interface->register_capability( + LIBINPUT_SEAT_CAP_TOUCH, + device->base.device_interface_data); device->seat_caps |= EVDEV_SEAT_TOUCH; - weston_log("input device %s, %s is a touch device\n", - device->devname, device->devnode); } return 0; } -struct evdev_device * -evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) +LIBINPUT_EXPORT struct libinput_device * +libinput_device_create_evdev( + const char *devnode, + int fd, + const struct libinput_device_interface *device_interface, + void *user_data) { struct evdev_device *device; - struct weston_compositor *ec; char devname[256] = "unknown"; device = zalloc(sizeof *device); if (device == NULL) return NULL; - ec = seat->compositor; - device->output = - container_of(ec->output_list.next, struct weston_output, link); + device->base.device_interface = device_interface; + device->base.device_interface_data = user_data; - device->seat = seat; device->seat_caps = 0; device->is_mt = 0; device->mtdev = NULL; - device->devnode = strdup(path); + device->devnode = strdup(devnode); device->mt.slot = -1; device->rel.dx = 0; device->rel.dy = 0; device->dispatch = NULL; - device->fd = device_fd; + device->fd = fd; device->pending_event = EVDEV_NONE; - wl_list_init(&device->link); ioctl(device->fd, EVIOCGNAME(sizeof(devname)), devname); devname[sizeof(devname) - 1] = '\0'; @@ -627,7 +640,7 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) if (!evdev_handle_device(device)) { evdev_device_destroy(device); - return EVDEV_UNHANDLED_DEVICE; + return NULL; } if (evdev_configure_device(device) == -1) @@ -639,38 +652,52 @@ evdev_device_create(struct weston_seat *seat, const char *path, int device_fd) if (device->dispatch == NULL) goto err; - device->source = wl_event_loop_add_fd(ec->input_loop, device->fd, - WL_EVENT_READABLE, - evdev_device_data, device); - if (device->source == NULL) - goto err; - - return device; + return &device->base; err: evdev_device_destroy(device); return NULL; } +int +evdev_device_get_keys(struct evdev_device *device, char *keys, size_t size) +{ + memset(keys, 0, size); + return ioctl(device->fd, EVIOCGKEY(size), keys); +} + +void +evdev_device_calibrate(struct evdev_device *device, float calibration[6]) +{ + device->abs.apply_calibration = 1; + memcpy(device->abs.calibration, calibration, sizeof calibration); +} + 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); + if (device->seat_caps & EVDEV_SEAT_POINTER) { + device->base.device_interface->unregister_capability( + LIBINPUT_SEAT_CAP_POINTER, + device->base.device_interface_data); + } + if (device->seat_caps & EVDEV_SEAT_KEYBOARD) { + device->base.device_interface->unregister_capability( + LIBINPUT_SEAT_CAP_KEYBOARD, + device->base.device_interface_data); + } + if (device->seat_caps & EVDEV_SEAT_TOUCH) { + device->base.device_interface->unregister_capability( + LIBINPUT_SEAT_CAP_TOUCH, + device->base.device_interface_data); + } 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); @@ -678,46 +705,3 @@ evdev_device_destroy(struct evdev_device *device) free(device->devnode); free(device); } - -void -evdev_notify_keyboard_focus(struct weston_seat *seat, - struct wl_list *evdev_devices) -{ - struct evdev_device *device; - struct wl_array keys; - unsigned int i, set; - char evdev_keys[(KEY_CNT + 7) / 8]; - char all_keys[(KEY_CNT + 7) / 8]; - uint32_t *k; - int ret; - - if (!seat->keyboard_device_count > 0) - return; - - 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); - if (ret < 0) { - weston_log("failed to get keys for device %s\n", - device->devnode); - continue; - } - for (i = 0; i < ARRAY_LENGTH(evdev_keys); i++) - all_keys[i] |= evdev_keys[i]; - } - - wl_array_init(&keys); - for (i = 0; i < KEY_CNT; i++) { - set = all_keys[i >> 3] & (1 << (i & 7)); - if (set) { - k = wl_array_add(&keys, sizeof *k); - *k = i; - } - } - - notify_keyboard_focus_in(seat, &keys, STATE_UPDATE_AUTOMATIC); - - wl_array_release(&keys); -} diff --git a/src/evdev.h b/src/evdev.h index e146d1a4..5efb5369 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -1,5 +1,6 @@ /* * Copyright © 2011, 2012 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 @@ -26,7 +27,15 @@ #include "config.h" #include -#include + +#include "evdev.h" +#include "libinput-private.h" + +static inline void * +zalloc(size_t size) +{ + return calloc(1, size); +} #define MAX_SLOTS 16 @@ -56,10 +65,8 @@ enum evdev_device_seat_capability { }; struct evdev_device { - struct weston_seat *seat; - struct wl_list link; - struct wl_event_source *source; - struct weston_output *output; + struct libinput_device base; + struct evdev_dispatch *dispatch; char *devnode; char *devname; @@ -81,7 +88,7 @@ struct evdev_device { struct mtdev *mtdev; struct { - wl_fixed_t dx, dy; + li_fixed_t dx, dy; } rel; enum evdev_event_type pending_event; @@ -123,17 +130,19 @@ struct evdev_dispatch { struct evdev_dispatch * evdev_touchpad_create(struct evdev_device *device); -void -evdev_led_update(struct evdev_device *device, enum weston_led leds); +int +evdev_device_dispatch(struct evdev_device *device); -struct evdev_device * -evdev_device_create(struct weston_seat *seat, const char *path, int device_fd); +void +evdev_device_led_update(struct evdev_device *device, enum libinput_led leds); + +int +evdev_device_get_keys(struct evdev_device *device, char *keys, size_t size); + +void +evdev_device_calibrate(struct evdev_device *device, float calibration[6]); void evdev_device_destroy(struct evdev_device *device); -void -evdev_notify_keyboard_focus(struct weston_seat *seat, - struct wl_list *evdev_devices); - #endif /* EVDEV_H */ diff --git a/src/filter.c b/src/filter.c index 89237bf8..397e0f63 100644 --- a/src/filter.c +++ b/src/filter.c @@ -27,15 +27,12 @@ #include #include -#include - -#include "compositor.h" #include "filter.h" void -weston_filter_dispatch(struct weston_motion_filter *filter, - struct weston_motion_params *motion, - void *data, uint32_t time) +filter_dispatch(struct motion_filter *filter, + struct motion_params *motion, + void *data, uint32_t time) { filter->interface->filter(filter, motion, data, time); } @@ -57,7 +54,7 @@ struct pointer_tracker { struct pointer_accelerator; struct pointer_accelerator { - struct weston_motion_filter base; + struct motion_filter base; accel_profile_func_t profile; @@ -267,15 +264,15 @@ soften_delta(double last_delta, double delta) static void apply_softening(struct pointer_accelerator *accel, - struct weston_motion_params *motion) + struct motion_params *motion) { motion->dx = soften_delta(accel->last_dx, motion->dx); motion->dy = soften_delta(accel->last_dy, motion->dy); } static void -accelerator_filter(struct weston_motion_filter *filter, - struct weston_motion_params *motion, +accelerator_filter(struct motion_filter *filter, + struct motion_params *motion, void *data, uint32_t time) { struct pointer_accelerator *accel = @@ -299,7 +296,7 @@ accelerator_filter(struct weston_motion_filter *filter, } static void -accelerator_destroy(struct weston_motion_filter *filter) +accelerator_destroy(struct motion_filter *filter) { struct pointer_accelerator *accel = (struct pointer_accelerator *) filter; @@ -308,12 +305,12 @@ accelerator_destroy(struct weston_motion_filter *filter) free(accel); } -struct weston_motion_filter_interface accelerator_interface = { +struct motion_filter_interface accelerator_interface = { accelerator_filter, accelerator_destroy }; -struct weston_motion_filter * +struct motion_filter * create_pointer_accelator_filter(accel_profile_func_t profile) { struct pointer_accelerator *filter; diff --git a/src/filter.h b/src/filter.h index dad538b2..6b2a1d20 100644 --- a/src/filter.h +++ b/src/filter.h @@ -20,47 +20,43 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#ifndef _FILTER_H_ -#define _FILTER_H_ +#ifndef FILTER_H +#define FILTER_H #include "config.h" -#include - -#include "compositor.h" - -struct weston_motion_params { +struct motion_params { double dx, dy; }; -struct weston_motion_filter; +struct motion_filter; -WL_EXPORT void -weston_filter_dispatch(struct weston_motion_filter *filter, - struct weston_motion_params *motion, +void +filter_dispatch(struct motion_filter *filter, + struct motion_params *motion, + void *data, uint32_t time); + + +struct motion_filter_interface { + void (*filter)(struct motion_filter *filter, + struct motion_params *motion, void *data, uint32_t time); - - -struct weston_motion_filter_interface { - void (*filter)(struct weston_motion_filter *filter, - struct weston_motion_params *motion, - void *data, uint32_t time); - void (*destroy)(struct weston_motion_filter *filter); + void (*destroy)(struct motion_filter *filter); }; -struct weston_motion_filter { - struct weston_motion_filter_interface *interface; +struct motion_filter { + struct motion_filter_interface *interface; }; -WL_EXPORT struct weston_motion_filter * +struct motion_filter * create_linear_acceleration_filter(double speed); -typedef double (*accel_profile_func_t)(struct weston_motion_filter *filter, +typedef double (*accel_profile_func_t)(struct motion_filter *filter, void *data, double velocity, uint32_t time); -WL_EXPORT struct weston_motion_filter * +struct motion_filter * create_pointer_accelator_filter(accel_profile_func_t filter); -#endif // _FILTER_H_ +#endif /* FILTER_H */ diff --git a/src/libinput-private.h b/src/libinput-private.h new file mode 100644 index 00000000..8a7970c8 --- /dev/null +++ b/src/libinput-private.h @@ -0,0 +1,102 @@ +/* + * 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 + * 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. + */ + +#ifndef LIBINPUT_PRIVATE_H +#define LIBINPUT_PRIVATE_H + +#include "libinput.h" + +struct libinput_device { + const struct libinput_device_interface *device_interface; + void *device_interface_data; + + const struct libinput_keyboard_listener *keyboard_listener; + void *keyboard_listener_data; + + const struct libinput_pointer_listener *pointer_listener; + void *pointer_listener_data; + + const struct libinput_touch_listener *touch_listener; + void *touch_listener_data; +}; + +void +keyboard_notify_key(struct libinput_device *device, + uint32_t time, + uint32_t key, + enum libinput_keyboard_key_state state); + +void +pointer_notify_motion(struct libinput_device *device, + uint32_t time, + li_fixed_t dx, + li_fixed_t dy); + +void +pointer_notify_motion_absolute(struct libinput_device *device, + uint32_t time, + li_fixed_t x, + li_fixed_t y); + +void +pointer_notify_button(struct libinput_device *device, + uint32_t time, + int32_t button, + enum libinput_pointer_button_state state); + +void +pointer_notify_axis(struct libinput_device *device, + uint32_t time, + enum libinput_pointer_axis axis, + li_fixed_t value); + +void +touch_notify_touch(struct libinput_device *device, + uint32_t time, + int32_t slot, + li_fixed_t x, + li_fixed_t y, + enum libinput_touch_type touch_type); + +static inline li_fixed_t li_fixed_from_int(int i) +{ + return i * 256; +} + +static inline li_fixed_t +li_fixed_from_double(double d) +{ + union { + double d; + int64_t i; + } u; + + u.d = d + (3LL << (51 - 8)); + + return u.i; +} + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + +#define LIBINPUT_EXPORT __attribute__ ((visibility("default"))) + +#endif /* LIBINPUT_PRIVATE_H */ diff --git a/src/libinput-version.h.in b/src/libinput-version.h.in new file mode 100644 index 00000000..2b1c4ea2 --- /dev/null +++ b/src/libinput-version.h.in @@ -0,0 +1,31 @@ +/* + * 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 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. + */ + +#ifndef LIBINPUT_VERSION_H +#define LIBINPUT_VERSION_H + +#define LIBINPUT_VERSION_MAJOR @LIBINPUT_VERSION_MAJOR@ +#define LIBINPUT_VERSION_MINOR @LIBINPUT_VERSION_MINOR@ +#define LIBINPUT_VERSION_MICRO @LIBINPUT_VERSION_MICRO@ +#define LIBINPUT_VERSION "@LIBINPUT_VERSION@" + +#endif diff --git a/src/libinput.c b/src/libinput.c new file mode 100644 index 00000000..10baf265 --- /dev/null +++ b/src/libinput.c @@ -0,0 +1,168 @@ +/* + * 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 + * 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 + +#include "libinput.h" +#include "evdev.h" +#include "libinput-private.h" + +void +keyboard_notify_key(struct libinput_device *device, + uint32_t time, + uint32_t key, + enum libinput_keyboard_key_state state) +{ + if (device->keyboard_listener) + device->keyboard_listener->notify_key( + time, key, state, + device->keyboard_listener_data); +} + +void +pointer_notify_motion(struct libinput_device *device, + uint32_t time, + li_fixed_t dx, + li_fixed_t dy) +{ + if (device->pointer_listener) + device->pointer_listener->notify_motion( + time, dx, dy, + device->pointer_listener_data); +} + +void +pointer_notify_motion_absolute(struct libinput_device *device, + uint32_t time, + li_fixed_t x, + li_fixed_t y) +{ + if (device->pointer_listener) + device->pointer_listener->notify_motion_absolute( + time, x, y, + device->pointer_listener_data); +} + +void +pointer_notify_button(struct libinput_device *device, + uint32_t time, + int32_t button, + enum libinput_pointer_button_state state) +{ + if (device->pointer_listener) + device->pointer_listener->notify_button( + time, button, state, + device->pointer_listener_data); +} + +void +pointer_notify_axis(struct libinput_device *device, + uint32_t time, + enum libinput_pointer_axis axis, + li_fixed_t value) +{ + if (device->pointer_listener) + device->pointer_listener->notify_axis( + time, axis, value, + device->pointer_listener_data); +} + +void +touch_notify_touch(struct libinput_device *device, + uint32_t time, + int32_t slot, + li_fixed_t x, + li_fixed_t y, + enum libinput_touch_type touch_type) +{ + if (device->touch_listener) + device->touch_listener->notify_touch( + time, slot, x, y, touch_type, + device->touch_listener_data); +} + +LIBINPUT_EXPORT void +libinput_device_set_keyboard_listener( + struct libinput_device *device, + const struct libinput_keyboard_listener *listener, + void *data) +{ + device->keyboard_listener = listener; + device->keyboard_listener_data = data; +} + +LIBINPUT_EXPORT void +libinput_device_set_pointer_listener( + struct libinput_device *device, + const struct libinput_pointer_listener *listener, + void *data) +{ + device->pointer_listener = listener; + device->pointer_listener_data = data; +} + +LIBINPUT_EXPORT void +libinput_device_set_touch_listener( + struct libinput_device *device, + const struct libinput_touch_listener *listener, + void *data) +{ + device->touch_listener = listener; + device->touch_listener_data = data; +} + +LIBINPUT_EXPORT int +libinput_device_dispatch(struct libinput_device *device) +{ + return evdev_device_dispatch((struct evdev_device *) device); +} + +LIBINPUT_EXPORT void +libinput_device_destroy(struct libinput_device *device) +{ + evdev_device_destroy((struct evdev_device *) device); +} + +LIBINPUT_EXPORT void +libinput_device_led_update(struct libinput_device *device, + enum libinput_led leds) +{ + evdev_device_led_update((struct evdev_device *) device, leds); +} + +LIBINPUT_EXPORT int +libinput_device_get_keys(struct libinput_device *device, + char *keys, size_t size) +{ + return evdev_device_get_keys((struct evdev_device *) device, + keys, + size); +} + +LIBINPUT_EXPORT void +libinput_device_calibrate(struct libinput_device *device, + float calibration[6]) +{ + evdev_device_calibrate((struct evdev_device *) device, calibration); +} diff --git a/src/libinput.h b/src/libinput.h new file mode 100644 index 00000000..6b1f3aff --- /dev/null +++ b/src/libinput.h @@ -0,0 +1,173 @@ +/* + * 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 + * 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. + */ + +#ifndef LIBINPUT_H +#define LIBINPUT_H + +#include +#include + +typedef int32_t li_fixed_t; + +enum libinput_seat_capability { + LIBINPUT_SEAT_CAP_KEYBOARD = 0, + LIBINPUT_SEAT_CAP_POINTER = 1, + LIBINPUT_SEAT_CAP_TOUCH = 2, +}; + +enum libinput_keyboard_key_state { + LIBINPUT_KEYBOARD_KEY_STATE_RELEASED = 0, + LIBINPUT_KEYBOARD_KEY_STATE_PRESSED = 1, +}; + +enum libinput_led { + LIBINPUT_LED_NUM_LOCK = (1 << 0), + LIBINPUT_LED_CAPS_LOCK = (1 << 1), + LIBINPUT_LED_SCROLL_LOCK = (1 << 2), +}; + +enum libinput_pointer_button_state { + LIBINPUT_POINTER_BUTTON_STATE_RELEASED = 0, + LIBINPUT_POINTER_BUTTON_STATE_PRESSED = 1, +}; + +enum libinput_pointer_axis { + LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL = 0, + LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL = 1, +}; + +enum libinput_touch_type { + LIBINPUT_TOUCH_TYPE_DOWN = 0, + LIBINPUT_TOUCH_TYPE_UP = 1, + LIBINPUT_TOUCH_TYPE_MOTION = 2, + LIBINPUT_TOUCH_TYPE_FRAME = 3, + LIBINPUT_TOUCH_TYPE_CANCEL = 4, +}; + +struct libinput_fd_handle; + +typedef void (*libinput_fd_callback)(int fd, void *data); + +struct libinput_device_interface { + /* */ + void (*register_capability)(enum libinput_seat_capability capability, + void *data); + void (*unregister_capability)(enum libinput_seat_capability capability, + void *data); + + /* */ + void (*get_current_screen_dimensions)(int *width, + int *height, + void *data); + + /* */ + struct libinput_fd_handle * (*add_fd)(int fd, + libinput_fd_callback callback, + void *data); + void (*remove_fd)(struct libinput_fd_handle *fd_container, + void *data); + + /* */ + void (*device_lost)(void *data); +}; + +struct libinput_keyboard_listener { + void (*notify_key)(uint32_t time, + uint32_t key, + enum libinput_keyboard_key_state state, + void *data); +}; + +struct libinput_pointer_listener { + void (*notify_motion)(uint32_t time, + li_fixed_t dx, + li_fixed_t dy, + void *data); + void (*notify_motion_absolute)(uint32_t time, + li_fixed_t x, + li_fixed_t y, + void *data); + void (*notify_button)(uint32_t time, + int32_t button, + enum libinput_pointer_button_state state, + void *data); + void (*notify_axis)(uint32_t time, + enum libinput_pointer_axis axis, + li_fixed_t value, + void *data); +}; + +struct libinput_touch_listener { + void (*notify_touch)(uint32_t time, + int32_t slot, + li_fixed_t x, + li_fixed_t y, + enum libinput_touch_type touch_type, + void *data); +}; + +struct libinput_seat; +struct libinput_device; + +struct libinput_device * +libinput_device_create_evdev(const char *devnode, + int fd, + const struct libinput_device_interface *interface, + void *user_data); + +void +libinput_device_set_keyboard_listener( + struct libinput_device *device, + const struct libinput_keyboard_listener *listener, + void *data); + +void +libinput_device_set_pointer_listener( + struct libinput_device *device, + const struct libinput_pointer_listener *listener, + void *data); + +void +libinput_device_set_touch_listener( + struct libinput_device *device, + const struct libinput_touch_listener *listener, + void *data); + +int +libinput_device_dispatch(struct libinput_device *device); + +void +libinput_device_destroy(struct libinput_device *device); + +void +libinput_device_led_update(struct libinput_device *device, + enum libinput_led leds); + +int +libinput_device_get_keys(struct libinput_device *device, + char *keys, size_t size); + +void +libinput_device_calibrate(struct libinput_device *device, + float calibration[6]); + +#endif /* LIBINPUT_H */ diff --git a/src/libinput.pc.in b/src/libinput.pc.in new file mode 100644 index 00000000..ed51acc9 --- /dev/null +++ b/src/libinput.pc.in @@ -0,0 +1,12 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +datarootdir=@datarootdir@ +pkgdatadir=@datadir@/@PACKAGE@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Libinput +Description: Input device library +Version: @LIBINPUT_VERSION@ +Cflags: -I${includedir} +Libs: -L${libdir} -linput From 79d77d4b8b68155506325086e217d751da2e057f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 13 Nov 2013 22:11:34 +0100 Subject: [PATCH 157/162] Don't use the `seat' concept on device capability enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl --- src/evdev.c | 24 ++++++++++++------------ src/evdev.h | 6 +++--- src/libinput.h | 12 ++++++------ 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index aa2ffa99..c326a433 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -586,21 +586,21 @@ evdev_configure_device(struct evdev_device *device) if ((device->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL)) && (device->caps & EVDEV_BUTTON)) { device->base.device_interface->register_capability( - LIBINPUT_SEAT_CAP_POINTER, + LIBINPUT_DEVICE_CAP_POINTER, device->base.device_interface_data); - device->seat_caps |= EVDEV_SEAT_POINTER; + device->seat_caps |= EVDEV_DEVICE_POINTER; } if ((device->caps & EVDEV_KEYBOARD)) { device->base.device_interface->register_capability( - LIBINPUT_SEAT_CAP_KEYBOARD, + LIBINPUT_DEVICE_CAP_KEYBOARD, device->base.device_interface_data); - device->seat_caps |= EVDEV_SEAT_KEYBOARD; + device->seat_caps |= EVDEV_DEVICE_KEYBOARD; } if ((device->caps & EVDEV_TOUCH)) { device->base.device_interface->register_capability( - LIBINPUT_SEAT_CAP_TOUCH, + LIBINPUT_DEVICE_CAP_TOUCH, device->base.device_interface_data); - device->seat_caps |= EVDEV_SEAT_TOUCH; + device->seat_caps |= EVDEV_DEVICE_TOUCH; } return 0; @@ -678,19 +678,19 @@ evdev_device_destroy(struct evdev_device *device) { struct evdev_dispatch *dispatch; - if (device->seat_caps & EVDEV_SEAT_POINTER) { + if (device->seat_caps & EVDEV_DEVICE_POINTER) { device->base.device_interface->unregister_capability( - LIBINPUT_SEAT_CAP_POINTER, + LIBINPUT_DEVICE_CAP_POINTER, device->base.device_interface_data); } - if (device->seat_caps & EVDEV_SEAT_KEYBOARD) { + if (device->seat_caps & EVDEV_DEVICE_KEYBOARD) { device->base.device_interface->unregister_capability( - LIBINPUT_SEAT_CAP_KEYBOARD, + LIBINPUT_DEVICE_CAP_KEYBOARD, device->base.device_interface_data); } - if (device->seat_caps & EVDEV_SEAT_TOUCH) { + if (device->seat_caps & EVDEV_DEVICE_TOUCH) { device->base.device_interface->unregister_capability( - LIBINPUT_SEAT_CAP_TOUCH, + LIBINPUT_DEVICE_CAP_TOUCH, device->base.device_interface_data); } diff --git a/src/evdev.h b/src/evdev.h index 5efb5369..6bb62ff9 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -59,9 +59,9 @@ enum evdev_device_capability { }; enum evdev_device_seat_capability { - EVDEV_SEAT_POINTER = (1 << 0), - EVDEV_SEAT_KEYBOARD = (1 << 1), - EVDEV_SEAT_TOUCH = (1 << 2) + EVDEV_DEVICE_POINTER = (1 << 0), + EVDEV_DEVICE_KEYBOARD = (1 << 1), + EVDEV_DEVICE_TOUCH = (1 << 2) }; struct evdev_device { diff --git a/src/libinput.h b/src/libinput.h index 6b1f3aff..ac396b79 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -28,10 +28,10 @@ typedef int32_t li_fixed_t; -enum libinput_seat_capability { - LIBINPUT_SEAT_CAP_KEYBOARD = 0, - LIBINPUT_SEAT_CAP_POINTER = 1, - LIBINPUT_SEAT_CAP_TOUCH = 2, +enum libinput_device_capability { + LIBINPUT_DEVICE_CAP_KEYBOARD = 0, + LIBINPUT_DEVICE_CAP_POINTER = 1, + LIBINPUT_DEVICE_CAP_TOUCH = 2, }; enum libinput_keyboard_key_state { @@ -69,9 +69,9 @@ typedef void (*libinput_fd_callback)(int fd, void *data); struct libinput_device_interface { /* */ - void (*register_capability)(enum libinput_seat_capability capability, + void (*register_capability)(enum libinput_device_capability capability, void *data); - void (*unregister_capability)(enum libinput_seat_capability capability, + void (*unregister_capability)(enum libinput_device_capability capability, void *data); /* */ From 2e6e33bc484c31b28b1f3dabdc85377bd6a8a84c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sat, 16 Nov 2013 19:32:46 +0100 Subject: [PATCH 158/162] Change API from using listeners to using an event queue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of having the input drivers invoke user set callbacks during libinput_device_dispatch() and add_fd callback, let the driver queue events that the user then reads from using libinput_device_get_event(). A typical use case would be: struct libinput_device *device = ...; struct libinput_event *event; libinput_device_dispatch(device); while ((event = libinput_device_get_event(device))) { process_event(device, event); free(event); } Signed-off-by: Jonas Ådahl --- src/libinput-private.h | 13 ++- src/libinput.c | 199 +++++++++++++++++++++++++++++++---------- src/libinput.h | 116 +++++++++++++----------- 3 files changed, 222 insertions(+), 106 deletions(-) diff --git a/src/libinput-private.h b/src/libinput-private.h index 8a7970c8..d245635a 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -29,14 +29,11 @@ struct libinput_device { const struct libinput_device_interface *device_interface; void *device_interface_data; - const struct libinput_keyboard_listener *keyboard_listener; - void *keyboard_listener_data; - - const struct libinput_pointer_listener *pointer_listener; - void *pointer_listener_data; - - const struct libinput_touch_listener *touch_listener; - void *touch_listener_data; + struct libinput_event **events; + size_t events_count; + size_t events_len; + size_t events_in; + size_t events_out; }; void diff --git a/src/libinput.c b/src/libinput.c index 10baf265..fd0fb1e7 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -22,22 +22,38 @@ #include "config.h" +#include #include +#include #include "libinput.h" #include "evdev.h" #include "libinput-private.h" +static void +post_event(struct libinput_device *device, + enum libinput_event_type type, + struct libinput_event *event); + void keyboard_notify_key(struct libinput_device *device, uint32_t time, uint32_t key, enum libinput_keyboard_key_state state) { - if (device->keyboard_listener) - device->keyboard_listener->notify_key( - time, key, state, - device->keyboard_listener_data); + struct libinput_event_keyboard_key *key_event; + + key_event = malloc(sizeof *key_event); + if (!key_event) + return; + + *key_event = (struct libinput_event_keyboard_key) { + .time = time, + .key = key, + .state = state, + }; + + post_event(device, LIBINPUT_EVENT_KEYBOARD_KEY, &key_event->base); } void @@ -46,10 +62,19 @@ pointer_notify_motion(struct libinput_device *device, li_fixed_t dx, li_fixed_t dy) { - if (device->pointer_listener) - device->pointer_listener->notify_motion( - time, dx, dy, - device->pointer_listener_data); + struct libinput_event_pointer_motion *motion_event; + + motion_event = malloc(sizeof *motion_event); + if (!motion_event) + return; + + *motion_event = (struct libinput_event_pointer_motion) { + .time = time, + .dx = dx, + .dy = dy, + }; + + post_event(device, LIBINPUT_EVENT_POINTER_MOTION, &motion_event->base); } void @@ -58,10 +83,21 @@ pointer_notify_motion_absolute(struct libinput_device *device, li_fixed_t x, li_fixed_t y) { - if (device->pointer_listener) - device->pointer_listener->notify_motion_absolute( - time, x, y, - device->pointer_listener_data); + struct libinput_event_pointer_motion_absolute *motion_absolute_event; + + motion_absolute_event = malloc(sizeof *motion_absolute_event); + if (!motion_absolute_event) + return; + + *motion_absolute_event = (struct libinput_event_pointer_motion_absolute) { + .time = time, + .x = x, + .y = y, + }; + + post_event(device, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, + &motion_absolute_event->base); } void @@ -70,10 +106,19 @@ pointer_notify_button(struct libinput_device *device, int32_t button, enum libinput_pointer_button_state state) { - if (device->pointer_listener) - device->pointer_listener->notify_button( - time, button, state, - device->pointer_listener_data); + struct libinput_event_pointer_button *button_event; + + button_event = malloc(sizeof *button_event); + if (!button_event) + return; + + *button_event = (struct libinput_event_pointer_button) { + .time = time, + .button = button, + .state = state, + }; + + post_event(device, LIBINPUT_EVENT_POINTER_BUTTON, &button_event->base); } void @@ -82,10 +127,19 @@ pointer_notify_axis(struct libinput_device *device, enum libinput_pointer_axis axis, li_fixed_t value) { - if (device->pointer_listener) - device->pointer_listener->notify_axis( - time, axis, value, - device->pointer_listener_data); + struct libinput_event_pointer_axis *axis_event; + + axis_event = malloc(sizeof *axis_event); + if (!axis_event) + return; + + *axis_event = (struct libinput_event_pointer_axis) { + .time = time, + .axis = axis, + .value = value, + }; + + post_event(device, LIBINPUT_EVENT_POINTER_AXIS, &axis_event->base); } void @@ -96,40 +150,89 @@ touch_notify_touch(struct libinput_device *device, li_fixed_t y, enum libinput_touch_type touch_type) { - if (device->touch_listener) - device->touch_listener->notify_touch( - time, slot, x, y, touch_type, - device->touch_listener_data); + struct libinput_event_touch_touch *touch_event; + + touch_event = malloc(sizeof *touch_event); + if (!touch_event) + return; + + *touch_event = (struct libinput_event_touch_touch) { + .time = time, + .slot = slot, + .x = x, + .y = y, + .touch_type = touch_type, + }; + + post_event(device, LIBINPUT_EVENT_TOUCH_TOUCH, &touch_event->base); } -LIBINPUT_EXPORT void -libinput_device_set_keyboard_listener( - struct libinput_device *device, - const struct libinput_keyboard_listener *listener, - void *data) +static void +init_event_base(struct libinput_event *event, enum libinput_event_type type) { - device->keyboard_listener = listener; - device->keyboard_listener_data = data; + event->type = type; } -LIBINPUT_EXPORT void -libinput_device_set_pointer_listener( - struct libinput_device *device, - const struct libinput_pointer_listener *listener, - void *data) +static void +post_event(struct libinput_device *device, + enum libinput_event_type type, + struct libinput_event *event) { - device->pointer_listener = listener; - device->pointer_listener_data = data; + struct libinput_event **events = device->events; + size_t events_len = device->events_len; + size_t events_count = device->events_count; + size_t move_len; + size_t new_out; + + events_count++; + if (events_count > events_len) { + if (events_len == 0) + events_len = 4; + else + events_len *= 2; + events = realloc(events, events_len * sizeof *events); + if (!events) { + fprintf(stderr, "Failed to reallocate event ring " + "buffer"); + return; + } + + if (device->events_count > 0 && device->events_in == 0) { + device->events_in = device->events_len; + } else if (device->events_count > 0 && + device->events_out >= device->events_in) { + move_len = device->events_len - device->events_out; + new_out = events_len - move_len; + memmove(events + new_out, + device->events + device->events_out, + move_len * sizeof *events); + device->events_out = new_out; + } + + device->events = events; + device->events_len = events_len; + } + + init_event_base(event, type); + + device->events_count = events_count; + events[device->events_in] = event; + device->events_in = (device->events_in + 1) % device->events_len; } -LIBINPUT_EXPORT void -libinput_device_set_touch_listener( - struct libinput_device *device, - const struct libinput_touch_listener *listener, - void *data) +LIBINPUT_EXPORT struct libinput_event * +libinput_device_get_event(struct libinput_device *device) { - device->touch_listener = listener; - device->touch_listener_data = data; + struct libinput_event *event; + + if (device->events_count == 0) + return NULL; + + event = device->events[device->events_out]; + device->events_out = (device->events_out + 1) % device->events_len; + device->events_count--; + + return event; } LIBINPUT_EXPORT int @@ -141,6 +244,12 @@ libinput_device_dispatch(struct libinput_device *device) LIBINPUT_EXPORT void libinput_device_destroy(struct libinput_device *device) { + struct libinput_event *event; + + while ((event = libinput_device_get_event(device))) + free(event); + free(device->events); + evdev_device_destroy((struct evdev_device *) device); } diff --git a/src/libinput.h b/src/libinput.h index ac396b79..745660c2 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -63,6 +63,66 @@ enum libinput_touch_type { LIBINPUT_TOUCH_TYPE_CANCEL = 4, }; +enum libinput_event_type { + + LIBINPUT_EVENT_KEYBOARD_KEY = 300, + + LIBINPUT_EVENT_POINTER_MOTION = 400, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, + LIBINPUT_EVENT_POINTER_BUTTON, + LIBINPUT_EVENT_POINTER_AXIS, + + LIBINPUT_EVENT_TOUCH_TOUCH = 500, +}; + +struct libinput_event { + enum libinput_event_type type; +}; + +struct libinput_event_keyboard_key { + struct libinput_event base; + uint32_t time; + uint32_t key; + enum libinput_keyboard_key_state state; +}; + +struct libinput_event_pointer_motion { + struct libinput_event base; + uint32_t time; + li_fixed_t dx; + li_fixed_t dy; +}; + +struct libinput_event_pointer_motion_absolute { + struct libinput_event base; + uint32_t time; + li_fixed_t x; + li_fixed_t y; +}; + +struct libinput_event_pointer_button { + struct libinput_event base; + uint32_t time; + int32_t button; + enum libinput_pointer_button_state state; +}; + +struct libinput_event_pointer_axis { + struct libinput_event base; + uint32_t time; + enum libinput_pointer_axis axis; + li_fixed_t value; +}; + +struct libinput_event_touch_touch { + struct libinput_event base; + uint32_t time; + int32_t slot; + li_fixed_t x; + li_fixed_t y; + enum libinput_touch_type touch_type; +}; + struct libinput_fd_handle; typedef void (*libinput_fd_callback)(int fd, void *data); @@ -90,41 +150,6 @@ struct libinput_device_interface { void (*device_lost)(void *data); }; -struct libinput_keyboard_listener { - void (*notify_key)(uint32_t time, - uint32_t key, - enum libinput_keyboard_key_state state, - void *data); -}; - -struct libinput_pointer_listener { - void (*notify_motion)(uint32_t time, - li_fixed_t dx, - li_fixed_t dy, - void *data); - void (*notify_motion_absolute)(uint32_t time, - li_fixed_t x, - li_fixed_t y, - void *data); - void (*notify_button)(uint32_t time, - int32_t button, - enum libinput_pointer_button_state state, - void *data); - void (*notify_axis)(uint32_t time, - enum libinput_pointer_axis axis, - li_fixed_t value, - void *data); -}; - -struct libinput_touch_listener { - void (*notify_touch)(uint32_t time, - int32_t slot, - li_fixed_t x, - li_fixed_t y, - enum libinput_touch_type touch_type, - void *data); -}; - struct libinput_seat; struct libinput_device; @@ -134,27 +159,12 @@ libinput_device_create_evdev(const char *devnode, const struct libinput_device_interface *interface, void *user_data); -void -libinput_device_set_keyboard_listener( - struct libinput_device *device, - const struct libinput_keyboard_listener *listener, - void *data); - -void -libinput_device_set_pointer_listener( - struct libinput_device *device, - const struct libinput_pointer_listener *listener, - void *data); - -void -libinput_device_set_touch_listener( - struct libinput_device *device, - const struct libinput_touch_listener *listener, - void *data); - int libinput_device_dispatch(struct libinput_device *device); +struct libinput_event * +libinput_device_get_event(struct libinput_device *device); + void libinput_device_destroy(struct libinput_device *device); From 8f8fdc85b17c6ea80911d998bcf0d9630bfc5d9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sun, 17 Nov 2013 02:38:58 +0100 Subject: [PATCH 159/162] src/Makefile.a: Fix whitespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl --- src/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 00b052e2..905bcd1c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,9 +6,9 @@ include_HEADERS = \ libinput_la_SOURCES = \ libinput.c \ libinput.h \ - evdev.c \ - evdev.h \ - evdev-touchpad.c \ + evdev.c \ + evdev.h \ + evdev-touchpad.c \ filter.c \ filter.h From ce787552bce26ccac433c7fcf9868d2a5561a0cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sun, 17 Nov 2013 11:19:50 +0100 Subject: [PATCH 160/162] Introduce libinput object managing all input data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of having the user manage added and removed fd's as well as the fd used for creating evdev devices, introduce a libinput object that itself has an epoll fd. The user no longer manages multiple fd's per libinput instance, but instead handles one fd, dispatches libinput when data is available, then reading events using libinput_get_event(). libinput_event's are now per libinstance, but divided into categories. So far the only category is device events. Device events are categorized by the presence of a non-NULL device pointer in the event. The current API usage should look like: struct libinput libinput = ...; struct libinput_event *event; if (libinput_dispatch(libinput) != 0) return -1; while ((event = libinput_get_event(libinput))) { if (event->device) process_device_event(event); free(event); } Signed-off-by: Jonas Ådahl --- configure.ac | 3 + src/Makefile.am | 2 + src/evdev-touchpad.c | 28 +++-- src/evdev.c | 21 ++-- src/evdev.h | 6 +- src/libinput-private.h | 53 +++++----- src/libinput-util.c | 62 +++++++++++ src/libinput-util.h | 91 ++++++++++++++++ src/libinput.c | 231 +++++++++++++++++++++++++++++++---------- src/libinput.h | 40 +++---- 10 files changed, 414 insertions(+), 123 deletions(-) create mode 100644 src/libinput-util.c create mode 100644 src/libinput-util.h diff --git a/configure.ac b/configure.ac index 8e0f1c93..08472cf0 100644 --- a/configure.ac +++ b/configure.ac @@ -31,6 +31,9 @@ AC_PROG_CC LT_PREREQ([2.2]) LT_INIT +AC_CHECK_DECL(EPOLL_CLOEXEC, [], + [AC_MSG_ERROR("EPOLL_CLOEXEC is needed to compile libinput")], + [[#include ]]) AC_CHECK_DECL(TFD_CLOEXEC,[], [AC_MSG_ERROR("TFD_CLOEXEC is needed to compile libinput")], [[#include ]]) diff --git a/src/Makefile.am b/src/Makefile.am index 905bcd1c..c1e31499 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -6,6 +6,8 @@ include_HEADERS = \ libinput_la_SOURCES = \ libinput.c \ libinput.h \ + libinput-util.c \ + libinput-util.h \ evdev.c \ evdev.h \ evdev-touchpad.c \ diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c index 6268dffa..a673a7b7 100644 --- a/src/evdev-touchpad.c +++ b/src/evdev-touchpad.c @@ -137,7 +137,7 @@ struct touchpad_dispatch { enum fsm_state state; struct { int fd; - struct libinput_fd_handle *fd_handle; + struct libinput_source *source; } timer; } fsm; @@ -440,17 +440,15 @@ push_fsm_event(struct touchpad_dispatch *touchpad, } static void -fsm_timeout_handler(int fd, void *data) +fsm_timeout_handler(void *data) { - struct evdev_device *device = data; - struct touchpad_dispatch *touchpad = - (struct touchpad_dispatch *) device->dispatch; + struct touchpad_dispatch *touchpad = data; uint64_t expires; int len; struct timespec ts; uint32_t now; - len = read(fd, &expires, sizeof expires); + len = read(touchpad->fsm.timer.fd, &expires, sizeof expires); if (len != sizeof expires) /* This will only happen if the application made the fd * non-blocking, but this function should only be called @@ -711,12 +709,10 @@ touchpad_destroy(struct evdev_dispatch *dispatch) { struct touchpad_dispatch *touchpad = (struct touchpad_dispatch *) dispatch; + struct libinput *libinput = touchpad->device->base.libinput; touchpad->filter->interface->destroy(touchpad->filter); - touchpad->device->base.device_interface->remove_fd( - touchpad->fsm.timer.fd_handle, - touchpad->device->base.device_interface_data); - close(touchpad->fsm.timer.fd); + libinput_remove_source(libinput, touchpad->fsm.timer.source); free(touchpad->fsm.events); free(dispatch); } @@ -801,13 +797,13 @@ touchpad_init(struct touchpad_dispatch *touchpad, touchpad->fsm.state = FSM_IDLE; touchpad->fsm.timer.fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC); - touchpad->fsm.timer.fd_handle = - touchpad->device->base.device_interface->add_fd( - touchpad->fsm.timer.fd, - fsm_timeout_handler, - touchpad->device->base.device_interface_data); + touchpad->fsm.timer.source = + libinput_add_fd(touchpad->device->base.libinput, + touchpad->fsm.timer.fd, + fsm_timeout_handler, + touchpad); - if (touchpad->fsm.timer.fd_handle == NULL) { + if (touchpad->fsm.timer.source == NULL) { close(touchpad->fsm.timer.fd); accel->interface->destroy(accel); return -1; diff --git a/src/evdev.c b/src/evdev.c index c326a433..4f107ea5 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -426,9 +426,10 @@ evdev_process_events(struct evdev_device *device, } } -int -evdev_device_dispatch(struct evdev_device *device) +static void +evdev_device_dispatch(void *data) { + struct evdev_device *device = data; int fd = device->fd; struct input_event ev[32]; int len; @@ -446,18 +447,17 @@ evdev_device_dispatch(struct evdev_device *device) if (len < 0 || len % sizeof ev[0] != 0) { if (len < 0 && errno != EAGAIN && errno != EINTR) { - device->base.device_interface->device_lost( - device->base.device_interface_data); + libinput_remove_source(device->base.libinput, + device->source); + device->source = NULL; } - return 1; + return; } evdev_process_events(device, ev, len / sizeof ev[0]); } while (len > 0); - - return 1; } static int @@ -608,6 +608,7 @@ evdev_configure_device(struct evdev_device *device) LIBINPUT_EXPORT struct libinput_device * libinput_device_create_evdev( + struct libinput *libinput, const char *devnode, int fd, const struct libinput_device_interface *device_interface, @@ -620,6 +621,7 @@ libinput_device_create_evdev( if (device == NULL) return NULL; + device->base.libinput = libinput; device->base.device_interface = device_interface; device->base.device_interface_data = user_data; @@ -652,6 +654,11 @@ libinput_device_create_evdev( if (device->dispatch == NULL) goto err; + device->source = + libinput_add_fd(libinput, fd, evdev_device_dispatch, device); + if (!device->source) + goto err; + return &device->base; err: diff --git a/src/evdev.h b/src/evdev.h index 6bb62ff9..1b45aed0 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -67,6 +67,8 @@ enum evdev_device_seat_capability { struct evdev_device { struct libinput_device base; + struct libinput_source *source; + struct evdev_dispatch *dispatch; char *devnode; char *devname; @@ -130,8 +132,8 @@ struct evdev_dispatch { struct evdev_dispatch * evdev_touchpad_create(struct evdev_device *device); -int -evdev_device_dispatch(struct evdev_device *device); +void +evdev_device_proces_event(struct libinput_event *event); void evdev_device_led_update(struct evdev_device *device, enum libinput_led leds); diff --git a/src/libinput-private.h b/src/libinput-private.h index d245635a..6796ccfa 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -24,10 +24,11 @@ #define LIBINPUT_PRIVATE_H #include "libinput.h" +#include "libinput-util.h" -struct libinput_device { - const struct libinput_device_interface *device_interface; - void *device_interface_data; +struct libinput { + int epoll_fd; + struct list source_destroy_list; struct libinput_event **events; size_t events_count; @@ -36,6 +37,30 @@ struct libinput_device { size_t events_out; }; +struct libinput_device { + struct libinput *libinput; + const struct libinput_device_interface *device_interface; + void *device_interface_data; +}; + +typedef void (*libinput_source_dispatch_t)(void *data); + +struct libinput_source; + +struct libinput_source * +libinput_add_fd(struct libinput *libinput, + int fd, + libinput_source_dispatch_t dispatch, + void *data); + +void +libinput_remove_source(struct libinput *libinput, + struct libinput_source *source); + +void +libinput_post_event(struct libinput *libinput, + struct libinput_event *event); + void keyboard_notify_key(struct libinput_device *device, uint32_t time, @@ -74,26 +99,4 @@ touch_notify_touch(struct libinput_device *device, li_fixed_t y, enum libinput_touch_type touch_type); -static inline li_fixed_t li_fixed_from_int(int i) -{ - return i * 256; -} - -static inline li_fixed_t -li_fixed_from_double(double d) -{ - union { - double d; - int64_t i; - } u; - - u.d = d + (3LL << (51 - 8)); - - return u.i; -} - -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) - -#define LIBINPUT_EXPORT __attribute__ ((visibility("default"))) - #endif /* LIBINPUT_PRIVATE_H */ diff --git a/src/libinput-util.c b/src/libinput-util.c new file mode 100644 index 00000000..9d9d4dd8 --- /dev/null +++ b/src/libinput-util.c @@ -0,0 +1,62 @@ +/* + * Copyright © 2008-2011 Kristian Høgsberg + * Copyright © 2011 Intel Corporation + * + * 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. + */ + +/* + * This list data structure is verbatim copy from wayland-util.h from the + * Wayland project; except that wl_ prefix has been removed. + */ + +#include "config.h" + +#include "libinput-private.h" + +void +list_init(struct list *list) +{ + list->prev = list; + list->next = list; +} + +void +list_insert(struct list *list, struct list *elm) +{ + elm->prev = list; + elm->next = list->next; + list->next = elm; + elm->next->prev = elm; +} + +void +list_remove(struct list *elm) +{ + elm->prev->next = elm->next; + elm->next->prev = elm->prev; + elm->next = NULL; + elm->prev = NULL; +} + +int +list_empty(const struct list *list) +{ + return list->next == list; +} diff --git a/src/libinput-util.h b/src/libinput-util.h new file mode 100644 index 00000000..1395106e --- /dev/null +++ b/src/libinput-util.h @@ -0,0 +1,91 @@ +/* + * Copyright © 2008 Kristian Høgsberg + * + * 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. + */ + +#ifndef LIBINPUT_UTIL_H +#define LIBINPUT_UTIL_H + +/* + * This list data structure is a verbatim copy from wayland-util.h from the + * Wayland project; except that wl_ prefix has been removed. + */ + +struct list { + struct list *prev; + struct list *next; +}; + +void list_init(struct list *list); +void list_insert(struct list *list, struct list *elm); +void list_remove(struct list *elm); +int list_empty(const struct list *list); + +#ifdef __GNUC__ +#define container_of(ptr, sample, member) \ + (__typeof__(sample))((char *)(ptr) - \ + ((char *)&(sample)->member - (char *)(sample))) +#else +#define container_of(ptr, sample, member) \ + (void *)((char *)(ptr) - \ + ((char *)&(sample)->member - (char *)(sample))) +#endif + +#define list_for_each(pos, head, member) \ + for (pos = 0, pos = container_of((head)->next, pos, member); \ + &pos->member != (head); \ + pos = container_of(pos->member.next, pos, member)) + +#define list_for_each_safe(pos, tmp, head, member) \ + for (pos = 0, tmp = 0, \ + pos = container_of((head)->next, pos, member), \ + tmp = container_of((pos)->member.next, tmp, member); \ + &pos->member != (head); \ + pos = tmp, \ + tmp = container_of(pos->member.next, tmp, member)) + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + +/* + * This fixed point implementation is a verbatim copy from wayland-util.h from + * the Wayland project, with the wl_ prefix renamed li_. + */ + +static inline li_fixed_t li_fixed_from_int(int i) +{ + return i * 256; +} + +static inline li_fixed_t +li_fixed_from_double(double d) +{ + union { + double d; + int64_t i; + } u; + + u.d = d + (3LL << (51 - 8)); + + return u.i; +} + +#define LIBINPUT_EXPORT __attribute__ ((visibility("default"))) + +#endif /* LIBINPUT_UTIL_H */ diff --git a/src/libinput.c b/src/libinput.c index fd0fb1e7..af00725d 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -25,15 +25,140 @@ #include #include #include +#include +#include #include "libinput.h" #include "evdev.h" #include "libinput-private.h" +struct libinput_source { + libinput_source_dispatch_t dispatch; + void *user_data; + int fd; + struct list link; +}; + +struct libinput_source * +libinput_add_fd(struct libinput *libinput, + int fd, + libinput_source_dispatch_t dispatch, + void *user_data) +{ + struct libinput_source *source; + struct epoll_event ep; + + source = malloc(sizeof *source); + if (!source) + return NULL; + + source->dispatch = dispatch; + source->user_data = user_data; + source->fd = fd; + + memset(&ep, 0, sizeof ep); + ep.events = EPOLLIN; + ep.data.ptr = source; + + if (epoll_ctl(libinput->epoll_fd, EPOLL_CTL_ADD, fd, &ep) < 0) { + close(source->fd); + free(source); + return NULL; + } + + return source; +} + +void +libinput_remove_source(struct libinput *libinput, + struct libinput_source *source) +{ + epoll_ctl(libinput->epoll_fd, EPOLL_CTL_DEL, source->fd, NULL); + close(source->fd); + source->fd = -1; + list_insert(&libinput->source_destroy_list, &source->link); +} + +LIBINPUT_EXPORT struct libinput * +libinput_create(void) +{ + struct libinput *libinput; + + libinput = zalloc(sizeof *libinput); + if (!libinput) + return NULL; + + list_init(&libinput->source_destroy_list); + + libinput->epoll_fd = epoll_create1(EPOLL_CLOEXEC);; + if (libinput->epoll_fd < 0) + return NULL; + + return libinput; +} + +LIBINPUT_EXPORT void +libinput_destroy(struct libinput *libinput) +{ + struct libinput_event *event; + + while ((event = libinput_get_event(libinput))) + free(event); + free(libinput->events); + + close(libinput->epoll_fd); + free(libinput); +} + +LIBINPUT_EXPORT int +libinput_get_fd(struct libinput *libinput) +{ + return libinput->epoll_fd; +} + +LIBINPUT_EXPORT int +libinput_dispatch(struct libinput *libinput) +{ + struct libinput_source *source, *next; + struct epoll_event ep[32]; + int i, count; + + count = epoll_wait(libinput->epoll_fd, ep, ARRAY_LENGTH(ep), 0); + if (count < 0) + return -1; + + for (i = 0; i < count; ++i) { + source = ep[i].data.ptr; + if (source->fd == -1) + continue; + + source->dispatch(source->user_data); + } + + list_for_each_safe(source, next, &libinput->source_destroy_list, link) + free(source); + list_init(&libinput->source_destroy_list); + + return 0; +} + static void -post_event(struct libinput_device *device, - enum libinput_event_type type, - struct libinput_event *event); +init_event_base(struct libinput_event *event, + enum libinput_event_type type, + struct libinput_device *device) +{ + event->type = type; + event->device = device; +} + +static void +post_device_event(struct libinput_device *device, + enum libinput_event_type type, + struct libinput_event *event) +{ + init_event_base(event, type, device); + libinput_post_event(device->libinput, event); +} void keyboard_notify_key(struct libinput_device *device, @@ -53,7 +178,9 @@ keyboard_notify_key(struct libinput_device *device, .state = state, }; - post_event(device, LIBINPUT_EVENT_KEYBOARD_KEY, &key_event->base); + post_device_event(device, + LIBINPUT_EVENT_KEYBOARD_KEY, + &key_event->base); } void @@ -74,7 +201,9 @@ pointer_notify_motion(struct libinput_device *device, .dy = dy, }; - post_event(device, LIBINPUT_EVENT_POINTER_MOTION, &motion_event->base); + post_device_event(device, + LIBINPUT_EVENT_POINTER_MOTION, + &motion_event->base); } void @@ -95,9 +224,9 @@ pointer_notify_motion_absolute(struct libinput_device *device, .y = y, }; - post_event(device, - LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, - &motion_absolute_event->base); + post_device_event(device, + LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE, + &motion_absolute_event->base); } void @@ -118,7 +247,9 @@ pointer_notify_button(struct libinput_device *device, .state = state, }; - post_event(device, LIBINPUT_EVENT_POINTER_BUTTON, &button_event->base); + post_device_event(device, + LIBINPUT_EVENT_POINTER_BUTTON, + &button_event->base); } void @@ -139,7 +270,9 @@ pointer_notify_axis(struct libinput_device *device, .value = value, }; - post_event(device, LIBINPUT_EVENT_POINTER_AXIS, &axis_event->base); + post_device_event(device, + LIBINPUT_EVENT_POINTER_AXIS, + &axis_event->base); } void @@ -164,23 +297,18 @@ touch_notify_touch(struct libinput_device *device, .touch_type = touch_type, }; - post_event(device, LIBINPUT_EVENT_TOUCH_TOUCH, &touch_event->base); + post_device_event(device, + LIBINPUT_EVENT_TOUCH_TOUCH, + &touch_event->base); } -static void -init_event_base(struct libinput_event *event, enum libinput_event_type type) +void +libinput_post_event(struct libinput *libinput, + struct libinput_event *event) { - event->type = type; -} - -static void -post_event(struct libinput_device *device, - enum libinput_event_type type, - struct libinput_event *event) -{ - struct libinput_event **events = device->events; - size_t events_len = device->events_len; - size_t events_count = device->events_count; + struct libinput_event **events = libinput->events; + size_t events_len = libinput->events_len; + size_t events_count = libinput->events_count; size_t move_len; size_t new_out; @@ -197,62 +325,55 @@ post_event(struct libinput_device *device, return; } - if (device->events_count > 0 && device->events_in == 0) { - device->events_in = device->events_len; - } else if (device->events_count > 0 && - device->events_out >= device->events_in) { - move_len = device->events_len - device->events_out; + if (libinput->events_count > 0 && libinput->events_in == 0) { + libinput->events_in = libinput->events_len; + } else if (libinput->events_count > 0 && + libinput->events_out >= libinput->events_in) { + move_len = libinput->events_len - libinput->events_out; new_out = events_len - move_len; memmove(events + new_out, - device->events + device->events_out, + libinput->events + libinput->events_out, move_len * sizeof *events); - device->events_out = new_out; + libinput->events_out = new_out; } - device->events = events; - device->events_len = events_len; + libinput->events = events; + libinput->events_len = events_len; } - init_event_base(event, type); - - device->events_count = events_count; - events[device->events_in] = event; - device->events_in = (device->events_in + 1) % device->events_len; + libinput->events_count = events_count; + events[libinput->events_in] = event; + libinput->events_in = (libinput->events_in + 1) % libinput->events_len; } LIBINPUT_EXPORT struct libinput_event * -libinput_device_get_event(struct libinput_device *device) +libinput_get_event(struct libinput *libinput) { struct libinput_event *event; - if (device->events_count == 0) + if (libinput->events_count == 0) return NULL; - event = device->events[device->events_out]; - device->events_out = (device->events_out + 1) % device->events_len; - device->events_count--; + event = libinput->events[libinput->events_out]; + libinput->events_out = + (libinput->events_out + 1) % libinput->events_len; + libinput->events_count--; return event; } -LIBINPUT_EXPORT int -libinput_device_dispatch(struct libinput_device *device) -{ - return evdev_device_dispatch((struct evdev_device *) device); -} - LIBINPUT_EXPORT void libinput_device_destroy(struct libinput_device *device) { - struct libinput_event *event; - - while ((event = libinput_device_get_event(device))) - free(event); - free(device->events); - evdev_device_destroy((struct evdev_device *) device); } +LIBINPUT_EXPORT void * +libinput_device_get_user_data(struct libinput_device *device) +{ + return device->device_interface_data; +} + LIBINPUT_EXPORT void libinput_device_led_update(struct libinput_device *device, enum libinput_led leds) diff --git a/src/libinput.h b/src/libinput.h index 745660c2..67b7c1e2 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -77,6 +77,7 @@ enum libinput_event_type { struct libinput_event { enum libinput_event_type type; + struct libinput_device *device; }; struct libinput_event_keyboard_key { @@ -138,36 +139,39 @@ struct libinput_device_interface { void (*get_current_screen_dimensions)(int *width, int *height, void *data); - - /* */ - struct libinput_fd_handle * (*add_fd)(int fd, - libinput_fd_callback callback, - void *data); - void (*remove_fd)(struct libinput_fd_handle *fd_container, - void *data); - - /* */ - void (*device_lost)(void *data); }; -struct libinput_seat; +struct libinput; struct libinput_device; +struct libinput * +libinput_create(void); + +int +libinput_get_fd(struct libinput *libinput); + +int +libinput_dispatch(struct libinput *libinput); + +struct libinput_event * +libinput_get_event(struct libinput *libinput); + +void +libinput_destroy(struct libinput *libinput); + struct libinput_device * -libinput_device_create_evdev(const char *devnode, +libinput_device_create_evdev(struct libinput *libinput, + const char *devnode, int fd, const struct libinput_device_interface *interface, void *user_data); -int -libinput_device_dispatch(struct libinput_device *device); - -struct libinput_event * -libinput_device_get_event(struct libinput_device *device); - void libinput_device_destroy(struct libinput_device *device); +void * +libinput_device_get_user_data(struct libinput_device *device); + void libinput_device_led_update(struct libinput_device *device, enum libinput_led leds); From d894b1d7003e1a7bbccc349d9d9df8a965707b77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sun, 17 Nov 2013 16:59:09 +0100 Subject: [PATCH 161/162] Use events instead of callbacks for capability registration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit also introduces a new requirement to libinput_device_destroy() - libinput_device_terminate() must be called before libinput_device_destroy() in order to allow the user to dispatch the events related to a terminating input devices while the device is still valid. Signed-off-by: Jonas Ådahl --- src/evdev.c | 48 ++++++++++++++++++++---------------------- src/evdev.h | 3 +++ src/libinput-private.h | 9 ++++++++ src/libinput.c | 43 +++++++++++++++++++++++++++++++++++++ src/libinput.h | 22 +++++++++++++------ 5 files changed, 93 insertions(+), 32 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 4f107ea5..0316c6fc 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -585,21 +585,18 @@ evdev_configure_device(struct evdev_device *device) { if ((device->caps & (EVDEV_MOTION_ABS | EVDEV_MOTION_REL)) && (device->caps & EVDEV_BUTTON)) { - device->base.device_interface->register_capability( - LIBINPUT_DEVICE_CAP_POINTER, - device->base.device_interface_data); + device_register_capability(&device->base, + LIBINPUT_DEVICE_CAP_POINTER); device->seat_caps |= EVDEV_DEVICE_POINTER; } if ((device->caps & EVDEV_KEYBOARD)) { - device->base.device_interface->register_capability( - LIBINPUT_DEVICE_CAP_KEYBOARD, - device->base.device_interface_data); + device_register_capability(&device->base, + LIBINPUT_DEVICE_CAP_KEYBOARD); device->seat_caps |= EVDEV_DEVICE_KEYBOARD; } if ((device->caps & EVDEV_TOUCH)) { - device->base.device_interface->register_capability( - LIBINPUT_DEVICE_CAP_TOUCH, - device->base.device_interface_data); + device_register_capability(&device->base, + LIBINPUT_DEVICE_CAP_TOUCH); device->seat_caps |= EVDEV_DEVICE_TOUCH; } @@ -680,27 +677,28 @@ evdev_device_calibrate(struct evdev_device *device, float calibration[6]) memcpy(device->abs.calibration, calibration, sizeof calibration); } +void +evdev_device_terminate(struct evdev_device *device) +{ + if (device->seat_caps & EVDEV_DEVICE_POINTER) { + device_unregister_capability(&device->base, + LIBINPUT_DEVICE_CAP_POINTER); + } + if (device->seat_caps & EVDEV_DEVICE_KEYBOARD) { + device_unregister_capability(&device->base, + LIBINPUT_DEVICE_CAP_KEYBOARD); + } + if (device->seat_caps & EVDEV_DEVICE_TOUCH) { + device_unregister_capability(&device->base, + LIBINPUT_DEVICE_CAP_TOUCH); + } +} + void evdev_device_destroy(struct evdev_device *device) { struct evdev_dispatch *dispatch; - if (device->seat_caps & EVDEV_DEVICE_POINTER) { - device->base.device_interface->unregister_capability( - LIBINPUT_DEVICE_CAP_POINTER, - device->base.device_interface_data); - } - if (device->seat_caps & EVDEV_DEVICE_KEYBOARD) { - device->base.device_interface->unregister_capability( - LIBINPUT_DEVICE_CAP_KEYBOARD, - device->base.device_interface_data); - } - if (device->seat_caps & EVDEV_DEVICE_TOUCH) { - device->base.device_interface->unregister_capability( - LIBINPUT_DEVICE_CAP_TOUCH, - device->base.device_interface_data); - } - dispatch = device->dispatch; if (dispatch) dispatch->interface->destroy(dispatch); diff --git a/src/evdev.h b/src/evdev.h index 1b45aed0..c8cb4054 100644 --- a/src/evdev.h +++ b/src/evdev.h @@ -144,6 +144,9 @@ evdev_device_get_keys(struct evdev_device *device, char *keys, size_t size); void evdev_device_calibrate(struct evdev_device *device, float calibration[6]); +void +evdev_device_terminate(struct evdev_device *terminate); + void evdev_device_destroy(struct evdev_device *device); diff --git a/src/libinput-private.h b/src/libinput-private.h index 6796ccfa..e9a5aaa9 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -41,6 +41,7 @@ struct libinput_device { struct libinput *libinput; const struct libinput_device_interface *device_interface; void *device_interface_data; + int terminated; }; typedef void (*libinput_source_dispatch_t)(void *data); @@ -61,6 +62,14 @@ void libinput_post_event(struct libinput *libinput, struct libinput_event *event); +void +device_register_capability(struct libinput_device *device, + enum libinput_device_capability capability); + +void +device_unregister_capability(struct libinput_device *device, + enum libinput_device_capability capability); + void keyboard_notify_key(struct libinput_device *device, uint32_t time, diff --git a/src/libinput.c b/src/libinput.c index af00725d..0226b81c 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "libinput.h" #include "evdev.h" @@ -160,6 +161,40 @@ post_device_event(struct libinput_device *device, libinput_post_event(device->libinput, event); } +void +device_register_capability(struct libinput_device *device, + enum libinput_device_capability capability) +{ + struct libinput_event_device_register_capability *capability_event; + + capability_event = malloc(sizeof *capability_event); + + *capability_event = (struct libinput_event_device_register_capability) { + .capability = capability, + }; + + post_device_event(device, + LIBINPUT_EVENT_DEVICE_REGISTER_CAPABILITY, + &capability_event->base); +} + +void +device_unregister_capability(struct libinput_device *device, + enum libinput_device_capability capability) +{ + struct libinput_event_device_unregister_capability *capability_event; + + capability_event = malloc(sizeof *capability_event); + + *capability_event = (struct libinput_event_device_unregister_capability) { + .capability = capability, + }; + + post_device_event(device, + LIBINPUT_EVENT_DEVICE_UNREGISTER_CAPABILITY, + &capability_event->base); +} + void keyboard_notify_key(struct libinput_device *device, uint32_t time, @@ -362,9 +397,17 @@ libinput_get_event(struct libinput *libinput) return event; } +LIBINPUT_EXPORT void +libinput_device_terminate(struct libinput_device *device) +{ + evdev_device_terminate((struct evdev_device *) device); + device->terminated = 1; +} + LIBINPUT_EXPORT void libinput_device_destroy(struct libinput_device *device) { + assert(device->terminated); evdev_device_destroy((struct evdev_device *) device); } diff --git a/src/libinput.h b/src/libinput.h index 67b7c1e2..ee6b98ae 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -64,6 +64,8 @@ enum libinput_touch_type { }; enum libinput_event_type { + LIBINPUT_EVENT_DEVICE_REGISTER_CAPABILITY = 200, + LIBINPUT_EVENT_DEVICE_UNREGISTER_CAPABILITY, LIBINPUT_EVENT_KEYBOARD_KEY = 300, @@ -80,6 +82,16 @@ struct libinput_event { struct libinput_device *device; }; +struct libinput_event_device_register_capability { + struct libinput_event base; + enum libinput_device_capability capability; +}; + +struct libinput_event_device_unregister_capability { + struct libinput_event base; + enum libinput_device_capability capability; +}; + struct libinput_event_keyboard_key { struct libinput_event base; uint32_t time; @@ -129,13 +141,6 @@ struct libinput_fd_handle; typedef void (*libinput_fd_callback)(int fd, void *data); struct libinput_device_interface { - /* */ - void (*register_capability)(enum libinput_device_capability capability, - void *data); - void (*unregister_capability)(enum libinput_device_capability capability, - void *data); - - /* */ void (*get_current_screen_dimensions)(int *width, int *height, void *data); @@ -166,6 +171,9 @@ libinput_device_create_evdev(struct libinput *libinput, const struct libinput_device_interface *interface, void *user_data); +void +libinput_device_terminate(struct libinput_device *device); + void libinput_device_destroy(struct libinput_device *device); From 3450e49c867e6f00db49f9093df75909147cce97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sun, 17 Nov 2013 19:31:34 +0100 Subject: [PATCH 162/162] Add interface to libinput object and move screen dimension callback to it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jonas Ådahl --- src/evdev.c | 16 +++++++++------- src/libinput-private.h | 6 ++++-- src/libinput.c | 7 +++++-- src/libinput.h | 10 +++++----- 4 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/evdev.c b/src/evdev.c index 0316c6fc..55d8a155 100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -227,13 +227,15 @@ evdev_process_touch(struct evdev_device *device, struct input_event *e, uint32_t time) { + struct libinput *libinput = device->base.libinput; int screen_width; int screen_height; - device->base.device_interface->get_current_screen_dimensions( + libinput->interface->get_current_screen_dimensions( + &device->base, &screen_width, &screen_height, - device->base.device_interface_data); + libinput->user_data); switch (e->code) { case ABS_MT_SLOT: @@ -270,13 +272,15 @@ static inline void evdev_process_absolute_motion(struct evdev_device *device, struct input_event *e) { + struct libinput *libinput = device->base.libinput; int screen_width; int screen_height; - device->base.device_interface->get_current_screen_dimensions( + libinput->interface->get_current_screen_dimensions( + &device->base, &screen_width, &screen_height, - device->base.device_interface_data); + libinput->user_data); switch (e->code) { case ABS_X: @@ -608,7 +612,6 @@ libinput_device_create_evdev( struct libinput *libinput, const char *devnode, int fd, - const struct libinput_device_interface *device_interface, void *user_data) { struct evdev_device *device; @@ -619,8 +622,7 @@ libinput_device_create_evdev( return NULL; device->base.libinput = libinput; - device->base.device_interface = device_interface; - device->base.device_interface_data = user_data; + device->base.user_data = user_data; device->seat_caps = 0; device->is_mt = 0; diff --git a/src/libinput-private.h b/src/libinput-private.h index e9a5aaa9..f49badce 100644 --- a/src/libinput-private.h +++ b/src/libinput-private.h @@ -35,12 +35,14 @@ struct libinput { size_t events_len; size_t events_in; size_t events_out; + + const struct libinput_interface *interface; + void *user_data; }; struct libinput_device { struct libinput *libinput; - const struct libinput_device_interface *device_interface; - void *device_interface_data; + void *user_data; int terminated; }; diff --git a/src/libinput.c b/src/libinput.c index 0226b81c..10d6fc13 100644 --- a/src/libinput.c +++ b/src/libinput.c @@ -81,7 +81,7 @@ libinput_remove_source(struct libinput *libinput, } LIBINPUT_EXPORT struct libinput * -libinput_create(void) +libinput_create(const struct libinput_interface *interface, void *user_data) { struct libinput *libinput; @@ -91,6 +91,9 @@ libinput_create(void) list_init(&libinput->source_destroy_list); + libinput->interface = interface; + libinput->user_data = user_data; + libinput->epoll_fd = epoll_create1(EPOLL_CLOEXEC);; if (libinput->epoll_fd < 0) return NULL; @@ -414,7 +417,7 @@ libinput_device_destroy(struct libinput_device *device) LIBINPUT_EXPORT void * libinput_device_get_user_data(struct libinput_device *device) { - return device->device_interface_data; + return device->user_data; } LIBINPUT_EXPORT void diff --git a/src/libinput.h b/src/libinput.h index ee6b98ae..a051e4ac 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -140,17 +140,18 @@ struct libinput_fd_handle; typedef void (*libinput_fd_callback)(int fd, void *data); -struct libinput_device_interface { - void (*get_current_screen_dimensions)(int *width, +struct libinput_interface { + void (*get_current_screen_dimensions)(struct libinput_device *device, + int *width, int *height, - void *data); + void *user_data); }; struct libinput; struct libinput_device; struct libinput * -libinput_create(void); +libinput_create(const struct libinput_interface *interface, void *user_data); int libinput_get_fd(struct libinput *libinput); @@ -168,7 +169,6 @@ struct libinput_device * libinput_device_create_evdev(struct libinput *libinput, const char *devnode, int fd, - const struct libinput_device_interface *interface, void *user_data); void