diff --git a/Xi/exevents.c b/Xi/exevents.c index 83ea387ab..16acd5814 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -691,6 +691,25 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to) /* Don't remove touch class if from->touch is non-existent. The to device * may have an active touch grab, so we need to keep the touch class record * around. */ + + if (from->gesture) { + if (!to->gesture) { + classes = to->unused_classes; + to->gesture = classes->gesture; + if (!to->gesture) { + if (!InitGestureClassDeviceStruct(to, from->gesture->max_touches)) + FatalError("[Xi] no memory for class shift.\n"); + } + else + classes->gesture = NULL; + } + + to->gesture->sourceid = from->gesture->sourceid; + /* to->gesture->gesture is separate on the master, don't copy */ + } + /* Don't remove gesture class if from->gesture is non-existent. The to device + * may have an active gesture grab, so we need to keep the gesture class record + * around. */ } /** diff --git a/dix/Makefile.am b/dix/Makefile.am index 652a08519..e1498cd56 100644 --- a/dix/Makefile.am +++ b/dix/Makefile.am @@ -23,6 +23,7 @@ libdix_la_SOURCES = \ extension.c \ gc.c \ getevents.c \ + gestures.c \ globals.c \ glyphcurs.c \ grabs.c \ diff --git a/dix/devices.c b/dix/devices.c index 85d899c20..29f3051aa 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -1670,6 +1670,32 @@ InitTouchClassDeviceStruct(DeviceIntPtr device, unsigned int max_touches, return FALSE; } +/** + * Sets up gesture capabilities on @device. + * + * @max_touches The maximum number of simultaneous touches, or 0 for unlimited. + */ +Bool +InitGestureClassDeviceStruct(DeviceIntPtr device, unsigned int max_touches) +{ + GestureClassPtr g; + + BUG_RETURN_VAL(device == NULL, FALSE); + BUG_RETURN_VAL(device->gesture != NULL, FALSE); + + g = calloc(1, sizeof(*g)); + if (!g) + return FALSE; + + g->sourceid = device->id; + g->max_touches = max_touches; + GestureInitGestureInfo(&g->gesture); + + device->gesture = g; + + return TRUE; +} + /* * Check if the given buffer contains elements between low (inclusive) and * high (inclusive) only. diff --git a/dix/gestures.c b/dix/gestures.c new file mode 100644 index 000000000..7e4057deb --- /dev/null +++ b/dix/gestures.c @@ -0,0 +1,57 @@ +/* + * Copyright © 2011 Collabra Ltd. + * Copyright © 2011 Red Hat, Inc. + * Copyright © 2020 Povilas Kanapickas + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "inputstr.h" +#include "scrnintstr.h" +#include "dixgrabs.h" + +#include "eventstr.h" +#include "exevents.h" +#include "exglobals.h" +#include "inpututils.h" +#include "eventconvert.h" +#include "windowstr.h" +#include "mi.h" + +Bool +GestureInitGestureInfo(GestureInfoPtr gi) +{ + memset(gi, 0, sizeof(*gi)); + + gi->sprite.spriteTrace = calloc(32, sizeof(*gi->sprite.spriteTrace)); + if (!gi->sprite.spriteTrace) { + return FALSE; + } + gi->sprite.spriteTraceSize = 32; + gi->sprite.spriteTrace[0] = screenInfo.screens[0]->root; + gi->sprite.hot.pScreen = screenInfo.screens[0]; + gi->sprite.hotPhys.pScreen = screenInfo.screens[0]; + + return TRUE; +} diff --git a/dix/meson.build b/dix/meson.build index ddc5cc392..fbbcf8646 100644 --- a/dix/meson.build +++ b/dix/meson.build @@ -12,6 +12,7 @@ srcs_dix = [ 'eventconvert.c', 'extension.c', 'gc.c', + 'gestures.c', 'getevents.c', 'globals.c', 'glyphcurs.c', diff --git a/include/input.h b/include/input.h index 8252914a6..d607e6b97 100644 --- a/include/input.h +++ b/include/input.h @@ -153,7 +153,9 @@ typedef struct _ValuatorClassRec *ValuatorClassPtr; typedef struct _ClassesRec *ClassesPtr; typedef struct _SpriteRec *SpritePtr; typedef struct _TouchClassRec *TouchClassPtr; +typedef struct _GestureClassRec *GestureClassPtr; typedef struct _TouchPointInfo *TouchPointInfoPtr; +typedef struct _GestureInfo *GestureInfoPtr; typedef struct _DDXTouchPointInfo *DDXTouchPointInfoPtr; typedef union _GrabMask GrabMask; @@ -340,6 +342,9 @@ extern _X_EXPORT Bool InitTouchClassDeviceStruct(DeviceIntPtr /*device */ , unsigned int /*mode */ , unsigned int /*numAxes */ ); +extern _X_EXPORT Bool InitGestureClassDeviceStruct(DeviceIntPtr device, + unsigned int max_touches); + typedef void (*BellProcPtr) (int percent, DeviceIntPtr device, void *ctrl, @@ -576,6 +581,12 @@ enum TouchListenerType { TOUCH_LISTENER_POINTER_REGULAR, }; +enum GestureListenerType { + GESTURE_LISTENER_GRAB, + GESTURE_LISTENER_NONGESTURE_GRAB, + GESTURE_LISTENER_REGULAR +}; + extern void TouchInitDDXTouchPoint(DeviceIntPtr dev, DDXTouchPointInfoPtr ddxtouch); extern DDXTouchPointInfoPtr TouchBeginDDXTouch(DeviceIntPtr dev, @@ -621,6 +632,7 @@ extern void TouchEndPhysicallyActiveTouches(DeviceIntPtr dev); extern void TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource); extern void TouchAcceptAndEnd(DeviceIntPtr dev, int touchid); +extern Bool GestureInitGestureInfo(GestureInfoPtr gesture); /* misc event helpers */ extern Mask GetEventMask(DeviceIntPtr dev, xEvent *ev, InputClientsPtr clients); extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event); diff --git a/include/inputstr.h b/include/inputstr.h index 1cf871530..ec11b39bb 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -352,6 +352,32 @@ typedef struct _TouchClassRec { Mask motionMask; } TouchClassRec; +typedef struct _GestureListener { + XID listener; /* grabs/event selection IDs receiving + * events for this gesture */ + int resource_type; /* listener's resource type */ + enum GestureListenerType type; + WindowPtr window; + GrabPtr grab; +} GestureListener; + +typedef struct _GestureInfo { + int sourceid; /* Source device's ID for this gesture */ + Bool active; /* whether or not the gesture is active */ + uint8_t type; /* Gesture type: either ET_GesturePinchBegin or + ET_GestureSwipeBegin. Valid if active == TRUE */ + int num_touches; /* The number of touches in the gesture */ + SpriteRec sprite; /* window trace for delivery */ + GestureListener listener; /* the listener that will receive events */ + Bool has_listener; /* true if listener has been setup already */ +} GestureInfoRec; + +typedef struct _GestureClassRec { + int sourceid; + GestureInfoRec gesture; + unsigned short max_touches; /* maximum number of touches, may be 0 */ +} GestureClassRec; + typedef struct _ButtonClassRec { int sourceid; CARD8 numButtons; @@ -435,6 +461,7 @@ typedef struct _ClassesRec { KeyClassPtr key; ValuatorClassPtr valuator; TouchClassPtr touch; + GestureClassPtr gesture; ButtonClassPtr button; FocusClassPtr focus; ProximityClassPtr proximity; @@ -550,6 +577,7 @@ typedef struct _DeviceIntRec { KeyClassPtr key; ValuatorClassPtr valuator; TouchClassPtr touch; + GestureClassPtr gesture; ButtonClassPtr button; FocusClassPtr focus; ProximityClassPtr proximity;