[PATCH 10/29] barriers: Add a couple pixels of elbow room for the hit detection

Peter Hutterer peter.hutterer at who-t.net
Tue Dec 11 23:19:03 PST 2012


From: "Jasper St. Pierre" <jstpierre at mecheye.net>

Pointers (and the hands that drive them) aren't very precise, and the
slightest amount of nudging to either side might be enough to reset
the event ID, making clients think they have an entirely new hit. Allow
for a slightly bigger "hit box" before these barriers get reset.

Signed-off-by: Jasper St. Pierre <jstpierre at mecheye.net>
---
 Xi/xibarriers.c | 40 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 35 insertions(+), 5 deletions(-)

diff --git a/Xi/xibarriers.c b/Xi/xibarriers.c
index ac94927..95a62ae 100644
--- a/Xi/xibarriers.c
+++ b/Xi/xibarriers.c
@@ -79,7 +79,7 @@ struct PointerBarrierClient {
     int barrier_event_id;
     int release_event_id;
     Bool hit;
-    Bool last_hit;
+    Bool seen;
 };
 
 typedef struct _BarrierScreen {
@@ -220,6 +220,35 @@ barrier_is_blocking(const struct PointerBarrier * barrier,
     return rc;
 }
 
+#define HIT_EDGE_EXTENTS 2
+static BOOL
+barrier_inside_hit_box(struct PointerBarrier *barrier, int x, int y)
+{
+    int x1, x2, y1, y2;
+    int dir;
+
+    x1 = barrier->x1;
+    x2 = barrier->x2;
+    y1 = barrier->y1;
+    y2 = barrier->y2;
+    dir = ~(barrier->directions);
+
+    if (barrier_is_vertical(barrier)) {
+        if (dir & BarrierPositiveX)
+            x1 -= HIT_EDGE_EXTENTS;
+        if (dir & BarrierNegativeX)
+            x2 += HIT_EDGE_EXTENTS;
+    }
+    if (barrier_is_horizontal(barrier)) {
+        if (dir & BarrierPositiveY)
+            y1 -= HIT_EDGE_EXTENTS;
+        if (dir & BarrierNegativeY)
+            y2 += HIT_EDGE_EXTENTS;
+    }
+
+    return x >= x1 && x <= x2 && y >= y1 && y <= y2;
+}
+
 static BOOL
 barrier_blocks_device(struct PointerBarrierClient *client,
                       DeviceIntPtr dev)
@@ -267,7 +296,7 @@ barrier_find_nearest(BarrierScreenPtr cs, DeviceIntPtr dev,
         struct PointerBarrier *b = &c->barrier;
         double distance;
 
-        if (c->hit)
+        if (c->seen)
             continue;
 
         if (!barrier_is_blocking_direction(b, dir))
@@ -388,8 +417,9 @@ input_constrain_cursor(DeviceIntPtr dev, ScreenPtr screen,
     }
 
     xorg_list_for_each_entry(c, &cs->barriers, entry) {
-        c->last_hit = c->hit;
-        c->hit = FALSE;
+        c->seen = FALSE;
+        if (c->hit && !barrier_inside_hit_box(&c->barrier, x, y))
+            c->hit = FALSE;
     }
 
  out:
@@ -459,7 +489,7 @@ CreatePointerBarrierClient(ClientPtr client,
     ret->barrier_event_id = 0;
     ret->release_event_id = 0;
     ret->hit = FALSE;
-    ret->last_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);
-- 
1.8.0.1



More information about the xorg-devel mailing list