How to reload Awesome and preserve layout

Sometimes you may need to reload awesome to apply a new config, and that resets all your tags configuration state such as layouts, mwfacts, and other things. Here I will show you how to preserve all that state.

First we need a table serialization function for Lua, like this. Download it and save to a file table-serialization.lua to a directory where your rc.lua is located (typically, ~/.config/awesome), then add to your rc.lua:

require('./table-serialization')

Then we need indexof function:

function table.indexof(t, needle)
  for k, v in pairs(t) do
    if v == needle then
      return k
    end
  end
  return -1
end

Again, save it to table-indexof.lua and load in rc.lua:

require('./table-indexof')

Then write a custom restart function that will dump tags state to a temporary file before restart, let's call it smart_restart:

local my_state_file = awful.util.get_cache_dir() .. "/state"

local function save_state()
  local screen = mouse.screen
  local tags = awful.tag.gettags(screen)

  local params = {}

  for i, t in ipairs(tags) do
    table.insert(params, {
      i,
      table.indexof(mytags.layout, t.layout),
      awful.tag.getncol(t),
      awful.tag.getmwfact(t),
      awful.tag.getnmaster(t)
    })
  end

  table.save(params, my_state_file)
end

local function smart_restart()
  save_state()
  awesome.restart()
end

Bind it to your restart shortcut instead of the default restart callback:

awful.key({ modkey, "Control" }, "r", smart_restart,
              {description = "reload awesome", group = "awesome"}),

Ok, the saving part is done, now we need to load these saved parameters on startup and delete the temporary file. Write a function for that:

local function restore_state()
  if posix.stat(my_state_file) ~= nil then
    local params = table.load(my_state_file)
    os.remove(my_state_file)

    local s = awful.screen.focused()
    for j, p in ipairs(params) do
      local i = p[1]
      local layout = p[2] -- index of layout in mytags.layout table
      local ncol = p[3]
      local mwfact = p[4]
      local nmaster = p[5]

      local t = s.tags[i]
      t.layout = mytags.layout[layout]

      awful.tag.setncol(ncol, t)
      awful.tag.setmwfact(mwfact, t)
      awful.tag.setnmaster(nmaster, t)
    end
  end
end

Add a signal callback to call this function after startup:

awesome.connect_signal("startup", function()
  restore_state()
end)

Tested on awesome 4.2.

P.S. I use luaposix for posix.stat, you can use it too or just write a custom function that checks whether a file exists.

If you have any comments, contact me by email.
powered by OpenBSD
© ch1p 2021