[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