Winsetter

Winsetter revisited. This time with yaml-config file. Code is sort of.. shitty. But I wrote this yesterday (2024-08-12), and it’s still a test.

This is the yaml

---
windows:
  - name: Alacritty
    xpos: 0 # position the app
    ypos: 0
    width: 800 # resize the app
    height: 1031
    #set: ['SHADED'] # roll up the app
  - name: Firefox
    xpos: 804 # position the app
    ypos: 0
    width: 1112 # resize the app
    height: 1031
  - name: KeePassXc
    minimize: true # minimize the app

  - name: Cherrytree
    start: cherrytree # launch the app
    desktop: 1 # move the app to desktop 1

Here is the code

require 'yaml'
require 'open3'

# TODO: set CONF via ARGV.. let mwdo.yaml be default
CONF = 'some.yaml'

class Xdo
  attr_reader :origin

  def initialize
    @cmds = {
      active: 'xdotool getactivewindow',
      search: 'xdotool search --onlyvisible --limit 1 --class %s', # id
      move: 'xdotool windowmove --sync %s %s %s', # id x y
      size: 'xdotool windowsize --sync %s %s %s', # id width height
      focus: 'xdotool windowfocus --sync %s', # id
      minimize: 'xdotool windowminimize --sync %s', # id
      set_state: 'xdotool windowstate --add %s %s', # property id
      unset_state: 'xdotool windowstate --remove %s %s', # property id
      desktop: 'xdotool set_desktop_for_window %s %s', # id desktop
    }
    @origin = cmd(:active)
  end
  
  def cmd(name, *args)
    o, s = Open3.capture2(@cmds[name] % args)
    s.success? ? o.chop : nil
  end

  def restore = ( cmd(:focus, @origin))
end

xdo = Xdo.new

db = YAML.load(File.read(CONF)).to_h

db['windows'].each {|win|
  if win['start']
    pid = fork {`#{win['start']}`}
    Process.detach(pid)
    sleep 0.5 while !xdo.cmd(:search, win['name'])
  end
}

db['windows'].each {|win|
  id = xdo.cmd(:search, win['name'])

  if id
    xdo.cmd(:move, id, win['xpos'], win['ypos']) if (win['xpos'] && win['ypos'])
    xdo.cmd(:size, id, win['width'], win['height']) if (win['width'] && win['height'])
    xdo.cmd(:minimize, id) if win['minimize']
    xdo.cmd(:desktop, id, win['desktop']) if win['desktop']
    win['set'].each { xdo.cmd(:set_state, _1, id) } if win['set']
    win['unset'].each { xdo.cmd(:unset_state, _1, id) } if win['unset']
  end
  
}

xdo.restore

=begin
# name            used by xdotool search --class
# xpos, ypos      set position of window
# width, height   set width and height of window
# minimize: true  minimizes the window
# set: [PROPS]    set properties for the window
# unset: [PROPS]  unset properties for the window
# start str       starts the app str
# desktop #:      moves the window to desktop #
#
# Properties:
# STATES: MODAL STICKY MAXIMIZED_VERT MAXIMIZED_HORZ
# ABOVE BELOW SKIP_TASKBAR SKIP_PAGER FULLSCREEN
# HIDDEN SHADED DEMANS_ATTENTION
=end