diff --git a/effects.cpp b/effects.cpp index e07694689a..389fda50fa 100644 --- a/effects.cpp +++ b/effects.cpp @@ -213,6 +213,14 @@ void EffectsHandlerImpl::postPaintWindow( EffectWindow* w ) // no special final code } +bool EffectsHandlerImpl::provideResizeEffect() + { + for( int i = 0; i < loaded_effects.size(); ++i ) + if( loaded_effects.at(i).second->isResizeEffect() ) + return true; + return false; + } + void EffectsHandlerImpl::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) { if( current_draw_window < loaded_effects.size()) diff --git a/effects.h b/effects.h index ebe001a192..6af0b3aeae 100644 --- a/effects.h +++ b/effects.h @@ -47,6 +47,8 @@ class EffectsHandlerImpl : public EffectsHandler virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); virtual void postPaintWindow( EffectWindow* w ); + bool provideResizeEffect(); + virtual void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); virtual void buildQuads( EffectWindow* w, WindowQuadList& quadList ); diff --git a/effects/resize/resize.cpp b/effects/resize/resize.cpp index 43edd88524..11d53825f9 100644 --- a/effects/resize/resize.cpp +++ b/effects/resize/resize.cpp @@ -55,50 +55,82 @@ void ResizeEffect::prePaintScreen( ScreenPrePaintData& data, int time ) effects->prePaintScreen( data, time ); } +void ResizeEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) + { + if( m_active && w == m_resizeWindow ) + data.mask |= PAINT_WINDOW_TRANSFORMED; + effects->prePaintWindow( w, data, time ); + } + void ResizeEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) { - effects->paintWindow( w, mask, region, data ); if( m_active && w == m_resizeWindow ) { - QRegion intersection = m_originalWindowRect.intersected( m_currentGeometry ); - QRegion paintRegion = m_originalWindowRect.united( m_currentGeometry ).subtracted( intersection ); - float alpha = 0.8f; - QColor color = KColorScheme( QPalette::Normal, KColorScheme::Selection ).background().color(); + if( m_features & TextureScale ) + { + data.xTranslate += m_currentGeometry.x() - m_originalGeometry.x(); + data.xScale *= m_currentGeometry.width(); + data.xScale /= m_originalGeometry.width(); + data.yTranslate += m_currentGeometry.y() - m_originalGeometry.y(); + data.yScale *= m_currentGeometry.height(); + data.yScale /= m_originalGeometry.height(); + } + effects->paintWindow( w, mask, region, data ); + + if( m_features & Outline ) + { + QRegion intersection = m_originalGeometry.intersected( m_currentGeometry ); + QRegion paintRegion = QRegion(m_originalGeometry).united( m_currentGeometry ).subtracted( intersection ); + float alpha = 0.8f; + QColor color = KColorScheme( QPalette::Normal, KColorScheme::Selection ).background().color(); #ifdef KWIN_HAVE_OPENGL_COMPOSITING - if( effects->compositingType() == OpenGLCompositing) - { - glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT ); - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); - glColor4f( color.red() / 255.0f, color.green() / 255.0f, color.blue() / 255.0f, alpha ); - glBegin( GL_QUADS ); - foreach( const QRect &r, paintRegion.rects() ) + if( effects->compositingType() == OpenGLCompositing) { - glVertex2i( r.x(), r.y() ); - glVertex2i( r.x() + r.width(), r.y() ); - glVertex2i( r.x() + r.width(), r.y() + r.height() ); - glVertex2i( r.x(), r.y() + r.height() ); + glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT ); + glEnable( GL_BLEND ); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glColor4f( color.red() / 255.0f, color.green() / 255.0f, color.blue() / 255.0f, alpha ); + glBegin( GL_QUADS ); + foreach( const QRect &r, paintRegion.rects() ) + { + glVertex2i( r.x(), r.y() ); + glVertex2i( r.x() + r.width(), r.y() ); + glVertex2i( r.x() + r.width(), r.y() + r.height() ); + glVertex2i( r.x(), r.y() + r.height() ); + } + glEnd(); + glPopAttrib(); } - glEnd(); - glPopAttrib(); - } #endif #ifdef KWIN_HAVE_XRENDER_COMPOSITING - if( effects->compositingType() == XRenderCompositing) - { - XRenderColor col; - col.alpha = int( alpha * 0xffff ); - col.red = int( alpha * 0xffff * color.red() / 255 ); - col.green = int( alpha * 0xffff * color.green() / 255 ); - col.blue= int( alpha * 0xffff * color.blue() / 255 ); - foreach( const QRect &r, paintRegion.rects() ) - XRenderFillRectangle( display(), PictOpOver, effects->xrenderBufferPicture(), - &col, r.x(), r.y(), r.width(), r.height()); - } + if( effects->compositingType() == XRenderCompositing) + { + XRenderColor col; + col.alpha = int( alpha * 0xffff ); + col.red = int( alpha * 0xffff * color.red() / 255 ); + col.green = int( alpha * 0xffff * color.green() / 255 ); + col.blue= int( alpha * 0xffff * color.blue() / 255 ); + foreach( const QRect &r, paintRegion.rects() ) + XRenderFillRectangle( display(), PictOpOver, effects->xrenderBufferPicture(), + &col, r.x(), r.y(), r.width(), r.height()); + } #endif + } } + else + effects->paintWindow( w, mask, region, data ); + } + +void ResizeEffect::reconfigure( ReconfigureFlags ) + { + KConfigGroup conf = effects->effectConfig("Resize"); + m_features = 0; + if ( conf.readEntry( "TextureScale", true ) ) + m_features |= TextureScale; + if ( conf.readEntry( "Outline", false ) ) + m_features |= Outline; } void ResizeEffect::windowUserMovedResized( EffectWindow* w, bool first, bool last ) @@ -112,7 +144,7 @@ void ResizeEffect::windowUserMovedResized( EffectWindow* w, bool first, bool las { m_active = true; m_resizeWindow = w; - m_originalWindowRect = w->geometry(); + m_originalGeometry = w->geometry(); m_currentGeometry = w->geometry(); w->addRepaintFull(); } diff --git a/effects/resize/resize.h b/effects/resize/resize.h index d2478adc97..2f0df4d669 100644 --- a/effects/resize/resize.h +++ b/effects/resize/resize.h @@ -32,16 +32,20 @@ class ResizeEffect public: ResizeEffect(); ~ResizeEffect(); + virtual inline bool isResizeEffect() { return true; } virtual void prePaintScreen( ScreenPrePaintData& data, int time ); + virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); + virtual void reconfigure( ReconfigureFlags ); virtual void windowUserMovedResized( EffectWindow *w, bool first, bool last ); virtual void windowMoveResizeGeometryUpdate(EffectWindow* c, const QRect& geometry); private: + enum Feature { TextureScale = 1<<0, Outline = 1<<1 }; bool m_active; + int m_features; EffectWindow* m_resizeWindow; - QRegion m_originalWindowRect; - QRect m_currentGeometry; + QRect m_currentGeometry, m_originalGeometry; }; } diff --git a/geometry.cpp b/geometry.cpp index 8880a053bd..08f1167daa 100644 --- a/geometry.cpp +++ b/geometry.cpp @@ -2660,7 +2660,9 @@ void Client::clearbound() void Client::doDrawbound( const QRect& geom, bool clear ) { - if( decoration != NULL && decoration->drawbound( geom, clear )) + if( effects && static_cast(effects)->provideResizeEffect() ) + return; // done by effect + if( decoration != NULL && decoration->drawbound( geom, clear ) ) return; // done by decoration XGCValues xgc; xgc.function = GXxor; @@ -3275,9 +3277,18 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root ) void Client::performMoveResize() { + bool haveResizeEffect = false; + bool transparent = false; + if( isResize() ) + { + haveResizeEffect = effects && static_cast(effects)->provideResizeEffect(); + transparent = haveResizeEffect || options->resizeMode == Options::Transparent; + } + else + transparent = options->moveMode == Options::Transparent; + #ifdef HAVE_XSYNC - if( isResize() && options->resizeMode == Options::Opaque && - sync_counter != None && !sync_resize_pending ) + if( isResize() && !transparent && sync_counter != None && !sync_resize_pending ) { sync_timeout = new QTimer( this ); connect( sync_timeout, SIGNAL( timeout()), SLOT( syncTimeout())); @@ -3287,20 +3298,20 @@ void Client::performMoveResize() } #endif sync_resize_pending = false; - if( rules()->checkMoveResizeMode - ( isResize() ? options->resizeMode : options->moveMode ) == Options::Opaque ) + if( transparent ) + { + if( !haveResizeEffect ) + clearbound(); // it's necessary to move the geometry tip when there's no outline + positionGeometryTip(); // shown, otherwise it would cause repaint problems in case + if( !haveResizeEffect ) + drawbound( moveResizeGeom ); // they overlap; the paint event will come after this, + } + else { if( !workspace()->tilingMode() ) - setGeometry( moveResizeGeom ); + setGeometry( moveResizeGeom ); positionGeometryTip(); } - else if( rules()->checkMoveResizeMode - ( isResize() ? options->resizeMode : options->moveMode ) == Options::Transparent ) - { - clearbound(); // it's necessary to move the geometry tip when there's no outline - positionGeometryTip(); // shown, otherwise it would cause repaint problems in case - drawbound( moveResizeGeom ); // they overlap; the paint event will come after this, - } // so the geometry tip will be painted above the outline if( effects ) { static_cast(effects)->windowMoveResizeGeometryUpdate( effectWindow(), moveResizeGeom ); diff --git a/lib/kwineffects.h b/lib/kwineffects.h index 6e11ff9ef9..21d7a6d159 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -170,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 132 +#define KWIN_EFFECT_API_VERSION_MINOR 133 #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \ KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR ) @@ -375,6 +375,12 @@ class KWIN_EXPORT Effect **/ virtual void postPaintWindow( EffectWindow* w ); + /** + * Called on Transparent resizes. + * return true if your effect substitutes the XOR rubberband + */ + virtual bool isResizeEffect() { return false; } + /** * Can be called to draw multiple copies (e.g. thumbnails) of a window. * You can change window's opacity/brightness/etc here, but you can't