How Ventoy Implements Theme Switching in the F5 Tools Menu

Ventoy implements F5 Tools theme switching by scanning /ventoy/themes at boot, dynamically generating GRUB menu entries for each discovered theme, and applying selections through custom GRUB commands that modify the theme environment variable.

The F5 Tools menu in Ventoy provides a Theme Select option that allows users to switch GUI themes without rebooting or modifying configuration files manually. This functionality is implemented entirely within the GRUB2 plugin architecture in the ventoy/Ventoy repository, specifically through runtime menu injection and custom GRUB commands defined in ventoy_plugin.c.

Theme Discovery and Linked List Management

When the Ventoy plugin initializes, ventoy_plugin_init() scans the directory structure for available themes. By default, it searches /ventoy/themes (or custom paths defined in ventoy.json) and builds a singly-linked list of available themes.

The following global variables manage the theme state in GRUB2/MOD_SRC/grub-2.04/grub-core/ventoy/ventoy_plugin.c:

  • g_theme_head – Head pointer to the linked list of theme_list nodes
  • g_theme_num – Count of discovered theme files
  • g_theme_single_file – Path when only one theme exists
  • g_theme_id – Index of the currently selected theme (0 indicates none)

This discovery phase populates the data structures necessary for the dynamic menu generation that follows.

Dynamic Menu Generation for Theme Select

The static structure of the F5 Tools menu is defined in INSTALL/grub/debug.cfg, which contains a placeholder submenu for theme selection:

submenu "$VTLANG_THEME_SELECT" --class=debug_theme_select --class=F5tool {
    …
}

During plugin initialization, the function ventoy_plugin_build_fstools_menu() (around line 3300 in ventoy_plugin.c) iterates over the theme linked list and constructs a temporary GRUB script. For each theme node, it generates a menuentry that calls the custom command vt_set_theme_path:

/* ventoy_plugin.c – L3382-L3386 */
pos += grub_snprintf(buf + pos, bufsize - pos,
    "menuentry \"%s\" --class=debug_theme_item "
    "--class=debug_theme_select --class=F5tool {\n"
    "    vt_set_theme_path \"%s\"\n"
    "}\n",
    name,                /* Display name in menu */
    node->theme.path);   /* Full path to theme.txt */

The generated buffer is executed via grub_script_execute_sourcecode(buf), which injects the entries into the submenu at runtime. When the user presses F5 and navigates to Theme Select, they see dynamically generated entries for every theme.txt file discovered during initialization.

Applying Themes via Custom GRUB Commands

Theme activation relies on two custom GRUB commands implemented in ventoy_plugin.c:

vt_set_theme_path – Implemented by ventoy_cmd_set_theme_path() at lines 3517-3529. This command stores the selected theme's file path in the global buffer g_ventoy_theme_path.

vt_set_theme – Implemented by ventoy_cmd_set_theme() at lines 3401-3514. This command handles the actual theme application logic.

When a user selects a theme from the F5 Tools menu, the following sequence occurs:

  1. The generated menu entry executes vt_set_theme_path "/ventoy/themes/name/theme.txt", storing the path in g_ventoy_theme_path.
  2. On the next boot or when the user activates the switch, ventoy_cmd_set_theme() processes the selection:
    • Checks for single-file scenarios using g_theme_single_file
    • Builds a candidate array (pThemePath) when multiple themes exist
    • Applies resolution-fit filtering if g_theme_res_fit is enabled
    • Handles random selection modes (second-based, day-based, or month-based) using g_theme_random and grub_get_datetime
  3. Finally, calls grub_env_set("theme", selected_path) to update GRUB's gfxterm configuration and apply the theme.

Code Example: Adding a Custom Theme

To add a new theme manually, place a theme.txt file in a subdirectory of /ventoy/themes. For example, adding /ventoy/themes/custom-dark/theme.txt triggers this automatic workflow:

/* Discovery phase pseudo-code from ventoy_plugin.c */
if (find_file("/ventoy/themes/custom-dark/theme.txt")) {
    node = grub_zalloc(sizeof(theme_list));
    node->theme.path = "/ventoy/themes/custom-dark/theme.txt";
    /* Insert into g_theme_head linked list */
    g_theme_num++;
}

The plugin then generates this menu entry automatically:

menuentry "custom-dark" --class=debug_theme_item --class=debug_theme_select --class=F5tool {
    vt_set_theme_path "/ventoy/themes/custom-dark/theme.txt"
}

When selected, the path propagates through vt_set_theme_path to vt_set_theme, which executes:

grub_env_set("theme", "/ventoy/themes/custom-dark/theme.txt");

No source code modification or recompilation is required; the plugin detects new themes during the boot-time filesystem scan.

Summary

  • Theme discovery occurs at plugin initialization in ventoy_plugin_init(), which scans /ventoy/themes and populates the g_theme_head linked list.
  • Dynamic menu injection happens through ventoy_plugin_build_fstools_menu(), which creates GRUB script code containing menuentry definitions for each theme and executes it at runtime.
  • Selection storage uses the vt_set_theme_path command (ventoy_cmd_set_theme_path) to cache the user's choice in g_ventoy_theme_path.
  • Theme activation is handled by vt_set_theme (ventoy_cmd_set_theme), which manages resolution filtering, random selection, and ultimately sets the GRUB theme variable via grub_env_set().

Frequently Asked Questions

Where does Ventoy scan for theme files?

Ventoy scans the /ventoy/themes directory by default during ventoy_plugin_init(), though users can configure additional paths in the ventoy.json configuration file. The plugin searches recursively for theme.txt files and stores their paths in a linked list (g_theme_head) for runtime menu generation.

What GRUB commands handle theme switching?

Ventoy registers two custom commands in ventoy_plugin.c: vt_set_theme_path (stores the selected path in g_ventoy_theme_path) and vt_set_theme (applies the theme by setting the GRUB theme environment variable). These commands are called automatically by the dynamically generated menu entries in the F5 Tools submenu.

Can I use multiple themes with random selection?

Yes. When multiple themes are present, ventoy_cmd_set_theme() supports random selection modes controlled by the g_theme_random variable. The implementation uses grub_get_datetime() to seed random choices based on seconds, days, or months, and can filter themes by screen resolution if g_theme_res_fit is enabled.

How do I add a new theme without modifying source code?

Place your theme's theme.txt file in a subdirectory under /ventoy/themes (for example, /ventoy/themes/mytheme/theme.txt). The Ventoy plugin automatically discovers the file during boot, generates a corresponding menu entry in the F5 Tools → Theme Select submenu, and makes it available for immediate selection without requiring recompilation or configuration changes.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →