grub/gfxmenu/gfxmenu.c
Vladimir 'phcoder' Serbinenko a9c12f8533 Remove hardcoded hotkeys
2009-11-24 04:20:18 +01:00

215 lines
5.9 KiB
C

/* gfxmenu.c - Graphical menu interface controller. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/err.h>
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/video.h>
#include <grub/gfxterm.h>
#include <grub/bitmap.h>
#include <grub/bitmap_scale.h>
#include <grub/term.h>
#include <grub/env.h>
#include <grub/normal.h>
#include <grub/gfxwidgets.h>
#include <grub/menu.h>
#include <grub/menu_viewer.h>
#include <grub/gfxmenu_model.h>
#include <grub/gfxmenu_view.h>
static void switch_to_text_menu (void)
{
grub_env_set ("menuviewer", "text");
}
static void
process_key_press (int c,
grub_gfxmenu_model_t model,
grub_gfxmenu_view_t view,
int nested,
int *should_exit)
{
/* When a key is pressed, stop the timeout. */
grub_gfxmenu_model_clear_timeout (model);
if (c == 'j' || c == GRUB_TERM_DOWN)
{
int i = grub_gfxmenu_model_get_selected_index (model);
int num_items = grub_gfxmenu_model_get_num_entries (model);
if (i < num_items - 1)
{
i++;
grub_gfxmenu_model_set_selected_index (model, i);
}
}
else if (c == 'k' || c == GRUB_TERM_UP)
{
int i = grub_gfxmenu_model_get_selected_index (model);
if (i > 0)
{
i--;
grub_gfxmenu_model_set_selected_index (model, i);
}
}
else if (c == '\r' || c == '\n' || c == GRUB_TERM_RIGHT)
{
int selected = grub_gfxmenu_model_get_selected_index (model);
int num_entries = grub_gfxmenu_model_get_num_entries (model);
if (selected >= 0 && selected < num_entries)
{
grub_menu_entry_t entry =
grub_gfxmenu_model_get_entry (model, selected);
grub_gfxmenu_view_execute_entry (view, entry);
}
}
else if (c == 'c')
{
grub_gfxmenu_view_run_terminal (view);
}
else if (c == 't')
{
/* The write hook for 'menuviewer' will cause
* grub_menu_viewer_should_return to return nonzero. */
switch_to_text_menu ();
*should_exit = 1;
}
else if (nested && c == GRUB_TERM_ESC)
{
*should_exit = 1;
}
if (grub_errno != GRUB_ERR_NONE)
*should_exit = 1;
}
static void
handle_key_events (grub_gfxmenu_model_t model,
grub_gfxmenu_view_t view,
int nested,
int *should_exit)
{
while ((! *should_exit) && (grub_checkkey () != -1))
{
int key = grub_getkey ();
int c = GRUB_TERM_ASCII_CHAR (key);
process_key_press (c, model, view, nested, should_exit);
}
}
static grub_err_t
show_menu (grub_menu_t menu, int nested)
{
grub_gfxmenu_model_t model;
model = grub_gfxmenu_model_new (menu);
if (! model)
{
grub_print_error ();
grub_printf ("Initializing menu data for graphical menu failed;\n"
"falling back to text based menu.\n");
grub_wait_after_message ();
switch_to_text_menu ();
return grub_errno;
}
grub_gfxmenu_view_t view;
/* Create the view. */
const char *theme_path = grub_env_get ("theme");
if (! theme_path)
theme_path = "/boot/grub/themes/proto/theme.txt";
view = grub_gfxmenu_view_new (theme_path, model);
if (! view)
{
grub_print_error ();
grub_printf ("Starting graphical menu failed;\n"
"falling back to text based menu.\n");
grub_wait_after_message ();
grub_gfxmenu_model_destroy (model);
switch_to_text_menu ();
return grub_errno;
}
/* Initially select the default menu entry. */
int default_index = grub_menu_get_default_entry_index (menu);
grub_gfxmenu_model_set_selected_index (model, default_index);
/* Start the timer to execute the default entry. */
grub_gfxmenu_model_set_timeout (model);
/* Main event loop. */
int exit_requested = 0;
while ((! exit_requested) && (! grub_menu_viewer_should_return ()))
{
if (grub_gfxmenu_model_timeout_expired (model))
{
grub_gfxmenu_model_clear_timeout (model);
int i = grub_gfxmenu_model_get_selected_index (model);
grub_menu_entry_t e = grub_gfxmenu_model_get_entry (model, i);
grub_gfxmenu_view_execute_with_fallback (view, e);
continue;
}
grub_gfxmenu_view_draw (view);
grub_video_swap_buffers ();
handle_key_events (model, view, nested, &exit_requested);
}
grub_gfxmenu_view_destroy (view);
grub_gfxmenu_model_destroy (model);
return grub_errno;
}
static grub_err_t
grub_cmd_gfxmenu (grub_command_t cmd UNUSED,
int argc UNUSED, char **args UNUSED)
{
grub_menu_t menu = grub_env_get_data_slot ("menu");
if (! menu)
return grub_error (GRUB_ERR_MENU, "no menu context");
return show_menu (menu, 1);
}
static struct grub_menu_viewer menu_viewer =
{
.name = "gfxmenu",
.show_menu = show_menu
};
static grub_command_t cmd;
GRUB_MOD_INIT (gfxmenu)
{
(void) mod; /* To stop warning. */
grub_menu_viewer_register (&menu_viewer);
cmd = grub_register_command ("gfxmenu", grub_cmd_gfxmenu,
"gfxmenu",
"Show graphical menu interface");
}
GRUB_MOD_FINI (gfxmenu)
{
grub_unregister_command (cmd);
}