commit efec7bd2e2b56c24a089c4c4d3188635ae33fdf5
Author: Juergen Spitzmueller <[email protected]>
Date:   Sun Jul 5 13:18:09 2026 +0200

    Unbreak foreground/background color adaptation with transparent backgrounds
---
 src/RowPainter.cpp                  |  9 ++++++---
 src/frontends/Application.h         |  5 +++--
 src/frontends/qt/ColorCache.cpp     | 27 +++++++++++++++++++++++----
 src/frontends/qt/ColorCache.h       |  5 ++++-
 src/frontends/qt/GuiApplication.cpp |  4 ++--
 src/frontends/qt/GuiApplication.h   |  2 +-
 src/frontends/qt/GuiWorkArea.cpp    | 12 +++++++-----
 src/insets/Inset.cpp                | 21 ++++++++++++++-------
 8 files changed, 60 insertions(+), 25 deletions(-)

diff --git a/src/RowPainter.cpp b/src/RowPainter.cpp
index 0d01ac1bcc..fae564ce3b 100644
--- a/src/RowPainter.cpp
+++ b/src/RowPainter.cpp
@@ -258,12 +258,15 @@ void RowPainter::paintStringAndSel(Row::Element const & 
e) const
 
        bool invert = false;
        if (theApp() && theApp()->isInDarkMode()) {
+               ColorCode cc = 
pi_.backgroundColor(&pi_.base.bv->buffer().inset());
                if (e.font.fontInfo().color() == Color_none
-                   && 
theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(pi_.background_color,
 true))))
+                   && 
theApp()->isLightColor(argbFromHexName(lcolor.get32bitHexName(cc, true)),
+                                             
argbFromHexName(lcolor.get32bitHexName("background", true))))
                        invert = true;
-               else if (pi_.background_color == Color_background
+               else if (cc == Color_background
                         && lcolor.isStaticColor(e.font.fontInfo().color())
-                        && 
!theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(e.font.fontInfo().color()))))
+                        && 
!theApp()->isLightColor(argbFromHexName(lcolor.get32bitHexName(e.font.fontInfo().color())),
+                                                   
argbFromHexName(lcolor.get32bitHexName("background", true))))
                        invert = true;
        }
 
diff --git a/src/frontends/Application.h b/src/frontends/Application.h
index 3fa4fa4482..931de7849a 100644
--- a/src/frontends/Application.h
+++ b/src/frontends/Application.h
@@ -220,9 +220,10 @@ public:
 
        /**
         * @return true this is a relatively light color
-        * depending on relative luminance
+        * depending on relative luminance.
+        * Transparent colors are overlayed with the background.
         */
-       virtual bool isLightColor(RGBColor const & rgb) = 0;
+       virtual bool isLightColor(ARGBColor const & fg, ARGBColor const & bg) = 
0;
 
        /** Eg, passing Color_black returns "000000",
        *      passing Color_white returns "ffffff".
diff --git a/src/frontends/qt/ColorCache.cpp b/src/frontends/qt/ColorCache.cpp
index 5cd1207e48..fadaa153c6 100644
--- a/src/frontends/qt/ColorCache.cpp
+++ b/src/frontends/qt/ColorCache.cpp
@@ -169,20 +169,23 @@ bool ColorCache::isDarkMode() const
 }
 
 
-bool ColorCache::isLightColor(RGBColor const & rgb)
+bool ColorCache::isLightColor(ARGBColor const & fg, ARGBColor const & bg)
 {
+       // Overlay on background (necessary with transparency)
+       ARGBColor const & argb = colorOverlay(fg, bg);
+
        // RGB to sRGB
-       double r = rgb.r / 255.0;
+       double r = argb.r / 255.0;
        if (r <= 0.04045)
                r = r / 12.92;
        else
                r = pow((r + 0.055) / 1.055, 2.4);
-       double g = rgb.g / 255.0;
+       double g = argb.g / 255.0;
        if (g <= 0.04045)
                g = g / 12.92;
        else
                g = pow((g + 0.055) / 1.055, 2.4);
-       double b = rgb.b / 255.0;
+       double b = argb.b / 255.0;
        if (b <= 0.04045)
                b = b / 12.92;
        else
@@ -224,6 +227,22 @@ QPixmap ColorCache::mergePixmaps(QPixmap const *fg, 
QPixmap const *bg)
 }
 
 
+ARGBColor ColorCache::colorOverlay(ARGBColor const & fg, ARGBColor const & bg)
+{
+       int red, green, blue, alpha;
+
+       auto fg_weight = fg.a;
+       auto bg_weight = 1 - fg.a;
+
+       red   = std::round((fg_weight * fg.r + bg_weight * bg.r) * 255);
+       green = std::round((fg_weight * fg.g + bg_weight * bg.g) * 255);
+       blue  = std::round((fg_weight*fg.b  + bg_weight * bg.b) * 255);
+       alpha = std::round((1 - (1 - fg.a) * (1 - bg.a) * 255));
+
+       return ARGBColor(red, green, blue, alpha);
+}
+
+
 QColor const rgb2qcolor(RGBColor const & rgb)
 {
        return QColor(rgb.r, rgb.g, rgb.b);
diff --git a/src/frontends/qt/ColorCache.h b/src/frontends/qt/ColorCache.h
index 617bae8e56..81644f03c0 100644
--- a/src/frontends/qt/ColorCache.h
+++ b/src/frontends/qt/ColorCache.h
@@ -52,7 +52,7 @@ public:
         * a dark one as contrast) depending on relative luminance
         * (cf. https://www.w3.org/TR/WCAG20/#relativeluminancedef)
        */
-       bool isLightColor(RGBColor const & rgb);
+       bool isLightColor(ARGBColor const & fg, ARGBColor const & bg);
 
        /// change the undelying palette
        void setPalette(QPalette const pal) { pal_ = pal; clear(); }
@@ -72,6 +72,9 @@ private:
        bool initialized_;
        ///
        QPalette pal_;
+       /// Overlay fg color on bg color
+       /// This is necessary with transparency in fg color
+       ARGBColor colorOverlay(ARGBColor const & fg, ARGBColor const & bg);
 };
 
 ///
diff --git a/src/frontends/qt/GuiApplication.cpp 
b/src/frontends/qt/GuiApplication.cpp
index 532388a888..e48087bba6 100644
--- a/src/frontends/qt/GuiApplication.cpp
+++ b/src/frontends/qt/GuiApplication.cpp
@@ -3084,9 +3084,9 @@ bool GuiApplication::isInDarkMode()
 }
 
 
-bool GuiApplication::isLightColor(RGBColor const & rgb)
+bool GuiApplication::isLightColor(ARGBColor const & fg, ARGBColor const & bg)
 {
-       return colorCache().isLightColor(rgb);
+       return colorCache().isLightColor(fg, bg);
 }
 
 
diff --git a/src/frontends/qt/GuiApplication.h 
b/src/frontends/qt/GuiApplication.h
index 3f03ad1458..eff522eb3c 100644
--- a/src/frontends/qt/GuiApplication.h
+++ b/src/frontends/qt/GuiApplication.h
@@ -76,7 +76,7 @@ public:
        bool getRgbColor(ColorCode col, RGBColor & rgbcol) override;
        bool getArgbColor(ColorCode col, ARGBColor & argbcol) override;
        bool isInDarkMode() override;
-       bool isLightColor(RGBColor const & rgb) override;
+       bool isLightColor(ARGBColor const & fg, ARGBColor const & bg) override;
        std::string const hexName(ColorCode col) override;
        void registerSocketCallback(int fd, SocketCallback func) override;
        void unregisterSocketCallback(int fd) override;
diff --git a/src/frontends/qt/GuiWorkArea.cpp b/src/frontends/qt/GuiWorkArea.cpp
index 3fb3f26e79..b4b4b7e401 100644
--- a/src/frontends/qt/GuiWorkArea.cpp
+++ b/src/frontends/qt/GuiWorkArea.cpp
@@ -581,12 +581,14 @@ void GuiWorkArea::Private::drawCaret(QPainter & painter, 
int horiz_offset) const
                && buffer_view_->getCaretBackground() != "none"
                && ((guiApp->colorCache().isDarkMode()
                    && guiApp->colorCache().isLightColor(
-                          rgbFromHexName(lcolor.getX11HexName(
-                                                 
buffer_view_->getCaretBackground(), true))))
+                            argbFromHexName(lcolor.get32bitHexName(
+                                                 
buffer_view_->getCaretBackground(), true)),
+                            
argbFromHexName(lcolor.get32bitHexName("background", true))))
                || (!guiApp->colorCache().isDarkMode()
-                   && !guiApp->colorCache().isLightColor(rgbFromHexName(
-                                                             
lcolor.getX11HexName(
-                                                                     
buffer_view_->getCaretBackground()))))))
+                   && !guiApp->colorCache().isLightColor(argbFromHexName(
+                                                             
lcolor.get32bitHexName(
+                                                                     
buffer_view_->getCaretBackground())),
+                                                         
argbFromHexName(lcolor.get32bitHexName("background"))))))
                        ? guiApp->colorCache().get(Color_cursor_inverted)
                        : guiApp->colorCache().get(Color_cursor);
        painter.setPen(color);
diff --git a/src/insets/Inset.cpp b/src/insets/Inset.cpp
index 14f93c9d2b..0924136107 100644
--- a/src/insets/Inset.cpp
+++ b/src/insets/Inset.cpp
@@ -308,12 +308,15 @@ Color Inset::getModeDependentColor(PainterInfo & pi) const
        FontInfo font = pi.base.font;
        bool invert = false;
        if (theApp() && theApp()->isInDarkMode()) {
+               ColorCode cc = pi.backgroundColor(this);
                if (font.color() == Color_none
-                   && 
theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(pi.background_color, 
true))))
+                   && 
theApp()->isLightColor(argbFromHexName(lcolor.get32bitHexName(cc, true)),
+                                             
argbFromHexName(lcolor.get32bitHexName("background", true))))
                        invert = true;
-               else if (pi.background_color == Color_background
+               else if (cc == Color_background
                         && font.color() != Color_none
-                        && 
!theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(font.color()))))
+                        && 
!theApp()->isLightColor(argbFromHexName(lcolor.get32bitHexName(font.color())),
+                                                   
argbFromHexName(lcolor.get32bitHexName("background", true))))
                        invert = true;
        }
        Color rc = font.realColor(invert);
@@ -331,16 +334,20 @@ Color Inset::getModeDependentColor(ColorCode const fgc, 
ColorCode const bgc) con
        bool darken = false;
        if (theApp() && theApp()->isInDarkMode()) {
                if (fgc == Color_none
-                   && 
theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(bgc, true))))
+                   && 
theApp()->isLightColor(argbFromHexName(lcolor.getX11HexName(bgc, true)),
+                                             
argbFromHexName(lcolor.get32bitHexName("background", true))))
                        invert = true;
                else if (bgc == Color_background
                         && fgc != Color_none
-                        && 
!theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(fgc, true))))
+                        && 
!theApp()->isLightColor(argbFromHexName(lcolor.getX11HexName(fgc, true)),
+                                                   
argbFromHexName(lcolor.get32bitHexName("background", true))))
                        invert = true;
                else if (bgc != Color_background
                         && fgc != Color_none
-                        && 
theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(fgc, true)))
-                        && 
theApp()->isLightColor(rgbFromHexName(lcolor.getX11HexName(bgc, true))))
+                        && 
theApp()->isLightColor(argbFromHexName(lcolor.getX11HexName(fgc, true)),
+                                                  
argbFromHexName(lcolor.get32bitHexName(bgc, true)))
+                        && 
theApp()->isLightColor(argbFromHexName(lcolor.getX11HexName(bgc, true)),
+                                                  
argbFromHexName(lcolor.get32bitHexName("background", true))))
                        darken = true;
        }
        Color res = fgc;
-- 
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs

Reply via email to