pcall(require, "luarocks.loader") local gears = require("gears") local awful = require("awful") require("awful.autofocus") local wibox = require("wibox") local beautiful = require("beautiful") local bling = require("bling") local naughty = require("naughty") local menubar = require("menubar") local hotkeys_popup = require("awful.hotkeys_popup") -- {{{ Error handling if awesome.startup_errors then naughty.notify({ preset = naughty.config.presets.critical, title = "Error during startup", 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 = "An error happened", text = tostring(err) }) in_error = false end) end -- }}} -- {{{ Variable definitions beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua") -- Gaps beautiful.useless_gap = 8 beautiful.gap_single_client = true -- ---- Qogir / polybar-matched palette ------------------------------------ local colors = { background = "#111111", background_alt = "#1a1a1a", foreground = "#d3dae3", accent = "#616161", accent_alt = "#6ba0e8", red = "#e35b5b", green = "#98c379", yellow = "#e5c07b", disabled = "#707880", white = "#ffffff", } -- Bar font (matches your polybar JetBrainsMono Nerd Font; bump the number to 14 -- if you want it as large as polybar's size=14). beautiful.font = "JetBrainsMono Nerd Font 12" -- Window borders beautiful.border_width = 4 beautiful.border_normal = colors.background_alt beautiful.border_focus = colors.accent -- Taglist colors to mirror polybar's xworkspaces module beautiful.taglist_bg_focus = colors.accent beautiful.taglist_fg_focus = colors.background beautiful.taglist_fg_occupied = colors.white beautiful.taglist_bg_occupied = colors.background beautiful.taglist_fg_empty = colors.disabled beautiful.taglist_bg_empty = colors.background beautiful.taglist_bg_urgent = colors.red beautiful.taglist_fg_urgent = colors.background -- Systray styling beautiful.bg_systray = colors.background beautiful.systray_icon_spacing = 4 terminal = "alacritty" editor = os.getenv("EDITOR") or "nano" -- THE modkey. "Mod1" = Alt. Use "Mod4" for the Super/Windows key. modkey = "Mod1" -- Layouts: suit.tile = master column LEFT, stack column RIGHT. awful.layout.layouts = { awful.layout.suit.tile, awful.layout.suit.max, awful.layout.suit.floating, } -- }}} -- {{{ Bar helpers --------------------------------------------------------- -- "ICON value" with ICON tinted accent, like polybar's *-prefix-foreground. local function label(icon, val) return string.format("%s %s", colors.accent, icon, val or "") end -- A slim "|" separator in the disabled color, like polybar's separator. local function sep() local w = wibox.widget.textbox() w.markup = string.format("", colors.disabled) return w end -- Wrap a widget in a small margin so bar modules aren't crammed together. local function padded(w, left, right) return wibox.container.margin(w, left or 8, right or 8) end -- Focused window title (polybar xwindow / %title%) local function make_title() local t = wibox.widget.textbox() local function update() local c = client.focus t.markup = c and string.format("%s", colors.white, gears.string.xml_escape(c.name or "")) or "" end client.connect_signal("focus", update) client.connect_signal("unfocus", update) client.connect_signal("property::name", update) return t end -- CPU usage % (two top samples so the reading is accurate) local function make_cpu() return awful.widget.watch( { "bash", "-c", [[LANG=C top -bn2 -d0.3 | grep -m2 '^%Cpu' | tail -1 | awk '{printf "%.0f", 100 - $8}']] }, 3, function(w, out) w.markup = label("CPU", out:gsub("%s+$","") .. "%") end) end -- Volume: click to mute, scroll to adjust, right-click for the mixer. -- Keeps its own refresh() so button presses update instantly instead of -- waiting on the polling timer. local function make_vol() local w = wibox.widget.textbox() local vol_script = [[ sink=$(LANG=C pactl get-default-sink 2>/dev/null) m=$(LANG=C pactl get-sink-mute "$sink" 2>/dev/null | grep -oE 'yes|no') v=$(LANG=C pactl get-sink-volume "$sink" 2>/dev/null | grep -oE '[0-9]+%' | head -n1) echo "$m $v" ]] local function shell_quote(s) return "'" .. s:gsub("'", "'\\''") .. "'" end local vol_cmd = "sh -c " .. shell_quote(vol_script) local function refresh() awful.spawn.easy_async_with_shell(vol_cmd, function(out) local muted, pct = out:match("(%a+)%s+(%d+)%%") if muted == nil and pct == nil then -- Command failed entirely (no sink found / pactl error). w.markup = string.format("VOL n/a", colors.disabled) return end muted = muted == "yes" pct = pct or "0" if muted then w.markup = string.format("MUTE", colors.disabled) else w.markup = label("VOL", pct .. "%") end end) end w:buttons(gears.table.join( -- left click: toggle mute awful.button({ }, 1, function () awful.spawn.easy_async_with_shell( [[sh -c 'pactl set-sink-mute "$(pactl get-default-sink)" toggle']], function() refresh() end) end), -- right click: open the mixer awful.button({ }, 3, function () awful.spawn("pavucontrol") end), -- scroll up: +2% awful.button({ }, 4, function () awful.spawn.easy_async_with_shell( [[sh -c 'pactl set-sink-volume "$(pactl get-default-sink)" +2%']], function() refresh() end) end), -- scroll down: -2% awful.button({ }, 5, function () awful.spawn.easy_async_with_shell( [[sh -c 'pactl set-sink-volume "$(pactl get-default-sink)" -2%']], function() refresh() end) end) )) -- Poll too, in case volume changes elsewhere (media keys, another app). gears.timer { timeout = 2, call_now = true, autostart = true, callback = refresh, } return w end -- {{{ Wibar widgets local mytextclock = wibox.widget.textclock("%Y-%m-%d %H:%M") 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 client.focus:move_to_tag(t) end end), awful.button({ }, 3, awful.tag.viewtoggle) ) local function set_wallpaper(s) if beautiful.wallpaper then local wp = beautiful.wallpaper if type(wp) == "function" then wp = wp(s) end gears.wallpaper.maximized(wp, s, true) end end screen.connect_signal("property::geometry", set_wallpaper) awful.screen.connect_for_each_screen(function(s) set_wallpaper(s) -- Workspaces 1..5 awful.tag({ "1", "2", "3", "4", "5" }, s, awful.layout.layouts[1]) s.mypromptbox = awful.widget.prompt() s.mylayoutbox = awful.widget.layoutbox(s) s.mylayoutbox:buttons(gears.table.join( awful.button({ }, 1, function () awful.layout.inc( 1) end), awful.button({ }, 3, function () awful.layout.inc(-1) end) )) s.mytaglist = awful.widget.taglist { screen = s, filter = awful.widget.taglist.filter.all, buttons = taglist_buttons, style = { shape = function(cr, w, h) gears.shape.rounded_rect(cr, w, h, 4) end, }, layout = { spacing = 4, layout = wibox.layout.fixed.horizontal, }, widget_template = { { { id = "text_role", widget = wibox.widget.textbox, }, left = 10, right = 10, top = 4, bottom = 4, widget = wibox.container.margin, }, id = "background_role", widget = wibox.container.background, }, } -- Per-screen monitor widgets (created here so multi-monitor stays valid) local title = make_title() local vol = make_vol() local cpu = make_cpu() local right = wibox.layout.fixed.horizontal() local function push(w) right:add(padded(w, 4, 4)) end push(vol); right:add(sep()) push(cpu); right:add(sep()) push(mytextclock) right:add(sep()) push(wibox.widget.systray()) right:add(sep()) push(s.mylayoutbox) s.mywibox = awful.wibar({ position = "top", screen = s, height = 36, bg = colors.background, fg = colors.foreground, shape = function(cr, w, h) gears.shape.rounded_rect(cr, w, h, 0) end, }) s.mywibox:setup { layout = wibox.layout.align.horizontal, { -- Left: workspaces + focused window title layout = wibox.layout.fixed.horizontal, padded(s.mytaglist, 8, 4), s.mypromptbox, { title, left = 8, widget = wibox.container.margin }, }, nil, -- empty center padded(right, 4, 12), } end) -- }}} -- {{{ Helper: launcher (prefer rofi, fall back to built-in menubar) local function launcher() awful.spawn.easy_async_with_shell("command -v rofi", function(out) if out and out:match("%S") then awful.spawn("rofi -show drun") else menubar.show() end end) end -- }}} -- {{{ Global keys globalkeys = gears.table.join( awful.key({ modkey }, "s", hotkeys_popup.show_help, {description = "show help", group = "awesome"}), -- Directional focus (vim keys) awful.key({ modkey }, "h", function () awful.client.focus.bydirection("left") end, {description = "focus left", group = "client"}), awful.key({ modkey }, "j", function () awful.client.focus.bydirection("down") end, {description = "focus down", group = "client"}), awful.key({ modkey }, "k", function () awful.client.focus.bydirection("up") end, {description = "focus up", group = "client"}), awful.key({ modkey }, "l", function () awful.client.focus.bydirection("right") end, {description = "focus right", group = "client"}), -- Directional move (swap clients in the tiling layout) awful.key({ modkey, "Shift" }, "h", function () awful.client.swap.bydirection("left") end, {description = "move left", group = "client"}), awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.bydirection("down") end, {description = "move down", group = "client"}), awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.bydirection("up") end, {description = "move up", group = "client"}), awful.key({ modkey, "Shift" }, "l", function () awful.client.swap.bydirection("right") end, {description = "move right", group = "client"}), -- Resize the master/other split awful.key({ modkey, "Control" }, "h", function () awful.tag.incmwfact(-0.05) end, {description = "shrink master", group = "layout"}), awful.key({ modkey, "Control" }, "l", function () awful.tag.incmwfact( 0.05) end, {description = "grow master", group = "layout"}), -- Launching / layout awful.key({ modkey }, "Return", function () awful.spawn(terminal) end, {description = "open a terminal", group = "launcher"}), awful.key({ modkey }, "space", launcher, {description = "application launcher", group = "launcher"}), awful.key({ modkey }, "e", function () awful.spawn("thunar") end, {description = "Filemanager", group = "system"}), awful.key({ modkey }, "b", function () awful.spawn("chromium") end, {description = "Browswer", group = "internet"}), awful.key({ modkey }, "t", function () awful.layout.inc(1) end, {description = "next layout", group = "layout"}), awful.key({ modkey }, "p", function () awful.spawn("xfce4-screenshooter") end, {description = "screenshot", group = "system"}), -- Alt tab only in max mode awful.key({ "Mod1" }, "Tab", function () if awful.layout.get(mouse.screen) == awful.layout.suit.max then awful.client.focus.byidx(1) if client.focus then client.focus:raise() end end end), -- Media keys: volume up/down/mute (works even without a hardware key -- if you bind these in your compositor/DE too) awful.key({ }, "XF86AudioRaiseVolume", function () awful.spawn.easy_async_with_shell([[sh -c 'pactl set-sink-volume "$(pactl get-default-sink)" +2%']]) end, {description = "volume up", group = "media"}), awful.key({ }, "XF86AudioLowerVolume", function () awful.spawn.easy_async_with_shell([[sh -c 'pactl set-sink-volume "$(pactl get-default-sink)" -2%']]) end, {description = "volume down", group = "media"}), awful.key({ }, "XF86AudioMute", function () awful.spawn.easy_async_with_shell([[sh -c 'pactl set-sink-mute "$(pactl get-default-sink)" toggle']]) end, {description = "toggle mute", group = "media"}), -- Awesome control awful.key({ modkey, "Shift" }, "r", awesome.restart, {description = "reload awesome", group = "awesome"}), awful.key({ modkey, "Shift" }, "e", awesome.quit, {description = "quit awesome", group = "awesome"}) ) -- Workspace keys 1..5: Alt+N view, Alt+Shift+N move client to tag for i = 1, 5 do globalkeys = gears.table.join(globalkeys, 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, "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"}) ) end -- }}} -- {{{ Per-client keys clientkeys = gears.table.join( awful.key({ modkey }, "q", function (c) c:kill() end, {description = "kill window", group = "client"}), awful.key({ modkey }, "f", function (c) c.fullscreen = not c.fullscreen c:raise() end, {description = "toggle fullscreen", group = "client"}), awful.key({ modkey }, "m", function (c) c:swap(awful.client.getmaster()) end, {description = "make master", group = "client"}), awful.key({ modkey, "Shift" }, "space", awful.client.floating.toggle, {description = "toggle floating", group = "client"}) ) clientbuttons = gears.table.join( awful.button({ }, 1, function (c) c:emit_signal("request::activate", "mouse_click", {raise = true}) end), awful.button({ modkey }, 1, function (c) c:emit_signal("request::activate", "mouse_click", {raise = true}) awful.mouse.client.move(c) end), awful.button({ modkey }, 3, function (c) c:emit_signal("request::activate", "mouse_click", {raise = true}) awful.mouse.client.resize(c) end) ) root.keys(globalkeys) -- }}} -- {{{ Rules awful.rules.rules = { { rule = { }, properties = { border_width = beautiful.border_width, border_color = beautiful.border_normal, focus = awful.client.focus.filter, raise = true, keys = clientkeys, buttons = clientbuttons, screen = awful.screen.preferred, placement = awful.placement.no_overlap + awful.placement.no_offscreen, } }, { rule_any = { instance = { "pinentry" }, class = { "Arandr", "Blueman-manager", "Gpick", "Pavucontrol" }, name = { "Event Tester" }, role = { "AlarmWindow", "pop-up" }, }, properties = { floating = true }}, } -- }}} -- {{{ 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 -- New windows open into the stack (to the right); first window becomes master. if not awesome.startup then awful.client.setslave(c) end c.shape = function(cr, width, height) -- 8 = corner radius in px gears.shape.rounded_rect(cr, width, height, 13) end end) -- Focus follows mouse (i3-like). Comment out for click-to-focus only. client.connect_signal("mouse::enter", function(c) c:emit_signal("request::activate", "mouse_enter", {raise = false}) 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) -- }}} -- Wallpaper bling.module.wallpaper.setup { wallpaper = {"/home/jason/Pictures/Wallpapers/farewell.jpg"}, position = "fit", background = "#181818" }