expo: Support highlighting menu items

Expo normally uses a pointer to show the current item. Add support for
highlighting as well, since this makes it easier for the user to see the
current item.

Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Simon Glass
2025-05-02 08:46:50 -06:00
parent 86acc21d85
commit 0dc8c7740c
5 changed files with 48 additions and 13 deletions

View File

@@ -126,6 +126,7 @@ int cedit_prepare(struct expo *exp, struct udevice *vid_dev,
return log_msg_ret("sid", ret);
exp->popup = true;
exp->show_highlight = true;
/* This is not supported for now */
if (0)

View File

@@ -466,8 +466,10 @@ int scene_obj_get_hw(struct scene *scn, uint id, int *widthp)
* @obj: Object to render
* @box_only: true to show a box around the object, but keep the normal
* background colour inside
* @cur_item: true to render the background only for the current menu item
*/
static void scene_render_background(struct scene_obj *obj, bool box_only)
static void scene_render_background(struct scene_obj *obj, bool box_only,
bool cur_item)
{
struct vidconsole_bbox bbox[SCENEBB_count], *sel;
struct expo *exp = obj->scene->expo;
@@ -493,7 +495,7 @@ static void scene_render_background(struct scene_obj *obj, bool box_only)
if (scene_obj_calc_bbox(obj, bbox))
return;
sel = &bbox[SCENEBB_label];
sel = cur_item ? &bbox[SCENEBB_curitem] : &bbox[SCENEBB_label];
if (!sel->valid)
return;
@@ -547,9 +549,13 @@ static int scene_txt_render(struct expo *exp, struct udevice *dev,
}
if (obj->flags & SCENEOF_POINT) {
int inset;
inset = exp->popup ? menu_inset : 0;
vidconsole_push_colour(cons, fore, back, &old);
video_fill_part(dev, x - menu_inset, y, obj->bbox.x1,
obj->bbox.y1, vid_priv->colour_bg);
video_fill_part(dev, x - inset, y,
obj->bbox.x1, obj->bbox.y1,
vid_priv->colour_bg);
}
mline = alist_get(&gen->lines, 0, typeof(*mline));
@@ -632,13 +638,18 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
case SCENEOBJT_MENU: {
struct scene_obj_menu *menu = (struct scene_obj_menu *)obj;
if (exp->popup && (obj->flags & SCENEOF_OPEN)) {
if (!cons)
return -ENOTSUPP;
if (exp->popup) {
if (obj->flags & SCENEOF_OPEN) {
if (!cons)
return -ENOTSUPP;
/* draw a background behind the menu items */
scene_render_background(obj, false);
/* draw a background behind the menu items */
scene_render_background(obj, false, false);
}
} else if (exp->show_highlight) {
/* do nothing */
}
/*
* With a vidconsole, the text and item pointer are rendered as
* normal objects so we don't need to do anything here. The menu
@@ -655,7 +666,7 @@ static int scene_obj_render(struct scene_obj *obj, bool text_mode)
}
case SCENEOBJT_TEXTLINE:
if (obj->flags & SCENEOF_OPEN)
scene_render_background(obj, true);
scene_render_background(obj, true, false);
break;
case SCENEOBJT_BOX: {
struct scene_obj_box *box = (struct scene_obj_box *)obj;

View File

@@ -87,7 +87,7 @@ struct scene_menitem *scene_menuitem_find_val(const struct scene_obj_menu *menu,
static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
{
struct scene *scn = menu->obj.scene;
const bool stack = scn->expo->popup;
const bool stack = scn->expo->show_highlight;
const struct scene_menitem *item;
int ret;
@@ -108,9 +108,17 @@ static int update_pointers(struct scene_obj_menu *menu, uint id, bool point)
}
if (stack) {
uint id;
int val;
point &= scn->highlight_id == menu->obj.id;
scene_obj_flag_clrset(scn, item->label_id, SCENEOF_POINT,
point ? SCENEOF_POINT : 0);
val = point ? SCENEOF_POINT : 0;
id = item->desc_id;
if (!id)
id = item->label_id;
if (!id)
id = item->key_id;
scene_obj_flag_clrset(scn, id, SCENEOF_POINT, val);
}
return 0;

View File

@@ -106,6 +106,7 @@ struct expo_theme {
* type set to EXPOACT_NONE if there is no action
* @text_mode: true to use text mode for the menu (no vidconsole)
* @popup: true to use popup menus, instead of showing all items
* @show_highlight: show a highlight bar on the selected menu item
* @priv: Private data for the controller
* @done: Indicates that a cedit session is complete and the user has quit
* @save: Indicates that cedit data should be saved, rather than discarded
@@ -123,6 +124,7 @@ struct expo {
struct expo_action action;
bool text_mode;
bool popup;
bool show_highlight;
void *priv;
bool done;
bool save;

View File

@@ -666,6 +666,13 @@ static int expo_render_image(struct unit_test_state *uts)
ut_assertok(scene_arrange(scn));
ut_asserteq(0, scn->highlight_id);
scene_set_highlight_id(scn, OBJ_MENU);
ut_assertok(scene_arrange(scn));
ut_asserteq(OBJ_MENU, scn->highlight_id);
ut_assertok(expo_render(exp));
ut_asserteq(19704, video_compress_fb(uts, dev, false));
/* move down */
ut_assertok(expo_send_key(exp, BKEY_DOWN));
@@ -719,6 +726,12 @@ static int expo_render_image(struct unit_test_state *uts)
/* make sure there was no console output */
ut_assert_console_end();
/* now try with the highlight */
exp->show_highlight = true;
ut_assertok(scene_arrange(scn));
ut_assertok(expo_render(exp));
ut_asserteq(18844, video_compress_fb(uts, dev, false));
/* now try in text mode */
expo_set_text_mode(exp, true);
ut_assertok(expo_render(exp));