From 90b177e5cbb9047453af426d2abfe9c0514fe866 Mon Sep 17 00:00:00 2001 From: Thomas Jaeger Date: Sat, 13 Oct 2012 22:43:26 -0400 Subject: [PATCH 1/5] Update the MD's position when a touch event is received Signed-off-by: Thomas Jaeger Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- dix/getevents.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dix/getevents.c b/dix/getevents.c index 2a686e877..5c1e97ef4 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -1994,6 +1994,14 @@ GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid, if (emulate_pointer) storeLastValuators(dev, &mask, 0, 1, devx, devy); + /* Update the MD's co-ordinates, which are always in desktop space. */ + if (emulate_pointer && !IsMaster(dev) && !IsFloating(dev)) { + DeviceIntPtr master = GetMaster(dev, MASTER_POINTER); + + master->last.valuators[0] = screenx; + master->last.valuators[1] = screeny; + } + event->root = scr->root->drawable.id; event_set_root_coordinates(event, screenx, screeny); From cc79107a5b60d2926e16ddbee04149e8d5acc969 Mon Sep 17 00:00:00 2001 From: Thomas Jaeger Date: Sat, 13 Oct 2012 22:51:24 -0400 Subject: [PATCH 2/5] Don't use GetTouchEvents when replaying events GetTouchEvents has plenty of side effects such as moving the pointer or updating the master device, which we don't want to happen when replaying. The only reason for calling it was to generate a DCCE event, but GetTouchEvents doesn't even do that right (we might need a DCCE event even when replaying a master event, or clients could interpret valuator data incorrectly). This discussion is moot at the moment anyway, since DeliverTouchEvents doesn't appear to deliver DCCE events. Signed-off-by: Thomas Jaeger Reviewed-by: Peter Hutterer [Added call to processInputProc instead of direct call to DeliverTouchEvents] Signed-off-by: Peter Hutterer --- dix/touch.c | 61 ++++++++++++++++++++++--------------------------- include/input.h | 2 ++ 2 files changed, 29 insertions(+), 34 deletions(-) diff --git a/dix/touch.c b/dix/touch.c index 5f77be575..29ba17194 100644 --- a/dix/touch.c +++ b/dix/touch.c @@ -463,45 +463,14 @@ TouchEventHistoryPush(TouchPointInfoPtr ti, const DeviceEvent *ev) void TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource) { - InternalEvent *tel; - ValuatorMask *mask; - int i, nev; - int flags; + int i; if (!ti->history) return; - tel = InitEventList(GetMaximumEventsNum()); - mask = valuator_mask_new(0); + TouchDeliverDeviceClassesChangedEvent(ti, ti->history[0].time, resource); - valuator_mask_set_double(mask, 0, ti->history[0].valuators.data[0]); - valuator_mask_set_double(mask, 1, ti->history[0].valuators.data[1]); - - flags = TOUCH_CLIENT_ID | TOUCH_REPLAYING; - if (ti->emulate_pointer) - flags |= TOUCH_POINTER_EMULATED; - /* Generate events based on a fake touch begin event to get DCCE events if - * needed */ - /* FIXME: This needs to be cleaned up */ - nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchBegin, flags, mask); - for (i = 0; i < nev; i++) { - /* Send saved touch begin event */ - if (tel[i].any.type == ET_TouchBegin) { - DeviceEvent *ev = &ti->history[0]; - ev->flags |= TOUCH_REPLAYING; - DeliverTouchEvents(dev, ti, (InternalEvent*)ev, resource); - } - else {/* Send DCCE event */ - tel[i].any.time = ti->history[0].time; - DeliverTouchEvents(dev, ti, tel + i, resource); - } - } - - valuator_mask_free(&mask); - FreeEventList(tel, GetMaximumEventsNum()); - - /* First event was TouchBegin, already replayed that one */ - for (i = 1; i < ti->history_elements; i++) { + for (i = 0; i < ti->history_elements; i++) { DeviceEvent *ev = &ti->history[i]; ev->flags |= TOUCH_REPLAYING; @@ -509,6 +478,30 @@ TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource) } } +void +TouchDeliverDeviceClassesChangedEvent(TouchPointInfoPtr ti, Time time, + XID resource) +{ + DeviceIntPtr dev; + int num_events = 0; + InternalEvent dcce; + + dixLookupDevice(&dev, ti->sourceid, serverClient, DixWriteAccess); + + if (!dev) + return; + + /* UpdateFromMaster generates at most one event */ + UpdateFromMaster(&dcce, dev, DEVCHANGE_POINTER_EVENT, &num_events); + BUG_WARN(num_events > 1); + + if (num_events) { + dcce.any.time = time; + /* FIXME: This doesn't do anything */ + dev->public.processInputProc(&dcce, dev); + } +} + Bool TouchBuildDependentSpriteTrace(DeviceIntPtr dev, SpritePtr sprite) { diff --git a/include/input.h b/include/input.h index f8459b8c8..9522d00e9 100644 --- a/include/input.h +++ b/include/input.h @@ -580,6 +580,8 @@ extern int TouchListenerAcceptReject(DeviceIntPtr dev, TouchPointInfoPtr ti, extern int TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode, uint32_t touchid, Window grab_window, XID *error); extern void TouchEndPhysicallyActiveTouches(DeviceIntPtr dev); +extern void TouchDeliverDeviceClassesChangedEvent(TouchPointInfoPtr ti, + Time time, XID resource); /* misc event helpers */ extern Mask GetEventMask(DeviceIntPtr dev, xEvent *ev, InputClientsPtr clients); From fe59774c55e5d423633405e0869c22f4ce382548 Mon Sep 17 00:00:00 2001 From: Thomas Jaeger Date: Sat, 13 Oct 2012 23:08:27 -0400 Subject: [PATCH 3/5] Don't use GetTouchEvents in EmitTouchEnd As before GetTouchEvents causes unwanted side effects. Add a new function GetDixTouchEnd, which generates a touch event from the touch point. We fill in the event's screen coordinates from the MD's current sprite position. Signed-off-by: Thomas Jaeger Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- Xi/exevents.c | 18 ++++-------------- dix/getevents.c | 31 +++++++++++++++++++++++++++++++ include/input.h | 5 +++++ 3 files changed, 40 insertions(+), 14 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 4248b9a86..2caf98c25 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1066,24 +1066,14 @@ ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti) static void EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource) { - InternalEvent *tel = InitEventList(GetMaximumEventsNum()); - ValuatorMask *mask = valuator_mask_new(2); - int i, nev; - - valuator_mask_set_double(mask, 0, - valuator_mask_get_double(ti->valuators, 0)); - valuator_mask_set_double(mask, 1, - valuator_mask_get_double(ti->valuators, 1)); + InternalEvent event; flags |= TOUCH_CLIENT_ID; if (ti->emulate_pointer) flags |= TOUCH_POINTER_EMULATED; - nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd, flags, mask); - for (i = 0; i < nev; i++) - DeliverTouchEvents(dev, ti, tel + i, resource); - - valuator_mask_free(&mask); - FreeEventList(tel, GetMaximumEventsNum()); + TouchDeliverDeviceClassesChangedEvent(ti, GetTimeInMillis(), resource); + GetDixTouchEnd(&event, dev, ti, flags); + DeliverTouchEvents(dev, ti, &event, resource); } /** diff --git a/dix/getevents.c b/dix/getevents.c index 5c1e97ef4..39b0821f6 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -2022,6 +2022,37 @@ GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid, return num_events; } +void +GetDixTouchEnd(InternalEvent *ievent, DeviceIntPtr dev, TouchPointInfoPtr ti, + uint32_t flags) +{ + ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen; + DeviceEvent *event = &ievent->device_event; + CARD32 ms = GetTimeInMillis(); + + BUG_WARN(!dev->enabled); + + init_device_event(event, dev, ms); + + event->sourceid = ti->sourceid; + event->type = ET_TouchEnd; + + event->root = scr->root->drawable.id; + + /* Get screen event coordinates from the sprite. Is this really the best + * we can do? */ + event_set_root_coordinates(event, + dev->last.valuators[0], + dev->last.valuators[1]); + event->touchid = ti->client_id; + event->flags = flags; + + if (flags & TOUCH_POINTER_EMULATED) { + event->flags |= TOUCH_POINTER_EMULATED; + event->detail.button = 1; + } +} + /** * Synthesize a single motion event for the core pointer. * diff --git a/include/input.h b/include/input.h index 9522d00e9..2387dbf4a 100644 --- a/include/input.h +++ b/include/input.h @@ -465,6 +465,11 @@ extern int GetTouchOwnershipEvents(InternalEvent *events, TouchPointInfoPtr ti, uint8_t mode, XID resource, uint32_t flags); +extern void GetDixTouchEnd(InternalEvent *ievent, + DeviceIntPtr dev, + TouchPointInfoPtr ti, + uint32_t flags); + extern _X_EXPORT int GetProximityEvents(InternalEvent *events, DeviceIntPtr pDev, int type, const ValuatorMask *mask); From d0fd592fc7be1706084923f43fa057e50122562c Mon Sep 17 00:00:00 2001 From: Thomas Jaeger Date: Sat, 13 Oct 2012 23:18:50 -0400 Subject: [PATCH 4/5] Simplify GetTouchEvents With only one callee left, we are free to assume that !(flags & TOUCH_CLIENT_ID) Signed-off-by: Thomas Jaeger Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- dix/getevents.c | 66 +++++++++++++------------------------------------ 1 file changed, 17 insertions(+), 49 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index 39b0821f6..9fc8047bd 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -1833,10 +1833,7 @@ GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid, int i; int num_events = 0; RawDeviceEvent *raw; - union touch { - TouchPointInfoPtr dix_ti; - DDXTouchPointInfoPtr ti; - } touchpoint; + DDXTouchPointInfoPtr ti; int need_rawevent = TRUE; Bool emulate_pointer = FALSE; int client_id = 0; @@ -1855,37 +1852,15 @@ GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid, /* Find and/or create the DDX touch info */ - if (flags & TOUCH_CLIENT_ID) { /* A DIX-submitted TouchEnd */ - touchpoint.dix_ti = TouchFindByClientID(dev, ddx_touchid); - BUG_RETURN_VAL(!touchpoint.dix_ti, 0); - - if (!mask_in || - !valuator_mask_isset(mask_in, 0) || - !valuator_mask_isset(mask_in, 1)) { - ErrorF - ("[dix] dix-submitted events must have x/y valuator information.\n"); - return 0; - } - - need_rawevent = FALSE; - client_id = touchpoint.dix_ti->client_id; + ti = TouchFindByDDXID(dev, ddx_touchid, (type == XI_TouchBegin)); + if (!ti) { + ErrorFSigSafe("[dix] %s: unable to %s touch point %u\n", dev->name, + type == XI_TouchBegin ? "begin" : "find", ddx_touchid); + return 0; } - else { /* a DDX-submitted touch */ + client_id = ti->client_id; - touchpoint.ti = - TouchFindByDDXID(dev, ddx_touchid, (type == XI_TouchBegin)); - if (!touchpoint.ti) { - ErrorFSigSafe("[dix] %s: unable to %s touch point %u\n", dev->name, - type == XI_TouchBegin ? "begin" : "find", ddx_touchid); - return 0; - } - client_id = touchpoint.ti->client_id; - } - - if (!(flags & TOUCH_CLIENT_ID)) - emulate_pointer = touchpoint.ti->emulate_pointer; - else - emulate_pointer = ! !(flags & TOUCH_POINTER_EMULATED); + emulate_pointer = ti->emulate_pointer; if (!IsMaster(dev)) events = @@ -1905,11 +1880,6 @@ GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid, num_events++; init_device_event(event, dev, ms); - /* if submitted for master device, get the sourceid from there */ - if (flags & TOUCH_CLIENT_ID) { - event->sourceid = touchpoint.dix_ti->sourceid; - /* TOUCH_CLIENT_ID implies norawevent */ - } switch (type) { case XI_TouchBegin: @@ -1934,20 +1904,20 @@ GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid, event->type = ET_TouchEnd; /* We can end the DDX touch here, since we don't use the active * field below */ - if (!(flags & TOUCH_CLIENT_ID)) - TouchEndDDXTouch(dev, touchpoint.ti); + TouchEndDDXTouch(dev, ti); break; default: return 0; } - if (t->mode == XIDirectTouch && !(flags & TOUCH_CLIENT_ID)) { + + if (t->mode == XIDirectTouch) { if (!valuator_mask_isset(&mask, 0)) valuator_mask_set_double(&mask, 0, - valuator_mask_get_double(touchpoint.ti-> + valuator_mask_get_double(ti-> valuators, 0)); if (!valuator_mask_isset(&mask, 1)) valuator_mask_set_double(&mask, 1, - valuator_mask_get_double(touchpoint.ti-> + valuator_mask_get_double(ti-> valuators, 1)); } @@ -1957,13 +1927,11 @@ GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid, if (t->mode == XIDirectTouch) { transformAbsolute(dev, &mask); - if (!(flags & TOUCH_CLIENT_ID)) { - for (i = 0; i < valuator_mask_size(&mask); i++) { - double val; + for (i = 0; i < valuator_mask_size(&mask); i++) { + double val; - if (valuator_mask_fetch_double(&mask, i, &val)) - valuator_mask_set_double(touchpoint.ti->valuators, i, val); - } + if (valuator_mask_fetch_double(&mask, i, &val)) + valuator_mask_set_double(ti->valuators, i, val); } clipAbsolute(dev, &mask); From 3b9f1c701787965246638c1a6fd99fb2b6078114 Mon Sep 17 00:00:00 2001 From: Yuly Novikov Date: Mon, 19 Nov 2012 21:04:57 -0500 Subject: [PATCH 5/5] dix: Save touchpoint last coordinates before transform. #49347 DDXTouchPointInfoRec.valuators used to store axis values after transform. This resulted in Coordinate Transformation Matrix being applied multiple times to the last coordinates, in the case when only pressure changes in the last touch event. Changed DDXTouchPointInfoRec.valuators to store values before transform. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=49347 Signed-off-by: Yuly Novikov Reviewed-by: Peter Hutterer Signed-off-by: Peter Hutterer --- dix/getevents.c | 22 ++++++++-------------- include/inputstr.h | 2 +- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/dix/getevents.c b/dix/getevents.c index 9fc8047bd..fa538d9f4 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -1910,30 +1910,24 @@ GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid, return 0; } - if (t->mode == XIDirectTouch) { - if (!valuator_mask_isset(&mask, 0)) - valuator_mask_set_double(&mask, 0, - valuator_mask_get_double(ti-> - valuators, 0)); - if (!valuator_mask_isset(&mask, 1)) - valuator_mask_set_double(&mask, 1, - valuator_mask_get_double(ti-> - valuators, 1)); - } - /* Get our screen event co-ordinates (root_x/root_y/event_x/event_y): * these come from the touchpoint in Absolute mode, or the sprite in * Relative. */ if (t->mode == XIDirectTouch) { - transformAbsolute(dev, &mask); - - for (i = 0; i < valuator_mask_size(&mask); i++) { + for (i = 0; i < max(valuator_mask_size(&mask), 2); i++) { double val; if (valuator_mask_fetch_double(&mask, i, &val)) valuator_mask_set_double(ti->valuators, i, val); + /* If the device doesn't post new X and Y axis values, + * use the last values posted. + */ + else if (i < 2 && + valuator_mask_fetch_double(ti->valuators, i, &val)) + valuator_mask_set_double(&mask, i, val); } + transformAbsolute(dev, &mask); clipAbsolute(dev, &mask); } else { diff --git a/include/inputstr.h b/include/inputstr.h index 5a38924de..bb0a77963 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -331,7 +331,7 @@ typedef struct _DDXTouchPointInfo { uint32_t ddx_id; /* touch ID given by the DDX */ Bool emulate_pointer; - ValuatorMask *valuators; /* last recorded axis values */ + ValuatorMask *valuators; /* last axis values as posted, pre-transform */ } DDXTouchPointInfoRec; typedef struct _TouchClassRec {