How to reload Awesome and preserve layout

Sometimes you may need to reload awesome to apply new config, and that resets all your tags configuration state such as layouts, mwfacts and other. I will show 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 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 2019