diff --git a/modules/config.nix b/modules/config.nix index 02b0a56..0234a82 100644 --- a/modules/config.nix +++ b/modules/config.nix @@ -863,7 +863,7 @@ in kfinal: kprev: { kwin = kprev.kwin.overrideAttrs (old: { patches = (old.patches or [ ]) ++ [ - ../patches/kde-decoration.patch + ../patches/vmsilo-decorations-combined-v6.5.5.patch ]; }); } diff --git a/patches/kde-decoration.patch b/patches/kde-decoration.patch deleted file mode 100644 index 5abc4a8..0000000 --- a/patches/kde-decoration.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 9c102e0fa2e268dad187f0a882f8b2db5feb1967 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Dav=C3=AD=C3=B0=20Steinn=20Geirsson?= -Date: Sun, 8 Feb 2026 23:31:28 +0000 -Subject: [PATCH] decorations: support vmsilo security context color override - -Add support for changing window decoration colors based on Wayland -security context. When a window's security context has the format -"vmsilo::", the decoration uses the specified color -for the frame and titlebar, with automatic contrast adjustment for -foreground text. - -Windows without a security context or with non-vmsilo contexts -continue to use standard palette behavior. - -Co-Authored-By: Claude Opus 4.5 ---- - src/decorations/decoratedwindow.cpp | 49 ++++++++++++++++++++++++++++- - 1 file changed, 48 insertions(+), 1 deletion(-) - -diff --git a/src/decorations/decoratedwindow.cpp b/src/decorations/decoratedwindow.cpp -index 74f799daa8..1cf52c647d 100644 ---- a/src/decorations/decoratedwindow.cpp -+++ b/src/decorations/decoratedwindow.cpp -@@ -17,11 +17,32 @@ - #include - #include - -+#include "wayland/clientconnection.h" -+#include "wayland/surface.h" -+ - #include - #include - #include - #include - -+namespace { -+QColor parseVmsiloColor(const QString &securityContextAppId) -+{ -+ if (securityContextAppId.isEmpty() || -+ !securityContextAppId.startsWith(QLatin1String("vmsilo:"))) { -+ return QColor(); -+ } -+ -+ const QStringList parts = securityContextAppId.split(QLatin1Char(':')); -+ if (parts.size() != 3) { -+ return QColor(); -+ } -+ -+ // parts[0] = "vmsilo", parts[1] = vmname, parts[2] = color -+ return QColor(parts[2]); -+} -+} // anonymous namespace -+ - namespace KWin - { - namespace Decoration -@@ -192,11 +213,37 @@ void DecoratedWindowImpl::requestClose() - - QColor DecoratedWindowImpl::color(KDecoration3::ColorGroup group, KDecoration3::ColorRole role) const - { -+ // Check for vmsilo security context color override -+ if (SurfaceInterface *surf = m_window->surface()) { -+ if (ClientConnection *client = surf->client()) { -+ const QColor vmsiloColor = parseVmsiloColor(client->securityContextAppId()); -+ if (vmsiloColor.isValid()) { -+ switch (role) { -+ case KDecoration3::ColorRole::Frame: -+ case KDecoration3::ColorRole::TitleBar: -+ if (group == KDecoration3::ColorGroup::Inactive) { -+ return vmsiloColor.darker(120); -+ } -+ return vmsiloColor; -+ case KDecoration3::ColorRole::Foreground: { -+ // Calculate contrasting foreground color -+ const qreal luminance = 0.299 * vmsiloColor.redF() -+ + 0.587 * vmsiloColor.greenF() -+ + 0.114 * vmsiloColor.blueF(); -+ return (luminance > 0.5) ? Qt::black : Qt::white; -+ } -+ default: -+ break; -+ } -+ } -+ } -+ } -+ -+ // Fall back to standard palette behavior - auto dp = m_window->decorationPalette(); - if (dp) { - return dp->color(group, role); - } -- - return QColor(); - } - --- -2.52.0 - diff --git a/patches/vmsilo-decorations-combined-v6.5.5.patch b/patches/vmsilo-decorations-combined-v6.5.5.patch new file mode 100644 index 0000000..1216aa7 --- /dev/null +++ b/patches/vmsilo-decorations-combined-v6.5.5.patch @@ -0,0 +1,266 @@ +diff --git a/src/decorations/decoratedwindow.cpp b/src/decorations/decoratedwindow.cpp +index ff1a4ad245..300dd996cb 100644 +--- a/src/decorations/decoratedwindow.cpp ++++ b/src/decorations/decoratedwindow.cpp +@@ -17,11 +17,32 @@ + #include + #include + ++#include "wayland/clientconnection.h" ++#include "wayland/surface.h" ++ + #include + #include + #include + #include + ++namespace { ++QColor parseVmsiloColor(const QString &securityContextAppId) ++{ ++ if (securityContextAppId.isEmpty() || ++ !securityContextAppId.startsWith(QLatin1String("vmsilo:"))) { ++ return QColor(); ++ } ++ ++ const QStringList parts = securityContextAppId.split(QLatin1Char(':')); ++ if (parts.size() != 3) { ++ return QColor(); ++ } ++ ++ // parts[0] = "vmsilo", parts[1] = vmname, parts[2] = color ++ return QColor(parts[2]); ++} ++} // anonymous namespace ++ + namespace KWin + { + namespace Decoration +@@ -187,11 +208,37 @@ void DecoratedWindowImpl::requestClose() + + QColor DecoratedWindowImpl::color(KDecoration3::ColorGroup group, KDecoration3::ColorRole role) const + { ++ // Check for vmsilo security context color override ++ if (SurfaceInterface *surf = m_window->surface()) { ++ if (ClientConnection *client = surf->client()) { ++ const QColor vmsiloColor = parseVmsiloColor(client->securityContextAppId()); ++ if (vmsiloColor.isValid()) { ++ switch (role) { ++ case KDecoration3::ColorRole::Frame: ++ case KDecoration3::ColorRole::TitleBar: ++ if (group == KDecoration3::ColorGroup::Inactive) { ++ return vmsiloColor.darker(120); ++ } ++ return vmsiloColor; ++ case KDecoration3::ColorRole::Foreground: { ++ // Calculate contrasting foreground color ++ const qreal luminance = 0.299 * vmsiloColor.redF() ++ + 0.587 * vmsiloColor.greenF() ++ + 0.114 * vmsiloColor.blueF(); ++ return (luminance > 0.5) ? Qt::black : Qt::white; ++ } ++ default: ++ break; ++ } ++ } ++ } ++ } ++ ++ // Fall back to standard palette behavior + auto dp = m_window->decorationPalette(); + if (dp) { + return dp->color(group, role); + } +- + return QColor(); + } + +diff --git a/src/decorations/decorationbridge.cpp b/src/decorations/decorationbridge.cpp +index bde1d82b06..48726d0fc2 100644 +--- a/src/decorations/decorationbridge.cpp ++++ b/src/decorations/decorationbridge.cpp +@@ -89,6 +89,10 @@ void DecorationBridge::init() + } + m_settings = std::make_shared(this); + ++ m_pendingBorderSizeOverride = KDecoration3::BorderSize::Tiny; ++ m_vmsiloSettings = std::make_shared(this); ++ m_pendingBorderSizeOverride.reset(); ++ + const QString pluginId = readPlugin(); + if (!initPlugin(pluginId)) { + if (s_defaultPlugin != pluginId) { +@@ -144,6 +148,7 @@ void DecorationBridge::reconfigure() + m_plugin = QString(); + m_factory.reset(); + m_settings.reset(); ++ m_vmsiloSettings.reset(); + } else { + // decorations enabled now + init(); +@@ -212,7 +217,7 @@ std::unique_ptr DecorationBridge::createCl + + std::unique_ptr DecorationBridge::settings(KDecoration3::DecorationSettings *parent) + { +- return std::unique_ptr(new SettingsImpl(parent)); ++ return std::make_unique(parent, m_pendingBorderSizeOverride); + } + + KDecoration3::Decoration *DecorationBridge::createDecoration(Window *window) +@@ -229,7 +234,11 @@ KDecoration3::Decoration *DecorationBridge::createDecoration(Window *window) + args.insert(QStringLiteral("theme"), m_theme); + } + auto deco = m_factory->create(window, QVariantList{args}); +- deco->setSettings(m_settings); ++ if (window->hasVmsiloSecurityContext()) { ++ deco->setSettings(m_vmsiloSettings); ++ } else { ++ deco->setSettings(m_settings); ++ } + deco->create(); + deco->init(); + return deco; +diff --git a/src/decorations/decorationbridge.h b/src/decorations/decorationbridge.h +index e06a131134..51c96dcd27 100644 +--- a/src/decorations/decorationbridge.h ++++ b/src/decorations/decorationbridge.h +@@ -10,7 +10,9 @@ + + #include "kwin_export.h" + #include ++#include + #include ++#include + + class KPluginFactory; + namespace KDecoration3 +@@ -76,6 +78,8 @@ private: + QString m_defaultTheme; + QString m_theme; + std::shared_ptr m_settings; ++ std::shared_ptr m_vmsiloSettings; ++ std::optional m_pendingBorderSizeOverride; + bool m_noPlugin; + }; + } // Decoration +diff --git a/src/decorations/settings.cpp b/src/decorations/settings.cpp +index 21b5bbf5cf..70f313d636 100644 +--- a/src/decorations/settings.cpp ++++ b/src/decorations/settings.cpp +@@ -22,10 +22,12 @@ namespace KWin + { + namespace Decoration + { +-SettingsImpl::SettingsImpl(KDecoration3::DecorationSettings *parent) ++SettingsImpl::SettingsImpl(KDecoration3::DecorationSettings *parent, ++ std::optional borderSizeOverride) + : QObject() + , DecorationSettingsPrivate(parent) + , m_borderSize(KDecoration3::BorderSize::Normal) ++ , m_borderSizeOverride(borderSizeOverride) + { + readSettings(); + +diff --git a/src/decorations/settings.h b/src/decorations/settings.h +index 128bead161..e6e4e83b60 100644 +--- a/src/decorations/settings.h ++++ b/src/decorations/settings.h +@@ -11,6 +11,7 @@ + #include + + #include ++#include + + class KConfigGroup; + +@@ -23,14 +24,15 @@ class SettingsImpl : public QObject, public KDecoration3::DecorationSettingsPriv + { + Q_OBJECT + public: +- explicit SettingsImpl(KDecoration3::DecorationSettings *parent); ++ explicit SettingsImpl(KDecoration3::DecorationSettings *parent, ++ std::optional borderSizeOverride = std::nullopt); + ~SettingsImpl() override; + bool isAlphaChannelSupported() const override; + bool isOnAllDesktopsAvailable() const override; + bool isCloseOnDoubleClickOnMenu() const override; + KDecoration3::BorderSize borderSize() const override + { +- return m_borderSize; ++ return m_borderSizeOverride.value_or(m_borderSize); + } + QList decorationButtonsLeft() const override + { +@@ -53,6 +55,7 @@ private: + QList m_leftButtons; + QList m_rightButtons; + KDecoration3::BorderSize m_borderSize; ++ std::optional m_borderSizeOverride; + bool m_autoBorderSize = true; + bool m_closeDoubleClickMenu = false; + QFont m_font; +diff --git a/src/window.cpp b/src/window.cpp +index c4dd92c06f..e8f1901252 100644 +--- a/src/window.cpp ++++ b/src/window.cpp +@@ -36,6 +36,7 @@ + #include "useractions.h" + #include "virtualdesktops.h" + #include "wayland/output.h" ++#include "wayland/clientconnection.h" + #include "wayland/plasmawindowmanagement.h" + #include "wayland/surface.h" + #include "wayland_server.h" +@@ -4336,6 +4337,16 @@ bool Window::userCanSetNoBorder() const + return false; + } + ++bool Window::hasVmsiloSecurityContext() const ++{ ++ if (SurfaceInterface *surf = surface()) { ++ if (ClientConnection *client = surf->client()) { ++ return client->securityContextAppId().startsWith(QLatin1String("vmsilo:")); ++ } ++ } ++ return false; ++} ++ + void Window::setNoBorder(bool set) + { + qCWarning(KWIN_CORE, "%s doesn't support setting decorations", metaObject()->className()); +diff --git a/src/window.h b/src/window.h +index 2b11fa365c..fcf37d32bb 100644 +--- a/src/window.h ++++ b/src/window.h +@@ -844,6 +844,8 @@ public: + SurfaceInterface *surface() const; + void setSurface(SurfaceInterface *surface); + ++ bool hasVmsiloSecurityContext() const; ++ + /** + * @returns Transformation to map from global to window coordinates. + */ +diff --git a/src/xdgshellwindow.cpp b/src/xdgshellwindow.cpp +index 092c284b8c..0439025636 100644 +--- a/src/xdgshellwindow.cpp ++++ b/src/xdgshellwindow.cpp +@@ -694,6 +694,9 @@ bool XdgToplevelWindow::isTransient() const + + bool XdgToplevelWindow::userCanSetNoBorder() const + { ++ if (hasVmsiloSecurityContext()) { ++ return false; ++ } + return (m_serverDecoration || m_xdgDecoration) && !isFullScreen(); + } + +@@ -704,6 +707,9 @@ bool XdgToplevelWindow::noBorder() const + + void XdgToplevelWindow::setNoBorder(bool set) + { ++ if (hasVmsiloSecurityContext()) { ++ set = false; ++ } + set = rules()->checkNoBorder(set); + if (m_userNoBorder == set) { + return;