From 91fe314e0b9d52f56ccc8c398767e10b1095c70f Mon Sep 17 00:00:00 2001 From: Emmanuel Lepage Vallee Date: Sat, 11 Dec 2021 09:29:27 -0800 Subject: [PATCH] gears.color: Fix color serialization. Some widgets like the tasklist serialize the theme colors to use them in Pango markup. If the theme color were already converted to pattern, that blew up. With this fix, pattern can be converted back into strings correctly. --- lib/gears/color.lua | 48 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/lib/gears/color.lua b/lib/gears/color.lua index 2d906ae0f..7497965b1 100644 --- a/lib/gears/color.lua +++ b/lib/gears/color.lua @@ -53,6 +53,7 @@ local surface = require("gears.surface") local color = { mt = {} } local pattern_cache +local color_string_cache = setmetatable({}, { __mode = "k" }) --- Parse a HTML-color. -- This function can parse colors like `#rrggbb` and `#rrggbbaa` and also `red`. @@ -354,12 +355,59 @@ function color.recolor_image(image, new_color) return image end +--- Convert a color back to an hexadecimal color code. +-- +-- This takes an input color, pattern or gradient and attempt to convert it +-- to a color. If this fails, `fallback` is returned. This is useful when a +-- color needs to be concatenated into a Pango markup string. +-- +-- @staticfct gears.color.to_rgba_string +-- @tparam pattern|string|gradient color Note that only solid colors can be +-- convedted to the `RGBA` format. +-- @tparam[opt=nil] pattern|string|gradient fallback The color to return +-- if `color` cannot be converted to a string. +-- @treturn string The color in `#rrggbbaa` format. +-- @see gears.color.ensure_pango_color + +function color.to_rgba_string(col, fallback) + if (not col) and (not fallback) then return nil end + + -- Prevent infinite recursion. + if not col then return color.to_rgba_string(fallback) end + + if color_string_cache[col] then + return color_string_cache[col] + end + + col = color.create_pattern(col) + + local error1, error2, r, g, b, a = pcall(function () return col:get_rgba() end) + + -- Surface patterns don't have an RGBA representation. + if (not error1) or error2 ~= "SUCCESS" then return color.to_rgba_string(fallback) end + + color_string_cache[col] = string.format( + "#%02x%02x%02x%02x", + math.floor(r*255), + math.floor(g*255), + math.floor(b*255), + math.floor(a*255) + ) + + return color_string_cache[col] +end + --- Get a valid color for Pango markup -- @param check_color The color to check. -- @tparam string fallback The color to return if the first is invalid. (default: black) -- @treturn string color if it is valid, else fallback. -- @staticfct gears.color.ensure_pango_color function color.ensure_pango_color(check_color, fallback) + -- This will happen if `gears.color` has been called in the theme. + if type(check_color) == "userdata" then + return color.to_rgba_string(check_color, fallback) + end + check_color = tostring(check_color) -- Pango markup supports alpha, PangoColor does not. Thus, check for this. local len = #check_color