diff --git a/ConfigModel.cpp b/ConfigModel.cpp index 15d48a3..4f56bb5 100644 --- a/ConfigModel.cpp +++ b/ConfigModel.cpp @@ -8,15 +8,21 @@ const QString key_size = "roundness", + key_shadowSize = "shadowSize", + key_inactiveShadowSize = "inactiveShadowSize", key_shadowColor = "shadowColor", + key_inactiveShadowColor = "inactiveShadowColor", key_outlineColor = "outlineColor", key_inactiveOutlineColor = "inactiveOutlineColor", key_outlineThickness = "outlineThickness"; ConfigModel::ConfigModel(): m_size(10), + m_shadowSize(25), + m_inactiveShadowSize(20), m_outlineThickness(1), m_shadowColor(QColor(Qt::black)), + m_inactiveShadowColor(QColor(Qt::black)), m_outlineColor(QColor(Qt::black)), m_inactiveOutlineColor(QColor(Qt::black)) { @@ -25,7 +31,10 @@ ConfigModel::ConfigModel(): void ConfigModel::Load() { KConfigGroup conf = KSharedConfig::openConfig("shapecorners.conf")->group("General"); m_size = conf.readEntry(key_size, m_size); + m_shadowSize = conf.readEntry(key_shadowSize, m_shadowSize); + m_inactiveShadowSize = conf.readEntry(key_inactiveShadowSize, m_inactiveShadowSize); m_shadowColor = conf.readEntry(key_shadowColor, m_shadowColor); + m_inactiveShadowColor = conf.readEntry(key_inactiveShadowColor, m_inactiveShadowColor); m_outlineColor = conf.readEntry(key_outlineColor, m_outlineColor); m_inactiveOutlineColor = conf.readEntry(key_inactiveOutlineColor,m_inactiveOutlineColor); m_outlineThickness = conf.readEntry(key_outlineThickness, m_outlineThickness); @@ -34,7 +43,10 @@ void ConfigModel::Load() { void ConfigModel::Save() const { KConfigGroup conf = KSharedConfig::openConfig("shapecorners.conf")->group("General"); conf.writeEntry(key_size, m_size); + conf.writeEntry(key_shadowSize, m_shadowSize); + conf.writeEntry(key_inactiveShadowSize, m_inactiveShadowSize); conf.writeEntry(key_shadowColor, m_shadowColor); + conf.writeEntry(key_inactiveShadowColor, m_inactiveShadowColor); conf.writeEntry(key_outlineColor, m_outlineColor); conf.writeEntry(key_inactiveOutlineColor,m_inactiveOutlineColor); conf.writeEntry(key_outlineThickness, m_outlineThickness); diff --git a/ConfigModel.h b/ConfigModel.h index 692d2b6..550d500 100644 --- a/ConfigModel.h +++ b/ConfigModel.h @@ -14,8 +14,11 @@ class ConfigModel { void Save() const; float m_size, + m_shadowSize, + m_inactiveShadowSize, m_outlineThickness; QColor m_shadowColor, + m_inactiveShadowColor, m_outlineColor, m_inactiveOutlineColor; }; diff --git a/README.md b/README.md index b3c2f77..f5c6786 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This effect rounds the corners of your windows and adds an outline around them without much affecting the performance of the KDE Plasma desktop (see [#49](https://github.com/matinlotfali/KDE-Rounded-Corners/pull/49) and [#50](https://github.com/matinlotfali/KDE-Rounded-Corners/issues/50)). -This effect started as a fork of [shapecorners](https://sourceforge.net/projects/shapecorners/) with some additional contributions in [Alex47's project](https://github.com/alex47/KDE-Rounded-Corners), then I optimized and reimplemented the effect with shaders. +This effect started as a fork of [shapecorners](https://sourceforge.net/projects/shapecorners/) with some additional contributions in [Alex47's project](https://github.com/alex47/KDE-Rounded-Corners), then I optimized and reimplemented the effect with shaders with influences from the [invert effect](https://github.com/KDE/kwin/tree/master/src/plugins/invert). #### Tested on: - ![Kubuntu 22.04 Jammy](https://img.shields.io/badge/-not_supported-red?label=Kubuntu%2022.04%20Jammy&logo=kubuntu&branch=master) @@ -17,7 +17,7 @@ This effect started as a fork of [shapecorners](https://sourceforge.net/projects ![](https://img.shields.io/badge/KWinEffects-v237-lightgrey) - [![Arch](https://img.shields.io/github/actions/workflow/status/matinlotfali/KDE-Rounded-Corners/arch.yml?branch=master&label=Arch%20Linux&logo=archlinux&logoColor=white) ![](https://img.shields.io/aur/maintainer/kwin-effect-rounded-corners-git?label=AUR%20Maintainer) ![](https://img.shields.io/aur/votes/kwin-effect-rounded-corners-git?label=AUR%20Votes)](https://aur.archlinux.org/packages/kwin-effect-rounded-corners-git) -![After](https://raw.githubusercontent.com/matinlotfali/KDE-Rounded-Corners/master/screenshots/outlines.png) +![After](screenshots/shadows.png) # Contributions: diff --git a/screenshots/shadows.png b/screenshots/shadows.png new file mode 100644 index 0000000..603e9cc Binary files /dev/null and b/screenshots/shadows.png differ diff --git a/shaders_110/shapecorners.frag b/shaders_110/shapecorners.frag index 73561ff..a67b6d2 100644 --- a/shaders_110/shapecorners.frag +++ b/shaders_110/shapecorners.frag @@ -2,45 +2,33 @@ uniform sampler2D front; uniform float radius; -uniform bool windowActive; uniform bool windowHasDecoration; uniform vec2 windowSize; uniform vec2 windowExpandedSize; uniform vec2 windowTopLeft; uniform vec4 shadowColor; +uniform float shadowSize; uniform vec4 outlineColor; uniform float outlineThickness; +uniform vec4 modulation; +uniform float saturation; varying vec2 texcoord0; bool isDrawingShadows() { return windowHasDecoration && shadowColor.a > 0.0; } bool isDrawingOutline() { return outlineColor.a > 0.0 && outlineThickness > 0.0; } -bool isExtendedFrame(vec2 c) { - return c.x < -1.0 || c.x > windowSize.x+1.0 - || c.y < -1.0 || c.y > windowSize.y+1.0; -} -vec4 shadowCorner(float distance_from_center, bool isTopCorner) { - float r2 = radius * sqrt(2.0); - float percent; - if (windowActive) { - if (isTopCorner) - percent = (distance_from_center) / (r2 + 0.1*radius); - else - percent = (distance_from_center - 0.25*radius) / (r2 + 0.1*radius); - } - else { - if (isTopCorner) - percent = (distance_from_center + 0.55*radius) / (r2 + 0.5*radius); - else - percent = (distance_from_center) / (r2 + 0.1*radius); - } - return vec4(shadowColor.rgb, 1.0-percent); +vec4 shadowCorner(float distance_from_center) { + float percent = -distance_from_center/shadowSize + 1.0; + if (percent < 0.0) + return vec4(0.0, 0.0, 0.0, 0.0); + else + return vec4(shadowColor.rgb, percent); } -vec4 shapeCorner(vec2 coord0, vec4 tex, vec2 center, bool isTopCorner) { +vec4 shapeCorner(vec2 coord0, vec4 tex, vec2 center) { float distance_from_center = distance(coord0, center); - vec4 c = isDrawingShadows() ? shadowCorner(distance_from_center, isTopCorner) : vec4(0.0,0.0,0.0,0.0); + vec4 c = isDrawingShadows() ? shadowCorner(distance_from_center) : vec4(0.0,0.0,0.0,0.0); if(isDrawingOutline()) { vec4 outlineOverlay = vec4(mix(tex.rgb, outlineColor.rgb, outlineColor.a), 1.0); @@ -66,30 +54,27 @@ void main(void) vec2 coord0 = vec2(texcoord0.x * windowExpandedSize.x - windowTopLeft.x, (1.0-texcoord0.y)* windowExpandedSize.y - windowTopLeft.y); - if(!isExtendedFrame(coord0)) - { - if (coord0.y < radius - 1.0) { - if (coord0.x < radius - 1.0) - tex = shapeCorner(coord0, tex, vec2(radius-1.0, radius-1.0), true); - else if (coord0.x > windowSize.x - radius + 1.0) - tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius+1.0, radius-1.0), true); - else if (coord0.y < outlineThickness - 1.0) - tex.rgb = mix(tex.rgb, outlineColor.rgb, outlineColor.a); - } - else if (coord0.y > windowSize.y - radius) { - if (coord0.x < radius - 1.0) - tex = shapeCorner(coord0, tex, vec2(radius-1.0, windowSize.y - radius+1.0), false); - else if (coord0.x > windowSize.x - radius + 1.0) - tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius+1.0, windowSize.y - radius+1.0), false); - else if (coord0.y > windowSize.y - outlineThickness + 1.0) - tex.rgb = mix(tex.rgb, outlineColor.rgb, outlineColor.a); - } - else { - if (outlineColor.a > 0.0 && coord0.x < outlineThickness - 1.0) - tex.rgb = mix(tex.rgb, outlineColor.rgb, outlineColor.a); - else if (outlineColor.a > 0.0 && coord0.x > windowSize.x - outlineThickness + 1.0) - tex.rgb = mix(tex.rgb, outlineColor.rgb, outlineColor.a); - } + if (coord0.y < radius - 1.0) { + if (coord0.x < radius - 1.0) + tex = shapeCorner(coord0, tex, vec2(radius-1.0, radius-1.0)); + else if (coord0.x > windowSize.x - radius + 1.0) + tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius+1.0, radius-1.0)); + else if (coord0.y < outlineThickness - 1.0) + tex = shapeCorner(coord0, tex, vec2(coord0.x, radius-1.0)); + } + else if (coord0.y > windowSize.y - radius) { + if (coord0.x < radius - 1.0) + tex = shapeCorner(coord0, tex, vec2(radius-1.0, windowSize.y - radius+1.0)); + else if (coord0.x > windowSize.x - radius + 1.0) + tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius+1.0, windowSize.y - radius+1.0)); + else if (coord0.y > windowSize.y - outlineThickness + 1.0) + tex = shapeCorner(coord0, tex, vec2(coord0.x, windowSize.y - radius+1.0)); + } + else { + if (coord0.x < radius - 1.0) + tex = shapeCorner(coord0, tex, vec2(radius-1.0, coord0.y)); + else if (coord0.x > windowSize.x - radius + 1.0) + tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius+1.0, coord0.y)); } gl_FragColor = tex; diff --git a/shaders_140/shapecorners.frag b/shaders_140/shapecorners.frag index cc4e02f..f0e4dfb 100644 --- a/shaders_140/shapecorners.frag +++ b/shaders_140/shapecorners.frag @@ -2,46 +2,34 @@ uniform sampler2D front; uniform float radius; -uniform bool windowActive; uniform bool windowHasDecoration; uniform vec2 windowSize; uniform vec2 windowExpandedSize; uniform vec2 windowTopLeft; uniform vec4 shadowColor; +uniform float shadowSize; uniform vec4 outlineColor; uniform float outlineThickness; +uniform vec4 modulation; +uniform float saturation; in vec2 texcoord0; out vec4 fragColor; bool isDrawingShadows() { return windowHasDecoration && shadowColor.a > 0.0; } bool isDrawingOutline() { return outlineColor.a > 0.0 && outlineThickness > 0.0; } -bool isExtendedFrame(vec2 c) { - return c.x < -1 || c.x > windowSize.x+1 - || c.y < -1 || c.y > windowSize.y+1; -} -vec4 shadowCorner(float distance_from_center, bool isTopCorner) { - float r2 = radius * sqrt(2.0); - float percent; - if (windowActive) { - if (isTopCorner) - percent = (distance_from_center) / (r2 + 0.1*radius); - else - percent = (distance_from_center - 0.25*radius) / (r2 + 0.1*radius); - } - else { - if (isTopCorner) - percent = (distance_from_center + 0.55*radius) / (r2 + 0.5*radius); - else - percent = (distance_from_center) / (r2 + 0.1*radius); - } - return vec4(shadowColor.rgb, 1-percent); +vec4 shadowCorner(float distance_from_center) { + float percent = -distance_from_center/shadowSize + 1; + if(percent < 0) + return vec4(0,0,0,0); + else + return vec4(shadowColor.rgb, percent); } -vec4 shapeCorner(vec2 coord0, vec4 tex, vec2 center, bool isTopCorner) { +vec4 shapeCorner(vec2 coord0, vec4 tex, vec2 center) { float distance_from_center = distance(coord0, center); - vec4 c = isDrawingShadows() ? shadowCorner(distance_from_center, isTopCorner) : vec4(0,0,0,0); + vec4 c = isDrawingShadows() ? shadowCorner(distance_from_center) : vec4(0,0,0,0); if(isDrawingOutline()) { vec4 outlineOverlay = vec4(mix(tex.rgb, outlineColor.rgb, outlineColor.a), 1.0); @@ -67,31 +55,36 @@ void main(void) vec2 coord0 = vec2(texcoord0.x * windowExpandedSize.x - windowTopLeft.x, (1-texcoord0.y)* windowExpandedSize.y - windowTopLeft.y); - if(!isExtendedFrame(coord0)) - { - if (coord0.y < radius - 1) { - if (coord0.x < radius - 1) - tex = shapeCorner(coord0, tex, vec2(radius-1, radius-1), true); - else if (coord0.x > windowSize.x - radius + 1) - tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius+1, radius-1), true); - else if (coord0.y < outlineThickness - 1) - tex.rgb = mix(tex.rgb, outlineColor.rgb, outlineColor.a); - } - else if (coord0.y > windowSize.y - radius + 1) { - if (coord0.x < radius - 1) - tex = shapeCorner(coord0, tex, vec2(radius-1, windowSize.y - radius+1), false); - else if (coord0.x > windowSize.x - radius + 1) - tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius+1, windowSize.y - radius+1), false); - else if (coord0.y > windowSize.y - outlineThickness + 1) - tex.rgb = mix(tex.rgb, outlineColor.rgb, outlineColor.a); - } - else { - if (outlineColor.a > 0.0 && coord0.x < outlineThickness - 1) - tex.rgb = mix(tex.rgb, outlineColor.rgb, outlineColor.a); - else if (outlineColor.a > 0.0 && coord0.x > windowSize.x - outlineThickness + 1) - tex.rgb = mix(tex.rgb, outlineColor.rgb, outlineColor.a); - } + if (coord0.y < radius - 1) { + if (coord0.x < radius - 1) + tex = shapeCorner(coord0, tex, vec2(radius-1, radius-1)); + else if (coord0.x > windowSize.x - radius + 1) + tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius+1, radius-1)); + else if (coord0.y < outlineThickness - 1) + tex = shapeCorner(coord0, tex, vec2(coord0.x, radius-1)); + } + else if (coord0.y > windowSize.y - radius + 1) { + if (coord0.x < radius - 1) + tex = shapeCorner(coord0, tex, vec2(radius-1, windowSize.y - radius+1)); + else if (coord0.x > windowSize.x - radius + 1) + tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius+1, windowSize.y - radius+1)); + else if (coord0.y > windowSize.y - outlineThickness + 1) + tex = shapeCorner(coord0, tex, vec2(coord0.x, windowSize.y - radius+1)); + } + else { + if (coord0.x < radius - 1) + tex = shapeCorner(coord0, tex, vec2(radius-1, coord0.y)); + else if (coord0.x > windowSize.x - radius + 1) + tex = shapeCorner(coord0, tex, vec2(windowSize.x - radius+1, coord0.y)); + } + + if (saturation != 1.0) { + vec3 desaturated = tex.rgb * vec3( 0.30, 0.59, 0.11 ); + desaturated = vec3( dot( desaturated, tex.rgb )); + tex.rgb = tex.rgb * vec3( saturation ) + desaturated * vec3( 1.0 - saturation ); } + tex *= modulation; + tex.rgb *= tex.a; fragColor = tex; } diff --git a/shapecorners_config.cpp b/shapecorners_config.cpp index dcf3758..1665086 100644 --- a/shapecorners_config.cpp +++ b/shapecorners_config.cpp @@ -37,7 +37,6 @@ ShapeCornersConfig::ShapeCornersConfig(QWidget* parent, const QVariantList& args : KCModule(parent, args) , ui(new ConfigDialog(this)) { - setAboutData(new KAboutData("ShapeCorners","ShapeCorners", "git")); auto* layout = new QVBoxLayout(this); layout->addWidget(ui); setLayout(layout); @@ -51,10 +50,15 @@ ShapeCornersConfig::load() KCModule::load(); m_config.Load(); ui->roundness->setValue(m_config.m_size); + QColor shadowColor = m_config.m_shadowColor; ui->drawShadowEnabled->setChecked(shadowColor.alpha() > 0); shadowColor.setAlpha(255); - ui->shadowColor->setColor(shadowColor); + ui->activeShadowColor->setColor(m_config.m_shadowColor); + ui->inactiveShadowColor->setColor(m_config.m_inactiveShadowColor); + ui->activeShadowSize->setValue(m_config.m_shadowSize); + ui->inactiveShadowSize->setValue(m_config.m_inactiveShadowSize); + QColor outlineColor = m_config.m_outlineColor; QColor inactiveOutlineColor = m_config.m_inactiveOutlineColor; ui->drawOutlineEnabled->setChecked(outlineColor.alpha() > 0); @@ -69,8 +73,14 @@ ShapeCornersConfig::save() { KCModule::save(); m_config.m_size = ui->roundness->value(); - m_config.m_shadowColor = ui->shadowColor->color(); + + m_config.m_shadowColor = ui->activeShadowColor->color(); m_config.m_shadowColor.setAlpha(ui->drawShadowEnabled->isChecked()? 255: 0); + m_config.m_shadowSize = ui->activeShadowSize->value(); + m_config.m_inactiveShadowColor = ui->inactiveShadowColor->color(); + m_config.m_inactiveShadowColor.setAlpha(ui->drawShadowEnabled->isChecked()? 255: 0); + m_config.m_inactiveShadowSize = ui->inactiveShadowSize->value(); + m_config.m_outlineColor = ui->outlineColor->color(); m_config.m_inactiveOutlineColor = ui->inactiveOutlineColor->color(); if(!ui->drawOutlineEnabled->isChecked()){ @@ -91,11 +101,17 @@ void ShapeCornersConfig::defaults() { KCModule::defaults(); + m_config = ConfigModel(); ui->roundness->setValue(m_config.m_size); + QColor shadowColor = m_config.m_shadowColor; ui->drawShadowEnabled->setChecked(shadowColor.alpha() > 0); shadowColor.setAlpha(255); - ui->shadowColor->setColor(shadowColor); + ui->activeShadowColor->setColor(m_config.m_shadowColor); + ui->inactiveShadowColor->setColor(m_config.m_inactiveShadowColor); + ui->activeShadowSize->setValue(m_config.m_shadowSize); + ui->inactiveShadowSize->setValue(m_config.m_inactiveShadowSize); + QColor outlineColor = m_config.m_outlineColor; QColor inactiveOutlineColor = m_config.m_inactiveOutlineColor; ui->drawOutlineEnabled->setChecked(outlineColor.alpha() > 0); diff --git a/shapecorners_config.ui b/shapecorners_config.ui index 2787183..fa5a594 100644 --- a/shapecorners_config.ui +++ b/shapecorners_config.ui @@ -10,6 +10,12 @@ 305 + + + 400 + 0 + + Form @@ -29,7 +35,7 @@ 1 - 64 + 50 1 @@ -65,7 +71,7 @@ - + true @@ -105,10 +111,10 @@ - - true - - + + true + + @@ -118,7 +124,7 @@ - Corner Shadows + Shadows true @@ -130,14 +136,68 @@ Qt::AlignHCenter|Qt::AlignTop - + - Shadow Color + Active Window Shadow Color - + + + + + + 1 + + + 50 + + + Qt::Horizontal + + + + + + + 1 + + + 50 + + + Qt::Horizontal + + + + + + + Active Window Shadow Size + + + + + + + Inactive Window Shadow Size + + + + + + + Inactive Window Shadow Color + + + + + + + + + diff --git a/shapecorners_shader.cpp b/shapecorners_shader.cpp index 3fd56e3..1c38fb2 100644 --- a/shapecorners_shader.cpp +++ b/shapecorners_shader.cpp @@ -28,12 +28,12 @@ ShapeCornersShader::ShapeCornersShader(): // qDebug() << frag; if (m_shader->isValid()) { - m_shader_windowActive = m_shader->uniformLocation("windowActive"); m_shader_windowHasDecoration = m_shader->uniformLocation("windowHasDecoration"); m_shader_windowSize = m_shader->uniformLocation("windowSize"); m_shader_windowExpandedSize = m_shader->uniformLocation("windowExpandedSize"); m_shader_windowTopLeft = m_shader->uniformLocation("windowTopLeft"); m_shader_shadowColor = m_shader->uniformLocation("shadowColor"); + m_shader_shadowSize = m_shader->uniformLocation("shadowSize"); m_shader_radius = m_shader->uniformLocation("radius"); m_shader_outlineColor = m_shader->uniformLocation("outlineColor"); m_shader_outlineThickness = m_shader->uniformLocation("outlineThickness"); @@ -62,12 +62,12 @@ ShapeCornersShader::Bind(KWin::EffectWindow *w, const ConfigModel& config) const auto xy = QVector2D((w->frameGeometry().left() - w->expandedGeometry().left()), (w->frameGeometry().top() - w->expandedGeometry().top())); m_manager->pushShader(m_shader.get()); - m_shader->setUniform(m_shader_windowActive, isWindowActive(w)); m_shader->setUniform(m_shader_windowSize, QVector2D(w->frameGeometry().width(), w->frameGeometry().height())); m_shader->setUniform(m_shader_windowExpandedSize, QVector2D(w->expandedGeometry().width(), w->expandedGeometry().height())); m_shader->setUniform(m_shader_windowTopLeft, xy); m_shader->setUniform(m_shader_windowHasDecoration, w->hasDecoration()); - m_shader->setUniform(m_shader_shadowColor, w->frameGeometry() != w->expandedGeometry()? config.m_shadowColor: QColor(Qt::transparent)); + m_shader->setUniform(m_shader_shadowColor, isWindowActive(w) ? config.m_shadowColor: config.m_inactiveShadowColor); + m_shader->setUniform(m_shader_shadowSize, isWindowActive(w) ? config.m_shadowSize: config.m_inactiveShadowSize); m_shader->setUniform(m_shader_radius, config.m_size); m_shader->setUniform(m_shader_outlineColor, isWindowActive(w) ? config.m_outlineColor : config.m_inactiveOutlineColor); m_shader->setUniform(m_shader_outlineThickness, config.m_outlineThickness); diff --git a/shapecorners_shader.h b/shapecorners_shader.h index a4c9180..f9633f3 100644 --- a/shapecorners_shader.h +++ b/shapecorners_shader.h @@ -28,12 +28,12 @@ class ShapeCornersShader { private: std::unique_ptr m_shader; KWin::ShaderManager* m_manager; - int m_shader_windowActive = 0; int m_shader_windowSize = 0; int m_shader_windowExpandedSize = 0; int m_shader_windowTopLeft = 0; int m_shader_windowHasDecoration = 0; int m_shader_shadowColor = 0; + int m_shader_shadowSize = 0; int m_shader_radius = 0; int m_shader_outlineColor = 0; int m_shader_outlineThickness = 0;