#ifdef HAVE_XINPUT2_2
+/* Record a touch sequence with the identifier DETAIL from the given
+ FRAME on the specified DEVICE. Round X and Y and record them as
+ its current position. */
+
static void
xi_link_touch_point (struct xi_device_t *device,
int detail, double x, double y,
touchpoint = xmalloc (sizeof *touchpoint);
touchpoint->next = device->touchpoints;
- touchpoint->x = x;
- touchpoint->y = y;
+ touchpoint->x = lrint (x);
+ touchpoint->y = lrint (y);
touchpoint->number = detail;
touchpoint->frame = frame;
+ touchpoint->ownership = TOUCH_OWNERSHIP_NONE;
device->touchpoints = touchpoint;
}
-static bool
-xi_unlink_touch_point (int detail,
- struct xi_device_t *device)
+/* Free and remove the touch sequence with the identifier DETAIL.
+ DEVICE is the device in which the touch sequence should be
+ recorded.
+
+ Value is 0 if no touch sequence by that identifier exists inside
+ DEVICE, 1 if a touch sequence has been found but is not owned by
+ Emacs, and 2 otherwise. */
+
+static int
+xi_unlink_touch_point (int detail, struct xi_device_t *device)
{
struct xi_touch_point_t *last, *tem;
+ enum xi_touch_ownership ownership;
for (last = NULL, tem = device->touchpoints; tem;
last = tem, tem = tem->next)
else
last->next = tem->next;
+ ownership = tem->ownership;
xfree (tem);
- return true;
+
+ if (ownership == TOUCH_OWNERSHIP_SELF)
+ return 2;
+
+ return 1;
}
}
- return false;
+ return 0;
}
/* Unlink all touch points associated with the frame F.
}
}
+/* Return the data associated with a touch sequence DETAIL recorded by
+ `xi_link_touch_point' from DEVICE, or NULL if it can't be
+ found. */
+
static struct xi_touch_point_t *
xi_find_touch_point (struct xi_device_t *device, int detail)
{
goto XI_OTHER;
}
+ case XI_TouchOwnership:
+ {
+ struct xi_device_t *device;
+ struct xi_touch_point_t *touchpoint;
+ XITouchOwnershipEvent *event;
+
+ /* All grabbing clients have decided to reject ownership
+ of this touch sequence. */
+
+ event = (XITouchOwnershipEvent *) xi_event;
+ device = xi_device_from_id (dpyinfo, event->deviceid);
+
+ if (!device || device->use == XIMasterPointer)
+ goto XI_OTHER;
+
+ touchpoint = xi_find_touch_point (device, event->touchid);
+
+ if (!touchpoint)
+ goto XI_OTHER;
+
+ /* As a result, Emacs should complete whatever editing
+ operations result from this touch sequence. */
+ touchpoint->ownership = TOUCH_OWNERSHIP_SELF;
+ }
+
case XI_TouchUpdate:
{
struct xi_device_t *device, *source;
struct xi_touch_point_t *touchpoint;
Lisp_Object arg = Qnil;
+ /* If flags & TouchPendingEnd, the touch sequence has
+ already ended, but some grabbing clients remain
+ undecided as to whether they will obtain ownership of
+ the touch sequence.
+
+ Wait for them to make their decision, resulting in
+ TouchOwnership and TouchEnd events being sent. */
+
+ if (xev->flags & XITouchPendingEnd)
+ goto XI_OTHER;
+
device = xi_device_from_id (dpyinfo, xev->deviceid);
source = xi_device_from_id (dpyinfo, xev->sourceid);
x_display_set_last_user_time (dpyinfo, xev->time,
detached, and master pointers may also represent
dependent touch devices. */
- if (!device)
+ if (!device || device->use == XIMasterPointer)
goto XI_OTHER;
touchpoint = xi_find_touch_point (device, xev->detail);
if (!touchpoint
/* Don't send this event if nothing has changed
either. */
- || (touchpoint->x == (int) xev->event_x
- && touchpoint->y == (int) xev->event_y))
+ || (touchpoint->x == lrint (xev->event_x)
+ && touchpoint->y == lrint (xev->event_y)))
goto XI_OTHER;
- touchpoint->x = xev->event_x;
- touchpoint->y = xev->event_y;
+ touchpoint->x = lrint (xev->event_x);
+ touchpoint->y = lrint (xev->event_y);
f = x_window_to_frame (dpyinfo, xev->event);
touchpoint; touchpoint = touchpoint->next)
{
if (touchpoint->frame == f)
- arg = Fcons (list3i (lrint (touchpoint->x),
- lrint (touchpoint->y),
+ arg = Fcons (list3i (touchpoint->x, touchpoint->y,
lrint (touchpoint->number)),
arg);
}
case XI_TouchEnd:
{
struct xi_device_t *device, *source;
- bool unlinked_p;
+ int state;
device = xi_device_from_id (dpyinfo, xev->deviceid);
source = xi_device_from_id (dpyinfo, xev->sourceid);
if (!device || device->use == XIMasterPointer)
goto XI_OTHER;
- unlinked_p = xi_unlink_touch_point (xev->detail, device);
+ state = xi_unlink_touch_point (xev->detail, device);
- if (unlinked_p)
+ if (state)
{
f = x_window_to_frame (dpyinfo, xev->event);
{
inev.ie.kind = TOUCHSCREEN_END_EVENT;
inev.ie.timestamp = xev->time;
+ inev.ie.modifiers = state != 2;
XSETFRAME (inev.ie.frame_or_window, f);
XSETINT (inev.ie.x, lrint (xev->event_x));
#ifdef HAVE_XINPUT2_2
+/* Enum describing the ownership of a touch point.
+
+ The input extension allows other clients to intercept touch
+ sequences destined for a client window through passively grabbing
+ for touch events on a parent window.
+
+ When a passive touch grab for an XI_TouchBegin event activates, one
+ grabbing client is designated the ``owner'' of the touch sequence
+ started by the grabbed event. Touch events are then delivered to
+ both the grabbing client and other clients that have selected for
+ touch events on the subwindow.
+
+ The X server will not deliver TouchEnd events to clients other than
+ the owner until one grabbing client decides to take over processing
+ the touch event sequence, or no more grabbing clients remain.
+ Instead, a TouchUpdate event with the TouchPendingEnd flag is sent,
+ and the TouchEnd event is postponed until the decision is made and
+ all XI_TouchOwnership events are sent.
+
+ If the owner decides to take over processing the touch sequence, an
+ XI_TouchEnd event is delivered to all other clients receiving
+ events for the current touch sequence, who are then expected to
+ cancel or undo any actions which have taken place in reaction to
+ events from that sequence.
+
+ If the owner decides to relinquish ownership over the touch
+ sequence, the X server looks for another grabbing client, and
+ transfers touch ownership to that client instead. Nothing changes
+ from the perspective of clients who have merely selected for events
+ from the subwindow, while an XI_TouchEnd event is delivered to the
+ old owner, and an XI_TouchOwnership event is delivered to the new
+ owner.
+
+ If all grabbing clients reject ownership over the touch sequence,
+ the X server delivers an XI_TouchOwnership event to the client that
+ has selected for touch events on the subwindow, the only client
+ that will receive events for this touch sequence from this time
+ forward. */
+
+enum xi_touch_ownership
+ {
+ /* Emacs doesn't own this touch sequence. */
+ TOUCH_OWNERSHIP_NONE,
+
+ /* Emacs owns this touch sequence. */
+ TOUCH_OWNERSHIP_SELF,
+ };
+
struct xi_touch_point_t
{
- /* The next touch point in this list. */
- struct xi_touch_point_t *next;
-
/* The touchpoint detail. */
int number;
- /* The last known X and Y position of the touchpoint. */
- double x, y;
+ /* Whether or not Emacs has ``exclusive'' access to this touch
+ point. */
+ enum xi_touch_ownership ownership;
+
+ /* The last known rounded X and Y positions of the touchpoint. */
+ int x, y;
/* The frame associated with this touch point. */
struct frame *frame;
+
+ /* The next touch point in this list. */
+ struct xi_touch_point_t *next;
};
#endif