Various fixes to make gfxmenu work smoothly in multioutput environment

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2009-12-26 16:41:54 +01:00
parent 9b1209ba15
commit d3ee2d201e
6 changed files with 137 additions and 197 deletions

View file

@ -39,26 +39,9 @@
grub_gfxmenu_view_t cached_view; grub_gfxmenu_view_t cached_view;
static grub_err_t
set_graphics_mode (void)
{
const char *modestr = grub_env_get ("gfxmode");
if (!modestr || !modestr[0])
modestr = "auto";
return grub_video_set_mode (modestr, GRUB_VIDEO_MODE_TYPE_PURE_TEXT, 0);
}
/* FIXME: conflicts with gfxterm. */
static grub_err_t
set_text_mode (void)
{
return grub_video_restore ();
}
void void
grub_gfxmenu_viewer_fini (void *data __attribute__ ((unused))) grub_gfxmenu_viewer_fini (void *data __attribute__ ((unused)))
{ {
set_text_mode ();
} }
/* FIXME: 't' and 'c'. */ /* FIXME: 't' and 'c'. */
@ -73,18 +56,23 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
theme_path = grub_env_get ("theme"); theme_path = grub_env_get ("theme");
if (! theme_path) if (! theme_path)
{
grub_gfxterm_fullscreen ();
return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no theme specified"); return grub_error (GRUB_ERR_FILE_NOT_FOUND, "no theme specified");
}
instance = grub_zalloc (sizeof (*instance)); instance = grub_zalloc (sizeof (*instance));
if (!instance) if (!instance)
{
grub_gfxterm_fullscreen ();
return grub_errno; return grub_errno;
}
set_graphics_mode ();
err = grub_video_get_info (&mode_info); err = grub_video_get_info (&mode_info);
if (err) if (err)
{ {
set_text_mode (); grub_gfxterm_fullscreen ();
return 0; return err;
} }
if (!cached_view || grub_strcmp (cached_view->theme_path, theme_path) != 0 if (!cached_view || grub_strcmp (cached_view->theme_path, theme_path) != 0
@ -100,7 +88,7 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
if (! cached_view) if (! cached_view)
{ {
grub_free (instance); grub_free (instance);
set_text_mode (); grub_gfxterm_fullscreen ();
return grub_errno; return grub_errno;
} }
@ -129,6 +117,15 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested)
GRUB_MOD_INIT (gfxmenu) GRUB_MOD_INIT (gfxmenu)
{ {
struct grub_term_output *term;
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_gfxmenu_try_hook && grub_strcmp (term->name, "gfxterm") == 0)
{
grub_gfxterm_fullscreen ();
break;
}
grub_gfxmenu_try_hook = grub_gfxmenu_try; grub_gfxmenu_try_hook = grub_gfxmenu_try;
} }

View file

@ -41,9 +41,10 @@
status changes. */ status changes. */
#define TIMEOUT_COMPONENT_ID "__timeout__" #define TIMEOUT_COMPONENT_ID "__timeout__"
#if 0 static void
init_terminal (grub_gfxmenu_view_t view);
static grub_video_rect_t term_rect;
static grub_gfxmenu_view_t term_view; static grub_gfxmenu_view_t term_view;
#endif
/* Create a new view object, loading the theme specified by THEME_PATH and /* Create a new view object, loading the theme specified by THEME_PATH and
associating MODEL with the view. */ associating MODEL with the view. */
@ -98,10 +99,6 @@ grub_gfxmenu_view_new (const char *theme_path,
return 0; return 0;
} }
#if 0
init_terminal (view);
#endif
return view; return view;
} }
@ -119,26 +116,8 @@ grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view)
if (view->canvas) if (view->canvas)
view->canvas->ops->component.destroy (view->canvas); view->canvas->ops->component.destroy (view->canvas);
grub_free (view); grub_free (view);
#if 0
destroy_terminal ();
#endif
} }
#if 0
/* Sets MESSAGE as the progress message for the view.
MESSAGE can be 0, in which case no message is displayed. */
static void
set_progress_message (grub_gfxmenu_view_t view, const char *message)
{
grub_free (view->progress_message_text);
if (message)
view->progress_message_text = grub_strdup (message);
else
view->progress_message_text = 0;
}
#endif
static void static void
redraw_background (grub_gfxmenu_view_t view, redraw_background (grub_gfxmenu_view_t view,
const grub_video_rect_t *bounds) const grub_video_rect_t *bounds)
@ -331,6 +310,9 @@ void
grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view,
const grub_video_rect_t *region) const grub_video_rect_t *region)
{ {
if (grub_video_have_common_points (&term_rect, region))
grub_gfxterm_schedule_repaint ();
grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
redraw_background (view, region); redraw_background (view, region);
@ -344,11 +326,17 @@ grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view,
void void
grub_gfxmenu_view_draw (grub_gfxmenu_view_t view) grub_gfxmenu_view_draw (grub_gfxmenu_view_t view)
{ {
init_terminal (view);
/* Clear the screen; there may be garbage left over in video memory. */ /* Clear the screen; there may be garbage left over in video memory. */
grub_video_fill_rect (grub_video_map_rgb (0, 0, 0), grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
view->screen.x, view->screen.y, view->screen.x, view->screen.y,
view->screen.width, view->screen.height); view->screen.width, view->screen.height);
grub_video_swap_buffers (); grub_video_swap_buffers ();
if (view->double_repaint)
grub_video_fill_rect (grub_video_map_rgb (0, 0, 0),
view->screen.x, view->screen.y,
view->screen.width, view->screen.height);
update_menu_components (view); update_menu_components (view);
@ -399,77 +387,60 @@ grub_gfxmenu_set_chosen_entry (int entry, void *data)
grub_gfxmenu_redraw_menu (view); grub_gfxmenu_redraw_menu (view);
} }
/* FIXME */
#if 0
static int term_target_width;
static int term_target_height;
static int term_initialized;
static grub_term_output_t term_original;
static void static void
draw_terminal_box (grub_gfxmenu_view_t view) grub_gfxmenu_draw_terminal_box (void)
{ {
grub_gfxmenu_box_t term_box; grub_gfxmenu_box_t term_box;
int termx;
int termy;
term_box = term_view->terminal_box; term_box = term_view->terminal_box;
if (!term_box) if (!term_box)
return; return;
termx = term_view->screen.x + term_view->screen.width * (10 - 7) / 10 / 2; term_box->set_content_size (term_box, term_rect.width,
termy = term_view->screen.y + term_view->screen.height * (10 - 7) / 10 / 2; term_rect.height);
term_box->set_content_size (term_box, term_target_width,
term_target_height);
term_box->draw (term_box, term_box->draw (term_box,
termx - term_box->get_left_pad (term_box), term_rect.x - term_box->get_left_pad (term_box),
termy - term_box->get_top_pad (term_box)); term_rect.y - term_box->get_top_pad (term_box));
grub_video_swap_buffers (); grub_video_swap_buffers ();
if (view->double_repaint) if (term_view->double_repaint)
term_box->draw (term_box, term_box->draw (term_box,
termx - term_box->get_left_pad (term_box), term_rect.x - term_box->get_left_pad (term_box),
termy - term_box->get_top_pad (term_box)); term_rect.y - term_box->get_top_pad (term_box));
} }
static void static void
init_terminal (grub_gfxmenu_view_t view) init_terminal (grub_gfxmenu_view_t view)
{ {
int termx; term_rect.width = view->screen.width * 7 / 10;
int termy; term_rect.height = view->screen.height * 7 / 10;
term_original = grub_term_get_current_output (); term_rect.x = view->screen.x + view->screen.width * (10 - 7) / 10 / 2;
term_rect.y = view->screen.y + view->screen.height * (10 - 7) / 10 / 2;
term_target_width = view->screen.width * 7 / 10; term_view = view;
term_target_height = view->screen.height * 7 / 10;
termx = view->screen.x + view->screen.width * (10 - 7) / 10 / 2;
termy = view->screen.y + view->screen.height * (10 - 7) / 10 / 2;
/* Note: currently there is no API for changing the gfxterm font /* Note: currently there is no API for changing the gfxterm font
on the fly, so whatever font the initially loaded theme specifies on the fly, so whatever font the initially loaded theme specifies
will be permanent. */ will be permanent. */
grub_gfxterm_init_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY, termx, termy, grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY, term_rect.x,
term_target_width, term_target_height, term_rect.y,
term_rect.width, term_rect.height,
view->double_repaint, view->terminal_font_name, 3); view->double_repaint, view->terminal_font_name, 3);
if (grub_errno != GRUB_ERR_NONE) grub_gfxterm_decorator_hook = grub_gfxmenu_draw_terminal_box;
return;
term_initialized = 1;
term_view = view;
grub_term_set_current_output (grub_gfxterm_get_term ());
grub_refresh ();
} }
static void destroy_terminal (void) #if 0
/* Sets MESSAGE as the progress message for the view.
MESSAGE can be 0, in which case no message is displayed. */
static void
set_progress_message (grub_gfxmenu_view_t view, const char *message)
{ {
if (term_initialized) grub_free (view->progress_message_text);
grub_gfxterm_destroy_window (); if (message)
if (term_original) view->progress_message_text = grub_strdup (message);
grub_term_set_current_output (term_original); else
view->progress_message_text = 0;
} }
static void static void

View file

@ -45,14 +45,6 @@ grub_err_t grub_gui_recreate_box (grub_gfxmenu_box_t *boxptr,
void grub_gfxmenu_view_draw (grub_gfxmenu_view_t view); void grub_gfxmenu_view_draw (grub_gfxmenu_view_t view);
int grub_gfxmenu_view_execute_with_fallback (grub_gfxmenu_view_t view,
grub_menu_entry_t entry);
int grub_gfxmenu_view_execute_entry (grub_gfxmenu_view_t view,
grub_menu_entry_t entry);
void grub_gfxmenu_view_run_terminal (grub_gfxmenu_view_t view);
void void
grub_gfxmenu_redraw_menu (grub_gfxmenu_view_t view); grub_gfxmenu_redraw_menu (grub_gfxmenu_view_t view);

View file

@ -25,18 +25,20 @@
#include <grub/video.h> #include <grub/video.h>
grub_err_t grub_err_t
grub_gfxterm_init_window (struct grub_video_render_target *target, grub_gfxterm_set_window (struct grub_video_render_target *target,
int x, int y, int width, int height, int x, int y, int width, int height,
int double_repaint, int double_repaint,
const char *font_name, int border_width); const char *font_name, int border_width);
void grub_gfxterm_destroy_window (void);
const struct grub_term_output *grub_gfxterm_get_term (void);
typedef void (*grub_gfxterm_repaint_callback_t)(int x, int y, typedef void (*grub_gfxterm_repaint_callback_t)(int x, int y,
int width, int height); int width, int height);
void grub_gfxterm_set_repaint_callback (grub_gfxterm_repaint_callback_t func); void grub_gfxterm_set_repaint_callback (grub_gfxterm_repaint_callback_t func);
void grub_gfxterm_schedule_repaint (void);
grub_err_t grub_gfxterm_fullscreen (void);
extern void (*grub_gfxterm_decorator_hook) (void);
#endif /* ! GRUB_GFXTERM_HEADER */ #endif /* ! GRUB_GFXTERM_HEADER */

View file

@ -83,10 +83,6 @@ typedef struct grub_menu_execute_callback
} }
*grub_menu_execute_callback_t; *grub_menu_execute_callback_t;
extern grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu,
int nested);
grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no); grub_menu_entry_t grub_menu_get_entry (grub_menu_t menu, int no);
int grub_menu_get_timeout (void); int grub_menu_get_timeout (void);
void grub_menu_set_timeout (int timeout); void grub_menu_set_timeout (int timeout);

View file

@ -115,20 +115,16 @@ struct grub_gfxterm_window
int double_repaint; int double_repaint;
}; };
static int refcount;
static struct grub_video_render_target *render_target; static struct grub_video_render_target *render_target;
void (*grub_gfxterm_decorator_hook) (void) = NULL;
static struct grub_gfxterm_window window; static struct grub_gfxterm_window window;
static struct grub_virtual_screen virtual_screen; static struct grub_virtual_screen virtual_screen;
static grub_gfxterm_repaint_callback_t repaint_callback; static grub_gfxterm_repaint_callback_t repaint_callback;
static int repaint_schedulded = 0;
static grub_err_t init_window (struct grub_video_render_target *target, static int repaint_was_schedulded = 0;
int x, int y, int width, int height,
int double_repaint,
const char *font_name, int border_width);
static void destroy_window (void); static void destroy_window (void);
static struct grub_video_render_target *text_layer; static struct grub_video_render_target *text_layer;
static unsigned int bitmap_width; static unsigned int bitmap_width;
@ -271,9 +267,16 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y,
return grub_errno; return grub_errno;
} }
static grub_err_t void
init_window (struct grub_video_render_target *target, grub_gfxterm_schedule_repaint (void)
int x, int y, int width, int height, int double_repaint, {
repaint_schedulded = 1;
}
grub_err_t
grub_gfxterm_set_window (struct grub_video_render_target *target,
int x, int y, int width, int height,
int double_repaint,
const char *font_name, int border_width) const char *font_name, int border_width)
{ {
/* Clean up any prior instance. */ /* Clean up any prior instance. */
@ -299,45 +302,55 @@ init_window (struct grub_video_render_target *target,
window.height = height; window.height = height;
window.double_repaint = double_repaint; window.double_repaint = double_repaint;
/* Mark whole window as dirty. */
dirty_region_reset (); dirty_region_reset ();
dirty_region_add (0, 0, width, height); grub_gfxterm_schedule_repaint ();
return grub_errno; return grub_errno;
} }
grub_err_t grub_err_t
grub_gfxterm_init_window (struct grub_video_render_target *target, grub_gfxterm_fullscreen (void)
int x, int y, int width, int height,
int double_repaint,
const char *font_name, int border_width)
{
if (refcount++ == 0)
init_window (target, x, y, width, height, double_repaint,
font_name, border_width);
return grub_errno;
}
static grub_err_t
grub_gfxterm_init (void)
{ {
const char *font_name; const char *font_name;
const char *modevar;
struct grub_video_mode_info mode_info; struct grub_video_mode_info mode_info;
char *tmp;
grub_err_t err;
grub_video_color_t color; grub_video_color_t color;
grub_err_t err;
/* If gfxterm has already been initialized by calling the init_window err = grub_video_get_info (&mode_info);
function, then leave it alone when it is set as the current terminal. */ /* Figure out what mode we ended up. */
if (refcount++ != 0) if (err)
return GRUB_ERR_NONE; return err;
grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
/* Make sure screen is black. */
color = grub_video_map_rgb (0, 0, 0);
grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
bitmap = 0;
/* Select the font to use. */ /* Select the font to use. */
font_name = grub_env_get ("gfxterm_font"); font_name = grub_env_get ("gfxterm_font");
if (! font_name) if (! font_name)
font_name = ""; /* Allow fallback to any font. */ font_name = ""; /* Allow fallback to any font. */
grub_gfxterm_decorator_hook = NULL;
return grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY,
0, 0, mode_info.width, mode_info.height,
mode_info.mode_type
& GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
&& !(mode_info.mode_type
& GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP),
font_name, DEFAULT_BORDER_WIDTH);
}
static grub_err_t
grub_gfxterm_init (void)
{
char *tmp;
grub_err_t err;
const char *modevar;
/* Parse gfxmode environment variable if set. */ /* Parse gfxmode environment variable if set. */
modevar = grub_env_get ("gfxmode"); modevar = grub_env_get ("gfxmode");
if (! modevar || *modevar == 0) if (! modevar || *modevar == 0)
@ -358,35 +371,11 @@ grub_gfxterm_init (void)
if (err) if (err)
return err; return err;
err = grub_video_get_info (&mode_info); err = grub_gfxterm_fullscreen ();
/* Figure out what mode we ended up. */
if (err) if (err)
return err;
/* Make sure screen is black. */
color = grub_video_map_rgb (0, 0, 0);
grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
bitmap = 0;
/* Select the font to use. */
font_name = grub_env_get ("gfxterm_font");
if (! font_name)
font_name = ""; /* Allow fallback to any font. */
/* Leave borders for virtual screen. */
if (init_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY,
0, 0, mode_info.width, mode_info.height,
mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
&& !(mode_info.mode_type
& GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP),
font_name,
DEFAULT_BORDER_WIDTH) != GRUB_ERR_NONE)
{
grub_video_restore (); grub_video_restore ();
return grub_errno;
}
return grub_errno; return err;
} }
static void static void
@ -402,26 +391,15 @@ destroy_window (void)
grub_virtual_screen_free (); grub_virtual_screen_free ();
} }
void
grub_gfxterm_destroy_window (void)
{
if (--refcount == 0)
destroy_window ();
}
static grub_err_t static grub_err_t
grub_gfxterm_fini (void) grub_gfxterm_fini (void)
{ {
/* Don't destroy an explicitly initialized terminal instance when it is
unset as the current terminal. */
if (--refcount == 0)
{
destroy_window (); destroy_window ();
grub_video_restore (); grub_video_restore ();
}
/* Clear error state. */ /* Clear error state. */
return (grub_errno = GRUB_ERR_NONE); grub_errno = GRUB_ERR_NONE;
return GRUB_ERR_NONE;
} }
static void static void
@ -521,6 +499,7 @@ dirty_region_reset (void)
dirty_region.top_left_y = -1; dirty_region.top_left_y = -1;
dirty_region.bottom_right_x = -1; dirty_region.bottom_right_x = -1;
dirty_region.bottom_right_y = -1; dirty_region.bottom_right_y = -1;
repaint_was_schedulded = 0;
} }
static int static int
@ -540,6 +519,16 @@ dirty_region_add (int x, int y, unsigned int width, unsigned int height)
if ((width == 0) || (height == 0)) if ((width == 0) || (height == 0))
return; return;
if (repaint_schedulded)
{
x = virtual_screen.offset_x;
y = virtual_screen.offset_y;
width = virtual_screen.width;
height = virtual_screen.height;
repaint_schedulded = 0;
repaint_was_schedulded = 1;
}
if (dirty_region_is_empty ()) if (dirty_region_is_empty ())
{ {
dirty_region.top_left_x = x; dirty_region.top_left_x = x;
@ -586,6 +575,9 @@ dirty_region_redraw (void)
width = dirty_region.bottom_right_x - x + 1; width = dirty_region.bottom_right_x - x + 1;
height = dirty_region.bottom_right_y - y + 1; height = dirty_region.bottom_right_y - y + 1;
if (repaint_was_schedulded && grub_gfxterm_decorator_hook)
grub_gfxterm_decorator_hook ();
redraw_screen_rect (x, y, width, height); redraw_screen_rect (x, y, width, height);
} }
@ -1109,7 +1101,6 @@ grub_gfxterm_background_image_cmd (grub_extcmd_t cmd __attribute__ ((unused)),
bitmap = 0; bitmap = 0;
/* Mark whole screen as dirty. */ /* Mark whole screen as dirty. */
dirty_region_reset ();
dirty_region_add (0, 0, window.width, window.height); dirty_region_add (0, 0, window.width, window.height);
} }
@ -1152,7 +1143,6 @@ grub_gfxterm_background_image_cmd (grub_extcmd_t cmd __attribute__ ((unused)),
bitmap_height = grub_video_bitmap_get_height (bitmap); bitmap_height = grub_video_bitmap_get_height (bitmap);
/* Mark whole screen as dirty. */ /* Mark whole screen as dirty. */
dirty_region_reset ();
dirty_region_add (0, 0, window.width, window.height); dirty_region_add (0, 0, window.width, window.height);
} }
} }
@ -1182,18 +1172,10 @@ static struct grub_term_output grub_video_term =
.next = 0 .next = 0
}; };
const struct grub_term_output *
grub_gfxterm_get_term (void)
{
return &grub_video_term;
}
static grub_extcmd_t background_image_cmd_handle; static grub_extcmd_t background_image_cmd_handle;
GRUB_MOD_INIT(term_gfxterm) GRUB_MOD_INIT(term_gfxterm)
{ {
refcount = 0;
grub_term_register_output ("gfxterm", &grub_video_term); grub_term_register_output ("gfxterm", &grub_video_term);
background_image_cmd_handle = background_image_cmd_handle =
grub_register_extcmd ("background_image", grub_register_extcmd ("background_image",