diff --git a/util/box.c b/util/box.c index bc2c60dd..73a42633 100644 --- a/util/box.c +++ b/util/box.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -14,10 +13,29 @@ void wlr_box_closest_point(const struct wlr_box *box, double x, double y, return; } + // Note: the width and height of the box are exclusive; that is, + // for a 100x100 box at (0,0), the point (99,99) is inside it + // while the point (100,100) is outside it. + // + // Mathematically, there exists no single closest point to the + // bottom-right corner of the box while remaining inside it. You + // can construct an infinite series approaching the limit, such + // as {(99,99), (99.9,99.9), (99.99,99.99)...}, but since the + // intervals are half-open, there is no "last" point. + // + // This function must therefore define an arbitrary "closest" + // point. For simplicity and consistency, this is defined to be + // (box.x + width - 1, box.y + height - 1). + // + // (The previous implementation was non-linear: with the example + // 100x100 box, it would return an input point of (99.9,99.9) + // unchanged, but for an input point (100.1,100.1) the returned + // point would jump back to (99.0,99.0). This is now fixed.) + // find the closest x point if (x < box->x) { *dest_x = box->x; - } else if (x >= box->x + box->width) { + } else if (x > box->x + box->width - 1) { *dest_x = box->x + box->width - 1; } else { *dest_x = x; @@ -26,7 +44,7 @@ void wlr_box_closest_point(const struct wlr_box *box, double x, double y, // find closest y point if (y < box->y) { *dest_y = box->y; - } else if (y >= box->y + box->height) { + } else if (y > box->y + box->height - 1) { *dest_y = box->y + box->height - 1; } else { *dest_y = y;