Sample menu:

Switch between xfwm4/metacity-compiz and keep windows in their working spaces

This is a script designed to switch between xfwm4 (xfce windows manager) and compiz windows manager and restore the windows in the working spaces where they were. I use to switch between these two windows managers in my laptop depending whether I am using the battery or it is docked and lying on the table with an external monitor plugged in. Unfortunately, if you type F2 and execute "compiz --replace" (or xfwm4 --replace), all windows are moved to the first working space, which is very annoying. This script pretends to solve this. You can easily modify it to use metacity instead of xfwm4.
#!/bin/bash

###Code partially taken from http://odyniec.net/
##Depends on: wmctrl, xdpyinfo, xprop, xwininfo, bc
##This script switches from xfwm4/metacity windwos manager to compiz and viceversa,
##and restores the windows in the working spaces where they were.
##By default it switches between xfwm4 (xfce4 windows manger) and compiz, but
##you can easily modify it to use metacity instead of xfwm4.
##TODO/improve: it would be worth to sort the windows by workin space.
##		The script does not work un dual screen mode.

function compiz_mw2cwsp(){
###Moves back WINDOW_ID window to current workspace in compiz
    # Calculate the new location of the window
    NEW_WINDOW_X=`echo "($CURRENT_X + ($WINDOW_X)) % $WORKSPACE_WIDTH" | bc`
    NEW_WINDOW_Y=`echo "($CURRENT_Y + ($WINDOW_Y)) % $WORKSPACE_HEIGHT" | bc`
 
    # Move the window to the new location and raise it
    wmctrl -i -r "$WINDOW_ID" -e 10,"$NEW_WINDOW_X","$NEW_WINDOW_Y",-1,-1
    wmctrl -i -R "$WINDOW_ID"
}

##Number of desktops:
N=5

# We get the dimensions of a single workspace
    XDPYINFO_OUT=`xdpyinfo | grep 'dimensions:'`
    WORKSPACE_WIDTH=`echo "$XDPYINFO_OUT" | sed -r 's/.*:\s+([0-9]+)x.*/\1/'`
    WORKSPACE_HEIGHT=`echo "$XDPYINFO_OUT" \
        | sed -r 's/.*:\s+[0-9]+x([0-9]+).*/\1/'`
 
    # Get the X and Y offset of the current workspace
    XPROP_OUT=`xprop -root -notype _NET_DESKTOP_VIEWPORT`
    CURRENT_X=`echo "$XPROP_OUT" | sed -r 's/.*= ([0-9]+),.*/\1/'`
    CURRENT_Y=`echo "$XPROP_OUT" | sed -r 's/.*= [0-9]+,\s*([0-9]+).*/\1/'`


WINDOWS_FILE=$HOME/windows_list.tmp
WINDOWS_POS_FILE=$HOME/windows_pos_list.tmp
wmctrl -l -G > $WINDOWS_FILE
NWINDOWS=$(wc -l $WINDOWS_FILE | awk '{print $1}')

###We first get information about the current position of all windows
for i in `seq 1 1 $NWINDOWS`; do
WINDOW_ID=$(tail -n +$i $WINDOWS_FILE | head -n 1 | awk '{print $1}')
	
	    # Get the coordinates of the top left corner of WINDOW_ID window
	XWININFO_OUT=`xwininfo -id "$WINDOW_ID"`
	WINDOW_X=`echo "$XWININFO_OUT" | grep 'Absolute upper-left X' \
	        | sed -r 's/.*:\s+([0-9-]+).*/\1/'`
	WINDOW_Y=`echo "$XWININFO_OUT" | grep 'Absolute upper-left Y' \
	        | sed -r 's/.*:\s+([0-9-]+).*/\1/'`
	##We save them in a file
	echo "$WINDOW_ID $WINDOW_X $WINDOW_Y" >> $WINDOWS_POS_FILE
done

##Windows Manager we are switching to:
WM=$(wmctrl -m | grep Name |awk '{print $2}')


if [ "$WM" == "compiz" ]; then
	echo "Switching to xfwm4"
	(xfwm4 --replace)&
	sleep 3s
	WM="xfwm4"
	###When switching to xfwm4, there is a bug that sets the number of desktops to 1.
	###We restore the number of desktops to N:
	wmctrl -n $N
else
	echo "Switching to compiz"
	(compiz --replace)&
	sleep 7s
	WM="compiz"
fi

###We now restore windows position
for i in `seq 1 1 $NWINDOWS`; do
	WINDOW_ID=$(tail -n +$i $WINDOWS_FILE | head -n 1 | awk '{print $1}')
	DESKTOP_NUM=$(tail -n +$i $WINDOWS_FILE | head -n 1 | awk '{print $2}')
	WINDOW_X=$(tail -n +$i $WINDOWS_POS_FILE | head -n 1 | awk '{print $2}')
	WINDOW_Y=$(tail -n +$i $WINDOWS_POS_FILE | head -n 1 | awk '{print $3}')
	if [ $DESKTOP_NUM -ne -1 ]; then ###To ignore sticky windows
		if [ "$WM" == "compiz" ]; then ##We are switching to compiz
			let DESKTOP_NUM=$DESKTOP_NUM+1
			xaux=$(echo "$DESKTOP_NUM*($WORKSPACE_WIDTH-1)" | bc)
			wmctrl -o $xaux,0
			sleep 1.5s
			compiz_mw2cwsp ##We move the window to the current viewport

		else ##We are switching from compiz
			DESKTOP_NUM=`echo "$WINDOW_X / $WORKSPACE_WIDTH" | bc`
			wmctrl -s $DESKTOP_NUM 
			sleep 0.5s
			wmctrl -i -R $WINDOW_ID
		fi
	fi
done

rm $WINDOWS_FILE
rm $WINDOWS_POS_FILE
exit 0