Refactoring of EffectFrame: EffectFrame becomes an interface just like EffectsHandler and EffectWindow and a concrete EffectFrameImpl in core.

Rendering of the EffectFrame is moved into the scene as Scene::EffectFrame with a concrete implementation in SceneXrender and SceneOpenGL.
A factory method for an EffectFrame is added to the EffectsHandler, which is used by the effects.
Next step: pass the EffectFrame through all effects, so that effects can transform, blur, invert whatever it.

svn path=/trunk/KDE/kdebase/workspace/; revision=1151271
icc-effect-5.14.5
Martin Gräßlin 2010-07-18 16:32:37 +00:00
parent 9c57c29385
commit e2eebb6503
21 changed files with 810 additions and 629 deletions

View File

@ -1164,6 +1164,10 @@ void EffectsHandlerImpl::effectsChanged()
}
}
EffectFrame* EffectsHandlerImpl::effectFrame( EffectFrameStyle style, bool staticSize, const QPoint& position, Qt::Alignment alignment ) const
{
return new EffectFrameImpl( style, staticSize, position, alignment );
}
//****************************************
// EffectWindowImpl
@ -1632,4 +1636,225 @@ EffectWindowList EffectWindowGroupImpl::members() const
return ret;
}
//****************************************
// EffectFrameImpl
//****************************************
EffectFrameImpl::EffectFrameImpl( EffectFrameStyle style, bool staticSize, QPoint position, Qt::Alignment alignment )
: QObject ( 0 )
, EffectFrame()
, m_style( style )
, m_static( staticSize )
, m_point( position )
, m_alignment( alignment )
{
if( m_style == Styled )
{
m_frame.setImagePath( "widgets/background" );
m_frame.setCacheAllRenderedFrames( true );
connect( Plasma::Theme::defaultTheme(), SIGNAL( themeChanged() ), this, SLOT( plasmaThemeChanged() ));
}
if( effects->compositingType() == OpenGLCompositing )
{
m_sceneFrame = new SceneOpenGL::EffectFrame( this );
}
else if( effects->compositingType() == XRenderCompositing )
{
m_sceneFrame = new SceneXrender::EffectFrame( this );
}
else
{
// that should not happen and will definitely crash!
m_sceneFrame = NULL;
}
}
EffectFrameImpl::~EffectFrameImpl()
{
delete m_sceneFrame;
}
const QFont& EffectFrameImpl::font() const
{
return m_font;
}
void EffectFrameImpl::setFont( const QFont& font )
{
if (m_font == font)
{
return;
}
m_font = font;
QRect oldGeom = m_geometry;
if( !m_text.isEmpty() )
{
autoResize();
}
if( oldGeom == m_geometry )
{ // Wasn't updated in autoResize()
m_sceneFrame->freeTextFrame();
}
}
void EffectFrameImpl::free()
{
m_sceneFrame->free();
}
const QRect& EffectFrameImpl::geometry() const
{
return m_geometry;
}
void EffectFrameImpl::setGeometry( const QRect& geometry, bool force )
{
QRect oldGeom = m_geometry;
m_geometry = geometry;
if( m_geometry == oldGeom && !force )
{
return;
}
effects->addRepaint( oldGeom );
effects->addRepaint( m_geometry );
if( m_geometry.size() == oldGeom.size() && !force )
{
return;
}
if( m_style == Styled )
{
qreal left, top, right, bottom;
m_frame.getMargins( left, top, right, bottom ); // m_geometry is the inner geometry
m_frame.resizeFrame( m_geometry.adjusted( -left, -top, right, bottom ).size() );
}
free();
}
const QPixmap& EffectFrameImpl::icon() const
{
return m_icon;
}
void EffectFrameImpl::setIcon( const QPixmap& icon )
{
m_icon = icon;
if( m_iconSize.isEmpty() ) // Set a size if we don't already have one
{
setIconSize( m_icon.size() );
}
}
const QSize& EffectFrameImpl::iconSize() const
{
return m_iconSize;
}
void EffectFrameImpl::setIconSize( const QSize& size )
{
if( m_iconSize == size )
{
return;
}
m_iconSize = size;
autoResize();
}
void EffectFrameImpl::plasmaThemeChanged()
{
free();
}
void EffectFrameImpl::render( QRegion region, double opacity, double frameOpacity )
{
if( m_geometry.isEmpty() )
{
return; // Nothing to display
}
region = infiniteRegion(); // TODO: Old region doesn't seem to work with OpenGL
// TODO: pass through all effects
m_sceneFrame->render( region, opacity, frameOpacity );
}
Qt::Alignment EffectFrameImpl::alignment() const
{
return m_alignment;
}
void EffectFrameImpl::setAlignment( Qt::Alignment alignment )
{
m_alignment = alignment;
}
void EffectFrameImpl::setPosition( const QPoint& point )
{
if( m_point == point )
{
return;
}
m_point = point;
autoResize();
}
const QString& EffectFrameImpl::text() const
{
return m_text;
}
void EffectFrameImpl::setText( const QString& text )
{
if( m_text == text )
{
return;
}
m_text = text;
QRect oldGeom = m_geometry;
autoResize();
if( oldGeom == m_geometry )
{ // Wasn't updated in autoResize()
m_sceneFrame->freeTextFrame();
}
}
void EffectFrameImpl::autoResize()
{
if( m_static )
return; // Not automatically resizing
QRect geometry;
// Set size
if( !m_text.isEmpty() )
{
QFontMetrics metrics( m_font );
geometry.setSize( metrics.size( 0, m_text ));
}
if( !m_icon.isNull() && !m_iconSize.isEmpty() )
{
geometry.setLeft( -m_iconSize.width() );
if( m_iconSize.height() > geometry.height() )
geometry.setHeight( m_iconSize.height() );
}
// Set position
if( m_alignment & Qt::AlignLeft )
geometry.moveLeft( m_point.x() );
else if( m_alignment & Qt::AlignRight )
geometry.moveLeft( m_point.x() - geometry.width() );
else
geometry.moveLeft( m_point.x() - geometry.width() / 2 );
if( m_alignment & Qt::AlignTop )
geometry.moveTop( m_point.y() );
else if( m_alignment & Qt::AlignBottom )
geometry.moveTop( m_point.y() - geometry.height() );
else
geometry.moveTop( m_point.y() - geometry.height() / 2 );
setGeometry( geometry );
}
} // namespace

View File

@ -144,6 +144,8 @@ class EffectsHandlerImpl : public EffectsHandler
virtual bool decorationsHaveAlpha() const;
virtual EffectFrame* effectFrame( EffectFrameStyle style, bool staticSize, const QPoint& position, Qt::Alignment alignment ) const;
// internal (used by kwin core or compositing code)
void startPaint();
void windowUserMovedResized( EffectWindow* c, bool first, bool last );
@ -307,6 +309,68 @@ class EffectWindowGroupImpl
Group* group;
};
class EffectFrameImpl
: public QObject, public EffectFrame
{
Q_OBJECT
public:
explicit EffectFrameImpl( EffectFrameStyle style, bool staticSize = true, QPoint position = QPoint( -1, -1 ),
Qt::Alignment alignment = Qt::AlignCenter );
virtual ~EffectFrameImpl();
virtual void free();
virtual void render( QRegion region = infiniteRegion(), double opacity = 1.0, double frameOpacity = 1.0 );
virtual Qt::Alignment alignment() const;
virtual void setAlignment( Qt::Alignment alignment );
virtual const QFont& font() const;
virtual void setFont( const QFont& font );
virtual const QRect& geometry() const;
virtual void setGeometry( const QRect& geometry, bool force = false );
virtual const QPixmap& icon() const;
virtual void setIcon( const QPixmap& icon );
virtual const QSize& iconSize() const;
virtual void setIconSize( const QSize& size );
virtual void setPosition( const QPoint& point );
virtual const QString& text() const;
virtual void setText( const QString& text );
EffectFrameStyle style() const
{
return m_style;
};
Plasma::FrameSvg& frame()
{
return m_frame;
}
bool isStatic() const
{
return m_static;
};
private Q_SLOTS:
void plasmaThemeChanged();
private:
Q_DISABLE_COPY( EffectFrameImpl ) // As we need to use Qt slots we cannot copy this class
void autoResize(); // Auto-resize if not a static size
EffectFrameStyle m_style;
Plasma::FrameSvg m_frame; // TODO: share between all EffectFrames
// Position
bool m_static;
QPoint m_point;
Qt::Alignment m_alignment;
QRect m_geometry;
// Contents
QString m_text;
QFont m_font;
QPixmap m_icon;
QSize m_iconSize;
Scene::EffectFrame* m_sceneFrame;
};
inline
QList<EffectWindow*> EffectsHandlerImpl::elevatedWindows() const

View File

@ -41,7 +41,7 @@ KWIN_EFFECT( boxswitch, BoxSwitchEffect )
BoxSwitchEffect::BoxSwitchEffect()
: mActivated( 0 )
, mMode( 0 )
, thumbnailFrame( EffectFrame::Styled )
, thumbnailFrame( effects->effectFrame( Styled ) )
, selected_window( 0 )
, painting_desktop( 0 )
, animation( false )
@ -56,8 +56,8 @@ BoxSwitchEffect::BoxSwitchEffect()
{
text_font.setBold( true );
text_font.setPointSize( 12 );
thumbnailFrame.setFont( text_font );
thumbnailFrame.setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
thumbnailFrame->setFont( text_font );
thumbnailFrame->setAlignment( Qt::AlignBottom | Qt::AlignHCenter );
highlight_margin = 10;
reconfigure( ReconfigureAll );
@ -65,6 +65,7 @@ BoxSwitchEffect::BoxSwitchEffect()
BoxSwitchEffect::~BoxSwitchEffect()
{
delete thumbnailFrame;
}
void BoxSwitchEffect::reconfigure( ReconfigureFlags )
@ -150,7 +151,7 @@ void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da
{
if( !painting_desktop )
{
thumbnailFrame.render( region );
thumbnailFrame->render( region );
QHash< int, ItemInfo* >::const_iterator i;
for( i = desktops.constBegin(); i != desktops.constEnd(); ++i )
@ -169,7 +170,7 @@ void BoxSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& da
void BoxSwitchEffect::paintWindowsBox(const QRegion& region)
{
thumbnailFrame.render( region );
thumbnailFrame->render( region );
if( (mAnimateSwitch && !mProxyActivated) || (mProxyActivated && mProxyAnimateSwitch) )
{
@ -438,7 +439,7 @@ void BoxSwitchEffect::tabBoxUpdated()
effects->addRepaint( desktops.value( selected_desktop )->area );
selected_desktop = effects->currentTabBoxDesktop();
if( !mProxyActivated || mProxyShowText )
thumbnailFrame.setText( effects->desktopName( selected_desktop ));
thumbnailFrame->setText( effects->desktopName( selected_desktop ));
if( desktops.contains( selected_desktop ))
effects->addRepaint( desktops.value( selected_desktop )->area );
effects->addRepaint( text_area );
@ -474,7 +475,7 @@ void BoxSwitchEffect::setActive()
original_desktops = effects->currentTabBoxDesktopList();
selected_desktop = effects->currentTabBoxDesktop();
if( !mProxyActivated || mProxyShowText )
thumbnailFrame.setText( effects->desktopName( selected_desktop ));
thumbnailFrame->setText( effects->desktopName( selected_desktop ));
}
calculateFrameSize();
calculateItemSizes();
@ -530,7 +531,7 @@ void BoxSwitchEffect::setInactive()
qDeleteAll( windows );
desktops.clear();
}
thumbnailFrame.free();
thumbnailFrame->free();
effects->addRepaint( frame_area );
frame_area = QRect();
}
@ -543,7 +544,7 @@ void BoxSwitchEffect::setSelectedWindow( EffectWindow* w )
}
selected_window = w;
if( selected_window && ( !mProxyActivated || mProxyShowText ) )
thumbnailFrame.setText( selected_window->caption() );
thumbnailFrame->setText( selected_window->caption() );
if( elevate_window && w )
{
effects->setElevatedWindow( selected_window, true );
@ -612,7 +613,7 @@ void BoxSwitchEffect::calculateFrameSize()
text_area.moveTo( frame_area.x(),
frame_area.y() + item_max_size.height() + separator_height);
thumbnailFrame.setGeometry( frame_area );
thumbnailFrame->setGeometry( frame_area );
}
void BoxSwitchEffect::calculateItemSizes()
@ -698,7 +699,7 @@ void BoxSwitchEffect::calculateItemSizes()
EffectWindow* w = ordered_windows.at( i );
windows[ w ] = new ItemInfo();
windows[ w ]->iconFrame = new EffectFrame( EffectFrame::Unstyled, false );
windows[ w ]->iconFrame = effects->effectFrame( Unstyled, false );
windows[ w ]->iconFrame->setAlignment( Qt::AlignTop | Qt::AlignLeft );
windows[ w ]->iconFrame->setIcon( w->icon() );
@ -736,7 +737,7 @@ void BoxSwitchEffect::calculateItemSizes()
EffectWindow* w = original_windows.at( i );
windows[ w ] = new ItemInfo();
windows[ w ]->iconFrame = new EffectFrame( EffectFrame::Unstyled, false );
windows[ w ]->iconFrame = effects->effectFrame( Unstyled, false );
windows[ w ]->iconFrame->setAlignment( Qt::AlignTop | Qt::AlignLeft );
windows[ w ]->iconFrame->setIcon( w->icon() );
@ -1086,7 +1087,7 @@ void BoxSwitchEffect::activateFromProxy( int mode, bool animate, bool showText,
mProxyAnimateSwitch = animate;
mProxyShowText = showText;
mPositioningFactor = positioningFactor;
thumbnailFrame.setText(" ");
thumbnailFrame->setText(" ");
if( ( mode == TabBoxWindowsMode ) || ( mode == TabBoxWindowsAlternativeMode ) )
{
if( effects->currentTabBoxWindowList().count() > 0 )

View File

@ -79,7 +79,7 @@ class BoxSwitchEffect
Window mInput;
int mMode;
EffectFrame thumbnailFrame;
EffectFrame* thumbnailFrame;
QRect frame_area;
int highlight_margin;

View File

@ -53,7 +53,7 @@ CoverSwitchEffect::CoverSwitchEffect()
, scaleFactor( 0.0 )
, direction( Left )
, selected_window( 0 )
, captionFrame( EffectFrame::Styled )
, captionFrame( effects->effectFrame( Styled ) )
, primaryTabBox( false )
, secondaryTabBox( false )
{
@ -62,11 +62,12 @@ CoverSwitchEffect::CoverSwitchEffect()
// Caption frame
captionFont.setBold( true );
captionFont.setPointSize( captionFont.pointSize() * 2 );
captionFrame.setFont( captionFont );
captionFrame->setFont( captionFont );
}
CoverSwitchEffect::~CoverSwitchEffect()
{
delete captionFrame;
}
bool CoverSwitchEffect::supported()
@ -327,7 +328,7 @@ void CoverSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData&
opacity = timeLine.value();
else if( stop )
opacity = 1.0 - timeLine.value();
captionFrame.render( region, opacity );
captionFrame->render( region, opacity );
}
if( ( thumbnails && (!dynamicThumbnails ||
@ -555,11 +556,11 @@ void CoverSwitchEffect::tabBoxAdded( int mode )
area.height() * 0.9f + area.y(),
area.width() * 0.5f,
QFontMetrics( captionFont ).height() );
captionFrame.setGeometry( frameRect );
captionFrame.setIconSize( QSize( frameRect.height(), frameRect.height() ));
captionFrame->setGeometry( frameRect );
captionFrame->setIconSize( QSize( frameRect.height(), frameRect.height() ));
// And initial contents
captionFrame.setText( selected_window->caption() );
captionFrame.setIcon( selected_window->icon() );
captionFrame->setText( selected_window->caption() );
captionFrame->setIcon( selected_window->icon() );
}
effects->addRepaintFull();
@ -657,8 +658,8 @@ void CoverSwitchEffect::tabBoxUpdated()
}
selected_window = effects->currentTabBoxWindow();
currentWindowList = effects->currentTabBoxWindowList();
captionFrame.setText( selected_window->caption() );
captionFrame.setIcon( selected_window->icon() );
captionFrame->setText( selected_window->caption() );
captionFrame->setIcon( selected_window->icon() );
}
}
effects->addRepaintFull();
@ -1016,7 +1017,7 @@ void CoverSwitchEffect::abort()
stop = false;
stopRequested = false;
effects->addRepaintFull();
captionFrame.free();
captionFrame->free();
}
void CoverSwitchEffect::windowClosed( EffectWindow* c )

View File

@ -93,7 +93,7 @@ class CoverSwitchEffect
EffectWindowList currentWindowList;
EffectWindowList referrencedWindows;
EffectFrame captionFrame;
EffectFrame* captionFrame;
QFont captionFont;
bool thumbnails;

View File

@ -56,7 +56,7 @@ CubeEffect::CubeEffect()
, cubeOpacity( 1.0 )
, opacityDesktopOnly( true )
, displayDesktopName( false )
, desktopNameFrame( EffectFrame::Styled )
, desktopNameFrame( effects->effectFrame( Styled ) )
, reflection( true )
, rotating( false )
, desktopChangedWhileRotating( false )
@ -95,7 +95,7 @@ CubeEffect::CubeEffect()
{
desktopNameFont.setBold( true );
desktopNameFont.setPointSize( 14 );
desktopNameFrame.setFont( desktopNameFont );
desktopNameFrame->setFont( desktopNameFont );
reconfigure( ReconfigureAll );
}
@ -249,6 +249,7 @@ CubeEffect::~CubeEffect()
delete capTexture;
delete cylinderShader;
delete sphereShader;
delete desktopNameFrame;
}
bool CubeEffect::loadShader()
@ -687,9 +688,9 @@ void CubeEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
QRect screenRect = effects->clientArea( ScreenArea, activeScreen, frontDesktop );
QRect frameRect = QRect( screenRect.width() * 0.33f + screenRect.x(), screenRect.height() * 0.95f + screenRect.y(),
screenRect.width() * 0.34f, QFontMetrics( desktopNameFont ).height() );
desktopNameFrame.setGeometry( frameRect );
desktopNameFrame.setText( effects->desktopName( frontDesktop ) );
desktopNameFrame.render( region, opacity );
desktopNameFrame->setGeometry( frameRect );
desktopNameFrame->setText( effects->desktopName( frontDesktop ) );
desktopNameFrame->render( region, opacity );
}
}
else
@ -1179,7 +1180,7 @@ void CubeEffect::postPaintScreen()
// delete the GL lists
glDeleteLists( glList, 3 );
desktopNameFrame.free();
desktopNameFrame->free();
}
effects->addRepaintFull();
}

View File

@ -115,7 +115,7 @@ class CubeEffect
float cubeOpacity;
bool opacityDesktopOnly;
bool displayDesktopName;
EffectFrame desktopNameFrame;
EffectFrame* desktopNameFrame;
QFont desktopNameFont;
bool reflection;
bool rotating;

View File

@ -1188,7 +1188,7 @@ void DesktopGridEffect::setup()
font.setPointSize( 12 );
for( int i = 0; i < effects->numberOfDesktops(); i++ )
{
EffectFrame* frame = new EffectFrame( EffectFrame::Unstyled, false );
EffectFrame* frame = effects->effectFrame( Unstyled, false );
frame->setFont( font );
frame->setText( effects->desktopName( i+1 ));
frame->setAlignment( desktopNameAlignment );
@ -1428,7 +1428,7 @@ void DesktopGridEffect::desktopsAdded( int old )
font.setPointSize( 12 );
for( int i = old; i < desktop; i++ )
{
EffectFrame* frame = new EffectFrame( EffectFrame::Unstyled, false );
EffectFrame* frame = effects->effectFrame( Unstyled, false );
frame->setFont( font );
frame->setText( effects->desktopName( i+1 ));
frame->setAlignment( desktopNameAlignment );

View File

@ -44,14 +44,14 @@ FlipSwitchEffect::FlipSwitchEffect()
, m_stop( false )
, m_animation( false )
, m_hasKeyboardGrab( false )
, m_captionFrame( EffectFrame::Styled )
, m_captionFrame( effects->effectFrame( Styled ) )
{
reconfigure( ReconfigureAll );
// Caption frame
m_captionFont.setBold( true );
m_captionFont.setPointSize( m_captionFont.pointSize() * 2 );
m_captionFrame.setFont( m_captionFont );
m_captionFrame->setFont( m_captionFont );
KActionCollection* actionCollection = new KActionCollection( this );
KAction* a = ( KAction* )actionCollection->addAction( "FlipSwitchCurrent" );
@ -78,6 +78,7 @@ FlipSwitchEffect::~FlipSwitchEffect()
{
effects->unreserveElectricBorder( border );
}
delete m_captionFrame;
}
bool FlipSwitchEffect::supported()
@ -417,9 +418,9 @@ void FlipSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& d
transparency.fill( QColor( 255, 255, 255, alpha ));
iconPixmap.setAlphaChannel( transparency.alphaChannel() );
}
m_captionFrame.setText( m_selectedWindow->caption() );
m_captionFrame.setIcon( iconPixmap );
m_captionFrame.render( region, opacity );
m_captionFrame->setText( m_selectedWindow->caption() );
m_captionFrame->setIcon( iconPixmap );
m_captionFrame->render( region, opacity );
}
}
}
@ -452,7 +453,7 @@ void FlipSwitchEffect::postPaintScreen()
{
m_stop = false;
m_active = false;
m_captionFrame.free();
m_captionFrame->free();
effects->setActiveFullScreenEffect( 0 );
effects->addRepaintFull();
qDeleteAll( m_windows );
@ -713,8 +714,8 @@ void FlipSwitchEffect::setActive( bool activate, FlipSwitchMode mode )
m_screenArea.height() * 0.1f + m_screenArea.y() - QFontMetrics( m_captionFont ).height(),
m_screenArea.width() * 0.5f,
QFontMetrics( m_captionFont ).height() );
m_captionFrame.setGeometry( frameRect );
m_captionFrame.setIconSize( QSize( frameRect.height(), frameRect.height() ));
m_captionFrame->setGeometry( frameRect );
m_captionFrame->setIconSize( QSize( frameRect.height(), frameRect.height() ));
effects->addRepaintFull();
}
else

View File

@ -90,7 +90,7 @@ class FlipSwitchEffect
bool m_hasKeyboardGrab;
Window m_input;
FlipSwitchMode m_mode;
EffectFrame m_captionFrame;
EffectFrame* m_captionFrame;
QFont m_captionFont;
EffectWindowList m_flipOrderedWindows;
QHash< const EffectWindow*, ItemInfo* > m_windows;

View File

@ -53,7 +53,7 @@ PresentWindowsEffect::PresentWindowsEffect()
, m_mode( ModeCurrentDesktop )
, m_managerWindow( NULL )
, m_highlightedWindow( NULL )
, m_filterFrame( EffectFrame::Styled, false )
, m_filterFrame( effects->effectFrame( Styled, false ) )
{
m_atomDesktop = XInternAtom( display(), "_KDE_PRESENT_WINDOWS_DESKTOP", False );
m_atomWindows = XInternAtom( display(), "_KDE_PRESENT_WINDOWS_GROUP", False );
@ -68,7 +68,7 @@ PresentWindowsEffect::PresentWindowsEffect()
QFont font;
font.setPointSize( font.pointSize() * 2 );
font.setBold( true );
m_filterFrame.setFont( font );
m_filterFrame->setFont( font );
KActionCollection* actionCollection = new KActionCollection( this );
KAction* a = ( KAction* )actionCollection->addAction( "Expose" );
@ -106,6 +106,7 @@ PresentWindowsEffect::~PresentWindowsEffect()
{
effects->unreserveElectricBorder( border );
}
delete m_filterFrame;
}
void PresentWindowsEffect::reconfigure( ReconfigureFlags )
@ -197,7 +198,7 @@ void PresentWindowsEffect::paintScreen( int mask, QRegion region, ScreenPaintDat
// Display the filter box
if( !m_windowFilter.isEmpty() )
m_filterFrame.render( region );
m_filterFrame->render( region );
}
void PresentWindowsEffect::postPaintScreen()
@ -376,12 +377,12 @@ void PresentWindowsEffect::windowAdded( EffectWindow *w )
m_windowData[w].visible = isVisibleWindow( w );
m_windowData[w].opacity = 0.0;
m_windowData[w].highlight = 0.0;
m_windowData[w].textFrame = new EffectFrame( EffectFrame::Unstyled, false );
m_windowData[w].textFrame = effects->effectFrame( Unstyled, false );
QFont font;
font.setBold( true );
font.setPointSize( 12 );
m_windowData[w].textFrame->setFont( font );
m_windowData[w].iconFrame = new EffectFrame( EffectFrame::Unstyled, false );
m_windowData[w].iconFrame = effects->effectFrame( Unstyled, false );
m_windowData[w].iconFrame->setAlignment( Qt::AlignRight | Qt::AlignBottom );
m_windowData[w].iconFrame->setIcon( w->icon() );
if( isSelectableWindow( w ))
@ -1549,12 +1550,12 @@ void PresentWindowsEffect::setActive( bool active, bool closingTab )
if( w->isOnCurrentDesktop() && !w->isMinimized() )
m_windowData[w].opacity = 1.0;
m_windowData[w].highlight = 1.0;
m_windowData[w].textFrame = new EffectFrame( EffectFrame::Unstyled, false );
m_windowData[w].textFrame = effects->effectFrame( Unstyled, false );
QFont font;
font.setBold( true );
font.setPointSize( 12 );
m_windowData[w].textFrame->setFont( font );
m_windowData[w].iconFrame = new EffectFrame( EffectFrame::Unstyled, false );
m_windowData[w].iconFrame = effects->effectFrame( Unstyled, false );
m_windowData[w].iconFrame->setAlignment( Qt::AlignRight | Qt::AlignBottom );
m_windowData[w].iconFrame->setIcon( w->icon() );
}
@ -1642,7 +1643,7 @@ void PresentWindowsEffect::setActive( bool active, bool closingTab )
// Move all windows back to their original position
foreach( EffectWindow *w, m_motionManager.managedWindows() )
m_motionManager.moveWindow( w, w->geometry() );
m_filterFrame.free();
m_filterFrame->free();
m_windowFilter.clear();
m_selectedWindows.clear();
@ -1670,8 +1671,8 @@ void PresentWindowsEffect::setActive( bool active, bool closingTab )
void PresentWindowsEffect::updateFilterFrame()
{
QRect area = effects->clientArea( ScreenArea, effects->activeScreen(), effects->currentDesktop() );
m_filterFrame.setPosition( QPoint( area.x() + area.width() / 2, area.y() + area.height() / 2 ));
m_filterFrame.setText( i18n( "Filter:\n%1", m_windowFilter ));
m_filterFrame->setPosition( QPoint( area.x() + area.width() / 2, area.y() + area.height() / 2 ));
m_filterFrame->setText( i18n( "Filter:\n%1", m_windowFilter ));
}
//-----------------------------------------------------------------------------

View File

@ -208,7 +208,7 @@ class PresentWindowsEffect
QList<GridSize> m_gridSizes;
// Filter box
EffectFrame m_filterFrame;
EffectFrame* m_filterFrame;
QString m_windowFilter;
// Shortcut - needed to toggle the effect

View File

@ -1289,331 +1289,12 @@ EffectWindow* WindowMotionManager::windowAtPoint( QPoint point, bool useStacking
/***************************************************************
EffectFrame
***************************************************************/
GLTexture* EffectFrame::m_unstyledTexture = NULL;
EffectFrame::EffectFrame( Style style, bool staticSize, QPoint position, Qt::Alignment alignment )
: QObject()
, m_style( style )
, m_static( staticSize )
, m_point( position )
, m_alignment( alignment )
EffectFrame::EffectFrame()
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
m_texture = NULL;
m_textTexture = NULL;
#endif
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
m_picture = NULL;
m_textPicture = NULL;
#endif
if( m_style == Unstyled )
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
if( effects->compositingType() == OpenGLCompositing && !m_unstyledTexture )
updateUnstyledTexture();
#endif
}
else if( m_style == Styled )
{
m_frame.setImagePath( "widgets/background" );
m_frame.setCacheAllRenderedFrames( true );
connect( Plasma::Theme::defaultTheme(), SIGNAL( themeChanged() ), this, SLOT( plasmaThemeChanged() ));
}
}
EffectFrame::~EffectFrame()
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
delete m_texture;
delete m_textTexture;
#endif
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
delete m_picture;
delete m_textPicture;
#endif
}
void EffectFrame::free()
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
delete m_texture;
m_texture = NULL;
delete m_textTexture;
m_textTexture = NULL;
#endif
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
delete m_picture;
m_picture = NULL;
delete m_textPicture;
m_textPicture = NULL;
#endif
}
void EffectFrame::render( QRegion region, double opacity, double frameOpacity )
{
if( m_geometry.isEmpty() )
return; // Nothing to display
region = infiniteRegion(); // TODO: Old region doesn't seem to work with OpenGL
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
if( effects->compositingType() == OpenGLCompositing )
{
glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glPushMatrix();
// Render the actual frame
if( m_style == Unstyled )
{
const QRect& area = m_geometry.adjusted( -5, -5, 5, 5 );
const int roundness = 5;
QVector<float> verts, texCoords;
verts.reserve( 80 );
texCoords.reserve( 80 );
// Center
addQuadVertices( verts, area.left() + roundness, area.top() + roundness,
area.right() - roundness, area.bottom() - roundness );
addQuadVertices( texCoords, 0.5, 0.5, 0.5, 0.5 );
// Left
addQuadVertices( verts, area.left(), area.top() + roundness,
area.left() + roundness, area.bottom() - roundness );
addQuadVertices( texCoords, 0.0, 0.5, 0.5, 0.5 );
// Top
addQuadVertices( verts, area.left() + roundness, area.top(),
area.right() - roundness, area.top() + roundness );
addQuadVertices( texCoords, 0.5, 0.0, 0.5, 0.5 );
// Right
addQuadVertices( verts, area.right() - roundness, area.top() + roundness,
area.right(), area.bottom() - roundness );
addQuadVertices( texCoords, 0.5, 0.5, 1.0, 0.5 );
// Bottom
addQuadVertices( verts, area.left() + roundness, area.bottom() - roundness,
area.right() - roundness, area.bottom() );
addQuadVertices( texCoords, 0.5, 0.5, 0.5, 1.0 );
// Top-left
addQuadVertices( verts, area.left(), area.top(),
area.left() + roundness, area.top() + roundness );
addQuadVertices( texCoords, 0.0, 0.0, 0.5, 0.5 );
// Top-right
addQuadVertices( verts, area.right() - roundness, area.top(),
area.right(), area.top() + roundness );
addQuadVertices( texCoords, 0.5, 0.0, 1.0, 0.5 );
// Bottom-left
addQuadVertices( verts, area.left(), area.bottom() - roundness,
area.left() + roundness, area.bottom() );
addQuadVertices( texCoords, 0.0, 0.5, 0.5, 1.0 );
// Bottom-right
addQuadVertices( verts, area.right() - roundness, area.bottom() - roundness,
area.right(), area.bottom() );
addQuadVertices( texCoords, 0.5, 0.5, 1.0, 1.0 );
glColor4f( 0.0, 0.0, 0.0, opacity * frameOpacity );
m_unstyledTexture->bind();
m_unstyledTexture->enableNormalizedTexCoords();
renderGLGeometry( verts.count() / 2, verts.data(), texCoords.data() );
m_unstyledTexture->disableNormalizedTexCoords();
m_unstyledTexture->unbind();
}
else if( m_style == Styled )
{
if( !m_texture ) // Lazy creation
updateTexture();
glColor4f( 1.0, 1.0, 1.0, opacity * frameOpacity );
m_texture->bind();
qreal left, top, right, bottom;
m_frame.getMargins( left, top, right, bottom ); // m_geometry is the inner geometry
m_texture->render( region, m_geometry.adjusted( -left, -top, right, bottom ));
m_texture->unbind();
}
glColor4f( 1.0, 1.0, 1.0, opacity );
// Render icon
if( !m_icon.isNull() && !m_iconSize.isEmpty() )
{
QPoint topLeft( m_geometry.x(), m_geometry.center().y() - m_iconSize.height() / 2 );
GLTexture* icon = new GLTexture( m_icon ); // TODO: Cache
icon->bind();
icon->render( region, QRect( topLeft, m_iconSize ));
icon->unbind();
delete icon;
}
// Render text
if( !m_text.isEmpty() )
{
if( !m_textTexture ) // Lazy creation
updateTextTexture();
m_textTexture->bind();
m_textTexture->render( region, m_geometry );
m_textTexture->unbind();
}
glPopMatrix();
glPopAttrib();
}
#endif
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
if( effects->compositingType() == XRenderCompositing )
{
// Render the actual frame
if( m_style == Unstyled )
xRenderRoundBox( effects->xrenderBufferPicture(), m_geometry.adjusted( -5, -5, 5, 5 ),
5, QColor( 0, 0, 0, int( opacity * frameOpacity * 255 )));
else if( m_style == Styled )
{
if( !m_picture ) // Lazy creation
updatePicture();
qreal left, top, right, bottom;
m_frame.getMargins( left, top, right, bottom ); // m_geometry is the inner geometry
QRect geom = m_geometry.adjusted( -left, -top, right, bottom );
XRenderComposite( display(), PictOpOver, *m_picture, None, effects->xrenderBufferPicture(),
0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height() );
}
XRenderPicture fill = xRenderBlendPicture(opacity);
// Render icon
if( !m_icon.isNull() && !m_iconSize.isEmpty() )
{
QPoint topLeft( m_geometry.x(), m_geometry.center().y() - m_iconSize.height() / 2 );
XRenderPicture* icon = new XRenderPicture( m_icon ); // TODO: Cache
QRect geom = QRect( topLeft, m_iconSize );
XRenderComposite( display(), PictOpOver, *icon, fill, effects->xrenderBufferPicture(),
0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height() );
delete icon;
}
// Render text
if( !m_text.isEmpty() )
{
if( !m_textPicture ) // Lazy creation
updateTextPicture();
XRenderComposite( display(), PictOpOver, *m_textPicture, fill, effects->xrenderBufferPicture(),
0, 0, 0, 0, m_geometry.x(), m_geometry.y(), m_geometry.width(), m_geometry.height() );
}
}
#endif
}
void EffectFrame::setPosition( const QPoint& point )
{
m_point = point;
autoResize();
}
void EffectFrame::setGeometry( const QRect& geometry, bool force )
{
QRect oldGeom = m_geometry;
m_geometry = geometry;
if( m_geometry == oldGeom && !force )
return;
effects->addRepaint( oldGeom );
effects->addRepaint( m_geometry );
if( m_geometry.size() == oldGeom.size() && !force )
return;
if( m_style == Styled )
{
qreal left, top, right, bottom;
m_frame.getMargins( left, top, right, bottom ); // m_geometry is the inner geometry
m_frame.resizeFrame( m_geometry.adjusted( -left, -top, right, bottom ).size() );
}
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
if( effects->compositingType() == OpenGLCompositing )
{
delete m_texture;
m_texture = NULL;
delete m_textTexture;
m_textTexture = NULL;
}
#endif
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
if( effects->compositingType() == XRenderCompositing )
{
delete m_picture;
m_picture = NULL;
delete m_textPicture;
m_textPicture = NULL;
}
#endif
}
void EffectFrame::setText( const QString& text )
{
m_text = text;
QRect oldGeom = m_geometry;
autoResize();
if( oldGeom == m_geometry )
{ // Wasn't updated in autoResize()
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
if( effects->compositingType() == OpenGLCompositing )
{
delete m_textTexture;
m_textTexture = NULL;
}
#endif
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
if( effects->compositingType() == XRenderCompositing )
{
delete m_textPicture;
m_textPicture = NULL;
}
#endif
}
}
void EffectFrame::setFont( const QFont& font )
{
m_font = font;
QRect oldGeom = m_geometry;
if( !m_text.isEmpty() )
autoResize();
if( oldGeom == m_geometry )
{ // Wasn't updated in autoResize()
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
if( effects->compositingType() == OpenGLCompositing )
{
delete m_textTexture;
m_textTexture = NULL;
}
#endif
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
if( effects->compositingType() == XRenderCompositing )
{
delete m_textPicture;
m_textPicture = NULL;
}
#endif
}
}
void EffectFrame::setIcon( const QPixmap& icon )
{
m_icon = icon;
if( m_iconSize.isEmpty() ) // Set a size if we don't already have one
setIconSize( m_icon.size() );
}
void EffectFrame::setIconSize( const QSize& size )
{
m_iconSize = size;
autoResize();
}
QColor EffectFrame::styledTextColor()
@ -1621,178 +1302,4 @@ QColor EffectFrame::styledTextColor()
return Plasma::Theme::defaultTheme()->color( Plasma::Theme::TextColor );
}
void EffectFrame::plasmaThemeChanged()
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
if( effects->compositingType() == OpenGLCompositing )
{
delete m_texture;
m_texture = NULL;
delete m_textTexture;
m_textTexture = NULL;
}
#endif
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
if( effects->compositingType() == XRenderCompositing )
{
delete m_picture;
m_picture = NULL;
delete m_textPicture;
m_textPicture = NULL;
}
#endif
}
void EffectFrame::autoResize()
{
if( m_static )
return; // Not automatically resizing
QRect geometry;
// Set size
if( !m_text.isEmpty() )
{
QFontMetrics metrics( m_font );
geometry.setSize( metrics.size( 0, m_text ));
}
if( !m_icon.isNull() && !m_iconSize.isEmpty() )
{
geometry.setLeft( -m_iconSize.width() );
if( m_iconSize.height() > geometry.height() )
geometry.setHeight( m_iconSize.height() );
}
// Set position
if( m_alignment & Qt::AlignLeft )
geometry.moveLeft( m_point.x() );
else if( m_alignment & Qt::AlignRight )
geometry.moveLeft( m_point.x() - geometry.width() );
else
geometry.moveLeft( m_point.x() - geometry.width() / 2 );
if( m_alignment & Qt::AlignTop )
geometry.moveTop( m_point.y() );
else if( m_alignment & Qt::AlignBottom )
geometry.moveTop( m_point.y() - geometry.height() );
else
geometry.moveTop( m_point.y() - geometry.height() / 2 );
setGeometry( geometry );
}
void EffectFrame::updateTexture()
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
delete m_texture;
if( m_style == Styled )
m_texture = new GLTexture( m_frame.framePixmap() );
#endif
}
void EffectFrame::updateTextTexture()
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
delete m_textTexture;
if( m_text.isEmpty() )
return;
// Determine position on texture to paint text
QRect rect( QPoint( 0, 0 ), m_geometry.size() );
if( !m_icon.isNull() && !m_iconSize.isEmpty() )
rect.setLeft( m_iconSize.width() );
// If static size elide text as required
QString text = m_text;
if( m_static )
{
QFontMetrics metrics( m_font );
text = metrics.elidedText( text, Qt::ElideRight, rect.width() );
}
QImage image( m_geometry.size(), QImage::Format_ARGB32 );
image.fill( Qt::transparent );
QPainter p( &image );
p.setFont( m_font );
if( m_style == Styled )
p.setPen( styledTextColor() );
else // TODO: What about no frame? Custom color setting required
p.setPen( Qt::white );
p.drawText( rect, m_alignment, text );
p.end();
m_textTexture = new GLTexture( image );
#endif
}
void EffectFrame::updatePicture()
{
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
delete m_picture;
if( m_style == Styled )
m_picture = new XRenderPicture( m_frame.framePixmap() );
#endif
}
void EffectFrame::updateTextPicture()
{ // Mostly copied from EffectFrame::updateTextTexture() above
#ifdef KWIN_HAVE_XRENDER_COMPOSITING
delete m_textPicture;
if( m_text.isEmpty() )
return;
// Determine position on texture to paint text
QRect rect( QPoint( 0, 0 ), m_geometry.size() );
if( !m_icon.isNull() && !m_iconSize.isEmpty() )
rect.setLeft( m_iconSize.width() );
// If static size elide text as required
QString text = m_text;
if( m_static )
{
QFontMetrics metrics( m_font );
text = metrics.elidedText( text, Qt::ElideRight, rect.width() );
}
QPixmap pixmap( m_geometry.size() );
pixmap.fill( Qt::transparent );
QPainter p( &pixmap );
p.setFont( m_font );
if( m_style == Styled )
p.setPen( styledTextColor() );
else // TODO: What about no frame? Custom color setting required
p.setPen( Qt::white );
p.drawText( rect, m_alignment, text );
p.end();
m_textPicture = new XRenderPicture( pixmap );
#endif
}
void EffectFrame::cleanup()
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
delete m_unstyledTexture;
m_unstyledTexture = NULL;
#endif
}
void EffectFrame::updateUnstyledTexture()
{
#ifdef KWIN_HAVE_OPENGL_COMPOSITING
delete m_unstyledTexture;
// Based off circle() from kwinxrenderutils.cpp
#define CS 8
QImage tmp( 2 * CS, 2 * CS, QImage::Format_ARGB32 );
tmp.fill( Qt::transparent );
QPainter p( &tmp );
p.setRenderHint( QPainter::Antialiasing );
p.setPen( Qt::NoPen );
p.setBrush( Qt::black );
p.drawEllipse( tmp.rect() );
p.end();
#undef CS
m_unstyledTexture = new GLTexture( tmp );
#endif
}
} // namespace

View File

@ -56,6 +56,7 @@ namespace KWin
class EffectWindow;
class EffectWindowGroup;
class EffectFrame;
class Effect;
class WindowQuad;
class GLRenderTarget;
@ -169,7 +170,7 @@ X-KDE-Library=kwin4_effect_cooleffect
#define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor ))
#define KWIN_EFFECT_API_VERSION_MAJOR 0
#define KWIN_EFFECT_API_VERSION_MINOR 151
#define KWIN_EFFECT_API_VERSION_MINOR 152
#define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \
KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR )
@ -196,6 +197,17 @@ enum DataRole
WindowForceBlurRole ///< For fullscreen effects to enforce blurring of windows
};
/**
* Style types used by @ref EffectFrame.
* @since 4.6
*/
enum EffectFrameStyle
{
None, ///< Displays no frame around the contents.
Unstyled, ///< Displays a basic box around the contents.
Styled ///< Displays a Plasma-styled frame around the contents.
};
/**
* Infinite region (i.e. a special region type saying that everything needs to be painted).
*/
@ -768,6 +780,16 @@ class KWIN_EXPORT EffectsHandler
*/
bool checkDriverBlacklist( const KConfigGroup& blacklist );
/**
* Creates a new frame object. If the frame does not have a static size
* then it will be located at @a position with @a alignment. A
* non-static frame will automatically adjust its size to fit the contents.
* @returns A new @ref EffectFrame. It is the responsibility of the caller to delete the
* EffectFrame.
* @since 4.6
*/
virtual EffectFrame* effectFrame( EffectFrameStyle style, bool staticSize = true,
const QPoint& position = QPoint( -1, -1 ), Qt::Alignment alignment = Qt::AlignCenter ) const = 0;
/**
* Sends message over DCOP to reload given effect.
@ -1662,110 +1684,49 @@ class KWIN_EXPORT WindowMotionManager
* another that doesn't.
* It is recommended to use this class whenever displaying text.
*/
class KWIN_EXPORT EffectFrame : public QObject
class KWIN_EXPORT EffectFrame
{
Q_OBJECT
public:
enum Style
{
None, ///< Displays no frame around the contents.
Unstyled, ///< Displays a basic box around the contents.
Styled ///< Displays a Plasma-styled frame around the contents.
};
/**
* Creates a new frame object. If the frame does not have a static size
* then it will be located at @a position with @a alignment. A
* non-static frame will automatically adjust its size to fit the
* contents.
*/
explicit EffectFrame( Style style, bool staticSize = true, QPoint position = QPoint( -1, -1 ),
Qt::Alignment alignment = Qt::AlignCenter );
~EffectFrame();
EffectFrame();
virtual ~EffectFrame();
/**
* Delete any existing textures to free up graphics memory. They will
* be automatically recreated the next time they are required.
*/
void free();
virtual void free() = 0;
/**
* Render the frame.
*/
void render( QRegion region = infiniteRegion(), double opacity = 1.0, double frameOpacity = 1.0 );
virtual void render( QRegion region = infiniteRegion(), double opacity = 1.0, double frameOpacity = 1.0 ) = 0;
void setPosition( const QPoint& point );
virtual void setPosition( const QPoint& point ) = 0;
/**
* Set the text alignment for static frames and the position alignment
* for non-static.
*/
inline void setAlignment( Qt::Alignment alignment )
{ m_alignment = alignment; }; // Doesn't change geometry
void setGeometry( const QRect& geometry, bool force = false );
inline QRect geometry() const // Inner/contents geometry
{ return m_geometry; };
virtual void setAlignment( Qt::Alignment alignment ) = 0;
virtual Qt::Alignment alignment() const = 0;
virtual void setGeometry( const QRect& geometry, bool force = false ) = 0;
virtual const QRect& geometry() const = 0;
void setText( const QString& text );
inline QString text() const
{ return m_text; };
void setFont( const QFont& font );
inline QFont font() const
{ return m_font; };
virtual void setText( const QString& text ) = 0;
virtual const QString& text() const = 0;
virtual void setFont( const QFont& font ) = 0;
virtual const QFont& font() const = 0;
/**
* Set the icon that will appear on the left-hand size of the frame.
*/
void setIcon( const QPixmap& icon );
inline QPixmap icon() const
{ return m_icon; };
void setIconSize( const QSize& size );
inline QSize iconSize() const
{ return m_iconSize; };
virtual void setIcon( const QPixmap& icon ) = 0;
virtual const QPixmap& icon() const = 0;
virtual void setIconSize( const QSize& size ) = 0;
virtual const QSize& iconSize() const = 0;
/**
* The foreground text color as specified by the default Plasma theme.
*/
static QColor styledTextColor();
/**
* Clean up all static texture data. Called when compositing is being disabled.
* @internal
*/
static void cleanup();
private Q_SLOTS:
void plasmaThemeChanged();
private:
Q_DISABLE_COPY( EffectFrame ) // As we need to use Qt slots we cannot copy this class
void autoResize(); // Auto-resize if not a static size
void updateTexture(); // Update OpenGL styled frame texture
void updateTextTexture(); // Update OpenGL text texture
void updatePicture(); // Update XRender styled frame picture
void updateTextPicture(); // Update XRender text picture
Style m_style;
Plasma::FrameSvg m_frame;
GLTexture* m_texture;
GLTexture* m_textTexture;
XRenderPicture* m_picture;
XRenderPicture* m_textPicture;
// Position
bool m_static;
QPoint m_point;
Qt::Alignment m_alignment;
QRect m_geometry;
// Contents
QString m_text;
QFont m_font;
QPixmap m_icon;
QSize m_iconSize;
static GLTexture* m_unstyledTexture;
static void updateUnstyledTexture(); // Update OpenGL unstyled frame texture
};
/**

View File

@ -532,4 +532,16 @@ WindowQuadList Scene::Window::makeQuads( WindowQuadType type, const QRegion& reg
return ret;
}
//****************************************
// Scene::EffectFrame
//****************************************
Scene::EffectFrame::EffectFrame(EffectFrameImpl* frame)
: m_effectFrame( frame )
{
}
Scene::EffectFrame::~EffectFrame()
{
}
} // namespace

15
scene.h
View File

@ -32,6 +32,7 @@ namespace KWin
class Workspace;
class Deleted;
class EffectFrameImpl;
class EffectWindowImpl;
class LanczosFilter;
@ -41,6 +42,7 @@ class Scene
public:
Scene( Workspace* ws );
virtual ~Scene() = 0;
class EffectFrame;
class Window;
// Returns true if the ctor failed to properly initialize.
@ -212,6 +214,19 @@ class Scene::Window
Q_DISABLE_COPY(Window)
};
class Scene::EffectFrame
{
public:
EffectFrame( EffectFrameImpl* frame );
virtual ~EffectFrame();
virtual void render( QRegion region, double opacity, double frameOpacity ) = 0;
virtual void free() = 0;
virtual void freeTextFrame() = 0;
protected:
EffectFrameImpl* m_effectFrame;
};
extern Scene* scene;
inline

View File

@ -233,7 +233,7 @@ SceneOpenGL::~SceneOpenGL()
glXDestroyPixmap( display(), last_pixmap );
glXDestroyContext( display(), ctxdrawable );
}
EffectFrame::cleanup();
SceneOpenGL::EffectFrame::cleanup();
checkGLError( "Cleanup" );
}
@ -1910,6 +1910,219 @@ void SceneOpenGL::Window::restoreRenderStates( TextureType type, double opacity,
glPopAttrib(); // ENABLE_BIT
}
//****************************************
// SceneOpenGL::EffectFrame
//****************************************
GLTexture* SceneOpenGL::EffectFrame::m_unstyledTexture = NULL;
SceneOpenGL::EffectFrame::EffectFrame( EffectFrameImpl* frame )
: Scene::EffectFrame( frame )
, m_texture( NULL )
, m_textTexture( NULL )
{
if( m_effectFrame->style() == Unstyled && !m_unstyledTexture )
{
updateUnstyledTexture();
}
}
SceneOpenGL::EffectFrame::~EffectFrame()
{
delete m_texture;
delete m_textTexture;
}
void SceneOpenGL::EffectFrame::free()
{
delete m_texture;
m_texture = NULL;
delete m_textTexture;
m_textTexture = NULL;
}
void SceneOpenGL::EffectFrame::freeTextFrame()
{
delete m_textTexture;
m_textTexture = NULL;
}
void SceneOpenGL::EffectFrame::render( QRegion region, double opacity, double frameOpacity )
{
if( m_effectFrame->geometry().isEmpty() )
return; // Nothing to display
region = infiniteRegion(); // TODO: Old region doesn't seem to work with OpenGL
glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
glPushMatrix();
// Render the actual frame
if( m_effectFrame->style() == Unstyled )
{
const QRect& area = m_effectFrame->geometry().adjusted( -5, -5, 5, 5 );
const int roundness = 5;
QVector<float> verts, texCoords;
verts.reserve( 80 );
texCoords.reserve( 80 );
// Center
addQuadVertices( verts, area.left() + roundness, area.top() + roundness,
area.right() - roundness, area.bottom() - roundness );
addQuadVertices( texCoords, 0.5, 0.5, 0.5, 0.5 );
// Left
addQuadVertices( verts, area.left(), area.top() + roundness,
area.left() + roundness, area.bottom() - roundness );
addQuadVertices( texCoords, 0.0, 0.5, 0.5, 0.5 );
// Top
addQuadVertices( verts, area.left() + roundness, area.top(),
area.right() - roundness, area.top() + roundness );
addQuadVertices( texCoords, 0.5, 0.0, 0.5, 0.5 );
// Right
addQuadVertices( verts, area.right() - roundness, area.top() + roundness,
area.right(), area.bottom() - roundness );
addQuadVertices( texCoords, 0.5, 0.5, 1.0, 0.5 );
// Bottom
addQuadVertices( verts, area.left() + roundness, area.bottom() - roundness,
area.right() - roundness, area.bottom() );
addQuadVertices( texCoords, 0.5, 0.5, 0.5, 1.0 );
// Top-left
addQuadVertices( verts, area.left(), area.top(),
area.left() + roundness, area.top() + roundness );
addQuadVertices( texCoords, 0.0, 0.0, 0.5, 0.5 );
// Top-right
addQuadVertices( verts, area.right() - roundness, area.top(),
area.right(), area.top() + roundness );
addQuadVertices( texCoords, 0.5, 0.0, 1.0, 0.5 );
// Bottom-left
addQuadVertices( verts, area.left(), area.bottom() - roundness,
area.left() + roundness, area.bottom() );
addQuadVertices( texCoords, 0.0, 0.5, 0.5, 1.0 );
// Bottom-right
addQuadVertices( verts, area.right() - roundness, area.bottom() - roundness,
area.right(), area.bottom() );
addQuadVertices( texCoords, 0.5, 0.5, 1.0, 1.0 );
glColor4f( 0.0, 0.0, 0.0, opacity * frameOpacity );
m_unstyledTexture->bind();
m_unstyledTexture->enableNormalizedTexCoords();
renderGLGeometry( verts.count() / 2, verts.data(), texCoords.data() );
m_unstyledTexture->disableNormalizedTexCoords();
m_unstyledTexture->unbind();
}
else if( m_effectFrame->style() == Styled )
{
if( !m_texture ) // Lazy creation
updateTexture();
glColor4f( 1.0, 1.0, 1.0, opacity * frameOpacity );
m_texture->bind();
qreal left, top, right, bottom;
m_effectFrame->frame().getMargins( left, top, right, bottom ); // m_geometry is the inner geometry
m_texture->render( region, m_effectFrame->geometry().adjusted( -left, -top, right, bottom ));
m_texture->unbind();
}
glColor4f( 1.0, 1.0, 1.0, opacity );
// Render icon
if( !m_effectFrame->icon().isNull() && !m_effectFrame->iconSize().isEmpty() )
{
QPoint topLeft( m_effectFrame->geometry().x(),
m_effectFrame->geometry().center().y() - m_effectFrame->iconSize().height() / 2 );
GLTexture* icon = new GLTexture( m_effectFrame->icon() ); // TODO: Cache
icon->bind();
icon->render( region, QRect( topLeft, m_effectFrame->iconSize() ));
icon->unbind();
delete icon;
}
// Render text
if( !m_effectFrame->text().isEmpty() )
{
if( !m_textTexture ) // Lazy creation
updateTextTexture();
m_textTexture->bind();
m_textTexture->render( region, m_effectFrame->geometry() );
m_textTexture->unbind();
}
glPopMatrix();
glPopAttrib();
}
void SceneOpenGL::EffectFrame::updateTexture()
{
delete m_texture;
if( m_effectFrame->style() == Styled )
m_texture = new GLTexture( m_effectFrame->frame().framePixmap() );
}
void SceneOpenGL::EffectFrame::updateTextTexture()
{
delete m_textTexture;
if( m_effectFrame->text().isEmpty() )
return;
// Determine position on texture to paint text
QRect rect( QPoint( 0, 0 ), m_effectFrame->geometry().size() );
if( !m_effectFrame->icon().isNull() && !m_effectFrame->iconSize().isEmpty() )
rect.setLeft( m_effectFrame->iconSize().width() );
// If static size elide text as required
QString text = m_effectFrame->text();
if( m_effectFrame->isStatic() )
{
QFontMetrics metrics( m_effectFrame->font() );
text = metrics.elidedText( text, Qt::ElideRight, rect.width() );
}
QImage image( m_effectFrame->geometry().size(), QImage::Format_ARGB32 );
image.fill( Qt::transparent );
QPainter p( &image );
p.setFont( m_effectFrame->font() );
if( m_effectFrame->style() == Styled )
p.setPen( m_effectFrame->styledTextColor() );
else // TODO: What about no frame? Custom color setting required
p.setPen( Qt::white );
p.drawText( rect, m_effectFrame->alignment(), text );
p.end();
m_textTexture = new GLTexture( image );
}
void SceneOpenGL::EffectFrame::updateUnstyledTexture()
{
delete m_unstyledTexture;
// Based off circle() from kwinxrenderutils.cpp
#define CS 8
QImage tmp( 2 * CS, 2 * CS, QImage::Format_ARGB32 );
tmp.fill( Qt::transparent );
QPainter p( &tmp );
p.setRenderHint( QPainter::Antialiasing );
p.setPen( Qt::NoPen );
p.setBrush( Qt::black );
p.drawEllipse( tmp.rect() );
p.end();
#undef CS
m_unstyledTexture = new GLTexture( tmp );
}
void SceneOpenGL::EffectFrame::cleanup()
{
delete m_unstyledTexture;
m_unstyledTexture = NULL;
}
} // namespace
#endif

View File

@ -38,6 +38,7 @@ class SceneOpenGL
: public Scene
{
public:
class EffectFrame;
class Texture;
class Window;
SceneOpenGL( Workspace* ws );
@ -165,6 +166,31 @@ class SceneOpenGL::Window
Texture bottomTexture;
};
class SceneOpenGL::EffectFrame
: public Scene::EffectFrame
{
public:
EffectFrame( EffectFrameImpl* frame );
virtual ~EffectFrame();
virtual void free();
virtual void freeTextFrame();
virtual void render(QRegion region, double opacity, double frameOpacity);
static void cleanup();
private:
void updateTexture();
void updateTextTexture();
GLTexture* m_texture;
GLTexture* m_textTexture;
static GLTexture* m_unstyledTexture;
static void updateUnstyledTexture(); // Update OpenGL unstyled frame texture
};
} // namespace
#endif

View File

@ -52,6 +52,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <kxerrorhandler.h>
#include <QtGui/QPainter>
namespace KWin
{
@ -843,5 +845,136 @@ void SceneXrender::Window::performPaint( int mask, QRegion region, WindowPaintDa
}
}
//****************************************
// SceneXrender::EffectFrame
//****************************************
SceneXrender::EffectFrame::EffectFrame( EffectFrameImpl* frame )
: Scene::EffectFrame( frame )
{
m_picture = NULL;
m_textPicture = NULL;
}
SceneXrender::EffectFrame::~EffectFrame()
{
delete m_picture;
delete m_textPicture;
}
void SceneXrender::EffectFrame::free()
{
delete m_picture;
m_picture = NULL;
delete m_textPicture;
m_textPicture = NULL;
}
void SceneXrender::EffectFrame::freeTextFrame()
{
delete m_textPicture;
m_textPicture = NULL;
}
void SceneXrender::EffectFrame::render( QRegion region, double opacity, double frameOpacity )
{
if( m_effectFrame->geometry().isEmpty() )
{
return; // Nothing to display
}
// Render the actual frame
if( m_effectFrame->style() == Unstyled )
xRenderRoundBox( effects->xrenderBufferPicture(), m_effectFrame->geometry().adjusted( -5, -5, 5, 5 ),
5, QColor( 0, 0, 0, int( opacity * frameOpacity * 255 )));
else if( m_effectFrame->style() == Styled )
{
if( !m_picture ) // Lazy creation
{
updatePicture();
}
qreal left, top, right, bottom;
m_effectFrame->frame().getMargins( left, top, right, bottom ); // m_geometry is the inner geometry
QRect geom = m_effectFrame->geometry().adjusted( -left, -top, right, bottom );
XRenderComposite( display(), PictOpOver, *m_picture, None, effects->xrenderBufferPicture(),
0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height() );
}
XRenderPicture fill = xRenderBlendPicture(opacity);
// Render icon
if( !m_effectFrame->icon().isNull() && !m_effectFrame->iconSize().isEmpty() )
{
QPoint topLeft( m_effectFrame->geometry().x(), m_effectFrame->geometry().center().y() - m_effectFrame->iconSize().height() / 2 );
XRenderPicture* icon = new XRenderPicture( m_effectFrame->icon() ); // TODO: Cache
QRect geom = QRect( topLeft, m_effectFrame->iconSize() );
XRenderComposite( display(), PictOpOver, *icon, fill, effects->xrenderBufferPicture(),
0, 0, 0, 0, geom.x(), geom.y(), geom.width(), geom.height() );
delete icon;
}
// Render text
if( !m_effectFrame->text().isEmpty() )
{
if( !m_textPicture ) // Lazy creation
{
updateTextPicture();
}
XRenderComposite( display(), PictOpOver, *m_textPicture, fill, effects->xrenderBufferPicture(),
0, 0, 0, 0, m_effectFrame->geometry().x(), m_effectFrame->geometry().y(),
m_effectFrame->geometry().width(), m_effectFrame->geometry().height() );
}
}
void SceneXrender::EffectFrame::updatePicture()
{
delete m_picture;
if( m_effectFrame->style() == Styled )
m_picture = new XRenderPicture( m_effectFrame->frame().framePixmap() );
}
void SceneXrender::EffectFrame::updateTextPicture()
{ // Mostly copied from SceneOpenGL::EffectFrame::updateTextTexture() above
delete m_textPicture;
if( m_effectFrame->text().isEmpty() )
{
return;
}
// Determine position on texture to paint text
QRect rect( QPoint( 0, 0 ), m_effectFrame->geometry().size() );
if( !m_effectFrame->icon().isNull() && !m_effectFrame->iconSize().isEmpty() )
{
rect.setLeft( m_effectFrame->iconSize().width() );
}
// If static size elide text as required
QString text = m_effectFrame->text();
if( m_effectFrame->isStatic() )
{
QFontMetrics metrics( m_effectFrame->text() );
text = metrics.elidedText( text, Qt::ElideRight, rect.width() );
}
QPixmap pixmap( m_effectFrame->geometry().size() );
pixmap.fill( Qt::transparent );
QPainter p( &pixmap );
p.setFont( m_effectFrame->font() );
if( m_effectFrame->style() == Styled )
{
p.setPen( m_effectFrame->styledTextColor() );
}
else
{
// TODO: What about no frame? Custom color setting required
p.setPen( Qt::white );
}
p.drawText( rect, m_effectFrame->alignment(), text );
p.end();
m_textPicture = new XRenderPicture( pixmap );
}
} // namespace
#endif

View File

@ -37,6 +37,7 @@ class SceneXrender
: public Scene
{
public:
class EffectFrame;
SceneXrender( Workspace* ws );
virtual ~SceneXrender();
virtual bool initFailed() const;
@ -92,6 +93,25 @@ class SceneXrender::Window
static QPixmap *temp_pixmap;
};
class SceneXrender::EffectFrame
: public Scene::EffectFrame
{
public:
EffectFrame( EffectFrameImpl* frame );
virtual ~EffectFrame();
virtual void free();
virtual void freeTextFrame();
virtual void render( QRegion region, double opacity, double frameOpacity );
private:
void updatePicture();
void updateTextPicture();
XRenderPicture* m_picture;
XRenderPicture* m_textPicture;
};
inline
Picture SceneXrender::bufferPicture()
{