diff --git a/docs/17-porting-tips.md b/docs/17-porting-tips.md new file mode 100644 index 000000000..ede354c2e --- /dev/null +++ b/docs/17-porting-tips.md @@ -0,0 +1,341 @@ +# Porting tips + +## 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 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 + -- 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 + 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" } }, + + diff --git a/docs/89-NEWS.md b/docs/89-NEWS.md index a1ea00fec..2d536718c 100644 --- a/docs/89-NEWS.md +++ b/docs/89-NEWS.md @@ -532,6 +532,8 @@ Many changes now cause a deprecation warning instead of breaking hard. However, it is important to take note of these changes in order to avoid new bugs. +Also see the porting tips + ### There can be off-screen clients unless rc.lua is adapted diff --git a/docs/config.ld b/docs/config.ld index 829501106..d8399f1f6 100644 --- a/docs/config.ld +++ b/docs/config.ld @@ -24,6 +24,7 @@ topics={ '05-awesomerc.md', '06-appearance.md', '16-using-cairo.md', + '17-porting-tips.md', '90-FAQ.md', '89-NEWS.md', }