Gtk3 Theme: Fix disabled colors for texts

Previously, disabled text colors were a darker version of the normal
text color. However, when the text color is black, the darker version
is also black, making the disabled text indistinguishable from the
enabled text.

To fix this issue, a source struct called `MixSources` has been
implemented. This struct contains the mixing sources. For disabled
texts, a mix of the background and text color sources creates a more
sensible appearance, making the disabled text look more like the
control's background color.

This solution does not require access to the system's color scheme, as
the disabled color depends only on the background and foreground colors.

Fixes: QTBUG-123449
Pick-to: 6.7 6.5
Change-Id: I469e4fc05ddd4851120b89646bd7ab17a3ee2c00
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
(cherry picked from commit 21a070052716c8ce1c471817b985f43e5b19af0c)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
MohammadHossein Qanbari 2024-06-27 18:41:19 +02:00 committed by Qt Cherry-pick Bot
parent 267e378d14
commit 4b7ad06dc4
3 changed files with 105 additions and 5 deletions

View File

@ -211,6 +211,15 @@ const QJsonDocument QGtk3Json::save(const QGtk3Storage::PaletteMap &map)
}
break;
case QGtk3Storage::SourceType::Mixed: {
sourceObject.insert(ceColorGroup, fromColorGroup(s.mix.sourceGroup));
QJsonArray colorRoles;
colorRoles << fromColorRole(s.mix.colorRole1)
<< fromColorRole(s.mix.colorRole2);
sourceObject.insert(ceColorRole, colorRoles);
}
break;
case QGtk3Storage::SourceType::Invalid:
break;
}
@ -387,6 +396,26 @@ bool QGtk3Json::load(QGtk3Storage::PaletteMap &map, const QJsonDocument &doc)
}
break;
case QGtk3Storage::SourceType::Mixed: {
if (!sourceObject[ceColorRole].isArray()) {
qCInfo(lcQGtk3Interface) << "Mixed brush missing the array of color roles for palette:" << paletteName
<< "Brush" << colorRoleName;
return false;
}
QJsonArray colorRoles = sourceObject[ceColorRole].toArray();
if (colorRoles.size() < 2) {
qCInfo(lcQGtk3Interface) << "Mixed brush missing enough color roles for palette" << paletteName
<< "Brush" << colorRoleName;
return false;
}
const QPalette::ColorRole colorRole1 = toColorRole(colorRoles[0].toString());
const QPalette::ColorRole colorRole2 = toColorRole(colorRoles[1].toString());
GETSTR(sourceObject, ceColorGroup);
const QPalette::ColorGroup sourceGroup = toColorGroup(value);
s = QGtk3Storage::Source(sourceGroup, colorRole1, colorRole2);
}
break;
case QGtk3Storage::SourceType::Invalid:
qInfo(lcQGtk3Interface) << "Invalid source type for palette" << paletteName
<< "Brush." << colorRoleName;

View File

@ -75,6 +75,31 @@ QBrush QGtk3Storage::brush(const Source &source, const BrushMap &map) const
return b;
}
case SourceType::Mixed: {
// check the mixing source to be valid and be a Gtk source
constexpr auto check_source = [](const Source &source) -> bool
{
return source.isValid() && (source.sourceType == SourceType::Gtk);
};
const Source source1 = brush(TargetBrush(source.mix.sourceGroup,
source.mix.colorRole1), map);
if (!check_source(source1))
return QBrush();
const Source source2 = brush(TargetBrush(source.mix.sourceGroup,
source.mix.colorRole2), map);
if (!check_source(source2))
return QBrush();
const QBrush brush2 = brush(source2, map);
// the output brush is a copy of the brush from the first source
QBrush brush1 = brush(source1, map);
// only color is mixed
brush1.setColor(MixSources::mixColors(brush1.color(), brush2.color()));
return brush1;
}
case SourceType::Fixed:
return source.fix.fixedBrush;
@ -413,6 +438,7 @@ const QGtk3Storage::PaletteMap QGtk3Storage::savePalettes() const
break;
case SourceType::Fixed:
case SourceType::Modified:
case SourceType::Mixed:
case SourceType::Invalid:
break;
}
@ -554,10 +580,22 @@ void QGtk3Storage::createMapping()
GTK(button, Foreground, ACTIVE);
ADD(Inactive, WindowText);
LIGHTER(Normal, WindowText, 50);
ADD(Disabled, Text);
ADD(Disabled, WindowText);
ADD(Disabled, ButtonText);
auto ADD_MIX = [&map](QPalette::ColorGroup targetGroup,
QPalette::ColorRole targetRole,
QPalette::ColorGroup sourceGroup,
QPalette::ColorRole role1,
QPalette::ColorRole role2)
{
const Source source{sourceGroup, role1, role2};
map.insert(TargetBrush(targetGroup, targetRole), source);
};
ADD_MIX(QPalette::Disabled, QPalette::Text,
QPalette::Normal, QPalette::Base, QPalette::Text);
ADD_MIX(QPalette::Disabled, QPalette::WindowText,
QPalette::Normal, QPalette::Window, QPalette::WindowText);
ADD_MIX(QPalette::Disabled, QPalette::ButtonText,
QPalette::Normal, QPalette::Button, QPalette::ButtonText);
GTK(button, Text, NORMAL);
ADD(Inactive, ButtonText);

View File

@ -41,6 +41,7 @@ public:
Gtk,
Fixed,
Modified,
Mixed,
Invalid
};
Q_ENUM(SourceType)
@ -80,6 +81,27 @@ public:
}
};
// Mixed source: Populate a brush by mixing two brushes.
// Useful for creating disabled color by mixing,
// for example the background and foreground colors.
struct MixSources {
QPalette::ColorGroup sourceGroup; // source group of the mixing color roles
QPalette::ColorRole colorRole1;
QPalette::ColorRole colorRole2;
QDebug operator<<(QDebug dbg)
{
return dbg << "QGtkStorage::MixSources(sourceGroup=" << sourceGroup
<< ", colorRole1=" << colorRole1
<< ", colorRole2=" << colorRole2 << ")";
}
static inline QColor mixColors(const QColor &color1, const QColor &color2)
{
return QColor{ (color1.red() + color2.red()) / 2,
(color1.green() + color2.green()) / 2,
(color1.blue() + color2.blue()) / 2 };
}
};
// Fixed source: Populate a brush with fixed values rather than reading GTK
struct FixedSource {
QBrush fixedBrush;
@ -95,6 +117,7 @@ public:
Gtk3Source gtk3;
RecursiveSource rec;
FixedSource fix;
MixSources mix;
// GTK constructor
Source(QGtk3Interface::QGtkWidget wtype, QGtk3Interface::QGtkColorSource csource,
@ -118,7 +141,7 @@ public:
rec.lighter = p_lighter;
}
// Recursive ocnstructor for color modification
// Recursive constructor for color modification
Source(QPalette::ColorGroup group, QPalette::ColorRole role,
Qt::ColorScheme scheme, int p_red, int p_green, int p_blue)
: sourceType(SourceType::Modified)
@ -145,6 +168,16 @@ public:
rec.deltaBlue = p_blue;
}
// Mixed constructor for color modification
Source(QPalette::ColorGroup sourceGroup,
QPalette::ColorRole role1, QPalette::ColorRole role2)
: sourceType(SourceType::Mixed)
{
mix.sourceGroup = sourceGroup;
mix.colorRole1 = role1;
mix.colorRole2 = role2;
}
// Fixed Source constructor
Source(const QBrush &brush) : sourceType(SourceType::Fixed)
{