My goal is to automatically start a few programs on specific tags when awesome first runs, e.g. starting Chromium on screen 1, tag 1; starting gVim on screen 2, tag 1. I've found a few places online that advocate using the following function:
function spawn_once(command, class, tag)
-- create move callback
local callback
callback = function(c)
if c.class == class then
awful.client.movetotag(tag, c)
client.remove_signal("manage", callback)
end
end
client.add_signal("manage", callback)
-- now check if not already running!
local findme = command
local firstspace = findme:find(" ")
if firstspace then
findme = findme:sub(0, firstspace-1)
end
-- finally run it
awful.util.spawn_with_shell("pgrep -u $USER -x " .. findme .. " > /dev/null || (" .. command .. ")")
end
spawn_once("chromium", "Chromium", root.tags()[2][1])
spawn_once("gvim", "gVim", root.tags()[1][2])
Unfortunately, the function doesn't work on newer versions of awesome. No matter what tag I choose or minor update to the function I make, it places the program on the first tag. See comments: https://gist.github.com/Flowkap/8858434
Doesn't work properly. Same as dvd001. So the programs run at tag 1 regardless of the specified tag.
How would I go about accomplishing this in the newer versions of awesome (v4.2+)?
Here is my rc.lua
:
-- libraries
local naughty = require("naughty")
local gears = require("gears")
local beautiful = require("beautiful")
local awful = require("awful")
require("awful.autofocus")
local wibox = require("wibox")
-- errors
if awesome.startup_errors then
naughty.notify({
preset = naughty.config.presets.critical,
title = "Startup errors",
text = awesome.startup_errors})
end
do
local in_error = false
awesome.connect_signal("debug::error", function (err)
if in_error then return end
in_error = true
naughty.notify({preset = naughty.config.presets.critical,
title = "Error",
text = tostring(err)})
in_error = false
end)
end
-- variables
local modkey = "Mod4"
local terminal = "xterm"
-- layouts
awful.layout.layouts = {
awful.layout.suit.tile.left,
awful.layout.suit.max,
awful.layout.suit.floating,
}
-- helper functions
local function client_menu_toggle_fn()
local instance = nil
return function ()
if instance and instance.wibox.visible then
instance:hide()
instance = nil
else
instance = awful.menu.clients({theme = {width = 250}})
end
end
end
local function set_wallpaper(s)
if beautiful.wallpaper then
local wallpaper = beautiful.wallpaper
if type(wallpaper) == "function" then
wallpaper = wallpaper(s)
end
gears.wallpaper.maximized(wallpaper, s, true)
end
end
-- init theme
beautiful.init(gears.filesystem.get_configuration_dir() .. "themes/shane/theme.lua")
-- change wallpaper on screen resize
screen.connect_signal("property::geometry", set_wallpaper)
-- tag buttons
local tag_buttons = gears.table.join(
awful.button({}, 1, function (t) t:view_only() end),
awful.button({modkey}, 1, function (t)
if client.focus then
client.focus:move_to_tag(t)
end
end),
awful.button({}, 3, function (t)
if client.focus then
client.focus:toggle_tag(t)
end
end),
awful.button({}, 4, function (t) awful.tag.viewnext(t.screen) end),
awful.button({}, 5, function (t) awful.tag.viewprev(t.screen) end)
)
-- task buttons
local task_buttons = gears.table.join(
awful.button({}, 1, function (c)
if c == client.focus then
c.minimized = true
else
c.minimized = false
if not c:isvisible() and c.first_tag then
c.first_tag:view_only()
end
client.focus = c
c:raise()
end
end),
awful.button({}, 3, client_menu_toggle_fn()),
awful.button({}, 4, function ()
awful.client.focus.byidx(1)
end),
awful.button({}, 5, function ()
awful.client.focus.byidx(-1)
end)
)
-- create clock
clock = wibox.widget.textclock(" %A, %B %d %l:%M%p ")
-- init screen
awful.screen.connect_for_each_screen(function (s)
-- set wallpaper
set_wallpaper(s)
-- create tags
if (s.index == 1) then
awful.tag({" 1. Browser ", " 2. Database ", " 3. Files ", " 4. Break ", " 5. Music ", " 6. Misc "},
s, awful.layout.layouts[1])
else
awful.tag({" 1. Terminal ", " 2. Edit ", " 3. Passwords ", " 4. Misc "}, s, awful.layout.layouts[1])
end
-- create tag list
s.taglist = awful.widget.taglist(s, awful.widget.taglist.filter.all, tag_buttons)
-- create prompt
s.prompt = awful.widget.prompt({prompt = " Run: ", prompt_fg = "#f0f"})
-- create tasks
s.tasks = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, task_buttons)
-- create the main bar
s.bar = awful.wibar({position = "top", screen = s, height = 32})
s.bar:setup {
layout = wibox.layout.align.horizontal,
{ layout = wibox.layout.fixed.horizontal,
s.taglist,
s.prompt },
{ layout = wibox.layout.fixed.horizontal },
{ layout = wibox.layout.fixed.horizontal,
clock },
}
-- task bar
s.taskbar = awful.wibar({position = "bottom", screen = s, height = 32})
s.taskbar:setup {
layout = wibox.layout.align.horizontal,
s.tasks,
}
end)
-- startup programs
function spawn_once(command, class, tag)
-- create move callback
local callback
callback = function(c)
if c.class == class then
awful.client.movetotag(tag, c)
client.remove_signal("manage", callback)
end
end
client.add_signal("manage", callback)
-- now check if not already running!
local findme = command
local firstspace = findme:find(" ")
if firstspace then
findme = findme:sub(0, firstspace-1)
end
-- finally run it
awful.util.spawn_with_shell("pgrep -u $USER -x " .. findme .. " > /dev/null || (" .. command .. ")")
end
spawn_once("chromium", "Chromium", screen[1].tags[1])
spawn_once("gvim", "gVim", screen[2].tags[2])
-- keybindings
keybindings = gears.table.join(
awful.key({modkey, "Shift"}, "q", awesome.quit,
{description = "quit awesome", group = "awesome"}),
awful.key({modkey, "Shift"}, "r", awesome.restart,
{description = "restart awesome", group = "awesome"}),
awful.key({modkey}, "r", function () awful.screen.focused().prompt:run() end,
{description = "run prompt", group = "launcher"}),
awful.key({modkey}, "Left", awful.tag.viewprev,
{description = "previous tag", group = "tag"}),
awful.key({modkey}, "Right", awful.tag.viewnext,
{description = "next tag", group = "tag"}),
awful.key({modkey}, "j", function () awful.client.focus.byidx(1) end,
{description = "focus next window", group = "client"}),
awful.key({modkey}, "k", function () awful.client.focus.byidx(-1) end,
{description = "focus previous window", group = "client"}),
awful.key({modkey, "Shift"}, "j", function () awful.client.swap.byidx(1) end,
{description = "swap with next client", group = "client"}),
awful.key({modkey, "Shift"}, "k", function () awful.client.swap.byidx(-1) end,
{description = "swap with previous client", group = "client"}),
awful.key({modkey, "Control"}, "j", function () awful.screen.focus_relative(1) end,
{description = "focus next screen", group = "screen"}),
awful.key({modkey, "Control"}, "k", function () awful.screen.focus_relative(-1) end,
{description = "focus previous screen", group = "screen"}),
awful.key({modkey}, "Tab", function ()
awful.client.focus.history.previous()
if client.focus then client.focus:raise() end end,
{description = "focus last client", group = "client"}),
awful.key({modkey}, "Return", function () awful.spawn(terminal) end,
{description = "open a terminal", group = "launcher"}),
awful.key({modkey}, "l", function () awful.tag.incmwfact(0.05) end,
{description = "increase master width", group = "layout"}),
awful.key({modkey}, "h", function () awful.tag.incmwfact(-0.05) end,
{description = "decrease master width", group = "layout"}),
awful.key({modkey, "Shift"}, "h", function () awful.tag.incnmaster(1, nil, true) end,
{description = "increase number of master clients", group = "layout"}),
awful.key({modkey, "Shift"}, "l", function () awful.tag.incnmaster(-1, nil, true) end,
{description = "decrease number of master clients", group = "layout"}),
awful.key({modkey, "Control"}, "h", function () awful.tag.incncol(1, nil, true) end,
{description = "increase number of columns", group = "layout"}),
awful.key({modkey, "Control"}, "l", function () awful.tag.incncol(-1, nil, true) end,
{description = "decrease number of columns", group = "layout"}),
awful.key({modkey}, "space", function () awful.layout.inc(1) end,
{description = "next layout", group = "layout"}),
awful.key({modkey, "Shift"}, "space", function () awful.layout.inc(-1) end,
{description = "previous layout", group = "layout"}),
awful.key({modkey}, "c", function () awful.spawn("chromium") end,
{description = "start chrome", group = "launcher"}),
awful.key({modkey}, "v", function () awful.spawn("gvim") end,
{description = "start gvim", group = "launcher"}),
awful.key({}, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 2 +2%", false) end,
{description = "raise volume", group = "launcher"}),
awful.key({}, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 2 -2%", false) end,
{description = "lower volume", group = "launcher"}),
awful.key({}, "XF86AudioPlay", function () awful.spawn("lollypop -t", false) end,
{description = "play track", group = "launcher"}),
awful.key({}, "XF86AudioPause", function () awful.spawn("lollypop -t", false) end,
{description = "pause track", group = "launcher"}),
awful.key({}, "XF86AudioNext", function () awful.spawn("lollypop -n", false) end,
{description = "next track", group = "launcher"}),
awful.key({}, "XF86AudioPrev", function () awful.spawn("lollypop -p", false) end,
{description = "previous track", group = "launcher"})
)
-- bind numbers to tags
for i = 1, 9 do
keybindings = gears.table.join(keybindings,
awful.key({modkey}, "#" .. i + 9,
function ()
local screen = awful.screen.focused()
local tag = screen.tags[i]
if tag then
tag:view_only()
end
end, {description = "view tag #" .. i, group = "tag"}),
awful.key({modkey, "Control"}, "#" .. i + 9,
function ()
local screen = awful.screen.focused()
local tag = screen.tags[i]
if tag then
awful.tag.viewtoggle(tag)
end
end, {description = "toggle tag #" .. i, group = "tag"}),
awful.key({modkey, "Shift"}, "#" .. i + 9,
function ()
if client.focus then
local tag = client.focus.screen.tags[i]
if tag then
client.focus:move_to_tag(tag)
end
end
end, {description = "move focused client to tag #" .. i, group = "tag"}),
awful.key({modkey, "Control", "Shift"}, "#" .. i + 9,
function ()
if client.focus then
local tag = client.focus.screen.tags[i]
if tag then
client.focus:toggle_tag(tag)
end
end
end, {description = "toggle focused client on tag #" .. i, group = "tag"})
)
end
root.keys(keybindings)
-- client keys
client_keybindings = gears.table.join(
awful.key({modkey, "Shift"}, "c", function (c) c:kill() end,
{description = "close", group = "client"}),
awful.key({modkey}, "m", function (c)
c.maximized = not c.maximized
c:raise()
end, {description = "toggle maximized", group = "client"})
)
-- client buttons
client_buttons = gears.table.join(
awful.button({}, 1, function (c) client.focus = c; c:raise() end),
awful.button({modkey}, 1, awful.mouse.client.move),
awful.button({modkey}, 3, awful.mouse.client.resize)
)
-- client rules
awful.rules.rules = {
{
rule = {},
properties = {
border_width = beautiful.border_width,
border_color = beautiful.border_normal,
focus = awful.client.focus.filter,
raise = true,
keys = client_keybindings,
buttons = client_buttons,
screen = awful.screen.preferred,
placement = awful.placement.no_overlap+awful.placement.no_offscreen,
size_hints_honor = false
}
}
}
-- signals
client.connect_signal("manage", function (c)
if awesome.startup
and not c.size_hints.user_position
and not c.size_hints.program_position then
awful.placement.no_offscreen(c)
end
end)
One more alternative here is to use the xproperties and startup notification backed spawn
commands.
First, you need to register an xproperty
[1]. After that you write a function that loop across the running clients and check if your property is set on them. If it isn't you use the second argument of the awful.spawn
to set your magic token. Please note that you can also add an awful.rules
source to address the problem when restarting Awesome and setting the tag based on the magical token[2].
For this solution, you need to use Awesome v4.3+ and apply this hack:
Force applications to support the startup notifications
[1] https://awesomewm.org/apidoc/classes/client.html#awful.client.property.persist
[2] https://awesomewm.org/apidoc/libraries/awful.rules.html#add_rule_source