Changeset View
Changeset View
Standalone View
Standalone View
kdecoration/breezedecoration.cpp
Show All 23 Lines | |||||
24 | #include "breeze.h" | 24 | #include "breeze.h" | ||
25 | #include "breezesettingsprovider.h" | 25 | #include "breezesettingsprovider.h" | ||
26 | #include "config-breeze.h" | 26 | #include "config-breeze.h" | ||
27 | #include "config/breezeconfigwidget.h" | 27 | #include "config/breezeconfigwidget.h" | ||
28 | 28 | | |||
29 | #include "breezebutton.h" | 29 | #include "breezebutton.h" | ||
30 | #include "breezesizegrip.h" | 30 | #include "breezesizegrip.h" | ||
31 | 31 | | |||
32 | #include "breezeboxshadowhelper.h" | ||||
33 | | ||||
32 | #include <KDecoration2/DecoratedClient> | 34 | #include <KDecoration2/DecoratedClient> | ||
33 | #include <KDecoration2/DecorationButtonGroup> | 35 | #include <KDecoration2/DecorationButtonGroup> | ||
34 | #include <KDecoration2/DecorationSettings> | 36 | #include <KDecoration2/DecorationSettings> | ||
35 | #include <KDecoration2/DecorationShadow> | 37 | #include <KDecoration2/DecorationShadow> | ||
36 | 38 | | |||
37 | #include <KConfigGroup> | 39 | #include <KConfigGroup> | ||
38 | #include <KColorUtils> | 40 | #include <KColorUtils> | ||
39 | #include <KSharedConfig> | 41 | #include <KSharedConfig> | ||
Show All 25 Lines | 63 | { | |||
65 | 67 | | |||
66 | //________________________________________________________________ | 68 | //________________________________________________________________ | ||
67 | static int g_sDecoCount = 0; | 69 | static int g_sDecoCount = 0; | ||
68 | static int g_shadowSizeEnum = InternalSettings::ShadowLarge; | 70 | static int g_shadowSizeEnum = InternalSettings::ShadowLarge; | ||
69 | static int g_shadowStrength = 90; | 71 | static int g_shadowStrength = 90; | ||
70 | static QColor g_shadowColor = Qt::black; | 72 | static QColor g_shadowColor = Qt::black; | ||
71 | static QSharedPointer<KDecoration2::DecorationShadow> g_sShadow; | 73 | static QSharedPointer<KDecoration2::DecorationShadow> g_sShadow; | ||
72 | 74 | | |||
75 | struct ShadowParam { | ||||
76 | struct { | ||||
77 | int left; | ||||
78 | int top; | ||||
79 | } offset; | ||||
80 | | ||||
81 | struct { | ||||
82 | int radius; | ||||
83 | } shadow1 | ||||
84 | , shadow2; | ||||
85 | }; | ||||
86 | | ||||
87 | static const ShadowParam s_shadowParams[] = { | ||||
88 | { | ||||
89 | // Small | ||||
90 | .offset = { | ||||
91 | .left = 0, | ||||
92 | .top = 6 | ||||
93 | }, | ||||
94 | .shadow1 = { | ||||
95 | .radius = 16 | ||||
96 | }, | ||||
97 | .shadow2 = { | ||||
98 | .radius = 4 | ||||
99 | } | ||||
100 | }, | ||||
101 | { | ||||
102 | // Medium | ||||
103 | .offset = { | ||||
104 | .left = 0, | ||||
105 | .top = 12 | ||||
106 | }, | ||||
107 | .shadow1 = { | ||||
108 | .radius = 32 | ||||
109 | }, | ||||
110 | .shadow2 = { | ||||
111 | .radius = 16 | ||||
112 | } | ||||
113 | }, | ||||
114 | { | ||||
115 | // Large | ||||
116 | .offset = { | ||||
117 | .left = 0, | ||||
118 | .top = 20 | ||||
119 | }, | ||||
120 | .shadow1 = { | ||||
121 | .radius = 64 | ||||
122 | }, | ||||
123 | .shadow2 = { | ||||
124 | .radius = 24 | ||||
125 | } | ||||
126 | }, | ||||
127 | { | ||||
128 | // Very large | ||||
129 | .offset = { | ||||
130 | .left = 0, | ||||
131 | .top = 34 | ||||
132 | }, | ||||
133 | .shadow1 = { | ||||
134 | .radius = 96 | ||||
135 | }, | ||||
136 | .shadow2 = { | ||||
137 | .radius = 28 | ||||
138 | } | ||||
139 | } | ||||
140 | }; | ||||
141 | | ||||
73 | //________________________________________________________________ | 142 | //________________________________________________________________ | ||
74 | Decoration::Decoration(QObject *parent, const QVariantList &args) | 143 | Decoration::Decoration(QObject *parent, const QVariantList &args) | ||
75 | : KDecoration2::Decoration(parent, args) | 144 | : KDecoration2::Decoration(parent, args) | ||
76 | , m_animation( new QPropertyAnimation( this ) ) | 145 | , m_animation( new QPropertyAnimation( this ) ) | ||
77 | { | 146 | { | ||
78 | g_sDecoCount++; | 147 | g_sDecoCount++; | ||
79 | } | 148 | } | ||
80 | 149 | | |||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Line(s) | 221 | { | |||
196 | connect(c, &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::setOpaque); | 265 | connect(c, &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::setOpaque); | ||
197 | 266 | | |||
198 | connect(c, &KDecoration2::DecoratedClient::widthChanged, this, &Decoration::updateButtonsGeometry); | 267 | connect(c, &KDecoration2::DecoratedClient::widthChanged, this, &Decoration::updateButtonsGeometry); | ||
199 | connect(c, &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::updateButtonsGeometry); | 268 | connect(c, &KDecoration2::DecoratedClient::maximizedChanged, this, &Decoration::updateButtonsGeometry); | ||
200 | connect(c, &KDecoration2::DecoratedClient::adjacentScreenEdgesChanged, this, &Decoration::updateButtonsGeometry); | 269 | connect(c, &KDecoration2::DecoratedClient::adjacentScreenEdgesChanged, this, &Decoration::updateButtonsGeometry); | ||
201 | connect(c, &KDecoration2::DecoratedClient::shadedChanged, this, &Decoration::updateButtonsGeometry); | 270 | connect(c, &KDecoration2::DecoratedClient::shadedChanged, this, &Decoration::updateButtonsGeometry); | ||
202 | 271 | | |||
203 | createButtons(); | 272 | createButtons(); | ||
204 | createShadow(); | 273 | updateShadow(true); | ||
205 | } | 274 | } | ||
206 | 275 | | |||
207 | //________________________________________________________________ | 276 | //________________________________________________________________ | ||
208 | void Decoration::updateTitleBar() | 277 | void Decoration::updateTitleBar() | ||
209 | { | 278 | { | ||
210 | auto s = settings(); | 279 | auto s = settings(); | ||
211 | auto c = client().data(); | 280 | auto c = client().data(); | ||
212 | const bool maximized = isMaximized(); | 281 | const bool maximized = isMaximized(); | ||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Line(s) | 354 | { | |||
288 | 357 | | |||
289 | // animation | 358 | // animation | ||
290 | m_animation->setDuration( m_internalSettings->animationsDuration() ); | 359 | m_animation->setDuration( m_internalSettings->animationsDuration() ); | ||
291 | 360 | | |||
292 | // borders | 361 | // borders | ||
293 | recalculateBorders(); | 362 | recalculateBorders(); | ||
294 | 363 | | |||
295 | // shadow | 364 | // shadow | ||
296 | createShadow(); | 365 | updateShadow(); | ||
297 | 366 | | |||
298 | // size grip | 367 | // size grip | ||
299 | if( hasNoBorders() && m_internalSettings->drawSizeGrip() ) createSizeGrip(); | 368 | if( hasNoBorders() && m_internalSettings->drawSizeGrip() ) createSizeGrip(); | ||
300 | else deleteSizeGrip(); | 369 | else deleteSizeGrip(); | ||
301 | 370 | | |||
302 | } | 371 | } | ||
303 | 372 | | |||
304 | //________________________________________________________________ | 373 | //________________________________________________________________ | ||
▲ Show 20 Lines • Show All 310 Lines • ▼ Show 20 Line(s) | 641 | else { | |||
615 | 684 | | |||
616 | } | 685 | } | ||
617 | 686 | | |||
618 | } | 687 | } | ||
619 | 688 | | |||
620 | } | 689 | } | ||
621 | 690 | | |||
622 | //________________________________________________________________ | 691 | //________________________________________________________________ | ||
623 | void Decoration::createShadow() | 692 | void Decoration::updateShadow(bool forced) | ||
624 | { | 693 | { | ||
625 | 694 | if (g_shadowSizeEnum != m_internalSettings->shadowSize() | |||
626 | // assign global shadow if exists and parameters match | 695 | || g_shadowStrength != m_internalSettings->shadowStrength() | ||
627 | if( | 696 | || g_shadowColor != m_internalSettings->shadowColor() | ||
628 | !g_sShadow || | 697 | || forced) | ||
629 | g_shadowSizeEnum != m_internalSettings->shadowSize() || | | |||
630 | g_shadowStrength != m_internalSettings->shadowStrength() || | | |||
631 | g_shadowColor != m_internalSettings->shadowColor() | | |||
632 | ) | | |||
633 | { | 698 | { | ||
634 | // assign parameters | | |||
635 | g_shadowSizeEnum = m_internalSettings->shadowSize(); | 699 | g_shadowSizeEnum = m_internalSettings->shadowSize(); | ||
636 | g_shadowStrength = m_internalSettings->shadowStrength(); | 700 | g_shadowStrength = m_internalSettings->shadowStrength(); // TODO: take shadow strength into account | ||
637 | g_shadowColor = m_internalSettings->shadowColor(); | 701 | g_shadowColor = m_internalSettings->shadowColor(); | ||
638 | 702 | | |||
639 | // shadow size from enum | 703 | ShadowParam params; | ||
640 | int shadowSize = 0; | | |||
641 | switch( g_shadowSizeEnum ) | | |||
642 | { | | |||
643 | default: | | |||
644 | case InternalSettings::ShadowLarge: shadowSize = 64; break; | | |||
645 | 704 | | |||
646 | case InternalSettings::ShadowNone: shadowSize = Metrics::Shadow_Overlap + 1; break; | 705 | switch (g_shadowSizeEnum) { | ||
647 | case InternalSettings::ShadowSmall: shadowSize = 16; break; | 706 | case InternalSettings::ShadowNone: | ||
648 | case InternalSettings::ShadowMedium: shadowSize = 32; break; | 707 | g_sShadow.clear(); | ||
649 | case InternalSettings::ShadowVeryLarge: shadowSize = 96; break; | 708 | setShadow(g_sShadow); | ||
709 | return; | ||||
710 | case InternalSettings::ShadowSmall: | ||||
711 | params = s_shadowParams[0]; | ||||
712 | break; | ||||
713 | case InternalSettings::ShadowMedium: | ||||
714 | params = s_shadowParams[1]; | ||||
715 | break; | ||||
716 | case InternalSettings::ShadowLarge: | ||||
717 | params = s_shadowParams[2]; | ||||
718 | break; | ||||
719 | case InternalSettings::ShadowVeryLarge: | ||||
720 | params = s_shadowParams[3]; | ||||
721 | break; | ||||
722 | default: | ||||
723 | // fallback to Large | ||||
724 | params = s_shadowParams[2]; | ||||
725 | break; | ||||
650 | } | 726 | } | ||
651 | 727 | | |||
652 | // offset | 728 | auto withAlpha = [](const QColor &color, int alpha) -> QColor { | ||
653 | int shadowOffset = (g_shadowSizeEnum == InternalSettings::ShadowNone) ? 0 : qMax( 6*shadowSize/16, Metrics::Shadow_Overlap*2 ); | 729 | QColor c(color); | ||
654 | 730 | c.setAlpha(alpha); | |||
655 | // create image | 731 | return c; | ||
656 | QImage image(2*shadowSize, 2*shadowSize, QImage::Format_ARGB32_Premultiplied); | | |||
657 | image.fill(Qt::transparent); | | |||
658 | | ||||
659 | // painter | | |||
660 | QPainter painter(&image); | | |||
661 | painter.setRenderHint( QPainter::Antialiasing, true ); | | |||
662 | | ||||
663 | // color calculation delta function | | |||
664 | auto gradientStopColor = [](QColor color, int alpha) | | |||
665 | { | | |||
666 | color.setAlpha(alpha); | | |||
667 | return color; | | |||
668 | }; | 732 | }; | ||
669 | 733 | | |||
670 | // create gradient | 734 | // The box size should be at least `2 * QSize(shadowSize, shadowSize)` | ||
671 | if( g_shadowSizeEnum != InternalSettings::ShadowNone ) | 735 | // in order to properly render a box shadow with a given radius | ||
672 | { | 736 | // `shadowSize`. | ||
673 | 737 | int shadowSize = qMax(params.shadow1.radius, params.shadow2.radius); | |||
674 | // gaussian lambda function | 738 | QSize boxSize = 2 * QSize(shadowSize, shadowSize) + QSize(1, 1); | ||
675 | auto alpha = [](qreal x) { return std::exp( -x*x/0.15 ); }; | 739 | QRect rect(QPoint(0, 0), boxSize + 2 * QSize(shadowSize, shadowSize)); | ||
676 | 740 | | |||
677 | QRadialGradient radialGradient( shadowSize, shadowSize, shadowSize ); | 741 | QImage shadow(rect.size(), QImage::Format_ARGB32_Premultiplied); | ||
678 | for( int i = 0; i < 10; ++i ) | 742 | shadow.fill(Qt::transparent); | ||
679 | { | 743 | | ||
680 | const qreal x( qreal( i )/9 ); | 744 | QPainter painter(&shadow); | ||
681 | radialGradient.setColorAt(x, gradientStopColor( g_shadowColor, alpha(x)*g_shadowStrength ) ); | 745 | painter.setRenderHint(QPainter::Antialiasing); | ||
682 | } | 746 | | ||
683 | 747 | // draw "shape" shadow | |||
684 | radialGradient.setColorAt(1, gradientStopColor( g_shadowColor, 0 ) ); | 748 | QImage shadow1 = BoxShadowHelper::boxShadow( | ||
685 | 749 | boxSize, | |||
686 | // fill | 750 | params.shadow1.radius, | ||
687 | painter.fillRect( image.rect(), radialGradient); | 751 | withAlpha(g_shadowColor, 255)); | ||
688 | 752 | QRect shadow1Rect = shadow1.rect(); | |||
689 | } | 753 | shadow1Rect.moveCenter(rect.center()); | ||
690 | 754 | painter.drawImage(shadow1Rect, shadow1); | |||
691 | // contrast pixel | 755 | | ||
692 | QRectF innerRect = QRectF( | 756 | // draw "contrast" shadow | ||
693 | shadowSize - Metrics::Shadow_Overlap, shadowSize - shadowOffset - Metrics::Shadow_Overlap, | 757 | QImage shadow2 = BoxShadowHelper::boxShadow( | ||
694 | 2*Metrics::Shadow_Overlap, shadowOffset + 2*Metrics::Shadow_Overlap ); | 758 | boxSize, | ||
695 | 759 | params.shadow2.radius, | |||
696 | painter.setPen( gradientStopColor( g_shadowColor, (g_shadowSizeEnum == InternalSettings::ShadowNone) ? g_shadowStrength:(g_shadowStrength*0.5) ) ); | 760 | withAlpha(g_shadowColor, 25)); | ||
697 | painter.setBrush( Qt::NoBrush ); | 761 | QRect shadow2Rect = shadow2.rect(); | ||
698 | painter.drawRoundedRect( innerRect, -0.5 + Metrics::Frame_FrameRadius, -0.5 + Metrics::Frame_FrameRadius ); | 762 | shadow2Rect.moveCenter(rect.center()); | ||
763 | painter.drawImage(shadow2Rect, shadow2); | ||||
699 | 764 | | |||
700 | // mask out inner rect | 765 | // mask out inner rect | ||
766 | QMargins padding = QMargins( | ||||
767 | shadowSize - Metrics::Shadow_Overlap - params.offset.left, | ||||
768 | shadowSize - Metrics::Shadow_Overlap - params.offset.top, | ||||
769 | shadowSize - Metrics::Shadow_Overlap + params.offset.left, | ||||
770 | shadowSize - Metrics::Shadow_Overlap + params.offset.top); | ||||
771 | | ||||
701 | painter.setPen( Qt::NoPen ); | 772 | painter.setPen(Qt::NoPen); | ||
702 | painter.setBrush( Qt::black ); | 773 | painter.setBrush(Qt::black); | ||
703 | painter.setCompositionMode(QPainter::CompositionMode_DestinationOut ); | 774 | painter.setCompositionMode(QPainter::CompositionMode_DestinationOut); | ||
704 | painter.drawRoundedRect( innerRect, 0.5 + Metrics::Frame_FrameRadius, 0.5 + Metrics::Frame_FrameRadius ); | 775 | painter.drawRoundedRect( | ||
776 | rect - padding, | ||||
777 | Metrics::Frame_FrameRadius + 0.5, | ||||
778 | Metrics::Frame_FrameRadius + 0.5); | ||||
779 | | ||||
780 | // draw pixel contrast | ||||
781 | painter.setPen(withAlpha(g_shadowColor, 20)); | ||||
782 | painter.setBrush(Qt::NoBrush); | ||||
783 | painter.setCompositionMode(QPainter::CompositionMode_SourceOver); | ||||
784 | painter.drawRoundedRect( | ||||
785 | rect - padding, | ||||
786 | Metrics::Frame_FrameRadius - 0.5, | ||||
787 | Metrics::Frame_FrameRadius - 0.5); | ||||
705 | 788 | | |||
706 | painter.end(); | 789 | painter.end(); | ||
707 | 790 | | |||
708 | g_sShadow = QSharedPointer<KDecoration2::DecorationShadow>::create(); | 791 | g_sShadow = QSharedPointer<KDecoration2::DecorationShadow>::create(); | ||
709 | g_sShadow->setPadding( QMargins( | 792 | g_sShadow->setPadding(padding); | ||
710 | shadowSize - Metrics::Shadow_Overlap, | 793 | g_sShadow->setInnerShadowRect(QRect(rect.center(), QSize(1, 1))); | ||
711 | shadowSize - shadowOffset - Metrics::Shadow_Overlap, | 794 | g_sShadow->setShadow(shadow); | ||
712 | shadowSize - Metrics::Shadow_Overlap, | | |||
713 | shadowSize - Metrics::Shadow_Overlap ) ); | | |||
714 | | ||||
715 | g_sShadow->setInnerShadowRect(QRect( shadowSize, shadowSize, 1, 1) ); | | |||
716 | | ||||
717 | // assign image | | |||
718 | g_sShadow->setShadow(image); | | |||
719 | | ||||
720 | } | 795 | } | ||
721 | 796 | | |||
722 | setShadow(g_sShadow); | 797 | setShadow(g_sShadow); | ||
723 | | ||||
724 | } | 798 | } | ||
725 | 799 | | |||
726 | //_________________________________________________________________ | 800 | //_________________________________________________________________ | ||
727 | void Decoration::createSizeGrip( void ) | 801 | void Decoration::createSizeGrip( void ) | ||
728 | { | 802 | { | ||
729 | 803 | | |||
730 | // do nothing if size grip already exist | 804 | // do nothing if size grip already exist | ||
731 | if( m_sizeGrip ) return; | 805 | if( m_sizeGrip ) return; | ||
Show All 33 Lines |