xorg-x11-server/u_01-Improved-ConfineToShape.patch

110 lines
2.7 KiB
Diff

From: Keith Packard <keithp@keithp.com>
Date: Fri Oct 4 16:00:49 2013 -0700
Subject: [PATCH 1/2]Improved ConfineToShape
Patch-mainline: to be upstreamed
Git-commit: 0d0951624db7ae4686b362c7c6307f1ed46c8579
References: bnc#62146
Signed-off-by: Egbert Eich <eich@suse.com>
Find the box within the region which is closest to the point and move
there.
Signed-off-by: Keith Packard <keithp@keithp.com>
---
dix/events.c | 74 ++++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 50 insertions(+), 24 deletions(-)
diff --git a/dix/events.c b/dix/events.c
index efaf91d..5244781 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -666,37 +666,63 @@ SetCriticalEvent(int event)
criticalEvents[event >> 3] |= 1 << (event & 7);
}
+static uint32_t
+ConfineToBox(int x, int y, BoxPtr box, int *px, int *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 = 0, best_y = 0;
+ uint32_t best_dist_2 = 0;
+ 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);
+ nbox = REGION_NUM_RECTS(shape);
+ for (i = 0; i < nbox; 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