3
@@ -67,6 +67,22 @@ AC_SUBST([sdkdir])
4
# Checks for header files.
7
+AC_ARG_ENABLE(utouch-grail, AS_HELP_STRING([--enable-grail], [Build with utouch-grail gesture support (default: auto)]), [GRAIL=$enableval], [GRAIL=auto])
8
+PKG_CHECK_MODULES(GRAIL, utouch-grail, [have_grail=yes], [have_grail=no])
9
+if test "x$GRAIL" = xauto; then
12
+if test "x$GRAIL" = xyes; then
13
+ if test "x$have_grail" = xno; then
14
+ AC_MSG_ERROR([Grail build explicitly requested, but required modules not found.])
16
+ AC_DEFINE(USE_GRAIL, 1, Whether to use grail or not)
17
+ AC_DEFINE(GESTURES, 1, Needed to interpret xorg headers properly)
19
+ AC_DEFINE(USE_GRAIL, 0, Whether to use grail or not)
21
+AM_CONDITIONAL(USE_GRAIL, [test "x$GRAIL" = xyes])
24
AC_SUBST([DRIVER_NAME])
29
AM_CFLAGS = $(XORG_CFLAGS)
31
@DRIVER_NAME@_drv_la_LTLIBRARIES = @DRIVER_NAME@_drv.la
32
-@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version
33
+@DRIVER_NAME@_drv_la_LDFLAGS = -module -avoid-version @GRAIL_LIBS@
34
@DRIVER_NAME@_drv_ladir = @inputdir@
36
INCLUDES=-I$(top_srcdir)/include/
38
-@DRIVER_NAME@_drv_la_SOURCES = @DRIVER_NAME@.c \
41
+GRAIL_SRC=evdev-grail.c evdev-grail.h
44
+@DRIVER_NAME@_drv_la_SOURCES = evdev.c \
51
+++ b/src/evdev-grail.c
54
+ * Copyright © 2010 Canonical, Ltd.
56
+ * Permission to use, copy, modify, distribute, and sell this software
57
+ * and its documentation for any purpose is hereby granted without
58
+ * fee, provided that the above copyright notice appear in all copies
59
+ * and that both that copyright notice and this permission notice
60
+ * appear in supporting documentation, and that the name of Red Hat
61
+ * not be used in advertising or publicity pertaining to distribution
62
+ * of the software without specific, written prior permission. Red
63
+ * Hat makes no representations about the suitability of this software
64
+ * for any purpose. It is provided "as is" without express or implied
67
+ * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
68
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
69
+ * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
70
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
71
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
72
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
73
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
76
+ * Chase Douglas (chase.douglas@canonical.com)
79
+/* So we can get at the right data in xorg/windowstr.h */
85
+#include <X11/Xatom.h>
87
+#include <xf86Xinput.h>
88
+#include <exevents.h>
89
+#include <windowstr.h>
92
+#include <evdev-properties.h>
94
+#include "evdev-grail.h"
95
+#include "gestureproto.h"
97
+/* Copied from evdev.c, will be in evdev.h when xserver 1.9 is merged */
98
+#define EVDEV_RELATIVE_EVENTS (1 << 2)
99
+#define EVDEV_TOUCHPAD (1 << 4)
101
+static WindowPtr CommonAncestor(WindowPtr a, WindowPtr b)
108
+ for (b = b; b; b = b->parent)
109
+ for (c = a; c; c = c->parent)
116
+static WindowPtr GetWindowForGestures(struct grail *grail,
117
+ const struct grail_coord *contacts,
120
+ WindowPtr window = NULL;
123
+ for (i = 0; i < num_contacts; i++)
125
+ float screen_x = contacts[i].x;
126
+ float screen_y = contacts[i].y;
127
+ WindowPtr this_window;
129
+ this_window = xf86CoordinatesToWindow(screen_x, screen_y, 0);
134
+ window = this_window;
136
+ window = CommonAncestor(window, this_window);
142
+static int GetClients(struct grail *grail,
143
+ struct grail_client_info *clients, int max_clients,
144
+ const struct grail_coord *contacts, int num_contacts,
145
+ const grail_mask_t *types, int type_bytes)
147
+ WindowPtr child_window;
149
+ WindowPtr root_window = NULL;
150
+ InputInfoPtr pInfo = grail->priv;
151
+ EvdevPtr pEvdev = pInfo->private;
153
+ int found_match = 0;
154
+ int num_clients = 0;
157
+ if (max_clients <= 0)
160
+ if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_TOUCHPAD))
162
+ DeviceIntPtr master = pInfo->dev->u.master;
163
+ struct grail_coord cursor_coord;
165
+ /* If this mouse isn't hooked up to a cursor, don't do anything */
169
+ cursor_coord.x = master->last.valuators[0];
170
+ cursor_coord.y = master->last.valuators[1];
172
+ child_window = GetWindowForGestures(grail, &cursor_coord, 1);
174
+ child_window = GetWindowForGestures(grail, contacts, num_contacts);
179
+ memset(clients, 0, sizeof(struct grail_client_info) * max_clients);
182
+ * Traverse the window hierarchy looking for a window with a client
183
+ * selecting for one of the recognized gestures.
185
+ * All clients of the top most window with a match will receive events if
186
+ * they have selected for gestures that have been recognized, even if they
187
+ * have selected for different gestures between them.
189
+ * Once any gesture is matched on a window, propagation through the window
192
+ for (window = child_window; window && !found_match; window = window->parent)
194
+ /* No client selected for gestures on this window */
195
+ if (!wGestureMasks(window))
198
+ /* For each recognized gesture */
199
+ grail_mask_foreach(type, types, type_bytes)
201
+ /* Check if any client selected for this gesture on the window */
202
+ if (BitIsOn(wGestureMasks(window)->mask, type))
204
+ GestureClientsPtr client;
207
+ for (root_window = window; root_window->parent;
208
+ root_window = root_window->parent);
210
+ /* For each client that selected for gestures on this window */
211
+ for (client = wGestureMasks(window)->clients; client;
212
+ client = client->next)
215
+ * Check if this client selected for this gesture. Request
216
+ * may be for this device or all devices.
218
+ if (BitIsOn(client->gestureMask[pInfo->dev->id], type) ||
219
+ BitIsOn(client->gestureMask[0], type))
222
+ * Find this client in the clients array passed back to
225
+ for (j = 0; j < num_clients; j++)
226
+ if (clients[j].id.client ==
227
+ CLIENT_ID(client->resource))
230
+ /* Check if the client exists in the array yet */
231
+ if (j >= num_clients)
233
+ /* We ran out of room in the array, return error */
234
+ if (num_clients >= max_clients)
236
+ /* Set up new client in array */
237
+ clients[j].id.client = CLIENT_ID(client->resource);
238
+ clients[j].id.root = root_window->drawable.id;
239
+ clients[j].id.child = child_window->drawable.id;
240
+ clients[j].id.event = window->drawable.id;
244
+ /* Set this gesture bit in the client's gesture mask */
245
+ SetBit(clients[j].mask, type);
249
+ /* A match has been found, stop propagating */
255
+ return num_clients;
258
+static void GrailEvent(struct grail *grail, const struct input_event *ev)
260
+ InputInfoPtr pInfo = (InputInfoPtr)grail->priv;
261
+ EvdevProcessEvent(pInfo, (struct input_event *)ev);
264
+static void GrailGesture(struct grail *grail, const struct grail_event *ev)
266
+ InputInfoPtr pInfo = grail->priv;
267
+ EvdevPtr pEvdev = pInfo->private;
268
+ GestureEvent event;
269
+ float props[DIM_GRAIL_PROP];
270
+ int len = sizeof(GestureEvent) + ev->nprop * sizeof(grail_prop_t);
272
+ /* Client could have disappeared by now */
273
+ if (!clients[ev->client_id.client])
276
+ event.type = GenericEvent;
277
+ event.extension = GestureReqCode;
278
+ event.sequenceNumber = clients[ev->client_id.client]->sequence;
280
+ event.time = GetTimeInMillis();
281
+ event.length = (len - sizeof(xEvent)) / 4;
282
+ event.gesture_id = ev->id;
283
+ event.gesture_type = ev->type;
284
+ event.device_id = pInfo->dev->id;
285
+ event.root = ev->client_id.root;
286
+ event.event = ev->client_id.event;
287
+ event.child = ev->client_id.child;
288
+ event.status = ev->status;
289
+ event.num_props = ev->nprop;
291
+ /* Override event focus point if this is a relative device */
292
+ if (pEvdev->flags & (EVDEV_RELATIVE_EVENTS | EVDEV_TOUCHPAD))
294
+ DeviceIntPtr master = pInfo->dev->u.master;
296
+ /* If this mouse isn't hooked up to a cursor, don't do anything */
300
+ /* Note: Master device valuators are in screen coordinates */
301
+ event.focus_x = master->last.valuators[0];
302
+ event.focus_y = master->last.valuators[1];
304
+ event.focus_x = ev->pos.x;
305
+ event.focus_y = ev->pos.y;
308
+ memcpy(props, ev->prop, ev->nprop * sizeof(grail_prop_t));
310
+ WriteToClient(clients[ev->client_id.client], sizeof(GestureEvent), &event);
311
+ WriteToClient(clients[ev->client_id.client],
312
+ sizeof(float) * event.num_props, props);
316
+GrailOpen(InputInfoPtr pInfo)
318
+ EvdevPtr pEvdev = pInfo->private;
320
+ pEvdev->grail = malloc(sizeof(struct grail));
321
+ if (!pEvdev->grail) {
322
+ xf86Msg(X_ERROR, "evdev-grail: failed to allocate grail structure\n");
326
+ memset(pEvdev->grail, 0, sizeof(struct grail));
327
+ pEvdev->grail->get_clients = GetClients;
328
+ pEvdev->grail->event = GrailEvent;
329
+ pEvdev->grail->gesture = GrailGesture;
330
+ pEvdev->grail->priv = pInfo;
332
+ if (grail_open(pEvdev->grail, pInfo->fd)) {
334
+ "evdev-grail: failed to open grail, no gesture support\n");
335
+ free(pEvdev->grail);
336
+ pEvdev->grail = NULL;
341
+ struct grail_coord min;
342
+ struct grail_coord max;
344
+ min.x = screenInfo.screens[0]->x;
345
+ min.y = screenInfo.screens[0]->y;
346
+ max.x = min.x + screenInfo.screens[0]->width;
347
+ max.y = min.y + screenInfo.screens[0]->height;
349
+ grail_set_bbox(pEvdev->grail, &min, &max);
356
+GrailClose(InputInfoPtr pInfo)
358
+ EvdevPtr pEvdev = pInfo->private;
360
+ if (pEvdev->grail) {
361
+ grail_close(pEvdev->grail, pInfo->fd);
362
+ free(pEvdev->grail);
363
+ pEvdev->grail = NULL;
367
+++ b/src/evdev-grail.h
369
+#ifndef EVDEV_GRAIL_H_
370
+#define EVDEV_GRAIL_H_
374
+extern int GrailOpen(InputInfoPtr pInfo);
375
+extern void GrailClose(InputInfoPtr pInfo);
377
+#endif /* _EVDEV_GRAIL_H_ */
385
+#include "evdev-grail.h"
387
+#define GrailOpen(pInfo)
388
+#define GrailClose(pInfo)
391
#define ArrayLength(a) (sizeof(a) / (sizeof((a)[0])))
394
@@ -736,7 +743,7 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo
395
* Process the events from the device; nothing is actually posted to the server
396
* until an EV_SYN event is received.
400
EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
403
@@ -771,7 +778,12 @@ EvdevReadInput(InputInfoPtr pInfo)
405
while (len == sizeof(ev))
407
- len = read(pInfo->fd, &ev, sizeof(ev));
410
+ len = grail_pull(pEvdev->grail, pInfo->fd);
413
+ len = read(pInfo->fd, &ev, sizeof(ev));
416
if (errno == ENODEV) /* May happen after resume */
417
@@ -794,6 +806,11 @@ EvdevReadInput(InputInfoPtr pInfo)
426
/* The kernel promises that we always only read a complete
427
* event, so len != sizeof ev is an error. */
428
if (len % sizeof(ev[0])) {
429
@@ -1214,7 +1231,7 @@ EvdevAddAbsClass(DeviceIntPtr device)
430
memset(pEvdev->old_vals, -1, num_axes * sizeof(int));
431
atoms = xalloc(pEvdev->num_vals * sizeof(Atom));
433
- for (axis = ABS_X; axis <= ABS_MAX; axis++) {
434
+ for (axis = ABS_X; axis <= ABS_MISC; axis++) {
435
pEvdev->axis_map[axis] = -1;
436
if (!TestBit(axis, pEvdev->abs_bitmask))
438
@@ -1234,7 +1251,7 @@ EvdevAddAbsClass(DeviceIntPtr device)
439
GetMotionHistorySize(), Absolute))
442
- for (axis = ABS_X; axis <= ABS_MAX; axis++) {
443
+ for (axis = ABS_X; axis <= ABS_MISC; axis++) {
444
int axnum = pEvdev->axis_map[axis];
447
@@ -1611,7 +1628,6 @@ EvdevOn(DeviceIntPtr device)
453
EvdevProc(DeviceIntPtr device, int what)
455
@@ -1657,6 +1673,7 @@ EvdevProc(DeviceIntPtr device, int what)
460
EvdevRemoveDevice(pInfo);
463
@@ -1927,6 +1944,8 @@ EvdevProbe(InputInfoPtr pInfo)
464
xf86Msg(X_INFO, "%s: Found absolute axes\n", pInfo->name);
465
pEvdev->flags |= EVDEV_ABSOLUTE_EVENTS;
469
if ((TestBit(ABS_X, pEvdev->abs_bitmask) &&
470
TestBit(ABS_Y, pEvdev->abs_bitmask))) {
471
xf86Msg(X_INFO, "%s: Found x and y absolute axes\n", pInfo->name);
474
@@ -178,8 +178,14 @@ typedef struct {
475
/* Event queue used to defer keyboard/button events until EV_SYN time. */
477
EventQueueRec queue[EVDEV_MAXQUEUE];
480
+ struct grail *grail;
482
} EvdevRec, *EvdevPtr;
484
+void EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev);
486
/* Event posting functions */
487
void EvdevQueueKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value);
488
void EvdevQueueButtonEvent(InputInfoPtr pInfo, int button, int value);
490
+++ b/src/gestureproto.h
493
+ * Copyright © 2010 Canonical, Ltd.
495
+ * Permission is hereby granted, free of charge, to any person obtaining a
496
+ * copy of this software and associated documentation files (the "Software"),
497
+ * to deal in the Software without restriction, including without limitation
498
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
499
+ * and/or sell copies of the Software, and to permit persons to whom the
500
+ * Software is furnished to do so, subject to the following conditions:
502
+ * The above copyright notice and this permission notice (including the next
503
+ * paragraph) shall be included in all copies or substantial portions of the
506
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
507
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
508
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
509
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
510
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
511
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
512
+ * DEALINGS IN THE SOFTWARE.
514
+ * Authors: Chase Douglas <chase.douglas@canonical.com>
518
+#ifndef _GESTUREPROTO_H_
519
+#define _GESTUREPROTO_H_
524
+#define Window uint32_t
525
+#define Time uint32_t
527
+#define X_GestureQueryVersion 1
528
+#define X_GestureSelectEvents 2
529
+#define X_GestureGetSelectedEvents 3
531
+#define GESTUREREQUESTS (X_GestureGetSelectedEvents - X_GestureQueryVersion + 1)
533
+#define GestureAllDevices 0
536
+ * Used to select for events on a given window.
537
+ * Struct is followed by (mask_len * CARD8), with each bit set representing
538
+ * the event mask for the given type. A mask bit represents an event type if
539
+ * (mask == (1 << type)).
542
+ uint16_t device_id; /**< Device id to select for */
543
+ uint16_t mask_len; /**< Length of mask in 4 byte units */
547
+ uint8_t reqType; /**< Gesture extension major code */
548
+ uint8_t ReqType; /**< Always ::X_GestureQueryVersion */
549
+ uint16_t length; /**< Length in 4 byte units */
550
+ uint16_t major_version;
551
+ uint16_t minor_version;
552
+} GestureQueryVersionReq;
555
+ uint8_t repType; /**< ::X_Reply */
556
+ uint8_t RepType; /**< Always ::X_GestureQueryVersion */
557
+ uint16_t sequenceNumber;
559
+ uint16_t major_version;
560
+ uint16_t minor_version;
566
+} GestureQueryVersionReply;
569
+ uint8_t reqType; /**< Gesture extension major code */
570
+ uint8_t ReqType; /**< Always ::X_GestureSelectEvents */
571
+ uint16_t length; /**< Length in 4 byte units */
573
+ GestureEventMask mask;
574
+} GestureSelectEventsReq;
577
+ uint8_t reqType; /**< Gesture extension major code */
578
+ uint8_t ReqType; /**< Always ::X_GestureGetSelectedEvents */
579
+ uint16_t length; /**< Length in 4 byte units */
581
+} GestureGetSelectedEventsReq;
584
+ uint8_t repType; /**< Gesture extension major opcode */
585
+ uint8_t RepType; /**< Always ::X_GestureGetSelectedEvents */
586
+ uint16_t sequenceNumber;
588
+ uint16_t num_masks; /**< Number of GestureEventMask structs
589
+ trailing the reply */
596
+} GestureGetSelectedEventsReply;
600
+ uint8_t type; /**< Always GenericEvent */
601
+ uint8_t extension; /**< Gesture extension offset */
602
+ uint16_t sequenceNumber; /**< Xevent sequence number */
603
+ uint32_t length; /**< Length in 4 byte uints */
604
+ uint16_t evtype; /**< X generic event type */
605
+ uint16_t gesture_id; /**< Unique ID for gesture */
606
+ uint16_t gesture_type; /**< Gesture type (zoom, rotate, etc.) */
607
+ uint16_t device_id; /**< Device that generated this gesture */
608
+ Time time; /**< Time of gesture event */
609
+ Window root; /**< Root window event occurred on */
610
+ Window event; /**< Window selecting this event for a client */
611
+ Window child; /**< Top-most window of gesture event */
612
+/* └──────── 32 byte boundary ────────┘ */
613
+ float focus_x; /**< Always window coords, 16.16 fixed point */
614
+ float focus_y; /**< Relative to event window */
615
+ uint16_t status; /**< Gesture event status */
616
+ uint16_t num_props; /**< Number of properties for gesture event */
617
+/* └──── Gesture properties below ────┘ */
623
+#endif /* _GESTUREPROTO_H_ */