[Concept,15/23] expo: Support sending a click to a menu

Message ID 20250915122905.1217249-16-sjg@u-boot.org
State New
Headers
Series expo: Support interactions with a mouse or touchpad |

Commit Message

Simon Glass Sept. 15, 2025, 12:28 p.m. UTC
  From: Simon Glass <sjg@chromium.org>

Clicking on a menu can result in selecting an item. If it is a popup
menu then the item should be closed. Add support for this.

Signed-off-by: Simon Glass <sjg@chromium.org>
---

 boot/scene_internal.h | 13 +++++++++++++
 boot/scene_menu.c     | 30 ++++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)
  

Patch

diff --git a/boot/scene_internal.h b/boot/scene_internal.h
index 03bc925edfe..91828538417 100644
--- a/boot/scene_internal.h
+++ b/boot/scene_internal.h
@@ -184,6 +184,19 @@  int scene_apply_theme(struct scene *scn, struct expo_theme *theme);
 int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key,
 			struct expo_action *event);
 
+/**
+ * scene_menu_send_click() - Send a click to a menu for processing
+ *
+ * @scn: Scene to use
+ * @menu: Menu to use
+ * @x: X coordinate of click
+ * @y: Y coordinate of click
+ * @event: Place to put any event which is generated by the click
+ * Returns: 0 if OK, -ENOTTY if there is no menu item at that position
+ */
+int scene_menu_send_click(struct scene *scn, struct scene_obj_menu *menu, int x,
+			  int y, struct expo_action *event);
+
 /**
  * scene_textline_send_key() - Send a key to a textline for processing
  *
diff --git a/boot/scene_menu.c b/boot/scene_menu.c
index 758343fe909..d54b99979e1 100644
--- a/boot/scene_menu.c
+++ b/boot/scene_menu.c
@@ -528,6 +528,36 @@  struct scene_menitem *scene_menu_within(const struct scene *scn,
 	return NULL;
 }
 
+int scene_menu_send_click(struct scene *scn, struct scene_obj_menu *menu, int x,
+			  int y, struct expo_action *event)
+{
+	struct scene_menitem *item;
+
+	if (scn->expo->popup)
+		assert(menu->obj.flags & SCENEOF_OPEN);
+
+	log_debug("menu %d '%s': x %d y %d\n", menu->obj.id, menu->obj.name,
+		  x, y);
+
+	item = scene_menu_within(scn, menu, x, y);
+	if (!item) {
+		log_debug("not found\n");
+		return -ENOTTY;
+	}
+
+	if (scn->expo->popup) {
+		assert(menu->obj.flags & SCENEOF_OPEN);
+		/* Menu is open - point to item and close menu */
+		event->type = EXPOACT_POINT_CLOSE;
+		log_debug("point-close item %d\n", item->id);
+	} else {
+		event->type = EXPOACT_SELECT;
+		log_debug("select item %d\n", item->id);
+	}
+	event->select.id = item->id;
+		return 0;
+}
+
 int scene_menuitem(struct scene *scn, uint menu_id, const char *name, uint id,
 		   uint key_id, uint label_id, uint desc_id, uint preview_id,
 		   uint flags, struct scene_menitem **itemp)