/awesome-copycats

Awesome WM themes

Primary LanguageLua

My Awesome Config

Literate programing, org-mode, and tangle make my awesome config

Run org-bable-tangle on this README.org file to get a compiled rc.lua.

imports

-- Standard awesome library
local gears = require("gears")
local awful = require("awful")
awful.rules = require("awful.rules")
require("awful.autofocus")

-- Widget and layout library
local wibox = require("wibox")

-- Theme handling library
local beautiful = require("beautiful")

-- Notification library
local naughty = require("naughty")
local menubar = require("menubar")

-- https://github.com/jorenheit/awesome_alttab
local alttab = require("alttab")

-- https://github.com/copycat-killer/lain
local lain      = require("lain")

local drop      = require("scratchdrop")

error handling

Check if awesome encountered an error during startup and fell back to another config (This code will only ever execute for the fallback config).

if awesome.startup_errors then
    naughty.notify({ preset = naughty.config.presets.critical,
                     title = "Oops, there were errors during startup!",
                     text = awesome.startup_errors })
end

-- Handle runtime errors after startup
do
    local in_error = false
    awesome.connect_signal("debug::error", function (err)
        -- Make sure we don'i go into an endless error loop
        if in_error then return end
        in_error = true

        naughty.notify({ preset = naughty.config.presets.critical,
                         title = "Oops, an error happened!",
                         text = err })
        in_error = false
    end)
end

autostart apps

turfed to .xinitrc where it belongs.

function run_once(cmd)
  findme = cmd
  firstspace = cmd:find(" ")
  if firstspace then
     findme = cmd:sub(0, firstspace-1)
  end
  awful.util.spawn_with_shell("pgrep -u $USER -x " .. findme .. " > /dev/null || (" .. cmd .. ")")
end

-- run_once("xterm")
-- run_once("xset r rate 200 30") -- cursor repeat speed
-- run_once("unclutter") -- BUG: the "--root" option causes problems with focus when switching desktop tags. https://github.com/awesomeWM/awesome/issues/202
-- run_once("sh /home/jhaus/bin/nasa_image_of_the_day.sh")  -- http://www.nasa.gov/rss/lg_image_of_the_day.rss

variables

-- localization
os.setlocale(os.getenv("LANG"))

-- common
modkey     = "Mod4"
altkey     = "Mod1"
terminal   = "urxvt" or "xterm" or "xfce4-terminal"
gterminal  = "gnome-terminal --hide-menubar"
eterminal  = "emacsclient -c -e \"(eshell \\\"new\\\")\""
editor = os.getenv("EDITOR") or "emacsclient"
editor_cmd = terminal .. " -e " .. editor
lock_srceen = "sxlock" or "xscreensaver-command -lock"

-- user defined
browser    = "firefox"
-- browser2   = "iron"
-- browser3   = "dwb"
gui_editor = "emacsclient"
graphics   = "gimp"
mail       = terminal .. " -e mutt "
iptraf     = terminal .. " -e sudo iptraf-ng -i all " -- " -g 180x54-20+34 -e sudo iptraf-ng -i all "
musicplr   = terminal .. " -e ncmpcpp " --" -g 130x34-320+16 -e ncmpcpp "

layouts

Table of layouts to cover with awful.layout.inc, order matters.

local layouts = {
--    awful.layout.suit.floating,
    awful.layout.suit.max,
--    awful.layout.suit.max.fullscreen,
    awful.layout.suit.tile,
--    awful.layout.suit.tile.left,
--    awful.layout.suit.tile.bottom,
--    awful.layout.suit.tile.top,
    awful.layout.suit.fair,
--    awful.layout.suit.fair.horizontal,
--    awful.layout.suit.spiral,
--    awful.layout.suit.spiral.dwindle,
    awful.layout.suit.magnifier
}
-- lain config
lain.layout.termfair.nmaster = 3
lain.layout.termfair.ncol    = 1
lain.layout.centerfair.nmaster = 3
lain.layout.centerfair.ncol = 1

local layouts = {
    awful.layout.suit.floating,
    lain.layout.uselesstile,
    -- lain.layout.cascadetile,
    -- lain.layout.uselessfair.vertical,
    -- lain.layout.centerwork,
    -- lain.layout.termfair,
    -- lain.layout.centerfair,
    --awful.layout.suit.max,
     awful.layout.suit.magnifier
}

appearance

-- beautiful init
 beautiful.init(os.getenv("HOME") .. "/.config/awesome/themes/powerarrow-darker/theme.lua")
-- theme_name = "powerarrow-darker" -- vinyl, zenburn, bamboo, arch, steamburn, niceandclean, wabbit
-- beautiful.init("/usr/share/awesome/themes/" .. theme_name .. "/theme.lua")

steamburn

copycatted from ok100_ [porting from dwm] Steamburn Awesome WM config 3.0 http://github.com/copycat-killer

.. image:: http://dotshare.it/public/images/uploads/648.png

-- beautiful init
beautiful.init(os.getenv("HOME") .. "/.config/awesome/themes/steamburn/theme.lua")


-- {{{ Wallpaper
if beautiful.wallpaper then
    for s = 1, screen.count() do
        gears.wallpaper.maximized(beautiful.wallpaper, s, true)
    end
end
-- }}}

-- {{{ Menu
mymainmenu = awful.menu.new({ items = require("menugen").build_menu(),
                              theme = { height = 16, width = 130 }})
-- }}}

-- {{{ Wibox
markup = lain.util.markup
gray   = "#94928F"

-- Textclock
mytextclock = awful.widget.textclock(" %H:%M ")

-- Calendar
lain.widgets.calendar:attach(mytextclock)

-- Mail IMAP check
mailwidget = lain.widgets.imap({
    timeout  = 180,
    server   = "server",
    mail     = "mail",
    password = "keyring get mail",
    settings = function()
        mail  = ""
        count = ""

        if mailcount > 0 then
            mail = "Mail "
            count = mailcount .. " "
        end

        widget:set_markup(markup(gray, mail) .. count)
    end
})

-- MPD
mpdwidget = lain.widgets.mpd({
    settings = function()
        artist = mpd_now.artist .. " "
        title  = mpd_now.title  .. " "

        if mpd_now.state == "pause" then
            artist = "mpd "
            title  = "paused "
        elseif mpd_now.state == "stop" then
            artist = ""
            title  = ""
        end

        widget:set_markup(markup(gray, artist) .. title)
    end
})

-- CPU
cpuwidget = lain.widgets.sysload({
    settings = function()
        widget:set_markup(markup(gray, " Cpu ") .. load_1 .. " ")
    end
})

-- MEM
memwidget = lain.widgets.mem({
    settings = function()
        widget:set_markup(markup(gray, " Mem ") .. mem_now.used .. " ")
    end
})

-- /home fs
fshomeupd = lain.widgets.fs({
    partition = "/home"
})

-- Battery
batwidget = lain.widgets.bat({
    settings = function()
        bat_perc = bat_now.perc
        if bat_perc == "N/A" then bat_perc = "Plug" end
        widget:set_markup(markup(gray, " Bat ") .. bat_perc .. " ")
    end
})

-- Net checker
netwidget = lain.widgets.net({
    settings = function()
        if net_now.state == "up" then net_state = "On"
        else net_state = "Off" end
        widget:set_markup(markup(gray, " Net ") .. net_state .. " ")
    end
})

-- ALSA volume
volumewidget = lain.widgets.alsa({
    settings = function()
        header = " Vol "
        vlevel  = volume_now.level

        if volume_now.status == "off" then
            vlevel = vlevel .. "M "
        else
            vlevel = vlevel .. " "
        end

        widget:set_markup(markup(gray, header) .. vlevel)
    end
})

-- Weather
yawn = lain.widgets.yawn(123456)

-- Separators
first = wibox.widget.textbox(markup.font("Tamsyn 4", " "))
spr = wibox.widget.textbox(' ')

-- Create a wibox for each screen and add it
mywibox = {}
mypromptbox = {}
txtlayoutbox = {}
mytaglist = {}
mytasklist = {}
mytaglist.buttons = awful.util.table.join(
                    awful.button({ }, 1, awful.tag.viewonly),
                    awful.button({ modkey }, 1, awful.client.movetotag),
                    awful.button({ }, 3, awful.tag.viewtoggle),
                    awful.button({ modkey }, 3, awful.client.toggletag),
                    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))
mytasklist.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])
                                                  end
                                                  -- This will also un-minimize
                                                  -- the client, if needed
                                                  client.focus = c
                                                  c:raise()
                                              end
                                          end),
                     awful.button({ }, 3, function ()
                                              if instance then
                                                  instance:hide()
                                                  instance = nil
                                              else
                                                  instance = awful.menu.clients({ width=250 })
                                              end
                                          end),
                     awful.button({ }, 4, function ()
                                              awful.client.focus.byidx(1)
                                              if client.focus then client.focus:raise() end
                                          end),
                     awful.button({ }, 5, function ()
                                              awful.client.focus.byidx(-1)
                                              if client.focus then client.focus:raise() end
                                          end))

-- Writes a string representation of the current layout in a textbox widget
function updatelayoutbox(layout, s)
    local screen = s or 1
    local txt_l = beautiful["layout_txt_" .. awful.layout.getname(awful.layout.get(screen))] or ""
    layout:set_text(txt_l)
end

for s = 1, screen.count() do
    -- Create a promptbox for each screen
    mypromptbox[s] = awful.widget.prompt()

    -- Create a textbox widget which will contains a short string representing the
    -- layout we're using.  We need one layoutbox per screen.
    txtlayoutbox[s] = wibox.widget.textbox(beautiful["layout_txt_" .. awful.layout.getname(awful.layout.get(s))])
    awful.tag.attached_connect_signal(s, "property::selected", function ()
        updatelayoutbox(txtlayoutbox[s], s)
    end)
    awful.tag.attached_connect_signal(s, "property::layout", function ()
        updatelayoutbox(txtlayoutbox[s], s)
    end)
    txtlayoutbox[s]:buttons(awful.util.table.join(
            awful.button({}, 1, function() awful.layout.inc(layouts, 1) end),
            awful.button({}, 3, function() awful.layout.inc(layouts, -1) end),
            awful.button({}, 4, function() awful.layout.inc(layouts, 1) end),
            awful.button({}, 5, function() awful.layout.inc(layouts, -1) end)))

    -- Create a taglist widget
    mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)

    -- Create a tasklist widget
    mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)

    -- Create the wibox
    mywibox[s] = awful.wibox({ position = "top", screen = s, height = 18 })

    -- Widgets that are aligned to the left
    local left_layout = wibox.layout.fixed.horizontal()
    left_layout:add(first)
    left_layout:add(mytaglist[s])
    left_layout:add(spr)
    left_layout:add(txtlayoutbox[s])
    left_layout:add(spr)
    left_layout:add(mypromptbox[s])

    -- 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(spr)
    right_layout:add(mpdwidget)
    --right_layout:add(mailwidget)
    right_layout:add(cpuwidget)
    right_layout:add(memwidget)
    right_layout:add(batwidget)
    right_layout:add(netwidget)
    right_layout:add(volumewidget)
    right_layout:add(mytextclock)

    -- 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_right(right_layout)

    mywibox[s]:set_widget(layout)
end
-- }}}

rainbow theme

.. image:: http://dotshare.it/public/images/uploads/606.png

Rainbow Awesome WM config 2.0 http://github.com/copycat-killer

-- beautiful init
beautiful.init(os.getenv("HOME") .. "/.config/awesome/themes/rainbow/theme.lua")


-- {{{ Wallpaper
if beautiful.wallpaper then
    for s = 1, screen.count() do
        gears.wallpaper.maximized(beautiful.wallpaper, s, true)
    end
end
-- }}}

-- {{{ Menu
mymainmenu = awful.menu.new({ items = require("menugen").build_menu(),
                              theme = { height = 16, width = 130 }})
-- }}}

-- {{{ Wibox
markup = lain.util.markup
white  = beautiful.fg_focus
gray   = beautiful.fg_normal

-- Textclock
mytextclock = awful.widget.textclock(markup.font("Tamsyn 3", " ") ..
                                     markup(white, " %H:%M "))

-- Calendar
lain.widgets.calendar:attach(mytextclock, { fg = beautiful.fg_focus })

--[[ Mail IMAP check
-- commented because it needs to be set before use
mailwidget = lain.widgets.imap({
    timeout  = 180,
    server   = "server",
    mail     = "mail",
    password = "keyring get mail",
    settings = function()
        mail_notification_preset.fg = white

        mail  = ""
        count = ""

        if mailcount > 0 then
            mail = "Mail "
            count = mailcount .. " "
        end

        widget:set_markup(markup(gray, mail) .. markup(white, count))
    end
})
]]

-- MPD
mpdwidget = lain.widgets.mpd({
    settings = function()
        mpd_notification_preset.fg = white

        artist = mpd_now.artist .. " "
        title  = mpd_now.title  .. " "

        if mpd_now.state == "pause" then
            artist = "mpd "
            title  = "paused "
        elseif mpd_now.state == "stop" then
            artist = ""
            title  = ""
        end

        widget:set_markup(markup(gray, artist) .. markup(white, title))
    end
})

-- /home fs
fshome = lain.widgets.fs({
    partition = "/home",
    settings  = function()
        fs_notification_preset.fg = white

        hdd = ""
        p   = ""

        if fs_now.used >= 90 then
            hdd = " Hdd "
            p   = fs_now.used .. " "
        end

        widget:set_markup(markup(gray, hdd) .. markup(white, p))
    end
})

-- ALSA volume bar
volume = lain.widgets.alsabar({ card = "0", ticks = true })
volmargin = wibox.layout.margin(volume.bar, 5, 8, 80)
volmargin:set_top(7)
volmargin:set_bottom(7)
volumewidget = wibox.widget.background(volmargin)
volumewidget:set_bgimage(beautiful.vol_bg)

-- Weather
yawn = lain.widgets.yawn(123456,
{
    settings = function()
        yawn_notification_preset.fg = white
    end
})

-- Separators
spr = wibox.widget.textbox(' ')
small_spr = wibox.widget.textbox('<span font="Tamsyn 4"> </span>')
med_spr = wibox.widget.textbox('<span font="Tamsyn 7"> </span>')

-- Create a wibox for each screen and add it
mywibox = {}
mypromptbox = {}
txtlayoutbox = {}
mytaglist = {}
mytasklist = {}
mytaglist.buttons = awful.util.table.join(
                    awful.button({ }, 1, awful.tag.viewonly),
                    awful.button({ modkey }, 1, awful.client.movetotag),
                    awful.button({ }, 3, awful.tag.viewtoggle),
                    awful.button({ modkey }, 3, awful.client.toggletag),
                    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))
mytasklist.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])
                                                  end
                                                  -- This will also un-minimize
                                                  -- the client, if needed
                                                  client.focus = c
                                                  c:raise()
                                              end
                                          end),
                     awful.button({ }, 3, function ()
                                              if instance then
                                                  instance:hide()
                                                  instance = nil
                                              else
                                                  instance = awful.menu.clients({ width=250 })
                                              end
                                          end),
                     awful.button({ }, 4, function ()
                                              awful.client.focus.byidx(1)
                                              if client.focus then client.focus:raise() end
                                          end),
                     awful.button({ }, 5, function ()
                                              awful.client.focus.byidx(-1)
                                              if client.focus then client.focus:raise() end
                                          end))

-- Writes a string representation of the current layout in a textbox widget
function updatelayoutbox(layout, s)
    local screen = s or 1
    local txt_l = beautiful["layout_txt_" .. awful.layout.getname(awful.layout.get(screen))] or ""
    layout:set_text(txt_l)
end

for s = 1, screen.count() do
    -- Create a promptbox for each screen
    mypromptbox[s] = awful.widget.prompt()

    -- Create a textbox widget which will contains a short string representing the
    -- layout we're using.  We need one layoutbox per screen.
    txtlayoutbox[s] = wibox.widget.textbox(beautiful["layout_txt_" .. awful.layout.getname(awful.layout.get(s))])
    awful.tag.attached_connect_signal(s, "property::selected", function ()
        updatelayoutbox(txtlayoutbox[s], s)
    end)
    awful.tag.attached_connect_signal(s, "property::layout", function ()
        updatelayoutbox(txtlayoutbox[s], s)
    end)
    txtlayoutbox[s]:buttons(awful.util.table.join(
            awful.button({}, 1, function() awful.layout.inc(layouts, 1) end),
            awful.button({}, 3, function() awful.layout.inc(layouts, -1) end),
            awful.button({}, 4, function() awful.layout.inc(layouts, 1) end),
            awful.button({}, 5, function() awful.layout.inc(layouts, -1) end)))

    -- Create a taglist widget
    mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)

    -- Create a tasklist widget
    mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)

    -- Create the wibox
    mywibox[s] = awful.wibox({ position = "top", screen = s, height = 18 })

    -- Widgets that are aligned to the left
    local left_layout = wibox.layout.fixed.horizontal()
    left_layout:add(small_spr)
    left_layout:add(mytaglist[s])
    left_layout:add(spr)
    left_layout:add(txtlayoutbox[s])
    left_layout:add(spr)
    left_layout:add(mypromptbox[s])

    -- 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(small_spr)
    right_layout:add(mpdwidget)
    --right_layout:add(mailwidget)
    right_layout:add(fshome)
    right_layout:add(med_spr)
    right_layout:add(volumewidget)
    right_layout:add(mytextclock)

    -- 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_right(right_layout)

    mywibox[s]:set_widget(layout)
end
-- }}}


powerarrow-darker theme

Powerarrow Darker Awesome WM config 2.0 http://github.com/copycat-killer

.. image:: http://dotshare.it/public/images/uploads/649.png

beautiful.init(os.getenv("HOME") .. "/.config/awesome/themes/powerarrow-darker/theme.lua")


-- {{{ Wallpaper
if beautiful.wallpaper then
    for s = 1, screen.count() do
        gears.wallpaper.maximized(beautiful.wallpaper, s, true)
    end
end
-- }}}

-- {{{ Menu
mymainmenu = awful.menu.new({ items = require("menugen").build_menu(),
                              theme = { height = 16, width = 130 }})
-- }}}

-- {{{ Wibox
markup = lain.util.markup
separators = lain.util.separators

-- Textclock
clockicon = wibox.widget.imagebox(beautiful.widget_clock)
mytextclock = awful.widget.textclock(" %a %d %b  %H:%M")

-- calendar
lain.widgets.calendar:attach(mytextclock, { font_size = 10 })

-- Mail IMAP check
mailicon = wibox.widget.imagebox(beautiful.widget_mail)
mailicon:buttons(awful.util.table.join(awful.button({ }, 1, function () awful.util.spawn(mail) end)))
--[[ commented because it needs to be set before use
mailwidget = lain.widgets.imap({
    timeout  = 180,
    server   = "server",
    mail     = "mail",
    password = "keyring get mail",
    settings = function()
        if mailcount > 0 then
            widget:set_text(" " .. mailcount .. " ")
            mailicon:set_image(beautiful.widget_mail_on)
        else
            widget:set_text("")
            mailicon:set_image(beautiful.widget_mail)
            ever not been sure
            ever not been sure
        end
    end
})
-- ]]

-- MPD
mpdicon = wibox.widget.imagebox(beautiful.widget_music)
mpdicon:buttons(awful.util.table.join(awful.button({ }, 1, function () awful.util.spawn_with_shell(musicplr) end)))
mpdwidget = lain.widgets.mpd({
    settings = function()
        if mpd_now.state == "play" then
            artist = " " .. mpd_now.artist .. " "
            title  = mpd_now.title  .. " "
            mpdicon:set_image(beautiful.widget_music_on)
        elseif mpd_now.state == "pause" then
            artist = " mpd "
            title  = "paused "
        else
            artist = ""
            title  = ""
            mpdicon:set_image(beautiful.widget_music)
        end

        widget:set_markup(markup("#EA6F81", artist) .. title)
    end
})

-- MEM
memicon = wibox.widget.imagebox(beautiful.widget_mem)
memwidget = lain.widgets.mem({
    settings = function()
        widget:set_text(string.format("%5d", mem_now.used) .. "MB ")
    end
})

-- CPU
cpuicon = wibox.widget.imagebox(beautiful.widget_cpu)
cpuwidget = lain.widgets.cpu({
    settings = function()
        widget:set_text(string.format("%3d", cpu_now.usage) .. "% ")
    end
})

-- Coretemp
tempicon = wibox.widget.imagebox(beautiful.widget_temp)
tempwidget = lain.widgets.temp({
    settings = function()
        widget:set_text(string.format("%3.0f", coretemp_now) .. "°C ")
    end
})

-- / fs
fsicon = wibox.widget.imagebox(beautiful.widget_hdd)
fswidget = lain.widgets.fs({
    settings  = function()
        widget:set_text(" " .. fs_now.used .. "% ")
    end
})

-- Battery
baticon = wibox.widget.imagebox(beautiful.widget_battery)
batwidget = lain.widgets.bat({
    settings = function()
        if tonumber(bat_now.perc) <= 9 then
            baticon:set_image(beautiful.widget_battery_empty)
        elseif tonumber(bat_now.perc) <= 15 then
            baticon:set_image(beautiful.widget_battery_low)
        else
            baticon:set_image(beautiful.widget_battery)
        end
        
        if bat_now.status == "Full" then
           widget:set_markup(" Full ")
        else
           widget:set_markup(" " .. bat_now.perc .. "% ")
        end
    end
})

-- ALSA volume
volicon = wibox.widget.imagebox(beautiful.widget_vol)
volumewidget = lain.widgets.alsa({
    settings = function()
        if volume_now.status == "off" then
            volicon:set_image(beautiful.widget_vol_mute)
        elseif tonumber(volume_now.level) == 0 then
            volicon:set_image(beautiful.widget_vol_no)
        elseif tonumber(volume_now.level) <= 50 then
            volicon:set_image(beautiful.widget_vol_low)
        else
            volicon:set_image(beautiful.widget_vol)
        end

        widget:set_text(" " .. volume_now.level .. "% ")
    end
})

-- Net
neticon = wibox.widget.imagebox(beautiful.widget_net)
neticon:buttons(awful.util.table.join(awful.button({ }, 1, function () awful.util.spawn_with_shell(iptraf) end)))

netwidget = lain.widgets.net({
    settings = function()
        widget:set_markup(markup("#7AC82E", string.format("%6.1f", net_now.received))
                          .. " " ..
                          markup("#46A8C3", string.format("%4.1f", net_now.sent) .. " "))
    end
})

-- Separators
spr = wibox.widget.textbox(' ')
arrl = wibox.widget.imagebox()
arrl:set_image(beautiful.arrl)
arrl_dl = separators.arrow_left(beautiful.bg_focus, "alpha")
arrl_ld = separators.arrow_left("alpha", beautiful.bg_focus)

-- Create a wibox for each screen and add it
mywibox = {}
mypromptbox = {}
mylayoutbox = {}
mytaglist = {}
mytaglist.buttons = awful.util.table.join(
                    awful.button({ }, 1, awful.tag.viewonly),
                    awful.button({ modkey }, 1, awful.client.movetotag),
                    awful.button({ }, 3, awful.tag.viewtoggle),
                    awful.button({ modkey }, 3, awful.client.toggletag),
                    awful.button({ }, 9, function(t) awful.tag.viewnext(awful.tag.getscreen(t)) end),
                    awful.button({ }, 9, function(t) awful.tag.viewprev(awful.tag.getscreen(t)) end)
                    )
mytasklist = {}
mytasklist.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])
                                                  end
                                                  -- This will also un-minimize
                                                  -- the client, if needed
                                                  client.focus = c
                                                  c:raise()
                                              end
                                          end),
                     awful.button({ }, 3, function ()
                                              if instance then
                                                  instance:hide()
                                                  instance = nil
                                              else
                                                  instance = awful.menu.clients({ width=250 })
                                              end
                                          end),
                     awful.button({ }, 9, function ()
                                              awful.client.focus.byidx(1)
                                              if client.focus then client.focus:raise() end
                                          end),
                     awful.button({ }, 9, function ()
                                              awful.client.focus.byidx(-1)
                                              if client.focus then client.focus:raise() end
                                          end))

for s = 1, screen.count() do

    -- Create a promptbox for each screen
    mypromptbox[s] = awful.widget.prompt()

    -- We need one layoutbox per screen.
    mylayoutbox[s] = awful.widget.layoutbox(s)
    mylayoutbox[s]:buttons(awful.util.table.join(
                            awful.button({ }, 1, function () awful.layout.inc(layouts, 1) end),
                            awful.button({ }, 3, function () awful.layout.inc(layouts, -1) end),
                            awful.button({ }, 9, function () awful.layout.inc(layouts, 1) end),
                            awful.button({ }, 9, function () awful.layout.inc(layouts, -1) end)))

    -- Create a taglist widget
    mytaglist[s] = awful.widget.taglist(s, awful.widget.taglist.filter.all, mytaglist.buttons)

    -- Create a tasklist widget
    mytasklist[s] = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, mytasklist.buttons)

    -- Create the wibox
    mywibox[s] = awful.wibox({ position = "top", screen = s, height = 18 })

    -- Widgets that are aligned to the upper left
    local left_layout = wibox.layout.fixed.horizontal()
    left_layout:add(spr)
    left_layout:add(mytaglist[s])
    left_layout:add(mypromptbox[s])
    left_layout:add(spr)

    -- Widgets that are aligned to the upper right
    local right_layout_toggle = true
    local function right_layout_add (...)
        local arg = {...}
        if right_layout_toggle then
            right_layout:add(arrl_ld)
            for i, n in pairs(arg) do
                right_layout:add(wibox.widget.background(n, beautiful.bg_focus))
            end
        else
            right_layout:add(arrl_dl)
            for i, n in pairs(arg) do
                right_layout:add(n)
            end
        end
        right_layout_toggle = not right_layout_toggle
    end

    right_layout = wibox.layout.fixed.horizontal()
    if s == 1 then right_layout:add(wibox.widget.systray()) end
    right_layout:add(spr)
    right_layout:add(arrl)
    right_layout_add(mpdicon, mpdwidget)
    right_layout_add(volicon, volumewidget)
    --right_layout_add(mailicon, mailwidget)
    right_layout_add(memicon, memwidget)
    right_layout_add(cpuicon, cpuwidget)
    right_layout_add(tempicon, tempwidget)
    right_layout_add(fsicon, fswidget)
    right_layout_add(baticon, batwidget)
    right_layout_add(neticon,netwidget)
    right_layout_add(mytextclock, spr)
    right_layout_add(mylayoutbox[s])

    -- 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_right(right_layout)
    mywibox[s]:set_widget(layout)

end
-- }}}

-- {{{ Mouse bindings
root.buttons(awful.util.table.join(
    awful.button({ }, 3, function () mymainmenu:toggle() end),
    awful.button({ }, 9, awful.tag.viewnext),
    awful.button({ }, 9, awful.tag.viewprev)
))
-- }}}

Invert desktop colors

We can invert the desktop colors (white to black, etc) using xcalib. We should also change Awesome’s background and menu bar to something white (which would be black).

invert_screen = "xcalib -invert -alter"

-- the code below does not work --
inverted = false
function invert_screens()
   -- need a static variable that we can check each time.
   -- probably just a global
   if inverted then
      inverted = false
   else
      inverted = true
   end
   
   awful.util.spawn_with_shell("xcalib -invert -alter")
   -- set the wallpaper
   for s = 1, screen.count() do
      gears.wallpaper.maximized("some_light_wallpaper.png", s, true)
   end
   -- TODO: change the colors on the menu
   -- probably by calling beautiful.init again, and putting the theme in its
   -- own function.
   beautiful.init(os.getenv("HOME") .. "/.config/awesome/themes/powerarrow-lighter/theme.lua")  -- doesn't exist, yet
   -- TODO: change emacs and terminal themes
   -- TODO: change firefox theme
   -- this would be so awesome
end

Always on Top

http://stackoverflow.com/questions/29681677/always-on-top-window-and-keeping-focus-on-awesomewm

Also set focus = custom_focus_filter in awful.rules. And a keybind for the global_focus_disable.

function custom_focus_filter(c)
    if global_focus_disable then
        return nil
    end
    return awful.client.focus.filter(c)
end

key bindings

global keys

globalkeys = awful.util.table.join(
    awful.key({ modkey,           }, "Left",   awful.tag.viewprev       ),
    awful.key({ modkey,           }, "Right",  awful.tag.viewnext       ),
    awful.key({ modkey,           }, "Escape", awful.tag.history.restore),

    awful.key({ modkey,           }, "s",
        function ()
            awful.client.focus.byidx( 1)
            if client.focus then client.focus:raise() end
        end),
    awful.key({ modkey,           }, "f",
        function ()
            awful.client.focus.byidx(-1)
            if client.focus then client.focus:raise() end
        end),
    -- awful.key({ modkey,           }, "w", function () mymainmenu:show() end),
    awful.key({ modkey },            "l", function () awful.util.spawn(lock_srceen) end),
    -- Layout manipulation
    awful.key({ modkey, "Control" }, "s", function () awful.client.swap.byidx(  1)    end),
    awful.key({ modkey, "Control" }, "f", function () awful.client.swap.byidx( -1)    end),
    awful.key({ modkey, "Shift"   }, "s", function () awful.screen.focus_relative( 1) end),
    awful.key({ modkey, "Shift"   }, "f", function () awful.screen.focus_relative(-1) end),
    awful.key({ modkey,           }, "u", awful.client.urgent.jumpto),
    awful.key({ modkey,           }, "a", function () global_focus_disable = not global_focus_disable end),
    awful.key({ modkey            }, "i", function () awful.util.spawn("xcalib -invert -alter") end),
    -- awful.key({ modkey,           }, "Tab",
    --     function ()
    --         awful.client.focus.history.previous()
    --         if client.focus then
    --             client.focus:raise()
    --         end
    --     end),

standard program

-- Standard program
awful.key({ modkey,           }, "Return", function () awful.util.spawn(eterminal) end),
awful.key({ modkey, "Control" }, "Return", function () awful.util.spawn(terminal)  end),
awful.key({ altkey, "Control" }, "r", awesome.restart),
-- awful.key({ modkey, "Shift"   }, "q", awesome.quit),

awful.key({ modkey,           }, "t",     function () awful.tag.incmwfact( 0.05)    end),
awful.key({ modkey,           }, "r",     function () awful.tag.incmwfact(-0.05)    end),
awful.key({ modkey, "Shift"   }, "r",     function () awful.tag.incnmaster( 1)      end),
awful.key({ modkey, "Shift"   }, "t",     function () awful.tag.incnmaster(-1)      end),
awful.key({ modkey, "Control" }, "r" ,    function () awful.tag.incncol( 1)         end),
awful.key({ modkey, "Control" }, "t",     function () awful.tag.incncol(-1)         end),
awful.key({ modkey,           }, "Tab", function () awful.layout.inc(layouts,  1) end),
awful.key({ modkey, "Shift"   }, "Tab", function () awful.layout.inc(layouts, -1) end),

awful.key({ modkey, "Control" }, "b", awful.client.restore),

dropdown terminal

    -- awful.key({ modkey,	          }, "z",      function () drop(terminal) end),
    -- Widgets popups
--    awful.key({ altkey,           }, "c",      function () lain.widgets.calendar:show(7) end),
--    awful.key({ altkey,           }, "h",      function () fswidget.show(7) end),

ALSA volume control

Borrowed most of this from the default qtile config. Those guys had this figured out.

awful.key({ }, "XF86AudioRaiseVolume",
    function ()
        os.execute("amixer -q -c 0 sset Master 5dB+")
        volumewidget.update()
    end),
awful.key({ }, "XF86AudioLowerVolume",
    function ()
        os.execute("amixer -q -c 0 sset Master 5dB-")
        volumewidget.update()
    end),
awful.key({ }, "XF86AudioMute",
    function ()
        os.execute("amixer -q set Master toggle")
        --os.execute(string.format("amixer set %s toggle", volumewidget.channel))
        volumewidget.update()
    end),
awful.key({ }, "XF86AudioPlay",
    function ()
        awful.util.spawn_with_shell("mpc toggle || ncmpc toggle || pms toggle")
        mpdwidget.update()
    end),
awful.key({ }, "XF86AudioPrev",
    function ()
        awful.util.spawn_with_shell("mpc prev || ncmpc prev || pms prev")
        mpdwidget.update()
    end),
awful.key({ }, "XF86AudioNext",
    function ()
        awful.util.spawn_with_shell("mpc next || ncmpc next || pms next")
        mpdwidget.update()
    end),

misc

    -- Copy to clipboard
    -- TODO: not sure this works, and it overrides tag swithcing to 'c'
    -- awful.key({ modkey }, "c", function () os.execute("xsel -p -o | xsel -i -b") end),


    -- Prompt
    awful.key({ altkey },            "F2",     function () mypromptbox[mouse.screen]:run() end),

    -- awful.key({ modkey }, "u",
    --           function ()
    --               awful.prompt.run({ prompt = "Run Lua code: " },
    --               mypromptbox[mouse.screen].widget,
    --               awful.util.eval, nil,
    --               awful.util.getdir("cache") .. "/history_eval")
    --           end),

    -- dmenu Menubar
    awful.key({ modkey }, "p", function() menubar.show() end)
)

tags

Qtile style “zxcv”. Maybe someday I’ll want more than 4 desktops. Probably not.

tags = {
   names = { "z", "x", "c", "v"},
   layout = { layouts[1], layouts[2], layouts[2], lain.layout.uselessfair}
}

-- tags = {  -- I could go for naming the desktops, but would require moving them back to numbers...
--    names = { "web", "emacs", "docs", "media", "down", "all"}, 
--    layout = { layouts[1], layouts[3], layouts[4], layouts[1], layouts[6], layouts[6] }
-- }

for i = 1, #tags.names do
    globalkeys = awful.util.table.join(globalkeys,
        -- View tag only.
        awful.key({ modkey }, tags.names[i],
                  function ()
                        local screen = mouse.screen
                        local tag = awful.tag.gettags(screen)[i]
                        if tag then
                           awful.tag.viewonly(tag)
                        end
                  end),
        -- View Toggle.
        awful.key({ modkey, "Shift" }, tags.names[i],
                  function ()
                      local screen = mouse.screen
                      local tag = awful.tag.gettags(screen)[i]
                      if tag then
                         awful.tag.viewtoggle(tag)
                      end
                  end),
        -- Move client to tag.
        awful.key({ modkey, "Control" }, tags.names[i],
                  function ()
                      if client.focus then
                          local tag = awful.tag.gettags(client.focus.screen)[i]
                          if tag then
                              awful.client.movetotag(tag)
                          end
                     end
                  end),
        -- Toggle tag.
        awful.key({ modkey, altkey}, tags.names[i],
                  function ()
                      if client.focus then
                          local tag = awful.tag.gettags(client.focus.screen)[i]
                          if tag then
                              awful.client.toggletag(tag)
                          end
                      end
                  end)
    )
end


for s = 1, screen.count() do
   tags[s] = awful.tag(tags.names, s, tags.layout)
end

client keys

clientkeys = awful.util.table.join(
    awful.key({ modkey,           }, "q",      function (c) c.fullscreen = not c.fullscreen  end),
    awful.key({ modkey,           }, "w",      function (c) c:kill()                         end),
    awful.key({          altkey   }, "Tab",    awful.client.floating.toggle                     ),
    awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end),
    awful.key({ modkey,           }, "o",      awful.client.movetoscreen                        ),
--    awful.key({ modkey,           }, "i",      function (c) c.ontop = not c.ontop            end),
    awful.key({ modkey,           }, "b",
        function (c)
            -- The client currently has the input focus, so it cannot be
            -- minimized, since minimized clients can'i have the focus.
            c.minimized = true
        end),
    awful.key({ modkey,           }, "m",
        function (c)
            c.maximized_horizontal = not c.maximized_horizontal
            c.maximized_vertical   = not c.maximized_vertical
        end)
)



-- Mouse Client Buttons
clientbuttons = awful.util.table.join(
    awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
    awful.button({ altkey }, 1, awful.mouse.client.move),
    awful.button({ altkey }, 3, awful.mouse.client.resize))

set keys

root.keys(globalkeys)

Battery

Borrowed from http://bpdp.blogspot.be/2013/06/battery-warning-notification-for.html

-- battery warning
-- created by bpdp

local function trim(s)
  return s:find'^%s*$' and '' or s:match'^%s*(.*%S)'
end

local function bat_notification()
  
  local f_capacity = assert(io.open("/sys/class/power_supply/BAT0/capacity", "r"))
  local f_status = assert(io.open("/sys/class/power_supply/BAT0/status", "r"))

  local bat_capacity = tonumber(f_capacity:read("*all"))
  local bat_status = trim(f_status:read("*all"))

  if (bat_capacity <= 10 and bat_status == "Discharging") then
    naughty.notify({ title      = "Battery Warning"
      , text       = "Battery low! " .. bat_capacity .."%" .. " left!"
      , fg="#ff0000"
      , bg="#deb887"
      , timeout    = 15
      , position   = "bottom_left"
    })
  end
end

battimer = timer({timeout = 120})
battimer:connect_signal("timeout", bat_notification)
battimer:start()

-- end here for battery warning

rules

Rules to apply to new clients (through the “manage” signal).

awful.rules.rules = {
    -- All clients will match this rule.
    { rule = { },
      properties = { border_width = beautiful.border_width,
                     border_color = beautiful.border_normal,
                     -- focus = awful.client.focus.filter,
                     focus = custom_focus_filter,
                     raise = true,
                     keys = clientkeys,
                     size_hints_honor = false,
                     -- tag = tags[1][4],
                     buttons = clientbuttons },
      -- Put a copy of every window on 'v', expose like
      -- callback = function(c) awful.client.toggletag(tags[1][4], c) end},
    { rule = { class = "MPlayer" },
      properties = { floating = true } },
    { rule = { class = "pinentry" },
      properties = { floating = true } },
    { rule = { class = "gimp" },
      properties = { floating = true } },
    { rule = { class = "Pidgin" },
      properties = { floating = true } },
    { rule = { name = "Guild Wars 2" },
      properties = { floating = true } },
    { rule = { name = "LibreOffice" },
      properties = { floating = true } },
    { rule = { class = "Emacs" },
     properties = { size_hints_honor = false } },
    -- Set Firefox to always map on tags number 2 of screen 1.
    -- { rule = { class = "Firefox" },
    --   properties = { tag = tags[1][2] } },
}}

signals

Signal function to execute when a new client appears.

local sloppyfocus_last = {c=nil}
client.connect_signal("manage", function (c, startup)
    -- Enable sloppy focus
    client.connect_signal("mouse::enter", function(c)
         if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
            and awful.client.focus.filter(c) then
             -- Skip focusing the client if the mouse wasn't moved.
             if c ~= sloppyfocus_last.c then
                 client.focus = c
                 sloppyfocus_last.c = c
             end
         end
    end)


    if not startup then
        -- Set the windows at the slave,
        -- i.e. put it at the end of others instead of setting it master.
        awful.client.setslave(c)

        -- Put windows in a smart way, only if they does not set an initial position.
        if not c.size_hints.user_position and not c.size_hints.program_position then
            awful.placement.no_overlap(c)
            awful.placement.no_offscreen(c)
        end
    end

    local titlebars_enabled = false
    if titlebars_enabled and (c.type == "normal" or c.type == "dialog") then
        -- buttons for the titlebar
        local buttons = awful.util.table.join(
                awful.button({ }, 1, function()
                    client.focus = c
                    c:raise()
                    awful.mouse.client.move(c)
                end),
                awful.button({ }, 3, function()
                    client.focus = c
                    c:raise()
                    awful.mouse.client.resize(c)
                end)
                )

        -- Widgets that are aligned to the left
        local left_layout = wibox.layout.fixed.horizontal()
        left_layout:add(awful.titlebar.widget.iconwidget(c))
        left_layout:buttons(buttons)

        -- Widgets that are aligned to the right
        local right_layout = wibox.layout.fixed.horizontal()
        right_layout:add(awful.titlebar.widget.floatingbutton(c))
        right_layout:add(awful.titlebar.widget.maximizedbutton(c))
        right_layout:add(awful.titlebar.widget.stickybutton(c))
        right_layout:add(awful.titlebar.widget.ontopbutton(c))
        right_layout:add(awful.titlebar.widget.closebutton(c))

        -- The title goes in the middle
        local middle_layout = wibox.layout.flex.horizontal()
        local title = awful.titlebar.widget.titlewidget(c)
        title:set_align("center")
        middle_layout:add(title)
        middle_layout:buttons(buttons)

        -- Now bring it all together
        local layout = wibox.layout.align.horizontal()
        layout:set_left(left_layout)
        layout:set_right(right_layout)
        layout:set_middle(middle_layout)

        awful.titlebar(c):set_widget(layout)
    end
end)

-- No border for maximized clients
client.connect_signal("focus",
    function(c)
        if c.maximized_horizontal == true and c.maximized_vertical == true then
            c.border_color = beautiful.border_normal
        else
            c.border_color = beautiful.border_focus
        end
    end)
client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)

Arange signal handle

for s = 1, screen.count() do screen[s]:connect_signal("arrange", function ()
        local clients = awful.client.visible(s)
        local layout  = awful.layout.getname(awful.layout.get(s))

        if #clients > 0 then -- Fine grained borders and floaters control
            for _, c in pairs(clients) do -- Floaters always have borders
                if awful.client.floating.get(c) or layout == "floating" then
                    c.border_width = beautiful.border_width

                -- No borders with only one visible client
                elseif #clients == 1 or layout == "max" then
                    c.border_width = 0
                else
                    c.border_width = beautiful.border_width
                end
            end
        end
      end)
end

Remember floating window positions

When cycling through layouts it is remembered where the windows are floating so that when returning you don’t get a messed up desktop. This should be the default behavior really. https://bbs.archlinux.org/viewtopic.php?id=128623

TODO:

  • [ ] Only remember geometries when on floating layouts. When a window is tagged for another desktop, and you switch to that desktop, the windows geometry is set to the managed size. i.e. all floating windows become little tiles after switching to a desktop where that window was tiled.
floatgeoms = {}

tag.connect_signal("property::layout", function(t)
    for k, c in ipairs(t:clients()) do
        if ((awful.layout.get(mouse.screen) == awful.layout.suit.floating) or (awful.client.floating.get(c) == true)) then
            c:geometry(floatgeoms[c.window])
        end
    end
end)

client.connect_signal("property::geometry", function(c)
    if ((awful.layout.get(mouse.screen) == awful.layout.suit.floating) or (awful.client.floating.get(c) == true)) then
        floatgeoms[c.window] = c:geometry()
    end
end)

client.connect_signal("unmanage", function(c) floatgeoms[c.window] = nil end)

client.connect_signal("manage", function(c)
    if ((awful.layout.get(mouse.screen) == awful.layout.suit.floating) or (awful.client.floating.get(c) == true)) then
        floatgeoms[c.window] = c:geometry()
    end
end)