From patchwork Mon Sep 15 12:28:44 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 326 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1757939402; bh=aUlhYq1GkdhBtArbr4gnD+uyWxCnUetlFpkGooU1e+U=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=KqReUBiEHVA0eZ2LIc0Op7uMFa6UqzM0533nJr3/hBnRDwldKWQR/C2fasYn+3efD dJSqxsVZV6hcBNeqAIQN9w2n3zVm6W5zwytlROf+ATcFOm5SUzI4k/WAEwjZHO5Xx1 JTFHYWkpuD7NnOnSWQcWx99a1nMj31A1eQ3x9aM5XXsmC5PrqevP5vOmWIXjaA8ql1 TGQUayOpZdwjgQLa2dC9HuXLUo+LZvHhwKLyyqK8QHC6pByzy9AX/igO+lSU8y5/Du jjr7YDT3vSX+dpCSBdHDoH7Hy3b8c/dmMVMrfjfBsRIG8zaNa0vIoGcr7R/O3V/KIn IEovsqQ2Wb/AA== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 10C1367BD5 for ; Mon, 15 Sep 2025 06:30:02 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id 9vkeXqlxKwoX for ; Mon, 15 Sep 2025 06:30:01 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1757939401; bh=aUlhYq1GkdhBtArbr4gnD+uyWxCnUetlFpkGooU1e+U=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=LUtlxNCvUw5k9EYcuNUKGLOGrmsxzmn2bm5qP3alcTJ9JUVXuGmEKnIdxtRs4uzHq On58o0N9I3ycUATiSvBx9YysKhdXL6FDNJyqmYPJGbPZVnxhY1TX099dQ6csW+qGIv hFRIfafAB33pchW3JRx8dDcnF9aFMQ2XycWxRSowrPwYf2OWvsmCnnfM0NfQazRDOQ 1k/LHnoAshlLc8S+yphvgALgW6NwVUgdbRJrhMnrWPjyXbnyPdGNy/NOipCaHvzx1x bJaYELuDoxd7m8XK7MtqUHGOI82nh8r6xgkybM1ykRvXsdGf/F8QH+PQcHptMdob06 gKYW221bb84gQ== Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 01AC667B44 for ; Mon, 15 Sep 2025 06:30:01 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1757939399; bh=cIZCTDr3YMJeeQjKlZFou4/zogsxgOGO5h+mlnjxr70=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=tCicUPGOB2byX2QdxP5LchPZY+YcITxAi2/v62A+SPvakgyHt0w6BxvtiCQF2BLk/ RVFKMXqW8+IYMFYHVqwy9g2z5zXHZy2P2yxxcGVLYVplev310+NNLgXayCJTp3Lr4V eovSycF1EC8LgfZMiPjBKw9eGSd7F4i5ZYD3A2pbfbbn3nwBfeFNyXYv00ZVHXcgJU t87Wj0l9RkoBbNzmIiAos5mOxm4Uf+aSVP5Mlp67BfJ1RxHharBR2m3+IuDI/mPGsN hi1M5vMDkoVVd0IEhZVSUK73Oh066OAwS222Nvbomf4EvckpEoROgNOeTK3juzCzok S7MQt4uZBcPxg== Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 5FB4B67B44; Mon, 15 Sep 2025 06:29:59 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id ZilBeRfylSjN; Mon, 15 Sep 2025 06:29:59 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1757939397; bh=jhLAABVJH3hBvJhNTbw3DVDVy8gylzM+qMGXarmUn8M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=omST5VHKYZCI50/zbart4+sRFKtsITA2bjA+475IlVm2hQrV/7PF9vW6p8kaeWB+Z 85V2jH64Yr49h/JVA4c3h3uOt2r8QYBfiIYpP4KqJaJNVd7Yj31aCiyEo6wzBo49l7 BBXwsy9eCktLaialYrxo8iRSjglVmDUCTH2xFDastbOoNzV6nqbx9V2UxecsKtfY7y 4jQPl7nu1YUnJgaogqkxDd7io14uNVLt1XEVsRbIn7oa1BUVI5aMQym4Rx4OlZKcrP 6o38uoO41VSwHUGApcmYfycChDO97OJb0y1V2nPsfv/3Fjg+CdnRi8kpkfPkdQy2xF 7kzniZaijjYxA== Received: from u-boot.org (unknown [73.34.74.121]) by mail.u-boot.org (Postfix) with ESMTPSA id 8162267B3C; Mon, 15 Sep 2025 06:29:57 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Mon, 15 Sep 2025 06:28:44 -0600 Message-ID: <20250915122905.1217249-12-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250915122905.1217249-1-sjg@u-boot.org> References: <20250915122905.1217249-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: D2DM7IKCTEC3OCOFSBXOR5QJIUFIKK5Y X-Message-ID-Hash: D2DM7IKCTEC3OCOFSBXOR5QJIUFIKK5Y X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Heinrich Schuchardt , Simon Glass , Claude X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 11/23] expo: Provide a way to check if a position is within a menu List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass To implement mouse clicks we need a way to figure out what the user has clicked on. As a starting point, create a scene_menu_within() function which returns the item containing an x, y coordinate. Provide a helper function in scene.c for use with this. Add a simple for completeness. Co-developed-by: Claude Signed-off-by: Simon Glass --- boot/scene.c | 17 +++++++++++++++ boot/scene_internal.h | 24 +++++++++++++++++++++ boot/scene_menu.c | 31 +++++++++++++++++++++++++++ test/boot/expo.c | 49 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+) diff --git a/boot/scene.c b/boot/scene.c index 50a7dfb22a1..98716ef2337 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -1028,6 +1028,23 @@ int scene_send_key(struct scene *scn, int key, struct expo_action *event) return 0; } +bool scene_within(const struct scene *scn, uint id, int x, int y) +{ + struct scene_obj *obj; + + obj = scene_obj_find(scn, id, SCENEOBJT_NONE); + if (!obj) { + log_debug("Cannot find id %d\n", id); + return false; + } + log_debug("- id %d: '%s' bbox x0 %d y0 %d x1 %d y1 %d\n", id, obj->name, + obj->bbox.x0, obj->bbox.y0, obj->bbox.x1, obj->bbox.x1); + + /* Check if point (x, y) is within object's bounding box */ + return (x >= obj->bbox.x0 && x <= obj->bbox.x1 && + y >= obj->bbox.y0 && y <= obj->bbox.y1); +} + int scene_obj_calc_bbox(struct scene_obj *obj, struct vidconsole_bbox bbox[]) { switch (obj->type) { diff --git a/boot/scene_internal.h b/boot/scene_internal.h index c6f2615a2c5..15a96b1e31e 100644 --- a/boot/scene_internal.h +++ b/boot/scene_internal.h @@ -241,6 +241,30 @@ int scene_render(struct scene *scn); */ int scene_send_key(struct scene *scn, int key, struct expo_action *event); +/** + * scene_within() - check if a point is considered within an object ID + * + * @scn: Scene to check + * @id: ID of object to check + * @x: X coordinate of the point + * @y: Y coordinate of the point + * Return: true if the point is considered within the object, false if not + */ +bool scene_within(const struct scene *scn, uint id, int x, int y); + +/** + * scene_menu_within() - check if a point is considered within a menu + * + * @scn: Scene to check + * @menu: Menu to check + * @x: X coordinate of the point + * @y: Y coordinate of the point + * Return: item the point is within, or NULL if none + */ +struct scene_menitem *scene_menu_within(const struct scene *scn, + struct scene_obj_menu *menu, + int x, int y); + /** * scene_render_deps() - Render an object and its dependencies * diff --git a/boot/scene_menu.c b/boot/scene_menu.c index 0ed73cd12cc..758343fe909 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -497,6 +497,37 @@ int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key, return 0; } +struct scene_menitem *scene_menu_within(const struct scene *scn, + struct scene_obj_menu *menu, + int x, int y) +{ + struct scene_menitem *item; + + list_for_each_entry(item, &menu->item_head, sibling) { + log_debug(" item %d: label %d\n", item->id, item->label_id); + bool within; + + within = scene_within(scn, item->label_id, x, y); + log_debug("- item %d within %d\n", item->id, within); + if (!within && !scn->expo->popup) { + log_debug("- non-popup within key %d desc %d preview %d\n", + scene_within(scn, item->key_id, x, y), + scene_within(scn, item->desc_id, x, y), + scene_within(scn, item->preview_id, x, y)); + within |= scene_within(scn, item->key_id, x, y) || + scene_within(scn, item->desc_id, x, y) || + scene_within(scn, item->preview_id, x, y); + log_debug("- popup within %d\n", within); + } + + log_debug("- final within %d\n", within); + if (within) + return item; + } + + return NULL; +} + int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id, uint key_id, uint label_id, uint desc_id, uint preview_id, uint flags, struct scene_menitem **itemp) diff --git a/test/boot/expo.c b/test/boot/expo.c index d407ad839f6..99c28cc77f6 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -962,6 +962,55 @@ static int expo_test_build(struct unit_test_state *uts) } BOOTSTD_TEST(expo_test_build, UTF_DM); +/* test scene_menu_within() function */ +static int expo_menu_within(struct unit_test_state *uts) +{ + struct scene_obj_menu *menu; + struct scene_menitem *item; + struct scene_obj *obj; + struct udevice *dev; + struct scene *scn; + struct expo *exp; + ofnode node; + + node = ofnode_path("/cedit"); + ut_assert(ofnode_valid(node)); + ut_assertok(expo_build(node, &exp)); + + scn = expo_lookup_scene_id(exp, ID_SCENE1); + ut_assertnonnull(scn); + + menu = scene_obj_find(scn, ID_CPU_SPEED, SCENEOBJT_NONE); + ut_assertnonnull(menu); + + ut_assertok(uclass_first_device_err(UCLASS_VIDEO, &dev)); + ut_assertok(expo_set_display(exp, dev)); + + ut_assertok(scene_arrange(scn)); + + /* get first menu item and test with its coordinates */ + item = list_first_entry(&menu->item_head, struct scene_menitem, + sibling); + ut_assertnonnull(item); + + /* get the label object to find coordinates */ + obj = scene_obj_find(scn, item->label_id, SCENEOBJT_NONE); + ut_assertnonnull(obj); + ut_asserteq_ptr(item, scene_menu_within(scn, menu, obj->bbox.x0 + 1, + obj->bbox.y0 + 1)); + + /* test point outside menu bounds */ + ut_assertnull(scene_menu_within(scn, menu, -1, -1)); + + /* test point far outside menu bounds */ + ut_assertnull(scene_menu_within(scn, menu, 9999, 9999)); + + expo_destroy(exp); + + return 0; +} +BOOTSTD_TEST(expo_menu_within, UTF_DM | UTF_SCAN_FDT); + /* test expo_set_mouse_enable() */ static int expo_mouse_enable(struct unit_test_state *uts) {