From a47080a4565c95ec45a369385fd50683cbc6fa57 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Jun 06 2013 00:23:00 +0000 Subject: Backport the touch grab race condition patches from fdo #56578 --- diff --git a/0001-dix-plug-memory-leak-in-freeing-TouchClass.patch b/0001-dix-plug-memory-leak-in-freeing-TouchClass.patch new file mode 100644 index 0000000..e3900a3 --- /dev/null +++ b/0001-dix-plug-memory-leak-in-freeing-TouchClass.patch @@ -0,0 +1,31 @@ +From bf115aa906795df872104083c1187c126c3b1d76 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 17 Apr 2013 19:47:42 +1000 +Subject: [PATCH 01/35] dix: plug memory leak in freeing TouchClass + +==15562== 1,800 bytes in 1 blocks are definitely lost in loss record 298 of 330 +==15562== at 0x4A06B6F: calloc (vg_replace_malloc.c:593) +==15562== by 0x4312C7: InitTouchClassDeviceStruct (devices.c:1644) + +Signed-off-by: Peter Hutterer +Reviewed-by: Alan Coopersmith +(cherry picked from commit 7d722796c678532e8c5897c673c43184da353f44) +--- + dix/devices.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/dix/devices.c b/dix/devices.c +index be236dd..85961a0 100644 +--- a/dix/devices.c ++++ b/dix/devices.c +@@ -795,6 +795,7 @@ FreeDeviceClass(int type, pointer *class) + free((*t)->touches[i].valuators); + } + ++ free((*t)->touches); + free((*t)); + break; + } +-- +1.8.2.1 + diff --git a/0002-dix-don-t-overwrite-proximity-focus-classes.patch b/0002-dix-don-t-overwrite-proximity-focus-classes.patch new file mode 100644 index 0000000..5b311c8 --- /dev/null +++ b/0002-dix-don-t-overwrite-proximity-focus-classes.patch @@ -0,0 +1,51 @@ +From 8cc686735296f1ff32089e64f78dfee46b8e7149 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Thu, 9 May 2013 14:30:49 +1000 +Subject: [PATCH 02/35] dix: don't overwrite proximity/focus classes + +InitPointerClassDeviceStruct/InitKeyboardDeviceStruct allocate a +proximity/focus class, respectively. If a driver calls +InitFocusClassDeviceStruct or InitProximityClassDeviceStruct beforehand, +the previously allocated class is overwritten, leaking the memory. + +Neither takes a parameter other than the device, so we can simply skip +initialising it if we already have one. + +Signed-off-by: Peter Hutterer +Reviewed-by: Dave Airlie +(cherry picked from commit 8a88b0ab52ba375ae84463a90503db88af10e368) +--- + dix/devices.c | 2 +- + xkb/xkbInit.c | 3 ++- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/dix/devices.c b/dix/devices.c +index 85961a0..b2db4aa 100644 +--- a/dix/devices.c ++++ b/dix/devices.c +@@ -1366,7 +1366,7 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels, + valc->numMotionEvents = numMotionEvents; + valc->motionHintWindow = NullWindow; + +- if (mode & OutOfProximity) ++ if ((mode & OutOfProximity) && !dev->proximity) + InitProximityClassDeviceStruct(dev); + + dev->valuator = valc; +diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c +index 4e8e267..ed01114 100644 +--- a/xkb/xkbInit.c ++++ b/xkb/xkbInit.c +@@ -574,7 +574,8 @@ InitKeyboardDeviceStruct(DeviceIntPtr dev, XkbRMLVOSet * rmlvo, + XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &changes, + &check, &cause); + +- InitFocusClassDeviceStruct(dev); ++ if (!dev->focus) ++ InitFocusClassDeviceStruct(dev); + + xkbi->kbdProc = ctrl_func; + dev->kbdfeed->BellProc = bell_func; +-- +1.8.2.1 + diff --git a/0003-os-Reset-input-buffer-s-ignoreBytes-field.patch b/0003-os-Reset-input-buffer-s-ignoreBytes-field.patch new file mode 100644 index 0000000..da2fa36 --- /dev/null +++ b/0003-os-Reset-input-buffer-s-ignoreBytes-field.patch @@ -0,0 +1,42 @@ +From 57f6dbb3032b934a39c15cd1980b345f477ce1e6 Mon Sep 17 00:00:00 2001 +From: Robert Morell +Date: Thu, 9 May 2013 13:09:02 -0700 +Subject: [PATCH 03/35] os: Reset input buffer's 'ignoreBytes' field + +If a client sends a request larger than maxBigRequestSize, the server is +supposed to ignore it. + +Before commit cf88363d, the server would simply disconnect the client. After +that commit, it attempts to gracefully ignore the request by remembering how +long the client specified the request to be, and ignoring that many bytes. +However, if a client sends a BigReq header with a large size and disconnects +before actually sending the rest of the specified request, the server will +reuse the ConnectionInput buffer without resetting the ignoreBytes field. This +makes the server ignore new X clients' requests. + +This fixes that behavior by resetting the ignoreBytes field when putting the +ConnectionInput buffer back on the FreeInputs list. + +Signed-off-by: Robert Morell +Reviewed-by: Peter Hutterer +Signed-off-by: Peter Hutterer +(cherry picked from commit 67c66606c760c263d7a4c2d1bba43ed6225a4e7c) +--- + os/io.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/os/io.c b/os/io.c +index 2f091c4..0d980ab 100644 +--- a/os/io.c ++++ b/os/io.c +@@ -1063,6 +1063,7 @@ FreeOsBuffers(OsCommPtr oc) + oci->bufptr = oci->buffer; + oci->bufcnt = 0; + oci->lenLastReq = 0; ++ oci->ignoreBytes = 0; + } + } + if ((oco = oc->output)) { +-- +1.8.2.1 + diff --git a/0004-dix-pre-scale-x-by-the-screen-device-resolution-rati.patch b/0004-dix-pre-scale-x-by-the-screen-device-resolution-rati.patch new file mode 100644 index 0000000..52eff32 --- /dev/null +++ b/0004-dix-pre-scale-x-by-the-screen-device-resolution-rati.patch @@ -0,0 +1,103 @@ +From 14d89b9a466b521b985bc95fc4994637367362a8 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Sat, 9 Mar 2013 20:43:51 +1000 +Subject: [PATCH 04/35] dix: pre-scale x by the screen:device:resolution ratio + +commit 61a99aff9d33728a0b67920254d2d4d79f80cf39 + dix: pre-scale relative events from abs devices to desktop ratio (#31636) + +added pre-scaling of relative coordinates coming from absolute devices to +undo uneven scaling based on the screen dimensions. + +Devices have their own device width/height ratio as well (in a specific +resolution) and this must be applied for relative devices as well to avoid +scaling of the relative events into the device's ratio. + +e.g. a Wacom Intuos4 6x9 is in 16:10 format with equal horiz/vert +resolution (dpi). A movement by 1000/1000 coordinates is a perfect diagonal +on the tablet and must be reflected as such on the screen. + +However, we map the relative device-coordinate events to absolute screen +coordinates based on the axis ranges. This results in an effective scaling +of 1000/(1000 * 1.6) and thus an uneven x/y axis movement - the y +axis is always faster. + +So we need to pre-scale not only by the desktop dimenstions but also by the +device width/height ratio _and_ the resolution ratio. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 5cc2c96f824dbb28b9f8da61efc41596f8bd0561) +--- + dix/getevents.c | 46 ++++++++++++++++++++++++++++------------------ + 1 file changed, 28 insertions(+), 18 deletions(-) + +diff --git a/dix/getevents.c b/dix/getevents.c +index 241c7ec..ac0ccb2 100644 +--- a/dix/getevents.c ++++ b/dix/getevents.c +@@ -770,6 +770,29 @@ add_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, doubl + } + + ++static void ++scale_for_device_resolution(DeviceIntPtr dev, ValuatorMask *mask) ++{ ++ double x; ++ ValuatorClassPtr v = dev->valuator; ++ int xrange = v->axes[0].max_value - v->axes[0].min_value + 1; ++ int yrange = v->axes[1].max_value - v->axes[1].min_value + 1; ++ ++ double screen_ratio = 1.0 * screenInfo.width/screenInfo.height; ++ double device_ratio = 1.0 * xrange/yrange; ++ double resolution_ratio = 1.0; ++ double ratio; ++ ++ if (!valuator_mask_fetch_double(mask, 0, &x)) ++ return; ++ ++ if (v->axes[0].resolution != 0 && v->axes[1].resolution != 0) ++ resolution_ratio = 1.0 * v->axes[0].resolution/v->axes[1].resolution; ++ ++ ratio = device_ratio/resolution_ratio/screen_ratio; ++ valuator_mask_set_double(mask, 0, x * ratio); ++} ++ + /** + * Move the device's pointer by the values given in @valuators. + * +@@ -781,27 +804,14 @@ moveRelative(DeviceIntPtr dev, int flags, ValuatorMask *mask) + { + int i; + Bool clip_xy = IsMaster(dev) || !IsFloating(dev); ++ ValuatorClassPtr v = dev->valuator; + + /* for abs devices in relative mode, we've just scaled wrong, since we + mapped the device's shape into the screen shape. Undo this. */ +- if ((flags & POINTER_ABSOLUTE) == 0 && dev->valuator && +- dev->valuator->axes[0].min_value < dev->valuator->axes[0].max_value) { +- +- double ratio = 1.0 * screenInfo.width/screenInfo.height; +- +- if (ratio > 1.0) { +- double y; +- if (valuator_mask_fetch_double(mask, 1, &y)) { +- y *= ratio; +- valuator_mask_set_double(mask, 1, y); +- } +- } else { +- double x; +- if (valuator_mask_fetch_double(mask, 0, &x)) { +- x *= ratio; +- valuator_mask_set_double(mask, 0, x); +- } +- } ++ if ((flags & POINTER_ABSOLUTE) == 0 && v && v->numAxes > 1 && ++ v->axes[0].min_value < v->axes[0].max_value && ++ v->axes[1].min_value < v->axes[1].max_value) { ++ scale_for_device_resolution(dev, mask); + } + + /* calc other axes, clip, drop back into valuators */ +-- +1.8.2.1 + diff --git a/0005-dix-fix-device-scaling-to-use-a-min-max-range.patch b/0005-dix-fix-device-scaling-to-use-a-min-max-range.patch new file mode 100644 index 0000000..6781784 --- /dev/null +++ b/0005-dix-fix-device-scaling-to-use-a-min-max-range.patch @@ -0,0 +1,86 @@ +From 31e066546fd085725cc29e95867a04c70ce46ebc Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 26 Apr 2013 15:10:08 +1000 +Subject: [PATCH 05/35] dix: fix device scaling to use a [min,max[ range. + +defmin/defmax are screen coords and thus use a min-inclusive, max-exclusive +range. device axes ranges are inclusive, so bump the max up by one to get the +scaling right. + +This fixes off-by-one coordinate errors if the coordinate matrix is used to +bind the device to a fraction of the screen. It introduces an off-by-one +scaling error in the device coordinate range, but since most devices have a +higher resolution than the screen (e.g. a Wacom I4 has 5080 dpi) the effect +of this should be limited. + +This error manifests when we have numScreens > 1, as the scaling from +desktop size back to screen size drops one device unit. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 756ab88d93542f0589c9bf46f40ccc57df64f0fd) +--- + dix/devices.c | 4 ++-- + dix/getevents.c | 14 ++++++++++---- + 2 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/dix/devices.c b/dix/devices.c +index b2db4aa..a0d545a 100644 +--- a/dix/devices.c ++++ b/dix/devices.c +@@ -112,8 +112,8 @@ DeviceSetTransform(DeviceIntPtr dev, float *transform_data) + * Transform is the user supplied (affine) transform + * InvScale scales coordinates back up into their native range + */ +- sx = dev->valuator->axes[0].max_value - dev->valuator->axes[0].min_value; +- sy = dev->valuator->axes[1].max_value - dev->valuator->axes[1].min_value; ++ sx = dev->valuator->axes[0].max_value - dev->valuator->axes[0].min_value + 1; ++ sy = dev->valuator->axes[1].max_value - dev->valuator->axes[1].min_value + 1; + + /* invscale */ + pixman_f_transform_init_scale(&scale, sx, sy); +diff --git a/dix/getevents.c b/dix/getevents.c +index ac0ccb2..51d4fd4 100644 +--- a/dix/getevents.c ++++ b/dix/getevents.c +@@ -298,11 +298,11 @@ rescaleValuatorAxis(double coord, AxisInfoPtr from, AxisInfoPtr to, + + if (from && from->min_value < from->max_value) { + fmin = from->min_value; +- fmax = from->max_value; ++ fmax = from->max_value + 1; + } + if (to && to->min_value < to->max_value) { + tmin = to->min_value; +- tmax = to->max_value; ++ tmax = to->max_value + 1; + } + + if (fmin == tmin && fmax == tmax) +@@ -924,9 +924,9 @@ scale_to_desktop(DeviceIntPtr dev, ValuatorMask *mask, + + /* scale x&y to desktop coordinates */ + *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL, +- screenInfo.x, screenInfo.width - 1); ++ screenInfo.x, screenInfo.width); + *screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL, +- screenInfo.y, screenInfo.height - 1); ++ screenInfo.y, screenInfo.height); + + *devx = x; + *devy = y; +@@ -1366,6 +1366,12 @@ QueuePointerEvents(DeviceIntPtr device, int type, + * is the last coordinate on the first screen and must be rescaled for the + * event to be m. XI2 clients that do their own coordinate mapping would + * otherwise interpret the position of the device elsewere to the cursor. ++ * However, this scaling leads to losses: ++ * if we have two ScreenRecs we scale from e.g. [0..44704] (Wacom I4) to ++ * [0..2048[. that gives us 2047.954 as desktop coord, or the per-screen ++ * coordinate 1023.954. Scaling that back into the device coordinate range ++ * gives us 44703. So off by one device unit. It's a bug, but we'll have to ++ * live with it because with all this scaling, we just cannot win. + * + * @return the number of events written into events. + */ +-- +1.8.2.1 + diff --git a/0006-Xi-not-having-an-ownership-mask-does-not-mean-automa.patch b/0006-Xi-not-having-an-ownership-mask-does-not-mean-automa.patch new file mode 100644 index 0000000..e3e935d --- /dev/null +++ b/0006-Xi-not-having-an-ownership-mask-does-not-mean-automa.patch @@ -0,0 +1,33 @@ +From ba530e45120648d01917043125265b20b7f42c20 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 13 Feb 2013 10:49:23 +1000 +Subject: [PATCH 06/35] Xi: not having an ownership mask does not mean + automatic acceptance + +If we only have a single touch-grabbing client, setting the client as owner +would clean up the touch once the TouchEnd was processed. If the client then +calls XIAllowTouches() it will receive a BadValue for the touch ID (since +the internal record is already cleaned up). + +Signed-off-by: Peter Hutterer +(cherry picked from commit 9cc45c18ad1511adf3fb163dd4cefbef106edb23) +--- + Xi/exevents.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index d39cf89..d9122c9 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1865,7 +1865,7 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, + if (has_ownershipmask) + TouchSendOwnershipEvent(dev, ti, 0, listener->listener); + +- if (!has_ownershipmask || listener->type == LISTENER_REGULAR) ++ if (listener->type == LISTENER_REGULAR) + state = LISTENER_HAS_ACCEPTED; + else + state = LISTENER_IS_OWNER; +-- +1.8.2.1 + diff --git a/0007-dix-don-t-prepend-an-activated-passive-grab-to-the-l.patch b/0007-dix-don-t-prepend-an-activated-passive-grab-to-the-l.patch new file mode 100644 index 0000000..243333b --- /dev/null +++ b/0007-dix-don-t-prepend-an-activated-passive-grab-to-the-l.patch @@ -0,0 +1,33 @@ +From ef9ad64cfdee85ff7e3e47cb49fc7c3c1b2b2ccc Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 13 Feb 2013 11:26:11 +1000 +Subject: [PATCH 07/35] dix: don't prepend an activated passive grab to the + listeners + +If the device is currently grabbed as the result of a passive grab +activating, do not prepend that grab to the listeners (unlike active grabs). +Otherwise, a client with a passive pointer grab will prevent touch grabs +from activating higher up in the window stack. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 363b6387da6e669099a2da3861c73a29808295a6) +--- + dix/touch.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/dix/touch.c b/dix/touch.c +index 3027bbb..5d6e2a7 100644 +--- a/dix/touch.c ++++ b/dix/touch.c +@@ -874,7 +874,7 @@ TouchSetupListeners(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev) + SpritePtr sprite = &ti->sprite; + WindowPtr win; + +- if (dev->deviceGrab.grab) ++ if (dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab) + TouchAddActiveGrabListener(dev, ti, ev, dev->deviceGrab.grab); + + /* We set up an active touch listener for existing touches, but not any +-- +1.8.2.1 + diff --git a/0008-Xi-if-we-delivered-a-TouchEnd-to-a-passive-grab-end-.patch b/0008-Xi-if-we-delivered-a-TouchEnd-to-a-passive-grab-end-.patch new file mode 100644 index 0000000..d153282 --- /dev/null +++ b/0008-Xi-if-we-delivered-a-TouchEnd-to-a-passive-grab-end-.patch @@ -0,0 +1,46 @@ +From 67f4d682336aa3af2e03be528f4a373499dd8353 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Mon, 25 Feb 2013 11:21:07 +1000 +Subject: [PATCH 08/35] Xi: if we delivered a TouchEnd to a passive grab, end + it + +ef64b5ee97099618cf2e2cbbd3e471095695ae24 (which introduced the +TOUCH_CLIENT_ID check) has a wrong assumption that generated touch events +(TOUCH_CLIENT_ID) should not terminate passive grabs. +This is untrue, a TouchEnd may be generated in response to a TouchReject +higher up. If we _deliver_ an event to a client, terminate the passive grab. + +This requires us to count the actually delivered events too (first hunk). + +Signed-off-by: Peter Hutterer +(cherry picked from commit 81554d274f04951c55ea7f2e38d0455e2025e08d) +--- + Xi/exevents.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index d9122c9..a6a08b5 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1415,7 +1415,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, + } + + if (!deliveries) +- DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype); ++ deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype); + + /* We must accept the touch sequence once a pointer listener has + * received one event past ButtonPress. */ +@@ -1423,8 +1423,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, + !(ev->device_event.flags & TOUCH_CLIENT_ID)) + TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); + +- if (ev->any.type == ET_TouchEnd && +- !(ev->device_event.flags & TOUCH_CLIENT_ID) && ++ if (deliveries && ev->any.type == ET_TouchEnd && + !dev->button->buttonsDown && + dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) { + (*dev->deviceGrab.DeactivateGrab) (dev); +-- +1.8.2.1 + diff --git a/0009-Xi-update-the-core-listener-state-if-we-delivered-th.patch b/0009-Xi-update-the-core-listener-state-if-we-delivered-th.patch new file mode 100644 index 0000000..68a14e9 --- /dev/null +++ b/0009-Xi-update-the-core-listener-state-if-we-delivered-th.patch @@ -0,0 +1,59 @@ +From 4d123332764eeaaa522b3171cf5077db5fdacc93 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Thu, 28 Feb 2013 13:08:27 +1000 +Subject: [PATCH 09/35] Xi: update the core listener state if we delivered the + touch event + +If a TouchBegin is sent to a core client, that client is now the owner. + +By the time the TouchEnd is being processed, the client cannot replay +anymore, so we can assume that this is the final touch end and we can clean +up the touch record. + +Note: DeliverTouchEmulatedEvent is called for all listeners and immediately +bails out if the client is not the owner and thus shouldn't yet get the +event. Thus, check the return code. + +Signed-off-by: Peter Hutterer +(cherry picked from commit d08bae297f9d7651edb1923d6b0d6b14b3d674fc) +--- + Xi/exevents.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index a6a08b5..99bc595 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1847,6 +1847,8 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, + listener->type == LISTENER_POINTER_GRAB) { + rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, + grab, xi2mask); ++ if (rc == Success) ++ listener->state = LISTENER_IS_OWNER; + goto out; + } + +@@ -1887,13 +1889,13 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev, + rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, + grab, xi2mask); + +- if (ti->num_listeners > 1) { +- ev->any.type = ET_TouchUpdate; +- ev->device_event.flags |= TOUCH_PENDING_END; +- if (!(ev->device_event.flags & TOUCH_CLIENT_ID)) +- ti->pending_finish = TRUE; +- } +- ++ /* Once we send a TouchEnd to a legacy listener, we're already well ++ * past the accepting/rejecting stage (can only happen on ++ * GrabModeSync + replay. This listener now gets the end event, ++ * and we can continue. ++ */ ++ if (rc == Success) ++ listener->state = LISTENER_HAS_END; + goto out; + } + +-- +1.8.2.1 + diff --git a/0010-Xi-fix-lookup-in-ActivateEarlyAccept.patch b/0010-Xi-fix-lookup-in-ActivateEarlyAccept.patch new file mode 100644 index 0000000..41c63f9 --- /dev/null +++ b/0010-Xi-fix-lookup-in-ActivateEarlyAccept.patch @@ -0,0 +1,47 @@ +From a2a10e9ad51fe2b24024a49db1fb6ef1272c4bec Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Thu, 28 Feb 2013 13:04:36 +1000 +Subject: [PATCH 10/35] Xi: fix lookup in ActivateEarlyAccept + +ActivateEarlyAccept() can only be called from a grabbing client, so we can +ignore the rest. And it's easy enough to get the client from that since +9ad0fdb135a1c336771aee1f6eab75a6ad874aff. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 8b0d21044956f3810199d5e2f38ce33069e97be7) +--- + Xi/exevents.c | 15 +++++++-------- + 1 file changed, 7 insertions(+), 8 deletions(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index 99bc595..f3fd697 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1039,17 +1039,16 @@ ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti) + int rc; + ClientPtr client; + XID error; ++ GrabPtr grab = ti->listeners[0].grab; + +- rc = dixLookupClient(&client, ti->listeners[0].listener, serverClient, +- DixSendAccess); +- if (rc != Success) { +- ErrorF("[Xi] Failed to lookup early accepting client.\n"); +- return; +- } ++ BUG_RETURN(ti->listeners[0].type != LISTENER_GRAB && ++ ti->listeners[0].type != LISTENER_POINTER_GRAB); ++ BUG_RETURN(!grab); ++ ++ client = rClient(grab); + + if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id, +- ti->listeners[0].window->drawable.id, &error) != +- Success) ++ ti->listeners[0].window->drawable.id, &error) != Success) + ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n"); + } + +-- +1.8.2.1 + diff --git a/0011-Xi-if-a-passive-async-grab-is-activated-from-an-emul.patch b/0011-Xi-if-a-passive-async-grab-is-activated-from-an-emul.patch new file mode 100644 index 0000000..49bb427 --- /dev/null +++ b/0011-Xi-if-a-passive-async-grab-is-activated-from-an-emul.patch @@ -0,0 +1,38 @@ +From 6c9e0b84996a13aafd01cccdb63d0d3949d15851 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Thu, 28 Feb 2013 15:28:46 +1000 +Subject: [PATCH 11/35] Xi: if a passive async grab is activated from an + emulated touch, accept + +Async grabs cannot replay events, they cannot reject, so we can do an early +accept here. + +Signed-off-by: Peter Hutterer +(cherry picked from commit d905348134c80f19793eefb761731b00559ddf3a) +--- + Xi/exevents.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index f3fd697..21acf79 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1846,8 +1846,14 @@ DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, + listener->type == LISTENER_POINTER_GRAB) { + rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, + grab, xi2mask); +- if (rc == Success) ++ if (rc == Success) { + listener->state = LISTENER_IS_OWNER; ++ /* async grabs cannot replay, so automatically accept this touch */ ++ if (dev->deviceGrab.grab && ++ dev->deviceGrab.fromPassiveGrab && ++ dev->deviceGrab.grab->pointerMode == GrabModeAsync) ++ ActivateEarlyAccept(dev, ti); ++ } + goto out; + } + +-- +1.8.2.1 + diff --git a/0012-Xi-return-Success-from-DeliverTouchEmulatedEvent-if-.patch b/0012-Xi-return-Success-from-DeliverTouchEmulatedEvent-if-.patch new file mode 100644 index 0000000..d71b7ee --- /dev/null +++ b/0012-Xi-return-Success-from-DeliverTouchEmulatedEvent-if-.patch @@ -0,0 +1,50 @@ +From 5f7c3b1e50fb321d4c4489fad38a544419b1c21f Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 1 Mar 2013 08:43:58 +1000 +Subject: [PATCH 12/35] Xi: return !Success from DeliverTouchEmulatedEvent if + we didn't deliver + +All callers currently ignore the new value, so this patch has no effect. +Inverse call graph: + +DeliverTouchEmulatedEvent + DeliverEmulatedMotionEvent Ignores value + DeliverTouchBeginEvent + DeliverTouchEvent + DeliverTouchEvents Ignores value + DeliverTouchEndEvent + DeliverTouchEvent + DeliverTouchEvents Ignores value + +Signed-off-by: Peter Hutterer +Reviewed-by: Keith Packard +(cherry picked from commit 9978b57b8d94f061d72a67b99a02b0ba16a11429) +--- + Xi/exevents.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index 21acf79..2d531c7 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1382,7 +1382,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, + + /* We don't deliver pointer events to non-owners */ + if (!TouchResourceIsOwner(ti, listener->listener)) +- return Success; ++ return !Success; + + nevents = TouchConvertToPointerEvent(ev, &motion, &button); + BUG_RETURN_VAL(nevents == 0, BadValue); +@@ -1404,7 +1404,7 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, + /* 'grab' is the passive grab, but if the grab isn't active, + * don't deliver */ + if (!dev->deviceGrab.grab) +- return Success; ++ return !Success; + + if (grab->ownerEvents) { + WindowPtr focus = NullWindow; +-- +1.8.2.1 + diff --git a/0013-Xi-use-a-temp-variable-for-the-new-listener.patch b/0013-Xi-use-a-temp-variable-for-the-new-listener.patch new file mode 100644 index 0000000..ee5dc03 --- /dev/null +++ b/0013-Xi-use-a-temp-variable-for-the-new-listener.patch @@ -0,0 +1,62 @@ +From 435a0e5b747526b14bed380025d705ffb82fddfb Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 1 Mar 2013 08:26:06 +1000 +Subject: [PATCH 13/35] Xi: use a temp variable for the new listener + +Instead of accessing ti->listener[0] all the time. + +No functional changes. + +Signed-off-by: Peter Hutterer +Reviewed-by: Keith Packard +(cherry picked from commit fc504a44d12d537d4e07f659f1863f200a0272ad) +--- + Xi/exevents.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index 2d531c7..06a0e03 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1125,20 +1125,22 @@ static void + TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, + TouchOwnershipEvent *ev) + { ++ TouchListener *listener = &ti->listeners[0]; /* new owner */ ++ + /* Deliver the ownership */ +- if (ti->listeners[0].state == LISTENER_AWAITING_OWNER || +- ti->listeners[0].state == LISTENER_EARLY_ACCEPT) ++ if (listener->state == LISTENER_AWAITING_OWNER || ++ listener->state == LISTENER_EARLY_ACCEPT) + DeliverTouchEvents(dev, ti, (InternalEvent *) ev, +- ti->listeners[0].listener); +- else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN) { ++ listener->listener); ++ else if (listener->state == LISTENER_AWAITING_BEGIN) { + /* We can't punt to a pointer listener unless all older pointer + * emulated touches have been seen already. */ +- if ((ti->listeners[0].type == LISTENER_POINTER_GRAB || +- ti->listeners[0].type == LISTENER_POINTER_REGULAR) && ++ if ((listener->type == LISTENER_POINTER_GRAB || ++ listener->type == LISTENER_POINTER_REGULAR) && + ti != FindOldestPointerEmulatedTouch(dev)) + return; + +- TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener); ++ TouchEventHistoryReplay(ti, dev, listener->listener); + } + + /* If we've just removed the last grab and the touch has physically +@@ -1149,7 +1151,7 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, + return; + } + +- if (ti->listeners[0].state == LISTENER_EARLY_ACCEPT) ++ if (listener->state == LISTENER_EARLY_ACCEPT) + ActivateEarlyAccept(dev, ti); + } + +-- +1.8.2.1 + diff --git a/0014-Xi-save-state-for-early-acceptance.patch b/0014-Xi-save-state-for-early-acceptance.patch new file mode 100644 index 0000000..5bd44b3 --- /dev/null +++ b/0014-Xi-save-state-for-early-acceptance.patch @@ -0,0 +1,43 @@ +From b51e55b721f5c410bf6332eb993d02c92bde291e Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 1 Mar 2013 09:15:37 +1000 +Subject: [PATCH 14/35] Xi: save state for early acceptance + +Delivering an event changes the state to LISTENER_IS_OWNER and we thus lose +the information of early acceptance. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 026627fe19aad007544eccf209f0dea05e67a7a7) +--- + Xi/exevents.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index 06a0e03..0518bf8 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1126,10 +1126,10 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, + TouchOwnershipEvent *ev) + { + TouchListener *listener = &ti->listeners[0]; /* new owner */ ++ int accepted_early = listener->state == LISTENER_EARLY_ACCEPT; + + /* Deliver the ownership */ +- if (listener->state == LISTENER_AWAITING_OWNER || +- listener->state == LISTENER_EARLY_ACCEPT) ++ if (listener->state == LISTENER_AWAITING_OWNER || accepted_early) + DeliverTouchEvents(dev, ti, (InternalEvent *) ev, + listener->listener); + else if (listener->state == LISTENER_AWAITING_BEGIN) { +@@ -1151,7 +1151,7 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, + return; + } + +- if (listener->state == LISTENER_EARLY_ACCEPT) ++ if (accepted_early) + ActivateEarlyAccept(dev, ti); + } + +-- +1.8.2.1 + diff --git a/0015-Xi-when-punting-to-a-new-owner-always-create-TouchEn.patch b/0015-Xi-when-punting-to-a-new-owner-always-create-TouchEn.patch new file mode 100644 index 0000000..88dec25 --- /dev/null +++ b/0015-Xi-when-punting-to-a-new-owner-always-create-TouchEn.patch @@ -0,0 +1,53 @@ +From 4564d3995f926434fe9325f1b167002cc50c1e79 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 27 Feb 2013 15:05:54 +1000 +Subject: [PATCH 15/35] Xi: when punting to a new owner, always create TouchEnd + events + +If a touch is pending_finish and we just punted it to the next owner, that +client must receive a TouchEnd event. + +If we just punted to the last owner and that owner not a touch grab, we need +to end the touch since this is the last event to be sent, and the client +cannot accept/reject this. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 214d11d3fcdac51fc7afbf3770516ec14f9e13c1) +--- + Xi/exevents.c | 19 ++++++++++++++----- + 1 file changed, 14 insertions(+), 5 deletions(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index 0518bf8..7c34c81 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1143,12 +1143,21 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, + TouchEventHistoryReplay(ti, dev, listener->listener); + } + +- /* If we've just removed the last grab and the touch has physically +- * ended, send a TouchEnd event too and finalise the touch. */ +- if (ti->num_listeners == 1 && ti->num_grabs == 0 && ti->pending_finish) { ++ /* New owner has Begin/Update but not end. If touch is pending_finish, ++ * emulate the TouchEnd now */ ++ if (ti->pending_finish) { + EmitTouchEnd(dev, ti, 0, 0); +- TouchEndTouch(dev, ti); +- return; ++ ++ /* If the last owner is not a touch grab, finalise the touch, we ++ won't get more correspondence on this. ++ */ ++ if (ti->num_listeners == 1 && ++ (ti->num_grabs == 0 || ++ listener->grab->grabtype != XI2 || ++ !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin))) { ++ TouchEndTouch(dev, ti); ++ return; ++ } + } + + if (accepted_early) +-- +1.8.2.1 + diff --git a/0016-Xi-use-public.processInputProc-to-replay-the-touch-h.patch b/0016-Xi-use-public.processInputProc-to-replay-the-touch-h.patch new file mode 100644 index 0000000..6f1af37 --- /dev/null +++ b/0016-Xi-use-public.processInputProc-to-replay-the-touch-h.patch @@ -0,0 +1,104 @@ +From e9201c9c1f5c80ee818a452ad1719994357971aa Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Thu, 28 Feb 2013 13:07:26 +1000 +Subject: [PATCH 16/35] Xi: use public.processInputProc to replay the touch + history + +If a device is frozen in results to a grab, we need to enqueue the events. + +This makes things complicated, and hard to follow since touch events are now +replayed in the history, pushed into EnqueueEvent, then replayed later +during PlayReleasedEvents in response to an XAllowEvents. + +While the device is frozen, no touch events are processed, so if there is a +touch client with ownership mask _below_ the grab this will delay the +delivery and potentially screw gesture recognition. However, this is the +behaviour we have already anyway if the top-most client is a sync pgrab or +there is a sync grab active on the device when the TouchBegin was generated. + +(also note, such a client would only reliably work in case of ReplayPointer +anyway) + +Signed-off-by: Peter Hutterer +(cherry picked from commit a7d989d335f903ffd8b168cd2beeb82c78d30c21) +--- + Xi/exevents.c | 8 +++++--- + dix/touch.c | 16 +++++++++++++++- + include/eventstr.h | 1 + + 3 files changed, 21 insertions(+), 4 deletions(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index 7c34c81..812ad08 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1554,7 +1554,7 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) + + touchid = ev->device_event.touchid; + +- if (type == ET_TouchBegin) { ++ if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) { + ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid, + emulate_pointer); + } +@@ -1621,7 +1621,9 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) + * called after event type mutation. Touch end events are always processed + * in order to end touch records. */ + /* FIXME: check this */ +- if ((type == ET_TouchBegin && !TouchBuildSprite(dev, ti, ev)) || ++ if ((type == ET_TouchBegin && ++ !(ev->device_event.flags & TOUCH_REPLAYING) && ++ !TouchBuildSprite(dev, ti, ev)) || + (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0)) + return; + +@@ -1629,7 +1631,7 @@ ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev) + /* WARNING: the event type may change to TouchUpdate in + * DeliverTouchEvents if a TouchEnd was delivered to a grabbing + * owner */ +- DeliverTouchEvents(dev, ti, (InternalEvent *) ev, 0); ++ DeliverTouchEvents(dev, ti, ev, ev->device_event.resource); + if (ev->any.type == ET_TouchEnd) + TouchEndTouch(dev, ti); + +diff --git a/dix/touch.c b/dix/touch.c +index 5d6e2a7..76592e7 100644 +--- a/dix/touch.c ++++ b/dix/touch.c +@@ -474,7 +474,21 @@ TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource) + DeviceEvent *ev = &ti->history[i]; + + ev->flags |= TOUCH_REPLAYING; +- DeliverTouchEvents(dev, ti, (InternalEvent *) ev, resource); ++ ev->resource = resource; ++ /* FIXME: ++ We're replaying ti->history which contains the TouchBegin + ++ all TouchUpdates for ti. This needs to be passed on to the next ++ listener. If that is a touch listener, everything is dandy. ++ If the TouchBegin however triggers a sync passive grab, the ++ TouchUpdate events must be sent to EnqueueEvent so the events end ++ up in syncEvents.pending to be forwarded correctly in a ++ subsequent ComputeFreeze(). ++ ++ However, if we just send them to EnqueueEvent the sync'ing device ++ prevents handling of touch events for ownership listeners who ++ want the events right here, right now. ++ */ ++ dev->public.processInputProc((InternalEvent*)ev, dev); + } + } + +diff --git a/include/eventstr.h b/include/eventstr.h +index 5c1adc4..3950584 100644 +--- a/include/eventstr.h ++++ b/include/eventstr.h +@@ -123,6 +123,7 @@ struct _DeviceEvent { + int corestate; /**< Core key/button state BEFORE the event */ + int key_repeat; /**< Internally-generated key repeat event */ + uint32_t flags; /**< Flags to be copied into the generated event */ ++ uint32_t resource; /**< Touch event resource, only for TOUCH_REPLAYING */ + }; + + /** +-- +1.8.2.1 + diff --git a/0017-Xi-Don-t-emit-a-TouchEnd-event-to-a-frozen-device.patch b/0017-Xi-Don-t-emit-a-TouchEnd-event-to-a-frozen-device.patch new file mode 100644 index 0000000..78d13d2 --- /dev/null +++ b/0017-Xi-Don-t-emit-a-TouchEnd-event-to-a-frozen-device.patch @@ -0,0 +1,39 @@ +From 5bc56f53669a983ea0d263cbcd5af8302dbc28b1 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 1 Mar 2013 10:41:01 +1000 +Subject: [PATCH 17/35] Xi: Don't emit a TouchEnd event to a frozen device + +EmitTouchEnd calls DeliverTouchEvents directly instead of through +public.processInputProc. If a device is frozen, the TouchEnd is +processed while the device is waiting for a XAllowEvents and thus ends the +touch point (and the grab) before the client decided what to do with it. In +the case of ReplayPointer, this loses the event. + +This is a hack, but making EmitTouchEnd use processInputProc breaks +approximately everything, especially the touch point is cleaned up during +ProcessTouchEvents. Working around that is a bigger hack than this. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 0eb9390f6048049136347d5a5834d88bfc67cc09) +--- + Xi/exevents.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index 812ad08..a6e76f7 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1067,6 +1067,10 @@ EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource) + { + InternalEvent event; + ++ /* We're not processing a touch end for a frozen device */ ++ if (dev->deviceGrab.sync.frozen) ++ return; ++ + flags |= TOUCH_CLIENT_ID; + if (ti->emulate_pointer) + flags |= TOUCH_POINTER_EMULATED; +-- +1.8.2.1 + diff --git a/0018-dix-move-EmitTouchEnd-to-touch.c.patch b/0018-dix-move-EmitTouchEnd-to-touch.c.patch new file mode 100644 index 0000000..5ead337 --- /dev/null +++ b/0018-dix-move-EmitTouchEnd-to-touch.c.patch @@ -0,0 +1,136 @@ +From 2e4e12c4fa98c7b156f8e6301eed270748e7d045 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 1 Mar 2013 12:52:35 +1000 +Subject: [PATCH 18/35] dix: move EmitTouchEnd to touch.c + +No functional changes, this just enables it to be re-used easier. + +Signed-off-by: Peter Hutterer +(cherry picked from commit e7f79c48b0faea910dc881034c00eb807fcd6210) +--- + Xi/exevents.c | 35 ++++------------------------------- + dix/touch.c | 27 +++++++++++++++++++++++++++ + include/input.h | 1 + + 3 files changed, 32 insertions(+), 31 deletions(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index a6e76f7..755a5b6 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1053,33 +1053,6 @@ ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti) + } + + /** +- * Generate and deliver a TouchEnd event. +- * +- * @param dev The device to deliver the event for. +- * @param ti The touch point record to deliver the event for. +- * @param flags Internal event flags. The called does not need to provide +- * TOUCH_CLIENT_ID and TOUCH_POINTER_EMULATED, this function will ensure +- * they are set appropriately. +- * @param resource The client resource to deliver to, or 0 for all clients. +- */ +-static void +-EmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource) +-{ +- InternalEvent event; +- +- /* We're not processing a touch end for a frozen device */ +- if (dev->deviceGrab.sync.frozen) +- return; +- +- flags |= TOUCH_CLIENT_ID; +- if (ti->emulate_pointer) +- flags |= TOUCH_POINTER_EMULATED; +- TouchDeliverDeviceClassesChangedEvent(ti, GetTimeInMillis(), resource); +- GetDixTouchEnd(&event, dev, ti, flags); +- DeliverTouchEvents(dev, ti, &event, resource); +-} +- +-/** + * Find the oldest touch that still has a pointer emulation client. + * + * Pointer emulation can only be performed for the oldest touch. Otherwise, the +@@ -1150,7 +1123,7 @@ TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti, + /* New owner has Begin/Update but not end. If touch is pending_finish, + * emulate the TouchEnd now */ + if (ti->pending_finish) { +- EmitTouchEnd(dev, ti, 0, 0); ++ TouchEmitTouchEnd(dev, ti, 0, 0); + + /* If the last owner is not a touch grab, finalise the touch, we + won't get more correspondence on this. +@@ -1208,7 +1181,7 @@ TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource, + for (i = 0; i < ti->num_listeners; i++) { + if (ti->listeners[i].listener == resource) { + if (ti->listeners[i].state != LISTENER_HAS_END) +- EmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource); ++ TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource); + break; + } + } +@@ -1255,12 +1228,12 @@ ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev, + * already seen the end. This ensures that the touch record is ended in + * the server. */ + if (ti->listeners[0].state == LISTENER_HAS_END) +- EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener); ++ TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener); + + /* The touch owner has accepted the touch. Send TouchEnd events to + * everyone else, and truncate the list of listeners. */ + for (i = 1; i < ti->num_listeners; i++) +- EmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener); ++ TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener); + + while (ti->num_listeners > 1) + TouchRemoveListener(ti, ti->listeners[1].listener); +diff --git a/dix/touch.c b/dix/touch.c +index 76592e7..f7112fc 100644 +--- a/dix/touch.c ++++ b/dix/touch.c +@@ -1075,3 +1075,30 @@ TouchEndPhysicallyActiveTouches(DeviceIntPtr dev) + + FreeEventList(eventlist, GetMaximumEventsNum()); + } ++ ++/** ++ * Generate and deliver a TouchEnd event. ++ * ++ * @param dev The device to deliver the event for. ++ * @param ti The touch point record to deliver the event for. ++ * @param flags Internal event flags. The called does not need to provide ++ * TOUCH_CLIENT_ID and TOUCH_POINTER_EMULATED, this function will ensure ++ * they are set appropriately. ++ * @param resource The client resource to deliver to, or 0 for all clients. ++ */ ++void ++TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource) ++{ ++ InternalEvent event; ++ ++ /* We're not processing a touch end for a frozen device */ ++ if (dev->deviceGrab.sync.frozen) ++ return; ++ ++ flags |= TOUCH_CLIENT_ID; ++ if (ti->emulate_pointer) ++ flags |= TOUCH_POINTER_EMULATED; ++ TouchDeliverDeviceClassesChangedEvent(ti, GetTimeInMillis(), resource); ++ GetDixTouchEnd(&event, dev, ti, flags); ++ DeliverTouchEvents(dev, ti, &event, resource); ++} +diff --git a/include/input.h b/include/input.h +index 5c65597..866879b 100644 +--- a/include/input.h ++++ b/include/input.h +@@ -590,6 +590,7 @@ extern int TouchAcceptReject(ClientPtr client, DeviceIntPtr dev, int mode, + extern void TouchEndPhysicallyActiveTouches(DeviceIntPtr dev); + extern void TouchDeliverDeviceClassesChangedEvent(TouchPointInfoPtr ti, + Time time, XID resource); ++extern void TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource); + + /* misc event helpers */ + extern Mask GetEventMask(DeviceIntPtr dev, xEvent *ev, InputClientsPtr clients); +-- +1.8.2.1 + diff --git a/0019-dix-XAllowEvents-on-a-touch-event-means-accepting-it.patch b/0019-dix-XAllowEvents-on-a-touch-event-means-accepting-it.patch new file mode 100644 index 0000000..cb84922 --- /dev/null +++ b/0019-dix-XAllowEvents-on-a-touch-event-means-accepting-it.patch @@ -0,0 +1,78 @@ +From f93370eed883a8f3593f8cbe5dafbd8dbf2b72e8 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Thu, 28 Feb 2013 11:02:40 +1000 +Subject: [PATCH 19/35] dix: XAllowEvents() on a touch event means accepting it + +A sync grab is the owner once it gets events. If it doesn't replay the +event it will get all events from this touch, equivalent to accepting it. + +If the touch has ended before XAllowEvents() is called, we also now need to +send the TouchEnd event and clean-up since we won't see anything more from +this touch. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 5174b1f98204beee79eba74c4cda5f2be0a60a8f) +--- + dix/events.c | 10 ++++++++++ + dix/touch.c | 14 ++++++++++++++ + include/input.h | 1 + + 3 files changed, 25 insertions(+) + +diff --git a/dix/events.c b/dix/events.c +index 2682ecd..7772c0b 100644 +--- a/dix/events.c ++++ b/dix/events.c +@@ -1739,6 +1739,16 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) + } + break; + } ++ ++ /* We've unfrozen the grab. If the grab was a touch grab, we're now the ++ * owner and expected to accept/reject it. Reject == ReplayPointer which ++ * we've handled in ComputeFreezes() (during DeactivateGrab) above, ++ * anything else is accept. ++ */ ++ if (newState != NOT_GRABBED /* Replay */ && ++ IsTouchEvent((InternalEvent*)grabinfo->sync.event)) { ++ TouchAcceptAndEnd(thisDev, grabinfo->sync.event->touchid); ++ } + } + + /** +diff --git a/dix/touch.c b/dix/touch.c +index f7112fc..0cbc2eb 100644 +--- a/dix/touch.c ++++ b/dix/touch.c +@@ -1102,3 +1102,17 @@ TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resourc + GetDixTouchEnd(&event, dev, ti, flags); + DeliverTouchEvents(dev, ti, &event, resource); + } ++ ++void ++TouchAcceptAndEnd(DeviceIntPtr dev, int touchid) ++{ ++ TouchPointInfoPtr ti = TouchFindByClientID(dev, touchid); ++ if (!ti) ++ return; ++ ++ TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch); ++ if (ti->pending_finish) ++ TouchEmitTouchEnd(dev, ti, 0, 0); ++ if (ti->num_listeners <= 1) ++ TouchEndTouch(dev, ti); ++} +diff --git a/include/input.h b/include/input.h +index 866879b..7eed60b 100644 +--- a/include/input.h ++++ b/include/input.h +@@ -591,6 +591,7 @@ extern void TouchEndPhysicallyActiveTouches(DeviceIntPtr dev); + extern void TouchDeliverDeviceClassesChangedEvent(TouchPointInfoPtr ti, + Time time, XID resource); + extern void TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resource); ++extern void TouchAcceptAndEnd(DeviceIntPtr dev, int touchid); + + /* misc event helpers */ + extern Mask GetEventMask(DeviceIntPtr dev, xEvent *ev, InputClientsPtr clients); +-- +1.8.2.1 + diff --git a/0020-dix-invert-a-loop-condition.patch b/0020-dix-invert-a-loop-condition.patch new file mode 100644 index 0000000..7f4aaad --- /dev/null +++ b/0020-dix-invert-a-loop-condition.patch @@ -0,0 +1,59 @@ +From 7c6a9b425a8366d3f9b9a823d4dfa1dfbdc66635 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 17 Apr 2013 20:13:34 +1000 +Subject: [PATCH 20/35] dix: invert a loop condition + +Change the single if condition in the loop body to a + if (!foo) continue; +and re-indent the rest. + +No functional changes. + +Signed-off-by: Peter Hutterer +(cherry picked from commit a71a283934406d870bcd8dc376eb1c9ce1c8bbb4) +--- + dix/touch.c | 25 +++++++++++++------------ + 1 file changed, 13 insertions(+), 12 deletions(-) + +diff --git a/dix/touch.c b/dix/touch.c +index 0cbc2eb..be4a7de 100644 +--- a/dix/touch.c ++++ b/dix/touch.c +@@ -718,21 +718,22 @@ TouchRemoveListener(TouchPointInfoPtr ti, XID resource) + int i; + + for (i = 0; i < ti->num_listeners; i++) { +- if (ti->listeners[i].listener == resource) { +- int j; ++ int j; + +- if (ti->listeners[i].grab) { +- ti->listeners[i].grab = NULL; +- ti->num_grabs--; +- } ++ if (ti->listeners[i].listener != resource) ++ continue; + +- for (j = i; j < ti->num_listeners - 1; j++) +- ti->listeners[j] = ti->listeners[j + 1]; +- ti->num_listeners--; +- ti->listeners[ti->num_listeners].listener = 0; +- ti->listeners[ti->num_listeners].state = LISTENER_AWAITING_BEGIN; +- return TRUE; ++ if (ti->listeners[i].grab) { ++ ti->listeners[i].grab = NULL; ++ ti->num_grabs--; + } ++ ++ for (j = i; j < ti->num_listeners - 1; j++) ++ ti->listeners[j] = ti->listeners[j + 1]; ++ ti->num_listeners--; ++ ti->listeners[ti->num_listeners].listener = 0; ++ ti->listeners[ti->num_listeners].state = LISTENER_AWAITING_BEGIN; ++ return TRUE; + } + return FALSE; + } +-- +1.8.2.1 + diff --git a/0021-dix-use-a-tmp-variable-for-the-to-be-removed-touch-l.patch b/0021-dix-use-a-tmp-variable-for-the-to-be-removed-touch-l.patch new file mode 100644 index 0000000..a134784 --- /dev/null +++ b/0021-dix-use-a-tmp-variable-for-the-to-be-removed-touch-l.patch @@ -0,0 +1,38 @@ +From c86dd2d607c653c57e5c9ad10ba959d58dfb9fc2 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 17 Apr 2013 20:14:56 +1000 +Subject: [PATCH 21/35] dix: use a tmp variable for the to-be-removed touch + listener + +No functional changes. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 7dbf61817d3bd4b1fc71710677e56c5d8cfcdb4e) +--- + dix/touch.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/dix/touch.c b/dix/touch.c +index be4a7de..01a554e 100644 +--- a/dix/touch.c ++++ b/dix/touch.c +@@ -719,12 +719,13 @@ TouchRemoveListener(TouchPointInfoPtr ti, XID resource) + + for (i = 0; i < ti->num_listeners; i++) { + int j; ++ TouchListener *listener = &ti->listeners[i]; + +- if (ti->listeners[i].listener != resource) ++ if (listener->listener != resource) + continue; + +- if (ti->listeners[i].grab) { +- ti->listeners[i].grab = NULL; ++ if (listener->grab) { ++ listener->grab = NULL; + ti->num_grabs--; + } + +-- +1.8.2.1 + diff --git a/0022-dix-drop-DeviceIntRec-s-activeGrab-struct.patch b/0022-dix-drop-DeviceIntRec-s-activeGrab-struct.patch new file mode 100644 index 0000000..5e09265 --- /dev/null +++ b/0022-dix-drop-DeviceIntRec-s-activeGrab-struct.patch @@ -0,0 +1,114 @@ +From fff0bd42fe5ecaaebffbb85b671bc4cf9cc71c16 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Thu, 18 Apr 2013 10:32:11 +1000 +Subject: [PATCH 22/35] dix: drop DeviceIntRec's activeGrab struct + +Obsolete since 4bc2761ad5ec2d0668aec639780ffb136605fbc8. This struct +existed so copying a passive grab could be simply done by + activeGrab = *grab + +and thus have a copy of the GrabPtr we'd get from various sources but still +be able to check device->grab for NULL. + +Since 4bc2761 activeGrab is a pointer itself and points to the same memory +as grabinfo->grab, leaving us with the potential of dangling pointers if +either calls FreeGrab() and doesn't reset the other one. + +There is no reader of activeGrab anyway, so simply removing it is +sufficient. + +Note: field is merely renamed to keep the ABI. Should be removed in the +future. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 5363433a5cc64e2f83859aa1c32a89e5e1ddf9e4) +--- + dix/devices.c | 4 ++-- + dix/events.c | 14 ++++++++++---- + include/inputstr.h | 2 +- + 3 files changed, 13 insertions(+), 7 deletions(-) + +diff --git a/dix/devices.c b/dix/devices.c +index a0d545a..9ef32bb 100644 +--- a/dix/devices.c ++++ b/dix/devices.c +@@ -281,7 +281,6 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) + dev->deviceGrab.grabTime = currentTime; + dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab; + dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; +- dev->deviceGrab.activeGrab = AllocGrab(); + dev->deviceGrab.sync.event = calloc(1, sizeof(DeviceEvent)); + + XkbSetExtension(dev, ProcessKeyboardEvent); +@@ -977,7 +976,8 @@ CloseDevice(DeviceIntPtr dev) + } + } + +- FreeGrab(dev->deviceGrab.activeGrab); ++ if (dev->deviceGrab.grab) ++ FreeGrab(dev->deviceGrab.grab); + free(dev->deviceGrab.sync.event); + free(dev->config_info); /* Allocated in xf86ActivateDevice. */ + free(dev->last.scroll); +diff --git a/dix/events.c b/dix/events.c +index 7772c0b..9ac8792 100644 +--- a/dix/events.c ++++ b/dix/events.c +@@ -1487,8 +1487,9 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, + grabinfo->grabTime = time; + if (grab->cursor) + grab->cursor->refcnt++; +- CopyGrab(grabinfo->activeGrab, grab); +- grabinfo->grab = grabinfo->activeGrab; ++ BUG_WARN(grabinfo->grab != NULL); ++ grabinfo->grab = AllocGrab(); ++ CopyGrab(grabinfo->grab, grab); + grabinfo->fromPassiveGrab = isPassive; + grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; + PostNewCursor(mouse); +@@ -1551,6 +1552,8 @@ DeactivatePointerGrab(DeviceIntPtr mouse) + ReattachToOldMaster(mouse); + + ComputeFreezes(); ++ ++ FreeGrab(grab); + } + + /** +@@ -1588,8 +1591,9 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, + grabinfo->grabTime = syncEvents.time; + else + grabinfo->grabTime = time; +- CopyGrab(grabinfo->activeGrab, grab); +- grabinfo->grab = grabinfo->activeGrab; ++ BUG_WARN(grabinfo->grab != NULL); ++ grabinfo->grab = AllocGrab(); ++ CopyGrab(grabinfo->grab, grab); + grabinfo->fromPassiveGrab = passive; + grabinfo->implicitGrab = passive & ImplicitGrabMask; + CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode, +@@ -1635,6 +1639,8 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd) + ReattachToOldMaster(keybd); + + ComputeFreezes(); ++ ++ FreeGrab(grab); + } + + void +diff --git a/include/inputstr.h b/include/inputstr.h +index de96fae..85be885 100644 +--- a/include/inputstr.h ++++ b/include/inputstr.h +@@ -485,7 +485,7 @@ typedef struct _GrabInfoRec { + TimeStamp grabTime; + Bool fromPassiveGrab; /* true if from passive grab */ + Bool implicitGrab; /* implicit from ButtonPress */ +- GrabPtr activeGrab; ++ GrabPtr unused; /* Kept for ABI stability, remove soon */ + GrabPtr grab; + CARD8 activatingKey; + void (*ActivateGrab) (DeviceIntPtr /*device */ , +-- +1.8.2.1 + diff --git a/0023-dix-use-a-temporary-variable-for-listeners-0.patch b/0023-dix-use-a-temporary-variable-for-listeners-0.patch new file mode 100644 index 0000000..b77dd1b --- /dev/null +++ b/0023-dix-use-a-temporary-variable-for-listeners-0.patch @@ -0,0 +1,51 @@ +From 54aab9052c3ba591a68bf773b0db05fcaa17c54c Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Tue, 23 Apr 2013 15:39:32 +1000 +Subject: [PATCH 23/35] dix: use a temporary variable for listeners[0] + +no functional changes + +Signed-off-by: Peter Hutterer +(cherry picked from commit ccfa0f2d5de557546815a5e4f59552e2af46b578) +--- + dix/events.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/dix/events.c b/dix/events.c +index 9ac8792..0216502 100644 +--- a/dix/events.c ++++ b/dix/events.c +@@ -1424,21 +1424,22 @@ UpdateTouchesForGrab(DeviceIntPtr mouse) + + for (i = 0; i < mouse->touch->num_touches; i++) { + TouchPointInfoPtr ti = mouse->touch->touches + i; ++ TouchListener *listener = &ti->listeners[0]; + GrabPtr grab = mouse->deviceGrab.grab; + + if (ti->active && +- CLIENT_BITS(ti->listeners[0].listener) == grab->resource) { +- ti->listeners[0].listener = grab->resource; +- ti->listeners[0].level = grab->grabtype; +- ti->listeners[0].state = LISTENER_IS_OWNER; +- ti->listeners[0].window = grab->window; ++ CLIENT_BITS(listener->listener) == grab->resource) { ++ listener->listener = grab->resource; ++ listener->level = grab->grabtype; ++ listener->state = LISTENER_IS_OWNER; ++ listener->window = grab->window; + + if (grab->grabtype == CORE || grab->grabtype == XI || + !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) +- ti->listeners[0].type = LISTENER_POINTER_GRAB; ++ listener->type = LISTENER_POINTER_GRAB; + else +- ti->listeners[0].type = LISTENER_GRAB; +- ti->listeners[0].grab = grab; ++ listener->type = LISTENER_GRAB; ++ listener->grab = grab; + } + } + } +-- +1.8.2.1 + diff --git a/0024-dix-freeing-a-null-grab-is-a-bug-complain-if-doing-s.patch b/0024-dix-freeing-a-null-grab-is-a-bug-complain-if-doing-s.patch new file mode 100644 index 0000000..03a8e5b --- /dev/null +++ b/0024-dix-freeing-a-null-grab-is-a-bug-complain-if-doing-s.patch @@ -0,0 +1,27 @@ +From 06b33d8b9f3d463810e6005379411bbd412accf4 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Tue, 23 Apr 2013 15:46:04 +1000 +Subject: [PATCH 24/35] dix: freeing a null grab is a bug, complain if doing so + +Signed-off-by: Peter Hutterer +(cherry picked from commit 4980bcef9973ba1f90f53028f061669ee5d2661b) +--- + dix/grabs.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/dix/grabs.c b/dix/grabs.c +index 3b02352..0a2111d 100644 +--- a/dix/grabs.c ++++ b/dix/grabs.c +@@ -249,6 +249,8 @@ CreateGrab(int client, DeviceIntPtr device, DeviceIntPtr modDevice, + void + FreeGrab(GrabPtr pGrab) + { ++ BUG_RETURN(!pGrab); ++ + if (pGrab->grabtype == XI2 && pGrab->type == XI_TouchBegin) + TouchListenerGone(pGrab->resource); + +-- +1.8.2.1 + diff --git a/0025-dix-AllocGrab-can-copy-if-an-argument-is-passed-in.patch b/0025-dix-AllocGrab-can-copy-if-an-argument-is-passed-in.patch new file mode 100644 index 0000000..c358f14 --- /dev/null +++ b/0025-dix-AllocGrab-can-copy-if-an-argument-is-passed-in.patch @@ -0,0 +1,189 @@ +From c34d411adcce6b183144a174838d5da441f3b9a2 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Tue, 23 Apr 2013 15:52:18 +1000 +Subject: [PATCH 25/35] dix: AllocGrab can copy if an argument is passed in + +Signed-off-by: Peter Hutterer +(cherry picked from commit 925e35122ebad877395bcf13676e9dbeb254bdfa) +--- + Xi/exevents.c | 2 +- + Xi/ungrdevb.c | 2 +- + Xi/ungrdevk.c | 2 +- + Xi/xipassivegrab.c | 2 +- + dix/events.c | 16 +++++++--------- + dix/grabs.c | 10 ++++++++-- + include/dixgrabs.h | 2 +- + 7 files changed, 20 insertions(+), 16 deletions(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index 755a5b6..7914b89 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -2845,7 +2845,7 @@ CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type, + (deliveryMask & DeviceButtonGrabMask)) { + GrabPtr tempGrab; + +- tempGrab = AllocGrab(); ++ tempGrab = AllocGrab(NULL); + if (!tempGrab) + return; + +diff --git a/Xi/ungrdevb.c b/Xi/ungrdevb.c +index c4632fa..b02510e 100644 +--- a/Xi/ungrdevb.c ++++ b/Xi/ungrdevb.c +@@ -127,7 +127,7 @@ ProcXUngrabDeviceButton(ClientPtr client) + (stuff->modifiers & ~AllModifiersMask)) + return BadValue; + +- temporaryGrab = AllocGrab(); ++ temporaryGrab = AllocGrab(NULL); + if (!temporaryGrab) + return BadAlloc; + +diff --git a/Xi/ungrdevk.c b/Xi/ungrdevk.c +index 3273878..f981171 100644 +--- a/Xi/ungrdevk.c ++++ b/Xi/ungrdevk.c +@@ -134,7 +134,7 @@ ProcXUngrabDeviceKey(ClientPtr client) + (stuff->modifiers & ~AllModifiersMask)) + return BadValue; + +- temporaryGrab = AllocGrab(); ++ temporaryGrab = AllocGrab(NULL); + if (!temporaryGrab) + return BadAlloc; + +diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c +index 62a3a46..eccec0a 100644 +--- a/Xi/xipassivegrab.c ++++ b/Xi/xipassivegrab.c +@@ -307,7 +307,7 @@ ProcXIPassiveUngrabDevice(ClientPtr client) + + mod_dev = (IsFloating(dev)) ? dev : GetMaster(dev, MASTER_KEYBOARD); + +- tempGrab = AllocGrab(); ++ tempGrab = AllocGrab(NULL); + if (!tempGrab) + return BadAlloc; + +diff --git a/dix/events.c b/dix/events.c +index 0216502..6a8e7a6 100644 +--- a/dix/events.c ++++ b/dix/events.c +@@ -1489,8 +1489,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, + if (grab->cursor) + grab->cursor->refcnt++; + BUG_WARN(grabinfo->grab != NULL); +- grabinfo->grab = AllocGrab(); +- CopyGrab(grabinfo->grab, grab); ++ grabinfo->grab = AllocGrab(grab); + grabinfo->fromPassiveGrab = isPassive; + grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; + PostNewCursor(mouse); +@@ -1593,8 +1592,7 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, + else + grabinfo->grabTime = time; + BUG_WARN(grabinfo->grab != NULL); +- grabinfo->grab = AllocGrab(); +- CopyGrab(grabinfo->grab, grab); ++ grabinfo->grab = AllocGrab(grab); + grabinfo->fromPassiveGrab = passive; + grabinfo->implicitGrab = passive & ImplicitGrabMask; + CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode, +@@ -1988,7 +1986,7 @@ ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win, + else + return FALSE; + +- tempGrab = AllocGrab(); ++ tempGrab = AllocGrab(NULL); + if (!tempGrab) + return FALSE; + tempGrab->next = NULL; +@@ -3895,7 +3893,7 @@ CheckPassiveGrabsOnWindow(WindowPtr pWin, + if (!grab) + return NULL; + +- tempGrab = AllocGrab(); ++ tempGrab = AllocGrab(NULL); + + /* Fill out the grab details, but leave the type for later before + * comparing */ +@@ -5084,7 +5082,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev, + else { + GrabPtr tempGrab; + +- tempGrab = AllocGrab(); ++ tempGrab = AllocGrab(NULL); + + tempGrab->next = NULL; + tempGrab->window = pWin; +@@ -5440,7 +5438,7 @@ ProcUngrabKey(ClientPtr client) + client->errorValue = stuff->modifiers; + return BadValue; + } +- tempGrab = AllocGrab(); ++ tempGrab = AllocGrab(NULL); + if (!tempGrab) + return BadAlloc; + tempGrab->resource = client->clientAsMask; +@@ -5634,7 +5632,7 @@ ProcUngrabButton(ClientPtr client) + + ptr = PickPointer(client); + +- tempGrab = AllocGrab(); ++ tempGrab = AllocGrab(NULL); + if (!tempGrab) + return BadAlloc; + tempGrab->resource = client->clientAsMask; +diff --git a/dix/grabs.c b/dix/grabs.c +index 0a2111d..f46a6b2 100644 +--- a/dix/grabs.c ++++ b/dix/grabs.c +@@ -189,7 +189,7 @@ UngrabAllDevices(Bool kill_client) + } + + GrabPtr +-AllocGrab(void) ++AllocGrab(const GrabPtr src) + { + GrabPtr grab = calloc(1, sizeof(GrabRec)); + +@@ -201,6 +201,12 @@ AllocGrab(void) + } + } + ++ if (src && !CopyGrab(grab, src)) { ++ free(grab->xi2mask); ++ free(grab); ++ grab = NULL; ++ } ++ + return grab; + } + +@@ -213,7 +219,7 @@ CreateGrab(int client, DeviceIntPtr device, DeviceIntPtr modDevice, + { + GrabPtr grab; + +- grab = AllocGrab(); ++ grab = AllocGrab(NULL); + if (!grab) + return (GrabPtr) NULL; + grab->resource = FakeClientID(client); +diff --git a/include/dixgrabs.h b/include/dixgrabs.h +index eccec77..ca3c95b 100644 +--- a/include/dixgrabs.h ++++ b/include/dixgrabs.h +@@ -31,7 +31,7 @@ struct _GrabParameters; + extern void PrintDeviceGrabInfo(DeviceIntPtr dev); + extern void UngrabAllDevices(Bool kill_client); + +-extern GrabPtr AllocGrab(void); ++extern GrabPtr AllocGrab(const GrabPtr src); + extern void FreeGrab(GrabPtr grab); + extern Bool CopyGrab(GrabPtr dst, const GrabPtr src); + +-- +1.8.2.1 + diff --git a/0026-dix-always-copy-grabs-don-t-reference-them.patch b/0026-dix-always-copy-grabs-don-t-reference-them.patch new file mode 100644 index 0000000..47c1dbd --- /dev/null +++ b/0026-dix-always-copy-grabs-don-t-reference-them.patch @@ -0,0 +1,133 @@ +From 30798524264bd63b1c993d4d2bf3e261c2328b9a Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 17 Apr 2013 20:15:35 +1000 +Subject: [PATCH 26/35] dix: always copy grabs, don't reference them + +Introduced in xorg-server-1.13.99.901-2-g9ad0fdb. Storing the grab pointer +in the listener turns out to be a bad idea. If the grab is not an active +grab or an implicit grab, the pointer stored is the one to the grab attached +on the window. This grab may be removed if the client calls UngrabButton or +similar while the touch is still active, leaving a dangling pointer. + +To avoid this, copy the grab wherever we need to reference it later. This +is also what we do for pointer/keyboard grabs, where we copy the grab as +soon as it becomes active. + +Reported-by: Maarten Lankhorst +Signed-off-by: Peter Hutterer +(cherry picked from commit 395124bd2782823de37e5c5b2f15dba49cff05f6) +--- + Xi/exevents.c | 7 +++++-- + dix/events.c | 3 ++- + dix/touch.c | 19 +++++++++++++++++-- + 3 files changed, 24 insertions(+), 5 deletions(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index 7914b89..7bebc9b 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1429,8 +1429,11 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, + */ + if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) { + TouchListener *l; ++ GrabPtr g; + + devgrab = dev->deviceGrab.grab; ++ g = AllocGrab(devgrab); ++ BUG_WARN(!g); + + *dev->deviceGrab.sync.event = ev->device_event; + +@@ -1439,8 +1442,8 @@ DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, + * event selection. Thus, we update the last listener in the array. + */ + l = &ti->listeners[ti->num_listeners - 1]; +- l->listener = devgrab->resource; +- l->grab = devgrab; ++ l->listener = g->resource; ++ l->grab = g; + //l->resource_type = RT_NONE; + + if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin) +diff --git a/dix/events.c b/dix/events.c +index 6a8e7a6..8745c11 100644 +--- a/dix/events.c ++++ b/dix/events.c +@@ -1439,7 +1439,8 @@ UpdateTouchesForGrab(DeviceIntPtr mouse) + listener->type = LISTENER_POINTER_GRAB; + else + listener->type = LISTENER_GRAB; +- listener->grab = grab; ++ FreeGrab(listener->grab); ++ listener->grab = AllocGrab(grab); + } + } + } +diff --git a/dix/touch.c b/dix/touch.c +index 01a554e..fb218d4 100644 +--- a/dix/touch.c ++++ b/dix/touch.c +@@ -365,6 +365,8 @@ TouchBeginTouch(DeviceIntPtr dev, int sourceid, uint32_t touchid, + void + TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti) + { ++ int i; ++ + if (ti->emulate_pointer) { + GrabPtr grab; + +@@ -376,6 +378,9 @@ TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti) + } + } + ++ for (i = 0; i < ti->num_listeners; i++) ++ TouchRemoveListener(ti, ti->listeners[0].listener); ++ + ti->active = FALSE; + ti->pending_finish = FALSE; + ti->sprite.spriteTraceGood = 0; +@@ -692,15 +697,23 @@ void + TouchAddListener(TouchPointInfoPtr ti, XID resource, int resource_type, + enum InputLevel level, enum TouchListenerType type, + enum TouchListenerState state, WindowPtr window, +- GrabPtr grab) ++ const GrabPtr grab) + { ++ GrabPtr g = NULL; ++ ++ /* 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); ++ + ti->listeners[ti->num_listeners].listener = resource; + ti->listeners[ti->num_listeners].resource_type = resource_type; + ti->listeners[ti->num_listeners].level = level; + ti->listeners[ti->num_listeners].state = state; + ti->listeners[ti->num_listeners].type = type; + ti->listeners[ti->num_listeners].window = window; +- ti->listeners[ti->num_listeners].grab = grab; ++ ti->listeners[ti->num_listeners].grab = g; + if (grab) + ti->num_grabs++; + ti->num_listeners++; +@@ -725,6 +738,7 @@ TouchRemoveListener(TouchPointInfoPtr ti, XID resource) + continue; + + if (listener->grab) { ++ FreeGrab(listener->grab); + listener->grab = NULL; + ti->num_grabs--; + } +@@ -734,6 +748,7 @@ TouchRemoveListener(TouchPointInfoPtr ti, XID resource) + ti->num_listeners--; + ti->listeners[ti->num_listeners].listener = 0; + ti->listeners[ti->num_listeners].state = LISTENER_AWAITING_BEGIN; ++ + return TRUE; + } + return FALSE; +-- +1.8.2.1 + diff --git a/0027-dix-remove-all-listeners-when-freeing-a-touch.patch b/0027-dix-remove-all-listeners-when-freeing-a-touch.patch new file mode 100644 index 0000000..b73be8b --- /dev/null +++ b/0027-dix-remove-all-listeners-when-freeing-a-touch.patch @@ -0,0 +1,36 @@ +From 43e97926e144ebd7180fe9a8dbd27dbf73e3aa08 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 24 Apr 2013 12:53:52 +1000 +Subject: [PATCH 27/35] dix: remove all listeners when freeing a touch + +Signed-off-by: Peter Hutterer +(cherry picked from commit 34c9b39d9937c2e19c2dffc9748605f90d40f965) +--- + dix/touch.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/dix/touch.c b/dix/touch.c +index fb218d4..0099914 100644 +--- a/dix/touch.c ++++ b/dix/touch.c +@@ -263,6 +263,7 @@ void + TouchFreeTouchPoint(DeviceIntPtr device, int index) + { + TouchPointInfoPtr ti; ++ int i; + + if (!device->touch || index >= device->touch->num_touches) + return; +@@ -271,6 +272,9 @@ TouchFreeTouchPoint(DeviceIntPtr device, int index) + if (ti->active) + TouchEndTouch(device, ti); + ++ for (i = 0; i < ti->num_listeners; i++) ++ TouchRemoveListener(ti, ti->listeners[0].listener); ++ + valuator_mask_free(&ti->valuators); + free(ti->sprite.spriteTrace); + ti->sprite.spriteTrace = NULL; +-- +1.8.2.1 + diff --git a/0028-Move-TouchListenerGone-call-to-CloseDownClient.patch b/0028-Move-TouchListenerGone-call-to-CloseDownClient.patch new file mode 100644 index 0000000..62fdf45 --- /dev/null +++ b/0028-Move-TouchListenerGone-call-to-CloseDownClient.patch @@ -0,0 +1,67 @@ +From 99e30237252fea7d17d4126a929dafb3766e936c Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 24 Apr 2013 14:40:31 +1000 +Subject: [PATCH 28/35] Move TouchListenerGone call to CloseDownClient + +TouchListenerGone cleans up if a client disappears. Having this in +FreeGrab() triggers cyclic removal of grabs, emitting wrong events. In +particular, it would clean up a passive grab record while that grab is +active. + +Move it to CloseDownClient() instead, cleaning up before we go. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 5b00fc52270e9cfdfe7ac1838a21defe50fc3d31) +--- + dix/dispatch.c | 1 + + dix/grabs.c | 3 --- + dix/touch.c | 4 ++-- + 3 files changed, 3 insertions(+), 5 deletions(-) + +diff --git a/dix/dispatch.c b/dix/dispatch.c +index 8d61735..20f2414 100644 +--- a/dix/dispatch.c ++++ b/dix/dispatch.c +@@ -3398,6 +3398,7 @@ CloseDownClient(ClientPtr client) + clientinfo.setup = (xConnSetup *) NULL; + CallCallbacks((&ClientStateCallback), (pointer) &clientinfo); + } ++ TouchListenerGone(client->clientAsMask); + FreeClientResources(client); + /* Disable client ID tracking. This must be done after + * ClientStateCallback. */ +diff --git a/dix/grabs.c b/dix/grabs.c +index f46a6b2..b254ddc 100644 +--- a/dix/grabs.c ++++ b/dix/grabs.c +@@ -257,9 +257,6 @@ FreeGrab(GrabPtr pGrab) + { + BUG_RETURN(!pGrab); + +- if (pGrab->grabtype == XI2 && pGrab->type == XI_TouchBegin) +- TouchListenerGone(pGrab->resource); +- + free(pGrab->modifiersDetail.pMask); + free(pGrab->detail.pMask); + +diff --git a/dix/touch.c b/dix/touch.c +index 0099914..110b1cc 100644 +--- a/dix/touch.c ++++ b/dix/touch.c +@@ -989,11 +989,11 @@ TouchListenerGone(XID resource) + continue; + + for (j = 0; j < ti->num_listeners; j++) { +- if (ti->listeners[j].listener != resource) ++ if (CLIENT_BITS(ti->listeners[j].listener) != resource) + continue; + + nev = GetTouchOwnershipEvents(events, dev, ti, XIRejectTouch, +- resource, 0); ++ ti->listeners[j].listener, 0); + for (k = 0; k < nev; k++) + mieqProcessDeviceEvent(dev, events + k, NULL); + +-- +1.8.2.1 + diff --git a/0029-Xi-check-for-HAS_ACCEPTED-only-for-grab-listeners.patch b/0029-Xi-check-for-HAS_ACCEPTED-only-for-grab-listeners.patch new file mode 100644 index 0000000..2d98e6d --- /dev/null +++ b/0029-Xi-check-for-HAS_ACCEPTED-only-for-grab-listeners.patch @@ -0,0 +1,30 @@ +From f0d2660f52d4dbfbe86f24b1952f92a91fa33506 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 24 Apr 2013 14:46:06 +1000 +Subject: [PATCH 29/35] Xi: check for HAS_ACCEPTED only for grab listeners + +If we have one listener left but it's not a grab, it cannot be in +LISTENER_HAS_ACCEPTED state. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 2566bdd8bc996cccde77b846819808c6239a89d2) +--- + Xi/exevents.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index 7bebc9b..a4120de 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1917,7 +1917,7 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev, + rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev); + + if ((ti->num_listeners > 1 || +- listener->state != LISTENER_HAS_ACCEPTED) && ++ (ti->num_grabs > 0 && listener->state != LISTENER_HAS_ACCEPTED)) && + (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) { + ev->any.type = ET_TouchUpdate; + ev->device_event.flags |= TOUCH_PENDING_END; +-- +1.8.2.1 + diff --git a/0030-dix-free-the-old-grab-when-activating-a-new-grab.patch b/0030-dix-free-the-old-grab-when-activating-a-new-grab.patch new file mode 100644 index 0000000..cca6098 --- /dev/null +++ b/0030-dix-free-the-old-grab-when-activating-a-new-grab.patch @@ -0,0 +1,63 @@ +From 300ecb63ae7cab90d5f7719259c9741f8495141f Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 3 May 2013 15:02:05 +1000 +Subject: [PATCH 30/35] dix: free the old grab when activating a new grab + +A client may call XIGrabDevice twice, overwriting the existing grab. Thus, +make sure we free the old copy after we copied it. Free it last, to make +sure our refcounts don't run to 0 and inadvertantly free something on the +way. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 3093f78d17e48a506aab170a9089cd10e21af299) +--- + dix/events.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/dix/events.c b/dix/events.c +index 8745c11..24fd6b9 100644 +--- a/dix/events.c ++++ b/dix/events.c +@@ -1465,6 +1465,7 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, + TimeStamp time, Bool autoGrab) + { + GrabInfoPtr grabinfo = &mouse->deviceGrab; ++ GrabPtr oldgrab = grabinfo->grab; + WindowPtr oldWin = (grabinfo->grab) ? + grabinfo->grab->window : mouse->spriteInfo->sprite->win; + Bool isPassive = autoGrab & ~ImplicitGrabMask; +@@ -1497,6 +1498,8 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, + UpdateTouchesForGrab(mouse); + CheckGrabForSyncs(mouse, (Bool) grab->pointerMode, + (Bool) grab->keyboardMode); ++ if (oldgrab) ++ FreeGrab(oldgrab); + } + + /** +@@ -1567,6 +1570,7 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, + Bool passive) + { + GrabInfoPtr grabinfo = &keybd->deviceGrab; ++ GrabPtr oldgrab = grabinfo->grab; + WindowPtr oldWin; + + /* slave devices need to float for the duration of the grab. */ +@@ -1592,12 +1596,13 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, + grabinfo->grabTime = syncEvents.time; + else + grabinfo->grabTime = time; +- BUG_WARN(grabinfo->grab != NULL); + grabinfo->grab = AllocGrab(grab); + grabinfo->fromPassiveGrab = passive; + grabinfo->implicitGrab = passive & ImplicitGrabMask; + CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode, + (Bool) grab->pointerMode); ++ if (oldgrab) ++ FreeGrab(oldgrab); + } + + /** +-- +1.8.2.1 + diff --git a/0031-dix-fix-cursor-refcounting.patch b/0031-dix-fix-cursor-refcounting.patch new file mode 100644 index 0000000..fa6a436 --- /dev/null +++ b/0031-dix-fix-cursor-refcounting.patch @@ -0,0 +1,91 @@ +From 7a7aa4cd23734ddcd8cc620fc4a5a82a050917cd Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Fri, 3 May 2013 15:07:58 +1000 +Subject: [PATCH 31/35] dix: fix cursor refcounting + +The cursor is referenced during CopyGrab(), thus doesn't need to be handled +manually anymore. It does need to be refcounted for temp grabs though. + +The oldGrab handling in ProcGrabPointer is a leftover from the cursor in the +grab being refcounted, but the grab itself being a static struct in the +DeviceIntRec. Now that all grabs are copied, this lead to a double-free of +the cursor (Reproduced in Thunderbird, dragging an email twice (or more +often) causes a crash). + +Signed-off-by: Peter Hutterer +(cherry picked from commit 481702101b86fff003430e952dc65fb41eb56400) +--- + dix/events.c | 20 ++++---------------- + 1 file changed, 4 insertions(+), 16 deletions(-) + +diff --git a/dix/events.c b/dix/events.c +index 24fd6b9..64a8f15 100644 +--- a/dix/events.c ++++ b/dix/events.c +@@ -1488,9 +1488,6 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, + grabinfo->grabTime = syncEvents.time; + else + grabinfo->grabTime = time; +- if (grab->cursor) +- grab->cursor->refcnt++; +- BUG_WARN(grabinfo->grab != NULL); + grabinfo->grab = AllocGrab(grab); + grabinfo->fromPassiveGrab = isPassive; + grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; +@@ -1549,8 +1546,6 @@ DeactivatePointerGrab(DeviceIntPtr mouse) + if (grab->confineTo) + ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE); + PostNewCursor(mouse); +- if (grab->cursor) +- FreeCursor(grab->cursor, (Cursor) 0); + + if (!wasImplicit && grab->grabtype == XI2) + ReattachToOldMaster(mouse); +@@ -4857,7 +4852,6 @@ ProcGrabPointer(ClientPtr client) + GrabPtr grab; + GrabMask mask; + WindowPtr confineTo; +- CursorPtr oldCursor; + BYTE status; + + REQUEST(xGrabPointerReq); +@@ -4880,15 +4874,10 @@ ProcGrabPointer(ClientPtr client) + return rc; + } + +- oldCursor = NullCursor; + grab = device->deviceGrab.grab; + +- if (grab) { +- if (grab->confineTo && !confineTo) +- ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, +- FALSE); +- oldCursor = grab->cursor; +- } ++ if (grab && grab->confineTo && !confineTo) ++ ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE); + + mask.core = stuff->eventMask; + +@@ -4898,9 +4887,6 @@ ProcGrabPointer(ClientPtr client) + if (rc != Success) + return rc; + +- if (oldCursor && status == GrabSuccess) +- FreeCursor(oldCursor, (Cursor) 0); +- + rep = (xGrabPointerReply) { + .type = X_Reply, + .status = status, +@@ -5104,6 +5090,8 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev, + xi2mask_merge(tempGrab->xi2mask, mask->xi2mask); + tempGrab->device = dev; + tempGrab->cursor = cursor; ++ if (cursor) ++ tempGrab->cursor->refcnt++; + tempGrab->confineTo = confineTo; + tempGrab->grabtype = grabtype; + (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE); +-- +1.8.2.1 + diff --git a/0032-Xi-fix-warning-remove-unused-rc.patch b/0032-Xi-fix-warning-remove-unused-rc.patch new file mode 100644 index 0000000..d216a02 --- /dev/null +++ b/0032-Xi-fix-warning-remove-unused-rc.patch @@ -0,0 +1,26 @@ +From 61259f5f0d03700751e60c0a9c95791dbca8cc9e Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Mon, 13 May 2013 15:22:12 +1000 +Subject: [PATCH 32/35] Xi: fix warning - remove unused 'rc' + +Signed-off-by: Peter Hutterer +(cherry picked from commit fd5ea0237db6d725a48f76b706135df9d3246b82) +--- + Xi/exevents.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/Xi/exevents.c b/Xi/exevents.c +index a4120de..b1318ab 100644 +--- a/Xi/exevents.c ++++ b/Xi/exevents.c +@@ -1036,7 +1036,6 @@ DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti, + static void + ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti) + { +- int rc; + ClientPtr client; + XID error; + GrabPtr grab = ti->listeners[0].grab; +-- +1.8.2.1 + diff --git a/0033-dix-call-UpdateDeviceState-for-emulated-TouchEndEven.patch b/0033-dix-call-UpdateDeviceState-for-emulated-TouchEndEven.patch new file mode 100644 index 0000000..764bd0c --- /dev/null +++ b/0033-dix-call-UpdateDeviceState-for-emulated-TouchEndEven.patch @@ -0,0 +1,51 @@ +From 2844b01a8571d30caa36f3bb22a64be5ed730062 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Tue, 14 May 2013 14:51:31 +1000 +Subject: [PATCH 33/35] dix: call UpdateDeviceState() for emulated + TouchEndEvents + +ProcessTouchEvents() calls UDS for all touch events, but if the event type +was switched to TouchUpdate(pending end) UDS is a noop. + +Daniel Drake found this can cause stuck buttons if a touch grab is +activated, rejected and the touch event is passed to a regular listener. +This sequence causes the TouchEnd to be changed to TouchUpdate(pending end). + +The actual TouchEnd event is later generated by the server once it is passed +to the next listener. UDS is never called for this event, thus the button +remains logically down. + +A previous patch suggested for UDS to handle TouchUpdate events [1], however +this would release the button when the first TouchEvent is processed, not +when the last grab has been released (as is the case for sync pointer +grabs). A client may thus have the grab on the device, receive a ButtonPress +but see the button logically up in an XQueryPointer request. + +This patch adds a call to UDS to TouchEmitTouchEnd(). The device state must +be updated once a TouchEnd event was sent to the last grabbing listener and +the number of grabs on the touchpoint is 0. + +[1] http://patchwork.freedesktop.org/patch/13464/ + +Signed-off-by: Peter Hutterer +(cherry picked from commit 35c2e263db01b2b61354298e5e85aa3cae8ac317) +--- + dix/touch.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/dix/touch.c b/dix/touch.c +index 110b1cc..a4b6d7e 100644 +--- a/dix/touch.c ++++ b/dix/touch.c +@@ -1122,6 +1122,8 @@ TouchEmitTouchEnd(DeviceIntPtr dev, TouchPointInfoPtr ti, int flags, XID resourc + TouchDeliverDeviceClassesChangedEvent(ti, GetTimeInMillis(), resource); + GetDixTouchEnd(&event, dev, ti, flags); + DeliverTouchEvents(dev, ti, &event, resource); ++ if (ti->num_grabs == 0) ++ UpdateDeviceState(dev, &event.device_event); + } + + void +-- +1.8.2.1 + diff --git a/0034-Abstract-cursor-refcounting.patch b/0034-Abstract-cursor-refcounting.patch new file mode 100644 index 0000000..277db3d --- /dev/null +++ b/0034-Abstract-cursor-refcounting.patch @@ -0,0 +1,407 @@ +From edbae190d409f1042102d30dd5cc6ba1af5555b4 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Wed, 15 May 2013 19:01:11 +1000 +Subject: [PATCH 34/35] Abstract cursor refcounting + +Too many callers relied on the refcnt being handled correctly. Use a simple +wrapper to handle that case. + +Signed-off-by: Peter Hutterer +(cherry picked from commit 9a5ad65330693b3273972b63d10f2907d9ab954a) +--- + Xext/saver.c | 8 ++++---- + dix/cursor.c | 33 ++++++++++++++++++++++++++++++++- + dix/events.c | 20 ++++++-------------- + dix/grabs.c | 8 ++------ + dix/window.c | 15 +++++---------- + hw/xfree86/modes/xf86Cursors.c | 4 ++-- + hw/xfree86/ramdac/xf86Cursor.c | 28 ++++++++++++++-------------- + include/cursor.h | 4 ++++ + render/animcur.c | 3 +-- + xfixes/cursor.c | 6 +++--- + 10 files changed, 73 insertions(+), 56 deletions(-) + +diff --git a/Xext/saver.c b/Xext/saver.c +index 8de043f..fe81bc4 100644 +--- a/Xext/saver.c ++++ b/Xext/saver.c +@@ -531,15 +531,16 @@ CreateSaverWindow(ScreenPtr pScreen) + mask |= CWBorderPixmap; + } + if (pAttr->pCursor) { ++ CursorPtr cursor; + if (!pWin->optional) + if (!MakeWindowOptional(pWin)) { + FreeResource(pWin->drawable.id, RT_NONE); + return FALSE; + } +- pAttr->pCursor->refcnt++; ++ cursor = RefCursor(pAttr->pCursor); + if (pWin->optional->cursor) + FreeCursor(pWin->optional->cursor, (Cursor) 0); +- pWin->optional->cursor = pAttr->pCursor; ++ pWin->optional->cursor = cursor; + pWin->cursorIsNone = FALSE; + CheckWindowOptionalNeed(pWin); + mask |= CWCursor; +@@ -1065,8 +1066,7 @@ ScreenSaverSetAttributes(ClientPtr client) + client->errorValue = cursorID; + goto PatchUp; + } +- pCursor->refcnt++; +- pAttr->pCursor = pCursor; ++ pAttr->pCursor = RefCursor(pCursor); + pAttr->mask &= ~CWCursor; + } + break; +diff --git a/dix/cursor.c b/dix/cursor.c +index 1ee127a..0820b18 100644 +--- a/dix/cursor.c ++++ b/dix/cursor.c +@@ -114,9 +114,13 @@ FreeCursor(pointer value, XID cid) + ScreenPtr pscr; + DeviceIntPtr pDev = NULL; /* unused anyway */ + +- if (--pCurs->refcnt != 0) ++ ++ UnrefCursor(pCurs); ++ if (CursorRefCount(pCurs) != 0) + return Success; + ++ BUG_WARN(CursorRefCount(pCurs) < 0); ++ + for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { + pscr = screenInfo.screens[nscr]; + (void) (*pscr->UnrealizeCursor) (pDev, pscr, pCurs); +@@ -127,6 +131,33 @@ FreeCursor(pointer value, XID cid) + return Success; + } + ++CursorPtr ++RefCursor(CursorPtr cursor) ++{ ++ ErrorF("%s ::::: cursor is %p", __func__, cursor); ++ if (cursor) { ++ xorg_backtrace(); ++ cursor->refcnt++; ++ } ++ ErrorF("\n"); ++ return cursor; ++} ++ ++CursorPtr ++UnrefCursor(CursorPtr cursor) ++{ ++ if (cursor) ++ cursor->refcnt--; ++ return cursor; ++} ++ ++int ++CursorRefCount(const CursorPtr cursor) ++{ ++ return cursor ? cursor->refcnt : 0; ++} ++ ++ + /* + * We check for empty cursors so that we won't have to display them + */ +diff --git a/dix/events.c b/dix/events.c +index 64a8f15..4d50a24 100644 +--- a/dix/events.c ++++ b/dix/events.c +@@ -931,8 +931,7 @@ ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) + + (*pScreen->DisplayCursor) (pDev, pScreen, cursor); + FreeCursor(pSprite->current, (Cursor) 0); +- pSprite->current = cursor; +- pSprite->current->refcnt++; ++ pSprite->current = RefCursor(cursor); + } + } + +@@ -3207,11 +3206,10 @@ InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) + pSprite->pEnqueueScreen = screenInfo.screens[0]; + pSprite->pDequeueScreen = pSprite->pEnqueueScreen; + } +- if (pCursor) +- pCursor->refcnt++; ++ pCursor = RefCursor(pCursor); + if (pSprite->current) + FreeCursor(pSprite->current, None); +- pSprite->current = pCursor; ++ pSprite->current = RefCursor(pCursor); + + if (pScreen) { + (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current); +@@ -3290,9 +3288,7 @@ UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen) + pSprite->hotLimits.x2 = pScreen->width; + pSprite->hotLimits.y2 = pScreen->height; + pSprite->win = win; +- pCursor = wCursor(win); +- if (pCursor) +- pCursor->refcnt++; ++ pCursor = RefCursor(wCursor(win)); + if (pSprite->current) + FreeCursor(pSprite->current, 0); + pSprite->current = pCursor; +@@ -4942,9 +4938,7 @@ ProcChangeActivePointerGrab(ClientPtr client) + (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) + return Success; + oldCursor = grab->cursor; +- grab->cursor = newCursor; +- if (newCursor) +- newCursor->refcnt++; ++ grab->cursor = RefCursor(newCursor); + PostNewCursor(device); + if (oldCursor) + FreeCursor(oldCursor, (Cursor) 0); +@@ -5089,9 +5083,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev, + else + xi2mask_merge(tempGrab->xi2mask, mask->xi2mask); + tempGrab->device = dev; +- tempGrab->cursor = cursor; +- if (cursor) +- tempGrab->cursor->refcnt++; ++ tempGrab->cursor = RefCursor(cursor); + tempGrab->confineTo = confineTo; + tempGrab->grabtype = grabtype; + (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE); +diff --git a/dix/grabs.c b/dix/grabs.c +index b254ddc..a03897a 100644 +--- a/dix/grabs.c ++++ b/dix/grabs.c +@@ -241,13 +241,11 @@ CreateGrab(int client, DeviceIntPtr device, DeviceIntPtr modDevice, + grab->detail.exact = keybut; + grab->detail.pMask = NULL; + grab->confineTo = confineTo; +- grab->cursor = cursor; ++ grab->cursor = RefCursor(cursor); + grab->next = NULL; + + if (grabtype == XI2) + xi2mask_merge(grab->xi2mask, mask->xi2mask); +- if (cursor) +- cursor->refcnt++; + return grab; + + } +@@ -274,9 +272,6 @@ CopyGrab(GrabPtr dst, const GrabPtr src) + Mask *details_mask = NULL; + XI2Mask *xi2mask; + +- if (src->cursor) +- src->cursor->refcnt++; +- + if (src->modifiersDetail.pMask) { + int len = MasksPerDetailMask * sizeof(Mask); + +@@ -314,6 +309,7 @@ CopyGrab(GrabPtr dst, const GrabPtr src) + dst->modifiersDetail.pMask = mdetails_mask; + dst->detail.pMask = details_mask; + dst->xi2mask = xi2mask; ++ dst->cursor = RefCursor(src->cursor); + + xi2mask_merge(dst->xi2mask, src->xi2mask); + +diff --git a/dix/window.c b/dix/window.c +index a5b28a6..8e61779 100644 +--- a/dix/window.c ++++ b/dix/window.c +@@ -547,8 +547,7 @@ InitRootWindow(WindowPtr pWin) + (*pScreen->PositionWindow) (pWin, 0, 0); + + pWin->cursorIsNone = FALSE; +- pWin->optional->cursor = rootCursor; +- rootCursor->refcnt++; ++ pWin->optional->cursor = RefCursor(rootCursor); + + if (party_like_its_1989) { + MakeRootTile(pWin); +@@ -1416,8 +1415,7 @@ ChangeWindowAttributes(WindowPtr pWin, Mask vmask, XID *vlist, ClientPtr client) + else if (pWin->parent && pCursor == wCursor(pWin->parent)) + checkOptional = TRUE; + pOldCursor = pWin->optional->cursor; +- pWin->optional->cursor = pCursor; +- pCursor->refcnt++; ++ pWin->optional->cursor = RefCursor(pCursor); + pWin->cursorIsNone = FALSE; + /* + * check on any children now matching the new cursor +@@ -3321,8 +3319,7 @@ MakeWindowOptional(WindowPtr pWin) + parentOptional = FindWindowWithOptional(pWin)->optional; + optional->visual = parentOptional->visual; + if (!pWin->cursorIsNone) { +- optional->cursor = parentOptional->cursor; +- optional->cursor->refcnt++; ++ optional->cursor = RefCursor(parentOptional->cursor); + } + else { + optional->cursor = None; +@@ -3410,8 +3407,7 @@ ChangeWindowDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev, CursorPtr pCursor) + if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor)) + pNode->cursor = None; + else { +- pNode->cursor = pCursor; +- pCursor->refcnt++; ++ pNode->cursor = RefCursor(pCursor); + } + + pNode = pPrev = NULL; +@@ -3419,8 +3415,7 @@ ChangeWindowDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev, CursorPtr pCursor) + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) { + if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev)) { + if (pNode->cursor == None) { /* inherited from parent */ +- pNode->cursor = pOldCursor; +- pOldCursor->refcnt++; ++ pNode->cursor = RefCursor(pOldCursor); + } + else if (pNode->cursor == pCursor) { + pNode->cursor = None; +diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c +index 634ee3f..2b0db34 100644 +--- a/hw/xfree86/modes/xf86Cursors.c ++++ b/hw/xfree86/modes/xf86Cursors.c +@@ -481,7 +481,7 @@ xf86_use_hw_cursor(ScreenPtr screen, CursorPtr cursor) + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; + +- ++cursor->refcnt; ++ cursor = RefCursor(cursor); + if (xf86_config->cursor) + FreeCursor(xf86_config->cursor, None); + xf86_config->cursor = cursor; +@@ -500,7 +500,7 @@ xf86_use_hw_cursor_argb(ScreenPtr screen, CursorPtr cursor) + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; + +- ++cursor->refcnt; ++ cursor = RefCursor(cursor); + if (xf86_config->cursor) + FreeCursor(xf86_config->cursor, None); + xf86_config->cursor = cursor; +diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c +index 8d48a75..f30bd33 100644 +--- a/hw/xfree86/ramdac/xf86Cursor.c ++++ b/hw/xfree86/ramdac/xf86Cursor.c +@@ -272,7 +272,7 @@ xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs) + (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, + xf86CursorScreenKey); + +- if (pCurs->refcnt <= 1) ++ if (CursorRefCount(pCurs) <= 1) + dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen, + NULL); + +@@ -286,7 +286,7 @@ xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs) + (xf86CursorScreenPtr) dixLookupPrivate(&pScreen->devPrivates, + xf86CursorScreenKey); + +- if (pCurs->refcnt <= 1) { ++ if (CursorRefCount(pCurs) <= 1) { + free(dixLookupScreenPrivate + (&pCurs->devPrivates, CursorScreenKey, pScreen)); + dixSetScreenPrivate(&pCurs->devPrivates, CursorScreenKey, pScreen, +@@ -323,37 +323,37 @@ xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, + /* only update for VCP, otherwise we get cursor jumps when removing a + sprite. The second cursor is never HW rendered anyway. */ + if (GetMaster(pDev, MASTER_POINTER) == inputInfo.pointer) { +- pCurs->refcnt++; ++ CursorPtr cursor = RefCursor(pCurs); + if (ScreenPriv->CurrentCursor) + FreeCursor(ScreenPriv->CurrentCursor, None); +- ScreenPriv->CurrentCursor = pCurs; ++ ScreenPriv->CurrentCursor = cursor; + ScreenPriv->x = x; + ScreenPriv->y = y; + ScreenPriv->CursorToRestore = NULL; +- ScreenPriv->HotX = pCurs->bits->xhot; +- ScreenPriv->HotY = pCurs->bits->yhot; ++ ScreenPriv->HotX = cursor->bits->xhot; ++ ScreenPriv->HotY = cursor->bits->yhot; + + if (!infoPtr->pScrn->vtSema) +- ScreenPriv->SavedCursor = pCurs; ++ ScreenPriv->SavedCursor = cursor; + + if (infoPtr->pScrn->vtSema && xorg_list_is_empty(&pScreen->pixmap_dirty_list) && + (ScreenPriv->ForceHWCursorCount || + (( + #ifdef ARGB_CURSOR +- pCurs->bits->argb && ++ cursor->bits->argb && + infoPtr->UseHWCursorARGB && +- (*infoPtr->UseHWCursorARGB)(pScreen, pCurs)) || +- (pCurs->bits->argb == 0 && ++ (*infoPtr->UseHWCursorARGB)(pScreen, cursor)) || ++ (cursor->bits->argb == 0 && + #endif +- (pCurs->bits->height <= infoPtr->MaxHeight) && +- (pCurs->bits->width <= infoPtr->MaxWidth) && +- (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor) (pScreen, pCurs)))))) { ++ (cursor->bits->height <= infoPtr->MaxHeight) && ++ (cursor->bits->width <= infoPtr->MaxWidth) && ++ (!infoPtr->UseHWCursor || (*infoPtr->UseHWCursor) (pScreen, cursor)))))) { + + if (ScreenPriv->SWCursor) /* remove the SW cursor */ + (*ScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, + NullCursor, x, y); + +- xf86SetCursor(pScreen, pCurs, x, y); ++ xf86SetCursor(pScreen, cursor, x, y); + ScreenPriv->SWCursor = FALSE; + ScreenPriv->isUp = TRUE; + +diff --git a/include/cursor.h b/include/cursor.h +index 0823251..89a650f 100644 +--- a/include/cursor.h ++++ b/include/cursor.h +@@ -71,6 +71,10 @@ extern _X_EXPORT CursorPtr rootCursor; + extern _X_EXPORT int FreeCursor(pointer /*pCurs */ , + XID /*cid */ ); + ++extern _X_EXPORT CursorPtr RefCursor(CursorPtr /* cursor */); ++extern _X_EXPORT CursorPtr UnrefCursor(CursorPtr /* cursor */); ++extern _X_EXPORT int CursorRefCount(const CursorPtr /* cursor */); ++ + extern _X_EXPORT int AllocARGBCursor(unsigned char * /*psrcbits */ , + unsigned char * /*pmaskbits */ , + CARD32 * /*argb */ , +diff --git a/render/animcur.c b/render/animcur.c +index 9cbba83..038c5b9 100644 +--- a/render/animcur.c ++++ b/render/animcur.c +@@ -383,8 +383,7 @@ AnimCursorCreate(CursorPtr *cursors, CARD32 *deltas, int ncursor, + ac->elts = (AnimCurElt *) (ac + 1); + + for (i = 0; i < ncursor; i++) { +- cursors[i]->refcnt++; +- ac->elts[i].pCursor = cursors[i]; ++ ac->elts[i].pCursor = RefCursor(cursors[i]); + ac->elts[i].delay = deltas[i]; + } + +diff --git a/xfixes/cursor.c b/xfixes/cursor.c +index 568e717..cc6e059 100644 +--- a/xfixes/cursor.c ++++ b/xfixes/cursor.c +@@ -619,12 +619,12 @@ ReplaceCursorLookup(pointer value, XID id, pointer closure) + } + if (pCursor && pCursor != rcl->pNew) { + if ((*rcl->testCursor) (pCursor, rcl->closure)) { +- rcl->pNew->refcnt++; ++ CursorPtr curs = RefCursor(rcl->pNew); + /* either redirect reference or update resource database */ + if (pCursorRef) +- *pCursorRef = rcl->pNew; ++ *pCursorRef = curs; + else +- ChangeResourceValue(id, RT_CURSOR, rcl->pNew); ++ ChangeResourceValue(id, RT_CURSOR, curs); + FreeCursor(pCursor, cursor); + } + } +-- +1.8.2.1 + diff --git a/0035-dix-remove-logspam-in-RefCursor.patch b/0035-dix-remove-logspam-in-RefCursor.patch new file mode 100644 index 0000000..9604eb1 --- /dev/null +++ b/0035-dix-remove-logspam-in-RefCursor.patch @@ -0,0 +1,37 @@ +From ee84aff9b29c95a45b739844ea42e2ab501e30b3 Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Mon, 27 May 2013 13:46:49 +1000 +Subject: [PATCH 35/35] dix: remove logspam in RefCursor() + +This shouldn't have been in the patch + +Reported-by: Colin Harrison +Signed-off-by: Peter Hutterer +Reviewed-by: Keith Packard +Signed-off-by: Keith Packard +(cherry picked from commit c21344add2fc589df83b29be5831c36a372201bd) +--- + dix/cursor.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/dix/cursor.c b/dix/cursor.c +index 0820b18..cd8305c 100644 +--- a/dix/cursor.c ++++ b/dix/cursor.c +@@ -134,12 +134,8 @@ FreeCursor(pointer value, XID cid) + CursorPtr + RefCursor(CursorPtr cursor) + { +- ErrorF("%s ::::: cursor is %p", __func__, cursor); +- if (cursor) { +- xorg_backtrace(); ++ if (cursor) + cursor->refcnt++; +- } +- ErrorF("\n"); + return cursor; + } + +-- +1.8.2.1 + diff --git a/xorg-x11-server.spec b/xorg-x11-server.spec index 5d27afb..dfab9fc 100644 --- a/xorg-x11-server.spec +++ b/xorg-x11-server.spec @@ -42,7 +42,7 @@ Summary: X.Org X11 X server Name: xorg-x11-server Version: 1.14.1.901 -Release: 1%{?gitdate:.%{gitdate}}%{dist} +Release: 2%{?gitdate:.%{gitdate}}%{dist} URL: http://www.x.org License: MIT Group: User Interface/X @@ -104,6 +104,45 @@ Patch7052: 0001-xf86-return-NULL-for-compat-output-if-no-outputs.patch # mustard: make the default queue length bigger to calm abrt down Patch7064: 0001-mieq-Bump-default-queue-size-to-512.patch +# touch-grab-race condition bug backports +# https://bugs.freedesktop.org/show_bug.cgi?id=56578 +Patch8000: 0001-dix-plug-memory-leak-in-freeing-TouchClass.patch +Patch8001: 0002-dix-don-t-overwrite-proximity-focus-classes.patch +Patch8002: 0003-os-Reset-input-buffer-s-ignoreBytes-field.patch +Patch8003: 0004-dix-pre-scale-x-by-the-screen-device-resolution-rati.patch +Patch8004: 0005-dix-fix-device-scaling-to-use-a-min-max-range.patch +Patch8005: 0006-Xi-not-having-an-ownership-mask-does-not-mean-automa.patch +Patch8006: 0007-dix-don-t-prepend-an-activated-passive-grab-to-the-l.patch +Patch8007: 0008-Xi-if-we-delivered-a-TouchEnd-to-a-passive-grab-end-.patch +Patch8008: 0009-Xi-update-the-core-listener-state-if-we-delivered-th.patch +Patch8009: 0010-Xi-fix-lookup-in-ActivateEarlyAccept.patch +Patch8010: 0011-Xi-if-a-passive-async-grab-is-activated-from-an-emul.patch +Patch8011: 0012-Xi-return-Success-from-DeliverTouchEmulatedEvent-if-.patch +Patch8012: 0013-Xi-use-a-temp-variable-for-the-new-listener.patch +Patch8013: 0014-Xi-save-state-for-early-acceptance.patch +Patch8014: 0015-Xi-when-punting-to-a-new-owner-always-create-TouchEn.patch +Patch8015: 0016-Xi-use-public.processInputProc-to-replay-the-touch-h.patch +Patch8016: 0017-Xi-Don-t-emit-a-TouchEnd-event-to-a-frozen-device.patch +Patch8017: 0018-dix-move-EmitTouchEnd-to-touch.c.patch +Patch8018: 0019-dix-XAllowEvents-on-a-touch-event-means-accepting-it.patch +Patch8019: 0020-dix-invert-a-loop-condition.patch +Patch8020: 0021-dix-use-a-tmp-variable-for-the-to-be-removed-touch-l.patch +Patch8021: 0022-dix-drop-DeviceIntRec-s-activeGrab-struct.patch +Patch8022: 0023-dix-use-a-temporary-variable-for-listeners-0.patch +Patch8023: 0024-dix-freeing-a-null-grab-is-a-bug-complain-if-doing-s.patch +Patch8024: 0025-dix-AllocGrab-can-copy-if-an-argument-is-passed-in.patch +Patch8025: 0026-dix-always-copy-grabs-don-t-reference-them.patch +Patch8026: 0027-dix-remove-all-listeners-when-freeing-a-touch.patch +Patch8027: 0028-Move-TouchListenerGone-call-to-CloseDownClient.patch +Patch8028: 0029-Xi-check-for-HAS_ACCEPTED-only-for-grab-listeners.patch +Patch8029: 0030-dix-free-the-old-grab-when-activating-a-new-grab.patch +Patch8030: 0031-dix-fix-cursor-refcounting.patch +Patch8031: 0032-Xi-fix-warning-remove-unused-rc.patch +Patch8032: 0033-dix-call-UpdateDeviceState-for-emulated-TouchEndEven.patch +Patch8033: 0034-Abstract-cursor-refcounting.patch +Patch8034: 0035-dix-remove-logspam-in-RefCursor.patch + + # upstream in -next for 1.15, e21e183059df5975e7086850d1931edb2c1bbd06 %if !0%{?rhel} Patch7071: 0001-os-use-libunwind-to-generate-backtraces.patch @@ -581,6 +620,9 @@ rm -rf $RPM_BUILD_ROOT %{xserver_source_dir} %changelog +* Thu Jun 06 2013 Peter Hutterer 1.14.1.901-2 +- Backport the touch grab race condition patches from fdo #56578 + * Thu Jun 06 2013 Peter Hutterer 1.14.1.901-1 - xserver 1.14.2RC1