From 752d5fa642295038155ffdf19e09b2bead520906 Mon Sep 17 00:00:00 2001 From: Lucas Murray Date: Sun, 1 Feb 2009 15:16:52 +0000 Subject: [PATCH] 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. svn path=/trunk/KDE/kdebase/workspace/; revision=919711 --- composite.cpp | 20 ++++++++++++++++---- effects.cpp | 16 ++++++++++++++++ effects.h | 3 +++ effects/cube.cpp | 2 ++ effects/lookingglass.cpp | 11 +++++++++++ effects/lookingglass.h | 1 + effects/magnifier.cpp | 11 +++++++++++ effects/magnifier.h | 1 + effects/mousemark.cpp | 6 ++++++ effects/mousemark.h | 1 + effects/trackmouse.cpp | 2 ++ effects/trackmouse.desktop | 2 +- effects/zoom.cpp | 11 +++++++++++ effects/zoom.h | 1 + lib/kwineffects.h | 4 ++++ workspace.cpp | 1 + workspace.h | 6 ++++++ 17 files changed, 94 insertions(+), 5 deletions(-) diff --git a/composite.cpp b/composite.cpp index 3579c42ff4..6922c2faa0 100644 --- a/composite.cpp +++ b/composite.cpp @@ -336,11 +336,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 +401,11 @@ void Workspace::performCompositing() #endif } +void Workspace::performMousePoll() + { + checkCursorPos(); + } + bool Workspace::windowRepaintsPending() const { foreach( Toplevel* c, clients ) @@ -430,6 +432,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 ); diff --git a/effects.cpp b/effects.cpp index d45bf41333..e0ebb6a755 100644 --- a/effects.cpp +++ b/effects.cpp @@ -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; diff --git a/effects.h b/effects.h index 8eaeb4fb7c..4bd7412976 100644 --- a/effects.h +++ b/effects.h @@ -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 diff --git a/effects/cube.cpp b/effects/cube.cpp index 9298570e54..894bb14fa5 100644 --- a/effects/cube.cpp +++ b/effects/cube.cpp @@ -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(); diff --git a/effects/lookingglass.cpp b/effects/lookingglass.cpp index a594dc3f52..c362f4e336 100644 --- a/effects/lookingglass.cpp +++ b/effects/lookingglass.cpp @@ -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 ); } diff --git a/effects/lookingglass.h b/effects/lookingglass.h index 367d59fbdc..96b4422002 100644 --- a/effects/lookingglass.h +++ b/effects/lookingglass.h @@ -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; diff --git a/effects/magnifier.cpp b/effects/magnifier.cpp index 0bc65c6694..c64737b789 100644 --- a/effects/magnifier.cpp +++ b/effects/magnifier.cpp @@ -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 )); } diff --git a/effects/magnifier.h b/effects/magnifier.h index 45d467a022..7ed5018846 100644 --- a/effects/magnifier.h +++ b/effects/magnifier.h @@ -47,6 +47,7 @@ class MagnifierEffect QRect magnifierArea( QPoint pos = cursorPos()) const; double zoom; double target_zoom; + bool polling; // Mouse polling QSize magnifier_size; }; diff --git a/effects/mousemark.cpp b/effects/mousemark.cpp index 93ba41cb06..8f5e3fcf33 100644 --- a/effects/mousemark.cpp +++ b/effects/mousemark.cpp @@ -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 ) diff --git a/effects/mousemark.h b/effects/mousemark.h index 217aa61262..11edfb7f4d 100644 --- a/effects/mousemark.h +++ b/effects/mousemark.h @@ -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, diff --git a/effects/trackmouse.cpp b/effects/trackmouse.cpp index 1d3573d05b..91a8481821 100644 --- a/effects/trackmouse.cpp +++ b/effects/trackmouse.cpp @@ -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; } diff --git a/effects/trackmouse.desktop b/effects/trackmouse.desktop index 51ad6164ff..621277d1f5 100644 --- a/effects/trackmouse.desktop +++ b/effects/trackmouse.desktop @@ -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 diff --git a/effects/zoom.cpp b/effects/zoom.cpp index 27c64b1103..8a57e35946 100644 --- a/effects/zoom.cpp +++ b/effects/zoom.cpp @@ -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(); } diff --git a/effects/zoom.h b/effects/zoom.h index d805ce2ea2..44037ccbbf 100644 --- a/effects/zoom.h +++ b/effects/zoom.h @@ -45,6 +45,7 @@ class ZoomEffect private: double zoom; double target_zoom; + bool polling; // Mouse polling }; } // namespace diff --git a/lib/kwineffects.h b/lib/kwineffects.h index dbd10f8b6e..94a7088a7c 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -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; diff --git a/workspace.cpp b/workspace.cpp index c46c6272ba..e5a9e0142e 100644 --- a/workspace.cpp +++ b/workspace.cpp @@ -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) )); diff --git a/workspace.h b/workspace.h index 1157689d80..b3835c9d6c 100644 --- a/workspace.h +++ b/workspace.h @@ -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