[PATCH weston 21/25] protocol: add weston_touch_calibration

Peter Hutterer peter.hutterer at who-t.net
Mon Apr 16 03:40:44 UTC 2018


On Fri, Apr 13, 2018 at 10:51:37AM +0300, Pekka Paalanen wrote:
> On Fri, 13 Apr 2018 14:31:39 +1000
> Peter Hutterer <peter.hutterer at who-t.net> wrote:
> 
> > On Wed, Apr 11, 2018 at 02:00:49PM +0300, Pekka Paalanen wrote:
> > > On Wed, 11 Apr 2018 10:16:46 +1000
> > > Peter Hutterer <peter.hutterer at who-t.net> wrote:  
> 
> > > > > > > +  <interface name="weston_touch_calibrator" version="1">
> > > > > > > +    <description summary="calibrator surface for a specific touch device">
> > > > > > > +      On creation, this object is tied to a specific touch device. The
> > > > > > > +      server sends a configure event which the client must obey with the
> > > > > > > +      associated wl_surface.
> > > > > > > +
> > > > > > > +      Once the client has committed content to the surface, the server can
> > > > > > > +      grab the touch input device, prevent it from emitting normal touch events,
> > > > > > > +      show the surface on the correct output, and relay input events from the
> > > > > > > +      touch device via this protocol object.
> > > > > > > +
> > > > > > > +      Touch events from other touch devices than the one tied to this object
> > > > > > > +      must generate wrong_touch events on at least touch-down and must not
> > > > > > > +      generate normal or calibration touch events.
> > > > > > > +
> > > > > > > +      At any time, the server can choose to cancel the calibration procedure by
> > > > > > > +      sending the cancel_calibration event. This should also be used if the
> > > > > > > +      touch device disappears or anything else prevents the calibration from
> > > > > > > +      continuing on the server side.
> > > > > > > +
> > > > > > > +      If the wl_surface is destroyed, the server must cancel the calibration.
> > > > > > > +
> > > > > > > +      The touch event coordinates and conversion results are delivered in
> > > > > > > +      calibration units. Calibration units are in the closed interval
> > > > > > > +      [0.0, 1.0] mapped into 32-bit unsigned integers. An integer can be      
> > > > > > 
> > > > > > should probably add what 0.0 and 1.0 represent on each axis, i.e. nominal
> > > > > > width and height of the device's sensor. Or is this something we need to
> > > > > > hide?    
> > > > > 
> > > > > I'm not sure. The underlying assumption is that there is a finite and
> > > > > closed range of values a sensor can output, and that is mapped to [0,
> > > > > 1]. I don't know what nominal width and height are or can the values
> > > > > extend to negative. It might be easier to define the calibration units
> > > > > without defining those first.    
> > > > 
> > > > sorry, I used "nominal" before I rewrote to use "sensor", probably made it
> > > > more confusing. On some devices, the sensor is larger than the screen so you
> > > > can get coordinates outside the screen area. This is not a technical
> > > > problem, just a user perception mismatch that doens't need to be exposed and
> > > > after all that's what calibration is about.
> > > > 
> > > > Once you apply calibration though you can get real negative coordinates,
> > > > especially if the device advertises a [n:m] range but then sends events less
> > > > than n. For example, all synaptics touchpads (pre 2014, some after that) do
> > > > that.  
> > > 
> > > But wait, if there are actually devices that report the range [n:m] but
> > > can still send values less than n or greater than m, it means I cannot
> > > transmit those with the encoding set up here, because
> > > libinput_event_touch_get_x_transformed(touch_event, 1) can return
> > > values outside of [0, 1] even when the loaded calibration matrix is
> > > identity. Is that right?  
> > 
> > correct, that can happen.
> > 
> > > Do I need to find an encoding to cope with that, or can I just reject
> > > such touches?
> > > 
> > > I mean, the range [n:m] is in raw input coordinates, before any
> > > normalization or calibration in userspace, right?  
> > 
> > uhm. let me just detail this and you can pick which one was the answer to
> > that question:
> > - the kernel exposes [n:m] axis ranges for ABS_X/Y and the MT equivalents
> > - libinput converts this into mm by default, see libinput_event_touch_get_x()
> > - libinput converts this to a ranged value [0:N] when calling
> >   libnput_event_touch_get_x_transformed(N). This is what weston uses to get
> >   the screen coordinates.
> > 
> > Both libinput values have the calibration factored in already.
> > 
> > Weston doesn't ever see raw input coordinates. But if you use
> > get_x_transformed, you can get values outside [0:N]. This happens when
> > the [n:m] range is incorrect. Accommodating for some error margin, libinput
> > will print a warning to the log when this happens.
> > 
> > The correct solution would be to warn the user that the device is garbage
> > and make them put a 60-evdev.hwdb quirk in to fix the axis ranges.
> > Depending on the device, this could be a generic solution but let's not bet
> > on that...
> > 
> > The user-friendly solution would be to have two layers of mapping. By
> > default, you map the libinput range into [0, 1]. Whenever you see negative
> > values or values > 1 you notify the user that this screen is garbage. The
> > only option you have now is to get the user to touch the furthest extents of
> > all axes to get the lowest and highest values the axis provides (similar to
> > the touchpad-edge-detector tool). Then you can map those into the libinput
> > provided range so that e.g. libinput's -0.25 is normalized 0 and 1.25 is
> > normalized 1.0.
> > 
> > Now you can restart calibration with that extra mapping on top. 
> > 
> > A few caveats, beyond the effort required:
> > - even with the calibration matrix applied, the libinput ranges will still
> >   be outside the [0:N] range. Only a real axis fix can fix that
> > - you cannot know the true min/max until you get respective event from the
> >   screen
> > 
> > So yeah, the situation is less than ideal...
> > 
> > I've considered auto-scaling libinput into the new axis range but this is
> > likely going to hurt even more because it's undiscoverable and for most
> > devices, a quirk in the hwdb file can solve this problem properly.
> 
> Thank you very much for the thorough explanation.
> 
> I think the appropriate solution for me here is to check whether the
> normalized value I expect to be in [0, 1] falls outside of the range,
> and if so, I will a) print a warning in Weston's log that the device
> may need a quirk like you explained, and b) send the "invalid touch"
> event instead of a touch event to the calibrator app.
> 
> This makes the calibrator app show a big red cross, so the user will
> know something is strange if he thinks he did touch the correct spot.

I'd argue that this is worthy of a custom event, given that the client will
have to provide a specific UI for this case. But it's also not worth
worrying about in the first iteration of the protocol.

> Well, it does touch-downs at least. I think if motion event would end
> up out of range, I'll send cancel event followed by invalid touch.
> Whee, I found use for the cancel event!

The cancel event would also be used for the multitouch-case, right?
If a second touch appears before the first one is fully processed, you also
need to cancel the first touch. Doesn't even need to be intentional by the
user, could be a palm touch or an accidental touch where they're holding the
screen on an edge.

Cheers,
   Peter

> > > > These devices are a problem because we rely on the coordinate range for the
> > > > size and then on the calibration on top to normalize the input. So they may
> > > > need two fixes, one for the range adjustment, one for calibration.  
> > > 
> > > If I can just transmit whatever values I get for "normalized" with
> > > identity in the above, then the calibration matrix will automatically
> > > account for any out-of-range values - I mean they become a non-issue,
> > > because the compositor just tranforms them to the output or a global
> > > coordinate system first and then clips to the actual output area. Or
> > > doesn't clip, makes no difference.
> > >   
> > > > > It doesn't really matter, the important point is that when the
> > > > > resulting matrix is loaded into libinput and then libinput is used
> > > > > according to its API, the result is as expected. I'd be tempted to just
> > > > > punt all this to libinput.    
> > > > 
> > > > libinput will sort-of punt it back :)
> > > > https://wayland.freedesktop.org/libinput/doc/latest/tablet-support.html#tablet-bounds
> > > >   
> > > 
> > > I don't see a problem in that section. The goal of this calibration is
> > > to match input event coordinates to output pixel coordinates in the
> > > complete pipeline by adjusting the normalized calibration matrix in
> > > libinput. It's ok for calibrated input coordinates go beyond any
> > > limits, the input and output coordinate planes can be thought as
> > > infinite.
> > > 
> > > Or do you refer to the functions returning positions in millimeters? I
> > > never looked at those, they're not used with touchscreens. I don't even
> > > know if a calibration matrix affects them.  
> > 
> > There's a corner-case with touchscreens and mm. Plenty of cheap touchscreens
> > don't have a resolution set, so the mm value is calculated using the default
> > resolution of 1.
> > 
> > The calibration matrix is applied to the mm as well. That's largely a
> > side-effect for the matrix originally being used for rotation rather than
> > scaling or translation.
> 
> Right. If someone needs this calibration method to work on devices that
> user by millimeter units, I'll let them figure out what to fix if
> anything. :-)
> 
> 
> Thanks,
> pq




More information about the wayland-devel mailing list