From 898077f8725ac4217388b50be4f42beb608b2a49 Mon Sep 17 00:00:00 2001 From: Vidar Hokstad Date: Thu, 25 Jan 2024 06:00:25 +0000 Subject: [PATCH] Externalize config. --- config.yml | 18 +++++++++++++++ rubywm.rb | 8 ++++++- wm.rb | 66 ++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 69 insertions(+), 23 deletions(-) create mode 100644 config.yml diff --git a/config.yml b/config.yml new file mode 100644 index 0000000..8f3da0c --- /dev/null +++ b/config.yml @@ -0,0 +1,18 @@ + +# Default layout is tiled. +# Desktops are numbered from 1, matching user-visible labelling rather than +# the internal array. + +desktops: + number: 10 # Default + + 2: + nodes: + - iclass: "todo-todo" + - dir: tb + nodes: + - iclass: "todo-done" + - iclass: "todo-note" + 10: + layout: floating + diff --git a/rubywm.rb b/rubywm.rb index 9005352..3c10bef 100644 --- a/rubywm.rb +++ b/rubywm.rb @@ -10,6 +10,7 @@ require 'bundler/setup' require 'X11' require 'set' +require 'yaml' require_relative 'window.rb' require_relative 'wm.rb' @@ -28,8 +29,13 @@ if ARGV.shift == "--debug" end end +# FIXME: This is only the first step towards splitting out config. +# E.g. honor a config flag and/or XDG, but for now I'm just migrating +# the config out of the WindowManager class. +config = YAML.load_file(__dir__ + "/config.yml", symbolize_names: true) + dpy = X11::Display.new -$wm = WindowManager.new(dpy, num_desktops: 10) +$wm = WindowManager.new(dpy, config) # FIXME: This can also go into the WindowManager class diff --git a/wm.rb b/wm.rb index 04fa8b3..d4d651e 100644 --- a/wm.rb +++ b/wm.rb @@ -6,7 +6,7 @@ class WindowManager def inspect = "" - def initialize dpy, num_desktops: 10 + def initialize dpy, config @dpy = dpy @windows = {} @@ -14,28 +14,10 @@ class WindowManager @border_focus = 0xffff66ff @floating = FloatingLayout.new(rootgeom) - - @desktops ||= num_desktops.times.map do |num| - Desktop.new(self, num, name: (num+1).to_s[-1]) - end - - # FIXME: Config - (0..8).each do |i| - desktops[i].layout = TiledLayout.new(desktops[i], rootgeom) - end - # FIXME: Config - # FIXME: Improved way of specifying pre-designed layouts. - r = desktops[1].layout.root - r.ratio = 0.5 - r.nodes[0] = Leaf.new(iclass: "todo-todo") - r.nodes[1] = Node.new([ - Leaf.new(iclass: "todo-done"), - Leaf.new(iclass: "todo-note")], - dir: :tb - ) - - change_property(:_NET_NUMBER_OF_DESKTOPS, :cardinal, num_desktops) + process_config(config) + + change_property(:_NET_NUMBER_OF_DESKTOPS, :cardinal, @desktops.count) mask = X11::Form::ButtonPressMask|X11::Form::ButtonReleaseMask|X11::Form::PointerMotionMask root.grab_button(true, mask, :async, :async, 0, 0, 1, X11::Form::Mod3) @@ -65,6 +47,46 @@ class WindowManager end + def process_node_child(spec, n) + if spec[:type] != :node && !spec[:nodes] + return Leaf.new(iclass: spec[:iclass], parent: n) + end + cur = Node.new(parent: n) + process_node_config(cur, spec, n) + return cur + end + + def process_node_config(n, spec, parent=nil) + n.ratio = spec[:ratio] if spec&.dig(:ratio) + n.dir = spec[:dir].to_sym if spec&.dig(:dir) + Array(spec&.dig(:nodes)).each do |sub| + n.nodes << process_node_child(sub, n) + end + end + + # FIXME: I'm not particlarly happy about building this in. + # I prefer the bspwm approach of externalising it, because + # I need/want an API to change it dynamically anyway, so + # this is likely to change. + def process_config(config) + num_desktops = config.dig(:desktops, :number) || 10 + @desktops ||= num_desktops.times.map do |num| + c = config.dig(:desktops, num+1) + name = c&.dig(:name) || (num+1).to_s + Desktop.new(self, num, name).tap do |d| + if c&.dig(:layout) == "floating" + # FIXME: Should be ok to set this to @floating + # but some logic checks for a nil layout + d.layout = nil + else + d.layout = TiledLayout.new(d, rootgeom) + process_node_config(d.layout.root,c) + end + end + end + end + + def change_property(atom, type, data, mode: :replace, format: 32) root.change_property(mode, atom, type, format, Array(data).pack("V*").unpack("C*")) end