Support for window thumbnails.
svn path=/branches/work/kwin_composite/; revision=640344
This commit is contained in:
parent
3da3488448
commit
f6ad1881e1
12 changed files with 229 additions and 5 deletions
|
@ -71,10 +71,11 @@ set(kwin_KDEINIT_SRCS
|
|||
effects/dialogparent.cpp
|
||||
effects/showfps.cpp
|
||||
effects/zoom.cpp
|
||||
effects/test_input.cpp
|
||||
effects/presentwindows.cpp
|
||||
effects/minimizeanimation.cpp
|
||||
effects/desktopchangeslide.cpp
|
||||
effects/test_input.cpp
|
||||
effects/test_thumbnail.cpp
|
||||
)
|
||||
|
||||
if( CAPTURY_FOUND )
|
||||
|
|
10
client.cpp
10
client.cpp
|
@ -281,6 +281,7 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
|
|||
|| ( decoration != NULL && !noBorder())))
|
||||
return;
|
||||
bool do_show = false;
|
||||
QRect oldgeom = geometry();
|
||||
blockGeometryUpdates( true );
|
||||
if( force )
|
||||
destroyDecoration();
|
||||
|
@ -304,6 +305,8 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
|
|||
discardWindowPixmap();
|
||||
if( scene != NULL )
|
||||
scene->windowGeometryShapeChanged( this );
|
||||
if( effects != NULL )
|
||||
effects->windowGeometryShapeChanged( effectWindow(), oldgeom );
|
||||
}
|
||||
else
|
||||
destroyDecoration();
|
||||
|
@ -317,6 +320,7 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
|
|||
|
||||
void Client::destroyDecoration()
|
||||
{
|
||||
QRect oldgeom = geometry();
|
||||
if( decoration != NULL )
|
||||
{
|
||||
delete decoration;
|
||||
|
@ -334,6 +338,8 @@ void Client::destroyDecoration()
|
|||
discardWindowPixmap();
|
||||
if( scene != NULL && !deleting )
|
||||
scene->windowGeometryShapeChanged( this );
|
||||
if( effects != NULL && !deleting )
|
||||
effects->windowGeometryShapeChanged( effectWindow(), oldgeom );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,6 +468,8 @@ void Client::updateShape()
|
|||
addDamageFull();
|
||||
if( scene != NULL )
|
||||
scene->windowGeometryShapeChanged( this );
|
||||
if( effects != NULL )
|
||||
effects->windowGeometryShapeChanged( effectWindow(), geometry());
|
||||
// workaround for #19644 - shaped windows shouldn't have decoration
|
||||
if( shape() && !noBorder())
|
||||
{
|
||||
|
@ -500,6 +508,8 @@ void Client::setMask( const QRegion& reg, int mode )
|
|||
addDamageFull();
|
||||
if( scene != NULL )
|
||||
scene->windowGeometryShapeChanged( this );
|
||||
if( effects != NULL )
|
||||
effects->windowGeometryShapeChanged( effectWindow(), geometry());
|
||||
}
|
||||
|
||||
QRegion Client::mask() const
|
||||
|
|
|
@ -429,6 +429,7 @@ void Toplevel::addDamage( int x, int y, int w, int h )
|
|||
r &= rect();
|
||||
damage_region += r;
|
||||
repaints_region += r;
|
||||
effects->windowDamaged( effectWindow(), r );
|
||||
}
|
||||
|
||||
void Toplevel::addDamageFull()
|
||||
|
@ -437,6 +438,7 @@ void Toplevel::addDamageFull()
|
|||
return;
|
||||
damage_region = rect();
|
||||
repaints_region = rect();
|
||||
effects->windowDamaged( effectWindow(), rect());
|
||||
}
|
||||
|
||||
void Toplevel::resetDamage( const QRect& r )
|
||||
|
|
65
effects.cpp
65
effects.cpp
|
@ -35,6 +35,7 @@ License. See the file "COPYING" for the exact licensing terms.
|
|||
#include "effects/zoom.h"
|
||||
|
||||
#include "effects/test_input.h"
|
||||
#include "effects/test_thumbnail.h"
|
||||
|
||||
namespace KWinInternal
|
||||
{
|
||||
|
@ -87,6 +88,14 @@ void Effect::desktopChanged( int )
|
|||
{
|
||||
}
|
||||
|
||||
void Effect::windowDamaged( EffectWindow*, const QRect& )
|
||||
{
|
||||
}
|
||||
|
||||
void Effect::windowGeometryShapeChanged( EffectWindow*, const QRect& )
|
||||
{
|
||||
}
|
||||
|
||||
void Effect::prePaintScreen( int* mask, QRegion* region, int time )
|
||||
{
|
||||
effects->prePaintScreen( mask, region, time );
|
||||
|
@ -117,13 +126,35 @@ void Effect::postPaintWindow( EffectWindow* w )
|
|||
effects->postPaintWindow( w );
|
||||
}
|
||||
|
||||
void Effect::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
|
||||
{
|
||||
effects->drawWindow( w, mask, region, data );
|
||||
}
|
||||
|
||||
void Effect::setPositionTransformations( WindowPaintData& data, QRect& region, EffectWindow* w,
|
||||
const QRect& r, Qt::AspectRatioMode aspect )
|
||||
{
|
||||
QSize size = w->size();
|
||||
size.scale( r.size(), aspect );
|
||||
data.xScale = size.width() / double( w->width());
|
||||
data.yScale = size.height() / double( w->height());
|
||||
int width = int( w->width() * data.xScale );
|
||||
int height = int( w->height() * data.yScale );
|
||||
int x = r.x() + ( r.width() - width ) / 2;
|
||||
int y = r.y() + ( r.height() - height ) / 2;
|
||||
region = QRect( x, y, width, height );
|
||||
data.xTranslate = x - w->x();
|
||||
data.yTranslate = y - w->y();
|
||||
}
|
||||
|
||||
//****************************************
|
||||
// EffectsHandler
|
||||
//****************************************
|
||||
|
||||
EffectsHandler::EffectsHandler()
|
||||
: current_paint_window( 0 )
|
||||
, current_paint_screen( 0 )
|
||||
: current_paint_screen( 0 )
|
||||
, current_paint_window( 0 )
|
||||
, current_draw_window( 0 )
|
||||
{
|
||||
if( !compositing())
|
||||
return;
|
||||
|
@ -147,7 +178,9 @@ EffectsHandler::EffectsHandler()
|
|||
registerEffect("ScaleIn", new GenericEffectFactory<ScaleInEffect>);
|
||||
registerEffect("DialogParent", new GenericEffectFactory<DialogParentEffect>);
|
||||
registerEffect("DesktopChangeSlide", new GenericEffectFactory<DesktopChangeSlideEffect>);
|
||||
|
||||
registerEffect("TestInput", new GenericEffectFactory<TestInputEffect>);
|
||||
registerEffect("TestThumbnail", new GenericEffectFactory<TestThumbnailEffect>);
|
||||
|
||||
QStringList::const_iterator effectsIterator;
|
||||
for( effectsIterator = options->defaultEffects.constBegin();
|
||||
|
@ -224,11 +257,26 @@ void EffectsHandler::desktopChanged( int old )
|
|||
ep.second->desktopChanged( old );
|
||||
}
|
||||
|
||||
void EffectsHandler::windowDamaged( EffectWindow* w, const QRect& r )
|
||||
{
|
||||
foreach( EffectPair ep, loaded_effects )
|
||||
ep.second->windowDamaged( w, r );
|
||||
}
|
||||
|
||||
void EffectsHandler::windowGeometryShapeChanged( EffectWindow* w, const QRect& old )
|
||||
{
|
||||
if( w == NULL ) // during late cleanup effectWindow() may be already NULL
|
||||
return; // in some functions that may still call this
|
||||
foreach( EffectPair ep, loaded_effects )
|
||||
ep.second->windowGeometryShapeChanged( w, old );
|
||||
}
|
||||
|
||||
// start another painting pass
|
||||
void EffectsHandler::startPaint()
|
||||
{
|
||||
assert( current_paint_screen == 0 );
|
||||
assert( current_paint_window == 0 );
|
||||
assert( current_draw_window == 0 );
|
||||
}
|
||||
|
||||
// the idea is that effects call this function again which calls the next one
|
||||
|
@ -294,6 +342,17 @@ void EffectsHandler::postPaintWindow( EffectWindow* w )
|
|||
// no special final code
|
||||
}
|
||||
|
||||
void EffectsHandler::drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
|
||||
{
|
||||
if( current_draw_window < loaded_effects.size())
|
||||
{
|
||||
loaded_effects[current_draw_window++].second->drawWindow( w, mask, region, data );
|
||||
--current_draw_window;
|
||||
}
|
||||
else
|
||||
scene->finalDrawWindow( w, mask, region, data );
|
||||
}
|
||||
|
||||
Window EffectsHandler::createInputWindow( Effect* e, int x, int y, int w, int h, const QCursor& cursor )
|
||||
{
|
||||
XSetWindowAttributes attrs;
|
||||
|
@ -400,6 +459,7 @@ void EffectsHandler::loadEffect( const QString& name )
|
|||
{
|
||||
assert( current_paint_screen == 0 );
|
||||
assert( current_paint_window == 0 );
|
||||
assert( current_draw_window == 0 );
|
||||
|
||||
for(QVector< EffectPair >::const_iterator it = loaded_effects.constBegin(); it != loaded_effects.constEnd(); it++)
|
||||
{
|
||||
|
@ -426,6 +486,7 @@ void EffectsHandler::unloadEffect( const QString& name )
|
|||
{
|
||||
assert( current_paint_screen == 0 );
|
||||
assert( current_paint_window == 0 );
|
||||
assert( current_draw_window == 0 );
|
||||
|
||||
for( QVector< EffectPair >::iterator it = loaded_effects.begin(); it != loaded_effects.end(); it++)
|
||||
{
|
||||
|
|
17
effects.h
17
effects.h
|
@ -69,8 +69,12 @@ class Effect
|
|||
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
|
||||
virtual void postPaintScreen();
|
||||
virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
|
||||
// paintWindow() can do various transformations
|
||||
virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
|
||||
virtual void postPaintWindow( EffectWindow* w );
|
||||
// drawWindow() is used even for thumbnails etc. - it can alter the window itself where it
|
||||
// makes sense (e.g.darkening out unresponsive windows), but it cannot do transformations
|
||||
virtual void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
|
||||
// called when moved/resized or once after it's finished
|
||||
virtual void windowUserMovedResized( EffectWindow* c, bool first, bool last );
|
||||
virtual void windowOpacityChanged( EffectWindow* c, double old_opacity );
|
||||
|
@ -82,12 +86,18 @@ class Effect
|
|||
virtual void windowUnminimized( EffectWindow* c );
|
||||
virtual void windowInputMouseEvent( Window w, QEvent* e );
|
||||
virtual void desktopChanged( int old );
|
||||
virtual void windowDamaged( EffectWindow* w, const QRect& r );
|
||||
virtual void windowGeometryShapeChanged( EffectWindow* w, const QRect& old );
|
||||
|
||||
// Interpolates between x and y
|
||||
static float interpolate(float x, float y, float a)
|
||||
{
|
||||
return x * (1 - a) + y * a;
|
||||
}
|
||||
// helper to set WindowPaintData and QRegion to necessary transformations so that
|
||||
// a following drawWindow() would put the window at the requested geometry (useful for thumbnails)
|
||||
static void setPositionTransformations( WindowPaintData& data, QRect& region, EffectWindow* w,
|
||||
const QRect& r, Qt::AspectRatioMode aspect );
|
||||
|
||||
protected:
|
||||
Workspace* workspace() const;
|
||||
|
@ -125,6 +135,7 @@ class EffectsHandler
|
|||
void prePaintWindow( EffectWindow* w, int* mask, QRegion* region, int time );
|
||||
void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
|
||||
void postPaintWindow( EffectWindow* w );
|
||||
void drawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
|
||||
// Functions for handling input - e.g. when an Expose-like effect is shown, an input window
|
||||
// covering the whole screen is created and all mouse events will be intercepted by it.
|
||||
// The effect's windowInputMouseEvent() will get called with such events.
|
||||
|
@ -148,6 +159,9 @@ class EffectsHandler
|
|||
bool checkInputWindowEvent( XEvent* e );
|
||||
void checkInputWindowStacking();
|
||||
void desktopChanged( int old );
|
||||
void windowDamaged( EffectWindow* w, const QRect& r );
|
||||
void windowGeometryShapeChanged( EffectWindow* w, const QRect& old );
|
||||
|
||||
void registerEffect( const QString& name, EffectFactory* factory );
|
||||
void loadEffect( const QString& name );
|
||||
void unloadEffect( const QString& name );
|
||||
|
@ -158,8 +172,9 @@ class EffectsHandler
|
|||
typedef QPair< Effect*, Window > InputWindowPair;
|
||||
QList< InputWindowPair > input_windows;
|
||||
QMap< QString, EffectFactory* > effect_factories;
|
||||
int current_paint_window;
|
||||
int current_paint_screen;
|
||||
int current_paint_window;
|
||||
int current_draw_window;
|
||||
};
|
||||
|
||||
// This class is a representation of a window used by/for Effect classes.
|
||||
|
|
75
effects/test_thumbnail.cpp
Normal file
75
effects/test_thumbnail.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
/*****************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
|
||||
|
||||
You can Freely distribute this program under the GNU General Public
|
||||
License. See the file "COPYING" for the exact licensing terms.
|
||||
******************************************************************/
|
||||
|
||||
/*
|
||||
|
||||
Testing of painting a window more than once. The active window is painted
|
||||
once more as a thumbnail in the bottom-right corner of the screen.
|
||||
|
||||
*/
|
||||
|
||||
#include "test_thumbnail.h"
|
||||
|
||||
namespace KWinInternal
|
||||
{
|
||||
|
||||
TestThumbnailEffect::TestThumbnailEffect()
|
||||
: active_window( NULL )
|
||||
{
|
||||
}
|
||||
|
||||
void TestThumbnailEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
|
||||
{
|
||||
effects->paintScreen( mask, region, data );
|
||||
if( active_window != NULL && region.contains( thumbnailRect()))
|
||||
{
|
||||
WindowPaintData data;
|
||||
QRect region;
|
||||
setPositionTransformations( data, region, active_window, thumbnailRect(), Qt::KeepAspectRatio );
|
||||
effects->drawWindow( active_window,
|
||||
Scene::PAINT_WINDOW_OPAQUE | Scene::PAINT_WINDOW_TRANSLUCENT | Scene::PAINT_WINDOW_TRANSFORMED,
|
||||
region, data );
|
||||
}
|
||||
}
|
||||
|
||||
void TestThumbnailEffect::windowActivated( EffectWindow* act )
|
||||
{
|
||||
active_window = act;
|
||||
workspace()->addRepaint( thumbnailRect());
|
||||
}
|
||||
|
||||
void TestThumbnailEffect::windowDamaged( EffectWindow* w, const QRect& )
|
||||
{
|
||||
if( w == active_window )
|
||||
workspace()->addRepaint( thumbnailRect());
|
||||
// TODO maybe just the relevant part of the area should be repainted?
|
||||
}
|
||||
|
||||
void TestThumbnailEffect::windowGeometryShapeChanged( EffectWindow* w, const QRect& old )
|
||||
{
|
||||
if( w == active_window && w->size() != old.size())
|
||||
workspace()->addRepaint( thumbnailRect());
|
||||
}
|
||||
|
||||
void TestThumbnailEffect::windowClosed( EffectWindow* w )
|
||||
{
|
||||
if( w == active_window )
|
||||
{
|
||||
active_window = NULL;
|
||||
workspace()->addRepaint( thumbnailRect());
|
||||
}
|
||||
}
|
||||
|
||||
QRect TestThumbnailEffect::thumbnailRect() const
|
||||
{
|
||||
return QRect( displayWidth() - 100, displayHeight() - 100, 100, 100 );
|
||||
}
|
||||
|
||||
} // namespace
|
42
effects/test_thumbnail.h
Normal file
42
effects/test_thumbnail.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*****************************************************************
|
||||
KWin - the KDE window manager
|
||||
This file is part of the KDE project.
|
||||
|
||||
Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
|
||||
|
||||
You can Freely distribute this program under the GNU General Public
|
||||
License. See the file "COPYING" for the exact licensing terms.
|
||||
******************************************************************/
|
||||
|
||||
/*
|
||||
|
||||
Testing of painting a window more than once.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef KWIN_TEST_THUMBNAIL_H
|
||||
#define KWIN_TEST_THUMBNAIL_H
|
||||
|
||||
#include <effects.h>
|
||||
|
||||
namespace KWinInternal
|
||||
{
|
||||
|
||||
class TestThumbnailEffect
|
||||
: public Effect
|
||||
{
|
||||
public:
|
||||
TestThumbnailEffect();
|
||||
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
|
||||
virtual void windowActivated( EffectWindow* w );
|
||||
virtual void windowDamaged( EffectWindow* w, const QRect& damage );
|
||||
virtual void windowGeometryShapeChanged( EffectWindow* w, const QRect& old );
|
||||
virtual void windowClosed( EffectWindow* w );
|
||||
private:
|
||||
QRect thumbnailRect() const;
|
||||
EffectWindow* active_window;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
|
@ -1636,6 +1636,8 @@ bool Unmanaged::windowEvent( XEvent* e )
|
|||
addDamageFull();
|
||||
if( scene != NULL )
|
||||
scene->windowGeometryShapeChanged( this );
|
||||
if( effects != NULL )
|
||||
effects->windowGeometryShapeChanged( effectWindow(), geometry());
|
||||
}
|
||||
#ifdef HAVE_XDAMAGE
|
||||
if( e->type == Extensions::damageNotifyEvent())
|
||||
|
@ -1664,10 +1666,13 @@ void Unmanaged::configureNotifyEvent( XConfigureEvent* e )
|
|||
if( newgeom == geom )
|
||||
return;
|
||||
workspace()->addRepaint( geometry()); // damage old area
|
||||
QRect old = geom;
|
||||
geom = newgeom;
|
||||
discardWindowPixmap();
|
||||
if( scene != NULL )
|
||||
scene->windowGeometryShapeChanged( this );
|
||||
if( effects != NULL )
|
||||
effects->windowGeometryShapeChanged( effectWindow(), old );
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
|
|
|
@ -1704,6 +1704,8 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
|
|||
discardWindowPixmap();
|
||||
if( scene != NULL )
|
||||
scene->windowGeometryShapeChanged( this );
|
||||
if( effects != NULL )
|
||||
effects->windowGeometryShapeChanged( effectWindow(), geom_before_block );
|
||||
}
|
||||
workspace()->addRepaint( geom_before_block );
|
||||
geom_before_block = geom;
|
||||
|
@ -1764,6 +1766,8 @@ void Client::plainResize( int w, int h, ForceGeometry_t force )
|
|||
discardWindowPixmap();
|
||||
if( scene != NULL )
|
||||
scene->windowGeometryShapeChanged( this );
|
||||
if( effects != NULL )
|
||||
effects->windowGeometryShapeChanged( effectWindow(), geom_before_block );
|
||||
workspace()->addRepaint( geom_before_block );
|
||||
geom_before_block = geom;
|
||||
}
|
||||
|
|
|
@ -230,6 +230,12 @@ void Scene::paintWindow( Window* w, int mask, QRegion region )
|
|||
|
||||
// the function that'll be eventually called by paintWindow() above
|
||||
void Scene::finalPaintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
|
||||
{
|
||||
effects->drawWindow( w, mask, region, data );
|
||||
}
|
||||
|
||||
// will be eventually called from drawWindow()
|
||||
void Scene::finalDrawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
|
||||
{
|
||||
w->sceneWindow()->performPaint( mask, region, data );
|
||||
}
|
||||
|
|
2
scene.h
2
scene.h
|
@ -90,6 +90,8 @@ class Scene
|
|||
void finalPaintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
|
||||
// shared implementation, starts painting the window
|
||||
virtual void paintWindow( Window* w, int mask, QRegion region );
|
||||
// called after all effects had their drawWindow() called
|
||||
void finalDrawWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data );
|
||||
// infinite region, i.e. everything
|
||||
static QRegion infiniteRegion();
|
||||
// compute time since the last repaint
|
||||
|
|
|
@ -1140,6 +1140,7 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat
|
|||
// paint only requested areas
|
||||
if( region != infiniteRegion()) // avoid integer overflow
|
||||
region.translate( -x(), -y());
|
||||
if(( mask & ( PAINT_SCREEN_TRANSFORMED | PAINT_WINDOW_TRANSFORMED )) == 0 )
|
||||
region &= shape();
|
||||
if( region.isEmpty())
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue