@@ -1194,18 +1194,19 @@ bool scene_obj_within(const struct scene *scn, struct scene_obj *obj, int x,
}
struct scene_obj *scene_find_obj_within(const struct scene *scn, int x, int y,
- bool reverse)
+ bool reverse, bool allow_any)
{
struct scene_obj *obj;
- log_debug("within: x %d y %d reverse %d\n", x, y, reverse);
+ log_debug("within: x %d y %d reverse %d allow_any %d\n", x, y, reverse,
+ allow_any);
if (reverse) {
list_for_each_entry_reverse(obj, &scn->obj_head, sibling) {
log_debug(" - obj %d '%s' can_highlight %d within %d\n",
obj->id, obj->name,
scene_obj_can_highlight(obj),
scene_obj_within(scn, obj, x, y));
- if (scene_obj_can_highlight(obj) &&
+ if ((allow_any || scene_obj_can_highlight(obj)) &&
scene_obj_within(scn, obj, x, y)) {
log_debug("- returning obj %d '%s'\n", obj->id,
obj->name);
@@ -1218,7 +1219,7 @@ struct scene_obj *scene_find_obj_within(const struct scene *scn, int x, int y,
obj->id, obj->name,
scene_obj_can_highlight(obj),
scene_obj_within(scn, obj, x, y));
- if (scene_obj_can_highlight(obj) &&
+ if ((allow_any || scene_obj_can_highlight(obj)) &&
scene_obj_within(scn, obj, x, y)) {
log_debug("- returning obj %d '%s'\n", obj->id,
obj->name);
@@ -1255,7 +1256,7 @@ static void send_click_obj(struct scene *scn, struct scene_obj *obj, int x,
}
log_debug("no object; finding...\n");
- obj = scene_find_obj_within(scn, x, y, false);
+ obj = scene_find_obj_within(scn, x, y, false, false);
if (obj) {
event->type = EXPOACT_POINT_OPEN;
event->select.id = obj->id;
@@ -1281,7 +1282,7 @@ static int scene_click_popup(struct scene *scn, int x, int y,
}
/* check that the click is within our object */
- chk = scene_find_obj_within(scn, x, y, false);
+ chk = scene_find_obj_within(scn, x, y, false, false);
log_debug("chk %d '%s' (obj %d '%s')\n", chk ? chk->id : -1,
chk ? chk->name : "(none)", obj->id, obj->name);
if (!chk) {
@@ -1340,7 +1341,7 @@ int scene_send_click(struct scene *scn, int x, int y, struct expo_action *event)
return 0;
}
- obj = scene_find_obj_within(scn, x, y, false);
+ obj = scene_find_obj_within(scn, x, y, false, false);
log_debug("non-popup obj %d '%s'\n", obj ? obj->id : -1,
obj ? obj->name : "(none)");
if (!obj)
@@ -564,9 +564,10 @@ const char *scene_obj_type_name(enum scene_obj_t type);
* @y: Y coordinate of the click
* @reverse: true to search from top to bottom (reverse order), false for
* bottom to top
+ * @allow_any: true to allow searching non-highlight objects
* Return: object that is being clicked on, NULL if none
*/
struct scene_obj *scene_find_obj_within(const struct scene *scn, int x, int y,
- bool reverse);
+ bool reverse, bool allow_any);
#endif /* __SCENE_INTERNAL_H */
@@ -1289,19 +1289,56 @@ static int expo_find_obj_within(struct unit_test_state *uts)
* Check finding a menu by 'clicking' on a menu item label - menu items
* are at (50,436) for ITEM1 and (50,454) for ITEM2
*/
- obj = scene_find_obj_within(scn, 60, 440, false);
+ obj = scene_find_obj_within(scn, 60, 440, false, false);
ut_assertnonnull(obj);
ut_asserteq(OBJ_MENU, obj->id);
- /* logo and text are not highlightable, so they should not be found */
- ut_assertnull(scene_find_obj_within(scn, 60, 30, false));
- ut_assertnull(scene_find_obj_within(scn, 410, 110, false));
+ /*
+ * Check with allow_any=false for non-highlightable objects - logo and
+ * text are not highlightable, so they should not be found
+ */
+ ut_assertnull(scene_find_obj_within(scn, 60, 30, false, false));
+ ut_assertnull(scene_find_obj_within(scn, 410, 110, false, false));
+
+ /* Test with allow_any=true for non-highlightable objects */
+ obj = scene_find_obj_within(scn, 60, 30, false, true);
+ ut_assertnonnull(obj);
+ ut_asserteq(OBJ_LOGO, obj->id);
+
+ /*
+ * Check reversing search order with allow_any=true at the overlapping
+ * position. OBJ_TEXT was created first at (400, 100), and the
+ * "overlap" text object was created second at (405, 105). They
+ * overlap at position (410, 110).
+ *
+ * With reverse=false, we search from start of list (bottom to top) and
+ * find OBJ_TEXT first.
+ */
+ obj = scene_find_obj_within(scn, 410, 110, false, true);
+ ut_assertnonnull(obj);
+ ut_asserteq(OBJ_TEXT, obj->id);
+
+ /*
+ * With reverse=true, we search from end of list (top to bottom) and
+ * find the OBJ_OVERLAP_TEST object first.
+ */
+ obj = scene_find_obj_within(scn, 410, 110, true, true);
+ ut_assertnonnull(obj);
+ ut_asserteq(OBJ_OVERLAP, obj->id);
+
+ /*
+ * Test reverse=true with a non-overlapping object - should get same
+ * result as reverse=false
+ */
+ obj = scene_find_obj_within(scn, 60, 30, true, true);
+ ut_assertnonnull(obj);
+ ut_asserteq(OBJ_LOGO, obj->id);
/* empty space */
- ut_assertnull(scene_find_obj_within(scn, 10, 10, false));
+ ut_assertnull(scene_find_obj_within(scn, 10, 10, false, false));
/* way outside bounds */
- ut_assertnull(scene_find_obj_within(scn, 9999, 9999, false));
+ ut_assertnull(scene_find_obj_within(scn, 9999, 9999, false, false));
abuf_uninit(&buf);
abuf_uninit(&logo_copy);