diff options
author | Jasper St. Pierre <jstpierre@mecheye.net> | 2012-11-27 15:31:52 -0500 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2012-12-17 15:03:07 +1000 |
commit | 707b4dc61f18960611409ef5ad8947be189f7296 (patch) | |
tree | a995a9644d4314aaf96ef332a97df5bb36eb900c /Xi | |
parent | 0a5a0d7c242add4d79721c1b90073b603a475534 (diff) |
barriers: Support line and ray barriers
This allows clients to add barriers that extend to the edge of the
screen. Clients are encouraged to use these instead of precise coordinates
in these cases to help prevent pointer leaks.
Signed-off-by: Jasper St. Pierre <jstpierre@mecheye.net>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'Xi')
-rw-r--r-- | Xi/xibarriers.c | 46 | ||||
-rw-r--r-- | Xi/xibarriers.h | 2 |
2 files changed, 41 insertions, 7 deletions
diff --git a/Xi/xibarriers.c b/Xi/xibarriers.c index a65d2080b..27b21eedb 100644 --- a/Xi/xibarriers.c +++ b/Xi/xibarriers.c @@ -140,6 +140,19 @@ barrier_is_blocking_direction(const struct PointerBarrier * barrier, return (barrier->directions & direction) != direction; } +static BOOL +inside_segment(int v, int v1, int v2) +{ + if (v1 < 0 && v2 < 0) /* line */ + return TRUE; + else if (v1 < 0) /* ray */ + return v <= v2; + else if (v2 < 0) /* ray */ + return v >= v1; + else /* line segment */ + return v >= v1 && v <= v2; +} + #define T(v, a, b) (((float)v) - (a)) / ((b) - (a)) #define F(t, a, b) ((t) * ((a) - (b)) + (a)) @@ -171,7 +184,7 @@ barrier_is_blocking(const struct PointerBarrier * barrier, return FALSE; y = F(t, y1, y2); - if (y < barrier->y1 || y > barrier->y2) + if (!inside_segment(y, barrier->y1, barrier->y2)) return FALSE; *distance = sqrt((pow(y - y1, 2) + pow(barrier->x1 - x1, 2))); @@ -188,7 +201,7 @@ barrier_is_blocking(const struct PointerBarrier * barrier, return FALSE; x = F(t, x1, x2); - if (x < barrier->x1 || x > barrier->x2) + if (!inside_segment(x, barrier->x1, barrier->x2)) return FALSE; *distance = sqrt((pow(x - x1, 2) + pow(barrier->y1 - y1, 2))); @@ -428,6 +441,18 @@ input_constrain_cursor(DeviceIntPtr dev, ScreenPtr screen, *out_y = y; } +static void +sort_min_max(INT16 *a, INT16 *b) +{ + INT16 A, B; + if (*a < 0 || *b < 0) + return; + A = *a; + B = *b; + *a = min(A, B); + *b = max(A, B); +} + static int CreatePointerBarrierClient(ClientPtr client, xXFixesCreatePointerBarrierReq * stuff, @@ -491,10 +516,12 @@ CreatePointerBarrierClient(ClientPtr client, ret->release_event_id = 0; ret->hit = FALSE; ret->seen = FALSE; - 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.x1 = stuff->x1; + ret->barrier.x2 = stuff->x2; + ret->barrier.y1 = stuff->y1; + ret->barrier.y2 = stuff->y2; + sort_min_max(&ret->barrier.x1, &ret->barrier.x2); + sort_min_max(&ret->barrier.y1, &ret->barrier.y2); ret->barrier.directions = stuff->directions & 0x0f; if (barrier_is_horizontal(&ret->barrier)) ret->barrier.directions &= ~(BarrierPositiveX | BarrierNegativeX); @@ -587,6 +614,13 @@ XICreatePointerBarrier(ClientPtr client, if (barrier_is_horizontal(&b) && barrier_is_vertical(&b)) return BadValue; + /* no infinite barriers on the wrong axis */ + if (barrier_is_horizontal(&b) && (b.y1 < 0 || b.y2 < 0)) + return BadValue; + + if (barrier_is_vertical(&b) && (b.x1 < 0 || b.x2 < 0)) + return BadValue; + if ((err = CreatePointerBarrierClient(client, stuff, &barrier))) return err; diff --git a/Xi/xibarriers.h b/Xi/xibarriers.h index f29bb6c8f..bdcb0b289 100644 --- a/Xi/xibarriers.h +++ b/Xi/xibarriers.h @@ -11,7 +11,7 @@ extern _X_EXPORT RESTYPE PointerBarrierType; struct PointerBarrier { - CARD16 x1, x2, y1, y2; + INT16 x1, x2, y1, y2; CARD32 directions; }; |