From e61ecff9b91af5031c94b8595abceb34fcfd0edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Tue, 27 Feb 2007 16:13:34 +0000 Subject: [PATCH] Check that getting compositing pixmap of a window succeeded. It may fail (or "fail") if the window is not mapped or if the geometry doesn't match, both of which may happen due to the asynchronous nature of X. svn path=/branches/work/kwin_composite/; revision=637741 --- client.cpp | 8 ++++---- composite.cpp | 20 ++++++++++++++++++-- events.cpp | 5 ++--- scene_basic.cpp | 2 ++ scene_opengl.cpp | 13 ++++++++----- scene_opengl.h | 2 +- scene_xrender.cpp | 2 ++ toplevel.h | 4 ++-- 8 files changed, 39 insertions(+), 17 deletions(-) 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 );