Skip to content

Commit

Permalink
Merge pull request #230 from matinlotfali/109-second-outline
Browse files Browse the repository at this point in the history
Add second outline
  • Loading branch information
matinlotfali authored May 26, 2024
2 parents 3162c11 + eec07fd commit 9bc9d96
Show file tree
Hide file tree
Showing 10 changed files with 1,205 additions and 515 deletions.
2 changes: 2 additions & 0 deletions src/Effect.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ namespace ShapeCorners {

[[nodiscard]] int requestedEffectChainPosition() const override { return 99; }
[[nodiscard]] bool blocksDirectScanout() const override { return false; }
[[nodiscard]] bool isActive() const override { return m_shaderManager.IsValid(); }
[[nodiscard]] bool provides(Feature feature) override { return feature == Feature::Nothing; }

public Q_SLOTS:
[[nodiscard]] QString get_window_titles() const;
Expand Down
8 changes: 7 additions & 1 deletion src/Shader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ ShapeCorners::Shader::Shader():
const QString shaderFilePath = QStandardPaths::locate(QStandardPaths::GenericDataLocation,
QStringLiteral("kwin/shaders/shapecorners.frag"));
m_shader = m_manager->generateShaderFromFile(KWin::ShaderTrait::MapTexture, QString(), shaderFilePath);
if (!m_shader->isValid())
if (!m_shader->isValid()) {
qCritical() << "ShapeCorners: no valid shaders found! ShapeCorners will not work.";
return;
}

m_shader_hasRoundCorners = m_shader->uniformLocation("hasRoundCorners");
m_shader_windowSize = m_shader->uniformLocation("windowSize");
Expand All @@ -34,6 +36,8 @@ ShapeCorners::Shader::Shader():
m_shader_radius = m_shader->uniformLocation("radius");
m_shader_outlineColor = m_shader->uniformLocation("outlineColor");
m_shader_outlineThickness = m_shader->uniformLocation("outlineThickness");
m_shader_secondOutlineColor = m_shader->uniformLocation("secondOutlineColor");
m_shader_secondOutlineThickness = m_shader->uniformLocation("secondOutlineThickness");
m_shader_front = m_shader->uniformLocation("front");
qInfo() << "ShapeCorners: shaders loaded.";
}
Expand All @@ -55,9 +59,11 @@ void ShapeCorners::Shader::Bind(const ShapeCorners::Window &window, qreal scale)
m_shader->setUniform(m_shader_front, 0);
m_shader->setUniform(m_shader_radius, static_cast<float>(window.cornerRadius * scale));
m_shader->setUniform(m_shader_outlineThickness, static_cast<float>(window.outlineSize * scale));
m_shader->setUniform(m_shader_secondOutlineThickness, static_cast<float>(window.secondOutlineSize * scale));
auto shadowSize = std::min(window.shadowSize * scale, max_shadow_size);
m_shader->setUniform(m_shader_shadowSize, static_cast<float>(shadowSize));
m_shader->setUniform(m_shader_outlineColor, window.outlineColor.toQColor());
m_shader->setUniform(m_shader_secondOutlineColor, window.secondOutlineColor.toQColor());
m_shader->setUniform(m_shader_shadowColor, window.shadowColor.toQColor());
}

Expand Down
12 changes: 12 additions & 0 deletions src/Shader.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,18 @@ namespace ShapeCorners {
*/
int m_shader_outlineThickness = 0;

/**
* \brief Reference to `uniform vec4 secondOutlineColor;`
* Containing the RGBA of the outline color specified in settings.
*/
int m_shader_secondOutlineColor = 0;

/**
* \brief Reference to `uniform float secondOutlineThickness;`
* Containing the thickness of the outline in pixels specified in settings.
*/
int m_shader_secondOutlineThickness = 0;

/**
* \brief Reference to `uniform sampler2D front;`
* Containing the active texture. When assigned to zero, it will contain the painted contents of the window.
Expand Down
27 changes: 27 additions & 0 deletions src/Window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,16 @@ void ShapeCorners::Window::animateProperties(const std::chrono::milliseconds& ti
float configCornerRadius;
float configShadowSize;
float configOutlineSize;
float configSecondOutlineSize;
Color configShadowColor;
Color configOutlineColor;
Color configSecondOutlineColor;
const QPalette& m_palette = m_widget.palette();
if (isActive()) {
configCornerRadius = static_cast<float>(Config::size());
configShadowSize = static_cast<float>(Config::shadowSize());
configOutlineSize = static_cast<float>(Config::outlineThickness());
configSecondOutlineSize = static_cast<float>(Config::secondOutlineThickness());

configShadowColor = Color(Config::activeShadowUsePalette() ?
m_palette.color(QPalette::Active, static_cast<QPalette::ColorRole>(Config::activeShadowPalette())):
Expand All @@ -75,10 +78,16 @@ void ShapeCorners::Window::animateProperties(const std::chrono::milliseconds& ti
m_palette.color(QPalette::Active, static_cast<QPalette::ColorRole>(Config::activeOutlinePalette())):
Config::outlineColor());
configOutlineColor.setAlpha(hasOutline() ? Config::activeOutlineAlpha(): 0);

configSecondOutlineColor = Color(Config::activeSecondOutlineUsePalette() ?
m_palette.color(QPalette::Active, static_cast<QPalette::ColorRole>(Config::activeSecondOutlinePalette())):
Config::secondOutlineColor());
configSecondOutlineColor.setAlpha(hasOutline() ? Config::activeSecondOutlineAlpha(): 0);
} else {
configCornerRadius = static_cast<float>(Config::inactiveCornerRadius());
configShadowSize = static_cast<float>(Config::inactiveShadowSize());
configOutlineSize = static_cast<float>(Config::inactiveOutlineThickness());
configSecondOutlineSize = static_cast<float>(Config::inactiveSecondOutlineThickness());

configShadowColor = Color(Config::inactiveShadowUsePalette() ?
m_palette.color(QPalette::Inactive, static_cast<QPalette::ColorRole>(Config::inactiveShadowPalette())):
Expand All @@ -89,19 +98,27 @@ void ShapeCorners::Window::animateProperties(const std::chrono::milliseconds& ti
m_palette.color(QPalette::Inactive, static_cast<QPalette::ColorRole>(Config::inactiveOutlinePalette())):
Config::inactiveOutlineColor());
configOutlineColor.setAlpha(hasOutline() ? Config::inactiveOutlineAlpha(): 0);

configSecondOutlineColor = Color(Config::inactiveSecondOutlineUsePalette() ?
m_palette.color(QPalette::Inactive, static_cast<QPalette::ColorRole>(Config::inactiveSecondOutlinePalette())):
Config::inactiveSecondOutlineColor());
configSecondOutlineColor.setAlpha(hasOutline() ? Config::inactiveSecondOutlineAlpha(): 0);
}

// if the properties are not initialized yet, don't animate them.
if (!Config::animationEnabled()
|| cornerRadius == -1
|| shadowSize == -1
|| outlineSize == -1
|| secondOutlineSize == -1
) {
cornerRadius = configCornerRadius;
shadowSize = configShadowSize;
outlineSize = configOutlineSize;
secondOutlineSize = configSecondOutlineSize;
shadowColor = configShadowColor;
outlineColor = configOutlineColor;
secondOutlineColor = configSecondOutlineColor;
return;
}

Expand All @@ -114,22 +131,28 @@ void ShapeCorners::Window::animateProperties(const std::chrono::milliseconds& ti
auto deltaCornerRadius = (configCornerRadius - cornerRadius) / deltaTime;
auto deltaShadowSize = (configShadowSize - shadowSize) / deltaTime;
auto deltaOutlineSize = (configOutlineSize - outlineSize) / deltaTime;
auto deltaSecondOutlineSize = (configSecondOutlineSize - secondOutlineSize) / deltaTime;
auto deltaShadowColor = (configShadowColor - shadowColor) / deltaTime;
auto deltaOutlineColor = (configOutlineColor - outlineColor) / deltaTime;
auto deltaSecondOutlineColor = (configSecondOutlineColor - secondOutlineColor) / deltaTime;

// adjust decimal precision
deltaCornerRadius = std::round(deltaCornerRadius * 10) / 10;
deltaShadowSize = std::round(deltaShadowSize * 10) / 10;
deltaOutlineSize = std::round(deltaOutlineSize * 10) / 10;
deltaSecondOutlineSize = std::round(deltaSecondOutlineSize * 10) / 10;
deltaShadowColor.round();
deltaOutlineColor.round();
deltaSecondOutlineColor.round();

// return false if the animation is over
if (deltaCornerRadius == 0
&& deltaShadowSize == 0
&& deltaOutlineSize == 0
&& deltaSecondOutlineSize == 0
&& deltaShadowColor.isZero()
&& deltaOutlineColor.isZero()
&& deltaSecondOutlineColor.isZero()
) {
#ifdef QT_DEBUG
if (repaintCount > 0)
Expand All @@ -143,15 +166,19 @@ void ShapeCorners::Window::animateProperties(const std::chrono::milliseconds& ti
cornerRadius += deltaCornerRadius;
shadowSize += deltaShadowSize;
outlineSize += deltaOutlineSize;
secondOutlineSize += deltaSecondOutlineSize;
shadowColor += deltaShadowColor;
outlineColor += deltaOutlineColor;
secondOutlineColor += deltaSecondOutlineColor;

// check boundaries after adjusting
clamp(cornerRadius, deltaCornerRadius, configCornerRadius);
clamp(shadowSize, deltaShadowSize, configShadowSize);
clamp(outlineSize, deltaOutlineSize, configOutlineSize);
clamp(secondOutlineSize, deltaSecondOutlineSize, configSecondOutlineSize);
shadowColor.clamp();
outlineColor.clamp();
secondOutlineColor.clamp();

// the animation is still in progress
#ifdef QT_DEBUG
Expand Down
2 changes: 2 additions & 0 deletions src/Window.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ namespace ShapeCorners {
float cornerRadius = -1;
float shadowSize = -1;
float outlineSize = -1;
float secondOutlineSize = -1;
Color shadowColor = {};
Color outlineColor = {};
Color secondOutlineColor = {};

#ifdef QT_DEBUG
uint32_t repaintCount = 0;
Expand Down
56 changes: 49 additions & 7 deletions src/kcm/KCM.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
#include "KCM.h"
#include "ui_KCM.h"
#include "kwineffects_interface.h"
#include <QDialog>

#if (QT_VERSION_MAJOR >= 6)
ShapeCorners::KCM::KCM(QObject* parent, const KPluginMetaData& args)
: KCModule(parent, args)
, ui(new Ui::Form)
, config()
{
ui->setupUi(widget());
addConfig(&config, widget());
Expand All @@ -29,12 +27,14 @@ ShapeCorners::KCM::KCM(QWidget* parent, const QVariantList& args)
pix.fill(c);
QIcon icon (pix);
ui->kcfg_ActiveOutlinePalette->setItemIcon(index, icon);
ui->kcfg_ActiveSecondOutlinePalette->setItemIcon(index, icon);
ui->kcfg_ActiveShadowPalette->setItemIcon(index, icon);

c = palette().color(QPalette::Inactive, static_cast<QPalette::ColorRole>(index));
pix.fill(c);
QIcon icon2 (pix);
ui->kcfg_InactiveOutlinePalette->setItemIcon(index, icon2);
ui->kcfg_InactiveSecondOutlinePalette->setItemIcon(index, icon2);
ui->kcfg_InactiveShadowPalette->setItemIcon(index, icon2);
}

Expand All @@ -45,6 +45,13 @@ ShapeCorners::KCM::KCM(QWidget* parent, const QVariantList& args)
connect(ui->kcfg_ActiveOutlineUsePalette, &QRadioButton::toggled, this, &KCM::update_colors);
connect(ui->kcfg_InactiveOutlineUsePalette, &QRadioButton::toggled, this, &KCM::update_colors);

connect(ui->kcfg_ActiveSecondOutlinePalette, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &KCM::update_colors);
connect(ui->kcfg_InactiveSecondOutlinePalette, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &KCM::update_colors);
connect(ui->kcfg_SecondOutlineColor, &KColorButton::changed, this, &KCM::update_colors);
connect(ui->kcfg_InactiveSecondOutlineColor, &KColorButton::changed, this, &KCM::update_colors);
connect(ui->kcfg_ActiveSecondOutlineUsePalette, &QRadioButton::toggled, this, &KCM::update_colors);
connect(ui->kcfg_InactiveSecondOutlineUsePalette, &QRadioButton::toggled, this, &KCM::update_colors);

connect(ui->kcfg_ActiveShadowPalette, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &KCM::update_colors);
connect(ui->kcfg_ActiveShadowPalette, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &KCM::update_colors);
connect(ui->kcfg_ShadowColor, &KColorButton::changed, this, &KCM::update_colors);
Expand All @@ -58,6 +65,11 @@ ShapeCorners::KCM::KCM(QWidget* parent, const QVariantList& args)
connect(ui->kcfg_InactiveShadowAlpha, &KGradientSelector::sliderMoved, this, &KCM::markAsChanged);
connect(ui->kcfg_ActiveOutlineAlpha, &KGradientSelector::sliderMoved, this, &KCM::markAsChanged);
connect(ui->kcfg_InactiveOutlineAlpha, &KGradientSelector::sliderMoved, this, &KCM::markAsChanged);
connect(ui->kcfg_ActiveSecondOutlineAlpha, &KGradientSelector::sliderMoved, this, &KCM::markAsChanged);
connect(ui->kcfg_InactiveSecondOutlineAlpha, &KGradientSelector::sliderMoved, this, &KCM::markAsChanged);

connect(ui->primaryOutline, &QGroupBox::toggled, this, &KCM::outline_group_toggled);
connect(ui->secondaryOutline, &QGroupBox::toggled, this, &KCM::outline_group_toggled);

connect(ui->refreshButton, &QPushButton::pressed, this, &KCM::update_windows);
connect(ui->includeButton, &QPushButton::pressed, [=, this]() {
Expand Down Expand Up @@ -90,11 +102,12 @@ ShapeCorners::KCM::save()
QStringList inclusions, exclusions;
for (int i = 0; i < ui->InclusionList->count(); ++i)
inclusions.push_back(ui->InclusionList->item(i)->text());
config.setInclusions(inclusions);
for (int i = 0; i < ui->ExclusionList->count(); ++i)
exclusions.push_back(ui->ExclusionList->item(i)->text());

config.setInclusions(inclusions);
config.setExclusions(exclusions);

qDebug() << "ShapeCorners: Saving configurations";
config.save();
KCModule::save();

Expand All @@ -109,6 +122,8 @@ ShapeCorners::KCM::save()
// Maybe it is a bug on the KWin side. Need to check and delete these lines later.
interface.unloadEffect(dbusName);
interface.loadEffect(dbusName);

load();
}

void ShapeCorners::KCM::update_colors() {
Expand All @@ -126,6 +141,16 @@ void ShapeCorners::KCM::update_colors() {
color = checked ? palette().color(QPalette::Inactive, static_cast<QPalette::ColorRole>(index)): ui->kcfg_InactiveOutlineColor->color();
ui->kcfg_InactiveOutlineAlpha->setSecondColor(color);

checked = ui->kcfg_ActiveSecondOutlineUsePalette->isChecked();
index = ui->kcfg_ActiveSecondOutlinePalette->currentIndex();
color = checked ? palette().color(QPalette::Active, static_cast<QPalette::ColorRole>(index)): ui->kcfg_SecondOutlineColor->color();
ui->kcfg_ActiveSecondOutlineAlpha->setSecondColor(color);

checked = ui->kcfg_InactiveSecondOutlineUsePalette->isChecked();
index = ui->kcfg_InactiveSecondOutlinePalette->currentIndex();
color = checked ? palette().color(QPalette::Inactive, static_cast<QPalette::ColorRole>(index)): ui->kcfg_InactiveSecondOutlineColor->color();
ui->kcfg_InactiveSecondOutlineAlpha->setSecondColor(color);

checked = ui->kcfg_ActiveShadowUsePalette->isChecked();
index = ui->kcfg_ActiveShadowPalette->currentIndex();
color = checked ? palette().color(QPalette::Active, static_cast<QPalette::ColorRole>(index)): ui->kcfg_ShadowColor->color();
Expand All @@ -148,18 +173,35 @@ void ShapeCorners::KCM::update_windows() const {
ui->currentWindowList->addItems(windowList);
}

void ShapeCorners::KCM::outline_group_toggled(bool value) const {
if (sender() == ui->primaryOutline) {
ui->kcfg_OutlineThickness->setValue(value ? 0.75 : 0);
ui->kcfg_InactiveOutlineThickness->setValue(value ? 0.75 : 0);
} else if (sender() == ui->secondaryOutline) {
ui->kcfg_SecondOutlineThickness->setValue(value ? 0.75 : 0);
ui->kcfg_InactiveSecondOutlineThickness->setValue(value ? 0.75 : 0);
}
}

void ShapeCorners::KCM::load() {
KCModule::load();
config.load();
ui->InclusionList->addItems(config.inclusions());
ui->ExclusionList->addItems(config.exclusions());
load_ui();
}

void ShapeCorners::KCM::defaults() {
KCModule::defaults();
config.setDefaults();
load_ui();
}

void ShapeCorners::KCM::load_ui() const {
ui->InclusionList->clear();
ui->InclusionList->addItems(config.inclusions());
ui->ExclusionList->clear();

ui->InclusionList->addItems(config.inclusions());
ui->ExclusionList->addItems(config.exclusions());

ui->primaryOutline->setChecked(ui->kcfg_OutlineThickness->value() > 0);
ui->secondaryOutline->setChecked(ui->kcfg_SecondOutlineThickness->value() > 0);
}
8 changes: 5 additions & 3 deletions src/kcm/KCM.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ namespace Ui {
}

namespace ShapeCorners {
class Config;

class KCM final : public KCModule {
Q_OBJECT

Expand All @@ -26,13 +24,17 @@ namespace ShapeCorners {
void save() override;
void update_colors();
void update_windows() const;
void outline_group_toggled(bool value) const;

private:
std::shared_ptr<Ui::Form> ui;
Config config;

void load_ui() const;

#if (QT_VERSION_MAJOR >= 6)
const QPalette &palette() { return widget()->palette(); };
QWidget* widget() final override { return KCModule::widget(); }
const QPalette& palette() { return widget()->palette(); };
#endif
};
}
Loading

0 comments on commit 9bc9d96

Please sign in to comment.