Backport: Extracted mouse polling out of the composite timer to allow

effects to detect mouse movement and modifier key changes even when KWin
is idle. As the track mouse effect requires polling to always be active
disabling it by default to prevent wasting CPU usage in the default
install.

Although this is a feature it is required to remove a major performance
issue in 4.2 that was caused by a last-minute hack before tagging.

svn path=/branches/KDE/4.2/kdebase/workspace/; revision=920966
This commit is contained in:
Lucas Murray 2009-02-04 07:16:24 +00:00
parent f0c91c7dea
commit 9bb76644b7
17 changed files with 96 additions and 6 deletions

View file

@ -247,6 +247,7 @@ void Workspace::finishCompositing()
delete scene;
scene = NULL;
compositeTimer.stop();
mousePollingTimer.stop();
repaints_region = QRegion();
for( ClientList::ConstIterator it = clients.constBegin();
it != clients.constEnd();
@ -336,11 +337,8 @@ void Workspace::performCompositing()
}
if( !scene->waitSyncAvailable())
nextPaintReference = QTime::currentTime();
checkCursorPos();
if((( repaints_region.isEmpty() && !windowRepaintsPending()) // no damage
|| !overlay_visible ) // nothing is visible anyway
// HACK: don't idle during active full screen effect so that mouse events are not dropped (bug #177226)
&& !static_cast< EffectsHandlerImpl* >( effects )->activeFullScreenEffect() )
|| !overlay_visible )) // nothing is visible anyway
{
scene->idle();
// Note: It would seem here we should undo suspended unredirect, but when scenes need
@ -404,6 +402,11 @@ void Workspace::performCompositing()
#endif
}
void Workspace::performMousePoll()
{
checkCursorPos();
}
bool Workspace::windowRepaintsPending() const
{
foreach( Toplevel* c, clients )
@ -430,6 +433,16 @@ void Workspace::setCompositeTimer()
compositeTimer.start( qBound( 0, nextPaintReference.msecsTo( QTime::currentTime() ), 250 ) % compositeRate );
}
void Workspace::startMousePolling()
{
mousePollingTimer.start( 20 ); // 50Hz. TODO: How often do we really need to poll?
}
void Workspace::stopMousePolling()
{
mousePollingTimer.stop();
}
bool Workspace::createOverlay()
{
assert( overlay == None );

View file

@ -52,6 +52,7 @@ EffectsHandlerImpl::EffectsHandlerImpl(CompositingType type)
, keyboard_grab_effect( NULL )
, fullscreen_effect( 0 )
, next_window_quad_type( EFFECT_QUAD_TYPE_START )
, mouse_poll_ref_count( 0 )
{
reconfigure();
}
@ -354,6 +355,21 @@ void EffectsHandlerImpl::grabbedKeyboardEvent( QKeyEvent* e )
keyboard_grab_effect->grabbedKeyboardEvent( e );
}
void EffectsHandlerImpl::startMousePolling()
{
if( !mouse_poll_ref_count ) // Start timer if required
Workspace::self()->startMousePolling();
mouse_poll_ref_count++;
}
void EffectsHandlerImpl::stopMousePolling()
{
assert( mouse_poll_ref_count );
mouse_poll_ref_count--;
if( !mouse_poll_ref_count ) // Stop timer if required
Workspace::self()->stopMousePolling();
}
bool EffectsHandlerImpl::hasKeyboardGrab() const
{
return keyboard_grab_effect != NULL;

View file

@ -65,6 +65,8 @@ class EffectsHandlerImpl : public EffectsHandler
virtual QPoint cursorPos() const;
virtual bool grabKeyboard( Effect* effect );
virtual void ungrabKeyboard();
virtual void startMousePolling();
virtual void stopMousePolling();
virtual EffectWindow* findWindow( WId id ) const;
virtual EffectWindowList stackingOrder() const;
virtual void setElevatedWindow( EffectWindow* w, bool set );
@ -168,6 +170,7 @@ class EffectsHandlerImpl : public EffectsHandler
QMultiMap< int, EffectPair > effect_order;
QHash< long, int > registered_atoms;
int next_window_quad_type;
int mouse_poll_ref_count;
};
class EffectWindowImpl : public EffectWindow

View file

@ -1537,6 +1537,7 @@ void CubeEffect::setActive( bool active )
{
if( active )
{
effects->startMousePolling();
activated = true;
activeScreen = effects->activeScreen();
if( !slide )
@ -1574,6 +1575,7 @@ void CubeEffect::setActive( bool active )
}
else
{
effects->stopMousePolling();
schedule_close = true;
// we have to add a repaint, to start the deactivating
effects->addRepaintFull();

View file

@ -42,6 +42,7 @@ LookingGlassEffect::LookingGlassEffect() : QObject(), ShaderEffect("lookingglass
{
zoom = 1.0f;
target_zoom = 1.0f;
polling = false;
actionCollection = new KActionCollection( this );
actionCollection->setConfigGlobal(true);
@ -83,6 +84,11 @@ void LookingGlassEffect::zoomIn()
{
target_zoom = qMin(7.0, target_zoom + 0.5);
setEnabled( true );
if( !polling )
{
polling = true;
effects->startMousePolling();
}
effects->addRepaint( cursorPos().x() - radius, cursorPos().y() - radius, 2*radius, 2*radius );
}
@ -94,6 +100,11 @@ void LookingGlassEffect::zoomOut()
target_zoom = 1;
setEnabled( false );
}
if( polling )
{
polling = false;
effects->stopMousePolling();
}
effects->addRepaint( cursorPos().x() - radius, cursorPos().y() - radius, 2*radius, 2*radius );
}

View file

@ -54,6 +54,7 @@ class LookingGlassEffect : public QObject, public ShaderEffect
private:
double zoom;
double target_zoom;
bool polling; // Mouse polling
int radius;
int initialradius;
KActionCollection* actionCollection;

View file

@ -42,6 +42,7 @@ const int FRAME_WIDTH = 5;
MagnifierEffect::MagnifierEffect()
: zoom( 1 )
, target_zoom( 1 )
, polling( false )
{
KActionCollection* actionCollection = new KActionCollection( this );
KAction* a;
@ -144,6 +145,11 @@ QRect MagnifierEffect::magnifierArea( QPoint pos ) const
void MagnifierEffect::zoomIn()
{
target_zoom *= 1.2;
if( !polling )
{
polling = true;
effects->startMousePolling();
}
effects->addRepaint( magnifierArea().adjusted( -FRAME_WIDTH, -FRAME_WIDTH, FRAME_WIDTH, FRAME_WIDTH ));
}
@ -152,6 +158,11 @@ void MagnifierEffect::zoomOut()
target_zoom /= 1.2;
if( target_zoom < 1 )
target_zoom = 1;
if( polling )
{
polling = false;
effects->stopMousePolling();
}
effects->addRepaint( magnifierArea().adjusted( -FRAME_WIDTH, -FRAME_WIDTH, FRAME_WIDTH, FRAME_WIDTH ));
}

View file

@ -47,6 +47,7 @@ class MagnifierEffect
QRect magnifierArea( QPoint pos = cursorPos()) const;
double zoom;
double target_zoom;
bool polling; // Mouse polling
QSize magnifier_size;
};

View file

@ -58,6 +58,12 @@ MouseMarkEffect::MouseMarkEffect()
connect( a, SIGNAL( triggered( bool )), this, SLOT( clearLast()));
reconfigure( ReconfigureAll );
arrow_start = NULL_POINT;
effects->startMousePolling(); // We require it to detect activation as well
}
MouseMarkEffect::~MouseMarkEffect()
{
effects->stopMousePolling();
}
void MouseMarkEffect::reconfigure( ReconfigureFlags )

View file

@ -33,6 +33,7 @@ class MouseMarkEffect
Q_OBJECT
public:
MouseMarkEffect();
~MouseMarkEffect();
virtual void reconfigure( ReconfigureFlags );
virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data );
virtual void mouseChanged( const QPoint& pos, const QPoint& old,

View file

@ -48,10 +48,12 @@ TrackMouseEffect::TrackMouseEffect()
, angle( 0 )
, texture( NULL )
{
effects->startMousePolling(); // We require it to detect activation as well
}
TrackMouseEffect::~TrackMouseEffect()
{
effects->stopMousePolling();
delete texture;
}

View file

@ -120,5 +120,5 @@ X-KDE-PluginInfo-Version=0.1.0
X-KDE-PluginInfo-Category=Accessibility
X-KDE-PluginInfo-Depends=
X-KDE-PluginInfo-License=GPL
X-KDE-PluginInfo-EnabledByDefault=true
X-KDE-PluginInfo-EnabledByDefault=false
X-KDE-Library=kwin4_effect_builtins

View file

@ -32,6 +32,7 @@ KWIN_EFFECT( zoom, ZoomEffect )
ZoomEffect::ZoomEffect()
: zoom( 1 )
, target_zoom( 1 )
, polling( false )
{
KActionCollection* actionCollection = new KActionCollection( this );
KAction* a;
@ -82,6 +83,11 @@ void ZoomEffect::postPaintScreen()
void ZoomEffect::zoomIn()
{
target_zoom *= 1.2;
if( !polling )
{
polling = true;
effects->startMousePolling();
}
effects->addRepaintFull();
}
@ -90,6 +96,11 @@ void ZoomEffect::zoomOut()
target_zoom /= 1.2;
if( target_zoom < 1 )
target_zoom = 1;
if( polling )
{
polling = false;
effects->stopMousePolling();
}
effects->addRepaintFull();
}

View file

@ -45,6 +45,7 @@ class ZoomEffect
private:
double zoom;
double target_zoom;
bool polling; // Mouse polling
};
} // namespace

View file

@ -164,7 +164,7 @@ X-KDE-Library=kwin4_effect_cooleffect
#define KWIN_EFFECT_API_MAKE_VERSION( major, minor ) (( major ) << 8 | ( minor ))
#define KWIN_EFFECT_API_VERSION_MAJOR 0
#define KWIN_EFFECT_API_VERSION_MINOR 57
#define KWIN_EFFECT_API_VERSION_MINOR 58
#define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \
KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR )
@ -508,6 +508,10 @@ class KWIN_EXPORT EffectsHandler
virtual bool grabKeyboard( Effect* effect ) = 0;
virtual void ungrabKeyboard() = 0;
// Mouse polling
virtual void startMousePolling() = 0;
virtual void stopMousePolling() = 0;
virtual void checkElectricBorder(const QPoint &pos, Time time) = 0;
virtual void reserveElectricBorder( ElectricBorder border ) = 0;
virtual void unreserveElectricBorder( ElectricBorder border ) = 0;

View file

@ -354,6 +354,7 @@ void Workspace::init()
connect( &reconfigureTimer, SIGNAL( timeout() ), this, SLOT( slotReconfigure() ));
connect( &updateToolWindowsTimer, SIGNAL( timeout() ), this, SLOT( slotUpdateToolWindows() ));
connect( &compositeTimer, SIGNAL( timeout() ), SLOT( performCompositing() ));
connect( &mousePollingTimer, SIGNAL( timeout() ), SLOT( performMousePoll() ));
connect( KGlobalSettings::self(), SIGNAL( appearanceChanged() ), this, SLOT( reconfigure() ));
connect( KGlobalSettings::self(), SIGNAL( settingsChanged(int) ), this, SLOT( slotSettingsChanged(int) ));

View file

@ -357,6 +357,10 @@ class Workspace : public QObject, public KDecorationDefines
void checkUnredirect( bool force = false );
void checkCompositeTimer();
// Mouse polling
void startMousePolling();
void stopMousePolling();
public slots:
void addRepaintFull();
void refresh();
@ -517,6 +521,7 @@ class Workspace : public QObject, public KDecorationDefines
void setPopupClientOpacity( QAction* action );
void setupCompositing();
void performCompositing();
void performMousePoll();
void lostCMSelection();
void updateElectricBorders();
void resetCursorPosTime();
@ -765,6 +770,7 @@ class Workspace : public QObject, public KDecorationDefines
QTimer compositeTimer;
QTime lastCompositePaint;
QTime nextPaintReference;
QTimer mousePollingTimer;
int compositeRate;
QRegion repaints_region;
Window overlay; // XComposite overlay window