Try to handle gracefully the case when there are many small changes
on the screen and the X server has absolutely no problem with flooding KWin with a huge number of damage events, overloading both the X connection and QRegion. BUG: 163643 svn path=/branches/KDE/4.1/kdebase/workspace/; revision=836665
This commit is contained in:
parent
8c6d1745e9
commit
f1063279cc
1 changed files with 28 additions and 2 deletions
|
@ -500,8 +500,9 @@ Pixmap Toplevel::createWindowPixmap()
|
||||||
#ifdef HAVE_XDAMAGE
|
#ifdef HAVE_XDAMAGE
|
||||||
void Toplevel::damageNotifyEvent( XDamageNotifyEvent* e )
|
void Toplevel::damageNotifyEvent( XDamageNotifyEvent* e )
|
||||||
{
|
{
|
||||||
addDamage( e->area.x, e->area.y, e->area.width, e->area.height );
|
QRegion damage( e->area.x, e->area.y, e->area.width, e->area.height );
|
||||||
// compress
|
// compress
|
||||||
|
int cnt = 1;
|
||||||
while( XPending( display()))
|
while( XPending( display()))
|
||||||
{
|
{
|
||||||
XEvent e2;
|
XEvent e2;
|
||||||
|
@ -509,12 +510,37 @@ void Toplevel::damageNotifyEvent( XDamageNotifyEvent* e )
|
||||||
&& e2.xany.window == frameId())
|
&& e2.xany.window == frameId())
|
||||||
{
|
{
|
||||||
XNextEvent( display(), &e2 );
|
XNextEvent( display(), &e2 );
|
||||||
|
if( cnt > 200 )
|
||||||
|
{
|
||||||
|
// If there are way too many damage events in the queue, just discard them
|
||||||
|
// and damage the whole window. Otherwise the X server can just overload
|
||||||
|
// us with a flood of damage events. Should be probably optimized
|
||||||
|
// in the X server, as this is rather lame.
|
||||||
|
damage = rect();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
XDamageNotifyEvent* e = reinterpret_cast< XDamageNotifyEvent* >( &e2 );
|
XDamageNotifyEvent* e = reinterpret_cast< XDamageNotifyEvent* >( &e2 );
|
||||||
addDamage( e->area.x, e->area.y, e->area.width, e->area.height );
|
QRect r( e->area.x, e->area.y, e->area.width, e->area.height );
|
||||||
|
++cnt;
|
||||||
|
// If there are too many damaged rectangles, increase them
|
||||||
|
// to be multiples of 100x100 px grid, since QRegion get quite
|
||||||
|
// slow with many rectangles, and there is little to gain by using
|
||||||
|
// many small rectangles (rather the opposite, several large should
|
||||||
|
// be often faster).
|
||||||
|
if( cnt > 50 )
|
||||||
|
{
|
||||||
|
r.setLeft( r.left() / 100 * 100 );
|
||||||
|
r.setRight(( r.right() + 99 ) / 100 * 100 );
|
||||||
|
r.setTop( r.top() / 100 * 100 );
|
||||||
|
r.setBottom(( r.bottom() + 99 ) / 100 * 100 );
|
||||||
|
}
|
||||||
|
damage += r;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
foreach( QRect r, damage.rects())
|
||||||
|
addDamage( r );
|
||||||
}
|
}
|
||||||
|
|
||||||
void Client::damageNotifyEvent( XDamageNotifyEvent* e )
|
void Client::damageNotifyEvent( XDamageNotifyEvent* e )
|
||||||
|
|
Loading…
Reference in a new issue