]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
expo: Provide a way to iterate through all scene objects
authorSimon Glass <sjg@chromium.org>
Mon, 14 Aug 2023 22:40:23 +0000 (16:40 -0600)
committerTom Rini <trini@konsulko.com>
Fri, 25 Aug 2023 17:54:33 +0000 (13:54 -0400)
For some operations it is necessary to process all objects in an expo.
Provide an iterator to handle this.

Signed-off-by: Simon Glass <sjg@chromium.org>
boot/expo.c
boot/scene.c
boot/scene_internal.h
test/boot/expo.c

index db837f7b49241c11cbe4ae58689fbd164e167202..139d684f8e6e06a0f4a1d48920213c2def9281af 100644 (file)
@@ -266,3 +266,18 @@ int expo_apply_theme(struct expo *exp, ofnode node)
 
        return 0;
 }
+
+int expo_iter_scene_objs(struct expo *exp, expo_scene_obj_iterator iter,
+                        void *priv)
+{
+       struct scene *scn;
+       int ret;
+
+       list_for_each_entry(scn, &exp->scene_head, sibling) {
+               ret = scene_iter_objs(scn, iter, priv);
+               if (ret)
+                       return log_msg_ret("wr", ret);
+       }
+
+       return 0;
+}
index b4c36c41702ffcc4218474f2add7d19e8bb91651..6c52948eb69c1942d4ac7ce2106019f9ff1360d7 100644 (file)
@@ -681,3 +681,19 @@ int scene_set_open(struct scene *scn, uint id, bool open)
 
        return 0;
 }
+
+int scene_iter_objs(struct scene *scn, expo_scene_obj_iterator iter,
+                   void *priv)
+{
+       struct scene_obj *obj;
+
+       list_for_each_entry(obj, &scn->obj_head, sibling) {
+               int ret;
+
+               ret = iter(obj, priv);
+               if (ret)
+                       return log_msg_ret("itr", ret);
+       }
+
+       return 0;
+}
index 1620d10a7778bb99142ff0ad86a425c167200507..60b143440785f056c00e01490166cafd3a0c4901 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef __SCENE_INTERNAL_H
 #define __SCENE_INTERNAL_H
 
+typedef int (*expo_scene_obj_iterator)(struct scene_obj *obj, void *priv);
+
 /**
  * expo_lookup_scene_id() - Look up a scene ID
  *
@@ -198,4 +200,26 @@ int scene_menu_render_deps(struct scene *scn, struct scene_obj_menu *menu);
  */
 int scene_menu_calc_dims(struct scene_obj_menu *menu);
 
+/**
+ * scene_iter_objs() - Iterate through all scene objects
+ *
+ * @scn: Scene to process
+ * @iter: Iterator to call on each object
+ * @priv: Private data to pass to the iterator, in addition to the object
+ * Return: 0 if OK, -ve on error
+ */
+int scene_iter_objs(struct scene *scn, expo_scene_obj_iterator iter,
+                   void *priv);
+
+/**
+ * expo_iter_scene_objects() - Iterate through all scene objects
+ *
+ * @exp: Expo to process
+ * @iter: Iterator to call on each object
+ * @priv: Private data to pass to the iterator, in addition to the object
+ * Return: 0 if OK, -ve on error
+ */
+int expo_iter_scene_objs(struct expo *exp, expo_scene_obj_iterator iter,
+                        void *priv);
+
 #endif /* __SCENE_INTERNAL_H */
index 3898f853a75165ca28eadca6766579dee8a1b02d..458e332440c343a87a9955d91332e1d0bb397812 100644 (file)
@@ -289,6 +289,33 @@ static int expo_object_attr(struct unit_test_state *uts)
 }
 BOOTSTD_TEST(expo_object_attr, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
 
+/**
+ * struct test_iter_priv - private data for expo-iterator test
+ *
+ * @count: number of scene objects
+ * @menu_count: number of menus
+ * @fail_at: item ID at which to return an error
+ */
+struct test_iter_priv {
+       int count;
+       int menu_count;
+       int fail_at;
+};
+
+int h_test_iter(struct scene_obj *obj, void *vpriv)
+{
+       struct test_iter_priv *priv = vpriv;
+
+       if (priv->fail_at == obj->id)
+               return -EINVAL;
+
+       priv->count++;
+       if (obj->type == SCENEOBJT_MENU)
+               priv->menu_count++;
+
+       return 0;
+}
+
 /* Check creating a scene with a menu */
 static int expo_object_menu(struct unit_test_state *uts)
 {
@@ -296,6 +323,7 @@ static int expo_object_menu(struct unit_test_state *uts)
        struct scene_menitem *item;
        int id, label_id, desc_id, key_id, pointer_id, preview_id;
        struct scene_obj_txt *ptr, *name1, *desc1, *key1, *tit, *prev1;
+       struct test_iter_priv priv;
        struct scene *scn;
        struct expo *exp;
        ulong start_mem;
@@ -382,6 +410,23 @@ static int expo_object_menu(struct unit_test_state *uts)
        ut_asserteq(menu->obj.dim.y + 32, prev1->obj.dim.y);
        ut_asserteq(true, prev1->obj.flags & SCENEOF_HIDE);
 
+       /* check iterating through scene items */
+       memset(&priv, '\0', sizeof(priv));
+       ut_assertok(expo_iter_scene_objs(exp, h_test_iter, &priv));
+       ut_asserteq(7, priv.count);
+       ut_asserteq(1, priv.menu_count);
+
+       /* check the iterator failing part way through iteration */
+       memset(&priv, '\0', sizeof(priv));
+       priv.fail_at = key_id;
+       ut_asserteq(-EINVAL, expo_iter_scene_objs(exp, h_test_iter, &priv));
+
+       /* 2 items (preview_id and the menuitem) are after key_id, 7 - 2 = 5 */
+       ut_asserteq(5, priv.count);
+
+       /* menu is first, so is still processed */
+       ut_asserteq(1, priv.menu_count);
+
        expo_destroy(exp);
 
        ut_assertok(ut_check_delta(start_mem));