aboutsummaryrefslogtreecommitdiff
path: root/scripts/monitor-to-monitor.nix
blob: fa039168044b66ac0191bd7c7b806dd8df0c8f35 (plain)
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
{ pkgs, ... }:

let
  name = "m2m";
in
pkgs.writeShellScriptBin name ''
  #
  # Move the current window to the next monitor.
  #
  # Also works only on one X screen (which is the most common case).
  #
  # Props to
  # http://icyrock.com/blog/2012/05/xubuntu-moving-windows-between-monitors/
  #
  # Unfortunately, both "xdotool getwindowgeometry --shell $window_id" and
  # checking "-geometry" of "xwininfo -id $window_id" are not sufficient, as
  # the first command does not respect panel/decoration offsets and the second
  # will sometimes give a "-0-0" geometry. This is why we resort to "xwininfo".

  screen_width=$(xdpyinfo | awk '/dimensions:/ { print $2; exit }' | cut -d"x" -f1)
  screen_height=$(xdpyinfo | awk '/dimensions:/ { print $2; exit }' | cut -d"x" -f2)
  display_width=$(xdotool getdisplaygeometry | cut -d" " -f1)
  display_height=$(xdotool getdisplaygeometry | cut -d" " -f2)
  window_id=$(xdotool getactivewindow)

  # Remember if it was maximized.
  window_horz_maxed=$(xprop -id "$window_id" _NET_WM_STATE | grep '_NET_WM_STATE_MAXIMIZED_HORZ')
  window_vert_maxed=$(xprop -id "$window_id" _NET_WM_STATE | grep '_NET_WM_STATE_MAXIMIZED_VERT')

  # Un-maximize current window so that we can move it
  wmctrl -ir "$window_id" -b remove,maximized_vert,maximized_horz

  # Read window position
  x=$(xwininfo -id "$window_id" | awk '/Absolute upper-left X:/ { print $4 }')
  y=$(xwininfo -id "$window_id" | awk '/Absolute upper-left Y:/ { print $4 }')

  # Subtract any offsets caused by panels or window decorations
  x_offset=$(xwininfo -id "$window_id" | awk '/Relative upper-left X:/ { print $4 }')
  y_offset=$(xwininfo -id "$window_id" | awk '/Relative upper-left Y:/ { print $4 }')
  x=$(( x - x_offset))
  y=$(( y - y_offset))

  # Compute new X position
  new_x=$((x + display_width))
  # Compute new Y position
  new_y=$((y + display_height))

  # If we would move off the right-most monitor, we set it to the left one.
  # We also respect the window's width here: moving a window off more than half its width won't happen.
  width=$(xdotool getwindowgeometry "$window_id" | awk '/Geometry:/ { print $2 }'|cut -d"x" -f1)
  if [ "$(( new_x + width / 2))" -gt "$screen_width" ]; then
      new_x=$((new_x - screen_width))
  fi

  height=$(xdotool getwindowgeometry "$window_id" | awk '/Geometry:/ { print $2 }'|cut -d"x" -f2)
  if [ "$((new_y + height / 2))" -gt "$screen_height" ]; then
      new_y=$((new_y - screen_height))
  fi

  # Don't move off the left side.
  if [ "$new_x" -lt 0 ]; then
      new_x=0
  fi

  # Don't move off the bottom
  if [ "$new_y" -lt 0 ]; then
      new_y=0
  fi

  # Move the window
  xdotool windowmove "$window_id" "$new_x" "$new_y"

  # Maximize window again, if it was before
  if [ -n "''${window_horz_maxed}" ] && [ -n "''${window_vert_maxed}" ]; then
      wmctrl -ir "$window_id" -b add,maximized_vert,maximized_horz
  elif [ -n  "''${window_horz_maxed}" ]; then
      wmctrl -ir "$window_id" -b add,maximized_horz
  elif [ -n  "''${window_vert_maxed}" ]; then
      wmctrl -ir "$window_id" -b add,maximized_vert
  fi
''