On 06/25/2014 06:05 PM, Peter Hutterer wrote:
On Wed, Jun 25, 2014 at 03:19:02PM +0300, Pekka Paalanen wrote:
On Tue, 24 Jun 2014 21:56:09 -0400
Chandler Paul <[email protected]> wrote:

Hello! As you all know I've been working on adding drawing tablet
support to the Wayland protocol. Now that we've added support for
tablets to libinput, the next step is writing the actual protocol that
will be implemented by the compositor. Following this blurb is the
current draft of the tablet protocol we have. Feel free to critique it.

Cheers,
        Lyude

----------------------------------------------------------------------------

                            wl_tablet specifications

General notes:
- Many of the axis values in this are normalized to either 0-65535 or
   (-65535)-65535. I would leave the axis values as-is since libinput reports
   them as doubles, but since we only have 8 bits of precision we'd lose way
   too many values. 65535 seemed like the best choice since it's the maximum
   length of a signed short, it's a whole number, it's way higher then the
   range of any of the axes (with the exception of X and Y, but these aren't
   normalized anyway) and we can do just about any basic arithmatic with it
   without having to worry about overflowing. plus, all we have to do is
   multiply the value by 65535 after we get it from libinput.

Definitions:
- WL_TABLET_AXIS_MAX = 65535
- WL_TABLET_AXIS_MIN = (-65535)

Enumerators:
- wl_tablet_axis:
         - WL_TABLET_AXIS_X
         - WL_TABLET_AXIS_Y
          Represents the X and Y axes respectively. Only used in bitfields to
          indicate whether or not they've changed since the last event.

         - WL_TABLET_AXIS_DISTANCE
           Represents the distance axis on a tablet. Normalized from 0 to
           WL_TABLET_AXIS_MAX. For tablets that do not support reporting the
           distance, this will always be 0.

         - WL_TABLET_AXIS_PRESSURE
           Represents the pressure axis on a tablet. Normalized from 0 to
           WL_TABLET_AXIS_MAX. For tablets that do not support reporting the
           pressure, this will always be WL_TABLET_AXIS_MAX.

         - WL_TABLET_AXIS_TILT_VERTICAL
         - WL_TABLET_AXIS_TILT_HORIZONTAL
           Each represents the vertical and horizontal tilt axes respectfully.
           Normalized from WL_TABLET_AXIS_MIN to WL_TABLET_AXIS_MAX. For
           tablets that do not support this, this value will always be 0.

         - WL_TABLET_AXIS_CNT
           Represents the number of axes
- wl_tablet_tool_type:
         - pen
         - eraser
         - brush
         - pencil
         - airbrush
         - finger
         - mouse
         - lens
- wl_tablet_button_state
         - pressed
         - released

Events:
- proximity_in
   Sent when the tool comes into proximity above the client surface, either by
   the tool coming into proximity or a tool being in-proximity and moving to
   the client surface. If a tablet tool makes contact with the tablet at the
   same time that the tool comes into proximity, the proximity event comes
   first and the down event comes afterwards.
   Arguments:
         - Name: id
           Type: uint
           the id of the tablet sending this event.

         - Name: type
           Type: uint
           The type of tool that came into proximity, e.g. pen, airbrush, etc.

         - Name: serial
           Type: uint
          The serial number of the tool that came into proximity. On tablets
          where this isn't provided, this value will always be 0.

         - Name: x
           Type: fixed
           Surface relative x coordinate

         - Name: y
           Type: fixed
           Surface relative y coordinate

         - Name: surface
           Type: object
           Interface: wl_surface
           The current surface the tablet tool is over

         - Name: time
           Type: uint
           The time of the event with millisecond granularity.

         - Name: axes
           Type: array
          The current values of each of the tablet axes starting at
          WL_TABLET_AXIS_DISTANCE. The length of the array is equal to the
          number of axes that are reported. Any axes >= WL_TABLET_AXIS_CNT
          must be ignored. The size of the array remains fixed for the
          lifetime of the tablet.

- proximity_out
   Send whenever the tool leaves the proximity of the tablet or moves out of
   the client surface. When the tool goes out of proximity, a set of button
   release events are sent before the initial proximity_out event for each
   button that was held down before the tablet tool left proximity. In
   addition, axis updates always come before a proximity-out event.
   Arguments:
         - Name: id
           Type: uint
           The id of the tablet sending this event.

         - Name: time
           Type: uint
           The time of the event with millisecond granularity.

- axis
   Sent whenever an axis on the tool changes. This can include movement on the
   X and Y axis.
   Arguments:
         - Name: id
           Type: uint
           The id of the tablet sending this event.

         - Name: x
           Type: fixed
           Surface relative x coordinate

         - Name: y
           Type: fixed
           Surface relative y coordinate

         - Name: surface
           Type: object
           Interface: wl_surface
           The current surface the tablet tool is over
How about using enter/leave events telling the client which wl_surface
the input device is targeting? That way you don't have to repeat the
wl_surface argument in every event.
good point, thanks!
         - Name: time
           Type: uint
           The time of the event with millisecond granularity.

         - Name: changed_axes
           Type: bitfield
           Indicates which axes have changed.

         - Name: axes
           Type: array
          The current values of each of the tablet axes starting at
          WL_TABLET_AXIS_DISTANCE. The length of the array is equal to the
          number of axes that are reported. Any axes >= WL_TABLET_AXIS_CNT
          must be ignored.
Is there a reason we are using an array rather than sending different events? It's tempting to try and save something by using an array, but extra events don't really cost anything significant. Also, once you use an enum value in a public protocol, you can NEVER change it. In particular, you can't change WL_TABLET_AXIS_CNT and you are locked into only ever using those axes and never extending the protocol to include more. I don't think this is what you intended.

Also, is there a reason why you have one axis event rather than wl_tablet.position, wl_tablet.distance, wl_tablet.tilt, etc? Not that having one axis event and an enum is bad, but it's something to think about.

- button
   Sent whenever a button on the tool is pressed or released.
   Arguments:
         - Name: id
           Type: uint
           The id of the tablet sending this event.

         - Name: button
           Type: uint
           The button whose state has changed

         - Name: state
           Type: uint
           Whether the button was pressed or released

         - Name: time
           Type: uint
           The time of the event with millisecond granularity.

- added
   Sent when a tablet device is added.
   Arguments:
         - Name: id
           Type: uint
           The id of the tablet sending this event.

- removed
   Sent when the tablet device has been removed.
   Arguments:
         - Name: id
           Type: uint
           The id of the tablet sending this event.

How tablet IDs are generated:
Tablet IDs are aggressively recycled, e.g. we always try to get the lowest
possible tablet ID. This means that the client can always assume that the ID
number for a new tablet will never be greater then the number of tablets
currently connected.
Hi,

using tablet IDs this way seems like this is a raw wire protocol, and
not object oriented like Wayland usually is.

Could this be wrapped into an object like the following?

Define interface "wl_tablet" which represents one device (I assume
aggregating makes no sense, just like with gamepads). Then you can drop
the "id" argument from all events and requests, and just use the
protocol object.
It's possible, look at this RFC from last september.
http://lists.freedesktop.org/archives/wayland-devel/2013-September/011173.html

The gist of that was that the wl_seat::get_tablet_manager request that
returned a tablet manager object. that object was then the one that sent
wl_tablet_manager::device_added events with the new tablet object. And that
object had the wl_tablet interface as above (without the IDs).

Lyude and I talked about this and couldn't decide which approach was the
correct-er one for wayland :)
I'll second what pekka said. We already have a way of handling IDs and agressively recycling them; it's called object IDs. I'm guessing the IDs thing came from the wl_touch interface. There we have a wl_touch object for the physical device and IDs for the different touchpoints. Here we have one pen per physical device (I think).
I'm not sure how you want to advertise and create the wl_tablet objects.
How do tablet devices relate to wl_seat protocol objects?
tablets control the cursor, so we definitely need to couple them
with the seats somehow.
Does it control THE cursor or A cursor? I question whether we really want it to be that intertwined with wl_pointer.

This brings up another point: tablet focus. How do you usually tell the compositor what window you want to receive tablet input? For a tablet with a screen, you can treat it more-or-less like a single-point touch-screen, but what about tablets that aren't attached to a screen? In the past, tablets frequently existed as a more natural way to move the mouse around with a little extra meta-data for an app if it wanted it. Is that the way they SHOULD work? That's a different question.
While the protocol is experimental, you could have your own (temporary)
global interface for advertising tablets, so that you don't need to
modify the Wayland core protocol (wl_seat). Or you could advertise each
tablet device as a separate global wl_tablet that a client can bind to.
The proper approach finally depends on the relation to wl_seat once you
are ready to set the protocol in stone.
good point, thanks.

Would clients need some information to differentiate between multiple
tablets in a human-friendly way?
yes, we'll at least need to add PID/VID. From then on the clients can look
up all they need in libwacom. I don't think we need much more than that.

Or should all clients always subscribe to all tablets?
Yes, I think that's the sensible option. in 99% of the cases there is only
one tablet anyway, sometimes there are 2 (laptops have wacom tablets
built-in or a Cintiq+Intuos combo), I haven't seen a real-world setup with 3
tablet yet.

Cheers,
    Peter
_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to