summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--render/box.c126
-rw-r--r--render/box.h5
2 files changed, 81 insertions, 50 deletions
diff --git a/render/box.c b/render/box.c
index 08272d166..1735eba56 100644
--- a/render/box.c
+++ b/render/box.c
@@ -34,7 +34,7 @@
#include "utils/log.h"
#include "utils/talloc.h"
-static bool box_contains_point(struct box *box, int x, int y);
+static bool box_contains_point(struct box *box, int x, int y, bool *physically);
#define box_is_float(box) (box->type == BOX_FLOAT_LEFT || \
box->type == BOX_FLOAT_RIGHT)
@@ -302,12 +302,13 @@ void box_bounds(struct box *box, struct rect *r)
* \endcode
*/
-struct box *box_at_point(struct box *box, int x, int y,
+struct box *box_at_point(struct box *box, const int x, const int y,
int *box_x, int *box_y,
struct content **content)
{
int bx = *box_x, by = *box_y;
struct box *child, *sibling;
+ bool physically;
assert(box);
@@ -324,10 +325,15 @@ struct box *box_at_point(struct box *box, int x, int y,
/* consider floats second, since they will often overlap other boxes */
for (child = box->float_children; child; child = child->next_float) {
- if (box_contains_point(child, x - bx, y - by)) {
+ if (box_contains_point(child, x - bx, y - by, &physically)) {
*box_x = bx + child->x - child->scroll_x;
*box_y = by + child->y - child->scroll_y;
- return child;
+
+ if (physically)
+ return child;
+ else
+ return box_at_point(child, x, y, box_x, box_y,
+ content);
}
}
@@ -336,20 +342,24 @@ non_float_children:
for (child = box->children; child; child = child->next) {
if (box_is_float(child))
continue;
- if (box_contains_point(child, x - bx, y - by)) {
+ if (box_contains_point(child, x - bx, y - by, &physically)) {
*box_x = bx + child->x - child->scroll_x;
*box_y = by + child->y - child->scroll_y;
- return child;
+
+ if (physically)
+ return child;
+ else
+ return box_at_point(child, x, y, box_x, box_y,
+ content);
}
}
/* marker boxes */
if (box->list_marker) {
- if (box_contains_point(box->list_marker, x - bx, y - by)) {
- *box_x = bx + box->list_marker->x -
- box->list_marker->scroll_x;
- *box_y = by + box->list_marker->y -
- box->list_marker->scroll_y;
+ if (box_contains_point(box->list_marker, x - bx, y - by,
+ &physically)) {
+ *box_x = bx + box->list_marker->x;
+ *box_y = by + box->list_marker->y;
return box->list_marker;
}
}
@@ -363,12 +373,19 @@ siblings:
for (sibling = box->next_float; sibling;
sibling = sibling->next_float) {
if (box_contains_point(sibling,
- x - bx, y - by)) {
+ x - bx, y - by, &physically)) {
*box_x = bx + sibling->x -
sibling->scroll_x;
*box_y = by + sibling->y -
sibling->scroll_y;
- return sibling;
+
+ if (physically)
+ return sibling;
+ else
+ return box_at_point(sibling,
+ x, y,
+ box_x, box_y,
+ content);
}
}
/* ascend to float's parent */
@@ -385,13 +402,20 @@ siblings:
sibling = sibling->next) {
if (box_is_float(sibling))
continue;
- if (box_contains_point(sibling,
- x - bx, y - by)) {
+ if (box_contains_point(sibling, x - bx, y - by,
+ &physically)) {
*box_x = bx + sibling->x -
sibling->scroll_x;
*box_y = by + sibling->y -
sibling->scroll_y;
- return sibling;
+
+ if (physically)
+ return sibling;
+ else
+ return box_at_point(sibling,
+ x, y,
+ box_x, box_y,
+ content);
}
}
box = box->parent;
@@ -405,47 +429,55 @@ siblings:
/**
* Determine if a point lies within a box.
*
- * \param box box to consider
- * \param x coordinate relative to box parent
- * \param y coordinate relative to box parent
+ * \param box box to consider
+ * \param x coordinate relative to box parent
+ * \param y coordinate relative to box parent
+ * \param physically if function returning true, physically is set true if
+ * point is within the box's physical dimensions and false
+ * if the point is not within the box's physical dimensions
+ * but is in the area defined by the box's descendants.
+ * if function returning false, physically is undefined.
* \return true if the point is within the box or a descendant box
*
* This is a helper function for box_at_point().
*/
-bool box_contains_point(struct box *box, int x, int y)
+bool box_contains_point(struct box *box, int x, int y, bool *physically)
{
- if ((box->style && box->style->overflow != CSS_OVERFLOW_VISIBLE) ||
- box->inline_end) {
- if (box->x <= x + box->border[LEFT] &&
- x < box->x + box->padding[LEFT] + box->width +
- box->border[RIGHT] + box->padding[RIGHT] &&
- box->y <= y + box->border[TOP] &&
- y < box->y + box->padding[TOP] + box->height +
- box->border[BOTTOM] + box->padding[BOTTOM])
- return true;
- if (box->list_marker && box->list_marker->x <= x +
- box->list_marker->border[LEFT] &&
- x < box->list_marker->x +
- box->list_marker->padding[LEFT] +
- box->list_marker->width +
- box->list_marker->border[RIGHT] +
- box->list_marker->padding[RIGHT] &&
- box->list_marker->y <= y +
- box->list_marker->border[TOP] &&
- y < box->list_marker->y +
- box->list_marker->padding[TOP] +
- box->list_marker->height +
- box->list_marker->border[BOTTOM] +
- box->list_marker->padding[BOTTOM]) {
- return true;
- }
- } else {
+ if (box->x <= x + box->border[LEFT] &&
+ x < box->x + box->padding[LEFT] + box->width +
+ box->border[RIGHT] + box->padding[RIGHT] &&
+ box->y <= y + box->border[TOP] &&
+ y < box->y + box->padding[TOP] + box->height +
+ box->border[BOTTOM] + box->padding[BOTTOM]) {
+ *physically = true;
+ return true;
+ }
+ if (box->list_marker && box->list_marker->x <= x +
+ box->list_marker->border[LEFT] &&
+ x < box->list_marker->x +
+ box->list_marker->padding[LEFT] +
+ box->list_marker->width +
+ box->list_marker->border[RIGHT] +
+ box->list_marker->padding[RIGHT] &&
+ box->list_marker->y <= y +
+ box->list_marker->border[TOP] &&
+ y < box->list_marker->y +
+ box->list_marker->padding[TOP] +
+ box->list_marker->height +
+ box->list_marker->border[BOTTOM] +
+ box->list_marker->padding[BOTTOM]) {
+ *physically = true;
+ return true;
+ }
+ if (box->style && box->style->overflow == CSS_OVERFLOW_VISIBLE) {
if (box->x + box->descendant_x0 <= x &&
x < box->x + box->descendant_x1 &&
box->y + box->descendant_y0 <= y &&
- y < box->y + box->descendant_y1)
+ y < box->y + box->descendant_y1) {
+ *physically = false;
return true;
+ }
}
return false;
}
diff --git a/render/box.h b/render/box.h
index 5d31a198b..9a90c21a4 100644
--- a/render/box.h
+++ b/render/box.h
@@ -293,9 +293,8 @@ void box_free_box(struct box *box);
void box_free_object_params(struct object_params *op);
void box_bounds(struct box *box, struct rect *r);
void box_coords(struct box *box, int *x, int *y);
-struct box *box_at_point(struct box *box, int x, int y,
- int *box_x, int *box_y,
- struct content **content);
+struct box *box_at_point(struct box *box, const int x, const int y,
+ int *box_x, int *box_y, struct content **content);
struct box *box_object_at_point(struct content *c, int x, int y);
struct box *box_href_at_point(struct content *c, int x, int y);
struct box *box_find_by_id(struct box *box, const char *id);