Fix compositing repaint bug where moving a window would not draw properly (especially noticeable when snapping to a border).

svn path=/branches/work/kwin_composite/; revision=632339
icc-effect-5.14.5
Philip Falkner 2007-02-10 18:28:04 +00:00
parent 6c224134db
commit ca856c28e1
1 changed files with 67 additions and 32 deletions

View File

@ -28,6 +28,7 @@ License. See the file "COPYING" for the exact licensing terms.
#include "notifications.h" #include "notifications.h"
#include "geometrytip.h" #include "geometrytip.h"
#include "rules.h" #include "rules.h"
#include "effects.h"
#include <QX11Info> #include <QX11Info>
#include <QDesktopWidget> #include <QDesktopWidget>
@ -48,8 +49,14 @@ void Workspace::desktopResized()
desktop_geometry.width = geom.width(); desktop_geometry.width = geom.width();
desktop_geometry.height = geom.height(); desktop_geometry.height = geom.height();
rootInfo->setDesktopGeometry( -1, desktop_geometry ); rootInfo->setDesktopGeometry( -1, desktop_geometry );
updateClientArea(); updateClientArea();
checkElectricBorders( true ); checkElectricBorders( true );
if( compositing() )
{
finishCompositing();
QTimer::singleShot( 0, this, SLOT( setupCompositing() ) );
}
} }
/*! /*!
@ -215,7 +222,7 @@ QRect Workspace::clientArea( clientAreaOption opt, const QPoint& p, int desktop
if( desktop == NETWinInfo::OnAllDesktops || desktop == 0 ) if( desktop == NETWinInfo::OnAllDesktops || desktop == 0 )
desktop = currentDesktop(); desktop = currentDesktop();
QDesktopWidget *desktopwidget = KApplication::desktop(); QDesktopWidget *desktopwidget = KApplication::desktop();
int screen = desktopwidget->isVirtualDesktop() ? desktopwidget->screenNumber( p ) : desktopwidget->primaryScreen(); int screen = desktopwidget->screenNumber( p );
if( screen < 0 ) if( screen < 0 )
screen = desktopwidget->primaryScreen(); screen = desktopwidget->primaryScreen();
QRect sarea = screenarea // may be NULL during KWin initialization QRect sarea = screenarea // may be NULL during KWin initialization
@ -1409,7 +1416,7 @@ void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, i
|| ns != size()) || ns != size())
{ {
QRect orig_geometry = geometry(); QRect orig_geometry = geometry();
GeometryUpdatesPostponer blocker( this ); GeometryUpdatesBlocker blocker( this );
move( new_pos ); move( new_pos );
plainResize( ns ); plainResize( ns );
setGeometry( QRect( calculateGravitation( false, gravity ), size())); setGeometry( QRect( calculateGravitation( false, gravity ), size()));
@ -1442,7 +1449,7 @@ void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, i
if( ns != size()) // don't restore if some app sets its own size again if( ns != size()) // don't restore if some app sets its own size again
{ {
QRect orig_geometry = geometry(); QRect orig_geometry = geometry();
GeometryUpdatesPostponer blocker( this ); GeometryUpdatesBlocker blocker( this );
int save_gravity = xSizeHint.win_gravity; int save_gravity = xSizeHint.win_gravity;
xSizeHint.win_gravity = gravity; xSizeHint.win_gravity = gravity;
resizeWithChecks( ns ); resizeWithChecks( ns );
@ -1662,31 +1669,46 @@ void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
{ {
client_size = QSize( w - border_left - border_right, h - border_top - border_bottom ); client_size = QSize( w - border_left - border_right, h - border_top - border_bottom );
} }
if( force == NormalGeometrySet && frame_geometry == QRect( x, y, w, h )) if( force == NormalGeometrySet && geom == QRect( x, y, w, h ))
return; return;
frame_geometry = QRect( x, y, w, h ); geom = QRect( x, y, w, h );
updateWorkareaDiffs(); updateWorkareaDiffs();
if( postpone_geometry_updates != 0 ) if( block_geometry_updates != 0 )
{ {
pending_geometry_update = true; pending_geometry_update = true;
return; return;
} }
resizeDecoration( QSize( w, h )); if( geom_before_block.size() != geom.size())
XMoveResizeWindow( display(), frameId(), x, y, w, h );
// resizeDecoration( QSize( w, h ));
if( !isShade())
{ {
QSize cs = clientSize(); resizeDecoration( QSize( w, h ));
XMoveResizeWindow( display(), wrapperId(), clientPos().x(), clientPos().y(), XMoveResizeWindow( display(), frameId(), x, y, w, h );
cs.width(), cs.height()); if( !isShade())
XMoveResizeWindow( display(), window(), 0, 0, cs.width(), cs.height()); {
QSize cs = clientSize();
XMoveResizeWindow( display(), wrapperId(), clientPos().x(), clientPos().y(),
cs.width(), cs.height());
XMoveResizeWindow( display(), window(), 0, 0, cs.width(), cs.height());
}
if( shape())
updateShape();
} }
updateShape(); else
XMoveWindow( display(), frameId(), x, y );
// SELI TODO won't this be too expensive? // SELI TODO won't this be too expensive?
updateWorkareaDiffs(); updateWorkareaDiffs();
sendSyntheticConfigureNotify(); sendSyntheticConfigureNotify();
updateWindowRules(); updateWindowRules();
checkMaximizeGeometry(); checkMaximizeGeometry();
if( geom_before_block.size() != geom.size())
{
addDamageFull(); // damage window only if it actually was a resize
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
}
else
workspace()->addDamage( geom ); // damage window's new location
workspace()->addDamage( geom_before_block ); // TODO add damage only if not obscured
geom_before_block = geom;
} }
void Client::plainResize( int w, int h, ForceGeometry_t force ) void Client::plainResize( int w, int h, ForceGeometry_t force )
@ -1716,11 +1738,11 @@ void Client::plainResize( int w, int h, ForceGeometry_t force )
kDebug() << "forced size fail:" << QSize( w,h ) << ":" << rules()->checkSize( QSize( w, h )) << endl; kDebug() << "forced size fail:" << QSize( w,h ) << ":" << rules()->checkSize( QSize( w, h )) << endl;
kDebug() << kBacktrace() << endl; kDebug() << kBacktrace() << endl;
} }
if( force == NormalGeometrySet && frame_geometry.size() == QSize( w, h )) if( force == NormalGeometrySet && geom.size() == QSize( w, h ))
return; return;
frame_geometry.setSize( QSize( w, h )); geom.setSize( QSize( w, h ));
updateWorkareaDiffs(); updateWorkareaDiffs();
if( postpone_geometry_updates != 0 ) if( block_geometry_updates != 0 )
{ {
pending_geometry_update = true; pending_geometry_update = true;
return; return;
@ -1735,11 +1757,17 @@ void Client::plainResize( int w, int h, ForceGeometry_t force )
cs.width(), cs.height()); cs.width(), cs.height());
XMoveResizeWindow( display(), window(), 0, 0, cs.width(), cs.height()); XMoveResizeWindow( display(), window(), 0, 0, cs.width(), cs.height());
} }
updateShape(); if( shape())
updateShape();
updateWorkareaDiffs(); updateWorkareaDiffs();
sendSyntheticConfigureNotify(); sendSyntheticConfigureNotify();
updateWindowRules(); updateWindowRules();
checkMaximizeGeometry(); checkMaximizeGeometry();
addDamageFull(); // TODO add damage only in added area?
if( scene != NULL )
scene->windowGeometryShapeChanged( this );
workspace()->addDamage( geom_before_block ); // TODO add damage only if not obscured
geom_before_block = geom;
} }
/*! /*!
@ -1747,11 +1775,11 @@ void Client::plainResize( int w, int h, ForceGeometry_t force )
*/ */
void Client::move( int x, int y, ForceGeometry_t force ) void Client::move( int x, int y, ForceGeometry_t force )
{ {
if( force == NormalGeometrySet && frame_geometry.topLeft() == QPoint( x, y )) if( force == NormalGeometrySet && geom.topLeft() == QPoint( x, y ))
return; return;
frame_geometry.moveTopLeft( QPoint( x, y )); geom.moveTopLeft( QPoint( x, y ));
updateWorkareaDiffs(); updateWorkareaDiffs();
if( postpone_geometry_updates != 0 ) if( block_geometry_updates != 0 )
{ {
pending_geometry_update = true; pending_geometry_update = true;
return; return;
@ -1760,20 +1788,22 @@ void Client::move( int x, int y, ForceGeometry_t force )
sendSyntheticConfigureNotify(); sendSyntheticConfigureNotify();
updateWindowRules(); updateWindowRules();
checkMaximizeGeometry(); checkMaximizeGeometry();
// client itself is not damaged
workspace()->addDamage( geom_before_block ); // TODO add damage only if not obscured
geom_before_block = geom;
} }
void Client::blockGeometryUpdates( bool block )
void Client::postponeGeometryUpdates( bool postpone )
{ {
if( postpone ) if( block )
{ {
if( postpone_geometry_updates == 0 ) if( block_geometry_updates == 0 )
pending_geometry_update = false; pending_geometry_update = false;
++postpone_geometry_updates; ++block_geometry_updates;
} }
else else
{ {
if( --postpone_geometry_updates == 0 ) if( --block_geometry_updates == 0 )
{ {
if( pending_geometry_update ) if( pending_geometry_update )
{ {
@ -1822,7 +1852,7 @@ void Client::changeMaximize( bool vertical, bool horizontal, bool adjust )
if( !adjust && max_mode == old_mode ) if( !adjust && max_mode == old_mode )
return; return;
GeometryUpdatesPostponer blocker( this ); GeometryUpdatesBlocker blocker( this );
// maximing one way and unmaximizing the other way shouldn't happen // maximing one way and unmaximizing the other way shouldn't happen
Q_ASSERT( !( vertical && horizontal ) Q_ASSERT( !( vertical && horizontal )
@ -2074,7 +2104,7 @@ void Client::setFullScreen( bool set, bool user )
if( was_fs == isFullScreen()) if( was_fs == isFullScreen())
return; return;
StackingUpdatesBlocker blocker1( workspace()); StackingUpdatesBlocker blocker1( workspace());
GeometryUpdatesPostponer blocker2( this ); GeometryUpdatesBlocker blocker2( this );
workspace()->updateClientLayer( this ); // active fullscreens get different layer workspace()->updateClientLayer( this ); // active fullscreens get different layer
info->setState( isFullScreen() ? NET::FullScreen : 0, NET::FullScreen ); info->setState( isFullScreen() ? NET::FullScreen : 0, NET::FullScreen );
updateDecoration( false, false ); updateDecoration( false, false );
@ -2230,7 +2260,7 @@ bool Client::startMoveResize()
XMapRaised( display(), move_resize_grab_window ); XMapRaised( display(), move_resize_grab_window );
if( XGrabPointer( display(), move_resize_grab_window, False, if( XGrabPointer( display(), move_resize_grab_window, False,
ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask, ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask,
GrabModeAsync, GrabModeAsync, move_resize_grab_window, cursor.handle(), xTime() ) == Success ) GrabModeAsync, GrabModeAsync, None, cursor.handle(), xTime() ) == Success )
has_grab = true; has_grab = true;
if( XGrabKeyboard( display(), frameId(), False, GrabModeAsync, GrabModeAsync, xTime() ) == Success ) if( XGrabKeyboard( display(), frameId(), False, GrabModeAsync, GrabModeAsync, xTime() ) == Success )
has_grab = true; has_grab = true;
@ -2260,6 +2290,8 @@ bool Client::startMoveResize()
// not needed anymore? kapp->installEventFilter( eater ); // not needed anymore? kapp->installEventFilter( eater );
} }
Notify::raise( isResize() ? Notify::ResizeStart : Notify::MoveStart ); Notify::raise( isResize() ? Notify::ResizeStart : Notify::MoveStart );
if( effects )
effects->windowUserMovedResized( effectWindow(), true, false );
return true; return true;
} }
@ -2273,6 +2305,8 @@ void Client::finishMoveResize( bool cancel )
checkMaximizeGeometry(); checkMaximizeGeometry();
// FRAME update(); // FRAME update();
Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd ); Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd );
if( effects )
effects->windowUserMovedResized( effectWindow(), false, true );
} }
void Client::leaveMoveResize() void Client::leaveMoveResize()
@ -2536,7 +2570,8 @@ void Client::handleMoveResize( int x, int y, int x_root, int y_root )
} }
if ( isMove() ) if ( isMove() )
workspace()->clientMoved(globalPos, xTime()); workspace()->clientMoved(globalPos, xTime());
if( effects )
effects->windowUserMovedResized( effectWindow(), false, false );
} }
} // namespace } // namespace