diff --git a/client.cpp b/client.cpp index b69485cf47..87d243cffc 100644 --- a/client.cpp +++ b/client.cpp @@ -458,8 +458,8 @@ void Client::updateShape() else XShapeCombineMask( display(), frameId(), ShapeBounding, 0, 0, None, ShapeSet); - if( compositing() ) - discardWindowPixmap(); + if( compositing()) + addDamageFull(); if( scene != NULL ) scene->windowGeometryShapeChanged( this ); // workaround for #19644 - shaped windows shouldn't have decoration @@ -496,8 +496,8 @@ void Client::setMask( const QRegion& reg, int mode ) xrects, rects.count(), ShapeSet, mode ); delete[] xrects; } - if( compositing() ) - discardWindowPixmap(); + if( compositing()) + addDamageFull(); if( scene != NULL ) scene->windowGeometryShapeChanged( this ); } diff --git a/composite.cpp b/composite.cpp index 2c9c5c2e0e..08c0217da0 100644 --- a/composite.cpp +++ b/composite.cpp @@ -39,6 +39,7 @@ License. See the file "COPYING" for the exact licensing terms. #include #include +#include #include @@ -367,11 +368,26 @@ void Toplevel::discardWindowPixmap() window_pix = None; } -Pixmap Toplevel::createWindowPixmap() const +Pixmap Toplevel::createWindowPixmap() { #ifdef HAVE_XCOMPOSITE assert( compositing()); - return XCompositeNameWindowPixmap( display(), frameId()); + grabXServer(); + KXErrorHandler err; + window_pix = XCompositeNameWindowPixmap( display(), frameId()); + // check that the received pixmap is valid and actually matches what we + // know about the window (i.e. size) + XWindowAttributes attrs; + if( !XGetWindowAttributes( display(), frameId(), &attrs )) + window_pix = None; + if( err.error( false )) + window_pix = None; + if( attrs.width != width() || attrs.height != height() || attrs.map_state != IsViewable ) + window_pix = None; + ungrabXServer(); + if( window_pix == None ) + kDebug( 1212 ) << "Creating window pixmap failed: " << this << endl; + return window_pix; #else return None; #endif diff --git a/events.cpp b/events.cpp index a503891c28..a9dffde648 100644 --- a/events.cpp +++ b/events.cpp @@ -1633,8 +1633,7 @@ bool Unmanaged::windowEvent( XEvent* e ) if( e->type == Extensions::shapeNotifyEvent() ) { detectShape( window()); - if( compositing() ) - discardWindowPixmap(); + addDamageFull(); if( scene != NULL ) scene->windowGeometryShapeChanged( this ); } @@ -1666,9 +1665,9 @@ void Unmanaged::configureNotifyEvent( XConfigureEvent* e ) return; workspace()->addRepaint( geometry()); // damage old area geom = newgeom; + discardWindowPixmap(); if( scene != NULL ) scene->windowGeometryShapeChanged( this ); - discardWindowPixmap(); } // **************************************** diff --git a/scene_basic.cpp b/scene_basic.cpp index 59c92c52b3..7a2726204d 100644 --- a/scene_basic.cpp +++ b/scene_basic.cpp @@ -48,6 +48,8 @@ void SceneBasic::paint( QRegion, ToplevelList windows ) if( !r.isEmpty()) { Pixmap pix = (*it)->windowPixmap(); + if( pix == None ) + continue; XCopyArea( display(), pix, composite_pixmap, gc, qMax( 0, -(*it)->x()), qMax( 0, -(*it)->y()), r.width(), r.height(), r.x(), r.y()); } diff --git a/scene_opengl.cpp b/scene_opengl.cpp index caceb6fb85..8e67134e28 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -851,14 +851,14 @@ void SceneOpenGL::Window::findTextureTarget() } // Bind the window pixmap to an OpenGL texture. -void SceneOpenGL::Window::bindTexture() +bool SceneOpenGL::Window::bindTexture() { if( texture != 0 && toplevel->damage().isEmpty() && !options->glAlwaysRebind ) // interestingly with some gfx cards always rebinding is faster { // texture doesn't need updating, just bind it glBindTexture( texture_target, texture ); - return; + return true; } if( !toplevel->damage().isEmpty()) texture_has_valid_mipmaps = false; @@ -868,11 +868,13 @@ void SceneOpenGL::Window::bindTexture() { kDebug( 1212 ) << "No framebuffer configuration for depth " << toplevel->depth() << "; not binding window" << endl; - return; + return false; } } // Get the pixmap with the window contents Pixmap pix = toplevel->windowPixmap(); + if( pix == None ) + return false; // HACK // When a window uses ARGB visual and has a decoration, the decoration // does use ARGB visual. When converting such window to a texture @@ -1029,9 +1031,9 @@ void SceneOpenGL::Window::bindTexture() // by GLXPixmap in the tfp case or not needed at all in non-tfp cases) if( copy_buffer ) XFreePixmap( display(), pix ); + return true; } - QRegion SceneOpenGL::Window::optimizeBindDamage( const QRegion& reg, int limit ) { if( reg.rects().count() <= 1 ) @@ -1141,7 +1143,8 @@ void SceneOpenGL::Window::performPaint( int mask, QRegion region, WindowPaintDat region &= shape(); if( region.isEmpty()) return; - bindTexture(); + if( !bindTexture()) + return; glPushMatrix(); // set texture filter if( options->smoothScale != 0 ) // default to yes diff --git a/scene_opengl.h b/scene_opengl.h index 458e4a427c..7b67d94098 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -94,7 +94,7 @@ class SceneOpenGL::Window virtual void performPaint( int mask, QRegion region, WindowPaintData data ); virtual void prepareForPainting(); void findTextureTarget(); - void bindTexture(); + bool bindTexture(); void enableTexture(); void disableTexture(); void discardTexture(); diff --git a/scene_xrender.cpp b/scene_xrender.cpp index 7ec6d42942..83f1404d33 100644 --- a/scene_xrender.cpp +++ b/scene_xrender.cpp @@ -325,6 +325,8 @@ Picture SceneXrender::Window::picture() { // Get the pixmap with the window contents. Pixmap pix = toplevel->windowPixmap(); + if( pix == None ) + return None; // HACK the same alpha clear hack like with opengl, see there Client* c = dynamic_cast< Client* >( toplevel ); bool alpha_clear = c != NULL && c->hasAlpha() && !c->noBorder(); diff --git a/toplevel.h b/toplevel.h index 04240ca4cd..b01276f5f9 100644 --- a/toplevel.h +++ b/toplevel.h @@ -78,7 +78,7 @@ class Toplevel pid_t pid() const; static bool resourceMatch( const Toplevel* c1, const Toplevel* c2 ); - Pixmap windowPixmap( bool allow_create = true ); // for use with compositing + Pixmap windowPixmap( bool allow_create = true ); // may return None (e.g. at a bad moment while resizing) Visual* visual() const; bool shape() const; void setOpacity( double opacity ); @@ -102,7 +102,7 @@ class Toplevel void detectShape( Window id ); virtual void propertyNotifyEvent( XPropertyEvent* e ); void damageNotifyEvent( XDamageNotifyEvent* e ); - Pixmap createWindowPixmap() const; + Pixmap createWindowPixmap(); void discardWindowPixmap(); void addDamage( const QRect& r ); void addDamage( int x, int y, int w, int h );