diff --git a/kdecoration/breezebutton.cpp b/kdecoration/breezebutton.cpp index 759eeddd..be7ff7f2 100644 --- a/kdecoration/breezebutton.cpp +++ b/kdecoration/breezebutton.cpp @@ -1,478 +1,481 @@ /* * Copyright 2014 Martin Gräßlin * Copyright 2014 Hugo Pereira Da Costa * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "breezebutton.h" #include #include #include +#include namespace Breeze { using KDecoration2::ColorRole; using KDecoration2::ColorGroup; using KDecoration2::DecorationButtonType; //__________________________________________________________________ Button::Button(DecorationButtonType type, Decoration* decoration, QObject* parent) : DecorationButton(type, decoration, parent) - , m_animation( new QPropertyAnimation( this ) ) + , m_animation( new QVariantAnimation( this ) ) { // setup animation - m_animation->setStartValue( 0 ); + // It is important start and end value are of the same type, hence 0.0 and not just 0 + m_animation->setStartValue( 0.0 ); m_animation->setEndValue( 1.0 ); - m_animation->setTargetObject( this ); - m_animation->setPropertyName( "opacity" ); m_animation->setEasingCurve( QEasingCurve::InOutQuad ); + connect(m_animation, &QVariantAnimation::valueChanged, this, [this](const QVariant &value) { + setOpacity(value.toReal()); + }); // setup default geometry const int height = decoration->buttonHeight(); setGeometry(QRect(0, 0, height, height)); setIconSize(QSize( height, height )); // connections connect(decoration->client().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 ); reconfigure(); } //__________________________________________________________________ Button::Button(QObject *parent, const QVariantList &args) : Button(args.at(0).value(), args.at(1).value(), parent) { m_flag = FlagStandalone; //! icon size must return to !valid because it was altered from the default constructor, //! in Standalone mode the button is not using the decoration metrics but its geometry m_iconSize = QSize(-1, -1); } //__________________________________________________________________ Button *Button::create(DecorationButtonType type, KDecoration2::Decoration *decoration, QObject *parent) { if (auto d = qobject_cast(decoration)) { Button *b = new Button(type, d, parent); switch( type ) { case DecorationButtonType::Close: b->setVisible( d->client().data()->isCloseable() ); QObject::connect(d->client().data(), &KDecoration2::DecoratedClient::closeableChanged, b, &Breeze::Button::setVisible ); break; case DecorationButtonType::Maximize: b->setVisible( d->client().data()->isMaximizeable() ); QObject::connect(d->client().data(), &KDecoration2::DecoratedClient::maximizeableChanged, b, &Breeze::Button::setVisible ); break; case DecorationButtonType::Minimize: b->setVisible( d->client().data()->isMinimizeable() ); QObject::connect(d->client().data(), &KDecoration2::DecoratedClient::minimizeableChanged, b, &Breeze::Button::setVisible ); break; case DecorationButtonType::ContextHelp: b->setVisible( d->client().data()->providesContextHelp() ); QObject::connect(d->client().data(), &KDecoration2::DecoratedClient::providesContextHelpChanged, b, &Breeze::Button::setVisible ); break; case DecorationButtonType::Shade: b->setVisible( d->client().data()->isShadeable() ); QObject::connect(d->client().data(), &KDecoration2::DecoratedClient::shadeableChanged, b, &Breeze::Button::setVisible ); break; case DecorationButtonType::Menu: QObject::connect(d->client().data(), &KDecoration2::DecoratedClient::iconChanged, b, [b]() { b->update(); }); break; default: break; } return b; } return nullptr; } //__________________________________________________________________ void Button::paint(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() ) m_iconSize = geometry().size().toSize(); // menu button if (type() == DecorationButtonType::Menu) { const QRectF iconRect( geometry().topLeft(), m_iconSize ); decoration()->client().data()->icon().paint(painter, iconRect.toRect()); } else { drawIcon( painter ); } painter->restore(); } //__________________________________________________________________ void Button::drawIcon( QPainter *painter ) const { painter->setRenderHints( QPainter::Antialiasing ); /* scale painter so that its window matches QRect( -1, -1, 20, 20 ) this makes all further rendering and scaling simpler all further rendering is preformed inside QRect( 0, 0, 18, 18 ) */ painter->translate( geometry().topLeft() ); const qreal width( m_iconSize.width() ); painter->scale( width/20, width/20 ); painter->translate( 1, 1 ); // render background const QColor backgroundColor( this->backgroundColor() ); if( backgroundColor.isValid() ) { painter->setPen( Qt::NoPen ); painter->setBrush( backgroundColor ); painter->drawEllipse( QRectF( 0, 0, 18, 18 ) ); } // render mark const QColor foregroundColor( this->foregroundColor() ); if( foregroundColor.isValid() ) { // setup painter QPen pen( foregroundColor ); pen.setCapStyle( Qt::RoundCap ); pen.setJoinStyle( Qt::MiterJoin ); pen.setWidthF( 1.1*qMax((qreal)1.0, 20/width ) ); painter->setPen( pen ); painter->setBrush( Qt::NoBrush ); switch( type() ) { case DecorationButtonType::Close: { painter->drawLine( QPointF( 5, 5 ), QPointF( 13, 13 ) ); painter->drawLine( 13, 5, 5, 13 ); break; } case DecorationButtonType::Maximize: { if( isChecked() ) { pen.setJoinStyle( Qt::RoundJoin ); painter->setPen( pen ); painter->drawPolygon( QVector{ QPointF( 4, 9 ), QPointF( 9, 4 ), QPointF( 14, 9 ), QPointF( 9, 14 )} ); } else { painter->drawPolyline( QVector{ QPointF( 4, 11 ), QPointF( 9, 6 ), QPointF( 14, 11 )}); } break; } case DecorationButtonType::Minimize: { painter->drawPolyline( QVector{ QPointF( 4, 7 ), QPointF( 9, 12 ), QPointF( 14, 7 ) }); break; } case DecorationButtonType::OnAllDesktops: { painter->setPen( Qt::NoPen ); painter->setBrush( foregroundColor ); if( isChecked()) { // outer ring painter->drawEllipse( QRectF( 3, 3, 12, 12 ) ); // center dot QColor backgroundColor( this->backgroundColor() ); auto d = qobject_cast( decoration() ); if( !backgroundColor.isValid() && d ) backgroundColor = d->titleBarColor(); if( backgroundColor.isValid() ) { painter->setBrush( backgroundColor ); painter->drawEllipse( QRectF( 8, 8, 2, 2 ) ); } } else { painter->drawPolygon( QVector { QPointF( 6.5, 8.5 ), QPointF( 12, 3 ), QPointF( 15, 6 ), QPointF( 9.5, 11.5 )} ); painter->setPen( pen ); painter->drawLine( QPointF( 5.5, 7.5 ), QPointF( 10.5, 12.5 ) ); painter->drawLine( QPointF( 12, 6 ), QPointF( 4.5, 13.5 ) ); } break; } case DecorationButtonType::Shade: { if (isChecked()) { painter->drawLine( QPointF( 4, 5.5 ), QPointF( 14, 5.5 ) ); painter->drawPolyline( QVector { QPointF( 4, 8 ), QPointF( 9, 13 ), QPointF( 14, 8 )} ); } else { painter->drawLine( QPointF( 4, 5.5 ), QPointF( 14, 5.5 ) ); painter->drawPolyline( QVector { QPointF( 4, 13 ), QPointF( 9, 8 ), QPointF( 14, 13 ) }); } break; } case DecorationButtonType::KeepBelow: { painter->drawPolyline( QVector { QPointF( 4, 5 ), QPointF( 9, 10 ), QPointF( 14, 5 ) }); painter->drawPolyline( QVector { QPointF( 4, 9 ), QPointF( 9, 14 ), QPointF( 14, 9 ) }); break; } case DecorationButtonType::KeepAbove: { painter->drawPolyline( QVector { QPointF( 4, 9 ), QPointF( 9, 4 ), QPointF( 14, 9 ) }); painter->drawPolyline( QVector { QPointF( 4, 13 ), QPointF( 9, 8 ), QPointF( 14, 13 ) }); break; } case DecorationButtonType::ApplicationMenu: { painter->drawRect( QRectF( 3.5, 4.5, 11, 1 ) ); painter->drawRect( QRectF( 3.5, 8.5, 11, 1 ) ); painter->drawRect( QRectF( 3.5, 12.5, 11, 1 ) ); break; } case DecorationButtonType::ContextHelp: { QPainterPath path; path.moveTo( 5, 6 ); path.arcTo( QRectF( 5, 3.5, 8, 5 ), 180, -180 ); path.cubicTo( QPointF(12.5, 9.5), QPointF( 9, 7.5 ), QPointF( 9, 11.5 ) ); painter->drawPath( path ); painter->drawRect( QRectF( 9, 15, 0.5, 0.5 ) ); break; } default: break; } } } //__________________________________________________________________ QColor Button::foregroundColor() const { auto d = qobject_cast( decoration() ); if( !d ) { return QColor(); } else if( isPressed() ) { return d->titleBarColor(); } else if( type() == DecorationButtonType::Close && d->internalSettings()->outlineCloseButton() ) { return d->titleBarColor(); } else if( ( type() == DecorationButtonType::KeepBelow || type() == DecorationButtonType::KeepAbove || type() == DecorationButtonType::Shade ) && isChecked() ) { return d->titleBarColor(); - } else if( m_animation->state() == QPropertyAnimation::Running ) { + } else if( m_animation->state() == QAbstractAnimation::Running ) { return KColorUtils::mix( d->fontColor(), d->titleBarColor(), m_opacity ); } else if( isHovered() ) { return d->titleBarColor(); } else { return d->fontColor(); } } //__________________________________________________________________ QColor Button::backgroundColor() const { auto d = qobject_cast( decoration() ); if( !d ) { return QColor(); } auto c = d->client().data(); if( isPressed() ) { if( type() == DecorationButtonType::Close ) return c->color( ColorGroup::Warning, ColorRole::Foreground ); else return KColorUtils::mix( d->titleBarColor(), d->fontColor(), 0.3 ); } else if( ( type() == DecorationButtonType::KeepBelow || type() == DecorationButtonType::KeepAbove || type() == DecorationButtonType::Shade ) && isChecked() ) { return d->fontColor(); - } else if( m_animation->state() == QPropertyAnimation::Running ) { + } else if( m_animation->state() == QAbstractAnimation::Running ) { if( type() == DecorationButtonType::Close ) { if( d->internalSettings()->outlineCloseButton() ) { return KColorUtils::mix( d->fontColor(), c->color( ColorGroup::Warning, ColorRole::Foreground ).lighter(), m_opacity ); } else { QColor color( c->color( ColorGroup::Warning, ColorRole::Foreground ).lighter() ); color.setAlpha( color.alpha()*m_opacity ); return color; } } else { QColor color( d->fontColor() ); color.setAlpha( color.alpha()*m_opacity ); return color; } } else if( isHovered() ) { if( type() == DecorationButtonType::Close ) return c->color( ColorGroup::Warning, ColorRole::Foreground ).lighter(); else return d->fontColor(); } else if( type() == DecorationButtonType::Close && d->internalSettings()->outlineCloseButton() ) { return d->fontColor(); } else { return QColor(); } } //________________________________________________________________ void Button::reconfigure() { // animation auto d = qobject_cast(decoration()); if( d ) m_animation->setDuration( d->internalSettings()->animationsDuration() ); } //__________________________________________________________________ void Button::updateAnimationState( bool hovered ) { auto d = qobject_cast(decoration()); if( !(d && d->internalSettings()->animationsEnabled() ) ) return; - m_animation->setDirection( hovered ? QPropertyAnimation::Forward : QPropertyAnimation::Backward ); - if( m_animation->state() != QPropertyAnimation::Running ) m_animation->start(); + m_animation->setDirection( hovered ? QAbstractAnimation::Forward : QAbstractAnimation::Backward ); + if( m_animation->state() != QAbstractAnimation::Running ) m_animation->start(); } } // namespace diff --git a/kdecoration/breezebutton.h b/kdecoration/breezebutton.h index 835d119d..531eb978 100644 --- a/kdecoration/breezebutton.h +++ b/kdecoration/breezebutton.h @@ -1,140 +1,138 @@ #ifndef BREEZE_BUTTONS_H #define BREEZE_BUTTONS_H /* * Copyright 2014 Martin Gräßlin * Copyright 2014 Hugo Pereira Da Costa * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "breezedecoration.h" #include #include -#include + +class QVariantAnimation; namespace Breeze { class Button : public KDecoration2::DecorationButton { Q_OBJECT - //* declare active state opacity - Q_PROPERTY( qreal opacity READ opacity WRITE setOpacity ) - public: //* constructor explicit Button(QObject *parent, const QVariantList &args); //* destructor virtual ~Button() = default; //* button creation static Button *create(KDecoration2::DecorationButtonType type, KDecoration2::Decoration *decoration, QObject *parent); //* render virtual void paint(QPainter *painter, const QRect &repaintRegion) override; //* flag enum Flag { FlagNone, FlagStandalone, FlagFirstInList, FlagLastInList }; //* flag void setFlag( Flag value ) { m_flag = value; } //* standalone buttons bool isStandAlone() const { return m_flag == FlagStandalone; } //* offset void setOffset( const QPointF& value ) { m_offset = value; } //* horizontal offset, for rendering void setHorizontalOffset( qreal value ) { m_offset.setX( value ); } //* vertical offset, for rendering void setVerticalOffset( qreal value ) { m_offset.setY( value ); } //* set icon size void setIconSize( const QSize& value ) { m_iconSize = value; } //*@name active state change animation //@{ void setOpacity( qreal value ) { if( m_opacity == value ) return; m_opacity = value; update(); } qreal opacity() const { return m_opacity; } //@} private Q_SLOTS: //* apply configuration changes void reconfigure(); //* animation state void updateAnimationState(bool); private: //* private constructor explicit Button(KDecoration2::DecorationButtonType type, Decoration *decoration, QObject *parent = nullptr); //* draw button icon void drawIcon( QPainter *) const; //*@name colors //@{ QColor foregroundColor() const; QColor backgroundColor() const; //@} Flag m_flag = FlagNone; //* active state change animation - QPropertyAnimation *m_animation; + QVariantAnimation *m_animation; //* vertical offset (for rendering) QPointF m_offset; //* icon size QSize m_iconSize; //* active state change opacity qreal m_opacity = 0; }; } // namespace #endif diff --git a/kdecoration/breezedecoration.cpp b/kdecoration/breezedecoration.cpp index d5526ce2..c9f9c424 100644 --- a/kdecoration/breezedecoration.cpp +++ b/kdecoration/breezedecoration.cpp @@ -1,831 +1,834 @@ /* * Copyright 2014 Martin Gräßlin * Copyright 2014 Hugo Pereira Da Costa * Copyright 2018 Vlad Zagorodniy * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "breezedecoration.h" #include "breeze.h" #include "breezesettingsprovider.h" #include "config-breeze.h" #include "config/breezeconfigwidget.h" #include "breezebutton.h" #include "breezesizegrip.h" #include "breezeboxshadowrenderer.h" #include #include #include #include #include #include #include #include #include #include #include +#include #if BREEZE_HAVE_X11 #include #endif #include K_PLUGIN_FACTORY_WITH_JSON( BreezeDecoFactory, "breeze.json", registerPlugin(); registerPlugin(QStringLiteral("button")); registerPlugin(QStringLiteral("kcmodule")); ) namespace { struct ShadowParams { ShadowParams() : offset(QPoint(0, 0)) , radius(0) , opacity(0) {} ShadowParams(const QPoint &offset, int radius, qreal opacity) : offset(offset) , radius(radius) , opacity(opacity) {} QPoint offset; int radius; qreal opacity; }; struct CompositeShadowParams { CompositeShadowParams() = default; CompositeShadowParams( const QPoint &offset, const ShadowParams &shadow1, const ShadowParams &shadow2) : offset(offset) , shadow1(shadow1) , shadow2(shadow2) {} bool isNone() const { return qMax(shadow1.radius, shadow2.radius) == 0; } QPoint offset; ShadowParams shadow1; ShadowParams shadow2; }; const CompositeShadowParams s_shadowParams[] = { // None CompositeShadowParams(), // Small CompositeShadowParams( QPoint(0, 4), ShadowParams(QPoint(0, 0), 16, 1), ShadowParams(QPoint(0, -2), 8, 0.4)), // Medium CompositeShadowParams( QPoint(0, 8), ShadowParams(QPoint(0, 0), 32, 0.9), ShadowParams(QPoint(0, -4), 16, 0.3)), // Large CompositeShadowParams( QPoint(0, 12), ShadowParams(QPoint(0, 0), 48, 0.8), ShadowParams(QPoint(0, -6), 24, 0.2)), // Very large CompositeShadowParams( QPoint(0, 16), ShadowParams(QPoint(0, 0), 64, 0.7), ShadowParams(QPoint(0, -8), 32, 0.1)), }; inline CompositeShadowParams lookupShadowParams(int size) { switch (size) { case Breeze::InternalSettings::ShadowNone: return s_shadowParams[0]; case Breeze::InternalSettings::ShadowSmall: return s_shadowParams[1]; case Breeze::InternalSettings::ShadowMedium: return s_shadowParams[2]; case Breeze::InternalSettings::ShadowLarge: return s_shadowParams[3]; case Breeze::InternalSettings::ShadowVeryLarge: return s_shadowParams[4]; default: // Fallback to the Large size. return s_shadowParams[3]; } } } namespace Breeze { using KDecoration2::ColorRole; using KDecoration2::ColorGroup; //________________________________________________________________ static int g_sDecoCount = 0; static int g_shadowSizeEnum = InternalSettings::ShadowLarge; static int g_shadowStrength = 255; static QColor g_shadowColor = Qt::black; static QSharedPointer g_sShadow; //________________________________________________________________ Decoration::Decoration(QObject *parent, const QVariantList &args) : KDecoration2::Decoration(parent, args) - , m_animation( new QPropertyAnimation( this ) ) + , m_animation( new QVariantAnimation( this ) ) { g_sDecoCount++; } //________________________________________________________________ Decoration::~Decoration() { g_sDecoCount--; if (g_sDecoCount == 0) { // last deco destroyed, clean up shadow g_sShadow.clear(); } deleteSizeGrip(); } //________________________________________________________________ void Decoration::setOpacity( qreal value ) { if( m_opacity == value ) return; m_opacity = value; update(); if( m_sizeGrip ) m_sizeGrip->update(); } //________________________________________________________________ QColor Decoration::titleBarColor() const { auto c = client().data(); if( hideTitleBar() ) return c->color( ColorGroup::Inactive, ColorRole::TitleBar ); - else if( m_animation->state() == QPropertyAnimation::Running ) + else if( m_animation->state() == QAbstractAnimation::Running ) { return KColorUtils::mix( c->color( ColorGroup::Inactive, ColorRole::TitleBar ), c->color( ColorGroup::Active, ColorRole::TitleBar ), m_opacity ); } else return c->color( c->isActive() ? ColorGroup::Active : ColorGroup::Inactive, ColorRole::TitleBar ); } //________________________________________________________________ QColor Decoration::outlineColor() const { auto c( client().data() ); if( !m_internalSettings->drawTitleBarSeparator() ) return QColor(); - if( m_animation->state() == QPropertyAnimation::Running ) + if( m_animation->state() == QAbstractAnimation::Running ) { QColor color( c->palette().color( QPalette::Highlight ) ); color.setAlpha( color.alpha()*m_opacity ); return color; } else if( c->isActive() ) return c->palette().color( QPalette::Highlight ); else return QColor(); } //________________________________________________________________ QColor Decoration::fontColor() const { auto c = client().data(); - if( m_animation->state() == QPropertyAnimation::Running ) + if( m_animation->state() == QAbstractAnimation::Running ) { return KColorUtils::mix( c->color( ColorGroup::Inactive, ColorRole::Foreground ), c->color( ColorGroup::Active, ColorRole::Foreground ), m_opacity ); } else return c->color( c->isActive() ? ColorGroup::Active : ColorGroup::Inactive, ColorRole::Foreground ); } //________________________________________________________________ void Decoration::init() { auto c = client().data(); // active state change animation - m_animation->setStartValue( 0 ); + // It is important start and end value are of the same type, hence 0.0 and not just 0 + m_animation->setStartValue( 0.0 ); m_animation->setEndValue( 1.0 ); - m_animation->setTargetObject( this ); - m_animation->setPropertyName( "opacity" ); m_animation->setEasingCurve( QEasingCurve::InOutQuad ); + connect(m_animation, &QVariantAnimation::valueChanged, this, [this](const QVariant &value) { + setOpacity(value.toReal()); + }); reconfigure(); updateTitleBar(); auto s = settings(); connect(s.data(), &KDecoration2::DecorationSettings::borderSizeChanged, this, &Decoration::recalculateBorders); // a change in font might cause the borders to change connect(s.data(), &KDecoration2::DecorationSettings::fontChanged, this, &Decoration::recalculateBorders); connect(s.data(), &KDecoration2::DecorationSettings::spacingChanged, this, &Decoration::recalculateBorders); // buttons connect(s.data(), &KDecoration2::DecorationSettings::spacingChanged, this, &Decoration::updateButtonsGeometryDelayed); connect(s.data(), &KDecoration2::DecorationSettings::decorationButtonsLeftChanged, this, &Decoration::updateButtonsGeometryDelayed); connect(s.data(), &KDecoration2::DecorationSettings::decorationButtonsRightChanged, this, &Decoration::updateButtonsGeometryDelayed); // full reconfiguration connect(s.data(), &KDecoration2::DecorationSettings::reconfigured, this, &Decoration::reconfigure); connect(s.data(), &KDecoration2::DecorationSettings::reconfigured, SettingsProvider::self(), &SettingsProvider::reconfigure, Qt::UniqueConnection ); connect(s.data(), &KDecoration2::DecorationSettings::reconfigured, this, &Decoration::updateButtonsGeometryDelayed); connect(c, &KDecoration2::DecoratedClient::adjacentScreenEdgesChanged, this, &Decoration::recalculateBorders); connect(c, &KDecoration2::DecoratedClient::maximizedHorizontallyChanged, this, &Decoration::recalculateBorders); connect(c, &KDecoration2::DecoratedClient::maximizedVerticallyChanged, this, &Decoration::recalculateBorders); connect(c, &KDecoration2::DecoratedClient::shadedChanged, this, &Decoration::recalculateBorders); connect(c, &KDecoration2::DecoratedClient::captionChanged, this, [this]() { // update the caption area update(titleBar()); } ); connect(c, &KDecoration2::DecoratedClient::activeChanged, this, &Decoration::updateAnimationState); connect(c, &KDecoration2::DecoratedClient::widthChanged, this, &Decoration::updateTitleBar); connect(c, &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::updateTitleBar); connect(c, &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::setOpaque); connect(c, &KDecoration2::DecoratedClient::widthChanged, this, &Decoration::updateButtonsGeometry); connect(c, &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::updateButtonsGeometry); connect(c, &KDecoration2::DecoratedClient::adjacentScreenEdgesChanged, this, &Decoration::updateButtonsGeometry); connect(c, &KDecoration2::DecoratedClient::shadedChanged, this, &Decoration::updateButtonsGeometry); createButtons(); createShadow(); } //________________________________________________________________ void Decoration::updateTitleBar() { auto s = settings(); auto c = client().data(); const bool maximized = isMaximized(); const int width = maximized ? c->width() : c->width() - 2*s->largeSpacing()*Metrics::TitleBar_SideMargin; const int height = maximized ? borderTop() : borderTop() - s->smallSpacing()*Metrics::TitleBar_TopMargin; const int x = maximized ? 0 : s->largeSpacing()*Metrics::TitleBar_SideMargin; const int y = maximized ? 0 : s->smallSpacing()*Metrics::TitleBar_TopMargin; setTitleBar(QRect(x, y, width, height)); } //________________________________________________________________ void Decoration::updateAnimationState() { if( m_internalSettings->animationsEnabled() ) { auto c = client().data(); - m_animation->setDirection( c->isActive() ? QPropertyAnimation::Forward : QPropertyAnimation::Backward ); - if( m_animation->state() != QPropertyAnimation::Running ) m_animation->start(); + m_animation->setDirection( c->isActive() ? QAbstractAnimation::Forward : QAbstractAnimation::Backward ); + if( m_animation->state() != QAbstractAnimation::Running ) m_animation->start(); } else { update(); } } //________________________________________________________________ void Decoration::updateSizeGripVisibility() { auto c = client().data(); if( m_sizeGrip ) { m_sizeGrip->setVisible( c->isResizeable() && !isMaximized() && !c->isShaded() ); } } //________________________________________________________________ int Decoration::borderSize(bool bottom) const { const int baseSize = settings()->smallSpacing(); if( m_internalSettings && (m_internalSettings->mask() & BorderSize ) ) { switch (m_internalSettings->borderSize()) { case InternalSettings::BorderNone: return 0; case InternalSettings::BorderNoSides: return bottom ? qMax(4, baseSize) : 0; default: case InternalSettings::BorderTiny: return bottom ? qMax(4, baseSize) : baseSize; case InternalSettings::BorderNormal: return baseSize*2; case InternalSettings::BorderLarge: return baseSize*3; case InternalSettings::BorderVeryLarge: return baseSize*4; case InternalSettings::BorderHuge: return baseSize*5; case InternalSettings::BorderVeryHuge: return baseSize*6; case InternalSettings::BorderOversized: return baseSize*10; } } else { switch (settings()->borderSize()) { case KDecoration2::BorderSize::None: return 0; case KDecoration2::BorderSize::NoSides: return bottom ? qMax(4, baseSize) : 0; default: case KDecoration2::BorderSize::Tiny: return bottom ? qMax(4, baseSize) : baseSize; case KDecoration2::BorderSize::Normal: return baseSize*2; case KDecoration2::BorderSize::Large: return baseSize*3; case KDecoration2::BorderSize::VeryLarge: return baseSize*4; case KDecoration2::BorderSize::Huge: return baseSize*5; case KDecoration2::BorderSize::VeryHuge: return baseSize*6; case KDecoration2::BorderSize::Oversized: return baseSize*10; } } } //________________________________________________________________ void Decoration::reconfigure() { m_internalSettings = SettingsProvider::self()->internalSettings( this ); // animation m_animation->setDuration( m_internalSettings->animationsDuration() ); // borders recalculateBorders(); // shadow createShadow(); // size grip if( hasNoBorders() && m_internalSettings->drawSizeGrip() ) createSizeGrip(); else deleteSizeGrip(); } //________________________________________________________________ void Decoration::recalculateBorders() { auto c = client().data(); 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 top = 0; if( hideTitleBar() ) top = bottom; else { QFontMetrics fm(s->font()); top += qMax(fm.height(), buttonHeight() ); // padding below // extra pixel is used for the active window outline const int baseSize = s->smallSpacing(); top += baseSize*Metrics::TitleBar_BottomMargin + 1; // padding above top += baseSize*TitleBar_TopMargin; } setBorders(QMargins(left, top, right, bottom)); // extended sizes const int extSize = s->largeSpacing(); int extSides = 0; int extBottom = 0; if( hasNoBorders() ) { if( !isMaximizedHorizontally() ) extSides = extSize; if( !isMaximizedVertically() ) extBottom = extSize; } else if( hasNoSideBorders() && !isMaximizedHorizontally() ) { extSides = extSize; } setResizeOnlyBorders(QMargins(extSides, 0, extSides, extBottom)); } //________________________________________________________________ void Decoration::createButtons() { m_leftButtons = new KDecoration2::DecorationButtonGroup(KDecoration2::DecorationButtonGroup::Position::Left, this, &Button::create); m_rightButtons = new KDecoration2::DecorationButtonGroup(KDecoration2::DecorationButtonGroup::Position::Right, this, &Button::create); updateButtonsGeometry(); } //________________________________________________________________ void Decoration::updateButtonsGeometryDelayed() { QTimer::singleShot( 0, this, &Decoration::updateButtonsGeometry ); } //________________________________________________________________ void Decoration::updateButtonsGeometry() { const auto s = settings(); // adjust button position const int bHeight = captionHeight() + (isTopEdge() ? s->smallSpacing()*Metrics::TitleBar_TopMargin:0); const int bWidth = buttonHeight(); const int verticalOffset = (isTopEdge() ? s->smallSpacing()*Metrics::TitleBar_TopMargin:0) + (captionHeight()-buttonHeight())/2; foreach( const QPointer& button, m_leftButtons->buttons() + m_rightButtons->buttons() ) { button.data()->setGeometry( QRectF( QPoint( 0, 0 ), QSizeF( bWidth, bHeight ) ) ); static_cast( button.data() )->setOffset( QPointF( 0, verticalOffset ) ); static_cast( button.data() )->setIconSize( QSize( bWidth, bWidth ) ); } // left buttons if( !m_leftButtons->buttons().isEmpty() ) { // spacing m_leftButtons->setSpacing(s->smallSpacing()*Metrics::TitleBar_ButtonSpacing); // padding const int vPadding = isTopEdge() ? 0 : s->smallSpacing()*Metrics::TitleBar_TopMargin; const int hPadding = s->smallSpacing()*Metrics::TitleBar_SideMargin; if( isLeftEdge() ) { // add offsets on the side buttons, to preserve padding, but satisfy Fitts law auto button = static_cast( m_leftButtons->buttons().front().data() ); button->setGeometry( QRectF( QPoint( 0, 0 ), QSizeF( bWidth + hPadding, bHeight ) ) ); button->setFlag( Button::FlagFirstInList ); button->setHorizontalOffset( hPadding ); m_leftButtons->setPos(QPointF(0, vPadding)); } else m_leftButtons->setPos(QPointF(hPadding + borderLeft(), vPadding)); } // right buttons if( !m_rightButtons->buttons().isEmpty() ) { // spacing m_rightButtons->setSpacing(s->smallSpacing()*Metrics::TitleBar_ButtonSpacing); // padding const int vPadding = isTopEdge() ? 0 : s->smallSpacing()*Metrics::TitleBar_TopMargin; const int hPadding = s->smallSpacing()*Metrics::TitleBar_SideMargin; if( isRightEdge() ) { auto button = static_cast( m_rightButtons->buttons().back().data() ); button->setGeometry( QRectF( QPoint( 0, 0 ), QSizeF( bWidth + hPadding, bHeight ) ) ); button->setFlag( Button::FlagLastInList ); m_rightButtons->setPos(QPointF(size().width() - m_rightButtons->geometry().width(), vPadding)); } else m_rightButtons->setPos(QPointF(size().width() - m_rightButtons->geometry().width() - hPadding - borderRight(), vPadding)); } update(); } //________________________________________________________________ void Decoration::paint(QPainter *painter, const QRect &repaintRegion) { // TODO: optimize based on repaintRegion auto c = client().data(); auto s = settings(); // paint background if( !c->isShaded() ) { painter->fillRect(rect(), Qt::transparent); painter->save(); painter->setRenderHint(QPainter::Antialiasing); painter->setPen(Qt::NoPen); painter->setBrush( c->color( c->isActive() ? ColorGroup::Active : ColorGroup::Inactive, ColorRole::Frame ) ); // clip away the top part if( !hideTitleBar() ) painter->setClipRect(0, borderTop(), size().width(), size().height() - borderTop(), Qt::IntersectClip); if( s->isAlphaChannelSupported() ) painter->drawRoundedRect(rect(), Metrics::Frame_FrameRadius, Metrics::Frame_FrameRadius); else painter->drawRect( rect() ); painter->restore(); } if( !hideTitleBar() ) paintTitleBar(painter, repaintRegion); if( hasBorders() && !s->isAlphaChannelSupported() ) { painter->save(); painter->setRenderHint(QPainter::Antialiasing, false); painter->setBrush( Qt::NoBrush ); painter->setPen( c->isActive() ? c->color( ColorGroup::Active, ColorRole::TitleBar ): c->color( ColorGroup::Inactive, ColorRole::Foreground ) ); painter->drawRect( rect().adjusted( 0, 0, -1, -1 ) ); painter->restore(); } } //________________________________________________________________ void Decoration::paintTitleBar(QPainter *painter, const QRect &repaintRegion) { const auto c = client().data(); const QRect titleRect(QPoint(0, 0), QSize(size().width(), borderTop())); if ( !titleRect.intersects(repaintRegion) ) return; painter->save(); painter->setPen(Qt::NoPen); // render a linear gradient on title area if( c->isActive() && m_internalSettings->drawBackgroundGradient() ) { const QColor titleBarColor( this->titleBarColor() ); QLinearGradient gradient( 0, 0, 0, titleRect.height() ); gradient.setColorAt(0.0, titleBarColor.lighter( 120 ) ); gradient.setColorAt(0.8, titleBarColor); painter->setBrush(gradient); } else { painter->setBrush( titleBarColor() ); } auto s = settings(); if( isMaximized() || !s->isAlphaChannelSupported() ) { painter->drawRect(titleRect); } else if( c->isShaded() ) { painter->drawRoundedRect(titleRect, Metrics::Frame_FrameRadius, Metrics::Frame_FrameRadius); } else { painter->setClipRect(titleRect, Qt::IntersectClip); // the rect is made a little bit larger to be able to clip away the rounded corners at the bottom and sides painter->drawRoundedRect(titleRect.adjusted( isLeftEdge() ? -Metrics::Frame_FrameRadius:0, isTopEdge() ? -Metrics::Frame_FrameRadius:0, isRightEdge() ? Metrics::Frame_FrameRadius:0, Metrics::Frame_FrameRadius), Metrics::Frame_FrameRadius, Metrics::Frame_FrameRadius); } const QColor outlineColor( this->outlineColor() ); if( !c->isShaded() && outlineColor.isValid() ) { // outline painter->setRenderHint( QPainter::Antialiasing, false ); painter->setBrush( Qt::NoBrush ); painter->setPen( outlineColor ); painter->drawLine( titleRect.bottomLeft(), titleRect.bottomRight() ); } painter->restore(); // draw caption painter->setFont(s->font()); painter->setPen( fontColor() ); const auto cR = captionRect(); const QString caption = painter->fontMetrics().elidedText(c->caption(), Qt::ElideMiddle, cR.first.width()); painter->drawText(cR.first, cR.second | Qt::TextSingleLine, caption); // draw all buttons m_leftButtons->paint(painter, repaintRegion); m_rightButtons->paint(painter, repaintRegion); } //________________________________________________________________ int Decoration::buttonHeight() const { const int baseSize = settings()->gridUnit(); switch( m_internalSettings->buttonSize() ) { case InternalSettings::ButtonTiny: return baseSize; case InternalSettings::ButtonSmall: return baseSize*1.5; default: case InternalSettings::ButtonDefault: return baseSize*2; case InternalSettings::ButtonLarge: return baseSize*2.5; case InternalSettings::ButtonVeryLarge: return baseSize*3.5; } } //________________________________________________________________ int Decoration::captionHeight() const { return hideTitleBar() ? borderTop() : borderTop() - settings()->smallSpacing()*(Metrics::TitleBar_BottomMargin + Metrics::TitleBar_TopMargin ) - 1; } //________________________________________________________________ QPair Decoration::captionRect() const { if( hideTitleBar() ) return qMakePair( QRect(), Qt::AlignCenter ); else { auto c = client().data(); const int leftOffset = m_leftButtons->buttons().isEmpty() ? Metrics::TitleBar_SideMargin*settings()->smallSpacing(): m_leftButtons->geometry().x() + m_leftButtons->geometry().width() + Metrics::TitleBar_SideMargin*settings()->smallSpacing(); const int rightOffset = m_rightButtons->buttons().isEmpty() ? Metrics::TitleBar_SideMargin*settings()->smallSpacing() : size().width() - m_rightButtons->geometry().x() + Metrics::TitleBar_SideMargin*settings()->smallSpacing(); const int yOffset = settings()->smallSpacing()*Metrics::TitleBar_TopMargin; const QRect maxRect( leftOffset, yOffset, size().width() - leftOffset - rightOffset, captionHeight() ); switch( m_internalSettings->titleAlignment() ) { case InternalSettings::AlignLeft: return qMakePair( maxRect, Qt::AlignVCenter|Qt::AlignLeft ); case InternalSettings::AlignRight: return qMakePair( maxRect, Qt::AlignVCenter|Qt::AlignRight ); case InternalSettings::AlignCenter: return qMakePair( maxRect, Qt::AlignCenter ); default: case InternalSettings::AlignCenterFullWidth: { // full caption rect const QRect fullRect = QRect( 0, yOffset, size().width(), captionHeight() ); QRect boundingRect( settings()->fontMetrics().boundingRect( c->caption()).toRect() ); // text bounding rect boundingRect.setTop( yOffset ); boundingRect.setHeight( captionHeight() ); boundingRect.moveLeft( ( size().width() - boundingRect.width() )/2 ); if( boundingRect.left() < leftOffset ) return qMakePair( maxRect, Qt::AlignVCenter|Qt::AlignLeft ); else if( boundingRect.right() > size().width() - rightOffset ) return qMakePair( maxRect, Qt::AlignVCenter|Qt::AlignRight ); else return qMakePair(fullRect, Qt::AlignCenter); } } } } //________________________________________________________________ void Decoration::createShadow() { if (!g_sShadow ||g_shadowSizeEnum != m_internalSettings->shadowSize() || g_shadowStrength != m_internalSettings->shadowStrength() || g_shadowColor != m_internalSettings->shadowColor()) { g_shadowSizeEnum = m_internalSettings->shadowSize(); g_shadowStrength = m_internalSettings->shadowStrength(); g_shadowColor = m_internalSettings->shadowColor(); const CompositeShadowParams params = lookupShadowParams(g_shadowSizeEnum); if (params.isNone()) { g_sShadow.clear(); setShadow(g_sShadow); return; } auto withOpacity = [](const QColor &color, qreal opacity) -> QColor { QColor c(color); c.setAlphaF(opacity); return c; }; const QSize boxSize = BoxShadowRenderer::calculateMinimumBoxSize(params.shadow1.radius) .expandedTo(BoxShadowRenderer::calculateMinimumBoxSize(params.shadow2.radius)); BoxShadowRenderer shadowRenderer; shadowRenderer.setBorderRadius(Metrics::Frame_FrameRadius + 0.5); shadowRenderer.setBoxSize(boxSize); shadowRenderer.setDevicePixelRatio(1.0); // TODO: Create HiDPI shadows? const qreal strength = static_cast(g_shadowStrength) / 255.0; shadowRenderer.addShadow(params.shadow1.offset, params.shadow1.radius, withOpacity(g_shadowColor, params.shadow1.opacity * strength)); shadowRenderer.addShadow(params.shadow2.offset, params.shadow2.radius, withOpacity(g_shadowColor, params.shadow2.opacity * strength)); QImage shadowTexture = shadowRenderer.render(); QPainter painter(&shadowTexture); painter.setRenderHint(QPainter::Antialiasing); const 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 QRect innerRect = outerRect - padding; painter.setPen(Qt::NoPen); painter.setBrush(Qt::black); painter.setCompositionMode(QPainter::CompositionMode_DestinationOut); painter.drawRoundedRect( innerRect, Metrics::Frame_FrameRadius + 0.5, Metrics::Frame_FrameRadius + 0.5); // Draw outline. painter.setPen(withOpacity(g_shadowColor, 0.2 * strength)); painter.setBrush(Qt::NoBrush); painter.setCompositionMode(QPainter::CompositionMode_SourceOver); painter.drawRoundedRect( innerRect, Metrics::Frame_FrameRadius - 0.5, Metrics::Frame_FrameRadius - 0.5); painter.end(); g_sShadow = QSharedPointer::create(); g_sShadow->setPadding(padding); g_sShadow->setInnerShadowRect(QRect(outerRect.center(), QSize(1, 1))); g_sShadow->setShadow(shadowTexture); } setShadow(g_sShadow); } //_________________________________________________________________ void Decoration::createSizeGrip() { // do nothing if size grip already exist if( m_sizeGrip ) return; #if BREEZE_HAVE_X11 if( !QX11Info::isPlatformX11() ) return; // access client auto c = client().data(); if( !c ) return; if( c->windowId() != 0 ) { m_sizeGrip = new SizeGrip( this ); connect( c, &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::updateSizeGripVisibility ); connect( c, &KDecoration2::DecoratedClient::shadedChanged, this, &Decoration::updateSizeGripVisibility ); connect( c, &KDecoration2::DecoratedClient::resizeableChanged, this, &Decoration::updateSizeGripVisibility ); } #endif } //_________________________________________________________________ void Decoration::deleteSizeGrip() { if( m_sizeGrip ) { m_sizeGrip->deleteLater(); m_sizeGrip = nullptr; } } } // namespace #include "breezedecoration.moc" diff --git a/kdecoration/breezedecoration.h b/kdecoration/breezedecoration.h index 3c535b52..0518bf25 100644 --- a/kdecoration/breezedecoration.h +++ b/kdecoration/breezedecoration.h @@ -1,199 +1,197 @@ #ifndef BREEZE_DECORATION_H #define BREEZE_DECORATION_H /* * Copyright 2014 Martin Gräßlin * Copyright 2014 Hugo Pereira Da Costa * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "breeze.h" #include "breezesettings.h" #include #include #include #include -#include #include +class QVariantAnimation; + namespace KDecoration2 { class DecorationButton; class DecorationButtonGroup; } namespace Breeze { class SizeGrip; class Decoration : public KDecoration2::Decoration { Q_OBJECT - //* declare active state opacity - Q_PROPERTY( qreal opacity READ opacity WRITE setOpacity ) - public: //* constructor explicit Decoration(QObject *parent = nullptr, const QVariantList &args = QVariantList()); //* destructor virtual ~Decoration(); //* paint void paint(QPainter *painter, const QRect &repaintRegion) override; //* internal settings InternalSettingsPtr internalSettings() const { return m_internalSettings; } //* caption height int captionHeight() const; //* button height int buttonHeight() const; //*@name active state change animation //@{ void setOpacity( qreal ); qreal opacity() const { return m_opacity; } //@} //*@name colors //@{ QColor titleBarColor() const; QColor outlineColor() const; QColor fontColor() const; //@} //*@name maximization modes //@{ inline bool isMaximized() const; inline bool isMaximizedHorizontally() const; inline bool isMaximizedVertically() const; inline bool isLeftEdge() const; inline bool isRightEdge() const; inline bool isTopEdge() const; inline bool isBottomEdge() const; inline bool hideTitleBar() const; //@} public Q_SLOTS: void init() override; private Q_SLOTS: void reconfigure(); void recalculateBorders(); void updateButtonsGeometry(); void updateButtonsGeometryDelayed(); void updateTitleBar(); void updateAnimationState(); void updateSizeGripVisibility(); private: //* return the rect in which caption will be drawn QPair captionRect() const; void createButtons(); void paintTitleBar(QPainter *painter, const QRect &repaintRegion); void createShadow(); //*@name border size //@{ int borderSize(bool bottom = false) const; inline bool hasBorders() const; inline bool hasNoBorders() const; inline bool hasNoSideBorders() const; //@} //*@name size grip //@{ void createSizeGrip(); void deleteSizeGrip(); SizeGrip* sizeGrip() const { return m_sizeGrip; } //@} InternalSettingsPtr m_internalSettings; KDecoration2::DecorationButtonGroup *m_leftButtons = nullptr; KDecoration2::DecorationButtonGroup *m_rightButtons = nullptr; //* size grip widget SizeGrip *m_sizeGrip = nullptr; //* active state change animation - QPropertyAnimation *m_animation; + QVariantAnimation *m_animation; //* active state change opacity qreal m_opacity = 0; }; bool Decoration::hasBorders() const { if( m_internalSettings && m_internalSettings->mask() & BorderSize ) return m_internalSettings->borderSize() > InternalSettings::BorderNoSides; else return settings()->borderSize() > KDecoration2::BorderSize::NoSides; } bool Decoration::hasNoBorders() const { if( m_internalSettings && m_internalSettings->mask() & BorderSize ) return m_internalSettings->borderSize() == InternalSettings::BorderNone; else return settings()->borderSize() == KDecoration2::BorderSize::None; } bool Decoration::hasNoSideBorders() const { if( m_internalSettings && m_internalSettings->mask() & BorderSize ) return m_internalSettings->borderSize() == InternalSettings::BorderNoSides; else return settings()->borderSize() == KDecoration2::BorderSize::NoSides; } bool Decoration::isMaximized() const { return client().data()->isMaximized() && !m_internalSettings->drawBorderOnMaximizedWindows(); } bool Decoration::isMaximizedHorizontally() const { return client().data()->isMaximizedHorizontally() && !m_internalSettings->drawBorderOnMaximizedWindows(); } bool Decoration::isMaximizedVertically() const { return client().data()->isMaximizedVertically() && !m_internalSettings->drawBorderOnMaximizedWindows(); } bool Decoration::isLeftEdge() const { return (client().data()->isMaximizedHorizontally() || client().data()->adjacentScreenEdges().testFlag( Qt::LeftEdge ) ) && !m_internalSettings->drawBorderOnMaximizedWindows(); } bool Decoration::isRightEdge() const { return (client().data()->isMaximizedHorizontally() || client().data()->adjacentScreenEdges().testFlag( Qt::RightEdge ) ) && !m_internalSettings->drawBorderOnMaximizedWindows(); } bool Decoration::isTopEdge() const { return (client().data()->isMaximizedVertically() || client().data()->adjacentScreenEdges().testFlag( Qt::TopEdge ) ) && !m_internalSettings->drawBorderOnMaximizedWindows(); } bool Decoration::isBottomEdge() const { return (client().data()->isMaximizedVertically() || client().data()->adjacentScreenEdges().testFlag( Qt::BottomEdge ) ) && !m_internalSettings->drawBorderOnMaximizedWindows(); } bool Decoration::hideTitleBar() const { return m_internalSettings->hideTitleBar() && !client().data()->isShaded(); } } #endif