[Concept,26/27] expo: Fix textedit height calculation

Message ID 20260119204130.3972647-27-sjg@u-boot.org
State New
Headers
Series Expo debugging and textedit improvements (part E) |

Commit Message

Simon Glass Jan. 19, 2026, 8:41 p.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

The scene_txted_arrange() function sets the textedit's height to zero,
which causes problems when highlighting since the bounding box has no
height. Fix this by calculating the height from the edit text's
dimensions, similar to how scene_textline_arrange() does it.

Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 boot/scene_textedit.c | 44 ++++++++++++++++++++++++++++++++++---------
 test/boot/expo.c      |  2 +-
 2 files changed, 36 insertions(+), 10 deletions(-)
  

Patch

diff --git a/boot/scene_textedit.c b/boot/scene_textedit.c
index 2075cfbd417..d6ef725db3e 100644
--- a/boot/scene_textedit.c
+++ b/boot/scene_textedit.c
@@ -54,21 +54,31 @@  int scene_txted_set_font(struct scene *scn, uint id, const char *font_name,
 
 int scene_txted_calc_dims(struct scene_obj_txtedit *ted, struct udevice *cons)
 {
+	const struct expo_theme *theme = &ted->obj.scene->expo->theme;
 	struct scene *scn = ted->obj.scene;
 	struct scene_obj_txt *txt;
-	int ret;
+	int x0, ret;
 
 	txt = scene_obj_find(scn, ted->tin.edit_id, SCENEOBJT_NONE);
 	if (!txt)
 		return log_msg_ret("txt", -ENOENT);
 
 	/*
-	 * Set the edit text's bbox to match the textedit's bbox. This ensures
-	 * SCENEOF_SIZE_VALID is set so vidconsole_measure() applies the width
-	 * limit for word-wrapping/clipping.
+	 * Set the edit text's bbox to fit within the textedit's bbox, after
+	 * the label. This ensures SCENEOF_SIZE_VALID is set so
+	 * vidconsole_measure() applies the width limit for word-wrapping.
 	 */
+	x0 = ted->obj.req_bbox.x0;
+	if (ted->tin.label_id) {
+		int width;
+
+		ret = scene_obj_get_hw(scn, ted->tin.label_id, &width);
+		if (ret < 0)
+			return log_msg_ret("lab", ret);
+		x0 += width + theme->textline_label_margin_x;
+	}
 	ret = scene_obj_set_bbox(scn, ted->tin.edit_id,
-				 ted->obj.req_bbox.x0, ted->obj.req_bbox.y0,
+				 x0, ted->obj.req_bbox.y0,
 				 ted->obj.req_bbox.x1, ted->obj.req_bbox.y1);
 	if (ret < 0)
 		return log_msg_ret("sbb", ret);
@@ -84,7 +94,8 @@  int scene_txted_calc_dims(struct scene_obj_txtedit *ted, struct udevice *cons)
 int scene_txted_arrange(struct scene *scn, struct expo_arrange_info *arr,
 			struct scene_obj_txtedit *ted)
 {
-	int x;
+	struct scene_obj *edit;
+	int x, y;
 	int ret;
 
 	x = scene_txtin_arrange(scn, arr, &ted->obj, &ted->tin);
@@ -92,14 +103,29 @@  int scene_txted_arrange(struct scene *scn, struct expo_arrange_info *arr,
 		return log_msg_ret("arr", x);
 
 	/* constrain the edit text to fit within the textedit bbox */
-	ret = scene_obj_set_bbox(scn, ted->tin.edit_id, x, ted->obj.req_bbox.y0,
+	y = ted->obj.req_bbox.y0;
+	ret = scene_obj_set_bbox(scn, ted->tin.edit_id, x, y,
 				 ted->obj.req_bbox.x1, ted->obj.req_bbox.y1);
 	if (ret < 0)
 		return log_msg_ret("edi", ret);
 
+	/* Re-measure text with the correct limit (bbox may have changed) */
+	ret = scene_obj_get_hw(scn, ted->tin.edit_id, NULL);
+	if (ret < 0)
+		return log_msg_ret("hw", ret);
+
+	edit = scene_obj_find(scn, ted->tin.edit_id, SCENEOBJT_NONE);
+	if (!edit)
+		return log_msg_ret("fnd", -ENOENT);
+	x += edit->dims.x;
+	y += edit->dims.y;
+
+	/*
+	 * Set dims based on content size, but don't call scene_obj_set_size()
+	 * as that would overwrite the user-specified req_bbox
+	 */
 	ted->obj.dims.x = x - ted->obj.req_bbox.x0;
-	ted->obj.dims.y = 0;
-	scene_obj_set_size(scn, ted->obj.id, ted->obj.dims.x, ted->obj.dims.y);
+	ted->obj.dims.y = y - ted->obj.req_bbox.y0;
 
 	return 0;
 }
diff --git a/test/boot/expo.c b/test/boot/expo.c
index c8c97057d54..79e77b83b0a 100644
--- a/test/boot/expo.c
+++ b/test/boot/expo.c
@@ -1570,7 +1570,7 @@  static int expo_render_textedit(struct unit_test_state *uts)
 	expo_set_scene_id(exp, SCENE1);
 	ut_assertok(scene_arrange(scn));
 	ut_assertok(expo_render(exp));
-	ut_asserteq(19860, video_compress_fb(uts, dev, false));
+	ut_asserteq(19841, video_compress_fb(uts, dev, false));
 
 	abuf_uninit(&buf);
 	abuf_uninit(&logo_copy);