Texture scaling in resize effect and disabling the drawbound when the effect is present.
This provides a good resizing performance for users having problems with the live-updating resize. Patch by Thomas Lübking. svn path=/trunk/KDE/kdebase/workspace/; revision=1118714
This commit is contained in:
parent
fa0bc81364
commit
f6ebb5d913
6 changed files with 111 additions and 48 deletions
|
@ -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())
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
37
geometry.cpp
37
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<EffectsHandlerImpl*>(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<EffectsHandlerImpl*>(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<EffectsHandlerImpl*>(effects)->windowMoveResizeGeometryUpdate( effectWindow(), moveResizeGeom );
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue