[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xorg-server: Changes to 'upstream-experimental'



 Xext/saver.c                        |    8 -
 Xi/exevents.c                       |  155 +++++++++++++++++++-----------------
 Xi/ungrdevb.c                       |    2 
 Xi/ungrdevk.c                       |    2 
 Xi/xipassivegrab.c                  |    2 
 configure.ac                        |    6 -
 dix/cursor.c                        |   29 ++++++
 dix/devices.c                       |    4 
 dix/dispatch.c                      |    3 
 dix/events.c                        |  101 ++++++++++++-----------
 dix/grabs.c                         |   21 ++--
 dix/main.c                          |    3 
 dix/pixmap.c                        |    2 
 dix/touch.c                         |  114 ++++++++++++++++++++++----
 dix/window.c                        |   15 +--
 fb/fbpixmap.c                       |    1 
 glx/glxdri.c                        |    2 
 hw/xfree86/common/xf86platformBus.c |    8 +
 hw/xfree86/modes/xf86Crtc.c         |   34 +++++--
 hw/xfree86/modes/xf86Cursors.c      |    4 
 hw/xfree86/ramdac/xf86Cursor.c      |   28 +++---
 include/cursor.h                    |    4 
 include/dixgrabs.h                  |    2 
 include/eventstr.h                  |    1 
 include/input.h                     |    2 
 include/inputstr.h                  |    2 
 render/animcur.c                    |    3 
 xfixes/cursor.c                     |    6 -
 28 files changed, 359 insertions(+), 205 deletions(-)

New commits:
commit 4ebd618bc5ef71507e708e7191091828eca3a7e8
Author: Matt Dew <marcoz@osource.org>
Date:   Thu Jul 25 22:24:00 2013 -0600

    Bah, bad rev number. Fixed:  changed 1.14.3-rc1 to 1.14.2.901

diff --git a/configure.ac b/configure.ac
index 8738813..271e49d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,7 +26,7 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.60)
-AC_INIT([xorg-server], 1.14.3-rc1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+AC_INIT([xorg-server], 1.14.2.901, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
 RELEASE_DATE="2013-07-25"
 RELEASE_NAME="Act semi-normal-rc1"
 AC_CONFIG_SRCDIR([Makefile.am])

commit fef66ffe7a7e899a9126a1e431b94d881163b00d
Author: Matt Dew <marcoz@osource.org>
Date:   Thu Jul 25 22:02:26 2013 -0600

    bump rev from 1.14.2 to 1.14.3-rc1

diff --git a/configure.ac b/configure.ac
index 99e3cd6..8738813 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,9 +26,9 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.60)
-AC_INIT([xorg-server], 1.14.2, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
-RELEASE_DATE="2013-06-25"
-RELEASE_NAME="Act Abnormal"
+AC_INIT([xorg-server], 1.14.3-rc1, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+RELEASE_DATE="2013-07-25"
+RELEASE_NAME="Act semi-normal-rc1"
 AC_CONFIG_SRCDIR([Makefile.am])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 

commit 2cd62dc02b67c70d2417b2ccd307ead9596a2967
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Fri Mar 1 08:43:58 2013 +1000

    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 <peter.hutterer@who-t.net>
    Reviewed-by: Keith Packard <keithp@keithp.com>
    (cherry picked from commit 9978b57b8d94f061d72a67b99a02b0ba16a11429)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 91281ae..067e6b3 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1373,7 +1373,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);
@@ -1395,7 +1395,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;

commit c203568905bcbb65fb1e079b626d2c1e90ecb72d
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon May 13 15:22:12 2013 +1000

    Xi: fix warning - remove unused 'rc'
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    (cherry picked from commit fd5ea0237db6d725a48f76b706135df9d3246b82)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 30e48f0..91281ae 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;

commit 93f063c40dc4b339ae9114551071c57b52d98dba
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Fri Jul 12 14:10:10 2013 +1000

    dix: UpdateTouchesForGrab must only free the listener grab if it is non-NULL
    
    If a client calls XIGrabDevice in response to a ButtonPress event (regular
    event selection), the device will have a grab, but listener->grab is NULL.
    
    Check for that, to avoid logspam.
    
    [ 26293.863] (EE) BUG: triggered 'if (!pGrab)'
    [ 26293.863] (EE) BUG: grabs.c:256 in FreeGrab()
    [ 26293.863] (EE)
    [ 26293.863] (EE) Backtrace:
    [ 26293.864] (EE) 0: /usr/bin/Xorg (FreeGrab+0x54) [0x45d3fc]
    [ 26293.864] (EE) 1: /usr/bin/Xorg (UpdateTouchesForGrab+0x135) [0x447d4e]
    [ 26293.864] (EE) 2: /usr/bin/Xorg (ActivatePointerGrab+0x1ba) [0x447f3d]
    [ 26293.864] (EE) 3: /usr/bin/Xorg (GrabDevice+0x3e6) [0x4503bc]
    [ 26293.864] (EE) 4: /usr/bin/Xorg (ProcXIGrabDevice+0x1f9) [0x5981b1]
    [ 26293.865] (EE) 5: /usr/bin/Xorg (ProcIDispatch+0x78) [0x58aa17]
    [ 26293.865] (EE) 6: /usr/bin/Xorg (Dispatch+0x30d) [0x43347e]
    [ 26293.865] (EE) 7: /usr/bin/Xorg (main+0x61d) [0x498175]
    [ 26293.865] (EE) 8: /lib64/libc.so.6 (__libc_start_main+0xf5) [0x3df5621b75]
    [ 26293.865] (EE) 9: /usr/bin/Xorg (_start+0x29) [0x423a19]
    [ 26293.866] (EE) 10: ? (?+0x29) [0x29]
    [ 26293.866] (EE)
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    Reviewed-by: Keith Packard <keithp@keithp.com>
    (cherry picked from commit 0e3be0b25fcfeff386bad132526352c2e45f1932)

diff --git a/dix/events.c b/dix/events.c
index f9b2ed7..c079f97 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1438,7 +1438,8 @@ UpdateTouchesForGrab(DeviceIntPtr mouse)
                 listener->type = LISTENER_POINTER_GRAB;
             else
                 listener->type = LISTENER_GRAB;
-            FreeGrab(listener->grab);
+            if (listener->grab)
+                FreeGrab(listener->grab);
             listener->grab = AllocGrab(grab);
         }
     }

commit ecd178e632a99ae2f12d2d9b6e9a48eaa421335d
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue Jul 9 13:27:19 2013 +1000

    dix: when ungrabbing an active grab, accept pointer grabs (#66720)
    
    Ungrabbing a device during an active touch grab rejects the grab. Ungrabbing
    a device during an active pointer grab accepts the grab.
    
    Rejection is not really an option for a pointer-emulated grab, if a client
    has a button mask on the window it would get a ButtonPress emulated after
    UngrabDevice. That is against the core grab behaviour.
    
    X.Org Bug 66720 <http://bugs.freedesktop.org/show_bug.cgi?id=66720>
    
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
    (cherry picked from commit 8eeaa74bc241acb41f1d3ed64971e0b01e794776)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index e1945b9..30e48f0 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1224,9 +1224,13 @@ ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev,
     else if (ev->reason == XIAcceptTouch) {
         int i;
 
-        /* Go through the motions of ending the touch if the listener has
+
+        /* For pointer-emulated listeners that ungrabbed the active grab,
+         * the state was forced to LISTENER_HAS_END. Still go
+         * through the motions of ending the touch if the listener has
          * already seen the end. This ensures that the touch record is ended in
-         * the server. */
+         * the server.
+         */
         if (ti->listeners[0].state == LISTENER_HAS_END)
             TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
 
@@ -1884,16 +1888,23 @@ DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
 
     if (listener->type == LISTENER_POINTER_REGULAR ||
         listener->type == LISTENER_POINTER_GRAB) {
-        rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
-                                       grab, xi2mask);
-
-         /* 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;
+        /* Note: If the active grab was ungrabbed, we already changed the
+         * state to LISTENER_HAS_END but still get here. So we mustn't
+         * actually send the event.
+         * This is part two of the hack in DeactivatePointerGrab
+         */
+        if (listener->state != LISTENER_HAS_END) {
+            rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
+                                           grab, xi2mask);
+
+             /* 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;
     }
 
diff --git a/dix/events.c b/dix/events.c
index 4d50a24..f9b2ed7 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -1519,13 +1519,20 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
     for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) {
         TouchPointInfoPtr ti = mouse->touch->touches + i;
         if (ti->active && TouchResourceIsOwner(ti, grab_resource)) {
+            int mode = XIRejectTouch;
             /* Rejecting will generate a TouchEnd, but we must not
                emulate a ButtonRelease here. So pretend the listener
                already has the end event */
             if (grab->grabtype == CORE || grab->grabtype == XI ||
-                    !xi2mask_isset(mouse->deviceGrab.grab->xi2mask, mouse, XI_TouchBegin))
+                    !xi2mask_isset(mouse->deviceGrab.grab->xi2mask, mouse, XI_TouchBegin)) {
+                mode = XIAcceptTouch;
+                /* NOTE: we set the state here, but
+                 * ProcessTouchOwnershipEvent() will still call
+                 * TouchEmitTouchEnd for this listener. The other half of
+                 * this hack is in DeliverTouchEndEvent */
                 ti->listeners[0].state = LISTENER_HAS_END;
-            TouchListenerAcceptReject(mouse, ti, 0, XIRejectTouch);
+            }
+            TouchListenerAcceptReject(mouse, ti, 0, mode);
         }
     }
 

commit 54a7ae04a8475df6ce87e52ff995de22fafc7c92
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Mon May 27 13:46:49 2013 +1000

    dix: remove logspam in RefCursor()
    
    This shouldn't have been in the patch
    
    Reported-by: Colin Harrison <colin.harrison@virgin.net>
    Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
    Reviewed-by: Keith Packard <keithp@keithp.com>
    Signed-off-by: Keith Packard <keithp@keithp.com>
    (cherry picked from commit c21344add2fc589df83b29be5831c36a372201bd)

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;
 }
 

commit 1e29b269fd712ae1e3552eeddd3529015baee7ae
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed May 15 19:01:11 2013 +1000

    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 <peter.hutterer@who-t.net>
    (cherry picked from commit 9a5ad65330693b3273972b63d10f2907d9ab954a)

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);
         }
     }

commit c0be1168fd3dd2eb01187789ddc30d7aab909a98
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Tue May 14 14:51:31 2013 +1000

    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 <peter.hutterer@who-t.net>
    (cherry picked from commit 35c2e263db01b2b61354298e5e85aa3cae8ac317)

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

commit 5c32bd0e2c104deaa2820c62289916fff6a4e3cd
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Fri May 3 15:07:58 2013 +1000

    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 <peter.hutterer@who-t.net>
    (cherry picked from commit 481702101b86fff003430e952dc65fb41eb56400)

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);

commit 0ee9704f3c70fa7cf77edef55d158ad78df72a25
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Fri May 3 15:02:05 2013 +1000

    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 <peter.hutterer@who-t.net>
    (cherry picked from commit 3093f78d17e48a506aab170a9089cd10e21af299)

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);
 }
 
 /**

commit ef0fff102d1feb5bccffc918da5c0dc7c0d28f3b
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Apr 24 14:46:06 2013 +1000

    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 <peter.hutterer@who-t.net>
    (cherry picked from commit 2566bdd8bc996cccde77b846819808c6239a89d2)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index 90cbcc5..e1945b9 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;

commit f3d63710d57aea0184ae07f0422a76b0fd6d415f
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Apr 24 14:40:31 2013 +1000

    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 <peter.hutterer@who-t.net>
    (cherry picked from commit 5b00fc52270e9cfdfe7ac1838a21defe50fc3d31)

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);
 

commit 6c880c143f6a32d3bbc529e4a0ab1663ddecf0a0
Author: Peter Hutterer <peter.hutterer@who-t.net>
Date:   Wed Apr 24 12:53:52 2013 +1000



Reply to: