1
0
mirror of https://github.com/KDE/latte-dock.git synced 2025-02-04 01:47:31 +03:00

provide effect/masks regions for custom backgrounds

--PlasmaExtended::Theme produces QRegions based on corners
radius that can be consumed afterwards from Effects calculations
in order to provide correct QRegions for custom backgrounds
produced from custom background radius option
This commit is contained in:
Michail Vourlakos 2020-08-22 01:22:08 +03:00
parent bd16a0da69
commit 1142950f69
6 changed files with 190 additions and 44 deletions

View File

@ -31,6 +31,7 @@
// Qt
#include <QDebug>
#include <QDir>
#include <QPainter>
#include <QProcess>
// KDE
@ -414,13 +415,74 @@ void Theme::loadThemeLightness()
}
}
const CornerRegions &Theme::cornersMask(const int &size)
const CornerRegions &Theme::cornersMask(const int &radius)
{
if (m_cornerRegions.contains(size)) {
return m_cornerRegions[size];
if (m_cornerRegions.contains(radius)) {
return m_cornerRegions[radius];
}
return m_cornerRegions[size];
qDebug() << radius;
CornerRegions corners;
int axis = (2 * radius) + 2;
QImage cornerimage(axis, axis, QImage::Format_ARGB32);
QPainter painter(&cornerimage);
//!does not provide valid masks
//painter.setRenderHints(QPainter::Antialiasing);
QPen pen(Qt::black);
pen.setStyle(Qt::SolidLine);
pen.setWidth(1);
painter.setPen(pen);
QRect rectArea(0,0,axis,axis);
painter.fillRect(rectArea, Qt::white);
painter.drawRoundedRect(rectArea, axis, axis);
QRegion topleft;
for(int y=0; y<radius; ++y) {
QRgb *line = (QRgb *)cornerimage.scanLine(y);
QString bits;
int width{0};
for(int x=0; x<radius; ++x) {
QRgb point = line[x];
if (QColor(point) == Qt::black) {
bits = bits + "1 ";
width = qMax(0, x);
break;
} else {
bits = bits + "0 ";
}
}
if (width>0) {
topleft += QRect(0, y, width, 1);
}
qDebug()<< " " << bits;
}
corners.topLeft = topleft;
QTransform transform;
transform.rotate(90);
corners.topRight = transform.map(corners.topLeft);
corners.topRight.translate(corners.topLeft.boundingRect().width(), 0);
corners.bottomRight = transform.map(corners.topRight);
corners.bottomRight.translate(corners.topLeft.boundingRect().width(), 0);
corners.bottomLeft = transform.map(corners.bottomRight);
corners.bottomLeft.translate(corners.topLeft.boundingRect().width(), 0);
//qDebug() << " reg top;: " << corners.topLeft;
//qDebug() << " reg topr: " << corners.topRight;
//qDebug() << " reg bottomr: " << corners.bottomRight;
//qDebug() << " reg bottoml: " << corners.bottomLeft;
m_cornerRegions[radius] = corners;
return m_cornerRegions[radius];
}
void Theme::loadConfig()

View File

@ -98,7 +98,7 @@ public:
WindowSystem::SchemeColors *lightTheme() const;
WindowSystem::SchemeColors *darkTheme() const;
const CornerRegions &cornersMask(const int &size);
const CornerRegions &cornersMask(const int &radius);
void load();

View File

@ -54,14 +54,19 @@ Effects::~Effects()
void Effects::init()
{
connect(this, &Effects::backgroundOpacityChanged, this, &Effects::updateEffects);
connect(this, &Effects::backgroundCornersMaskChanged, this, &Effects::updateEffects);
connect(this, &Effects::backgroundRadiusEnabledChanged, this, &Effects::updateEffects);
connect(this, &Effects::drawEffectsChanged, this, &Effects::updateEffects);
connect(this, &Effects::enabledBordersChanged, this, &Effects::updateEffects);
connect(this, &Effects::rectChanged, this, &Effects::updateEffects);
connect(this, &Effects::backgroundRadiusChanged, this, &Effects::updateBackgroundCorners);
connect(this, &Effects::backgroundCornersMaskChanged, this, &Effects::updateMask);
connect(this, &Effects::backgroundRadiusEnabledChanged, this, &Effects::updateMask);
connect(this, &Effects::subtractedMaskRegionsChanged, this, &Effects::updateMask);
connect(this, &Effects::unitedMaskRegionsChanged, this, &Effects::updateMask);
connect(this, &Effects::backgroundRadiusChanged, this, &Effects::updateBackgroundCorners);
connect(this, &Effects::drawShadowsChanged, this, [&]() {
if (m_view->behaveAsPlasmaPanel()) {
updateEnabledBorders();
@ -359,6 +364,39 @@ void Effects::removeUnitedMaskRegion(const QString &regionid)
emit unitedMaskRegionsChanged();
}
QRegion Effects::customMask(const QRect &rect)
{
QRegion result = rect;
int dx = rect.right() - m_cornersMaskRegion.topLeft.boundingRect().width() + 1;
int dy = rect.bottom() - m_cornersMaskRegion.topLeft.boundingRect().height() + 1;
if (m_hasTopLeftCorner) {
QRegion tl = m_cornersMaskRegion.topLeft;
tl.translate(rect.x(), rect.y());
result = result.subtracted(tl);
}
if (m_hasTopRightCorner) {
QRegion tr = m_cornersMaskRegion.topRight;
tr.translate(rect.x() + dx, rect.y());
result = result.subtracted(tr);
}
if (m_hasBottomRightCorner) {
QRegion br = m_cornersMaskRegion.bottomRight;
br.translate(rect.x() + dx, rect.y() + dy);
result = result.subtracted(br);
}
if (m_hasBottomLeftCorner) {
QRegion bl = m_cornersMaskRegion.bottomLeft;
bl.translate(rect.x(), rect.y() + dy);
result = result.subtracted(bl);
}
return result;
}
QRegion Effects::maskCombinedRegion()
{
QRegion region = m_mask;
@ -380,9 +418,10 @@ void Effects::updateBackgroundCorners()
return;
}
PlasmaExtended::CornerRegions corners = m_corona->themeExtended()->cornersMask(m_backgroundRadius);
m_corona->themeExtended()->cornersMask(m_backgroundRadius);
m_cornersMaskRegion = corners;
m_cornersMaskRegion = m_corona->themeExtended()->cornersMask(m_backgroundRadius);
emit backgroundCornersMaskChanged();
}
void Effects::updateMask()
@ -394,26 +433,35 @@ void Effects::updateMask()
m_view->setMask(maskCombinedRegion());
}
} else {
//! this is used when compositing is disabled and provides
//! the correct way for the mask to be painted in order for
//! rounded corners to be shown correctly
//! the enabledBorders check was added because there was cases
//! that the mask region wasn't calculated correctly after location changes
if (!m_background) {
if (m_background && m_background->enabledBorders() != m_enabledBorders) {
delete m_background;
QRegion fixedMask;
if (m_backgroundRadiusEnabled) {
//! CustomBackground way
fixedMask = customMask(QRect(0,0,m_mask.width(), m_mask.height()));
} else {
//! Plasma::Theme way
//! this is used when compositing is disabled and provides
//! the correct way for the mask to be painted in order for
//! rounded corners to be shown correctly
//! the enabledBorders check was added because there was cases
//! that the mask region wasn't calculated correctly after location changes
if (!m_background) {
if (m_background && m_background->enabledBorders() != m_enabledBorders) {
delete m_background;
}
m_background = new Plasma::FrameSvg(this);
}
m_background = new Plasma::FrameSvg(this);
if (m_background->imagePath() != "widgets/panel-background") {
m_background->setImagePath(QStringLiteral("widgets/panel-background"));
}
m_background->setEnabledBorders(m_enabledBorders);
m_background->resizeFrame(m_mask.size());
fixedMask = m_background->mask();
}
if (m_background->imagePath() != "widgets/panel-background") {
m_background->setImagePath(QStringLiteral("widgets/panel-background"));
}
m_background->setEnabledBorders(m_enabledBorders);
m_background->resizeFrame(m_mask.size());
QRegion fixedMask = m_background->mask();
fixedMask.translate(m_mask.x(), m_mask.y());
//! fix for KF5.32 that return empty QRegion's for the mask
@ -452,30 +500,34 @@ void Effects::updateEffects()
if (m_drawEffects) {
if (!m_view->behaveAsPlasmaPanel()) {
if (!m_rect.isNull() && !m_rect.isEmpty()) {
//! this is used when compositing is disabled and provides
//! the correct way for the mask to be painted in order for
//! rounded corners to be shown correctly
if (!m_background) {
m_background = new Plasma::FrameSvg(this);
QRegion backMask;
if (m_backgroundRadiusEnabled) {
//! CustomBackground way
backMask = customMask(QRect(0,0,m_rect.width(), m_rect.height()));
} else {
//! Plasma::Theme way
//! this is used when compositing is disabled and provides
//! the correct way for the mask to be painted in order for
//! rounded corners to be shown correctly
if (!m_background) {
m_background = new Plasma::FrameSvg(this);
}
if (m_background->imagePath() != "widgets/panel-background") {
m_background->setImagePath(QStringLiteral("widgets/panel-background"));
}
m_background->setEnabledBorders(m_enabledBorders);
m_background->resizeFrame(m_rect.size());
backMask = m_background->mask();
}
if (m_background->imagePath() != "widgets/panel-background") {
m_background->setImagePath(QStringLiteral("widgets/panel-background"));
}
m_background->setEnabledBorders(m_enabledBorders);
m_background->resizeFrame(m_rect.size());
QRegion backMask = m_background->mask();
//! There are cases that mask is NULL even though it should not
//! Example: SidebarOnDemand from v0.10 that BEHAVEASPLASMAPANEL in EditMode
//! switching multiple times between inConfigureAppletsMode and LiveEditMode
//! is such a case
QRegion fixedMask;
//! adjust mask coordinates based on local coordinates
int fX = m_rect.x(); int fY = m_rect.y();
#if KF5_VERSION_MINOR >= 65
//! Latte is now using GtkFrameExtents so Effects geometries must be adjusted
//! windows that use GtkFrameExtents and apply Effects on them they take GtkFrameExtents
@ -489,6 +541,12 @@ void Effects::updateEffects()
}
#endif
//! There are cases that mask is NULL even though it should not
//! Example: SidebarOnDemand from v0.10 that BEHAVEASPLASMAPANEL in EditMode
//! switching multiple times between inConfigureAppletsMode and LiveEditMode
//! is such a case
QRegion fixedMask;
if (!backMask.isNull()) {
fixedMask = backMask;
fixedMask.translate(fX, fY);
@ -633,6 +691,11 @@ void Effects::updateEnabledBorders()
}
}
m_hasTopLeftCorner = (borders == Plasma::FrameSvg::AllBorders) || ((borders & Plasma::FrameSvg::TopBorder) && (borders & Plasma::FrameSvg::LeftBorder));
m_hasTopRightCorner = (borders == Plasma::FrameSvg::AllBorders) || ((borders & Plasma::FrameSvg::TopBorder) && (borders & Plasma::FrameSvg::RightBorder));
m_hasBottomLeftCorner = (borders == Plasma::FrameSvg::AllBorders) || ((borders & Plasma::FrameSvg::BottomBorder) && (borders & Plasma::FrameSvg::LeftBorder));
m_hasBottomRightCorner = (borders == Plasma::FrameSvg::AllBorders) || ((borders & Plasma::FrameSvg::BottomBorder) && (borders & Plasma::FrameSvg::RightBorder));
if (m_enabledBorders != borders) {
m_enabledBorders = borders;
emit enabledBordersChanged();

View File

@ -149,6 +149,7 @@ private slots:
private:
bool backgroundRadiusIsEnabled() const;
qreal currentMidValue(const qreal &max, const qreal &factor, const qreal &min) const;
QRegion customMask(const QRect &rect);
QRegion maskCombinedRegion();
private:
@ -160,6 +161,11 @@ private:
bool m_forceTopBorder{false};
bool m_forceBottomBorder{false};
bool m_hasTopLeftCorner{false};
bool m_hasTopRightCorner{false};
bool m_hasBottomLeftCorner{false};
bool m_hasBottomRightCorner{false};
int m_editShadow{0};
int m_innerShadow{0};

View File

@ -281,6 +281,20 @@ Item{
&& !root.hideLengthScreenGaps))
}
Binding{
target: latteView && latteView.effects ? latteView.effects : null
property: "backgroundRadius"
when: latteView && latteView.effects
value: background.customRadius
}
Binding{
target: latteView && latteView.effects ? latteView.effects : null
property: "backgroundRadiusEnabled"
when: latteView && latteView.effects
value: background.customRadiusIsEnabled
}
Binding{
target: latteView && latteView.effects ? latteView.effects : null
property: "backgroundOpacity"

View File

@ -968,6 +968,7 @@ PlasmaComponents.Page {
RowLayout {
Layout.minimumWidth: dialog.optionsWidth
Layout.maximumWidth: Layout.minimumWidth
enabled: LatteCore.WindowSystem.compositingActive
visible: dialog.kirigamiLibraryIsFound
PlasmaComponents.Label {