16 KiB
Tips for upgrading your configuration
From 3.5 to 4.0
The
best advice is to start from the default rc.lua
and backport any changes
you might have added to your rc.lua
.
This avoids most of the possible errors due to missing important changes.
If you still wish to ignore this advice, first read the NEWS section about the breaking changes. This document assumes you did.
Be warned, even if it looks like it's working after changing some lines, it wont supports dynamic screen changes and will have many subtle bugs. The changes mentioned below are important for the stability of your window manager.
Here is a diff of the 3.5.9 rc.lua
with the 4.0 one. All changes due to
new features and new syntaxes have been removed. A -
in front of the line
correspond to content of the 3.5 rc.lua
and +
its replacement in 4.0.
This document does not cover the new features added in the Awesome 4 rc.lua
,
it only covers the minimal required changes to have a properly behaving config.
To test during the port, we recommend the Xephyr
X11 server.
If Awesome4 is not installed yet, we recommand to install it in its own prefix to avoid conflicts in case you wish to stay on 3.5 for a little longer:
cd path/to/awesome/code
mkdir -p $HOME/.config/awesome4
mkdir build -p
cd build
# Install in a local folder, this assumes all the dependencies are installed
cmake -DCMAKE_INSTALL_PREFIX=$HOME/awesome4_test ..
make -j4
# Use a copy of rc.lua to avoid it being overwritten accidentally
cp awesomerc.lua $HOME/.config/awesome4/rc.lua
make install
# Start Awesome in a 1280x800 window
Xephyr :1 -screen 1280x800 &
DISPLAY=:1 $HOME/awesome4_test/bin/awesome \
-c $HOME/.config/awesome4/rc.lua \
--search $HOME/awesome4_test/share/awesome/lib
If Awesome 4 is already installed, then backup your old rc.lua
and overwrite
~/.config/awesome/rc.lua
(replace this by another path if you use a custom
XDH config local directory). And only execute:
Xephyr :1 -screen 1280x800 &
DISPLAY=:1 awesome
Screens are now added and removed without reloading rc.lua
. The wallpaper are
now set in a signal callback.
--- {{{ Wallpaper
-if `beautiful.wallpaper` then
- for s = 1, screen.count() do
- `gears.wallpaper.maximized`(beautiful.wallpaper, s, true)
- end
-end
--- }}}
+local function set_wallpaper(s)
+ -- Wallpaper
+ if `beautiful.wallpaper` then
+ local wallpaper = `beautiful.wallpaper`
+ -- If wallpaper is a function, call it with the screen
+ if type(wallpaper) == "function" then
+ wallpaper = wallpaper(s)
+ end
+ `gears.wallpaper.maximized`(wallpaper, s, true)
+ end
+end
+
+-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
+`screen.connect_signal`("property::geometry", set_wallpaper)
Tags need to be created for each screens, the old static initialization cannot work. Remove this section.
--- {{{ Tags
--- Define a tag table which hold all screen tags.
-tags = {}
-for s = 1, `screen.count`() do
- -- Each screen has its own tag table.
- tags[s] = awful.tag({ 1, 2, 3, 4, 5, 6, 7, 8, 9 }, s, layouts[1])
- end
--- }}}
The quit
menu command must be wrapped in a function, otherwise an error
occurs due to mismatched argument types from the v4.0 awful.menu
library.
-- {{{ Menu
-- Create a laucher widget and a main menu
myawesomemenu = {
{ "manual", terminal .. " -e man awesome" },
{ "edit config", editor_cmd .. " " .. awesome.conffile },
{ "restart", awesome.restart },
- { "quit", awesome.quit }
+ { "quit", function() awesome.quit() end}
}
The textclock is now part of the wibox
library, rename it.
-- {{{ Wibar
-- Create a textclock widget
-mytextclock = `awful.widget.textclock`()
+mytextclock = `wibox.widget.textclock`()
Widgets were previously added to static global tables. This isn't going to behave correctly when screen are added and removed. Remove this section.
--- Create a wibox for each screen and add it
-mywibox = {}
-mypromptbox = {}
-mylayoutbox = {}
-mytaglist = {}
-mytasklist = {}
Many functions have been converted to methods. The old functions are deprecated, they are still supported, but will be removed in the next release.
-mytaglist.buttons = awful.util.table.join(
+local taglist_buttons = awful.util.table.join(
- awful.button({ }, 1, `awful.tag.viewonly`),
+ awful.button({ }, 1, function(t) t:`view_only`() end),
- awful.button({ modkey }, 1, `awful.client.movetotag`),
+ awful.button({ modkey }, 1, function(t)
+ if `client.focus` then
+ `client.focus:move_to_tag`(t)
+ end
+ end),
`awful.button`({ }, 3, `awful.tag.viewtoggle`),
- `awful.button`({ modkey }, 3, `awful.client.toggletag`),
+ `awful.button`({ modkey }, 3, function(t)
+ if client.focus then
+ client.focus:toggle_tag(t)
+ end
+ end),
- `awful.button`({ }, 4, function(t) `awful.tag.viewnext`(awful.tag.getscreen(t)) end),
- `awful.button`({ }, 5, function(t) `awful.tag.viewprev`(awful.tag.getscreen(t)) end)
+ `awful.button`({ }, 4, function(t) `awful.tag.viewnext`(t.screen) end),
+ `awful.button`({ }, 5, function(t) `awful.tag.viewprev`(t.screen) end)
)
-mytasklist.buttons = awful.util.table.join(
+local tasklist_buttons = awful.util.table.join(
awful.button({ }, 1, function (c)
if c == `client.focus` then
c.minimized = true
else
-- Without this, the following
-- :isvisible() makes no sense
c.minimized = false
- if not c:isvisible() then
- `awful.tag.viewonly`(c:tags()[1])
+ if not c:isvisible() and c.`first_tag` then
+ c.first_tag:view_only()
end
-- This will also un-minimize
-- the client, if needed
`client.focus` = c
c:raise()
end
end),
This section is very important. This is where adding and removing screens is
handled (including during startup). Note that the mysomething
table
previously removed are replaced by custom screens attributes.
-for s = 1, `screen.count`() do
+`awful.screen.connect_for_each_screen`(function(s)
+ -- Wallpaper
+ set_wallpaper(s)
+
+ -- Each screen has its own tag table.
+ awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[1])
+
-- Create a promptbox for each screen
- mypromptbox[s] = `awful.widget.prompt`()
+ s.mypromptbox = `awful.widget.prompt`()
-- Create an imagebox widget which will contains an icon indicating which layout we're using.
-- We need one layoutbox per screen.
- mylayoutbox[s] = `awful.widget.layoutbox`(s)
+ s.mylayoutbox = `awful.widget.layoutbox`(s)
- mylayoutbox[s]:buttons(`awful.util.table.join`(
+ s.mylayoutbox:buttons(`awful.util.table.join`(
`awful.button`({ }, 1, function () `awful.layout.inc`( 1) end),
`awful.button`({ }, 3, function () `awful.layout.inc`(-1) end),
`awful.button`({ }, 4, function () `awful.layout.inc`( 1) end),
`awful.button`({ }, 5, function () `awful.layout.inc`(-1) end)))
-- Create a taglist widget
- mytaglist[s] = `awful.widget.taglist`(s, `awful.widget.taglist.filter.all`, mytaglist.buttons)
+ s.mytaglist = `awful.widget.taglist`(s, `awful.widget.taglist.filter.all`, taglist_buttons)
-- Create a tasklist widget
- mytasklist[s] = `awful.widget.tasklist`(s, `awful.widget.tasklist.filter.currenttags`, mytasklist.buttons)
+ s.mytasklist = `awful.widget.tasklist`(s, `awful.widget.tasklist.filter.currenttags`, tasklist_buttons)
-- Create the wibox
- mywibox[s] = `awful.wibox`({ position = "top", screen = s })
+ s.mywibox = `awful.wibar`({ position = "top", screen = s })
-- Widgets that are aligned to the left
local left_layout = wibox.layout.fixed.horizontal()
- left_layout:add(mylauncher)
- left_layout:add(mytaglist[s])
- left_layout:add(mypromptbox[s])
+ left_layout:add(s.mytaglist)
+ left_layout:add(s.mypromptbox)
-- Widgets that are aligned to the right
local right_layout = wibox.layout.fixed.horizontal()
- if s == 1 then right_layout:add(wibox.widget.systray()) end
+ right_layout:add(wibox.widget.systray())
right_layout:add(mytextclock)
- right_layout:add(mylayoutbox[s])
+ right_layout:add(s.mylayoutbox)
-- Now bring it all together (with the tasklist in the middle)
local layout = wibox.layout.align.horizontal()
layout:set_left(left_layout)
- layout:set_middle(mytasklist[s])
+ layout:set_middle(s.mytasklist)
layout:set_right(right_layout)
- mywibox[s]:set_widget(layout)
+ s.mywibox:set_widget(layout)
end)
-- }}}
awful.util.spawn
is now called awful.spawn
.
-- Standard program
- `awful.key`({ modkey, }, "Return", function () `awful.util.spawn`(terminal) end),
+ `awful.key`({ modkey, }, "Return", function () `awful.spawn`(terminal) end),
Another dynamic screen related changes.
⠀-- Prompt
- awful.key({ modkey }, "r", function () mypromptbox[mouse.screen]:run() end),
+ awful.key({ modkey }, "r", function () `awful.screen.focused`().mypromptbox:run() end),
awful.prompt
now uses a more future proof arguments table instead of many
optional arguments.
⠀ awful.key({ modkey }, "x",
function ()
- `awful.prompt.run`({ prompt = "Run Lua code: " },
- mypromptbox[mouse.screen].widget,
- `awful.util.eval`, nil,
- `awful.util.getdir`("cache") .. "/history_eval")
- end),
+ awful.prompt.run {
+ prompt = "Run Lua code: ",
+ textbox = `awful.screen.focused`().mypromptbox.widget,
+ exe_callback = `awful.util.eval`,
+ history_path = `awful.util.get_cache_dir`() .. "/history_eval"
+ }
+ end),
Another function-to-method API change:
- `awful.key`({ modkey, }, "o", `awful.client.movetoscreen` ),
+ `awful.key`({ modkey, }, "o", function (c) c:`move_to_screen`() end),
The mod4+[1-9]
keybindings also have some changes related to deprecated
functions.
-- Bind all key numbers to tags.
-- Be careful: we use keycodes to make it works on any keyboard layout.
-- This should map on the top row of your keyboard, usually 1 to 9.
for i = 1, 9 do
-- View tag only.
awful.key({ modkey }, "#" .. i + 9,
function ()
- local screen = `mouse.screen`
- local tag = `awful.tag.gettags`(screen)[i]
+ local screen = `awful.screen.focused`()
+ local tag = `screen.tags`[i]
if tag then
- `awful.tag.viewonly`(tag)
+ `tag:view_only`()
end
end),
- -- Toggle tag.
+ -- Toggle tag display.
awful.key({ modkey, "Control" }, "#" .. i + 9,
function ()
- local screen = `mouse.screen`
- local tag = `awful.tag.gettags`(screen)[i]
+ local screen = `awful.screen.focused`()
+ local tag = `screen.tags`[i]
if tag then
`awful.tag.viewtoggle`(tag)
end
for i = 1, 9 do
awful.key({ modkey, "Shift" }, "#" .. i + 9,
function ()
if client.focus then
- local tag = `awful.tag.gettags`(client.focus.screen)[i]
+ local tag = `client.focus.screen.tags`[i]
if tag then
- `awful.client.movetotag`(tag)
+ `client.focus:move_to_tag`(tag)
end
end
end),
- -- Toggle tag.
+ -- Toggle tag on focused client.
awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
function ()
if client.focus then
- local tag = `awful.tag.gettags`(client.focus.screen)[i]
+ local tag = `client.focus.screen.tags`[i]
if tag then
- `awful.client.toggletag`(tag)
+ `client.focus:toggle_tag`(tag)
end
end
- end))
+ end),
+ )
end
The default rules need to be changed to avoid having offscreen clients:
awful.rules.rules = {
-- All clients will match this rule.
{ rule = { },
properties = { border_width = beautiful.border_width,
awful.rules.rules = {
focus = awful.client.focus.filter,
raise = true,
keys = clientkeys,
+ buttons = clientbuttons,
+ screen = `awful.screen.preferred`,
+ placement = `awful.placement.no_overlap`+`awful.placement.no_offscreen`
The tags
global table has been removed to support dynamic screens, you can
now access tags by name.
- -- properties = { tag = tags[1][2] } },
+ -- properties = { screen = 1, tag = "2" } },
If you need to get the current client object in global context, currently you can use
client.focus
for it. E.g., to mark/unmark the client:
- awful.client.mark()
+ client.focus.marked = true
- awful.client.unmark()
+ client.focus.marked = false