So, after a take on Metacity , I just went ahead and implemented the same quick workspace switching feature for KDE (namely, kwin) – with great help from Nicolas Lécureuil (a.k.a. Neoclust) of course!
Basically, it works essentially like the same feature in xfwm4 – when you switch to a different workspace via a keyboard shortcut, and press the same shortcut again while on this workspace, it will bring you back to the previous one. So you can press ctrl-f2 to switch to from workspace 1 workspace 2, and when you press ctrl-f2 again kwin will recognize that you want switch back, to whatever workspace you were before, and will do it. An extremely handy quirk which I cannot live without anymore
.
I have to assume that I have never ever coded anything for KDE until yesterday, but it turned out to be extremely simple. KDE has its flaws, its infrastructure with billions of libraries and processes everywhere is hard to understand, but I actually was surprised on how easy it was.
So, without further words, the patch for kdebase4-workspace which adds this functionality follows (sorry for the formatting, but kde has some very long lines of code..):
diff -p -up kdebase-workspace-4.5.65svn1165394/kwin/kcmkwin/kwindesktop/main.cpp.switchback kdebase-workspace-4.5.65svn1165394/kwin/kcmkwin/kwindesktop/main.cpp
--- kdebase-workspace-4.5.65svn1165394/kwin/kcmkwin/kwindesktop/main.cpp.switchback 2010-09-01 09:10:02.000000000 -0300
+++ kdebase-workspace-4.5.65svn1165394/kwin/kcmkwin/kwindesktop/main.cpp 2010-09-01 09:21:13.000000000 -0300
@@ -184,6 +184,7 @@ void KWinDesktopConfig::init()
connect( m_ui->popupHideSpinBox, SIGNAL(valueChanged(int)), SLOT(changed()));
connect( m_ui->desktopLayoutIndicatorCheckBox, SIGNAL(stateChanged(int)), SLOT(changed()));
connect( m_ui->wrapAroundBox, SIGNAL(stateChanged(int)), SLOT(changed()));
+ connect( m_ui->switchBackBox, SIGNAL(stateChanged(int)), SLOT(changed()));
connect( m_editor, SIGNAL(keyChange()), SLOT(changed()));
connect( m_ui->allShortcutsCheckBox, SIGNAL(stateChanged(int)), SLOT(slotShowAllShortcuts()));
connect( m_ui->effectComboBox, SIGNAL(currentIndexChanged(int)), SLOT(changed()));
@@ -252,6 +253,8 @@ void KWinDesktopConfig::defaults()
m_ui->wrapAroundBox->setChecked( true );
+ m_ui->switchBackBox->setChecked( false );
+
m_editor->allDefault();
emit changed(true);
@@ -285,6 +288,9 @@ void KWinDesktopConfig::load()
KConfigGroup windowConfig( m_config, "Windows" );
m_ui->wrapAroundBox->setChecked( windowConfig.readEntry<bool>( "RollOverDesktops", true ) );
+ // Quick switching back to previous desktop
+ m_ui->switchBackBox->setChecked( windowConfig.readEntry<bool>( "SwitchBackDesktops", false ) );
+
// Effect for desktop switching
// Set current option to "none" if no plugin is activated.
KConfigGroup effectconfig( m_config, "Plugins" );
@@ -341,6 +347,9 @@ void KWinDesktopConfig::save()
// Wrap Around on screen edge
KConfigGroup windowConfig( m_config, "Windows" );
windowConfig.writeEntry( "RollOverDesktops", m_ui->wrapAroundBox->isChecked() );
+ //
+ // Quickly back to previous desktop
+ windowConfig.writeEntry( "SwitchBackDesktops", m_ui->switchBackBox->isChecked() );
// Effect desktop switching
KConfigGroup effectconfig( m_config, "Plugins" );
diff -p -up kdebase-workspace-4.5.65svn1165394/kwin/kcmkwin/kwindesktop/main.ui.switchback kdebase-workspace-4.5.65svn1165394/kwin/kcmkwin/kwindesktop/main.ui
--- kdebase-workspace-4.5.65svn1165394/kwin/kcmkwin/kwindesktop/main.ui.switchback 2010-09-01 09:09:59.000000000 -0300
+++ kdebase-workspace-4.5.65svn1165394/kwin/kcmkwin/kwindesktop/main.ui 2010-09-01 09:59:02.000000000 -0300
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>572</width>
- <height>310</height>
+ <height>334</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
@@ -141,6 +141,16 @@
</property>
</widget>
</item>
+ <item>
+ <widget class="QCheckBox" name="switchBackBox">
+ <property name="whatsThis">
+ <string>Enable this option if you want to remember and recall previous desktop when switching via keyboard shortcuts. E.g., if you switched to desktop 2 by pressing its shortcut, pressing it again while on desktop 2 will bring you back to the previous desktop.</string>
+ </property>
+ <property name="text">
+ <string>Remember and recall previous desktop when switching via keyboard shortcuts</string>
+ </property>
+ </widget>
+ </item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
diff -p -up kdebase-workspace-4.5.65svn1165394/kwin/kwin.kcfg.switchback kdebase-workspace-4.5.65svn1165394/kwin/kwin.kcfg
--- kdebase-workspace-4.5.65svn1165394/kwin/kwin.kcfg.switchback 2010-09-01 09:10:56.000000000 -0300
+++ kdebase-workspace-4.5.65svn1165394/kwin/kwin.kcfg 2010-09-01 09:16:20.000000000 -0300
@@ -41,6 +41,7 @@
<entry key="ShadeHover" type="Bool" />
<entry key="GeometryTip" type="Bool" />
<entry key="RollOverDesktops" type="Bool" />
+ <entry key="SwitchBackDesktops" type="Bool" />
<entry key="FocusStealingPreventionLevel" type="Int" />
<entry key="Placement" type="String" />
<entry key="AutoRaise" type="Bool" />
diff -p -up kdebase-workspace-4.5.65svn1165394/kwin/options.cpp.switchback kdebase-workspace-4.5.65svn1165394/kwin/options.cpp
--- kdebase-workspace-4.5.65svn1165394/kwin/options.cpp.switchback 2010-09-01 09:12:09.000000000 -0300
+++ kdebase-workspace-4.5.65svn1165394/kwin/options.cpp 2010-09-01 09:26:40.000000000 -0300
@@ -87,6 +87,8 @@ unsigned long Options::updateSettings()
rollOverDesktops = config.readEntry("RollOverDesktops", true);
+ switchBackDesktops = config.readEntry("SwitchBackDesktops", false);
+
legacyFullscreenSupport = config.readEntry( "LegacyFullscreenSupport", false );
// focusStealingPreventionLevel = config.readEntry( "FocusStealingPreventionLevel", 2 );
diff -p -up kdebase-workspace-4.5.65svn1165394/kwin/options.h.switchback kdebase-workspace-4.5.65svn1165394/kwin/options.h
--- kdebase-workspace-4.5.65svn1165394/kwin/options.h.switchback 2010-09-01 09:12:07.000000000 -0300
+++ kdebase-workspace-4.5.65svn1165394/kwin/options.h 2010-09-01 09:22:14.000000000 -0300
@@ -215,6 +215,11 @@ class Options : public KDecorationOption
*/
bool rollOverDesktops;
+ /**
+ * whether or not quick switching back to previous desktop is allowed via keyboard shortcuts
+ */
+ bool switchBackDesktops;
+
// 0 - 4 , see Workspace::allowClientActivation()
int focusStealingPreventionLevel;
diff -p -up kdebase-workspace-4.5.65svn1165394/kwin/workspace.cpp.switchback kdebase-workspace-4.5.65svn1165394/kwin/workspace.cpp
--- kdebase-workspace-4.5.65svn1165394/kwin/workspace.cpp.switchback 2010-05-20 08:42:10.000000000 -0300
+++ kdebase-workspace-4.5.65svn1165394/kwin/workspace.cpp 2010-09-01 10:10:02.000000000 -0300
@@ -95,6 +95,7 @@ Workspace::Workspace( bool restore )
, desktopGridSize_( 1, 2 ) // Default to two rows
, desktopGrid_( new int[2] )
, currentDesktop_( 0 )
+ , prevDesktop_( 0 )
, desktopLayoutDynamicity_( false )
, tilingEnabled_( false )
// Unsorted
@@ -1403,6 +1404,15 @@ bool Workspace::setCurrentDesktop( int n
StackingUpdatesBlocker blocker( this );
int old_desktop = currentDesktop();
+
+ // Eugeni: are we trying to switch back to previous desktop?
+ if (options->switchBackDesktops && (old_desktop == new_desktop ) && (prevDesktop() > 0) )
+ {
+ // go back to previous desktop
+ new_desktop = prevDesktop();
+ kDebug(1212) << "Switching back to " << new_desktop;
+ }
+
if (new_desktop != currentDesktop() )
{
++block_showing_desktop;
@@ -1413,6 +1423,7 @@ bool Workspace::setCurrentDesktop( int n
ObscuringWindows obs_wins;
currentDesktop_ = new_desktop; // Change the desktop (so that Client::updateVisibility() works)
+ prevDesktop_ = old_desktop;
for( ClientList::ConstIterator it = stacking_order.constBegin();
it != stacking_order.constEnd();
diff -p -up kdebase-workspace-4.5.65svn1165394/kwin/workspace.h.switchback kdebase-workspace-4.5.65svn1165394/kwin/workspace.h
--- kdebase-workspace-4.5.65svn1165394/kwin/workspace.h.switchback 2010-08-11 07:08:13.000000000 -0300
+++ kdebase-workspace-4.5.65svn1165394/kwin/workspace.h 2010-08-31 23:34:01.000000000 -0300
@@ -245,6 +245,10 @@ class Workspace : public QObject, public
*/
int currentDesktop() const;
/**
+ * @returns The ID of the previous desktop.
+ */
+ int prevDesktop() const;
+ /**
* Set the current desktop to @a current.
* @returns True on success, false otherwise.
*/
@@ -314,6 +318,7 @@ class Workspace : public QObject, public
QSize desktopGridSize_;
int* desktopGrid_;
int currentDesktop_;
+ int prevDesktop_;
QString activity_;
bool desktopLayoutDynamicity_;
@@ -1142,6 +1147,11 @@ inline int Workspace::currentDesktop() c
return currentDesktop_;
}
+inline int Workspace::prevDesktop() const
+ {
+ return prevDesktop_;
+ }
+
inline int Workspace::desktopAtCoords( QPoint coords ) const
{
return desktopGrid_[coords.y() * desktopGridSize_.width() + coords.x()];