2011-03-17 18:15:32 +00:00
|
|
|
From 14f1112bec18ccece8e732fe6c200a56546230c7 Mon Sep 17 00:00:00 2001
|
|
|
|
From: Adam Jackson <ajax@redhat.com>
|
|
|
|
Date: Thu, 17 Mar 2011 13:56:17 -0400
|
|
|
|
Subject: [PATCH] CRTC confine and pointer barriers
|
|
|
|
|
|
|
|
---
|
|
|
|
dix/events.c | 7 +
|
|
|
|
dix/getevents.c | 12 +-
|
|
|
|
include/dix.h | 1 +
|
|
|
|
include/protocol-versions.h | 2 +-
|
|
|
|
mi/mipointer.c | 16 ++-
|
|
|
|
mi/mipointer.h | 6 +
|
|
|
|
randr/randr.c | 2 +
|
|
|
|
randr/randrstr.h | 4 +
|
|
|
|
randr/rrcrtc.c | 155 ++++++++++++++++
|
|
|
|
test/Makefile.am | 4 +-
|
|
|
|
xfixes/cursor.c | 408 ++++++++++++++++++++++++++++++++++++++++++-
|
|
|
|
xfixes/xfixes.c | 24 ++-
|
|
|
|
xfixes/xfixes.h | 17 ++
|
|
|
|
xfixes/xfixesint.h | 16 ++
|
|
|
|
14 files changed, 658 insertions(+), 16 deletions(-)
|
|
|
|
|
|
|
|
diff --git a/dix/events.c b/dix/events.c
|
|
|
|
index 07f8b05..d2be84f 100644
|
|
|
|
--- a/dix/events.c
|
|
|
|
+++ b/dix/events.c
|
|
|
|
@@ -328,6 +328,13 @@ IsMaster(DeviceIntPtr dev)
|
|
|
|
return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
|
|
|
|
}
|
|
|
|
|
|
|
|
+Bool
|
|
|
|
+IsFloating(DeviceIntPtr dev)
|
|
|
|
+{
|
|
|
|
+ return GetMaster(dev, MASTER_KEYBOARD) == NULL;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
/**
|
|
|
|
* Max event opcode.
|
|
|
|
*/
|
|
|
|
diff --git a/dix/getevents.c b/dix/getevents.c
|
|
|
|
index 794df42..c66e516 100644
|
|
|
|
--- a/dix/getevents.c
|
|
|
|
+++ b/dix/getevents.c
|
|
|
|
@@ -812,7 +812,11 @@ accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
|
|
|
|
* miPointerSetPosition() and then scale back into device coordinates (if
|
|
|
|
* needed). miPSP will change x/y if the screen was crossed.
|
|
|
|
*
|
|
|
|
+ * The coordinates provided are always absolute. The parameter mode whether
|
|
|
|
+ * it was relative or absolute movement that landed us at those coordinates.
|
|
|
|
+ *
|
|
|
|
* @param dev The device to be moved.
|
|
|
|
+ * @param mode Movement mode (Absolute or Relative)
|
|
|
|
* @param x Pointer to current x-axis value, may be modified.
|
|
|
|
* @param y Pointer to current y-axis value, may be modified.
|
|
|
|
* @param x_frac Fractional part of current x-axis value, may be modified.
|
|
|
|
@@ -824,7 +828,8 @@ accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
|
|
|
|
* @param screeny_frac Fractional part of screen y coordinate, as above.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
-positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
|
|
|
|
+positionSprite(DeviceIntPtr dev, int mode,
|
|
|
|
+ int *x, int *y, float x_frac, float y_frac,
|
|
|
|
ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
|
|
|
|
{
|
|
|
|
int old_screenx, old_screeny;
|
|
|
|
@@ -863,7 +868,7 @@ positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
|
|
|
|
old_screeny = *screeny;
|
|
|
|
/* This takes care of crossing screens for us, as well as clipping
|
|
|
|
* to the current screen. */
|
|
|
|
- miPointerSetPosition(dev, screenx, screeny);
|
|
|
|
+ _miPointerSetPosition(dev, mode, screenx, screeny);
|
|
|
|
|
|
|
|
if (dev->u.master) {
|
|
|
|
dev->u.master->last.valuators[0] = *screenx;
|
|
|
|
@@ -1193,7 +1198,8 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
|
|
|
|
|
|
|
|
set_raw_valuators(raw, &mask, raw->valuators.data);
|
|
|
|
|
|
|
|
- positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
|
|
|
|
+ positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
|
|
|
|
+ &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
|
|
|
|
updateHistory(pDev, &mask, ms);
|
|
|
|
|
|
|
|
/* Update the valuators with the true value sent to the client*/
|
|
|
|
diff --git a/include/dix.h b/include/dix.h
|
|
|
|
index 12e4b59..3f99098 100644
|
|
|
|
--- a/include/dix.h
|
|
|
|
+++ b/include/dix.h
|
|
|
|
@@ -570,6 +570,7 @@ extern Bool _X_EXPORT IsPointerDevice( DeviceIntPtr dev);
|
|
|
|
extern Bool _X_EXPORT IsKeyboardDevice(DeviceIntPtr dev);
|
|
|
|
extern Bool IsPointerEvent(InternalEvent *event);
|
|
|
|
extern _X_EXPORT Bool IsMaster(DeviceIntPtr dev);
|
|
|
|
+extern _X_EXPORT Bool IsFloating(DeviceIntPtr dev);
|
|
|
|
|
|
|
|
extern _X_HIDDEN void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
|
|
|
|
extern _X_HIDDEN int CorePointerProc(DeviceIntPtr dev, int what);
|
|
|
|
diff --git a/include/protocol-versions.h b/include/protocol-versions.h
|
|
|
|
index 1d33bdd..1dc66ad 100644
|
|
|
|
--- a/include/protocol-versions.h
|
|
|
|
+++ b/include/protocol-versions.h
|
|
|
|
@@ -126,7 +126,7 @@
|
|
|
|
#define SERVER_XF86VIDMODE_MINOR_VERSION 2
|
|
|
|
|
|
|
|
/* Fixes */
|
|
|
|
-#define SERVER_XFIXES_MAJOR_VERSION 4
|
|
|
|
+#define SERVER_XFIXES_MAJOR_VERSION 5
|
|
|
|
#define SERVER_XFIXES_MINOR_VERSION 0
|
|
|
|
|
|
|
|
/* X Input */
|
|
|
|
diff --git a/mi/mipointer.c b/mi/mipointer.c
|
|
|
|
index 554397a..85f1949 100644
|
|
|
|
--- a/mi/mipointer.c
|
|
|
|
+++ b/mi/mipointer.c
|
|
|
|
@@ -229,6 +229,10 @@ miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen,
|
|
|
|
SetupScreen (pScreen);
|
|
|
|
|
|
|
|
GenerateEvent = generateEvent;
|
|
|
|
+
|
|
|
|
+ if (pScreen->ConstrainCursorHarder)
|
|
|
|
+ pScreen->ConstrainCursorHarder(pDev, pScreen, Absolute, &x, &y);
|
|
|
|
+
|
|
|
|
/* device dependent - must pend signal and call miPointerWarpCursor */
|
|
|
|
(*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y);
|
|
|
|
if (!generateEvent)
|
|
|
|
@@ -484,7 +488,7 @@ miPointerMoveNoEvent (DeviceIntPtr pDev, ScreenPtr pScreen,
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
-miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
|
|
|
|
+_miPointerSetPosition(DeviceIntPtr pDev, int mode, int *x, int *y)
|
|
|
|
{
|
|
|
|
miPointerScreenPtr pScreenPriv;
|
|
|
|
ScreenPtr pScreen;
|
|
|
|
@@ -529,6 +533,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, mode, x, y);
|
|
|
|
+
|
|
|
|
if (pPointer->x == *x && pPointer->y == *y &&
|
|
|
|
pPointer->pScreen == pScreen)
|
|
|
|
return;
|
|
|
|
@@ -536,6 +543,13 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
|
|
|
|
miPointerMoveNoEvent(pDev, pScreen, *x, *y);
|
|
|
|
}
|
|
|
|
|
|
|
|
+/* ABI hack */
|
|
|
|
+void
|
|
|
|
+miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y)
|
|
|
|
+{
|
|
|
|
+ _miPointerSetPosition(pDev, Absolute, x, y);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
void
|
|
|
|
miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y)
|
|
|
|
{
|
|
|
|
diff --git a/mi/mipointer.h b/mi/mipointer.h
|
|
|
|
index 3c86110..6b6010c 100644
|
|
|
|
--- a/mi/mipointer.h
|
|
|
|
+++ b/mi/mipointer.h
|
|
|
|
@@ -131,6 +131,12 @@ extern _X_EXPORT void miPointerGetPosition(
|
|
|
|
|
|
|
|
/* Moves the cursor to the specified position. May clip the co-ordinates:
|
|
|
|
* x and y are modified in-place. */
|
|
|
|
+extern _X_EXPORT void _miPointerSetPosition(
|
|
|
|
+ DeviceIntPtr pDev,
|
|
|
|
+ int mode,
|
|
|
|
+ int *x,
|
|
|
|
+ int *y);
|
|
|
|
+
|
|
|
|
extern _X_EXPORT void miPointerSetPosition(
|
|
|
|
DeviceIntPtr pDev,
|
|
|
|
int *x,
|
|
|
|
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..d8dd37d 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 *, int *);
|
|
|
|
+
|
|
|
|
/* rrdispatch.c */
|
|
|
|
extern _X_EXPORT Bool
|
|
|
|
RRClientKnowsRates (ClientPtr pClient);
|
|
|
|
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
|
|
|
|
index 98206a2..d4d8f2a 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,92 @@ 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)
|
|
|
|
+{
|
|
|
|
+ /* 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
|
|
|
|
*/
|
|
|
|
@@ -306,6 +394,7 @@ RRCrtcSet (RRCrtcPtr crtc,
|
|
|
|
{
|
|
|
|
ScreenPtr pScreen = crtc->pScreen;
|
|
|
|
Bool ret = FALSE;
|
|
|
|
+ Bool recompute = TRUE;
|
|
|
|
rrScrPriv(pScreen);
|
|
|
|
|
|
|
|
/* See if nothing changed */
|
|
|
|
@@ -318,6 +407,7 @@ RRCrtcSet (RRCrtcPtr crtc,
|
|
|
|
!RRCrtcPendingProperties (crtc) &&
|
|
|
|
!RRCrtcPendingTransform (crtc))
|
|
|
|
{
|
|
|
|
+ recompute = FALSE;
|
|
|
|
ret = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
@@ -381,6 +471,10 @@ RRCrtcSet (RRCrtcPtr crtc,
|
|
|
|
RRPostPendingProperties (outputs[o]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+ if (recompute)
|
|
|
|
+ RRComputeContiguity(pScreen);
|
|
|
|
+
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1349,3 +1443,64 @@ ProcRRGetCrtcTransform (ClientPtr client)
|
|
|
|
free(reply);
|
|
|
|
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;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
diff --git a/test/Makefile.am b/test/Makefile.am
|
|
|
|
index 456221e..ccdb859 100644
|
|
|
|
--- a/test/Makefile.am
|
|
|
|
+++ b/test/Makefile.am
|
|
|
|
@@ -1,6 +1,6 @@
|
|
|
|
if UNITTESTS
|
|
|
|
SUBDIRS= . xi2
|
|
|
|
-check_PROGRAMS = xkb input xtest
|
|
|
|
+check_PROGRAMS = xkb input xtest list fixes
|
|
|
|
check_LTLIBRARIES = libxservertest.la
|
|
|
|
|
|
|
|
TESTS=$(check_PROGRAMS)
|
|
|
|
@@ -16,6 +16,8 @@ endif
|
|
|
|
xkb_LDADD=$(TEST_LDADD)
|
|
|
|
input_LDADD=$(TEST_LDADD)
|
|
|
|
xtest_LDADD=$(TEST_LDADD)
|
|
|
|
+list_LDADD=$(TEST_LDADD)
|
|
|
|
+fixes_LDADD=$(TEST_LDADD)
|
|
|
|
|
|
|
|
libxservertest_la_LIBADD = \
|
|
|
|
$(XSERVER_LIBS) \
|
|
|
|
diff --git a/xfixes/cursor.c b/xfixes/cursor.c
|
|
|
|
index fb608f6..5c55c95 100644
|
|
|
|
--- a/xfixes/cursor.c
|
|
|
|
+++ b/xfixes/cursor.c
|
|
|
|
@@ -1,5 +1,6 @@
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
+ * Copyright 2010 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
@@ -50,13 +51,16 @@
|
|
|
|
#include "cursorstr.h"
|
|
|
|
#include "dixevents.h"
|
|
|
|
#include "servermd.h"
|
|
|
|
+#include "mipointer.h"
|
|
|
|
#include "inputstr.h"
|
|
|
|
#include "windowstr.h"
|
|
|
|
#include "xace.h"
|
|
|
|
+#include "list.h"
|
|
|
|
|
|
|
|
static RESTYPE CursorClientType;
|
|
|
|
static RESTYPE CursorHideCountType;
|
|
|
|
static RESTYPE CursorWindowType;
|
|
|
|
+RESTYPE PointerBarrierType;
|
|
|
|
static CursorPtr CursorCurrent[MAXDEVICES];
|
|
|
|
|
|
|
|
static DevPrivateKeyRec CursorScreenPrivateKeyRec;
|
|
|
|
@@ -107,6 +111,14 @@ typedef struct _CursorHideCountRec {
|
|
|
|
XID resource;
|
|
|
|
} CursorHideCountRec;
|
|
|
|
|
|
|
|
+typedef struct PointerBarrierClient *PointerBarrierClientPtr;
|
|
|
|
+
|
|
|
|
+struct PointerBarrierClient {
|
|
|
|
+ ScreenPtr screen;
|
|
|
|
+ struct PointerBarrier barrier;
|
|
|
|
+ struct list entry;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
/*
|
|
|
|
* Wrap DisplayCursor to catch cursor change events
|
|
|
|
*/
|
|
|
|
@@ -114,7 +126,9 @@ typedef struct _CursorHideCountRec {
|
|
|
|
typedef struct _CursorScreen {
|
|
|
|
DisplayCursorProcPtr DisplayCursor;
|
|
|
|
CloseScreenProcPtr CloseScreen;
|
|
|
|
+ ConstrainCursorHarderProcPtr ConstrainCursorHarder;
|
|
|
|
CursorHideCountPtr pCursorHideCounts;
|
|
|
|
+ struct list barriers;
|
|
|
|
} CursorScreenRec, *CursorScreenPtr;
|
|
|
|
|
|
|
|
#define GetCursorScreen(s) ((CursorScreenPtr)dixLookupPrivate(&(s)->devPrivates, CursorScreenPrivateKey))
|
|
|
|
@@ -184,9 +198,11 @@ CursorCloseScreen (int index, ScreenPtr pScreen)
|
|
|
|
Bool ret;
|
|
|
|
CloseScreenProcPtr close_proc;
|
|
|
|
DisplayCursorProcPtr display_proc;
|
|
|
|
+ ConstrainCursorHarderProcPtr constrain_proc;
|
|
|
|
|
|
|
|
Unwrap (cs, pScreen, CloseScreen, close_proc);
|
|
|
|
Unwrap (cs, pScreen, DisplayCursor, display_proc);
|
|
|
|
+ Unwrap (cs, pScreen, ConstrainCursorHarder, constrain_proc);
|
|
|
|
deleteCursorHideCountsForScreen(pScreen);
|
|
|
|
ret = (*pScreen->CloseScreen) (index, pScreen);
|
|
|
|
free(cs);
|
|
|
|
@@ -1029,6 +1045,391 @@ CursorFreeWindow (pointer data, XID id)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
+static BOOL
|
|
|
|
+barrier_is_horizontal(const struct PointerBarrier *barrier)
|
|
|
|
+{
|
|
|
|
+ return barrier->y1 == barrier->y2;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static BOOL
|
|
|
|
+barrier_is_vertical(const struct PointerBarrier *barrier)
|
|
|
|
+{
|
|
|
|
+ return barrier->x1 == barrier->x2;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @return The set of barrier movement directions the movement vector
|
|
|
|
+ * x1/y1 → x2/y2 represents.
|
|
|
|
+ */
|
|
|
|
+int
|
|
|
|
+barrier_get_direction(int x1, int y1, int x2, int y2)
|
|
|
|
+{
|
|
|
|
+ int direction = 0;
|
|
|
|
+
|
|
|
|
+ /* which way are we trying to go */
|
|
|
|
+ if (x2 > x1)
|
|
|
|
+ direction |= BarrierPositiveX;
|
|
|
|
+ if (x2 < x1)
|
|
|
|
+ direction |= BarrierNegativeX;
|
|
|
|
+ if (y2 > y1)
|
|
|
|
+ direction |= BarrierPositiveY;
|
|
|
|
+ if (y2 < y1)
|
|
|
|
+ direction |= BarrierNegativeY;
|
|
|
|
+
|
|
|
|
+ return direction;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Test if the barrier may block movement in the direction defined by
|
|
|
|
+ * x1/y1 → x2/y2. This function only tests whether the directions could be
|
|
|
|
+ * blocked, it does not test if the barrier actually blocks the movement.
|
|
|
|
+ *
|
|
|
|
+ * @return TRUE if the barrier blocks the direction of movement or FALSE
|
|
|
|
+ * otherwise.
|
|
|
|
+ */
|
|
|
|
+BOOL
|
|
|
|
+barrier_is_blocking_direction(const struct PointerBarrier *barrier, int direction)
|
|
|
|
+{
|
|
|
|
+ /* Barriers define which way is ok, not which way is blocking */
|
|
|
|
+ return (barrier->directions & direction) != direction;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Test if the movement vector x1/y1 → x2/y2 is intersecting with the
|
|
|
|
+ * barrier. A movement vector with the startpoint or endpoint on the barrier
|
|
|
|
+ * itself counts as intersecting.
|
|
|
|
+ *
|
|
|
|
+ * @param x1 X start coordinate of movement vector
|
|
|
|
+ * @param y1 Y start coordinate of movement vector
|
|
|
|
+ * @param x2 X end coordinate of movement vector
|
|
|
|
+ * @param y2 Y end coordinate of movement vector
|
|
|
|
+ * @param[out] distance The distance between the start point and the
|
|
|
|
+ * intersection with the barrier (if applicable).
|
|
|
|
+ * @return TRUE if the barrier intersects with the given vector
|
|
|
|
+ */
|
|
|
|
+BOOL
|
|
|
|
+barrier_is_blocking(const struct PointerBarrier *barrier,
|
|
|
|
+ int x1, int y1, int x2, int y2,
|
|
|
|
+ double *distance)
|
|
|
|
+{
|
|
|
|
+ BOOL rc = FALSE;
|
|
|
|
+ float ua, ub, ud;
|
|
|
|
+ int dir = barrier_get_direction(x1, y1, x2, y2);
|
|
|
|
+
|
|
|
|
+ /* Algorithm below doesn't handle edge cases well, hence the extra
|
|
|
|
+ * checks. */
|
|
|
|
+ if (barrier_is_vertical(barrier)) {
|
|
|
|
+ /* handle immediate barrier adjacency, moving away */
|
|
|
|
+ if (dir & BarrierPositiveX && x1 == barrier->x1)
|
|
|
|
+ return FALSE;
|
|
|
|
+ if (dir & BarrierNegativeX && x1 == (barrier->x1 - 1))
|
|
|
|
+ return FALSE;
|
|
|
|
+ /* startpoint on barrier */
|
|
|
|
+ if (x1 == barrier->x1 && y1 >= barrier->y1 && y1 <= barrier->y2) {
|
|
|
|
+ *distance = 0;
|
|
|
|
+ return TRUE;
|
|
|
|
+ }
|
|
|
|
+ /* endpoint on barrier */
|
|
|
|
+ if (x2 == barrier->x1 && y2 >= barrier->y1 && y2 <= barrier->y2) {
|
|
|
|
+ *distance = abs(x2 - x1);
|
|
|
|
+ return TRUE;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ /* handle immediate barrier adjacency, moving away */
|
|
|
|
+ if (dir & BarrierPositiveY && y1 == barrier->y1)
|
|
|
|
+ return FALSE;
|
|
|
|
+ if (dir & BarrierNegativeY && y1 == (barrier->y1 - 1))
|
|
|
|
+ return FALSE;
|
|
|
|
+ /* startpoint on barrier */
|
|
|
|
+ if (y1 == barrier->y1 && x1 >= barrier->x1 && x1 <= barrier->x2) {
|
|
|
|
+ *distance = 0;
|
|
|
|
+ return TRUE;
|
|
|
|
+ }
|
|
|
|
+ /* endpoint on barrier */
|
|
|
|
+ if (y2 == barrier->y1 && x2 >= barrier->x1 && x2 <= barrier->x2) {
|
|
|
|
+ *distance = abs(y2 - y1);
|
|
|
|
+ return TRUE;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* not an edge case, compute distance */
|
|
|
|
+ ua = 0;
|
|
|
|
+ ud = (barrier->y2 - barrier->y1) * (x2 - x1) - (barrier->x2 - barrier->x1) * (y2 - y1);
|
|
|
|
+ if (ud != 0) {
|
|
|
|
+ ua = ((barrier->x2 - barrier->x1) * (y1 - barrier->y1) -
|
|
|
|
+ (barrier->y2 - barrier->y1) * (x1 - barrier->x1)) / ud;
|
|
|
|
+ ub = ((x2 - x1) * (y1 - barrier->y1) -
|
|
|
|
+ (y2 - y1) * (x1 - barrier->x1)) / ud;
|
|
|
|
+ if (ua < 0 || ua > 1 || ub < 0 || ub > 1)
|
|
|
|
+ ua = 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (ua > 0 && ua <= 1)
|
|
|
|
+ {
|
|
|
|
+ double ix = barrier->x1 + ua * (barrier->x2 - barrier->x1);
|
|
|
|
+ double iy = barrier->y1 + ua * (barrier->y2 - barrier->y1);
|
|
|
|
+
|
|
|
|
+ *distance = sqrt(pow(x1 - ix, 2) + pow(y1 - iy, 2));
|
|
|
|
+ rc = TRUE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return rc;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Find the nearest barrier that is blocking movement from x1/y1 to x2/y2.
|
|
|
|
+ *
|
|
|
|
+ * @param dir Only barriers blocking movement in direction dir are checked
|
|
|
|
+ * @param x1 X start coordinate of movement vector
|
|
|
|
+ * @param y1 Y start coordinate of movement vector
|
|
|
|
+ * @param x2 X end coordinate of movement vector
|
|
|
|
+ * @param y2 Y end coordinate of movement vector
|
|
|
|
+ * @return The barrier nearest to the movement origin that blocks this movement.
|
|
|
|
+ */
|
|
|
|
+static struct PointerBarrier*
|
|
|
|
+barrier_find_nearest(CursorScreenPtr cs, int dir,
|
|
|
|
+ int x1, int y1, int x2, int y2)
|
|
|
|
+{
|
|
|
|
+ struct PointerBarrierClient *c;
|
|
|
|
+ struct PointerBarrier *nearest = NULL;
|
|
|
|
+ double min_distance = INT_MAX; /* can't get higher than that in X anyway */
|
|
|
|
+
|
|
|
|
+ list_for_each_entry(c, &cs->barriers, entry) {
|
|
|
|
+ struct PointerBarrier *b = &c->barrier;
|
|
|
|
+ double distance;
|
|
|
|
+
|
|
|
|
+ if (!barrier_is_blocking_direction(b, dir))
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ if (barrier_is_blocking(b, x1, y1, x2, y2, &distance))
|
|
|
|
+ {
|
|
|
|
+ if (min_distance > distance)
|
|
|
|
+ {
|
|
|
|
+ min_distance = distance;
|
|
|
|
+ nearest = b;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return nearest;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Clamp to the given barrier given the movement direction specified in dir.
|
|
|
|
+ *
|
|
|
|
+ * @param barrier The barrier to clamp to
|
|
|
|
+ * @param dir The movement direction
|
|
|
|
+ * @param[out] x The clamped x coordinate.
|
|
|
|
+ * @param[out] y The clamped x coordinate.
|
|
|
|
+ */
|
|
|
|
+void
|
|
|
|
+barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x, int *y)
|
|
|
|
+{
|
|
|
|
+ if (barrier_is_vertical(barrier)) {
|
|
|
|
+ if ((dir & BarrierNegativeX) & ~barrier->directions)
|
|
|
|
+ *x = barrier->x1;
|
|
|
|
+ if ((dir & BarrierPositiveX) & ~barrier->directions)
|
|
|
|
+ *x = barrier->x1 - 1;
|
|
|
|
+ }
|
|
|
|
+ if (barrier_is_horizontal(barrier))
|
|
|
|
+ {
|
|
|
|
+ if ((dir & BarrierNegativeY) & ~barrier->directions)
|
|
|
|
+ *y = barrier->y1;
|
|
|
|
+ if ((dir & BarrierPositiveY) & ~barrier->directions)
|
|
|
|
+ *y = barrier->y1 - 1;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void
|
|
|
|
+CursorConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x, int *y)
|
|
|
|
+{
|
|
|
|
+ CursorScreenPtr cs = GetCursorScreen(screen);
|
|
|
|
+
|
|
|
|
+ if (!list_is_empty(&cs->barriers) && !IsFloating(dev) && mode == Relative) {
|
|
|
|
+ int ox, oy;
|
|
|
|
+ int dir;
|
|
|
|
+ struct PointerBarrier *nearest = NULL;
|
|
|
|
+
|
|
|
|
+ /* where are we coming from */
|
|
|
|
+ miPointerGetPosition(dev, &ox, &oy);
|
|
|
|
+
|
|
|
|
+ /* How this works:
|
|
|
|
+ * Given the origin and the movement vector, get the nearest barrier
|
|
|
|
+ * to the origin that is blocking the movement.
|
|
|
|
+ * Clamp to that barrier.
|
|
|
|
+ * Then, check from the clamped position to the original
|
|
|
|
+ * destination, again finding the nearest barrier and clamping.
|
|
|
|
+ */
|
|
|
|
+ dir = barrier_get_direction(ox, oy, *x, *y);
|
|
|
|
+
|
|
|
|
+ nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y);
|
|
|
|
+ if (nearest) {
|
|
|
|
+ barrier_clamp_to_barrier(nearest, dir, x, y);
|
|
|
|
+
|
|
|
|
+ if (barrier_is_vertical(nearest)) {
|
|
|
|
+ dir &= ~(BarrierNegativeX | BarrierPositiveX);
|
|
|
|
+ ox = *x;
|
|
|
|
+ } else if (barrier_is_horizontal(nearest)) {
|
|
|
|
+ dir &= ~(BarrierNegativeY | BarrierPositiveY);
|
|
|
|
+ oy = *y;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ nearest = barrier_find_nearest(cs, dir, ox, oy, *x, *y);
|
|
|
|
+ if (nearest) {
|
|
|
|
+ barrier_clamp_to_barrier(nearest, dir, x, y);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (cs->ConstrainCursorHarder) {
|
|
|
|
+ screen->ConstrainCursorHarder = cs->ConstrainCursorHarder;
|
|
|
|
+ screen->ConstrainCursorHarder(dev, screen, mode, x, y);
|
|
|
|
+ screen->ConstrainCursorHarder = CursorConstrainCursorHarder;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct PointerBarrierClient *
|
|
|
|
+CreatePointerBarrierClient(ScreenPtr screen, ClientPtr client,
|
|
|
|
+ xXFixesCreatePointerBarrierReq *stuff)
|
|
|
|
+{
|
|
|
|
+ CursorScreenPtr cs = GetCursorScreen(screen);
|
|
|
|
+ struct PointerBarrierClient *ret = malloc(sizeof(*ret));
|
|
|
|
+
|
|
|
|
+ if (ret) {
|
|
|
|
+ ret->screen = screen;
|
|
|
|
+ ret->barrier.x1 = min(stuff->x1, stuff->x2);
|
|
|
|
+ ret->barrier.x2 = max(stuff->x1, stuff->x2);
|
|
|
|
+ ret->barrier.y1 = min(stuff->y1, stuff->y2);
|
|
|
|
+ ret->barrier.y2 = max(stuff->y1, stuff->y2);
|
|
|
|
+ ret->barrier.directions = stuff->directions & 0x0f;
|
|
|
|
+ if (barrier_is_horizontal(&ret->barrier))
|
|
|
|
+ ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX);
|
|
|
|
+ if (barrier_is_vertical(&ret->barrier))
|
|
|
|
+ ret->barrier.directions &= ~(BarrierPositiveY | BarrierNegativeY);
|
|
|
|
+ list_add(&ret->entry, &cs->barriers);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+ProcXFixesCreatePointerBarrier (ClientPtr client)
|
|
|
|
+{
|
|
|
|
+ int err;
|
|
|
|
+ WindowPtr pWin;
|
|
|
|
+ struct PointerBarrierClient *barrier;
|
|
|
|
+ struct PointerBarrier b;
|
|
|
|
+ REQUEST (xXFixesCreatePointerBarrierReq);
|
|
|
|
+
|
|
|
|
+ REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq);
|
|
|
|
+ LEGAL_NEW_RESOURCE(stuff->barrier, client);
|
|
|
|
+
|
|
|
|
+ err = dixLookupWindow(&pWin, stuff->window, client, DixReadAccess);
|
|
|
|
+ if (err != Success) {
|
|
|
|
+ client->errorValue = stuff->window;
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* This sure does need fixing. */
|
|
|
|
+ if (stuff->num_devices)
|
|
|
|
+ return BadImplementation;
|
|
|
|
+
|
|
|
|
+ b.x1 = stuff->x1;
|
|
|
|
+ b.x2 = stuff->x2;
|
|
|
|
+ b.y1 = stuff->y1;
|
|
|
|
+ b.y2 = stuff->y2;
|
|
|
|
+
|
|
|
|
+ if (!barrier_is_horizontal(&b) && !barrier_is_vertical(&b))
|
|
|
|
+ return BadValue;
|
|
|
|
+
|
|
|
|
+ /* no 0-sized barriers */
|
|
|
|
+ if (barrier_is_horizontal(&b) && barrier_is_vertical(&b))
|
|
|
|
+ return BadValue;
|
|
|
|
+
|
|
|
|
+ if (!(barrier = CreatePointerBarrierClient(pWin->drawable.pScreen,
|
|
|
|
+ client, stuff)))
|
|
|
|
+ return BadAlloc;
|
|
|
|
+
|
|
|
|
+ if (!AddResource(stuff->barrier, PointerBarrierType, &barrier->barrier))
|
|
|
|
+ return BadAlloc;
|
|
|
|
+
|
|
|
|
+ return Success;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+SProcXFixesCreatePointerBarrier (ClientPtr client)
|
|
|
|
+{
|
|
|
|
+ int n;
|
|
|
|
+ REQUEST(xXFixesCreatePointerBarrierReq);
|
|
|
|
+
|
|
|
|
+ swaps(&stuff->length, n);
|
|
|
|
+ REQUEST_SIZE_MATCH(xXFixesCreatePointerBarrierReq);
|
|
|
|
+ swapl(&stuff->barrier, n);
|
|
|
|
+ swapl(&stuff->window, n);
|
|
|
|
+ swaps(&stuff->x1, n);
|
|
|
|
+ swaps(&stuff->y1, n);
|
|
|
|
+ swaps(&stuff->x2, n);
|
|
|
|
+ swaps(&stuff->y2, n);
|
|
|
|
+ swapl(&stuff->directions, n);
|
|
|
|
+ return ProcXFixesVector[stuff->xfixesReqType](client);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int
|
|
|
|
+CursorFreeBarrier(void *data, XID id)
|
|
|
|
+{
|
|
|
|
+ struct PointerBarrierClient *b = NULL, *barrier;
|
|
|
|
+ ScreenPtr screen;
|
|
|
|
+ CursorScreenPtr cs;
|
|
|
|
+
|
|
|
|
+ barrier = container_of(data, struct PointerBarrierClient, barrier);
|
|
|
|
+ screen = barrier->screen;
|
|
|
|
+ cs = GetCursorScreen(screen);
|
|
|
|
+
|
|
|
|
+ /* find and unlink from the screen private */
|
|
|
|
+ list_for_each_entry(b, &cs->barriers, entry) {
|
|
|
|
+ if (b == barrier) {
|
|
|
|
+ list_del(&b->entry);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ free(barrier);
|
|
|
|
+ return Success;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+ProcXFixesDestroyPointerBarrier (ClientPtr client)
|
|
|
|
+{
|
|
|
|
+ int err;
|
|
|
|
+ void *barrier;
|
|
|
|
+ REQUEST (xXFixesDestroyPointerBarrierReq);
|
|
|
|
+
|
|
|
|
+ REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
|
|
|
|
+
|
|
|
|
+ err = dixLookupResourceByType((void **)&barrier, stuff->barrier,
|
|
|
|
+ PointerBarrierType, client,
|
|
|
|
+ DixDestroyAccess);
|
|
|
|
+ if (err != Success) {
|
|
|
|
+ client->errorValue = stuff->barrier;
|
|
|
|
+ return err;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ FreeResource(stuff->barrier, RT_NONE);
|
|
|
|
+ return Success;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+SProcXFixesDestroyPointerBarrier (ClientPtr client)
|
|
|
|
+{
|
|
|
|
+ int n;
|
|
|
|
+ REQUEST(xXFixesDestroyPointerBarrierReq);
|
|
|
|
+
|
|
|
|
+ swaps(&stuff->length, n);
|
|
|
|
+ REQUEST_SIZE_MATCH(xXFixesDestroyPointerBarrierReq);
|
|
|
|
+ swapl(&stuff->barrier, n);
|
|
|
|
+ return ProcXFixesVector[stuff->xfixesReqType](client);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
Bool
|
|
|
|
XFixesCursorInit (void)
|
|
|
|
{
|
|
|
|
@@ -1048,8 +1449,10 @@ XFixesCursorInit (void)
|
|
|
|
cs = (CursorScreenPtr) calloc(1, sizeof (CursorScreenRec));
|
|
|
|
if (!cs)
|
|
|
|
return FALSE;
|
|
|
|
+ list_init(&cs->barriers);
|
|
|
|
Wrap (cs, pScreen, CloseScreen, CursorCloseScreen);
|
|
|
|
Wrap (cs, pScreen, DisplayCursor, CursorDisplayCursor);
|
|
|
|
+ Wrap (cs, pScreen, ConstrainCursorHarder, CursorConstrainCursorHarder);
|
|
|
|
cs->pCursorHideCounts = NULL;
|
|
|
|
SetCursorScreen (pScreen, cs);
|
|
|
|
}
|
|
|
|
@@ -1059,7 +1462,10 @@ XFixesCursorInit (void)
|
|
|
|
"XFixesCursorHideCount");
|
|
|
|
CursorWindowType = CreateNewResourceType(CursorFreeWindow,
|
|
|
|
"XFixesCursorWindow");
|
|
|
|
+ PointerBarrierType = CreateNewResourceType(CursorFreeBarrier,
|
|
|
|
+ "XFixesPointerBarrier");
|
|
|
|
|
|
|
|
- return CursorClientType && CursorHideCountType && CursorWindowType;
|
|
|
|
+ return CursorClientType && CursorHideCountType && CursorWindowType &&
|
|
|
|
+ PointerBarrierType;
|
|
|
|
}
|
|
|
|
|
|
|
|
diff --git a/xfixes/xfixes.c b/xfixes/xfixes.c
|
|
|
|
index e8c7bf1..a57884b 100644
|
|
|
|
--- a/xfixes/xfixes.c
|
|
|
|
+++ b/xfixes/xfixes.c
|
|
|
|
@@ -1,5 +1,6 @@
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
+ * Copyright 2010 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
@@ -47,10 +48,6 @@
|
|
|
|
|
|
|
|
#include "xfixesint.h"
|
|
|
|
#include "protocol-versions.h"
|
|
|
|
-/*
|
|
|
|
- * Must use these instead of the constants from xfixeswire.h. They advertise
|
|
|
|
- * what we implement, not what the protocol headers define.
|
|
|
|
- */
|
|
|
|
|
|
|
|
static unsigned char XFixesReqCode;
|
|
|
|
int XFixesEventBase;
|
|
|
|
@@ -97,11 +94,12 @@ ProcXFixesQueryVersion(ClientPtr client)
|
|
|
|
|
|
|
|
/* Major version controls available requests */
|
|
|
|
static const int version_requests[] = {
|
|
|
|
- X_XFixesQueryVersion, /* before client sends QueryVersion */
|
|
|
|
- X_XFixesGetCursorImage, /* Version 1 */
|
|
|
|
- X_XFixesChangeCursorByName, /* Version 2 */
|
|
|
|
- X_XFixesExpandRegion, /* Version 3 */
|
|
|
|
- X_XFixesShowCursor, /* Version 4 */
|
|
|
|
+ X_XFixesQueryVersion, /* before client sends QueryVersion */
|
|
|
|
+ X_XFixesGetCursorImage, /* Version 1 */
|
|
|
|
+ X_XFixesChangeCursorByName, /* Version 2 */
|
|
|
|
+ X_XFixesExpandRegion, /* Version 3 */
|
|
|
|
+ X_XFixesShowCursor, /* Version 4 */
|
2011-03-22 15:44:58 +00:00
|
|
|
+ X_XFixesDestroyPointerBarrier, /* Version 5 */
|
2011-03-17 18:15:32 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
|
|
|
|
@@ -142,6 +140,9 @@ int (*ProcXFixesVector[XFixesNumberRequests])(ClientPtr) = {
|
|
|
|
/*************** Version 4 ****************/
|
|
|
|
ProcXFixesHideCursor,
|
|
|
|
ProcXFixesShowCursor,
|
|
|
|
+/*************** Version 5 ****************/
|
|
|
|
+ ProcXFixesCreatePointerBarrier,
|
|
|
|
+ ProcXFixesDestroyPointerBarrier,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
@@ -205,6 +206,9 @@ static int (*SProcXFixesVector[XFixesNumberRequests])(ClientPtr) = {
|
|
|
|
/*************** Version 4 ****************/
|
|
|
|
SProcXFixesHideCursor,
|
|
|
|
SProcXFixesShowCursor,
|
|
|
|
+/*************** Version 5 ****************/
|
|
|
|
+ SProcXFixesCreatePointerBarrier,
|
|
|
|
+ SProcXFixesDestroyPointerBarrier,
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
@@ -260,6 +264,8 @@ XFixesExtensionInit(void)
|
|
|
|
EventSwapVector[XFixesEventBase + XFixesCursorNotify] =
|
|
|
|
(EventSwapPtr) SXFixesCursorNotifyEvent;
|
|
|
|
SetResourceTypeErrorValue(RegionResType, XFixesErrorBase + BadRegion);
|
|
|
|
+ SetResourceTypeErrorValue(PointerBarrierType,
|
|
|
|
+ XFixesErrorBase + BadBarrier);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
diff --git a/xfixes/xfixes.h b/xfixes/xfixes.h
|
|
|
|
index 1638350..5765e64 100644
|
|
|
|
--- a/xfixes/xfixes.h
|
|
|
|
+++ b/xfixes/xfixes.h
|
|
|
|
@@ -30,6 +30,7 @@
|
|
|
|
#include "resource.h"
|
|
|
|
|
|
|
|
extern _X_EXPORT RESTYPE RegionResType;
|
|
|
|
+extern _X_EXPORT RESTYPE PointerBarrierType;
|
|
|
|
extern _X_EXPORT int XFixesErrorBase;
|
|
|
|
|
|
|
|
#define VERIFY_REGION(pRegion, rid, client, mode) \
|
|
|
|
@@ -51,5 +52,21 @@ extern _X_EXPORT int XFixesErrorBase;
|
|
|
|
extern _X_EXPORT RegionPtr
|
|
|
|
XFixesRegionCopy (RegionPtr pRegion);
|
|
|
|
|
|
|
|
+struct PointerBarrier {
|
|
|
|
+ CARD16 x1, x2, y1, y2;
|
|
|
|
+ CARD32 directions;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+extern int
|
|
|
|
+barrier_get_direction(int, int, int, int);
|
|
|
|
+extern BOOL
|
|
|
|
+barrier_is_blocking(const struct PointerBarrier*, int, int, int, int, double*);
|
|
|
|
+extern BOOL
|
|
|
|
+barrier_is_blocking_direction(const struct PointerBarrier*, int);
|
|
|
|
+extern void
|
|
|
|
+barrier_clamp_to_barrier(struct PointerBarrier *barrier, int dir, int *x, int *y);
|
|
|
|
+
|
|
|
|
+
|
|
|
|
|
|
|
|
#endif /* _XFIXES_H_ */
|
|
|
|
diff --git a/xfixes/xfixesint.h b/xfixes/xfixesint.h
|
|
|
|
index d005369..6ba276e 100644
|
|
|
|
--- a/xfixes/xfixesint.h
|
|
|
|
+++ b/xfixes/xfixesint.h
|
|
|
|
@@ -1,5 +1,6 @@
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
|
|
|
|
+ * Copyright 2010 Red Hat, Inc.
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
@@ -278,6 +279,21 @@ ProcXFixesShowCursor (ClientPtr client);
|
|
|
|
int
|
|
|
|
SProcXFixesShowCursor (ClientPtr client);
|
|
|
|
|
|
|
|
+/* Version 5 */
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+ProcXFixesCreatePointerBarrier (ClientPtr client);
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+SProcXFixesCreatePointerBarrier (ClientPtr client);
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+ProcXFixesDestroyPointerBarrier (ClientPtr client);
|
|
|
|
+
|
|
|
|
+int
|
|
|
|
+SProcXFixesDestroyPointerBarrier (ClientPtr client);
|
|
|
|
+
|
|
|
|
+/* Xinerama */
|
|
|
|
extern int (*PanoramiXSaveXFixesVector[XFixesNumberRequests])(ClientPtr);
|
|
|
|
void PanoramiXFixesInit (void);
|
|
|
|
void PanoramiXFixesReset (void);
|
|
|
|
--
|
|
|
|
1.7.4
|
|
|
|
|