The newer Cintiqs have a minimum value of 400/400 advertised by the kernel but the actual sensor goes past the 0/0 origin. Test this, make sure that a value outside the boundaries generates negative mm values.
Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> --- Mostly just documenting this and adding a test. The behaviour is that any out-of-bounds motion may provide negative coordinates, when transformed may provide something outside the [0, max-range]. Now, this is documenting the API behaviour. For the Cintiq I think it might be better to put a device-specific quirk in to simply supress those events since we don't have anything outside of these boundaries. Jason, Carlos, any comments? doc/svg/tablet-out-of-bounds.svg | 271 +++++++++++++++++++++++++++++++++++++++ doc/tablet-support.dox | 22 ++++ src/libinput.h | 12 ++ test/tablet.c | 58 +++++++++ 4 files changed, 363 insertions(+) create mode 100644 doc/svg/tablet-out-of-bounds.svg diff --git a/doc/svg/tablet-out-of-bounds.svg b/doc/svg/tablet-out-of-bounds.svg new file mode 100644 index 0000000..83e5021 --- /dev/null +++ b/doc/svg/tablet-out-of-bounds.svg @@ -0,0 +1,271 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="134.12477mm" + height="73.121971mm" + viewBox="0 0 475.24525 259.0936" + id="svg2" + version="1.1" + inkscape:version="0.91 r13725" + sodipodi:docname="tablet-out-of-bounds.svg"> + <defs + id="defs4" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="5.6" + inkscape:cx="105.43109" + inkscape:cy="265.46934" + inkscape:document-units="px" + inkscape:current-layer="layer1" + showgrid="false" + showguides="true" + inkscape:guide-bbox="true" + inkscape:window-width="1920" + inkscape:window-height="1136" + inkscape:window-x="0" + inkscape:window-y="27" + inkscape:window-maximized="1" + fit-margin-top="0" + fit-margin-left="0" + fit-margin-right="0" + fit-margin-bottom="0"> + <sodipodi:guide + position="63.6133,240.91614" + orientation="0,1" + id="guide4164" /> + <sodipodi:guide + position="61.08792,13.126743" + orientation="0,1" + id="guide4166" /> + </sodipodi:namedview> + <metadata + id="metadata7"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="tablet" + inkscape:groupmode="layer" + id="layer1" + style="display:inline" + transform="translate(-139.42736,-156.36219)"> + <rect + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.9201867;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.68074643, 0.92018661;stroke-dashoffset:0;stroke-opacity:1" + id="rect4136" + width="474.32504" + height="258.1734" + x="139.88745" + y="156.82228" + rx="5" /> + <rect + y="175.42407" + x="199.33878" + height="226.52563" + width="357.34042" + id="rect4140" + style="opacity:0.92000002;fill:#a44d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.74800003;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" /> + <g + id="g7041" + transform="translate(12,0)"> + <g + transform="matrix(0.53265351,0,0,0.53265351,92.308091,96.440418)" + id="g7023"> + <circle + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.98900002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" + id="path4158" + cx="135.61298" + cy="287.06125" + r="22.98097" /> + <ellipse + cy="287.06125" + cx="135.61298" + id="circle4160" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.52043104;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:2.08172421, 0.52043105;stroke-dashoffset:0;stroke-opacity:1" + rx="11.5985" + ry="12.608653" /> + </g> + <rect + rx="0.5" + y="268.93671" + x="163.8243" + height="8.9902887" + width="13.786156" + id="rect4162" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.29022256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.16089031, 0.29022258;stroke-dashoffset:0;stroke-opacity:1" /> + <rect + rx="0.5" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.29022256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.16089031, 0.29022258;stroke-dashoffset:0;stroke-opacity:1" + id="rect7027" + width="13.786156" + height="8.9902887" + x="163.8243" + y="280.97675" /> + <rect + rx="0.5" + y="293.01678" + x="163.8243" + height="8.9902887" + width="13.786156" + id="rect7029" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.29022256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.16089031, 0.29022258;stroke-dashoffset:0;stroke-opacity:1" /> + <rect + rx="0.5" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.44849709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.79398834, 0.44849708;stroke-dashoffset:0;stroke-opacity:1" + id="rect7031" + width="9.1119308" + height="32.483532" + x="149.90343" + y="269.44443" /> + <rect + rx="0.5" + y="269.44443" + x="137.90343" + height="32.483532" + width="9.1119308" + id="rect7033" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.44849709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.79398834, 0.44849708;stroke-dashoffset:0;stroke-opacity:1" /> + <rect + rx="0.5" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.19463234;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0.77852936, 0.19463234;stroke-dashoffset:0;stroke-opacity:1" + id="rect7035" + width="9.3657951" + height="5.9516821" + x="137.77649" + y="256.10321" /> + <rect + rx="0.5" + y="246.10321" + x="137.77649" + height="5.9516821" + width="9.3657951" + id="rect7037" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.19463234;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0.77852936, 0.19463234;stroke-dashoffset:0;stroke-opacity:1" /> + <rect + rx="0.5" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.19463234;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0.77852936, 0.19463234;stroke-dashoffset:0;stroke-opacity:1" + id="rect7039" + width="9.3657951" + height="5.9516821" + x="137.77649" + y="236.10321" /> + </g> + <g + transform="matrix(-1,0,0,1,743.43474,0)" + id="g7054"> + <g + id="g7056" + transform="matrix(0.53265351,0,0,0.53265351,92.308091,96.440418)"> + <circle + r="22.98097" + cy="287.06125" + cx="135.61298" + id="circle7058" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.98900002;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:3.956, 0.989;stroke-dashoffset:0;stroke-opacity:1" /> + <ellipse + ry="12.608653" + rx="11.5985" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.52043104;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:2.08172421, 0.52043105;stroke-dashoffset:0;stroke-opacity:1" + id="ellipse7060" + cx="135.61298" + cy="287.06125" /> + </g> + <rect + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.29022256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.16089031, 0.29022258;stroke-dashoffset:0;stroke-opacity:1" + id="rect7062" + width="13.786156" + height="8.9902887" + x="163.8243" + y="268.93671" + rx="0.5" /> + <rect + y="280.97675" + x="163.8243" + height="8.9902887" + width="13.786156" + id="rect7064" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.29022256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.16089031, 0.29022258;stroke-dashoffset:0;stroke-opacity:1" + rx="0.5" /> + <rect + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.29022256;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.16089031, 0.29022258;stroke-dashoffset:0;stroke-opacity:1" + id="rect7066" + width="13.786156" + height="8.9902887" + x="163.8243" + y="293.01678" + rx="0.5" /> + <rect + y="269.44443" + x="149.90343" + height="32.483532" + width="9.1119308" + id="rect7068" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.44849709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.79398834, 0.44849708;stroke-dashoffset:0;stroke-opacity:1" + rx="0.5" /> + <rect + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.44849709;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:1.79398834, 0.44849708;stroke-dashoffset:0;stroke-opacity:1" + id="rect7070" + width="9.1119308" + height="32.483532" + x="137.90343" + y="269.44443" + rx="0.5" /> + <rect + y="256.10321" + x="137.77649" + height="5.9516821" + width="9.3657951" + id="rect7072" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.19463234;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0.77852936, 0.19463234;stroke-dashoffset:0;stroke-opacity:1" + rx="0.5" /> + <rect + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.19463234;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0.77852936, 0.19463234;stroke-dashoffset:0;stroke-opacity:1" + id="rect7074" + width="9.3657951" + height="5.9516821" + x="137.77649" + y="246.10321" + rx="0.5" /> + <rect + y="236.10321" + x="137.77649" + height="5.9516821" + width="9.3657951" + id="rect7076" + style="opacity:0.92000002;fill:#4d4d4d;fill-opacity:1;stroke:#4d4d4d;stroke-width:0.19463234;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:0.77852936, 0.19463234;stroke-dashoffset:0;stroke-opacity:1" + rx="0.5" /> + </g> + <rect + style="opacity:0.92000002;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.6687212;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:2.6748846, 0.66872115;stroke-dashoffset:0;stroke-opacity:1" + id="rect7078" + width="326.1051" + height="198.32079" + x="214.95644" + y="189.5265" /> + </g> + <g + inkscape:groupmode="layer" + id="layer3" + inkscape:label="stylus" + style="display:inline" + transform="translate(-139.42736,-156.36219)" /> +</svg> diff --git a/doc/tablet-support.dox b/doc/tablet-support.dox index ff4e460..0e719b7 100644 --- a/doc/tablet-support.dox +++ b/doc/tablet-support.dox @@ -186,4 +186,26 @@ Intuos 3, 4, 5, Wacon Cintiq and Wacom Intuos Pro series. The tool ID can be used to distinguish between e.g. a Wacom Classic Pen or a Wacom Pro Pen. It is the caller's responsibility to interpret the tool ID. +@section tablet-bounds Out-of-bounds motion events + +Some tablets integrated into a screen (e.g. Wacom Cintiq 24HD, 27QHD and +13HD series, etc.) have a sensor larger than the display area. libinput uses +the range advertised by the kernel as the valid range unless device-specific +quirks are present. Events outside this range will produce coordinates that +may be negative or larger than the tablet's width and/or height. It is up to +the caller to ignore these events. + +@image html tablet-out-of-bounds.svg "Illustration of the out-of-bounds area on a tablet" + +In the image above, the display area is shown in black. The red area around +the display illustrates the sensor area that generates input events. Events +within this area will have negative coordinate or coordinates larger than +the width/height of the tablet. + +If events outside the logical bounds of the input area are scaled into a +custom range with libinput_event_tablet_tool_get_x_transformed() and +libinput_event_tablet_tool_get_y_transformed() the resulting value may be +less than 0 or larger than the upper range provided. It is up to the caller +to test for this and handle or ignore these events accordingly. + */ diff --git a/src/libinput.h b/src/libinput.h index b14c281..cf33492 100644 --- a/src/libinput.h +++ b/src/libinput.h @@ -1562,6 +1562,9 @@ libinput_event_tablet_tool_wheel_has_changed( * libinput_event_tablet_tool_get_x_transformed() for transforming the axis * value into a different coordinate space. * + * @note On some devices, returned value may be negative or larger than the + * width of the device. See @ref tablet-bounds for more details. + * * @param event The libinput tablet tool event * @return The current value of the the axis */ @@ -1576,6 +1579,9 @@ libinput_event_tablet_tool_get_x(struct libinput_event_tablet_tool *event); * libinput_event_tablet_tool_get_y_transformed() for transforming the axis * value into a different coordinate space. * + * @note On some devices, returned value may be negative or larger than the + * width of the device. See @ref tablet-bounds for more details. + * * @param event The libinput tablet tool event * @return The current value of the the axis */ @@ -1754,6 +1760,9 @@ libinput_event_tablet_tool_get_wheel_delta_discrete( * libinput_event_tablet_tool_*_has_changed() returns 0 for that axis. * libinput always includes all device axes in the event. * + * @note On some devices, returned value may be negative or larger than the + * width of the device. See @ref tablet-bounds for more details. + * * @param event The libinput tablet tool event * @param width The current output screen width * @return the current absolute x coordinate transformed to a screen coordinate @@ -1772,6 +1781,9 @@ libinput_event_tablet_tool_get_x_transformed(struct libinput_event_tablet_tool * * libinput_event_tablet_tool_*_has_changed() returns 0 for that axis. * libinput always includes all device axes in the event. * + * @note On some devices, returned value may be negative or larger than the + * width of the device. See @ref tablet-bounds for more details. + * * @param event The libinput tablet tool event * @param height The current output screen height * @return the current absolute y coordinate transformed to a screen coordinate diff --git a/test/tablet.c b/test/tablet.c index 6909f95..c5dc892 100644 --- a/test/tablet.c +++ b/test/tablet.c @@ -1655,6 +1655,63 @@ START_TEST(motion_event_state) } END_TEST +START_TEST(motion_outside_bounds) +{ + struct litest_device *dev = litest_current_device(); + struct libinput *li = dev->libinput; + struct libinput_event *event; + struct libinput_event_tablet_tool *tablet_event; + double val; + + struct axis_replacement axes[] = { + { ABS_DISTANCE, 10 }, + { ABS_PRESSURE, 0 }, + { -1, -1 } + }; + + litest_tablet_proximity_in(dev, 50, 50, axes); + litest_drain_events(li); + + /* On the 24HD x/y of 0 is outside the limit */ + litest_event(dev, EV_ABS, ABS_X, 0); + litest_event(dev, EV_ABS, ABS_Y, 1000); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + event = libinput_get_event(li); + tablet_event = litest_is_tablet_event(event, + LIBINPUT_EVENT_TABLET_TOOL_AXIS); + val = libinput_event_tablet_tool_get_x(tablet_event); + ck_assert_double_lt(val, 0.0); + val = libinput_event_tablet_tool_get_y(tablet_event); + ck_assert_double_gt(val, 0.0); + + val = libinput_event_tablet_tool_get_x_transformed(tablet_event, 100); + ck_assert_double_lt(val, 0.0); + + libinput_event_destroy(event); + + /* On the 24HD x/y of 0 is outside the limit */ + litest_event(dev, EV_ABS, ABS_X, 1000); + litest_event(dev, EV_ABS, ABS_Y, 0); + litest_event(dev, EV_SYN, SYN_REPORT, 0); + libinput_dispatch(li); + + event = libinput_get_event(li); + tablet_event = litest_is_tablet_event(event, + LIBINPUT_EVENT_TABLET_TOOL_AXIS); + val = libinput_event_tablet_tool_get_x(tablet_event); + ck_assert_double_gt(val, 0.0); + val = libinput_event_tablet_tool_get_y(tablet_event); + ck_assert_double_lt(val, 0.0); + + val = libinput_event_tablet_tool_get_y_transformed(tablet_event, 100); + ck_assert_double_lt(val, 0.0); + + libinput_event_destroy(event); +} +END_TEST + START_TEST(bad_distance_events) { struct litest_device *dev = litest_current_device(); @@ -3577,6 +3634,7 @@ litest_setup_tests(void) litest_add("tablet:tip", tip_state_button, LITEST_TABLET, LITEST_ANY); litest_add("tablet:motion", motion, LITEST_TABLET, LITEST_ANY); litest_add("tablet:motion", motion_event_state, LITEST_TABLET, LITEST_ANY); + litest_add_for_device("tablet:motion", motion_outside_bounds, LITEST_WACOM_CINTIQ_24HD); litest_add("tablet:tilt", tilt_available, LITEST_TABLET|LITEST_TILT, LITEST_ANY); litest_add("tablet:tilt", tilt_not_available, LITEST_TABLET, LITEST_TILT); litest_add("tablet:tilt", tilt_x, LITEST_TABLET|LITEST_TILT, LITEST_ANY); -- 2.5.0 _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel