Add convenience functions for damaging full area.

svn path=/branches/work/kwin_composite/; revision=598834
This commit is contained in:
Luboš Luňák 2006-10-24 19:28:17 +00:00
parent 10b31e7222
commit 3f46d36bb9
7 changed files with 82 additions and 153 deletions

View file

@ -28,6 +28,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "atoms.h" #include "atoms.h"
#include "notifications.h" #include "notifications.h"
#include "rules.h" #include "rules.h"
#include "scene.h"
#include <X11/extensions/shape.h> #include <X11/extensions/shape.h>
#include <QX11Info> #include <QX11Info>
@ -63,12 +64,10 @@ namespace KWinInternal
is done in manage(). is done in manage().
*/ */
Client::Client( Workspace *ws ) Client::Client( Workspace *ws )
: QObject( NULL ), : Toplevel( ws ),
client( None ), client( None ),
wrapper( None ), wrapper( None ),
frame( None ),
decoration( NULL ), decoration( NULL ),
wspace( ws ),
bridge( new Bridge( this )), bridge( new Bridge( this )),
move_faked_activity( false ), move_faked_activity( false ),
move_resize_grab_window( None ), move_resize_grab_window( None ),
@ -111,7 +110,6 @@ Client::Client( Workspace *ws )
deleting = false; deleting = false;
keep_above = false; keep_above = false;
keep_below = false; keep_below = false;
is_shape = false;
motif_noborder = false; motif_noborder = false;
motif_may_move = true; motif_may_move = true;
motif_may_resize = true; motif_may_resize = true;
@ -143,7 +141,7 @@ Client::Client( Workspace *ws )
cmap = None; cmap = None;
frame_geometry = QRect( 0, 0, 100, 100 ); // so that decorations don't start with size being (0,0) geom = QRect( 0, 0, 100, 100 ); // so that decorations don't start with size being (0,0)
client_size = QSize( 100, 100 ); client_size = QSize( 100, 100 );
// SELI initialize xsizehints?? // SELI initialize xsizehints??
@ -156,7 +154,8 @@ Client::~Client()
{ {
assert(!moveResizeMode); assert(!moveResizeMode);
assert( client == None ); assert( client == None );
assert( frame == None && wrapper == None ); assert( wrapper == None );
// assert( frameId() == None );
assert( decoration == NULL ); assert( decoration == NULL );
assert( postpone_geometry_updates == 0 ); assert( postpone_geometry_updates == 0 );
assert( !check_active_modal ); assert( !check_active_modal );
@ -177,6 +176,7 @@ void Client::releaseWindow( bool on_shutdown )
{ {
assert( !deleting ); assert( !deleting );
deleting = true; deleting = true;
finishCompositing();
workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules
StackingUpdatesBlocker blocker( workspace()); StackingUpdatesBlocker blocker( workspace());
if (moveResizeMode) if (moveResizeMode)
@ -220,8 +220,8 @@ void Client::releaseWindow( bool on_shutdown )
client = None; client = None;
XDestroyWindow( display(), wrapper ); XDestroyWindow( display(), wrapper );
wrapper = None; wrapper = None;
XDestroyWindow( display(), frame ); XDestroyWindow( display(), frameId());
frame = None; // frame = None;
--postpone_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry --postpone_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry
deleteClient( this, Allowed ); deleteClient( this, Allowed );
} }
@ -232,6 +232,7 @@ void Client::destroyClient()
{ {
assert( !deleting ); assert( !deleting );
deleting = true; deleting = true;
finishCompositing();
workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules workspace()->discardUsedWindowRules( this, true ); // remove ForceTemporarily rules
StackingUpdatesBlocker blocker( workspace()); StackingUpdatesBlocker blocker( workspace());
if (moveResizeMode) if (moveResizeMode)
@ -247,8 +248,8 @@ void Client::destroyClient()
client = None; // invalidate client = None; // invalidate
XDestroyWindow( display(), wrapper ); XDestroyWindow( display(), wrapper );
wrapper = None; wrapper = None;
XDestroyWindow( display(), frame ); XDestroyWindow( display(), frameId());
frame = None; // frame = None;
--postpone_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry --postpone_geometry_updates; // don't use GeometryUpdatesBlocker, it would now set the geometry
deleteClient( this, Allowed ); deleteClient( this, Allowed );
} }
@ -264,7 +265,6 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
destroyDecoration(); destroyDecoration();
if( !noBorder()) if( !noBorder())
{ {
setMask( QRegion()); // reset shape mask
decoration = workspace()->createDecoration( bridge ); decoration = workspace()->createDecoration( bridge );
// TODO check decoration's minimum size? // TODO check decoration's minimum size?
decoration->init(); decoration->init();
@ -279,6 +279,8 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
workarea_diff_x = save_workarea_diff_x; workarea_diff_x = save_workarea_diff_x;
workarea_diff_y = save_workarea_diff_y; workarea_diff_y = save_workarea_diff_y;
do_show = true; do_show = true;
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
} }
else else
destroyDecoration(); destroyDecoration();
@ -288,6 +290,7 @@ void Client::updateDecoration( bool check_workspace_pos, bool force )
if( do_show ) if( do_show )
decoration->widget()->show(); decoration->widget()->show();
updateFrameExtents(); updateFrameExtents();
addDamageFull();
} }
void Client::destroyDecoration() void Client::destroyDecoration()
@ -305,6 +308,9 @@ void Client::destroyDecoration()
move( grav ); move( grav );
workarea_diff_x = save_workarea_diff_x; workarea_diff_x = save_workarea_diff_x;
workarea_diff_y = save_workarea_diff_y; workarea_diff_y = save_workarea_diff_y;
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
addDamageFull();
} }
} }
@ -334,7 +340,7 @@ void Client::checkBorderSizes()
void Client::detectNoBorder() void Client::detectNoBorder()
{ {
if( Shape::hasShape( window())) if( shape())
{ {
noborder = true; noborder = true;
return; return;
@ -422,47 +428,22 @@ void Client::setUserNoBorder( bool set )
void Client::updateShape() void Client::updateShape()
{ {
if ( shape() )
XShapeCombineShape(display(), frameId(), ShapeBounding,
clientPos().x(), clientPos().y(),
window(), ShapeBounding, ShapeSet);
else
XShapeCombineMask( display(), frameId(), ShapeBounding, 0, 0,
None, ShapeSet);
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
addDamageFull();
// workaround for #19644 - shaped windows shouldn't have decoration // workaround for #19644 - shaped windows shouldn't have decoration
if( shape() && !noBorder()) if( shape() && !noBorder())
{ {
noborder = true; noborder = true;
updateDecoration( true ); updateDecoration( true );
} }
if( shape())
{
XShapeCombineShape(display(), frameId(), ShapeBounding,
clientPos().x(), clientPos().y(),
window(), ShapeBounding, ShapeSet);
}
// !shape() mask setting is done in setMask() when the decoration
// calls it or when the decoration is created/destroyed
if( Shape::version() >= 0x11 ) // 1.1, has input shape support
{ // There appears to be no way to find out if a window has input
// shape set or not, so always propagate the input shape
// (it's the same like the bounding shape by default).
// Also, build the shape using a helper window, not directly
// in the frame window, because the sequence set-shape-to-frame,
// remove-shape-of-client, add-input-shape-of-client has the problem
// that after the second step there's a hole in the input shape
// until the real shape of the client is added and that can make
// the window lose focus (which is a problem with mouse focus policies)
static Window helper_window = None;
if( helper_window == None )
helper_window = XCreateSimpleWindow( display(), rootWindow(),
0, 0, 1, 1, 0, 0, 0 );
XResizeWindow( display(), helper_window, width(), height());
XShapeCombineShape( display(), helper_window, ShapeInput, 0, 0,
frameId(), ShapeBounding, ShapeSet );
XShapeCombineShape( display(), helper_window, ShapeInput,
clientPos().x(), clientPos().y(),
window(), ShapeBounding, ShapeSubtract );
XShapeCombineShape( display(), helper_window, ShapeInput,
clientPos().x(), clientPos().y(),
window(), ShapeInput, ShapeUnion );
XShapeCombineShape( display(), frameId(), ShapeInput, 0, 0,
helper_window, ShapeInput, ShapeSet );
}
} }
void Client::setMask( const QRegion& reg, int mode ) void Client::setMask( const QRegion& reg, int mode )
@ -491,7 +472,9 @@ void Client::setMask( const QRegion& reg, int mode )
xrects, rects.count(), ShapeSet, mode ); xrects, rects.count(), ShapeSet, mode );
delete[] xrects; delete[] xrects;
} }
updateShape(); if( scene != NULL )
scene->windowGeometryShapeChanged( this );
addDamageFull();
} }
QRegion Client::mask() const QRegion Client::mask() const
@ -936,7 +919,7 @@ void Client::rawShow()
{ {
if( decoration != NULL ) if( decoration != NULL )
decoration->widget()->show(); // not really necessary, but let it know the state decoration->widget()->show(); // not really necessary, but let it know the state
XMapWindow( display(), frame ); XMapWindow( display(), frameId());
if( !isShade()) if( !isShade())
{ {
XMapWindow( display(), wrapper ); XMapWindow( display(), wrapper );
@ -958,7 +941,7 @@ void Client::rawHide()
// will be missed is also very minimal, so I don't think it's needed to grab the server // will be missed is also very minimal, so I don't think it's needed to grab the server
// here. // here.
XSelectInput( display(), wrapper, ClientWinMask ); // avoid getting UnmapNotify XSelectInput( display(), wrapper, ClientWinMask ); // avoid getting UnmapNotify
XUnmapWindow( display(), frame ); XUnmapWindow( display(), frameId());
XUnmapWindow( display(), wrapper ); XUnmapWindow( display(), wrapper );
XUnmapWindow( display(), client ); XUnmapWindow( display(), client );
XSelectInput( display(), wrapper, ClientWinMask | SubstructureNotifyMask ); XSelectInput( display(), wrapper, ClientWinMask | SubstructureNotifyMask );
@ -1303,7 +1286,7 @@ QString Client::readName() const
return KWin::readNameProperty( window(), XA_WM_NAME ); return KWin::readNameProperty( window(), XA_WM_NAME );
} }
KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate, const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption()); KWIN_COMPARE_PREDICATE( FetchNameInternalPredicate, Client, const Client*, (!cl->isSpecialWindow() || cl->isToolbar()) && cl != value && cl->caption() == value->caption());
void Client::setCaption( const QString& _s, bool force ) void Client::setCaption( const QString& _s, bool force )
{ {
@ -1620,58 +1603,6 @@ bool Client::wantsInput() const
return rules()->checkAcceptFocus( input || Ptakefocus ); return rules()->checkAcceptFocus( input || Ptakefocus );
} }
bool Client::isDesktop() const
{
return windowType() == NET::Desktop;
}
bool Client::isDock() const
{
return windowType() == NET::Dock;
}
bool Client::isTopMenu() const
{
return windowType() == NET::TopMenu;
}
bool Client::isMenu() const
{
return windowType() == NET::Menu && !isTopMenu(); // because of backwards comp.
}
bool Client::isToolbar() const
{
return windowType() == NET::Toolbar;
}
bool Client::isSplash() const
{
return windowType() == NET::Splash;
}
bool Client::isUtility() const
{
return windowType() == NET::Utility;
}
bool Client::isDialog() const
{
return windowType() == NET::Dialog;
}
bool Client::isNormalWindow() const
{
return windowType() == NET::Normal;
}
bool Client::isSpecialWindow() const
{
return isDesktop() || isDock() || isSplash() || isTopMenu()
|| isToolbar(); // TODO
}
NET::WindowType Client::windowType( bool direct, int supported_types ) const NET::WindowType Client::windowType( bool direct, int supported_types ) const
{ {
NET::WindowType wt = info->windowType( supported_types ); NET::WindowType wt = info->windowType( supported_types );
@ -1703,6 +1634,12 @@ NET::WindowType Client::windowType( bool direct, int supported_types ) const
return wt; return wt;
} }
bool Client::isSpecialWindow() const
{
return isDesktop() || isDock() || isSplash() || isTopMenu()
|| isToolbar(); // TODO
}
/*! /*!
Sets an appropriate cursor shape for the logical mouse position \a m Sets an appropriate cursor shape for the logical mouse position \a m
@ -1799,46 +1736,24 @@ void Client::cancelAutoRaise()
autoRaiseTimer = 0; autoRaiseTimer = 0;
} }
#ifndef NDEBUG double Client::opacity() const
kdbgstream& operator<<( kdbgstream& stream, const Client* cl )
{ {
if( cl == NULL ) if( info->opacity() == 0xffffffff )
return stream << "\'NULL_CLIENT\'"; return 1.0;
return stream << "\'ID:" << cl->window() << ";WMCLASS:" << cl->resourceClass() << ":" << cl->resourceName() << ";Caption:" << cl->caption() << "\'"; return info->opacity() * 1.0 / 0xffffffff;
} }
kdbgstream& operator<<( kdbgstream& stream, const ClientList& list )
void Client::setOpacity( double opacity )
{ {
stream << "LIST:("; opacity = qBound( 0.0, opacity, 1.0 );
bool first = true; info->setOpacity( static_cast< unsigned long >( opacity * 0xffffffff ));
for( ClientList::ConstIterator it = list.begin(); // we'll react on PropertyNotify
it != list.end();
++it )
{
if( !first )
stream << ":";
first = false;
stream << *it;
}
stream << ")";
return stream;
} }
kdbgstream& operator<<( kdbgstream& stream, const ConstClientList& list )
void Client::debug( kdbgstream& stream ) const
{ {
stream << "LIST:("; stream << "\'ID:" << window() << ";WMCLASS:" << resourceClass() << ":" << resourceName() << ";Caption:" << caption() << "\'";
bool first = true;
for( ConstClientList::ConstIterator it = list.begin();
it != list.end();
++it )
{
if( !first )
stream << ":";
first = false;
stream << *it;
}
stream << ")";
return stream;
} }
#endif
QPixmap * kwin_get_menu_pix_hack() QPixmap * kwin_get_menu_pix_hack()
{ {

View file

@ -62,7 +62,7 @@ void Workspace::setupCompositing()
else if( dynamic_cast< SceneBasic* >( scene )) else if( dynamic_cast< SceneBasic* >( scene ))
kDebug() << "X compositing" << endl; kDebug() << "X compositing" << endl;
effects = new EffectsHandler( this ); effects = new EffectsHandler( this );
addDamage( 0, 0, displayWidth(), displayHeight()); addDamageFull();
foreach( Client* c, clients ) foreach( Client* c, clients )
c->setupCompositing(); c->setupCompositing();
foreach( Unmanaged* c, unmanaged ) foreach( Unmanaged* c, unmanaged )
@ -117,6 +117,13 @@ void Workspace::addDamage( const QRect& r )
return; return;
damage_region += r; damage_region += r;
} }
void Workspace::addDamageFull()
{
if( !compositing())
return;
damage_region = QRegion( 0, 0, displayWidth(), displayHeight());
}
void Workspace::compositeTimeout() void Workspace::compositeTimeout()
{ {
@ -210,6 +217,11 @@ void Toplevel::addDamage( int x, int y, int w, int h )
workspace()->addDamage( r ); workspace()->addDamage( r );
} }
void Toplevel::addDamageFull()
{
addDamage( rect());
}
void Toplevel::resetDamage() void Toplevel::resetDamage()
{ {
damage_region = QRegion(); damage_region = QRegion();

View file

@ -81,7 +81,7 @@ void MakeHalfTransparent::paintWindow( Scene::Window* w, int mask, QRegion regio
void MakeHalfTransparent::windowUserMovedResized( Toplevel* c, bool first, bool last ) void MakeHalfTransparent::windowUserMovedResized( Toplevel* c, bool first, bool last )
{ {
if( first || last ) if( first || last )
c->addDamage( c->rect()); c->addDamageFull();
} }
ShakyMove::ShakyMove() ShakyMove::ShakyMove()
@ -125,7 +125,7 @@ void ShakyMove::windowUserMovedResized( Toplevel* c, bool first, bool last )
{ {
windows.remove( c ); windows.remove( c );
// just damage whole screen, transformation is involved // just damage whole screen, transformation is involved
c->workspace()->addDamage( 0, 0, displayWidth(), displayHeight()); c->workspace()->addDamageFull();
if( windows.isEmpty()) if( windows.isEmpty())
timer.stop(); timer.stop();
} }
@ -149,7 +149,7 @@ void ShakyMove::tick()
else else
++(*it); ++(*it);
// just damage whole screen, transformation is involved // just damage whole screen, transformation is involved
it.key()->workspace()->addDamage( 0, 0, displayWidth(), displayHeight()); it.key()->workspace()->addDamageFull();
} }
} }
@ -191,13 +191,13 @@ void ShiftWorkspaceUp::prePaintScreen( int* mask, QRegion* region, int time )
{ {
diff = qBound( 0, diff + time, 1000 ); // KDE3: note this differs from KCLAMP diff = qBound( 0, diff + time, 1000 ); // KDE3: note this differs from KCLAMP
if( diff < 1000 ) if( diff < 1000 )
wspace->addDamage( 0, 0, displayWidth(), displayHeight()); // affects next redraw wspace->addDamageFull(); // affects next redraw
} }
if( !up && diff > 0 ) if( !up && diff > 0 )
{ {
diff = qBound( 0, diff - time, 1000 ); diff = qBound( 0, diff - time, 1000 );
if( diff > 0 ) if( diff > 0 )
wspace->addDamage( 0, 0, displayWidth(), displayHeight()); // affects next redraw wspace->addDamageFull(); // affects next redraw
} }
if( diff != 0 ) if( diff != 0 )
*mask |= Scene::PAINT_SCREEN_TRANSFORMED; *mask |= Scene::PAINT_SCREEN_TRANSFORMED;
@ -214,7 +214,7 @@ void ShiftWorkspaceUp::paintScreen( int mask, QRegion region, ScreenPaintData& d
void ShiftWorkspaceUp::tick() void ShiftWorkspaceUp::tick()
{ {
up = !up; up = !up;
wspace->addDamage( 0, 0, displayWidth(), displayHeight()); wspace->addDamageFull();
} }
@ -229,7 +229,7 @@ void FadeIn::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int t
*mask &= ~Scene::PAINT_WINDOW_OPAQUE; *mask &= ~Scene::PAINT_WINDOW_OPAQUE;
// TODO this should just damage the window, but right now window // TODO this should just damage the window, but right now window
// damage is cleared after the painting pass - a postpaint pass is needed // damage is cleared after the painting pass - a postpaint pass is needed
w->window()->workspace()->addDamage( 0, 0, displayWidth(), displayHeight()); w->window()->workspace()->addDamageFull();
} }
else else
windows.remove( w->window()); windows.remove( w->window());
@ -252,7 +252,7 @@ void FadeIn::windowAdded( Toplevel* c )
if( cc == NULL || cc->isOnCurrentDesktop()) if( cc == NULL || cc->isOnCurrentDesktop())
{ {
windows[ c ] = 0; windows[ c ] = 0;
c->addDamage( c->rect()); c->addDamageFull();
} }
} }
@ -272,7 +272,7 @@ void ScaleIn::prePaintWindow( Scene::Window* w, int* mask, QRegion* region, int
*mask |= Scene::PAINT_WINDOW_TRANSFORMED; *mask |= Scene::PAINT_WINDOW_TRANSFORMED;
// TODO this should just damage the window, but right now window // TODO this should just damage the window, but right now window
// damage is cleared after the painting pass - a postpaint pass is needed // damage is cleared after the painting pass - a postpaint pass is needed
w->window()->workspace()->addDamage( 0, 0, displayWidth(), displayHeight()); w->window()->workspace()->addDamageFull();
} }
else else
windows.remove( w->window()); windows.remove( w->window());
@ -298,7 +298,7 @@ void ScaleIn::windowAdded( Toplevel* c )
if( cc == NULL || cc->isOnCurrentDesktop()) if( cc == NULL || cc->isOnCurrentDesktop())
{ {
windows[ c ] = 0; windows[ c ] = 0;
c->addDamage( c->rect()); c->addDamageFull();
} }
} }

View file

@ -577,7 +577,7 @@ bool Client::windowEvent( XEvent* e )
{ {
if( compositing()) if( compositing())
{ {
addDamage( rect()); addDamageFull();
scene->windowOpacityChanged( this ); scene->windowOpacityChanged( this );
} }
else else
@ -1613,7 +1613,7 @@ bool Unmanaged::windowEvent( XEvent* e )
if( dirty[ NETWinInfo::PROTOCOLS2 ] & NET::WM2Opacity ) if( dirty[ NETWinInfo::PROTOCOLS2 ] & NET::WM2Opacity )
{ {
scene->windowOpacityChanged( this ); scene->windowOpacityChanged( this );
addDamage( rect()); addDamageFull();
} }
switch (e->type) switch (e->type)
{ {
@ -1657,7 +1657,7 @@ void Unmanaged::configureNotifyEvent( XConfigureEvent* e )
workspace()->addDamage( geometry()); workspace()->addDamage( geometry());
geom = QRect( e->x, e->y, e->width, e->height ); geom = QRect( e->x, e->y, e->width, e->height );
// TODO maybe only damage changed area // TODO maybe only damage changed area
addDamage( rect()); addDamageFull();
} }
// **************************************** // ****************************************

View file

@ -1686,7 +1686,7 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
sendSyntheticConfigureNotify(); sendSyntheticConfigureNotify();
updateWindowRules(); updateWindowRules();
checkMaximizeGeometry(); checkMaximizeGeometry();
addDamage( rect()); addDamageFull();
} }
void Client::plainResize( int w, int h, ForceGeometry_t force ) void Client::plainResize( int w, int h, ForceGeometry_t force )
@ -1743,7 +1743,7 @@ void Client::plainResize( int w, int h, ForceGeometry_t force )
updateWindowRules(); updateWindowRules();
checkMaximizeGeometry(); checkMaximizeGeometry();
// TODO add damage only in added area? // TODO add damage only in added area?
addDamage( rect()); addDamageFull();
} }
/*! /*!

View file

@ -63,6 +63,7 @@ class Toplevel
void finishCompositing(); void finishCompositing();
void addDamage( const QRect& r ); void addDamage( const QRect& r );
void addDamage( int x, int y, int w, int h ); void addDamage( int x, int y, int w, int h );
void addDamageFull();
QRegion damage() const; QRegion damage() const;
void resetDamage(); void resetDamage();
protected: protected:

View file

@ -286,6 +286,7 @@ class Workspace : public QObject, public KDecorationDefines
void addDamage( const QRect& r ); void addDamage( const QRect& r );
void addDamage( int x, int y, int w, int h ); void addDamage( int x, int y, int w, int h );
void addDamageFull();
public slots: public slots:
void refresh(); void refresh();