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 <s...@chromium.org> --- boot/cedit.c | 1 + boot/scene.c | 31 +++++++++++++++++++++---------- boot/scene_menu.c | 14 +++++++++++--- include/expo.h | 2 ++ test/boot/expo.c | 12 ++++++++++++ 5 files changed, 47 insertions(+), 13 deletions(-) diff --git a/boot/cedit.c b/boot/cedit.c index ead54b47b5b..46a48d69347 100644 --- a/boot/cedit.c +++ b/boot/cedit.c @@ -129,6 +129,7 @@ int cedit_prepare(struct expo *exp, struct video_priv **vid_privp, return log_msg_ret("sid", ret); exp->popup = true; + exp->show_highlight = true; /* This is not supported for now */ if (0) diff --git a/boot/scene.c b/boot/scene.c index 1f410ede97c..02494fff603 100644 --- a/boot/scene.c +++ b/boot/scene.c @@ -465,8 +465,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; @@ -492,7 +494,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; @@ -546,9 +548,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)); @@ -626,13 +632,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 @@ -649,7 +660,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; diff --git a/boot/scene_menu.c b/boot/scene_menu.c index fafc058a959..6fa2603bc92 100644 --- a/boot/scene_menu.c +++ b/boot/scene_menu.c @@ -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; diff --git a/include/expo.h b/include/expo.h index 16f2f18c4fa..dfecd6ed239 100644 --- a/include/expo.h +++ b/include/expo.h @@ -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; diff --git a/test/boot/expo.c b/test/boot/expo.c index 515a50f72ec..c574b6732ae 100644 --- a/test/boot/expo.c +++ b/test/boot/expo.c @@ -666,6 +666,12 @@ 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(19804, video_compress_fb(uts, dev, false)); + /* move down */ ut_assertok(expo_send_key(exp, BKEY_DOWN)); @@ -720,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(18943, video_compress_fb(uts, dev, false)); + /* now try in text mode */ expo_set_text_mode(exp, true); ut_assertok(expo_render(exp)); -- 2.43.0