Switching workspace in GNOME via the command line

March 04, 2011 [GNOME, Tech]

I use rdesktop to connect to some Windows machines, and it works beautifully. I like to allow it to grab keyboard input so I can switch and close windows on my Windows desktop without fear of accidentally doing something to the rest of my Linux desktop.

However, I have never found a way of letting some keystrokes escape - specifically Ctrl-Alt-Left, Right, Up, Down so that I can switch workspaces (virtual desktops) away from the workspace containing rdesktop.

I have finally found what I hope is a good workaround - I have installed easystroke and defined some mouse gestures I can use to switch desktop. These mouse gestures are not swallowed by rdesktop, so they still work, even when it has focus.

When I asked easystroke to send the Ctrl-Alt-Left etc. keystrokes, they got swallowed by rdesktop, so all I needed to be able to do complete the story was a command-line tool to switch workspace.

That turned out to be trickier than you might imagine, but here is my solution, using the amazing wmctrl.

This should work on GNOME with the metacity window manager, and the standard GNOME workspace switcher. It should be easy to adapt to other window managers and workspace tools.

First, install some tools. On Ubuntu you need:

sudo apt-get install bc wmctrl coreutils grep bash

Now create a file with gedit ~/bin/workspace-switcher & and edit it to look like this:

#!/bin/bash

CMD="$1"

NUM_WORKSPACES=`gconftool-2 --get /apps/metacity/general/num_workspaces`
NUM_COLS=`gconftool-2 --get /apps/panel/applets/workspace_switcher_screen0/prefs/num_rows`

NUM_ROWS=`echo "$NUM_WORKSPACES / $NUM_COLS" | bc`

CURRENT_WS=`wmctrl -d | grep \* | cut -d " " -f 1`

MOVE_LEFT="- $NUM_ROWS"
MOVE_RIGHT="+ $NUM_ROWS"
MOVE_UP="-1"
MOVE_DOWN="+1"

case $CMD in

"Left" )
	NEW_WS=`echo $CURRENT_WS "-" $NUM_ROWS | bc`
	if [[ $NEW_WS -lt 0 ]]; then NEW_WS=$CURRENT_WS; fi
	;;

"Right" )
	NEW_WS=`echo $CURRENT_WS "+" $NUM_ROWS | bc`
	if [[ $NEW_WS -ge $NUM_WORKSPACES ]]; then NEW_WS=$CURRENT_WS; fi
	;;

"Up" )
	WS_COL=`echo $CURRENT_WS "%" $NUM_ROWS | bc`
	if [[ $WS_COL -eq 0 ]]; then
	{
		NEW_WS=$CURRENT_WS
	}
	else
	{
		NEW_WS=`echo $CURRENT_WS "- 1" | bc`
	}; fi
	;;

"Down" )
	NEW_WS=`echo $CURRENT_WS "+ 1" | bc`
	NEW_WS_COL=`echo $NEW_WS "%" $NUM_ROWS | bc`
	if [[ $NEW_WS_COL -eq 0 ]]; then NEW_WS=$CURRENT_WS; fi
	;;

* )
	NEW_WS=$CMD

esac

wmctrl -s $NEW_WS

Make it executable with chmod +x ~/bin/workspace-switcher and make sure ~/bin is in your PATH.

You can run it like this:

switch-workspace Left

to move left - the other possiblities are, obviously, Right, Up and Down.

Or like this:

switch-workspace 3

to move to a workspace by number.

If you want to use it with easystroke, create an action, and for the command simply enter switch-workspace Left and similar as the command.

Easystroke can be installed on Ubuntu like this:

sudo apt-get install easystroke