From e080d09ea9f4908b5802510f48b8453efb608b8d Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Mon, 20 Sep 2010 15:03:08 +1000 Subject: Add multitouch support from Xi 2.1 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 --- 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 + #include #include #include @@ -133,6 +135,35 @@ typedef struct int mode; } XIValuatorClassInfo; +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; @@ -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 eed6637..8dff669 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); +} -- cgit v1.2.3