From e2eebb6503876140840482aaf81f294a367b0509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sun, 18 Jul 2010 16:32:37 +0000 Subject: [PATCH] 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 --- effects.cpp | 225 ++++++++++ effects.h | 64 +++ effects/boxswitch/boxswitch.cpp | 27 +- effects/boxswitch/boxswitch.h | 2 +- effects/coverswitch/coverswitch.cpp | 21 +- effects/coverswitch/coverswitch.h | 2 +- effects/cube/cube.cpp | 13 +- effects/cube/cube.h | 2 +- effects/desktopgrid/desktopgrid.cpp | 4 +- effects/flipswitch/flipswitch.cpp | 17 +- effects/flipswitch/flipswitch.h | 2 +- effects/presentwindows/presentwindows.cpp | 21 +- effects/presentwindows/presentwindows.h | 2 +- lib/kwineffects.cpp | 495 +--------------------- lib/kwineffects.h | 121 ++---- scene.cpp | 12 + scene.h | 15 + scene_opengl.cpp | 215 +++++++++- scene_opengl.h | 26 ++ scene_xrender.cpp | 133 ++++++ scene_xrender.h | 20 + 21 files changed, 810 insertions(+), 629 deletions(-) diff --git a/effects.cpp b/effects.cpp index 155d55afb7..991b8f9045 100644 --- a/effects.cpp +++ b/effects.cpp @@ -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 diff --git a/effects.h b/effects.h index 29133d7788..c5c413d5c5 100644 --- a/effects.h +++ b/effects.h @@ -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 EffectsHandlerImpl::elevatedWindows() const diff --git a/effects/boxswitch/boxswitch.cpp b/effects/boxswitch/boxswitch.cpp index e50847e684..de89568eb9 100644 --- a/effects/boxswitch/boxswitch.cpp +++ b/effects/boxswitch/boxswitch.cpp @@ -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 ) diff --git a/effects/boxswitch/boxswitch.h b/effects/boxswitch/boxswitch.h index 75f7e87a85..7a80daad68 100644 --- a/effects/boxswitch/boxswitch.h +++ b/effects/boxswitch/boxswitch.h @@ -79,7 +79,7 @@ class BoxSwitchEffect Window mInput; int mMode; - EffectFrame thumbnailFrame; + EffectFrame* thumbnailFrame; QRect frame_area; int highlight_margin; diff --git a/effects/coverswitch/coverswitch.cpp b/effects/coverswitch/coverswitch.cpp index 9e4ff8c59d..299e0b0925 100644 --- a/effects/coverswitch/coverswitch.cpp +++ b/effects/coverswitch/coverswitch.cpp @@ -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 ) diff --git a/effects/coverswitch/coverswitch.h b/effects/coverswitch/coverswitch.h index ee305ed19e..a4a8d33cb7 100644 --- a/effects/coverswitch/coverswitch.h +++ b/effects/coverswitch/coverswitch.h @@ -93,7 +93,7 @@ class CoverSwitchEffect EffectWindowList currentWindowList; EffectWindowList referrencedWindows; - EffectFrame captionFrame; + EffectFrame* captionFrame; QFont captionFont; bool thumbnails; diff --git a/effects/cube/cube.cpp b/effects/cube/cube.cpp index 3ede4d53a7..9cbb3ff9f5 100644 --- a/effects/cube/cube.cpp +++ b/effects/cube/cube.cpp @@ -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(); } diff --git a/effects/cube/cube.h b/effects/cube/cube.h index c03d58b06c..f31085970e 100644 --- a/effects/cube/cube.h +++ b/effects/cube/cube.h @@ -115,7 +115,7 @@ class CubeEffect float cubeOpacity; bool opacityDesktopOnly; bool displayDesktopName; - EffectFrame desktopNameFrame; + EffectFrame* desktopNameFrame; QFont desktopNameFont; bool reflection; bool rotating; diff --git a/effects/desktopgrid/desktopgrid.cpp b/effects/desktopgrid/desktopgrid.cpp index 9aedf5bef8..57cc30d76e 100644 --- a/effects/desktopgrid/desktopgrid.cpp +++ b/effects/desktopgrid/desktopgrid.cpp @@ -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 ); diff --git a/effects/flipswitch/flipswitch.cpp b/effects/flipswitch/flipswitch.cpp index 07ffe899f1..17cea76cf0 100644 --- a/effects/flipswitch/flipswitch.cpp +++ b/effects/flipswitch/flipswitch.cpp @@ -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 diff --git a/effects/flipswitch/flipswitch.h b/effects/flipswitch/flipswitch.h index 934c701a9d..50f846e273 100644 --- a/effects/flipswitch/flipswitch.h +++ b/effects/flipswitch/flipswitch.h @@ -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; diff --git a/effects/presentwindows/presentwindows.cpp b/effects/presentwindows/presentwindows.cpp index 772f6c0a78..d98a4caa52 100644 --- a/effects/presentwindows/presentwindows.cpp +++ b/effects/presentwindows/presentwindows.cpp @@ -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 )); } //----------------------------------------------------------------------------- diff --git a/effects/presentwindows/presentwindows.h b/effects/presentwindows/presentwindows.h index 82ff77020a..24bc1a0da0 100644 --- a/effects/presentwindows/presentwindows.h +++ b/effects/presentwindows/presentwindows.h @@ -208,7 +208,7 @@ class PresentWindowsEffect QList m_gridSizes; // Filter box - EffectFrame m_filterFrame; + EffectFrame* m_filterFrame; QString m_windowFilter; // Shortcut - needed to toggle the effect diff --git a/lib/kwineffects.cpp b/lib/kwineffects.cpp index fb2373d47a..7a287d820b 100644 --- a/lib/kwineffects.cpp +++ b/lib/kwineffects.cpp @@ -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 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 diff --git a/lib/kwineffects.h b/lib/kwineffects.h index e25afbe407..f923961f54 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -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 }; /** diff --git a/scene.cpp b/scene.cpp index 543eec25aa..b775cef371 100644 --- a/scene.cpp +++ b/scene.cpp @@ -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 diff --git a/scene.h b/scene.h index 6de409e480..870749e140 100644 --- a/scene.h +++ b/scene.h @@ -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 diff --git a/scene_opengl.cpp b/scene_opengl.cpp index fc6e967408..f6049b4b14 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -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 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 diff --git a/scene_opengl.h b/scene_opengl.h index ddf20360b2..85de6eecf2 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -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 diff --git a/scene_xrender.cpp b/scene_xrender.cpp index fd293b2997..537116b818 100644 --- a/scene_xrender.cpp +++ b/scene_xrender.cpp @@ -52,6 +52,8 @@ along with this program. If not, see . #include +#include + 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 diff --git a/scene_xrender.h b/scene_xrender.h index 730e9b3086..6e6990e910 100644 --- a/scene_xrender.h +++ b/scene_xrender.h @@ -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() {