Tweaking my desktop seems to be my preferred form of procrastination. So, a blog like this is a sure sign I have too much work on my plate.

I have a laptop. I carry it to work and plug it into a large monitor - where I like to keep all my instant or near-instant communications displayed at all times while I switch between workspaces on my smaller laptop screen as I move from email (workspace one), to shell (workspace two), to web (workspace three), etc.

When I'm not at the office, I only have my laptop screen - which has to accomdate everything.

I soon got tired of dragging things around everytime I plugged or unplugged the monitor and starting accumulating a mess of bash scripts running wmctrl and even calling my own python-wnck script. (At first I couldn't get wmctrl to pin a window but I lived with it. But when gajim switched to gtk3 and my openbox window decorations disappeared, then I couldn't even pin my window manually.)

Now I have the following simpler setup.

Manage hot plugging of my monitor.

Symlink to my monitor status device:

0 jamie@turkey:~$ ls -l ~/.config/turkey/monitor.status 
lrwxrwxrwx 1 jamie jamie 64 Jan 15 15:26 /home/jamie/.config/turkey/monitor.status -> /sys/devices/pci0000:00/0000:00:02.0/drm/card0/card0-DP-1/status
0 jamie@turkey:~$ 

Create a udev rule to place my monitor to the right of my LCD every time the monitor is plugged in and every time it is unplugged.

0 jamie@turkey:~$ cat /etc/udev/rules.d/90-vga.rules 
# When a monitor is plugged in, adjust my display to take advantage of it
ACTION=="change", SUBSYSTEM=="drm", ENV{HOTPLUG}=="1", RUN+="/etc/udev/scripts/vga-adjust"
0 jamie@turkey:~$ 

And here is the udev script:

0 jamie@turkey:~$ cat /etc/udev/scripts/vga-adjust 
#!/bin/bash

logger -t "jamie-udev" "Monitor event detected, waiting 1 second for system to detect change."

# We don't know whether the VGA monitor is being plugged in or unplugged so we
# have to autodetect first. And,it takes a few seconds to assess whether the
# monitor is there or not, so sleep for 1 second.
sleep 1 
monitor_status="/home/jamie/.config/turkey/monitor.status"
status=$(cat "$monitor_status")  

XAUTHORITY=/home/jamie/.Xauthority
if [ "$status" = "disconnected" ]; then
  # The monitor is not plugged in   
  logger -t "jamie-udev" "Monitor is being unplugged"
  xrandr --output DP-1 --off
else
  logger -t "jamie-udev" "Monitor is being plugged in"
  xrandr --output DP-1 --right-of eDP-1 --auto
fi  
0 jamie@turkey:~$

Move windows into place.

So far, this handles ensuring the monitor is activated and placed in the right position. But, nothing has changed in my workspace.

Here's where the devilspie2 configuration comes in:

==> /home/jamie/.config/devilspie2/00-globals.lua <==
-- Collect some global varibles to be used throughout.
name = get_window_name();
app = get_application_name();
instance = get_class_instance_name();

-- See if the monitor is plugged in or not. If monitor is true, it is
-- plugged in, if it is false, it is not plugged in.
monitor = false;
device = "/home/jamie/.config/turkey/monitor.status"
f = io.open(device, "rb")
if f then
  -- Read the contents, remove the trailing line break.
  content = string.gsub(f:read "*all", "\n", "");
  if content == "connected" then
    monitor = true;
  end
end


==> /home/jamie/.config/devilspie2/gajim.lua <==
-- Look for my gajim message window. Pin it if we have the monitor.
if string.find(name, "Gajim: conversations.im") then
  if monitor then
    set_window_geometry(1931,31,590,1025);
    pin_window();
  else
    set_window_workspace(4);
    set_window_geometry(676,31,676,725);
    unpin_window();
  end
end

==> /home/jamie/.config/devilspie2/grunt.lua <==
-- grunt is the window I use to connect via irc. I typically connect to
-- grunt via a terminal called spade, which is opened using a-terminal-yoohoo
-- so that bell actions cause a notification. The window is called spade if I
-- just opened it but usually changes names to grunt after I connect via autossh
-- to grunt. 
--
-- If no monitor, put spade in workspace 2, if monitor, then pin it to all
-- workspaces and maximize it vertically.

if instance == "urxvt" then
  -- When we launch, the terminal is called spade, after we connect it
  -- seems to get changed to jamie@grunt or something like that.
  if name == "spade" or string.find(name, "grunt:") then
    if monitor then
      set_window_geometry(1365,10,570,1025);
      set_window_workspace(3);
      -- maximize_vertically();
      pin_window();
    else
      set_window_geometry(677,10,676,375);
      set_window_workspace(2);
      unpin_window();
    end
  end
end

==> /home/jamie/.config/devilspie2/terminals.lua <==
-- Note - these will typically only work after I start the terminals
-- for the first time because their names seem to change.
if instance == "urxvt" then
  if name == "heart" then
    set_window_geometry(0,10,676,375);
  elseif name == "spade" then
    set_window_geometry(677,10,676,375);
  elseif name == "diamond" then
    set_window_geometry(0,376,676,375);
  elseif name == "clover" then
    set_window_geometry(677,376,676,375);
  end
end

==> /home/jamie/.config/devilspie2/zimbra.lua <==
-- Look for my zimbra firefox window. Shows support queue.
if string.find(name, "Zimbra") then
  if monitor then
    unmaximize();
    set_window_geometry(2520,10,760,1022);
    pin_window();
  else
    set_window_workspace(5);
    set_window_geometry(0,10,676,375);
    -- Zimbra can take up the whole window on this workspace.
    maximize();
    unpin_window();
  end
end

And lastly, it is started (and restartd) with:

0 jamie@turkey:~$ cat ~/.config/systemd/user/devilspie2.service 
[Unit]
Description=Start devilspie2, program to place windows in the right locations.

[Service]
ExecStart=/usr/bin/devilspie2

[Install]
WantedBy=multi-user.target
0 jamie@turkey:~$ 

Which I have configured via a key combination that I hit everytime I plug in or unplug my monitor.