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