X-Git-Url: https://git.madduck.net/etc/awesome.git/blobdiff_plain/33ce8ff0b0e93ab9fc4b86716269e1180a16b5d4..2f8a1fff3b542207a3fdbd3f478d62b9caf59849:/.config/awesome/rc.lua?ds=sidebyside diff --git a/.config/awesome/rc.lua b/.config/awesome/rc.lua index 920d28f..81f5476 100644 --- a/.config/awesome/rc.lua +++ b/.config/awesome/rc.lua @@ -7,10 +7,24 @@ require("awful.autofocus") local wibox = require("wibox") -- Theme handling library local beautiful = require("beautiful") +local xrdb = beautiful.xresources -- Notification library local naughty = require("naughty") local menubar = require("menubar") local hotkeys_popup = require("awful.hotkeys_popup").widget +-- Enable hotkeys help widget for VIM and other apps +-- when client with a matching name is opened: +require("awful.hotkeys_popup.keys") + +-- Load Debian menu entries +local debian = require("debian.menu") +local has_fdo, freedesktop = pcall(require, "freedesktop") +-- Other libraries +local tblutils = require("tblutils") +local lain = require("lain") +local dkjson = require("lain.util").dkjson +local math = require("math") +local luatz = require("luatz") -- }}} -- {{{ Error handling @@ -39,12 +53,16 @@ end -- }}} -- {{{ Variable definitions --- Themes define colours, icons, and wallpapers -beautiful.init(awful.util.get_themes_dir() .. "default/theme.lua") +--xrdb.set_dpi(95, screen[1]) +--xrdb.set_dpi(120, screen[2]) + +-- Themes define colours, icons, font and wallpapers. +beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua") +beautiful.font = 'Sans 10' -- This is used later as the default terminal and editor to run. terminal = "x-terminal-emulator" -editor = "sensible-editor" +editor = os.getenv("EDITOR") or "editor" editor_cmd = terminal .. " -e " .. editor -- Default modkey. @@ -94,32 +112,59 @@ local function client_menu_toggle_fn() end end -local function sorted_pairs(t, f) - local a = {} - for n in pairs(t) do table.insert(a, n) end - table.sort(a, f) - local i = 0 -- iterator variable - local iter = function () -- iterator function - i = i + 1 - if a[i] == nil then return nil - else return a[i], t[a[i]] +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 - return iter end -local function print_table(tbl, indent) - if not indent then indent = 0 end - for k, v in pairs(tbl) do - formatting = string.rep(" ", indent) .. k .. ": " - if type(v) == "table" then - print(formatting) - print_table(v, indent+1) - else - print(formatting .. tostring(v)) - end +local lain_bat = lain.widget.bat({ + batteries = {"BAT0", "BAT1"}, + settings = function() + local delim = "↓" + if bat_now.status == "Charging" then delim = "↑" + elseif bat_now.status == "Unknown" then delim = "٭" end + widget:set_text(bat_now.perc .. "% " .. delim .. " " .. bat_now.time) + end, +}) + +local function poloniex_price(output, pair, prec) + local xc, pos, err = dkjson.decode(output, 1, nil) + if not prec then prec = 4 end + val = (xc and xc[pair]["last"]) or 0 + val = math.floor(val*10^prec+0.5)/10^prec + return (not err and val) or "n/a" +end + +local eth_widget = lain.widget.watch({ + cmd = "curl -m5 -s 'https://poloniex.com/public?command=returnTicker'", + timeout = 600, + settings = function() + widget:set_text(poloniex_price(output, 'BTC_ETH') .. " Ƀ/Ξ") end +}) + +local function coindesk_price(output, base, prec) + local xc, pos, err = dkjson.decode(output, 1, nil) + if not prec then prec = 4 end + val = (xc and xc["bpi"][base]["rate_float"]) or 0 + val = math.floor(val*10^prec+0.5)/10^prec + return (not err and val) or "n/a" end + +local btc_widget = lain.widget.watch({ + cmd = "curl -m5 -Ls 'https://api.coindesk.com/v1/bpi/currentprice/EUR.json'", + timeout = 600, + settings = function() + widget:set_text(coindesk_price(output, "EUR", 2) .. " €/Ƀ") + end +}) -- }}} -- {{{ Menu @@ -129,32 +174,61 @@ myawesomemenu = { { "manual", terminal .. " -e man awesome" }, { "edit config", editor_cmd .. " " .. awesome.conffile }, { "restart", awesome.restart }, - { "quit", awesome.quit } + { "quit", function() awesome.quit() end} } -mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon }, - { "open terminal", terminal } - } - }) +local menu_awesome = { "awesome", myawesomemenu, beautiful.awesome_icon } +local menu_terminal = { "open terminal", terminal } + +if has_fdo then + mymainmenu = freedesktop.menu.build({ + before = { menu_awesome }, + after = { menu_terminal } + }) +else + mymainmenu = awful.menu({ + items = { + menu_awesome, + { "Debian", debian.menu.Debian_menu.Debian }, + menu_terminal, + } + }) +end + mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon, menu = mymainmenu }) --- }}} --- {{{ Menubar configuration +-- Menubar configuration menubar.utils.terminal = terminal -- Set the terminal for applications that require it -- }}} --- {{{ Wibox +-- {{{ Wibar +local spacer = wibox.widget.textbox() +spacer:set_text(' │ ') + +-- Keyboard map indicator and switcher +mykeyboardlayout = awful.widget.keyboardlayout() + -- Create a textclock widget -mytextclock = wibox.widget.textclock("%a %d %b %H:%M:%S", 1) +clocks = { wibox.widget.textclock("%a %d %b %H:%M:%S %Z", 1) } + +ZONES = { + ["NZ"] = "Pacific/Auckland", + ["DE"] = "Europe/Berlin" +} +local now = luatz.time_in(nil) +for c, tz in tblutils.sorted_pairs(ZONES) do + local t = luatz.time_in(tz) + if math.abs(os.difftime(t, now)) > 10 then + local widget = wibox.widget.textclock(c .. ": %H:%M (%a)", 60, tz) + table.insert(clocks, 1, spacer) + table.insert(clocks, 1, widget) + end +end -- Create a wibox for each screen and add it -mywibox = {} -mypromptbox = {} -mylayoutbox = {} -mytaglist = {} -mytaglist.buttons = awful.util.table.join( +local taglist_buttons = gears.table.join( awful.button({ }, 1, function(t) t:view_only() end), awful.button({ modkey }, 1, function(t) if client.focus then @@ -171,11 +245,11 @@ mytaglist.buttons = awful.util.table.join( awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end) ) -mytasklist = {} -mytasklist.buttons = awful.util.table.join( +local tasklist_buttons = gears.table.join( awful.button({ }, 1, function (c) if c == client.focus then - c.minimized = true + -- I don't like click-minimising + -- c.minimized = true else -- Without this, the following -- :isvisible() makes no sense @@ -198,6 +272,9 @@ mytasklist.buttons = awful.util.table.join( end)) -- }}} +-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution) +screen.connect_signal("property::geometry", set_wallpaper) + -- {{{ Tags tags = {} tags.config = {} @@ -234,20 +311,13 @@ elseif screen.count() == 3 then -- main screen is still #1 in the middle end awful.screen.connect_for_each_screen(function(s) - -- Wallpaper - --DISABLED--if beautiful.wallpaper then - --DISABLED-- local wallpaper = beautiful.wallpaper - --DISABLED-- -- If wallpaper is a function, call it with the screen - --DISABLED-- if type(wallpaper) == "function" then - --DISABLED-- wallpaper = wallpaper(s) - --DISABLED-- end - --DISABLED-- gears.wallpaper.maximized(wallpaper, s, true) - --DISABLED--end + -- local fontsize = math.floor(250 * xrdb.get_dpi(s)/s.geometry.width) + -- beautiful.font = "Sans " .. tostring(fontsize) if not tags[s.index] then tags[s.index] = {} end - for n,p in sorted_pairs(screentags[s.index]) do + for n,p in tblutils.sorted_pairs(screentags[s.index]) do p["screen"] = s n = string.sub(n, 2) -- remove leading 't' needed for syntax in table table.insert(tags[s.index], awful.tag.add(n, p)) @@ -282,19 +352,27 @@ awful.screen.connect_for_each_screen(function(s) mypromptbox[s], }, mytasklist[s], -- Middle widget - { -- Right widgets - layout = wibox.layout.fixed.horizontal, - mykeyboardlayout, - wibox.widget.systray(), - mytextclock, - mylayoutbox[s], - }, + awful.util.table.join( -- Right widgets + { + layout = wibox.layout.fixed.horizontal, + mykeyboardlayout, + wibox.widget.systray(), + btc_widget, + spacer, + lain_bat.widget, + spacer, + }, + clocks, + { + mylayoutbox[s], + } + ), } end) -- }}} -- {{{ Mouse bindings -root.buttons(awful.util.table.join( +root.buttons(gears.table.join( awful.button({ }, 3, function () mymainmenu:toggle() end), awful.button({ }, 4, awful.tag.viewnext), awful.button({ }, 5, awful.tag.viewprev) @@ -302,7 +380,7 @@ root.buttons(awful.util.table.join( -- }}} -- {{{ Key bindings -globalkeys = awful.util.table.join( +globalkeys = gears.table.join( awful.key({ modkey, }, "s", hotkeys_popup.show_help, {description="show help", group="awesome"}), awful.key({ modkey, }, "Left", awful.tag.viewprev, @@ -384,15 +462,17 @@ globalkeys = awful.util.table.join( {description = "restore minimized", group = "client"}), -- Prompt - awful.key({ modkey }, "r", function () mypromptbox[awful.screen.focused()]:run() end, + awful.key({ modkey }, "r", function () awful.screen.focused().mypromptbox:run() end, {description = "run prompt", group = "launcher"}), awful.key({ modkey }, "x", function () - awful.prompt.run({ prompt = "Run Lua code: " }, - mypromptbox[awful.screen.focused()].widget, - awful.util.eval, nil, - awful.util.get_cache_dir() .. "/history_eval") + 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, {description = "lua execute prompt", group = "awesome"}), -- Menubar @@ -400,7 +480,7 @@ globalkeys = awful.util.table.join( {description = "show the menubar", group = "launcher"}) ) -clientkeys = awful.util.table.join( +clientkeys = gears.table.join( awful.key({ modkey, }, "f", function (c) c.fullscreen = not c.fullscreen @@ -427,16 +507,30 @@ clientkeys = awful.util.table.join( awful.key({ modkey, }, "m", function (c) c.maximized = not c.maximized + c.maximized_horizontal = false + c.maximized_vertical = false + c:raise() + end , + {description = "(un)maximize", group = "client"}), + awful.key({ modkey, "Control" }, "m", + function (c) + c.maximized_vertical = not c.maximized_vertical c:raise() end , - {description = "maximize", group = "client"}) + {description = "(un)maximize vertically", group = "client"}), + awful.key({ modkey, "Shift" }, "m", + function (c) + c.maximized_horizontal = not c.maximized_horizontal + c:raise() + end , + {description = "(un)maximize horizontally", group = "client"}) ) -- Bind all key numbers to tags. --- Be careful: we use keycodes to make it works on any keyboard layout. +-- Be careful: we use keycodes to make it work on any keyboard layout. -- This should map on the top row of your keyboard, usually 1 to 9. for i = 1, 9 do - globalkeys = awful.util.table.join(globalkeys, + globalkeys = gears.table.join(globalkeys, -- View tag only. awful.key({ modkey }, "#" .. i + 9, function () @@ -447,7 +541,7 @@ for i = 1, 9 do end end, {description = "view tag #"..i, group = "tag"}), - -- Toggle tag. + -- Toggle tag display. awful.key({ modkey, "Control" }, "#" .. i + 9, function () local screen = awful.screen.focused() @@ -482,7 +576,7 @@ for i = 1, 9 do ) end -clientbuttons = awful.util.table.join( +clientbuttons = 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)) @@ -490,23 +584,28 @@ clientbuttons = awful.util.table.join( -- misc apps globalkeys = awful.util.table.join(globalkeys, awful.key({ cmdkey }, "n", function () awful.spawn("firefox") end), -awful.key({ cmdkey }, "m", function () awful.spawn("chromium") end), +awful.key({ cmdkey }, "m", function () awful.spawn("chromium --enable-remote-extensions") end), awful.key({ cmdkey }, "y", function () awful.spawn(terminal .. " -e python") end), -awful.key({ cmdkey }, "c", function () awful.spawn("icedove") end), +awful.key({ cmdkey }, "c", function () awful.spawn("thunderbird") end), awful.key({ cmdkey }, "r", function () mypromptbox[mouse.screen]:run() end), awful.key({ cmdkey }, "g", function () awful.spawn("gscan2pdf") end), awful.key({ cmdkey }, "v", function () awful.spawn("virt-manager") end), awful.key({ cmdkey }, "l", function () awful.spawn("libreoffice") end), -awful.key({ cmdkey }, "i", function () awful.spawn(terminal .. " -title irc -name irc -e env MOSH_TITLE_NOPREFIX=true mosh -4 -- irc-host screen -dr irc") end), +awful.key({ cmdkey }, "f", function () awful.spawn("thunar") end), +awful.key({ cmdkey }, "i", function () awful.spawn(terminal .. " -name irc -e env MOSH_TITLE_NOPREFIX=true mosh -4 -- irc-host tmux new -As irc irssi") end), awful.key({ cmdkey }, "x", function () awful.spawn.with_shell("/sbin/start-stop-daemon --start --background --exec /usr/bin/xscreensaver -- -no-capture-stderr; sleep 2; xscreensaver-command -lock") end), awful.key({ cmdkey, "Shift" }, "x", function () awful.spawn("xscreensaver-command -exit") end), -- function keys awful.key(nil, "XF86ScreenSaver", function () awful.spawn("xset dpms force off") end), awful.key(nil, "XF86AudioMute", function () awful.spawn("pactl set-sink-mute 0 toggle") end), +awful.key({ cmdkey }, "End", function () awful.spawn("pactl set-sink-mute 0 toggle") end), awful.key(nil, "XF86AudioLowerVolume", function () awful.spawn("pactl set-sink-volume 0 -2%") end), +awful.key({ cmdkey }, "Next", function () awful.spawn("pactl set-sink-volume 0 -2%") end), awful.key(nil, "XF86AudioRaiseVolume", function () awful.spawn("pactl set-sink-volume 0 +2%") end), +awful.key({ cmdkey }, "Prior", function () awful.spawn("pactl set-sink-volume 0 +2%") end), awful.key(nil, "XF86AudioMicMute", function () awful.spawn("pactl set-source-mute 1 toggle") end), +awful.key({ cmdkey }, "Home", function () awful.spawn("pactl set-source-mute 1 toggle") end), awful.key(nil, "XF86MonBrightnessDown", function () awful.spawn("xbacklight -dec 5%") end), awful.key(nil, "XF86MonBrightnessUp", function () awful.spawn("xbacklight -inc 5%") end), awful.key(nil, "XF86Display", function () awful.spawn("") end), @@ -541,7 +640,7 @@ awful.rules.rules = { buttons = clientbuttons, screen = awful.screen.preferred, placement = awful.placement.no_overlap+awful.placement.no_offscreen, - floating = true + floating = false }, }, @@ -551,11 +650,14 @@ awful.rules.rules = { --DISABLED-- }, { rule = { type = "dialog" }, - properties = { placement = awful.placement.centered }}, + properties = { floating = true, + placement = awful.placement.centered + } + }, { rule = { class = "URxvt" }, properties = { - floating = false, + -- floating = false, size_hints_honor = false } }, { rule = { class = "URxvt", instance = "irc" }, @@ -564,19 +666,25 @@ awful.rules.rules = { }, callback = move_to_tag(screen.count(), screen.count() == 1 and 2 or 1) }, - { rule = { class = "Firefox" }, + { rule = { class = "Firefox", instance = "Navigator" }, properties = { floating = false, }, callback = move_to_tag(screen.count() == 1 and 1 or 2, 9) }, - { rule = { class = "Icedove" }, + { rule = { class = "Firefox-esr", instance = "Navigator" }, + properties = { + floating = false, + }, + callback = move_to_tag(screen.count() == 1 and 1 or 2, 9) + }, + { rule = { class = "Thunderbird", instance = "Mail" }, properties = { floating = false, }, callback = move_to_tag(screen.count() == 1 and 1 or 2, 8) }, - { rule = { class = "chromium" }, + { rule = { class = "Chromium", instance = "chromium" }, properties = { floating = false, }, @@ -584,8 +692,7 @@ awful.rules.rules = { }, { rule = { class = "Gscan2pdf" }, properties = { - screen = 1, - tag = "5" + switchtotag = true }, callback = move_to_tag(1, 5) }, @@ -593,7 +700,26 @@ awful.rules.rules = { properties = { floating = false, }, - callback = move_to_tag(1, 5) + }, + { rule = { class = "Thunar", type = "normal" }, + properties = { + floating = false, + }, + }, + { rule = { class = "MuPDF", instance = "mupdf" }, + properties = { + floating = true, + }, + }, + { rule = { class = "Pinentry", instance = "pinentry" }, + properties = { + floating = true, + }, + }, + { rule = { class = "Gxmessage" }, + properties = { + floating = true, + }, }, } -- }}} @@ -603,7 +729,7 @@ awful.rules.rules = { client.connect_signal("manage", function (c) -- Set the windows at the slave, -- i.e. put it at the end of others instead of setting it master. - -- if not awesome.startup then awful.client.setslave(c) end + if not awesome.startup then awful.client.setslave(c) end if awesome.startup and not c.size_hints.user_position @@ -611,12 +737,15 @@ client.connect_signal("manage", function (c) -- Prevent clients from being unreachable after screen count changes. awful.placement.no_offscreen(c) end + + c.maximized_horizontal = false + c.maximized_vertical = false end) -- Add a titlebar if titlebars_enabled is set to true in the rules. client.connect_signal("request::titlebars", function(c) -- buttons for the titlebar - local buttons = awful.util.table.join( + local buttons = gears.table.join( awful.button({ }, 1, function() client.focus = c c:raise() @@ -655,7 +784,7 @@ client.connect_signal("request::titlebars", function(c) } end) --- Enable sloppy focus +-- Enable sloppy focus, so that focus follows mouse. client.connect_signal("mouse::enter", function(c) if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier and awful.client.focus.filter(c) then @@ -666,14 +795,8 @@ end) client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end) client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end) --- https://www.mail-archive.com/awesome@naquadah.org/msg08285.html -client.disconnect_signal("request::activate", awful.ewmh.activate) -client.connect_signal("request::activate", function(c, context, hints) - if c.class == "Firefox" and context == "ewmh" then - return - end - return awful.ewmh.activate(c, context, hints) +awful.ewmh.add_activate_filter(function(c, context, hints) + if context == "ewmh" and (c.class == "Firefox-esr" or c.class == "Firefox") then return false end end) --- }}} -- vim:ft=lua:sw=4:sts=4:ts=4:et