mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-22 04:44:46 +00:00
expo: Implement the keypress logic for popup menus
In 'popup' mode, the expo allows moving around the objects in a scene. When 'enter' is pressed on a menu, it opens and the user can move around the items in the menu. Implement this using keypress handles and actions. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
4c87e073a4
commit
4e64beeba7
4 changed files with 96 additions and 4 deletions
80
boot/scene.c
80
boot/scene.c
|
@ -13,6 +13,7 @@
|
||||||
#include <expo.h>
|
#include <expo.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <mapmem.h>
|
#include <mapmem.h>
|
||||||
|
#include <menu.h>
|
||||||
#include <video.h>
|
#include <video.h>
|
||||||
#include <video_console.h>
|
#include <video_console.h>
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
@ -469,11 +470,90 @@ int scene_render(struct scene *scn)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* send_key_obj() - Handle a keypress for moving between objects
|
||||||
|
*
|
||||||
|
* @scn: Scene to receive the key
|
||||||
|
* @key: Key to send (KEYCODE_UP)
|
||||||
|
* @event: Returns resulting event from this keypress
|
||||||
|
* Returns: 0 if OK, -ve on error
|
||||||
|
*/
|
||||||
|
static void send_key_obj(struct scene *scn, struct scene_obj *obj, int key,
|
||||||
|
struct expo_action *event)
|
||||||
|
{
|
||||||
|
switch (key) {
|
||||||
|
case BKEY_UP:
|
||||||
|
while (obj != list_first_entry(&scn->obj_head, struct scene_obj,
|
||||||
|
sibling)) {
|
||||||
|
obj = list_entry(obj->sibling.prev,
|
||||||
|
struct scene_obj, sibling);
|
||||||
|
if (obj->type == SCENEOBJT_MENU) {
|
||||||
|
event->type = EXPOACT_POINT_OBJ;
|
||||||
|
event->select.id = obj->id;
|
||||||
|
log_debug("up to obj %d\n", event->select.id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BKEY_DOWN:
|
||||||
|
while (!list_is_last(&obj->sibling, &scn->obj_head)) {
|
||||||
|
obj = list_entry(obj->sibling.next, struct scene_obj,
|
||||||
|
sibling);
|
||||||
|
if (obj->type == SCENEOBJT_MENU) {
|
||||||
|
event->type = EXPOACT_POINT_OBJ;
|
||||||
|
event->select.id = obj->id;
|
||||||
|
log_debug("down to obj %d\n", event->select.id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BKEY_SELECT:
|
||||||
|
if (obj->type == SCENEOBJT_MENU) {
|
||||||
|
event->type = EXPOACT_OPEN;
|
||||||
|
event->select.id = obj->id;
|
||||||
|
log_debug("open obj %d\n", event->select.id);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BKEY_QUIT:
|
||||||
|
event->type = EXPOACT_QUIT;
|
||||||
|
log_debug("obj quit\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int scene_send_key(struct scene *scn, int key, struct expo_action *event)
|
int scene_send_key(struct scene *scn, int key, struct expo_action *event)
|
||||||
{
|
{
|
||||||
|
struct scene_obj_menu *menu;
|
||||||
struct scene_obj *obj;
|
struct scene_obj *obj;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
event->type = EXPOACT_NONE;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In 'popup' mode, arrow keys move betwen objects, unless a menu is
|
||||||
|
* opened
|
||||||
|
*/
|
||||||
|
if (scn->expo->popup) {
|
||||||
|
obj = NULL;
|
||||||
|
if (scn->highlight_id) {
|
||||||
|
obj = scene_obj_find(scn, scn->highlight_id,
|
||||||
|
SCENEOBJT_NONE);
|
||||||
|
}
|
||||||
|
if (!obj)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(obj->flags & SCENEOF_OPEN)) {
|
||||||
|
send_key_obj(scn, obj, key, event);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu = (struct scene_obj_menu *)obj,
|
||||||
|
ret = scene_menu_send_key(scn, menu, key, event);
|
||||||
|
if (ret)
|
||||||
|
return log_msg_ret("key", ret);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
list_for_each_entry(obj, &scn->obj_head, sibling) {
|
list_for_each_entry(obj, &scn->obj_head, sibling) {
|
||||||
if (obj->type == SCENEOBJT_MENU) {
|
if (obj->type == SCENEOBJT_MENU) {
|
||||||
struct scene_obj_menu *menu;
|
struct scene_obj_menu *menu;
|
||||||
|
|
|
@ -323,6 +323,7 @@ static struct scene_menitem *scene_menu_find_key(struct scene *scn,
|
||||||
int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key,
|
int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key,
|
||||||
struct expo_action *event)
|
struct expo_action *event)
|
||||||
{
|
{
|
||||||
|
const bool open = menu->obj.flags & SCENEOF_OPEN;
|
||||||
struct scene_menitem *item, *cur, *key_item;
|
struct scene_menitem *item, *cur, *key_item;
|
||||||
|
|
||||||
cur = NULL;
|
cur = NULL;
|
||||||
|
@ -367,8 +368,13 @@ int scene_menu_send_key(struct scene *scn, struct scene_obj_menu *menu, int key,
|
||||||
log_debug("select item %d\n", event->select.id);
|
log_debug("select item %d\n", event->select.id);
|
||||||
break;
|
break;
|
||||||
case BKEY_QUIT:
|
case BKEY_QUIT:
|
||||||
|
if (scn->expo->popup && open) {
|
||||||
|
event->type = EXPOACT_CLOSE;
|
||||||
|
event->select.id = menu->obj.id;
|
||||||
|
} else {
|
||||||
event->type = EXPOACT_QUIT;
|
event->type = EXPOACT_QUIT;
|
||||||
log_debug("quit\n");
|
log_debug("menu quit\n");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case '0'...'9':
|
case '0'...'9':
|
||||||
key_item = scene_menu_find_key(scn, menu, key);
|
key_item = scene_menu_find_key(scn, menu, key);
|
||||||
|
|
|
@ -178,8 +178,7 @@ Some ideas for future work:
|
||||||
- Image formats other than BMP
|
- Image formats other than BMP
|
||||||
- Use of ANSI sequences to control a serial terminal
|
- Use of ANSI sequences to control a serial terminal
|
||||||
- Colour selection
|
- Colour selection
|
||||||
- Better support for handling lots of settings, e.g. with multiple menus and
|
- Better support for handling lots of settings, e.g. with radio/option widgets
|
||||||
radio/option widgets
|
|
||||||
- Mouse support
|
- Mouse support
|
||||||
- Integrate Nuklear, NxWidgets or some other library for a richer UI
|
- Integrate Nuklear, NxWidgets or some other library for a richer UI
|
||||||
- Optimise rendering by only updating the display with changes since last render
|
- Optimise rendering by only updating the display with changes since last render
|
||||||
|
|
|
@ -16,14 +16,21 @@ struct udevice;
|
||||||
* enum expoact_type - types of actions reported by the expo
|
* enum expoact_type - types of actions reported by the expo
|
||||||
*
|
*
|
||||||
* @EXPOACT_NONE: no action
|
* @EXPOACT_NONE: no action
|
||||||
|
* @EXPOACT_POINT_OBJ: object was highlighted (@id indicates which)
|
||||||
* @EXPOACT_POINT_ITEM: menu item was highlighted (@id indicates which)
|
* @EXPOACT_POINT_ITEM: menu item was highlighted (@id indicates which)
|
||||||
* @EXPOACT_SELECT: menu item was selected (@id indicates which)
|
* @EXPOACT_SELECT: menu item was selected (@id indicates which)
|
||||||
|
* @EXPOACT_OPEN: menu was opened, so an item can be selected (@id indicates
|
||||||
|
* which menu object)
|
||||||
|
* @EXPOACT_CLOSE: menu was closed (@id indicates which menu object)
|
||||||
* @EXPOACT_QUIT: request to exit the menu
|
* @EXPOACT_QUIT: request to exit the menu
|
||||||
*/
|
*/
|
||||||
enum expoact_type {
|
enum expoact_type {
|
||||||
EXPOACT_NONE,
|
EXPOACT_NONE,
|
||||||
|
EXPOACT_POINT_OBJ,
|
||||||
EXPOACT_POINT_ITEM,
|
EXPOACT_POINT_ITEM,
|
||||||
EXPOACT_SELECT,
|
EXPOACT_SELECT,
|
||||||
|
EXPOACT_OPEN,
|
||||||
|
EXPOACT_CLOSE,
|
||||||
EXPOACT_QUIT,
|
EXPOACT_QUIT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue