[PATCH] DIX/ConfineTo: Improve algorithm to jump to the nearest point inside
Keith Packard
keithp at keithp.com
Fri Oct 4 16:07:28 PDT 2013
Egbert Eich <eich at freedesktop.org> writes:
> ConfineToShape does not work well: The cursor often times doesn't jump
> to the point closest to the current cursor position outside the shape.
> This patch fixes this.
I came up with something a bit simpler which confines the point to each
box in the region and then picks the result which moves the cursor the
shortest distance. I think it would generate the same result, but I
stuck a bunch of range tests in the distance computation to avoid
overflow in weird cases. Dunno if you like this better or not?
commit d8a52a3a3b5bc4a1ff0a986e87dd6c36366e531b
Author: Keith Packard <keithp at keithp.com>
Date: Fri Oct 4 16:00:49 2013 -0700
Improved ConfineToShape
Find the box within the region which is closest to the point and move
there.
Signed-off-by: Keith Packard <keithp at keithp.com>
diff --git a/dix/events.c b/dix/events.c
index 086601a..8610e60 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -667,37 +667,62 @@ SetCriticalEvent(int event)
criticalEvents[event >> 3] |= 1 << (event & 7);
}
+static uint32_t
+ConfineToBox(int x, int y, BoxPtr box, int *px, int16_t *py)
+{
+ int dx, dy;
+
+ *px = x;
+ *py = y;
+
+ if (*px < box->x1)
+ *px = box->x1;
+ else if (*px >= box->x2)
+ *px = box->x2 - 1;
+
+ if (*py < box->y1)
+ *py = box->y1;
+ else if (*py >= box->y2)
+ *py = box->y2 - 1;
+
+ dx = x - *px;
+ if (dx < 0) dx = -dx;
+ if (dx > 32767)
+ dx = 32767;
+ dy = y - *py;
+ if (dy < 0) dy = -dy;
+ if (dy > 32767)
+ dy = 32767;
+
+ return (uint32_t) dx * (uint32_t) dx + (uint32_t) dy * (uint32_t) dy;
+}
+
void
ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
{
- BoxRec box;
+ BoxPtr box;
+ int nbox;
int x = *px, y = *py;
- int incx = 1, incy = 1;
+ int bx, by;
+ uint32_t box_dist_2;
+ int best_x, best_y;
+ uint32_t best_dist_2;
+ int i;
- if (RegionContainsPoint(shape, x, y, &box))
+ if (RegionContainsPoint(shape, x, y, NULL))
return;
- box = *RegionExtents(shape);
- /* this is rather crude */
- do {
- x += incx;
- if (x >= box.x2) {
- incx = -1;
- x = *px - 1;
- }
- else if (x < box.x1) {
- incx = 1;
- x = *px;
- y += incy;
- if (y >= box.y2) {
- incy = -1;
- y = *py - 1;
- }
- else if (y < box.y1)
- return; /* should never get here! */
+ box = REGION_RECTS(shape);
+ for (i = 0; i < REGION_NUM_RECTS(shape); i++) {
+ box_dist_2 = ConfineToBox(x, y, &box[i], &bx, &by);
+ if (i == 0 || box_dist_2 < best_dist_2) {
+ best_dist_2 = box_dist_2;
+ best_x = bx;
+ best_y = by;
}
- } while (!RegionContainsPoint(shape, x, y, &box));
- *px = x;
- *py = y;
+ }
+
+ *px = best_x;
+ *py = best_y;
}
static void
--
keith.packard at intel.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 827 bytes
Desc: not available
URL: <http://lists.x.org/archives/xorg-devel/attachments/20131004/8c01c601/attachment.pgp>
More information about the xorg-devel
mailing list