2018-11-30 21:33:46 +02:00
/*
* Copyright 2018 Michail Vourlakos < mvourlakos @ gmail . com >
*
* This file is part of Latte - Dock
*
* Latte - Dock 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 ) any later version .
*
* Latte - Dock 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 < http : //www.gnu.org/licenses/>.
*/
# include "effects.h"
2018-12-02 02:05:52 +02:00
// local
2018-11-30 21:33:46 +02:00
# include "panelshadows_p.h"
2018-12-06 12:15:58 +02:00
# include "view.h"
2019-03-08 23:43:08 +02:00
# include "settings/primaryconfigview.h"
2018-12-07 18:55:35 +02:00
# include "../../liblatte2/types.h"
2018-11-30 21:33:46 +02:00
2018-12-02 02:05:52 +02:00
// Qt
2018-11-30 21:33:46 +02:00
# include <QRegion>
2018-12-02 02:05:52 +02:00
// KDE
2018-11-30 21:33:46 +02:00
# include <KWindowEffects>
# include <KWindowSystem>
namespace Latte {
2018-12-06 11:37:14 +02:00
namespace ViewPart {
2018-11-30 21:33:46 +02:00
2018-12-06 12:15:58 +02:00
Effects : : Effects ( Latte : : View * parent )
2018-11-30 21:33:46 +02:00
: QObject ( parent ) ,
m_view ( parent )
{
init ( ) ;
}
Effects : : ~ Effects ( )
{
}
void Effects : : init ( )
{
2018-12-01 09:29:20 +02:00
connect ( this , & Effects : : backgroundOpacityChanged , this , & Effects : : updateEffects ) ;
2018-11-30 21:33:46 +02:00
connect ( this , & Effects : : drawEffectsChanged , this , & Effects : : updateEffects ) ;
2018-12-01 00:26:56 +02:00
connect ( this , & Effects : : rectChanged , this , & Effects : : updateEffects ) ;
2019-03-08 23:43:08 +02:00
connect ( this , & Effects : : settingsMaskSubtractedChanged , this , & Effects : : updateMask ) ;
2018-11-30 21:33:46 +02:00
connect ( this , & Effects : : drawShadowsChanged , this , [ & ] ( ) {
if ( m_view - > behaveAsPlasmaPanel ( ) ) {
updateEnabledBorders ( ) ;
}
} ) ;
2018-12-06 12:15:58 +02:00
connect ( m_view , & Latte : : View : : alignmentChanged , this , & Effects : : updateEnabledBorders ) ;
connect ( m_view , & Latte : : View : : behaveAsPlasmaPanelChanged , this , & Effects : : updateEffects ) ;
connect ( m_view , & Latte : : View : : behaveAsPlasmaPanelChanged , this , & Effects : : updateShadows ) ;
2019-03-08 23:43:08 +02:00
connect ( m_view , & Latte : : View : : configWindowGeometryChanged , this , & Effects : : updateMask ) ;
2019-06-16 15:31:37 +03:00
connect ( & m_theme , & Plasma : : Theme : : themeChanged , this , [ & ] ( ) {
updateBackgroundContrastValues ( ) ;
updateEffects ( ) ;
} ) ;
2018-11-30 21:33:46 +02:00
}
2018-12-01 09:42:09 +02:00
bool Effects : : animationsBlocked ( ) const
{
return m_animationsBlocked ;
}
void Effects : : setAnimationsBlocked ( bool blocked )
{
if ( m_animationsBlocked = = blocked ) {
return ;
}
m_animationsBlocked = blocked ;
emit animationsBlockedChanged ( ) ;
}
2018-11-30 21:33:46 +02:00
bool Effects : : drawShadows ( ) const
{
return m_drawShadows ;
}
void Effects : : setDrawShadows ( bool draw )
{
if ( m_drawShadows = = draw ) {
return ;
}
m_drawShadows = draw ;
if ( m_view - > behaveAsPlasmaPanel ( ) & & m_drawShadows ) {
PanelShadows : : self ( ) - > addWindow ( m_view , m_enabledBorders ) ;
} else {
PanelShadows : : self ( ) - > removeWindow ( m_view ) ;
}
emit drawShadowsChanged ( ) ;
}
bool Effects : : drawEffects ( ) const
{
return m_drawEffects ;
}
void Effects : : setDrawEffects ( bool draw )
{
if ( m_drawEffects = = draw ) {
return ;
}
m_drawEffects = draw ;
emit drawEffectsChanged ( ) ;
}
bool Effects : : forceDrawCenteredBorders ( ) const
{
return m_forceDrawCenteredBorders ;
}
void Effects : : setForceDrawCenteredBorders ( bool draw )
{
if ( m_forceDrawCenteredBorders = = draw ) {
return ;
}
m_forceDrawCenteredBorders = draw ;
}
2018-12-01 09:29:20 +02:00
int Effects : : backgroundOpacity ( ) const
{
return m_backgroundOpacity ;
}
void Effects : : setBackgroundOpacity ( int opacity )
{
if ( m_backgroundOpacity = = opacity ) {
return ;
}
m_backgroundOpacity = opacity ;
2019-06-16 15:31:37 +03:00
updateBackgroundContrastValues ( ) ;
2018-12-01 09:29:20 +02:00
emit backgroundOpacityChanged ( ) ;
}
2019-03-09 12:23:51 +02:00
int Effects : : editShadow ( ) const
{
return m_editShadow ;
}
void Effects : : setEditShadow ( int shadow )
{
if ( m_editShadow = = shadow ) {
return ;
}
m_editShadow = shadow ;
emit editShadowChanged ( ) ;
}
2018-12-01 00:52:05 +02:00
int Effects : : innerShadow ( ) const
{
return m_innerShadow ;
}
void Effects : : setInnerShadow ( int shadow )
{
if ( m_innerShadow = = shadow )
return ;
m_innerShadow = shadow ;
emit innerShadowChanged ( ) ;
}
2019-03-08 23:43:08 +02:00
bool Effects : : settingsMaskSubtracted ( ) const
{
return m_settingsMaskSubtracted ;
}
void Effects : : setSettingsMaskSubtracted ( bool enabled )
{
if ( m_settingsMaskSubtracted = = enabled ) {
return ;
}
m_settingsMaskSubtracted = enabled ;
2019-04-11 16:55:45 +03:00
2019-03-08 23:43:08 +02:00
emit settingsMaskSubtractedChanged ( ) ;
}
QRegion Effects : : subtrackedMaskFromWindow ( QRegion initialRegion , QQuickView * window )
{
QRegion subtractedMask = initialRegion ;
2019-04-03 22:57:01 +03:00
int start ;
int length ;
if ( m_view - > formFactor ( ) = = Plasma : : Types : : Horizontal ) {
if ( KWindowSystem : : isPlatformX11 ( ) ) {
start = window - > x ( ) ;
length = window - > width ( ) ;
} else {
start = m_view - > x ( ) ;
length = m_view - > width ( ) ;
}
} else {
if ( KWindowSystem : : isPlatformX11 ( ) ) {
start = window - > y ( ) ;
length = window - > height ( ) ;
} else {
start = m_view - > y ( ) ;
length = m_view - > height ( ) ;
}
}
2019-03-08 23:43:08 +02:00
if ( m_settingsMaskSubtracted & & window ) {
QRect windowMask ;
//! we need to subtrack the mask areas that overlap with underlying window
switch ( m_view - > location ( ) ) {
2019-06-15 16:11:41 +03:00
case Plasma : : Types : : TopEdge :
windowMask . setTopLeft ( QPoint ( start - m_view - > x ( ) , m_mask . y ( ) + m_mask . height ( ) - m_editShadow ) ) ;
windowMask . setSize ( QSize ( length , m_editShadow ) ) ;
break ;
case Plasma : : Types : : LeftEdge :
windowMask . setTopLeft ( QPoint ( m_mask . right ( ) + 1 - m_editShadow , start - m_view - > y ( ) ) ) ;
windowMask . setSize ( QSize ( m_editShadow , length ) ) ;
break ;
case Plasma : : Types : : RightEdge :
windowMask . setTopLeft ( QPoint ( m_mask . x ( ) , start - m_view - > y ( ) ) ) ;
windowMask . setSize ( QSize ( m_editShadow , length ) ) ;
break ;
case Plasma : : Types : : BottomEdge :
windowMask . setTopLeft ( QPoint ( start - m_view - > x ( ) , m_mask . y ( ) ) ) ;
windowMask . setSize ( QSize ( length , m_editShadow ) ) ;
break ;
default :
break ;
2019-03-08 23:43:08 +02:00
}
subtractedMask = subtractedMask . subtracted ( windowMask ) ;
}
return subtractedMask ;
}
QRegion Effects : : subtractedMask ( )
{
QRegion subMask = m_mask ;
if ( m_settingsMaskSubtracted & & m_view - > configView ( ) ) {
subMask = subtrackedMaskFromWindow ( subMask , m_view - > configView ( ) ) ;
ViewPart : : PrimaryConfigView * primaryConfig = qobject_cast < ViewPart : : PrimaryConfigView * > ( m_view - > configView ( ) ) ;
2019-04-03 22:35:27 +03:00
if ( primaryConfig & & m_view - > formFactor ( ) = = Plasma : : Types : : Horizontal & & primaryConfig - > secondaryWindow ( ) ) {
2019-03-08 23:43:08 +02:00
subMask = subtrackedMaskFromWindow ( subMask , primaryConfig - > secondaryWindow ( ) ) ;
}
}
return subMask ;
}
2018-12-01 00:26:56 +02:00
QRect Effects : : rect ( ) const
2018-11-30 21:33:46 +02:00
{
2018-12-01 00:26:56 +02:00
return m_rect ;
2018-11-30 21:33:46 +02:00
}
2018-12-01 00:26:56 +02:00
void Effects : : setRect ( QRect area )
2018-11-30 21:33:46 +02:00
{
2019-03-03 19:07:20 +02:00
if ( KWindowSystem : : compositingActive ( ) ) {
QRect inWindowRect = area . intersected ( QRect ( 0 , 0 , m_view - > width ( ) , m_view - > height ( ) ) ) ;
2018-11-30 21:33:46 +02:00
2019-03-03 19:07:20 +02:00
if ( m_rect = = inWindowRect ) {
return ;
}
m_rect = inWindowRect ;
} else {
if ( m_rect = = area ) {
return ;
}
m_rect = area ;
2018-11-30 21:33:46 +02:00
}
2018-12-01 00:26:56 +02:00
emit rectChanged ( ) ;
2018-11-30 21:33:46 +02:00
}
2018-12-01 00:26:56 +02:00
QRect Effects : : mask ( ) const
2018-11-30 21:33:46 +02:00
{
2018-12-01 00:26:56 +02:00
return m_mask ;
2018-11-30 21:33:46 +02:00
}
2018-12-01 00:26:56 +02:00
void Effects : : setMask ( QRect area )
2018-11-30 21:33:46 +02:00
{
2019-06-15 15:43:12 +03:00
if ( m_mask = = area )
2018-11-30 21:33:46 +02:00
return ;
2018-12-01 00:26:56 +02:00
m_mask = area ;
2019-03-08 23:43:08 +02:00
updateMask ( ) ;
2018-11-30 21:33:46 +02:00
2019-03-08 23:43:08 +02:00
// qDebug() << "dock mask set:" << m_mask;
emit maskChanged ( ) ;
}
2019-04-16 23:51:06 +03:00
void Effects : : forceMaskRedraw ( )
{
if ( m_background ) {
delete m_background ;
}
m_background = new Plasma : : FrameSvg ( this ) ;
m_background - > setImagePath ( QStringLiteral ( " widgets/panel-background " ) ) ;
m_background - > setEnabledBorders ( m_enabledBorders ) ;
updateMask ( ) ;
}
2019-03-08 23:43:08 +02:00
void Effects : : updateMask ( )
{
2018-11-30 21:33:46 +02:00
if ( KWindowSystem : : compositingActive ( ) ) {
if ( m_view - > behaveAsPlasmaPanel ( ) ) {
m_view - > setMask ( QRect ( ) ) ;
} else {
2019-03-08 23:43:08 +02:00
m_view - > setMask ( subtractedMask ( ) ) ;
2018-11-30 21:33:46 +02:00
}
} else {
//! this is used when compositing is disabled and provides
//! the correct way for the mask to be painted in order for
//! rounded corners to be shown correctly
//! the enabledBorders check was added because there was cases
2019-01-01 11:19:44 +02:00
//! that the mask region wasn't calculated correctly after location changes
2019-04-16 23:51:06 +03:00
if ( ! m_background ) {
if ( m_background & & m_background - > enabledBorders ( ) ! = m_enabledBorders ) {
delete m_background ;
}
2018-11-30 21:33:46 +02:00
m_background = new Plasma : : FrameSvg ( this ) ;
}
2019-04-16 23:51:06 +03:00
if ( m_background - > imagePath ( ) ! = " widgets/panel-background " ) {
m_background - > setImagePath ( QStringLiteral ( " widgets/panel-background " ) ) ;
2018-11-30 21:33:46 +02:00
}
m_background - > setEnabledBorders ( m_enabledBorders ) ;
2019-03-08 23:43:08 +02:00
m_background - > resizeFrame ( m_mask . size ( ) ) ;
2018-11-30 21:33:46 +02:00
QRegion fixedMask = m_background - > mask ( ) ;
2018-12-01 00:26:56 +02:00
fixedMask . translate ( m_mask . x ( ) , m_mask . y ( ) ) ;
2018-11-30 21:33:46 +02:00
//! fix for KF5.32 that return empty QRegion's for the mask
if ( fixedMask . isEmpty ( ) ) {
2018-12-01 00:26:56 +02:00
fixedMask = QRegion ( m_mask ) ;
2018-11-30 21:33:46 +02:00
}
m_view - > setMask ( fixedMask ) ;
}
}
2018-12-01 10:18:56 +02:00
void Effects : : clearShadows ( )
{
PanelShadows : : self ( ) - > removeWindow ( m_view ) ;
}
void Effects : : updateShadows ( )
{
if ( m_view - > behaveAsPlasmaPanel ( ) & & drawShadows ( ) ) {
PanelShadows : : self ( ) - > addWindow ( m_view , enabledBorders ( ) ) ;
} else {
PanelShadows : : self ( ) - > removeWindow ( m_view ) ;
}
}
2018-11-30 21:33:46 +02:00
void Effects : : updateEffects ( )
{
//! Don't apply any effect before the wayland surface is created under wayland
//! https://bugs.kde.org/show_bug.cgi?id=392890
if ( KWindowSystem : : isPlatformWayland ( ) & & ! m_view - > surface ( ) ) {
return ;
}
2019-06-15 16:11:41 +03:00
if ( m_drawEffects & & ! m_rect . isNull ( ) & & ! m_rect . isEmpty ( ) ) {
//! this is used when compositing is disabled and provides
//! the correct way for the mask to be painted in order for
//! rounded corners to be shown correctly
if ( ! m_background ) {
m_background = new Plasma : : FrameSvg ( this ) ;
}
2018-11-30 21:33:46 +02:00
2019-06-15 16:11:41 +03:00
if ( m_background - > imagePath ( ) ! = " widgets/panel-background " ) {
m_background - > setImagePath ( QStringLiteral ( " widgets/panel-background " ) ) ;
}
2018-11-30 21:33:46 +02:00
2019-06-15 16:11:41 +03:00
m_background - > setEnabledBorders ( m_enabledBorders ) ;
m_background - > resizeFrame ( m_rect . size ( ) ) ;
QRegion fixedMask = m_background - > mask ( ) ;
fixedMask . translate ( m_rect . x ( ) , m_rect . y ( ) ) ;
2018-11-30 21:33:46 +02:00
2019-06-15 16:11:41 +03:00
//! fix1, for KF5.32 that return empty QRegion's for the mask
if ( fixedMask . isEmpty ( ) ) {
fixedMask = QRegion ( m_rect ) ;
2018-11-30 21:33:46 +02:00
}
2019-06-15 16:11:41 +03:00
KWindowEffects : : enableBlurBehind ( m_view - > winId ( ) , true , fixedMask ) ;
KWindowEffects : : enableBackgroundContrast ( m_view - > winId ( ) ,
2019-06-16 15:31:37 +03:00
m_theme . backgroundContrastEnabled ( ) ,
m_backEffectContrast ,
m_backEffectIntesity ,
m_backEffectSaturation ,
2019-06-15 16:11:41 +03:00
fixedMask ) ;
2018-11-30 21:33:46 +02:00
} else {
KWindowEffects : : enableBlurBehind ( m_view - > winId ( ) , false ) ;
KWindowEffects : : enableBackgroundContrast ( m_view - > winId ( ) , false ) ;
}
}
//!BEGIN draw panel shadows outside the dock window
Plasma : : FrameSvg : : EnabledBorders Effects : : enabledBorders ( ) const
{
return m_enabledBorders ;
}
2019-06-16 15:31:37 +03:00
qreal Effects : : currentMidValue ( const qreal & max , const qreal & factor , const qreal & min ) const
{
if ( max = = min | | factor = = 0 ) {
return min ;
}
qreal space = 0 ;
qreal distance = 0 ;
if ( max < min ) {
space = min - max ;
distance = factor * space ;
return 1 - distance ;
} else {
space = max - min ;
distance = factor * space ;
return 1 + distance ;
}
}
void Effects : : updateBackgroundContrastValues ( )
{
if ( ! m_theme . backgroundContrastEnabled ( ) ) {
m_backEffectContrast = 1 ;
m_backEffectIntesity = 1 ;
m_backEffectSaturation = 1 ;
return ;
}
const qreal factor = ( qreal ) m_backgroundOpacity / ( qreal ) 100 ;
m_backEffectContrast = currentMidValue ( m_theme . backgroundContrast ( ) , factor , 1 ) ;
m_backEffectIntesity = currentMidValue ( m_theme . backgroundIntensity ( ) , factor , 1 ) ;
m_backEffectSaturation = currentMidValue ( m_theme . backgroundSaturation ( ) , factor , 1 ) ;
}
2018-11-30 21:33:46 +02:00
void Effects : : updateEnabledBorders ( )
{
if ( ! m_view - > screen ( ) ) {
return ;
}
Plasma : : FrameSvg : : EnabledBorders borders = Plasma : : FrameSvg : : AllBorders ;
switch ( m_view - > location ( ) ) {
2019-06-15 16:11:41 +03:00
case Plasma : : Types : : TopEdge :
borders & = ~ Plasma : : FrameSvg : : TopBorder ;
break ;
2018-11-30 21:33:46 +02:00
2019-06-15 16:11:41 +03:00
case Plasma : : Types : : LeftEdge :
borders & = ~ Plasma : : FrameSvg : : LeftBorder ;
break ;
2018-11-30 21:33:46 +02:00
2019-06-15 16:11:41 +03:00
case Plasma : : Types : : RightEdge :
borders & = ~ Plasma : : FrameSvg : : RightBorder ;
break ;
2018-11-30 21:33:46 +02:00
2019-06-15 16:11:41 +03:00
case Plasma : : Types : : BottomEdge :
borders & = ~ Plasma : : FrameSvg : : BottomBorder ;
break ;
2018-11-30 21:33:46 +02:00
2019-06-15 16:11:41 +03:00
default :
break ;
2018-11-30 21:33:46 +02:00
}
if ( ( m_view - > location ( ) = = Plasma : : Types : : LeftEdge | | m_view - > location ( ) = = Plasma : : Types : : RightEdge ) ) {
2018-12-07 18:55:35 +02:00
if ( m_view - > maxLength ( ) = = 1 & & m_view - > alignment ( ) = = Latte : : Types : : Justify & & ! m_forceDrawCenteredBorders ) {
2018-11-30 21:33:46 +02:00
borders & = ~ Plasma : : FrameSvg : : TopBorder ;
borders & = ~ Plasma : : FrameSvg : : BottomBorder ;
}
2018-12-07 18:55:35 +02:00
if ( m_view - > alignment ( ) = = Latte : : Types : : Top & & ! m_forceDrawCenteredBorders & & m_view - > offset ( ) = = 0 ) {
2018-11-30 21:33:46 +02:00
borders & = ~ Plasma : : FrameSvg : : TopBorder ;
}
2018-12-07 18:55:35 +02:00
if ( m_view - > alignment ( ) = = Latte : : Types : : Bottom & & ! m_forceDrawCenteredBorders & & m_view - > offset ( ) = = 0 ) {
2018-11-30 21:33:46 +02:00
borders & = ~ Plasma : : FrameSvg : : BottomBorder ;
}
}
if ( m_view - > location ( ) = = Plasma : : Types : : TopEdge | | m_view - > location ( ) = = Plasma : : Types : : BottomEdge ) {
2018-12-07 18:55:35 +02:00
if ( m_view - > maxLength ( ) = = 1 & & m_view - > alignment ( ) = = Latte : : Types : : Justify ) {
2018-11-30 21:33:46 +02:00
borders & = ~ Plasma : : FrameSvg : : LeftBorder ;
borders & = ~ Plasma : : FrameSvg : : RightBorder ;
}
2018-12-07 18:55:35 +02:00
if ( m_view - > alignment ( ) = = Latte : : Types : : Left & & m_view - > offset ( ) = = 0 ) {
2018-11-30 21:33:46 +02:00
borders & = ~ Plasma : : FrameSvg : : LeftBorder ;
}
2018-12-07 18:55:35 +02:00
if ( m_view - > alignment ( ) = = Latte : : Types : : Right & & m_view - > offset ( ) = = 0 ) {
2018-11-30 21:33:46 +02:00
borders & = ~ Plasma : : FrameSvg : : RightBorder ;
}
}
if ( m_enabledBorders ! = borders ) {
m_enabledBorders = borders ;
emit enabledBordersChanged ( ) ;
}
if ( ! m_view - > behaveAsPlasmaPanel ( ) | | ! m_drawShadows ) {
PanelShadows : : self ( ) - > removeWindow ( m_view ) ;
} else {
PanelShadows : : self ( ) - > setEnabledBorders ( m_view , borders ) ;
}
}
//!END draw panel shadows outside the dock window
}
}