Switch active window via shortcut between two monitors on linux

By Christopher, January 25, 2011

SCRIPT UPDATED: ERROR CORRECTION AND IMPROVEMENTS DEPENDING SOME SPECIAL CONDITIONS 30.1.2011

If I use two monitors in windows environment I use some scrips of the tool active aid http://activaid.telgkamp.de/ to have the ability to switch the active window between both monitors with a shortcut. Since I meanly use Linux on my private pc and laptop I missed this feature badly and I did not find some tool or script which fills this gap.
But like the world works as Linux user, if something does not exist, make it on your own:
My result is a bash-script which switches the active window between both monitors. This script based on wmiface, a tool which gives you the ability to control windows from a NetWm compatible Window-Manager, so at least KDE and GNOME (I tested it on GNOME). A special requirement for my environment is the ability to switch between to monitors with different resolutions.
To use my script you need to install wmiface on your distribution, I think you will not find it in your package manager, but you could download install packages for nearly all huge distributions (or the source) from this site:
http://kde-apps.org/content/show.php/WMIface?content=40425
If you use debian (like my on my workstation) choose the ubuntu packages. On my test-system(debian 64 testing) the ubuntu 64 packages works fine.
Here is the script, download it or copy it and save it to a file. Give execution rights wiht chmod +x. (I copied it to /usr/bin but this it not necessary. You could run it from every directory.) You should test the script in terminal and if everything works fine you could assign this script to a shortcut with gnome-keybinding-properties. Do not forget to edit the resolution for the left and right monitor in line 10 and 11. If you have more than two monitors you should be able to write your own script based on my work.

SCRIPT UPDATED: ERROR CORRECTION AND IMPROVEMENTS DEPENDING SOME SPECIAL CONDITIONS 30.1.2011

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/bin/bash
#author: Christopher-Eyk Hrabia - http://www.ceh-photo.de - c.hrabia@gmail.com
#
# Dependency: wmiface
# General: https://www.linux-apps.com/content/show.php/WMIface?content=40425
# For Ubuntu: sudo apt install wmiface
DEBUG="" # write DEBUG="1" for debugging

#redirect stdin, stdout and stderr
[ ! "${DEBUG}" ] && exec>/dev/null 2>&1 </dev/null

#configuration for monitor width resolution of both monitors
monitorLeft=1680
monitorRight=1280


#calculate resizing factor
if [ $monitorLeft -gt $monitorRight ];then
    faktorBigToSmall=$(echo "scale=5; ($monitorRight / $monitorLeft)" | bc)
    faktorSmallToBig=$(echo "scale=5; ($monitorLeft / $monitorRight)" | bc)
    monitorBigger=$monitorLeft
else
    faktorBigToSmall=$(echo "scale=5; ($monitorLeft / $monitorRight)" | bc)
    faktorSmallToBig=$(echo "scale=5; ($monitorRight / $monitorLeft)" | bc)
    monitorBigger=$monitorRight
fi

#get pointer of active window
win=$(wmiface activeWindow)


#get maximized status
#0 for not maximized,
#1 for maximized horizontally,
#2 for maximized vertically or
#3 for fully maximized.
maximized=$(wmiface windowMaximized $win)

echo MaxMin $maximized

#bring window to normal size avoids some strange effects during window shifting
if [[ $maximized -gt 0 ]];then
    wmiface maximize $win 0 0
fi


#get position

set `wmiface framePosition $win | tr '+' ' '`

x=$1
y=$2

echo x: $x
echo y: $y

#get framesize
echo framesize
set `wmiface frameSize $win | tr 'x' ' '`

sizeX=$1
sizeY=$2
if [[ $maximized -eq 0 ]] || [[ ($maximized -eq 2) ]];then
notHorizontalMax=1 # our window is not horizontally maximzed
fi;


# calculate new x position
if [[ $x -ge $monitorLeft ]];then # we are on the right screen

    if [[ $monitorBigger -gt $monitorLeft ]];then #the right screen is bigger
   
        if [[ $notHorizontalMax -eq 1 ]] && [[ ($sizeX -gt $monitorLeft) ]];then #resize window if it does not fit into smaller monitor
            sizeX=$monitorLeft
        fi;
   
        x=$(echo "($x - $monitorLeft) * $faktorBigToSmall" | bc)
        echo BigToSmall $faktorBigToSmall
       
    else # the left screen is bigger
   
        x=$(echo "($x - $monitorLeft) * $faktorSmallToBig" | bc)
        echo SmallToBig $faktorSmallToBig
       
    fi
   
    #round x
    x=$(echo "($x+0.5)/1" | bc)
   
    xAllInAll=$(( x + sizeX ))
   
    if [[ $xAllInAll -gt $monitorLeft ]];then
        x=0
    fi
   
   
else # we are on the left screen

    if [[ $monitorBigger -gt $monitorLeft ]];then  #the right screen is bigger
   
        x=$(echo "$monitorLeft+ $x * $faktorSmallToBig" | bc)
        echo BigToSmall2 $faktorBigToSmall
       
    else # the left screen is bigger
   
        if [[ $notHorizontalMax -eq 1 ]] && [[ ($sizeX -gt $monitorRight) ]];then #resize window if it does not fit into smaller monitor
            sizeX=$monitorRight
        fi;
       
        x=$(echo "$monitorLeft + $x * $faktorBigToSmall" | bc)
        echo SmallToBig2 $faktorSmallToBig
    fi
   
    #round x
    x=$(echo "($x+0.5)/1" | bc)
   
    xAllInAll=$(( x + sizeX ))
    echo All x $xAllInAll
   
    if [[ $xAllInAll -gt $(( monitorRight + monitorLeft )) ]];then
        x=$monitorLeft
    fi
fi


echo x $x
echo y $y

#move window
wmiface setFrameGeometry $win $x $y $sizeX $sizeY

#if window was maximized bring it to former size
case $maximized in
1)
   wmiface maximize $win 1 0;;
2)
   wmiface maximize $win 0 1;;
3)
   wmiface maximize $win 1 1;;
esac

Some hint for google chrome/chromium users, the script does only work if you set the setting in chrome for using the system frame and not the special one from chrome.

Here is a screenshot of the correct setting in german environment:

Script as Download:
SCRIPT UPDATED: ERROR CORRECTION AND IMPROVEMENTS DEPENDING SOME SPECIAL CONDITIONS 30.1.2011
monitorSwitch.run

If you study my script you see the power of wmiface. If you download the source package from the mentioned site you found a list of all available commands in the Readme. For example you could also switch windows between virtual desktops…

3 Comments

  1. […] uses wmctrl but I used wmiface like in this post http://www.ceh-photo.de/blog/?p=265 (please check that post to get information about installing/downloading wmiface), because I am […]

  2. Christopher says:

    Just tested with the wmiface package for Ubuntu 12.04 (amd64) on Ubuntu 13.10 (amd64) and everything is still working nicely!

  3. Christopher says:

    Updated script documentation and comments

What do you think?

You must be logged in to post a comment.