-
Notifications
You must be signed in to change notification settings - Fork 0
/
switch_monitor.sh
executable file
·161 lines (136 loc) · 4.74 KB
/
switch_monitor.sh
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#!/bin/bash
#
# This is based loosely on a script available here:
#
# http://makandracards.com/makandra/12447-how-to-move-a-window-to-the-next-monitor-on-xfce-xubuntu
#
# Which was in turn based on one available here:
#
# http://icyrock.com/blog/2012/05/xubuntu-moving-windows-between-monitors/
#
# Neither of which worked quite right with fullscreen (distinct from maximized) windows
#
# Unfortunately it *is* necessary to remove the fullscreen property before moving. For some reason,
# not doing so can lead to a window switching back to its original monitor after alt+tab is pressed.
# Fortunately it can then be restored, but this leads to a visually unappealing move
# since cut indexes from 1, pretty much everything in this script will too
function index {
echo `echo $1 | cut -d"$2" -f$3`
}
# get monitor dimension information from monitors listed as 'connected' by xrandr
# if for whatever reason this doesn't work, you can manually set widths and offsets.
# if your screens (left to right) have widths W1, W2, W3,
# then you would set widths to "W1 W2 W3" and offsets to "0 W1 W2"
widths=""
heights=""
offsets=""
monitor_count=0
while read -r line
do
info=`echo $line | sed -n 's/.* \([0-9]*x[0-9]*+[0-9]*+[0-9]*\).*/\1/p'`
widths="$widths $(index $info 'x' 1)"
heights="$heights $(index $(index $info 'x' 2) '+' 1)"
offsets="$offsets $(index $info '+' 2)"
((monitor_count++))
done < <(xrandr --current | grep ' connected')
# put them in left-right order--computationally inefficient selection sort, but you probably don't have 100000 monitors
start=0
ordered_widths=""
ordered_heights=""
ordered_offsets=""
for i in $(seq 1 $monitor_count)
do
for j in $(seq 1 $monitor_count)
do
width=$(index "$widths" " " $j)
height=$(index "$heights" " " $j)
offset=$(index "$offsets" " " $j)
if [ $offset -eq $start ]
then
ordered_widths="$ordered_widths $width"
ordered_heights="$ordered_heights $height"
ordered_offsets="$ordered_offsets $offset"
start=`expr $start + $width`
fi
done
done
widths=$ordered_widths
heights=$ordered_heights
offsets=$ordered_offsets
# store the windows maximized/fullscreen state information and undo all of it
pattern='horz|vert|full'
window_id=`xdotool getactivewindow`
window_states=`xprop -id $window_id _NET_WM_STATE | sed 's/,//g' | cut -d ' ' -f3-`
remember_states=""
for state in $window_states
do
#remove _NET_WM_STATE_ prefix
state=`echo $state | sed -r 's/^.{14}//' | awk '{print tolower($0)}'`
#echo $w
if [[ $state =~ $pattern ]]
then
wmctrl -ir $window_id -b remove,$state
remember_states="$remember_states $state"
fi
done
# get position of upper-left corner
specs=`xwininfo -id $window_id`
x=`echo "$specs" | awk '/Absolute upper-left X:/ { print $4 }'`
y=`echo "$specs" | awk '/Absolute upper-left Y:/ { print $4 }'`
window_width=`echo "$specs" | awk '/Width:/ { print $2 }'`
window_height=`echo "$specs" | awk '/Height:/ { print $2 }'`
# get the current monitor of the window, indexed from 1
current_monitor=0
for i in $(seq 1 $monitor_count)
do
width=$(index "$widths" " " $i)
start=$(index "$offsets" " " $i)
end=`expr $start + $width`
if [ $x -ge $start ] && [ $x -lt $end ]
then
current_monitor=$i
fi
done
# remember, monitors are indexed from 1, not 0, so this works
shift_by=1
numre='^-?[0-9]+$'
if [ $# -gt 0 ] && [[ $1 =~ $nume ]]; then shift_by=$1; fi
next_monitor=`expr $current_monitor + $shift_by`
((next_monitor--))
next_monitor=`expr $next_monitor % $monitor_count`
while [ $next_monitor -lt 0 ] # since expr's modulus can give negative results
do
next_monitor=`expr $next_monitor + $monitor_count`
done
((next_monitor++))
echo $current_monitor
echo $next_monitor
# compute new absolute x,y position based on relative positions and offsets
current_offset=$(index "$offsets" " " $current_monitor)
next_offset=$(index "$offsets" " " $next_monitor)
current_width=$(index "$widths" " " $current_monitor)
current_height=$(index "$heights" " " $current_monitor)
next_width=$(index "$widths" " " $next_monitor)
next_height=$(index "$heights" " " $next_monitor)
x_rel=`expr $x - $current_offset`
new_x=`expr $x_rel + $next_offset`
resize=0
if [ $next_width -lt $window_width ]
then
resize=1
window_width=`expr $next_width - 30`
fi
if [ $next_height -lt $window_height ]
then
window_height=`expr $next_height - 30`
resize=1
fi
if [ $resize -eq 1 ]; then xdotool windowsize $window_id $window_width $window_height; fi
# move the window to the same relative x,y position in the other monitor
xdotool windowmove $window_id $new_x $y
# restore maximized/fullscreen state
for w in $remember_states
do
wmctrl -ir $window_id -b add,$w
done
exit