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

Reply via email to