File u_01-Improved-ConfineToShape.patch of Package xorg-x11-server

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