Package: grub-common
Version: 2.02~beta2-10

Hello. I am using Kubuntu Trusty. Since GRUB is not modified
downstream for Ubuntu, I'm filing this bug (actually an enhancement
request) against Debian. Perhaps some of these could be actually
included in topstream GRUB, but I leave it to the developers.

Currently it is unnecessarily difficult to specify the colors *and*
background image for GRUB 2. From
https://help.ubuntu.com/community/Grub2/Displays (I am not aware of
the equivalent Debian page) one learns that: To specify the background
image one has to edit /etc/default/grub and provide a GRUB_BACKGROUND=
entry, which seems a logical thing to do. But one is not able to
specify the colors therein as well. To get the required colors, one
can not "specify" custom colors in a settings file per se (i.e. meant
to be user-editable) but one is required to edit/alter files directly
part of packages[1], which seems awkward. And furthermore, there are
*two* files to edit, /etc/grub.d/05_debian_theme if a background image
is present and /lib/plymouth/themes/default.grub if not.

This is all totally sub-optimal IMO and I submit the attached patch as
a remedy. (While I'm using Trusty's GRUB 2.02~beta2-9, I am able to
successfully apply this patch on the recent 2.02*-10 tree too.)

This patch allows the colors to be specified in /etc/default/grub by
the variables GRUB_COLOR_{NORMAL,HIGHLIGHT} and
GRUB_MENU_COLOR_{NORMAL,HIGHLIGHT} just like the background image is
specified by GRUB_BACKGROUND. It also streamlines the selection of a
background image and its linkup with the colors being specified (i.e.
if there is a user-specified image, the user-specified colors are used
only if the image could be loaded at bootup). It also ties in
correctly with desktop-base[2] providing a default theme, with any
user-specified theme overriding that default. Further comments are
included inline in the patch.

A few related points:

1) I thought maybe I should patch debian/default/grub.md5sum too since
from the name one would assume it's an md5sum of the actual
debian/default/grub file but apparently it has lots of outdated
md5sum-s so I leave it to the developers to decide what to do with
that.

2) I've patched grub.texi documenting the new GRUB_*COLOR* variables.
I presume the info page (and any other documentation) will be
generated from that by the build process.

3) Two of the files to be patched (05_debian_theme and
grub-mkconfig.in) go into the grub-common package and two
(default/grub and grub.texi) go into the grub2-common package. I'm not
sure why these two are separate and I am sure not whether to specify
both packages or not. I am filing against grub-common only. Please
clone if needed.

Thanks.

Shriramana Sharma.

Footnotes:

[1 = I mean /etc/default/grub is not directly a part of a package but
is copied from /usr/share/grub/default/grub in package grub2-common by
its postinst.in lines 363 and 379 so the original from the package is
untouched by user configuration.]

[2 = The only requirement of the desktop-base for this integration is
that its grub_background.sh should also henceforth use the same
spellings for the image/colors as /etc/default/grub: GRUB_BACKGROUND,
GRUB_COLOR_* and GRUB_MENU_COLOR_*.]

-- 
Shriramana Sharma ஶ்ரீரமணஶர்மா श्रीरमणशर्मा
diff --git a/debian/default/grub b/debian/default/grub
index 7617f01..9cb55af 100644
--- a/debian/default/grub
+++ b/debian/default/grub
@@ -30,3 +30,34 @@ GRUB_CMDLINE_LINUX=""
 
 # Uncomment to get a beep at grub start
 #GRUB_INIT_TUNE="480 440 1"
+
+# Uncomment and set path to specify background image.
+# A relative path will be taken w.r.t. /boot/grub/.
+# Note that this is not required if the image is directly under this directory
+# (e.g. /boot/grub/splash.png) and is the only image there.
+#GRUB_BACKGROUND="grub-background.png"
+
+# Uncomment and set colors below to avoid default colors or those specified by
+# the desktop-base package. Colors are specified in pairs -- foreground/background.
# I feel it important to specify the color name spellings here.
# One should not need to navigate through the info page for such a simple thing.
+# Valid color names are:
+#   black dark-gray light-gray white
+#   blue cyan green magenta red
+#   light-blue light-cyan light-green light-magenta light-red
+#   brown yellow
+#GRUB_COLOR_NORMAL=light-cyan/black
+#GRUB_COLOR_HIGHLIGHT=yellow/brown
+#GRUB_MENU_COLOR_NORMAL=white/black
+#GRUB_MENU_COLOR_HIGHLIGHT=white/green
+
# These notes should be highly visible too IMO:
+# Notes on images & colors:
+# 1) If a background image is used, a background color of black is taken as
+#    transparent. Remember that any other background color will block the image,
+#    especially in GRUB_COLOR_NORMAL.
+# 2) If both a background image and a color scheme are specified, the color scheme
+#    will be applied only if the background image is successfully loaded at bootup
+#    time, else a default theme will be used. This is because the color scheme
+#    is assumed to be tailored to the background image and hence may not be readable
+#    if the image is not loaded (like dark colors on a light image).
+# 3) GRUB_MENU_COLOR_* values if specified will override GRUB_COLOR_* values for
+#    the primary menu. Text outside the primary menu (including that in
+#    secondary menus) will use the GRUB_COLOR_* colors only.
# Re point 3 above: This is the current behaviour. However, I am not sure whether the
# GRUB developers intentionally made it so that menu_color* values do NOT apply to
# the secondary menu, or whether there is even any applicability of color_highlight
# outside the secondary menu. I asked about this at
# http://lists.gnu.org/archive/html/grub-devel/2014-05/msg00009.html
# but I didn't get any response.
diff --git a/debian/grub.d/05_debian_theme b/debian/grub.d/05_debian_theme
index 77564f2..07db701 100755
--- a/debian/grub.d/05_debian_theme
+++ b/debian/grub.d/05_debian_theme
@@ -27,15 +27,18 @@ test -d /boot/grub; cd /boot/grub
 # NOTE: This MUST BE A DOTFILE to avoid confusing it with user-defined images.
 BACKGROUND_CACHE=".background_cache"
 
+# In this file, a "theme" is just a set of text/highlight colors with a possible
+# background image, and not a full graphical theme.
+
 set_default_theme(){
 	case $GRUB_DISTRIBUTOR in
 		Tanglu|Ubuntu|Kubuntu)
-			# Set a monochromatic theme for Tanglu/Ubuntu.
-			echo "${1}set menu_color_normal=white/black"
-			echo "${1}set menu_color_highlight=black/light-gray"
-
 			if [ -e /lib/plymouth/themes/default.grub ]; then
 				sed "s/^/${1}/" /lib/plymouth/themes/default.grub
+			else
# This is the correct place for this, since the plymouth default.grub would specify
# its own colors. (At least it should, right? If not, please tell me and drop this chunk.)
+				# Set a monochromatic theme for Tanglu/Ubuntu/Kubuntu.
+				echo "${1}set menu_color_normal=white/black"
+				echo "${1}set menu_color_highlight=black/light-gray"
 			fi
 			;;
 		*)
@@ -46,6 +49,34 @@ set_default_theme(){
 	esac
 }
 
+no_custom_colors(){
+	if [ -z "${GRUB_COLOR_NORMAL}" ] && [ -z "${GRUB_COLOR_HIGHLIGHT}" ] && [ -z "${GRUB_MENU_COLOR_NORMAL}" ] && [ -z "${GRUB_MENU_COLOR_HIGHLIGHT}" ]; then
+		return 0
+	else
+		return 1
+	fi
+}
+
# A function to set the user-specified colors if any, since that needs to be done in multiple contexts.
+set_theme(){
+	# If the user has not provided any colors, fallback to the default theme.
+	if no_custom_colors; then
+		set_default_theme "${1}"
+		return 0
+	fi
+	if [ -n "${GRUB_COLOR_NORMAL}" ]; then
+		echo "${1}set color_normal=${GRUB_COLOR_NORMAL}"
+	fi
+	if [ -n "${GRUB_COLOR_HIGHLIGHT}" ]; then
+		echo "${1}set color_highlight=${GRUB_COLOR_HIGHLIGHT}"
+	fi
+	if [ -n "${GRUB_MENU_COLOR_NORMAL}" ]; then
+		echo "${1}set menu_color_normal=${GRUB_MENU_COLOR_NORMAL}"
+	fi
+	if [ -n "${GRUB_MENU_COLOR_HIGHLIGHT}" ]; then
+		echo "${1}set menu_color_highlight=${GRUB_MENU_COLOR_HIGHLIGHT}"
+	fi
+}
+
 module_available(){
 	local module
 	for module in "${1}.mod" */"${1}.mod"; do
@@ -96,7 +127,7 @@ set_background_image(){
 		rm --force "${BACKGROUND_CACHE}.jpeg" \
 			"${BACKGROUND_CACHE}.png" "${BACKGROUND_CACHE}.tga"
 	elif cp "${1}" "${BACKGROUND_CACHE}.${reader}"; then
# The colors will be directly read from the environment and not passed as arguments.
-		set -- "${BACKGROUND_CACHE}.${reader}" "${2}" "${3}"
+		set -- "${BACKGROUND_CACHE}.${reader}"
 	else
 		return 5
 	fi
@@ -108,28 +139,19 @@ set_background_image(){
 
 	# Step #7: Everything went fine, print out a message to stderr ...
 	echo "Found background image: ${1}" >&2
-
-	# ... and write our configuration snippet to stdout. Use the colors
-	# desktop-base specified. If we're using a user-defined background, use
-	# the default colors since we've got no idea how the image looks like.
-	# If loading the background image fails, use the default theme.
+	# ... and write our configuration snippet to stdout.
+	# What it does: Attempt to load the background image. If successful, use the
+	# user-specified colors if any. If not, use the default theme (since those
+	# colors may be tailored to the background and not visible without it).
 	echo "insmod ${reader}"
 	echo "if background_image `make_system_path_relative_to_its_root "${1}"`; then"
# Use the dedicated function to set colors.
-	if [ -n "${2}" ]; then
-		echo "  set color_normal=${2}"
-	fi
-	if [ -n "${3}" ]; then
-		echo "  set color_highlight=${3}"
-	fi
-	if [ -z "${2}" ] && [ -z "${3}" ]; then
-		echo "  true"
-	fi
+	set_theme "  "
 	echo "else"
 	set_default_theme "  "
 	echo "fi"
 }
 
# Just small nitpicking to keep in line with formatting of paths above and below:
-# Earlier versions of grub-pc copied the default background image to /boot/grub
+# Earlier versions of grub-pc copied the default background image to /boot/grub/
 # during postinst. Remove those obsolete images if they haven't been touched by
 # the user. They are still available under /usr/share/images/desktop-base/ if
 # desktop-base is installed.
@@ -147,46 +169,37 @@ d00d5e505ab63f2d53fa880bfac447e2d3bb197c  moreblue-orbit-grub.png
 f5b12c1009ec0a3b029185f6b66cd0d7e5611019  moreblue-orbit-grub.png
 EOF
 
# The desktop-base specifications should/need only be loaded if the user has provided
# neither a background image nor colors. Pushing this to later on.
-# Include the configuration of desktop-base if available.
-if [ -f "/usr/share/desktop-base/grub_background.sh" ]; then
-	. "/usr/share/desktop-base/grub_background.sh"
-fi
-
# No sense in calling set_background_image if the user has requested absence of one.
-# First check whether the user has specified a background image explicitly.
-# If so, try to use it. Don't try the other possibilities in that case
-# (#608263).
-if [ -n "${GRUB_BACKGROUND+x}" ]; then
+# First check whether the user has specified a background image (in /etc/default/grub).
+if [ -n "${GRUB_BACKGROUND:+x}" ]; then
+	# Background image specified and not empty; try to set it.
+	# Here also (as in step #7 above) user-specified colors are used only if
+	# the user-specified background image could be used.
 	set_background_image "${GRUB_BACKGROUND}" || set_default_theme
 	exit 0
+elif [ -n "${GRUB_BACKGROUND+x}" ]; then
+	# Background image specified and empty; just set colors and exit. (see Debian bug #608263)
+	set_theme
+	exit 0
# Next two lines are for clarification of what is happening.
+# else
+	# Background image not specified; continue.
 fi
 
-# Next search for pictures the user put into /boot/grub/ and use the first one.
+# Next search for pictures the user put into /boot/grub/ and use the first one
+# in lexicographic (dictionary) order.
 for background in *.jpg *.JPG *.jpeg *.JPEG *.png *.PNG *.tga *.TGA; do
 	if set_background_image "${background}"; then
 		exit 0
 	fi
 done
 
-# Next try to use the background image and colors specified by desktop-base.
-if set_background_image "${WALLPAPER}" "${COLOR_NORMAL}" "${COLOR_HIGHLIGHT}"; then
-	exit 0
+# If the user has not provided any background image or colors,
+# use those provided/specified by desktop-base if available.
+if [ -f "/usr/share/desktop-base/grub_background.sh" ] && no_custom_colors; then
+	. "/usr/share/desktop-base/grub_background.sh"
# It is expected that desktop-base will provide/specify a background image and possibly colors.
# We don't check whether it does.
+	if set_background_image "${GRUB_BACKGROUND}"; then
+		exit 0
+	fi
 fi
 
# Entirely not sure what this case block is for. If desktop-base is installed, it should provide
# its default recommended colors and background image in /usr/share/desktop-base/grub_background.sh,
# right? So removing this. (If there is an explanation, please tell me and drop this chunk.)
-# If we haven't found a background image yet, use the default from desktop-base.
-case $GRUB_DISTRIBUTOR in
-	Ubuntu|Kubuntu)
-		;;
-	Tanglu)
-		if set_background_image "/usr/share/images/grub/grub.png"; then
-			exit 0
-		fi
-		;;
-	*)
-		if set_background_image "/usr/share/images/desktop-base/desktop-grub.png"; then
-			exit 0
-		fi
-		;;
-esac
-
# User may have specified only colors. So set_theme should be used and not set_default_theme.
-# Finally, if all of the above fails, use the default theme.
-set_default_theme
+# Finally, even if we still haven't found a background image, at least set the (color) theme.
+set_theme
diff --git a/docs/grub.texi b/docs/grub.texi
index af020ec..8ace292 100644
--- a/docs/grub.texi
+++ b/docs/grub.texi
@@ -1432,6 +1432,20 @@ The value of this option must be a file readable by GRUB at boot time, and
 it must end with @file{.png}, @file{.tga}, @file{.jpg}, or @file{.jpeg}.
 The image will be scaled if necessary to fit the screen.
 
+@item GRUB_COLOR_NORMAL
+@item GRUB_COLOR_HIGHLIGHT
+@item GRUB_MENU_COLOR_NORMAL
+@item GRUB_MENU_COLOR_HIGHLIGHT
+Set the value of @samp{color_normal}, @samp{color_highlight},
+@samp{menu_color_normal} and @samp{menu_color_highlight}. If a background image
+is specified using @samp{GRUB_BACKGROUND} (see above) or by placing it in the
+GRUB installation directory (such as /boot/grub/), then these colors are set
+only if that image could be loaded, since these colors are assumed to be
+tailored to the background and possibly not visible without it.
+
+See @ref{color_normal}, @ref{color_highlight}, @ref{menu_color_normal} and
+@ref{menu_color_highlight}. For the available color names, @pxref{color_normal}.
+
 @item GRUB_THEME
 Set a theme for use with the @samp{gfxterm} graphical terminal.
 
@@ -3133,7 +3147,7 @@ without path name.
 @node color_highlight
 @subsection color_highlight
 
# "Highlight" is just a regular adjective, not a name; hence should not be quoted.
-This variable contains the ``highlight'' foreground and background terminal
+This variable contains the highlight foreground and background terminal
 colors, separated by a slash (@samp{/}).  Setting this variable changes
 those colors.  For the available color names, @pxref{color_normal}.
 
@@ -3143,7 +3157,7 @@ The default is @samp{black/light-gray}.
 @node color_normal
 @subsection color_normal
 
# "Normal" is just a regular adjective, not a name; hence should not be quoted.
-This variable contains the ``normal'' foreground and background terminal
+This variable contains the normal foreground and background terminal
 colors, separated by a slash (@samp{/}).  Setting this variable changes
 those colors.  Each color must be a name from the following list:
 
@@ -3166,6 +3180,9 @@ those colors.  Each color must be a name from the following list:
 @item white
 @end itemize
 
+Note that @samp{black} when specified as a background color actually
+means @samp{transparent} if a background image is present.
+
 The default is @samp{light-gray/black}.
 
 The color support support varies from terminal to terminal.
diff --git a/util/grub-mkconfig.in b/util/grub-mkconfig.in
index ccce9e5..3c3c217 100644
--- a/util/grub-mkconfig.in
+++ b/util/grub-mkconfig.in
@@ -232,6 +232,10 @@ export GRUB_DEFAULT \
   GRUB_VIDEO_BACKEND \
   GRUB_GFXMODE \
   GRUB_BACKGROUND \
+  GRUB_COLOR_NORMAL \
+  GRUB_COLOR_HIGHLIGHT \
+  GRUB_MENU_COLOR_NORMAL \
+  GRUB_MENU_COLOR_HIGHLIGHT \
   GRUB_THEME \
   GRUB_GFXPAYLOAD_LINUX \
   GRUB_DISABLE_OS_PROBER \

Reply via email to