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
This commit is contained in:
Luboš Luňák 2007-02-27 16:13:34 +00:00
parent e81db7c1b5
commit e61ecff9b9
8 changed files with 39 additions and 17 deletions

View file

@ -459,7 +459,7 @@ void Client::updateShape()
XShapeCombineMask( display(), frameId(), ShapeBounding, 0, 0,
None, ShapeSet);
if( compositing())
discardWindowPixmap();
addDamageFull();
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
// workaround for #19644 - shaped windows shouldn't have decoration
@ -497,7 +497,7 @@ void Client::setMask( const QRegion& reg, int mode )
delete[] xrects;
}
if( compositing())
discardWindowPixmap();
addDamageFull();
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
}

View file

@ -39,6 +39,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include <stdio.h>
#include <QMenu>
#include <kxerrorhandler.h>
#include <X11/extensions/shape.h>
@ -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

View file

@ -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();
}
// ****************************************

View file

@ -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());
}

View file

@ -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

View file

@ -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();

View file

@ -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();

View file

@ -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 );