[PATCH libXi] Add multitouch support from Xi 2.1

Daniel Stone daniel at fooishbar.org
Sun Sep 19 22:03:08 PDT 2010


Add support to libXi for all the Xi 2.1 additions to the spec:
TouchClass, TouchBegin, TouchEnd and TouchMotion, as well as touch grabs.

Signed-off-by: Daniel Stone <daniel at fooishbar.org>
---
 configure.ac                     |    4 +-
 include/X11/extensions/XInput2.h |  108 ++++++++++++++++++++++++++++++
 src/XExtInt.c                    |  136 +++++++++++++++++++++++++++++++++++++-
 src/XIAllowEvents.c              |   29 ++++++++
 src/XIPassiveGrab.c              |   21 ++++++
 5 files changed, 295 insertions(+), 3 deletions(-)

diff --git a/configure.ac b/configure.ac
index 2f773f9..b5a28e1 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.3, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], libXi)
+AC_INIT(libXi, 1.4, [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.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..651b459 100644
--- a/include/X11/extensions/XInput2.h
+++ b/include/X11/extensions/XInput2.h
@@ -27,6 +27,8 @@
 #ifndef _XINPUT2_H_
 #define _XINPUT2_H_
 
+#include <stdint.h>
+
 #include <X11/Xlib.h>
 #include <X11/extensions/XI2.h>
 #include <X11/extensions/Xge.h>
@@ -135,6 +137,35 @@ typedef struct
 
 typedef struct
 {
+    uint32_t     touchid;
+    uint32_t     tool;
+    double       x;
+    double       y;
+    double       touch_major;
+    double       touch_minor;
+    double       tool_major;
+    double       tool_minor;
+    unsigned int orientation;
+} XITouchInfo;
+
+typedef struct
+{
+    int          type;
+    int          sourceid;
+    int          mode;
+    double       min_x;
+    double       max_x;
+    double       min_y;
+    double       max_y;
+    double       min_touch_width;
+    double       max_touch_width;
+    unsigned int num_touches;
+    unsigned int max_touches;
+    XITouchInfo  *touches;
+} XITouchClassInfo;
+
+typedef struct
+{
     int                 deviceid;
     char                *name;
     int                 use;
@@ -292,6 +323,55 @@ typedef struct {
     int           what;
 } XIPropertyEvent;
 
+typedef struct {
+    int             type;               /* GenericEvent */
+    unsigned long   serial;             /* # of last request processed */
+    Bool            send_event;         /* true if this came from SendEvent */
+    Display         *display;           /* Display the event was read from */
+    int             extension;          /* XI extension offset */
+    int             evtype;             /* XI_TouchBegin or XI_TouchEnd */
+    Time            time;
+    int             deviceid;           /* id of delivery device */
+    int             sourceid;           /* id of originating device */
+    Window          root;               /* root window for delivery */
+    Window          event;              /* window event delivered to */
+    Window          child;              /* window event occured in */
+    unsigned long   touchid;            /* unique ID for this touch */
+    unsigned long   tool;               /* identifier of physical tool */
+} XITouchStateEvent;
+
+typedef XITouchStateEvent XITouchBeginEvent;
+typedef XITouchStateEvent XITouchEndEvent;
+
+typedef struct {
+    int             type;               /* GenericEvent */
+    unsigned long   serial;             /* # of last request processed */
+    Bool            send_event;         /* true if this came from SendEvent */
+    Display         *display;           /* Display the event was read from */
+    int             extension;          /* XI extension offset */
+    int             evtype;             /* XI_TouchStateNotify */
+    Time            time;               /* time event was received */
+    int             deviceid;           /* id of delivery device */
+    int             sourceid;           /* id of originating device */
+    int             mask;               /* fields present in this event */
+    Window          root;               /* root window for delivery */
+    Window          event;              /* window event delivered to */
+    Window          child;              /* window event occured in */
+    unsigned long   touchid;            /* unique ID for this touch */
+    unsigned long   tool;               /* identifier of physical tool */
+    double          root_x;             /* X in screen co-ords */
+    double          root_y;             /* Y in screen co-ords */
+    double          event_x;            /* X relative to event window */
+    double          event_y;            /* Y relative to event window */
+    double          x;                  /* unscaled X */
+    double          y;                  /* unscaled Y */
+    double          touch_width_major;  /* major axis of contact area */
+    double          touch_width_minor;  /* minor axis of contact area */
+    double          tool_width_major;   /* major axis of proximate tool */
+    double          tool_width_minor;   /* minor axis of proximate tool */
+    unsigned int    orientation;        /* orientation of tool, in degrees */
+} XITouchMotionEvent;
+
 _XFUNCPROTOBEGIN
 
 extern Bool     XIQueryPointer(
@@ -415,6 +495,14 @@ extern Status XIAllowEvents(
     Time                time
 );
 
+extern Status XIAllowTouchEvents(
+    Display*            display,
+    int                 deviceid,
+    int                 event_mode,
+    Time                time,
+    uint32_t            detail
+);
+
 extern int XIGrabButton(
     Display*            display,
     int                 deviceid,
@@ -466,6 +554,18 @@ extern int XIGrabFocusIn(
     int                 num_modifiers,
     XIGrabModifiers     *modifiers_inout
 );
+
+extern int XIGrabTouchBegin(
+    Display*            display,
+    int                 deviceid,
+    Window              grab_window,
+    int                 grab_mode,
+    int                 owner_events,
+    XIEventMask         *mask,
+    int                 num_modifiers,
+    XIGrabModifiers     *modifiers_inout
+);
+
 extern Status XIUngrabButton(
     Display*            display,
     int                 deviceid,
@@ -500,6 +600,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 bbd406d..c7fe102 100644
--- a/src/XExtInt.c
+++ b/src/XExtInt.c
@@ -146,6 +146,10 @@ static int
 wireToEnterLeave(xXIEnterEvent *in, XGenericEventCookie *cookie);
 static int
 wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie);
+static int
+wireToTouchStateEvent(xXITouchStateEvent *in, XGenericEventCookie *cookie);
+static int
+wireToTouchMotionEvent(xXITouchMotionEvent*in, XGenericEventCookie *cookie);
 
 static /* const */ XEvent emptyevent;
 
@@ -268,7 +272,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}
 };
 
 /***********************************************************************
@@ -985,6 +990,25 @@ XInputWireToCookie(
                 break;
             }
             return ENQUEUE_EVENT;
+        case XI_TouchBegin:
+        case XI_TouchEnd:
+            *cookie = *(XGenericEventCookie*)save;
+            if (!wireToTouchStateEvent((xXITouchStateEvent*)event, cookie))
+            {
+                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
+                        ge->evtype);
+                break;
+            }
+            return ENQUEUE_EVENT;
+        case XI_TouchMotion:
+            *cookie = *(XGenericEventCookie*)save;
+            if (!wireToTouchMotionEvent((xXITouchMotionEvent*)event, cookie))
+            {
+                printf("XInputWireToCookie: CONVERSION FAILURE!  evtype=%d\n",
+                        ge->evtype);
+                break;
+            }
+            return ENQUEUE_EVENT;
         default:
             printf("XInputWireToCookie: Unknown generic event. type %d\n", ge->evtype);
 
@@ -1037,6 +1061,10 @@ sizeDeviceClassType(int type, int num_elements)
         case XIValuatorClass:
             l = sizeof(XIValuatorClassInfo);
             break;
+        case XITouchClass:
+            l = sizeof(XITouchClassInfo);
+            l += num_elements * sizeof(XITouchInfo);
+            break;
         default:
             printf("sizeDeviceClassType: unknown type %d\n", type);
             break;
@@ -1426,6 +1454,9 @@ size_classes(xXIAnyInfo* from, int nclasses)
             case XIValuatorClass:
                 l = sizeDeviceClassType(XIValuatorClass, 0);
                 break;
+            case XITouchClass:
+                l = sizeDeviceClassType(XITouchClass,
+                        ((xXITouchClassInfo*)any_wire)->num_touches);
         }
 
         len += l;
@@ -1526,6 +1557,51 @@ copy_classes(XIDeviceInfo* to, xXIAnyInfo* from, int nclasses)
 
                 }
                 break;
+            case XITouchClass:
+                {
+                    XITouchClassInfo *cls_lib;
+                    xXITouchClassInfo *cls_wire;
+                    XITouchInfo *tp_lib;
+                    xXITouchInfo *tp_wire;
+                    int j;
+
+                    cls_wire = (xXITouchClassInfo*)any_wire;
+                    cls_lib = next_block(&ptr_lib,
+                                         sizeof(XITouchClassInfo) +
+                                          (cls_wire->num_touches *
+                                           sizeof(XITouchInfo)));
+
+                    cls_lib->mode = cls_wire->mode;
+                    /* FIXME: fractional parts */
+                    cls_lib->min_x = cls_wire->min_x.integral;
+                    cls_lib->max_x = cls_wire->max_x.integral;
+                    cls_lib->min_y = cls_wire->min_y.integral;
+                    cls_lib->max_y = cls_wire->max_y.integral;
+                    cls_lib->min_touch_width =
+                        cls_wire->min_touch_width.integral;
+                    cls_lib->max_touch_width =
+                        cls_wire->max_touch_width.integral;
+                    cls_lib->max_touches = cls_wire->max_touches;
+                    cls_lib->num_touches = cls_wire->num_touches;
+                    cls_lib->touches = (XITouchInfo *) &cls_lib[1];
+
+                    tp_lib = cls_lib->touches;
+                    tp_wire = (xXITouchInfo *) &cls_wire[1];
+                    for (j = 0; j < cls_wire->num_touches; j++) {
+                        tp_lib->touchid = tp_wire->touchid;
+                        tp_lib->tool = tp_wire->tool;
+                        tp_lib->x = tp_wire->x.integral;
+                        tp_lib->y = tp_wire->y.integral;
+                        tp_lib->touch_major = tp_wire->touch_major.integral;
+                        tp_lib->touch_minor = tp_wire->touch_minor.integral;
+                        tp_lib->tool_major = tp_wire->tool_major.integral;
+                        tp_lib->tool_minor = tp_wire->tool_minor.integral;
+                        tp_lib->orientation = tp_wire->orientation;
+                        tp_lib++;
+                        tp_wire++;
+                    }
+                }
+                break;
         }
         len += any_wire->length * 4;
         ptr_wire += any_wire->length * 4;
@@ -1711,3 +1787,61 @@ wireToPropertyEvent(xXIPropertyEvent *in, XGenericEventCookie *cookie)
 
     return 1;
 }
+
+static int
+wireToTouchStateEvent(xXITouchStateEvent *in, XGenericEventCookie *cookie)
+{
+    XITouchStateEvent *out = malloc(sizeof(XITouchStateEvent));
+
+    cookie->data = out;
+
+    out->type            = in->type;
+    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->root            = in->root;
+    out->event           = in->event;
+    out->child           = in->child;
+    out->touchid         = in->touchid;
+    out->tool            = in->tool;
+
+    return 1;
+}
+
+static int
+wireToTouchMotionEvent(xXITouchMotionEvent *in, XGenericEventCookie *cookie)
+{
+    XITouchMotionEvent *out = malloc(sizeof(XITouchMotionEvent));
+
+    cookie->data = out;
+
+    out->type              = in->type;
+    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->mask              = in->mask;
+    out->root              = in->root;
+    out->event             = in->event;
+    out->child             = in->child;
+    out->touchid           = in->touchid;
+    out->root_x            = FP1616toDBL(in->root_x);
+    out->root_y            = FP1616toDBL(in->root_y);
+    out->event_x           = FP1616toDBL(in->event_x);
+    out->event_y           = FP1616toDBL(in->event_y);
+    /* FIXME: fractional values */
+    out->x                 = in->x.integral;
+    out->y                 = in->y.integral;
+    out->touch_width_major = in->touch_width_major.integral;
+    out->touch_width_minor = in->touch_width_minor.integral;
+    out->tool_width_major  = in->tool_width_major.integral;
+    out->tool_width_minor  = in->tool_width_minor.integral;
+    out->orientation       = in->orientation;
+
+    return 1;
+}
diff --git a/src/XIAllowEvents.c b/src/XIAllowEvents.c
index 75980a0..00229c9 100644
--- a/src/XIAllowEvents.c
+++ b/src/XIAllowEvents.c
@@ -51,3 +51,32 @@ XIAllowEvents(Display *dpy, int deviceid, int event_mode, Time time)
     SyncHandle();
     return Success;
 }
+
+Status
+XIAllowTouchEvents(Display *dpy, int deviceid, int event_mode, Time time,
+                   uint32_t touchid)
+{
+    xXIAllowEventsDetailReq *req;
+
+    XExtDisplayInfo *extinfo = XInput_find_display(dpy);
+
+    LockDisplay(dpy);
+    if (_XiCheckExtInit(dpy, XInput_2_1, extinfo) == -1)
+	return (NoSuchExtension);
+
+    /* Xlib really wants the struct and req names to be the same. */
+#define X_XIAllowEventsDetail X_XIAllowEvents
+    GetReq(XIAllowEventsDetail, req);
+#undef X_XIAllowEventsDetail
+
+    req->reqType = extinfo->codes->major_opcode;
+    req->ReqType = X_XIAllowEvents;
+    req->deviceid = deviceid;
+    req->mode = event_mode;
+    req->time = time;
+    req->detail = touchid;
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+    return Success;
+}
diff --git a/src/XIPassiveGrab.c b/src/XIPassiveGrab.c
index 8953013..6bfea82 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, int grab_mode,
+                 Bool owner_events, XIEventMask *mask, int num_modifiers,
+                 XIGrabModifiers *modifiers_inout)
+{
+    /* FIXME: Don't send to Xi 2.0 servers. */
+    return _XIPassiveGrabDevice(dpy, deviceid, XIGrabtypeTouchBegin, 0,
+                                grab_window, None, grab_mode, 0,
+                                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)
+{
+    /* FIXME: Don't send to Xi 2.0 servers. */
+    return _XIPassiveUngrabDevice(display, deviceid, XIGrabtypeTouchBegin, 0,
+                                  grab_window, num_modifiers, modifiers);
+}
-- 
1.7.1



More information about the xorg-devel mailing list