Moved all shadow handling into global cache oxygenShadowCache. This allows to share same
shadow tilesets between clients, thus reducing the memory usage; to simplify the oxygenclient class; and leave room for optimizing active/inactive shadow transitions. The global class is declared using K_GLOBAL_STATIC_WITH_ARGS. Also cleaned-up unnecessary headers. svn path=/trunk/KDE/kdebase/workspace/; revision=1025063icc-effect-5.14.5
parent
d58e7b7812
commit
9eec5543bf
|
@ -13,6 +13,7 @@ set(kwin_oxygen_SRCS
|
|||
oxygenexception.cpp
|
||||
oxygenexceptionlist.cpp
|
||||
oxygenshadowconfiguration.cpp
|
||||
oxygenshadowcache.cpp
|
||||
oxygensizegrip.cpp
|
||||
x11util.cpp
|
||||
)
|
||||
|
|
|
@ -27,12 +27,13 @@
|
|||
#include "oxygen.h"
|
||||
#include "oxygen.moc"
|
||||
#include "oxygenclient.h"
|
||||
#include "oxygenshadowcache.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <kdebug.h>
|
||||
#include <kconfiggroup.h>
|
||||
#include <KDebug>
|
||||
#include <KConfigGroup>
|
||||
#include <KWindowInfo>
|
||||
#include <kdeversion.h>
|
||||
#include <kwindowinfo.h>
|
||||
#include <QApplication>
|
||||
#include <QPainter>
|
||||
|
||||
|
@ -47,12 +48,11 @@ namespace Oxygen
|
|||
|
||||
// referenced from definition in Oxygendclient.cpp
|
||||
OxygenHelper *oxygenHelper();
|
||||
OxygenShadowCache *oxygenShadowCache();
|
||||
|
||||
// initialize static members
|
||||
bool OxygenFactory::initialized_ = false;
|
||||
OxygenConfiguration OxygenFactory::defaultConfiguration_;
|
||||
OxygenShadowConfiguration OxygenFactory::activeShadowConfiguration_ = OxygenShadowConfiguration( QPalette::Active );
|
||||
OxygenShadowConfiguration OxygenFactory::inactiveShadowConfiguration_ = OxygenShadowConfiguration( QPalette::Inactive );
|
||||
OxygenExceptionList OxygenFactory::exceptions_;
|
||||
|
||||
//___________________________________________________
|
||||
|
@ -85,15 +85,14 @@ namespace Oxygen
|
|||
bool configuration_changed = readConfig();
|
||||
setInitialized( true );
|
||||
|
||||
emit configurationChanged();
|
||||
if( configuration_changed || (changed & (SettingDecoration | SettingButtons | SettingBorder)) )
|
||||
{
|
||||
|
||||
emit configurationChanged();
|
||||
return true;
|
||||
|
||||
} else {
|
||||
|
||||
emit configurationChanged();
|
||||
resetDecorations(changed);
|
||||
return false;
|
||||
|
||||
|
@ -129,23 +128,24 @@ namespace Oxygen
|
|||
|
||||
// read shadow configurations
|
||||
OxygenShadowConfiguration activeShadowConfiguration( QPalette::Active, config.group( "ActiveShadow" ) );
|
||||
if( !( activeShadowConfiguration == activeShadowConfiguration_ ) )
|
||||
if( oxygenShadowCache()->shadowConfigurationChanged( activeShadowConfiguration ) )
|
||||
{
|
||||
activeShadowConfiguration_ = activeShadowConfiguration;
|
||||
oxygenShadowCache()->setShadowConfiguration( activeShadowConfiguration );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// read shadow configurations
|
||||
OxygenShadowConfiguration inactiveShadowConfiguration( QPalette::Inactive, config.group( "InactiveShadow" ) );
|
||||
if( !( inactiveShadowConfiguration == inactiveShadowConfiguration_ ) )
|
||||
if( oxygenShadowCache()->shadowConfigurationChanged( inactiveShadowConfiguration ) )
|
||||
{
|
||||
inactiveShadowConfiguration_ = inactiveShadowConfiguration;
|
||||
oxygenShadowCache()->setShadowConfiguration( inactiveShadowConfiguration );
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if( changed )
|
||||
{
|
||||
|
||||
oxygenShadowCache()->invalidateCaches();
|
||||
oxygenHelper()->invalidateCaches();
|
||||
return true;
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <kdeversion.h>
|
||||
|
||||
#include "oxygenconfiguration.h"
|
||||
#include "oxygenshadowconfiguration.h"
|
||||
#include "oxygenexceptionlist.h"
|
||||
|
||||
// TODO:
|
||||
|
@ -103,22 +102,6 @@ namespace Oxygen
|
|||
//! get configuration for a give client
|
||||
static OxygenConfiguration configuration( const OxygenClient& );
|
||||
|
||||
//! shadow configuration
|
||||
static OxygenShadowConfiguration activeShadowConfiguration( void )
|
||||
{ return activeShadowConfiguration_; }
|
||||
|
||||
//! shadow configuration
|
||||
static OxygenShadowConfiguration inactiveShadowConfiguration( void )
|
||||
{ return inactiveShadowConfiguration_; }
|
||||
|
||||
//! shadow configuration
|
||||
static OxygenShadowConfiguration shadowConfiguration( bool active )
|
||||
{ return active ? activeShadowConfiguration():inactiveShadowConfiguration(); }
|
||||
|
||||
//! shadow size
|
||||
static qreal shadowSize( void )
|
||||
{ return qMax( activeShadowConfiguration().shadowSize(), inactiveShadowConfiguration().shadowSize() ); }
|
||||
|
||||
signals:
|
||||
|
||||
//! configuration has changed
|
||||
|
@ -147,12 +130,6 @@ namespace Oxygen
|
|||
//! default configuration
|
||||
static OxygenConfiguration defaultConfiguration_;
|
||||
|
||||
//! shadow configuration
|
||||
static OxygenShadowConfiguration activeShadowConfiguration_;
|
||||
|
||||
//! shadow configuration
|
||||
static OxygenShadowConfiguration inactiveShadowConfiguration_;
|
||||
|
||||
//! exceptions
|
||||
static OxygenExceptionList exceptions_;
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include <cmath>
|
||||
|
||||
#include <QPainterPath>
|
||||
#include <QPainter>
|
||||
#include <QPen>
|
||||
|
||||
|
|
|
@ -30,11 +30,11 @@
|
|||
|
||||
#include "oxygen.h"
|
||||
#include "oxygenbutton.h"
|
||||
#include "oxygenshadowcache.h"
|
||||
#include "oxygensizegrip.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#include <kdeversion.h>
|
||||
#include <KGlobal>
|
||||
|
@ -44,7 +44,6 @@
|
|||
|
||||
#include <QLabel>
|
||||
#include <QPainter>
|
||||
#include <QTextStream>
|
||||
#include <QApplication>
|
||||
|
||||
using namespace std;
|
||||
|
@ -52,16 +51,23 @@ namespace Oxygen
|
|||
{
|
||||
|
||||
K_GLOBAL_STATIC_WITH_ARGS(OxygenHelper, globalHelper, ("oxygenDeco"))
|
||||
K_GLOBAL_STATIC_WITH_ARGS(OxygenShadowCache, globalShadowCache, (512))
|
||||
|
||||
//___________________________________________
|
||||
OxygenHelper *oxygenHelper()
|
||||
{ return globalHelper; }
|
||||
|
||||
//___________________________________________
|
||||
OxygenShadowCache *oxygenShadowCache()
|
||||
{ return globalShadowCache; }
|
||||
|
||||
//___________________________________________
|
||||
static void oxkwincleanupBefore()
|
||||
{
|
||||
OxygenHelper *h = globalHelper;
|
||||
h->invalidateCaches();
|
||||
|
||||
globalHelper->invalidateCaches();
|
||||
globalShadowCache->invalidateCaches();
|
||||
|
||||
}
|
||||
|
||||
//___________________________________________
|
||||
|
@ -75,10 +81,6 @@ namespace Oxygen
|
|||
KCommonDecorationUnstable(b, f),
|
||||
colorCacheInvalid_(true),
|
||||
sizeGrip_( 0 ),
|
||||
inactiveShadowConfiguration_( QPalette::Inactive ),
|
||||
activeShadowConfiguration_( QPalette::Active ),
|
||||
inactiveShadowTiles_( 0 ),
|
||||
activeShadowTiles_( 0 ),
|
||||
helper_(*globalHelper),
|
||||
initialized_( false )
|
||||
{ qAddPostRoutine(oxkwincleanupBefore); }
|
||||
|
@ -90,10 +92,6 @@ namespace Oxygen
|
|||
// delete sizegrip if any
|
||||
if( hasSizeGrip() ) deleteSizeGrip();
|
||||
|
||||
// delete tilesets
|
||||
if( inactiveShadowTiles_ ) delete inactiveShadowTiles_;
|
||||
if( activeShadowTiles_ ) delete activeShadowTiles_;
|
||||
|
||||
}
|
||||
|
||||
//___________________________________________
|
||||
|
@ -267,7 +265,7 @@ namespace Oxygen
|
|||
case LM_OuterPaddingRight:
|
||||
case LM_OuterPaddingTop:
|
||||
case LM_OuterPaddingBottom:
|
||||
return OxygenFactory::shadowSize() - extraBorder;
|
||||
return oxygenShadowCache()->shadowSize() - extraBorder;
|
||||
|
||||
default:
|
||||
return KCommonDecoration::layoutMetric(lm, respectWindowState, btn);
|
||||
|
@ -450,7 +448,8 @@ namespace Oxygen
|
|||
}
|
||||
|
||||
QRect r = (isPreview()) ? OxygenClient::widget()->rect():window->rect();
|
||||
r.adjust( OxygenFactory::shadowSize(), OxygenFactory::shadowSize(), -OxygenFactory::shadowSize(), -OxygenFactory::shadowSize() );
|
||||
qreal shadowSize( oxygenShadowCache()->shadowSize() );
|
||||
r.adjust( shadowSize, shadowSize, -shadowSize, -shadowSize );
|
||||
r.adjust(0,0, 1, 1);
|
||||
|
||||
// mask and painting frame
|
||||
|
@ -459,10 +458,10 @@ namespace Oxygen
|
|||
|
||||
// top line
|
||||
{
|
||||
int shadow_size = 5;
|
||||
int shadowSize = 5;
|
||||
int height = HFRAMESIZE;
|
||||
QRect rect( r.topLeft()-position, QSize( r.width(), height ) );
|
||||
helper().slab( palette.color( widget->backgroundRole() ), 0, shadow_size )->render( rect.adjusted(-shadow_size-1, 0, shadow_size+1, 2 ), painter, TileSet::Bottom );
|
||||
helper().slab( palette.color( widget->backgroundRole() ), 0, shadowSize )->render( rect.adjusted(-shadowSize-1, 0, shadowSize+1, 2 ), painter, TileSet::Bottom );
|
||||
mask += rect;
|
||||
frame |= rect;
|
||||
}
|
||||
|
@ -513,10 +512,10 @@ namespace Oxygen
|
|||
|
||||
// shadow
|
||||
{
|
||||
int shadow_size = 7;
|
||||
int voffset = -shadow_size;
|
||||
int shadowSize = 7;
|
||||
int voffset = -shadowSize;
|
||||
if( !isMaximized() ) voffset += HFRAMESIZE;
|
||||
helper().slab( palette.color( widget()->backgroundRole() ), 0, shadow_size )->render( rect.adjusted(0, voffset, 0, 0 ), painter, TileSet::Bottom|TileSet::Left|TileSet::Right );
|
||||
helper().slab( palette.color( widget()->backgroundRole() ), 0, shadowSize )->render( rect.adjusted(0, voffset, 0, 0 ), painter, TileSet::Bottom|TileSet::Left|TileSet::Right );
|
||||
}
|
||||
|
||||
// center
|
||||
|
@ -553,15 +552,6 @@ namespace Oxygen
|
|||
void OxygenClient::shadeChange( void )
|
||||
{
|
||||
if( hasSizeGrip() ) sizeGrip().setVisible( !( isShade() || isMaximized() ) );
|
||||
|
||||
// in border none mode, need to reinitialze shadowTiles because
|
||||
// bottom corner rounding is changed
|
||||
if( compositingActive() && configuration().frameBorder() == OxygenConfiguration::BorderNone )
|
||||
{
|
||||
inactiveShadowConfiguration_ = OxygenShadowConfiguration( QPalette::Active );
|
||||
activeShadowConfiguration_ = OxygenShadowConfiguration( QPalette::Active );
|
||||
}
|
||||
|
||||
KCommonDecorationUnstable::shadeChange();
|
||||
}
|
||||
|
||||
|
@ -636,14 +626,16 @@ namespace Oxygen
|
|||
// draw shadows
|
||||
if( compositingActive() && !isMaximized() )
|
||||
{
|
||||
shadowTiles(
|
||||
backgroundPalette( widget(), palette ).color( widget()->backgroundRole() ),
|
||||
isActive() )->render( frame.adjusted( 4, 4, -4, -4),
|
||||
|
||||
oxygenShadowCache()->tileSet( this )->render(
|
||||
frame.adjusted( 4, 4, -4, -4),
|
||||
&painter, TileSet::Ring);
|
||||
|
||||
}
|
||||
|
||||
// adjust frame
|
||||
frame.adjust( OxygenFactory::shadowSize(), OxygenFactory::shadowSize(), -OxygenFactory::shadowSize(), -OxygenFactory::shadowSize() );
|
||||
qreal shadowSize( oxygenShadowCache()->shadowSize() );
|
||||
frame.adjust( shadowSize, shadowSize, -shadowSize, -shadowSize );
|
||||
|
||||
// adjust mask
|
||||
if( compositingActive() || isPreview() )
|
||||
|
@ -835,265 +827,4 @@ namespace Oxygen
|
|||
sizeGrip_ = 0;
|
||||
}
|
||||
|
||||
//_________________________________________________________________
|
||||
TileSet *OxygenClient::shadowTiles(const QColor& color, bool active)
|
||||
{
|
||||
|
||||
OxygenShadowConfiguration shadowConfiguration( OxygenFactory::shadowConfiguration( active && useOxygenShadows() ) );
|
||||
|
||||
OxygenShadowConfiguration local( shadowConfiguration );
|
||||
local.setShadowSize( OxygenFactory::shadowSize() );
|
||||
|
||||
OxygenShadowConfiguration current = active ? activeShadowConfiguration_:inactiveShadowConfiguration_;
|
||||
|
||||
bool optionChanged = !(current == local );
|
||||
if (active && activeShadowTiles_ )
|
||||
{
|
||||
|
||||
if( optionChanged) delete activeShadowTiles_;
|
||||
else return activeShadowTiles_;
|
||||
|
||||
} else if (!active && inactiveShadowTiles_ ) {
|
||||
|
||||
if( optionChanged ) delete inactiveShadowTiles_;
|
||||
else return inactiveShadowTiles_;
|
||||
|
||||
}
|
||||
|
||||
kDebug( 1212 ) << " creating tiles - active: " << active << endl;
|
||||
TileSet *tileSet = 0;
|
||||
|
||||
//
|
||||
qreal size( OxygenFactory::shadowSize() );
|
||||
if( active && configuration().drawTitleOutline() && configuration().frameBorder() == OxygenConfiguration::BorderNone )
|
||||
{
|
||||
|
||||
// a more complex tile set is needed for the configuration above:
|
||||
// top corners must be beveled with the "active titlebar color" while
|
||||
// bottom corners must be beveled with the "window background color".
|
||||
// this requires generating two shadow pixmaps and tiling them in the tileSet.
|
||||
QPixmap shadow = QPixmap( size*2, size*2 );
|
||||
shadow.fill( Qt::transparent );
|
||||
|
||||
QPainter p( &shadow );
|
||||
p.setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
QPixmap shadowTop = shadowPixmap( color, active );
|
||||
QRect topRect( shadow.rect() );
|
||||
topRect.setBottom( int( size )-1 );
|
||||
p.setClipRect( topRect );
|
||||
p.drawPixmap( QPointF( 0, 0 ), shadowTop );
|
||||
|
||||
QPixmap shadowBottom = shadowPixmap( widget()->palette().color( widget()->backgroundRole() ), active );
|
||||
QRect bottomRect( shadow.rect() );
|
||||
bottomRect.setTop( int( size ) );
|
||||
p.setClipRect( bottomRect );
|
||||
p.drawPixmap( QPointF( 0, 0 ), shadowBottom );
|
||||
p.end();
|
||||
|
||||
tileSet = new TileSet( shadow, size, size, 1, 1);
|
||||
|
||||
} else {
|
||||
|
||||
tileSet = new TileSet(
|
||||
shadowPixmap( color, active ),
|
||||
size, size, 1, 1);
|
||||
|
||||
}
|
||||
|
||||
// store option and style
|
||||
if( active )
|
||||
{
|
||||
|
||||
activeShadowConfiguration_ = local;
|
||||
activeShadowTiles_ = tileSet;
|
||||
|
||||
} else {
|
||||
|
||||
inactiveShadowConfiguration_ = local;
|
||||
inactiveShadowTiles_ = tileSet;
|
||||
|
||||
}
|
||||
|
||||
return tileSet;
|
||||
}
|
||||
|
||||
//_________________________________________________________________
|
||||
QPixmap OxygenClient::shadowPixmap(const QColor& color, bool active ) const
|
||||
{
|
||||
|
||||
OxygenShadowConfiguration shadowConfiguration( OxygenFactory::shadowConfiguration( active && useOxygenShadows() ) );
|
||||
|
||||
static const qreal fixedSize = 25.5;
|
||||
qreal size( OxygenFactory::shadowSize() );
|
||||
qreal shadowSize( shadowConfiguration.shadowSize() );
|
||||
|
||||
QPixmap shadow = QPixmap( size*2, size*2 );
|
||||
shadow.fill( Qt::transparent );
|
||||
|
||||
QPainter p( &shadow );
|
||||
p.setRenderHint( QPainter::Antialiasing );
|
||||
p.setPen( Qt::NoPen );
|
||||
|
||||
// offsets are scaled with the shadow size
|
||||
// so that the ratio Top-shadow/Bottom-shadow is kept constant
|
||||
// when shadow size is chqnged
|
||||
qreal hoffset = shadowConfiguration.horizontalOffset()*shadowSize/fixedSize;
|
||||
qreal voffset = shadowConfiguration.verticalOffset()*shadowSize/fixedSize;
|
||||
|
||||
if( active && useOxygenShadows() )
|
||||
{
|
||||
|
||||
{
|
||||
|
||||
int values[5] = {255, 220, 180, 25, 0};
|
||||
qreal x[5] = {4.4, 4.5, 5, 5.5, 6.5};
|
||||
|
||||
// the first point of this gradient does not scale
|
||||
QRadialGradient rg( size, size, shadowSize );
|
||||
|
||||
QColor c = color;
|
||||
for( int i = 0; i<5; i++ )
|
||||
{ c.setAlpha( values[i] ); rg.setColorAt( x[0]/shadowSize+(x[i]-x[0])/fixedSize, c ); }
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
// this gradient scales with shadow size
|
||||
int nPoints = 8;
|
||||
qreal values[8] = {1, 0.58, 0.43, 0.30, 0.22, 0.15, 0.08, 0 };
|
||||
qreal x[8] = {0, 4.5, 5.5, 6.5, 7.5, 8.5, 11.5, 14.4};
|
||||
|
||||
// this gradient scales with shadow size
|
||||
QRadialGradient rg(
|
||||
size+hoffset,
|
||||
size+voffset,
|
||||
shadowSize );
|
||||
|
||||
QColor c = shadowConfiguration.innerColor();
|
||||
for( int i = 0; i<nPoints; i++ )
|
||||
{ c.setAlphaF( values[i] ); rg.setColorAt( x[i]/fixedSize, c ); }
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
QRadialGradient rg = QRadialGradient( size, size, size );
|
||||
QColor c = color;
|
||||
|
||||
c.setAlpha( 255 ); rg.setColorAt( 4.0/size, c );
|
||||
c.setAlpha( 0 ); rg.setColorAt( 4.01/size, c );
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
{
|
||||
|
||||
int nPoints = 9;
|
||||
qreal values[9] = { 0.17, 0.12, 0.11, 0.075, 0.06, 0.035, 0.025, 0.01, 0 };
|
||||
qreal x[9] = {0, 4.5, 6.6, 8.5, 11.5, 14.5, 17.5, 21.5, 25.5 };
|
||||
QRadialGradient rg = QRadialGradient(
|
||||
size+20.0*hoffset,
|
||||
size+20.0*voffset,
|
||||
shadowSize );
|
||||
|
||||
QColor c = shadowConfiguration.outerColor();
|
||||
for( int i = 0; i<nPoints; i++ )
|
||||
{ c.setAlphaF( values[i] ); rg.setColorAt( x[i]/fixedSize, c ); }
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
int nPoints = 7;
|
||||
qreal values[7] = {0.55, 0.25, 0.20, 0.1, 0.06, 0.015, 0 };
|
||||
qreal x[7] = {0, 4.5, 5.5, 7.5, 8.5, 11.5, 14.5 };
|
||||
QRadialGradient rg = QRadialGradient(
|
||||
size+10.0*hoffset,
|
||||
size+10.0*voffset,
|
||||
shadowSize );
|
||||
|
||||
QColor c = shadowConfiguration.midColor();
|
||||
for( int i = 0; i<nPoints; i++ )
|
||||
{ c.setAlphaF( values[i] ); rg.setColorAt( x[i]/fixedSize, c ); }
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
int nPoints = 5;
|
||||
qreal values[5] = { 1, 0.32, 0.22, 0.03, 0 };
|
||||
qreal x[5] = { 0, 4.5, 5.0, 5.5, 6.5 };
|
||||
QRadialGradient rg = QRadialGradient(
|
||||
size+hoffset,
|
||||
size+voffset,
|
||||
shadowSize );
|
||||
|
||||
QColor c = shadowConfiguration.innerColor();
|
||||
for( int i = 0; i<nPoints; i++ )
|
||||
{ c.setAlphaF( values[i] ); rg.setColorAt( x[i]/fixedSize, c ); }
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
QRadialGradient rg = QRadialGradient( size, size, size );
|
||||
QColor c = color;
|
||||
|
||||
c.setAlpha( 255 ); rg.setColorAt( 4.0/size, c );
|
||||
c.setAlpha( 0 ); rg.setColorAt( 4.01/size, c );
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// draw the corner of the window - actually all 4 corners as one circle
|
||||
// this is all fixedSize. Does not scale with shadow size
|
||||
QLinearGradient lg = QLinearGradient(0.0, size-4.5, 0.0, size+4.5);
|
||||
if( configuration().frameBorder() < OxygenConfiguration::BorderTiny )
|
||||
{
|
||||
|
||||
lg.setColorAt(0.52, helper().backgroundTopColor(color));
|
||||
lg.setColorAt(1.0, helper().backgroundBottomColor(color) );
|
||||
|
||||
} else {
|
||||
|
||||
QColor light = helper().calcLightColor( helper().backgroundTopColor(color) );
|
||||
QColor dark = helper().calcDarkColor(helper().backgroundBottomColor(color));
|
||||
|
||||
lg.setColorAt(0.52, light);
|
||||
lg.setColorAt(1.0, dark);
|
||||
|
||||
}
|
||||
|
||||
p.setBrush( Qt::NoBrush );
|
||||
if( configuration().frameBorder() == OxygenConfiguration::BorderNone && !isShade() )
|
||||
{ p.setClipRect( QRectF( 0, 0, 2*size, size ) ); }
|
||||
|
||||
p.setPen(QPen(lg, 0.8));
|
||||
p.drawEllipse(QRectF(size-4, size-4, 8, 8));
|
||||
|
||||
p.end();
|
||||
return shadow;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <kcommondecoration.h>
|
||||
|
||||
#include "oxygenconfiguration.h"
|
||||
#include "oxygenshadowconfiguration.h"
|
||||
#include "lib/helper.h"
|
||||
#include "lib/tileset.h"
|
||||
|
||||
|
@ -65,10 +64,6 @@ namespace Oxygen
|
|||
virtual bool drawSeparator( void ) const
|
||||
{ return isActive() && configuration().drawSeparator() && !configuration().drawTitleOutline(); }
|
||||
|
||||
//! true when oxygen 'glow' shadow is to be drawn for active window
|
||||
virtual bool useOxygenShadows( void ) const
|
||||
{ return isActive() && configuration().useOxygenShadows(); }
|
||||
|
||||
//! dimensions
|
||||
virtual int layoutMetric(LayoutMetric lm, bool respectWindowState = true, const KCommonDecorationButton * = 0) const;
|
||||
|
||||
|
@ -120,12 +115,6 @@ namespace Oxygen
|
|||
//! paint
|
||||
void paintEvent( QPaintEvent* );
|
||||
|
||||
//! shadows
|
||||
TileSet *shadowTiles(const QColor& color, bool active);
|
||||
|
||||
//! shadows
|
||||
QPixmap shadowPixmap( const QColor& color, bool active ) const;
|
||||
|
||||
private:
|
||||
|
||||
//! calculate mask
|
||||
|
@ -165,11 +154,6 @@ namespace Oxygen
|
|||
//! size grip widget
|
||||
OxygenSizeGrip* sizeGrip_;
|
||||
|
||||
OxygenShadowConfiguration inactiveShadowConfiguration_;
|
||||
OxygenShadowConfiguration activeShadowConfiguration_;
|
||||
TileSet *inactiveShadowTiles_;
|
||||
TileSet *activeShadowTiles_;
|
||||
|
||||
//! helper
|
||||
OxygenHelper& helper_;
|
||||
|
||||
|
|
|
@ -0,0 +1,326 @@
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
// oxygenshadowcache.cpp
|
||||
// handles caching of TileSet objects to draw shadows
|
||||
// -------------------
|
||||
//
|
||||
// Copyright (c) 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "oxygenshadowcache.h"
|
||||
#include "oxygenclient.h"
|
||||
|
||||
#include <KDebug>
|
||||
#include <QPainter>
|
||||
|
||||
namespace Oxygen
|
||||
{
|
||||
|
||||
//_______________________________________________________
|
||||
bool OxygenShadowCache::shadowConfigurationChanged( const OxygenShadowConfiguration& other ) const
|
||||
{
|
||||
const OxygenShadowConfiguration& local = (other.colorGroup() == QPalette::Active ) ? activeShadowConfiguration_:inactiveShadowConfiguration_;
|
||||
return !(local == other);
|
||||
}
|
||||
|
||||
//_______________________________________________________
|
||||
void OxygenShadowCache::setShadowConfiguration( const OxygenShadowConfiguration& other )
|
||||
{
|
||||
OxygenShadowConfiguration& local = (other.colorGroup() == QPalette::Active ) ? activeShadowConfiguration_:inactiveShadowConfiguration_;
|
||||
local = other;
|
||||
}
|
||||
|
||||
//_______________________________________________________
|
||||
TileSet* OxygenShadowCache::tileSet( const OxygenClient* client )
|
||||
{
|
||||
|
||||
// construct key
|
||||
Key key = Key();
|
||||
key.active = client->isActive();
|
||||
key.useOxygenShadows = client->configuration().useOxygenShadows();
|
||||
key.isShade = client->isShade();
|
||||
key.hasNoBorder = client->configuration().frameBorder() == OxygenConfiguration::BorderNone;
|
||||
key.hasTitleOutline = client->configuration().drawTitleOutline();
|
||||
|
||||
// check if tileset already in cache
|
||||
int hash( key.hash() );
|
||||
if( shadowCache_.contains(hash) ) return shadowCache_.object(hash);
|
||||
|
||||
// create tileset otherwise
|
||||
qreal size( shadowSize() );
|
||||
TileSet* tileSet = new TileSet( shadowPixmap( client, key.active ), size, size, 1, 1);
|
||||
shadowCache_.insert( hash, tileSet );
|
||||
return tileSet;
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________________
|
||||
OxygenShadowCache::OxygenShadowCache( int maxIndex ):
|
||||
maxIndex_( maxIndex ),
|
||||
activeShadowConfiguration_( OxygenShadowConfiguration( QPalette::Active ) ),
|
||||
inactiveShadowConfiguration_( OxygenShadowConfiguration( QPalette::Inactive ) )
|
||||
{
|
||||
kDebug(1212) << endl;
|
||||
shadowCache_.setMaxCost( 1<<5 );
|
||||
}
|
||||
|
||||
//_________________________________________________________________
|
||||
QPixmap OxygenShadowCache::shadowPixmap(const OxygenClient* client, bool active ) const
|
||||
{
|
||||
|
||||
// get window color
|
||||
QPalette palette( client->backgroundPalette( client->widget(), client->widget()->palette() ) );
|
||||
QColor color( palette.color( client->widget()->backgroundRole() ) );
|
||||
|
||||
if( active && client->configuration().drawTitleOutline() && client->configuration().frameBorder() == OxygenConfiguration::BorderNone )
|
||||
{
|
||||
|
||||
// a more complex tile set is needed for the configuration above:
|
||||
// top corners must be beveled with the "active titlebar color" while
|
||||
// bottom corners must be beveled with the "window background color".
|
||||
// this requires generating two shadow pixmaps and tiling them in the tileSet.
|
||||
|
||||
qreal size( shadowSize() );
|
||||
QPixmap shadow( 2*size, 2*size );
|
||||
shadow.fill( Qt::transparent );
|
||||
QPainter p( &shadow );
|
||||
p.setRenderHint( QPainter::Antialiasing );
|
||||
|
||||
QPixmap shadowTop = simpleShadowPixmap( color, client, active );
|
||||
QRect topRect( shadow.rect() );
|
||||
topRect.setBottom( int( size )-1 );
|
||||
p.setClipRect( topRect );
|
||||
p.drawPixmap( QPointF( 0, 0 ), shadowTop );
|
||||
|
||||
// get window color
|
||||
palette = client->widget()->palette();
|
||||
color = palette.color( client->widget()->backgroundRole() );
|
||||
QPixmap shadowBottom = simpleShadowPixmap( color, client, active );
|
||||
QRect bottomRect( shadow.rect() );
|
||||
bottomRect.setTop( int( size ) );
|
||||
p.setClipRect( bottomRect );
|
||||
p.drawPixmap( QPointF( 0, 0 ), shadowBottom );
|
||||
p.end();
|
||||
|
||||
return shadow;
|
||||
|
||||
} else return simpleShadowPixmap( color, client, active );
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________________
|
||||
QPixmap OxygenShadowCache::simpleShadowPixmap( const QColor& color, const OxygenClient* client, bool active ) const
|
||||
{
|
||||
|
||||
// local reference to relevant shadow configuration
|
||||
const OxygenShadowConfiguration& shadowConfiguration(
|
||||
active && client->configuration().useOxygenShadows() ?
|
||||
activeShadowConfiguration_:inactiveShadowConfiguration_ );
|
||||
|
||||
static const qreal fixedSize = 25.5;
|
||||
qreal size( shadowSize() );
|
||||
qreal shadowSize( shadowConfiguration.shadowSize() );
|
||||
|
||||
QPixmap shadow = QPixmap( size*2, size*2 );
|
||||
shadow.fill( Qt::transparent );
|
||||
|
||||
QPainter p( &shadow );
|
||||
p.setRenderHint( QPainter::Antialiasing );
|
||||
p.setPen( Qt::NoPen );
|
||||
|
||||
// offsets are scaled with the shadow size
|
||||
// so that the ratio Top-shadow/Bottom-shadow is kept constant
|
||||
// when shadow size is changed
|
||||
qreal hoffset = shadowConfiguration.horizontalOffset()*shadowSize/fixedSize;
|
||||
qreal voffset = shadowConfiguration.verticalOffset()*shadowSize/fixedSize;
|
||||
|
||||
if( active && client->configuration().useOxygenShadows() )
|
||||
{
|
||||
|
||||
{
|
||||
|
||||
int values[5] = {255, 220, 180, 25, 0};
|
||||
qreal x[5] = {4.4, 4.5, 5, 5.5, 6.5};
|
||||
|
||||
// the first point of this gradient does not scale
|
||||
QRadialGradient rg( size, size, shadowSize );
|
||||
|
||||
QColor c = color;
|
||||
for( int i = 0; i<5; i++ )
|
||||
{ c.setAlpha( values[i] ); rg.setColorAt( x[0]/shadowSize+(x[i]-x[0])/fixedSize, c ); }
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
// this gradient scales with shadow size
|
||||
int nPoints = 8;
|
||||
qreal values[8] = {1, 0.58, 0.43, 0.30, 0.22, 0.15, 0.08, 0 };
|
||||
qreal x[8] = {0, 4.5, 5.5, 6.5, 7.5, 8.5, 11.5, 14.4};
|
||||
|
||||
// this gradient scales with shadow size
|
||||
QRadialGradient rg(
|
||||
size+hoffset,
|
||||
size+voffset,
|
||||
shadowSize );
|
||||
|
||||
QColor c = shadowConfiguration.innerColor();
|
||||
for( int i = 0; i<nPoints; i++ )
|
||||
{ c.setAlphaF( values[i] ); rg.setColorAt( x[i]/fixedSize, c ); }
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
QRadialGradient rg = QRadialGradient( size, size, size );
|
||||
QColor c = color;
|
||||
|
||||
c.setAlpha( 255 ); rg.setColorAt( 4.0/size, c );
|
||||
c.setAlpha( 0 ); rg.setColorAt( 4.01/size, c );
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
{
|
||||
|
||||
int nPoints = 9;
|
||||
qreal values[9] = { 0.17, 0.12, 0.11, 0.075, 0.06, 0.035, 0.025, 0.01, 0 };
|
||||
qreal x[9] = {0, 4.5, 6.6, 8.5, 11.5, 14.5, 17.5, 21.5, 25.5 };
|
||||
QRadialGradient rg = QRadialGradient(
|
||||
size+20.0*hoffset,
|
||||
size+20.0*voffset,
|
||||
shadowSize );
|
||||
|
||||
QColor c = shadowConfiguration.outerColor();
|
||||
for( int i = 0; i<nPoints; i++ )
|
||||
{ c.setAlphaF( values[i] ); rg.setColorAt( x[i]/fixedSize, c ); }
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
int nPoints = 7;
|
||||
qreal values[7] = {0.55, 0.25, 0.20, 0.1, 0.06, 0.015, 0 };
|
||||
qreal x[7] = {0, 4.5, 5.5, 7.5, 8.5, 11.5, 14.5 };
|
||||
QRadialGradient rg = QRadialGradient(
|
||||
size+10.0*hoffset,
|
||||
size+10.0*voffset,
|
||||
shadowSize );
|
||||
|
||||
QColor c = shadowConfiguration.midColor();
|
||||
for( int i = 0; i<nPoints; i++ )
|
||||
{ c.setAlphaF( values[i] ); rg.setColorAt( x[i]/fixedSize, c ); }
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
int nPoints = 5;
|
||||
qreal values[5] = { 1, 0.32, 0.22, 0.03, 0 };
|
||||
qreal x[5] = { 0, 4.5, 5.0, 5.5, 6.5 };
|
||||
QRadialGradient rg = QRadialGradient(
|
||||
size+hoffset,
|
||||
size+voffset,
|
||||
shadowSize );
|
||||
|
||||
QColor c = shadowConfiguration.innerColor();
|
||||
for( int i = 0; i<nPoints; i++ )
|
||||
{ c.setAlphaF( values[i] ); rg.setColorAt( x[i]/fixedSize, c ); }
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
QRadialGradient rg = QRadialGradient( size, size, size );
|
||||
QColor c = color;
|
||||
|
||||
c.setAlpha( 255 ); rg.setColorAt( 4.0/size, c );
|
||||
c.setAlpha( 0 ); rg.setColorAt( 4.01/size, c );
|
||||
|
||||
p.setBrush( rg );
|
||||
p.drawRect( shadow.rect() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// draw the corner of the window - actually all 4 corners as one circle
|
||||
// this is all fixedSize. Does not scale with shadow size
|
||||
QLinearGradient lg = QLinearGradient(0.0, size-4.5, 0.0, size+4.5);
|
||||
if( client->configuration().frameBorder() < OxygenConfiguration::BorderTiny )
|
||||
{
|
||||
|
||||
lg.setColorAt(0.52, client->helper().backgroundTopColor(color));
|
||||
lg.setColorAt(1.0, client->helper().backgroundBottomColor(color) );
|
||||
|
||||
} else {
|
||||
|
||||
QColor light = client->helper().calcLightColor( client->helper().backgroundTopColor(color) );
|
||||
QColor dark = client->helper().calcDarkColor( client->helper().backgroundBottomColor(color));
|
||||
|
||||
lg.setColorAt(0.52, light);
|
||||
lg.setColorAt(1.0, dark);
|
||||
|
||||
}
|
||||
|
||||
p.setBrush( Qt::NoBrush );
|
||||
if( client->configuration().frameBorder() == OxygenConfiguration::BorderNone && !client->isShade() )
|
||||
{ p.setClipRect( QRectF( 0, 0, 2*size, size ) ); }
|
||||
|
||||
p.setPen(QPen(lg, 0.8));
|
||||
p.drawEllipse(QRectF(size-4, size-4, 8, 8));
|
||||
|
||||
p.end();
|
||||
return shadow;
|
||||
|
||||
}
|
||||
|
||||
//_______________________________________________________
|
||||
int OxygenShadowCache::Key::hash( void ) const
|
||||
{
|
||||
|
||||
// note this can be optimized because not all of the flag configurations are actually relevant
|
||||
// allocate 3 empty bits for flags
|
||||
int out =
|
||||
( active << 4 ) |
|
||||
(useOxygenShadows << 3 ) |
|
||||
(isShade<<2) |
|
||||
(hasNoBorder<<1) |
|
||||
(hasTitleOutline<<0);
|
||||
|
||||
return out;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
#ifndef oxygenshadowcache_h
|
||||
#define oxygenshadowcache_h
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// oxygenshadowcache.h
|
||||
// handles caching of TileSet objects to draw shadows
|
||||
// -------------------
|
||||
//
|
||||
// Copyright (c) 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QCache>
|
||||
|
||||
#include "oxygenshadowconfiguration.h"
|
||||
#include "lib/tileset.h"
|
||||
|
||||
namespace Oxygen
|
||||
{
|
||||
|
||||
class OxygenClient;
|
||||
|
||||
class OxygenShadowCache
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
OxygenShadowCache( int maxIndex );
|
||||
|
||||
//! destructor
|
||||
virtual ~OxygenShadowCache( void )
|
||||
{}
|
||||
|
||||
//! invalidate caches
|
||||
void invalidateCaches( void )
|
||||
{
|
||||
shadowCache_.clear();
|
||||
}
|
||||
|
||||
//! returns true if provided shadow configuration changes with respect to stored
|
||||
/*!
|
||||
use OxygenShadowConfiguration::colorRole() to decide whether it should be stored
|
||||
as active or inactive
|
||||
*/
|
||||
bool shadowConfigurationChanged( const OxygenShadowConfiguration& ) const;
|
||||
|
||||
//! set shadowConfiguration
|
||||
/*!
|
||||
use OxygenShadowConfiguration::colorRole() to decide whether it should be stored
|
||||
as active or inactive
|
||||
*/
|
||||
void setShadowConfiguration( const OxygenShadowConfiguration& );
|
||||
|
||||
//! shadow size
|
||||
qreal shadowSize( void ) const
|
||||
{ return qMax( activeShadowConfiguration_.shadowSize(), inactiveShadowConfiguration_.shadowSize() ); }
|
||||
|
||||
//! get shadow matching client
|
||||
TileSet* tileSet( const OxygenClient* );
|
||||
|
||||
//! get shadow matching client and animation index
|
||||
TileSet* tileSet( const OxygenClient*, int );
|
||||
|
||||
//! Key class to be used into QCache
|
||||
class Key
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
//! explicit constructor
|
||||
explicit Key( void ):
|
||||
active(false),
|
||||
useOxygenShadows(false),
|
||||
isShade(false),
|
||||
hasNoBorder(false),
|
||||
hasTitleOutline(false)
|
||||
{}
|
||||
|
||||
//! hash function
|
||||
int hash( void ) const;
|
||||
|
||||
bool active;
|
||||
bool useOxygenShadows;
|
||||
bool isShade;
|
||||
bool hasNoBorder;
|
||||
bool hasTitleOutline;
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
//! complex pixmap (when needed)
|
||||
QPixmap shadowPixmap( const OxygenClient*, bool active ) const;
|
||||
|
||||
//! simple pixmap
|
||||
QPixmap simpleShadowPixmap( const QColor&, const OxygenClient*, bool active ) const;
|
||||
|
||||
private:
|
||||
|
||||
//! max index
|
||||
/*! it is used to set caches max cost, and calculate animation opacity */
|
||||
int maxIndex_;
|
||||
|
||||
//! shadow configuration
|
||||
OxygenShadowConfiguration activeShadowConfiguration_;
|
||||
|
||||
//! shadow configuration
|
||||
OxygenShadowConfiguration inactiveShadowConfiguration_;
|
||||
|
||||
//! cache
|
||||
typedef QCache<int, TileSet> TileSetCache;
|
||||
|
||||
//! active shadow cache
|
||||
TileSetCache shadowCache_;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue