diff --git a/kdecoration/config/darklyconfigwidget.cpp b/kdecoration/config/darklyconfigwidget.cpp
index 00ccbc51..dcafd4de 100644
--- a/kdecoration/config/darklyconfigwidget.cpp
+++ b/kdecoration/config/darklyconfigwidget.cpp
@@ -54,6 +54,8 @@ ConfigWidget::ConfigWidget(QObject *parent, const KPluginMetaData &data, const Q
connect(m_ui.roundedCorners, &QAbstractButton::clicked, this, &ConfigWidget::updateChanged);
connect(m_ui.otherCornerRadius, SIGNAL(valueChanged(int)), SLOT(updateChanged()));
connect(m_ui.floatingTitlebar, &QAbstractButton::clicked, this, &ConfigWidget::updateChanged);
+ connect(m_ui.blurTransparentTitleBar, &QAbstractButton::clicked, this, &ConfigWidget::updateChanged);
+ connect(m_ui.matchInactiveTitleBar, &QAbstractButton::clicked, this, &ConfigWidget::updateChanged);
// track animations changes
connect(m_ui.animationsEnabled, &QAbstractButton::clicked, this, &ConfigWidget::updateChanged);
@@ -92,6 +94,8 @@ void ConfigWidget::load()
#endif
m_ui.otherCornerRadius->setValue(m_internalSettings->otherCornerRadius());
m_ui.floatingTitlebar->setChecked(m_internalSettings->floatingTitlebar());
+ m_ui.blurTransparentTitleBar->setChecked(m_internalSettings->blurTransparentTitleBar());
+ m_ui.matchInactiveTitleBar->setChecked(m_internalSettings->matchInactiveTitleBar());
// load shadows
if (m_internalSettings->shadowSize() <= InternalSettings::ShadowVeryLarge)
@@ -128,6 +132,8 @@ void ConfigWidget::save()
m_internalSettings->setRoundedCorners(m_ui.roundedCorners->isChecked());
m_internalSettings->setOtherCornerRadius(m_ui.otherCornerRadius->value());
m_internalSettings->setFloatingTitlebar(m_ui.floatingTitlebar->isChecked());
+ m_internalSettings->setBlurTransparentTitleBar(m_ui.blurTransparentTitleBar->isChecked());
+ m_internalSettings->setMatchInactiveTitleBar(m_ui.matchInactiveTitleBar->isChecked());
m_internalSettings->setShadowSize(m_ui.shadowSize->currentIndex());
m_internalSettings->setShadowStrength(qRound(qreal(m_ui.shadowStrength->value() * 255) / 100));
@@ -176,6 +182,8 @@ void ConfigWidget::defaults()
m_ui.roundedCorners->setChecked(m_internalSettings->roundedCorners());
m_ui.otherCornerRadius->setValue(m_internalSettings->otherCornerRadius());
m_ui.floatingTitlebar->setChecked(m_internalSettings->floatingTitlebar());
+ m_ui.blurTransparentTitleBar->setChecked(m_internalSettings->blurTransparentTitleBar());
+ m_ui.matchInactiveTitleBar->setChecked(m_internalSettings->matchInactiveTitleBar());
m_ui.shadowSize->setCurrentIndex(m_internalSettings->shadowSize());
m_ui.shadowStrength->setValue(qRound(qreal(m_internalSettings->shadowStrength() * 100) / 255));
@@ -210,6 +218,10 @@ void ConfigWidget::updateChanged()
modified = true;
else if (m_ui.floatingTitlebar->isChecked() != m_internalSettings->floatingTitlebar())
modified = true;
+ else if (m_ui.blurTransparentTitleBar->isChecked() != m_internalSettings->blurTransparentTitleBar())
+ modified = true;
+ else if (m_ui.matchInactiveTitleBar->isChecked() != m_internalSettings->matchInactiveTitleBar())
+ modified = true;
// animations
else if (m_ui.animationsEnabled->isChecked() != m_internalSettings->animationsEnabled())
diff --git a/kdecoration/config/ui/darklyconfigurationui.ui b/kdecoration/config/ui/darklyconfigurationui.ui
index ae1acde2..4aa77415 100644
--- a/kdecoration/config/ui/darklyconfigurationui.ui
+++ b/kdecoration/config/ui/darklyconfigurationui.ui
@@ -191,6 +191,26 @@
+ -
+
+
+ Make the title bar translucent and blurred, matched to the toolbar opacity so the top of the window is seamless.
+
+
+ Transparent, blurred title bar
+
+
+
+ -
+
+
+ Keep the titlebar background and text colors identical whether the window is focused or not, so unfocused windows don't appear lighter or more transparent.
+
+
+ Use active titlebar colors for inactive windows
+
+
+
diff --git a/kdecoration/darklydecoration.cpp b/kdecoration/darklydecoration.cpp
index 262b44bb..23718a15 100644
--- a/kdecoration/darklydecoration.cpp
+++ b/kdecoration/darklydecoration.cpp
@@ -174,10 +174,27 @@ QColor Decoration::titleBarColor() const
auto c = window();
if (hideTitleBar())
return c->color(ColorGroup::Inactive, ColorRole::TitleBar);
- else if (m_animation->state() == QAbstractAnimation::Running) {
- return KColorUtils::mix(c->color(ColorGroup::Inactive, ColorRole::TitleBar), c->color(ColorGroup::Active, ColorRole::TitleBar), m_opacity);
- } else
- return c->color(c->isActive() ? ColorGroup::Active : ColorGroup::Inactive, ColorRole::TitleBar);
+
+ QColor color;
+ if (!m_internalSettings->matchInactiveTitleBar() &&
+ m_animation->state() == QAbstractAnimation::Running) {
+ color = KColorUtils::mix(c->color(ColorGroup::Inactive, ColorRole::TitleBar),
+ c->color(ColorGroup::Active, ColorRole::TitleBar),
+ m_opacity);
+ } else {
+ const ColorGroup group = (c->isActive() || m_internalSettings->matchInactiveTitleBar())
+ ? ColorGroup::Active : ColorGroup::Inactive;
+ color = c->color(group, ColorRole::TitleBar);
+ }
+
+ if (m_internalSettings->blurTransparentTitleBar()) {
+ const int opacity = KSharedConfig::openConfig(QStringLiteral("darklyrc"))
+ ->group(QStringLiteral("Style"))
+ .readEntry("ToolBarOpacity", 100);
+ color.setAlpha(qRound(qBound(0, opacity, 100) * 255.0 / 100));
+ }
+
+ return color;
}
//________________________________________________________________
QColor Decoration::outlineColor() const
@@ -199,7 +216,8 @@ QColor Decoration::outlineColor() const
QColor Decoration::fontColor() const
{
auto c = window();
- return c->color(c->isActive() ? ColorGroup::Active : ColorGroup::Inactive, ColorRole::Foreground);
+ const bool useActive = c->isActive() || m_internalSettings->matchInactiveTitleBar();
+ return c->color(useActive ? ColorGroup::Active : ColorGroup::Inactive, ColorRole::Foreground);
}
//________________________________________________________________
@@ -272,50 +290,38 @@ bool Decoration::init()
//________________________________________________________________
void Decoration::updateBlur()
{
-if (m_internalSettings->floatingTitlebar()){
auto c = window();
- const QColor titleBarColor = c->color(c->isActive() ? ColorGroup::Active : ColorGroup::Inactive, ColorRole::TitleBar);
-
- // set opaque to false when non-maximized, regardless of color (prevents kornerbug)
- if (titleBarColor.alpha() == 255) {
+ const QColor tbColor = this->titleBarColor();
+ if (tbColor.alpha() == 255) {
this->setOpaque(c->isMaximized());
} else {
this->setOpaque(false);
}
- // Recalculate window shapes
- calculateWindowAndTitleBarShapes(true);
+ if (m_internalSettings->floatingTitlebar()) {
+ // Recalculate window shapes
+ calculateWindowAndTitleBarShapes(true);
- // Get window rectangle as integers
- QRect windowRect(QPoint(0, 0), c->size().toSize());
+ // Get window rectangle as integers
+ QRect windowRect(QPoint(0, 0), c->size().toSize());
- // Height of the blur region
- const int blurHeight = (buttonSize() + (Metrics::TitleBar_TopMargin * 2) + 8);
+ // Height of the blur region
+ const int blurHeight = (buttonSize() + (Metrics::TitleBar_TopMargin * 2) + 8);
- // Corner radius
- const qreal blurRadius = c->isMaximized() ? 0.0 : m_scaledCornerRadius;
+ // Corner radius
+ const qreal blurRadius = c->isMaximized() ? 0.0 : m_scaledCornerRadius;
- // Create a rounded rectangle path for the top strip
- QPainterPath path;
- path.addRoundedRect(QRectF(0, 0, windowRect.width(), blurHeight), blurRadius, blurRadius);
+ // Create a rounded rectangle path for the top strip
+ QPainterPath path;
+ path.addRoundedRect(QRectF(0, 0, windowRect.width(), blurHeight), blurRadius, blurRadius);
- // Convert path to QRegion and set as blur region
- QRegion blurRegion(path.toFillPolygon().toPolygon());
- this->setBlurRegion(blurRegion);
-} else {
- auto c = window();
- const QColor titleBarColor = c->color(c->isActive() ? ColorGroup::Active : ColorGroup::Inactive, ColorRole::TitleBar);
-
- // set opaque to false when non-maximized, regardless of color (prevents kornerbug)
- if (titleBarColor.alpha() == 255) {
- this->setOpaque(c->isMaximized());
+ // Convert path to QRegion and set as blur region
+ QRegion blurRegion(path.toFillPolygon().toPolygon());
+ this->setBlurRegion(blurRegion);
} else {
- this->setOpaque(false);
+ calculateWindowAndTitleBarShapes(true);
+ this->setBlurRegion(QRegion(m_windowPath->toFillPolygon().toPolygon()));
}
-
- calculateWindowAndTitleBarShapes(true);
- this->setBlurRegion(QRegion(m_windowPath->toFillPolygon().toPolygon()));
-}
}
//________________________________________________________________
@@ -877,9 +883,10 @@ void Decoration::paint(QPainter *painter, const QRectF &repaintRegion)
void Decoration::paintTitleBar(QPainter *painter, const QRectF &repaintRegion)
{
const auto c = window();
+ const QColor titleBarColor = this->titleBarColor();
QRectF rect(QPointF(0, 0), QSizeF(size().width(), borderTop()));
QBrush frontBrush;
- QBrush backBrush(this->titleBarColor());
+ QBrush backBrush(titleBarColor);
if (!rect.intersects(repaintRegion)) {
return;
@@ -890,21 +897,20 @@ void Decoration::paintTitleBar(QPainter *painter, const QRectF &repaintRegion)
// render a linear gradient on title area
if (c->isActive() && m_internalSettings->drawBackgroundGradient()) {
- const QColor titleBarColor(this->titleBarColor());
QLinearGradient gradient(0, 0, 0, m_titleRect.height());
gradient.setColorAt(0.0, titleBarColor.lighter(120));
gradient.setColorAt(0.8, titleBarColor);
painter->setBrush(gradient);
} else {
- painter->setBrush(titleBarColor());
+ painter->setBrush(titleBarColor);
}
auto s = settings();
painter->drawPath(*m_titleBarPath);
// top highlight
- if (qGray(this->titleBarColor().rgb()) < 130 && m_internalSettings->drawHighlight()) {
+ if (qGray(titleBarColor.rgb()) < 130 && m_internalSettings->drawHighlight()) {
if (isMaximized() || !s->isAlphaChannelSupported()) {
painter->setPen(QColor(255, 255, 255, 30));
painter->drawLine(m_titleRect.topLeft(), m_titleRect.topRight());
diff --git a/kdecoration/darklydecoration.h b/kdecoration/darklydecoration.h
index 114b9753..5eba40ad 100644
--- a/kdecoration/darklydecoration.h
+++ b/kdecoration/darklydecoration.h
@@ -162,6 +162,7 @@ private Q_SLOTS:
//*frame corner radius, scaled according to DPI
qreal m_scaledCornerRadius = 3;
+
};
bool Decoration::hasBorders() const
diff --git a/kdecoration/darklysettingsdata.kcfg b/kdecoration/darklysettingsdata.kcfg
index 4b206a64..fd7dc7d3 100644
--- a/kdecoration/darklysettingsdata.kcfg
+++ b/kdecoration/darklysettingsdata.kcfg
@@ -132,6 +132,16 @@
false
+
+
+ false
+
+
+
+
+ false
+
+
diff --git a/kstyle/darklystyle.cpp b/kstyle/darklystyle.cpp
index 883d61dd..24fbccd4 100644
--- a/kstyle/darklystyle.cpp
+++ b/kstyle/darklystyle.cpp
@@ -4391,6 +4391,18 @@ bool Style::drawFrameTabWidgetPrimitive(const QStyleOption *option, QPainter *pa
if (tabOption->tabBarSize.isEmpty() && !isQtQuickControl)
return true;
+ // When Dolphin's view is transparent, the tab bar above and KItemListContainer below
+ // both punch transparent holes and fill at dolphinViewOpacity. The frame background
+ // here would otherwise be a fully opaque strip between them — the visible line.
+ // Match the surrounding areas: punch transparent and fill at the same opacity.
+ if (_isDolphin && StyleConfigData::dolphinViewOpacity() < 100 && widget && _translucentWidgets.contains(widget->window())) {
+ _helper->renderTransparentArea(painter, option->rect);
+ QColor backgroundColor = option->palette.color(QPalette::Window);
+ backgroundColor.setAlphaF(StyleConfigData::dolphinViewOpacity() / 100.0);
+ painter->fillRect(option->rect, backgroundColor);
+ return true;
+ }
+
// define colors
const auto &palette(option->palette);
const auto background(_helper->frameBackgroundColor(palette));