[PATCH v6 inputproto 1/1] Multitouch updates for pointer emulation

Peter Hutterer peter.hutterer at who-t.net
Tue Mar 1 22:34:30 PST 2011


On Tue, Feb 08, 2011 at 10:53:19AM +0000, Daniel Stone wrote:
> Attached is the diff between the last multitouch spec posted to the
> list, and what I've just pushed to my p.fd.o repository.  This takes in
> a lot of stuff I discussed with Peter during LCA, including:
> 
> Pointer emulation: We'd hoped it'd be simpler, but as soon as Peter
> pointed out that we need to support WMs grabbing pointer events on their
> frame windows to raise the window, I knew we were in trouble.  The new
> approach is to consider both touch and pointer events as delivery
> candidates at every level.  So, constructing the window tree, we first
> look for a touch grab on each window, then a pointer grab; after the
> grabs are done, we look for the first touch or pointer selection.  This
> means that one touch event may be simultaneously sending touch events
> through to touch clients, and enqueuing emulated pointer events as the
> device is frozen for a grab.  Fun times.
> 
> Splitting touch rejection into two modes: RejectEnd with the same
> behaviour as previously, and RejectContinue which passes ownership to
> the next client in line, but does not remove that client from the
> delivery set.  The usecase here was for window managers and global
> gesture managers that want to continue providing feedback to the user
> (e.g. a visual trace of the path the gesture is taking, or an indication
> of the touch location to show you that you've actually just missed the
> button you were trying to press).
> 
> New TouchBeginInert grab mode: As with above, will deliver events to
> that grab but never grant it ownership.
> 
> Add to and clarify usecases.
> 
> Cosmetic cleanups: renaming PendingFinish to PendingEnd, TouchPointer to
> PointerEmulated, et al.  Should reduce confusion a little - I certainly
> mixed up TouchOwnerAccept and TouchOwnerAccepted a couple of times.
> 
> Comments welcome!
> 
> Cheers,
> Daniel
> 
> diff --git a/XI2.h b/XI2.h
> index 3f4d2c3..40c9ca6 100644
> --- a/XI2.h
> +++ b/XI2.h
> @@ -67,6 +67,7 @@
>  #define XIGrabtypeEnter                         2
>  #define XIGrabtypeFocusIn                       3
>  #define XIGrabtypeTouchBegin                    4
> +#define XIGrabtypeTouchBeginInert               5

I'm struggling to come up with a better name but I'm not sure Inert is the
best option here.

>  /* Passive grab modifier */
>  #define XIAnyModifier                           (1U << 31)
> @@ -83,8 +84,8 @@
>  
>  /* XIAllowTouchEvents bitmask event-modes */
>  #define XITouchOwnerAccept                      (1 << 0)
> -#define XITouchOwnerReject                      (1 << 1)
> -#define XITouchNoPointerEmulation               (1 << 2)
> +#define XITouchOwnerRejectEnd                   (1 << 1)
> +#define XITouchOwnerRejectContinue              (1 << 2)

just thinking aloud: XITouchOwnerReject and XITouchOwnerPass?
or XITouchOwnerIgnore and XITouchOwnerPass?

also, after 10 minutes of reading this over and over I found what was
bothering me. We have XIGrabtypeTouchBeginInert for the grab type to get the
behaviour that XITouchOwnerRejectContinue gives us too. these two need to be
consistently named. to go with my suggestions from above:
XIGrabtypeTouchBeginPass and XITouchOwnerPass?

Chase, this should also clarify your comment here. Inert isn't a new event
type it's a grab on touch with an automatic RejectContinue if the grab
activates.

>  /* DeviceChangedEvent change reasons */
>  #define XISlaveSwitch                           1
> @@ -132,11 +133,11 @@
>  /* Device event flags (key events only) */
>  #define XIKeyRepeat                             (1 << 16)
>  /* Device event flags (pointer events only) */
> -#define XITouchPointer                          (1 << 16)
> +#define XIPointerEmulated                       (1 << 16)
>  /* Device event flags (touch events only) */
> -#define XITouchOwner                            (1 << 16)
> -#define XITouchOwnerAccepted                    (1 << 17)
> -#define XITouchPendingFinish                    (1 << 18)
> +#define XITouchPendingEnd                       (1 << 16)
> +/* Device event flags (touch end events only) */
> +#define XITouchAccepted                         (1 << 17)
>  
>  /* Touch modes */
>  #define XIDirectTouch                           1
> @@ -173,9 +174,9 @@
>  #define XI_TouchBegin                    18
>  #define XI_TouchEnd                      19
>  #define XI_TouchOwnership                20
> -#define XI_TouchMotion                   21
> -#define XI_TouchMotionUnowned            22
> -#define XI_LASTEVENT                     XI_TouchMotionUnowned
> +#define XI_TouchUpdate                   21
> +#define XI_TouchUpdateUnowned            22
> +#define XI_LASTEVENT                     XI_TouchUpdateUnowned
>  /* NOTE: XI2LASTEVENT in xserver/include/inputstr.h must be the same value
>   * as XI_LASTEVENT if the server is supposed to handle masks etc. for this
>   * type of event. */
> @@ -204,7 +205,7 @@
>  #define XI_TouchBeginMask                (1 << XI_TouchBegin)
>  #define XI_TouchEndMask                  (1 << XI_TouchEnd)
>  #define XI_TouchOwnershipChangedMask     (1 << XI_TouchOwnershipChanged)
> -#define XI_TouchMotionMask               (1 << XI_TouchMotion)
> -#define XI_TouchMotionUnownedMask        (1 << XI_TouchMotionUnowned)
> +#define XI_TouchUpdateMask               (1 << XI_TouchUpdate)
> +#define XI_TouchUpdateUnownedMask        (1 << XI_TouchUpdateUnowned)
>  
>  #endif /* _XI2_H_ */
> diff --git a/XI2proto.h b/XI2proto.h
> index 6a5280c..f6348b4 100644
> --- a/XI2proto.h
> +++ b/XI2proto.h
> @@ -197,7 +197,7 @@ typedef struct {
>      uint16_t    length;         /**< Length in 4 byte units */
>      uint16_t    sourceid;       /**< source device for this class */
>      uint8_t     mode;           /**< DirectTouch or DependentTouch */
> -    uint8_t     num_touches;    /**< Maximum number of touches */
> +    uint8_t     num_touches;    /**< Maximum number of touches (0==unlimited) */

I'd prefer "unknown" or "unspecified".

>  } xXITouchInfo;
>  
>  /**
> @@ -909,8 +909,7 @@ typedef struct
>      uint16_t    deviceid;           /**< Device that has changed */
>      Time        time;
>      uint16_t    sourceid;           /**< Source of the new classes */
> -    uint8_t     reason;             /**< ::XITouchOwnerReject */
> -    uint8_t     pad0;
> +    uint16_t    pad0;
>      uint32_t    touchid;
>      uint32_t    flags;
>      uint32_t    pad1;
> diff --git a/XI2proto.txt b/XI2proto.txt
> index d079ddb..5ebe59d 100644
> --- a/XI2proto.txt
> +++ b/XI2proto.txt
> @@ -9,11 +9,11 @@
>  
>                                 Daniel Stone
>                             daniel at fooishbar.org
> -                             Collabora, Ltd.
> +                              Collabora, Ltd.
>  
>                                Chase Douglas
>                          chase.douglas at canonical.com
> -                             Canonical, Ltd.
> +                              Canonical, Ltd.
>  
>  
>  
> @@ -45,18 +45,15 @@ XI 2.1 introduces support for multi-touch devices. The traditional
>  pointer/keyboard approach enforced by XI 2.0 with the master/slave device
>  hierarchy is not always suitable for multi-touch devices that can provide a
>  dynamic number of multiple independent input points per physical device.
> -Furthermore, such devices are often direct input devices, the virtual
> -abstraction of master devices is not necessary.
> +Furthermore, as such devices are often direct input devices (e.g. touchscreens,
> +able to focus without a pointer), the virtual abstraction of master devices is
> +not always necessary.
>  
>  The additions in XI 2.1 aim to:
>  - support a dynamic number of simultaneous touch points,
> -- support devices that are both multi-touch and traditional pointer devices.
> -
> -It is also hoped to provide backwards compatible pointer emulation for
> -single-touch interaction, but the exact semantics of pointer emulation have
> -not yet been determined.  While it is likely that most of the semantics will
> -remain implementation-defined, future revisions of the specification are
> -likely to clarify and expand on pointer emulation behaviour.
> +- support devices that are both multi-touch and traditional pointer devices,
> +- while supporting pre-XI2.1 clients through emulation of XI 2.0 and core
> +  pointer events.

I think pointer emulation should have its own section. One thing I just
found in my notes: TouchBegin and TouchEnd must be the equivalent of a
Button1 press. This seems obvious but must be spelled out.

>  
>  XI 2.1 caters for two modes of touch input devices:
>  - direct multi-touch input devices such as touch screens. These devices
> @@ -207,8 +204,10 @@ location any number of times, and finally “destroy” the sequence by ceasing
>  to touch the device. The init and destroy stage of this sequence are always
>  present, while the move stage is optional. Within this document, the term
>  "touch sequence" is used to describe the above chain of events. A client
> -wishing to receive touch events must register for all three touch events
> -simultaneously.
> +wishing to receive touch events must register for at least TouchBegin,
> +TouchOwnership, TouchUpdate, and TouchEnd simultaneously; it may also select
> +for TouchUpdateUnowned events if it wants to receive the full touch stream,
> +rather than just the final state.
>  
>  A touch sequence is only considered to be meaningful in its entirety: clients
>  may not capture part of a touch sequence, interpret only that part, and then
> @@ -216,19 +215,19 @@ pass a partial touch sequence on to the next client.  To this end, all clients
>  with active “grabs” on the window hierarchy for a touch sequence receive events
>  from that touch sequence, as well as the client with the deepest selection
>  (i.e. furthest from the root window).  Clients currently in control of the
> -touch sequence receive TouchMotion events, whereas clients not in control
> -receive TouchMotionUnowned events.
> +touch sequence receive TouchUpdate events, whereas clients not in control
> +receive TouchUpdateUnowned events.
>  
>  Touch grabs are similar to standard input event grabs in that they take
>  precedence over selections and are searched from the root window to the child
>  window.  The first grab found for a touch sequence will be the owner of that
>  touch sequence, however events for that touch sequence will continue to be
>  delivered to all clients with grabs in the window tree, as well as the client
> -with the deepest selection.  The grabbing client may either “accept” the
> -touch, which claims the touch sequence and stops delivery to all other
> -clients for the duration of the touch sequence, or “reject” the touch sequence,
> -which will remove that client from the delivery set and pass ownership on to
> -the next client.
> +with the deepest selection.  The first client may either “accept” the touch,
> +which claims the touch sequence and stops delivery to all other clients for
> +the duration of the touch sequence, or “reject” the touch sequence, which
> +will remove that client from the delivery set and pass ownership on to the
> +next client.
>  
>  Window sets for direct device touches contain the windows from the root to the
>  child in which the touch originated.
> @@ -243,6 +242,12 @@ window set is reset and re-calculated on the first subsequent touch.
>  No touches from a dependent device may begin while the device is floating, as
>  it does not have an associated pointer position to focus events.
>  
> +If there is no touch grab on a window and the server supports pointer
> +emulation, it will look for a pointer grab on that window and include it as
> +part of the delivery set; similarly, if no client has selected to receive
> +touch events on a window, the server may look for pointer event selections
> +on that window to add to the delivery set.
> +
>  The delivery of touch events is not changed by any modifications to the window
>  hierarchy after the window set has been determined for the touch, nor is it
>  affected by new grabs or selections.
> @@ -254,7 +259,7 @@ owner accepted, the client having rejected that touch, etc).
>  A device that sends touch events may also generate pointer events on demand.
>  The decision of which touch events are converted into pointer events is
>  implementation-specific, however any pointer event generated from a touch
> -event will have the TouchPointer flag set. Emulated pointer/keyboard events
> +event will have the PointerEmulated flag set. Emulated pointer/keyboard events
>  follow the core and XI2 grab semantics.
>  
>  4.5. The ClientPointer principle
> @@ -542,7 +547,8 @@ are required to be 0.
>          current position of the pointer.
>      num_touches
>          The maximum number of simultaneous touchpoints the device may send.
> -        If num_touches is 0, the number of supported touches is unknown.
> +        If num_touches is 0, the number of supported touches is unknown or
> +        unlimited.
>  
>      A device with a TouchClass must provide one or more TOUCHAXISCLASS
>      specifiers.
> @@ -614,13 +620,13 @@ are required to be 0.
>      The mask for XIHierarchyEvents may only be selected for XIAllDevices.
>      Setting it for any other device results in a BadValue error.
>  
> -    A client selecting for any of XI_TouchBegin, XI_TouchMotion or XI_TouchEnd
> -    must select for all three events at the same time, else BadValue will be
> -    returned. A client selecting for XI_TouchMotionUnowned must select for all
> -    three of the other touch events. If the selection for these touch events
> -    overlaps a current selection by another client (e.g. selecting for a
> -    specific device when another client has a selection for XIAllDevices), a
> -    BadAccess error occurs.
> +    A client selecting for any of XI_TouchBegin, XI_TouchOwnership,
> +    XI_TouchUpdate or XI_TouchEnd must select for all three events at the
> +    same time, else BadValue will be returned. A client selecting for
> +    XI_TouchUpdateUnowned must select for all three of the other touch
> +    events. If the selection for these touch events overlaps a current
> +    selection by another client (e.g. selecting for a specific device when
> +    another client has a selection for XIAllDevices), a BadAccess error occurs.

s/three/four/g

>  
>      ┌───
>          XIGetSelectedEvents
> @@ -977,7 +983,8 @@ are required to be 0.
>      This request actively grabs control of the specified input device. Further
>      input events from this device are reported only to the grabbing client.
>      This request overides any previous active grab by this client for this
> -    device.
> +    device.  This request does not, however, affect the processing of XI 2.1
> +    touch events.
>  
>      deviceid
>          The device to grab.
> @@ -1182,7 +1189,8 @@ are required to be 0.
>      └───
>  
>          GRABTYPE         { GrabtypeButton, GrabtypeKeycode, GrabtypeEnter,
> -                           GrabtypeFocusIn, GrabtypeTouchBegin }
> +                           GrabtypeFocusIn, GrabtypeTouchBegin,
> +                           GrabtypeTouchBeginInert }
>  
>          GRABMODIFIERINFO {   status:    Access
>                               modifiers: CARD32 }
> @@ -1214,7 +1222,8 @@ are required to be 0.
>              releasing XIAllowEvents request or until the device grab is
>              released. Actual device input events are not lost while the device
>              is frozen; they are simply queued for later processing.
> -            Must be Asynchronous for GrabtypeTouchBegin (see section 4.4).
> +            Must be Asynchronous for GrabtypeTouchBegin and
> +            GrabtypeTouchBeginInert (see section 4.4).
>          mask_len
>              Length of mask in 4 byte units.
>          mask
> @@ -1272,12 +1281,15 @@ are required to be 0.
>          - a passive grab of the same grab_type + modifier combination does not
>            does not exist on an ancestor of grab_window.
>  
> -        Or if grab_type is GrabtypeTouchBegin, a touch grab (see section 4.4)
> -        begins if:
> +        Or if grab_type is GrabtypeTouchBegin or GrabtypeTouchBeginInert, a
> +        touch grab (see section 4.4) begins if:
>          - a touch begins in grab_window or one of its ancestors, and
> -        - the specified modifier keys are down, and
> -        - a passive grab of the same grab_type + modifier combination does not
> -          exist on an ancestor of grab_window.
> +        - the specified modifier keys are down
> +        Ownership of the touch sequence is granted to the grabbing client if:
> +        - grab_type is not GrabtypeTouchBeginInert, and
> +        - a TouchBegin, TouchBeginInert, or pointer passive grab with the same
> +          modifier set does not exist on an ancestor of grab_window, or all
> +          applicable grabs have released ownership.

Inert means that the ancestor won't get ownership and this client should get
the grab then, right? if so, the second part is incorrect.

some more extensive description of Inert may help too, it's easier to get
this out of your email than out of the spec.

>          A modifier of GrabAnyModifier is equivalent to issuing the request for
>          all possible modifier combinations (including no modifiers). A client
> @@ -1289,9 +1301,9 @@ are required to be 0.
>          A GrabtypeEnter or GrabtypeFocusIn grab is released when the
>          pointer or focus leaves the window and all of its descendants,
>          independent of the state of modifier keys.
> -        A GrabtypeTouchBegin grab is released when the touch sequence ends,
> -        or a client uses XIAllowTouchEvents to reject the touch and remove
> -        itself from the touch delivery sequence.
> +        A GrabtypeTouchBegin or GrabtypeTouchBeginInert grab is released when
> +        the touch sequence ends, or a client uses XIAllowTouchEvents to reject
> +        the touch and remove itself from the touch delivery sequence.

reject is ambiguous here with the current naming of Reject/RejectContinue

>          Note that the logical state of a device (as seen by means of the
>          protocol) may lag the physical state if device event processing is
>          frozen.
> @@ -1304,10 +1316,11 @@ are required to be 0.
>          with the same button or keycode and modifier combination, the
>          failed modifier combinations is returned in modifiers_return. If some
>          other client already has issued an XIPassiveGrabDevice request of
> -        grab_type XIGrabtypeEnter, XIGrabtypeFocusIn, or XIGrabtypeTouchBegin
> -        with the same grab_window and the same modifier combination, the failed
> -        modifier combinations are returned in modifiers_return. If
> -        num_modifiers_return is zero, all passive grabs have been successful.
> +        grab_type XIGrabtypeEnter, XIGrabtypeFocusIn, XIGrabtypeTouchBegin, or
> +        XIGrabtypeTouchBeginInert with the same grab_window and the same
> +        modifier combination, the failed modifier combinations are returned
> +        in modifiers_return. If num_modifiers_return is zero, all passive
> +        grabs have been successful.
>  
>          If a button grab or enter grab activates, EnterNotify and LeaveNotify
>          events with mode Grab are generated as if the pointer were to suddenly
> @@ -1513,11 +1526,13 @@ are required to be 0.
>          XIAllowTouchEvents: (since XI 2.1)
>              deviceid:        DEVICEID
>              touchid:         CARD32
> -            event_mode:      SETofALLOWTOUCHMODEs
> +            event_mode:      ALLOWTOUCHMODE
> +            flags:           SETofALLOWTOUCHFLAGS
>      └───
>  
> -    ALLOWTOUCHMODE  { TouchOwnerAccept, TouchOwnerReject,
> -                      TouchNoPointerEmulation }
> +    ALLOWTOUCHMODE  { TouchOwnerAccept, TouchOwnerRejectEnd,
> +                      TouchOwnerRejectContinue }
> +    ALLOWTOUCHFLAGS (none currently defined)
>  
>      The XIAllowTouchEvents request allows the current owner of a touch
>      sequence to direct further delivery.
> @@ -1527,21 +1542,23 @@ are required to be 0.
>      touchid
>          The ID of the currently-grabbed touch sequence.
>      event_mode
> -        A bitmask of event modes for future delivery:
> -        If TouchOwnerAccept is set, the client is deemed to have taken control
> -        of the touch sequence, and no further events will be sent to any other
> -        clients for this touch sequence.  Additionally, if
> -        TouchNoPointerEmulation is set, then no more emulated pointer events
> -        will be generated from this touch sequence.  Setting
> -        TouchNoPointerEmulation with anything other than TouchOwnerAccept will
> -        result in a BadValue error.
> -        If TouchOwnerReject is set, the client is no longer interested in the
> -        touch sequence, and ownership will be passed on to the next delivery
> -        candidate (a grab on a child window, or a selection).
> +        Given TouchOwnerAccept, the client is deemed to have taken control
> +        of the touch sequence; TouchEnd events will be sent to all other
> +        clients listening to the touch sequence, and they will no longer
> +        receive any TouchUpdate events.
> +        Given TouchOwnerRejectEnd, the client is no longer interested in the
> +        touch sequence, and will receive a TouchEnd event; ownership will be
> +        passed on to the next listener.
> +        Given TouchOwnerRejectContinue, the client is not interested in
> +        ownership, but still wishes to receive TouchUpdate events;
> +        ownership will be passed on to the next listener.
> +    flags
> +        A bitmask of applicable flags.
>  
>      A BadValue error occurs if the touch ID is invalid, or BadAccess if this
> -    client is not the current owner of the specified touchid.  BadValue errors
> -    also occur if an invalid value is given for event_mode.
> +    client is not the current owner of the specified touch ID.  BadValue errors
> +    also occur if an invalid value is given for event_mode.  Any flags not
> +    understood by the server will be ignored.
>  
>  
>  8. Events:
> @@ -1575,8 +1592,8 @@ Version 2.0:
>          PropertyEvent
>  Version 2.1:
>          TouchBegin
> -        TouchMotion
> -        TouchMotionUnowned
> +        TouchUpdate
> +        TouchUpdateUnowned
>          TouchOwnership
>          TouchEnd
>  
> @@ -1722,17 +1739,17 @@ EVENTHEADER { type:                       BYTE
>  
>      DEVICEEVENTFLAGS (all events): none
>      DEVICEEVENTFLAGS (key events only): { KeyRepeat }
> -    DEVICEEVENTFLAGS (pointer events only): { TouchPointer }
> -    DEVICEEVENTFLAGS (touch events only): { TouchPendingFinish }
> -    DEVICEEVENTFLAGS (touch end events only): { TouchOwnerAccepted }
> +    DEVICEEVENTFLAGS (pointer events only): { PointerEmulated }
> +    DEVICEEVENTFLAGS (touch events only): { TouchPendingEnd }
> +    DEVICEEVENTFLAGS (touch end events only): { TouchAccepted }
>  
>      An XIDeviceEvent is generated whenever the logical state of a device
>      changes in response to a button press, a button release, a motion, a key
>      press or a key release. The event type may be one of KeyPress,
>      KeyRelease, ButtonPress, ButtonRelease, Motion.
>  
> -    XI 2.1: The event type may also be TouchBegin, TouchMotion,
> -            TouchMotionUnowned, or TouchEnd.
> +    XI 2.1: The event type may also be TouchBegin, TouchUpdate,
> +            TouchUpdateUnowned, or TouchEnd.
>  
>      detail
>          The button number, key code, touch ID, or 0.
> @@ -1763,11 +1780,11 @@ EVENTHEADER { type:                       BYTE
>          Button state before the event.
>      valuators
>          Bitmask of valuators provided in axisvalues.
> -        XI 2.1: For event types TouchBegin, TouchMotion, TouchMotionUnowned, and
> +        XI 2.1: For event types TouchBegin, TouchUpdate, TouchUpdateUnowned, and
>          TouchEnd, the valuators are those specified as TouchAxisClass.
>      axisvalues
>          Valuator data in device-native resolution.
> -        XI 2.1: For event types TouchBegin, TouchMotion, TouchMotionUnowned, and
> +        XI 2.1: For event types TouchBegin, TouchUpdate, TouchUpdateUnowned, and
>          TouchEnd, the valuators are those specified as TouchAxisClass.
>      flags
>          Miscellaneous information about this event; the union of the
> @@ -1776,19 +1793,19 @@ EVENTHEADER { type:                       BYTE
>          KeyRepeat means that this event is for repeating purposes, and
>          the physical state of the key has not changed.  This is only
>          valid for KeyPress events.
> -        TouchPointer means that this event is an emulated pointer event caused
> -        by a touch device. A client listening to touch events and pointer
> -        events should ignore TouchPointer events to avoid duplicate
> +        PointerEmulated means that this event is an emulated pointer event
> +        caused by a touch device. A client listening to touch events and pointer
> +        events should ignore PointerEmulated events to avoid duplicate
>          processing.  This is only valid for pointer events (MotionNotify,
>          ButtonPress, ButtonRelease).
> -        TouchOwnerAccepted (for TouchEnd events only) means that the current
> -        owner of the touch stream has “accepted” it, and this client will not 
> -        receive any further events from that touch sequence.
> -        TouchPendingFinish (for touch events only) means that the touch
> +        TouchAccepted (for TouchEnd events only) means that the current owner
> +        of the touch stream has “accepted” it, and this client will not receive
> +        any further events from that touch sequence.


thinking about this again, it leaves us with a strange situation for
RejectContinue:
Given the window hierarchy A being parent of B being parent of C and touch
grabs by different clients on all three.

Touch starts
  * TouchBegin + TouchUpdate to A
  * TouchBegin + TouchUpdateUnowned to B and C

RejectContinue on A
  * TouchUpdateUnowned to A
  * TouchOwner + TouchUpdate to B
  * TouchUpdateUnownd to C

Accept on B
  * * TouchUpdateUnowned to A, or
    * TouchUpate(End) to A
  * TouchUpdate + eventual TouchEnd to B
  * TouchUpdate(End) to C


so depending on what we do with A, we have the two different scenarios:
- if we keep sending events to A, this means that you can only do touch
  event monitoring (such as for the visual feedback) you're on top of all
  other windows. all clients will thus race to the top and compete there
  (only one client can select on a window, right?)
- if we stop sending events to A, then exactly the features this would allow
  aren't possible (and GrabtypeInert/RejectContinue becomes rather pointless)

The only solution seems to be  keep sending UpdateUnowned events regardless
of the "accept" status. this needs to be worked into the text.

> +        TouchPendingEnd (for touch events only) means that the touch
>          has physically ended, however another client still holds a grab, so the
>          touch should be considered alive until all grabbing clients have
>          accepted or passed on ownership.  The touch will not generate any
> -        further motion events once an event with TouchPendingFinish has been
> +        further motion events once an event with TouchPendingEnd has been
>          received.
>  
>      Modifier state in mods is detailed as follows:
> @@ -1811,11 +1828,10 @@ EVENTHEADER { type:                       BYTE
>  
>      A TouchBegin event is generated whenever a new touch sequence initializes
>      A TouchEnd event is generated whenever a touch sequence ceases. A
> -    TouchMotion event is generated whenever a touch axis valuator value
> -    changes, or a flag (e.g. pending finish) has changed for that touch
> -    sequence; this may result in a TouchMotion event being sent with zero
> -    valuators. A TouchOwnership event is sent when a client becomes the owner
> -    of a touch.
> +    TouchUpdate event is generated whenever a touch axis valuator value
> +    changes, or a flag (e.g. pending end) has changed for that touch sequence;
> +    this may result in a TouchUpdate event being sent with zero valuators. A
> +    TouchOwnership event is sent when a client becomes the owner of a touch.
>  
>      The average finger size is significantly larger than one pixel. The
>      selection of the hotspot of a touchpoint is implementation dependent and
> @@ -1824,10 +1840,13 @@ EVENTHEADER { type:                       BYTE
>      Touch tracking IDs are provided in the detail field of touch events. Its
>      value is always provided in every touch event. Tracking IDs are
>      represented as unsigned 32-bit values and increase in value for each new
> -    touch. Values will wrap back to 0 upon reaching the numerical limit of IDs.
> +    touch, wrapping back to 0 upon reaching the numerical limit of IDs.
>  
>      Touch events do not generate enter/leave events, and are not affected by
> -    other grabs (including device freezing).
> +    other grabs (including device freezing), although any pointer events
> +    generated by emulation will still be subject to all the same constraints
> +    as normal pointer events, including enter/leave events, and being affected
> +    by frozen devices.

btw, what will get really interesting is if you have a confine_to window
involved. I think the best solution here is to simply state that confine_to only
affects pointer emulation but not touch events.

>      ┌───
>          RawEvent
> @@ -1965,27 +1984,21 @@ XI 2.1:
>          TouchOwnershipEvent (since XI 2.1):
>              EVENTHEADER
>              sourceid:                   DEVICEID
> -            reason:                     TOUCHOWNERSHIPREASON
>              touchid:                    CARD32
>              flags:                      SETofTOUCHOWNERSHIPFLAGS
>      └───
>  
> -    TOUCHOWNERSHIPREASON:   { XITouchOwnerAccept, XITouchOwnerReject }
>      TOUCHOWNERSHIPFLAGS:    (none currently defined)
>  
>      A TouchOwnershipEvent indicates that ownership has changed, and the client
> -    is now the owner of the touch sequence specified by touchid.  The reason
> -    field optionally provides an indication of why this occurred.
> +    is now the owner of the touch sequence specified by touchid.
>  
>      sourceid
>          The source device that originally generated the event.
> -    reason
> -        The reason ownership changed; at present, XITouchOwnerReject is the
> -        only defined reason.
>      touchid
>          The identifier of the touch sequence.
>      flags
> -        A bitmask of flags for this event; none are currently defined.
> +        A bitmask of flags for this event.
>  
>  
>                                ❧❧❧❧❧❧❧❧❧❧❧
> @@ -1998,12 +2011,12 @@ require the client to announce XI 2.1 support in the XIQueryVersion request.
>  
>  ∙ Client C wants to process touch events from a device D on window W.
>      ⊳ C calls XISelectEvent for
> -      XI_Touch{Begin|Motion|MotionUnowned|Ownership|End} from D on W.
> +      XI_Touch{Begin|Update|UpdateUnowned|Ownership|End} from D on W.
>      ⊳ C receives TouchBegin whenever a touch sequence starts within
>        W's borders.
>      ⊳ C receives a TouchOwnership event indicating that it is now the owner
>        of the touch sequence.
> -    ⊳ C receives TouchMotion events whenever a touch axis valuator value
> +    ⊳ C receives TouchUpdate events whenever a touch axis valuator value
>        changes for a touch sequence it received a TouchBegin event for.
>      ⊳ C receives TouchEnd whenever a touch it received an TouchBegin event
>        for ceases.
> @@ -2011,36 +2024,57 @@ require the client to announce XI 2.1 support in the XIQueryVersion request.
>  ∙ Client C wants to process touch events from a device D on window W, while
>    client I wants to pre-process these events.
>      ⊳ C calls XISelectEvent for
> -      XI_Touch{Begin|Motion|MotionUnowned|Ownership|End} from D on W.
> +      XI_Touch{Begin|Update|UpdateUnowned|Ownership|End} from D on W.
>      ⊳ I calls XIPassiveGrab for
> -      XI_Touch{Begin|Motion|MotionUnowned|Ownership|End} from D on a parent
> +      XI_Touch{Begin|Update|UpdateUnowned|Ownership|End} from D on a parent
>        window of W.
>      ⊳ I receives TouchBegin whenever a touch begins within window W, as well
>        as a TouchOwnership event indicating that it currently owns the touch
>        sequence.  C receives a TouchBegin event as well, but without
>        TouchOwnership.
>      ⊳ When a touch axis valuator changes in this touch sequence, I receives a
> -      TouchMotion event, while C receives a TouchMotionUnowned event.  I may
> +      TouchUpdate event, while C receives a TouchUpdateUnowned event.  I may
>        process the events to determine if it is going to claim or reject the
>        touch, whereas C may perform reversible processing.
>      ⊳ If I decides it is going to claim the event for its exclusive
>        processing, it calls XIAllowTouchEvents with the XITouchOwnerAccept flag
>        set; at this point, C receives a TouchEnd event with the
> -      TouchOwnerAccepted flag set, and undoes any processing it may have done
> -      on the touch sequence.  Further TouchMotion events are delivered only
> +      TouchAccepted flag set, and undoes any processing it may have done
> +      on the touch sequence.  Further TouchUpdate events are delivered only
>        to I.
>      ⊳ Alternately, if I decides it does not want to receive further events from
>        this touch sequence, it calls XIAllowTouchEvents with the
>        XITouchOwnerReject flag set; at this point, I receives a TouchEnd event
>        confirming that it has rejected the touch.  C receives a TouchOwnership
>        event confirming that it is now the new owner of the touch, and further
> -      TouchMotion events are delivered only to C.  As C now owns the touch,
> +      TouchUpdate events are delivered only to C.  As C now owns the touch,
>        it is free to perform irreversible processing of the sequence.
>      ⊳ When the touch physically ceases, a TouchEnd event is sent to all
> -      clients still receiving TouchMotion events.
> +      clients still receiving TouchUpdate events.
> +
> +∙ Client C wants to process touch events from a device D on window W, while
> +  client I wants to process pointer events on window Y, which is W's parent.
> +    ⊳ I calls XIPassiveGrab for XI_{ButtonPress,MotionNotify,ButtonRelease}

typo: XI_Motion, not XI_MotionNotify

I think this looks good, but by now my head is rather spinning.

Cheers,
  Peter

> +      from D on Y.
> +    ⊳ C calls XISelectEvent for
> +      XI_Touch{Begin|Update|UpdateUnowned|Ownership|End} from D on W.
> +    ⊳ I receives a ButtonPress event whenever a touch begins within W, and is
> +      considered the owner of the event.  C receives a TouchBegin event, but
> +      does not receive a TouchOwnership event.
> +    ⊳ When the touchpoint moves, I will receive a MotionNotify event, and C
> +      will receive a TouchUpdateUnowned event.  Event delivery to I will be
> +      subject to the standard delivery mechanism (including being queued if
> +      the device is frozen, et al), while C receives events as soon as they
> +      are processed by the server.
> +    ⊳ I may assert ownership by calling XIAllowEvents on Y with AsyncDevice,
> +      which will cause all further events to be sent only to I, with a
> +      TouchEnd event being sent to C.
> +    ⊳ Alternately, I may assert disinterest by calling XIAllowEvents on Y
> +      with ReplayDevice, which will cause no further events from that touch
> +      to be sent to I, and a TouchOwnership event to be sent to C, with
> +      subsequent motion events being sent as TouchMotion.
>  
>  ∙  Driver DRV provides touch support from tracked device D:
> -    XXX: Pointer emulation semantics are yet to be determined.
>      ⊳ DRV initializes a TouchClass for the device and a TouchAxisClass for
>        each axis available on the device.
>      ⊳ DRV parses D's device protocol and selects one touch sequence to be





More information about the xorg-devel mailing list