diff --git a/config/awesome/rc.lua b/config/awesome/rc.lua index b74d3f9..8d3b331 100644 --- a/config/awesome/rc.lua +++ b/config/awesome/rc.lua @@ -1,13 +1,11 @@ pcall(require, "luarocks.loader") - -local gears = require("gears") -local awful = require("awful") -local naughty = require("naughty") +local gears = require("gears") +local awful = require("awful") +local naughty = require("naughty") local wibox = require("wibox") -local beautiful = require("beautiful") +local beautiful = require("beautiful") local hotkeys_popup = require("awful.hotkeys_popup") local menubar = require("menubar") - require("awful.autofocus") -- Pick a random image from the folder on start/reload @@ -15,7 +13,7 @@ awful.spawn.with_shell("feh --bg-fill --randomize /home/jason/Pictures/Wallpaper -- Global config -- Alt. Use "Mod4" for the Super/Windows key. -modkey = "Mod4" +modkey = "Mod4" terminal = "alacritty" theChurch = "emacs" editor = os.getenv("EDITOR") or "nano" @@ -27,22 +25,22 @@ awful.layout.layouts = { awful.layout.suit.tile, awful.layout.suit.max } -- hasn't started yet at this point in the session) awful.spawn.easy_async_with_shell("pkill xfce4-notifyd", function() end) gears.timer.start_new(3, function() - awful.spawn.easy_async_with_shell("pkill xfce4-notifyd", function() end) - return false -- don't repeat + awful.spawn.easy_async_with_shell("pkill xfce4-notifyd", function() end) + return false -- don't repeat end) -- Error handling if awesome.startup_errors then - naughty.notify({ preset = naughty.config.presets.critical, title = "Error during startup", text = awesome.startup_errors }) + 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) + 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 -- ================================================ @@ -60,18 +58,14 @@ local colors = { disabled = "#6a9589", -- cyan (normal) - muted, low-contrast white = "#ffffff", -- white (normal) - dimmer than foreground } - - beautiful.wallpaper = nil beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua") - beautiful.useless_gap = 8 beautiful.gap_single_client = true beautiful.font = "JetBrainsMono Nerd Font 11" beautiful.border_width = 4 beautiful.border_normal = colors.background_alt beautiful.border_focus = colors.accent - beautiful.taglist_bg_focus = colors.accent beautiful.taglist_fg_focus = colors.background beautiful.taglist_fg_occupied = colors.accent @@ -80,10 +74,8 @@ beautiful.taglist_fg_empty = colors.white beautiful.taglist_bg_empty = colors.background beautiful.taglist_bg_urgent = colors.red beautiful.taglist_fg_urgent = colors.background - beautiful.bg_systray = colors.background beautiful.systray_icon_spacing = 4 - -- Notifications, styled to match the wibar/client theme naughty.config.defaults.position = "top_right" naughty.config.defaults.timeout = 5 @@ -94,7 +86,6 @@ naughty.config.defaults.icon_size = 48 naughty.config.defaults.border_width = 3 naughty.config.defaults.font = "JetBrainsMono Nerd Font 12" naughty.config.defaults.shape = function(cr, w, h) gears.shape.rounded_rect(cr, w, h, 13) end - naughty.config.presets.normal = { bg = colors.background, fg = colors.foreground, border_color = colors.accent, border_width = 3, font = "JetBrainsMono Nerd Font 12", timeout = 5, @@ -109,27 +100,24 @@ naughty.config.presets.critical = { -- WIDGETS -- ================================================ local widgets = {} - -- "ICON value" with ICON tinted accent, like polybar's *-prefix-foreground. function widgets.label(icon, val) return string.format("%s %s", colors.white, icon, val or "") end - -- A slim separator in the disabled color, like polybar's separator. function widgets.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. function widgets.padded(w, left, right) return wibox.container.margin(w, left or 8, right or 8) end - -- Focused window title (polybar xwindow / %title%) function widgets.make_title() local t = wibox.widget.textbox() + t.align = "center" local function update() local c = client.focus t.markup = c and string.format("%s", colors.white, gears.string.xml_escape(c.name or "")) or "" @@ -139,20 +127,17 @@ function widgets.make_title() client.connect_signal("property::name", update) return t end - -- CPU usage % (two top samples so the reading is accurate) function widgets.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 = widgets.label(" ", out:gsub("%s+$", "") .. "%") end) + 3, function(w, out) w.markup = widgets.label("", 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. function widgets.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') @@ -161,7 +146,6 @@ function widgets.make_vol() ]] 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+)%%") @@ -174,36 +158,29 @@ function widgets.make_vol() w.markup = muted and string.format("MUTE", colors.yellow) or widgets.label("󱄠", pct .. "%") end) end - w:buttons(gears.table.join( awful.button({ }, 1, function() awful.spawn("/home/jason/.local/bin/audioswitch") end), awful.button({ }, 3, function() awful.spawn.easy_async_with_shell([[sh -c 'pactl set-sink-mute "$(pactl get-default-sink)" toggle']], function() refresh() end) end), 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), 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) )) - gears.timer { timeout = 2, call_now = true, autostart = true, callback = refresh } return w end - -- Brightness: click to toggle between night (default gamma) and day (boosted). function widgets.make_brightness() - local OUTPUT = "HDMI-A-0" - local DAY_CMD = "xrandr --output " .. OUTPUT .. " --set CTM \"1.1,0,0,0,1.1,0,0,0,1.1\" --gamma 1.08:1.08:1.08" - local NIGHT_CMD = "xrandr --output " .. OUTPUT .. " --set CTM \"1,0,0,0,1,0,0,0,1\" --gamma 1.0:1.0:1.0" - + local OUTPUT = "HDMI-A-0" + local DAY_CMD = "xrandr --output " .. OUTPUT .. " --set CTM \"1.1,0,0,0,1.1,0,0,0,1.1\" --gamma 1.08:1.08:1.08" + local NIGHT_CMD = "xrandr --output " .. OUTPUT .. " --set CTM \"1,0,0,0,1,0,0,0,1\" --gamma 1.0:1.0:1.0" local w = wibox.widget.textbox() local is_day = true - - local function render() - local icon = is_day and " 󱁞 " or " 󱠩 " - - w.markup = string.format( - "%s", - colors.white, icon - ) - end - + local function render() + local icon = is_day and "󱁞" or "󱠩" + w.markup = string.format( + "%s ", + colors.white, icon + ) + end local function apply(day) local cmd = day and DAY_CMD or NIGHT_CMD awful.spawn.easy_async_with_shell(cmd, function() @@ -211,11 +188,9 @@ function widgets.make_brightness() render() end) end - w:buttons(gears.table.join( awful.button({ }, 1, function() apply(not is_day) end) )) - apply(true) return w end @@ -224,54 +199,42 @@ end -- KEYBINDS -- ================================================ local keys = {} - 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, "Control" }, "h", function() awful.client.swap.bydirection("left") end, { description = "move left", group = "client" }), awful.key({ modkey, "Control" }, "j", function() awful.client.swap.bydirection("down") end, { description = "move down", group = "client" }), awful.key({ modkey, "Control" }, "k", function() awful.client.swap.bydirection("up") end, { description = "move up", group = "client" }), awful.key({ modkey, "Control" }, "l", function() awful.client.swap.bydirection("right") end, { description = "move right", group = "client" }), - -- Resize the master/other split awful.key({ modkey, "Shift" }, "h", function() awful.tag.incmwfact(-0.05) end, { description = "shrink master", group = "layout" }), awful.key({ modkey, "Shift" }, "l", function() awful.tag.incmwfact( 0.05) end, { description = "grow master", group = "layout" }), - -- Launching / layout awful.key({ modkey }, "Return", function() awful.spawn(theChurch) end, { description = "open the church of emacs", group = "launcher" }), awful.key({ modkey }, "t", function() awful.spawn(terminal) end, { description = "open alacritty", group = "launcher" }), awful.key({ modkey }, "e", function() awful.spawn("thunar") end, { description = "Filemanager", group = "system" }), awful.key({ modkey }, "w", function() awful.layout.inc(1) end, { description = "next layout", group = "layout" }), - - - -- screenshooter + -- screenshooter awful.key({ modkey, "Control" }, "p", function() awful.spawn("xfce4-screenshooter") end, { description = "screenshot", group = "system" }), - - -- Alt tab current workspace windows - awful.key({ modkey }, "Tab", function() awful.client.focus.byidx(1) end), - + -- Alt tab current workspace windows + awful.key({ modkey }, "Tab", function() awful.client.focus.byidx(1) end, { description = "cycle focus", group = "client" }), -- Media keys 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" }), - -- rofi menus - awful.key({ modkey }, "space", function() awful.spawn("/home/jason/.local/bin/runrofi") end, { description = "application launcher", group = "launcher" }), + awful.key({ modkey }, "space", function() awful.spawn("/home/jason/.local/bin/runrofi") end, { description = "application launcher", group = "launcher" }), awful.key({ modkey }, "`", function() awful.spawn("/home/jason/.local/bin/powermenu") end, { description = "power menu", group = "system" }), awful.key({ modkey }, "a", function() awful.spawn("/home/jason/.local/bin/audioswitch") end, { description = "audio output", group = "system" }), - awful.key({ modkey }, "b", function () awful.spawn("/home/jason/.local/bin/bookmarks") end, {description = "bookmarks", group = "internet"}), - + awful.key({ modkey }, "b", function () awful.spawn("/home/jason/.local/bin/bookmarks") end, {description = "bookmarks", group = "internet"}), -- Awesome control awful.key({ modkey, "Control" }, "r", awesome.restart, { description = "reload awesome", group = "awesome" }) ) - -- Workspace keys 1..5: Alt+N view, Alt+Shift+N move client to tag for i = 1, 5 do keys.globalkeys = gears.table.join(keys.globalkeys, @@ -280,7 +243,6 @@ for i = 1, 5 do 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() if client.focus then local tag = client.focus.screen.tags[i] @@ -289,21 +251,18 @@ for i = 1, 5 do end, { description = "move focused client to tag #" .. i, group = "tag" }) ) end - 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 }, "m", function (c) c.maximized = not c.maximized c:raise() end, {description = "(un)maximize", group = "client"}), + awful.key({ modkey }, "m", function (c) c.maximized = not c.maximized c:raise() end, {description = "(un)maximize", group = "client"}), awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle, { description = "toggle floating", group = "client" }) ) - keys.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(keys.globalkeys) -- ================================================ @@ -314,97 +273,96 @@ local taglist_buttons = gears.table.join( 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 bar_setup() awful.screen.connect_for_each_screen(function(s) 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 }, + layout = { spacing = 8, 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 = widgets.make_title() local vol = widgets.make_vol() local cpu = widgets.make_cpu() - local brightness = widgets.make_brightness() + local brightness = widgets.make_brightness() local clock = wibox.widget.textclock("%Y-%m-%d %H:%M") - local right = wibox.layout.fixed.horizontal() - local function push(w) right:add(widgets.padded(w, 4, 4)) end - push(wibox.widget.systray()); right:add(widgets.sep()) - push(vol); right:add(widgets.sep()) - push(cpu); right:add(widgets.sep()) - push(clock); - push(brightness); - push(s.mylayoutbox) - + right.spacing = 16 -- one uniform gap between all right-hand modules + right:add(wibox.widget.systray()) + right:add(vol) + right:add(cpu) + right:add(clock) + right:add(brightness) s.mywibox = awful.wibar { position = "top", screen = s, height = 45, bg = colors.background, fg = colors.white, shape = function(cr, w, h) gears.shape.rounded_rect(cr, w, h, 0) end, } - s.mywibox:setup { layout = wibox.container.margin, left = 8, right = 8, top = 10, bottom = 10, { layout = wibox.layout.align.horizontal, - { -- Left: workspaces + focused window title + expand = "none", -- center widget is centered on the whole bar + -- Left: layout indicator + workspaces + { layout = wibox.layout.fixed.horizontal, - widgets.padded(s.mytaglist, 8, 4), s.mypromptbox, - { title, left = 18, widget = wibox.container.margin }, + widgets.padded(s.mylayoutbox, 8, 8), + widgets.padded(s.mytaglist, 4, 4), s.mypromptbox, }, - nil, -- empty center + -- Center: focused window title + title, + -- Right widgets.padded(right, 4, 12), } } end) - - -- Overlay for rofi launchers - local dim_overlay = wibox({ - visible = false, - ontop = true, - type = "splash", - bg = "#00000099", - }) - dim_overlay.name = "awesome_dim_overlay" - - awful.screen.connect_for_each_screen(function(s) - dim_overlay.screen = s -- adjust if you want it per-screen vs spanning all - end) - - -- span the primary screen's geometry (or loop over all screens if you use a multi-monitor dim) - local function update_dim_geometry() - local geo = screen.primary.geometry - dim_overlay:geometry(geo) - end - update_dim_geometry() - screen.connect_signal("property::geometry", update_dim_geometry) - - -- expose functions over awesome-client - _G.show_dim = function() dim_overlay.visible = true end - _G.hide_dim = function() dim_overlay.visible = false end - - -- Prime the window so X/picom register its type before first real use, - -- avoiding a one-time grow animation on the very first show_dim() call - dim_overlay.visible = true - gears.timer.delayed_call(function() - dim_overlay.visible = false - end) + -- Overlay for rofi launchers. + -- Real dim colour; the overlay is created fully transparent so the + -- startup prime (below) can run without ever showing on screen. + local DIM_BG = "#00000099" + local dim_overlay = wibox({ + visible = false, + ontop = true, + type = "splash", + bg = "#00000000", + }) + dim_overlay.name = "awesome_dim_overlay" + awful.screen.connect_for_each_screen(function(s) + dim_overlay.screen = s -- adjust if you want it per-screen vs spanning all + end) + -- span the primary screen's geometry (or loop over all screens if you use a multi-monitor dim) + local function update_dim_geometry() + local geo = screen.primary.geometry + dim_overlay:geometry(geo) + end + update_dim_geometry() + screen.connect_signal("property::geometry", update_dim_geometry) + -- expose functions over awesome-client + _G.show_dim = function() dim_overlay.visible = true end + _G.hide_dim = function() dim_overlay.visible = false end + -- Prime the overlay invisibly at startup. While it is fully + -- transparent we map it once, so picom plays and finishes its one-time + -- "open" animation now -- with alpha 00 there is nothing to see, so no + -- flash. We then hide it and swap in the real dim colour. Every later + -- show_dim() is a re-map ("show"), which picom doesn't animate, so the + -- overlay simply appears: no startup flash, no grow. + dim_overlay.visible = true + gears.timer.start_new(1.0, function() + dim_overlay.visible = false + dim_overlay.bg = DIM_BG + return false -- one-shot + end) end - bar_setup() -- ================================================ @@ -435,7 +393,6 @@ awful.rules.rules = { properties = { floating = false, }, callback = function(c) awful.client.setslave(c) - local t = c.first_tag if t then t.master_width_factor = 0.67 @@ -453,20 +410,16 @@ client.connect_signal("manage", function(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 - -- 0 or ie 13 = corner radius + -- 0 or ie 13 = corner radius c.shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, 0) end end) - client.connect_signal("property::floating", function(c) if c.floating and c.type ~= "notification" then awful.placement.centered(c, { honor_workarea = true }) end end) - client.connect_signal("manage", function(c) if c.floating and c.type ~= "notification" then awful.placement.centered(c, { honor_workarea = true }) 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) diff --git a/config/picom/picom.conf b/config/picom/picom.conf index e973138..2217432 100644 --- a/config/picom/picom.conf +++ b/config/picom/picom.conf @@ -7,7 +7,7 @@ fade-out-step = 0.04; ################################# # Corners # ################################# -# corner-radius = 0; +corner-radius = 5; ################################# # FAST SNAPPY ANIMATIONS #