3

When undocking my laptop from twinview external monitors back to a single screen I would like to have a single command to move all windows onto my primary screen.

Although nvidia does some of the work so that I can see the edge of the windows, moving each one with the mouse, keyboard or compiz plugins takes time.

4 Answers 4

4

You can use wmctrl and a little bash script to loop through the windows and then position them onto your primary display. I threw this together. It might be sufficient for you.

#! /bin/bash

#dump the list of windows to a file
wmctrl -l > /tmp/window_list.txt
x=40; y=40

#read the window information from the file
while read id sticky host win_title; do

    #move any non-sticky windows except the desktop
    if [ "$sticky" == "0" -a "$win_title" != "x-nautilus-desktop" ]
      then
        wmctrl -i -r $id -e 0,$x,$y,-1,-1
        x=$(($x + 40))
        y=$(($y + 40))
    fi

done < /tmp/window_list.txt

#delete the temporary file
rm /tmp/window_list.txt
exit 0

Save it to a file called "move_windows.sh" or something and give it execute permissions with chmod +x move_windows.sh and then create a launcher for it.

3
  • Oh, almost forgot. I don't use Unity so I'm not sure what it will do in that environment.
    – Ramón
    May 26, 2011 at 0:26
  • Yep it need some tweaks for unity, ill test again tomorrow.
    – Cas
    May 26, 2011 at 1:38
  • Thank you! Your script was very useful in finding a workaround for a bug I had with openbox (it would crash every time I switched monitor configuration if a window was on an external monitor). Mar 7, 2013 at 4:14
3

The script I made below works for me, only requires wmctrl. You can get this on Ubuntu with the command sudo apt-get install wmctrl.

If needed, you may need to make some minor modifications.

$BEFORE_WINDOW_NAME must be set to the last string of your computer name pulled (you can view this from System Settings>Details>Device name).

$MONITORS this will work with 2 monitors (with a resoloution of 1920x####) although you may re-define this variable by setting an element for each monitor connected to your device and setting it to any x coordinate on that screen.

$SKIPPED_WINDOWS is a list of windows you do not want to move when this script is called. Feel free to add or remove items. List of items can be view by typing in the command wmctrl -l.

Finally, this script take in one parameter ie : window_control.sh n, where n is the monitor the to move the windows.

#! /bin/bash
IFS=$'\n' #prevents window names from breaking in loop

#Computers Name
#change this to the last characters before window names 
#0x02a00002  0 mycomputer-Envy-M3970 XdndCollectionWindowImp -> ie:last characters in computer name

BEFORE_WINDOW_NAME="M3970" #MODIFY ME!!
WINDOWS=$(wmctrl -l | grep -oh -P "(?<=$BEFORE_WINDOW_NAME\ ).*")
#MODIFY MONITORS if needed
declare -a MONITORS=(
'0'     # Monitor 1
'2150'  # Monitor 2
);  
declare -a SKIPPED_WINDOWS=(
'XdndCollectionWindowImp'
'unity-launcher'
'unity-panel'
'unity-dash'
'Hud'
'Desktop'
'Ubuntu'
);

#loop through window names and move them
for i in $WINDOWS; do
  if [[ " ${SKIPPED_WINDOWS[@]} " =~ " ${i} " ]]; then
    # whatever you DO NOT want to do when arr contains value
#    echo "Skipping $i"
    echo ""
  else
    # whatever you want to do when arr contains value
    echo "Moving $i"
    wmctrl -r "$i" -b remove,maximized_vert,maximized_horz
    wmctrl -r "$i" -e 0,"${MONITORS[$1]}",0,800,800
    wmctrl -r "$i" -b add,maximized_vert,maximized_horz
  fi
done
0

I would love to find a better solution, but Compiz has Grouping of windows.

0

In addition to @Ramón's answer (thanks bwt). I wanted to move all my windows on the primary monitor so I used xrandr for that.

Normally the primary monitor is marked with an * in the output list when running xrandr --listactivemonitors

sven@NB-PF26RJG3:~$ xrandr --listactivemonitors
Monitors: 3
 0: +*DVI-I-1-1 1920/598x1080/336+2560+1080  DVI-I-1-1
 1: +eDP-1 1920/309x1080/174+2560+0  eDP-1
 2: +DVI-I-2-2 2560/597x1440/336+0+1080  DVI-I-2-2

So I added some extra lines to determine the original x and y of the primary monitor

MAIN_MONITOR_WORSPACE=`xrandr --listactivemonitors | awk '/\+\*/ {print $3}' | awk '{ print $2, $3}' FS=+`
declare -i x=`echo "${MAIN_MONITOR_WORSPACE}" | awk '{print $1}'`
declare -i y=`echo "${MAIN_MONITOR_WORSPACE}" | awk '{print $2}'`

# Some horizontal padding, i have my taskbar vertically on the left
x=$((${x} + 24))

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .