Compare commits

...

8 Commits

Author SHA1 Message Date
jasonhilder 8c06125493 Really never ends. 2026-07-03 10:45:31 +02:00
jasonhilder d7863ed010 Its just dotfiles... 2026-07-03 09:28:42 +02:00
jasonhilder 5bb60e1a35 Getting old now... 2026-07-03 08:13:08 +02:00
jasonhilder 00d3b3c3d9 Testing new remote 2026-07-02 10:17:39 +02:00
jasonhilder 379e008024 Added overlay for rofi menus 2026-07-02 08:21:47 +02:00
jasonhilder e1c3745f3b Awesomewm config into modules. 2026-07-02 07:44:28 +02:00
jasonhilder 1a49af00cc Awesome updates.
Setup naughty for the notification manager.
Stoped default notification service.
Made better rules for window placement.
2026-07-02 07:06:06 +02:00
jasonhilder d3c89f89f6 Rofi scripts for extra menus 2026-07-02 07:04:59 +02:00
18 changed files with 664 additions and 472 deletions
+2 -2
View File
@@ -93,5 +93,5 @@ These are not run automatically by `install.sh` — they are opt-in.
---
This setup prioritises **stability** and **simplicity** over customisation. Void Linux + XFCE4 + X11
provides a fast, predictable base with minimal moving parts.
This setup prioritises **stability** and **simplicity** over customisation.
Void Linux + XFCE4 + X11 provides a fast, predictable base with minimal moving parts.
+32 -13
View File
@@ -1,7 +1,7 @@
[general]
[font]
size = 13
size = 12
offset = { x = 0, y = 3 }
normal = { family = "JetBrainsMono Nerd Font", style = "Regular" }
@@ -14,20 +14,39 @@ padding.y = 10
style.shape = "Beam"
style.blinking = "Always"
# LACKLUSTER COLORS
# Kanagawa Wave Alacritty Colors
[colors.primary]
background = '#101010'
foreground = '#dcd7ba'
[colors.normal]
# black is gray0
black = '#111111'
red = '#C11F1F'
green = '#789978'
yellow = '#ffAA88'
blue = '#7788AA'
magenta = '#BD61A3'
# cyan is set to lack
cyan = '#708090'
# white is set to luster
white = '#DEEEED'
black = '#090618'
red = '#c34043'
green = '#76946a'
yellow = '#c0a36e'
blue = '#7e9cd8'
magenta = '#957fb8'
cyan = '#6a9589'
white = '#c8c093'
[colors.bright]
black = '#727169'
red = '#e82424'
green = '#98bb6c'
yellow = '#e6c384'
blue = '#7fb4ca'
magenta = '#938aa9'
cyan = '#7aa89f'
white = '#dcd7ba'
[colors.selection]
background = '#2d4f67'
foreground = '#c8c093'
[[colors.indexed_colors]]
index = 16
color = '#ffa066'
[[colors.indexed_colors]]
index = 17
color = '#ff5d62'
+116
View File
@@ -0,0 +1,116 @@
local awful = require("awful")
local gears = require("gears")
local wibox = require("wibox")
local beautiful = require("beautiful")
local colors = require("config.colors")
local widgets = require("config.widgets")
local 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)
function M.setup()
awful.screen.connect_for_each_screen(function(s)
set_wallpaper(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 },
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 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)
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
layout = wibox.layout.fixed.horizontal,
widgets.padded(s.mytaglist, 8, 4), s.mypromptbox,
{ title, left = 18, widget = wibox.container.margin },
},
nil, -- empty center
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)
end
return M
+12
View File
@@ -0,0 +1,12 @@
return {
background = "#111111",
background_alt = "#1a1a1a",
foreground = "#dcd7ba", -- kanagawa foreground
accent = "#6a9589", -- black (bright) - muted gray, same role as old #6e6e6e
accent_alt = "#7fb4ca", -- blue (normal) - crystalBlue
red = "#e82424", -- red (bright) - samuraiRed, vivid
green = "#98bb6c", -- green (bright) - springGreen
yellow = "#e6c384", -- yellow (bright) - carpYellow
disabled = "#6a9589", -- cyan (normal) - muted, low-contrast
white = "#ffffff", -- white (normal) - dimmer than foreground
}
+85
View File
@@ -0,0 +1,85 @@
local awful = require("awful")
local gears = require("gears")
local hotkeys_popup = require("awful.hotkeys_popup")
local menubar = require("menubar")
local M = {}
M.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(terminal) end, { description = "open a terminal", 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
awful.key({ modkey, "Control" }, "p", function() awful.spawn("xfce4-screenshooter") end, { description = "screenshot", group = "system" }),
-- Alt tab current workspace windows
awful.key({ "Mod1" }, "Tab", function() awful.client.focus.byidx(1) end),
-- 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 }, "`", 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"}),
-- 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
M.globalkeys = gears.table.join(M.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, "Control" }, "#" .. 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
M.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, "Control" }, "space", awful.client.floating.toggle, { description = "toggle floating", group = "client" })
)
M.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)
)
return M
+20
View File
@@ -0,0 +1,20 @@
local awful = require("awful")
local beautiful = require("beautiful")
local keys = require("config.keys")
return {
{ rule = { }, properties = {
border_width = beautiful.border_width, border_color = beautiful.border_normal,
focus = awful.client.focus.filter, raise = true,
keys = keys.clientkeys, buttons = keys.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 }},
}
+27
View File
@@ -0,0 +1,27 @@
local gears = require("gears")
local awful = require("awful")
local beautiful = require("beautiful")
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
-- 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)
+47
View File
@@ -0,0 +1,47 @@
local gears = require("gears")
local beautiful = require("beautiful")
local naughty = require("naughty")
local colors = require("config.colors")
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
beautiful.taglist_bg_occupied = colors.background
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
naughty.config.padding = 12
naughty.config.defaults.margin = 12
naughty.config.defaults.spacing = 8
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.background_alt,
border_width = 3, font = "JetBrainsMono Nerd Font 12", timeout = 5,
}
naughty.config.presets.low = naughty.config.presets.normal
naughty.config.presets.critical = {
bg = colors.background, fg = colors.red, border_color = colors.red,
border_width = 3, font = "JetBrainsMono Nerd Font 12", timeout = 0, -- stays until dismissed
}
+118
View File
@@ -0,0 +1,118 @@
local awful = require("awful")
local gears = require("gears")
local wibox = require("wibox")
local colors = require("config.colors")
local M = {}
-- "ICON value" with ICON tinted accent, like polybar's *-prefix-foreground.
function M.label(icon, val)
return string.format("<span foreground='%s'>%s</span> %s", colors.white, icon, val or "")
end
-- A slim separator in the disabled color, like polybar's separator.
function M.sep()
local w = wibox.widget.textbox()
w.markup = string.format("<span foreground='%s00'> </span>", colors.disabled)
return w
end
-- Wrap a widget in a small margin so bar modules aren't crammed together.
function M.padded(w, left, right)
return wibox.container.margin(w, left or 8, right or 8)
end
-- Focused window title (polybar xwindow / %title%)
function M.make_title()
local t = wibox.widget.textbox()
local function update()
local c = client.focus
t.markup = c and string.format("<span foreground='%s'>%s</span>", 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)
function M.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 = M.label("<span font_size='large'> </span>", 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 M.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
w.markup = string.format("<span foreground='%s'><span font_size='large'>󱄠</span> n/a</span>", colors.disabled)
return
end
muted = muted == "yes"
pct = pct or "0"
w.markup = muted and string.format("<span foreground='%s'>MUTE</span>", colors.yellow) or M.label("<span font_size='large'>󱄠</span>", 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 M.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 w = wibox.widget.textbox()
local is_day = true
local function render()
local icon = is_day and " 󱁞 " or " 󱠩 "
w.markup = string.format(
"<span font_family='JetBrainsMono Nerd Font' foreground='%s' font_size='large'>%s</span>",
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()
is_day = day
render()
end)
end
w:buttons(gears.table.join(
awful.button({ }, 1, function() apply(not is_day) end)
))
apply(true)
return w
end
return M
+36 -421
View File
@@ -1,437 +1,52 @@
pcall(require, "luarocks.loader")
local gears = require("gears")
local awful = require("awful")
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
local naughty = require("naughty")
local bling = require("bling")
-- Global config
modkey = "Mod1" -- Alt. Use "Mod4" for the Super/Windows key.
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,
}
-- }}}
awful.layout.layouts = { awful.layout.suit.tile, awful.layout.suit.max }
-- {{{ Bar helpers ---------------------------------------------------------
-- "ICON value" with ICON tinted accent, like polybar's *-prefix-foreground.
local function label(icon, val)
return string.format("<span foreground='%s'>%s</span> %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("<span foreground='%s'> │ </span>", 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("<span foreground='%s'>%s</span>", 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("<span foreground='%s'>VOL n/a</span>", colors.disabled)
return
end
muted = muted == "yes"
pct = pct or "0"
if muted then
w.markup = string.format("<span foreground='%s'>MUTE</span>", 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
-- Kill xfce4-notifyd on startup (with a short delay + retry, in case it
-- 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
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)
-- 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
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)
-- }}}
-- Modules (order matters: theme before bar, keys before rules)
require("config.theme")
local keys = require("config.keys")
require("config.bar").setup()
root.keys(keys.globalkeys)
awful.rules.rules = require("config.rules")
require("config.signals")
-- Wallpaper
bling.module.wallpaper.setup {
wallpaper = {"/home/jason/Pictures/Wallpapers/farewell.jpg"},
position = "fit",
background = "#181818"
wallpaper = { "/home/jason/Pictures/Wallpapers/farewell.jpg" },
position = "fit",
background = "#181818",
}
+2 -1
View File
@@ -87,12 +87,13 @@ alias bat='bat --theme="ansi" --paging=never'
# Application shortcuts
alias vi='nvim'
alias :q='exit'
alias lg='lazygit'
alias files='thunar .'
alias fetch='pfetch'
# Custom shortcuts
alias reload='source ~/.config/fish/config.fish'
alias dotf='cd ~/.dotfiles'
alias dots='cd ~/.dotfiles && nvim'
alias doti='bash ~/.dotfiles/install.sh -i'
alias dotl='bash ~/.dotfiles/install.sh -l'
alias myip='curl ipinfo.io/ip; echo ""'
+3 -2
View File
@@ -46,7 +46,8 @@ vim.pack.add({
{ src = 'https://github.com/nvim-tree/nvim-tree.lua' },
{ src = 'https://github.com/romus204/tree-sitter-manager.nvim' },
{ src = 'https://github.com/lukas-reineke/indent-blankline.nvim' },
{ src = 'https://github.com/slugbyte/lackluster.nvim' },
{ src = 'https://github.com/rebelot/kanagawa.nvim' },
{ src = 'https://github.com/rose-pine/neovim' },
{ src = 'https://github.com/xiyaowong/transparent.nvim' },
})
@@ -58,7 +59,7 @@ require("ibl").setup({
indent = { char = "" },
scope = { show_start = false, show_end = false },
})
vim.cmd.colorscheme('lackluster-night')
vim.cmd.colorscheme('kanagawa')
vim.api.nvim_set_hl(0, "WinSeparator", { fg = "#54546D" })
-- Lsp specific, uses nvim-lspconfigs with the below
+10 -2
View File
@@ -7,7 +7,8 @@ fade-out-step = 0.04;
#################################
# Corners #
#################################
corner-radius = 12;
# corner-radius = 0;
#################################
# FAST SNAPPY ANIMATIONS #
#################################
@@ -218,7 +219,7 @@ animations = (
#################################
# General Settings #
#################################
backend = "xrender";
backend = "glx";
dithered-present = false;
vsync = true;
detect-rounded-corners = true;
@@ -274,5 +275,12 @@ rules: (
},
);
},
{
match = "window_type = 'splash' && name = 'awesome_dim_overlay'";
animations = ();
shadow = false;
corner-radius = 0;
fade = false;
},
)
+8 -31
View File
@@ -2,43 +2,35 @@
/* -- Palette, matches colors{} in awesome rc.lua -- */
bg0: #111111; /* colors.background */
bg1: #1a1a1a; /* colors.background_alt */
fg0: #d3dae3; /* colors.foreground */
fg0: #dcd7ba; /* colors.foreground */
fg-selected: #ffffff; /* colors.white */
accent: #616161; /* colors.accent */
accent-alt: #6ba0e8; /* colors.accent_alt */
red: #e35b5b; /* colors.red */
disabled: #707880; /* colors.disabled */
accent: #6a9589; /* colors.accent */
accent-alt: #727169; /* colors.accent_alt */
red: #e82424; /* colors.red */
disabled: #6a9589; /* colors.disabled */
font: "JetBrainsMono Nerd Font 14";
background-color: transparent;
text-color: @fg0;
}
window {
transparency: "real";
/* Anchor top-center, right below the wibar. */
location: north;
anchor: north;
y-offset: 38px;
y-offset: 48px;
width: 32em;
height: 26em; /* fixed — box size no longer changes with result count */
background-color: @bg0;
border: 3px;
border-color: @accent;
border-radius: 13px; /* matches gears.shape.rounded_rect radius in rc.lua */
border-radius: -1px; /* matches gears.shape.rounded_rect radius in rc.lua */
padding: 14px;
}
mainbox {
children: [ inputbar, message, listview, mode-switcher ];
spacing: 10px;
background-color: transparent;
}
/* -- Search field -- */
inputbar {
children: [ prompt, entry ];
@@ -47,23 +39,19 @@ inputbar {
border-radius: 10px;
padding: 10px 14px;
}
prompt {
text-color: @accent-alt;
}
entry {
placeholder: "Search";
placeholder-color: @disabled;
text-color: @fg0;
cursor: text;
}
/* -- List/grid toggle icons, top-right (matches screenshot) -- */
mode-switcher {
enabled: false; /* flip to true if you use rofi's built-in mode tabs */
}
/* -- Results -- */
listview {
lines: 8;
@@ -74,7 +62,6 @@ listview {
fixed-height: true; /* box height stays locked, doesn't shrink/grow with result count */
dynamic: false; /* don't resize dynamically as you type either */
}
/*
* Rofi tracks row state as a combination of position (normal/alternate,
* i.e. even/odd rows for banding) and status (normal/urgent/active/selected).
@@ -87,59 +74,49 @@ element {
border-radius: 10px;
orientation: horizontal;
}
element normal.normal,
element alternate.normal {
background-color: @bg1;
text-color: @fg0;
}
element normal.urgent,
element alternate.urgent {
background-color: @bg1;
text-color: @red;
}
element normal.active,
element alternate.active {
background-color: @bg1;
text-color: @accent-alt;
}
element selected.normal {
background-color: @accent;
background-color: @accent-alt;
text-color: @fg-selected;
}
element selected.urgent {
background-color: @red;
text-color: @fg-selected;
}
element selected.active {
background-color: @accent-alt;
text-color: @bg0;
}
element-icon {
size: 24px;
padding: 0 12px 0 0;
vertical-align: 0.5;
background-color: transparent;
}
element-text {
vertical-align: 0.5;
text-color: inherit;
background-color: transparent;
}
message {
background-color: @bg1;
border-radius: 10px;
padding: 8px 12px;
}
textbox {
text-color: @fg0;
}
+68
View File
@@ -0,0 +1,68 @@
#!/usr/bin/env bash
# rofi-audio-switch: pick a PulseAudio/PipeWire sink via rofi
set -euo pipefail
awesome-client 'show_dim()' >/dev/null 2>&1
trap 'awesome-client "hide_dim()" >/dev/null 2>&1' EXIT
# Get list of sinks: index, name, description
mapfile -t sinks < <(pactl list sinks | awk -F': ' '
/^Sink #/ { idx=$2 }
/Name:/ { name=$2 }
/Description:/ { desc=$2; print idx"\t"name"\t"desc }
')
if [ "${#sinks[@]}" -eq 0 ]; then
notify-send "Audio Switch" "No sinks found"
exit 1
fi
current_sink=$(pactl get-default-sink)
# Build rofi menu: show description, mark current with a star
menu=""
for line in "${sinks[@]}"; do
name=$(echo "$line" | cut -f2)
desc=$(echo "$line" | cut -f3)
if [ "$name" = "$current_sink" ]; then
menu+="* $desc\n"
else
menu+=" $desc\n"
fi
done
chosen=$(echo -e "$menu" | rofi -dmenu -i -p "Audio Output" -markup-rows \
-theme-str 'listview { lines: 3; }' \
-theme-str 'window { height: 220px; }')
[ -z "$chosen" ] && exit 0
# Strip the leading marker to match description text
chosen_desc=$(echo "$chosen" | sed 's/^[* ] //')
# Find matching sink name for that description
target_name=""
for line in "${sinks[@]}"; do
desc=$(echo "$line" | cut -f3)
if [ "$desc" = "$chosen_desc" ]; then
target_name=$(echo "$line" | cut -f2)
break
fi
done
if [ -z "$target_name" ]; then
notify-send "Audio Switch" "Could not resolve selection"
exit 1
fi
# Set as default sink
pactl set-default-sink "$target_name"
# Move all currently running streams to the new sink
mapfile -t inputs < <(pactl list short sink-inputs | cut -f1)
for input in "${inputs[@]}"; do
pactl move-sink-input "$input" "$target_name"
done
notify-send "Audio Switch" "Switched to: $chosen_desc"
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# rofi-bookmarks: pick a Chromium bookmark and open it (new tab or new window)
set -euo pipefail
awesome-client 'show_dim()' >/dev/null 2>&1
trap 'awesome-client "hide_dim()" >/dev/null 2>&1' EXIT
BOOKMARKS_FILE="$HOME/.config/chromium/Default/Bookmarks"
if [ ! -f "$BOOKMARKS_FILE" ]; then
notify-send "Bookmarks" "Chromium bookmarks file not found"
exit 1
fi
# Recursively walk the bookmark tree (roots -> bookmark_bar / other / synced)
# and emit "title\turl" for every leaf ("type": "url"), skipping folders.
list=$(jq -r '
def walk_nodes:
if .type == "url" then
"\(.name)\t\(.url)"
elif .children then
.children[] | walk_nodes
else
empty
end;
.roots | to_entries[] | .value | walk_nodes
' "$BOOKMARKS_FILE")
if [ -z "$list" ]; then
notify-send "Bookmarks" "No bookmarks found"
exit 0
fi
chosen=$(echo "$list" | awk -F'\t' '{print $1}' | rofi -dmenu -i -p "Bookmarks" \
-theme-str 'listview { lines: 5; }' \
-theme-str 'window { width: 21%; }' \
-theme-str 'window { height: 400px; }')
[ -z "$chosen" ] && exit 0
url=$(echo "$list" | awk -F'\t' -v title="$chosen" '$1 == title { print $2; exit }')
[ -z "$url" ] && exit 0
# Open in a new tab of the existing Chromium window if one's running,
# otherwise this also launches Chromium fresh with that tab.
chromium --new-tab "$url"
+27
View File
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# rofi-power-menu: logout / restart / shutdown via rofi
set -euo pipefail
awesome-client 'show_dim()' >/dev/null 2>&1
trap 'awesome-client "hide_dim()" >/dev/null 2>&1' EXIT
options=" Logout\n Restart\n Shutdown"
chosen=$(echo -e "$options" | rofi -dmenu -i -p "Power" -markup-rows \
-theme-str 'listview { lines: 3; }' \
-theme-str 'window { height: 240px; }')
[ -z "$chosen" ] && exit 0
case "$chosen" in
*Logout*)
loginctl terminate-session ${XDG_SESSION_ID-}
;;
*Restart*)
loginctl reboot
;;
*Shutdown*)
loginctl poweroff
;;
esac
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
awesome-client 'show_dim()'
rofi -show drun "$@"
awesome-client 'hide_dim()'