Implementation of ConfineTo
Egbert Eich
eich at pdx.freedesktop.org
Fri May 20 09:15:09 PDT 2005
The current implementation of ConfineTo is pretty cheezy.
The cursor often times doesn't jump to the point inside the
region closest to the location of the previous location of
the pointer.
Attached patch will improve this considerably, however it
exposes a lot of the internals of the BoxRec and region internals
on the DIX level. Since there is no other place in DIX that does
this I'm not sure if this is permitted on this level.
An alternative would be to create a wrapper function for this
and move this code to the mi level.
Opinions?
Egbert.
-------------- next part --------------
Index: events.c
===================================================================
RCS file: /home/eich/cvs/xc/programs/Xserver/dix/events.c,v
retrieving revision 1.1.1.19
diff -u -r1.1.1.19 events.c
--- events.c 26 Aug 2004 12:09:13 -0000 1.1.1.19
+++ events.c 2 Mar 2005 20:04:13 -0000
@@ -656,35 +656,79 @@
{
BoxRec box;
int x = *px, y = *py;
- int incx = 1, incy = 1;
-
+ int nbox;
+ BoxPtr pbox;
+ int d, min = (~0U >> 1), dx2, dy2, x_r, y_r;
+
if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box))
return;
- box = *REGION_EXTENTS(sprite.hot.pScreen, shape);
- /* this is rather crude */
- do {
- x += incx;
- if (x >= box.x2)
- {
- incx = -1;
- x = *px - 1;
+
+ for (nbox = REGION_NUM_RECTS (shape),
+ pbox = REGION_RECTS(shape);
+ nbox--;
+ pbox++)
+ {
+ if (pbox->x1 < x && pbox->x2 > x) {
+ d = pbox->y1 - y;
+ if (d >= 0) {
+ d *= d;
+ if (d < min) {
+ *px = x;
+ *py = pbox->y1 + 1;
+ min = d;
+ }
+ } else {
+ d = pbox->y2 - y; d *= d;
+ if (d < min) {
+ *px = x;
+ *py = pbox->y2 - 1;
+ min = d;
+ }
+ }
}
- else if (x < box.x1)
- {
- incx = 1;
- x = *px;
- y += incy;
- if (y >= box.y2)
- {
- incy = -1;
- y = *py - 1;
+ else if (pbox->y1 < y && pbox->y2 > y) {
+ d = pbox->x1 - x;
+ if (d >= 0) {
+ d *= d;
+ if (d < min) {
+ *px = pbox->x1 + 1;
+ *py = y;
+ min = d;
+ }
+ } else {
+ d = pbox->x2 - x; d *= d;
+ if (d < min) {
+ *px = pbox->x2 - 1;
+ *py = y;
+ min = d;
+ }
+ }
+
+ } else {
+ dx2 = pbox->x1 - x;
+ if (dx2 >= 0) {
+ dx2 *= dx2;
+ x_r = pbox->x1 + 1;
+ } else {
+ dx2 = pbox->x2 - x; dx2 *= dx2;
+ x_r = pbox->x2 - 1;
+ }
+ dy2 = pbox->y1 - y;
+ if (dy2 >= 0) {
+ dy2 *= dy2;
+ y_r = pbox->y1 + 1;
+ } else {
+ dy2 = pbox->y2 - y; dy2 *= dy2;
+ y_r = pbox->y2 - 1;
+ }
+ if ((d = dx2 + dy2) < min) {
+ *px = x_r;
+ *py = y_r;
+ min = d;
}
- else if (y < box.y1)
- return; /* should never get here! */
}
- } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box));
- *px = x;
- *py = y;
+ }
+
}
#endif
More information about the xorg-arch
mailing list