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 ) ;
2018-12-01 00:52:05 +02:00
connect ( this , SIGNAL ( innerShadowChanged ( ) ) , m_view - > corona ( ) , SIGNAL ( availableScreenRectChanged ( ) ) ) ;
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 ;
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 ;
emit settingsMaskSubtractedChanged ( ) ;
}
QRegion Effects : : subtrackedMaskFromWindow ( QRegion initialRegion , QQuickView * window )
{
QRegion subtractedMask = initialRegion ;
if ( m_settingsMaskSubtracted & & window ) {
QRect windowMask ;
//! we need to subtrack the mask areas that overlap with underlying window
switch ( m_view - > location ( ) ) {
case Plasma : : Types : : TopEdge :
2019-03-09 18:37:49 +02:00
windowMask . setTopLeft ( QPoint ( window - > x ( ) - m_view - > x ( ) , m_mask . y ( ) + m_mask . height ( ) - m_editShadow ) ) ;
2019-03-09 12:23:51 +02:00
windowMask . setSize ( QSize ( window - > width ( ) , m_editShadow ) ) ;
2019-03-08 23:43:08 +02:00
break ;
case Plasma : : Types : : LeftEdge :
2019-03-09 12:23:51 +02:00
windowMask . setTopLeft ( QPoint ( m_mask . right ( ) + 1 - m_editShadow , window - > y ( ) - m_view - > y ( ) ) ) ;
windowMask . setSize ( QSize ( m_editShadow , window - > height ( ) ) ) ;
2019-03-08 23:43:08 +02:00
break ;
case Plasma : : Types : : RightEdge :
windowMask . setTopLeft ( QPoint ( m_mask . x ( ) , window - > y ( ) - m_view - > y ( ) ) ) ;
2019-03-09 12:23:51 +02:00
windowMask . setSize ( QSize ( m_editShadow , window - > height ( ) ) ) ;
2019-03-08 23:43:08 +02:00
break ;
case Plasma : : Types : : BottomEdge :
windowMask . setTopLeft ( QPoint ( window - > x ( ) - m_view - > x ( ) , m_mask . y ( ) ) ) ;
2019-03-09 12:23:51 +02:00
windowMask . setSize ( QSize ( window - > width ( ) , m_editShadow ) ) ;
2019-03-08 23:43:08 +02:00
break ;
default :
break ;
}
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 ( ) ) ;
if ( primaryConfig & & primaryConfig - > secondaryWindow ( ) ) {
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
{
2018-12-01 00:26:56 +02: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 ( ) ;
}
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
2018-11-30 21:33:46 +02:00
if ( ! m_background | | m_background - > enabledBorders ( ) ! = m_enabledBorders ) {
m_background = new Plasma : : FrameSvg ( this ) ;
}
if ( m_background - > imagePath ( ) ! = " opaque/dialogs/background " ) {
m_background - > setImagePath ( QStringLiteral ( " opaque/dialogs/background " ) ) ;
}
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 ;
}
if ( ! m_view - > behaveAsPlasmaPanel ( ) ) {
2018-12-01 00:26:56 +02:00
if ( m_drawEffects & & ! m_rect . isNull ( ) & & ! m_rect . isEmpty ( ) ) {
2018-11-30 21:33:46 +02:00
//! 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 ) ;
}
if ( m_background - > imagePath ( ) ! = " widgets/panel-background " ) {
m_background - > setImagePath ( QStringLiteral ( " widgets/panel-background " ) ) ;
}
m_background - > setEnabledBorders ( m_enabledBorders ) ;
2018-12-01 00:26:56 +02:00
m_background - > resizeFrame ( m_rect . 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_rect . x ( ) , m_rect . y ( ) ) ;
2018-11-30 21:33:46 +02:00
//! fix1, 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_rect ) ;
2018-11-30 21:33:46 +02:00
}
KWindowEffects : : enableBlurBehind ( m_view - > winId ( ) , true , fixedMask ) ;
2018-12-01 09:29:20 +02:00
bool drawBackgroundEffect = m_theme . backgroundContrastEnabled ( ) & & ( m_backgroundOpacity = = 100 ) ;
2018-11-30 21:33:46 +02:00
//based on Breeze Dark theme behavior the enableBackgroundContrast even though it does accept
//a QRegion it uses only the first rect. The bug was that for Breeze Dark there was a line
//at the dock bottom that was distinguishing it from other themes
KWindowEffects : : enableBackgroundContrast ( m_view - > winId ( ) , drawBackgroundEffect ,
m_theme . backgroundContrast ( ) ,
m_theme . backgroundIntensity ( ) ,
m_theme . backgroundSaturation ( ) ,
fixedMask . boundingRect ( ) ) ;
} else {
KWindowEffects : : enableBlurBehind ( m_view - > winId ( ) , false ) ;
KWindowEffects : : enableBackgroundContrast ( m_view - > winId ( ) , false ) ;
}
} else if ( m_view - > behaveAsPlasmaPanel ( ) & & m_drawEffects ) {
KWindowEffects : : enableBlurBehind ( m_view - > winId ( ) , true ) ;
2018-12-01 09:29:20 +02:00
bool drawBackgroundEffect = m_theme . backgroundContrastEnabled ( ) & & ( m_backgroundOpacity = = 100 ) ;
2018-11-30 21:33:46 +02:00
KWindowEffects : : enableBackgroundContrast ( m_view - > winId ( ) , drawBackgroundEffect ,
m_theme . backgroundContrast ( ) ,
m_theme . backgroundIntensity ( ) ,
m_theme . backgroundSaturation ( ) ) ;
} 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 ;
}
void Effects : : updateEnabledBorders ( )
{
if ( ! m_view - > screen ( ) ) {
return ;
}
Plasma : : FrameSvg : : EnabledBorders borders = Plasma : : FrameSvg : : AllBorders ;
switch ( m_view - > location ( ) ) {
case Plasma : : Types : : TopEdge :
borders & = ~ Plasma : : FrameSvg : : TopBorder ;
break ;
case Plasma : : Types : : LeftEdge :
borders & = ~ Plasma : : FrameSvg : : LeftBorder ;
break ;
case Plasma : : Types : : RightEdge :
borders & = ~ Plasma : : FrameSvg : : RightBorder ;
break ;
case Plasma : : Types : : BottomEdge :
borders & = ~ Plasma : : FrameSvg : : BottomBorder ;
break ;
default :
break ;
}
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
}
}