[PATCH inputproto 2/2] Add touch classes and events, bump to 2.1

Daniel Stone daniel at fooishbar.org
Fri Dec 17 09:11:10 PST 2010

From: Chase Douglas <chase.douglas at canonical.com>

Introduce multitouch support through a new TouchClass, as well as new
TouchBegin, TouchEnd and TouchMotion events.  Bump to version 2.1.

Based on an initial patch by Daniel Stone (headers) and Peter Hutterer
(protocol documentation).

Signed-off-by: Daniel Stone <daniel at fooishbar.org>
Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
 XI2.h        |   29 +++++-
 XI2proto.h   |   44 ++++++++-
 XI2proto.txt |  303 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 configure.ac |    2 +-
 4 files changed, 362 insertions(+), 16 deletions(-)

diff --git a/XI2.h b/XI2.h
index 6ba1377..18602f8 100644
--- a/XI2.h
+++ b/XI2.h
@@ -36,6 +36,7 @@
 #define XI_2_Major                              2
 #define XI_2_Minor                              0
+#define XI_2_1_Minor                            1
 /* Property event flags */
 #define XIPropertyDeleted                       0
@@ -65,6 +66,7 @@
 #define XIGrabtypeKeycode                       1
 #define XIGrabtypeEnter                         2
 #define XIGrabtypeFocusIn                       3
+#define XIGrabtypeTouchBegin                    4
 /* Passive grab modifier */
 #define XIAnyModifier                           (1U << 31)
@@ -79,6 +81,11 @@
 #define XIAsyncPair                             4
 #define XISyncPair                              5
+/* XIAllowTouchEvents bitmask event-modes */
+#define XITouchOwnerAccept                      (1 << 0)
+#define XITouchOwnerReject                      (1 << 1)
+#define XITouchNoPointerEmulation               (1 << 2)
 /* DeviceChangedEvent change reasons */
 #define XISlaveSwitch                           1
 #define XIDeviceChange                          2
@@ -113,15 +120,27 @@
 #define XISlaveKeyboard                         4
 #define XIFloatingSlave                         5
-/* Device classes */
+/* Device classes: classes that are not identical to Xi 1.x classes must be
+ * numbered starting from 8. */
 #define XIKeyClass                              0
 #define XIButtonClass                           1
 #define XIValuatorClass                         2
+#define XITouchClass                            8
+#define XITouchValuatorClass                    9
 /* Device event flags (common) */
 /* Device event flags (key events only) */
 #define XIKeyRepeat                             (1 << 16)
 /* Device event flags (pointer events only) */
+#define XITouchPointer                          (1 << 16)
+/* Device event flags (touch events only) */
+#define XITouchOwner                            (1 << 16)
+#define XITouchOwnerAccepted                    (1 << 17)
+#define XITouchPendingFinish                    (1 << 18)
+/* Touch modes */
+#define XIDirectTouch                           1
+#define XIDependentTouch                        2
 /* XI2 event mask macros */
 #define XISetMask(ptr, event)   (((unsigned char*)(ptr))[(event)>>3] |=  (1 << ((event) & 7)))
@@ -151,7 +170,10 @@
 #define XI_RawButtonPress                15
 #define XI_RawButtonRelease              16
 #define XI_RawMotion                     17
-#define XI_LASTEVENT                     XI_RawMotion
+#define XI_TouchBegin                    18
+#define XI_TouchEnd                      19
+#define XI_TouchMotion                   20
+#define XI_LASTEVENT                     XI_TouchMotion
 /* 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. */
@@ -177,5 +199,8 @@
 #define XI_RawButtonPressMask            (1 << XI_RawButtonPress)
 #define XI_RawButtonReleaseMask          (1 << XI_RawButtonRelease)
 #define XI_RawMotionMask                 (1 << XI_RawMotion)
+#define XI_TouchBeginMask                (1 << XI_TouchBegin)
+#define XI_TouchEndMask                  (1 << XI_TouchEnd)
+#define XI_TouchMotionMask               (1 << XI_TouchMotion)
 #endif /* _XI2_H_ */
diff --git a/XI2proto.h b/XI2proto.h
index 84574a5..f7510cc 100644
--- a/XI2proto.h
+++ b/XI2proto.h
@@ -92,9 +92,10 @@
 #define X_XIDeleteProperty              58
 #define X_XIGetProperty                 59
 #define X_XIGetSelectedEvents           60
+#define X_XIAllowTouchEvents            61
 /** Number of XI requests */
-#define XI2REQUESTS (X_XIGetSelectedEvents - X_XIQueryPointer + 1)
+#define XI2REQUESTS (X_XIAllowTouchEvents - X_XIQueryPointer + 1)
 /** Number of XI2 events */
 #define XI2EVENTS   (XI_LASTEVENT + 1)
@@ -188,6 +189,31 @@ typedef struct {
     uint16_t    pad2;
 } xXIValuatorInfo;
+ * Denotes multitouch capability on a device.
+ */
+typedef struct {
+    uint16_t    type;           /**< Always TouchClass */
+    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 */
+} xXITouchInfo;
+ * Denotes a multitouch valuator capability on a device.
+ * One XITouchValuatorInfo describes exactly one valuator (axis) on the device.
+ */
+typedef struct {
+    uint16_t    type;           /**< Always TouchValuatorClass  */
+    uint16_t    length;         /**< Length in 4 byte units */
+    uint16_t    sourceid;       /**< source device for this class */
+    uint16_t    number;         /**< Valuator number            */
+    Atom        label;          /**< Axis label                 */
+    FP3232      min;            /**< Min value                  */
+    FP3232      max;            /**< Max value                  */
+    uint32_t    resolution;     /**< Resolutions in units/m     */
+} xXITouchValuatorInfo;
  * Used to select for events on a given window.
@@ -772,6 +798,20 @@ typedef struct {
 } xXIGetPropertyReply;
 #define sz_xXIGetPropertyReply               32
+ * Accept or reject a grabbed touch sequence.
+ */
+typedef struct {
+    uint8_t     reqType;
+    uint8_t     ReqType;        /**< Always ::X_XIAllowTouchEvents */
+    uint16_t    length;         /**< Length in 4 byte units */
+    uint32_t    touchid;
+    uint16_t    deviceid;
+    uint8_t     mode;           /**< bitmask */
+    uint8_t     pad;
+} xXIAllowTouchEventsReq;
+#define sz_xXIAllowTouchEventsReq                   12
  *                                                                                   *
  *                                      EVENTS                                       *
@@ -857,7 +897,7 @@ typedef struct
 } xXIDeviceChangedEvent;
- * Default input event for pointer or keyboard input.
+ * Default input event for pointer, keyboard or touch input.
 typedef struct
diff --git a/XI2proto.txt b/XI2proto.txt
index 10f58c2..7105c74 100644
--- a/XI2proto.txt
+++ b/XI2proto.txt
@@ -1,6 +1,7 @@
                             The X Input Extension
                                 Version 2.0
+                                Version 2.1
                               Peter Hutterer
                          peter.hutterer at redhat.com
@@ -31,6 +32,40 @@ used on applications employing the core protocol. XI2 addresses both of these
 issues by enabling devices to be both extended and core devices and providing
 device information in each event (with the exception of core events).
+1.1 X Input Extension version 2.1 (XI 2.1)
+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.
+The additions in XI 2.1 aim to:
+- provide backwards compatible pointer emulation for single-touch
+  interaction,
+- support a dynamic number of simultaneous touch points,
+- support devices that are both multi-touch and traditional pointer devices.
+XI 2.1 caters for two modes of touch input devices:
+- direct multi-touch input devices such as touch screens. These devices
+  provide independent touchpoints that can occur anywhere on the screen and
+  are usually the result of direct touch interaction.
+- indirect touch input devices such as multi-touch trackpads. These devices
+  provide independent touchpoints that may need to be interpreted
+  relative to the current position of the pointer on that same device. Such
+  interactions are usually the result of a gesture performed on the device.
+A device may change its touch mode at runtime. Clients are informed which
+type of touch device they are dealing with. See XIQueryDevice for more
+Touch device support is only available to clients supporting version 2.1 or
+later of the X Input Extension. Clients must use the XIQueryVersion request to
+announce support of this version.
+XI 2.1 requires devices to track touch points over time. Devices that cannot
+do so in hardware must employ software trackers to be useable with XI 2.1.
 2. Notations used in this document
@@ -149,7 +184,63 @@ to P is only attempted if neither the XI event, nor the core event has been
 delivered on W. Once an event has been delivered as either XI or core event,
 event processing stops.
-4.4. The ClientPointer principle
+4.4 Touch device support
+Touch event processing differs from normal event processing in a few ways,
+most notably in that touch events are processed partially out-of-band from
+pointer and keyboard events.
+Touch input follows a three-stage cycle: init - move - move - ... - destroy,
+i.e. “init” the sequence by touching the device, “move” the current touch
+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
+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
+pass a partial touch sequence on to the next client.  To this end, all clients
+with active “grabs” on the window hierachy 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).  An “owner” flag is provided for clients
+to know whether they are currently in control of the touch sequence or not.
+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.
+Window sets for direct device touches contain the windows from the root to the
+child in which the touch originated.
+Dependent device window sets depend on whether other touches are active. For
+the first dependent touch on a device, the window set contains the windows from
+the root to the the current window underneath the position of the device's
+sprite. For subsequent touches on this device, the window set is identical to
+the window set of the first touch. Once all touches have been released, the
+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 a sprite to focus events to.
+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.
+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
+follow the core and XI2 grab semantics.
+4.5. The ClientPointer principle
 Many core protocol and some extension requests are ambiguous when multiple
 master devices are available (e.g. QueryPointer does not specfy which pointer).
@@ -271,7 +362,7 @@ are required to be 0.
                  name:                  LISTofCHAR8
                  classes:               LISTofCLASS }
     BUTTONCLASS { type:                 ButtonClass
                   length:               CARD16
@@ -296,6 +387,26 @@ are required to be 0.
                   value:                FP3232
                   resolution:           CARD32 }
+    TOUCHCLASS* { type:                 TouchClass
+                  length:               CARD16
+                  sourceid:             CARD16
+                  mode:                 TOUCHMODE
+                  num_touches:          CARD16 }
+                  type:                 TouchAxisClass
+                  length:               CARD16
+                  sourceid:             CARD16
+                  axisnumber:           CARD16
+                  label:                ATOM
+                  min:                  FP3232
+                  max:                  FP3232
+                  resolution:           CARD32 }
+    TOUCHMODE* { DirectTouch, DependentTouch }
+    * since XI 2.1
     XIQueryDevice details information about the requested input devices.
@@ -397,6 +508,53 @@ are required to be 0.
     An axis in Relative mode may specify min and max as a hint to the
     client. If no min and max information is available, both must be 0.
+    XI 2.1:
+    TouchClass:
+    type
+        Always TouchClass.
+    length
+        Length in 4 byte units.
+    sourceid
+        The device this class originates from.
+    mode
+        The device type of the touch device. Touch sequences from a device
+        of type DirectTouch should be interpreted as directly occuring on
+        the position they are reported on. Touch sequences from a device of
+        type DependentTouch should be interpreted as dependent of the
+        current position of the pointer.
+    num_touches
+        The maximum number of sumultaneous touchpoints the device may send.
+        If num_touches is 0, the number of supported touches is unknown.
+    A device with a TouchClass must provide one or more TOUCHAXISCLASS
+    specifiers.
+    TouchAxisClass:
+    type
+        Always TouchAxisClass.
+    length
+        Length in 4 byte units.
+    sourceid
+        The device this class originates from.
+    axisnumber
+        Axis number of this axis. The axis number is in device-native
+        order and potential axis mappings are ignored.
+    label
+        Atom specifying the axis name. An Atom of None specifies an unlabeled
+        axis.
+    min
+        Minimum value.
+    max
+        Minimum value.
+    resolution
+        Resolution in counts/meter.
+    Devices generating touch events must provide exactly one TouchClass and
+    two or more TouchAxisClasses. TouchAxisClasses and AxisClasses are not
+    interchangable. A TouchAxisClass may only be part of a touch event,
+    whereas an AxisClass may only be part of non-touch events.
             window:         Window
@@ -439,6 +597,12 @@ 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. 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.
             window:         Window
@@ -999,7 +1163,7 @@ are required to be 0.
         GRABTYPE         { GrabtypeButton, GrabtypeKeycode, GrabtypeEnter,
-                           GrabtypeFocusIn}
+                           GrabtypeFocusIn, GrabtypeTouchBegin }
         GRABMODIFIERINFO {   status:    Access
                              modifiers: CARD32 }
@@ -1015,7 +1179,8 @@ are required to be 0.
             The button number, or key symbol to grab for.
-            Must be 0 for GrabtypeEnter and GrabtypeFocusIn.
+            Must be 0 for GrabtypeEnter, GrabtypeFocusIn, and
+            GrabtypeTouchBegin.
             The type of grab to establish.
@@ -1030,6 +1195,7 @@ 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).
             Length of mask in 4 byte units.
@@ -1087,6 +1253,13 @@ 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:
+        - 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.
         A modifier of GrabAnyModifier is equivalent to issuing the request for
         all possible modifier combinations (including no modifiers). A client
         may request a grab for GrabAnyModifier and explicit modifier
@@ -1097,6 +1270,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.
         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
@@ -1109,10 +1285,10 @@ 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 or XIGrabtypeFocusIn 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, 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.
         If a button grab or enter grab activates, EnterNotify and LeaveNotify
         events with mode Grab are generated as if the pointer were to suddenly
@@ -1133,6 +1309,11 @@ are required to be 0.
         XIPassiveUngrabNotify are generated and sent to the grabbing client
         before the grab deactivates.
+        See section 4.4 for additional notes on touch grabs, as they do not
+        behave like traditional grabs: in particular, they do not freeze the
+        device, and delivery of touch events continues even if the device is
+        frozen due to a grab by another client.
             deviceid:        DEVICEID
@@ -1149,7 +1330,8 @@ are required to be 0.
             The device to establish the passive grab on.
             The button number or key symbol to ungrab.
-            Must be 0 for GrabtypeEnter and GrabtypeFocusIn.
+            Must be 0 for GrabtypeEnter, GrabtypeFocusIn, and
+            GrabtypeTouchBegin.
             The type of grab to establish.
@@ -1308,6 +1490,37 @@ are required to be 0.
         deleted from the device, and a XIPropertyNotify event is generated on
         the device.  
+    ┌───
+        XIAllowTouchEvents: (since XI 2.1)
+            deviceid:        DEVICEID
+            touchid:         CARD32
+            event_mode:      CARD8
+    └───
+    The XIAllowTouchEvents request allows the current owner of a touch
+    sequence to direct further delivery.
+    deviceid
+        The grabbed device ID.
+    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).
+    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.
 8. Events:
@@ -1338,6 +1551,10 @@ Version 2.0:
+Version 2.1:
+        TouchBegin
+        TouchMotion
+        TouchEnd
 All events have a set of common fields specified as EVENTHEADER.
@@ -1481,15 +1698,19 @@ EVENTHEADER { type:                       BYTE
     DEVICEEVENTFLAGS (all events): none
     DEVICEEVENTFLAGS (key events only): { KeyRepeat }
-    DEVICEEVENTFLAGS (pointer events only): none
+    DEVICEEVENTFLAGS (pointer events only): { TouchPointer }
+    DEVICEEVENTFLAGS (touch events only): { TouchOwner, TouchOwnerAccepted,
+                                            TouchPendingFinish }
     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, or TouchEnd.
-        The button number or key code, or 0.
+        The button number, key code, touch ID, or 0.
@@ -1517,8 +1738,12 @@ EVENTHEADER { type:                       BYTE
         Button state before the event.
         Bitmask of valuators provided in axisvalues.
+        XI 2.1: For event types TouchBegin, TouchMotion, TouchEnd, the
+        valuators are those specified as TouchAxisClass.
         Valuator data in device-native resolution.
+        XI 2.1: For event types TouchBegin, TouchMotion, TouchEnd, the
+        valuators are those specified as TouchAxisClass.
         Miscellaneous information about this event; the union of the
         common flag set and either the key or pointer flag set,
@@ -1526,6 +1751,17 @@ 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
+        processing.
+        TouchOwner means that the client is the current owner of the touch.
+        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 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.
     Modifier state in mods is detailed as follows:
@@ -1543,6 +1779,25 @@ EVENTHEADER { type:                       BYTE
         XKB locked group state.
+    XI 2.1:
+    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 ownership has changed for that touch sequence.
+    The average finger size is significantly larger than one pixel. The
+    selection of the hotspot of a touchpoint is implementation dependent and
+    may not be the logical center of the touch.
+    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 events do not generate enter/leave events, and are not affected by
+    other grabs (including device freezing).
@@ -1675,3 +1930,29 @@ EVENTHEADER { type:                       BYTE
+Appendix A: XI 2.1 Use-cases
+All use-cases that include the receiving and processing of touch events
+require the client to announce XI 2.1 support in the XIQueryVersion request.
+XXX: Add grab usecases.
+∙ Client C wants to process touch events from a device D on window W.
+    ⊳ C registers for XITouch{Begin|Motion|End}Event from D on W.
+    ⊳ C receives XITouchBeginEvent whenever a touch sequence starts within
+      W's borders.
+    ⊳ C receives XITouchMotionEvents whenever a touch axis valuator value
+      changes for a touch that began within W's borders.
+    ⊳ C receives XITouchEndEvent whenever a touch that began within W's
+      borders ceases.
+∙  Driver DRV provides touch support from tracked device D:
+    ⊳ 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
+      emulated as pointer event.
+    ⊳ DRV calls the respective input driver API with the touch sequence
+      data. The touch sequence emulating a pointer has the respective flag
+      set. DRV does not submit pointer data for any touchpoint.
diff --git a/configure.ac b/configure.ac
index 39e4df9..894d2cd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
-AC_INIT([InputProto], [2.0.1], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg])
+AC_INIT([InputProto], [], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])

More information about the xorg-devel mailing list