xserver: Branch 'master' - 21 commits
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Sun May 30 10:55:21 UTC 2021
.gitlab-ci.yml | 2
.gitlab-ci/cross-prereqs-build.sh | 2
.gitlab-ci/debian-install.sh | 9
Xi/exevents.c | 248 +++++++
Xi/extinit.c | 80 ++
Xi/xipassivegrab.c | 29
Xi/xiquerydevice.c | 57 +
Xi/xiselectev.c | 53 +
dix/Makefile.am | 1
dix/devices.c | 27
dix/dispatch.c | 1
dix/eventconvert.c | 164 ++++
dix/events.c | 110 +++
dix/gestures.c | 362 +++++++++++
dix/getevents.c | 136 ++++
dix/grabs.c | 7
dix/inpututils.c | 33 +
dix/meson.build | 1
hw/xfree86/common/xf86Module.h | 2
hw/xfree86/common/xf86Xinput.c | 52 +
hw/xfree86/common/xf86Xinput.h | 14
hw/xfree86/drivers/inputtest/xf86-input-inputtest-protocol.h | 30
hw/xfree86/drivers/inputtest/xf86-input-inputtest.c | 57 +
include/dix.h | 11
include/dixgrabs.h | 1
include/eventconvert.h | 3
include/events.h | 1
include/eventstr.h | 39 +
include/exevents.h | 11
include/input.h | 57 +
include/inputstr.h | 30
include/inpututils.h | 2
include/protocol-versions.h | 2
meson.build | 2
mi/mieq.c | 8
test/xi2/protocol-xipassivegrabdevice.c | 2
test/xi2/protocol-xiselectevents.c | 33 -
37 files changed, 1654 insertions(+), 25 deletions(-)
New commits:
commit eb6f8daca5dc15af321d0bcc54cd6cb8b6779257
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:48 2021 +0300
Xi: Work around broken libxcb that doesn't ignore unknown device classes
libxcb 14.1 and older are not forwards-compatible with new device
classes as it does not properly ignore unknown device classes. Since
breaking libxcb would break quite a lot of applications, we instead
report Gesture device class only if the client advertised support for XI
2.4.
Clients may still not work in cases when a client advertises XI 2.4
support and then a completely separate module within the client uses
broken libxcb to call XIQueryDevice.
Signed-off-by: Povilas Kanapickas <povilas at radix.lt>
diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c
index 5c6799a7c..e4731a119 100644
--- a/Xi/xiquerydevice.c
+++ b/Xi/xiquerydevice.c
@@ -43,6 +43,9 @@
#include "xace.h"
#include "inpututils.h"
+#include "exglobals.h"
+#include "privates.h"
+
#include "xiquerydevice.h"
static Bool ShouldSkipDevice(ClientPtr client, int deviceid, DeviceIntPtr d);
@@ -467,6 +470,22 @@ SwapTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
swaps(&touch->sourceid);
}
+static Bool ShouldListGestureInfo(ClientPtr client)
+{
+ /* libxcb 14.1 and older are not forwards-compatible with new device classes as it does not
+ * properly ignore unknown device classes. Since breaking libxcb would break quite a lot of
+ * applications, we instead report Gesture device class only if the client advertised support
+ * for XI 2.4. Clients may still not work in cases when a client advertises XI 2.4 support
+ * and then a completely separate module within the client uses broken libxcb to call
+ * XIQueryDevice.
+ */
+ XIClientPtr pXIClient = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
+ if (pXIClient->major_version) {
+ return version_compare(pXIClient->major_version, pXIClient->minor_version, 2, 4) >= 0;
+ }
+ return FALSE;
+}
+
/**
* List gesture information
*
@@ -594,7 +613,7 @@ ListDeviceClasses(ClientPtr client, DeviceIntPtr dev,
total_len += len;
}
- if (dev->gesture) {
+ if (dev->gesture && ShouldListGestureInfo(client)) {
(*nclasses)++;
len = ListGestureInfo(dev, (xXIGestureInfo *) any);
any += len;
commit 7e692633fb9ab8e1ed2a88c3abb4fe04144c0a80
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:47 2021 +0300
Xi: Implement gesture support for XIQueryDevice
diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c
index fbb51fe81..5c6799a7c 100644
--- a/Xi/xiquerydevice.c
+++ b/Xi/xiquerydevice.c
@@ -234,6 +234,9 @@ SizeDeviceClasses(DeviceIntPtr dev)
if (dev->touch)
len += sizeof(xXITouchInfo);
+ if (dev->gesture)
+ len += sizeof(xXIGestureInfo);
+
return len;
}
@@ -464,6 +467,30 @@ SwapTouchInfo(DeviceIntPtr dev, xXITouchInfo * touch)
swaps(&touch->sourceid);
}
+/**
+ * List gesture information
+ *
+ * @return The number of bytes written into info.
+ */
+static int
+ListGestureInfo(DeviceIntPtr dev, xXIGestureInfo * gesture)
+{
+ gesture->type = XIGestureClass;
+ gesture->length = sizeof(xXIGestureInfo) >> 2;
+ gesture->sourceid = dev->gesture->sourceid;
+ gesture->num_touches = dev->gesture->max_touches;
+
+ return gesture->length << 2;
+}
+
+static void
+SwapGestureInfo(DeviceIntPtr dev, xXIGestureInfo * gesture)
+{
+ swaps(&gesture->type);
+ swaps(&gesture->length);
+ swaps(&gesture->sourceid);
+}
+
int
GetDeviceUse(DeviceIntPtr dev, uint16_t * attachment)
{
@@ -567,6 +594,13 @@ ListDeviceClasses(ClientPtr client, DeviceIntPtr dev,
total_len += len;
}
+ if (dev->gesture) {
+ (*nclasses)++;
+ len = ListGestureInfo(dev, (xXIGestureInfo *) any);
+ any += len;
+ total_len += len;
+ }
+
return total_len;
}
@@ -598,7 +632,9 @@ SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo * info)
case XITouchClass:
SwapTouchInfo(dev, (xXITouchInfo *) any);
break;
-
+ case XIGestureClass:
+ SwapGestureInfo(dev, (xXIGestureInfo *) any);
+ break;
}
any += len * 4;
commit 0886254f96f40e59193ccbb0e3acbd5ae92dbaa3
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:46 2021 +0300
xfree86: Bump input minor ABI due to addition touchpad gestures
Signed-off-by: Povilas Kanapickas <povilas at radix.lt>
diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index 7b478d5c2..1eb09bca3 100644
--- a/hw/xfree86/common/xf86Module.h
+++ b/hw/xfree86/common/xf86Module.h
@@ -75,7 +75,7 @@
*/
#define ABI_ANSIC_VERSION SET_ABI_VERSION(0, 4)
#define ABI_VIDEODRV_VERSION SET_ABI_VERSION(25, 2)
-#define ABI_XINPUT_VERSION SET_ABI_VERSION(24, 3)
+#define ABI_XINPUT_VERSION SET_ABI_VERSION(24, 4)
#define ABI_EXTENSION_VERSION SET_ABI_VERSION(10, 0)
#define MODINFOSTRING1 0xef23fdc5
commit 1cdc3b5d146818993c5a9436d17e1d0888054c38
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:45 2021 +0300
xfree86: Implement gesture support for test input driver
diff --git a/hw/xfree86/drivers/inputtest/xf86-input-inputtest-protocol.h b/hw/xfree86/drivers/inputtest/xf86-input-inputtest-protocol.h
index 267532348..46837f3ba 100644
--- a/hw/xfree86/drivers/inputtest/xf86-input-inputtest-protocol.h
+++ b/hw/xfree86/drivers/inputtest/xf86-input-inputtest-protocol.h
@@ -31,7 +31,7 @@ extern "C" {
#include <stdint.h>
#define XF86IT_PROTOCOL_VERSION_MAJOR 1
-#define XF86IT_PROTOCOL_VERSION_MINOR 0
+#define XF86IT_PROTOCOL_VERSION_MINOR 1
enum xf86ITResponseType {
XF86IT_RESPONSE_SERVER_VERSION,
@@ -70,6 +70,8 @@ enum xf86ITEventType {
XF86IT_EVENT_BUTTON,
XF86IT_EVENT_KEY,
XF86IT_EVENT_TOUCH,
+ XF86IT_EVENT_GESTURE_PINCH,
+ XF86IT_EVENT_GESTURE_SWIPE,
};
typedef struct {
@@ -127,6 +129,30 @@ typedef struct {
xf86ITValuatorData valuators;
} xf86ITEventTouch;
+typedef struct {
+ xf86ITEventHeader header;
+ uint16_t gesture_type;
+ uint16_t num_touches;
+ uint32_t flags;
+ double delta_x;
+ double delta_y;
+ double delta_unaccel_x;
+ double delta_unaccel_y;
+ double scale;
+ double delta_angle;
+} xf86ITEventGesturePinch;
+
+typedef struct {
+ xf86ITEventHeader header;
+ uint16_t gesture_type;
+ uint16_t num_touches;
+ uint32_t flags;
+ double delta_x;
+ double delta_y;
+ double delta_unaccel_x;
+ double delta_unaccel_y;
+} xf86ITEventGestureSwipe;
+
typedef union {
xf86ITEventHeader header;
xf86ITEventClientVersion version;
@@ -135,6 +161,8 @@ typedef union {
xf86ITEventButton button;
xf86ITEventKey key;
xf86ITEventTouch touch;
+ xf86ITEventGesturePinch pinch;
+ xf86ITEventGestureSwipe swipe;
} xf86ITEventAny;
#ifdef __cplusplus
diff --git a/hw/xfree86/drivers/inputtest/xf86-input-inputtest.c b/hw/xfree86/drivers/inputtest/xf86-input-inputtest.c
index 147d46e0d..70f8fe964 100644
--- a/hw/xfree86/drivers/inputtest/xf86-input-inputtest.c
+++ b/hw/xfree86/drivers/inputtest/xf86-input-inputtest.c
@@ -58,6 +58,7 @@
enum xf86ITDeviceType {
DEVICE_KEYBOARD = 1,
DEVICE_POINTER,
+ DEVICE_POINTER_GESTURE,
DEVICE_POINTER_ABS,
DEVICE_POINTER_ABS_PROXIMITY,
DEVICE_TOUCH,
@@ -474,6 +475,14 @@ init_touch(InputInfoPtr pInfo)
InitTouchClassDeviceStruct(dev, ntouches, XIDirectTouch, 2);
}
+static void
+init_gesture(InputInfoPtr pInfo)
+{
+ DeviceIntPtr dev = pInfo->dev;
+ int ntouches = TOUCH_MAX_SLOTS;
+ InitGestureClassDeviceStruct(dev, ntouches);
+}
+
static void
device_init(DeviceIntPtr dev)
{
@@ -489,6 +498,10 @@ device_init(DeviceIntPtr dev)
case DEVICE_POINTER:
init_pointer(pInfo);
break;
+ case DEVICE_POINTER_GESTURE:
+ init_pointer(pInfo);
+ init_gesture(pInfo);
+ break;
case DEVICE_POINTER_ABS:
init_pointer_absolute(pInfo);
break;
@@ -678,6 +691,37 @@ handle_touch(InputInfoPtr pInfo, xf86ITEventTouch *event)
xf86PostTouchEvent(dev, event->touchid, event->touch_type, 0, mask);
}
+static void
+handle_gesture_swipe(InputInfoPtr pInfo, xf86ITEventGestureSwipe *event)
+{
+ DeviceIntPtr dev = pInfo->dev;
+ xf86ITDevicePtr driver_data = pInfo->private;
+
+ xf86IDrvMsg(pInfo, X_DEBUG, "Handling gesture swipe event\n");
+
+ driver_data->last_event_num++;
+
+ xf86PostGestureSwipeEvent(dev, event->gesture_type, event->num_touches, event->flags,
+ event->delta_x, event->delta_y,
+ event->delta_unaccel_x, event->delta_unaccel_y);
+}
+
+static void
+handle_gesture_pinch(InputInfoPtr pInfo, xf86ITEventGesturePinch *event)
+{
+ DeviceIntPtr dev = pInfo->dev;
+ xf86ITDevicePtr driver_data = pInfo->private;
+
+ xf86IDrvMsg(pInfo, X_DEBUG, "Handling gesture pinch event\n");
+
+ driver_data->last_event_num++;
+
+ xf86PostGesturePinchEvent(dev, event->gesture_type, event->num_touches, event->flags,
+ event->delta_x, event->delta_y,
+ event->delta_unaccel_x, event->delta_unaccel_y,
+ event->scale, event->delta_angle);
+}
+
static void
client_new_handle_event(InputInfoPtr pInfo, xf86ITEventAny *event)
{
@@ -715,6 +759,12 @@ client_ready_handle_event(InputInfoPtr pInfo, xf86ITEventAny *event)
case XF86IT_EVENT_TOUCH:
handle_touch(pInfo, &event->touch);
break;
+ case XF86IT_EVENT_GESTURE_PINCH:
+ handle_gesture_pinch(pInfo, &(event->pinch));
+ break;
+ case XF86IT_EVENT_GESTURE_SWIPE:
+ handle_gesture_swipe(pInfo, &(event->swipe));
+ break;
case XF86IT_EVENT_CLIENT_VERSION:
xf86IDrvMsg(pInfo, X_ERROR, "Only single ClientVersion event is allowed\n");
teardown_client_connection(pInfo);
@@ -759,6 +809,8 @@ is_supported_event(enum xf86ITEventType type)
case XF86IT_EVENT_BUTTON:
case XF86IT_EVENT_KEY:
case XF86IT_EVENT_TOUCH:
+ case XF86IT_EVENT_GESTURE_PINCH:
+ case XF86IT_EVENT_GESTURE_SWIPE:
return true;
}
return false;
@@ -775,6 +827,8 @@ get_event_size(enum xf86ITEventType type)
case XF86IT_EVENT_BUTTON: return sizeof(xf86ITEventButton);
case XF86IT_EVENT_KEY: return sizeof(xf86ITEventKey);
case XF86IT_EVENT_TOUCH: return sizeof(xf86ITEventTouch);
+ case XF86IT_EVENT_GESTURE_PINCH: return sizeof(xf86ITEventGesturePinch);
+ case XF86IT_EVENT_GESTURE_SWIPE: return sizeof(xf86ITEventGestureSwipe);
}
abort();
}
@@ -864,6 +918,7 @@ get_type_name(InputInfoPtr pInfo, xf86ITDevicePtr driver_data)
switch (driver_data->device_type) {
case DEVICE_TOUCH: return XI_TOUCHSCREEN;
case DEVICE_POINTER: return XI_MOUSE;
+ case DEVICE_POINTER_GESTURE: return XI_TOUCHPAD;
case DEVICE_POINTER_ABS: return XI_MOUSE;
case DEVICE_POINTER_ABS_PROXIMITY: return XI_TABLET;
case DEVICE_KEYBOARD: return XI_KEYBOARD;
@@ -986,6 +1041,8 @@ pre_init(InputDriverPtr drv, InputInfoPtr pInfo, int flags)
driver_data->device_type = DEVICE_KEYBOARD;
} else if (strcmp(device_type_option, "Pointer") == 0) {
driver_data->device_type = DEVICE_POINTER;
+ } else if (strcmp(device_type_option, "PointerGesture") == 0) {
+ driver_data->device_type = DEVICE_POINTER_GESTURE;
} else if (strcmp(device_type_option, "PointerAbsolute") == 0) {
driver_data->device_type = DEVICE_POINTER_ABS;
} else if (strcmp(device_type_option, "PointerAbsoluteProximity") == 0) {
commit dccc0275f4f3740cc625fb60ab1d014d6ec10709
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:44 2021 +0300
Bump XI protocol version to 2.4
diff --git a/include/protocol-versions.h b/include/protocol-versions.h
index 8e149b27f..25abee5b7 100644
--- a/include/protocol-versions.h
+++ b/include/protocol-versions.h
@@ -144,7 +144,7 @@
/* X Input */
#define SERVER_XI_MAJOR_VERSION 2
-#define SERVER_XI_MINOR_VERSION 3
+#define SERVER_XI_MINOR_VERSION 4
/* XKB */
#define SERVER_XKB_MAJOR_VERSION 1
commit 75feb1366809bfb6d50734c10ab11258783a2e9d
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:43 2021 +0300
Xi: Include gestures among events that may freeze device
diff --git a/Xi/exevents.c b/Xi/exevents.c
index f878dd212..9d4886212 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1766,6 +1766,7 @@ ProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev)
GestureInfoPtr gi;
DeviceIntPtr kbd;
Bool deactivateGestureGrab = FALSE;
+ Bool delivered = FALSE;
if (!dev->gesture)
return;
@@ -1795,7 +1796,11 @@ ProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev)
GrabIsGestureGrab(dev->deviceGrab.grab))
deactivateGestureGrab = TRUE;
- DeliverGestureEventToOwner(dev, gi, ev);
+ delivered = DeliverGestureEventToOwner(dev, gi, ev);
+
+ if (delivered && !deactivateGestureGrab &&
+ (IsGestureBeginEvent(ev) || IsGestureEndEvent(ev)))
+ FreezeThisEventIfNeededForSyncGrab(dev, ev);
if (IsGestureEndEvent(ev))
GestureEndGesture(gi);
commit 5163fc8bc28ce8bc2703cddcd9f2775ebc311766
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:42 2021 +0300
Implement gesture processing logic
diff --git a/Xi/exevents.c b/Xi/exevents.c
index 16acd5814..f878dd212 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1743,6 +1743,67 @@ ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
free(ev);
}
+static BOOL
+IsAnotherGestureActiveOnMaster(DeviceIntPtr dev, InternalEvent* ev)
+{
+ GestureClassPtr g = dev->gesture;
+ if (g->gesture.active && g->gesture.sourceid != ev->gesture_event.sourceid) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * Processes and delivers a Gesture{Pinch,Swipe}{Begin,Update,End}.
+ *
+ * Due to having rather different delivery semantics (see the Xi 2.4 protocol
+ * spec for more information), this implements its own grab and event-selection
+ * delivery logic.
+ */
+void
+ProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev)
+{
+ GestureInfoPtr gi;
+ DeviceIntPtr kbd;
+ Bool deactivateGestureGrab = FALSE;
+
+ if (!dev->gesture)
+ return;
+
+ if (IsMaster(dev) && IsAnotherGestureActiveOnMaster(dev, ev))
+ return;
+
+ if (IsGestureBeginEvent(ev))
+ gi = GestureBeginGesture(dev, ev);
+ else
+ gi = GestureFindActiveByEventType(dev, ev->any.type);
+
+ if (!gi) {
+ /* This may happen if gesture is no longer active or was never started. */
+ return;
+ }
+
+ kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
+ event_set_state_gesture(kbd, &ev->gesture_event);
+
+ if (IsGestureBeginEvent(ev))
+ GestureSetupListener(dev, gi, ev);
+
+ if (IsGestureEndEvent(ev) &&
+ dev->deviceGrab.grab &&
+ dev->deviceGrab.fromPassiveGrab &&
+ GrabIsGestureGrab(dev->deviceGrab.grab))
+ deactivateGestureGrab = TRUE;
+
+ DeliverGestureEventToOwner(dev, gi, ev);
+
+ if (IsGestureEndEvent(ev))
+ GestureEndGesture(gi);
+
+ if (deactivateGestureGrab)
+ (*dev->deviceGrab.DeactivateGrab) (dev);
+}
+
/**
* Process DeviceEvents and DeviceChangedEvents.
*/
@@ -1937,6 +1998,14 @@ ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
case ET_BarrierLeave:
ProcessBarrierEvent(ev, device);
break;
+ case ET_GesturePinchBegin:
+ case ET_GesturePinchUpdate:
+ case ET_GesturePinchEnd:
+ case ET_GestureSwipeBegin:
+ case ET_GestureSwipeUpdate:
+ case ET_GestureSwipeEnd:
+ ProcessGestureEvent(ev, device);
+ break;
default:
ProcessDeviceEvent(ev, device);
break;
@@ -2141,6 +2210,111 @@ DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
}
}
+/**
+ * Attempts to deliver a gesture event to the given client.
+ */
+static Bool
+DeliverOneGestureEvent(ClientPtr client, DeviceIntPtr dev, GestureInfoPtr gi,
+ GrabPtr grab, WindowPtr win, InternalEvent *ev)
+{
+ int err;
+ xEvent *xi2;
+ Mask filter;
+ Window child = DeepestSpriteWin(&gi->sprite)->drawable.id;
+
+ /* If we fail here, we're going to leave a client hanging. */
+ err = EventToXI2(ev, &xi2);
+ if (err != Success)
+ FatalError("[Xi] %s: XI2 conversion failed in %s"
+ " (%d)\n", dev->name, __func__, err);
+
+ FixUpEventFromWindow(&gi->sprite, xi2, win, child, FALSE);
+ filter = GetEventFilter(dev, xi2);
+ if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
+ return FALSE;
+ err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
+ free(xi2);
+
+ /* Returning the value from TryClientEvents isn't useful, since all our
+ * resource-gone cleanups will update the delivery list anyway. */
+ return TRUE;
+}
+
+/**
+ * Given a gesture event and a potential listener, retrieve info needed for processing the event.
+ *
+ * @param dev The device generating the gesture event.
+ * @param ev The gesture event to process.
+ * @param listener The gesture event listener that may receive the gesture event.
+ * @param[out] client The client that should receive the gesture event.
+ * @param[out] win The window to deliver the event on.
+ * @param[out] grab The grab to deliver the event through, if any.
+ * @return TRUE if an event should be delivered to the listener, FALSE
+ * otherwise.
+ */
+static Bool
+RetrieveGestureDeliveryData(DeviceIntPtr dev, InternalEvent *ev, GestureListener* listener,
+ ClientPtr *client, WindowPtr *win, GrabPtr *grab)
+{
+ int rc;
+ int evtype;
+ InputClients *iclients = NULL;
+ *grab = NULL;
+
+ if (listener->type == GESTURE_LISTENER_GRAB ||
+ listener->type == GESTURE_LISTENER_NONGESTURE_GRAB) {
+ *grab = listener->grab;
+
+ BUG_RETURN_VAL(!*grab, FALSE);
+
+ *client = rClient(*grab);
+ *win = (*grab)->window;
+ }
+ else {
+ rc = dixLookupResourceByType((void **) win, listener->listener, listener->resource_type,
+ serverClient, DixSendAccess);
+ if (rc != Success)
+ return FALSE;
+
+ /* note that we only will have XI2 listeners as
+ listener->type == GESTURE_LISTENER_REGULAR */
+ evtype = GetXI2Type(ev->any.type);
+
+ nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
+ if (xi2mask_isset(iclients->xi2mask, dev, evtype))
+ break;
+
+ BUG_RETURN_VAL(!iclients, FALSE);
+
+ *client = rClient(iclients);
+ }
+
+ return TRUE;
+}
+
+/**
+ * Delivers a gesture to the owner, if possible and needed. Returns whether
+ * an event was delivered.
+ */
+Bool
+DeliverGestureEventToOwner(DeviceIntPtr dev, GestureInfoPtr gi, InternalEvent *ev)
+{
+ GrabPtr grab = NULL;
+ ClientPtr client;
+ WindowPtr win;
+
+ if (!gi->has_listener || gi->listener.type == GESTURE_LISTENER_NONGESTURE_GRAB) {
+ return 0;
+ }
+
+ if (!RetrieveGestureDeliveryData(dev, ev, &gi->listener, &client, &win, &grab))
+ return 0;
+
+ ev->gesture_event.deviceid = dev->id;
+
+ return DeliverOneGestureEvent(client, dev, gi, grab, win, ev);
+}
+
int
InitProximityClassDeviceStruct(DeviceIntPtr dev)
{
diff --git a/dix/devices.c b/dix/devices.c
index 29f3051aa..5bf956ead 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -458,6 +458,7 @@ DisableDevice(DeviceIntPtr dev, BOOL sendevent)
return FALSE;
TouchEndPhysicallyActiveTouches(dev);
+ GestureEndActiveGestures(dev);
ReleaseButtonsAndKeys(dev);
SyncRemoveDeviceIdleTime(dev->idle_counter);
dev->idle_counter = NULL;
diff --git a/dix/dispatch.c b/dix/dispatch.c
index ba01de6cf..083553610 100644
--- a/dix/dispatch.c
+++ b/dix/dispatch.c
@@ -3487,6 +3487,7 @@ CloseDownClient(ClientPtr client)
CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
}
TouchListenerGone(client->clientAsMask);
+ GestureListenerGone(client->clientAsMask);
FreeClientResources(client);
/* Disable client ID tracking. This must be done after
* ClientStateCallback. */
diff --git a/dix/events.c b/dix/events.c
index e2455a4bb..d29868ef0 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1328,6 +1328,15 @@ ComputeFreezes(void)
TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch);
}
+ else if (IsGestureEvent(event)) {
+ GestureInfoPtr gi =
+ GestureFindActiveByEventType(replayDev, event->any.type);
+ if (gi) {
+ GestureEmitGestureEndToOwner(replayDev, gi);
+ GestureEndGesture(gi);
+ }
+ ProcessGestureEvent(event, replayDev);
+ }
else {
WindowPtr w = XYToWindow(replayDev->spriteInfo->sprite,
event->device_event.root_x,
@@ -1509,6 +1518,46 @@ UpdateTouchesForGrab(DeviceIntPtr mouse)
}
}
+/**
+ * Update gesture records when an explicit grab is activated. Any gestures owned
+ * by the grabbing client are updated so the listener state reflects the new
+ * grab.
+ */
+static void
+UpdateGesturesForGrab(DeviceIntPtr mouse)
+{
+ if (!mouse->gesture || mouse->deviceGrab.fromPassiveGrab)
+ return;
+
+ GestureInfoPtr gi = &mouse->gesture->gesture;
+ GestureListener *listener = &gi->listener;
+ GrabPtr grab = mouse->deviceGrab.grab;
+
+ if (gi->active && CLIENT_BITS(listener->listener) == grab->resource) {
+ if (grab->grabtype == CORE || grab->grabtype == XI ||
+ !xi2mask_isset(grab->xi2mask, mouse, GetXI2Type(gi->type))) {
+
+ if (listener->type == GESTURE_LISTENER_REGULAR) {
+ /* if the listener already got any events relating to the gesture, we must send
+ a gesture end because the grab overrides the previous listener and won't
+ itself send any gesture events.
+ */
+ GestureEmitGestureEndToOwner(mouse, gi);
+ }
+ listener->type = GESTURE_LISTENER_NONGESTURE_GRAB;
+ } else {
+ listener->type = GESTURE_LISTENER_GRAB;
+ }
+
+ listener->listener = grab->resource;
+ listener->window = grab->window;
+
+ if (listener->grab)
+ FreeGrab(listener->grab);
+ listener->grab = AllocGrab(grab);
+ }
+}
+
/**
* Activate a pointer grab on the given device. A pointer grab will cause all
* core pointer events of this device to be delivered to the grabbing client only.
@@ -1559,6 +1608,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
PostNewCursor(mouse);
UpdateTouchesForGrab(mouse);
+ UpdateGesturesForGrab(mouse);
CheckGrabForSyncs(mouse, (Bool) grab->pointerMode,
(Bool) grab->keyboardMode);
if (oldgrab)
@@ -1614,6 +1664,16 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
if (dev->deviceGrab.sync.other == grab)
dev->deviceGrab.sync.other = NullGrab;
}
+
+ /* in case of explicit gesture grab, send end event to the grab client */
+ if (!wasPassive && mouse->gesture) {
+ GestureInfoPtr gi = &mouse->gesture->gesture;
+ if (gi->active && GestureResourceIsOwner(gi, grab_resource)) {
+ GestureEmitGestureEndToOwner(mouse, gi);
+ GestureEndGesture(gi);
+ }
+ }
+
DoEnterLeaveEvents(mouse, mouse->id, grab->window,
mouse->spriteInfo->sprite->win, NotifyUngrab);
if (grab->confineTo)
diff --git a/dix/gestures.c b/dix/gestures.c
index 7e4057deb..593a4a67f 100644
--- a/dix/gestures.c
+++ b/dix/gestures.c
@@ -39,6 +39,8 @@
#include "windowstr.h"
#include "mi.h"
+#define GESTURE_HISTORY_SIZE 100
+
Bool
GestureInitGestureInfo(GestureInfoPtr gi)
{
@@ -55,3 +57,306 @@ GestureInitGestureInfo(GestureInfoPtr gi)
return TRUE;
}
+
+/**
+ * Given an event type returns the associated gesture event info.
+ */
+GestureInfoPtr
+GestureFindActiveByEventType(DeviceIntPtr dev, int type)
+{
+ GestureClassPtr g = dev->gesture;
+ enum EventType type_to_expect = GestureTypeToBegin(type);
+
+ if (!g || type_to_expect == 0 || !g->gesture.active ||
+ g->gesture.type != type_to_expect) {
+ return NULL;
+ }
+
+ return &g->gesture;
+}
+
+/**
+ * Sets up gesture info for a new gesture. Returns NULL on failure.
+ */
+GestureInfoPtr
+GestureBeginGesture(DeviceIntPtr dev, InternalEvent *ev)
+{
+ GestureClassPtr g = dev->gesture;
+ enum EventType gesture_type = GestureTypeToBegin(ev->any.type);
+
+ /* Note that we ignore begin events when an existing gesture is active */
+ if (!g || gesture_type == 0 || g->gesture.active)
+ return NULL;
+
+ g->gesture.type = gesture_type;
+
+ if (!GestureBuildSprite(dev, &g->gesture))
+ return NULL;
+
+ g->gesture.active = TRUE;
+ g->gesture.num_touches = ev->gesture_event.num_touches;
+ g->gesture.sourceid = ev->gesture_event.sourceid;
+ g->gesture.has_listener = FALSE;
+ return &g->gesture;
+}
+
+/**
+ * Releases a gesture: this must only be called after all events
+ * related to that gesture have been sent and finalised.
+ */
+void
+GestureEndGesture(GestureInfoPtr gi)
+{
+ if (gi->has_listener) {
+ if (gi->listener.grab) {
+ FreeGrab(gi->listener.grab);
+ gi->listener.grab = NULL;
+ }
+ gi->listener.listener = 0;
+ gi->has_listener = FALSE;
+ }
+
+ gi->active = FALSE;
+ gi->num_touches = 0;
+ gi->sprite.spriteTraceGood = 0;
+}
+
+/**
+ * Ensure a window trace is present in gi->sprite, constructing one for
+ * Gesture{Pinch,Swipe}Begin events.
+ */
+Bool
+GestureBuildSprite(DeviceIntPtr sourcedev, GestureInfoPtr gi)
+{
+ SpritePtr sprite = &gi->sprite;
+
+ if (!sourcedev->spriteInfo->sprite)
+ return FALSE;
+
+ if (!CopySprite(sourcedev->spriteInfo->sprite, sprite))
+ return FALSE;
+
+ if (sprite->spriteTraceGood <= 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+/**
+ * @returns TRUE if the specified grab or selection is the current owner of
+ * the gesture sequence.
+ */
+Bool
+GestureResourceIsOwner(GestureInfoPtr gi, XID resource)
+{
+ return (gi->listener.listener == resource);
+}
+
+void
+GestureAddListener(GestureInfoPtr gi, XID resource, int resource_type,
+ enum GestureListenerType type, WindowPtr window, const GrabPtr grab)
+{
+ GrabPtr g = NULL;
+
+ BUG_RETURN(gi->has_listener);
+
+ /* We need a copy of the grab, not the grab itself since that may be deleted by
+ * a UngrabButton request and leaves us with a dangling pointer */
+ if (grab)
+ g = AllocGrab(grab);
+
+ gi->listener.listener = resource;
+ gi->listener.resource_type = resource_type;
+ gi->listener.type = type;
+ gi->listener.window = window;
+ gi->listener.grab = g;
+ gi->has_listener = TRUE;
+}
+
+static void
+GestureAddGrabListener(DeviceIntPtr dev, GestureInfoPtr gi, GrabPtr grab)
+{
+ enum GestureListenerType type;
+
+ /* FIXME: owner_events */
+
+ if (grab->grabtype == XI2) {
+ if (xi2mask_isset(grab->xi2mask, dev, XI_GesturePinchBegin) ||
+ xi2mask_isset(grab->xi2mask, dev, XI_GestureSwipeBegin)) {
+ type = GESTURE_LISTENER_GRAB;
+ } else
+ type = GESTURE_LISTENER_NONGESTURE_GRAB;
+ }
+ else if (grab->grabtype == XI || grab->grabtype == CORE) {
+ type = GESTURE_LISTENER_NONGESTURE_GRAB;
+ }
+ else {
+ BUG_RETURN_MSG(1, "Unsupported grab type\n");
+ }
+
+ /* grab listeners are always RT_NONE since we keep the grab pointer */
+ GestureAddListener(gi, grab->resource, RT_NONE, type, grab->window, grab);
+}
+
+/**
+ * Add one listener if there is a grab on the given window.
+ */
+static void
+GestureAddPassiveGrabListener(DeviceIntPtr dev, GestureInfoPtr gi, WindowPtr win, InternalEvent *ev)
+{
+ Bool activate = FALSE;
+ Bool check_core = FALSE;
+
+ GrabPtr grab = CheckPassiveGrabsOnWindow(win, dev, ev, check_core,
+ activate);
+ if (!grab)
+ return;
+
+ /* We'll deliver later in gesture-specific code */
+ ActivateGrabNoDelivery(dev, grab, ev, ev);
+ GestureAddGrabListener(dev, gi, grab);
+}
+
+static void
+GestureAddRegularListener(DeviceIntPtr dev, GestureInfoPtr gi, WindowPtr win, InternalEvent *ev)
+{
+ InputClients *iclients = NULL;
+ OtherInputMasks *inputMasks = NULL;
+ uint16_t evtype = GetXI2Type(ev->any.type);
+ int mask;
+
+ mask = EventIsDeliverable(dev, ev->any.type, win);
+ if (!mask)
+ return;
+
+ inputMasks = wOtherInputMasks(win);
+
+ if (mask & EVENT_XI2_MASK) {
+ nt_list_for_each_entry(iclients, inputMasks->inputClients, next) {
+ if (!xi2mask_isset(iclients->xi2mask, dev, evtype))
+ continue;
+
+ GestureAddListener(gi, iclients->resource, RT_INPUTCLIENT,
+ GESTURE_LISTENER_REGULAR, win, NULL);
+ return;
+ }
+ }
+}
+
+void
+GestureSetupListener(DeviceIntPtr dev, GestureInfoPtr gi, InternalEvent *ev)
+{
+ int i;
+ SpritePtr sprite = &gi->sprite;
+ WindowPtr win;
+
+ /* Any current grab will consume all gesture events */
+ if (dev->deviceGrab.grab) {
+ GestureAddGrabListener(dev, gi, dev->deviceGrab.grab);
+ return;
+ }
+
+ /* Find passive grab that would be activated by this event, if any. If we're handling
+ * ReplayDevice then the search starts from the descendant of the grab window, otherwise
+ * the search starts at the root window. The search ends at deepest child window. */
+ i = 0;
+ if (syncEvents.playingEvents) {
+ while (i < dev->spriteInfo->sprite->spriteTraceGood) {
+ if (dev->spriteInfo->sprite->spriteTrace[i++] == syncEvents.replayWin)
+ break;
+ }
+ }
+
+ for (; i < sprite->spriteTraceGood; i++) {
+ win = sprite->spriteTrace[i];
+ GestureAddPassiveGrabListener(dev, gi, win, ev);
+ if (gi->has_listener)
+ return;
+ }
+
+ /* Find the first client with an applicable event selection,
+ * going from deepest child window back up to the root window. */
+ for (i = sprite->spriteTraceGood - 1; i >= 0; i--) {
+ win = sprite->spriteTrace[i];
+ GestureAddRegularListener(dev, gi, win, ev);
+ if (gi->has_listener)
+ return;
+ }
+}
+
+/* As gesture grabs don't turn into active grabs with their own resources, we
+ * need to walk all the gestures and remove this grab from listener */
+void
+GestureListenerGone(XID resource)
+{
+ GestureInfoPtr gi;
+ DeviceIntPtr dev;
+ InternalEvent *events = InitEventList(GetMaximumEventsNum());
+
+ if (!events)
+ FatalError("GestureListenerGone: couldn't allocate events\n");
+
+ for (dev = inputInfo.devices; dev; dev = dev->next) {
+ if (!dev->gesture)
+ continue;
+
+ gi = &dev->gesture->gesture;
+ if (!gi->active)
+ continue;
+
+ if (CLIENT_BITS(gi->listener.listener) == resource)
+ GestureEndGesture(gi);
+ }
+
+ FreeEventList(events, GetMaximumEventsNum());
+}
+
+/**
+ * End physically active gestures for a device.
+ */
+void
+GestureEndActiveGestures(DeviceIntPtr dev)
+{
+ GestureClassPtr g = dev->gesture;
+ InternalEvent *eventlist;
+
+ if (!g)
+ return;
+
+ eventlist = InitEventList(GetMaximumEventsNum());
+
+ input_lock();
+ mieqProcessInputEvents();
+ if (g->gesture.active) {
+ int j;
+ int type = GetXI2Type(GestureTypeToEnd(g->gesture.type));
+ int nevents = GetGestureEvents(eventlist, dev, type, g->gesture.num_touches,
+ 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+
+ for (j = 0; j < nevents; j++)
+ mieqProcessDeviceEvent(dev, eventlist + j, NULL);
+ }
+ input_unlock();
+
+ FreeEventList(eventlist, GetMaximumEventsNum());
+}
+
+/**
+ * Generate and deliver a Gesture{Pinch,Swipe}End event to the owner.
+ *
+ * @param dev The device to deliver the event for.
+ * @param gi The gesture record to deliver the event for.
+ */
+void
+GestureEmitGestureEndToOwner(DeviceIntPtr dev, GestureInfoPtr gi)
+{
+ InternalEvent event;
+ /* We're not processing a gesture end for a frozen device */
+ if (dev->deviceGrab.sync.frozen)
+ return;
+
+ DeliverDeviceClassesChangedEvent(gi->sourceid, GetTimeInMillis());
+ InitGestureEvent(&event, dev, GetTimeInMillis(), GestureTypeToEnd(gi->type),
+ 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0);
+ DeliverGestureEventToOwner(dev, gi, &event);
+}
diff --git a/dix/inpututils.c b/dix/inpututils.c
index 6906f997b..9026f651b 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -809,6 +809,24 @@ event_set_state(DeviceIntPtr mouse, DeviceIntPtr kbd, DeviceEvent *event)
}
}
+void
+event_set_state_gesture(DeviceIntPtr kbd, GestureEvent *event)
+{
+ if (kbd && kbd->key) {
+ XkbStatePtr state= &kbd->key->xkbInfo->state;
+
+ event->mods.base = state->base_mods;
+ event->mods.latched = state->latched_mods;
+ event->mods.locked = state->locked_mods;
+ event->mods.effective = state->mods;
+
+ event->group.base = state->base_group;
+ event->group.latched = state->latched_group;
+ event->group.locked = state->locked_group;
+ event->group.effective = state->group;
+ }
+}
+
/**
* Return the event filter mask for the given device and the given core or
* XI1 protocol type.
diff --git a/include/dix.h b/include/dix.h
index 07d3607f2..432bdcc35 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -421,6 +421,10 @@ DeliverTouchEvents(DeviceIntPtr /* dev */ ,
InternalEvent * /* ev */ ,
XID /* resource */ );
+extern Bool
+DeliverGestureEventToOwner(DeviceIntPtr dev, GestureInfoPtr gi,
+ InternalEvent *ev);
+
extern void
InitializeSprite(DeviceIntPtr /* pDev */ ,
WindowPtr /* pWin */ );
diff --git a/include/input.h b/include/input.h
index c19e74969..b1aef3663 100644
--- a/include/input.h
+++ b/include/input.h
@@ -660,6 +660,21 @@ extern void TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags,
extern void TouchAcceptAndEnd(DeviceIntPtr dev, int touchid);
extern Bool GestureInitGestureInfo(GestureInfoPtr gesture);
+extern GestureInfoPtr GestureBeginGesture(DeviceIntPtr dev, InternalEvent *ev);
+extern GestureInfoPtr GestureFindActiveByEventType(DeviceIntPtr dev, int type);
+extern void GestureEndGesture(GestureInfoPtr gi);
+extern Bool GestureResourceIsOwner(GestureInfoPtr gi, XID resource);
+extern void GestureAddListener(GestureInfoPtr gi, XID resource, int resource_type,
+ enum GestureListenerType type,
+ WindowPtr window, GrabPtr grab);
+extern void GestureSetupListener(DeviceIntPtr dev, GestureInfoPtr gi,
+ InternalEvent *ev);
+extern Bool GestureBuildSprite(DeviceIntPtr sourcedev, GestureInfoPtr gi);
+extern void GestureListenerGone(XID resource);
+extern void GestureEndActiveGestures(DeviceIntPtr dev);
+extern void GestureEmitGestureEndToOwner(DeviceIntPtr dev, GestureInfoPtr gi);
+extern void ProcessGestureEvent(InternalEvent *ev, DeviceIntPtr dev);
+
/* misc event helpers */
extern Mask GetEventMask(DeviceIntPtr dev, xEvent *ev, InputClientsPtr clients);
extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event);
diff --git a/include/inpututils.h b/include/inpututils.h
index 489e1d9b7..49b1c1074 100644
--- a/include/inpututils.h
+++ b/include/inpututils.h
@@ -50,6 +50,7 @@ extern void init_gesture_event(GestureEvent *event, DeviceIntPtr dev, Time ms);
extern int event_get_corestate(DeviceIntPtr mouse, DeviceIntPtr kbd);
extern void event_set_state(DeviceIntPtr mouse, DeviceIntPtr kbd,
DeviceEvent *event);
+extern void event_set_state_gesture(DeviceIntPtr kbd, GestureEvent *event);
extern Mask event_get_filter_from_type(DeviceIntPtr dev, int evtype);
extern Mask event_get_filter_from_xi2type(int evtype);
diff --git a/mi/mieq.c b/mi/mieq.c
index bcd62d572..c98d46862 100644
--- a/mi/mieq.c
+++ b/mi/mieq.c
@@ -342,6 +342,14 @@ ChangeDeviceID(DeviceIntPtr dev, InternalEvent *event)
case ET_BarrierLeave:
event->barrier_event.deviceid = dev->id;
break;
+ case ET_GesturePinchBegin:
+ case ET_GesturePinchUpdate:
+ case ET_GesturePinchEnd:
+ case ET_GestureSwipeBegin:
+ case ET_GestureSwipeUpdate:
+ case ET_GestureSwipeEnd:
+ event->gesture_event.deviceid = dev->id;
+ break;
default:
ErrorF("[mi] Unknown event type (%d), cannot change id.\n",
event->any.type);
commit d3c52df16105de5ac37e196a49b173e426caf417
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:41 2021 +0300
hw/xfree86: Implement public APIs to submit gesture events
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index a2b2de392..8cf3f62f0 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -1590,6 +1590,58 @@ xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid, uint16_t type,
QueueTouchEvents(dev, type, touchid, flags, mask);
}
+/**
+ * Post a gesture pinch event. The driver is responsible for maintaining the
+ * correct event sequence (GesturePinchBegin, GesturePinchUpdate,
+ * GesturePinchEnd).
+ *
+ * @param dev The device to post the event for
+ * @param type One of XI_GesturePinchBegin, XI_GesturePinchUpdate,
+ * XI_GesturePinchEnd
+ * @param num_touches The number of touches in the gesture
+ * @param flags Flags for this event
+ * @param delta_x,delta_y accelerated relative motion delta
+ * @param delta_unaccel_x,delta_unaccel_y unaccelerated relative motion delta
+ * @param scale absolute scale of a pinch gesture
+ * @param delta_angle the ange delta in degrees between the last and the current pinch event.
+ */
+void
+xf86PostGesturePinchEvent(DeviceIntPtr dev, uint16_t type,
+ uint16_t num_touches, uint32_t flags,
+ double delta_x, double delta_y,
+ double delta_unaccel_x,
+ double delta_unaccel_y,
+ double scale, double delta_angle)
+{
+ QueueGesturePinchEvents(dev, type, num_touches, flags, delta_x, delta_y,
+ delta_unaccel_x, delta_unaccel_y,
+ scale, delta_angle);
+}
+
+/**
+ * Post a gesture swipe event. The driver is responsible for maintaining the
+ * correct event sequence (GestureSwipeBegin, GestureSwipeUpdate,
+ * GestureSwipeEnd).
+ *
+ * @param dev The device to post the event for
+ * @param type One of XI_GestureSwipeBegin, XI_GestureSwipeUpdate,
+ * XI_GestureSwipeEnd
+ * @param num_touches The number of touches in the gesture
+ * @param flags Flags for this event
+ * @param delta_x,delta_y accelerated relative motion delta
+ * @param delta_unaccel_x,delta_unaccel_y unaccelerated relative motion delta
+ */
+void
+xf86PostGestureSwipeEvent(DeviceIntPtr dev, uint16_t type,
+ uint16_t num_touches, uint32_t flags,
+ double delta_x, double delta_y,
+ double delta_unaccel_x,
+ double delta_unaccel_y)
+{
+ QueueGestureSwipeEvents(dev, type, num_touches, flags, delta_x, delta_y,
+ delta_unaccel_x, delta_unaccel_y);
+}
+
void
xf86InputEnableVTProbe(void)
{
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index 749a80d4b..e73aff269 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -158,6 +158,20 @@ extern _X_EXPORT void xf86PostKeyboardEvent(DeviceIntPtr device,
extern _X_EXPORT void xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid,
uint16_t type, uint32_t flags,
const ValuatorMask *mask);
+extern _X_EXPORT void xf86PostGesturePinchEvent(DeviceIntPtr dev, uint16_t type,
+ uint16_t num_touches,
+ uint32_t flags,
+ double delta_x, double delta_y,
+ double delta_unaccel_x,
+ double delta_unaccel_y,
+ double scale, double delta_angle);
+extern _X_EXPORT void xf86PostGestureSwipeEvent(DeviceIntPtr dev, uint16_t type,
+ uint16_t num_touches,
+ uint32_t flags,
+ double delta_x, double delta_y,
+ double delta_unaccel_x,
+ double delta_unaccel_y);
+
extern _X_EXPORT InputInfoPtr xf86FirstLocalDevice(void);
extern _X_EXPORT int xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max,
int from_min);
commit 100a2ad6da4ba90f8d489c7a2ed3f3f0ac879a6f
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:40 2021 +0300
dix: Implement gesture event submission code path
diff --git a/dix/getevents.c b/dix/getevents.c
index 5dceec39b..368e0fb2a 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -2099,3 +2099,139 @@ PostSyntheticMotion(DeviceIntPtr pDev,
/* FIXME: MD/SD considerations? */
(*pDev->public.processInputProc) ((InternalEvent *) &ev, pDev);
}
+
+void
+InitGestureEvent(InternalEvent *ievent, DeviceIntPtr dev, CARD32 ms,
+ int type, uint16_t num_touches, uint32_t flags,
+ double delta_x, double delta_y,
+ double delta_unaccel_x, double delta_unaccel_y,
+ double scale, double delta_angle)
+{
+ ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen;
+ GestureEvent *event = &ievent->gesture_event;
+ double screenx = 0.0, screeny = 0.0; /* desktop coordinate system */
+
+ init_gesture_event(event, dev, ms);
+
+ screenx = dev->spriteInfo->sprite->hotPhys.x;
+ screeny = dev->spriteInfo->sprite->hotPhys.y;
+
+ event->type = type;
+ event->root = scr->root->drawable.id;
+ event->root_x = screenx - scr->x;
+ event->root_y = screeny - scr->y;
+ event->num_touches = num_touches;
+ event->flags = flags;
+
+ event->delta_x = delta_x;
+ event->delta_y = delta_y;
+ event->delta_unaccel_x = delta_unaccel_x;
+ event->delta_unaccel_y = delta_unaccel_y;
+ event->scale = scale;
+ event->delta_angle = delta_angle;
+}
+
+/**
+ * Get events for a pinch or swipe gesture.
+ *
+ * events is not NULL-terminated; the return value is the number of events.
+ * The DDX is responsible for allocating the event structure in the first
+ * place via GetMaximumEventsNum(), and for freeing it.
+ *
+ * @param[out] events The list of events generated
+ * @param dev The device to generate the events for
+ * @param type XI_Gesture{Pinch,Swipe}{Begin,Update,End}
+ * @prama num_touches The number of touches in the gesture
+ * @param flags Event flags
+ * @param delta_x,delta_y accelerated relative motion delta
+ * @param delta_unaccel_x,delta_unaccel_y unaccelerated relative motion delta
+ * @param scale (valid only to pinch events) absolute scale of a pinch gesture
+ * @param delta_angle (valid only to pinch events) the ange delta in degrees between the last and
+ * the current pinch event.
+ */
+int
+GetGestureEvents(InternalEvent *events, DeviceIntPtr dev,
+ uint16_t type, uint16_t num_touches, uint32_t flags,
+ double delta_x, double delta_y,
+ double delta_unaccel_x, double delta_unaccel_y,
+ double scale, double delta_angle)
+
+{
+ GestureClassPtr g = dev->gesture;
+ CARD32 ms = GetTimeInMillis();
+ enum EventType evtype;
+ int num_events = 0;
+ uint32_t evflags = 0;
+
+ if (!dev->enabled || !g)
+ return 0;
+
+ if (!IsMaster(dev))
+ events = UpdateFromMaster(events, dev, DEVCHANGE_POINTER_EVENT,
+ &num_events);
+
+ switch (type) {
+ case XI_GesturePinchBegin:
+ evtype = ET_GesturePinchBegin;
+ break;
+ case XI_GesturePinchUpdate:
+ evtype = ET_GesturePinchUpdate;
+ break;
+ case XI_GesturePinchEnd:
+ evtype = ET_GesturePinchEnd;
+ if (flags & XIGesturePinchEventCancelled)
+ evflags |= GESTURE_CANCELLED;
+ break;
+ case XI_GestureSwipeBegin:
+ evtype = ET_GestureSwipeBegin;
+ break;
+ case XI_GestureSwipeUpdate:
+ evtype = ET_GestureSwipeUpdate;
+ break;
+ case XI_GestureSwipeEnd:
+ evtype = ET_GestureSwipeEnd;
+ if (flags & XIGestureSwipeEventCancelled)
+ evflags |= GESTURE_CANCELLED;
+ break;
+ default:
+ return 0;
+ }
+
+ InitGestureEvent(events, dev, ms, evtype, num_touches, evflags,
+ delta_x, delta_y, delta_unaccel_x, delta_unaccel_y,
+ scale, delta_angle);
+ num_events++;
+
+ return num_events;
+}
+
+void
+QueueGesturePinchEvents(DeviceIntPtr dev, uint16_t type,
+ uint16_t num_touches, uint32_t flags,
+ double delta_x, double delta_y,
+ double delta_unaccel_x,
+ double delta_unaccel_y,
+ double scale, double delta_angle)
+{
+ int nevents;
+ nevents = GetGestureEvents(InputEventList, dev, type, num_touches, flags,
+ delta_x, delta_y,
+ delta_unaccel_x, delta_unaccel_y,
+ scale, delta_angle);
+ queueEventList(dev, InputEventList, nevents);
+}
+
+void
+QueueGestureSwipeEvents(DeviceIntPtr dev, uint16_t type,
+ uint16_t num_touches, uint32_t flags,
+ double delta_x, double delta_y,
+ double delta_unaccel_x,
+ double delta_unaccel_y)
+{
+ int nevents;
+ nevents = GetGestureEvents(InputEventList, dev, type, num_touches, flags,
+ delta_x, delta_y,
+ delta_unaccel_x, delta_unaccel_y,
+ 0.0, 0.0);
+ queueEventList(dev, InputEventList, nevents);
+}
diff --git a/dix/inpututils.c b/dix/inpututils.c
index b60ffff0d..6906f997b 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -746,6 +746,21 @@ init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms,
event->source_type = source_type;
}
+/**
+ * Initializes the given gesture event to zero (or default values),
+ * for the given device.
+ */
+void
+init_gesture_event(GestureEvent *event, DeviceIntPtr dev, Time ms)
+{
+ memset(event, 0, sizeof(GestureEvent));
+ event->header = ET_Internal;
+ event->length = sizeof(GestureEvent);
+ event->time = ms;
+ event->deviceid = dev->id;
+ event->sourceid = dev->id;
+}
+
int
event_get_corestate(DeviceIntPtr mouse, DeviceIntPtr kbd)
{
diff --git a/include/input.h b/include/input.h
index d607e6b97..c19e74969 100644
--- a/include/input.h
+++ b/include/input.h
@@ -496,6 +496,33 @@ void QueueTouchEvents(DeviceIntPtr device,
uint32_t ddx_touchid,
int flags, const ValuatorMask *mask);
+void InitGestureEvent(InternalEvent *ievent, DeviceIntPtr dev, CARD32 ms,
+ int type, uint16_t num_touches, uint32_t flags,
+ double delta_x, double delta_y,
+ double delta_unaccel_x, double delta_unaccel_y,
+ double scale, double delta_angle);
+
+int GetGestureEvents(InternalEvent *events, DeviceIntPtr dev,
+ uint16_t type, uint16_t num_touches, uint32_t flags,
+ double delta_x, double delta_y,
+ double delta_unaccel_x,
+ double delta_unaccel_y,
+ double scale, double delta_angle);
+
+
+void QueueGesturePinchEvents(DeviceIntPtr dev, uint16_t type,
+ uint16_t num_touches, uint32_t flags,
+ double delta_x, double delta_y,
+ double delta_unaccel_x,
+ double delta_unaccel_y,
+ double scale, double delta_angle);
+
+void QueueGestureSwipeEvents(DeviceIntPtr dev, uint16_t type,
+ uint16_t num_touches, uint32_t flags,
+ double delta_x, double delta_y,
+ double delta_unaccel_x,
+ double delta_unaccel_y);
+
extern int GetTouchOwnershipEvents(InternalEvent *events,
DeviceIntPtr pDev,
TouchPointInfoPtr ti,
diff --git a/include/inpututils.h b/include/inpututils.h
index 2dfe122c9..489e1d9b7 100644
--- a/include/inpututils.h
+++ b/include/inpututils.h
@@ -46,6 +46,7 @@ struct _ValuatorMask {
extern void verify_internal_event(const InternalEvent *ev);
extern void init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms,
enum DeviceEventSource event_source);
+extern void init_gesture_event(GestureEvent *event, DeviceIntPtr dev, Time ms);
extern int event_get_corestate(DeviceIntPtr mouse, DeviceIntPtr kbd);
extern void event_set_state(DeviceIntPtr mouse, DeviceIntPtr kbd,
DeviceEvent *event);
commit 7656a9c8dddbc57adfd4fd05f8e26b1845ac8738
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:39 2021 +0300
dix: Implement internal gesture state handling
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 <povilas at radix.lt>
+ *
+ * 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 <dix-config.h>
+#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;
commit 0bf4123fd3bc945d150884e6ea38bd2b81c0994b
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:38 2021 +0300
dix: Implement gesture event fixups before delivery
diff --git a/dix/events.c b/dix/events.c
index 20a40ecb2..e2455a4bb 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -2545,6 +2545,44 @@ FixUpXI2DeviceEventFromWindow(SpritePtr pSprite, int evtype,
(pSprite->hot.pScreen == pWin->drawable.pScreen);
}
+static void
+FixUpXI2PinchEventFromWindow(SpritePtr pSprite, xXIGesturePinchEvent *event,
+ WindowPtr pWin, Window child)
+{
+ event->root = RootWindow(pSprite)->drawable.id;
+ event->event = pWin->drawable.id;
+
+ if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
+ event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
+ event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
+ event->child = child;
+ }
+ else {
+ event->event_x = 0;
+ event->event_y = 0;
+ event->child = None;
+ }
+}
+
+static void
+FixUpXI2SwipeEventFromWindow(SpritePtr pSprite, xXIGestureSwipeEvent *event,
+ WindowPtr pWin, Window child)
+{
+ event->root = RootWindow(pSprite)->drawable.id;
+ event->event = pWin->drawable.id;
+
+ if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
+ event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
+ event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
+ event->child = child;
+ }
+ else {
+ event->event_x = 0;
+ event->event_y = 0;
+ event->child = None;
+ }
+}
+
/**
* Adjust event fields to comply with the window properties.
*
@@ -2578,6 +2616,18 @@ FixUpEventFromWindow(SpritePtr pSprite,
case XI_BarrierHit:
case XI_BarrierLeave:
return;
+ case XI_GesturePinchBegin:
+ case XI_GesturePinchUpdate:
+ case XI_GesturePinchEnd:
+ FixUpXI2PinchEventFromWindow(pSprite,
+ (xXIGesturePinchEvent*) xE, pWin, child);
+ break;
+ case XI_GestureSwipeBegin:
+ case XI_GestureSwipeUpdate:
+ case XI_GestureSwipeEnd:
+ FixUpXI2SwipeEventFromWindow(pSprite,
+ (xXIGestureSwipeEvent*) xE, pWin, child);
+ break;
default:
FixUpXI2DeviceEventFromWindow(pSprite, evtype,
(xXIDeviceEvent*) xE, pWin, child);
commit 227f601de31aabf6aaa897477e42e6b7f8f7c963
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:37 2021 +0300
xi: Implement conversions from internal to Xi2 gesture event structs
diff --git a/Xi/extinit.c b/Xi/extinit.c
index 8d9120866..4e5a13fc5 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -850,6 +850,74 @@ SBarrierEvent(xXIBarrierEvent * from,
swapl(&to->eventid);
}
+static void
+SGesturePinchEvent(xXIGesturePinchEvent* from,
+ xXIGesturePinchEvent* to)
+{
+ *to = *from;
+
+ swaps(&to->sequenceNumber);
+ swapl(&to->length);
+ swaps(&to->evtype);
+ swaps(&to->deviceid);
+ swapl(&to->time);
+ swapl(&to->detail);
+ swapl(&to->root);
+ swapl(&to->event);
+ swapl(&to->child);
+ swapl(&to->root_x);
+ swapl(&to->root_y);
+ swapl(&to->event_x);
+ swapl(&to->event_y);
+
+ swapl(&to->delta_x);
+ swapl(&to->delta_y);
+ swapl(&to->delta_unaccel_x);
+ swapl(&to->delta_unaccel_y);
+ swapl(&to->scale);
+ swapl(&to->delta_angle);
+ swaps(&to->sourceid);
+
+ swapl(&to->mods.base_mods);
+ swapl(&to->mods.latched_mods);
+ swapl(&to->mods.locked_mods);
+ swapl(&to->mods.effective_mods);
+ swapl(&to->flags);
+}
+
+static void
+SGestureSwipeEvent(xXIGestureSwipeEvent* from,
+ xXIGestureSwipeEvent* to)
+{
+ *to = *from;
+
+ swaps(&to->sequenceNumber);
+ swapl(&to->length);
+ swaps(&to->evtype);
+ swaps(&to->deviceid);
+ swapl(&to->time);
+ swapl(&to->detail);
+ swapl(&to->root);
+ swapl(&to->event);
+ swapl(&to->child);
+ swapl(&to->root_x);
+ swapl(&to->root_y);
+ swapl(&to->event_x);
+ swapl(&to->event_y);
+
+ swapl(&to->delta_x);
+ swapl(&to->delta_y);
+ swapl(&to->delta_unaccel_x);
+ swapl(&to->delta_unaccel_y);
+ swaps(&to->sourceid);
+
+ swapl(&to->mods.base_mods);
+ swapl(&to->mods.latched_mods);
+ swapl(&to->mods.locked_mods);
+ swapl(&to->mods.effective_mods);
+ swapl(&to->flags);
+}
+
/** Event swapping function for XI2 events. */
void _X_COLD
XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
@@ -901,6 +969,18 @@ XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
SBarrierEvent((xXIBarrierEvent *) from,
(xXIBarrierEvent *) to);
break;
+ case XI_GesturePinchBegin:
+ case XI_GesturePinchUpdate:
+ case XI_GesturePinchEnd:
+ SGesturePinchEvent((xXIGesturePinchEvent*) from,
+ (xXIGesturePinchEvent*) to);
+ break;
+ case XI_GestureSwipeBegin:
+ case XI_GestureSwipeUpdate:
+ case XI_GestureSwipeEnd:
+ SGestureSwipeEvent((xXIGestureSwipeEvent*) from,
+ (xXIGestureSwipeEvent*) to);
+ break;
default:
ErrorF("[Xi] Unknown event type to swap. This is a bug.\n");
break;
diff --git a/dix/eventconvert.c b/dix/eventconvert.c
index 9bba2c7c5..53b8c79e3 100644
--- a/dix/eventconvert.c
+++ b/dix/eventconvert.c
@@ -59,6 +59,8 @@ static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi);
static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi);
static int eventToBarrierEvent(BarrierEvent *ev, xEvent **xi);
static int eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi);
+static int eventToGestureSwipeEvent(GestureEvent *ev, xEvent **xi);
+static int eventToGesturePinchEvent(GestureEvent *ev, xEvent **xi);
/* Do not use, read comments below */
BOOL EventIsKeyRepeat(xEvent *event);
@@ -163,6 +165,12 @@ EventToCore(InternalEvent *event, xEvent **core_out, int *count_out)
case ET_TouchOwnership:
case ET_BarrierHit:
case ET_BarrierLeave:
+ case ET_GesturePinchBegin:
+ case ET_GesturePinchUpdate:
+ case ET_GesturePinchEnd:
+ case ET_GestureSwipeBegin:
+ case ET_GestureSwipeUpdate:
+ case ET_GestureSwipeEnd:
ret = BadMatch;
break;
default:
@@ -221,6 +229,12 @@ EventToXI(InternalEvent *ev, xEvent **xi, int *count)
case ET_TouchOwnership:
case ET_BarrierHit:
case ET_BarrierLeave:
+ case ET_GesturePinchBegin:
+ case ET_GesturePinchUpdate:
+ case ET_GesturePinchEnd:
+ case ET_GestureSwipeBegin:
+ case ET_GestureSwipeUpdate:
+ case ET_GestureSwipeEnd:
*count = 0;
*xi = NULL;
return BadMatch;
@@ -285,6 +299,14 @@ EventToXI2(InternalEvent *ev, xEvent **xi)
case ET_BarrierHit:
case ET_BarrierLeave:
return eventToBarrierEvent(&ev->barrier_event, xi);
+ case ET_GesturePinchBegin:
+ case ET_GesturePinchUpdate:
+ case ET_GesturePinchEnd:
+ return eventToGesturePinchEvent(&ev->gesture_event, xi);
+ case ET_GestureSwipeBegin:
+ case ET_GestureSwipeUpdate:
+ case ET_GestureSwipeEnd:
+ return eventToGestureSwipeEvent(&ev->gesture_event, xi);
default:
break;
}
@@ -816,6 +838,88 @@ eventToBarrierEvent(BarrierEvent *ev, xEvent **xi)
return Success;
}
+int
+eventToGesturePinchEvent(GestureEvent *ev, xEvent **xi)
+{
+ int len = sizeof(xXIGesturePinchEvent);
+ xXIGesturePinchEvent *xpe;
+
+ *xi = calloc(1, len);
+ xpe = (xXIGesturePinchEvent *) * xi;
+ xpe->type = GenericEvent;
+ xpe->extension = IReqCode;
+ xpe->evtype = GetXI2Type(ev->type);
+ xpe->time = ev->time;
+ xpe->length = bytes_to_int32(len - sizeof(xEvent));
+ xpe->detail = ev->num_touches;
+
+ xpe->root = ev->root;
+ xpe->deviceid = ev->deviceid;
+ xpe->sourceid = ev->sourceid;
+ xpe->root_x = double_to_fp1616(ev->root_x);
+ xpe->root_y = double_to_fp1616(ev->root_y);
+ xpe->flags |= (ev->flags & GESTURE_CANCELLED) ? XIGesturePinchEventCancelled : 0;
+
+ xpe->delta_x = double_to_fp1616(ev->delta_x);
+ xpe->delta_y = double_to_fp1616(ev->delta_y);
+ xpe->delta_unaccel_x = double_to_fp1616(ev->delta_unaccel_x);
+ xpe->delta_unaccel_y = double_to_fp1616(ev->delta_unaccel_y);
+ xpe->scale = double_to_fp1616(ev->scale);
+ xpe->delta_angle = double_to_fp1616(ev->delta_angle);
+
+ xpe->mods.base_mods = ev->mods.base;
+ xpe->mods.latched_mods = ev->mods.latched;
+ xpe->mods.locked_mods = ev->mods.locked;
+ xpe->mods.effective_mods = ev->mods.effective;
+
+ xpe->group.base_group = ev->group.base;
+ xpe->group.latched_group = ev->group.latched;
+ xpe->group.locked_group = ev->group.locked;
+ xpe->group.effective_group = ev->group.effective;
+
+ return Success;
+}
+
+int
+eventToGestureSwipeEvent(GestureEvent *ev, xEvent **xi)
+{
+ int len = sizeof(xXIGestureSwipeEvent);
+ xXIGestureSwipeEvent *xde;
+
+ *xi = calloc(1, len);
+ xde = (xXIGestureSwipeEvent *) * xi;
+ xde->type = GenericEvent;
+ xde->extension = IReqCode;
+ xde->evtype = GetXI2Type(ev->type);
+ xde->time = ev->time;
+ xde->length = bytes_to_int32(len - sizeof(xEvent));
+ xde->detail = ev->num_touches;
+
+ xde->root = ev->root;
+ xde->deviceid = ev->deviceid;
+ xde->sourceid = ev->sourceid;
+ xde->root_x = double_to_fp1616(ev->root_x);
+ xde->root_y = double_to_fp1616(ev->root_y);
+ xde->flags |= (ev->flags & GESTURE_CANCELLED) ? XIGestureSwipeEventCancelled : 0;
+
+ xde->delta_x = double_to_fp1616(ev->delta_x);
+ xde->delta_y = double_to_fp1616(ev->delta_y);
+ xde->delta_unaccel_x = double_to_fp1616(ev->delta_unaccel_x);
+ xde->delta_unaccel_y = double_to_fp1616(ev->delta_unaccel_y);
+
+ xde->mods.base_mods = ev->mods.base;
+ xde->mods.latched_mods = ev->mods.latched;
+ xde->mods.locked_mods = ev->mods.locked;
+ xde->mods.effective_mods = ev->mods.effective;
+
+ xde->group.base_group = ev->group.base;
+ xde->group.latched_group = ev->group.latched;
+ xde->group.locked_group = ev->group.locked;
+ xde->group.effective_group = ev->group.effective;
+
+ return Success;
+}
+
/**
* Return the corresponding core type for the given event or 0 if no core
* equivalent exists.
diff --git a/include/input.h b/include/input.h
index 98fdf0aed..8252914a6 100644
--- a/include/input.h
+++ b/include/input.h
@@ -105,6 +105,9 @@ SOFTWARE.
#define TOUCH_POINTER_EMULATED (1 << 5) /* touch event may be pointer emulated */
#define TOUCH_END (1 << 6) /* really end this touch now */
+/* GetGestureEvent flags */
+#define GESTURE_CANCELLED (1 << 0)
+
/*int constants for pointer acceleration schemes*/
#define PtrAccelNoOp 0
#define PtrAccelPredictable 1
commit f3462178caf09a8777b8671eb03949b75c8ee07a
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:36 2021 +0300
test/xi2: Verify that XI_GestureSwipeEnd is ignored when outside mask
diff --git a/test/xi2/protocol-xiselectevents.c b/test/xi2/protocol-xiselectevents.c
index 6753bdfa6..7301c46b9 100644
--- a/test/xi2/protocol-xiselectevents.c
+++ b/test/xi2/protocol-xiselectevents.c
@@ -233,6 +233,17 @@ request_XISelectEvents_masks(xXISelectEventsReq * req)
}
/* Test 5:
+ * Mask len is 1 and XI_GestureSwipeEnd is set outside the mask.
+ * That bit should be ignored -> Success
+ */
+ bits = (unsigned char *) &mask[1];
+ mask->mask_len = 1;
+ memset(bits, 0, 5);
+ SetBit(bits, XI_ButtonPress); // does not matter which one
+ SetBit(bits, XI_GestureSwipeEnd);
+ request_XISelectEvent(req, Success);
+
+ /* Test 6:
* HierarchyChanged bit is BadValue for devices other than
* XIAllDevices
*/
@@ -247,7 +258,7 @@ request_XISelectEvents_masks(xXISelectEventsReq * req)
request_XISelectEvent(req, BadValue);
}
- /* Test 6:
+ /* Test 7:
* All bits set minus hierarchy changed bit -> Success
*/
bits = (unsigned char *) &mask[1];
commit 407a2234b32d9cb3fed2cc7e8069bb41b98e143f
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:35 2021 +0300
test/xi2: Update tests for gesture event types
diff --git a/test/xi2/protocol-xipassivegrabdevice.c b/test/xi2/protocol-xipassivegrabdevice.c
index 142bcecb7..dc4602d5d 100644
--- a/test/xi2/protocol-xipassivegrabdevice.c
+++ b/test/xi2/protocol-xipassivegrabdevice.c
@@ -194,7 +194,7 @@ test_XIPassiveGrabDevice(void)
request->deviceid = XIAllMasterDevices;
printf("Testing invalid grab types\n");
- for (i = XIGrabtypeTouchBegin + 1; i < 0xFF; i++) {
+ for (i = XIGrabtypeGestureSwipeBegin + 1; i < 0xFF; i++) {
request->grab_type = i;
request_XIPassiveGrabDevice(&client_request, request, BadValue,
request->grab_type);
diff --git a/test/xi2/protocol-xiselectevents.c b/test/xi2/protocol-xiselectevents.c
index 6c94ea73c..6753bdfa6 100644
--- a/test/xi2/protocol-xiselectevents.c
+++ b/test/xi2/protocol-xiselectevents.c
@@ -124,6 +124,16 @@ _set_bit(unsigned char *bits, int bit)
SetBit(bits, XI_TouchUpdate);
SetBit(bits, XI_TouchEnd);
}
+ if (bit >= XI_GesturePinchBegin && bit <= XI_GesturePinchEnd) {
+ SetBit(bits, XI_GesturePinchBegin);
+ SetBit(bits, XI_GesturePinchUpdate);
+ SetBit(bits, XI_GesturePinchEnd);
+ }
+ if (bit >= XI_GestureSwipeBegin && bit <= XI_GestureSwipeEnd) {
+ SetBit(bits, XI_GestureSwipeBegin);
+ SetBit(bits, XI_GestureSwipeUpdate);
+ SetBit(bits, XI_GestureSwipeEnd);
+ }
}
static void
@@ -135,6 +145,16 @@ _clear_bit(unsigned char *bits, int bit)
ClearBit(bits, XI_TouchUpdate);
ClearBit(bits, XI_TouchEnd);
}
+ if (bit >= XI_GesturePinchBegin && bit <= XI_GesturePinchEnd) {
+ ClearBit(bits, XI_GesturePinchBegin);
+ ClearBit(bits, XI_GesturePinchUpdate);
+ ClearBit(bits, XI_GesturePinchEnd);
+ }
+ if (bit >= XI_GestureSwipeBegin && bit <= XI_GestureSwipeEnd) {
+ ClearBit(bits, XI_GestureSwipeBegin);
+ ClearBit(bits, XI_GestureSwipeUpdate);
+ ClearBit(bits, XI_GestureSwipeEnd);
+ }
}
static void
commit f83f7dbb1c1be406b82da9bca12be3c43d6bfeee
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:34 2021 +0300
xi: Bump max supported XI2 event type
diff --git a/include/inputstr.h b/include/inputstr.h
index 33d440b2c..1cf871530 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -75,7 +75,7 @@ extern _X_EXPORT int CountBits(const uint8_t * mask, int len);
* events to the protocol, the server will not support these events until
* this number here is bumped.
*/
-#define XI2LASTEVENT XI_BarrierLeave
+#define XI2LASTEVENT XI_GestureSwipeEnd
#define XI2MASKSIZE ((XI2LASTEVENT >> 3) + 1) /* no of bytes for masks */
/**
commit 81909546397eb180ed8983bdb80f5673dbae71ac
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:33 2021 +0300
xi: Implement selection logic for gesture event types
diff --git a/Xi/xiselectev.c b/Xi/xiselectev.c
index 0266a8d30..edcb8a0d3 100644
--- a/Xi/xiselectev.c
+++ b/Xi/xiselectev.c
@@ -226,8 +226,41 @@ ProcXISelectEvents(ClientPtr client)
return BadValue;
}
- /* Only one client per window may select for touch events on the
- * same devices, including master devices.
+ /* All three pinch gesture events must be selected at once */
+ if ((BitIsOn(bits, XI_GesturePinchBegin) ||
+ BitIsOn(bits, XI_GesturePinchUpdate) ||
+ BitIsOn(bits, XI_GesturePinchEnd)) &&
+ (!BitIsOn(bits, XI_GesturePinchBegin) ||
+ !BitIsOn(bits, XI_GesturePinchUpdate) ||
+ !BitIsOn(bits, XI_GesturePinchEnd))) {
+ client->errorValue = XI_GesturePinchBegin;
+ return BadValue;
+ }
+
+ /* All three swipe gesture events must be selected at once. Note
+ that the XI_GestureSwipeEnd is at index 32 which is on the next
+ 4-byte mask element */
+ if (evmask->mask_len == 1 &&
+ (BitIsOn(bits, XI_GestureSwipeBegin) ||
+ BitIsOn(bits, XI_GestureSwipeUpdate)))
+ {
+ client->errorValue = XI_GestureSwipeBegin;
+ return BadValue;
+ }
+
+ if (evmask->mask_len >= 2 &&
+ (BitIsOn(bits, XI_GestureSwipeBegin) ||
+ BitIsOn(bits, XI_GestureSwipeUpdate) ||
+ BitIsOn(bits, XI_GestureSwipeEnd)) &&
+ (!BitIsOn(bits, XI_GestureSwipeBegin) ||
+ !BitIsOn(bits, XI_GestureSwipeUpdate) ||
+ !BitIsOn(bits, XI_GestureSwipeEnd))) {
+ client->errorValue = XI_GestureSwipeBegin;
+ return BadValue;
+ }
+
+ /* Only one client per window may select for touch or gesture events
+ * on the same devices, including master devices.
* XXX: This breaks if a device goes from floating to attached. */
if (BitIsOn(bits, XI_TouchBegin)) {
rc = check_for_touch_selection_conflicts(client,
@@ -237,6 +270,22 @@ ProcXISelectEvents(ClientPtr client)
if (rc != Success)
return rc;
}
+ if (BitIsOn(bits, XI_GesturePinchBegin)) {
+ rc = check_for_touch_selection_conflicts(client,
+ win,
+ evmask->deviceid,
+ XI_GesturePinchBegin);
+ if (rc != Success)
+ return rc;
+ }
+ if (BitIsOn(bits, XI_GestureSwipeBegin)) {
+ rc = check_for_touch_selection_conflicts(client,
+ win,
+ evmask->deviceid,
+ XI_GestureSwipeBegin);
+ if (rc != Success)
+ return rc;
+ }
}
if (XICheckInvalidMaskBits(client, (unsigned char *) &evmask[1],
commit 080bac39c844bd16b7e1493797c6e7644badf0ab
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:32 2021 +0300
xi: Implement grab support for new gesture event types
diff --git a/Xi/exevents.c b/Xi/exevents.c
index c8751ce18..83ea387ab 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -2427,8 +2427,8 @@ GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
/* Touch grab */
int
-GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
- GrabParameters *param, GrabMask *mask)
+GrabTouchOrGesture(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
+ int type, GrabParameters *param, GrabMask *mask)
{
WindowPtr pWin;
GrabPtr grab;
@@ -2446,7 +2446,7 @@ GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
return rc;
grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
- mask, param, XI_TouchBegin, 0, NullWindow, NullCursor);
+ mask, param, type, 0, NullWindow, NullCursor);
if (!grab)
return BadAlloc;
diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c
index d30f51f3c..2769fb7c9 100644
--- a/Xi/xipassivegrab.c
+++ b/Xi/xipassivegrab.c
@@ -114,14 +114,18 @@ ProcXIPassiveGrabDevice(ClientPtr client)
stuff->grab_type != XIGrabtypeKeycode &&
stuff->grab_type != XIGrabtypeEnter &&
stuff->grab_type != XIGrabtypeFocusIn &&
- stuff->grab_type != XIGrabtypeTouchBegin) {
+ stuff->grab_type != XIGrabtypeTouchBegin &&
+ stuff->grab_type != XIGrabtypeGesturePinchBegin &&
+ stuff->grab_type != XIGrabtypeGestureSwipeBegin) {
client->errorValue = stuff->grab_type;
return BadValue;
}
if ((stuff->grab_type == XIGrabtypeEnter ||
stuff->grab_type == XIGrabtypeFocusIn ||
- stuff->grab_type == XIGrabtypeTouchBegin) && stuff->detail != 0) {
+ stuff->grab_type == XIGrabtypeTouchBegin ||
+ stuff->grab_type == XIGrabtypeGesturePinchBegin ||
+ stuff->grab_type == XIGrabtypeGestureSwipeBegin) && stuff->detail != 0) {
client->errorValue = stuff->detail;
return BadValue;
}
@@ -217,7 +221,16 @@ ProcXIPassiveGrabDevice(ClientPtr client)
status = GrabWindow(client, dev, stuff->grab_type, ¶m, &mask);
break;
case XIGrabtypeTouchBegin:
- status = GrabTouch(client, dev, mod_dev, ¶m, &mask);
+ status = GrabTouchOrGesture(client, dev, mod_dev, XI_TouchBegin,
+ ¶m, &mask);
+ break;
+ case XIGrabtypeGesturePinchBegin:
+ status = GrabTouchOrGesture(client, dev, mod_dev,
+ XI_GesturePinchBegin, ¶m, &mask);
+ break;
+ case XIGrabtypeGestureSwipeBegin:
+ status = GrabTouchOrGesture(client, dev, mod_dev,
+ XI_GestureSwipeBegin, ¶m, &mask);
break;
}
@@ -307,7 +320,9 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
stuff->grab_type != XIGrabtypeKeycode &&
stuff->grab_type != XIGrabtypeEnter &&
stuff->grab_type != XIGrabtypeFocusIn &&
- stuff->grab_type != XIGrabtypeTouchBegin) {
+ stuff->grab_type != XIGrabtypeTouchBegin &&
+ stuff->grab_type != XIGrabtypeGesturePinchBegin &&
+ stuff->grab_type != XIGrabtypeGestureSwipeBegin) {
client->errorValue = stuff->grab_type;
return BadValue;
}
@@ -348,6 +363,12 @@ ProcXIPassiveUngrabDevice(ClientPtr client)
case XIGrabtypeTouchBegin:
tempGrab->type = XI_TouchBegin;
break;
+ case XIGrabtypeGesturePinchBegin:
+ tempGrab->type = XI_GesturePinchBegin;
+ break;
+ case XIGrabtypeGestureSwipeBegin:
+ tempGrab->type = XI_GestureSwipeBegin;
+ break;
}
tempGrab->grabtype = XI2;
tempGrab->modifierDevice = mod_dev;
diff --git a/dix/grabs.c b/dix/grabs.c
index 2a307a2b9..53ba1d6b9 100644
--- a/dix/grabs.c
+++ b/dix/grabs.c
@@ -716,3 +716,10 @@ GrabIsKeyboardGrab(GrabPtr grab)
return (grab->type == KeyPress ||
grab->type == DeviceKeyPress || grab->type == XI_KeyPress);
}
+
+Bool
+GrabIsGestureGrab(GrabPtr grab)
+{
+ return (grab->type == XI_GesturePinchBegin ||
+ grab->type == XI_GestureSwipeBegin);
+}
diff --git a/include/dixgrabs.h b/include/dixgrabs.h
index 3bd80132b..dc1068fef 100644
--- a/include/dixgrabs.h
+++ b/include/dixgrabs.h
@@ -61,4 +61,5 @@ extern _X_EXPORT Bool DeletePassiveGrabFromList(GrabPtr /* pMinuendGrab */ );
extern Bool GrabIsPointerGrab(GrabPtr grab);
extern Bool GrabIsKeyboardGrab(GrabPtr grab);
+extern Bool GrabIsGestureGrab(GrabPtr grab);
#endif /* DIXGRABS_H */
diff --git a/include/exevents.h b/include/exevents.h
index 321fc422d..c900c7b2c 100644
--- a/include/exevents.h
+++ b/include/exevents.h
@@ -192,11 +192,12 @@ extern int
GrabMask * /* eventMask */ );
extern int
- GrabTouch(ClientPtr /* client */ ,
- DeviceIntPtr /* dev */ ,
- DeviceIntPtr /* mod_dev */ ,
- GrabParameters * /* param */ ,
- GrabMask * /* eventMask */ );
+ GrabTouchOrGesture(ClientPtr /* client */ ,
+ DeviceIntPtr /* dev */ ,
+ DeviceIntPtr /* mod_dev */ ,
+ int /* type */ ,
+ GrabParameters * /* param */ ,
+ GrabMask * /* eventMask */ );
extern int
SelectForWindow(DeviceIntPtr /* dev */ ,
commit b544a1fdb8fa7e7efc7dde66089e901d957061d9
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:31 2021 +0300
xi: Implement internal gesture event struct
diff --git a/include/events.h b/include/events.h
index 0cbd8c84a..544dfad02 100644
--- a/include/events.h
+++ b/include/events.h
@@ -28,6 +28,7 @@ typedef struct _DeviceEvent DeviceEvent;
typedef struct _DeviceChangedEvent DeviceChangedEvent;
typedef struct _TouchOwnershipEvent TouchOwnershipEvent;
typedef struct _BarrierEvent BarrierEvent;
+typedef struct _GestureEvent GestureEvent;
#ifdef XFreeXDGA
typedef struct _DGAEvent DGAEvent;
diff --git a/include/eventstr.h b/include/eventstr.h
index 16df595d6..93308f9b2 100644
--- a/include/eventstr.h
+++ b/include/eventstr.h
@@ -266,6 +266,38 @@ struct _BarrierEvent {
uint32_t flags;
};
+struct _GestureEvent {
+ unsigned char header; /**< Always ET_Internal */
+ enum EventType type; /**< One of ET_Gesture{Pinch,Swipe}{Begin,Update,End} */
+ int length; /**< Length in bytes */
+ Time time; /**< Time in ms */
+ int deviceid; /**< Device to post this event for */
+ int sourceid; /**< The physical source device */
+ uint32_t num_touches; /**< The number of touches in this gesture */
+ double root_x; /**< Pos relative to root window */
+ double root_y; /**< Pos relative to root window */
+ double delta_x;
+ double delta_y;
+ double delta_unaccel_x;
+ double delta_unaccel_y;
+ double scale; /**< Only on ET_GesturePinch{Begin,Update} */
+ double delta_angle; /**< Only on ET_GesturePinch{Begin,Update} */
+ struct {
+ uint32_t base; /**< XKB base modifiers */
+ uint32_t latched; /**< XKB latched modifiers */
+ uint32_t locked; /**< XKB locked modifiers */
+ uint32_t effective;/**< XKB effective modifiers */
+ } mods;
+ struct {
+ uint8_t base; /**< XKB base group */
+ uint8_t latched; /**< XKB latched group */
+ uint8_t locked; /**< XKB locked group */
+ uint8_t effective;/**< XKB effective group */
+ } group;
+ Window root; /**< Root window of the event */
+ uint32_t flags; /**< Flags to be copied into the generated event */
+};
+
#ifdef XQUARTZ
#define XQUARTZ_EVENT_MAXARGS 5
struct _XQuartzEvent {
@@ -300,6 +332,7 @@ union _InternalEvent {
#ifdef XQUARTZ
XQuartzEvent xquartz_event;
#endif
+ GestureEvent gesture_event;
};
#endif
commit 22fa31ed561ed1e78bf3651f28e11882b1eac51f
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:30 2021 +0300
dix: Add new internal event enums for gesture events
diff --git a/Xi/exevents.c b/Xi/exevents.c
index dd3e90ae5..c8751ce18 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -95,6 +95,7 @@ SOFTWARE.
#include "exevents.h"
#include "extnsionst.h"
#include "exglobals.h"
+#include "eventstr.h"
#include "dixevents.h" /* DeliverFocusedEvent */
#include "dixgrabs.h" /* CreateGrab() */
#include "scrnintstr.h"
@@ -168,6 +169,49 @@ IsTouchEvent(InternalEvent *event)
return FALSE;
}
+Bool
+IsGestureEvent(InternalEvent *event)
+{
+ switch (event->any.type) {
+ case ET_GesturePinchBegin:
+ case ET_GesturePinchUpdate:
+ case ET_GesturePinchEnd:
+ case ET_GestureSwipeBegin:
+ case ET_GestureSwipeUpdate:
+ case ET_GestureSwipeEnd:
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+Bool
+IsGestureBeginEvent(InternalEvent *event)
+{
+ switch (event->any.type) {
+ case ET_GesturePinchBegin:
+ case ET_GestureSwipeBegin:
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
+Bool
+IsGestureEndEvent(InternalEvent *event)
+{
+ switch (event->any.type) {
+ case ET_GesturePinchEnd:
+ case ET_GestureSwipeEnd:
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
+
/**
* @return the device matching the deviceid of the device set in the event, or
* NULL if the event is not an XInput event.
diff --git a/dix/eventconvert.c b/dix/eventconvert.c
index 4a07b6b6f..9bba2c7c5 100644
--- a/dix/eventconvert.c
+++ b/dix/eventconvert.c
@@ -969,8 +969,68 @@ GetXI2Type(enum EventType type)
case ET_BarrierLeave:
xi2type = XI_BarrierLeave;
break;
+ case ET_GesturePinchBegin:
+ xi2type = XI_GesturePinchBegin;
+ break;
+ case ET_GesturePinchUpdate:
+ xi2type = XI_GesturePinchUpdate;
+ break;
+ case ET_GesturePinchEnd:
+ xi2type = XI_GesturePinchEnd;
+ break;
+ case ET_GestureSwipeBegin:
+ xi2type = XI_GestureSwipeBegin;
+ break;
+ case ET_GestureSwipeUpdate:
+ xi2type = XI_GestureSwipeUpdate;
+ break;
+ case ET_GestureSwipeEnd:
+ xi2type = XI_GestureSwipeEnd;
+ break;
default:
break;
}
return xi2type;
}
+
+/**
+ * Converts a gesture type to corresponding Gesture{Pinch,Swipe}Begin.
+ * Returns 0 if the input type is not a gesture.
+ */
+enum EventType
+GestureTypeToBegin(enum EventType type)
+{
+ switch (type) {
+ case ET_GesturePinchBegin:
+ case ET_GesturePinchUpdate:
+ case ET_GesturePinchEnd:
+ return ET_GesturePinchBegin;
+ case ET_GestureSwipeBegin:
+ case ET_GestureSwipeUpdate:
+ case ET_GestureSwipeEnd:
+ return ET_GestureSwipeBegin;
+ default:
+ return 0;
+ }
+}
+
+/**
+ * Converts a gesture type to corresponding Gesture{Pinch,Swipe}End.
+ * Returns 0 if the input type is not a gesture.
+ */
+enum EventType
+GestureTypeToEnd(enum EventType type)
+{
+ switch (type) {
+ case ET_GesturePinchBegin:
+ case ET_GesturePinchUpdate:
+ case ET_GesturePinchEnd:
+ return ET_GesturePinchEnd;
+ case ET_GestureSwipeBegin:
+ case ET_GestureSwipeUpdate:
+ case ET_GestureSwipeEnd:
+ return ET_GestureSwipeEnd;
+ default:
+ return 0;
+ }
+}
diff --git a/include/dix.h b/include/dix.h
index ece8b6f76..07d3607f2 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -610,6 +610,13 @@ extern Bool
IsPointerEvent(InternalEvent *event);
extern Bool
IsTouchEvent(InternalEvent *event);
+Bool
+IsGestureEvent(InternalEvent *event);
+Bool
+IsGestureBeginEvent(InternalEvent *event);
+Bool
+IsGestureEndEvent(InternalEvent *event);
+
extern _X_EXPORT Bool
IsMaster(DeviceIntPtr dev);
extern _X_EXPORT Bool
diff --git a/include/eventconvert.h b/include/eventconvert.h
index 01172f0ee..cf425f7a9 100644
--- a/include/eventconvert.h
+++ b/include/eventconvert.h
@@ -36,4 +36,7 @@ _X_INTERNAL int GetCoreType(enum EventType type);
_X_INTERNAL int GetXIType(enum EventType type);
_X_INTERNAL int GetXI2Type(enum EventType type);
+_X_INTERNAL enum EventType GestureTypeToBegin(enum EventType type);
+_X_INTERNAL enum EventType GestureTypeToEnd(enum EventType type);
+
#endif /* _EVENTCONVERT_H_ */
diff --git a/include/eventstr.h b/include/eventstr.h
index bf3b95fe4..16df595d6 100644
--- a/include/eventstr.h
+++ b/include/eventstr.h
@@ -75,6 +75,12 @@ enum EventType {
ET_XQuartz,
ET_BarrierHit,
ET_BarrierLeave,
+ ET_GesturePinchBegin,
+ ET_GesturePinchUpdate,
+ ET_GesturePinchEnd,
+ ET_GestureSwipeBegin,
+ ET_GestureSwipeUpdate,
+ ET_GestureSwipeEnd,
ET_Internal = 0xFF /* First byte */
};
commit 8e504d8b36eb8f23bf8cfa46143d046cc6b8ea51
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:29 2021 +0300
meson: Depend on inputproto 2.3.99.1
Signed-off-by: Povilas Kanapickas <povilas at radix.lt>
diff --git a/meson.build b/meson.build
index 35770ba5e..fdb101f80 100644
--- a/meson.build
+++ b/meson.build
@@ -70,7 +70,7 @@ xproto_dep = dependency('xproto', version: '>= 7.0.31')
randrproto_dep = dependency('randrproto', version: '>= 1.6.0')
renderproto_dep = dependency('renderproto', version: '>= 0.11')
xextproto_dep = dependency('xextproto', version: '>= 7.2.99.901')
-inputproto_dep = dependency('inputproto', version: '>= 2.3')
+inputproto_dep = dependency('inputproto', version: '>= 2.3.99.1')
kbproto_dep = dependency('kbproto', version: '>= 1.0.3')
fontsproto_dep = dependency('fontsproto', version: '>= 2.1.3')
fixesproto_dep = dependency('fixesproto', version: '>= 5.0')
commit 2acde60147797393e0ee9428cff0f74cdc0a9227
Author: Povilas Kanapickas <povilas at radix.lt>
Date: Sun May 30 13:26:28 2021 +0300
.gitlab-ci: Install xorgproto 2021.4.99.2 from git
This is required for the support of upcoming XI 2.4 protocol.
Signed-off-by: Povilas Kanapickas <povilas at radix.lt>
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 75b2aed31..6cdb346c7 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -11,7 +11,7 @@ variables:
UPSTREAM_REPO: xorg/xserver
FDO_DISTRIBUTION_VERSION: buster-slim
FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} bash .gitlab-ci/debian-install.sh'
- FDO_DISTRIBUTION_TAG: "2021-04-06"
+ FDO_DISTRIBUTION_TAG: "2021-05-17"
include:
- project: 'freedesktop/ci-templates'
diff --git a/.gitlab-ci/cross-prereqs-build.sh b/.gitlab-ci/cross-prereqs-build.sh
index 3decf707b..4596667a1 100755
--- a/.gitlab-ci/cross-prereqs-build.sh
+++ b/.gitlab-ci/cross-prereqs-build.sh
@@ -49,7 +49,7 @@ build 'https://gitlab.freedesktop.org/pixman/pixman.git' 'pixman-0.38.4'
build 'https://gitlab.freedesktop.org/xorg/lib/pthread-stubs.git' '0.4'
# we can't use the xorgproto pkgconfig files from /usr/share/pkgconfig, because
# these would add -I/usr/include to CFLAGS, which breaks cross-compilation
-build 'https://gitlab.freedesktop.org/xorg/proto/xorgproto.git' 'xorgproto-2019.1' '--datadir=/lib'
+build 'https://gitlab.freedesktop.org/xorg/proto/xorgproto.git' 'xorgproto-2021.4.99.2' '--datadir=/lib'
build 'https://gitlab.freedesktop.org/xorg/lib/libXau.git' 'libXau-1.0.9'
build 'https://gitlab.freedesktop.org/xorg/proto/xcbproto.git' 'xcb-proto-1.14'
build 'https://gitlab.freedesktop.org/xorg/lib/libxcb.git' 'libxcb-1.14'
diff --git a/.gitlab-ci/debian-install.sh b/.gitlab-ci/debian-install.sh
index 60d76c831..963533cda 100644
--- a/.gitlab-ci/debian-install.sh
+++ b/.gitlab-ci/debian-install.sh
@@ -98,7 +98,6 @@ apt-get install -y \
python3-mako \
python3-numpy \
python3-six \
- x11proto-dev \
xfonts-utils \
xkb-data \
xtrans-dev \
@@ -108,6 +107,14 @@ apt-get install -y \
cd /root
+# xserver requires xorgproto >= 2021.4.99.2 for XI 2.3.99.1
+git clone https://gitlab.freedesktop.org/xorg/proto/xorgproto.git --depth 1 --branch=xorgproto-2021.4.99.2
+pushd xorgproto
+./autogen.sh
+make -j${FDO_CI_CONCURRENT:-4} install
+popd
+rm -rf xorgproto
+
# weston 9.0 requires libwayland >= 1.18
git clone https://gitlab.freedesktop.org/wayland/wayland.git --depth 1 --branch=1.18.0
cd wayland
More information about the xorg-commit
mailing list