mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-24 21:54:01 +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 <malloc.h>
|
||||
#include <mapmem.h>
|
||||
#include <menu.h>
|
||||
#include <video.h>
|
||||
#include <video_console.h>
|
||||
#include <linux/input.h>
|
||||
|
@ -469,11 +470,90 @@ int scene_render(struct scene *scn)
|
|||
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)
|
||||
{
|
||||
struct scene_obj_menu *menu;
|
||||
struct scene_obj *obj;
|
||||
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) {
|
||||
if (obj->type == SCENEOBJT_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,
|
||||
struct expo_action *event)
|
||||
{
|
||||
const bool open = menu->obj.flags & SCENEOF_OPEN;
|
||||
struct scene_menitem *item, *cur, *key_item;
|
||||
|
||||
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);
|
||||
break;
|
||||
case BKEY_QUIT:
|
||||
event->type = EXPOACT_QUIT;
|
||||
log_debug("quit\n");
|
||||
if (scn->expo->popup && open) {
|
||||
event->type = EXPOACT_CLOSE;
|
||||
event->select.id = menu->obj.id;
|
||||
} else {
|
||||
event->type = EXPOACT_QUIT;
|
||||
log_debug("menu quit\n");
|
||||
}
|
||||
break;
|
||||
case '0'...'9':
|
||||
key_item = scene_menu_find_key(scn, menu, key);
|
||||
|
|
|
@ -178,8 +178,7 @@ Some ideas for future work:
|
|||
- Image formats other than BMP
|
||||
- Use of ANSI sequences to control a serial terminal
|
||||
- Colour selection
|
||||
- Better support for handling lots of settings, e.g. with multiple menus and
|
||||
radio/option widgets
|
||||
- Better support for handling lots of settings, e.g. with radio/option widgets
|
||||
- Mouse support
|
||||
- Integrate Nuklear, NxWidgets or some other library for a richer UI
|
||||
- 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
|
||||
*
|
||||
* @EXPOACT_NONE: no action
|
||||
* @EXPOACT_POINT_OBJ: object 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_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
|
||||
*/
|
||||
enum expoact_type {
|
||||
EXPOACT_NONE,
|
||||
EXPOACT_POINT_OBJ,
|
||||
EXPOACT_POINT_ITEM,
|
||||
EXPOACT_SELECT,
|
||||
EXPOACT_OPEN,
|
||||
EXPOACT_CLOSE,
|
||||
EXPOACT_QUIT,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue