[PATCH] Handle animated cursor on shared sprite
Alan Hourihane
alanh at fairlite.co.uk
Mon Dec 11 16:43:28 UTC 2017
Keith/Adam,
Another patch for cursor issues that can cause the Xserver to crash
that's over 12 months old and hasn't been committed or commented on.
Can you take a look at this too ?
Thanks,
Alan.
On 12/10/16 10:05, Pierre Ossman wrote:
> 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);
More information about the xorg-devel
mailing list