[PATCH (v5) libXi 1/1] Add multitouch support from Xi 2.1

Daniel Stone daniel at fooishbar.org
Wed Jan 19 15:11:43 PST 2011


Add support to libXi for touch events.

Signed-off-by: Daniel Stone <daniel at fooishbar.org>
Co-authored-by: Chase Douglas <chase.douglas at canonical.com>
---

v5: Added support for new TouchMotionUnowned and TouchOwnership events.
    Fix a CopyCookie buglet where touch events wouldn't get copied at all.

 configure.ac                     |    4 +-
 include/X11/extensions/XInput2.h |   60 +++++++++++++++++++++
 src/XExtInt.c                    |  108 +++++++++++++++++++++++++++++++++++++-
 src/XIAllowEvents.c              |   24 ++++++++
 src/XIPassiveGrab.c              |   21 +++++++
 5 files changed, 213 insertions(+), 4 deletions(-)

diff --git a/configure.ac b/configure.ac
index 0a4b384..173537a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to create configure.
 
 AC_PREREQ([2.60])
 
-AC_INIT(libXi, 1.4.0, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], libXi)
+AC_INIT(libXi, 1.4.99.1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], libXi)
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
 
@@ -24,7 +24,7 @@ AC_PROG_LIBTOOL
 AC_PROG_SED
 
 # Checks for pkg-config packages
-PKG_CHECK_MODULES(XI, [xproto >= 7.0.13] [x11 >= 1.2.99.1] [xextproto >= 7.0.3] [xext >= 1.0.99.1] [inputproto >= 1.9.99.902])
+PKG_CHECK_MODULES(XI, [xproto >= 7.0.13] [x11 >= 1.2.99.1] [xextproto >= 7.0.3] [xext >= 1.0.99.1] [inputproto >= 2.0.99.1])
 
 # Check for xmlto and asciidoc for man page conversion
 # (only needed by people building tarballs)
diff --git a/include/X11/extensions/XInput2.h b/include/X11/extensions/XInput2.h
index e6c7b30..46b0162 100644
--- a/include/X11/extensions/XInput2.h
+++ b/include/X11/extensions/XInput2.h
@@ -135,6 +135,25 @@ typedef struct
 
 typedef struct
 {
+    int          type;
+    int          sourceid;
+    int          mode;
+    int          num_touches;
+} XITouchClassInfo;
+
+typedef struct
+{
+    int          type;
+    int          sourceid;
+    int          number;
+    Atom         label;
+    double       min;
+    double       max;
+    int          resolution;
+} XITouchValuatorClassInfo;
+
+typedef struct
+{
     int                 deviceid;
     char                *name;
     int                 use;
@@ -292,6 +311,21 @@ typedef struct {
     int           what;
 } XIPropertyEvent;
 
+typedef struct {
+    int           type;         /* GenericEvent */
+    unsigned long serial;       /* # of last request processed by server */
+    Bool          send_event;   /* true if this came from a SendEvent request */
+    Display       *display;     /* Display the event was read from */
+    int           extension;    /* XI extension offset */
+    int           evtype;
+    Time          time;
+    int           deviceid;
+    int           sourceid;
+    unsigned long touchid;
+    int           reason;
+    unsigned long flags;
+} XITouchOwnershipEvent;
+
 _XFUNCPROTOBEGIN
 
 extern Bool     XIQueryPointer(
@@ -415,6 +449,13 @@ extern Status XIAllowEvents(
     Time                time
 );
 
+extern Status XIAllowTouchEvents(
+    Display*            display,
+    int                 deviceid,
+    unsigned long       touchid,
+    int                 event_mode
+);
+
 extern int XIGrabButton(
     Display*            display,
     int                 deviceid,
@@ -466,6 +507,17 @@ extern int XIGrabFocusIn(
     int                 num_modifiers,
     XIGrabModifiers     *modifiers_inout
 );
+
+extern int XIGrabTouchBegin(
+    Display*            display,
+    int                 deviceid,
+    Window              grab_window,
+    int                 owner_events,
+    XIEventMask         *mask,
+    int                 num_modifiers,
+    XIGrabModifiers     *modifiers_inout
+);
+
 extern Status XIUngrabButton(
     Display*            display,
     int                 deviceid,
@@ -500,6 +552,14 @@ extern Status XIUngrabFocusIn(
     XIGrabModifiers     *modifiers
 );
 
+extern Status XIUngrabTouchBegin(
+    Display*            display,
+    int                 deviceid,
+    Window              grab_window,
+    int                 num_modifiers,
+    XIGrabModifiers     *modifiers
+);
+
 
 extern Atom *XIListProperties(
     Display*            display,
diff --git a/src/XExtInt.c b/src/XExtInt.c
index f96e3ff..055bdf5 100644
--- a/src/XExtInt.c
+++ b/src/XExtInt.c
@@ -146,6 +146,9 @@ static int
 wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie);
 static int
 wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie);
+static int
+wireToTouchOwnershipEvent(xXITouchOwnershipEvent *in,
+                          XGenericEventCookie *cookie);
 
 static /* const */ XEvent emptyevent;
 
@@ -268,7 +271,8 @@ static XExtensionVersion versions[] = { {XI_Absent, 0, 0},
  XI_Add_DevicePresenceNotify_Minor},
 {XI_Present, XI_Add_DeviceProperties_Major,
  XI_Add_DeviceProperties_Minor},
-{XI_Present, XI_2_Major, XI_2_Minor}
+{XI_Present, XI_2_Major, XI_2_Minor},
+{XI_Present, XI_2_Major, XI_2_1_Minor}
 };
 
 /***********************************************************************
@@ -924,6 +928,10 @@ XInputWireToCookie(
         case XI_ButtonRelease:
         case XI_KeyPress:
         case XI_KeyRelease:
+        case XI_TouchBegin:
+        case XI_TouchMotion:
+        case XI_TouchMotionUnowned:
+        case XI_TouchEnd:
             *cookie = *(XGenericEventCookie*)save;
             if (!wireToDeviceEvent((xXIDeviceEvent*)event, cookie))
             {
@@ -950,7 +958,16 @@ XInputWireToCookie(
                 break;
             }
             return ENQUEUE_EVENT;
-
+        case XI_TouchOwnership:
+            *cookie = *(XGenericEventCookie*)save;
+            if (!wireToTouchOwnershipEvent((xXITouchOwnershipEvent*)event,
+                                           cookie))
+            {
+                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
+                        ge->evtype);
+                break;
+            }
+            return ENQUEUE_EVENT;
         case XI_RawKeyPress:
         case XI_RawKeyRelease:
         case XI_RawButtonPress:
@@ -1037,6 +1054,12 @@ sizeDeviceClassType(int type, int num_elements)
         case XIValuatorClass:
             l = sizeof(XIValuatorClassInfo);
             break;
+        case XITouchClass:
+            l = sizeof(XITouchClassInfo);
+            break;
+        case XITouchValuatorClass:
+            l = sizeof(XITouchValuatorClassInfo);
+            break;
         default:
             printf("sizeDeviceClassType: unknown type %d\n", type);
             break;
@@ -1239,6 +1262,22 @@ copyPropertyEvent(XGenericEventCookie *cookie_in,
 }
 
 static Bool
+copyTouchOwnershipEvent(XGenericEventCookie *cookie_in,
+                        XGenericEventCookie *cookie_out)
+{
+    XITouchOwnershipEvent *in, *out;
+
+    in = cookie_in->data;
+
+    out = cookie_out->data = malloc(sizeof(XITouchOwnershipEvent));
+    if (!out)
+        return False;
+
+    *out = *in;
+    return True;
+}
+
+static Bool
 copyRawEvent(XGenericEventCookie *cookie_in,
              XGenericEventCookie *cookie_out)
 {
@@ -1297,8 +1336,15 @@ XInputCopyCookie(Display *dpy, XGenericEventCookie *in, XGenericEventCookie *out
         case XI_ButtonRelease:
         case XI_KeyPress:
         case XI_KeyRelease:
+        case XI_TouchBegin:
+        case XI_TouchMotion:
+        case XI_TouchMotionUnowned:
+        case XI_TouchEnd:
             ret = copyDeviceEvent(in, out);
             break;
+        case XI_TouchOwnership:
+            ret = copyTouchOwnershipEvent(in, out);
+            break;
         case XI_DeviceChanged:
             ret = copyDeviceChangedEvent(in, out);
             break;
@@ -1427,6 +1473,12 @@ size_classes(xXIAnyInfo* from, int nclasses)
             case XIValuatorClass:
                 l = sizeDeviceClassType(XIValuatorClass, 0);
                 break;
+            case XITouchClass:
+                l = sizeDeviceClassType(XITouchClass, 0);
+                break;
+            case XITouchValuatorClass:
+                l = sizeDeviceClassType(XITouchValuatorClass, 0);
+                break;
         }
 
         len += l;
@@ -1527,6 +1579,35 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int nclasses)
 
                 }
                 break;
+            case XITouchClass:
+                {
+                    XITouchClassInfo *cls_lib;
+                    xXITouchInfo *cls_wire;
+
+                    cls_wire = (xXITouchInfo*)any_wire;
+                    cls_lib = next_block(&ptr_lib, sizeof(XITouchClassInfo));
+
+                    cls_lib->mode = cls_wire->mode;
+                    cls_lib->num_touches = cls_wire->num_touches;
+                }
+                break;
+            case XITouchValuatorClass:
+                {
+                    XITouchValuatorClassInfo *cls_lib;
+                    xXITouchValuatorInfo *cls_wire;
+
+                    cls_wire = (xXITouchValuatorInfo*)any_wire;
+                    cls_lib = next_block(&ptr_lib,
+                                         sizeof(XITouchValuatorClassInfo));
+
+                    cls_lib->number = cls_wire->number;
+                    cls_lib->label = cls_wire->label;
+                    /* FIXME: fractional parts */
+                    cls_lib->min = cls_wire->min.integral;
+                    cls_lib->max = cls_wire->max.integral;
+                    cls_lib->resolution = cls_wire->resolution;
+                }
+                break;
         }
         len += any_wire->length * 4;
         ptr_wire += any_wire->length * 4;
@@ -1699,6 +1780,29 @@ wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie)
 }
 
 static int
+wireToTouchOwnershipEvent(xXITouchOwnershipEvent *in,
+                          XGenericEventCookie *cookie)
+{
+    XITouchOwnershipEvent *out = malloc(sizeof(XITouchOwnershipEvent));
+
+    cookie->data = out;
+
+    out->type           = in->type;
+    out->display        = cookie->display;
+    out->extension      = in->extension;
+    out->evtype         = in->evtype;
+    out->send_event     = ((in->type & 0x80) != 0);
+    out->time           = in->time;
+    out->deviceid       = in->deviceid;
+    out->sourceid       = in->sourceid;
+    out->touchid        = in->touchid;
+    out->reason         = in->reason;
+    out->flags          = in->flags;
+
+    return 1;
+}
+
+static int
 wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie)
 {
     XIPropertyEvent *out = malloc(sizeof(XIPropertyEvent));
diff --git a/src/XIAllowEvents.c b/src/XIAllowEvents.c
index 75980a0..7a4ab53 100644
--- a/src/XIAllowEvents.c
+++ b/src/XIAllowEvents.c
@@ -51,3 +51,27 @@ XIAllowEvents(Display *dpy, int deviceid, int event_mode, Time time)
     SyncHandle();
     return Success;
 }
+
+Status
+XIAllowTouchEvents(Display *dpy, int deviceid, unsigned long touchid,
+                   int event_mode)
+{
+    xXIAllowTouchEventsReq *req;
+
+    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
+
+    LockDisplay(dpy);
+    if (_XiCheckExtInit(dpy, Dont_Check, extinfo) == -1) /* XXX: XI 2.1 only */
+	return (NoSuchExtension);
+
+    GetReq(XIAllowTouchEvents, req);
+    req->reqType = extinfo->codes->major_opcode;
+    req->ReqType = X_XIAllowTouchEvents;
+    req->deviceid = deviceid;
+    req->touchid = touchid;
+    req->mode = event_mode;
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+    return Success;
+}
diff --git a/src/XIPassiveGrab.c b/src/XIPassiveGrab.c
index 8953013..2867d9b 100644
--- a/src/XIPassiveGrab.c
+++ b/src/XIPassiveGrab.c
@@ -145,6 +145,18 @@ XIGrabFocusIn(Display *dpy, int deviceid, Window grab_window, int grab_mode,
                                 modifiers_inout);
 }
 
+int
+XIGrabTouchBegin(Display *dpy, int deviceid, Window grab_window,
+                 Bool owner_events, XIEventMask *mask,
+                 int num_modifiers, XIGrabModifiers *modifiers_inout)
+{
+    /* XXX: Check XI 2.1. */
+    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeTouchBegin, 0,
+                                grab_window, None, GrabModeAsync, GrabModeAsync,
+                                owner_events, mask, num_modifiers,
+                                modifiers_inout);
+}
+
 static int
 _XIPassiveUngrabDevice(Display* dpy, int deviceid, int grabtype, int detail,
                        Window grab_window, int num_modifiers, XIGrabModifiers *modifiers)
@@ -208,3 +220,12 @@ XIUngrabFocusIn(Display* display, int deviceid, Window grab_window,
     return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeFocusIn, 0,
                                   grab_window, num_modifiers, modifiers);
 }
+
+int
+XIUngrabTouchBegin(Display* display, int deviceid, Window grab_window,
+                   int num_modifiers, XIGrabModifiers *modifiers)
+{
+    /* XXX: Check XI 2.1. */
+    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeTouchBegin, 0,
+                                  grab_window, num_modifiers, modifiers);
+}
-- 
1.7.2.3



More information about the xorg-devel mailing list