From a26c5b12251d15ef44c5c30d6a178e432587cc94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sun, 28 Jun 2009 17:17:29 +0000 Subject: [PATCH] Configurable mouse actions in present windows for clicking a window and desktop. It's possible to activate a window, exit without activating, bring window to current desktop, send window on all desktops, mimize the window and close the window. Clicking desktop allows to activate selected window, exit without activating, show the desktop (minimize all apps) and of course do nothing. FEATURE: 163116 svn path=/trunk/KDE/kdebase/workspace/; revision=988788 --- effects.cpp | 30 ++ effects.h | 5 + effects/presentwindows/presentwindows.cpp | 114 ++++- effects/presentwindows/presentwindows.h | 29 ++ .../presentwindows/presentwindows_config.cpp | 40 ++ .../presentwindows/presentwindows_config.ui | 439 ++++++++++++++---- lib/kwineffects.h | 7 +- 7 files changed, 566 insertions(+), 98 deletions(-) diff --git a/effects.cpp b/effects.cpp index 9b11607f3a..65a39b730d 100644 --- a/effects.cpp +++ b/effects.cpp @@ -421,6 +421,12 @@ void EffectsHandlerImpl::windowToDesktop( EffectWindow* w, int desktop ) Workspace::self()->sendClientToDesktop( cl, desktop, true ); } +void EffectsHandlerImpl::setShowingDesktop( bool showing ) + { + Workspace::self()->setShowingDesktop( showing ); + } + + int EffectsHandlerImpl::currentDesktop() const { return Workspace::self()->currentDesktop(); @@ -1446,6 +1452,30 @@ WindowQuadList EffectWindowImpl::buildQuads( bool force ) const return sceneWindow()->buildQuads( force ); } +void EffectWindowImpl::minimize() const + { + if( Client* c = dynamic_cast< Client* >( toplevel )) + { + c->minimize(); + } + } + +void EffectWindowImpl::unminimize() const + { + if( Client* c = dynamic_cast< Client* >( toplevel )) + { + c->unminimize(); + } + } + +void EffectWindowImpl::closeWindow() const + { + if( Client* c = dynamic_cast< Client* >( toplevel )) + { + c->closeWindow(); + } + } + EffectWindow* effectWindow( Toplevel* w ) { EffectWindowImpl* ret = w->effectWindow(); diff --git a/effects.h b/effects.h index ad566e169e..3b611f1d40 100644 --- a/effects.h +++ b/effects.h @@ -55,6 +55,7 @@ class EffectsHandlerImpl : public EffectsHandler virtual EffectWindow* activeWindow() const; virtual void moveWindow( EffectWindow* w, const QPoint& pos ); virtual void windowToDesktop( EffectWindow* w, int desktop ); + virtual void setShowingDesktop( bool showing ); virtual int currentDesktop() const; virtual int numberOfDesktops() const; @@ -257,6 +258,10 @@ class EffectWindowImpl : public EffectWindow virtual WindowQuadList buildQuads( bool force = false ) const; + virtual void minimize() const; + virtual void unminimize() const; + virtual void closeWindow() const; + const Toplevel* window() const; Toplevel* window(); diff --git a/effects/presentwindows/presentwindows.cpp b/effects/presentwindows/presentwindows.cpp index 69ed54880f..89d2ae40fe 100644 --- a/effects/presentwindows/presentwindows.cpp +++ b/effects/presentwindows/presentwindows.cpp @@ -141,6 +141,12 @@ void PresentWindowsEffect::reconfigure( ReconfigureFlags ) m_fillGaps = conf.readEntry( "FillGaps", true ); m_fadeDuration = double( animationTime( 150 )); m_showPanel = conf.readEntry( "ShowPanel", false ); + m_leftButtonWindow = (WindowMouseAction)conf.readEntry( "LeftButtonWindow", (int)WindowActivateAction ); + m_middleButtonWindow = (WindowMouseAction)conf.readEntry( "MiddleButtonWindow", (int)WindowNoAction ); + m_rightButtonWindow = (WindowMouseAction)conf.readEntry( "RightButtonWindow", (int)WindowExitAction ); + m_leftButtonDesktop = (DesktopMouseAction)conf.readEntry( "LeftButtonDesktop", (int)DesktopExitAction ); + m_middleButtonDesktop = (DesktopMouseAction)conf.readEntry( "MiddleButtonDesktop", (int)DesktopNoAction ); + m_rightButtonDesktop = (DesktopMouseAction)conf.readEntry( "RightButtonDesktop", (int)DesktopNoAction ); } const void* PresentWindowsEffect::proxy() const @@ -375,12 +381,14 @@ void PresentWindowsEffect::windowInputMouseEvent( Window w, QEvent *e ) // Which window are we hovering over? Always trigger as we don't always get move events before clicking // We cannot use m_motionManager.windowAtPoint() as the window might not be visible EffectWindowList windows = m_motionManager.managedWindows(); + bool hovering = false; for( int i = 0; i < windows.size(); i++ ) { assert( m_windowData.contains( windows.at( i ))); if( m_motionManager.transformedGeometry( windows.at( i )).contains( cursorPos() ) && m_windowData[windows.at( i )].visible ) { + hovering = true; if( windows.at( i ) && m_highlightedWindow != windows.at( i )) setHighlightedWindow( windows.at( i )); break; @@ -393,13 +401,111 @@ void PresentWindowsEffect::windowInputMouseEvent( Window w, QEvent *e ) QMouseEvent* me = static_cast( e ); if( me->button() == Qt::LeftButton ) { - if( m_highlightedWindow ) - effects->activateWindow( m_highlightedWindow ); - setActive( false ); + if( hovering ) + { + // mouse is hovering above a window - use MouseActionsWindow + mouseActionWindow( m_leftButtonWindow ); + } + else + { + // mouse is hovering above desktop - use MouseActionsDesktop + mouseActionDesktop( m_leftButtonDesktop ); + } + } + if( me->button() == Qt::MidButton ) + { + if( hovering ) + { + // mouse is hovering above a window - use MouseActionsWindow + mouseActionWindow( m_middleButtonWindow ); + } + else + { + // mouse is hovering above desktop - use MouseActionsDesktop + mouseActionDesktop( m_middleButtonDesktop ); + } + } + if( me->button() == Qt::RightButton ) + { + if( hovering ) + { + // mouse is hovering above a window - use MouseActionsWindow + mouseActionWindow( m_rightButtonWindow ); + } + else + { + // mouse is hovering above desktop - use MouseActionsDesktop + mouseActionDesktop( m_rightButtonDesktop ); + } } - // TODO: User mouse actions. E.g. right-click stickies and middle-click brings to current desktop } +void PresentWindowsEffect::mouseActionWindow( WindowMouseAction& action ) + { + switch( action ) + { + case WindowActivateAction: + if( m_highlightedWindow ) + effects->activateWindow( m_highlightedWindow ); + setActive( false ); + break; + case WindowExitAction: + setActive( false ); + break; + case WindowToCurrentDesktopAction: + if( m_highlightedWindow ) + effects->windowToDesktop( m_highlightedWindow, effects->currentDesktop() ); + break; + case WindowToAllDesktopsAction: + if( m_highlightedWindow ) + { + if( m_highlightedWindow->isOnAllDesktops() ) + effects->windowToDesktop( m_highlightedWindow, effects->currentDesktop() ); + else + effects->windowToDesktop( m_highlightedWindow, NET::OnAllDesktops ); + } + break; + case WindowMinimizeAction: + if( m_highlightedWindow ) + { + if( m_highlightedWindow->isMinimized() ) + m_highlightedWindow->unminimize(); + else + m_highlightedWindow->minimize(); + } + break; + case WindowCloseAction: + if( m_highlightedWindow ) + { + m_highlightedWindow->closeWindow(); + } + break; + default: + break; + } + } + +void PresentWindowsEffect::mouseActionDesktop( DesktopMouseAction& action ) + { + switch( action ) + { + case DesktopActivateAction: + if( m_highlightedWindow ) + effects->activateWindow( m_highlightedWindow ); + setActive( false ); + break; + case DesktopExitAction: + setActive( false ); + break; + case DesktopShowDesktopAction: + effects->setShowingDesktop( true ); + setActive( false ); + default: + break; + } + } + + void PresentWindowsEffect::grabbedKeyboardEvent( QKeyEvent *e ) { if( e->type() == QEvent::KeyPress ) diff --git a/effects/presentwindows/presentwindows.h b/effects/presentwindows/presentwindows.h index 27ad514806..2a189615bc 100644 --- a/effects/presentwindows/presentwindows.h +++ b/effects/presentwindows/presentwindows.h @@ -97,6 +97,23 @@ class PresentWindowsEffect ModeSelectedDesktop, // Shows windows of selected desktop via property (m_desktop) ModeWindowGroup // Shows windows selected via property }; + enum WindowMouseAction + { + WindowActivateAction = 0, // Activates the window and deactivates the effect + WindowExitAction = 1, // Deactivates the effect without activating new window + WindowToCurrentDesktopAction = 2, // Brings window to current desktop + WindowToAllDesktopsAction = 3, // Brings window to all desktops + WindowMinimizeAction = 4, // Minimize the window + WindowCloseAction = 5, // Closes the window + WindowNoAction = 6 // nothing + }; + enum DesktopMouseAction + { + DesktopActivateAction = 0, // Activates the window and deactivates the effect + DesktopExitAction = 1, // Deactivates the effect without activating new window + DesktopShowDesktopAction = 2, // Minimizes all windows + DesktopNoAction = 3 // nothing + }; public slots: void setActive( bool active, bool closingTab = false ); // HACK: closingTab shouldn't be needed @@ -136,6 +153,10 @@ class PresentWindowsEffect EffectWindow* relativeWindow( EffectWindow *w, int xdiff, int ydiff, bool wrap ) const; EffectWindow* findFirstWindow() const; + // Helper functions for mouse actions + void mouseActionWindow( WindowMouseAction& action ); + void mouseActionDesktop( DesktopMouseAction& action ); + private: PresentWindowsEffectProxy m_proxy; friend class PresentWindowsEffectProxy; @@ -186,6 +207,14 @@ class PresentWindowsEffect long m_atomDesktop; // Present windows for group of window ids long m_atomWindows; + + // Mouse Actions + WindowMouseAction m_leftButtonWindow; + WindowMouseAction m_middleButtonWindow; + WindowMouseAction m_rightButtonWindow; + DesktopMouseAction m_leftButtonDesktop; + DesktopMouseAction m_middleButtonDesktop; + DesktopMouseAction m_rightButtonDesktop; }; } // namespace diff --git a/effects/presentwindows/presentwindows_config.cpp b/effects/presentwindows/presentwindows_config.cpp index b4d40ed68f..136313a927 100644 --- a/effects/presentwindows/presentwindows_config.cpp +++ b/effects/presentwindows/presentwindows_config.cpp @@ -76,6 +76,12 @@ PresentWindowsEffectConfig::PresentWindowsEffectConfig(QWidget* parent, const QV connect( m_ui->accuracySlider, SIGNAL( valueChanged( int )), this, SLOT( changed() )); connect( m_ui->fillGapsBox, SIGNAL( stateChanged( int )), this, SLOT( changed() )); connect( m_ui->shortcutEditor, SIGNAL( keyChange() ), this, SLOT( changed() )); + connect( m_ui->leftButtonWindowCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() )); + connect( m_ui->middleButtonWindowCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() )); + connect( m_ui->rightButtonWindowCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() )); + connect( m_ui->leftButtonDesktopCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() )); + connect( m_ui->middleButtonDesktopCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() )); + connect( m_ui->rightButtonDesktopCombo, SIGNAL( currentIndexChanged( int )), this, SLOT( changed() )); load(); } @@ -118,6 +124,20 @@ void PresentWindowsEffectConfig::load() bool fillGaps = conf.readEntry( "FillGaps", true ); m_ui->fillGapsBox->setChecked( fillGaps ); + int leftButtonWindow = conf.readEntry( "LeftButtonWindow", int( PresentWindowsEffect::WindowActivateAction )); + m_ui->leftButtonWindowCombo->setCurrentIndex( leftButtonWindow ); + int middleButtonWindow = conf.readEntry( "MiddleButtonWindow", int( PresentWindowsEffect::WindowNoAction )); + m_ui->middleButtonWindowCombo->setCurrentIndex( middleButtonWindow ); + int rightButtonWindow = conf.readEntry( "RightButtonWindow", int( PresentWindowsEffect::WindowExitAction )); + m_ui->rightButtonWindowCombo->setCurrentIndex( rightButtonWindow ); + + int leftButtonDesktop = conf.readEntry( "LeftButtonDesktop", int( PresentWindowsEffect::DesktopExitAction )); + m_ui->leftButtonDesktopCombo->setCurrentIndex( leftButtonDesktop ); + int middleButtonDesktop = conf.readEntry( "MiddleButtonDesktop", int( PresentWindowsEffect::DesktopNoAction )); + m_ui->middleButtonDesktopCombo->setCurrentIndex( middleButtonDesktop ); + int rightButtonDesktop = conf.readEntry( "RightButtonDesktop", int( PresentWindowsEffect::DesktopNoAction )); + m_ui->rightButtonDesktopCombo->setCurrentIndex( rightButtonDesktop ); + emit changed(false); } @@ -143,6 +163,20 @@ void PresentWindowsEffectConfig::save() conf.writeEntry( "FillGaps", m_ui->fillGapsBox->isChecked() ); + int leftButtonWindow = m_ui->leftButtonWindowCombo->currentIndex(); + conf.writeEntry( "LeftButtonWindow", leftButtonWindow ); + int middleButtonWindow = m_ui->middleButtonWindowCombo->currentIndex(); + conf.writeEntry( "MiddleButtonWindow", middleButtonWindow ); + int rightButtonWindow = m_ui->rightButtonWindowCombo->currentIndex(); + conf.writeEntry( "RightButtonWindow", rightButtonWindow ); + + int leftButtonDesktop = m_ui->leftButtonDesktopCombo->currentIndex(); + conf.writeEntry( "LeftButtonDesktop", leftButtonDesktop ); + int middleButtonDesktop = m_ui->middleButtonDesktopCombo->currentIndex(); + conf.writeEntry( "MiddleButtonDesktop", middleButtonDesktop ); + int rightButtonDesktop = m_ui->rightButtonDesktopCombo->currentIndex(); + conf.writeEntry( "RightButtonDesktop", rightButtonDesktop ); + m_ui->shortcutEditor->save(); conf.sync(); @@ -163,6 +197,12 @@ void PresentWindowsEffectConfig::defaults() m_ui->accuracySlider->setSliderPosition( 1 ); m_ui->fillGapsBox->setChecked( true ); m_ui->shortcutEditor->allDefault(); + m_ui->leftButtonWindowCombo->setCurrentIndex( int( PresentWindowsEffect::WindowActivateAction )); + m_ui->middleButtonWindowCombo->setCurrentIndex( int( PresentWindowsEffect::WindowNoAction )); + m_ui->rightButtonWindowCombo->setCurrentIndex( int( PresentWindowsEffect::WindowExitAction )); + m_ui->leftButtonDesktopCombo->setCurrentIndex( int( PresentWindowsEffect::DesktopExitAction )); + m_ui->middleButtonDesktopCombo->setCurrentIndex( int( PresentWindowsEffect::DesktopNoAction )); + m_ui->rightButtonDesktopCombo->setCurrentIndex( int( PresentWindowsEffect::DesktopNoAction )); emit changed(true); } diff --git a/effects/presentwindows/presentwindows_config.ui b/effects/presentwindows/presentwindows_config.ui index 5cd868eff9..a729eb1e88 100644 --- a/effects/presentwindows/presentwindows_config.ui +++ b/effects/presentwindows/presentwindows_config.ui @@ -1,128 +1,129 @@ - + + KWin::PresentWindowsEffectConfigForm - - + + 0 0 - 535 - 345 + 542 + 441 - - - - + + + + Appearance - - - - + + + + Rearrange &duration: - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + rearrangeDurationSpin - - - - + + + + 0 0 - - Default + + Default - + msec - + 5000 - + 10 - + 0 - - - + + + Layout mode: - + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - + layoutCombo - - - - + + + + 0 0 - + Natural - + Regular Grid - + Flexible Grid - - - + + + Display window &titles - - - + + + Display window &icons - - - + + + Use for window &switching - - - + + + Ignore &minimized windows - - - + + + Show &panels @@ -130,16 +131,16 @@ - - - + + + Activation - - - - - + + + + + 0 0 @@ -149,25 +150,25 @@ - - - + + + Natural Layout Settings - - - - + + + + Fill &gaps - - - + + + Qt::Vertical - + 20 40 @@ -175,62 +176,62 @@ - - - + + + Faster - + - - - + + + 130 0 - + 1 - + 8 - + 1 - + 1 - + 1 - + true - + Qt::Horizontal - + true - + false - + QSlider::TicksBelow - - - + + + Nicer - + @@ -238,13 +239,265 @@ + + + + Windows + + + + + + Left button: + + + + + + + + Activate window + + + + + End effect + + + + + Bring window to current desktop + + + + + Send window to all desktops + + + + + (Un-)Minimize window + + + + + Close window + + + + + No action + + + + + + + + Middle button: + + + + + + + + Activate window + + + + + End effect + + + + + Bring window to current desktop + + + + + Send window to all desktops + + + + + (Un-)Minimize window + + + + + Close window + + + + + No action + + + + + + + + Right button: + + + + + + + + Activate window + + + + + End effect + + + + + Bring window to current desktop + + + + + Send window to all desktops + + + + + (Un-)Minimize window + + + + + Close window + + + + + No action + + + + + + + + + + + Desktop + + + + QFormLayout::ExpandingFieldsGrow + + + + + Left button: + + + + + + + + Activate window + + + + + End effect + + + + + Show desktop + + + + + No action + + + + + + + + Middle button: + + + + + + + + Activate window + + + + + End effect + + + + + Show desktop + + + + + No action + + + + + + + + Right button: + + + + + + + + Activate window + + + + + End effect + + + + + Show desktop + + + + + No action + + + + + + + KWin::GlobalShortcutsEditor QWidget -
kwineffects.h
+
kwineffects.h
1
diff --git a/lib/kwineffects.h b/lib/kwineffects.h index a09b38fe5e..36e7e2c9d4 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -170,7 +170,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 100 +#define KWIN_EFFECT_API_VERSION_MINOR 101 #define KWIN_EFFECT_API_VERSION KWIN_EFFECT_API_MAKE_VERSION( \ KWIN_EFFECT_API_VERSION_MAJOR, KWIN_EFFECT_API_VERSION_MINOR ) @@ -557,6 +557,7 @@ class KWIN_EXPORT EffectsHandler virtual EffectWindow* activeWindow() const = 0 ; virtual void moveWindow( EffectWindow* w, const QPoint& pos ) = 0; virtual void windowToDesktop( EffectWindow* w, int desktop ) = 0; + virtual void setShowingDesktop( bool showing ) = 0; // Desktops /** @@ -948,6 +949,10 @@ class KWIN_EXPORT EffectWindow * Returns the unmodified window quad list. Can also be used to force rebuilding. */ virtual WindowQuadList buildQuads( bool force = false ) const = 0; + + virtual void minimize() const = 0; + virtual void unminimize() const = 0; + virtual void closeWindow() const = 0; }; class KWIN_EXPORT EffectWindowGroup