[PATCH] randr: Add additional cursor confinement hook in the ScreenRec

Christopher James Halse Rogers christopher.halse.rogers at canonical.com
Mon Dec 20 17:15:33 PST 2010


On Mon, 2010-11-15 at 16:23 -0500, Adam Jackson wrote:
> And use it to confine cursor motion to within the bounds of a single
> CRTC, iff all the CRTCs within a ScreenRec are reachable from each
> other.  If not you get the same "cursor floats within the bounding rect"
> behaviour you get now.
> 
> v2:
> - Fix a read-from-uninitialized typo in crtcs_adjacent
> - Silence a warning from crtc_bounds
> - Avoid over-exposing miPointerRec to the rest of DIX
> - Replace clever matrix math with simple depthi-first-search code from
>   Mikhail Gusarov
> 
> Signed-off-by: Adam Jackson <ajax at redhat.com>
> ---
>  include/scrnintstr.h |    4 +
>  mi/mipointer.c       |    3 +
>  randr/randr.c        |    2 +
>  randr/randrstr.h     |    4 +
>  randr/rrcrtc.c       |  154 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 167 insertions(+), 0 deletions(-)
> 

git chokes with conflicts with Keith's RandR 1.4 stuff on master,
although it's trivial to unconfuse it.

> diff --git a/include/scrnintstr.h b/include/scrnintstr.h
> index cd4fb70..ddd564d 100644
> --- a/include/scrnintstr.h
> +++ b/include/scrnintstr.h
> @@ -453,6 +453,9 @@ typedef    void (* DeviceCursorCleanupProcPtr)(
>          DeviceIntPtr /* pDev */,
>          ScreenPtr    /* pScreen */);
>  
> +typedef void (*ConstrainCursorHarderProcPtr)(
> +       DeviceIntPtr, ScreenPtr, int *, int *);
> +
>  typedef struct _Screen {
>      int			myNum;	/* index of this instance in Screens[] */
>      ATOM		id;
> @@ -533,6 +536,7 @@ typedef struct _Screen {
>      /* Cursor Procedures */
>  
>      ConstrainCursorProcPtr	ConstrainCursor;
> +    ConstrainCursorHarderProcPtr ConstrainCursorHarder;
>      CursorLimitsProcPtr		CursorLimits;
>      DisplayCursorProcPtr	DisplayCursor;
>      RealizeCursorProcPtr	RealizeCursor;
> diff --git a/mi/mipointer.c b/mi/mipointer.c
> index 554397a..9bfabb7 100644
> --- a/mi/mipointer.c
> +++ b/mi/mipointer.c
> @@ -529,6 +529,9 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
>      if (*y >= pPointer->limits.y2)
>  	*y = pPointer->limits.y2 - 1;
>  
> +    if (pScreen->ConstrainCursorHarder)
> +       pScreen->ConstrainCursorHarder(pDev, pScreen, x, y);
> +
>      if (pPointer->x == *x && pPointer->y == *y && 
>              pPointer->pScreen == pScreen) 
>          return;
> diff --git a/randr/randr.c b/randr/randr.c
> index 6077705..d337129 100644
> --- a/randr/randr.c
> +++ b/randr/randr.c
> @@ -270,6 +270,8 @@ Bool RRScreenInit(ScreenPtr pScreen)
>      
>      wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
>  
> +    pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
> +
>      pScrPriv->numOutputs = 0;
>      pScrPriv->outputs = NULL;
>      pScrPriv->numCrtcs = 0;
> diff --git a/randr/randrstr.h b/randr/randrstr.h
> index 7ea6080..048e827 100644
> --- a/randr/randrstr.h
> +++ b/randr/randrstr.h
> @@ -297,6 +297,7 @@ typedef struct _rrScrPriv {
>      int			    rate;
>      int			    size;
>  #endif
> +    Bool                   discontiguous;
>  } rrScrPrivRec, *rrScrPrivPtr;
>  
>  extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
> @@ -700,6 +701,9 @@ ProcRRGetPanning (ClientPtr client);
>  int
>  ProcRRSetPanning (ClientPtr client);
>  
> +void
> +RRConstrainCursorHarder (DeviceIntPtr, ScreenPtr, int *, int *);
> +
>  /* rrdispatch.c */
>  extern _X_EXPORT Bool
>  RRClientKnowsRates (ClientPtr	pClient);
> diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
> index 98206a2..9af4a38 100644
> --- a/randr/rrcrtc.c
> +++ b/randr/rrcrtc.c
> @@ -1,5 +1,6 @@
>  /*
>   * Copyright © 2006 Keith Packard
> + * Copyright 2010 Red Hat, Inc
>   *
>   * Permission to use, copy, modify, distribute, and sell this software and its
>   * documentation for any purpose is hereby granted without fee, provided that
> @@ -22,6 +23,7 @@
>  
>  #include "randrstr.h"
>  #include "swaprep.h"
> +#include "mipointer.h"
>  
>  RESTYPE	RRCrtcType;
>  
> @@ -292,6 +294,91 @@ RRCrtcPendingProperties (RRCrtcPtr crtc)
>      return FALSE;
>  }
>  
> +static void
> +crtc_bounds(RRCrtcPtr crtc, int *left, int *right, int *top, int *bottom)
> +{
> +    *left = crtc->x;
> +    *top = crtc->y;
> +
> +    switch (crtc->rotation) {
> +    case RR_Rotate_0:
> +    case RR_Rotate_180:
> +    default:
> +       *right = crtc->x + crtc->mode->mode.width;
> +       *bottom = crtc->y + crtc->mode->mode.height;
> +       return;
> +    case RR_Rotate_90:
> +    case RR_Rotate_270:
> +       *right = crtc->x + crtc->mode->mode.height;
> +       *bottom = crtc->y + crtc->mode->mode.width;
> +       return;
> +    }
> +}
> +
> +/* overlapping counts as adjacent */
> +static Bool
> +crtcs_adjacent(const RRCrtcPtr a, const RRCrtcPtr b)
> +{
> +    int al, ar, at, ab;
> +    int bl, br, bt, bb;
> +    int cl, cr, ct, cb;

The purpose of al, ar, bl, br etc are relatively from the nameing, but
the cl etc aren't.  It's a short function and staring at it for a moment
makes these clear, but maybe these could get more descriptive names to
save us poor hard-of-thinking folks?

> +
> +    crtc_bounds(a, &al, &ar, &at, &ab);
> +    crtc_bounds(b, &bl, &br, &bt, &bb);
> +
> +    cl = max(al, bl);
> +    cr = min(ar, br);
> +    ct = max(at, bt);
> +    cb = min(ab, bb);
> +
> +    return (cl <= cr) && (ct <= cb);
> +}
> +
> +/* Depth-first search and mark all CRTCs reachable from cur */
> +static void
> +dfs (rrScrPrivPtr pScrPriv, int *reachable, int cur)

Could this perhaps have a more obvious name?  Maybe
mark_reachable_crtcs?

> +{
> +    int i;
> +    reachable[cur] = TRUE;
> +    for (i = 0; i < pScrPriv->numCrtcs; ++i) {
> +        if (reachable[i] || !pScrPriv->crtcs[i]->mode)
> +            continue;
> +        if (crtcs_adjacent(pScrPriv->crtcs[cur], pScrPriv->crtcs[i]))
> +            dfs(pScrPriv, reachable, i);
> +    }
> +}
> +
> +static void
> +RRComputeContiguity (ScreenPtr pScreen)
> +{
> +    rrScrPriv(pScreen);
> +    Bool discontiguous = TRUE;
> +    int i, n = pScrPriv->numCrtcs;
> +
> +    int *reachable = calloc(1, n);

This doesn't quite look right to me?  Won't this allocate enough memory
for n chars, rather than n ints?

Also, wouldn't it be more obvious to have this as a Bool array?

> +    if (!reachable)
> +        goto out;
> +
> +    /* Find first enabled CRTC and start search for reachable CRTCs from it */
> +    for (i = 0; i < n; ++i) {
> +        if (pScrPriv->crtcs[i]->mode) {
> +            dfs(pScrPriv, reachable, i);
> +            break;
> +        }
> +    }
> +
> +    /* Check that all enabled CRTCs were marked as reachable */
> +    for (i = 0; i < n; ++i)
> +        if (pScrPriv->crtcs[i]->mode && !reachable[i])
> +            goto out;
> +
> +    discontiguous = FALSE;
> +
> +out:
> +    free(reachable);
> +    pScrPriv->discontiguous = discontiguous;
> +}
> +
>  /*
>   * Request that the Crtc be reconfigured
>   */
> @@ -306,6 +393,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
>  {
>      ScreenPtr	pScreen = crtc->pScreen;
>      Bool	ret = FALSE;
> +    Bool	recompute = TRUE;
>      rrScrPriv(pScreen);
>  
>      /* See if nothing changed */
> @@ -318,6 +406,7 @@ RRCrtcSet (RRCrtcPtr    crtc,
>  	!RRCrtcPendingProperties (crtc) &&
>  	!RRCrtcPendingTransform (crtc))
>      {
> +	recompute = FALSE;
>  	ret = TRUE;
>      }
>      else
> @@ -381,6 +470,10 @@ RRCrtcSet (RRCrtcPtr    crtc,
>  		RRPostPendingProperties (outputs[o]);
>  	}
>      }
> +
> +    if (recompute)
> +       RRComputeContiguity(pScreen);
> +
>      return ret;
>  }
>  
> @@ -1349,3 +1442,64 @@ ProcRRGetCrtcTransform (ClientPtr client)
>      free(reply);
>      return Success;
>  }
> +
> +void
> +RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int *x, int *y)
> +{
> +    rrScrPriv (pScreen);
> +    int i;
> +
> +    /* intentional dead space -> let it float */
> +    if (pScrPriv->discontiguous)
> +       return;
> +
> +    /* if we're moving inside a crtc, we're fine */
> +    for (i = 0; i < pScrPriv->numCrtcs; i++) {
> +       RRCrtcPtr crtc = pScrPriv->crtcs[i];
> +
> +       int left, right, top, bottom;
> +
> +       if (!crtc->mode)
> +           continue;
> +
> +       crtc_bounds(crtc, &left, &right, &top, &bottom);
> +
> +       if ((*x >= left) && (*x <= right) && (*y >= top) && (*y <= bottom))
> +           return;
> +    }
> +
> +    /* if we're trying to escape, clamp to the CRTC we're coming from */
> +    for (i = 0; i < pScrPriv->numCrtcs; i++) {
> +       RRCrtcPtr crtc = pScrPriv->crtcs[i];
> +       int nx, ny;
> +       int left, right, top, bottom;
> +
> +       if (!crtc->mode)
> +           continue;
> +
> +       crtc_bounds(crtc, &left, &right, &top, &bottom);
> +       miPointerGetPosition(pDev, &nx, &ny);
> +
> +       if ((nx >= left) && (nx <= right) && (ny >= top) && (ny <= bottom)) {
> +           if ((*x <= left) || (*x >= right)) {
> +               int dx = *x - nx;
> +
> +               if (dx > 0)
> +                   *x = right;
> +               else if (dx < 0)
> +                   *x = left;
> +           }
> +
> +           if ((*y <= top) || (*y >= bottom)) {
> +               int dy = *y - ny;
> +
> +               if (dy > 0)
> +                   *y = bottom;
> +               else if (dy < 0)
> +                   *y = top;
> +           }
> +
> +           return;
> +       }
> +    }
> +}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: This is a digitally signed message part
URL: <http://lists.x.org/archives/xorg-devel/attachments/20101221/a7d5303c/attachment-0001.pgp>


More information about the xorg-devel mailing list