[PATCH] Handle animated cursor on shared sprite

Pierre Ossman ossman at cendio.se
Wed Oct 12 09:05:31 UTC 2016


Sprites (and hence cursors) can be shared between multiple devices.
However the animation code was not prepared for this and could wind
up in a case where it would continue to animate a free:d cursor.
---
 include/inputstr.h | 14 ++++-----
 render/animcur.c   | 85 +++++++++++++++++++++++++++++-------------------------
 2 files changed, 51 insertions(+), 48 deletions(-)

diff --git a/include/inputstr.h b/include/inputstr.h
index 568f5f9..a485f5e 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -246,6 +246,12 @@ typedef struct _SpriteRec {
     ScreenPtr pEnqueueScreen;
     ScreenPtr pDequeueScreen;
 +    /* keep states for animated cursor */
+    struct {
+        ScreenPtr pScreen;
+        int elt;
+        CARD32 time;
+    } anim;
 } SpriteRec;
  typedef struct _KeyClassRec {
@@ -509,14 +515,6 @@ typedef struct _SpriteInfoRec {
     DeviceIntPtr paired;        /* The paired device. Keyboard if
                                    spriteOwner is TRUE, otherwise the
                                    pointer that owns the sprite. */
-
-    /* keep states for animated cursor */
-    struct {
-        CursorPtr pCursor;
-        ScreenPtr pScreen;
-        int elt;
-        CARD32 time;
-    } anim;
 } SpriteInfoRec, *SpriteInfoPtr;
  /* device types */
diff --git a/render/animcur.c b/render/animcur.c
index 52e6b8b..fc87e0d 100644
--- a/render/animcur.c
+++ b/render/animcur.c
@@ -142,35 +142,42 @@ AnimCurTimerNotify(OsTimerPtr timer, CARD32 now, void *arg)
     CARD32 soonest = ~0;       /* earliest time to wakeup again */
      for (dev = inputInfo.devices; dev; dev = dev->next) {
-        if (IsPointerDevice(dev) && pScreen == dev->spriteInfo->anim.pScreen) {
-            if (!activeDevice)
-                activeDevice = TRUE;
-
-            if ((INT32) (now - dev->spriteInfo->anim.time) >= 0) {
-                AnimCurPtr ac = GetAnimCur(dev->spriteInfo->anim.pCursor);
-                int elt = (dev->spriteInfo->anim.elt + 1) % ac->nelt;
-                DisplayCursorProcPtr DisplayCursor;
-
-                /*
-                 * Not a simple Unwrap/Wrap as this
-                 * isn't called along the DisplayCursor
-                 * wrapper chain.
-                 */
-                DisplayCursor = pScreen->DisplayCursor;
-                pScreen->DisplayCursor = as->DisplayCursor;
-                (void) (*pScreen->DisplayCursor) (dev,
-                                                  pScreen,
-                                                  ac->elts[elt].pCursor);
-                as->DisplayCursor = pScreen->DisplayCursor;
-                pScreen->DisplayCursor = DisplayCursor;
-
-                dev->spriteInfo->anim.elt = elt;
-                dev->spriteInfo->anim.time = now + ac->elts[elt].delay;
-            }
-
-            if (soonest > dev->spriteInfo->anim.time)
-                soonest = dev->spriteInfo->anim.time;
+        if (!IsPointerDevice(dev))
+            continue;
+        if (!dev->spriteInfo->spriteOwner)
+            continue;
+        if (!IsAnimCur(dev->spriteInfo->sprite->current))
+            continue;
+        if (pScreen != dev->spriteInfo->sprite->anim.pScreen)
+            continue;
+
+        if (!activeDevice)
+            activeDevice = TRUE;
+
+        if ((INT32) (now - dev->spriteInfo->sprite->anim.time) >= 0) {
+            AnimCurPtr ac = GetAnimCur(dev->spriteInfo->sprite->current);
+            int elt = (dev->spriteInfo->sprite->anim.elt + 1) % ac->nelt;
+            DisplayCursorProcPtr DisplayCursor;
+
+            /*
+             * Not a simple Unwrap/Wrap as this
+             * isn't called along the DisplayCursor
+             * wrapper chain.
+             */
+            DisplayCursor = pScreen->DisplayCursor;
+            pScreen->DisplayCursor = as->DisplayCursor;
+            (void) (*pScreen->DisplayCursor) (dev,
+                                              pScreen,
+                                              ac->elts[elt].pCursor);
+            as->DisplayCursor = pScreen->DisplayCursor;
+            pScreen->DisplayCursor = DisplayCursor;
+
+            dev->spriteInfo->sprite->anim.elt = elt;
+            dev->spriteInfo->sprite->anim.time = now + ac->elts[elt].delay;
         }
+
+        if (soonest > dev->spriteInfo->sprite->anim.time)
+            soonest = dev->spriteInfo->sprite->anim.time;
     }
      if (activeDevice)
@@ -192,17 +199,17 @@ AnimCurDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
      Unwrap(as, pScreen, DisplayCursor);
     if (IsAnimCur(pCursor)) {
-        if (pCursor != pDev->spriteInfo->anim.pCursor) {
+        if (pDev->spriteInfo->spriteOwner &&
+            (pCursor != pDev->spriteInfo->sprite->current)) {
             AnimCurPtr ac = GetAnimCur(pCursor);
              ret = (*pScreen->DisplayCursor)
                 (pDev, pScreen, ac->elts[0].pCursor);
             if (ret) {
-                pDev->spriteInfo->anim.elt = 0;
-                pDev->spriteInfo->anim.time =
+                pDev->spriteInfo->sprite->anim.elt = 0;
+                pDev->spriteInfo->sprite->anim.time =
                     GetTimeInMillis() + ac->elts[0].delay;
-                pDev->spriteInfo->anim.pCursor = pCursor;
-                pDev->spriteInfo->anim.pScreen = pScreen;
+                pDev->spriteInfo->sprite->anim.pScreen = pScreen;
                  if (!as->timer_set) {
                     TimerSet(as->timer, TimerAbsolute, pDev->spriteInfo->anim.time,
@@ -214,11 +221,8 @@ AnimCurDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
         else
             ret = TRUE;
     }
-    else {
-        pDev->spriteInfo->anim.pCursor = 0;
-        pDev->spriteInfo->anim.pScreen = 0;
+    else
         ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor);
-    }
     Wrap(as, pScreen, DisplayCursor, AnimCurDisplayCursor);
     return ret;
 }
@@ -231,8 +235,9 @@ AnimCurSetCursorPosition(DeviceIntPtr pDev,
     Bool ret;
      Unwrap(as, pScreen, SetCursorPosition);
-    if (pDev->spriteInfo->anim.pCursor) {
-        pDev->spriteInfo->anim.pScreen = pScreen;
+    if (pDev->spriteInfo->spriteOwner &&
+        IsAnimCur(pDev->spriteInfo->sprite->current)) {
+        pDev->spriteInfo->sprite->anim.pScreen = pScreen;
          if (!as->timer_set) {
             TimerSet(as->timer, TimerAbsolute, pDev->spriteInfo->anim.time,
@@ -296,7 +301,7 @@ AnimCurRecolorCursor(DeviceIntPtr pDev,
         for (i = 0; i < ac->nelt; i++)
             (*pScreen->RecolorCursor) (pDev, pScreen, ac->elts[i].pCursor,
                                        displayed &&
-                                       pDev->spriteInfo->anim.elt == i);
+                                       pDev->spriteInfo->sprite->anim.elt == i);
     }
     else
         (*pScreen->RecolorCursor) (pDev, pScreen, pCursor, displayed);
-- 
2.7.4



More information about the xorg-devel mailing list