randr: Add RRConstrainCursorHarder
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. v3: - Incorporate review feedback from Christopher James Halse Rogers v4: - Add mode field. Signed-off-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
810fbfa446
commit
56c90e29f0
|
@ -270,6 +270,8 @@ Bool RRScreenInit(ScreenPtr pScreen)
|
||||||
|
|
||||||
wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
|
wrap (pScrPriv, pScreen, CloseScreen, RRCloseScreen);
|
||||||
|
|
||||||
|
pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
|
||||||
|
|
||||||
pScrPriv->numOutputs = 0;
|
pScrPriv->numOutputs = 0;
|
||||||
pScrPriv->outputs = NULL;
|
pScrPriv->outputs = NULL;
|
||||||
pScrPriv->numCrtcs = 0;
|
pScrPriv->numCrtcs = 0;
|
||||||
|
|
|
@ -297,6 +297,7 @@ typedef struct _rrScrPriv {
|
||||||
int rate;
|
int rate;
|
||||||
int size;
|
int size;
|
||||||
#endif
|
#endif
|
||||||
|
Bool discontiguous;
|
||||||
} rrScrPrivRec, *rrScrPrivPtr;
|
} rrScrPrivRec, *rrScrPrivPtr;
|
||||||
|
|
||||||
extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
|
extern _X_EXPORT DevPrivateKeyRec rrPrivKeyRec;
|
||||||
|
@ -700,6 +701,9 @@ ProcRRGetPanning (ClientPtr client);
|
||||||
int
|
int
|
||||||
ProcRRSetPanning (ClientPtr client);
|
ProcRRSetPanning (ClientPtr client);
|
||||||
|
|
||||||
|
void
|
||||||
|
RRConstrainCursorHarder (DeviceIntPtr, ScreenPtr, int, int *, int *);
|
||||||
|
|
||||||
/* rrdispatch.c */
|
/* rrdispatch.c */
|
||||||
extern _X_EXPORT Bool
|
extern _X_EXPORT Bool
|
||||||
RRClientKnowsRates (ClientPtr pClient);
|
RRClientKnowsRates (ClientPtr pClient);
|
||||||
|
|
155
randr/rrcrtc.c
155
randr/rrcrtc.c
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2006 Keith Packard
|
* Copyright © 2006 Keith Packard
|
||||||
|
* Copyright 2010 Red Hat, Inc
|
||||||
*
|
*
|
||||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||||
* documentation for any purpose is hereby granted without fee, provided that
|
* documentation for any purpose is hereby granted without fee, provided that
|
||||||
|
@ -22,6 +23,7 @@
|
||||||
|
|
||||||
#include "randrstr.h"
|
#include "randrstr.h"
|
||||||
#include "swaprep.h"
|
#include "swaprep.h"
|
||||||
|
#include "mipointer.h"
|
||||||
|
|
||||||
RESTYPE RRCrtcType;
|
RESTYPE RRCrtcType;
|
||||||
|
|
||||||
|
@ -292,6 +294,92 @@ RRCrtcPendingProperties (RRCrtcPtr crtc)
|
||||||
return FALSE;
|
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)
|
||||||
|
{
|
||||||
|
/* left, right, top, bottom... */
|
||||||
|
int al, ar, at, ab;
|
||||||
|
int bl, br, bt, bb;
|
||||||
|
int cl, cr, ct, cb; /* the overlap, if any */
|
||||||
|
|
||||||
|
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
|
||||||
|
mark_crtcs (rrScrPrivPtr pScrPriv, int *reachable, int cur)
|
||||||
|
{
|
||||||
|
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]))
|
||||||
|
mark_crtcs(pScrPriv, reachable, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
RRComputeContiguity (ScreenPtr pScreen)
|
||||||
|
{
|
||||||
|
rrScrPriv(pScreen);
|
||||||
|
Bool discontiguous = TRUE;
|
||||||
|
int i, n = pScrPriv->numCrtcs;
|
||||||
|
|
||||||
|
int *reachable = calloc(n, sizeof(int));
|
||||||
|
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) {
|
||||||
|
mark_crtcs(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
|
* Request that the Crtc be reconfigured
|
||||||
*/
|
*/
|
||||||
|
@ -306,6 +394,7 @@ RRCrtcSet (RRCrtcPtr crtc,
|
||||||
{
|
{
|
||||||
ScreenPtr pScreen = crtc->pScreen;
|
ScreenPtr pScreen = crtc->pScreen;
|
||||||
Bool ret = FALSE;
|
Bool ret = FALSE;
|
||||||
|
Bool recompute = TRUE;
|
||||||
rrScrPriv(pScreen);
|
rrScrPriv(pScreen);
|
||||||
|
|
||||||
/* See if nothing changed */
|
/* See if nothing changed */
|
||||||
|
@ -318,6 +407,7 @@ RRCrtcSet (RRCrtcPtr crtc,
|
||||||
!RRCrtcPendingProperties (crtc) &&
|
!RRCrtcPendingProperties (crtc) &&
|
||||||
!RRCrtcPendingTransform (crtc))
|
!RRCrtcPendingTransform (crtc))
|
||||||
{
|
{
|
||||||
|
recompute = FALSE;
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -381,6 +471,10 @@ RRCrtcSet (RRCrtcPtr crtc,
|
||||||
RRPostPendingProperties (outputs[o]);
|
RRPostPendingProperties (outputs[o]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (recompute)
|
||||||
|
RRComputeContiguity(pScreen);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1349,3 +1443,64 @@ ProcRRGetCrtcTransform (ClientPtr client)
|
||||||
free(reply);
|
free(reply);
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user