Re: [PATCH libinput] tablet: handle custom proximity handling
On Thu, Dec 03, 2015 at 02:37:26PM +0100, Hans de Goede wrote: > Hi, > > On 03-12-15 00:57, Peter Hutterer wrote: > >For the puck/lens cursor tool we need to artificially reduce proximity > >detection. These tools are usually used in a relative mode (i.e. like a > >mouse) > >and thus require lifting and resetting the tool multiple times to move across > >the screen. The tablets' distance detection goes too far, requiring the user > >to lift the device several cm on every move. This is uncomfortable. > > > >Introduce an artificial distance threshold for the devices with the default > >value taken from the X.Org wacom driver. If a tool is in proximity but > >outside > >of this range, fake proximity events accordingly. > > > >If a button was pressed while we were out of range we discard that event and > >send it later when we enter proximity again. > > > >This is the simple implementation that only takes one proximity out value > >(the > >one from the wacom driver) and applies it to all. Those devices that support > >a > >button/lens tool and have a different default threshold are well out of date. > > > >Signed-off-by: Peter Hutterer > > Patch looks good to me: > > Reviewed-by: Hans de Goede > > Regards, > > Hans > > p.s. > > I've a (serial!) graphire tablet, and I'm sure there are also quite a few > usb graphire tablets out there, so we do need to deal with supporting the > mouse on the graphire tablet eventually. maybe. I don't doubt that the tablets are still out there and used, I just thing that there is only a small number of those tablets being used together with the mouse :) Cheers, Peter > >--- > > src/evdev-tablet.c | 103 - > > src/evdev-tablet.h | 3 + > > test/litest.c | 18 + > > test/litest.h | 3 +- > > test/tablet.c | 221 > > + > > 5 files changed, 346 insertions(+), 2 deletions(-) > > > >diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c > >index 7e3298c..777ffad 100644 > >--- a/src/evdev-tablet.c > >+++ b/src/evdev-tablet.c > >@@ -67,6 +67,22 @@ tablet_get_released_buttons(struct tablet_dispatch > >*tablet, > > ~(state->stylus_buttons[i]); > > } > > > >+/* Merge the previous state with the current one so all buttons look like > >+ * they just got pressed in this frame */ > >+static inline void > >+tablet_force_button_presses(struct tablet_dispatch *tablet) > >+{ > >+struct button_state *state = &tablet->button_state, > >+*prev_state = &tablet->prev_button_state; > >+size_t i; > >+ > >+for (i = 0; i < sizeof(state->stylus_buttons); i++) { > >+state->stylus_buttons[i] = state->stylus_buttons[i] | > >+prev_state->stylus_buttons[i]; > >+prev_state->stylus_buttons[i] = 0; > >+} > >+} > >+ > > static int > > tablet_device_has_axis(struct tablet_dispatch *tablet, > >enum libinput_tablet_tool_axis axis) > >@@ -994,6 +1010,62 @@ sanitize_tablet_axes(struct tablet_dispatch *tablet) > > } > > > > static void > >+tablet_update_proximity_state(struct tablet_dispatch *tablet, > >+ struct evdev_device *device) > >+{ > >+const struct input_absinfo *distance; > >+int dist_max = tablet->cursor_proximity_threshold; > >+int dist; > >+ > >+distance = libevdev_get_abs_info(tablet->device->evdev, ABS_DISTANCE); > >+if (!distance) > >+return; > >+ > >+dist = distance->value; > >+if (dist == 0) > >+return; > >+ > >+/* Tool got into permitted range */ > >+if (dist < dist_max && > >+(tablet_has_status(tablet, TABLET_TOOL_OUT_OF_RANGE) || > >+ tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY))) { > >+tablet_unset_status(tablet, > >+TABLET_TOOL_OUT_OF_RANGE); > >+tablet_unset_status(tablet, > >+TABLET_TOOL_OUT_OF_PROXIMITY); > >+tablet_set_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY); > >+tablet_mark_all_axes_changed(tablet, device); > >+ > >+tablet_set_status(tablet, TABLET_BUTTONS_PRESSED); > >+tablet_force_button_presses(tablet); > >+return; > >+} > >+ > >+if (dist < dist_max) > >+return; > >+ > >+/* Still out of range/proximity */ > >+if (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_RANGE) || > >+tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY)) > >+return; > >+ > >+/* Tool entered prox but is outside of permitted range */ > >+if (tablet_has_status(tablet, > >+ TABLET_TOOL_ENTERING_PROXIMITY)) { > >+tablet_set_status(tablet, > >+ TABLET_TOOL_OUT_OF_RANGE); > >+tablet_unset_status(tablet, > >+TABLET_TOOL_ENTER
Re: [PATCH libinput] tablet: handle custom proximity handling
Hi, On 03-12-15 00:57, Peter Hutterer wrote: For the puck/lens cursor tool we need to artificially reduce proximity detection. These tools are usually used in a relative mode (i.e. like a mouse) and thus require lifting and resetting the tool multiple times to move across the screen. The tablets' distance detection goes too far, requiring the user to lift the device several cm on every move. This is uncomfortable. Introduce an artificial distance threshold for the devices with the default value taken from the X.Org wacom driver. If a tool is in proximity but outside of this range, fake proximity events accordingly. If a button was pressed while we were out of range we discard that event and send it later when we enter proximity again. This is the simple implementation that only takes one proximity out value (the one from the wacom driver) and applies it to all. Those devices that support a button/lens tool and have a different default threshold are well out of date. Signed-off-by: Peter Hutterer Patch looks good to me: Reviewed-by: Hans de Goede Regards, Hans p.s. I've a (serial!) graphire tablet, and I'm sure there are also quite a few usb graphire tablets out there, so we do need to deal with supporting the mouse on the graphire tablet eventually. --- src/evdev-tablet.c | 103 - src/evdev-tablet.h | 3 + test/litest.c | 18 + test/litest.h | 3 +- test/tablet.c | 221 + 5 files changed, 346 insertions(+), 2 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 7e3298c..777ffad 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -67,6 +67,22 @@ tablet_get_released_buttons(struct tablet_dispatch *tablet, ~(state->stylus_buttons[i]); } +/* Merge the previous state with the current one so all buttons look like + * they just got pressed in this frame */ +static inline void +tablet_force_button_presses(struct tablet_dispatch *tablet) +{ + struct button_state *state = &tablet->button_state, + *prev_state = &tablet->prev_button_state; + size_t i; + + for (i = 0; i < sizeof(state->stylus_buttons); i++) { + state->stylus_buttons[i] = state->stylus_buttons[i] | + prev_state->stylus_buttons[i]; + prev_state->stylus_buttons[i] = 0; + } +} + static int tablet_device_has_axis(struct tablet_dispatch *tablet, enum libinput_tablet_tool_axis axis) @@ -994,6 +1010,62 @@ sanitize_tablet_axes(struct tablet_dispatch *tablet) } static void +tablet_update_proximity_state(struct tablet_dispatch *tablet, + struct evdev_device *device) +{ + const struct input_absinfo *distance; + int dist_max = tablet->cursor_proximity_threshold; + int dist; + + distance = libevdev_get_abs_info(tablet->device->evdev, ABS_DISTANCE); + if (!distance) + return; + + dist = distance->value; + if (dist == 0) + return; + + /* Tool got into permitted range */ + if (dist < dist_max && + (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_RANGE) || +tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY))) { + tablet_unset_status(tablet, + TABLET_TOOL_OUT_OF_RANGE); + tablet_unset_status(tablet, + TABLET_TOOL_OUT_OF_PROXIMITY); + tablet_set_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY); + tablet_mark_all_axes_changed(tablet, device); + + tablet_set_status(tablet, TABLET_BUTTONS_PRESSED); + tablet_force_button_presses(tablet); + return; + } + + if (dist < dist_max) + return; + + /* Still out of range/proximity */ + if (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_RANGE) || + tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY)) + return; + + /* Tool entered prox but is outside of permitted range */ + if (tablet_has_status(tablet, + TABLET_TOOL_ENTERING_PROXIMITY)) { + tablet_set_status(tablet, + TABLET_TOOL_OUT_OF_RANGE); + tablet_unset_status(tablet, + TABLET_TOOL_ENTERING_PROXIMITY); + return; + } + + /* Tool was in prox and is now outside of range. Set leaving +* proximity, on the next event it will be OUT_OF_PROXIMITY and thus +* caught by the above conditions */ + tablet_set_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY); +} + +static void tablet_flush(struct tablet_dispatch *tablet, struct evdev_device *device, uint64_t time) @@ -1004,7 +1076,12 @@ tablet
Re: [PATCH libinput] tablet: handle custom proximity handling
On Wed, Dec 2, 2015 at 3:57 PM, Peter Hutterer wrote: > For the puck/lens cursor tool we need to artificially reduce proximity > detection. These tools are usually used in a relative mode (i.e. like a > mouse) > and thus require lifting and resetting the tool multiple times to move > across > the screen. The tablets' distance detection goes too far, requiring the > user > to lift the device several cm on every move. This is uncomfortable. > > Introduce an artificial distance threshold for the devices with the default > value taken from the X.Org wacom driver. If a tool is in proximity but > outside > of this range, fake proximity events accordingly. > > You will want something like this for pens and all other tools, as it is possible to use them in a relative mode (very common if the tablet is smaller than the screen). I think rather than typing this to the type of tool, you need to tie it to whether relative motion is being used or not. Not sure where in libinput or wayland that would be, though. ___ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel
[PATCH libinput] tablet: handle custom proximity handling
For the puck/lens cursor tool we need to artificially reduce proximity detection. These tools are usually used in a relative mode (i.e. like a mouse) and thus require lifting and resetting the tool multiple times to move across the screen. The tablets' distance detection goes too far, requiring the user to lift the device several cm on every move. This is uncomfortable. Introduce an artificial distance threshold for the devices with the default value taken from the X.Org wacom driver. If a tool is in proximity but outside of this range, fake proximity events accordingly. If a button was pressed while we were out of range we discard that event and send it later when we enter proximity again. This is the simple implementation that only takes one proximity out value (the one from the wacom driver) and applies it to all. Those devices that support a button/lens tool and have a different default threshold are well out of date. Signed-off-by: Peter Hutterer --- src/evdev-tablet.c | 103 - src/evdev-tablet.h | 3 + test/litest.c | 18 + test/litest.h | 3 +- test/tablet.c | 221 + 5 files changed, 346 insertions(+), 2 deletions(-) diff --git a/src/evdev-tablet.c b/src/evdev-tablet.c index 7e3298c..777ffad 100644 --- a/src/evdev-tablet.c +++ b/src/evdev-tablet.c @@ -67,6 +67,22 @@ tablet_get_released_buttons(struct tablet_dispatch *tablet, ~(state->stylus_buttons[i]); } +/* Merge the previous state with the current one so all buttons look like + * they just got pressed in this frame */ +static inline void +tablet_force_button_presses(struct tablet_dispatch *tablet) +{ + struct button_state *state = &tablet->button_state, + *prev_state = &tablet->prev_button_state; + size_t i; + + for (i = 0; i < sizeof(state->stylus_buttons); i++) { + state->stylus_buttons[i] = state->stylus_buttons[i] | + prev_state->stylus_buttons[i]; + prev_state->stylus_buttons[i] = 0; + } +} + static int tablet_device_has_axis(struct tablet_dispatch *tablet, enum libinput_tablet_tool_axis axis) @@ -994,6 +1010,62 @@ sanitize_tablet_axes(struct tablet_dispatch *tablet) } static void +tablet_update_proximity_state(struct tablet_dispatch *tablet, + struct evdev_device *device) +{ + const struct input_absinfo *distance; + int dist_max = tablet->cursor_proximity_threshold; + int dist; + + distance = libevdev_get_abs_info(tablet->device->evdev, ABS_DISTANCE); + if (!distance) + return; + + dist = distance->value; + if (dist == 0) + return; + + /* Tool got into permitted range */ + if (dist < dist_max && + (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_RANGE) || +tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY))) { + tablet_unset_status(tablet, + TABLET_TOOL_OUT_OF_RANGE); + tablet_unset_status(tablet, + TABLET_TOOL_OUT_OF_PROXIMITY); + tablet_set_status(tablet, TABLET_TOOL_ENTERING_PROXIMITY); + tablet_mark_all_axes_changed(tablet, device); + + tablet_set_status(tablet, TABLET_BUTTONS_PRESSED); + tablet_force_button_presses(tablet); + return; + } + + if (dist < dist_max) + return; + + /* Still out of range/proximity */ + if (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_RANGE) || + tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY)) + return; + + /* Tool entered prox but is outside of permitted range */ + if (tablet_has_status(tablet, + TABLET_TOOL_ENTERING_PROXIMITY)) { + tablet_set_status(tablet, + TABLET_TOOL_OUT_OF_RANGE); + tablet_unset_status(tablet, + TABLET_TOOL_ENTERING_PROXIMITY); + return; + } + + /* Tool was in prox and is now outside of range. Set leaving +* proximity, on the next event it will be OUT_OF_PROXIMITY and thus +* caught by the above conditions */ + tablet_set_status(tablet, TABLET_TOOL_LEAVING_PROXIMITY); +} + +static void tablet_flush(struct tablet_dispatch *tablet, struct evdev_device *device, uint64_t time) @@ -1004,7 +1076,12 @@ tablet_flush(struct tablet_dispatch *tablet, tablet->current_tool_id, tablet->current_tool_serial); - if (tablet_has_status(tablet, TABLET_TOOL_OUT_OF_PROXIMITY)) + if (tool->type == LIBINPUT_TABLET_TOOL_TYPE_MOUSE || + tool->type == LIBINPUT_TABL