diff --git a/gfxmenu/gfxmenu.c b/gfxmenu/gfxmenu.c index 0d807914b..f39cdbbfe 100644 --- a/gfxmenu/gfxmenu.c +++ b/gfxmenu/gfxmenu.c @@ -37,21 +37,39 @@ #include #include -void -grub_gfxmenu_viewer_fini (void *data) -{ - grub_gfxmenu_view_t view = data; +grub_gfxmenu_view_t cached_view; - grub_gfxmenu_view_destroy (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 +grub_gfxmenu_viewer_fini (void *data __attribute__ ((unused))) +{ + set_text_mode (); } /* FIXME: 't' and 'c'. */ grub_err_t grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) { - grub_gfxmenu_view_t view; + grub_gfxmenu_view_t view = NULL; const char *theme_path; struct grub_menu_viewer *instance; + grub_err_t err; + struct grub_video_mode_info mode_info; theme_path = grub_env_get ("theme"); if (! theme_path) @@ -61,15 +79,41 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) if (!instance) return grub_errno; - /* Create the view. */ - view = grub_gfxmenu_view_new (theme_path, menu, entry, nested); + set_graphics_mode (); + err = grub_video_get_info (&mode_info); + if (err) + { + set_text_mode (); + return 0; + } - if (! view) + if (!cached_view || grub_strcmp (cached_view->theme_path, theme_path) != 0 + || cached_view->screen.width != (int) mode_info.width + || cached_view->screen.height != (int) mode_info.height) + { + grub_free (cached_view); + /* Create the view. */ + cached_view = grub_gfxmenu_view_new (theme_path, mode_info.width, + mode_info.height); + } + + if (! cached_view) { grub_free (instance); + set_text_mode (); return grub_errno; } + view = cached_view; + + view->double_repaint = (mode_info.mode_type + & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED) + && !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); + view->selected = entry; + view->menu = menu; + view->nested = nested; + view->first_timeout = -1; + grub_gfxmenu_view_draw (view); instance->data = view; @@ -90,5 +134,6 @@ GRUB_MOD_INIT (gfxmenu) GRUB_MOD_FINI (gfxmenu) { + grub_gfxmenu_view_destroy (cached_view); grub_gfxmenu_try_hook = NULL; } diff --git a/gfxmenu/view.c b/gfxmenu/view.c index 882469447..8c460ff88 100644 --- a/gfxmenu/view.c +++ b/gfxmenu/view.c @@ -45,62 +45,31 @@ static grub_gfxmenu_view_t term_view; #endif -static grub_err_t set_graphics_mode (void); -static grub_err_t set_text_mode (void); - /* Create a new view object, loading the theme specified by THEME_PATH and associating MODEL with the view. */ grub_gfxmenu_view_t -grub_gfxmenu_view_new (const char *theme_path, grub_menu_t menu, int entry, - int nested) +grub_gfxmenu_view_new (const char *theme_path, + int width, int height) { grub_gfxmenu_view_t view; - grub_err_t err; - struct grub_video_mode_info mode_info; + grub_font_t default_font; + grub_gui_color_t default_fg_color; + grub_gui_color_t default_bg_color; view = grub_malloc (sizeof (*view)); if (! view) return 0; - set_graphics_mode (); - grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); - grub_video_get_viewport ((unsigned *) &view->screen.x, - (unsigned *) &view->screen.y, - (unsigned *) &view->screen.width, - (unsigned *) &view->screen.height); - - err = grub_video_get_info (&mode_info); - if (err) - { - grub_free (view); - return 0; - } - else - view->double_repaint = (mode_info.mode_type - & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED) - && !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP); - - - /* Clear the screen; there may be garbage left over in video memory, and - loading the menu style (particularly the background) can take a while. */ - grub_video_fill_rect (grub_video_map_rgb (0, 0, 0), - view->screen.x, view->screen.y, - view->screen.width, view->screen.height); - grub_video_swap_buffers (); - - grub_font_t default_font; - grub_gui_color_t default_fg_color; - grub_gui_color_t default_bg_color; + view->screen.x = 0; + view->screen.y = 0; + view->screen.width = width; + view->screen.height = height; default_font = grub_font_get ("Helvetica 12"); default_fg_color = grub_gui_color_rgb (0, 0, 0); default_bg_color = grub_gui_color_rgb (255, 255, 255); view->canvas = 0; - view->selected = entry; - view->menu = menu; - view->nested = nested; - view->first_timeout = -1; view->title_font = default_font; view->message_font = default_font; @@ -151,7 +120,6 @@ grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view) view->canvas->ops->component.destroy (view->canvas); grub_free (view); - set_text_mode (); #if 0 destroy_terminal (); #endif @@ -376,6 +344,12 @@ grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, void grub_gfxmenu_view_draw (grub_gfxmenu_view_t view) { + /* Clear the screen; there may be garbage left over in video memory. */ + grub_video_fill_rect (grub_video_map_rgb (0, 0, 0), + view->screen.x, view->screen.y, + view->screen.width, view->screen.height); + grub_video_swap_buffers (); + update_menu_components (view); grub_gfxmenu_view_redraw (view, &view->screen); @@ -426,21 +400,6 @@ grub_gfxmenu_set_chosen_entry (int entry, void *data) } -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); -} - -static grub_err_t -set_text_mode (void) -{ - return grub_video_restore (); -} - /* FIXME */ #if 0 static int term_target_width; diff --git a/include/grub/gfxmenu_view.h b/include/grub/gfxmenu_view.h index 92cedc6a7..1b83cc5a3 100644 --- a/include/grub/gfxmenu_view.h +++ b/include/grub/gfxmenu_view.h @@ -31,8 +31,7 @@ typedef struct grub_gfxmenu_view *grub_gfxmenu_view_t; grub_gfxmenu_view_t grub_gfxmenu_view_new (const char *theme_path, - grub_menu_t menu, int entry, - int nested); + int width, int height); void grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view);