libinput repository created

2014-01-27 Thread Peter Hutterer
Hi guys

after a bit of waiting time, we now have libinput in a fresh, still warm
repository on freedesktop:
http://cgit.freedesktop.org/wayland/libinput

libinput is the weston input handling code forked off into a library. The
goal of libinput is to provide a common code base for the various
input-device related bits we need in all compositors. There's little point
to every compositor having a separate implementation for touchpad tapping,
scrolling, etc.

Since Jonas' original announcement in November a few bits and pieces have
changed. If you haven't followed the history on Jonas' github repository,
here is a short summary:

* the API is an event-based API as opposed to the original interface API, so
  the basic interaction with libinput is libinput_dispatch() followed by
  libinput_get_event() for the actual event handling in the compositor.
  The event types are one high-level type (libinput_event) and one for each
  logical group of events (libinput_event_pointer, libinput_event_keyboard,
  ...), each of which with their own accessors.

* plenty of doxygen documentation was added, so it looks almost like a
  well-documented library now ;)

* the udev discovery code is now inside libinput, so a simple
  libinput_create_from_udev() is enough to get libinput onto the device list

* a path-based backend was added (mainly for Xorg drivers and the test
  suite) to create a context from a single device node
 
* a test suite was added, still needs a few more tests but it's coming along
  well

* seat events were removed as top-level events, libinput provides device
  added/removed events and if seat information is needed it can be obtained
  from the device directly

I've collected the usual links and basic information on a small wiki page:
http://freedesktop.org/wiki/Software/libinput/

Note that the project is still quite young, the actual code on features not
related to transforming it to a library has changed very little so don't
expect it to behave much different to what weston already uses.

Specificially, two big bits that are currently missing are device capability
discovery (is this a touchpad? what's the x axis resolution?) and a
configuration interface (tapping enabled or disabled?). This will come over
the next weeks and months.

This email is mostly a heads-up that the project exists 'officially' now.
And we'll be using wayland-devel as the discussion and patch review list, so
expect to see a number of patches heading straight for here. Do chime in and
comment.

Cheers,
   Peter
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 5/5] tools: add a tool for basic event debugging

2014-01-28 Thread Peter Hutterer
Simply prints the various events to make it easier to check what's coming out
of libinput. Works for --udev (the default) or for --device /dev/input/event0.
Example output:

event7  DEVICE_ADDEDseat0   default
event8  DEVICE_ADDEDseat0   default
event4  POINTER_BUTTON   +1.35s 272 pressed
event5  POINTER_MOTION   +2.31s  -3.00/  2.00

Time is displayed relative to the starting time.

Note: statically linked for easier debugging, but we don't distribute it
(yet) anyway.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 Makefile.am |   2 +-
 configure.ac|   3 +-
 tools/.gitignore|   1 +
 tools/Makefile.am   |   7 +
 tools/event-debug.c | 453 
 5 files changed, 464 insertions(+), 2 deletions(-)
 create mode 100644 tools/.gitignore
 create mode 100644 tools/Makefile.am
 create mode 100644 tools/event-debug.c

diff --git a/Makefile.am b/Makefile.am
index 07bfcd4..08bf7ce 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,3 +1,3 @@
-SUBDIRS = src doc test
+SUBDIRS = src doc test tools
 
 ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
diff --git a/configure.ac b/configure.ac
index 7281bb4..44729a9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -87,5 +87,6 @@ AC_CONFIG_FILES([Makefile
 src/Makefile
 src/libinput.pc
 src/libinput-version.h
-test/Makefile])
+test/Makefile
+tools/Makefile])
 AC_OUTPUT
diff --git a/tools/.gitignore b/tools/.gitignore
new file mode 100644
index 000..2cdd654
--- /dev/null
+++ b/tools/.gitignore
@@ -0,0 +1 @@
+event-debug
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 000..9c29f56
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,7 @@
+noinst_PROGRAMS = event-debug
+
+AM_CPPFLAGS = -I$(top_srcdir)/src
+
+event_debug_SOURCES = event-debug.c
+event_debug_LDADD = ../src/libinput.la
+event_debug_LDFLAGS = -static
diff --git a/tools/event-debug.c b/tools/event-debug.c
new file mode 100644
index 000..53e92b0
--- /dev/null
+++ b/tools/event-debug.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright © 2014 Red Hat, Inc.
+ *
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include errno.h
+#include fcntl.h
+#include getopt.h
+#include poll.h
+#include stdio.h
+#include signal.h
+#include string.h
+#include time.h
+#include unistd.h
+#include linux/input.h
+#include sys/ioctl.h
+#include sys/signalfd.h
+
+#include libinput.h
+
+static enum {
+   MODE_UDEV,
+   MODE_DEVICE,
+} mode = MODE_UDEV;
+static const char *device;
+static const char *seat = seat0;
+static struct udev *udev;
+uint32_t start_time;
+
+static void
+usage(void)
+{
+   printf(Usage: %s [--udev [seat]|--device /dev/input/event0]\n
+  --udev seat Use udev device discovery (default).\n
+Specifying a seat ID is optional.\n
+  --device /path/to/device  open the given device only\n,
+   program_invocation_short_name);
+}
+
+static int
+parse_args(int argc, char **argv)
+{
+   while (1) {
+   int c;
+   int option_index = 0;
+   static struct option opts[] = {
+   { device, 1, 0, 'd' },
+   { udev, 0, 0, 'u' },
+   { help, 0, 0, 'h' },
+   { 0, 0, 0, 0}
+   };
+
+   c = getopt_long(argc, argv, h, opts, option_index);
+   if (c == -1)
+   break;
+
+   switch(c) {
+   case 'h': /* --help */
+   usage();
+   exit(0);
+   case 'd': /* --device */
+   mode = MODE_DEVICE;
+   if (!optarg

[PATCH libinput 3/5] path: print error when failing to open a device

2014-01-28 Thread Peter Hutterer
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/path.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/path.c b/src/path.c
index 2553005..2b8f530 100644
--- a/src/path.c
+++ b/src/path.c
@@ -130,7 +130,8 @@ path_input_enable(struct libinput *libinput)
 
fd = open_restricted(libinput, input-path, O_RDWR|O_NONBLOCK);
if (fd  0) {
-   log_info(opening input device '%s' failed.\n, devnode);
+   log_info(opening input device '%s' failed (%s).\n,
+devnode, strerror(-fd));
return -1;
}
 
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 4/5] test: Make sure the sysname of a device is correct

2014-01-28 Thread Peter Hutterer
Currently this means start with event and don't contain /.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 test/path.c | 23 +++
 test/udev.c | 34 ++
 2 files changed, 57 insertions(+)

diff --git a/test/path.c b/test/path.c
index 12787f6..875cd88 100644
--- a/test/path.c
+++ b/test/path.c
@@ -187,6 +187,28 @@ START_TEST(path_added_device)
 }
 END_TEST
 
+START_TEST(path_device_sysname)
+{
+   struct litest_device *dev = litest_current_device();
+   struct libinput_event *ev;
+   struct libinput_device *device;
+   const char *sysname;
+
+   libinput_dispatch(dev-libinput);
+
+   while ((ev = libinput_get_event(dev-libinput))) {
+   if (libinput_event_get_type(ev) != LIBINPUT_EVENT_DEVICE_ADDED)
+   continue;
+
+   device = libinput_event_get_device(ev);
+   sysname = libinput_device_get_sysname(device);
+   ck_assert(sysname != NULL  strlen(sysname)  1);
+   ck_assert(strchr(sysname, '/') == NULL);
+   ck_assert_int_eq(strncmp(sysname, event, 5), 0);
+   }
+}
+END_TEST
+
 START_TEST(path_suspend)
 {
struct libinput *li;
@@ -304,6 +326,7 @@ int main (int argc, char **argv) {
litest_add(path:suspend, path_double_resume, LITEST_ANY, LITEST_ANY);
litest_add(path:seat events, path_added_seat, LITEST_ANY, LITEST_ANY);
litest_add(path:device events, path_added_device, LITEST_ANY, 
LITEST_ANY);
+   litest_add(path:device events, path_device_sysname, LITEST_ANY, 
LITEST_ANY);
 
return litest_run(argc, argv);
 }
diff --git a/test/udev.c b/test/udev.c
index f61dd24..235d10e 100644
--- a/test/udev.c
+++ b/test/udev.c
@@ -294,6 +294,39 @@ START_TEST(udev_suspend_resume)
 }
 END_TEST
 
+START_TEST(udev_device_sysname)
+{
+   struct libinput *li;
+   struct libinput_event *ev;
+   struct libinput_device *device;
+   const char *sysname;
+   struct udev *udev;
+
+   udev = udev_new();
+   ck_assert(udev != NULL);
+
+   li = libinput_create_from_udev(simple_interface, NULL, udev, seat0);
+   ck_assert(li != NULL);
+
+   libinput_dispatch(li);
+
+   while ((ev = libinput_get_event(li))) {
+   if (libinput_event_get_type(ev) != LIBINPUT_EVENT_DEVICE_ADDED)
+   continue;
+
+   device = libinput_event_get_device(ev);
+   sysname = libinput_device_get_sysname(device);
+   ck_assert(sysname != NULL  strlen(sysname)  1);
+   ck_assert(strchr(sysname, '/') == NULL);
+   ck_assert_int_eq(strncmp(sysname, event, 5), 0);
+   libinput_event_destroy(ev);
+   }
+
+   libinput_destroy(li);
+   udev_unref(udev);
+}
+END_TEST
+
 int main (int argc, char **argv) {
 
litest_add_no_device(udev:create, udev_create_NULL);
@@ -305,6 +338,7 @@ int main (int argc, char **argv) {
litest_add(udev:suspend, udev_double_suspend, LITEST_ANY, LITEST_ANY);
litest_add(udev:suspend, udev_double_resume, LITEST_ANY, LITEST_ANY);
litest_add(udev:suspend, udev_suspend_resume, LITEST_ANY, LITEST_ANY);
+   litest_add(udev:device events, udev_device_sysname, LITEST_ANY, 
LITEST_ANY);
 
return litest_run(argc, argv);
 }
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 2/5] path: store the sysname, not the syspath, in the device

2014-01-28 Thread Peter Hutterer
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/path.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/src/path.c b/src/path.c
index 3b09cbe..2553005 100644
--- a/src/path.c
+++ b/src/path.c
@@ -75,7 +75,7 @@ path_seat_create(struct path_input *input,
 
 static int
 path_get_udev_properties(const char *path,
-char **syspath,
+char **sysname,
 char **seat_name,
 char **seat_logical_name)
 {
@@ -96,7 +96,7 @@ path_get_udev_properties(const char *path,
if (!device)
goto out;
 
-   *syspath = strdup(udev_device_get_syspath(device));
+   *sysname = strdup(udev_device_get_sysname(device));
 
seat = udev_device_get_property_value(device, ID_SEAT);
*seat_name = strdup(seat ? seat : default_seat);
@@ -121,7 +121,7 @@ path_input_enable(struct libinput *libinput)
struct path_seat *seat;
struct evdev_device *device;
const char *devnode = input-path;
-   char *syspath;
+   char *sysname;
int fd;
char *seat_name, *seat_logical_name;
 
@@ -134,10 +134,10 @@ path_input_enable(struct libinput *libinput)
return -1;
}
 
-   if (path_get_udev_properties(devnode, syspath,
+   if (path_get_udev_properties(devnode, sysname,
 seat_name, seat_logical_name) == -1) {
close_restricted(libinput, fd);
-   log_info(failed to obtain syspath for device '%s'.\n, 
devnode);
+   log_info(failed to obtain sysname for device '%s'.\n, 
devnode);
return -1;
}
 
@@ -145,8 +145,8 @@ path_input_enable(struct libinput *libinput)
free(seat_name);
free(seat_logical_name);
 
-   device = evdev_device_create(seat-base, devnode, syspath, fd);
-   free(syspath);
+   device = evdev_device_create(seat-base, devnode, sysname, fd);
+   free(sysname);
libinput_seat_unref(seat-base);
 
if (device == EVDEV_UNHANDLED_DEVICE) {
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


libinput requirements for feature parity with X

2014-01-28 Thread Peter Hutterer
Here's a list of features I consider the minimum to get something akin to
feature-parity with the current X.Org-based stack. This is not a wishlist
for features, it's a list of minimum requirements that covers 90% of the
user base.

keyboard:
I don't think there's much to do, keyboards are fairly simple and the hard
bits are handled in the client with XKB.

mouse-like pointer devices:
* middle mouse button emulation (left+right → middle)
* configuration interface for mouse button mapping, specifically left-handed
* lower-priority: wheel emulation
* lower-priority: rotation

direct-touch touchscreens:
* optional: configuration interface for rotation. can be achieved with the
  calibration matrix already

touchpads:
* clickpad-style software buttons
* middle mouse button emulation (for physical buttons)
* two/three-finger tapping + configuration interface
* edge scrolling
* support for Lenovo T440 style trackstick buttons
* disable-while-typing
* clickfinger handling
* lower-priority: palm detection
* lower-priority: accidental click detection

graphics tablets:
* extended axis event support
* tool change notification (could be just button events? not sure)
* interface to switch between relative and absolute mode
* device rotation
* touch-vs-pen event synchronization (disable touch while the pen is in use,
  etc.)

generic:
* type identifier interface, so that a compositor can tell that there's a
  touchpad present, or a mouse, or...
* configuration interfaces for the various settings
* device capability discovery interfaces for axis resolutions, number of
  buttons, etc.

Anything obvious I missed here?

Cheers,
   Peter
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 2/2] Remove mention of delta coordinates having device specific direction

2014-01-29 Thread Peter Hutterer
On Wed, Jan 29, 2014 at 09:33:12PM +0100, Jonas Ådahl wrote:
 The event represent pointer motions on a screen, so this information is
 unnecessary. It could also be confused for meaning the provided
 coordinate's direction being device specific.
 
 Signed-off-by: Jonas Ådahl jad...@gmail.com

just for the archives: what I meant with this sentence is that while the
positive x/y coordinates are right/down on the screen, there is no guarantee
that matches a device's notion of up/down. for example, if you hold a
graphics tablet upside down, the positive y direction is actually up on
the tablet (if it isn't software-rotated).

This is probably obvious anyway, and the extra documentation does little
other than adding confusion, so 
Reviewed-by: Peter Hutterer peter.hutte...@who-t.net.

Cheers,
   Peter

 ---
  src/libinput.h | 12 ++--
  1 file changed, 6 insertions(+), 6 deletions(-)
 
 diff --git a/src/libinput.h b/src/libinput.h
 index 8d347b9..e2d83bf 100644
 --- a/src/libinput.h
 +++ b/src/libinput.h
 @@ -363,9 +363,9 @@ libinput_event_pointer_get_time(
  /**
   * @ingroup event_pointer
   *
 - * Return the delta between the last event and the current event. The axis'
 - * positive direction is device-specific. For pointer events that are
 - * not of type LIBINPUT_EVENT_POINTER_MOTION, this function returns 0.
 + * Return the delta between the last event and the current event. For pointer
 + * events that are not of type LIBINPUT_EVENT_POINTER_MOTION, this function
 + * returns 0.
   *
   * @note It is an application bug to call this function for events other than
   * LIBINPUT_EVENT_POINTER_MOTION.
 @@ -379,9 +379,9 @@ libinput_event_pointer_get_dx(
  /**
   * @ingroup event_pointer
   *
 - * Return the delta between the last event and the current event. The
 - * axis' positive direction is device-specific. For pointer events that are
 - * not of type LIBINPUT_EVENT_POINTER_MOTION, this function returns 0.
 + * Return the delta between the last event and the current event. For pointer
 + * events that are not of type LIBINPUT_EVENT_POINTER_MOTION, this function
 + * returns 0.
   *
   * @note It is an application bug to call this function for events other than
   * LIBINPUT_EVENT_POINTER_MOTION.
 -- 
 1.8.3.2
 
 ___
 wayland-devel mailing list
 wayland-devel@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/wayland-devel
 
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 1/2] Replace output screen size callback with transform helpers

2014-01-29 Thread Peter Hutterer
On Wed, Jan 29, 2014 at 09:33:11PM +0100, Jonas Ådahl wrote:
 Instead of automatically transforming absolute coordinates of touch and
 pointer events to screen coordinates, the user now uses the corresponding
 transform helper function. This means the coordinates returned by
 libinput_event_pointer_get_absolute_x(),
 libinput_event_pointer_get_absolute_y(), libinput_touch_get_x() and
 libinput_touch_get_y() has changed from being in output screen coordinate
 space to being in device specific coordinate space.
 
 For example, where one before would call libinput_event_touch_get_x(event),
 one now calls libinput_event_touch_get_x_transformed(event, output_width).
 
 Signed-off-by: Jonas Ådahl jad...@gmail.com
 ---
  src/evdev.c|  54 ++--
  src/evdev.h|  10 +
  src/libinput.c |  44 
  src/libinput.h | 128 
 +
  test/litest.c  |  11 -
  5 files changed, 186 insertions(+), 61 deletions(-)
 
 diff --git a/src/evdev.c b/src/evdev.c
 index 46bd35a..cb83a1f 100644
 --- a/src/evdev.c
 +++ b/src/evdev.c
 @@ -86,6 +86,24 @@ transform_absolute(struct evdev_device *device, int32_t 
 *x, int32_t *y)
   }
  }
  
 +li_fixed_t
 +evdev_device_transform_x(struct evdev_device *device,
 +  li_fixed_t x,
 +  uint32_t width)
 +{
 + return (x - device-abs.min_x) * width /
 + (device-abs.max_x - device-abs.min_x);
 +}
 +
 +li_fixed_t
 +evdev_device_transform_y(struct evdev_device *device,
 +  li_fixed_t y,
 +  uint32_t height)
 +{
 + return (y - device-abs.min_y) * height /
 + (device-abs.max_y - device-abs.min_y);

you're mixing coordinate systems here, x and y are in fixed_t but
abs.min/max is in normal integers. that breaks if you have a non-zero min.
You'll need to convert the rest to li_fixed_t too if you want to keep the
integer division.

also, should we add a non-zero min for width and height to scale to a screen
not the top/left-most? The compositor can just add it afterwards, but 
it would have to convert to fixed_t as well:

x = libinput_event_touch_get_x_transformed(event, screen_width);
x += li_fixed_from_int(screen_offset);

which is more error prone than something like:

x = libinput_event_touch_get_x_transformed(event, screen_offset_x, 
screen_width);

also, is it likely that the caller always has the screen dimensions handy
when it comes to processing events? or would an config-style approach work
better:

   libinput_device_set_output_dimensions(device, xoff, yoff, width, height);
   ...
   x = libinput_event_touch_get_x_transformed(event);
   y = libinput_event_touch_get_y_transformed(event);

I also suspect that the device-specific dimensions will be rather useless if
we don't have a call to get the min/max from each device. which I should be
focusing on real soon :)

Cheers,
   Peter

 +}
 +
  static void
  evdev_flush_pending_event(struct evdev_device *device, uint32_t time)
  {
 @@ -242,16 +260,6 @@ evdev_process_touch(struct evdev_device *device,
   struct input_event *e,
   uint32_t time)
  {
 - struct libinput *libinput = device-base.seat-libinput;
 - int screen_width;
 - int screen_height;
 -
 - libinput-interface-get_current_screen_dimensions(
 - device-base,
 - screen_width,
 - screen_height,
 - libinput-user_data);
 -
   switch (e-code) {
   case ABS_MT_SLOT:
   evdev_flush_pending_event(device, time);
 @@ -267,16 +275,12 @@ evdev_process_touch(struct evdev_device *device,
   device-pending_event = EVDEV_ABSOLUTE_MT_UP;
   break;
   case ABS_MT_POSITION_X:
 - device-mt.slots[device-mt.slot].x =
 - (e-value - device-abs.min_x) * screen_width /
 - (device-abs.max_x - device-abs.min_x);
 + device-mt.slots[device-mt.slot].x = e-value;
   if (device-pending_event == EVDEV_NONE)
   device-pending_event = EVDEV_ABSOLUTE_MT_MOTION;
   break;
   case ABS_MT_POSITION_Y:
 - device-mt.slots[device-mt.slot].y =
 - (e-value - device-abs.min_y) * screen_height /
 - (device-abs.max_y - device-abs.min_y);
 + device-mt.slots[device-mt.slot].y = e-value;
   if (device-pending_event == EVDEV_NONE)
   device-pending_event = EVDEV_ABSOLUTE_MT_MOTION;
   break;
 @@ -287,28 +291,14 @@ static inline void
  evdev_process_absolute_motion(struct evdev_device *device,
 struct input_event *e)
  {
 - struct libinput *libinput = device-base.seat-libinput;
 - int screen_width;
 - int screen_height;
 -
 - libinput-interface-get_current_screen_dimensions(
 - device-base,
 -

Re: libinput requirements for feature parity with X

2014-01-30 Thread Peter Hutterer
On Thu, Jan 30, 2014 at 10:30:40AM -0800, Ping Cheng wrote:
 On Tue, Jan 28, 2014 at 6:18 PM, Peter Hutterer 
 peter.hutte...@who-t.netwrote:
 
  Here's a list of features I consider the minimum to get something akin to
  feature-parity with the current X.Org-based stack. This is not a wishlist
  for features, it's a list of minimum requirements that covers 90% of the
  user base.
 
  keyboard:
  I don't think there's much to do, keyboards are fairly simple and the hard
  bits are handled in the client with XKB.
 
  mouse-like pointer devices:
  * middle mouse button emulation (left+right → middle)
  * configuration interface for mouse button mapping, specifically
  left-handed
  * lower-priority: wheel emulation
  * lower-priority: rotation
 
  direct-touch touchscreens:
  * optional: configuration interface for rotation. can be achieved with the
calibration matrix already
 
  touchpads:
  * clickpad-style software buttons
  * middle mouse button emulation (for physical buttons)
  * two/three-finger tapping + configuration interface
  * edge scrolling
  * support for Lenovo T440 style trackstick buttons
  * disable-while-typing
  * clickfinger handling
  * lower-priority: palm detection
  * lower-priority: accidental click detection
 
  graphics tablets:
  * extended axis event support
  * tool change notification (could be just button events? not sure)
 
 
 Will tool id, serial number, and tool type be supported here?

eventually, yes, though I'm not quite sure yet how.

Cheers,
   Peter

  * interface to switch between relative and absolute mode
  * device rotation
  * touch-vs-pen event synchronization (disable touch while the pen is in
  use,
etc.)
 
  generic:
  * type identifier interface, so that a compositor can tell that there's a
touchpad present, or a mouse, or...
  * configuration interfaces for the various settings
  * device capability discovery interfaces for axis resolutions, number of
buttons, etc.
 
  Anything obvious I missed here?
 
  Cheers,
 Peter
  ___
  wayland-devel mailing list
  wayland-devel@lists.freedesktop.org
  http://lists.freedesktop.org/mailman/listinfo/wayland-devel
 
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: libinput requirements for feature parity with X

2014-01-30 Thread Peter Hutterer
On Thu, Jan 30, 2014 at 01:42:20PM -0800, Bill Spitzak wrote:
 Ping Cheng wrote:
 
 graphics tablets:
 * extended axis event support
 * tool change notification (could be just button events? not sure)
 
 
 Will tool id, serial number, and tool type be supported here?
 
 Shouldn't each tool be a different pointing device? 

That largely depends on where tools are expected to be unified. Some pens
(Intuos 4, 5, Pro series) have unique IDs. So if you take them from one
tablet to the next, the ID obviously stays the same so in theory you could
attach a color to that tool and have it span multiple tablets.

I think this is something the client stack should provide, if at all. That
leaves libinput with the tablet as the main device, and the tool as a
subfeature on it.

 It at least
 needs to know which tool is being used when moving it, it can't be
 deferred until the first button is being pushed.
 
 Are tablets capable of handling more than one tool at a time? If

In the Wacom range the answer to that is some old serial ones did, but none
of the tablets that came out in recent years. And I think it's unlikely to
happen again.

 this is at all plausable I think they all have to be different
 pointers since otherwise there is no way to indicate which x/y
 position is which tool. Otherwise I guess a tool changed event
 would work.

You can augment events through other means to indicate the tool in use, you
don't need several devices.

Cheers,
   Peter
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 1/2] Replace output screen size callback with transform helpers

2014-01-30 Thread Peter Hutterer
On Thu, Jan 30, 2014 at 08:38:02AM +0100, Jonas Ådahl wrote:
 On Thu, Jan 30, 2014 at 01:02:15PM +1000, Peter Hutterer wrote:
  On Wed, Jan 29, 2014 at 09:33:11PM +0100, Jonas Ådahl wrote:
   Instead of automatically transforming absolute coordinates of touch and
   pointer events to screen coordinates, the user now uses the corresponding
   transform helper function. This means the coordinates returned by
   libinput_event_pointer_get_absolute_x(),
   libinput_event_pointer_get_absolute_y(), libinput_touch_get_x() and
   libinput_touch_get_y() has changed from being in output screen coordinate
   space to being in device specific coordinate space.
   
   For example, where one before would call 
   libinput_event_touch_get_x(event),
   one now calls libinput_event_touch_get_x_transformed(event, output_width).
   
   Signed-off-by: Jonas Ådahl jad...@gmail.com
   ---
src/evdev.c|  54 ++--
src/evdev.h|  10 +
src/libinput.c |  44 
src/libinput.h | 128 
   +
test/litest.c  |  11 -
5 files changed, 186 insertions(+), 61 deletions(-)
   
   diff --git a/src/evdev.c b/src/evdev.c
   index 46bd35a..cb83a1f 100644
   --- a/src/evdev.c
   +++ b/src/evdev.c
   @@ -86,6 +86,24 @@ transform_absolute(struct evdev_device *device, 
   int32_t *x, int32_t *y)
 }
}

   +li_fixed_t
   +evdev_device_transform_x(struct evdev_device *device,
   +  li_fixed_t x,
   +  uint32_t width)
   +{
   + return (x - device-abs.min_x) * width /
   + (device-abs.max_x - device-abs.min_x);
   +}
   +
   +li_fixed_t
   +evdev_device_transform_y(struct evdev_device *device,
   +  li_fixed_t y,
   +  uint32_t height)
   +{
   + return (y - device-abs.min_y) * height /
   + (device-abs.max_y - device-abs.min_y);
  
  you're mixing coordinate systems here, x and y are in fixed_t but
  abs.min/max is in normal integers. that breaks if you have a non-zero min.
  You'll need to convert the rest to li_fixed_t too if you want to keep the
  integer division.
 
 Yea, missed the wl_fixed_from_int here (and in _x), and they were all 0
 so didn't notice it either. For multiplication, one of the factors cannot be
 li_fixed_t though. Same goes for division where the denominator needs to
 be a normal int even if the numerator is li_fixed_t.

I agree, but cannot should read does not need to be. the complete formula 
is:

  scaled = (x - xmin) * (screen_max_x - screen_min_x)/(xmax - xmin) + 
screen_min_x

fixed_t is essentially (foo * 256), so if we assume x is in fixed_t and we
convert everything to fixed, we have

  = (x - xmin * 256) * (screen_max_x * 256 - screen_min_x * 256)/(xmax * 256 - 
xmin * 256) + screen_min_x * 256
  = (x - xmin * 256) * (screen_max_x - screen_min_x) * 256/((xmax - xmin) * 
256) + screen_min_x  * 256
  = (x - xmin * 256) * (screen_max_x - screen_min_x)/(xmax - xmin) + 
screen_min_x * 256

and because we have an offset of 0, and thus screen_max_x == width, we end
up with

  = (x - xmin * 256) * width/(xmax - xmin)

so yes, you only need to convert xmin to li_fixed_t, but that only
applies because we expect a 0 screen offset.

and that concludes today's math tutorial.
(which I mainly did because I wasn't 100% sure on this either ;)

It'd probably be worth noting this somewhere, or at least writing down the
base formula so that if there are ever patches that change this at least the
base formula is clear. We've messed up missing out on (+ screen_min_x) a few
times in the X stack over the years.

Also, there is one problem with the formula. the screen dimensions are
exclusive [0,width[, the device coordinates are inclusive [min, max]. so the
correct scaling should be (xmax - xmin + 1).
   
  also, should we add a non-zero min for width and height to scale to a screen
  not the top/left-most? The compositor can just add it afterwards, but 
  it would have to convert to fixed_t as well:
  
  x = libinput_event_touch_get_x_transformed(event, screen_width);
  x += li_fixed_from_int(screen_offset);
  
  which is more error prone than something like:
  
  x = libinput_event_touch_get_x_transformed(event, screen_offset_x, 
  screen_width);
 
 
 That transform wouldn't be enough. We'd have to rotate etc as well. See
 http://cgit.freedesktop.org/wayland/weston/tree/src/compositor.c#n3408 .
 Given that, I think its easiest to let libinput do the device specific
 transform (device coords - output coords) and then have the user
 translate, and do other transformations.

fair enough. There is an argument to be made for libinput to do these
things, or provide helper functions to avoid callers writing potentially
buggy code. but not this time :)

  also, is it likely that the caller always has the screen dimensions handy
  when it comes to processing events? or would an config-style approach work
  better

Re: libinput mouse mode for tablets

2014-01-30 Thread Peter Hutterer
On Thu, Jan 30, 2014 at 02:14:30PM -0800, Bill Spitzak wrote:
 It is not clear from this discussion what support there will be for
 mouse mode for the tablets.
 
 A problem I have had with the current tablet api is that it is
 designed for mapping the tablet to the bounding box surrounding all
 the outputs. mouse mode simply means that the movement is relative
 and does not change this scaling.
 
 What is wanted in mouse mode is a fixed translation of a 1 square
 on the tablet to a square in output space. Other operating systems
 do this when you switch to mouse mode. I have to run a rather
 annoying Python program every time the screen layout is changed to
 calculate the very non-intuitive rectangle I have to send to the
 mouse driver.
 
 Also I only want mouse mode when I have two outputs. If I have one
 the tablet can be used in direct mode. This may also be true if a
 program could grab the tablet and direct it to it's window that
 turning off mouse mode would be useful. I also have a smaller tablet
 that I would like to be in mouse mode all the time.
 
 I think a much more intelligent version can be done, which
 automatically goes into mouse mode. Basically the user chooses how
 big a 1-inch square on the tablet turns into in output space, and a
 limit to how distorted this output square can be (perhaps from 1.5:1
 to 1:1.5). On every change of the tablet or outputs wayland/libinput
 then figures out a mapping that is not too far from this scale and
 within the distortion dimensions for non-mouse-mode, if that is
 impossible it goes to mouse mode.

this has so many more cases where it won't work correctly from the user's
POV that it's likely easier to just have an easily accessible way of
switching between absolute and relative mode.

other than that, there will be support for relative mouse mode on tablet
hardware. Your general use-case is not unique, though I don't think I've
heard of the the case of mapping a tablet area to the exact screen area
before. Mapping it so that a square is a square, yes, but the requirement
for exact size matches is new to me.

Cheers,
   Peter

 I don't know if this would be libinput or the compositor but the
 ability to do this would be a nice addition to Wayland.
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 4/4] path: add error handling for failing to create a seat

2014-02-03 Thread Peter Hutterer
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/path.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/src/path.c b/src/path.c
index 7a00c0b..a2878f9 100644
--- a/src/path.c
+++ b/src/path.c
@@ -144,6 +144,11 @@ path_input_enable(struct libinput *libinput)
 
seat = path_seat_create(input, seat_name, seat_logical_name);
 
+   if (!seat) {
+   log_info(failed to create seat for device '%s'.\n, devnode);
+   goto out;
+   }
+
device = evdev_device_create(seat-base, devnode, sysname, fd);
libinput_seat_unref(seat-base);
 
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 2/4] Move closing the device fd into evdev.c

2014-02-03 Thread Peter Hutterer
evdev_device_remove() already calls close(device-fd). Move the
close_restricted call there to avoid one privileged call in the backend and
one in the device.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev.c | 2 +-
 src/path.c  | 1 -
 src/udev-seat.c | 3 ---
 3 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index 46bd35a..c1d33a9 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -720,7 +720,7 @@ evdev_device_remove(struct evdev_device *device)
 
if (device-mtdev)
mtdev_close_delete(device-mtdev);
-   close(device-fd);
+   close_restricted(device-base.seat-libinput, device-fd);
list_remove(device-base.link);
 
notify_removed_device(device-base);
diff --git a/src/path.c b/src/path.c
index 2893ad4..29d722b 100644
--- a/src/path.c
+++ b/src/path.c
@@ -42,7 +42,6 @@ path_input_disable(struct libinput *libinput)
struct evdev_device *device = input-device;
 
if (device) {
-   close_restricted(libinput, device-fd);
evdev_device_remove(device);
input-device = NULL;
}
diff --git a/src/udev-seat.c b/src/udev-seat.c
index 5936511..86b17d7 100644
--- a/src/udev-seat.c
+++ b/src/udev-seat.c
@@ -169,7 +169,6 @@ static void
 evdev_udev_handler(void *data)
 {
struct udev_input *input = data;
-   struct libinput *libinput = input-base;
struct udev_device *udev_device;
struct evdev_device *device, *next;
const char *action;
@@ -198,7 +197,6 @@ evdev_udev_handler(void *data)
if (!strcmp(device-devnode, devnode)) {
log_info(input device %s, %s 
removed\n,
 device-devname, 
device-devnode);
-   close_restricted(libinput, device-fd);
evdev_device_remove(device);
break;
}
@@ -219,7 +217,6 @@ udev_input_remove_devices(struct udev_input *input)
libinput_seat_ref(seat-base);
list_for_each_safe(device, next,
   seat-base.devices_list, base.link) {
-   close_restricted(input-base, device-fd);
evdev_device_remove(device);
if (list_empty(seat-base.devices_list)) {
/* if the seat may be referenced by the
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH v2 libinput 2/4] Move opening and closing the device fd into evdev.c

2014-02-05 Thread Peter Hutterer
evdev_device_remove() already calls close(device-fd). Move the
close_restricted call there to avoid one privileged call in the backend and
one in the device. And move the open_restricted() into the evdev device too to
reduce the duplicated code in the two backends.

Update to one of the tests: since we'd now fail getting the device node from
the invalid /tmp path, the open_func_count is 0.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
Changes to v1:
- move open_restricted into evdev_device_create()

If we really get an fd open failure, we now get two error messages, but I'll
fix that up in a follow-up restructure.

 src/evdev.c | 18 +++---
 src/evdev.h |  3 +--
 src/path.c  | 14 +-
 src/udev-seat.c | 20 +---
 test/path.c |  2 +-
 5 files changed, 19 insertions(+), 38 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index 2bc301b..61ab083 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -600,12 +600,22 @@ evdev_configure_device(struct evdev_device *device)
 struct evdev_device *
 evdev_device_create(struct libinput_seat *seat,
const char *devnode,
-   const char *sysname,
-   int fd)
+   const char *sysname)
 {
struct libinput *libinput = seat-libinput;
struct evdev_device *device;
char devname[256] = unknown;
+   int fd;
+
+   /* Use non-blocking mode so that we can loop on read on
+* evdev_device_data() until all events on the fd are
+* read.  mtdev_get() also expects this. */
+   fd = open_restricted(libinput, devnode, O_RDWR | O_NONBLOCK);
+   if (fd  0) {
+   log_info(opening input device '%s' failed (%s).\n,
+devnode, strerror(-fd));
+   return NULL;
+   }
 
device = zalloc(sizeof *device);
if (device == NULL)
@@ -655,6 +665,8 @@ evdev_device_create(struct libinput_seat *seat,
return device;
 
 err:
+   if (fd = 0)
+   close_restricted(libinput, fd);
evdev_device_destroy(device);
return NULL;
 }
@@ -710,7 +722,7 @@ evdev_device_remove(struct evdev_device *device)
 
if (device-mtdev)
mtdev_close_delete(device-mtdev);
-   close(device-fd);
+   close_restricted(device-base.seat-libinput, device-fd);
list_remove(device-base.link);
 
notify_removed_device(device-base);
diff --git a/src/evdev.h b/src/evdev.h
index 37c32e5..3c9f93a 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -118,8 +118,7 @@ struct evdev_dispatch {
 struct evdev_device *
 evdev_device_create(struct libinput_seat *seat,
const char *devnode,
-   const char *sysname,
-   int fd);
+   const char *sysname);
 
 struct evdev_dispatch *
 evdev_touchpad_create(struct evdev_device *device);
diff --git a/src/path.c b/src/path.c
index 2893ad4..2254bbe 100644
--- a/src/path.c
+++ b/src/path.c
@@ -42,7 +42,6 @@ path_input_disable(struct libinput *libinput)
struct evdev_device *device = input-device;
 
if (device) {
-   close_restricted(libinput, device-fd);
evdev_device_remove(device);
input-device = NULL;
}
@@ -122,22 +121,13 @@ path_input_enable(struct libinput *libinput)
struct evdev_device *device;
const char *devnode = input-path;
char *sysname;
-   int fd;
char *seat_name, *seat_logical_name;
 
if (input-device)
return 0;
 
-   fd = open_restricted(libinput, devnode, O_RDWR|O_NONBLOCK);
-   if (fd  0) {
-   log_info(opening input device '%s' failed (%s).\n,
-devnode, strerror(-fd));
-   return -1;
-   }
-
if (path_get_udev_properties(devnode, sysname,
 seat_name, seat_logical_name) == -1) {
-   close_restricted(libinput, fd);
log_info(failed to obtain sysname for device '%s'.\n, 
devnode);
return -1;
}
@@ -146,16 +136,14 @@ path_input_enable(struct libinput *libinput)
free(seat_name);
free(seat_logical_name);
 
-   device = evdev_device_create(seat-base, devnode, sysname, fd);
+   device = evdev_device_create(seat-base, devnode, sysname);
free(sysname);
libinput_seat_unref(seat-base);
 
if (device == EVDEV_UNHANDLED_DEVICE) {
-   close_restricted(libinput, fd);
log_info(not using input device '%s'.\n, devnode);
return -1;
} else if (device == NULL) {
-   close_restricted(libinput, fd);
log_info(failed to create input device '%s'.\n, devnode);
return -1;
}
diff --git a/src/udev-seat.c b/src/udev-seat.c
index 5936511..957e762 100644
--- a/src/udev-seat.c
+++ b/src/udev-seat.c
@@ -44,13 +44,11

[PATCH libinput 3/6] path: add libinput_path_add_device() and libinput_path_remove_device()

2014-02-05 Thread Peter Hutterer
This allows multiple devices to share a single libinput context. The new
function returns the newly added device immediately. Unlike the udev seat
where devices may or may not be added - over the lifetime of the seat - a
path-based backend knows immediately if device exists or doesn't exist.

Returning the device is required by callers that have the event processing
separate from adding devices - by the time we have the DEVICE_ADDED event in
the queue we may have other events to process first. And the DEVICE_ADDED
event won't easily link to the path we gave it anyway, so it's hard to figure
out which DEVICE_ADDED event corresponds to the new device.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/libinput.h |  45 +++
 src/path.c | 104 ++--
 test/path.c| 114 +
 3 files changed, 252 insertions(+), 11 deletions(-)

diff --git a/src/libinput.h b/src/libinput.h
index e2d83bf..e1d1ffb 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -729,6 +729,51 @@ libinput_create_from_path(const struct libinput_interface 
*interface,
 /**
  * @ingroup base
  *
+ * Add a device to a libinput context initialized with
+ * libinput_path_create_from_device(). If successful, the device will be
+ * added to the internal list and re-opened on libinput_resume(). The device
+ * can be removed with libinput_path_remove_device().
+ *
+ * If the device was successfully initialized, it is returned in the device
+ * argument. The lifetime of the returned device pointer is limited until
+ * the next linput_dispatch(), use libinput_device_ref() to keep a permanent
+ * reference.
+ *
+ * @param libinput A previously initialized libinput context
+ * @param path Path to an input device
+ * @return The newly initiated device on success, or NULL on failure.
+ *
+ * @note It is an application bug to call this function on a libinput
+ * context initialize with libinput_udev_create_for_seat().
+ */
+struct libinput_device *
+libinput_path_add_device(struct libinput *libinput,
+const char *path);
+
+/**
+ * @ingroup base
+ *
+ * Remove a device from a libinput context initialized with
+ * libinput_path_create_from_device() or added to such a context with
+ * libinput_path_add_device().
+ *
+ * Events already processed from this input device are kept in the queue,
+ * the LIBINPUT_EVENT_DEVICE_REMOVED event marks the end of events for this
+ * device.
+ *
+ * If no matching device exists, this function does nothing.
+ *
+ * @param device A libinput device
+ *
+ * @note It is an application bug to call this function on a libinput
+ * context initialize with libinput_udev_create_for_seat().
+ */
+void
+libinput_path_remove_device(struct libinput_device *device);
+
+/**
+ * @ingroup base
+ *
  * libinput keeps a single file descriptor for all events. Call into
  * libinput_dispatch() if any events become available on this fd.
  *
diff --git a/src/path.c b/src/path.c
index 32483df..a5b3338 100644
--- a/src/path.c
+++ b/src/path.c
@@ -22,6 +22,7 @@
 
 #include config.h
 
+#include errno.h
 #include fcntl.h
 #include string.h
 #include libudev.h
@@ -36,6 +37,31 @@ int path_input_process_event(struct libinput_event);
 static void path_seat_destroy(struct libinput_seat *seat);
 
 static void
+path_disable_device(struct libinput *libinput,
+   struct evdev_device *device)
+{
+   struct libinput_seat *seat = device-base.seat;
+   struct evdev_device *dev, *next;
+
+   list_for_each_safe(dev, next,
+  seat-devices_list, base.link) {
+   if (dev != device)
+   continue;
+
+   evdev_device_remove(device);
+   if (list_empty(seat-devices_list)) {
+   /* if the seat may be referenced by the
+  client, so make sure it's dropped from
+  the seat list now, to be freed whenever
+* the device is removed */
+   list_remove(seat-link);
+   list_init(seat-link);
+   }
+   break;
+   }
+}
+
+static void
 path_input_disable(struct libinput *libinput)
 {
struct path_input *input = (struct path_input*)libinput;
@@ -45,17 +71,8 @@ path_input_disable(struct libinput *libinput)
list_for_each_safe(seat, tmp, input-base.seat_list, base.link) {
libinput_seat_ref(seat-base);
list_for_each_safe(device, next,
-  seat-base.devices_list, base.link) {
-   evdev_device_remove(device);
-   if (list_empty(seat-base.devices_list)) {
-   /* if the seat may be referenced by the
-  client, so make sure it's dropped from
-  the seat list now, to be freed

[PATCH libinput 6/6] test: Add tests for adding/removing devices

2014-02-05 Thread Peter Hutterer
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 test/path.c | 317 
 1 file changed, 317 insertions(+)

diff --git a/test/path.c b/test/path.c
index 3aade76..59d3e5f 100644
--- a/test/path.c
+++ b/test/path.c
@@ -252,6 +252,25 @@ START_TEST(path_add_device)
 }
 END_TEST
 
+START_TEST(path_add_invalid_path)
+{
+   struct litest_device *dev = litest_current_device();
+   struct libinput *li = dev-libinput;
+   struct libinput_event *event;
+   struct libinput_device *device;
+
+   litest_drain_events(li);
+
+   device = libinput_path_add_device(li, /tmp/);
+   ck_assert(device == NULL);
+
+   libinput_dispatch(li);
+
+   while ((event = libinput_get_event(li)))
+   ck_abort();
+}
+END_TEST
+
 START_TEST(path_device_sysname)
 {
struct litest_device *dev = litest_current_device();
@@ -465,6 +484,300 @@ START_TEST(path_double_resume)
 }
 END_TEST
 
+START_TEST(path_add_device_suspend_resume)
+{
+   struct libinput *li;
+   struct libinput_device *device;
+   struct libinput_event *event;
+   struct libevdev *evdev;
+   struct libevdev_uinput *uinput1, *uinput2;
+   int rc;
+   int nevents;
+   void *userdata = rc;
+
+   evdev = libevdev_new();
+   ck_assert(evdev != NULL);
+
+   libevdev_set_name(evdev, test device);
+   libevdev_enable_event_code(evdev, EV_KEY, BTN_LEFT, NULL);
+   libevdev_enable_event_code(evdev, EV_KEY, BTN_RIGHT, NULL);
+   libevdev_enable_event_code(evdev, EV_REL, REL_X, NULL);
+   libevdev_enable_event_code(evdev, EV_REL, REL_Y, NULL);
+
+   rc = libevdev_uinput_create_from_device(evdev,
+   LIBEVDEV_UINPUT_OPEN_MANAGED,
+   uinput1);
+   ck_assert_int_eq(rc, 0);
+
+   libevdev_set_name(evdev, test device 2);
+   rc = libevdev_uinput_create_from_device(evdev,
+   LIBEVDEV_UINPUT_OPEN_MANAGED,
+   uinput2);
+   ck_assert_int_eq(rc, 0);
+
+   libevdev_free(evdev);
+
+   li = libinput_path_create_context(simple_interface, userdata);
+   ck_assert(li != NULL);
+
+   device = libinput_path_add_device(li,
+ libevdev_uinput_get_devnode(uinput1));
+   ck_assert(device != NULL);
+   device = libinput_path_add_device(li,
+ libevdev_uinput_get_devnode(uinput2));
+
+   libinput_dispatch(li);
+
+   nevents = 0;
+   while ((event = libinput_get_event(li))) {
+   enum libinput_event_type type;
+   type = libinput_event_get_type(event);
+   ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_ADDED);
+   libinput_event_destroy(event);
+   nevents++;
+   }
+
+   ck_assert_int_eq(nevents, 2);
+
+
+   libinput_suspend(li);
+   libinput_dispatch(li);
+
+   nevents = 0;
+   while ((event = libinput_get_event(li))) {
+   enum libinput_event_type type;
+   type = libinput_event_get_type(event);
+   ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_REMOVED);
+   libinput_event_destroy(event);
+   nevents++;
+   }
+
+   ck_assert_int_eq(nevents, 2);
+
+   libinput_resume(li);
+   libinput_dispatch(li);
+
+   nevents = 0;
+   while ((event = libinput_get_event(li))) {
+   enum libinput_event_type type;
+   type = libinput_event_get_type(event);
+   ck_assert_int_eq(type, LIBINPUT_EVENT_DEVICE_ADDED);
+   libinput_event_destroy(event);
+   nevents++;
+   }
+
+   ck_assert_int_eq(nevents, 2);
+
+   libevdev_uinput_destroy(uinput1);
+   libevdev_uinput_destroy(uinput2);
+   libinput_destroy(li);
+
+   open_func_count = 0;
+   close_func_count = 0;
+}
+END_TEST
+
+START_TEST(path_add_device_suspend_resume_fail)
+{
+   struct libinput *li;
+   struct libinput_device *device;
+   struct libinput_event *event;
+   struct libevdev *evdev;
+   struct libevdev_uinput *uinput1, *uinput2;
+   int rc;
+   int nevents;
+   void *userdata = rc;
+
+   evdev = libevdev_new();
+   ck_assert(evdev != NULL);
+
+   libevdev_set_name(evdev, test device);
+   libevdev_enable_event_code(evdev, EV_KEY, BTN_LEFT, NULL);
+   libevdev_enable_event_code(evdev, EV_KEY, BTN_RIGHT, NULL);
+   libevdev_enable_event_code(evdev, EV_REL, REL_X, NULL);
+   libevdev_enable_event_code(evdev, EV_REL, REL_Y, NULL);
+
+   rc = libevdev_uinput_create_from_device(evdev,
+   LIBEVDEV_UINPUT_OPEN_MANAGED,
+   uinput1);
+   ck_assert_int_eq(rc, 0);
+
+   libevdev_set_name

[PATCH libinput 0/6] Add dynamic devices to the path backend

2014-02-05 Thread Peter Hutterer

This patchset revamps the path backend to allow for more than one path-based
device per context. I thought the initial approach of having one context per
device is sufficient but there are a few use-cases that can really only be
solved by having libinput control all devices. A common example is disabling
the touchpad while typing, or making the trackstick buttons on the Lenovo
T440s useful.

So for my little libinput-based xorg driver [1] I need to have a shared
context between the various devices added. The change looks bigger than it
is, it largely just replicates what the udev-seat backend already does
anyway.

Most notable there are a few API changes:
- libinput_create_from_path() has been removed, a caller should now use
  libinput_path_create_context(), then libinput_path_add_device()
  I found this to be nicer in the caller code than having
  libinput_path_create_from_device() and then adding devices.
- more devices can be added or removed with libinput_path_add_device and
  libinput_path_remove_device
- to ensure proper namespacing, libinput_create_from_udev is now
  libinput_udev_create_for_seat()

So far this looks flexible enough for the xorg drivers which have different
use-cases than in weston, specifically each device can be disabled and
enabled individually. I just call remove/add device when that happens.

What's not so nice is a shortcut in libinput_path_add_device(). Instead of
just succeeding and letting the caller handle the DEVICE_ADDED event, it
returns the struct libinput_device directly. At least within the xorg driver
context I found it too hard to work with the events (long description on
request) but the short summary is that I'd need to cache any events before
DEVICE_ADDED and use timers to re-trigger the read once I have the device,
aside from the problem of not being able to figure out which device is which
based on the events only (we don't expose the devnode to the caller).

On the positive side, the xorg driver seems to be working quite nicely
already, though it is rather featureless.

Cheers,
  Peter
 
[1] https://github.com/whot/xf86-input-libinput

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 1/6] Store the backend type in the interface

2014-02-05 Thread Peter Hutterer
This enables us to prevent callers from calling backend-specific functions on
mismatching backends.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/libinput-private.h | 6 ++
 src/path.c | 1 +
 src/udev-seat.c| 1 +
 3 files changed, 8 insertions(+)

diff --git a/src/libinput-private.h b/src/libinput-private.h
index 0d7de90..ee5a17d 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -26,7 +26,13 @@
 #include libinput.h
 #include libinput-util.h
 
+enum libinput_backend_type {
+   BACKEND_UDEV,
+   BACKEND_PATH,
+};
+
 struct libinput_interface_backend {
+   enum libinput_backend_type backend_type;
int (*resume)(struct libinput *libinput);
void (*suspend)(struct libinput *libinput);
void (*destroy)(struct libinput *libinput);
diff --git a/src/path.c b/src/path.c
index de2ca49..4924b31 100644
--- a/src/path.c
+++ b/src/path.c
@@ -167,6 +167,7 @@ path_input_destroy(struct libinput *input)
 }
 
 static const struct libinput_interface_backend interface_backend = {
+   .backend_type = BACKEND_PATH,
.resume = path_input_enable,
.suspend = path_input_disable,
.destroy = path_input_destroy,
diff --git a/src/udev-seat.c b/src/udev-seat.c
index 957e762..b564c83 100644
--- a/src/udev-seat.c
+++ b/src/udev-seat.c
@@ -330,6 +330,7 @@ udev_seat_get_named(struct udev_input *input, const char 
*seat_name)
 }
 
 static const struct libinput_interface_backend interface_backend = {
+   .backend_type = BACKEND_UDEV,
.resume = udev_input_enable,
.suspend = udev_input_disable,
.destroy = udev_input_destroy,
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 2/6] path: modify backend to allow for more than one device

2014-02-05 Thread Peter Hutterer
The previous path backend created a libinput context attached to a single
device. This is insufficient when we need to use cross-device functionality.
One example of this cross-device functionality include disabling a touchpad
while the trackstick is in use (Lenovo T440 and related models).

This patch merely adds the infrastructure to support multiple devices for a
path backend. Follow-up patches add the function calls to add and remove
devices. This is needed by Xorg input drivers that still make use of the
server's device hotplug mechanisms but want to otherwise use libinput.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/path.c | 120 +++--
 src/path.h |   6 +++-
 2 files changed, 99 insertions(+), 27 deletions(-)

diff --git a/src/path.c b/src/path.c
index 4924b31..32483df 100644
--- a/src/path.c
+++ b/src/path.c
@@ -39,11 +39,24 @@ static void
 path_input_disable(struct libinput *libinput)
 {
struct path_input *input = (struct path_input*)libinput;
-   struct evdev_device *device = input-device;
+   struct path_seat *seat, *tmp;
+   struct evdev_device *device, *next;
 
-   if (device) {
-   evdev_device_remove(device);
-   input-device = NULL;
+   list_for_each_safe(seat, tmp, input-base.seat_list, base.link) {
+   libinput_seat_ref(seat-base);
+   list_for_each_safe(device, next,
+  seat-base.devices_list, base.link) {
+   evdev_device_remove(device);
+   if (list_empty(seat-base.devices_list)) {
+   /* if the seat may be referenced by the
+  client, so make sure it's dropped from
+  the seat list now, to be freed whenever
+* the device is removed */
+   list_remove(seat-base.link);
+   list_init(seat-base.link);
+   }
+   }
+   libinput_seat_unref(seat-base);
}
 }
 
@@ -72,6 +85,22 @@ path_seat_create(struct path_input *input,
return seat;
 }
 
+static struct path_seat*
+path_seat_get_named(struct path_input *input,
+   const char *seat_name_physical,
+   const char *seat_name_logical)
+{
+   struct path_seat *seat;
+
+   list_for_each(seat, input-base.seat_list, base.link) {
+   if (strcmp(seat-base.physical_name, seat_name_physical) == 0 
+   strcmp(seat-base.logical_name, seat_name_logical) == 0)
+   return seat;
+   }
+
+   return NULL;
+}
+
 static int
 path_get_udev_properties(const char *path,
 char **sysname,
@@ -113,48 +142,64 @@ out:
return rc;
 }
 
-static int
-path_input_enable(struct libinput *libinput)
+static struct libinput_device *
+path_device_enable(struct path_input *input, const char *devnode)
 {
-   struct path_input *input = (struct path_input*)libinput;
struct path_seat *seat;
-   struct evdev_device *device;
-   const char *devnode = input-path;
+   struct evdev_device *device = NULL;
char *sysname;
char *seat_name, *seat_logical_name;
 
-   if (input-device)
-   return 0;
-
if (path_get_udev_properties(devnode, sysname,
 seat_name, seat_logical_name) == -1) {
log_info(failed to obtain sysname for device '%s'.\n, 
devnode);
-   return -1;
+   return NULL;
}
 
-   seat = path_seat_create(input, seat_name, seat_logical_name);
-   free(seat_name);
-   free(seat_logical_name);
+   seat = path_seat_get_named(input, seat_name, seat_logical_name);
 
-   if (!seat) {
-   log_info(failed to create seat for device '%s'.\n, devnode);
-   free(sysname);
-   return -1;
+   if (seat) {
+   libinput_seat_ref(seat-base);
+   } else {
+   seat = path_seat_create(input, seat_name, seat_logical_name);
+   if (!seat) {
+   log_info(failed to create seat for device '%s'.\n, 
devnode);
+   goto out;
+   }
}
 
device = evdev_device_create(seat-base, devnode, sysname);
-   free(sysname);
libinput_seat_unref(seat-base);
 
if (device == EVDEV_UNHANDLED_DEVICE) {
+   device = NULL;
log_info(not using input device '%s'.\n, devnode);
-   return -1;
+   goto out;
} else if (device == NULL) {
log_info(failed to create input device '%s'.\n, devnode);
-   return -1;
+   goto out;
}
 
-   input-device = device;
+out:
+   free(sysname);
+   free(seat_name);
+   free

Re: [PATCH libinput 1/6] Store the backend type in the interface

2014-02-06 Thread Peter Hutterer
On Thu, Feb 06, 2014 at 10:11:34PM +0100, Jonas Ådahl wrote:
 On Thu, Feb 06, 2014 at 02:13:05PM +1000, Peter Hutterer wrote:
  This enables us to prevent callers from calling backend-specific functions 
  on
  mismatching backends.
 
 This can be done instead by comparing the backend interface pointer in
 struct libinput to the one defined in either path.c or udev-seat.c.
 
 if (libinput-interface_backend != interface_backend) {
   log(...);
   return NULL;
 }
 
 I think doing it like that is preferred, since we should avoid
 per-backend logic in the front end anyway.

ok, no problem. amended locally, and that drops this patch completely and
replaces it with the above condition in 3/6.

Cheers,
   Peter

  Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
  ---
   src/libinput-private.h | 6 ++
   src/path.c | 1 +
   src/udev-seat.c| 1 +
   3 files changed, 8 insertions(+)
  
  diff --git a/src/libinput-private.h b/src/libinput-private.h
  index 0d7de90..ee5a17d 100644
  --- a/src/libinput-private.h
  +++ b/src/libinput-private.h
  @@ -26,7 +26,13 @@
   #include libinput.h
   #include libinput-util.h
   
  +enum libinput_backend_type {
  +   BACKEND_UDEV,
  +   BACKEND_PATH,
  +};
  +
   struct libinput_interface_backend {
  +   enum libinput_backend_type backend_type;
  int (*resume)(struct libinput *libinput);
  void (*suspend)(struct libinput *libinput);
  void (*destroy)(struct libinput *libinput);
  diff --git a/src/path.c b/src/path.c
  index de2ca49..4924b31 100644
  --- a/src/path.c
  +++ b/src/path.c
  @@ -167,6 +167,7 @@ path_input_destroy(struct libinput *input)
   }
   
   static const struct libinput_interface_backend interface_backend = {
  +   .backend_type = BACKEND_PATH,
  .resume = path_input_enable,
  .suspend = path_input_disable,
  .destroy = path_input_destroy,
  diff --git a/src/udev-seat.c b/src/udev-seat.c
  index 957e762..b564c83 100644
  --- a/src/udev-seat.c
  +++ b/src/udev-seat.c
  @@ -330,6 +330,7 @@ udev_seat_get_named(struct udev_input *input, const 
  char *seat_name)
   }
   
   static const struct libinput_interface_backend interface_backend = {
  +   .backend_type = BACKEND_UDEV,
  .resume = udev_input_enable,
  .suspend = udev_input_disable,
  .destroy = udev_input_destroy,
  -- 
  1.8.4.2
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 0/6] Add dynamic devices to the path backend

2014-02-06 Thread Peter Hutterer
On Thu, Feb 06, 2014 at 10:23:57PM +0100, Jonas Ådahl wrote:
 On Thu, Feb 06, 2014 at 02:13:04PM +1000, Peter Hutterer wrote:
  
  This patchset revamps the path backend to allow for more than one path-based
  device per context. I thought the initial approach of having one context per
  device is sufficient but there are a few use-cases that can really only be
  solved by having libinput control all devices. A common example is disabling
  the touchpad while typing, or making the trackstick buttons on the Lenovo
  T440s useful.
  
  So for my little libinput-based xorg driver [1] I need to have a shared
  context between the various devices added. The change looks bigger than it
  is, it largely just replicates what the udev-seat backend already does
  anyway.
  
  Most notable there are a few API changes:
  - libinput_create_from_path() has been removed, a caller should now use
libinput_path_create_context(), then libinput_path_add_device()
 
 Why not just libinput_path_create()?

I wanted to make it explicit that all this call does is create the context,
as opposed to e.g. udev_create_... which adds devices too.

I found this to be nicer in the caller code than having
libinput_path_create_from_device() and then adding devices.
  - more devices can be added or removed with libinput_path_add_device and
libinput_path_remove_device
  - to ensure proper namespacing, libinput_create_from_udev is now
libinput_udev_create_for_seat()
 
 These API changes looks good to me, but should maybe suspend and resume
 behaviour be documented? Is it required to re-add devices after having
 resumed?

it's not required, the behaviour is that suspend/resume removes and re-adds
all devices, or fails if a device cannot be added. exactly the same behavour
as the udev seat. I'll expand on the suspend/resume documentation in a
separate patch.

  So far this looks flexible enough for the xorg drivers which have different
  use-cases than in weston, specifically each device can be disabled and
  enabled individually. I just call remove/add device when that happens.
  
  What's not so nice is a shortcut in libinput_path_add_device(). Instead of
  just succeeding and letting the caller handle the DEVICE_ADDED event, it
  returns the struct libinput_device directly. At least within the xorg driver
  context I found it too hard to work with the events (long description on
  request) but the short summary is that I'd need to cache any events before
  DEVICE_ADDED and use timers to re-trigger the read once I have the device,
  aside from the problem of not being able to figure out which device is which
  based on the events only (we don't expose the devnode to the caller).
 
 So I guess you can't just add and then flush and process the queue right
 there, as the DEVICE_ADDED event will already have been queued when
 calling libinput_path_add_device()?

Not without doing some work to the server, the enable/disable bits are in a
quirky order and called from different places than the actual event
processing. So without auditing the call paths I can't guarantee that the
server is in the correct state for handling events when you get the first
couple of events. Returning the device pointer was the less-intrusive but
still somewhat-sensible approach :)

 We could also simply expose the devnode to the caller as well,
 caching and matching later is not very nice.

IMO we should do this anyway, otherwise we'd require the caller to use udev
and subsystem guessing* to match it up themselves. At least a devnode is
non-ambiguous.

Cheers,
   Peter

* probably not much of an issue since we don't deal with serial devices, so
we can assume subsystem is always input
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [RFC] libinput configuration interface

2014-02-08 Thread Peter Hutterer
On Thu, Feb 06, 2014 at 11:28:49PM +0100, Eugen Friedrich wrote:
 Hi together,
 i would like to put some input from the embedded/ automotive perspective.
 
 you can think about huge amount of different configurations for different
 device types.
 A lot of configuration in the initial post deals with behavior of buttons
 and scrolling
 areas of the touch panels.
 
 The good approach could be a kind of general configuration of button and
 scrolling areas of the touch panels
 the button area could contain a position and dimension of the button in the
 device coordinate system and the button code
 the slider area could contain a position and dimension of the slider along
 with the range.

generally for real touch screens (i.e. not touchpads) I think any
interpretation of the values should be on the client side, not in the input
library. There just isn't enough context to interpret it otherwise since
you're at least partially reliant on UI hints or other elements to make sure
you're emulating the right thing.

For specialized cases like having a permanent input region that maps into
semantic buttons (e.g. the button bar on the Android phones) this should IMO
be handled by the compositor.

 Also the weston code contains calibration of the absolute values.
 It would be good also to have a calibration possibilities in libinput.

Yes, calibration is a required feature, I forgot to mention that since it's
already supported.

Cheers,
   Peter

 
 What do you think?
 
 
 2014-02-03 6:11 GMT+01:00 Alexander E. Patrakov patra...@gmail.com:
 
  2014-02-03 Peter Hutterer peter.hutte...@who-t.net:
   On Fri, Jan 31, 2014 at 08:26:54PM +0600, Alexander E. Patrakov wrote:
   Peter Hutterer wrote:
I've been thinking about how to add a device configuration interface
  to
libinput, and after getting feedback from Jonas and Benjamin, here's a
proposal (no code yet).
   
First, I think the configuration should be feature-specific, not
  device
specific, so it is independent of a classification or capabilities of
  a
device. To the user it doesn't matter if we classify something as
  touchpad
or as mouse, if middle mouse button emulation works that's the only
  thing
that counts. At least for configuration purposes, this also avoids the
difficult task of classifying a device correctly. Those pesky HW
manufacturers do have a habit of coming up with devices that elude
previously agreed-on classification schemes, e.g. mice with touchpads
  on
them.
   
Aside from setting an item, there should be calls to get the current
  value,
and a call to reset to the built-in defaults. And, since we're
feature-based, a call to check if the config item is possible for a
  device.
Which leads us the the following quartet for each item:
   
int libinput_device_config_set_foo(device, value);
int libinput_device_config_get_foo(device, value);
int libinput_device_config_reset_foo(device);
bool libinput_device_config_has_foo(device);
   
And the actual configuration items I've come up with so far:
* {set|get|reset|has}_tap_single_finger_button
* tap_double_finger_button
* tap_triple_finger_button
* click_finger_single
* click_finger_double
* click_finger_triple
* twofinger_scroll_vertical
* twofinger_scroll_horizonal
* edge_scroll_vertical
* edge_scroll_horizontal
* disable_while_typing
* disable_touch (while pen is in use)
  these two could be merged into disable while linked device is in
  use
* softbutton_left
* softbutton_middle
* softbutton_right
* emulate_middle_button
* button_mapping
* emulate_wheel
* rotation
* palm_detection
* mode (relative/absolute)
* valid_area
  This is needed on tablets that have a different ratio than the
  monitor.
  Mapping them to the monitor results in uneven x/y movements, so the
  easiest approach here is to cut a portion of the tablet off to
  match the
  ratio.
* stylus_button_behaviour(some enum)
  Some tablets don't report proximity, the only way to get a
  right-button
  click is to hold the right button down and then tip with the stylus.
   
Note that the above is not a 1:1 API mapping, e.g. tapping
  configuration
could be an API taking nfingers as argument as opposed to 3 different
  calls.
Likewise, they can take more than one value argument, e.g. middle
  button
emulation could take a boolean to enable it, and a timeout.
   
This list excludes options we currently have in the X drivers to
  adjust for
hw-specific quirks. Such as defining which pressure makes up a tap,
  etc. I
really hope this is something we can work out based on the device.
   
It also excludes configurations that I'd really like to hide away if
possible. For example, on the new T440-style touchpads the top part
  of it is
a set of buttons for the trackstick. There's nothing

Re: [RFC] libinput configuration interface

2014-02-09 Thread Peter Hutterer
On Sun, Feb 09, 2014 at 01:32:41PM +0100, Eugen Friedrich wrote:
 
 
 On 09.02.2014 05:10, Peter Hutterer wrote:
 On Thu, Feb 06, 2014 at 11:28:49PM +0100, Eugen Friedrich wrote:
 Hi together,
 i would like to put some input from the embedded/ automotive perspective.
 
 you can think about huge amount of different configurations for different
 device types.
 A lot of configuration in the initial post deals with behavior of buttons
 and scrolling
 areas of the touch panels.
 
 The good approach could be a kind of general configuration of button and
 scrolling areas of the touch panels
 the button area could contain a position and dimension of the button in the
 device coordinate system and the button code
 the slider area could contain a position and dimension of the slider along
 with the range.
 
 generally for real touch screens (i.e. not touchpads) I think any
 interpretation of the valthis should IMO
 be handled by the compositorues should be on the client side, not in
 the input
 library. There just isn't enough context to interpret it otherwise since
 you're at least partially reliant on UI hints or other elements to make sure
 you're emulating the right thing.
 Completely agree, active input elements which are drawn by some
 application should be handled by this application.
 
 For specialized cases like having a permanent input region that maps into
 semantic buttons (e.g. the button bar on the Android phones) this should IMO
 be handled by the compositor.
 Yes this was the aim of my proposal. This would give a flexibility
 to use different touch panel with different screens and put you
 permanent buttons and slider wherever you like. Such cases are maybe
 only important if you are building up a new devices but this
 configuration possibility would add a big value for the libinput.

my main worry here is that the semantics of such buttons are unknown to
anyone but the compositor. libinput has _no_ semantics other than here's
and area but especially with direct-touch devices you get more complex
interactions to this. For example, let's say we have a defined button area
at the bottom of the screen:
- should the button trigger if the finger moved from the outside into the
  area?
- should the button trigger if the finger left and re-entered the area?
- should the button trigger if the finger left the area?
-- oh, btw, now you need enter/leave events to notify the compositor
- should the button trigger if there is another finger within the area?
- should the button trigger if there was extensive movement between
  press/release in the button area?
..

All these usually have fairly obvious answers from a UI perspective, but a
low-level library without semantic context would have to provide some matrix
to enable all of them or restrict itself to a set of the above. The latter
wouldn't be a problem, but we'd have to really see some good use-cases to
justify the extra complexity.

Cheers,
   Peter
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH v2 libinput] Make it possible to have persistent libinput_seat instances

2014-02-09 Thread Peter Hutterer
From: Jonas Ådahl jad...@gmail.com

With this patch, a user can keep a reference to a libinput_seat
instance, which will cause the seat to never be unlinked from the
libinput context nor destroyed.

Previously, a when the last device of a seat was removed, the seat was
unlinked and if a new device was discovered with a previously empty seat
a new seat instance would always be created, meaning two potential seat
instances with identical physical and logical seat name pairs.

Signed-off-by: Jonas Ådahl jad...@gmail.com
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
Changes to v1:
- rebased on top of my path add/remove devices patch, the changes to path
  and udev backends are now identical
- use litest_drain_events() instead of manual loop in tests
- destroy the uinput device when done with it, closes a leak in the test 

 src/libinput.c  |  1 +
 src/libinput.h  |  5 +++
 src/path.c  |  9 --
 src/udev-seat.c |  9 --
 test/path.c | 96 +
 test/udev.c | 75 
 6 files changed, 177 insertions(+), 18 deletions(-)

diff --git a/src/libinput.c b/src/libinput.c
index cfce2c5..cc84fb5 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -508,6 +508,7 @@ libinput_seat_init(struct libinput_seat *seat,
seat-logical_name = strdup(logical_name);
seat-destroy = destroy;
list_init(seat-devices_list);
+   list_insert(libinput-seat_list, seat-link);
 }
 
 LIBINPUT_EXPORT void
diff --git a/src/libinput.h b/src/libinput.h
index e87b2b7..2fd9638 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -1069,6 +1069,11 @@ libinput_device_get_output_name(struct libinput_device 
*device);
  *
  * Get the seat associated with this input device.
  *
+ * A seat can be uniquely identified by the physical and logical seat name.
+ * There will ever be only one seat instance with a given physical and logical
+ * seat name pair at any given time, but if no external reference is kept, it
+ * may be destroyed if no device belonging to it is left.
+ *
  * @param device A previously obtained device
  * @return The seat this input device belongs to
  */
diff --git a/src/path.c b/src/path.c
index 31a916a..1b929e8 100644
--- a/src/path.c
+++ b/src/path.c
@@ -49,14 +49,6 @@ path_disable_device(struct libinput *libinput,
continue;
 
evdev_device_remove(device);
-   if (list_empty(seat-devices_list)) {
-   /* if the seat may be referenced by the
-  client, so make sure it's dropped from
-  the seat list now, to be freed whenever
-* the device is removed */
-   list_remove(seat-link);
-   list_init(seat-link);
-   }
break;
}
 }
@@ -97,7 +89,6 @@ path_seat_create(struct path_input *input,
 
libinput_seat_init(seat-base, input-base, seat_name,
   seat_logical_name, path_seat_destroy);
-   list_insert(input-base.seat_list, seat-base.link);
 
return seat;
 }
diff --git a/src/udev-seat.c b/src/udev-seat.c
index 9b807be..e622de2 100644
--- a/src/udev-seat.c
+++ b/src/udev-seat.c
@@ -203,14 +203,6 @@ udev_input_remove_devices(struct udev_input *input)
list_for_each_safe(device, next,
   seat-base.devices_list, base.link) {
evdev_device_remove(device);
-   if (list_empty(seat-base.devices_list)) {
-   /* if the seat may be referenced by the
-  client, so make sure it's dropped from
-  the seat list now, to be freed whenever
-* the device is removed */
-   list_remove(seat-base.link);
-   list_init(seat-base.link);
-   }
}
libinput_seat_unref(seat-base);
}
@@ -311,7 +303,6 @@ udev_seat_create(struct udev_input *input,
libinput_seat_init(seat-base, input-base,
   device_seat, seat_name,
   udev_seat_destroy);
-   list_insert(input-base.seat_list, seat-base.link);
 
return seat;
 }
diff --git a/test/path.c b/test/path.c
index 59d3e5f..41ee5c6 100644
--- a/test/path.c
+++ b/test/path.c
@@ -778,6 +778,100 @@ START_TEST(path_add_device_suspend_resume_remove_device)
 }
 END_TEST
 
+START_TEST(path_seat_recycle)
+{
+   struct libinput *li;
+   struct libevdev *evdev;
+   struct libevdev_uinput *uinput;
+   int rc;
+   void *userdata = rc;
+   struct libinput_event *ev;
+   struct libinput_device *device;
+   struct libinput_seat *saved_seat = NULL;
+   struct libinput_seat *seat;
+   int data = 0;
+   int found = 0

[PATCH libinput] evdev: restore EVDEV_UNHANDLED_DEVICE error code

2014-02-09 Thread Peter Hutterer
If we don't have capabilities we can deal with, return a different
error so the backends can handle it separately (they already do).

Signe-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/evdev.c b/src/evdev.c
index 9c6d116..d8dff65 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -606,6 +606,7 @@ evdev_device_create(struct libinput_seat *seat,
struct evdev_device *device;
char devname[256] = unknown;
int fd;
+   int unhandled_device = 0;
 
/* Use non-blocking mode so that we can loop on read on
 * evdev_device_data() until all events on the fd are
@@ -645,6 +646,7 @@ evdev_device_create(struct libinput_seat *seat,
goto err;
 
if (device-seat_caps == 0) {
+   unhandled_device = 1;
goto err;
}
 
@@ -668,7 +670,8 @@ err:
if (fd = 0)
close_restricted(libinput, fd);
evdev_device_destroy(device);
-   return NULL;
+
+   return unhandled_device ? EVDEV_UNHANDLED_DEVICE :  NULL;
 }
 
 int
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput] Make touch event slots seat wide

2014-02-10 Thread Peter Hutterer
On Mon, Feb 10, 2014 at 10:11:47AM +0100, Jonas Ådahl wrote:
 On Mon, Feb 10, 2014 at 03:13:55PM +1000, Peter Hutterer wrote:
  On Thu, Feb 06, 2014 at 10:27:54PM +0100, Jonas Ådahl wrote:
   Since a Wayland compositor have to represent all touch devices of a seat
   as one virtual device, lets make that easier by making the slots of
   touch events seat wide unique.
  
  is this really something we want to expose from libinput? it seems odd,
  given that everything else is per-device and even seats themselves are
  almost second-class citizens - i.e. you don't have to care about them at all
  if you don't need them.
  
  I don't think tying slot number to seats is a good idea here.
 
 I think it could be good to have libinput help out with virtual seat
 devices, such as ways to avoid double button and key presses,
 overlapping touch point slots, etc, as this is as well something that
 would otherwise need to be duplicated in almost every (seat aware)
 application.
 
 Regarding seat slots, it's more convenient to manage these in libinput
 since we already do keep track of per slot state, and with this patch,
 at least weston doesn't need to be aware of per-device slots at all.
 
 What do you think of providing this but not via the _get_slot()
 function?

I fully agree that we should abstract this. something like
libinput_event_pointer_get_seat_button()
libinput_event_touch_get_seat_slot()

would probably work and provide essentially the same API depending on the
use-case. the only other option I can come up with right now is having a
wl_pointer-like fake device in the list, but that seems about as insane as
XI2 :)

 As a side note, making slots seat wide does not make them any less
 device wide.

of course. what it does change though is that if we add a function to
retrieve the number of simultaneous touches (i.e. slots) per device, this
wouldn't map easily anymore and would in fact be rather unpredictable (since
it depends on the number of devices).

Cheers,
   Peter


   
   Signed-off-by: Jonas Ådahl jad...@gmail.com
   ---
src/evdev.c| 24 +---
src/evdev.h|  3 +++
src/libinput-private.h |  1 +
src/libinput.h |  4 ++--
4 files changed, 27 insertions(+), 5 deletions(-)
   
   diff --git a/src/evdev.c b/src/evdev.c
   index 2bc301b..80210fb 100644
   --- a/src/evdev.c
   +++ b/src/evdev.c
   @@ -109,7 +109,9 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
{
 int32_t cx, cy;
 int slot;
   + uint32_t seat_slot;
 struct libinput_device *base = device-base;
   + struct libinput_seat *seat = base-seat;

 slot = device-mt.slot;

   @@ -128,9 +130,13 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
 break;

   + seat_slot = ffs(~seat-slot_map) - 1;
   + device-mt.slots[slot].seat_slot = seat_slot;
   + seat-slot_map |= 1  seat_slot;
   +
 touch_notify_touch(base,
time,
   -slot,
   +seat_slot,
li_fixed_from_int(device-mt.slots[slot].x),
li_fixed_from_int(device-mt.slots[slot].y),
LIBINPUT_TOUCH_TYPE_DOWN);
   @@ -139,6 +145,8 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
 break;

   + seat_slot = device-mt.slots[slot].seat_slot;
   +
 touch_notify_touch(base,
time,
slot,
   @@ -150,9 +158,12 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
 break;

   + seat_slot = device-mt.slots[slot].seat_slot;
   + seat-slot_map = ~(1  seat_slot);
   +
 touch_notify_touch(base,
time,
   -slot,
   +seat_slot,
0, 0,
LIBINPUT_TOUCH_TYPE_UP);
 break;
   @@ -160,6 +171,10 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
 break;

   + seat_slot = ffs(~seat-slot_map) - 1;
   + device-abs.seat_slot = seat_slot;
   + seat-slot_map |= 1  seat_slot;
   +
 transform_absolute(device, cx, cy);
 touch_notify_touch(base,
time,
   @@ -173,7 +188,7 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (device-seat_caps  EVDEV_DEVICE_TOUCH

Re: [PATCH libinput 5/5] Add seat wide slot to touch events

2014-02-12 Thread Peter Hutterer
On Wed, Feb 12, 2014 at 09:36:42PM +0100, Jonas Ådahl wrote:
 Since a Wayland compositor have to represent all touch devices of a seat
 as one virtual device, lets make that easier by also providing seat wide
 slots with touch events.
 
 Seat wide slots may be accessed using
 libinput_event_touch_get_seat_slot().
 
 Signed-off-by: Jonas Ådahl jad...@gmail.com
 ---
  src/evdev.c| 24 
  src/evdev.h|  3 +++
  src/libinput-private.h |  2 ++
  src/libinput.c |  9 +
  src/libinput.h | 13 +
  5 files changed, 51 insertions(+)
 
 diff --git a/src/evdev.c b/src/evdev.c
 index 3fe28e4..7393df7 100644
 --- a/src/evdev.c
 +++ b/src/evdev.c
 @@ -109,7 +109,9 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
  {
   int32_t cx, cy;
   int slot;
 + uint32_t seat_slot;
   struct libinput_device *base = device-base;
 + struct libinput_seat *seat = base-seat;
  
   slot = device-mt.slot;
  
 @@ -128,9 +130,14 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + seat_slot = ffs(~seat-slot_map) - 1;

this needs some check for ffs() returning 0, it's not that hard to create
32 touchpoints.

 + device-mt.slots[slot].seat_slot = seat_slot;
 + seat-slot_map |= 1  seat_slot;
 +
   touch_notify_touch(base,
  time,
  slot,
 +seat_slot,
  li_fixed_from_int(device-mt.slots[slot].x),
  li_fixed_from_int(device-mt.slots[slot].y),
  LIBINPUT_TOUCH_TYPE_DOWN);
 @@ -139,9 +146,12 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + seat_slot = device-mt.slots[slot].seat_slot;
 +
   touch_notify_touch(base,
  time,
  slot,
 +seat_slot,
  li_fixed_from_int(device-mt.slots[slot].x),
  li_fixed_from_int(device-mt.slots[slot].y),
  LIBINPUT_TOUCH_TYPE_MOTION);
 @@ -150,9 +160,13 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + seat_slot = device-mt.slots[slot].seat_slot;
 + seat-slot_map = ~(1  seat_slot);
 +
   touch_notify_touch(base,
  time,
  slot,
 +seat_slot,
  0, 0,
  LIBINPUT_TOUCH_TYPE_UP);
   break;
 @@ -160,10 +174,15 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + seat_slot = ffs(~seat-slot_map) - 1;
 + device-abs.seat_slot = seat_slot;
 + seat-slot_map |= 1  seat_slot;

I think in light of 4/5 it should be documented that the seat_slot is never
-1, lest people expect the same behaviour for both functions.

Reviewed-by: Peter Hutterer peter.hutte...@who-t.net
for the series otherwise.

Cheers,
   Peter


 +
   transform_absolute(device, cx, cy);
   touch_notify_touch(base,
  time,
  -1,
 +seat_slot,
  li_fixed_from_int(cx),
  li_fixed_from_int(cy),
  LIBINPUT_TOUCH_TYPE_DOWN);
 @@ -174,6 +193,7 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   touch_notify_touch(base,
  time,
  -1,
 +device-abs.seat_slot,
  li_fixed_from_int(cx),
  li_fixed_from_int(cy),
  LIBINPUT_TOUCH_TYPE_DOWN);
 @@ -188,9 +208,13 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + seat_slot = device-abs.seat_slot;
 + seat-slot_map = ~(1  seat_slot);
 +
   touch_notify_touch(base,
  time,
  -1,
 +seat_slot

[PATCH libinput] Add a customizable log handler

2014-02-13 Thread Peter Hutterer
The previous log handler wasn't actually hooked up to anything. Add a public
API for the log handler with priority filtering, defaulting to priority
'error' and stderr as output stream.

And to keep the diff down and convenience up, provide a few simple wrappers
for logging. The generic is log_msg(), but let's use log_info, log_error, etc.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/libinput-private.h |   7 ++
 src/libinput-util.c|  20 --
 src/libinput.c |  62 ++
 src/libinput.h |  76 ++
 src/path.c |   4 +-
 test/Makefile.am   |   7 +-
 test/log.c | 169 +
 7 files changed, 322 insertions(+), 23 deletions(-)
 create mode 100644 test/log.c

diff --git a/src/libinput-private.h b/src/libinput-private.h
index 0d7de90..1fff7de 100644
--- a/src/libinput-private.h
+++ b/src/libinput-private.h
@@ -74,6 +74,13 @@ typedef void (*libinput_source_dispatch_t)(void *data);
 
 struct libinput_source;
 
+#define log_debug(...) log_msg(LIBINPUT_LOG_PRIORITY_DEBUG, __VA_ARGS__)
+#define log_info(...) log_msg(LIBINPUT_LOG_PRIORITY_INFO, __VA_ARGS__)
+#define log_error(...) log_msg(LIBINPUT_LOG_PRIORITY_ERROR, __VA_ARGS__)
+
+void
+log_msg(enum libinput_log_priority priority, const char *format, ...);
+
 int
 libinput_init(struct libinput *libinput,
  const struct libinput_interface *interface,
diff --git a/src/libinput-util.c b/src/libinput-util.c
index a3534e1..eeb9786 100644
--- a/src/libinput-util.c
+++ b/src/libinput-util.c
@@ -35,26 +35,6 @@
 #include libinput-util.h
 #include libinput-private.h
 
-static FILE *g_log_file = NULL;
-
-void
-set_logging_enabled(int enabled)
-{
-   g_log_file = enabled ? stdout : NULL;
-}
-
-void
-log_info(const char *format, ...)
-{
-   va_list ap;
-
-   if (g_log_file) {
-   va_start(ap, format);
-   vfprintf(g_log_file, format, ap);
-   va_end(ap);
-   }
-}
-
 void
 list_init(struct list *list)
 {
diff --git a/src/libinput.c b/src/libinput.c
index cfce2c5..b4879af 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -78,6 +78,68 @@ struct libinput_event_touch {
 };
 
 static void
+libinput_default_log_func(enum libinput_log_priority priority,
+ void *data,
+ const char *format, va_list args)
+{
+   const char *prefix;
+
+   switch(priority) {
+   case LIBINPUT_LOG_PRIORITY_DEBUG: prefix = debug; break;
+   case LIBINPUT_LOG_PRIORITY_INFO: prefix = info; break;
+   case LIBINPUT_LOG_PRIORITY_ERROR: prefix = error; break;
+   default: prefix=invalid priority; break;
+   }
+
+   fprintf(stderr, libinput %s: , prefix);
+   vfprintf(stderr, format, args);
+}
+
+struct log_data {
+   enum libinput_log_priority priority;
+   libinput_log_handler handler;
+   void *user_data;
+};
+
+static struct log_data log_data = {
+   .priority = LIBINPUT_LOG_PRIORITY_ERROR,
+   .handler = libinput_default_log_func,
+   .user_data = NULL,
+};
+
+void
+log_msg(enum libinput_log_priority priority, const char *format, ...)
+{
+   va_list args;
+
+   if (log_data.handler  log_data.priority = priority) {
+   va_start(args, format);
+   log_data.handler(priority, log_data.user_data, format, args);
+   va_end(args);
+   }
+}
+
+LIBINPUT_EXPORT void
+libinput_log_set_priority(enum libinput_log_priority priority)
+{
+   log_data.priority = priority;
+}
+
+LIBINPUT_EXPORT enum libinput_log_priority
+libinput_log_get_priority(void)
+{
+   return log_data.priority;
+}
+
+LIBINPUT_EXPORT void
+libinput_log_set_handler(libinput_log_handler log_handler,
+void *user_data)
+{
+   log_data.handler = log_handler;
+   log_data.user_data = user_data;
+}
+
+static void
 libinput_post_event(struct libinput *libinput,
struct libinput_event *event);
 
diff --git a/src/libinput.h b/src/libinput.h
index e87b2b7..6bf538a 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -42,6 +42,15 @@
 typedef int32_t li_fixed_t;
 
 /**
+ * Log priority for internal logging messages.
+ */
+enum libinput_log_priority {
+   LIBINPUT_LOG_PRIORITY_DEBUG = 10,
+   LIBINPUT_LOG_PRIORITY_INFO = 20,
+   LIBINPUT_LOG_PRIORITY_ERROR = 30,
+};
+
+/**
  * @ingroup device
  *
  * Capabilities on a device. A device may have one or more capabilities
@@ -875,6 +884,73 @@ void
 libinput_destroy(struct libinput *libinput);
 
 /**
+ * @ingroup base
+ *
+ * Set the global log priority. Messages with priorities equal to or
+ * higher than the argument will be printed to the current log handler.
+ *
+ * The default log priority is LIBINPUT_LOG_PRIORITY_ERROR.
+ *
+ * @param priority The minimum priority of log messages to print.
+ *
+ * @see libinput_log_set_handler
+ */
+void
+libinput_log_set_priority(enum libinput_log_priority

[PATCH libinput 01/19] Add the shell for a multitouch-compatible touchpad implementation

2014-02-16 Thread Peter Hutterer
Doesn't do anything but initialize and destroy. This is not a permanent
separate implementation, it's just easier to start this way and then switch
over than to add to the current one.

Temporary measure: LIBINPUT_NEW_TOUCHPAD_DRIVER environment variable can be
used to enable the new driver

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/Makefile.am |  1 +
 src/evdev-mt-touchpad.c | 76 +
 src/evdev.c |  5 +++-
 src/evdev.h |  3 ++
 4 files changed, 84 insertions(+), 1 deletion(-)
 create mode 100644 src/evdev-mt-touchpad.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 6e27b3b..c6afb82 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,6 +10,7 @@ libinput_la_SOURCES = \
libinput-util.h \
evdev.c \
evdev.h \
+   evdev-mt-touchpad.c \
evdev-touchpad.c\
filter.c\
filter.h\
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
new file mode 100644
index 000..a360651
--- /dev/null
+++ b/src/evdev-mt-touchpad.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright © 2014 Red Hat, Inc.
+ *
+ * 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 evdev.h
+
+struct touchpad_dispatch {
+   struct evdev_dispatch base;
+   struct evdev_device *device;
+};
+
+static void
+touchpad_process(struct evdev_dispatch *dispatch,
+struct evdev_device *device,
+struct input_event *e,
+uint32_t time)
+{
+}
+
+static void
+touchpad_destroy(struct evdev_dispatch *dispatch)
+{
+   free(dispatch);
+}
+
+static struct evdev_dispatch_interface touchpad_interface = {
+   touchpad_process,
+   touchpad_destroy
+};
+
+static int
+touchpad_init(struct touchpad_dispatch *touchpad,
+ struct evdev_device *device)
+{
+   touchpad-base.interface = touchpad_interface;
+   touchpad-device = device;
+
+   return 0;
+}
+
+struct evdev_dispatch *
+evdev_mt_touchpad_create(struct evdev_device *device)
+{
+   struct touchpad_dispatch *touchpad;
+
+   touchpad = zalloc(sizeof *touchpad);
+   if (!touchpad)
+   return NULL;
+
+   if (touchpad_init(touchpad, device) != 0) {
+   free(touchpad);
+   return NULL;
+   }
+
+   return  touchpad-base;
+}
diff --git a/src/evdev.c b/src/evdev.c
index d8dff65..ffa8557 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -565,7 +565,10 @@ evdev_configure_device(struct evdev_device *device)
if (TEST_BIT(key_bits, BTN_TOOL_FINGER) 
!TEST_BIT(key_bits, BTN_TOOL_PEN) 
(has_abs || has_mt)) {
-   device-dispatch = evdev_touchpad_create(device);
+   if (getenv(LIBINPUT_NEW_TOUCHPAD_DRIVER)  has_mt)
+   device-dispatch = 
evdev_mt_touchpad_create(device);
+   else
+   device-dispatch = 
evdev_touchpad_create(device);
}
for (i = KEY_ESC; i  KEY_MAX; i++) {
if (i = BTN_MISC  i  KEY_OK)
diff --git a/src/evdev.h b/src/evdev.h
index 3c9f93a..ce7fbb3 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -123,6 +123,9 @@ evdev_device_create(struct libinput_seat *seat,
 struct evdev_dispatch *
 evdev_touchpad_create(struct evdev_device *device);
 
+struct evdev_dispatch *
+evdev_mt_touchpad_create(struct evdev_device *device);
+
 void
 evdev_device_proces_event(struct libinput_event *event);
 
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org

[PATCH libinput 05/19] touchpad: add two-finger average scrolling

2014-02-16 Thread Peter Hutterer
If two fingers are down and moving, take the average movement of both fingers
and use that for scrolling.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 44 +++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 1968199..6d1793b 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -332,13 +332,55 @@ tp_post_process_state(struct tp_dispatch *tp, uint32_t 
time)
 }
 
 static void
+tp_post_twofinger_scroll(struct tp_dispatch *tp, uint32_t time)
+{
+   struct tp_touch *t;
+   int nchanged = 0;
+   double dx = 0, dy =0;
+   double tmpx, tmpy;
+
+   tp_for_each_touch(tp, t) {
+   if (t-dirty) {
+   nchanged++;
+   tp_get_delta(t, tmpx, tmpy);
+
+   dx += tmpx;
+   dy += tmpy;
+   }
+   }
+
+   if (nchanged == 0)
+   return;
+
+   dx /= nchanged;
+   dy /= nchanged;
+
+   tp_filter_motion(tp, dx, dy, time);
+
+   if (dx != 0.0)
+   pointer_notify_axis(tp-device-base,
+   time,
+   LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
+   li_fixed_from_double(dx));
+   if (dy != 0.0)
+   pointer_notify_axis(tp-device-base,
+   time,
+   LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
+   li_fixed_from_double(dy));
+}
+
+static void
 tp_post_events(struct tp_dispatch *tp, uint32_t time)
 {
struct tp_touch *t = tp_current_touch(tp);
double dx, dy;
 
-   if (tp-nfingers_down != 1)
+   if (tp-nfingers_down  2) {
return;
+   } else if (tp-nfingers_down == 2) {
+   tp_post_twofinger_scroll(tp, time);
+   return;
+   }
 
 
if (t-history.count  4)
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 04/19] touchpad: hook up the pointer acceleration

2014-02-16 Thread Peter Hutterer
Same algorithm as in evdev-touchpad.c

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 76 +
 1 file changed, 76 insertions(+)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index f625814..1968199 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -27,7 +27,11 @@
 #include stdbool.h
 
 #include evdev.h
+#include filter.h
 
+#define DEFAULT_CONSTANT_ACCEL_NUMERATOR 50
+#define DEFAULT_MIN_ACCEL_FACTOR 0.16
+#define DEFAULT_MAX_ACCEL_FACTOR 1.0
 #define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
 #define TOUCHPAD_HISTORY_LENGTH 4
 
@@ -78,6 +82,14 @@ struct tp_dispatch {
int32_t margin_x;
int32_t margin_y;
} hysteresis;
+
+   struct motion_filter *filter;
+
+   struct {
+   double constant_factor;
+   double min_factor;
+   double max_factor;
+   } accel;
 };
 
 static inline int
@@ -94,6 +106,27 @@ tp_hysteresis(int in, int center, int margin)
return center + diff;
 }
 
+static double
+tp_accel_profile(struct motion_filter *filter,
+void *data,
+double velocity,
+uint32_t time)
+{
+   struct tp_dispatch *tp =
+   (struct tp_dispatch *) data;
+
+   double accel_factor;
+
+   accel_factor = velocity * tp-accel.constant_factor;
+
+   if (accel_factor  tp-accel.max_factor)
+   accel_factor = tp-accel.max_factor;
+   else if (accel_factor  tp-accel.min_factor)
+   accel_factor = tp-accel.min_factor;
+
+   return accel_factor;
+}
+
 static inline struct tp_motion *
 tp_motion_history_offset(struct tp_touch *t, int offset)
 {
@@ -104,6 +137,21 @@ tp_motion_history_offset(struct tp_touch *t, int offset)
return t-history.samples[offset_index];
 }
 
+static void
+tp_filter_motion(struct tp_dispatch *tp,
+double *dx, double *dy, uint32_t time)
+{
+   struct motion_params motion;
+
+   motion.dx = *dx;
+   motion.dy = *dy;
+
+   filter_dispatch(tp-filter, motion, tp, time);
+
+   *dx = motion.dx;
+   *dy = motion.dy;
+}
+
 static inline void
 tp_motion_history_push(struct tp_touch *t)
 {
@@ -292,7 +340,12 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
if (tp-nfingers_down != 1)
return;
 
+
+   if (t-history.count  4)
+   return;
+
tp_get_delta(t, dx, dy);
+   tp_filter_motion(tp, dx, dy, time);
 
if (dx != 0 || dy != 0)
pointer_notify_motion(
@@ -332,6 +385,8 @@ tp_destroy(struct evdev_dispatch *dispatch)
struct tp_dispatch *tp =
(struct tp_dispatch*)dispatch;
 
+   if (tp-filter)
+   tp-filter-interface-destroy(tp-filter);
free(tp-touches);
free(tp);
 }
@@ -357,6 +412,24 @@ tp_init_slots(struct tp_dispatch *tp,
return 0;
 }
 
+static int
+tp_init_accel(struct tp_dispatch *touchpad, double diagonal)
+{
+   struct motion_filter *accel;
+
+   touchpad-accel.constant_factor =
+   DEFAULT_CONSTANT_ACCEL_NUMERATOR / diagonal;
+   touchpad-accel.min_factor = DEFAULT_MIN_ACCEL_FACTOR;
+   touchpad-accel.max_factor = DEFAULT_MAX_ACCEL_FACTOR;
+
+   accel = create_pointer_accelator_filter(tp_accel_profile);
+   if (accel == NULL)
+   return -1;
+
+   touchpad-filter = accel;
+
+   return 0;
+}
 
 static int
 tp_init(struct tp_dispatch *tp,
@@ -380,6 +453,9 @@ tp_init(struct tp_dispatch *tp,
tp-hysteresis.margin_y =
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
 
+   if (tp_init_accel(tp, diagonal) != 0)
+   return -1;
+
return 0;
 }
 
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 02/19] touchpad: add a touchpad driver based on per-finger tracking

2014-02-16 Thread Peter Hutterer
This patch is a mixture of an experimental project (libtouchpad) and
evdev-touchpad.c. It adds a new touchpad driver for multi-touch touchpads that
tracks each touchpoint separately. This makes it a lot easier to handle
multi-finger tapping, software button areas, etc.

libtouchpad used a slightly different coding style, this is the attempt to get
closer to the one used in libinput.

Currently sends motion events for single-finger motion, button events only for
physical buttons.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 300 +---
 1 file changed, 281 insertions(+), 19 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index a360651..856d54f 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -22,38 +22,300 @@
 
 #include config.h
 
+#include assert.h
+#include stdbool.h
+
 #include evdev.h
 
-struct touchpad_dispatch {
+#define TOUCHPAD_HISTORY_LENGTH 4
+
+#define tp_for_each_touch(_tp, _t) \
+   for (unsigned int _i = 0; _i  (_tp)-ntouches  (_t = 
(_tp)-touches[_i]); _i++)
+
+enum touch_state {
+   TOUCH_NONE = 0,
+   TOUCH_BEGIN,
+   TOUCH_UPDATE,
+   TOUCH_END
+};
+
+struct tp_motion {
+   int32_t x;
+   int32_t y;
+};
+
+struct tp_touch {
+   enum touch_state state;
+   bool dirty;
+   int32_t x;
+   int32_t y;
+   uint32_t millis;
+
+   struct {
+   struct tp_motion samples[TOUCHPAD_HISTORY_LENGTH];
+   unsigned int index;
+   unsigned int count;
+   } history;
+};
+
+struct tp_dispatch {
struct evdev_dispatch base;
struct evdev_device *device;
+   unsigned int nfingers_down; /* number of fingers down */
+   unsigned int slot;  /* current slot */
+
+   unsigned int ntouches;  /* number of slots */
+   struct tp_touch *touches;   /* len == ntouches */
 };
 
+static inline struct tp_motion *
+tp_motion_history_offset(struct tp_touch *t, int offset)
+{
+   int offset_index =
+   (t-history.index - offset + TOUCHPAD_HISTORY_LENGTH) %
+   TOUCHPAD_HISTORY_LENGTH;
+
+   return t-history.samples[offset_index];
+}
+
+static inline void
+tp_motion_history_push(struct tp_touch *t)
+{
+   int motion_index = (t-history.index + 1) % TOUCHPAD_HISTORY_LENGTH;
+
+   if (t-history.count  TOUCHPAD_HISTORY_LENGTH)
+   t-history.count++;
+
+   t-history.samples[motion_index].x = t-x;
+   t-history.samples[motion_index].y = t-y;
+   t-history.index = motion_index;
+}
+
+static inline void
+tp_motion_history_reset(struct tp_touch *t)
+{
+   t-history.count = 0;
+}
+
+static inline struct tp_touch *
+tp_current_touch(struct tp_dispatch *tp)
+{
+   return tp-touches[min(tp-slot, tp-ntouches)];
+}
+
+static inline void
+tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t)
+{
+   if (t-state != TOUCH_UPDATE) {
+   tp_motion_history_reset(t);
+   t-dirty = true;
+   t-state = TOUCH_BEGIN;
+   tp-nfingers_down++;
+   assert(tp-nfingers_down = 1);
+   }
+}
+
+static inline void
+tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t)
+{
+   if (t-state == TOUCH_NONE)
+   return;
+
+   t-dirty = true;
+   t-state = TOUCH_END;
+   assert(tp-nfingers_down = 1);
+   tp-nfingers_down--;
+}
+
+static double
+tp_estimate_delta(int x0, int x1, int x2, int x3)
+{
+   return (x0 + x1 - x2 - x3) / 4;
+}
+
 static void
-touchpad_process(struct evdev_dispatch *dispatch,
-struct evdev_device *device,
-struct input_event *e,
-uint32_t time)
+tp_get_delta(struct tp_touch *t, double *dx, double *dy)
 {
+   if (t-history.count  4) {
+   *dx = 0;
+   *dy = 0;
+   return;
+   }
+
+   *dx = tp_estimate_delta(tp_motion_history_offset(t, 0)-x,
+   tp_motion_history_offset(t, 1)-x,
+   tp_motion_history_offset(t, 2)-x,
+   tp_motion_history_offset(t, 3)-x);
+   *dy = tp_estimate_delta(tp_motion_history_offset(t, 0)-y,
+   tp_motion_history_offset(t, 1)-y,
+   tp_motion_history_offset(t, 2)-y,
+   tp_motion_history_offset(t, 3)-y);
+}
+
+static void
+tp_process_absolute(struct tp_dispatch *tp,
+   const struct input_event *e,
+   uint32_t time)
+{
+   struct tp_touch *t = tp_current_touch(tp);
+
+   switch(e-code) {
+   case ABS_MT_POSITION_X:
+   t-x = e-value;
+   t-millis = time;
+   t-dirty = true;
+   break;
+   case ABS_MT_POSITION_Y:
+   t-y = e-value;
+   t-millis = time

[PATCH libinput 03/19] touchpad: add hysteresis smoothing for input coordinates

2014-02-16 Thread Peter Hutterer
Same algorithm as in evdev-touchpad.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 63 +
 1 file changed, 63 insertions(+)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 856d54f..f625814 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -23,10 +23,12 @@
 #include config.h
 
 #include assert.h
+#include math.h
 #include stdbool.h
 
 #include evdev.h
 
+#define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
 #define TOUCHPAD_HISTORY_LENGTH 4
 
 #define tp_for_each_touch(_tp, _t) \
@@ -56,6 +58,11 @@ struct tp_touch {
unsigned int index;
unsigned int count;
} history;
+
+   struct {
+   int32_t center_x;
+   int32_t center_y;
+   } hysteresis;
 };
 
 struct tp_dispatch {
@@ -66,8 +73,27 @@ struct tp_dispatch {
 
unsigned int ntouches;  /* number of slots */
struct tp_touch *touches;   /* len == ntouches */
+
+   struct {
+   int32_t margin_x;
+   int32_t margin_y;
+   } hysteresis;
 };
 
+static inline int
+tp_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 inline struct tp_motion *
 tp_motion_history_offset(struct tp_touch *t, int offset)
 {
@@ -92,6 +118,30 @@ tp_motion_history_push(struct tp_touch *t)
 }
 
 static inline void
+tp_motion_hysteresis(struct tp_dispatch *tp,
+struct tp_touch *t)
+{
+   int x = t-x,
+   y = t-y;
+
+   if (t-history.count == 0) {
+   t-hysteresis.center_x = t-x;
+   t-hysteresis.center_y = t-y;
+   } else {
+   x = tp_hysteresis(x,
+ t-hysteresis.center_x,
+ tp-hysteresis.margin_x);
+   y = tp_hysteresis(y,
+ t-hysteresis.center_y,
+ tp-hysteresis.margin_y);
+   t-hysteresis.center_x = x;
+   t-hysteresis.center_y = y;
+   t-x = x;
+   t-y = y;
+   }
+}
+
+static inline void
 tp_motion_history_reset(struct tp_touch *t)
 {
t-history.count = 0;
@@ -210,6 +260,7 @@ tp_process_state(struct tp_dispatch *tp, uint32_t time)
if (!t-dirty)
continue;
 
+   tp_motion_hysteresis(tp, t);
tp_motion_history_push(t);
}
 }
@@ -311,12 +362,24 @@ static int
 tp_init(struct tp_dispatch *tp,
struct evdev_device *device)
 {
+   int width, height;
+   double diagonal;
+
tp-base.interface = tp_interface;
tp-device = device;
 
if (tp_init_slots(tp, device) != 0)
return -1;
 
+   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);
+
+   tp-hysteresis.margin_x =
+   diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
+   tp-hysteresis.margin_y =
+   diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
+
return 0;
 }
 
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 19/19] evdev: drop hook to init old touchpad driver

2014-02-16 Thread Peter Hutterer
Still leaving the driver itself in place for removal later, but only
initialize the new driver now.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index ffa8557..7d91e09 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -565,10 +565,7 @@ evdev_configure_device(struct evdev_device *device)
if (TEST_BIT(key_bits, BTN_TOOL_FINGER) 
!TEST_BIT(key_bits, BTN_TOOL_PEN) 
(has_abs || has_mt)) {
-   if (getenv(LIBINPUT_NEW_TOUCHPAD_DRIVER)  has_mt)
-   device-dispatch = 
evdev_mt_touchpad_create(device);
-   else
-   device-dispatch = 
evdev_touchpad_create(device);
+   device-dispatch = evdev_mt_touchpad_create(device);
}
for (i = KEY_ESC; i  KEY_MAX; i++) {
if (i = BTN_MISC  i  KEY_OK)
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 16/19] touchpad: add support for clickfingers

2014-02-16 Thread Peter Hutterer
On touchpads without physical buttons, the number of fingers on the touchpad
at the time the physical click happens decides the button type. 1/2/3 fingers
is handled left/right/middle.

We also swallow the motion event on the actual click event, this reduces
erroneous motion events by a bit. More processing is needed here though.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 67 +++--
 src/evdev-mt-touchpad.h |  1 +
 test/pointer.c  |  2 +-
 3 files changed, 62 insertions(+), 8 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index d0864fe..154df85 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -461,14 +461,42 @@ tp_post_scroll_events(struct tp_dispatch *tp, uint32_t 
time)
return 0;
 }
 
-static void
-tp_post_button_events(struct tp_dispatch *tp, uint32_t time)
+static int
+tp_post_clickfinger_buttons(struct tp_dispatch *tp, uint32_t time)
 {
uint32_t current, old, button;
+   enum libinput_pointer_button_state state;
 
-   if ((tp-queued 
-   (TOUCHPAD_EVENT_BUTTON_PRESS|TOUCHPAD_EVENT_BUTTON_RELEASE)) == 
0)
-   return;
+   current = tp-buttons.state;
+   old = tp-buttons.old_state;
+
+   if (current == old)
+   return 0;
+
+   switch (tp-nfingers_down) {
+   case 1: button = BTN_LEFT; break;
+   case 2: button = BTN_RIGHT; break;
+   case 3: button = BTN_MIDDLE; break;
+   default:
+   return 0;
+   }
+
+   if (current)
+   state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
+   else
+   state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
+
+   pointer_notify_button(tp-device-base,
+ time,
+ button,
+ state);
+   return 1;
+}
+
+static int
+tp_post_physical_buttons(struct tp_dispatch *tp, uint32_t time)
+{
+   uint32_t current, old, button;
 
current = tp-buttons.state;
old = tp-buttons.old_state;
@@ -493,6 +521,25 @@ tp_post_button_events(struct tp_dispatch *tp, uint32_t 
time)
current = 1;
old = 1;
}
+
+   return 0;
+}
+
+static int
+tp_post_button_events(struct tp_dispatch *tp, uint32_t time)
+{
+   int rc;
+
+   if ((tp-queued 
+   (TOUCHPAD_EVENT_BUTTON_PRESS|TOUCHPAD_EVENT_BUTTON_RELEASE)) == 
0)
+   return 0;
+
+   if (tp-buttons.has_buttons)
+   rc = tp_post_physical_buttons(tp, time);
+   else
+   rc = tp_post_clickfinger_buttons(tp, time);
+
+   return rc;
 }
 
 static void
@@ -501,6 +548,9 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
struct tp_touch *t = tp_current_touch(tp);
double dx, dy;
 
+   if (tp_post_button_events(tp, time) != 0)
+   return;
+
if (tp_tap_handle_state(tp, time) != 0)
return;
 
@@ -519,8 +569,6 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
li_fixed_from_double(dx),
li_fixed_from_double(dy));
}
-
-   tp_post_button_events(tp, time);
 }
 
 static void
@@ -622,6 +670,7 @@ tp_init(struct tp_dispatch *tp,
 {
int width, height;
double diagonal;
+   unsigned long key_bits[NBITS(KEY_MAX)];
 
tp-base.interface = tp_interface;
tp-device = device;
@@ -638,6 +687,10 @@ tp_init(struct tp_dispatch *tp,
tp-hysteresis.margin_y =
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
 
+   ioctl(device-fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), key_bits);
+   if (TEST_BIT(key_bits, BTN_RIGHT) || TEST_BIT(key_bits, BTN_MIDDLE))
+   tp-buttons.has_buttons = true;
+
if (tp_init_scroll(tp) != 0)
return -1;
 
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 84d8cec..327ce11 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -117,6 +117,7 @@ struct tp_dispatch {
} accel;
 
struct {
+   bool has_buttons;   /* true for physical LMR 
buttons */
uint32_t state;
uint32_t old_state;
} buttons;  /* physical buttons */
diff --git a/test/pointer.c b/test/pointer.c
index e864169..59fe818 100644
--- a/test/pointer.c
+++ b/test/pointer.c
@@ -186,7 +186,7 @@ END_TEST
 int main (int argc, char **argv) {
 
litest_add(pointer:motion, pointer_motion_relative, LITEST_POINTER, 
LITEST_ANY);
-   litest_add(pointer:button, pointer_button, LITEST_BUTTON, LITEST_ANY);
+   litest_add(pointer:button, pointer_button, LITEST_BUTTON, 
LITEST_CLICKPAD);
litest_add(pointer:scroll, pointer_scroll_wheel, LITEST_WHEEL, 
LITEST_ANY);
 
return

[PATCH libinput 12/19] touchpad: require minimum scroll distance and lock scroll direction

2014-02-16 Thread Peter Hutterer
This is a fairly rough approach, but can be handled more fine-grained later.
Require a minimum of 1 unit to start scrolling and lock the scrolling in the
initial direction, so further scroll events are limited to that direction
only.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 82 +
 src/evdev-mt-touchpad.h | 10 ++
 2 files changed, 79 insertions(+), 13 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 873ddf0..14fb7f3 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -310,16 +310,64 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint32_t 
time)
 
tp_filter_motion(tp, dx, dy, time);
 
-   if (dx != 0.0)
-   pointer_notify_axis(tp-device-base,
-   time,
-   LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
-   li_fixed_from_double(dx));
-   if (dy != 0.0)
+   if (tp-scroll.state == SCROLL_STATE_NONE) {
+   /* Require at least one px scrolling to start */
+   if (dx = -1.0 || dx = 1.0) {
+   tp-scroll.state = SCROLL_STATE_SCROLLING;
+   tp-scroll.direction |= (1  
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL);
+   }
+
+   if (dy = -1.0 || dy = 1.0) {
+   tp-scroll.state = SCROLL_STATE_SCROLLING;
+   tp-scroll.direction |= (1  
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL);
+   }
+
+   if (tp-scroll.state == SCROLL_STATE_NONE)
+   return;
+   }
+
+   if (dy != 0.0 
+   (tp-scroll.direction  (1  
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL))) {
pointer_notify_axis(tp-device-base,
time,
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
li_fixed_from_double(dy));
+   }
+
+   if (dx != 0.0 
+   (tp-scroll.direction  (1  
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL))) {
+   pointer_notify_axis(tp-device-base,
+   time,
+   LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
+   li_fixed_from_double(dx));
+   }
+}
+
+static int
+tp_post_scroll_events(struct tp_dispatch *tp, uint32_t time)
+{
+   if (tp-nfingers_down != 2) {
+   /* terminate scrolling with a zero scroll event to notify
+* caller that it really ended now */
+   if (tp-scroll.state != SCROLL_STATE_NONE) {
+   tp-scroll.state = SCROLL_STATE_NONE;
+   tp-scroll.direction = 0;
+   if (tp-scroll.direction  
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL)
+   pointer_notify_axis(tp-device-base,
+   time,
+   
LIBINPUT_POINTER_AXIS_VERTICAL_SCROLL,
+   0);
+   if (tp-scroll.direction  
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL)
+   pointer_notify_axis(tp-device-base,
+   time,
+   
LIBINPUT_POINTER_AXIS_HORIZONTAL_SCROLL,
+   0);
+   }
+   } else {
+   tp_post_twofinger_scroll(tp, time);
+   return 1;
+   }
+   return 0;
 }
 
 static void
@@ -362,16 +410,12 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
struct tp_touch *t = tp_current_touch(tp);
double dx, dy;
 
-   if (tp-nfingers_down  2) {
-   return;
-   } else if (tp-nfingers_down == 2) {
-   tp_post_twofinger_scroll(tp, time);
-   return;
-   }
-
if (tp_tap_handle_state(tp, time) != 0)
return;
 
+   if (tp_post_scroll_events(tp, time) != 0)
+   return;
+
if (t-history.count = TOUCHPAD_MIN_SAMPLES) {
tp_get_delta(t, dx, dy);
tp_filter_motion(tp, dx, dy, time);
@@ -464,6 +508,15 @@ tp_init_accel(struct tp_dispatch *touchpad, double 
diagonal)
 }
 
 static int
+tp_init_scroll(struct tp_dispatch *tp)
+{
+   tp-scroll.direction = 0;
+   tp-scroll.state = SCROLL_STATE_NONE;
+
+   return 0;
+}
+
+static int
 tp_init(struct tp_dispatch *tp,
struct evdev_device *device)
 {
@@ -485,6 +538,9 @@ tp_init(struct tp_dispatch *tp,
tp-hysteresis.margin_y =
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
 
+   if (tp_init_scroll(tp) != 0)
+   return -1;
+
if (tp_init_accel(tp, diagonal) != 0)
return -1;
 
diff --git a/src/evdev-mt

[PATCH libinput 14/19] touchpad: support single-touch touchpads

2014-02-16 Thread Peter Hutterer
Touchpads without ABS_MT_SLOT create 5 slots by default (for up to QUINTTAP)
and ABS_X/Y is mapped to the 0-slot touchpoint. This commit adds handling for
a single finger, no BTN_TOOL_DOUBLETAP or similar is being processed yet.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 57 +++--
 src/evdev-mt-touchpad.h |  2 ++
 2 files changed, 52 insertions(+), 7 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index c4c4c41..f8edb8c 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -226,6 +226,28 @@ tp_process_absolute(struct tp_dispatch *tp,
 }
 
 static void
+tp_process_absolute_st(struct tp_dispatch *tp,
+  const struct input_event *e,
+  uint32_t time)
+{
+   struct tp_touch *t = tp_current_touch(tp);
+
+   switch(e-code) {
+   case ABS_X:
+   t-x = e-value;
+   t-millis = time;
+   t-dirty = true;
+   break;
+   case ABS_Y:
+   t-y = e-value;
+   t-millis = time;
+   t-dirty = true;
+   tp-queued |= TOUCHPAD_EVENT_MOTION;
+   break;
+   }
+}
+
+static void
 tp_process_key(struct tp_dispatch *tp,
   const struct input_event *e,
   uint32_t time)
@@ -245,6 +267,18 @@ tp_process_key(struct tp_dispatch *tp,
tp-queued |= TOUCHPAD_EVENT_BUTTON_RELEASE;
}
break;
+   case BTN_TOUCH:
+   if (!tp-has_mt) {
+   struct tp_touch *t = tp_current_touch(tp);
+   if (e-value) {
+   tp_begin_touch(tp, t);
+   t-fake = true;
+   } else {
+   tp_end_touch(tp, t);
+   }
+   t-millis = time;
+   }
+   break;
}
 }
 
@@ -271,9 +305,10 @@ tp_post_process_state(struct tp_dispatch *tp, uint32_t 
time)
if (!t-dirty)
continue;
 
-   if (t-state == TOUCH_END)
+   if (t-state == TOUCH_END) {
t-state = TOUCH_NONE;
-   else if (t-state == TOUCH_BEGIN)
+   t-fake = false;
+   } else if (t-state == TOUCH_BEGIN)
t-state = TOUCH_UPDATE;
 
t-dirty = false;
@@ -443,7 +478,10 @@ tp_process(struct evdev_dispatch *dispatch,
 
switch (e-type) {
case EV_ABS:
-   tp_process_absolute(tp, e, time);
+   if (tp-has_mt)
+   tp_process_absolute(tp, e, time);
+   else
+   tp_process_absolute_st(tp, e, time);
break;
case EV_KEY:
tp_process_key(tp, e, time);
@@ -479,12 +517,17 @@ tp_init_slots(struct tp_dispatch *tp,
 {
struct input_absinfo absinfo = {0};
 
-   ioctl(device-fd, EVIOCGABS(ABS_MT_SLOT), absinfo);
-
-   tp-ntouches = absinfo.maximum + 1;
+   if (ioctl(device-fd, EVIOCGABS(ABS_MT_SLOT), absinfo) == -1) {
+   tp-ntouches = 5; /* FIXME: based on DOUBLETAP, etc. */
+   tp-slot = 0;
+   tp-has_mt = false;
+   } else {
+   tp-ntouches = absinfo.maximum + 1;
+   tp-slot = absinfo.value;
+   tp-has_mt = true;
+   }
tp-touches = calloc(tp-ntouches,
 sizeof(struct tp_touch));
-   tp-slot = absinfo.value;
 
return 0;
 }
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 17e9055..1e09497 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -75,6 +75,7 @@ struct tp_motion {
 struct tp_touch {
enum touch_state state;
bool dirty;
+   bool fake;  /* a fake touch */
int32_t x;
int32_t y;
uint32_t millis;
@@ -96,6 +97,7 @@ struct tp_dispatch {
struct evdev_device *device;
unsigned int nfingers_down; /* number of fingers down */
unsigned int slot;  /* current slot */
+   bool has_mt;
 
unsigned int ntouches;  /* number of slots */
struct tp_touch *touches;   /* len == ntouches */
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 09/19] touchpad: Make touchpad_get_delta() available from other files

2014-02-16 Thread Peter Hutterer
No functional changes.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 2 +-
 src/evdev-mt-touchpad.h | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index e25997d..73ea8a8 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -174,7 +174,7 @@ tp_estimate_delta(int x0, int x1, int x2, int x3)
return (x0 + x1 - x2 - x3) / 4;
 }
 
-static void
+void
 tp_get_delta(struct tp_touch *t, double *dx, double *dy)
 {
if (t-history.count  4) {
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index d12647d..907aec8 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -102,4 +102,7 @@ struct tp_dispatch {
 #define tp_for_each_touch(_tp, _t) \
for (unsigned int _i = 0; _i  (_tp)-ntouches  (_t = 
(_tp)-touches[_i]); _i++)
 
+void
+tp_get_delta(struct tp_touch *t, double *dx, double *dy);
+
 #endif
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 06/19] touchpad: move structs into a header file

2014-02-16 Thread Peter Hutterer
The tapping state implementation will be in a separate file, so let's make
sure we can access the structs we need.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/Makefile.am |  1 +
 src/evdev-mt-touchpad.c | 61 +
 src/evdev-mt-touchpad.h | 91 +
 3 files changed, 93 insertions(+), 60 deletions(-)
 create mode 100644 src/evdev-mt-touchpad.h

diff --git a/src/Makefile.am b/src/Makefile.am
index c6afb82..f6d0335 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,6 +11,7 @@ libinput_la_SOURCES = \
evdev.c \
evdev.h \
evdev-mt-touchpad.c \
+   evdev-mt-touchpad.h \
evdev-touchpad.c\
filter.c\
filter.h\
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 6d1793b..8a8586a 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -26,71 +26,12 @@
 #include math.h
 #include stdbool.h
 
-#include evdev.h
-#include filter.h
+#include evdev-mt-touchpad.h
 
 #define DEFAULT_CONSTANT_ACCEL_NUMERATOR 50
 #define DEFAULT_MIN_ACCEL_FACTOR 0.16
 #define DEFAULT_MAX_ACCEL_FACTOR 1.0
 #define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
-#define TOUCHPAD_HISTORY_LENGTH 4
-
-#define tp_for_each_touch(_tp, _t) \
-   for (unsigned int _i = 0; _i  (_tp)-ntouches  (_t = 
(_tp)-touches[_i]); _i++)
-
-enum touch_state {
-   TOUCH_NONE = 0,
-   TOUCH_BEGIN,
-   TOUCH_UPDATE,
-   TOUCH_END
-};
-
-struct tp_motion {
-   int32_t x;
-   int32_t y;
-};
-
-struct tp_touch {
-   enum touch_state state;
-   bool dirty;
-   int32_t x;
-   int32_t y;
-   uint32_t millis;
-
-   struct {
-   struct tp_motion samples[TOUCHPAD_HISTORY_LENGTH];
-   unsigned int index;
-   unsigned int count;
-   } history;
-
-   struct {
-   int32_t center_x;
-   int32_t center_y;
-   } hysteresis;
-};
-
-struct tp_dispatch {
-   struct evdev_dispatch base;
-   struct evdev_device *device;
-   unsigned int nfingers_down; /* number of fingers down */
-   unsigned int slot;  /* current slot */
-
-   unsigned int ntouches;  /* number of slots */
-   struct tp_touch *touches;   /* len == ntouches */
-
-   struct {
-   int32_t margin_x;
-   int32_t margin_y;
-   } hysteresis;
-
-   struct motion_filter *filter;
-
-   struct {
-   double constant_factor;
-   double min_factor;
-   double max_factor;
-   } accel;
-};
 
 static inline int
 tp_hysteresis(int in, int center, int margin)
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
new file mode 100644
index 000..f7f413b
--- /dev/null
+++ b/src/evdev-mt-touchpad.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2014 Red Hat, Inc.
+ *
+ * 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_MT_TOUCHPAD_H
+#define EVDEV_MT_TOUCHPAD_H
+
+#include stdbool.h
+
+#include evdev.h
+#include filter.h
+
+#define TOUCHPAD_HISTORY_LENGTH 4
+
+enum touch_state {
+   TOUCH_NONE = 0,
+   TOUCH_BEGIN,
+   TOUCH_UPDATE,
+   TOUCH_END
+};
+
+struct tp_motion {
+   int32_t x;
+   int32_t y;
+};
+
+struct tp_touch {
+   enum touch_state state;
+   bool dirty;
+   int32_t x;
+   int32_t y;
+   uint32_t millis;
+
+   struct {
+   struct tp_motion samples[TOUCHPAD_HISTORY_LENGTH];
+   unsigned int index;
+   unsigned int count;
+   } history;
+
+   struct {
+   int32_t center_x;
+   int32_t

[PATCH libinput 13/19] touchpad: Only move the pointer when there's a single finger down

2014-02-16 Thread Peter Hutterer
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 14fb7f3..c4c4c41 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -416,7 +416,8 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
if (tp_post_scroll_events(tp, time) != 0)
return;
 
-   if (t-history.count = TOUCHPAD_MIN_SAMPLES) {
+   if (t-history.count = TOUCHPAD_MIN_SAMPLES 
+   tp-nfingers_down == 1) {
tp_get_delta(t, dx, dy);
tp_filter_motion(tp, dx, dy, time);
 
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 08/19] touchpad: add a struct for handling physical button event state changes

2014-02-16 Thread Peter Hutterer
On ClickPads (touchpads without phys. middle/right buttons) it is important to
know whether a physical click is queued up. The finger position or number of
fingers decide which button event to send.

This isn't currently used, we still just send the button number at the moment.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 54 +++--
 src/evdev-mt-touchpad.h |  5 +
 2 files changed, 53 insertions(+), 6 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 1d34df8..e25997d 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -230,16 +230,20 @@ tp_process_key(struct tp_dispatch *tp,
   const struct input_event *e,
   uint32_t time)
 {
+   uint32_t mask;
+
switch (e-code) {
case BTN_LEFT:
case BTN_MIDDLE:
case BTN_RIGHT:
-   pointer_notify_button(
-   tp-device-base,
-   time,
-   e-code,
-   e-value ? 
LIBINPUT_POINTER_BUTTON_STATE_PRESSED :
-  
LIBINPUT_POINTER_BUTTON_STATE_RELEASED);
+   mask = 1  (e-code - BTN_LEFT);
+   if (e-value) {
+   tp-buttons.state |= mask;
+   tp-queued |= TOUCHPAD_EVENT_BUTTON_PRESS;
+   } else {
+   tp-buttons.state = ~mask;
+   tp-queued |= TOUCHPAD_EVENT_BUTTON_RELEASE;
+   }
break;
}
 }
@@ -275,6 +279,8 @@ tp_post_process_state(struct tp_dispatch *tp, uint32_t time)
t-dirty = false;
}
 
+   tp-buttons.old_state = tp-buttons.state;
+
tp-queued = TOUCHPAD_EVENT_NONE;
 }
 
@@ -317,6 +323,40 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint32_t 
time)
 }
 
 static void
+tp_post_button_events(struct tp_dispatch *tp, uint32_t time)
+{
+   uint32_t current, old, button;
+
+   if ((tp-queued 
+   (TOUCHPAD_EVENT_BUTTON_PRESS|TOUCHPAD_EVENT_BUTTON_RELEASE)) == 
0)
+   return;
+
+   current = tp-buttons.state;
+   old = tp-buttons.old_state;
+   button = BTN_LEFT;
+
+   while (current || old) {
+   enum libinput_pointer_button_state state;
+
+   if ((current  0x1) ^ (old  0x1)) {
+   if (!!(current  0x1))
+   state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
+   else
+   state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
+
+   pointer_notify_button(tp-device-base,
+ time,
+ button,
+ state);
+   }
+
+   button++;
+   current = 1;
+   old = 1;
+   }
+}
+
+static void
 tp_post_events(struct tp_dispatch *tp, uint32_t time)
 {
struct tp_touch *t = tp_current_touch(tp);
@@ -342,6 +382,8 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
time,
li_fixed_from_double(dx),
li_fixed_from_double(dy));
+
+   tp_post_button_events(tp, time);
 }
 
 static void
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 52ad3ab..d12647d 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -91,6 +91,11 @@ struct tp_dispatch {
double max_factor;
} accel;
 
+   struct {
+   uint32_t state;
+   uint32_t old_state;
+   } buttons;  /* physical buttons */
+
enum touchpad_event queued;
 };
 
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 11/19] touchpad: Filter motion in a certain number of tap states

2014-02-16 Thread Peter Hutterer
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad-tap.c | 23 ++-
 src/evdev-mt-touchpad.c | 22 +++---
 src/evdev-mt-touchpad.h |  1 +
 3 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c
index 7ac592b..bc7acbd 100644
--- a/src/evdev-mt-touchpad-tap.c
+++ b/src/evdev-mt-touchpad-tap.c
@@ -504,6 +504,7 @@ int
 tp_tap_handle_state(struct tp_dispatch *tp, uint32_t time)
 {
struct tp_touch *t;
+   int filter_motion = 0;
 
if (tp-queued  TOUCHPAD_EVENT_BUTTON_PRESS)
tp_tap_handle_event(tp, TAP_EVENT_BUTTON, time);
@@ -521,7 +522,27 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint32_t time)
tp_tap_handle_event(tp, TAP_EVENT_MOTION, time);
}
 
-   return 0;
+   /**
+* In any state where motion exceeding the move threshold would
+* move to the next state, filter that motion until we actually
+* exceed it. This prevents small motion events while we're waiting
+* on a decision if a tap is a tap.
+*/
+   switch (tp-tap.state) {
+   case TAP_STATE_TOUCH:
+   case TAP_STATE_TAPPED:
+   case TAP_STATE_DRAGGING_OR_DOUBLETAP:
+   case TAP_STATE_TOUCH_2:
+   case TAP_STATE_TOUCH_3:
+   filter_motion = 1;
+   break;
+
+   default:
+   break;
+
+   }
+
+   return filter_motion;
 }
 
 static void
diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index d1268f6..873ddf0 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -369,20 +369,20 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
return;
}
 
-   tp_tap_handle_state(tp, time);
-
-   if (t-history.count  4)
+   if (tp_tap_handle_state(tp, time) != 0)
return;
 
-   tp_get_delta(t, dx, dy);
-   tp_filter_motion(tp, dx, dy, time);
+   if (t-history.count = TOUCHPAD_MIN_SAMPLES) {
+   tp_get_delta(t, dx, dy);
+   tp_filter_motion(tp, dx, dy, time);
 
-   if (dx != 0 || dy != 0)
-   pointer_notify_motion(
-   tp-device-base,
-   time,
-   li_fixed_from_double(dx),
-   li_fixed_from_double(dy));
+   if (dx != 0 || dy != 0)
+   pointer_notify_motion(
+   tp-device-base,
+   time,
+   li_fixed_from_double(dx),
+   li_fixed_from_double(dy));
+   }
 
tp_post_button_events(tp, time);
 }
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 973b478..a5cfaa6 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -30,6 +30,7 @@
 #include filter.h
 
 #define TOUCHPAD_HISTORY_LENGTH 4
+#define TOUCHPAD_MIN_SAMPLES 4
 
 enum touchpad_event {
TOUCHPAD_EVENT_NONE = 0,
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 17/19] touchpad: mark the first finger as pointer-controlling finger

2014-02-16 Thread Peter Hutterer
Unused at the moment, but will be used later to determine if a finger should
trigger motion events.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 4 
 src/evdev-mt-touchpad.h | 1 +
 2 files changed, 5 insertions(+)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 154df85..84764ac 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -159,6 +159,9 @@ tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t)
tp-nfingers_down++;
assert(tp-nfingers_down = 1);
tp-queued |= TOUCHPAD_EVENT_MOTION;
+
+   if (tp-nfingers_down == 1)
+   t-is_pointer = true;
}
 }
 
@@ -169,6 +172,7 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t)
return;
 
t-dirty = true;
+   t-is_pointer = false;
t-state = TOUCH_END;
assert(tp-nfingers_down = 1);
tp-nfingers_down--;
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 327ce11..df83b2c 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -76,6 +76,7 @@ struct tp_touch {
enum touch_state state;
bool dirty;
bool fake;  /* a fake touch */
+   bool is_pointer;/* the pointer-controlling 
touch */
int32_t x;
int32_t y;
uint32_t millis;
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 07/19] touchpad: mark which events are currently pending processing

2014-02-16 Thread Peter Hutterer
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 6 ++
 src/evdev-mt-touchpad.h | 9 +
 2 files changed, 15 insertions(+)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 8a8586a..1d34df8 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -151,6 +151,7 @@ tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t)
t-state = TOUCH_BEGIN;
tp-nfingers_down++;
assert(tp-nfingers_down = 1);
+   tp-queued |= TOUCHPAD_EVENT_MOTION;
}
 }
 
@@ -164,6 +165,7 @@ tp_end_touch(struct tp_dispatch *tp, struct tp_touch *t)
t-state = TOUCH_END;
assert(tp-nfingers_down = 1);
tp-nfingers_down--;
+   tp-queued |= TOUCHPAD_EVENT_MOTION;
 }
 
 static double
@@ -203,11 +205,13 @@ tp_process_absolute(struct tp_dispatch *tp,
t-x = e-value;
t-millis = time;
t-dirty = true;
+   tp-queued |= TOUCHPAD_EVENT_MOTION;
break;
case ABS_MT_POSITION_Y:
t-y = e-value;
t-millis = time;
t-dirty = true;
+   tp-queued |= TOUCHPAD_EVENT_MOTION;
break;
case ABS_MT_SLOT:
tp-slot = e-value;
@@ -270,6 +274,8 @@ tp_post_process_state(struct tp_dispatch *tp, uint32_t time)
 
t-dirty = false;
}
+
+   tp-queued = TOUCHPAD_EVENT_NONE;
 }
 
 static void
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index f7f413b..52ad3ab 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -31,6 +31,13 @@
 
 #define TOUCHPAD_HISTORY_LENGTH 4
 
+enum touchpad_event {
+   TOUCHPAD_EVENT_NONE = 0,
+   TOUCHPAD_EVENT_MOTION   = (1  0),
+   TOUCHPAD_EVENT_BUTTON_PRESS = (1  1),
+   TOUCHPAD_EVENT_BUTTON_RELEASE   = (1  2),
+};
+
 enum touch_state {
TOUCH_NONE = 0,
TOUCH_BEGIN,
@@ -83,6 +90,8 @@ struct tp_dispatch {
double min_factor;
double max_factor;
} accel;
+
+   enum touchpad_event queued;
 };
 
 #define tp_for_each_touch(_tp, _t) \
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 15/19] touchpad: add fake-touch support for BTN_TOOL_DOUBLETAP and friends

2014-02-16 Thread Peter Hutterer
This enables two-finger scrolling and two- and three-finger tapping on a
single-touch touchpad if BTN_TOOL_DOUBLETAP and BTN_TOOL_TRIPLETAP is set.

These require a bit of special processing:
BTN_TOUCH is set with the first finger down, but somewhat randomly unset and
re-set when switching between the various BTN_TOOL_*TAP values.
BTN_TOOL_NTAP is only set for N fingers down, thus a double-triple move
will see a release for DOUBLETAP and a press for TRIPLETAP. This may happen in
the same event, or across two consecutive events.

This patch adds a fake_touches mask to the touchpad struct. The mask is set
for each matching BTN_* event and used to count the number of expected
fake touchpoints. From that we begin/end the number of actual touchpoints
required. Fake touchpoints take their x/y coordinates from the first
touchpoint, which reads ABS_X/ABS_Y.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 78 ++---
 src/evdev-mt-touchpad.h |  1 +
 2 files changed, 68 insertions(+), 11 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index f8edb8c..d0864fe 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -142,6 +142,13 @@ tp_current_touch(struct tp_dispatch *tp)
return tp-touches[min(tp-slot, tp-ntouches)];
 }
 
+static inline struct tp_touch *
+tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
+{
+   assert(slot  tp-ntouches);
+   return tp-touches[slot];
+}
+
 static inline void
 tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t)
 {
@@ -248,6 +255,54 @@ tp_process_absolute_st(struct tp_dispatch *tp,
 }
 
 static void
+tp_process_fake_touch(struct tp_dispatch *tp,
+ const struct input_event *e,
+ uint32_t time)
+{
+   struct tp_touch *t;
+   unsigned int fake_touches;
+   unsigned int nfake_touches;
+   unsigned int i;
+   unsigned int shift;
+
+   if (e-code != BTN_TOUCH 
+   (e-code  BTN_TOOL_DOUBLETAP || e-code  BTN_TOOL_QUADTAP))
+   return;
+
+   shift = e-code == BTN_TOUCH ? 0 : (e-code - BTN_TOOL_DOUBLETAP + 1);
+
+   if (e-value)
+   tp-fake_touches |= 1  shift;
+   else
+   tp-fake_touches = ~(0x1  shift);
+
+   fake_touches = tp-fake_touches;
+   nfake_touches = 0;
+   while (fake_touches) {
+   nfake_touches++;
+   fake_touches = 1;
+   }
+
+   for (i = 0; i  tp-ntouches; i++) {
+   t = tp_get_touch(tp, i);
+   if (i = nfake_touches) {
+   if (t-state != TOUCH_NONE) {
+   tp_end_touch(tp, t);
+   t-millis = time;
+   }
+   } else if (t-state != TOUCH_UPDATE 
+  t-state != TOUCH_BEGIN) {
+   t-state = TOUCH_NONE;
+   tp_begin_touch(tp, t);
+   t-millis = time;
+   t-fake =true;
+   }
+   }
+
+   assert(tp-nfingers_down == nfake_touches);
+}
+
+static void
 tp_process_key(struct tp_dispatch *tp,
   const struct input_event *e,
   uint32_t time)
@@ -268,16 +323,11 @@ tp_process_key(struct tp_dispatch *tp,
}
break;
case BTN_TOUCH:
-   if (!tp-has_mt) {
-   struct tp_touch *t = tp_current_touch(tp);
-   if (e-value) {
-   tp_begin_touch(tp, t);
-   t-fake = true;
-   } else {
-   tp_end_touch(tp, t);
-   }
-   t-millis = time;
-   }
+   case BTN_TOOL_DOUBLETAP:
+   case BTN_TOOL_TRIPLETAP:
+   case BTN_TOOL_QUADTAP:
+   if (!tp-has_mt)
+   tp_process_fake_touch(tp, e, time);
break;
}
 }
@@ -286,9 +336,15 @@ static void
 tp_process_state(struct tp_dispatch *tp, uint32_t time)
 {
struct tp_touch *t;
+   struct tp_touch *first = tp_get_touch(tp, 0);
 
tp_for_each_touch(tp, t) {
-   if (!t-dirty)
+   if (!tp-has_mt  t != first  first-fake) {
+   t-x = first-x;
+   t-y = first-y;
+   if (!t-dirty)
+   t-dirty = first-dirty;
+   } else if (!t-dirty)
continue;
 
tp_motion_hysteresis(tp, t);
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 1e09497..84d8cec 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -101,6 +101,7 @@ struct tp_dispatch

[PATCH libinput 18/19] touchpad: Support finger-pinnnig during physical button presses

2014-02-16 Thread Peter Hutterer
On a clickpad, one finger has be on the trackpad to trigger a physical button
press. For drag and drop, we still want motion events though when a second
finger is down.

This patch adds finger-pinning. If the touchpad is pressed, the pressing
finger is pinned and ignored for further motion events. A second finger may
then be used to drag.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 87 +++--
 src/evdev-mt-touchpad.h |  1 +
 2 files changed, 85 insertions(+), 3 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 84764ac..dea99a9 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -152,6 +152,8 @@ tp_get_touch(struct tp_dispatch *tp, unsigned int slot)
 static inline void
 tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t)
 {
+   struct tp_touch *tmp;
+
if (t-state != TOUCH_UPDATE) {
tp_motion_history_reset(t);
t-dirty = true;
@@ -160,8 +162,14 @@ tp_begin_touch(struct tp_dispatch *tp, struct tp_touch *t)
assert(tp-nfingers_down = 1);
tp-queued |= TOUCHPAD_EVENT_MOTION;
 
-   if (tp-nfingers_down == 1)
+   tp_for_each_touch(tp, tmp) {
+   if (tmp-is_pointer)
+   break;
+   }
+
+   if (!tmp-is_pointer) {
t-is_pointer = true;
+   }
}
 }
 
@@ -337,6 +345,53 @@ tp_process_key(struct tp_dispatch *tp,
 }
 
 static void
+tp_unpin_finger(struct tp_dispatch *tp)
+{
+   struct tp_touch *t;
+   tp_for_each_touch(tp, t) {
+   if (t-is_pinned) {
+   t-is_pinned = false;
+
+   if (t-state != TOUCH_END 
+   tp-nfingers_down == 1)
+   t-is_pointer = true;
+   break;
+   }
+   }
+}
+
+static void
+tp_pin_finger(struct tp_dispatch *tp)
+{
+   struct tp_touch *t,
+   *pinned = NULL;
+
+   tp_for_each_touch(tp, t) {
+   if (t-is_pinned) {
+   pinned = t;
+   break;
+   }
+   }
+
+   assert(!pinned);
+
+   pinned = tp_current_touch(tp);
+
+   if (tp-nfingers_down != 1) {
+   tp_for_each_touch(tp, t) {
+   if (t == pinned)
+   continue;
+
+   if (t-y  pinned-y)
+   pinned = t;
+   }
+   }
+
+   pinned-is_pinned = true;
+   pinned-is_pointer = false;
+}
+
+static void
 tp_process_state(struct tp_dispatch *tp, uint32_t time)
 {
struct tp_touch *t;
@@ -354,6 +409,15 @@ tp_process_state(struct tp_dispatch *tp, uint32_t time)
tp_motion_hysteresis(tp, t);
tp_motion_history_push(t);
}
+
+   /* We have a physical button down event on a clickpad. For drag and
+  drop, this means we try to identify which finger pressed the
+  physical button and pin it, i.e. remove pointer-moving
+  capabilities from it.
+*/
+   if ((tp-queued  TOUCHPAD_EVENT_BUTTON_PRESS) 
+   !tp-buttons.has_buttons)
+   tp_pin_finger(tp);
 }
 
 static void
@@ -376,6 +440,9 @@ tp_post_process_state(struct tp_dispatch *tp, uint32_t time)
 
tp-buttons.old_state = tp-buttons.state;
 
+   if (tp-queued  TOUCHPAD_EVENT_BUTTON_RELEASE)
+   tp_unpin_finger(tp);
+
tp-queued = TOUCHPAD_EVENT_NONE;
 }
 
@@ -441,6 +508,11 @@ tp_post_twofinger_scroll(struct tp_dispatch *tp, uint32_t 
time)
 static int
 tp_post_scroll_events(struct tp_dispatch *tp, uint32_t time)
 {
+   /* don't scroll if a clickpad is held down */
+   if (!tp-buttons.has_buttons 
+   (tp-buttons.state || tp-buttons.old_state))
+   return 0;
+
if (tp-nfingers_down != 2) {
/* terminate scrolling with a zero scroll event to notify
 * caller that it really ended now */
@@ -561,8 +633,17 @@ tp_post_events(struct tp_dispatch *tp, uint32_t time)
if (tp_post_scroll_events(tp, time) != 0)
return;
 
-   if (t-history.count = TOUCHPAD_MIN_SAMPLES 
-   tp-nfingers_down == 1) {
+   if (t-history.count = TOUCHPAD_MIN_SAMPLES) {
+   if (!t-is_pointer) {
+   tp_for_each_touch(tp, t) {
+   if (t-is_pointer)
+   break;
+   }
+   }
+
+   if (!t-is_pointer)
+   return;
+
tp_get_delta(t, dx, dy);
tp_filter_motion(tp, dx, dy, time);
 
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index df83b2c..c30dc9e 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev

Re: [PATCH libinput] evdev: fix device_transform_ functions

2014-02-17 Thread Peter Hutterer
On Mon, Feb 17, 2014 at 01:42:52PM -0500, Benjamin Tissoires wrote:
 X and Y are li_fixed_t, which is 24.8 fixed point real number.
 li_fixed_t max is thus ~8388607.
 
 On a touchscreen with a range of 32767 values (like a 3M sensor), and
 mapped on monitor with a resolution of 1920x1080, we currently have:
 (x - li_fixed_from_int(device-abs.min_x)) * width == 62912640
 
 which is 7 times bigger than li_fixed_t max.
 
 To keep the precision of the sensor, first compute the uniformized
 coordinate (in range 0 .. 1.0) of the touch point, then multiply it
 by the screen dimension, and revert it to a li_fixed_t.
 
 Signed-off-by: Benjamin Tissoires benjamin.tissoi...@gmail.com
 ---
 
 Hi,
 
 I have hit this problem by playing with a touchscreen reporting 4096 values, 
 on
 xf86-input-libinput. xf86-input-libinput does not use the real screen size, 
 but
 0x instead. This allows to report a touchscreen with a range of 128 values
 to work properly :(
 
 I went through the multitouch device database, and took one example of a more
 real use-case (xf86-input-libinput is still in an early shape).

fwiw, this is exactly the type of use-case where it would be simple and
worth it to knock up a test for a single device and make sure that the
coordinates are correct. which gives us a nice reproducer and prevents us
from errors like this in the future.

  src/evdev.c | 6 --
  1 file changed, 4 insertions(+), 2 deletions(-)
 
 diff --git a/src/evdev.c b/src/evdev.c
 index d8dff65..0d033b8 100644
 --- a/src/evdev.c
 +++ b/src/evdev.c
 @@ -91,8 +91,9 @@ evdev_device_transform_x(struct evdev_device *device,
li_fixed_t x,
uint32_t width)
  {
 - return (x - li_fixed_from_int(device-abs.min_x)) * width /
 + double x_scaled = (li_fixed_to_double(x) - device-abs.min_x) /
   (device-abs.max_x - device-abs.min_x + 1);
 + return li_fixed_from_double(x_scaled * width);

A simple 1L *  should suffice, right?

Cheers,
   Peter

  }
  
  li_fixed_t
 @@ -100,8 +101,9 @@ evdev_device_transform_y(struct evdev_device *device,
li_fixed_t y,
uint32_t height)
  {
 - return (y - li_fixed_from_int(device-abs.min_y)) * height /
 + double y_scaled = (li_fixed_to_double(y) - device-abs.min_y) /
   (device-abs.max_y - device-abs.min_y + 1);
 + return li_fixed_from_double(y_scaled * height);
  }
  
  static void
 -- 
 1.8.5.3
 
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 1/2] Hook up libevdev as backend

2014-02-17 Thread Peter Hutterer
libevdev wraps the various peculiarities of the evdev kernel API into a
type-safe API. It also buffers the device so checking for specific features at
a later time is easier than re-issuing the ioctls. Plus, it gives us almost
free support for SYN_DROPPED events (in the following patch).

This patch switches all the bit checks over to libevdev and leaves the event
processing as-is. Makes it easier to review.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 configure.ac |  7 ++---
 src/Makefile.am  |  2 ++
 src/evdev-touchpad.c | 25 ++-
 src/evdev.c  | 87 +---
 src/evdev.h  | 14 ++---
 5 files changed, 52 insertions(+), 83 deletions(-)

diff --git a/configure.ac b/configure.ac
index 44729a9..68e1d35 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,6 +44,7 @@ AC_CHECK_DECL(CLOCK_MONOTONIC,[],
 PKG_PROG_PKG_CONFIG()
 PKG_CHECK_MODULES(MTDEV, [mtdev = 1.1.0])
 PKG_CHECK_MODULES(LIBUDEV, [libudev])
+PKG_CHECK_MODULES(LIBEVDEV, [libevdev = 0.4])
 
 if test x$GCC = xyes; then
GCC_CFLAGS=-Wall -Wextra -Wno-unused-parameter -g -Wstrict-prototypes 
-Wmissing-prototypes -fvisibility=hidden
@@ -64,20 +65,16 @@ AC_ARG_ENABLE(tests,
  [build_tests=$enableval],
  [build_tests=auto])
 
-PKG_CHECK_MODULES(LIBEVDEV, [libevdev = 0.4], [HAVE_LIBEVDEV=yes], 
[HAVE_LIBEVDEV=no])
 PKG_CHECK_MODULES(CHECK, [check = 0.9.9], [HAVE_CHECK=yes], 
[HAVE_CHECK=no])
 
 if test x$build_tests = xauto; then
-   if test x$HAVE_CHECK = xyes -a x$HAVE_LIBEVDEV = xyes; then
+   if test x$HAVE_CHECK = xyes; then
build_tests=yes
fi
 fi
 if test x$build_tests = xyes -a x$HAVE_CHECK = xno; then
AC_MSG_ERROR([Cannot build tests, check is missing])
 fi
-if test x$build_tests = xyes -a x$HAVE_LIBEVDEV = xno; then
-   AC_MSG_ERROR([Cannot build tests, libevdev is missing])
-fi
 
 AM_CONDITIONAL(BUILD_TESTS, [test x$build_tests = xyes])
 
diff --git a/src/Makefile.am b/src/Makefile.am
index 6e27b3b..f544ccd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -20,9 +20,11 @@ libinput_la_SOURCES =\
 
 libinput_la_LIBADD = $(MTDEV_LIBS) \
 $(LIBUDEV_LIBS) \
+$(LIBEVDEV_LIBS) \
 -lm
 libinput_la_CFLAGS = $(MTDEV_CFLAGS)   \
 $(LIBUDEV_CFLAGS)  \
+$(LIBEVDEV_CFLAGS) \
 $(GCC_CFLAGS)
 
 pkgconfigdir = $(libdir)/pkgconfig
diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c
index d65ebb2..8185bf2 100644
--- a/src/evdev-touchpad.c
+++ b/src/evdev-touchpad.c
@@ -170,16 +170,16 @@ struct touchpad_dispatch {
 static enum touchpad_model
 get_touchpad_model(struct evdev_device *device)
 {
-   struct input_id id;
+   int vendor, product;
unsigned int i;
 
-   if (ioctl(device-fd, EVIOCGID, id)  0)
-   return TOUCHPAD_MODEL_UNKNOWN;
+   vendor = libevdev_get_id_vendor(device-evdev);
+   product = libevdev_get_id_product(device-evdev);
 
for (i = 0; i  ARRAY_LENGTH(touchpad_spec_table); i++)
-   if (touchpad_spec_table[i].vendor == id.vendor 
+   if (touchpad_spec_table[i].vendor == vendor 
(!touchpad_spec_table[i].product ||
-touchpad_spec_table[i].product == id.product))
+touchpad_spec_table[i].product == product))
return touchpad_spec_table[i].model;
 
return TOUCHPAD_MODEL_UNKNOWN;
@@ -730,9 +730,7 @@ touchpad_init(struct touchpad_dispatch *touchpad,
 {
struct motion_filter *accel;
 
-   unsigned long prop_bits[INPUT_PROP_MAX];
-   struct input_absinfo absinfo;
-   unsigned long abs_bits[NBITS(ABS_MAX)];
+   const struct input_absinfo *absinfo;
 
bool has_buttonpad;
 
@@ -746,16 +744,13 @@ 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);
+   has_buttonpad = libevdev_has_property(device-evdev, 
INPUT_PROP_BUTTONPAD);
 
/* Configure pressure */
-   ioctl(device-fd, EVIOCGBIT(EV_ABS, sizeof(abs_bits)), abs_bits);
-   if (TEST_BIT(abs_bits, ABS_PRESSURE)) {
-   ioctl(device-fd, EVIOCGABS(ABS_PRESSURE), absinfo);
+   if ((absinfo = libevdev_get_abs_info(device-evdev, ABS_PRESSURE))) {
configure_touchpad_pressure(touchpad,
-   absinfo.minimum,
-   absinfo.maximum);
+   absinfo-minimum,
+   absinfo-maximum);
}
 
/* Configure acceleration factor */
diff --git a/src/evdev.c b/src/evdev.c
index d8dff65..ba28fc6 100644

[PATCH libinput] evdev: set CLOCK_MONOTONIC as the time source

2014-02-18 Thread Peter Hutterer
Avoids erroneous timestamps when the system time is reset. This used to a be a
problem with the X.Org synaptics driver where taps, scrolling and a couple of
other things would potentially lock up.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/evdev.c b/src/evdev.c
index 2c88c04..ab5a0c9 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -31,6 +31,7 @@
 #include fcntl.h
 #include mtdev-plumbing.h
 #include assert.h
+#include time.h
 
 #include libinput.h
 #include evdev.h
@@ -639,6 +640,8 @@ evdev_device_create(struct libinput_seat *seat,
if (rc != 0)
return NULL;
 
+   libevdev_set_clock_id(device-evdev, CLOCK_MONOTONIC);
+
device-seat_caps = 0;
device-is_mt = 0;
device-mtdev = NULL;
-- 
1.8.4.2

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [RFC] libinput configuration interface

2014-02-18 Thread Peter Hutterer
On Tue, Feb 18, 2014 at 04:33:53PM +, Dominic Jänichen wrote:
 On Mon, 03 Feb 2014 11:02:42 +1000, Peter Hutterer wrote:
  
  tbh, I'm not planning to support every potential option under the sun.
  There's a fine and rather blurry line between what is a preference and
  what is merely configuration because we can't commit to a single
  default. I'd rather have less configuration options and support those
  well and do the synaptics approach of supporting everything but being
  quite bad at how the various options interact.
 
 snip 
  
  As for the softbuttons config items, I'm somewhat leaning towards finger
  movement in the button areas, but no clicks outside the button area. And
  to actually trigger a button, you need to start inside the button area -
  which becomes easier when you have proper finger tracking (synaptics
  currently doesn't). 
 
 Does that imply the following use case will be supported?
 
 Being used to TP trackpoints, I am using the index finger outside the 
 button area (on a touchpad that doubles as one hardware button) and the 
 thumb to click.
 I'd expect to able to move the pointer with the index finger while 
 clicking, disregarding slight thumb movements while doing so.
 
 
 This seems to very difficult to archieve (if at all) with the synaptics 
 driver; the points jumps widely, especially if the index finger is 
 removed from the touch pad immediately before clicking.
 
 I can imagine that this boils down to having areas insensitive to motion, 
 but still working as softbuttons.

The set of touchpad patches I sent out recently already handle this by
default. When the physical clickpad button is depressed, the driver picks
the finger that is pressing the button (sometimes guessing, but hey...).
That finger cannot control the pointer movement until the button is released
again.

In your specific use case, the driver would see two touchpoints and it will
select the one closer to the bottom edge as the pressing finger (i.e. your
thumb). The index finger can still move while the button is down.

Cheers,
   Peter
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 2/2] test: Add scale li_fixed overflow test

2014-02-18 Thread Peter Hutterer
On Tue, Feb 18, 2014 at 08:13:58PM +0100, Jonas Ådahl wrote:
 Add a test case and test device that checks if the scale transform can
 handle high resolution devices and output monitor resolutions.
 
 The test case is created in a way that it will fail if the coordinate
 transform expression will overflow if only 32 bit integer data
 containers are used.
 
 Signed-off-by: Jonas Ådahl jad...@gmail.com
 ---
 
  fwiw, this is exactly the type of use-case where it would be simple and
  worth it to knock up a test for a single device and make sure that the
  coordinates are correct. which gives us a nice reproducer and prevents us
  from errors like this in the future.
 
 And here is such a test case. It will fail as is, but pass if either the
 expression uses 64 bit integers or doubles.
 
 
 Jonas
 
 
  test/Makefile.am|   1 +
  test/litest-generic-highres-touch.c | 139 
 
  test/litest.c   |   2 +
  test/litest.h   |   1 +
  test/touch.c|  40 ++-
  5 files changed, 182 insertions(+), 1 deletion(-)
  create mode 100644 test/litest-generic-highres-touch.c
 
 diff --git a/test/Makefile.am b/test/Makefile.am
 index 59687f6..4b923aa 100644
 --- a/test/Makefile.am
 +++ b/test/Makefile.am
 @@ -14,6 +14,7 @@ liblitest_la_SOURCES = \
   litest-synaptics.c \
   litest-trackpoint.c \
   litest-wacom-touch.c \
 + litest-generic-highres-touch.c \
   litest.c
  
  run_tests = test-udev test-path test-pointer test-touch
 diff --git a/test/litest-generic-highres-touch.c 
 b/test/litest-generic-highres-touch.c
 new file mode 100644
 index 000..bd326ce
 --- /dev/null
 +++ b/test/litest-generic-highres-touch.c
 @@ -0,0 +1,139 @@
 +/*
 + * Copyright © 2013 Red Hat, Inc.
 + * Copyright © 2014 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 litest.h
 +#include litest-int.h
 +#include libinput-util.h
 +
 +void litest_generic_highres_touch_setup(void)
 +{
 + struct litest_device *d =
 + litest_create_device(LITEST_GENERIC_HIGHRES_TOUCH);
 + litest_set_current_device(d);
 +}
 +
 +void
 +litest_generic_highres_touch_touch_down(struct litest_device *d,
 + unsigned int slot,
 + int x, int y)
 +{
 + static int tracking_id;
 + struct input_event *ev;
 + struct input_event down[] = {
 + { .type = EV_ABS, .code = ABS_X, .value = x  },
 + { .type = EV_ABS, .code = ABS_Y, .value = y },
 + { .type = EV_ABS, .code = ABS_MT_SLOT, .value = slot },
 + { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = 
 ++tracking_id },
 + { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = x },
 + { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = y },
 + { .type = EV_KEY, .code = BTN_TOUCH, .value = 1 },
 + { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
 + };
 +
 + down[0].value = litest_scale(d, ABS_X, x);
 + down[1].value = litest_scale(d, ABS_Y, y);
 + down[4].value = litest_scale(d, ABS_X, x);
 + down[5].value = litest_scale(d, ABS_Y, y);
 +
 + ARRAY_FOR_EACH(down, ev)
 + litest_event(d, ev-type, ev-code, ev-value);
 +}
 +
 +void
 +litest_generic_highres_touch_move(struct litest_device *d,
 +   unsigned int slot,
 +   int x, int y)
 +{
 + struct input_event *ev;
 + struct input_event move[] = {
 + { .type = EV_ABS, .code = ABS_MT_SLOT, .value = slot },
 + { .type = EV_ABS, .code = ABS_X, .value = x  },
 + { .type = EV_ABS, .code = ABS_Y, .value = y },
 + { .type = EV_ABS, 

Re: [PATCH libinput] evdev: set CLOCK_MONOTONIC as the time source

2014-02-19 Thread Peter Hutterer
On Wed, Feb 19, 2014 at 07:19:15PM +0100, Rui Tiago Cação Matos wrote:
 On 19 February 2014 13:35, Daniel Stone dan...@fooishbar.org wrote:
  Can this be CLOCK_MONOTONIC_COARSE instead, to avoid griefing HPET and
  thus causing much higher power usage?
 
 Makes sense and indeed the X server seems to use _COARSE if it's
 available and has good enough resolution:
 
 http://cgit.freedesktop.org/xorg/xserver/tree/os/utils.c#n440
 
 Perhaps libevdev should do something like that too?

Note that this doesn't affect clock_gettime like the server's code does, it
only affects the timestamps of the events as reported by the kernel. It's a
wrapper around the EVIOCSCLOCKID ioctl and that only allows for
CLOCK_MONOTONIC and CLOCK_REALTIME (as of 3.14-rc3). So using _COARSE here
would merely yield -EINVAL.

Cheers,
   Peter

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput] evdev: set CLOCK_MONOTONIC as the time source

2014-02-19 Thread Peter Hutterer
On Tue, Feb 18, 2014 at 07:44:54PM -0800, Thiago Macieira wrote:
 Em ter 18 fev 2014, às 22:33:26, Jasper St. Pierre escreveu:
  ... and what if it fails? I'd say that requiring CLOCK_MONOTONIC is fine.
  
  Are there any popular Linux setups that don't have CLOCK_MONOTONIC?
 
 I'm guessing that some weird and niche embedded boards might not support it. 
 Which is a use-case for libinput.
 
 However, I'm guessing that it's ok to let the ioctl fail. No need to check if 
 it will fail, simply let it.

if the ioctl fails the time reported will be in CLOCK_REALTIME, which is the
default. So aside from optionally printing an error there isn't much of a
recovery path anyway, I don't think failing to set the clock id is a fatal
condition for a device.

Cheers,
   Peter
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 1/2] Add seat wide slot to touch events

2014-02-19 Thread Peter Hutterer
On Wed, Feb 19, 2014 at 10:04:10PM +0100, Jonas Ådahl wrote:
 Since a Wayland compositor have to represent all touch devices of a seat
 as one virtual device, lets make that easier by also providing seat wide
 slots with touch events.
 
 Seat wide slots may be accessed using
 libinput_event_touch_get_seat_slot().
 
 Signed-off-by: Jonas Ådahl jad...@gmail.com
 ---
  src/evdev.c| 24 
  src/evdev.h|  3 +++
  src/libinput-private.h |  2 ++
  src/libinput.c |  9 +
  src/libinput.h | 16 
  tools/event-debug.c|  3 ++-
  6 files changed, 56 insertions(+), 1 deletion(-)
 
 diff --git a/src/evdev.c b/src/evdev.c
 index d2cdbaf..2b7070a 100644
 --- a/src/evdev.c
 +++ b/src/evdev.c
 @@ -111,7 +111,9 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
  {
   int32_t cx, cy;
   int slot;
 + uint32_t seat_slot;
   struct libinput_device *base = device-base;
 + struct libinput_seat *seat = base-seat;
  
   slot = device-mt.slot;
  
 @@ -130,9 +132,14 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + seat_slot = ffs(~seat-slot_map) - 1;

funny, had a bit of a deja-vu here :)
see 
http://lists.freedesktop.org/archives/wayland-devel/2014-February/013238.html
for my comments, both still apply.

Cheers,
   Peter


 + device-mt.slots[slot].seat_slot = seat_slot;
 + seat-slot_map |= 1  seat_slot;
 +
   touch_notify_touch(base,
  time,
  slot,
 +seat_slot,
  li_fixed_from_int(device-mt.slots[slot].x),
  li_fixed_from_int(device-mt.slots[slot].y),
  LIBINPUT_TOUCH_TYPE_DOWN);
 @@ -141,9 +148,12 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + seat_slot = device-mt.slots[slot].seat_slot;
 +
   touch_notify_touch(base,
  time,
  slot,
 +seat_slot,
  li_fixed_from_int(device-mt.slots[slot].x),
  li_fixed_from_int(device-mt.slots[slot].y),
  LIBINPUT_TOUCH_TYPE_MOTION);
 @@ -152,9 +162,13 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + seat_slot = device-mt.slots[slot].seat_slot;
 + seat-slot_map = ~(1  seat_slot);
 +
   touch_notify_touch(base,
  time,
  slot,
 +seat_slot,
  0, 0,
  LIBINPUT_TOUCH_TYPE_UP);
   break;
 @@ -162,10 +176,15 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + seat_slot = ffs(~seat-slot_map) - 1;
 + device-abs.seat_slot = seat_slot;
 + seat-slot_map |= 1  seat_slot;
 +
   transform_absolute(device, cx, cy);
   touch_notify_touch(base,
  time,
  -1,
 +seat_slot,
  li_fixed_from_int(cx),
  li_fixed_from_int(cy),
  LIBINPUT_TOUCH_TYPE_DOWN);
 @@ -176,6 +195,7 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   touch_notify_touch(base,
  time,
  -1,
 +device-abs.seat_slot,
  li_fixed_from_int(cx),
  li_fixed_from_int(cy),
  LIBINPUT_TOUCH_TYPE_DOWN);
 @@ -190,9 +210,13 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + seat_slot = device-abs.seat_slot;
 + seat-slot_map = ~(1  seat_slot);
 +
   touch_notify_touch(base,
  time,
  -1,
 +seat_slot,
  0, 0,
  LIBINPUT_TOUCH_TYPE_UP);
   break;
 diff 

Re: [RFC] libinput configuration interface

2014-02-19 Thread Peter Hutterer
On Wed, Feb 19, 2014 at 11:55:28AM +0600, Alexander E. Patrakov wrote:
 19.02.2014 04:52, Peter Hutterer wrote:
 The set of touchpad patches I sent out recently already handle this by
 default. When the physical clickpad button is depressed, the driver picks
 the finger that is pressing the button (sometimes guessing, but hey...).
 That finger cannot control the pointer movement until the button is released
 again.
 
 In your specific use case, the driver would see two touchpoints and it will
 select the one closer to the bottom edge as the pressing finger (i.e. your
 thumb). The index finger can still move while the button is down.
 
 From my experience with the Sony touchpad (Vaio Z23A4R laptop), I'd
 say that it doesn't solve the whole problem. Here is what goes wrong
 with the old synaptics driver by default and can be worked around
 with AreaBottomEdge.
 
 Option SoftButtonAreas 4360 0 4000 0 2880 4359 3500 0
 Option AreaBottomEdge 3500
 
 1. I move the right-hand index finger on the touchpad, thus moving
 the pointer to the place where I want to click.
 
 2. I place the left-hand index finger into the virtual-button area,
 while still keeping the right finger on the touchpad. I cannot
 remove the right-hand finger: if I do that, while the contact area
 shrinks, its center also moves, and the driver picks that up.

 3. As I increase the pressure on the left-hand finger until the
 touchpad clicks, the contact area increases. Unfortunately, its
 center moves, too, and this can accumulate to ~2-3 pixels until it
 clicks.
 
 The important point is that the bad thing happens before the
 hardware button click, so the quoted solution totally misses the
 point.
 
 So we need something, either a sledgehammer solution in the form of
 ignoring all motion in the virtual button area (but that would break
 Sony Vaio Duo 13 because the only usable height of the virtual
 button area is 100% there), or some very good filter that pays

can you expand on the 100% comment here? is the touchpad too small for
anything else?

 attention to changes in pressure and filters any spurious movement
 (i.e. any movement that is combined with significant pressure
 changes) out.
 
 But hey, Sony in their new laptops started to ignore the problem
 under Windows, too, so I think I just have to swallow this and/or
 use my Bluetooth mouse.

couple of comments here:
2 is a synaptics bug that should really be fixed, the driver shouldn't be
that sensible - in fact there's probably something that can be done about
making the driver more sensible while the finger is moving and less sensible
while the finger is still (just an idea, may not work for small
movements). there is also the option of using pressure to counteract
movements, i.e. a pressure change will increase the hysteresis to avoid
erroneous movements. If you have that many issues with the Sony, I really
recommend looking at the evdev-mt-touchpad patches I sent to this list,
it'll allow for things like that relatively simple.
the xorg synaptics driver has for historical reasons and portability a
different approach to finger tracking and some of the misbehaviours are
easier to fix now.

The proposed patches have a different approach to the above:
1 - would be recognised as touchpoint, since no other finger is active it is
designated as the pointer-moving touchpoint
2 - second finger recognised, but not assigned as pointer-moving. Movements
on that finger have no effect, unless 2-finger scrolling is triggered.
3 - no effect, finger is not moving

So really, the goal here is that whatever the motion we see in 2 and 3 is to
not go past the trigger 2-finger scrolling threshold.

I do have a set of patches not yet ported for the virtual buttons and they
add additional tracking, so that a finger that starts (and stays) inside a
softbutton area won't contribute to movements, but as you said above that
may not work with the vaio.

Cheers,
   Peter
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [RFC] libinput configuration interface

2014-02-19 Thread Peter Hutterer
On Thu, Feb 20, 2014 at 12:21:53PM +0600, Alexander E. Patrakov wrote:
 20.02.2014 11:14, Peter Hutterer wrote:
 On Wed, Feb 19, 2014 at 11:55:28AM +0600, Alexander E. Patrakov wrote:
 19.02.2014 04:52, Peter Hutterer wrote:
 The set of touchpad patches I sent out recently already handle this by
 default. When the physical clickpad button is depressed, the driver picks
 the finger that is pressing the button (sometimes guessing, but hey...).
 That finger cannot control the pointer movement until the button is 
 released
 again.
 
 In your specific use case, the driver would see two touchpoints and it will
 select the one closer to the bottom edge as the pressing finger (i.e. your
 thumb). The index finger can still move while the button is down.
 
  From my experience with the Sony touchpad (Vaio Z23A4R laptop), I'd
 say that it doesn't solve the whole problem. Here is what goes wrong
 with the old synaptics driver by default and can be worked around
 with AreaBottomEdge.
 
  Option SoftButtonAreas 4360 0 4000 0 2880 4359 3500 0
  Option AreaBottomEdge 3500
 
 1. I move the right-hand index finger on the touchpad, thus moving
 the pointer to the place where I want to click.
 
 2. I place the left-hand index finger into the virtual-button area,
 while still keeping the right finger on the touchpad. I cannot
 remove the right-hand finger: if I do that, while the contact area
 shrinks, its center also moves, and the driver picks that up.
 
 3. As I increase the pressure on the left-hand finger until the
 touchpad clicks, the contact area increases. Unfortunately, its
 center moves, too, and this can accumulate to ~2-3 pixels until it
 clicks.
 
 The important point is that the bad thing happens before the
 hardware button click, so the quoted solution totally misses the
 point.
 
 So we need something, either a sledgehammer solution in the form of
 ignoring all motion in the virtual button area (but that would break
 Sony Vaio Duo 13 because the only usable height of the virtual
 button area is 100% there), or some very good filter that pays
 
 can you expand on the 100% comment here? is the touchpad too small for
 anything else?
 
 The height of the touchpad is too small (the width is OK). See e.g. 
 http://www.blogcdn.com/www.engadget.com/media/2013/06/dsc00149-1370365891.jpg
 
 (Just to avoid confusion: I have a Sony Vaio Z23A4R, don't have a
 Sony Vaio Duo 13, and don't have a Sony Vaio Pro 13. As for my
 accent on Sony laptops, that's only because there is a Sony shop
 nearby.)

quite frankly, I think this touchpad is one where you (the user) would have
to get used to tap-and-drag and two-finger tapping or two-finger clicking
instead virtual button areas. I think that'd be a much better fit for a
touchpad like this.

Cheers,
   Peter

 attention to changes in pressure and filters any spurious movement
 (i.e. any movement that is combined with significant pressure
 changes) out.
 
 But hey, Sony in their new laptops started to ignore the problem
 under Windows, too, so I think I just have to swallow this and/or
 use my Bluetooth mouse.
 
 couple of comments here:
 2 is a synaptics bug that should really be fixed, the driver shouldn't be
 that sensible - in fact there's probably something that can be done about
 making the driver more sensible while the finger is moving and less sensible
 while the finger is still (just an idea, may not work for small
 movements). there is also the option of using pressure to counteract
 movements, i.e. a pressure change will increase the hysteresis to avoid
 erroneous movements. If you have that many issues with the Sony, I really
 recommend looking at the evdev-mt-touchpad patches I sent to this list,
 it'll allow for things like that relatively simple.
 
 OK, I will build this on my laptop from git later today.
 
 the xorg synaptics driver has for historical reasons and portability a
 different approach to finger tracking and some of the misbehaviours are
 easier to fix now.
 
 The proposed patches have a different approach to the above:
 1 - would be recognised as touchpoint, since no other finger is active it is
 designated as the pointer-moving touchpoint
 2 - second finger recognised, but not assigned as pointer-moving. Movements
 on that finger have no effect, unless 2-finger scrolling is triggered.
 3 - no effect, finger is not moving
 
 So really, the goal here is that whatever the motion we see in 2 and 3 is to
 not go past the trigger 2-finger scrolling threshold.
 
 Yes, I think we agree on that.
 
 I do have a set of patches not yet ported for the virtual buttons and they
 add additional tracking, so that a finger that starts (and stays) inside a
 softbutton area won't contribute to movements, but as you said above that
 may not work with the vaio.
 
 Yes, I would like to see that on my Z23A4R (and it matches the
 Windows default), but users of Duo 13 definitely would not want that
 enabled on their laptops. As for Sony Vaio Pro 13

Re: [PATCH libinput 1/2] Add seat wide slot to touch events

2014-02-19 Thread Peter Hutterer
On Thu, Feb 20, 2014 at 08:39:08AM +0100, Jonas Ådahl wrote:
 On Thu, Feb 20, 2014 at 02:53:18PM +1000, Peter Hutterer wrote:
  On Wed, Feb 19, 2014 at 10:04:10PM +0100, Jonas Ådahl wrote:
   Since a Wayland compositor have to represent all touch devices of a seat
   as one virtual device, lets make that easier by also providing seat wide
   slots with touch events.
   
   Seat wide slots may be accessed using
   libinput_event_touch_get_seat_slot().
   
   Signed-off-by: Jonas Ådahl jad...@gmail.com
   ---
src/evdev.c| 24 
src/evdev.h|  3 +++
src/libinput-private.h |  2 ++
src/libinput.c |  9 +
src/libinput.h | 16 
tools/event-debug.c|  3 ++-
6 files changed, 56 insertions(+), 1 deletion(-)
   
   diff --git a/src/evdev.c b/src/evdev.c
   index d2cdbaf..2b7070a 100644
   --- a/src/evdev.c
   +++ b/src/evdev.c
   @@ -111,7 +111,9 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
{
 int32_t cx, cy;
 int slot;
   + uint32_t seat_slot;
 struct libinput_device *base = device-base;
   + struct libinput_seat *seat = base-seat;

 slot = device-mt.slot;

   @@ -130,9 +132,14 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
 break;

   + seat_slot = ffs(~seat-slot_map) - 1;
  
  funny, had a bit of a deja-vu here :)
  see 
  http://lists.freedesktop.org/archives/wayland-devel/2014-February/013238.html
  for my comments, both still apply.
 
 Hmm :)
 
  ... 32 touch points ...
 
 Oops, seems I stashed away that part together with the unfinished test case.
 
  ... seat_slot is never -1, ...
 
 This I did address without stashing away though.

oh, right, non-negative, I read over that searching for something that
explicitly uses -1...

Cheers,
   Peter

  
  Cheers,
 Peter
  
  
   + device-mt.slots[slot].seat_slot = seat_slot;
   + seat-slot_map |= 1  seat_slot;
   +
 touch_notify_touch(base,
time,
slot,
   +seat_slot,
li_fixed_from_int(device-mt.slots[slot].x),
li_fixed_from_int(device-mt.slots[slot].y),
LIBINPUT_TOUCH_TYPE_DOWN);
   @@ -141,9 +148,12 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
 break;

   + seat_slot = device-mt.slots[slot].seat_slot;
   +
 touch_notify_touch(base,
time,
slot,
   +seat_slot,
li_fixed_from_int(device-mt.slots[slot].x),
li_fixed_from_int(device-mt.slots[slot].y),
LIBINPUT_TOUCH_TYPE_MOTION);
   @@ -152,9 +162,13 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
 break;

   + seat_slot = device-mt.slots[slot].seat_slot;
   + seat-slot_map = ~(1  seat_slot);
   +
 touch_notify_touch(base,
time,
slot,
   +seat_slot,
0, 0,
LIBINPUT_TOUCH_TYPE_UP);
 break;
   @@ -162,10 +176,15 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
 break;

   + seat_slot = ffs(~seat-slot_map) - 1;
   + device-abs.seat_slot = seat_slot;
   + seat-slot_map |= 1  seat_slot;
   +
 transform_absolute(device, cx, cy);
 touch_notify_touch(base,
time,
-1,
   +seat_slot,
li_fixed_from_int(cx),
li_fixed_from_int(cy),
LIBINPUT_TOUCH_TYPE_DOWN);
   @@ -176,6 +195,7 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 touch_notify_touch(base,
time,
-1,
   +device-abs.seat_slot,
li_fixed_from_int(cx),
li_fixed_from_int(cy),
LIBINPUT_TOUCH_TYPE_DOWN);
   @@ -190,9 +210,13 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (!(device-seat_caps

Re: [RFC] libinput configuration interface

2014-02-20 Thread Peter Hutterer
On Fri, Feb 21, 2014 at 01:29:05AM +0600, Alexander E. Patrakov wrote:
 20.02.2014 12:21, I wrote:
 20.02.2014 11:14, Peter Hutterer wrote:
 On Wed, Feb 19, 2014 at 11:55:28AM +0600, Alexander E. Patrakov wrote:
  From my experience with the Sony touchpad (Vaio Z23A4R laptop), I'd
 say that it doesn't solve the whole problem. Here is what goes wrong
 with the old synaptics driver by default and can be worked around
 with AreaBottomEdge.
 
  Option SoftButtonAreas 4360 0 4000 0 2880 4359 3500 0
  Option AreaBottomEdge 3500
 
 1. I move the right-hand index finger on the touchpad, thus moving
 the pointer to the place where I want to click.
 
 2. I place the left-hand index finger into the virtual-button area,
 while still keeping the right finger on the touchpad. I cannot
 remove the right-hand finger: if I do that, while the contact area
 shrinks, its center also moves, and the driver picks that up.
 
 3. As I increase the pressure on the left-hand finger until the
 touchpad clicks, the contact area increases. Unfortunately, its
 center moves, too, and this can accumulate to ~2-3 pixels until it
 clicks.
 
 The important point is that the bad thing happens before the
 hardware button click, so the quoted solution totally misses the
 point.
 
 So we need something, either a sledgehammer solution in the form of
 ignoring all motion in the virtual button area (but that would break
 Sony Vaio Duo 13 because the only usable height of the virtual
 button area is 100% there), or some very good filter that pays
 
 couple of comments here:
 2 is a synaptics bug that should really be fixed, the driver shouldn't be
 that sensible - in fact there's probably something that can be done about
 making the driver more sensible while the finger is moving and less
 sensible
 while the finger is still (just an idea, may not work for small
 movements). there is also the option of using pressure to counteract
 movements, i.e. a pressure change will increase the hysteresis to avoid
 erroneous movements. If you have that many issues with the Sony, I really
 recommend looking at the evdev-mt-touchpad patches I sent to this list,
 it'll allow for things like that relatively simple.
 
 OK, I will build this on my laptop from git later today.
 
 Just did this, but have not looked at the code yet. Tested with
 xf86-input-libinput, thus had no chance to configure anything
 specific to libinput. If this has any chance of yielding different
 results, I will retest with Weston on Saturday.

libinput currently exposes no configuration interfaces, so the only
differences you may see is in pointer acceleration.

 Software versions:
 
  * mtdev 1.1.4 (Gentoo)
  * xorg-server 1.15.0 (Gentoo)
  * libevdev from git, cf70d0
  * libinput from git, 128f98 + your 19 patches
  * xf86-input-libinput from git, 761603
 
 Hardware: Sony VAIO Z23A4R, the touchpad identifies itself as follows:
 
 I: Bus=0011 Vendor=0002 Product=0007 Version=01b1
 N: Name=SynPS/2 Synaptics TouchPad
 P: Phys=isa0060/serio1/input0
 S: Sysfs=/devices/platform/i8042/serio1/input/input4
 U: Uniq=
 H: Handlers=mouse0 event3
 B: PROP=5
 B: EV=b
 B: KEY=e520 1 0 0 0 0
 B: ABS=66080001103
 
 Pointer movement works, but it is too slow by default on this
 laptop. That is, a VERY quick swipe (not expected during normal work
 and even during games) from left to right is just enough to move the
 pointer across the entire screen (1920x1080). Setting constant
 deceleration to 0.3 or 0.4 makes it more usable in terms of speed,
 but this might be my personal preference, and I am not sure if the
 constant deceleration is the correct knob here.

I have not yet looked into pointer-accel fine-tuning on the touchpad or in
xf86-input-libinput. What you're seeing is quite simliar to what I have here
- it's slow but not unusable. Sorry, just haven't focused on that yet by any
help would be appreciated.

I don't think deceleration is the right nob here, but I can't remember what
you need to tweak. Generally I try not to touch constant deceleration unless
the device is a high-resolution device that sends way too many events. If
you need to use a value 0..1 for CD then you're effectively using it to
speed things up, the term deceleration should hint that this may not work
perfectly :)

 With the default constant deceleration (1.0), pointer movement is
 very precise. It follows the finger equally well in all parts of the
 touchpad and in all directions, as expected. I get no misplaced
 clicks.
 
 With constant deceleration 0.3, this is not true. It works better in
 the central part of the touchpad, but, when crossing the physical
 border between the area for pointer movement (which is rough) and
 the area for virtual buttons (which is smooth), it starts to behave
 like a dirty mechanical mouse. Here is what I mean by that: hard to
 move the cursor diagonally (i.e. there is a strong preference
 towards horizontal or vertical movements), and the motion is uneven
 if I move

Re: [PATCH libinput 1/2] Hook up libevdev as backend

2014-02-23 Thread Peter Hutterer
On Sat, Feb 22, 2014 at 03:51:57PM +0100, Jonas Ådahl wrote:
 On Tue, Feb 18, 2014 at 04:09:09PM +1000, Peter Hutterer wrote:
  libevdev wraps the various peculiarities of the evdev kernel API into a
  type-safe API. It also buffers the device so checking for specific features 
  at
  a later time is easier than re-issuing the ioctls. Plus, it gives us almost
  free support for SYN_DROPPED events (in the following patch).
  
  This patch switches all the bit checks over to libevdev and leaves the event
  processing as-is. Makes it easier to review.
  
  Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
 
 Looks good to me as well, with one comment inline.
 
 Reviewed-by: Jonas Ådahl jad...@gmail.com

..

  @@ -624,6 +607,10 @@ evdev_device_create(struct libinput_seat *seat,
   
  libinput_device_init(device-base, seat);
   
  +   rc = libevdev_new_from_fd(fd, device-evdev);
  +   if (rc != 0)
  +   return NULL;
  +
  device-seat_caps = 0;
  device-is_mt = 0;
  device-mtdev = NULL;
  @@ -635,10 +622,7 @@ evdev_device_create(struct libinput_seat *seat,
  device-dispatch = NULL;
  device-fd = fd;
  device-pending_event = EVDEV_NONE;
  -
  -   ioctl(device-fd, EVIOCGNAME(sizeof(devname)), devname);
  -   devname[sizeof(devname) - 1] = '\0';
  -   device-devname = strdup(devname);
  +   device-devname = libevdev_get_name(device-evdev);
 
 This makes the assumption that the const char * returned by
 libevdev_get_name() is valid until we destroy the device. Is this
 guaranteed anywhere by libevdev?

It's guaranteed by the kernel. There is no facility to set the name through
the API and there is no facility to notify the caller if the name would
change. so libevdev (which has a copy, obviuosly) wouldn't know that it
changed. libevdev_change_fd() doesn't re-sync the name, so yes, this name
is constant.

Cheers,
   Peter

 
   
  libinput_seat_ref(seat);
   
  @@ -742,8 +726,7 @@ evdev_device_destroy(struct evdev_device *device)
  dispatch-interface-destroy(dispatch);
   
  libinput_seat_unref(device-base.seat);
  -
  -   free(device-devname);
  +   libevdev_free(device-evdev);
  free(device-devnode);
  free(device-sysname);
  free(device);
  diff --git a/src/evdev.h b/src/evdev.h
  index 3c9f93a..a9e27bf 100644
  --- a/src/evdev.h
  +++ b/src/evdev.h
  @@ -27,6 +27,7 @@
   #include config.h
   
   #include linux/input.h
  +#include libevdev/libevdev.h
   
   #include libinput-private.h
   
  @@ -55,10 +56,11 @@ struct evdev_device {
  struct libinput_source *source;
   
  struct evdev_dispatch *dispatch;
  +   struct libevdev *evdev;
  char *output_name;
  char *devnode;
  char *sysname;
  -   char *devname;
  +   const char *devname;
  int fd;
  struct {
  int min_x, max_x, min_y, max_y;
  @@ -86,16 +88,6 @@ struct evdev_device {
  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)  (1ULOFF(x))
  -#define LONG(x) ((x)/BITS_PER_LONG)
  -#define TEST_BIT(array, bit)((array[LONG(bit)]  OFF(bit))  1)
  -/* end copied */
  -
   #define EVDEV_UNHANDLED_DEVICE ((struct evdev_device *) 1)
   
   struct evdev_dispatch;
  -- 
  1.8.4.2
  
  ___
  wayland-devel mailing list
  wayland-devel@lists.freedesktop.org
  http://lists.freedesktop.org/mailman/listinfo/wayland-devel
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 1/2] Hook up libevdev as backend

2014-02-23 Thread Peter Hutterer
On Mon, Feb 24, 2014 at 09:28:49AM +1000, Peter Hutterer wrote:
 On Sat, Feb 22, 2014 at 03:51:57PM +0100, Jonas Ådahl wrote:
  On Tue, Feb 18, 2014 at 04:09:09PM +1000, Peter Hutterer wrote:
   libevdev wraps the various peculiarities of the evdev kernel API into a
   type-safe API. It also buffers the device so checking for specific 
   features at
   a later time is easier than re-issuing the ioctls. Plus, it gives us 
   almost
   free support for SYN_DROPPED events (in the following patch).
   
   This patch switches all the bit checks over to libevdev and leaves the 
   event
   processing as-is. Makes it easier to review.
   
   Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
  
  Looks good to me as well, with one comment inline.
  
  Reviewed-by: Jonas Ådahl jad...@gmail.com
 
 ...
 
   @@ -624,6 +607,10 @@ evdev_device_create(struct libinput_seat *seat,

 libinput_device_init(device-base, seat);

   + rc = libevdev_new_from_fd(fd, device-evdev);
   + if (rc != 0)
   + return NULL;
   +
 device-seat_caps = 0;
 device-is_mt = 0;
 device-mtdev = NULL;
   @@ -635,10 +622,7 @@ evdev_device_create(struct libinput_seat *seat,
 device-dispatch = NULL;
 device-fd = fd;
 device-pending_event = EVDEV_NONE;
   -
   - ioctl(device-fd, EVIOCGNAME(sizeof(devname)), devname);
   - devname[sizeof(devname) - 1] = '\0';
   - device-devname = strdup(devname);
   + device-devname = libevdev_get_name(device-evdev);
  
  This makes the assumption that the const char * returned by
  libevdev_get_name() is valid until we destroy the device. Is this
  guaranteed anywhere by libevdev?
 
 It's guaranteed by the kernel. There is no facility to set the name through
 the API and there is no facility to notify the caller if the name would
 change. so libevdev (which has a copy, obviuosly) wouldn't know that it
 changed. libevdev_change_fd() doesn't re-sync the name, so yes, this name
 is constant.
 
I should've been more precise here: there is no facility to set the name
through the _kernel_ API. libevdev enables a caller to change the name (and
thus free the string) though I'm strongly inclined to say that's a
caller problem that we don't need to worry about.

I'll add some extra notes to the libevdev documentation here.

Cheers,
   Peter
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput] test: Add seat slot tests

2014-02-23 Thread Peter Hutterer
On Sat, Feb 22, 2014 at 03:38:28PM +0100, Jonas Ådahl wrote:
 Add one test that checks uniqueness of seat slots when having multiple
 devices with active touch points.
 
 Add one test that checks that libinput drops touch points when it could
 not represent them with a seat wide slot.
 
 This commit also adds support for from a test case add test devices to
 an existing libinput context. Only litest-wacom-touch supports this so
 far.
 
 Signed-off-by: Jonas Ådahl jad...@gmail.com
 ---
 
 Needs to be applied after 'Split up the touch event into the different
 touch types'.
 
  test/litest-wacom-touch.c |  24 ++-
  test/litest.c |  30 -
  test/litest.h |  13 +++-
  test/touch.c  | 156 
 ++
  4 files changed, 217 insertions(+), 6 deletions(-)
 
 diff --git a/test/litest-wacom-touch.c b/test/litest-wacom-touch.c
 index 464d541..a6c22ef 100644
 --- a/test/litest-wacom-touch.c
 +++ b/test/litest-wacom-touch.c
 @@ -24,11 +24,22 @@
  #include config.h
  #endif
  
 +#include stdio.h
 +
  #include litest.h
  #include litest-int.h
  #include libinput-util.h
  
 -void litest_wacom_touch_setup(void)
 +static int device_ids = 0;
 +
 +static void
 +litest_wacom_touch_destroy(struct litest_device *dev)
 +{
 + device_ids = ~dev-device_id;
 +}
 +
 +void
 +litest_wacom_touch_setup(void)
  {
   struct litest_device *d = litest_create_device(LITEST_WACOM_TOUCH);
   litest_set_current_device(d);
 @@ -104,14 +115,23 @@ litest_create_wacom_touch(struct litest_device *d)
   { ABS_MT_TRACKING_ID, 0, 65535, 0 },
   };
   struct input_absinfo *a;
 + char name[256];
 + int device_id;
   int rc;
  
   d-interface = interface;
 + d-destroy = litest_wacom_touch_destroy;
  
   dev = libevdev_new();
   ck_assert(dev != NULL);
  
 - libevdev_set_name(dev, Wacom ISDv4 E6 Finger);
 + device_id = ffs(~device_ids) - 1;
 + ck_assert_int_ge(device_id, 0);
 + device_ids |= 1  device_id;
 + d-device_id = device_id;
 + snprintf(name, sizeof name, Wacom ISDv4 E6 Finger (%d), device_id);
 + libevdev_set_name(dev, name);
 +

IMO the actual devices should stay as close to the real thing as possible.
That leaves us, for this test, with two options: put a 1.5s sleep in to
avoid the uinput duplicate issue, or push this code into the generic touch
device that you created for the scaling overflow issue. with that we have
more freedom of messing around with the device name.


   libevdev_set_id_bustype(dev, 0x3);
   libevdev_set_id_vendor(dev, 0x56a);
   libevdev_set_id_product(dev, 0xe6);
 diff --git a/test/litest.c b/test/litest.c
 index 78a0472..e69f354 100644
 --- a/test/litest.c
 +++ b/test/litest.c
 @@ -325,8 +325,15 @@ const struct libinput_interface interface = {
   .close_restricted = close_restricted,
  };
  
 +const struct libinput_interface *
 +litest_get_libinput_interface()
 +{
 + return interface;
 +}
 +
  struct litest_device *
 -litest_create_device(enum litest_device_type which)
 +litest_create_device_for(struct libinput *libinput,
 +  enum litest_device_type which)
  {
   struct litest_device *d = zalloc(sizeof(*d));
   int fd;
 @@ -358,7 +365,7 @@ litest_create_device(enum litest_device_type which)
   rc = libevdev_new_from_fd(fd, d-evdev);
   ck_assert_int_eq(rc, 0);
  
 - d-libinput = libinput_path_create_context(interface, NULL);
 + d-libinput = libinput;
   ck_assert(d-libinput != NULL);
  
   d-libinput_device = libinput_path_add_device(d-libinput, path);
 @@ -372,6 +379,19 @@ litest_create_device(enum litest_device_type which)
   return d;
  }
  
 +struct litest_device *
 +litest_create_device(enum litest_device_type which)
 +{
 + struct libinput *libinput;
 + struct litest_device *d;
 +
 + libinput = libinput_path_create_context(interface, NULL);
 + d = litest_create_device_for(libinput, which);
 + d-owns_context = true;
 +
 + return d;
 +}
 +
  int
  litest_handle_events(struct litest_device *d)
  {
 @@ -392,8 +412,12 @@ litest_delete_device(struct litest_device *d)
   if (!d)
   return;
  
 + if (d-destroy)
 + d-destroy(d);
 +
   libinput_device_unref(d-libinput_device);
 - libinput_destroy(d-libinput);
 + if (d-owns_context)
 + libinput_destroy(d-libinput);
   libevdev_free(d-evdev);
   libevdev_uinput_destroy(d-uinput);
   memset(d,0, sizeof(*d));
 diff --git a/test/litest.h b/test/litest.h
 index 9cc0ff5..fef051d 100644
 --- a/test/litest.h
 +++ b/test/litest.h
 @@ -60,8 +60,11 @@ struct litest_device {
   struct libevdev *evdev;
   struct libevdev_uinput *uinput;
   struct libinput *libinput;
 + void (*destroy)(struct litest_device *d);
 + bool owns_context;
   struct libinput_device *libinput_device;
   struct litest_device_interface *interface;
 + int 

Re: [PATCH libinput 2/2] Hook up event processing to libevdev

2014-02-24 Thread Peter Hutterer
On Mon, Feb 24, 2014 at 10:03:59PM +0100, Jonas Ådahl wrote:
 On Mon, Feb 24, 2014 at 09:44:34AM +1000, Peter Hutterer wrote:
  On Sat, Feb 22, 2014 at 04:44:06PM +0100, Jonas Ådahl wrote:
   On Tue, Feb 18, 2014 at 04:09:10PM +1000, Peter Hutterer wrote:
This gives us the ability to handle SYN_DROPPED transparently to the 
caller.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev.c | 90 
+++--
 1 file changed, 58 insertions(+), 32 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index ba28fc6..836d0af 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -29,7 +29,7 @@
 #include linux/input.h
 #include unistd.h
 #include fcntl.h
-#include mtdev.h
+#include mtdev-plumbing.h
 #include assert.h
 
 #include libinput.h
@@ -436,56 +436,82 @@ fallback_dispatch_create(void)
return dispatch;
 }
 
-static void
-evdev_process_events(struct evdev_device *device,
-struct input_event *ev, int count)
+static inline void
+evdev_process_event(struct evdev_device *device, struct input_event *e)
 {
struct evdev_dispatch *dispatch = device-dispatch;
-   struct input_event *e, *end;
-   uint32_t time = 0;
+   uint32_t time = e-time.tv_sec * 1000 + e-time.tv_usec / 1000;
 
-   e = ev;
-   end = e + count;
-   for (e = ev; e  end; e++) {
-   time = e-time.tv_sec * 1000 + e-time.tv_usec / 1000;
+   dispatch-interface-process(dispatch, device, e, time);
+}
 
-   dispatch-interface-process(dispatch, device, e, time);
+static inline void
+evdev_device_dispatch_one(struct evdev_device *device,
+ struct input_event *ev)
+{
+   if (!device-mtdev) {
+   evdev_process_event(device, ev);
+   } else {
+   mtdev_put_event(device-mtdev, ev);
+   if (libevdev_event_is_code(ev, EV_SYN, SYN_REPORT)) {
+   while(!mtdev_empty(device-mtdev)) {
 
 Nit (coding style): space between while and (

amended, thanks.

..

 static void
 evdev_device_dispatch(void *data)
 {
struct evdev_device *device = data;
struct libinput *libinput = device-base.seat-libinput;
-   int fd = device-fd;
-   struct input_event ev[32];
-   int len;
+   struct input_event ev;
+   int rc;
 
/* 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);
+   rc = libevdev_next_event(device-evdev,
+LIBEVDEV_READ_FLAG_NORMAL, 
ev);
+   if (rc == LIBEVDEV_READ_STATUS_SYNC) {
+   /* send one more sync event so we handle all
+  currently pending events before we sync up
+  to the current state */
+   ev.code = SYN_REPORT;
+   evdev_device_dispatch_one(device, ev);
   
   Is this really correct? Shouldn't calling libevdev_next_event() in SYNC
   mode return a SYN_REPORT event as part of the synchronization? If we do
   like this it looks like we might cut one series of events that would
   otherwise be grouped using SYN_REPORT in half.
  
  I think you may have misread the diff, this code is only ever called once,
  on the SYN_DROPPED, all the other events are handled in evdev_sync_device().
  
  libevdev guarantees that the event you pass in when you get
  LIBEVDEV_READ_STATUS_SYNC is the SYN_DROPPED event that triggered the sync.
  All we do here is change from EV_SYN/SYN_DROPPED to EV_SYN/SYN_REPORT and
  process that normally. That finishes the current event sequence.
  
  We then call evdev_sync_device() which empties and processes the sync queue
  until -EAGAIN. That queue is also guaranteed to end with a
  EV_SYN/SYN_REPORT. Once that is done, we jump back here and continue with
  the loop, which now hopefully has SUCCESS on the next read.
 
 My concern is not that we would add several extra SYN_REPORT splitting
 event series when synchronizing, but that when we have reached the state
 where libevdev_next_event() returns LIBEVDEV_READ_STATUS_SYNC, we might
 be in progress of queuing up a series of events waiting for the next
 SYN_REPORT. What

Re: [PATCH libinput 2/2] Hook up event processing to libevdev

2014-02-24 Thread Peter Hutterer
On Tue, Feb 25, 2014 at 08:17:24AM +1000, Peter Hutterer wrote:
  static void
  evdev_device_dispatch(void *data)
  {
   struct evdev_device *device = data;
   struct libinput *libinput = device-base.seat-libinput;
 - int fd = device-fd;
 - struct input_event ev[32];
 - int len;
 + struct input_event ev;
 + int rc;
  
   /* 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);
 + rc = libevdev_next_event(device-evdev,
 +  LIBEVDEV_READ_FLAG_NORMAL, 
 ev);
 + if (rc == LIBEVDEV_READ_STATUS_SYNC) {
 + /* send one more sync event so we handle all
 +currently pending events before we sync up
 +to the current state */
 + ev.code = SYN_REPORT;
 + evdev_device_dispatch_one(device, ev);

Is this really correct? Shouldn't calling libevdev_next_event() in SYNC
mode return a SYN_REPORT event as part of the synchronization? If we do
like this it looks like we might cut one series of events that would
otherwise be grouped using SYN_REPORT in half.
   
   I think you may have misread the diff, this code is only ever called once,
   on the SYN_DROPPED, all the other events are handled in 
   evdev_sync_device().
   
   libevdev guarantees that the event you pass in when you get
   LIBEVDEV_READ_STATUS_SYNC is the SYN_DROPPED event that triggered the 
   sync.
   All we do here is change from EV_SYN/SYN_DROPPED to EV_SYN/SYN_REPORT and
   process that normally. That finishes the current event sequence.
   
   We then call evdev_sync_device() which empties and processes the sync 
   queue
   until -EAGAIN. That queue is also guaranteed to end with a
   EV_SYN/SYN_REPORT. Once that is done, we jump back here and continue with
   the loop, which now hopefully has SUCCESS on the next read.
  
  My concern is not that we would add several extra SYN_REPORT splitting
  event series when synchronizing, but that when we have reached the state
  where libevdev_next_event() returns LIBEVDEV_READ_STATUS_SYNC, we might
  be in progress of queuing up a series of events waiting for the next
  SYN_REPORT. What the documentation[0] states regarding this is that all
  events up and including the next SYN_REPORT should be ignored and the
  device should be synchronized. The way I'm reading that is when we reach
  SYN_DROPPED, we should wait with flushing the queue until we can
  synchronize and can provide a more complete state. However, we could as
  well in this case end up with multiple events with the same time in the
  same series (for example if we already queued ABS_X but x has since then
  changed, which would mean we'd have two ABS_X in the same series) so I
  guess its not really better to not flush there.
 
 I think the documentation is a bit off here. As of 3.7
 (4369c64c79a22b98d3b7eff9d089196cd878a10a) events are now
 atomic, the kernel doesn't write until the SYN_REPORT is ready so there
 aren't any events left that we haven't read yet. the documentation predates
 that commit (2.6.39).

I double-checked this and it's a bit different than I wrote above.
the kernel input code submits this as a single frame but we may still get a
buffer overflow and thus SYN_DROPPED (at random times) in evdev when we're
not reading fast enough. However, this is exactly the kind of problem that
libevdev is there for, so I'll add the handling there so that what comes out
of libevdev is consistent.

Cheers,
   Peter

 
 The only exception is SYN_REPORT with value 1 which I've been told doesn't
 really happen anymore and in any way should be handled within libevdev, so
 we don't need to cater for it here.
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput] libinput: Fix the close_restricted interface callback

2014-03-03 Thread Peter Hutterer
On Sat, Mar 01, 2014 at 02:19:03PM -0500, Jasper St. Pierre wrote:
 libinput is supposed to take a close callback in its interface
 to allow you to call out to a privileged API to close FDs. But
 the FD that libinput passes you is bogus, because
 libinput_remove_source closes the FD on which it's passed. This
 is really bad, as the libinput_source really doesn't own the FD
 which it's passed, so it shouldn't be trying to close() it.
 
 Only one out of the four users of libinput_remove_source actually
 wants their FD closed, so move the close() call there.

pushed, thanks.

Cheers,
   Peter

 ---
  src/evdev-touchpad.c | 1 +
  src/libinput.c   | 1 -
  2 files changed, 1 insertion(+), 1 deletion(-)
 
 diff --git a/src/evdev-touchpad.c b/src/evdev-touchpad.c
 index 8185bf2..65c5ea0 100644
 --- a/src/evdev-touchpad.c
 +++ b/src/evdev-touchpad.c
 @@ -714,6 +714,7 @@ touchpad_destroy(struct evdev_dispatch *dispatch)
   struct libinput *libinput = touchpad-device-base.seat-libinput;
  
   touchpad-filter-interface-destroy(touchpad-filter);
 + close(touchpad-fsm.timer.fd);
   libinput_remove_source(libinput, touchpad-fsm.timer.source);
   free(touchpad-fsm.events);
   free(dispatch);
 diff --git a/src/libinput.c b/src/libinput.c
 index 58b87b0..182c401 100644
 --- a/src/libinput.c
 +++ b/src/libinput.c
 @@ -442,7 +442,6 @@ 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);
  }
 -- 
 1.8.5.3
 
 ___
 wayland-devel mailing list
 wayland-devel@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/wayland-devel
 
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[RFC PATCH libinput] udev: add libinput_udev_rescan_devices()

2014-03-13 Thread Peter Hutterer
When a libinput context for a given seat is initialized, not all devices may
be available. Some or all devices may be paused by systemd-logind. Waiting for
a unplug event is not appropriate here as the devices are physically
available, just prevented from getting access.

Add a libinput_udev_rescan_devices() function that triggers a scan of all
devices on the current udev seat. Devices that do not exist on the seat are
added, devices that already exist on the seat but have been revoked are
removed.

Note that devices that have been physically removed are not removed, instead
we wait for the udev event to handle this for us.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
The idea here is basically to start a udev context as usual. If the
compositor doesn't have the session, open_restricted will fail. Once the
ResumeDevice signals are handled by the compositor it can ask libinput to
rescan the device list to add the ones that failed before (or remove revoked
ones).

Notes on why this approach:
* libinput_device_suspend()/resume() seems nicer at first but if a device
  fails to open, we don't have a libinput_device context. handling that
  would make the API complicated since we cannot guarantee that all
  libinput_device_* functions (specificall has_capability) work on all
  devices anymore.
* I suspect in the 90% case the the PauseDevice/ResumeDevice signals come in
  in a batch anyway, so the compositor should be able to optimise this to
  one single call
* this is a udev specific call, for the path backend the compositor can and
  should maintain the devices manually anyway
* EVIOCGVERSION was picked because it always succeeds, except after revoke

This is an RFC at this point, let me know if that approach works. Still need
to write tests and better evdev duplicate detection - right now there is a
race condition that could remove the wrong device.

 src/evdev.c | 15 +++
 src/evdev.h |  2 ++
 src/libinput.h  | 21 +
 src/udev-seat.c | 46 +-
 4 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index ba7c8b3..018fbb1 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -790,3 +790,18 @@ evdev_device_destroy(struct evdev_device *device)
free(device-sysname);
free(device);
 }
+
+int
+evdev_device_is_alive(struct evdev_device *device)
+{
+   int rc;
+   int version;
+
+   rc = ioctl(device-fd, EVIOCGVERSION, version);
+
+   if (rc  0  errno != ENODEV)
+   log_info(evdev: %s failed with errno %d (%s)\n,
+__func__, errno, strerror(errno));
+
+   return rc != -1;
+}
diff --git a/src/evdev.h b/src/evdev.h
index b83a2f9..82a3873 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -156,4 +156,6 @@ evdev_device_remove(struct evdev_device *device);
 void
 evdev_device_destroy(struct evdev_device *device);
 
+int
+evdev_device_is_alive(struct evdev_device *device);
 #endif /* EVDEV_H */
diff --git a/src/libinput.h b/src/libinput.h
index 3e09871..dadcac2 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -715,6 +715,27 @@ libinput_udev_create_for_seat(const struct 
libinput_interface *interface,
 /**
  * @ingroup base
  *
+ * Re-scan the list of devices available to this context. Devices in the
+ * seat specified in libinput_udev_create_for_seat() that previously have
+ * failed to initialize are re-initialized. Devices that have successfully
+ * re-initialized but are now revoked are removed.
+ *
+ * Calling libinput_udev_rescan_devices() on a context suspended with
+ * libinput_suspend() does nothing.
+ *
+ * @note This function should not be used for detection of physically added
+ * or removed devices, libinput_dispatch() detects those. This function
+ * should only be used to re-open or close existing devices, e.g. if
+ * systemd-logind prevented access to a device before.
+ *
+ * @param libinput The previously initialized libinput context
+ */
+void
+libinput_udev_rescan_devices(struct libinput *libinput);
+
+/**
+ * @ingroup base
+ *
  * Create a new libinput context that requires the caller to manually add or
  * remove devices with libinput_path_add_device() and
  * libinput_path_remove_device().
diff --git a/src/udev-seat.c b/src/udev-seat.c
index 366c92b..5b09e4b 100644
--- a/src/udev-seat.c
+++ b/src/udev-seat.c
@@ -136,12 +136,28 @@ device_removed(struct udev_device *udev_device, struct 
udev_input *input)
}
 }
 
+static struct evdev_device*
+udev_input_find_device_by_sysname(struct udev_input *input, const char 
*sysname)
+{
+   struct udev_seat *seat;
+   struct evdev_device *device;
+
+   list_for_each(seat, input-base.seat_list, base.link) {
+   list_for_each(device, seat-base.devices_list, base.link)
+   if (!strcmp(device-sysname, sysname)) {
+   return device;
+   }
+   }
+   return NULL;
+}
+
 static

Re: [RFC PATCH libinput] udev: add libinput_udev_rescan_devices()

2014-03-17 Thread Peter Hutterer
On Sat, Mar 15, 2014 at 07:59:29PM +0100, Jonas Ådahl wrote:
 On Thu, Mar 13, 2014 at 04:18:20PM +1000, Peter Hutterer wrote:
  When a libinput context for a given seat is initialized, not all devices may
  be available. Some or all devices may be paused by systemd-logind. Waiting 
  for
  a unplug event is not appropriate here as the devices are physically
  available, just prevented from getting access.
  
  Add a libinput_udev_rescan_devices() function that triggers a scan of all
  devices on the current udev seat. Devices that do not exist on the seat are
  added, devices that already exist on the seat but have been revoked are
  removed.
  
  Note that devices that have been physically removed are not removed, instead
  we wait for the udev event to handle this for us.
  
  Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
  ---
  The idea here is basically to start a udev context as usual. If the
  compositor doesn't have the session, open_restricted will fail. Once the
  ResumeDevice signals are handled by the compositor it can ask libinput to
  rescan the device list to add the ones that failed before (or remove revoked
  ones).
  
  Notes on why this approach:
  * libinput_device_suspend()/resume() seems nicer at first but if a device
fails to open, we don't have a libinput_device context. handling that
would make the API complicated since we cannot guarantee that all
libinput_device_* functions (specificall has_capability) work on all
devices anymore.
  * I suspect in the 90% case the the PauseDevice/ResumeDevice signals come in
in a batch anyway, so the compositor should be able to optimise this to
one single call
  * this is a udev specific call, for the path backend the compositor can and
should maintain the devices manually anyway
  * EVIOCGVERSION was picked because it always succeeds, except after revoke
  
  This is an RFC at this point, let me know if that approach works. Still need
  to write tests and better evdev duplicate detection - right now there is a
  race condition that could remove the wrong device.
 
 Hi,
 
 So what this patch is trying to solve is handling the following flow:
 
 * create libinput udev context
  - some or all devices will fail to open due to being paused
 * devices are resumed
 
 What stops us from simply doing
 
 * devices are resumed
 * create libinput udev context

Jasper? you can answer that better than me

 As you say, a compositor should be able to know when it should rescan,
 and in most cases (?) before this, we won't get a single device anyway
 so whats the point of creating earlier than that? For resuming after
 session switch I suppose we'd have the same problem, but this would then
 just work the same:
 
 * devices are resumed
 * resume libinput context

the question here is: is there a use-case for a single device to be
paused/resumed outside of the usual process? David?

We're struggling with this in X but that's caused by a completely different
problem and is rather orthogonal to this.

Cheers,
   Peter

 
   src/evdev.c | 15 +++
   src/evdev.h |  2 ++
   src/libinput.h  | 21 +
   src/udev-seat.c | 46 +-
   4 files changed, 79 insertions(+), 5 deletions(-)
  
  diff --git a/src/evdev.c b/src/evdev.c
  index ba7c8b3..018fbb1 100644
  --- a/src/evdev.c
  +++ b/src/evdev.c
  @@ -790,3 +790,18 @@ evdev_device_destroy(struct evdev_device *device)
  free(device-sysname);
  free(device);
   }
  +
  +int
  +evdev_device_is_alive(struct evdev_device *device)
  +{
  +   int rc;
  +   int version;
  +
  +   rc = ioctl(device-fd, EVIOCGVERSION, version);
  +
  +   if (rc  0  errno != ENODEV)
  +   log_info(evdev: %s failed with errno %d (%s)\n,
  +__func__, errno, strerror(errno));
  +
  +   return rc != -1;
  +}
  diff --git a/src/evdev.h b/src/evdev.h
  index b83a2f9..82a3873 100644
  --- a/src/evdev.h
  +++ b/src/evdev.h
  @@ -156,4 +156,6 @@ evdev_device_remove(struct evdev_device *device);
   void
   evdev_device_destroy(struct evdev_device *device);
   
  +int
  +evdev_device_is_alive(struct evdev_device *device);
   #endif /* EVDEV_H */
  diff --git a/src/libinput.h b/src/libinput.h
  index 3e09871..dadcac2 100644
  --- a/src/libinput.h
  +++ b/src/libinput.h
  @@ -715,6 +715,27 @@ libinput_udev_create_for_seat(const struct 
  libinput_interface *interface,
   /**
* @ingroup base
*
  + * Re-scan the list of devices available to this context. Devices in the
  + * seat specified in libinput_udev_create_for_seat() that previously have
  + * failed to initialize are re-initialized. Devices that have successfully
  + * re-initialized but are now revoked are removed.
  + *
  + * Calling libinput_udev_rescan_devices() on a context suspended with
  + * libinput_suspend() does nothing.
  + *
  + * @note This function should not be used for detection of physically added
  + * or removed devices

[PATCH libinput 3/3] Expand documentation for libinput_udev_create_for_seat

2014-03-20 Thread Peter Hutterer
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/libinput.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/src/libinput.h b/src/libinput.h
index d6bf9f8..3e09871 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -691,6 +691,12 @@ struct libinput_interface {
  * the given seat ID. New devices or devices removed will appear as events
  * during libinput_dispatch.
  *
+ * libinput_udev_create_for_seat() fails for internal values only. No
+ * guarantee is made that a device is available once the call finishes, and
+ * only devices handled by libinput are avialable. Devices that cannot be
+ * opened in @ref libinput_interface::open_restricted or do not match
+ * libinput requirements are ignored.
+ *
  * @param interface The callback interface
  * @param user_data Caller-specific data passed to the various callback
  * interfaces.
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 1/3] Return the length or a neg errno from libinput_device_get_keys()

2014-03-20 Thread Peter Hutterer
Previous return value was the straight ioctl, we should try to avoid errno
mangling.

This changes the API, if not the ABI. Callers with code along the lines of
if (libinput_device_get_keys() == -1) will now break.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
weston is not affected by this, it checks for  .

 src/evdev.c| 6 +-
 src/libinput.h | 2 ++
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/evdev.c b/src/evdev.c
index 5d01e3b..ba7c8b3 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -715,8 +715,12 @@ err:
 int
 evdev_device_get_keys(struct evdev_device *device, char *keys, size_t size)
 {
+   int len;
+
memset(keys, 0, size);
-   return ioctl(device-fd, EVIOCGKEY(size), keys);
+   len = ioctl(device-fd, EVIOCGKEY(size), keys);
+
+   return (len == -1) ? -errno : len;
 }
 
 const char *
diff --git a/src/libinput.h b/src/libinput.h
index 9a9cd8c..d6bf9f8 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -1169,6 +1169,8 @@ libinput_device_led_update(struct libinput_device *device,
  * @param device A current input device
  * @param keys An array filled with the bitmask for the keys
  * @param size Size of the keys array
+ *
+ * @return The number of valid bytes in keys, or a negative errno on failure
  */
 int
 libinput_device_get_keys(struct libinput_device *device,
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 2/3] udev: factor out device_removed handling

2014-03-20 Thread Peter Hutterer
No functional changes

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
I needed this for the rescan patch but it makes the calls more symmetrical,
so we might as well push it independently.

 src/udev-seat.c | 41 +++--
 1 file changed, 23 insertions(+), 18 deletions(-)

diff --git a/src/udev-seat.c b/src/udev-seat.c
index e622de2..366c92b 100644
--- a/src/udev-seat.c
+++ b/src/udev-seat.c
@@ -116,6 +116,26 @@ device_added(struct udev_device *udev_device, struct 
udev_input *input)
return 0;
 }
 
+static void
+device_removed(struct udev_device *udev_device, struct udev_input *input)
+{
+   const char *devnode;
+   struct evdev_device *device, *next;
+   struct udev_seat *seat;
+
+   devnode = udev_device_get_devnode(udev_device);
+   list_for_each(seat, input-base.seat_list, base.link) {
+   list_for_each_safe(device, next,
+   seat-base.devices_list, base.link)
+   if (!strcmp(device-devnode, devnode)) {
+   log_info(input device %s, %s removed\n,
+   device-devname, 
device-devnode);
+   evdev_device_remove(device);
+   break;
+   }
+   }
+}
+
 static int
 udev_input_add_devices(struct udev_input *input, struct udev *udev)
 {
@@ -155,10 +175,7 @@ evdev_udev_handler(void *data)
 {
struct udev_input *input = data;
struct udev_device *udev_device;
-   struct evdev_device *device, *next;
const char *action;
-   const char *devnode;
-   struct udev_seat *seat;
 
udev_device = udev_monitor_receive_device(input-udev_monitor);
if (!udev_device)
@@ -171,22 +188,10 @@ evdev_udev_handler(void *data)
if (strncmp(event, udev_device_get_sysname(udev_device), 5) != 0)
goto out;
 
-   if (!strcmp(action, add)) {
+   if (!strcmp(action, add))
device_added(udev_device, input);
-   }
-   else if (!strcmp(action, remove)) {
-   devnode = udev_device_get_devnode(udev_device);
-   list_for_each(seat, input-base.seat_list, base.link) {
-   list_for_each_safe(device, next,
-  seat-base.devices_list, base.link)
-   if (!strcmp(device-devnode, devnode)) {
-   log_info(input device %s, %s 
removed\n,
-device-devname, 
device-devnode);
-   evdev_device_remove(device);
-   break;
-   }
-   }
-   }
+   else if (!strcmp(action, remove))
+   device_removed(udev_device, input);
 
 out:
udev_device_unref(udev_device);
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [RFC PATCH libinput] udev: add libinput_udev_rescan_devices()

2014-03-20 Thread Peter Hutterer
On Fri, Mar 21, 2014 at 12:27:45AM -0400, Jasper St. Pierre wrote:
 So you're saying that every time we're suspended, we simply throw out the
 entire context and drop all the devices on the floor, as if you just
 unplugged all of them?

fwiw, this is effectively what happens internally anyway, you get removed
events for every device on suspend, and added events on resume for those
still there.

 I suppose I just never thought of that. On first though, I don't see
 anything wrong with that.
 
 If that's what we should do, should we remove libinput_suspend /
 libinput_resume then?

libinput_suspend/resume only tear down the devices, but not anything
else. there isn't much global state that's kept across suspend/resume yet
(seats are one example though) but the biggest difference is that that you
can't use _any_ object around after libinput_destroy(). suspend/resume
keeps them alive until you unref them.

Cheers,
   Peter

 
 
 On Mon, Mar 17, 2014 at 11:21 PM, Peter Hutterer
 peter.hutte...@who-t.netwrote:
 
  On Sat, Mar 15, 2014 at 07:59:29PM +0100, Jonas Ådahl wrote:
   On Thu, Mar 13, 2014 at 04:18:20PM +1000, Peter Hutterer wrote:
When a libinput context for a given seat is initialized, not all
  devices may
be available. Some or all devices may be paused by systemd-logind.
  Waiting for
a unplug event is not appropriate here as the devices are physically
available, just prevented from getting access.
   
Add a libinput_udev_rescan_devices() function that triggers a scan of
  all
devices on the current udev seat. Devices that do not exist on the
  seat are
added, devices that already exist on the seat but have been revoked are
removed.
   
Note that devices that have been physically removed are not removed,
  instead
we wait for the udev event to handle this for us.
   
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
The idea here is basically to start a udev context as usual. If the
compositor doesn't have the session, open_restricted will fail. Once
  the
ResumeDevice signals are handled by the compositor it can ask libinput
  to
rescan the device list to add the ones that failed before (or remove
  revoked
ones).
   
Notes on why this approach:
* libinput_device_suspend()/resume() seems nicer at first but if a
  device
  fails to open, we don't have a libinput_device context. handling that
  would make the API complicated since we cannot guarantee that all
  libinput_device_* functions (specificall has_capability) work on all
  devices anymore.
* I suspect in the 90% case the the PauseDevice/ResumeDevice signals
  come in
  in a batch anyway, so the compositor should be able to optimise this
  to
  one single call
* this is a udev specific call, for the path backend the compositor
  can and
  should maintain the devices manually anyway
* EVIOCGVERSION was picked because it always succeeds, except after
  revoke
   
This is an RFC at this point, let me know if that approach works.
  Still need
to write tests and better evdev duplicate detection - right now there
  is a
race condition that could remove the wrong device.
  
   Hi,
  
   So what this patch is trying to solve is handling the following flow:
  
   * create libinput udev context
- some or all devices will fail to open due to being paused
   * devices are resumed
  
   What stops us from simply doing
  
   * devices are resumed
   * create libinput udev context
 
  Jasper? you can answer that better than me
 
   As you say, a compositor should be able to know when it should rescan,
   and in most cases (?) before this, we won't get a single device anyway
   so whats the point of creating earlier than that? For resuming after
   session switch I suppose we'd have the same problem, but this would then
   just work the same:
  
   * devices are resumed
   * resume libinput context
 
  the question here is: is there a use-case for a single device to be
  paused/resumed outside of the usual process? David?
 
  We're struggling with this in X but that's caused by a completely different
  problem and is rather orthogonal to this.
 
  Cheers,
 Peter
 
 
 src/evdev.c | 15 +++
 src/evdev.h |  2 ++
 src/libinput.h  | 21 +
 src/udev-seat.c | 46 +-
 4 files changed, 79 insertions(+), 5 deletions(-)
   
diff --git a/src/evdev.c b/src/evdev.c
index ba7c8b3..018fbb1 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -790,3 +790,18 @@ evdev_device_destroy(struct evdev_device *device)
free(device-sysname);
free(device);
 }
+
+int
+evdev_device_is_alive(struct evdev_device *device)
+{
+   int rc;
+   int version;
+
+   rc = ioctl(device-fd, EVIOCGVERSION, version);
+
+   if (rc  0  errno != ENODEV)
+   log_info(evdev: %s failed

Re: [PATCH libinput 00/19] mt touchpad implementation

2014-03-24 Thread Peter Hutterer
On Mon, Feb 17, 2014 at 04:48:19PM +1000, Peter Hutterer wrote:
 Here's the base of a touchpad implementation that's more geared towards
 modern multitouch-capable touchpads than the current xorg synaptics driver
 or, for that matter, the libinput one.

just for the archives, I've pushed this driver now. The old one is still in
the repo so if this one really doesn't work on your hardware you can revert
6a6103262530d8fca66ee3847d5664824158c12b locally. While you hopefully file a
bug and give us a chance to fix the new one :)

Cheers,
   Peter

 
 This isn't a completely new implementation, I worked on a project named
 libtouchpad a few months back, most of this is porting things over to
 libinput. Note that parts are still work in progress, but I'd like to merge
 it soon so we can concentrate on fixing it instead of me rebasing a massive
 patchset.
 
 The big difference to other existing drivers is that each touchpoint is
 handled separately. That allows us to do a couple of things better than
 before: because we can tell where each finger is, software button handling,
 clickpad drag-and-drop, etc. becomes a lot easier to handle.
 
 The features already working in this driver:
 - 1, 2, 3-finger tapping
 - 2-finger scrolling
 - clickfinger, 1-2-3 fingers on the touchpad when clicking cause LRM click
 - drag-n-drop on clickpads
 - single-touch touchpad support (+ tapping and 2 finger scrolling)
 
 Features in the pipe (i.e. need porting):
 - clickpad software button support
 - better timeout handling (a read delay coupled with a timeout may trigger
   the wrong events)
 
 Features planned:
 - top software button area
 - trackstick mode (T440)
 - disable-while-typing
 - better motion filters, especially during tapping and clicking
 - pinch/rotation support
 - better handling of vert → horizontal scrolling. Right now the scroll
   direction is locked after the first movement, I'd like to use a
   time-dependent vector to decide when a sideways motion enables horizontal
   scrolling
 
 I think that about covers it for now. You can test the code on
   http://github.com/whot/libinput wip/mt-touchpad
 
 and a basic X driver is here:
   http://github.com/whot/xf86-input-libinput
 
 Any comments?
 
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [RFC] libinput configuration interface

2014-03-26 Thread Peter Hutterer
hey, sorry about the delay, I got moved to other stuff for a while and only
now just picked up libinput again.

On Sat, Feb 22, 2014 at 03:33:26PM +0600, Alexander E. Patrakov wrote:
 2014-02-21 5:26 GMT+06:00 Peter Hutterer peter.hutte...@who-t.net:
  On Fri, Feb 21, 2014 at 01:29:05AM +0600, Alexander E. Patrakov wrote:
  Vertical two-finger scrolling works, but is way too sensitive both
  with constant deceleration 1.0 and with 0.3.
 
  that's a xf86-input-libinput bug, Benjamin fixed that but I forgot to
  push. 761603d..bee8989 now, please re-test that.
 
 The speed is now fixed indeed, but scrolling is now subject to the
 same dirty mouse bug. See the badscroll.rec file in the attached
 archive. It contains two scoll gestures - one down, and one up. The
 driver has picked up only the beginning of the up-scroll (i.e. the
 chromium window was not scrolled as far as I wanted, even though I
 continued moving both fingers).
 
I've looked at this and I think I know what you mean. I get a massive jump
down first, then a slight up only. Looking at the ./tools/event-debug output
from libinput it looks like the coordinates for downward scroll are massive
too (between 10 and 48), the upwards ones are hanging around the -3 to -4
mark. That would explain the different scrolling. however, that matches the
recordings.

I think what may be the problem here is the motion averaging between the
fingers. the driver currently takes the changed touchpoints and averages the
motion between the two for the actual scroll distance. this may slow down
slow scrolls, I'll need to run some tests on this.

  Tapping and tap-and-drag are not usable. They require not tapping,
  but knocking with force. So this points to the driver being
  miscalibrated on the pressure axis. Can this also be the reason of
  the low x/y sensitivity and dirty mouse feeling?
 
  that's a bit odd. I'd like to see an evemu-record output from that then.
  Currently I ignore pressure completely, so any touch should be detected.
 
 Actually the first tap after the server start is detected reliably.
 The problem only affects other taps. See the file tap-libinput.rec
 in the attached archive.
 
I had a look at the recording files, mainly with the event-debug tools but
I'm struggingling to see the same issues. the tap recording has 6 touches,
some of which are taps, others are moves. I can spot three taps in there,
one in the middle somewhere, two towards the end and that seems to match the
recordings.

Cheers,
   Peter
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 2/8] evdev: Avoid double touch down/up events

2014-03-26 Thread Peter Hutterer
On Wed, Mar 26, 2014 at 07:45:32AM +0100, Michael Schellenberger Costa wrote:
 I might be dumb but doesnt this require motion between clicks?
 
 In that case you would lose for example track balls which do not
 necessary move between clicks.

this is for touch events only here, and the only way you can get here is if
you have a SYN_DROPPED event and you're losing one of the
ABS_MT_TRACKING_ID. This is fixed with libevdev 1.1, but better be safe than
sorry here.

Cheers,
   Peter

 On 25.03.2014 21:45, Jonas Ådahl wrote:
  When the kernel sends multiple touch down or touch up for the same
  slot in a row, ignore any such subsequent event ensuring libinput
  always produces 1 x touch down - [n x touch motion] - 1 x touch
  up event series.
  
  Signed-off-by: Jonas Ådahl jad...@gmail.com --- src/evdev.c | 13
  + 1 file changed, 13 insertions(+)
  
  diff --git a/src/evdev.c b/src/evdev.c index ff8b27a..729e1f4
  100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -135,6 +135,9 @@
  evdev_flush_pending_event(struct evdev_device *device, uint32_t
  time) if (slot = MAX_SLOTS) break;
  
  +   if (device-mt.slots[slot].seat_slot != -1) +   
  break; + 
  seat_slot = ffs(~seat-slot_map) - 1; 
  device-mt.slots[slot].seat_slot = seat_slot;
  
  @@ -171,6 +174,7 @@ evdev_flush_pending_event(struct evdev_device
  *device, uint32_t time) break;
  
  seat_slot = device-mt.slots[slot].seat_slot; +
  device-mt.slots[slot].seat_slot = -1;
  
  if (seat_slot == -1) break; @@ -183,6 +187,9 @@
  evdev_flush_pending_event(struct evdev_device *device, uint32_t
  time) if (!(device-seat_caps  EVDEV_DEVICE_TOUCH)) break;
  
  +   if (device-abs.seat_slot != -1) +  break; 
  + seat_slot =
  ffs(~seat-slot_map) - 1; device-abs.seat_slot = seat_slot;
  
  @@ -218,6 +225,7 @@ evdev_flush_pending_event(struct evdev_device
  *device, uint32_t time) break;
  
  seat_slot = device-abs.seat_slot; +device-abs.seat_slot = 
  -1;
  
  if (seat_slot == -1) break; @@ -655,6 +663,7 @@
  evdev_device_create(struct libinput_seat *seat, int rc; int fd; int
  unhandled_device = 0; + int i;
  
  /* Use non-blocking mode so that we can loop on read on *
  evdev_device_data() until all events on the fd are @@ -712,6
  +721,10 @@ evdev_device_create(struct libinput_seat *seat, if
  (!device-source) goto err;
  
  +   device-abs.seat_slot = -1; +   for (i = 0; i  MAX_SLOTS; ++i) +
  device-mt.slots[i].seat_slot = -1; + 
  list_insert(seat-devices_list.prev, device-base.link); 
  notify_added_device(device-base);
  
  
 
 ___
 wayland-devel mailing list
 wayland-devel@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/wayland-devel
 
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 2/8] evdev: Avoid double touch down/up events

2014-03-26 Thread Peter Hutterer
On Wed, Mar 26, 2014 at 08:40:43AM +0100, Jonas Ådahl wrote:
 On Wed, Mar 26, 2014 at 05:30:14PM +1000, Peter Hutterer wrote:
  On Wed, Mar 26, 2014 at 07:45:32AM +0100, Michael Schellenberger Costa 
  wrote:
   I might be dumb but doesnt this require motion between clicks?
   
   In that case you would lose for example track balls which do not
   necessary move between clicks.
  
  this is for touch events only here, and the only way you can get here is if
  you have a SYN_DROPPED event and you're losing one of the
  ABS_MT_TRACKING_ID. This is fixed with libevdev 1.1, but better be safe than
  sorry here.
 
 We can also get this if we have an libevdev managed uinput device with
 mt slot limit x while sending mt slot x + n events. libevdev will
 sanitize the events making any mt slot x + n event a mt slot x event.

huh, right, I didn't think of that. I'll see if I can fix this in libevdev.

Cheers,
   Peter

  
   On 25.03.2014 21:45, Jonas Ådahl wrote:
When the kernel sends multiple touch down or touch up for the same
slot in a row, ignore any such subsequent event ensuring libinput
always produces 1 x touch down - [n x touch motion] - 1 x touch
up event series.

Signed-off-by: Jonas Ådahl jad...@gmail.com --- src/evdev.c | 13
+ 1 file changed, 13 insertions(+)

diff --git a/src/evdev.c b/src/evdev.c index ff8b27a..729e1f4
100644 --- a/src/evdev.c +++ b/src/evdev.c @@ -135,6 +135,9 @@
evdev_flush_pending_event(struct evdev_device *device, uint32_t
time) if (slot = MAX_SLOTS) break;

+   if (device-mt.slots[slot].seat_slot != -1) +   
break; + 
seat_slot = ffs(~seat-slot_map) - 1; 
device-mt.slots[slot].seat_slot = seat_slot;

@@ -171,6 +174,7 @@ evdev_flush_pending_event(struct evdev_device
*device, uint32_t time) break;

seat_slot = device-mt.slots[slot].seat_slot; +
device-mt.slots[slot].seat_slot = -1;

if (seat_slot == -1) break; @@ -183,6 +187,9 @@
evdev_flush_pending_event(struct evdev_device *device, uint32_t
time) if (!(device-seat_caps  EVDEV_DEVICE_TOUCH)) break;

+   if (device-abs.seat_slot != -1) +  
break; + seat_slot =
ffs(~seat-slot_map) - 1; device-abs.seat_slot = seat_slot;

@@ -218,6 +225,7 @@ evdev_flush_pending_event(struct evdev_device
*device, uint32_t time) break;

seat_slot = device-abs.seat_slot; +device-abs.seat_slot = 
-1;

if (seat_slot == -1) break; @@ -655,6 +663,7 @@
evdev_device_create(struct libinput_seat *seat, int rc; int fd; int
unhandled_device = 0; + int i;

/* Use non-blocking mode so that we can loop on read on *
evdev_device_data() until all events on the fd are @@ -712,6
+721,10 @@ evdev_device_create(struct libinput_seat *seat, if
(!device-source) goto err;

+   device-abs.seat_slot = -1; +   for (i = 0; i  MAX_SLOTS; ++i) 
+
device-mt.slots[i].seat_slot = -1; + 
list_insert(seat-devices_list.prev, device-base.link); 
notify_added_device(device-base);


   
   ___
   wayland-devel mailing list
   wayland-devel@lists.freedesktop.org
   http://lists.freedesktop.org/mailman/listinfo/wayland-devel
   
  ___
  wayland-devel mailing list
  wayland-devel@lists.freedesktop.org
  http://lists.freedesktop.org/mailman/listinfo/wayland-devel
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 4/8] test: Test handling of many touch points

2014-03-26 Thread Peter Hutterer
On Tue, Mar 25, 2014 at 09:45:55PM +0100, Jonas Ådahl wrote:
 libinput currently handles 16 per device touch points. Test that we
 behave as expected when a device has an even higher number of active
 touch points.
 
 Signed-off-by: Jonas Ådahl jad...@gmail.com
 ---
  test/touch.c | 50 ++
  1 file changed, 50 insertions(+)
 
 diff --git a/test/touch.c b/test/touch.c
 index 9354c25..61d8762 100644
 --- a/test/touch.c
 +++ b/test/touch.c
 @@ -275,6 +275,54 @@ START_TEST(touch_seat_slot_drop)
  }
  END_TEST
  
 +START_TEST(touch_many_slots)
 +{
 + struct libinput *libinput;
 + struct litest_device *dev;
 + struct libinput_event *ev;
 + int slot;
 + const int num_tps = 100;
 + int slot_count = 0;
 + enum libinput_event_type type;
 +
 + dev = litest_current_device();
 + libinput = dev-libinput;
 +
 + for (slot = 0; slot  num_tps; ++slot)
 + litest_touch_down(dev, slot, 0, 0);
 + for (slot = 0; slot  num_tps; ++slot)
 + litest_touch_up(dev, slot);
 +
 + libinput_dispatch(libinput);
 + while ((ev = libinput_get_event(libinput))) {
 + type = libinput_event_get_type(ev);
 +
 + if (type == LIBINPUT_EVENT_TOUCH_DOWN)
 + slot_count++;
 + else if (type == LIBINPUT_EVENT_TOUCH_UP)
 + break;
 +
 + libinput_dispatch(libinput);
 + }
 +
 + ck_assert_notnull(ev);
 + ck_assert_int_gt(slot_count, 0);
 +
 + libinput_dispatch(libinput);
 + do {
 + type = libinput_event_get_type(ev);
 + ck_assert_int_ne(type, LIBINPUT_EVENT_TOUCH_DOWN);
 + if (type == LIBINPUT_EVENT_TOUCH_UP) {
 + slot_count--;
 + }
 +
 + libinput_dispatch(libinput);
 + } while ((ev = libinput_get_event(libinput)));
 +
 + ck_assert_int_eq(slot_count, 0);
 +}
 +END_TEST
 +
  int
  main(int argc, char **argv)
  {
 @@ -283,6 +331,8 @@ main(int argc, char **argv)
  LITEST_TOUCH, LITEST_ANY);
   litest_add_no_device(touch:seat-slot, touch_seat_slots);
   litest_add_no_device(touch:seat-slot-drop, touch_seat_slot_drop);
 + litest_add(touch:many-slots, touch_many_slots,
 +LITEST_TOUCH, LITEST_ANY);

even though it breaks the 80 char width, I'd really prefer it if the tests
would just be on one line, it's a lot easier to view them on screens that
are less than 10 years old :)

Cheers,
   Peter

  
   return litest_run(argc, argv);
  }
 -- 
 1.8.3.2
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 1/8] evdev: Don't write out of bounds when mt slot is too large

2014-03-26 Thread Peter Hutterer
On Tue, Mar 25, 2014 at 09:45:52PM +0100, Jonas Ådahl wrote:
 Signed-off-by: Jonas Ådahl jad...@gmail.com

patch looks good, but I do wonder if it'd be better to just dynamically
allocate slots based on the number of touches. A quick glance shows we don't
really need this a fixed length anyway, MAX_SLOTS is unnecessary.

Cheers,
   Peter

 ---
  src/evdev.c | 13 +
  1 file changed, 13 insertions(+)
 
 diff --git a/src/evdev.c b/src/evdev.c
 index 72e4086..ff8b27a 100644
 --- a/src/evdev.c
 +++ b/src/evdev.c
 @@ -132,6 +132,9 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + if (slot = MAX_SLOTS)
 + break;
 +
   seat_slot = ffs(~seat-slot_map) - 1;
   device-mt.slots[slot].seat_slot = seat_slot;
  
 @@ -148,6 +151,9 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + if (slot = MAX_SLOTS)
 + break;
 +
   seat_slot = device-mt.slots[slot].seat_slot;
   x = li_fixed_from_int(device-mt.slots[slot].x);
   y = li_fixed_from_int(device-mt.slots[slot].y);
 @@ -161,6 +167,9 @@ evdev_flush_pending_event(struct evdev_device *device, 
 uint32_t time)
   if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
   break;
  
 + if (slot = MAX_SLOTS)
 + break;
 +
   seat_slot = device-mt.slots[slot].seat_slot;
  
   if (seat_slot == -1)
 @@ -300,11 +309,15 @@ evdev_process_touch(struct evdev_device *device,
   device-pending_event = EVDEV_ABSOLUTE_MT_UP;
   break;
   case ABS_MT_POSITION_X:
 + if (device-mt.slot = MAX_SLOTS)
 + break;
   device-mt.slots[device-mt.slot].x = e-value;
   if (device-pending_event == EVDEV_NONE)
   device-pending_event = EVDEV_ABSOLUTE_MT_MOTION;
   break;
   case ABS_MT_POSITION_Y:
 + if (device-mt.slot = MAX_SLOTS)
 + break;
   device-mt.slots[device-mt.slot].y = e-value;
   if (device-pending_event == EVDEV_NONE)
   device-pending_event = EVDEV_ABSOLUTE_MT_MOTION;
 -- 
 1.8.3.2
 
 ___
 wayland-devel mailing list
 wayland-devel@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/wayland-devel
 
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 1/8] evdev: Don't write out of bounds when mt slot is too large

2014-03-26 Thread Peter Hutterer
On Wed, Mar 26, 2014 at 09:20:27AM +0100, Jonas Ådahl wrote:
 On Wed, Mar 26, 2014 at 06:05:19PM +1000, Peter Hutterer wrote:
  On Tue, Mar 25, 2014 at 09:45:52PM +0100, Jonas Ådahl wrote:
   Signed-off-by: Jonas Ådahl jad...@gmail.com
  
  patch looks good, but I do wonder if it'd be better to just dynamically
  allocate slots based on the number of touches. A quick glance shows we don't
  really need this a fixed length anyway, MAX_SLOTS is unnecessary.
 
 We probably want a MAX_SLOTS anyway if we want to structure it as slot =
 index in (dynamically allocated) array, in order to protect from misbehaving 
 drivers.

the kernel filters slots outside the ranges, so we should be good for the
normal use-case. using a min macro that caps it to num_slots when we assign
the slot number should be enough too (that's essentially what libevdev
does). You'll overwrite stuff in the same slot but by then you already have
a misbehaving device anyway.

Cheers,
   Peter

   ---
src/evdev.c | 13 +
1 file changed, 13 insertions(+)
   
   diff --git a/src/evdev.c b/src/evdev.c
   index 72e4086..ff8b27a 100644
   --- a/src/evdev.c
   +++ b/src/evdev.c
   @@ -132,6 +132,9 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
 break;

   + if (slot = MAX_SLOTS)
   + break;
   +
 seat_slot = ffs(~seat-slot_map) - 1;
 device-mt.slots[slot].seat_slot = seat_slot;

   @@ -148,6 +151,9 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
 break;

   + if (slot = MAX_SLOTS)
   + break;
   +
 seat_slot = device-mt.slots[slot].seat_slot;
 x = li_fixed_from_int(device-mt.slots[slot].x);
 y = li_fixed_from_int(device-mt.slots[slot].y);
   @@ -161,6 +167,9 @@ evdev_flush_pending_event(struct evdev_device 
   *device, uint32_t time)
 if (!(device-seat_caps  EVDEV_DEVICE_TOUCH))
 break;

   + if (slot = MAX_SLOTS)
   + break;
   +
 seat_slot = device-mt.slots[slot].seat_slot;

 if (seat_slot == -1)
   @@ -300,11 +309,15 @@ evdev_process_touch(struct evdev_device *device,
 device-pending_event = EVDEV_ABSOLUTE_MT_UP;
 break;
 case ABS_MT_POSITION_X:
   + if (device-mt.slot = MAX_SLOTS)
   + break;
 device-mt.slots[device-mt.slot].x = e-value;
 if (device-pending_event == EVDEV_NONE)
 device-pending_event = EVDEV_ABSOLUTE_MT_MOTION;
 break;
 case ABS_MT_POSITION_Y:
   + if (device-mt.slot = MAX_SLOTS)
   + break;
 device-mt.slots[device-mt.slot].y = e-value;
 if (device-pending_event == EVDEV_NONE)
 device-pending_event = EVDEV_ABSOLUTE_MT_MOTION;
   -- 
   1.8.3.2
   
   ___
   wayland-devel mailing list
   wayland-devel@lists.freedesktop.org
   http://lists.freedesktop.org/mailman/listinfo/wayland-devel
   
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 4/8] test: Test handling of many touch points

2014-03-26 Thread Peter Hutterer
On Wed, Mar 26, 2014 at 09:24:08AM +0100, Jonas Ådahl wrote:
 On Wed, Mar 26, 2014 at 06:02:46PM +1000, Peter Hutterer wrote:
  On Tue, Mar 25, 2014 at 09:45:55PM +0100, Jonas Ådahl wrote:
   libinput currently handles 16 per device touch points. Test that we
   behave as expected when a device has an even higher number of active
   touch points.
   
   Signed-off-by: Jonas Ådahl jad...@gmail.com
   ---
test/touch.c | 50 ++
1 file changed, 50 insertions(+)
   
   diff --git a/test/touch.c b/test/touch.c
   index 9354c25..61d8762 100644
   --- a/test/touch.c
   +++ b/test/touch.c
   @@ -275,6 +275,54 @@ START_TEST(touch_seat_slot_drop)
}
END_TEST

   +START_TEST(touch_many_slots)
   +{
   + struct libinput *libinput;
   + struct litest_device *dev;
   + struct libinput_event *ev;
   + int slot;
   + const int num_tps = 100;
   + int slot_count = 0;
   + enum libinput_event_type type;
   +
   + dev = litest_current_device();
   + libinput = dev-libinput;
   +
   + for (slot = 0; slot  num_tps; ++slot)
   + litest_touch_down(dev, slot, 0, 0);
   + for (slot = 0; slot  num_tps; ++slot)
   + litest_touch_up(dev, slot);
   +
   + libinput_dispatch(libinput);
   + while ((ev = libinput_get_event(libinput))) {
   + type = libinput_event_get_type(ev);
   +
   + if (type == LIBINPUT_EVENT_TOUCH_DOWN)
   + slot_count++;
   + else if (type == LIBINPUT_EVENT_TOUCH_UP)
   + break;
   +
   + libinput_dispatch(libinput);
   + }
   +
   + ck_assert_notnull(ev);
   + ck_assert_int_gt(slot_count, 0);
   +
   + libinput_dispatch(libinput);
   + do {
   + type = libinput_event_get_type(ev);
   + ck_assert_int_ne(type, LIBINPUT_EVENT_TOUCH_DOWN);
   + if (type == LIBINPUT_EVENT_TOUCH_UP) {
   + slot_count--;
   + }
   +
   + libinput_dispatch(libinput);
   + } while ((ev = libinput_get_event(libinput)));
   +
   + ck_assert_int_eq(slot_count, 0);
   +}
   +END_TEST
   +
int
main(int argc, char **argv)
{
   @@ -283,6 +331,8 @@ main(int argc, char **argv)
LITEST_TOUCH, LITEST_ANY);
 litest_add_no_device(touch:seat-slot, touch_seat_slots);
 litest_add_no_device(touch:seat-slot-drop, touch_seat_slot_drop);
   + litest_add(touch:many-slots, touch_many_slots,
   +LITEST_TOUCH, LITEST_ANY);
  
  even though it breaks the 80 char width, I'd really prefer it if the tests
  would just be on one line, it's a lot easier to view them on screens that
  are less than 10 years old :)
 
 I tend to use vertical split screen on a laptop and in those cases 80
 char length limit makes code more readable. I guess I could change it to
 ignore the 80 char limit for test case adding lines, albeit reluctantly.

thanks. I'm not proposing to change it for the rest of the code, but it really
makes the code nicer to look at. this isn't code that gets edited
frequently, so the exception shouldn't hurt too much.

Cheers,
   Peter
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [PATCH libinput 3/8] test: Add seat slot tests

2014-03-26 Thread Peter Hutterer
On Tue, Mar 25, 2014 at 09:45:54PM +0100, Jonas Ådahl wrote:
 Add one test that checks uniqueness of seat slots when having multiple
 devices with active touch points.
 
 Add one test that checks that libinput drops touch points when it could
 not represent them with a seat wide slot.
 
 This commit also adds support for from a test case add test devices to
 an existing libinput context. Only litest-genric-highres-touch supports
 this so far and only generic artifical test devices should, in order to
 keep emulated devices closer to their originals.

I'm generally happy with the test itself, but the extension to the litest
framework I'm not convinced.

There are a bunch of tests already that need specific devices and they just
create a uinput device. I've got an unfinished series here that adds a
wrapper to make this easier and with less boilerplate.

My main worries with this here is that the deviceid is part of the
litest_device now but meaningless for all other devices. And for this
specific test you're essentially hiding one of the main features in the
generic_highres device - that it has  MAX_SLOT slots. Plus the extra bits
that elevate litest from a initializes behind the scenes for multiple
devices to something that almost looks like an API when it really doesn't
give you that much benefit over just creating a uinput device. Finally, we
already have generic devices, you could simply add a generic_toomanyslots
device.

I'll try to clean up the uinput wrapper I mentioned above tomorrow, maybe
that will be enough for this patch.

a few other comments inline

 
 Signed-off-by: Jonas Ådahl jad...@gmail.com
 ---
  test/litest-generic-highres-touch.c |  28 +-
  test/litest.c   |  33 ++-
  test/litest.h   |  13 ++-
  test/touch.c| 184 
 
  4 files changed, 251 insertions(+), 7 deletions(-)
 
 diff --git a/test/litest-generic-highres-touch.c 
 b/test/litest-generic-highres-touch.c
 index 68615c3..5f2f023 100644
 --- a/test/litest-generic-highres-touch.c
 +++ b/test/litest-generic-highres-touch.c
 @@ -23,11 +23,22 @@
  
  #include config.h
  
 +#include stdio.h
 +
  #include litest.h
  #include litest-int.h
  #include libinput-util.h
  
 -void litest_generic_highres_touch_setup(void)
 +static int device_ids = 0;
 +
 +static void
 +litest_generic_highres_touch_destroy(struct litest_device *dev)
 +{
 + device_ids = ~dev-device_id;
 +}
 +
 +void
 +litest_generic_highres_touch_setup(void)
  {
   struct litest_device *d =
   litest_create_device(LITEST_GENERIC_HIGHRES_TOUCH);
 @@ -96,22 +107,33 @@ litest_create_generic_highres_touch(struct litest_device 
 *d)
  {
   struct libevdev *dev;
   int rc;
 + int device_id;
 + char name[255];
   struct input_absinfo *a;
   struct input_absinfo abs[] = {
   { ABS_X, 0, 32767, 75 },
   { ABS_Y, 0, 32767, 129 },
 - { ABS_MT_SLOT, 0, 1, 0 },
 + { ABS_MT_SLOT, 0, 40, 0 },
   { ABS_MT_POSITION_X, 0, 32767, 0, 0, 10 },
   { ABS_MT_POSITION_Y, 0, 32767, 0, 0, 9 },
   { ABS_MT_TRACKING_ID, 0, 65535, 0 },
   };
  
   d-interface = interface;
 + d-destroy = litest_generic_highres_touch_destroy;
  
   dev = libevdev_new();
   ck_assert(dev != NULL);
  
 - libevdev_set_name(dev, Generic emulated highres touch device);
 + device_id = ffs(~device_ids) - 1;
 + ck_assert_int_ge(device_id, 0);
 + device_ids |= 1  device_id;
 + d-device_id = device_id;
 + snprintf(name, sizeof name,
 +  Generic emulated highres touch device (%d),
 +  device_id);
 + libevdev_set_name(dev, name);
 +
   libevdev_set_id_bustype(dev, 0x3);
   libevdev_set_id_vendor(dev, 0xabcd); /* Some random vendor. */
   libevdev_set_id_product(dev, 0x1234); /* Some random product id. */
 diff --git a/test/litest.c b/test/litest.c
 index 9241623..0e7da70 100644
 --- a/test/litest.c
 +++ b/test/litest.c
 @@ -328,7 +328,8 @@ const struct libinput_interface interface = {
  };
  
  struct litest_device *
 -litest_create_device(enum litest_device_type which)
 +litest_create_device_for(struct libinput *libinput,
 +  enum litest_device_type which)
  {
   struct litest_device *d = zalloc(sizeof(*d));
   int fd;
 @@ -360,7 +361,7 @@ litest_create_device(enum litest_device_type which)
   rc = libevdev_new_from_fd(fd, d-evdev);
   ck_assert_int_eq(rc, 0);
  
 - d-libinput = libinput_path_create_context(interface, NULL);
 + d-libinput = libinput;
   ck_assert(d-libinput != NULL);
  
   d-libinput_device = libinput_path_add_device(d-libinput, path);
 @@ -374,6 +375,28 @@ litest_create_device(enum litest_device_type which)
   return d;
  }
  
 +struct libinput *
 +litest_create_context(void)
 +{
 + struct libinput *libinput =
 + 

Re: [PATCH libinput 5/8] test: Check that libinput doesn't send double touch down/up events

2014-03-26 Thread Peter Hutterer
On Tue, Mar 25, 2014 at 09:45:56PM +0100, Jonas Ådahl wrote:
 Signed-off-by: Jonas Ådahl jad...@gmail.com
 ---
  test/touch.c | 43 +++
  1 file changed, 43 insertions(+)
 
 diff --git a/test/touch.c b/test/touch.c
 index 61d8762..4a6af21 100644
 --- a/test/touch.c
 +++ b/test/touch.c
 @@ -323,6 +323,47 @@ START_TEST(touch_many_slots)
  }
  END_TEST
  
 +START_TEST(touch_double_touch_down_up)
 +{
 + struct libinput *libinput;
 + struct litest_device *dev;
 + struct libinput_event *ev;
 + bool got_down = false;
 + bool got_up = false;
 +
 + dev = litest_current_device();
 + libinput = dev-libinput;
 +
 + litest_touch_down(dev, 0, 0, 0);
 + litest_touch_down(dev, 0, 0, 0);

with this the kernel will filter the coordinates. This only works because
the tracking_id is automatically picked in touch_down. IMO it might be worth
changing the coordinates here too. It has no real effect but it'll look more
like two touchpoints and the evdev events will be more obvious to read too.

Reviewed-by: Peter Hutterer peter.hutte...@who-t.net
for the patches where I didn't complain about something :)

Cheers,
   Peter

 + litest_touch_up(dev, 0);
 + litest_touch_up(dev, 0);
 +
 + libinput_dispatch(libinput);
 +
 + while ((ev = libinput_get_event(libinput))) {
 + switch (libinput_event_get_type(ev)) {
 + case LIBINPUT_EVENT_TOUCH_DOWN:
 + ck_assert(!got_down);
 + got_down = true;
 + break;
 + case LIBINPUT_EVENT_TOUCH_UP:
 + ck_assert(got_down);
 + ck_assert(!got_up);
 + got_up = true;
 + break;
 + default:
 + break;
 + }
 +
 + libinput_dispatch(libinput);
 + }
 +
 + ck_assert(got_down);
 + ck_assert(got_up);
 +}
 +END_TEST
 +
  int
  main(int argc, char **argv)
  {
 @@ -333,6 +374,8 @@ main(int argc, char **argv)
   litest_add_no_device(touch:seat-slot-drop, touch_seat_slot_drop);
   litest_add(touch:many-slots, touch_many_slots,
  LITEST_TOUCH, LITEST_ANY);
 + litest_add(touch:double-touch-down-up, touch_double_touch_down_up,
 +LITEST_TOUCH, LITEST_ANY);
  
   return litest_run(argc, argv);
  }
 -- 
 1.8.3.2
 
 ___
 wayland-devel mailing list
 wayland-devel@lists.freedesktop.org
 http://lists.freedesktop.org/mailman/listinfo/wayland-devel
 
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput] test: add litest helper functions for creating uinput devices

2014-03-26 Thread Peter Hutterer
Both functions accept a series of event types/codes tuples, terminated by -1.
For the even type INPUT_PROP_MAX (an invalid type otherwise) the code is used
as a property to enable.

The _abs function als takes an array of absinfo, with absinfo.value
determining the axis to change. If none are given, abs axes are initialized
with default settings.

Both functions abort on failure, so the caller does not need to check the
return value.

Example code for creating a rel device:

struct libevdev_uinput *uinput;
struct input_id id = { ... };
uinput = litest_create_uinput_device(foo, id,
 EV_REL, REL_X,
 EV_REL, REL_Y,
 EV_KEY, BTN_LEFT,
 INPUT_PROP_MAX, INPUT_PROP_BUTTONPAD,
 -1);
libevdev_uinput_write_event(uinput, EV_REL, REL_X, -1);
libevdev_uinput_write_event(uinput, EV_SYN, SYN_REPORT, 0);
..
libevdev_uinput_destroy(uinput);

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 test/litest-bcm5974.c   |  43 +++-
 test/litest-generic-highres-touch.c |  34 +++---
 test/litest-synaptics-st.c  |  37 +++
 test/litest-synaptics.c |  43 +++-
 test/litest-trackpoint.c|  32 +++---
 test/litest-wacom-touch.c   |  33 ++
 test/litest.c   |  89 
 test/litest.h   |   9 ++
 test/path.c | 207 
 9 files changed, 244 insertions(+), 283 deletions(-)

diff --git a/test/litest-bcm5974.c b/test/litest-bcm5974.c
index 5a8ce8a..c76a892 100644
--- a/test/litest-bcm5974.c
+++ b/test/litest-bcm5974.c
@@ -95,7 +95,6 @@ static struct litest_device_interface interface = {
 void
 litest_create_bcm5974(struct litest_device *d)
 {
-   struct libevdev *dev;
struct input_absinfo abs[] = {
{ ABS_X, 1472, 5472, 75 },
{ ABS_Y, 1408, 4448, 129 },
@@ -107,34 +106,24 @@ litest_create_bcm5974(struct litest_device *d)
{ ABS_MT_TRACKING_ID, 0, 65535, 0 },
{ ABS_MT_PRESSURE, 0, 255, 0 }
};
-   struct input_absinfo *a;
-   int rc;
+   struct input_id id = {
+   .bustype = 0x3,
+   .vendor = 0x5ac,
+   .product = 0x249,
+   };
 
d-interface = interface;
-
-   dev = libevdev_new();
-   ck_assert(dev != NULL);
-
-   libevdev_set_name(dev, bcm5974);
-   libevdev_set_id_bustype(dev, 0x3);
-   libevdev_set_id_vendor(dev, 0x5ac);
-   libevdev_set_id_product(dev, 0x249);
-   libevdev_enable_event_code(dev, EV_KEY, BTN_LEFT, NULL);
-   libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_FINGER, NULL);
-   libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_QUINTTAP, NULL);
-   libevdev_enable_event_code(dev, EV_KEY, BTN_TOUCH, NULL);
-   libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_DOUBLETAP, NULL);
-   libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_TRIPLETAP, NULL);
-   libevdev_enable_event_code(dev, EV_KEY, BTN_TOOL_QUADTAP, NULL);
-
-   ARRAY_FOR_EACH(abs, a)
-   libevdev_enable_event_code(dev, EV_ABS, a-value, a);
-
-   rc = libevdev_uinput_create_from_device(dev,
-   LIBEVDEV_UINPUT_OPEN_MANAGED,
-   d-uinput);
-   ck_assert_int_eq(rc, 0);
-   libevdev_free(dev);
+   d-uinput = litest_create_uinput_abs_device(bcm5974, id,
+   ARRAY_LENGTH(abs),
+   abs,
+   EV_KEY, BTN_LEFT,
+   EV_KEY, BTN_TOOL_FINGER,
+   EV_KEY, BTN_TOOL_QUINTTAP,
+   EV_KEY, BTN_TOUCH,
+   EV_KEY, BTN_TOOL_DOUBLETAP,
+   EV_KEY, BTN_TOOL_TRIPLETAP,
+   EV_KEY, BTN_TOOL_QUADTAP,
+   -1, -1);
 }
 
 struct litest_test_device litest_bcm5974_device = {
diff --git a/test/litest-generic-highres-touch.c 
b/test/litest-generic-highres-touch.c
index 68615c3..0d239fd 100644
--- a/test/litest-generic-highres-touch.c
+++ b/test/litest-generic-highres-touch.c
@@ -94,9 +94,6 @@ static struct litest_device_interface interface = {
 void
 litest_create_generic_highres_touch(struct litest_device *d)
 {
-   struct libevdev *dev;
-   int rc;
-   struct input_absinfo *a;
struct input_absinfo abs[] = {
{ ABS_X, 0, 32767, 75 },
{ ABS_Y, 0, 32767, 129 },
@@ -105,27 +102,20 @@ litest_create_generic_highres_touch

Re: [RFC] libinput configuration interface

2014-03-27 Thread Peter Hutterer
On Thu, Mar 27, 2014 at 07:34:37PM +0600, Alexander E. Patrakov wrote:
 2014-03-27 19:22 GMT+06:00 Alexander E. Patrakov patra...@gmail.com:
 
 (regarding slow scrolling)
 
  I don't think so. I have tried to reproduce the bug by hand. It still
  exists, but ./tools/event-debug still picks the scrolling up
  correctly. I guess that this tool output already has the finger motion
  averaging logic applied, so this speaks against your hypothesis. An
  interesting observation that can ring some bells: Chromium picks up
  the scroll events if and only if event-debug prints values whose
  absolute value is greater than 10. Maybe the driver fails to combine
  several small scroll events into a big one, or rounds the individual
  scroll amounts instead of the accumulated value?
 
 I have also tested regular (X/Y) pointer motion, and noticed the same
 pattern. event-debug properly reports sub-pixel motion (i.e. prints
 values below 1.0 if I move the finger slowly), but such multiple
 sub-pixel motions are never added up into proper pointer events that
 actually move the X pointer by at least one pixel.

yeah, I found that yesterday and it's a xf86-input-libinput issue.
Conversion to integers would just drop small values. I've pushed a fix to
use valuator masks with doubles now and that seems to fix the issue.
Try 1ab6637b56272bb5cef0568a785e2e5948e6b022.

Cheers,
   Peter
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 2/9] Fix up ARRAY_FOR_EACH macro

2014-03-27 Thread Peter Hutterer
Remove compiler warning about signed/unsigned comparison. And while we're at
it, rename i to _i in the macro to avoid name clashes.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/libinput-util.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libinput-util.h b/src/libinput-util.h
index 2fbce72..c920568 100644
--- a/src/libinput-util.h
+++ b/src/libinput-util.h
@@ -71,7 +71,7 @@ int list_empty(const struct list *list);
 
 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
 #define ARRAY_FOR_EACH(_arr, _elem) \
-   for (int i = 0; (_elem = _arr[i])  i  ARRAY_LENGTH(_arr); i++)
+   for (size_t _i = 0; (_elem = _arr[_i])  _i  ARRAY_LENGTH(_arr); 
_i++)
 
 #define min(a, b) (((a)  (b)) ? (a) : (b))
 #define max(a, b) (((a)  (b)) ? (a) : (b))
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 5/9] test: disable parallel build in test directory

2014-03-27 Thread Peter Hutterer
We depend on device creation on the host system, having the tests run in
parallel runs a risk of random failure.

Ideally we'd just disable for the actual run target, but I couldn't figure out
how to do that.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 test/Makefile.am | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/test/Makefile.am b/test/Makefile.am
index b59d4a9..9b71511 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,4 +1,6 @@
 if BUILD_TESTS
+# Disable parallel build, running tests in parallel will screw things up
+AM_MAKEFLAGS = -j1
 AM_CPPFLAGS = -I$(top_srcdir)/src $(CHECK_CFLAGS) $(LIBEVDEV_CFLAGS)
 
 TEST_LIBS = liblitest.la $(CHECK_LIBS) $(LIBUDEV_LIBS) $(LIBEVDEV_LIBS) 
$(top_builddir)/src/libinput.la -lm
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 9/9] Add libinput_device_get_name() to advertise the kernel name

2014-03-27 Thread Peter Hutterer
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
I didn't end up needing this but it seems a nice to have. However, it does
lead to a discussion on how much of the device should we expose to the
caller through libinput.

Right now libinput hides virtually everthing but the sysname and even that
may not be enough to even get a udev reference. It is enough for now though
because we only handle one subsystem.

If a caller needs settings or get other information on the device, they need
to be able to query udev or the fd, but the latter then needs 
needs open_restricted-like hooks.

 src/libinput.c  |  6 ++
 src/libinput.h  | 12 
 tools/event-debug.c |  5 +++--
 3 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/src/libinput.c b/src/libinput.c
index 1e31be3..2863f1d 100644
--- a/src/libinput.c
+++ b/src/libinput.c
@@ -1043,6 +1043,12 @@ libinput_device_get_user_data(struct libinput_device 
*device)
 }
 
 LIBINPUT_EXPORT const char *
+libinput_device_get_name(struct libinput_device *device)
+{
+   return ((struct evdev_device *) device)-devname;
+}
+
+LIBINPUT_EXPORT const char *
 libinput_device_get_sysname(struct libinput_device *device)
 {
return evdev_device_get_sysname((struct evdev_device *) device);
diff --git a/src/libinput.h b/src/libinput.h
index 6e43181..f291ce8 100644
--- a/src/libinput.h
+++ b/src/libinput.h
@@ -1158,6 +1158,18 @@ libinput_device_get_user_data(struct libinput_device 
*device);
 /**
  * @ingroup device
  *
+ * Get the name of the device.
+ *
+ * @param device A previously obtained device
+ * @return The product name of the device
+ *
+ */
+const char*
+libinput_device_get_name(struct libinput_device *device);
+
+/**
+ * @ingroup device
+ *
  * Get the system name of the device.
  *
  * @param device A previously obtained device
diff --git a/tools/event-debug.c b/tools/event-debug.c
index c0a08a7..3d0a383 100644
--- a/tools/event-debug.c
+++ b/tools/event-debug.c
@@ -231,9 +231,10 @@ print_device_notify(struct libinput_event *ev)
struct libinput_device *dev = libinput_event_get_device(ev);
struct libinput_seat *seat = libinput_device_get_seat(dev);
 
-   printf(%s  %s\n,
+   printf(%s  %s  %s\n,
   libinput_seat_get_physical_name(seat),
-  libinput_seat_get_logical_name(seat));
+  libinput_seat_get_logical_name(seat),
+  libinput_device_get_name(dev));
 }
 
 static void
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 3/9] tools: add --verbose to event-debug

2014-03-27 Thread Peter Hutterer
And redirect the log to stdout. libinput logs to stderr by default, but if
we're running with --verbose we want all msgs on the same stream.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 tools/event-debug.c | 20 +++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/tools/event-debug.c b/tools/event-debug.c
index 12a2df8..c0a08a7 100644
--- a/tools/event-debug.c
+++ b/tools/event-debug.c
@@ -46,11 +46,13 @@ static struct udev *udev;
 uint32_t start_time;
 static const uint32_t screen_width = 100;
 static const uint32_t screen_height = 100;
+static int verbose = 0;
 
 static void
 usage(void)
 {
-   printf(Usage: %s [--udev [seat]|--device /dev/input/event0]\n
+   printf(Usage: %s [--verbose] [--udev [seat]|--device 
/dev/input/event0]\n
+  --verbose ... Print debugging output.\n
   --udev seat Use udev device discovery (default).\n
 Specifying a seat ID is optional.\n
   --device /path/to/device  open the given device only\n,
@@ -67,6 +69,7 @@ parse_args(int argc, char **argv)
{ device, 1, 0, 'd' },
{ udev, 0, 0, 'u' },
{ help, 0, 0, 'h' },
+   { verbose, 0, 0, 'v'},
{ 0, 0, 0, 0}
};
 
@@ -91,6 +94,9 @@ parse_args(int argc, char **argv)
if (optarg)
seat = optarg;
break;
+   case 'v': /* --verbose */
+   verbose = 1;
+   break;
default:
usage();
return 1;
@@ -430,6 +436,13 @@ mainloop(struct libinput *li)
close(fds[1].fd);
 }
 
+static void log_handler(enum libinput_log_priority priority,
+   void *user_data,
+   const char *format, va_list args)
+{
+   vprintf(format, args);
+}
+
 int
 main(int argc, char **argv)
 {
@@ -439,6 +452,11 @@ main(int argc, char **argv)
if (parse_args(argc, argv))
return 1;
 
+   if (verbose) {
+   libinput_log_set_handler(log_handler, NULL);
+   libinput_log_set_priority(LIBINPUT_LOG_PRIORITY_DEBUG);
+   }
+
if (mode == MODE_UDEV) {
if (open_udev(li))
return 1;
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 1/9] Use log_error instead of fprintf in old touchpad code

2014-03-27 Thread Peter Hutterer
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 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 65c5ea0..1a48441 100644
--- a/src/evdev-touchpad.c
+++ b/src/evdev-touchpad.c
@@ -454,7 +454,7 @@ fsm_timeout_handler(void *data)
/* 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);
+   log_error(timerfd read error: %m\n);
 
if (touchpad-fsm.events_count == 0) {
clock_gettime(CLOCK_MONOTONIC, ts);
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 8/9] test: add tests for event conversion and back

2014-03-27 Thread Peter Hutterer
Looks a bit excessive given how simple the base is but hey, we don't want to
ever break that bit. That'd be embarrassing.

And while we're at it make sure that the 'wrong' event getters return NULL for
each event.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
This requires the uinput device creation patch I sent out yesterday.

 test/Makefile.am |   7 +-
 test/misc.c  | 377 +++
 2 files changed, 383 insertions(+), 1 deletion(-)
 create mode 100644 test/misc.c

diff --git a/test/Makefile.am b/test/Makefile.am
index adb58e9..44afc95 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -20,7 +20,7 @@ liblitest_la_SOURCES = \
litest-generic-highres-touch.c \
litest.c
 
-run_tests = test-udev test-path test-pointer test-touch test-log test-touchpad
+run_tests = test-udev test-path test-pointer test-touch test-log test-touchpad 
test-misc
 build_tests = test-build-linker test-build-pedantic-c99 test-build-std-gnuc90
 
 noinst_PROGRAMS = $(build_tests) $(run_tests)
@@ -56,6 +56,11 @@ test_touchpad_CFLAGS = $(AM_CPPFLAGS)
 test_touchpad_LDADD = $(TEST_LIBS)
 test_touchpad_LDFLAGS = -static
 
+test_misc_SOURCES = misc.c
+test_misc_CFLAGS = $(AM_CPPFLAGS)
+test_misc_LDADD = $(TEST_LIBS)
+test_misc_LDFLAGS = -static
+
 # build-test only
 test_build_pedantic_c99_SOURCES = build-pedantic.c
 test_build_pedantic_c99_CFLAGS = $(AM_CPPFLAGS) -std=c99 -pedantic -Werror
diff --git a/test/misc.c b/test/misc.c
new file mode 100644
index 000..5bf9477
--- /dev/null
+++ b/test/misc.c
@@ -0,0 +1,377 @@
+/*
+ * Copyright © 2014 Red Hat, Inc.
+ *
+ * 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 check.h
+#include errno.h
+#include fcntl.h
+#include libinput.h
+#include unistd.h
+
+#include litest.h
+
+static int open_restricted(const char *path, int flags, void *data)
+{
+   int fd = open(path, flags);
+   return fd  0 ? -errno : fd;
+}
+static void close_restricted(int fd, void *data)
+{
+   close(fd);
+}
+
+const struct libinput_interface simple_interface = {
+   .open_restricted = open_restricted,
+   .close_restricted = close_restricted,
+};
+
+static struct libevdev_uinput *
+create_simple_test_device(const char *name, ...)
+{
+   va_list args;
+   struct libevdev_uinput *uinput;
+   struct libevdev *evdev;
+   unsigned int type, code;
+   int rc;
+   struct input_absinfo abs = {
+   .value = -1,
+   .minimum = 0,
+   .maximum = 100,
+   .fuzz = 0,
+   .flat = 0,
+   .resolution = 100,
+   };
+
+   evdev = libevdev_new();
+   ck_assert(evdev != NULL);
+   libevdev_set_name(evdev, name);
+
+   va_start(args, name);
+
+   while ((type = va_arg(args, unsigned int)) != -1 
+  (code = va_arg(args, unsigned int)) != -1) {
+   const struct input_absinfo *a = NULL;
+   if (type == EV_ABS)
+   a = abs;
+   libevdev_enable_event_code(evdev, type, code, a);
+   }
+
+   va_end(args);
+
+   rc = libevdev_uinput_create_from_device(evdev,
+   LIBEVDEV_UINPUT_OPEN_MANAGED,
+   uinput);
+   ck_assert_int_eq(rc, 0);
+   libevdev_free(evdev);
+
+   return uinput;
+}
+
+START_TEST(event_conversion_device_notify)
+{
+   struct libevdev_uinput *uinput;
+   struct libinput *li;
+   struct libinput_event *event;
+   int device_added = 0, device_removed = 0;
+
+   uinput = create_simple_test_device(test device,
+  EV_REL, REL_X,
+  EV_REL, REL_Y,
+  EV_KEY, BTN_LEFT

Re: SynPS/2 Synaptics TouchPad firmware bug

2014-03-27 Thread Peter Hutterer
On Thu, Mar 27, 2014 at 10:19:50PM +0600, Alexander E. Patrakov wrote:
 Hello.
 
 This is a report of a touchpad firmware bug that I want you to work
 around in libinput. I found this bug while testing
 xf86-input-libinput. I guess that the synaptics driver already has a
 workaround, or the bug does not manifest itself with the following
 options:
 
 Option SoftButtonAreas 4360 0 4000 0 2880 4359 3500 0
 Option AreaBottomEdge 3500
 Option VertTwoFingerScroll true
 Option HorizTwoFingerScroll true
 Option MinSpeed 1
 Option MaxSpeed 10
 Option FingerLow 60
 Option FingerHigh 70
 
 (indeed, FingerLow would have prevented this bug for the attached trace).

for the xorg driver this is correct, for libinput it's a bit different. it
largely depends on whether we want the pressure to filter events, or to
filter completely. I haven't done anything in that direction yet at all
though.

 To reproduce the bug, get the affected touchpad, move the cursor as
 you would normally do using a finger on the right hand, then use the
 finger on the left hand to click in the bottom area of the touchpad.
 Usually the driver would register the click as expected, but sometimes
 it would move the pointer to the lower left corner and click there.
 
 I have managed to capture one of these cases using evemu-record. The
 compressed file is attached. Please ignore the first 240 seconds or
 so, they contain some movements, scrolling and clicks.
 
 The interesting part is:
 
 E: 249.206319   #  SYN_REPORT (0) --
 E: 249.218008 0003 0035 3764# EV_ABS / ABS_MT_POSITION_X3764
 E: 249.218008 0003 0036 2221# EV_ABS / ABS_MT_POSITION_Y2221
 E: 249.218008 0003 003a 0065# EV_ABS / ABS_MT_PRESSURE  65
 E: 249.218008 0003  3764# EV_ABS / ABS_X3764
 E: 249.218008 0003 0001 2216# EV_ABS / ABS_Y2216
 E: 249.218008 0003 0018 0065# EV_ABS / ABS_PRESSURE 65
 E: 249.218008   #  SYN_REPORT (0) --
 E: 249.230881 0003 0035 3752# EV_ABS / ABS_MT_POSITION_X3752
 E: 249.230881 0003 003a 0046# EV_ABS / ABS_MT_PRESSURE  46
 E: 249.230881 0003  3758# EV_ABS / ABS_X3758
 E: 249.230881 0003 0018 0046# EV_ABS / ABS_PRESSURE 46
 E: 249.230881   #  SYN_REPORT (0) --
 E: 249.242648 0003 0035 1640# EV_ABS / ABS_MT_POSITION_X1640
 E: 249.242648 0003 0036 4681# EV_ABS / ABS_MT_POSITION_Y4681
 E: 249.242648 0003 003a 0025# EV_ABS / ABS_MT_PRESSURE  25
 E: 249.242648 0003  1640# EV_ABS / ABS_X1640
 E: 249.242648 0003 0001 4681# EV_ABS / ABS_Y4681
 E: 249.242648 0003 0018 0025# EV_ABS / ABS_PRESSURE 25
 E: 249.242648   #  SYN_REPORT (0) --
 E: 249.254568 0003 0035 1648# EV_ABS / ABS_MT_POSITION_X1648
 E: 249.254568 0003 003a 0027# EV_ABS / ABS_MT_PRESSURE  27
 E: 249.254568 0003  1644# EV_ABS / ABS_X1644
 E: 249.254568 0003 0018 0027# EV_ABS / ABS_PRESSURE 27
 
 As you see, the touchpad reports a huge jump in the touch position
 without getting a new tracking ID. I.e. produces garbage data. A
 non-buggy touchpad would have recognized that this is in fact a
 different finger.
 
 So, I would like libinput to recognize such huge jumps (e.g. any
 movements by more than 15% of the touchpad width in less than 0.03
 seconds) as firmware bugs and treat them as if this indicated a
 completely new touch.

please file this in bugzilla, this really is something that we need to keep
in one place because it'll likely have a rather complex solution that I'd
like to be able to link to.

having said that, I'm currently struggling with getting libinput up to
feature parity with the xorg drivers, hacking around broken devices will
have to wait a bit, sorry.

Cheers,
   Peter


___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 6/9] doc: add state machine SVG to EXTRA_DIST

2014-03-28 Thread Peter Hutterer
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 doc/Makefile.am | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/doc/Makefile.am b/doc/Makefile.am
index 31b673b..75fa98a 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,3 +1,5 @@
+EXTRA_DIST = touchpad-tap-state-machine.svg
+
 if HAVE_DOXYGEN
 
 noinst_DATA = html/index.html
@@ -12,7 +14,7 @@ clean-local:
$(AM_V_at)rm -rf html
 
 doc_src= $(shell find html -type f -printf html/%P\n 2/dev/null)
-EXTRA_DIST = $(builddir)/html/index.html $(doc_src)
+EXTRA_DIST += $(builddir)/html/index.html $(doc_src)
 
 endif
 
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 8/9] touchpad: Only enable clickfingers on Apple touchpads

2014-03-28 Thread Peter Hutterer
Apple touchpads don't have visible markings for the software button areas
that almost all other vendors use. OS X provides clickfinger behaviour
instead, where a click with two fingers on the touchpad generate a right
button click. Use that same behaviour in libinput.

For all other touchpads, use the software button areas introduced in a
follow-up commit.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
This should probably be configurable at some point in the future...

 src/evdev-mt-touchpad-buttons.c |  7 ++-
 src/evdev-mt-touchpad.h |  1 +
 test/touchpad.c | 12 
 3 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c
index c3c97b0..08783a3 100644
--- a/src/evdev-mt-touchpad-buttons.c
+++ b/src/evdev-mt-touchpad-buttons.c
@@ -60,6 +60,11 @@ tp_init_buttons(struct tp_dispatch *tp,
 
tp-buttons.motion_dist = diagonal * DEFAULT_BUTTON_MOTION_THRESHOLD;
 
+   if (libevdev_get_id_vendor(device-evdev) == 0x5ac) /* Apple */
+   tp-buttons.use_clickfinger = true;
+   else
+   tp-buttons.use_clickfinger = false;
+
return 0;
 }
 
@@ -142,7 +147,7 @@ tp_post_button_events(struct tp_dispatch *tp, uint32_t time)
 
if (tp-buttons.has_buttons)
rc = tp_post_physical_buttons(tp, time);
-   else
+   else if (tp-buttons.use_clickfinger)
rc = tp_post_clickfinger_buttons(tp, time);
 
return rc;
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 1dee663..f3e5b31 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -135,6 +135,7 @@ struct tp_dispatch {
 
struct {
bool has_buttons;   /* true for physical LMR 
buttons */
+   bool use_clickfinger;   /* number of fingers decides 
button number */
uint32_t state;
uint32_t old_state;
uint32_t motion_dist;   /* for pinned touches */
diff --git a/test/touchpad.c b/test/touchpad.c
index f4d7839..bbae6cd 100644
--- a/test/touchpad.c
+++ b/test/touchpad.c
@@ -217,7 +217,7 @@ END_TEST
 
 START_TEST(touchpad_1fg_clickfinger)
 {
-   struct litest_device *dev = litest_current_device();
+   struct litest_device *dev = litest_create_device(LITEST_BCM5974);
struct libinput *li = dev-libinput;
struct libinput_event *event;
struct libinput_event_pointer *ptrev;
@@ -237,12 +237,14 @@ START_TEST(touchpad_1fg_clickfinger)
LIBINPUT_POINTER_BUTTON_STATE_PRESSED);
assert_button_event(li, BTN_LEFT,
LIBINPUT_POINTER_BUTTON_STATE_RELEASED);
+
+   litest_delete_device(dev);
 }
 END_TEST
 
 START_TEST(touchpad_2fg_clickfinger)
 {
-   struct litest_device *dev = litest_current_device();
+   struct litest_device *dev = litest_create_device(LITEST_BCM5974);
struct libinput *li = dev-libinput;
struct libinput_event *event;
struct libinput_event_pointer *ptrev;
@@ -264,6 +266,8 @@ START_TEST(touchpad_2fg_clickfinger)
LIBINPUT_POINTER_BUTTON_STATE_PRESSED);
assert_button_event(li, BTN_RIGHT,
LIBINPUT_POINTER_BUTTON_STATE_RELEASED);
+
+   litest_delete_device(dev);
 }
 END_TEST
 
@@ -362,8 +366,8 @@ int main(int argc, char **argv) {
litest_add(touchpad:tap, touchpad_1fg_tap_n_drag, LITEST_TOUCHPAD, 
LITEST_ANY);
litest_add(touchpad:tap, touchpad_2fg_tap, LITEST_TOUCHPAD, 
LITEST_SINGLE_TOUCH);
 
-   litest_add(touchpad:clickfinger, touchpad_1fg_clickfinger, 
LITEST_TOUCHPAD, LITEST_ANY);
-   litest_add(touchpad:clickfinger, touchpad_2fg_clickfinger, 
LITEST_TOUCHPAD, LITEST_SINGLE_TOUCH);
+   litest_add_no_device(touchpad:clickfinger, touchpad_1fg_clickfinger);
+   litest_add_no_device(touchpad:clickfinger, touchpad_2fg_clickfinger);
 
litest_add(touchpad:click, touchpad_btn_left, LITEST_TOUCHPAD, 
LITEST_CLICKPAD);
litest_add(touchpad:click, clickpad_btn_left, LITEST_CLICKPAD, 
LITEST_ANY);
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 7/9] touchpad: save the active clickfinger button

2014-03-28 Thread Peter Hutterer
To avoid having a button left press and a button right release if the number
of fingers changes.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad-buttons.c | 22 +-
 src/evdev-mt-touchpad.h |  1 +
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/src/evdev-mt-touchpad-buttons.c b/src/evdev-mt-touchpad-buttons.c
index 8946fc7..c3c97b0 100644
--- a/src/evdev-mt-touchpad-buttons.c
+++ b/src/evdev-mt-touchpad-buttons.c
@@ -75,23 +75,27 @@ tp_post_clickfinger_buttons(struct tp_dispatch *tp, 
uint32_t time)
if (current == old)
return 0;
 
-   switch (tp-nfingers_down) {
+   if (current) {
+   switch (tp-nfingers_down) {
case 1: button = BTN_LEFT; break;
case 2: button = BTN_RIGHT; break;
case 3: button = BTN_MIDDLE; break;
default:
return 0;
-   }
-
-   if (current)
+   }
+   tp-buttons.active = button;
state = LIBINPUT_POINTER_BUTTON_STATE_PRESSED;
-   else
+   } else {
+   button = tp-buttons.active;
+   tp-buttons.active = 0;
state = LIBINPUT_POINTER_BUTTON_STATE_RELEASED;
+   }
 
-   pointer_notify_button(tp-device-base,
- time,
- button,
- state);
+   if (button)
+   pointer_notify_button(tp-device-base,
+ time,
+ button,
+ state);
return 1;
 }
 
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 0879776..1dee663 100644
--- a/src/evdev-mt-touchpad.h
+++ b/src/evdev-mt-touchpad.h
@@ -138,6 +138,7 @@ struct tp_dispatch {
uint32_t state;
uint32_t old_state;
uint32_t motion_dist;   /* for pinned touches */
+   unsigned int active;/* currently active button, for 
release event */
} buttons;  /* physical buttons */
 
struct {
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 4/9] touchpad: don't allow tapping while any button is down

2014-03-28 Thread Peter Hutterer
Immediately set the state to DEAD, waiting for the tap release to go back to
idle.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad-tap.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c
index bcc5700..863e004 100644
--- a/src/evdev-mt-touchpad-tap.c
+++ b/src/evdev-mt-touchpad-tap.c
@@ -508,7 +508,7 @@ tp_tap_handle_state(struct tp_dispatch *tp, uint32_t time)
struct tp_touch *t;
int filter_motion = 0;
 
-   if (tp-queued  TOUCHPAD_EVENT_BUTTON_PRESS)
+   if (tp-buttons.state != 0)
tp_tap_handle_event(tp, TAP_EVENT_BUTTON, time);
 
tp_for_each_touch(tp, t) {
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 2/9] touchpad: after a click, lock the finger to its current position

2014-03-28 Thread Peter Hutterer
On clickpads, releasing the button usually causes some motion events. To avoid
erroneous movements, lock the finger into position on the up event and don't
allow for motion events until we move past a given threshold (currently 2% of
the touchpad diagonal).

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad.c | 70 +
 src/evdev-mt-touchpad.h | 18 -
 2 files changed, 64 insertions(+), 24 deletions(-)

diff --git a/src/evdev-mt-touchpad.c b/src/evdev-mt-touchpad.c
index 8021db2..5318b8f 100644
--- a/src/evdev-mt-touchpad.c
+++ b/src/evdev-mt-touchpad.c
@@ -32,6 +32,7 @@
 #define DEFAULT_MIN_ACCEL_FACTOR 0.16
 #define DEFAULT_MAX_ACCEL_FACTOR 1.0
 #define DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR 700.0
+#define DEFAULT_BUTTON_MOTION_THRESHOLD 0.02 /* in percent of size */
 
 static inline int
 tp_hysteresis(int in, int center, int margin)
@@ -346,16 +347,36 @@ tp_process_key(struct tp_dispatch *tp,
 }
 
 static void
-tp_unpin_finger(struct tp_dispatch *tp)
+tp_unpin_finger(struct tp_dispatch *tp, struct tp_touch *t)
+{
+   unsigned int xdist, ydist;
+
+   if (t-pinned.state != PIN_STATE_UP)
+   return;
+
+   xdist = abs(t-x - t-pinned.center_x);
+   ydist = abs(t-y - t-pinned.center_y);
+
+   if (xdist * xdist + ydist * ydist 
+   tp-buttons.motion_dist * tp-buttons.motion_dist)
+   return;
+
+   t-pinned.state = PIN_STATE_NONE;
+
+   if (t-state != TOUCH_END  tp-nfingers_down == 1)
+   t-is_pointer = true;
+}
+
+static void
+tp_lift_pinned_finger(struct tp_dispatch *tp)
 {
struct tp_touch *t;
+
tp_for_each_touch(tp, t) {
-   if (t-is_pinned) {
-   t-is_pinned = false;
-
-   if (t-state != TOUCH_END 
-   tp-nfingers_down == 1)
-   t-is_pointer = true;
+   if (t-pinned.state == PIN_STATE_DOWN) {
+   t-pinned.state = PIN_STATE_UP;
+   t-pinned.center_x = t-x;
+   t-pinned.center_y = t-y;
break;
}
}
@@ -368,15 +389,14 @@ tp_pin_finger(struct tp_dispatch *tp)
*pinned = NULL;
 
tp_for_each_touch(tp, t) {
-   if (t-is_pinned) {
+   if (t-pinned.state != PIN_STATE_NONE) {
pinned = t;
break;
}
}
 
-   assert(!pinned);
-
-   pinned = tp_current_touch(tp);
+   if (!pinned)
+   pinned = tp_current_touch(tp);
 
if (tp-nfingers_down != 1) {
tp_for_each_touch(tp, t) {
@@ -388,7 +408,7 @@ tp_pin_finger(struct tp_dispatch *tp)
}
}
 
-   pinned-is_pinned = true;
+   pinned-pinned.state = PIN_STATE_DOWN;
pinned-is_pointer = false;
 }
 
@@ -409,16 +429,21 @@ tp_process_state(struct tp_dispatch *tp, uint32_t time)
 
tp_motion_hysteresis(tp, t);
tp_motion_history_push(t);
+
+   tp_unpin_finger(tp, t);
}
 
-   /* We have a physical button down event on a clickpad. For drag and
-  drop, this means we try to identify which finger pressed the
-  physical button and pin it, i.e. remove pointer-moving
-  capabilities from it.
-*/
-   if ((tp-queued  TOUCHPAD_EVENT_BUTTON_PRESS) 
-   !tp-buttons.has_buttons)
-   tp_pin_finger(tp);
+   if (!tp-buttons.has_buttons) {
+   /* We have a physical button down event on a clickpad. For drag 
and
+  drop, this means we try to identify which finger pressed the
+  physical button and pin it, i.e. remove pointer-moving
+  capabilities from it.
+*/
+   if (tp-queued  TOUCHPAD_EVENT_BUTTON_PRESS)
+   tp_pin_finger(tp);
+   else if ((tp-queued  TOUCHPAD_EVENT_BUTTON_RELEASE))
+   tp_lift_pinned_finger(tp);
+   }
 }
 
 static void
@@ -441,9 +466,6 @@ tp_post_process_state(struct tp_dispatch *tp, uint32_t time)
 
tp-buttons.old_state = tp-buttons.state;
 
-   if (tp-queued  TOUCHPAD_EVENT_BUTTON_RELEASE)
-   tp_unpin_finger(tp);
-
tp-queued = TOUCHPAD_EVENT_NONE;
 }
 
@@ -796,6 +818,8 @@ tp_init(struct tp_dispatch *tp,
tp-hysteresis.margin_y =
diagonal / DEFAULT_HYSTERESIS_MARGIN_DENOMINATOR;
 
+   tp-buttons.motion_dist = diagonal * DEFAULT_BUTTON_MOTION_THRESHOLD;
+
if (libevdev_has_event_code(device-evdev, EV_KEY, BTN_MIDDLE) ||
libevdev_has_event_code(device-evdev, EV_KEY, BTN_RIGHT))
tp-buttons.has_buttons = true;
diff --git a/src/evdev-mt-touchpad.h b/src/evdev-mt-touchpad.h
index 2bdb329..51e7702 100644
--- a/src/evdev-mt-touchpad.h

[PATCH libinput 3/9] touchpad: reset the tap timer_fd to -1 on destroy

2014-03-28 Thread Peter Hutterer
No real effect, just for safety

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 src/evdev-mt-touchpad-tap.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/evdev-mt-touchpad-tap.c b/src/evdev-mt-touchpad-tap.c
index 5fa712f..bcc5700 100644
--- a/src/evdev-mt-touchpad-tap.c
+++ b/src/evdev-mt-touchpad-tap.c
@@ -615,6 +615,8 @@ tp_destroy_tap(struct tp_dispatch *tp)
libinput_remove_source(tp-device-base.seat-libinput, 
tp-tap.source);
tp-tap.source = NULL;
}
-   if (tp-tap.timer_fd  -1)
+   if (tp-tap.timer_fd  -1) {
close(tp-tap.timer_fd);
+   tp-tap.timer_fd = -1;
+   }
 }
-- 
1.8.5.3

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: SynPS/2 Synaptics TouchPad firmware bug

2014-03-28 Thread Peter Hutterer

On 29/03/2014 04:54 , Alexander E. Patrakov wrote:

2014-03-29 0:16 GMT+06:00 Alexander E. Patrakov patra...@gmail.com:

No problem, I just did that for you. See the attached patch. Seems to
work here, but I am not 100% sure, especially about the non-mt case.
It does prevent sudden pointer jumps to the bottom left corner of the
screen (survived a while round of the Harvest Honors game, something
that the original driver cound not do!), but I also get some click
attempts mistreated as right-clicks. Probably because there are in
fact some moments when the touchpad thinks that two fingers are on it.


And now rebased on top of your wip/clickpad-improvements branch (which
works otherwise). Note that now I can get a right-click both using a
software button area and using a two-finger tap. Is this intentional?


yes, tapping and software button areas are independent of each other and 
are enabled at the same time. clickfinger and software buttons are 
mutually exclusive (and the former is only enabled on apple touchpads 
anyway). Other than that anytime a click isn't what you expect it to be 
is likely a bug.


Cheers,
  Peter

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


Re: [libinput] AC_PROG_CXX missing in libinput/configure.ac

2014-03-30 Thread Peter Hutterer
On Sat, Mar 29, 2014 at 07:12:59PM +0100, Sylvain BERTRAND wrote:
 On Sat, Mar 29, 2014 at 06:59:12PM +0100, Jonas Ådahl wrote:
  Yes, for now at least.
 
 Sad.
 
 But till there is no crazy code generator, it should be easy
 to write a makefile/shell script to by-pass the autotools and
 build the lib.

note that the only binary that needs a C++ compiler is the C++ build test.
the library itself only needs a C compiler.

Cheers,
   Peter
___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 2/5] test: if no teardown func is set, use the default

2014-03-31 Thread Peter Hutterer
Reduces the amount of boilerplate code.

Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 test/litest-bcm5974.c   | 2 +-
 test/litest-generic-highres-touch.c | 2 +-
 test/litest-keyboard.c  | 2 +-
 test/litest-mouse.c | 2 +-
 test/litest-synaptics-st.c  | 2 +-
 test/litest-trackpoint.c| 2 +-
 test/litest-wacom-touch.c   | 2 +-
 test/litest.c   | 3 ++-
 8 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/test/litest-bcm5974.c b/test/litest-bcm5974.c
index 6b7a22b..ff822f9 100644
--- a/test/litest-bcm5974.c
+++ b/test/litest-bcm5974.c
@@ -131,6 +131,6 @@ struct litest_test_device litest_bcm5974_device = {
.features = LITEST_TOUCHPAD | LITEST_CLICKPAD | LITEST_BUTTON,
.shortname = bcm5974,
.setup = litest_bcm5974_setup,
-   .teardown = litest_generic_device_teardown,
+   .teardown = NULL,
.create = litest_create_bcm5974,
 };
diff --git a/test/litest-generic-highres-touch.c 
b/test/litest-generic-highres-touch.c
index bb226d6..4d21b0d 100644
--- a/test/litest-generic-highres-touch.c
+++ b/test/litest-generic-highres-touch.c
@@ -123,6 +123,6 @@ struct litest_test_device 
litest_generic_highres_touch_device = {
.features = LITEST_TOUCH,
.shortname = generic-highres-touch,
.setup = litest_generic_highres_touch_setup,
-   .teardown = litest_generic_device_teardown,
+   .teardown = NULL,
.create = litest_create_generic_highres_touch,
 };
diff --git a/test/litest-keyboard.c b/test/litest-keyboard.c
index dd91158..ab05014 100644
--- a/test/litest-keyboard.c
+++ b/test/litest-keyboard.c
@@ -109,6 +109,6 @@ struct litest_test_device litest_keyboard_device = {
.features = LITEST_KEYS,
.shortname = default keyboard,
.setup = litest_keyboard_setup,
-   .teardown = litest_generic_device_teardown,
+   .teardown = NULL,
.create = litest_create_keyboard,
 };
diff --git a/test/litest-mouse.c b/test/litest-mouse.c
index 2fde095..2f70767 100644
--- a/test/litest-mouse.c
+++ b/test/litest-mouse.c
@@ -70,6 +70,6 @@ struct litest_test_device litest_mouse_device = {
.features = LITEST_POINTER | LITEST_BUTTON | LITEST_WHEEL,
.shortname = mouse,
.setup = litest_mouse_setup,
-   .teardown = litest_generic_device_teardown,
+   .teardown = NULL,
.create = litest_create_mouse,
 };
diff --git a/test/litest-synaptics-st.c b/test/litest-synaptics-st.c
index d13d9a2..de56c22 100644
--- a/test/litest-synaptics-st.c
+++ b/test/litest-synaptics-st.c
@@ -126,6 +126,6 @@ struct litest_test_device litest_synaptics_touchpad_device 
= {
.features = LITEST_TOUCHPAD | LITEST_BUTTON | LITEST_SINGLE_TOUCH,
.shortname = synaptics ST,
.setup = litest_synaptics_touchpad_setup,
-   .teardown = litest_generic_device_teardown,
+   .teardown = NULL,
.create = litest_create_synaptics_touchpad,
 };
diff --git a/test/litest-trackpoint.c b/test/litest-trackpoint.c
index e0b79c5..1c0fb0a 100644
--- a/test/litest-trackpoint.c
+++ b/test/litest-trackpoint.c
@@ -61,6 +61,6 @@ struct litest_test_device litest_trackpoint_device = {
.features = LITEST_POINTER | LITEST_BUTTON,
.shortname = trackpoint,
.setup = litest_trackpoint_setup,
-   .teardown = litest_generic_device_teardown,
+   .teardown = NULL,
.create = litest_create_trackpoint,
 };
diff --git a/test/litest-wacom-touch.c b/test/litest-wacom-touch.c
index 01a5a5d..e9119a9 100644
--- a/test/litest-wacom-touch.c
+++ b/test/litest-wacom-touch.c
@@ -122,6 +122,6 @@ struct litest_test_device litest_wacom_touch_device = {
.features = LITEST_TOUCH,
.shortname = wacom-touch,
.setup = litest_wacom_touch_setup,
-   .teardown = litest_generic_device_teardown,
+   .teardown = NULL,
.create = litest_create_wacom_touch,
 };
diff --git a/test/litest.c b/test/litest.c
index f7fe24e..6767952 100644
--- a/test/litest.c
+++ b/test/litest.c
@@ -119,7 +119,8 @@ litest_add_tcase_for_device(struct suite *suite,
t-name = strdup(test_name);
t-tc = tcase_create(test_name);
list_insert(suite-tests, t-node);
-   tcase_add_checked_fixture(t-tc, dev-setup, dev-teardown);
+   tcase_add_checked_fixture(t-tc, dev-setup,
+ dev-teardown ? dev-teardown : 
litest_generic_device_teardown);
tcase_add_test(t-tc, func);
suite_add_tcase(suite-suite, t-tc);
 }
-- 
1.9.0

___
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel


[PATCH libinput 5/5] test: switch the remaining devices to a description-based device

2014-03-31 Thread Peter Hutterer
Signed-off-by: Peter Hutterer peter.hutte...@who-t.net
---
 test/litest-bcm5974.c   | 147 ++-
 test/litest-generic-highres-touch.c | 128 
 test/litest-keyboard.c  | 231 +---
 test/litest-mouse.c |  48 
 test/litest-synaptics-st.c  | 131 
 test/litest-trackpoint.c|  39 +++---
 test/litest-wacom-touch.c   | 127 
 7 files changed, 419 insertions(+), 432 deletions(-)

diff --git a/test/litest-bcm5974.c b/test/litest-bcm5974.c
index ff822f9..ab944a7 100644
--- a/test/litest-bcm5974.c
+++ b/test/litest-bcm5974.c
@@ -34,97 +34,66 @@ static void litest_bcm5974_setup(void)
litest_set_current_device(d);
 }
 
-static void
-litest_bcm5974_touch_down(struct litest_device *d,
- unsigned int slot,
- int x, int y)
-{
-   static int tracking_id;
-   struct input_event *ev;
-   struct input_event down[] = {
-   { .type = EV_KEY, .code = BTN_TOOL_FINGER, .value = 1 },
-   { .type = EV_KEY, .code = BTN_TOUCH, .value = 1 },
-   { .type = EV_ABS, .code = ABS_X, .value = x  },
-   { .type = EV_ABS, .code = ABS_Y, .value = y },
-   { .type = EV_ABS, .code = ABS_PRESSURE, .value = 30  },
-   { .type = EV_ABS, .code = ABS_MT_SLOT, .value = slot },
-   { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = 
++tracking_id },
-   { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = x },
-   { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = y },
-   { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
-   };
+struct input_event down[] = {
+   { .type = EV_KEY, .code = BTN_TOOL_FINGER, .value = 1 },
+   { .type = EV_KEY, .code = BTN_TOUCH, .value = 1 },
+   { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN  },
+   { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
+   { .type = EV_ABS, .code = ABS_PRESSURE, .value = 30  },
+   { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
+   { .type = EV_ABS, .code = ABS_MT_TRACKING_ID, .value = 
LITEST_AUTO_ASSIGN },
+   { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = 
LITEST_AUTO_ASSIGN },
+   { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = 
LITEST_AUTO_ASSIGN },
+   { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+   { .type = -1, .code = -1 },
+};
 
-   down[2].value = litest_scale(d, ABS_X, x);
-   down[3].value = litest_scale(d, ABS_Y, y);
-   down[7].value = litest_scale(d, ABS_X, x);
-   down[8].value = litest_scale(d, ABS_Y, y);
-
-   ARRAY_FOR_EACH(down, ev)
-   litest_event(d, ev-type, ev-code, ev-value);
-}
-
-void
-litest_bcm5974_move(struct litest_device *d, unsigned int slot, int x, int y)
-{
-   struct input_event *ev;
-   struct input_event move[] = {
-   { .type = EV_ABS, .code = ABS_MT_SLOT, .value = slot },
-   { .type = EV_ABS, .code = ABS_X, .value = x  },
-   { .type = EV_ABS, .code = ABS_Y, .value = y },
-   { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = x },
-   { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = y },
-   { .type = EV_KEY, .code = BTN_TOOL_FINGER, .value = 1 },
-   { .type = EV_KEY, .code = BTN_TOUCH, .value = 1 },
-   { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
-   };
-
-   move[1].value = litest_scale(d, ABS_X, x);
-   move[2].value = litest_scale(d, ABS_Y, y);
-   move[3].value = litest_scale(d, ABS_X, x);
-   move[4].value = litest_scale(d, ABS_Y, y);
-
-   ARRAY_FOR_EACH(move, ev)
-   litest_event(d, ev-type, ev-code, ev-value);
-}
+static struct input_event move[] = {
+   { .type = EV_ABS, .code = ABS_MT_SLOT, .value = LITEST_AUTO_ASSIGN },
+   { .type = EV_ABS, .code = ABS_X, .value = LITEST_AUTO_ASSIGN },
+   { .type = EV_ABS, .code = ABS_Y, .value = LITEST_AUTO_ASSIGN },
+   { .type = EV_ABS, .code = ABS_MT_POSITION_X, .value = 
LITEST_AUTO_ASSIGN },
+   { .type = EV_ABS, .code = ABS_MT_POSITION_Y, .value = 
LITEST_AUTO_ASSIGN },
+   { .type = EV_KEY, .code = BTN_TOOL_FINGER, .value = 1 },
+   { .type = EV_KEY, .code = BTN_TOUCH, .value = 1 },
+   { .type = EV_SYN, .code = SYN_REPORT, .value = 0 },
+   { .type = -1, .code = -1 },
+};
 
 static struct litest_device_interface interface = {
-   .touch_down = litest_bcm5974_touch_down,
-   .touch_move = litest_bcm5974_move,
+   .touch_down_events = down,
+   .touch_move_events = move,
 };
 
-void
-litest_create_bcm5974(struct litest_device *d)
-{
-   struct input_absinfo abs[] = {
-   { ABS_X, 1472, 5472, 75 },
-   { ABS_Y, 1408, 4448, 129

  1   2   3   4   5   6   7   8   9   10   >