diff -Naru a/breeze-v5.27.10/CMakeLists.txt b/breeze-v5.27.10/CMakeLists.txt --- a/breeze-v5.27.10/CMakeLists.txt 2023-12-06 05:36:15.000000000 +1030 +++ b/breeze-v5.27.10/CMakeLists.txt 2024-02-17 09:40:46.575421655 +1030 @@ -24,59 +24,21 @@ include(KDECompilerSettings NO_POLICY_SCOPE) include(KDEClangFormat) include(KDEGitCommitHooks) +include(ECMGenerateHeaders) +include(ECMGeneratePkgConfigFile) include(GtkUpdateIconCache) -option(WITH_DECORATIONS "Build Breeze window decorations for KWin" ON) - -if(WIN32 OR APPLE) - set(WITH_DECORATIONS OFF) -endif() - find_package(KF5KCMUtils ${KF5_MIN_VERSION} REQUIRED) -if(WITH_DECORATIONS) - find_package(KDecoration2 REQUIRED) - add_subdirectory(kdecoration) -endif() +find_package(KDecoration2 REQUIRED) +add_subdirectory(kdecoration) -add_subdirectory(colors) -add_subdirectory(cursors) add_subdirectory(libbreezecommon) -add_subdirectory(kstyle) -add_subdirectory(misc) - -option(WITH_WALLPAPERS "Install Breeze default wallpapers" ON) -if (WITH_WALLPAPERS) - add_subdirectory(wallpapers) -endif() find_package(KF5I18n ${KF5_MIN_VERSION} CONFIG REQUIRED) -ki18n_install(po) +#ki18n_install(po) include(ECMSetupVersion) -ecm_setup_version(${PROJECT_VERSION} VARIABLE_PREFIX BREEZE - PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/BreezeConfigVersion.cmake" - ) - -# create a Config.cmake and a ConfigVersion.cmake file and install them -set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/Breeze") - -configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/BreezeConfig.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/BreezeConfig.cmake" - PATH_VARS KDE_INSTALL_FULL_DATADIR - INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} - ) - -# add clang-format target for all our real source files -file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h) -kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES}) -kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT) - -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/BreezeConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/BreezeConfigVersion.cmake" - DESTINATION "${CMAKECONFIG_INSTALL_DIR}" - COMPONENT Devel - ) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff -Naru a/breeze-v5.27.10/kdecoration/breezebutton.cpp b/breeze-v5.27.10/kdecoration/breezebutton.cpp --- a/breeze-v5.27.10/kdecoration/breezebutton.cpp 2023-12-06 05:36:15.000000000 +1030 +++ b/breeze-v5.27.10/kdecoration/breezebutton.cpp 2024-02-17 09:40:46.575421655 +1030 @@ -24,6 +24,7 @@ Button::Button(DecorationButtonType type, Decoration *decoration, QObject *parent) : DecorationButton(type, decoration, parent) , m_animation(new QVariantAnimation(this)) + , m_hoverProgress(0.0) { // setup animation // It is important start and end value are of the same type, hence 0.0 and not just 0 @@ -34,16 +35,42 @@ setOpacity(value.toReal()); }); + int width = 27; + int height = 20; + + switch (type) + { + case DecorationButtonType::Minimize: + width = 29; + break; + case DecorationButtonType::Maximize: + width = 27; + break; + case DecorationButtonType::Close: + width = 49; + break; + case DecorationButtonType::Menu: + width = 16; + height = 20; + break; + default: + break; + } + // setup default geometry - const int height = decoration->buttonHeight(); - setGeometry(QRect(0, 0, height, height)); - setIconSize(QSize(height, height)); + //const int height = decoration->buttonHeight(); + setGeometry(QRect(0, 0, width, height)); + setIconSize(QSize(width, height)); + + const auto c = decoration->client().toStrongRef(); // connections - connect(decoration->client().toStrongRef().data(), SIGNAL(iconChanged(QIcon)), this, SLOT(update())); + connect(c.data(), SIGNAL(iconChanged(QIcon)), this, SLOT(update())); connect(decoration->settings().data(), &KDecoration2::DecorationSettings::reconfigured, this, &Button::reconfigure); connect(this, &KDecoration2::DecorationButton::hoveredChanged, this, &Button::updateAnimationState); + connect(this, &Button::buttonHoverStatus, decoration, &Decoration::buttonHoverStatus); + reconfigure(); } @@ -65,18 +92,45 @@ const auto c = d->client().toStrongRef(); switch (type) { case DecorationButtonType::Close: - b->setVisible(c->isCloseable()); - QObject::connect(c.data(), &KDecoration2::DecoratedClient::closeableChanged, b, &Breeze::Button::setVisible); + b->setVisible(true); + //b->setVisible(c->isCloseable()); + //QObject::connect(c.data(), &KDecoration2::DecoratedClient::closeableChanged, b, &Breeze::Button::setVisible); break; case DecorationButtonType::Maximize: - b->setVisible(c->isMaximizeable()); - QObject::connect(c.data(), &KDecoration2::DecoratedClient::maximizeableChanged, b, &Breeze::Button::setVisible); + b->setVisible(c->isMaximizeable() || c->isMinimizeable()); + b->setEnabled(c->isMaximizeable()); + QObject::connect(c.data(), &KDecoration2::DecoratedClient::maximizeableChanged, b, + [b](bool maximizeable) { + auto d = qobject_cast(b->decoration()); + const auto c = d->client().toStrongRef(); + + if (!c) + { + return; + } + + b->setVisible(c->isMaximizeable() || c->isMinimizeable()); + b->setEnabled(maximizeable); + }); break; case DecorationButtonType::Minimize: - b->setVisible(c->isMinimizeable()); - QObject::connect(c.data(), &KDecoration2::DecoratedClient::minimizeableChanged, b, &Breeze::Button::setVisible); + b->setVisible(c->isMinimizeable() || c->isMaximizeable()); + b->setEnabled(c->isMinimizeable()); + QObject::connect(c.data(), &KDecoration2::DecoratedClient::minimizeableChanged, b, + [b](bool minimizeable) { + auto d = qobject_cast(b->decoration()); + const auto c = d->client().toStrongRef(); + + if (!c) + { + return; + } + + b->setVisible(c->isMinimizeable() || c->isMaximizeable()); + b->setEnabled(minimizeable); + }); break; case DecorationButtonType::ContextHelp: @@ -105,9 +159,296 @@ return nullptr; } +static QImage hoverImage(const QImage &image, const QImage &hoverImage, qreal hoverProgress) +{ + if (hoverProgress <= 0.5 / 256) + { + return image; + } + + if (hoverProgress >= 1.0 - 0.5 / 256) + { + return hoverImage; + } + + QImage result = image; + QImage over = hoverImage; + QColor alpha = Qt::black; + alpha.setAlphaF(hoverProgress); + QPainter p; + p.begin(&over); + p.setCompositionMode(QPainter::CompositionMode_DestinationIn); + p.fillRect(image.rect(), alpha); + p.end(); + p.begin(&result); + p.setCompositionMode(QPainter::CompositionMode_DestinationOut); + p.fillRect(image.rect(), alpha); + p.setCompositionMode(QPainter::CompositionMode_Plus); + p.drawImage(0, 0, over); + p.end(); + + return result; +} + +void Button::smodPaint(QPainter *painter, const QRect &repaintRegion) +{ + Q_UNUSED(repaintRegion) + + if (!decoration()) { + return; + } + + painter->save(); + + // translate from offset + if (m_flag == FlagFirstInList) { + painter->translate(m_offset); + } else { + painter->translate(0, m_offset.y()); + } + + if (!m_iconSize.isValid() || isStandAlone()) { + m_iconSize = geometry().size().toSize(); + } + + // menu button + if (type() == DecorationButtonType::Menu) { + const QRectF iconRect(geometry().topLeft(), m_iconSize); + const auto c = decoration()->client().toStrongRef(); + if (auto deco = qobject_cast(decoration())) { + const QPalette activePalette = KIconLoader::global()->customPalette(); + QPalette palette = c->palette(); + palette.setColor(QPalette::WindowText, deco->fontColor()); + KIconLoader::global()->setCustomPalette(palette); + c->icon().paint(painter, iconRect.toRect()); + if (activePalette == QPalette()) { + KIconLoader::global()->resetPalette(); + } else { + KIconLoader::global()->setCustomPalette(palette); + } + } else { + c->icon().paint(painter, iconRect.toRect()); + } + + } else if (type() == DecorationButtonType::Close || type() == DecorationButtonType::Maximize || type() == DecorationButtonType::Minimize) { + QRectF g = geometry(); + qreal w = g.width(); + qreal h = g.height(); + const auto c = decoration()->client().toStrongRef(); + + painter->translate(g.topLeft()); + + auto d = qobject_cast(decoration()); + + QPixmap normal, hover, active, glyph, glyphHover, glyphActive; + + QPoint glyphOffset; + + switch (type()) + { + case DecorationButtonType::Minimize: + glyphOffset = QPoint(10, 9); + + if (c->isActive()) + { + glyph = QPixmap(":/smod/decoration/minimize-glyph"); + glyphHover = QPixmap(":/smod/decoration/minimize-hover-glyph"); + glyphActive = QPixmap(":/smod/decoration/minimize-active-glyph"); + + normal = QPixmap(":/smod/decoration/minimize"); + hover = QPixmap(":/smod/decoration/minimize-hover"); + active = QPixmap(":/smod/decoration/minimize-active"); + } + else + { + glyph = QPixmap(":/smod/decoration/minimize-glyph"); + glyphHover = QPixmap(":/smod/decoration/minimize-hover-glyph"); + glyphActive = QPixmap(":/smod/decoration/minimize-active-glyph"); + + normal = QPixmap(":/smod/decoration/minimize-unfocus"); + hover = QPixmap(":/smod/decoration/minimize-unfocus-hover"); + active = QPixmap(":/smod/decoration/minimize-unfocus-active"); + } + + if (!isEnabled()) + { + glyph = QPixmap(":/smod/decoration/minimize-inactive-glyph"); + } + break; + case DecorationButtonType::Maximize: + if (d && d->isMaximized()) + { + glyphOffset = QPoint(7, 3); + + if (c->isActive()) + { + glyph = QPixmap(":/smod/decoration/restore-glyph"); + glyphHover = QPixmap(":/smod/decoration/restore-hover-glyph"); + glyphActive = QPixmap(":/smod/decoration/restore-active-glyph"); + + normal = QPixmap(":/smod/decoration/maximize"); + hover = QPixmap(":/smod/decoration/maximize-hover"); + active = QPixmap(":/smod/decoration/maximize-active"); + } + else + { + glyph = QPixmap(":/smod/decoration/restore-glyph"); + glyphHover = QPixmap(":/smod/decoration/restore-hover-glyph"); + glyphActive = QPixmap(":/smod/decoration/restore-active-glyph"); + + normal = QPixmap(":/smod/decoration/maximize-unfocus"); + hover = QPixmap(":/smod/decoration/maximize-unfocus-hover"); + active = QPixmap(":/smod/decoration/maximize-unfocus-active"); + } + } + else + { + glyphOffset = QPoint(8, 4); + + if (c->isActive()) + { + glyph = QPixmap(":/smod/decoration/maximize-glyph"); + glyphHover = QPixmap(":/smod/decoration/maximize-hover-glyph"); + glyphActive = QPixmap(":/smod/decoration/maximize-active-glyph"); + + normal = QPixmap(":/smod/decoration/maximize"); + hover = QPixmap(":/smod/decoration/maximize-hover"); + active = QPixmap(":/smod/decoration/maximize-active"); + } + else + { + glyph = QPixmap(":/smod/decoration/maximize-glyph"); + glyphHover = QPixmap(":/smod/decoration/maximize-hover-glyph"); + glyphActive = QPixmap(":/smod/decoration/maximize-active-glyph"); + + normal = QPixmap(":/smod/decoration/maximize-unfocus"); + hover = QPixmap(":/smod/decoration/maximize-unfocus-hover"); + active = QPixmap(":/smod/decoration/maximize-unfocus-active"); + } + } + + if (!isEnabled()) + { + glyph = QPixmap(":/smod/decoration/maximize-inactive-glyph"); + } + break; + case DecorationButtonType::Close: + glyphOffset = QPoint(19, 4); + + if (c->isActive()) + { + glyph = QPixmap(":/smod/decoration/close-glyph"); + glyphHover = QPixmap(":/smod/decoration/close-hover-glyph"); + glyphActive = QPixmap(":/smod/decoration/close-active-glyph"); + + normal = QPixmap(":/smod/decoration/close"); + hover = QPixmap(":/smod/decoration/close-hover"); + active = QPixmap(":/smod/decoration/close-active"); + } + else + { + glyph = QPixmap(":/smod/decoration/close-glyph"); + glyphHover = QPixmap(":/smod/decoration/close-hover-glyph"); + glyphActive = QPixmap(":/smod/decoration/close-active-glyph"); + + normal = QPixmap(":/smod/decoration/close-unfocus"); + hover = QPixmap(":/smod/decoration/close-unfocus-hover"); + active = QPixmap(":/smod/decoration/close-unfocus-active"); + } + + if (!isEnabled()) + { + glyph = QPixmap(":/smod/decoration/close-inactive-glyph"); + } + break; + default: + break; + } + + QImage image, hImage, aImage; + image = normal.toImage(); + hImage = hover.toImage(); + aImage = active.toImage(); + + if (!isPressed()) + { + image = hoverImage(image, hImage, m_hoverProgress); + + painter->drawImage(QRectF(0, 0, w, h), image); + painter->drawPixmap(glyphOffset, glyph); + } + else + { + painter->drawImage(QRectF(0, 0, w, h), aImage); + painter->drawPixmap(glyphOffset, glyphActive); + } + } else { + drawIcon(painter); + } + + painter->restore(); +} + +void Button::smodPaintGlow(QPainter *painter, const QRect &repaintArea) +{ + return; + + if (m_hoverProgress > 0.0 && isVisible() && type() != KDecoration2::DecorationButtonType::Menu) { + //Decoration *decoration = static_cast(KDecoration2::DecorationButton::decoration().data()); + //KDecoration2::DecoratedClient *client = decoration->client().data(); + //DecorationFactory *decorationFactory =decoration->factory(); + //window_settings *ws = decorationFactory->windowSettings(); + //const bool active = client->isActive(); + + QRect rect = geometry().toRect(); + //int glyph = decoration->buttonGlyph(type()); + //if (glyph == -1) { + // return; + //} + QImage image; + QPoint xy; + + switch (type()) + { + case DecorationButtonType::Minimize: + image = QImage(":/smod/decoration/minimize-glow"); + xy = QPoint(-10, -9); + break; + case DecorationButtonType::Maximize: + image = QImage(":/smod/decoration/maximize-glow"); + xy = QPoint(-10, -9); + break; + case DecorationButtonType::Close: + image = QImage(":/smod/decoration/close-glow"); + xy = QPoint(-10, -9); + break; + default: + return; + } + + //if (active && ws->use_button_glow) { + // image = ws->ButtonGlowPix[glyph]->image; + //} else if (!active && ws->use_button_inactive_glow) { + // image = ws->ButtonInactiveGlowPix[glyph]->image; + //} + if (!image.isNull()) { // && ws->use_pixmap_buttons) { + QImage buttonImage = image; + //QImage buttonImage = ws->ButtonPix[glyph * S_COUNT]->image; + painter->setOpacity(m_hoverProgress); + const int xp = rect.x(); //rect.x() + (buttonImage.width() - ws->c_glow_size.w) / 2; + const int yp = rect.y(); //rect.y() + (buttonImage.height() - ws->c_glow_size.h) / 2; + painter->drawImage(QPoint(xp, yp) + xy, image); + } + } +} + //__________________________________________________________________ void Button::paint(QPainter *painter, const QRect &repaintRegion) { + smodPaint(painter, repaintRegion); + + return; + Q_UNUSED(repaintRegion) if (!decoration()) { @@ -386,6 +727,11 @@ if (d) { m_animation->setDuration(d->animationsDuration()); } + + if (type() == DecorationButtonType::Menu) + { + setVisible(!d->hideIcon()); + } } //__________________________________________________________________ @@ -402,4 +748,71 @@ } } +void Button::hoverEnterEvent(QHoverEvent *event) +{ + KDecoration2::DecorationButton::hoverEnterEvent(event); + + if (isHovered()) + { + Q_EMIT buttonHoverStatus(type(), true, geometry().topLeft().toPoint()); + startHoverAnimation(1.0); + } +} + +void Button::hoverLeaveEvent(QHoverEvent *event) +{ + KDecoration2::DecorationButton::hoverLeaveEvent(event); + + if (!isHovered()) + { + Q_EMIT buttonHoverStatus(type(), false, geometry().topLeft().toPoint()); + startHoverAnimation(0.0); + } +} + +qreal Button::hoverProgress() const +{ + return m_hoverProgress; +} + +void Button::setHoverProgress(qreal hoverProgress) +{ + if (m_hoverProgress != hoverProgress) + { + m_hoverProgress = hoverProgress; + + if (qobject_cast(decoration())) + { + update(geometry().adjusted(-32, -32, 32, 32)); + } + } +} + +void Button::startHoverAnimation(qreal endValue) +{ + QPropertyAnimation *hoverAnimation = m_hoverAnimation.data(); + + if (hoverAnimation) + { + if (hoverAnimation->endValue() == endValue) + { + return; + } + + hoverAnimation->stop(); + } else if (m_hoverProgress != endValue) + { + hoverAnimation = new QPropertyAnimation(this, "hoverProgress"); + m_hoverAnimation = hoverAnimation; + } else { + return; + } + + hoverAnimation->setEasingCurve(QEasingCurve::OutQuad); + hoverAnimation->setStartValue(m_hoverProgress); + hoverAnimation->setEndValue(endValue); + hoverAnimation->setDuration(1 + qRound(200 * qAbs(m_hoverProgress - endValue))); + hoverAnimation->start(); +} + } // namespace diff -Naru a/breeze-v5.27.10/kdecoration/breezebutton.h b/breeze-v5.27.10/kdecoration/breezebutton.h --- a/breeze-v5.27.10/kdecoration/breezebutton.h 2023-12-06 05:36:15.000000000 +1030 +++ b/breeze-v5.27.10/kdecoration/breezebutton.h 2024-02-17 09:40:46.575421655 +1030 @@ -11,7 +11,9 @@ #include #include -#include +#include +#include +#include class QVariantAnimation; @@ -21,6 +23,8 @@ { Q_OBJECT + Q_PROPERTY(qreal hoverProgress READ hoverProgress WRITE setHoverProgress); + public: //* constructor explicit Button(QObject *parent, const QVariantList &args); @@ -96,6 +100,18 @@ //@} + qreal hoverProgress() const; + void setHoverProgress(qreal hoverProgress); + + void smodPaintGlow(QPainter *painter, const QRect &repaintArea); + +signals: + void buttonHoverStatus(KDecoration2::DecorationButtonType button, bool hovered, QPoint pos); + +protected: + virtual void hoverEnterEvent(QHoverEvent *event) override; + virtual void hoverLeaveEvent(QHoverEvent *event) override; + private Q_SLOTS: //* apply configuration changes @@ -108,6 +124,10 @@ //* private constructor explicit Button(KDecoration2::DecorationButtonType type, Decoration *decoration, QObject *parent = nullptr); + void startHoverAnimation(qreal endValue); + + void smodPaint(QPainter *painter, const QRect &repaintRegion); + //* draw button icon void drawIcon(QPainter *) const; @@ -130,6 +150,9 @@ //* active state change opacity qreal m_opacity = 0; + + QPointer m_hoverAnimation; + qreal m_hoverProgress; }; } // namespace diff -Naru a/breeze-v5.27.10/kdecoration/breezedecoration.cpp b/breeze-v5.27.10/kdecoration/breezedecoration.cpp --- a/breeze-v5.27.10/kdecoration/breezedecoration.cpp 2023-12-06 05:36:15.000000000 +1030 +++ b/breeze-v5.27.10/kdecoration/breezedecoration.cpp 2024-02-17 09:40:46.575421655 +1030 @@ -28,14 +28,20 @@ #include #include #include +#include #include #include +#include #include #include #include -K_PLUGIN_FACTORY_WITH_JSON(BreezeDecoFactory, "breeze.json", registerPlugin(); registerPlugin(); +#include "smod/qgraphicsgloweffect.h" + +#define INNER_BORDER_SIZE 2 + +K_PLUGIN_FACTORY_WITH_JSON(BreezeDecoFactory, "smod.json", registerPlugin(); registerPlugin(); registerPlugin();) namespace @@ -160,6 +166,8 @@ //________________________________________________________________ QColor Decoration::titleBarColor() const { + return QColor(Qt::transparent); + const auto c = client().toStrongRef(); if (hideTitleBar()) { return c->color(ColorGroup::Inactive, ColorRole::TitleBar); @@ -184,6 +192,8 @@ //________________________________________________________________ void Decoration::init() { + QResource::registerResource(QDir::homePath() + "/.local/share/smod/decoration.smod.rcc"); + const auto c = client().toStrongRef(); // active state change animation @@ -267,13 +277,18 @@ connect(c.data(), &KDecoration2::DecoratedClient::activeChanged, this, &Decoration::updateAnimationState); connect(c.data(), &KDecoration2::DecoratedClient::widthChanged, this, &Decoration::updateTitleBar); connect(c.data(), &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::updateTitleBar); - connect(c.data(), &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::setOpaque); + //connect(c.data(), &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::setOpaque); connect(c.data(), &KDecoration2::DecoratedClient::widthChanged, this, &Decoration::updateButtonsGeometry); connect(c.data(), &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::updateButtonsGeometry); connect(c.data(), &KDecoration2::DecoratedClient::adjacentScreenEdgesChanged, this, &Decoration::updateButtonsGeometry); connect(c.data(), &KDecoration2::DecoratedClient::shadedChanged, this, &Decoration::updateButtonsGeometry); + connect(c.data(), &KDecoration2::DecoratedClient::widthChanged, this, &Decoration::updateBlur); + connect(c.data(), &KDecoration2::DecoratedClient::heightChanged, this, &Decoration::updateBlur); + connect(c.data(), &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::updateBlur); + connect(c.data(), &KDecoration2::DecoratedClient::shadedChanged, this, &Decoration::updateBlur); + createButtons(); updateShadow(); } @@ -356,7 +371,7 @@ case KDecoration2::BorderSize::Tiny: return bottom ? qMax(4, baseSize) : baseSize; case KDecoration2::BorderSize::Normal: - return baseSize * 2; + return baseSize * 4; case KDecoration2::BorderSize::Large: return baseSize * 3; case KDecoration2::BorderSize::VeryLarge: @@ -374,6 +389,8 @@ //________________________________________________________________ void Decoration::reconfigure() { + QResource::registerResource(QDir::homePath() + "/.local/share/smod/decoration.smod.rcc"); + m_internalSettings = SettingsProvider::self()->internalSettings(this); setScaledCornerRadius(); @@ -405,9 +422,9 @@ auto s = settings(); // left, right and bottom borders - const int left = isLeftEdge() ? 0 : borderSize(); - const int right = isRightEdge() ? 0 : borderSize(); - const int bottom = (c->isShaded() || isBottomEdge()) ? 0 : borderSize(true); + int left = isMaximized() ? 0 : borderSize(); + int right = isMaximized() ? 0 : borderSize(); + int bottom = (c->isShaded() || isMaximized()) ? 0 : borderSize(true); int top = 0; if (hideTitleBar()) { @@ -424,6 +441,21 @@ top += baseSize * Metrics::TitleBar_TopMargin; } + top = isMaximized() ? 22 : 30; + + if (hideInnerBorder()) + { + left = left < INNER_BORDER_SIZE ? 0 : left - INNER_BORDER_SIZE; + right = right < INNER_BORDER_SIZE ? 0 : right - INNER_BORDER_SIZE; + top = top < INNER_BORDER_SIZE ? 0 : top - INNER_BORDER_SIZE; + bottom = bottom < INNER_BORDER_SIZE ? 0 : bottom - INNER_BORDER_SIZE; + } + + left = qMax(0, left); + right = qMax(0, right); + top = qMax(0, top); + bottom = qMax(0, bottom); + setBorders(QMargins(left, top, right, bottom)); // extended sizes @@ -446,6 +478,8 @@ // Update shadows and clear outline to make sure outline changes when borders are changed updateShadow(); + + updateBlur(); } //________________________________________________________________ @@ -467,6 +501,24 @@ { const auto s = settings(); + // left buttons + if (!m_leftButtons->buttons().isEmpty()) { + const int vPadding = isMaximized() ? 0 : s->smallSpacing() * Metrics::TitleBar_TopMargin; + const int hPadding = 0; //s->smallSpacing() * Metrics::TitleBar_SideMargin; + m_leftButtons->setPos(QPointF(hPadding + borderLeft(), vPadding)); + } + + if (!m_rightButtons->buttons().isEmpty()) { + const int vPadding = isMaximized() ? -1 : 1; + const int lessPadding = hideInnerBorder() ? 0 : INNER_BORDER_SIZE; + m_rightButtons->setPos(QPointF( + size().width() - m_rightButtons->geometry().width() - borderRight() - (isMaximized() ? 4 : 0) + lessPadding, vPadding)); + } + + update(); + + return; + // adjust button position const int bHeight = captionHeight() + (isTopEdge() ? s->smallSpacing() * Metrics::TitleBar_TopMargin : 0); const int bWidth = buttonHeight(); @@ -525,6 +577,10 @@ //________________________________________________________________ void Decoration::paint(QPainter *painter, const QRect &repaintRegion) { + smodPaint(painter, repaintRegion); + + return; + // TODO: optimize based on repaintRegion auto c = client().toStrongRef(); auto s = settings(); @@ -802,16 +858,18 @@ QPainter painter(&shadowTexture); painter.setRenderHint(QPainter::Antialiasing); - const QRect outerRect = shadowTexture.rect(); + QRect outerRect = shadowTexture.rect(); QRect boxRect(QPoint(0, 0), boxSize); boxRect.moveCenter(outerRect.center()); // Mask out inner rect. - const QMargins padding = QMargins(boxRect.left() - outerRect.left() - Metrics::Shadow_Overlap - params.offset.x(), - boxRect.top() - outerRect.top() - Metrics::Shadow_Overlap - params.offset.y(), - outerRect.right() - boxRect.right() - Metrics::Shadow_Overlap + params.offset.x(), - outerRect.bottom() - boxRect.bottom() - Metrics::Shadow_Overlap + params.offset.y()); + const QMargins padding = QMargins( + boxRect.left() - outerRect.left() - Metrics::Shadow_Overlap - params.offset.x(), + boxRect.top() - outerRect.top() - Metrics::Shadow_Overlap - params.offset.y(), + outerRect.right() - boxRect.right() - Metrics::Shadow_Overlap + params.offset.x(), + outerRect.bottom() - boxRect.bottom() - Metrics::Shadow_Overlap + params.offset.y()); + const QRect innerRect = outerRect - padding; painter.setPen(Qt::NoPen); @@ -819,6 +877,8 @@ painter.setCompositionMode(QPainter::CompositionMode_DestinationOut); painter.drawRoundedRect(innerRect, m_scaledCornerRadius + 0.5, m_scaledCornerRadius + 0.5); + +#if 0 // Draw window outline const qreal outlineWidth = 1.001; const qreal penOffset = outlineWidth / 2; @@ -850,6 +910,7 @@ painter.setCompositionMode(QPainter::CompositionMode_Source); painter.setRenderHint(QPainter::Antialiasing); painter.drawPath(outlinePath); +#endif painter.end(); @@ -857,6 +918,8 @@ ret->setPadding(padding); ret->setInnerShadowRect(QRect(outerRect.center(), QSize(1, 1))); ret->setShadow(shadowTexture); + + return ret; } @@ -864,6 +927,311 @@ { m_scaledCornerRadius = Metrics::Frame_FrameRadius * settings()->smallSpacing(); } + +void Decoration::updateBlur() +{ + const int radius = isMaximized() ? 0 : 6; + + QPainterPath path; + path.addRoundedRect(rect(), radius, radius); + + setBlurRegion(QRegion(path.toFillPolygon().toPolygon())); + + updateShadow(); +} + +void Decoration::smodPaint(QPainter *painter, const QRect &repaintRegion) +{ + painter->fillRect(rect(), Qt::transparent); + + smodPaintGlow(painter, repaintRegion); + smodPaintOuterBorder(painter, repaintRegion); + smodPaintInnerBorder(painter, repaintRegion); + smodPaintTitleBar(painter, repaintRegion); +} + +void Decoration::smodPaintGlow(QPainter *painter, const QRect &repaintRegion) +{ + auto c = client().toStrongRef(); + + int SIDEBAR_HEIGHT = qMax(50, (size().height() / 4)); + + painter->setOpacity(0.75); + + if (c->isActive()) + { + if (isMaximized()) + { + QPixmap nwCorner(":/smod/decoration/framecornereffect"); + painter->drawPixmap(0, 0, nwCorner, 4, 4, nwCorner.width() - 4, nwCorner.height() - 4); + + QPixmap neCorner = nwCorner.transformed(QTransform().scale(-1, 1)); + //QPixmap neCorner(":/smod/decoration/ne-corner"); + painter->drawPixmap(size().width() - (neCorner.width() - 4), 0, neCorner, 0, 4, neCorner.width() - 4, neCorner.height() - 4); + } + else + { + QPixmap nwCorner(":/smod/decoration/framecornereffect"); + painter->drawPixmap(0, 0, nwCorner); + + QPixmap neCorner = nwCorner.transformed(QTransform().scale(-1, 1)); + //QPixmap neCorner(":/smod/decoration/ne-corner"); + painter->drawPixmap(size().width() - neCorner.width(), 0, neCorner); + + painter->setOpacity(1.0); + + // 7x116 + QPixmap sidehighlight(":/smod/decoration/sidehighlight"); + painter->drawPixmap(0, 0, 7, SIDEBAR_HEIGHT, sidehighlight); + painter->drawPixmap(size().width() - 7, 0, 7, SIDEBAR_HEIGHT, sidehighlight); + } + } + else + { + if (isMaximized()) + { + QPixmap nwCorner(":/smod/decoration/framecornereffect-unfocus"); + painter->drawPixmap(0, 0, nwCorner, 4, 4, nwCorner.width() - 4, nwCorner.height() - 4); + + QPixmap neCorner = nwCorner.transformed(QTransform().scale(-1, 1)); + //QPixmap neCorner(":/smod/decoration/ne-corner"); + painter->drawPixmap(size().width() - (neCorner.width() - 4), 0, neCorner, 0, 4, neCorner.width() - 4, neCorner.height() - 4); + } + else + { + QPixmap nwCorner(":/smod/decoration/framecornereffect-unfocus"); + painter->drawPixmap(0, 0, nwCorner); + + QPixmap neCorner = nwCorner.transformed(QTransform().scale(-1, 1)); + //QPixmap neCorner(":/smod/decoration/ne-corner"); + painter->drawPixmap(size().width() - neCorner.width(), 0, neCorner); + + painter->setOpacity(1.0); + + // 7x116 + QPixmap sidehighlight(":/smod/decoration/sidehighlight-unfocus"); + painter->drawPixmap(0, 0, 7, SIDEBAR_HEIGHT, sidehighlight); + painter->drawPixmap(size().width() - 7, 0, 7, SIDEBAR_HEIGHT, sidehighlight); + } + } + + painter->setOpacity(1.0); +} + +void Decoration::smodPaintOuterBorder(QPainter *painter, const QRect &repaintRegion) +{ + if (isMaximized()) + { + return; + } + + auto c = client().toStrongRef(); + + QPixmap nw, n, ne, e, se, s, sw, w; + + if (c->isActive()) + { + nw = QPixmap(":/smod/decoration/nw"); + n = QPixmap(":/smod/decoration/n"); + ne = QPixmap(":/smod/decoration/ne"); + e = QPixmap(":/smod/decoration/e"); + se = QPixmap(":/smod/decoration/se"); + s = QPixmap(":/smod/decoration/s"); + sw = QPixmap(":/smod/decoration/sw"); + w = QPixmap(":/smod/decoration/w"); + } + else + { + nw = QPixmap(":/smod/decoration/nw-unfocus"); + n = QPixmap(":/smod/decoration/n-unfocus"); + ne = QPixmap(":/smod/decoration/ne-unfocus"); + e = QPixmap(":/smod/decoration/e-unfocus"); + se = QPixmap(":/smod/decoration/se-unfocus"); + s = QPixmap(":/smod/decoration/s-unfocus"); + sw = QPixmap(":/smod/decoration/sw-unfocus"); + w = QPixmap(":/smod/decoration/w-unfocus"); + } + +#if 0 + if (c->isActive()) + { + painter->save(); + QPen pen(Qt::white, 0); + painter->setPen(pen); + painter->drawRoundedRect(rect().x() + 1, rect().y() + 1, rect().width() - 2, rect().height() - 2, 6, 6); + painter->restore(); + } +#endif + int PIX_RIGHT = size().width() - 9; + int PIX_BOTTOM = size().height() - 9; + + painter->drawPixmap(0, 0, nw); + + painter->drawTiledPixmap(9, 0, PIX_RIGHT - 9, 9, n); + + painter->drawPixmap(PIX_RIGHT, 0, ne); + + painter->drawTiledPixmap(PIX_RIGHT, 9, 9, PIX_BOTTOM - 9, e); + + painter->drawPixmap(PIX_RIGHT, PIX_BOTTOM, se); + + painter->drawTiledPixmap(9, PIX_BOTTOM, PIX_RIGHT - 9, 9, s); + + painter->drawPixmap(0, PIX_BOTTOM, sw); + + painter->drawTiledPixmap(0, 9, 9, PIX_BOTTOM - 9, w); +} + +void Decoration::smodPaintInnerBorder(QPainter *painter, const QRect &repaintRegion) +{ + if (hideInnerBorder()) + { + return; + } + + auto c = client().toStrongRef(); + + QPixmap nw, n, ne, e, se, s, sw, w; + + if (c->isActive()) + { + nw = QPixmap(":/smod/decoration/nw-inner"); + n = QPixmap(":/smod/decoration/n-inner"); + ne = QPixmap(":/smod/decoration/ne-inner"); + e = QPixmap(":/smod/decoration/e-inner"); + se = QPixmap(":/smod/decoration/se-inner"); + s = QPixmap(":/smod/decoration/s-inner"); + sw = QPixmap(":/smod/decoration/sw-inner"); + w = QPixmap(":/smod/decoration/w-inner"); + } + else + { + nw = QPixmap(":/smod/decoration/nw-unfocus-inner"); + n = QPixmap(":/smod/decoration/n-unfocus-inner"); + ne = QPixmap(":/smod/decoration/ne-unfocus-inner"); + e = QPixmap(":/smod/decoration/e-unfocus-inner"); + se = QPixmap(":/smod/decoration/se-unfocus-inner"); + s = QPixmap(":/smod/decoration/s-unfocus-inner"); + sw = QPixmap(":/smod/decoration/sw-unfocus-inner"); + w = QPixmap(":/smod/decoration/w-unfocus-inner"); + } + + // left + painter->drawTiledPixmap( + borderLeft() - INNER_BORDER_SIZE, + borderTop(), + INNER_BORDER_SIZE, + size().height() - borderBottom() - borderTop(), + w); + + // right + painter->drawTiledPixmap( + size().width() - borderRight(), + borderTop(), + INNER_BORDER_SIZE, + size().height() - borderBottom() - borderTop(), + e); + + // bottom + painter->drawTiledPixmap( + borderLeft(), + size().height() - borderBottom(), + size().width() - borderLeft() - borderRight(), + INNER_BORDER_SIZE, + s); + + // top + painter->drawTiledPixmap( + borderLeft(), + borderTop() - INNER_BORDER_SIZE, + size().width() - borderLeft() - borderRight(), + INNER_BORDER_SIZE, + n); + + painter->drawPixmap(borderLeft() - INNER_BORDER_SIZE, borderTop() - INNER_BORDER_SIZE, nw); + painter->drawPixmap(size().width() - borderRight(), borderTop() - INNER_BORDER_SIZE, ne); + painter->drawPixmap(size().width() - borderRight(), size().height() - borderBottom(), se); + painter->drawPixmap(borderLeft() - INNER_BORDER_SIZE, size().height() - borderBottom(), sw); +} + +void Decoration::smodPaintTitleBar(QPainter *painter, const QRect &repaintRegion) +{ + if (hideTitleBar()) + { + return; + } + + if (!hideCaption()) + { + const auto c = client().toStrongRef(); + const bool active = c->isActive(); + + QRect captionRect(m_leftButtons->geometry().right() + 4 + (c->isMaximized() ? 5 : 0), 0, m_rightButtons->geometry().left() - m_leftButtons->geometry().right() - 4, borderTop()); + QString caption = settings()->fontMetrics().elidedText(c->caption(), Qt::ElideMiddle, captionRect.width()); + QStringList programname = caption.split(" — "); + caption.remove(" — " + programname.at(programname.size()-1)); + caption.prepend(" "); + caption.append(" "); + int blurWidth = settings()->fontMetrics().width(caption + "..JO"); + int blurHeight = settings()->fontMetrics().height(); + //factory()->setTitleTextWidth(blurWidth); + //factory()->setTitleTextHeight(blurHeight); + //factory()->setMaximized(c->isMaximized()); + + //if (drawTitle) + //{ + QColor shadowColor = QColor(0, 0, 0, 255); + QColor textColor = c->color(active ? KDecoration2::ColorGroup::Active : KDecoration2::ColorGroup::Inactive, KDecoration2::ColorRole::Foreground); + int textHaloXOffset = 1; + int textHaloYOffset = 1; + int textHaloSize = 2; + //if (!config->useKWinTextColors) { + // alpha_color &c = fs->text_halo; + // shadowColor = QColor::fromRgbF(c.color.r, c.color.g, c.color.b, c.alpha); + // c = fs->text; + // textColor = QColor::fromRgbF(c.color.r, c.color.g, c.color.b, c.alpha); + //} + captionRect.setHeight(captionRect.height() & -2); + painter->setFont(settings()->font()); + painter->setPen(shadowColor); + // painter->drawText(captionRect.adjusted(1, 1, 1, 1), Qt::AlignVCenter, caption); + painter->setPen(textColor); + //Qt::Alignment alignment = Qt::AlignHCenter; + Qt::Alignment alignment = Qt::AlignLeft; + //if (ws->tobj_layout) { + // alignment = parseTitleAlignment(ws->tobj_layout); + //} + QLabel temp_label(caption); + QGraphicsGlowEffect temp_effect; + temp_effect.setColor(QColor::fromRgb(255, 255, 255, 0)); + temp_effect.setBlurRadius(7); + temp_label.setGraphicsEffect(&temp_effect); + + int captionHeight = captionRect.height() * 0.8; + QPixmap final_label(blurWidth, captionHeight); + final_label.fill(QColor::fromRgb(0,0,0,0)); + QPainter *ptr = new QPainter(&final_label); + QPainterPath path; + path.addRoundedRect(0, 0, blurWidth, captionHeight, 12,12); + ptr->fillPath(path, QColor::fromRgb(255,255,255, active ? 186 : 148)); + delete ptr; + + if(!caption.trimmed().isEmpty()) + { + QPixmap blur_effect = temp_effect.drawBlur(final_label); + painter->drawPixmap(QRect(captionRect.x()*0.7,captionRect.y(),blurWidth,captionRect.height()), blur_effect); + painter->drawText(captionRect, alignment | Qt::AlignVCenter | Qt::TextSingleLine, caption); + } + } + + m_leftButtons->paint(painter, repaintRegion); + m_rightButtons->paint(painter, repaintRegion); + + foreach (QPointer button, m_rightButtons->buttons()) { + static_cast