Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19594ff8b3 | ||
|
|
15a20af8a5 | ||
|
|
d014f9c268 | ||
|
|
76226cb637 | ||
|
|
4f391cf1ca | ||
|
|
9663c18c7e | ||
|
|
307163b567 | ||
|
|
3cadcad501 |
No files matched your search
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"diagnostics": {
|
||||
"globals": [
|
||||
"hl"
|
||||
]
|
||||
},
|
||||
"workspace": {
|
||||
"library": [
|
||||
"/usr/share/hypr/stubs",
|
||||
"/usr/share/hyprland/stubs"
|
||||
],
|
||||
"checkThirdParty": false
|
||||
}
|
||||
}
|
||||
+412
@@ -0,0 +1,412 @@
|
||||
-- ~/.config/hypr/functions.lua
|
||||
local M = {}
|
||||
|
||||
-- focusOrLaunch: checks if a window with the given class exists.
|
||||
-- If it does, focuses it (and sends specific shortcuts if it's qutebrowser).
|
||||
-- If not, optionally switches to a workspace and launches the app.
|
||||
function M.focusOrLaunch(app_cmd, class_name, workspace_name)
|
||||
local clients = hl.get_windows()
|
||||
local found = false
|
||||
|
||||
for _, client in ipairs(clients) do
|
||||
if client.class == class_name then
|
||||
hl.dispatch(hl.dsp.focus({ window = "class:" .. class_name }))
|
||||
-- Specific qutebrowser logic ported from your zsh script
|
||||
if app_cmd:match("qutebrowser") then
|
||||
hl.dispatch(hl.dsp.send_shortcut({ mods = "", key = "Escape", window = "class:" .. class_name }))
|
||||
hl.dispatch(hl.dsp.send_shortcut({ mods = "", key = "0", window = "class:" .. class_name }))
|
||||
hl.dispatch(hl.dsp.send_shortcut({ mods = "", key = "1", window = "class:" .. class_name }))
|
||||
hl.dispatch(hl.dsp.send_shortcut({ mods = "ALT", key = "J", window = "class:" .. class_name }))
|
||||
hl.dispatch(hl.dsp.send_shortcut({ mods = "", key = "Escape", window = "class:" .. class_name }))
|
||||
end
|
||||
found = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not found then
|
||||
if workspace_name and #workspace_name > 0 then
|
||||
hl.dispatch(hl.dsp.focus({ workspace = workspace_name }))
|
||||
end
|
||||
hl.dispatch(hl.dsp.exec_cmd(app_cmd))
|
||||
end
|
||||
end
|
||||
|
||||
function M.getActiveWorkspaceName()
|
||||
local f = io.popen("hyprctl -j activeworkspace | jq -r '.name'")
|
||||
local active_ws_name = f:read("*a"):gsub("%s+", "")
|
||||
f:close()
|
||||
return active_ws_name
|
||||
end
|
||||
|
||||
function M.mv2workspace()
|
||||
local cmd = [[
|
||||
bash -c '
|
||||
WORKSPACES=$(hyprctl -j workspaces | jq -r ".[] | .name")
|
||||
ACTIVE="$(hyprctl -j activewindow)"
|
||||
CLASS="$(jq -r ".class" <<< "$ACTIVE")"
|
||||
TITLE="$(jq -r ".title" <<< "$ACTIVE")"
|
||||
ADDR="$(jq -r ".address" <<< "$ACTIVE")"
|
||||
PROMPT="Move window of ${CLASS} with title '\''${TITLE}'\'' to which workspace? "
|
||||
NEW_WS="$(echo "$WORKSPACES" | rofi -dmenu -p "$PROMPT")"
|
||||
if [ -n "$NEW_WS" ]; then
|
||||
hyprctl dispatch "hl.dsp.window.move({ workspace = \"$NEW_WS\", window = \"address:$ADDR\", follow = false })"
|
||||
fi
|
||||
'
|
||||
]]
|
||||
hl.dispatch(hl.dsp.exec_cmd(cmd))
|
||||
end
|
||||
|
||||
function M.createWorkspace(after_name)
|
||||
local after_str = after_name or ""
|
||||
local cmd = string.format([[
|
||||
bash -c '
|
||||
NEW_NAME=$(rofi -dmenu -p "new workspace name" -l 0 < /dev/null | tr -d "[:space:]")
|
||||
if [ -z "$NEW_NAME" ]; then exit 0; fi
|
||||
|
||||
ACTIVE_MON=$(hyprctl -j monitors | jq -r ".[] | select(.focused) | .name")
|
||||
NEW_LINE=" { name = \"$NEW_NAME\", monitor = \"$ACTIVE_MON\" },"
|
||||
FILE="$HOME/.config/hypr/workspace_config.lua"
|
||||
|
||||
AFTER="%s"
|
||||
|
||||
if [ -n "$AFTER" ] && grep -q "name *= *\"$AFTER\"" "$FILE"; then
|
||||
sed -i "/name *= *\"$AFTER\"/a \\$NEW_LINE" "$FILE"
|
||||
else
|
||||
sed -i "/^}/i \\$NEW_LINE" "$FILE"
|
||||
fi
|
||||
hyprctl reload
|
||||
'
|
||||
]], after_str)
|
||||
hl.dispatch(hl.dsp.exec_cmd(cmd))
|
||||
end
|
||||
|
||||
function M.deleteWorkspace()
|
||||
local cmd = [[
|
||||
bash -c '
|
||||
ACTIVE_WS=$(hyprctl -j activeworkspace | jq -r ".name")
|
||||
if [ -z "$ACTIVE_WS" ]; then exit 0; fi
|
||||
FILE="$HOME/.config/hypr/workspace_config.lua"
|
||||
sed -i "/name *= *\"$ACTIVE_WS\"/d" "$FILE"
|
||||
hyprctl dispatch "hl.dsp.focus({ workspace = \"m-1\" })"
|
||||
hyprctl reload
|
||||
'
|
||||
]]
|
||||
hl.dispatch(hl.dsp.exec_cmd(cmd))
|
||||
end
|
||||
|
||||
function M.moveWorkspace(direction, target_monitor)
|
||||
-- If no target_monitor is provided and direction is nil, prompt interactively via async bash to avoid deadlocks
|
||||
if (not target_monitor or target_monitor == "") and not direction then
|
||||
local cmd = [[
|
||||
bash -c '
|
||||
ACTIVE_WS=$(hyprctl -j activeworkspace | jq -r ".name")
|
||||
if [ -z "$ACTIVE_WS" ]; then exit 0; fi
|
||||
MONITORS=$(hyprctl -j monitors | jq -r ".[].name")
|
||||
PROMPT="Move workspace '\''$ACTIVE_WS'\'' to which monitor? "
|
||||
NEW_MON=$(echo "$MONITORS" | rofi -dmenu -p "$PROMPT")
|
||||
if [ -n "$NEW_MON" ]; then
|
||||
FILE="$HOME/.config/hypr/workspace_config.lua"
|
||||
sed -i -E "/name *= *\"$ACTIVE_WS\"/ s/monitor *= *\"[^\"]+\"/monitor = \"$NEW_MON\"/" "$FILE"
|
||||
hyprctl reload
|
||||
fi
|
||||
'
|
||||
]]
|
||||
hl.dispatch(hl.dsp.exec_cmd(cmd))
|
||||
return
|
||||
end
|
||||
|
||||
-- NATIVE LUA PATH for directional shifts or explicit monitor arguments passed from keybinds
|
||||
local active_ws_name = M.getActiveWorkspaceName()
|
||||
if not active_ws_name or active_ws_name == "" then return end
|
||||
|
||||
local path = os.getenv("HOME") .. "/.config/hypr/workspace_config.lua"
|
||||
local f_in = io.open(path, "r")
|
||||
if not f_in then return end
|
||||
|
||||
local lines = {}
|
||||
local ws_idx = nil
|
||||
|
||||
for line in f_in:lines() do
|
||||
table.insert(lines, line)
|
||||
if line:match('name%s*=%s*"' .. active_ws_name .. '"') then
|
||||
ws_idx = #lines
|
||||
end
|
||||
end
|
||||
f_in:close()
|
||||
|
||||
if not ws_idx then return end
|
||||
|
||||
if target_monitor and target_monitor ~= "" then
|
||||
lines[ws_idx] = lines[ws_idx]:gsub('monitor%s*=%s*"[^"]+"', 'monitor = "' .. target_monitor .. '"')
|
||||
end
|
||||
|
||||
if direction then
|
||||
local first_idx = 2
|
||||
local last_idx = #lines - 1
|
||||
|
||||
while first_idx < #lines and not lines[first_idx]:match("name%s*=") do first_idx = first_idx + 1 end
|
||||
while last_idx > 1 and not lines[last_idx]:match("name%s*=") do last_idx = last_idx - 1 end
|
||||
|
||||
if first_idx <= last_idx then
|
||||
local current_line = table.remove(lines, ws_idx)
|
||||
local new_idx = ws_idx
|
||||
|
||||
if direction > 0 then
|
||||
new_idx = ws_idx + 1
|
||||
if new_idx > last_idx then
|
||||
new_idx = first_idx
|
||||
end
|
||||
elseif direction < 0 then
|
||||
new_idx = ws_idx - 1
|
||||
if new_idx < first_idx then
|
||||
new_idx = last_idx
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(lines, new_idx, current_line)
|
||||
end
|
||||
end
|
||||
|
||||
local f_out = io.open(path, "w")
|
||||
for _, line in ipairs(lines) do
|
||||
f_out:write(line .. "\n")
|
||||
end
|
||||
f_out:close()
|
||||
|
||||
hl.dispatch(hl.dsp.exec_cmd("hyprctl reload"))
|
||||
end
|
||||
|
||||
function M.pasteMacro(script_path)
|
||||
local cmd = string.format([[
|
||||
bash -c '
|
||||
exec > /tmp/paste.log 2>&1
|
||||
out="$(%s)"
|
||||
echo -n "$out" | wl-copy
|
||||
|
||||
# 1. Wait a moment for physical keys to be released
|
||||
sleep 0.3
|
||||
# 2. Release modifiers logically, then execute CTRL+V
|
||||
wtype -m logo -m ctrl -m shift -m alt -M ctrl -k v -m ctrl
|
||||
|
||||
# 3. Wait a full second to ensure Wayland apps finish reading the clipboard asynchronously
|
||||
sleep 1.0
|
||||
|
||||
# 4. Scrub the password from cliphist securely
|
||||
PREV=$(cliphist list | awk "NR==2")
|
||||
cliphist list | awk "NR==1" | cliphist delete
|
||||
if [ -n "$PREV" ]; then
|
||||
echo "$PREV" | cliphist decode | wl-copy
|
||||
else
|
||||
wl-copy -c
|
||||
fi
|
||||
'
|
||||
]], script_path)
|
||||
hl.dispatch(hl.dsp.exec_cmd(cmd))
|
||||
end
|
||||
|
||||
function M.pasteText(text)
|
||||
local cmd = string.format([[
|
||||
bash -c '
|
||||
exec &> /tmp/$(date +%%FT%%H%%M%%S)_paste.log
|
||||
echo -n "%s" | wl-copy
|
||||
|
||||
# Wait a moment for physical keys to be released, then execute CTRL+V
|
||||
sleep 0.3
|
||||
wtype -m logo -m ctrl -m shift -m alt -M ctrl -k v -m ctrl
|
||||
# Note: We do not scrub cliphist here because dates are not sensitive passwords,
|
||||
# which completely eliminates the paste race condition for dates!
|
||||
'
|
||||
]], text)
|
||||
hl.dispatch(hl.dsp.exec_cmd(cmd))
|
||||
end
|
||||
|
||||
function M.timetracker()
|
||||
local cmd = [[
|
||||
bash -c '
|
||||
CHOICE=$(echo -e "Begin...\nEnd..." | rofi -dmenu -theme-str "inputbar {enabled: false;}" -i -matching prefix -auto-select -l 2)
|
||||
if [ "$CHOICE" = "Begin..." ]; then
|
||||
DATE_STR=$(date "+%F %T")
|
||||
wtype -m logo -m ctrl -m shift -m alt -k Escape
|
||||
wtype "I${DATE_STR}: Begin "
|
||||
elif [ "$CHOICE" = "End..." ]; then
|
||||
DATE_STR=$(date "+%F %T")
|
||||
wtype -m logo -m ctrl -m shift -m alt -k Escape
|
||||
wtype "I${DATE_STR}: End "
|
||||
wtype -k Escape
|
||||
wtype "kly\$jpo"
|
||||
wtype "${DATE_STR}: Begin "
|
||||
fi
|
||||
'
|
||||
]]
|
||||
hl.dispatch(hl.dsp.exec_cmd(cmd))
|
||||
end
|
||||
|
||||
function M.randomizeWallpaper()
|
||||
local monitors = hl.get_monitors()
|
||||
local home = os.getenv("HOME")
|
||||
local april_dir = home .. "/images/April"
|
||||
local sbm_dir = home .. "/images/Seven Beats Music"
|
||||
local black_png = home .. "/images/black.png"
|
||||
|
||||
-- Determine if we are on the home WiFi ("keep")
|
||||
local is_home_wifi = false
|
||||
local f = io.popen("iwgetid -r 2>/dev/null")
|
||||
if f then
|
||||
local ssid = f:read("*a")
|
||||
f:close()
|
||||
if ssid and ssid:match("keep") then
|
||||
is_home_wifi = true
|
||||
end
|
||||
end
|
||||
|
||||
-- Select image source based on location
|
||||
local img_dir = april_dir
|
||||
if #monitors > 1 then
|
||||
img_dir = sbm_dir
|
||||
elseif is_home_wifi then
|
||||
img_dir = april_dir
|
||||
end
|
||||
|
||||
local images = {}
|
||||
local handle = io.popen('find "' .. img_dir .. '" -type f \\( -iname "*.jpg" -o -iname "*.png" -o -iname "*.jpeg" \\) 2>/dev/null')
|
||||
if handle then
|
||||
for line in handle:lines() do
|
||||
table.insert(images, line)
|
||||
end
|
||||
handle:close()
|
||||
end
|
||||
|
||||
if #images == 0 then
|
||||
table.insert(images, black_png)
|
||||
end
|
||||
|
||||
local conf_lines = {
|
||||
"ipc = on",
|
||||
"splash = false",
|
||||
""
|
||||
}
|
||||
|
||||
-- Pick a unique random image for each monitor
|
||||
math.randomseed(os.time())
|
||||
local used = {}
|
||||
local matugen_cmds = {}
|
||||
local primary_logical_name = "eDP-1"
|
||||
for _, mon in ipairs(monitors) do
|
||||
if mon.description and mon.description:match("E3LMTF071391") then
|
||||
primary_logical_name = "DP-8"
|
||||
end
|
||||
end
|
||||
|
||||
for _, mon in ipairs(monitors) do
|
||||
local img = nil
|
||||
local attempts = 0
|
||||
while attempts < #images do
|
||||
local idx = math.random(1, #images)
|
||||
if not used[idx] then
|
||||
img = images[idx]
|
||||
used[idx] = true
|
||||
break
|
||||
end
|
||||
attempts = attempts + 1
|
||||
end
|
||||
if not img then img = images[1] end -- fallback if we run out of unique images
|
||||
|
||||
if img then
|
||||
table.insert(conf_lines, "wallpaper {")
|
||||
table.insert(conf_lines, " monitor = " .. mon.name)
|
||||
table.insert(conf_lines, " path = " .. img)
|
||||
table.insert(conf_lines, " fit_mode = cover")
|
||||
table.insert(conf_lines, "}")
|
||||
table.insert(conf_lines, "")
|
||||
|
||||
local logical_name = mon.name
|
||||
if mon.description then
|
||||
if mon.description:match("E3LMTF071438") then logical_name = "DP-7" end
|
||||
if mon.description:match("E3LMTF071391") then logical_name = "DP-8" end
|
||||
end
|
||||
local matugen_cmd = "matugen image '" .. img .. "' -c /home/trey/src/dotfiles/matugen/matugen-" .. logical_name .. ".toml --source-color-index 0"
|
||||
|
||||
-- Push primary monitor to the end of the array so its global configs (like tmux) overwrite the others
|
||||
if logical_name == primary_logical_name then
|
||||
table.insert(matugen_cmds, matugen_cmd)
|
||||
else
|
||||
table.insert(matugen_cmds, 1, matugen_cmd)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #matugen_cmds > 0 then
|
||||
local all_cmds = table.concat(matugen_cmds, " ; ")
|
||||
local reload_cmd = M.reloadAppsCmd()
|
||||
hl.dispatch(hl.dsp.exec_cmd("bash -c \"" .. all_cmds .. " ; " .. reload_cmd .. "\""))
|
||||
end
|
||||
|
||||
local c = io.open(home .. "/.config/hypr/hyprpaper.conf", "w")
|
||||
if c then
|
||||
c:write(table.concat(conf_lines, "\n"))
|
||||
c:close()
|
||||
end
|
||||
|
||||
-- Restart hyprpaper natively to avoid uwsm systemd rate limits on rapid monitor hotplugs
|
||||
hl.dispatch(hl.dsp.exec_cmd("killall -q hyprpaper; sleep 0.2; hyprpaper &"))
|
||||
end
|
||||
|
||||
function M.reloadAppsCmd()
|
||||
-- Return a shell command to reload apps that don't auto-reload (executed sequentially after matugen)
|
||||
local cmds = {
|
||||
"tmux source ~/.config/tmux/tmux.conf",
|
||||
"for pane in $(tmux list-panes -a -F '#{pane_id} #{pane_current_command}' | awk '$2 == \"vim\" {print $1}'); do tmux send-keys -t $pane Escape ':colorscheme matugen' Enter; done",
|
||||
"killall -q -USR1 zsh"
|
||||
}
|
||||
return table.concat(cmds, " ; ")
|
||||
end
|
||||
|
||||
function M.setupMonitors()
|
||||
-- Automatically handle the wallpaper update natively
|
||||
M.randomizeWallpaper()
|
||||
|
||||
local monitors = hl.get_monitors()
|
||||
local logical_to_physical = {
|
||||
["eDP-1"] = "eDP-1"
|
||||
}
|
||||
|
||||
for _, mon in ipairs(monitors) do
|
||||
if mon.description then
|
||||
if mon.description:match("E3LMTF071438") then logical_to_physical["DP-7"] = mon.name end
|
||||
if mon.description:match("E3LMTF071391") then logical_to_physical["DP-8"] = mon.name end
|
||||
end
|
||||
end
|
||||
|
||||
local home = os.getenv("HOME")
|
||||
for logical, physical in pairs(logical_to_physical) do
|
||||
local config_path = home .. "/.config/waybar/config-" .. logical .. ".jsonc"
|
||||
local f = io.open(config_path, "r")
|
||||
if f then
|
||||
local content = f:read("*a")
|
||||
f:close()
|
||||
-- Replace any existing output value with the actual physical monitor name
|
||||
content = content:gsub('"output":%s*"[^"]+"', '"output": "' .. physical .. '"')
|
||||
local w = io.open(config_path, "w")
|
||||
if w then
|
||||
w:write(content)
|
||||
w:close()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Dynamically spawn waybar only for connected monitors, and use a robust kill sequence
|
||||
-- inside the background script to prevent race conditions during rapid hotplug events
|
||||
local waybar_cmds = {
|
||||
"killall -q waybar",
|
||||
"sleep 0.5",
|
||||
"killall -q waybar"
|
||||
}
|
||||
for logical, _ in pairs(logical_to_physical) do
|
||||
table.insert(waybar_cmds, string.format("nohup waybar -c ~/.config/waybar/config-%s.jsonc -s ~/.config/waybar/style-%s.css >/dev/null 2>&1 &", logical, logical))
|
||||
end
|
||||
|
||||
hl.dispatch(hl.dsp.exec_cmd("bash -c '" .. table.concat(waybar_cmds, "\n") .. "'"))
|
||||
end
|
||||
|
||||
return M
|
||||
+8
-12
@@ -1,7 +1,8 @@
|
||||
general {
|
||||
lock_cmd = pidof hyprlock || hyprlock # avoid starting multiple hyprlock instances.
|
||||
unlock_cmd = ~/.local/bin/unlock-ring.sh # run when session is unlocked (hyprlock exits)
|
||||
before_sleep_cmd = loginctl lock-session # lock before suspend.
|
||||
after_sleep_cmd = hyprctl dispatch dpms on # to avoid having to press a key twice to turn on the display.
|
||||
after_sleep_cmd = hyprctl eval 'hl.dispatch(hl.dsp.dpms({ action = "on" }))' # to avoid having to press a key twice to turn on the display.
|
||||
}
|
||||
|
||||
listener {
|
||||
@@ -17,26 +18,21 @@ listener {
|
||||
on-resume = brightnessctl -rd rgb:kbd_backlight # turn on keyboard backlight.
|
||||
}
|
||||
|
||||
#listener {
|
||||
# timeout = 300 # 5min
|
||||
# on-timeout = loginctl lock-session # lock screen when timeout has passed
|
||||
#}
|
||||
|
||||
listener {
|
||||
timeout = 300
|
||||
# 1. Lock the vault via DBus, 2. Start the lock screen
|
||||
on-timeout = busctl --user call org.freedesktop.secrets /org/freedesktop/secrets org.freedesktop.Secret.Service Lock "as" 1 "/org/freedesktop/secrets/aliases/default" && hyprlock
|
||||
# When hyprlock exits (via fingerprint or password), instantly run the unlock script
|
||||
on-resume = ~/.local/bin/unlock-ring.sh
|
||||
# 1. Lock the vault via DBus, 2. Start the lock screen (using ';' so it locks even if the vault fails/is already locked)
|
||||
on-timeout = busctl --user call org.freedesktop.secrets /org/freedesktop/secrets org.freedesktop.Secret.Service Lock "as" 1 "/org/freedesktop/secrets/aliases/default" ; loginctl lock-session
|
||||
}
|
||||
|
||||
listener {
|
||||
timeout = 330 # 5.5min
|
||||
on-timeout = hyprctl dispatch dpms off # screen off when timeout has passed
|
||||
on-resume = hyprctl dispatch dpms on # screen on when activity is detected after timeout has fired.
|
||||
on-timeout = hyprctl eval 'hl.dispatch(hl.dsp.dpms({ action = "off" }))' # screen off when timeout has passed
|
||||
on-resume = hyprctl eval 'hl.dispatch(hl.dsp.dpms({ action = "on" }))' # screen on when activity is detected after timeout has fired.
|
||||
}
|
||||
|
||||
listener {
|
||||
timeout = 900 # 10min
|
||||
on-timeout = systemd-ac-power || systemctl suspend # only suspend pc on battery
|
||||
}
|
||||
|
||||
# vim:ft=hyprlang
|
||||
+317
@@ -0,0 +1,317 @@
|
||||
-- ~/.config/hypr/hyprland.luaA
|
||||
|
||||
-----------------------------------------------------
|
||||
-- Variables (from variables.conf)
|
||||
-----------------------------------------------------
|
||||
local copy = "wl-copy --trim-newline"
|
||||
local paste = "wl-paste"
|
||||
local launcher = "rofi -show run -p 'launch'"
|
||||
-- local clear = "cliphist list | head -n1 | cliphist delete"
|
||||
|
||||
|
||||
-----------------------------------------------------
|
||||
-- Monitors (from monitors.conf)
|
||||
-----------------------------------------------------
|
||||
hl.monitor({ output = "desc:Ancor Communications Inc ASUS VS228 E3LMTF071438", mode = "preferred", position = "0x0", scale = "1" }) -- DP-7, left
|
||||
hl.monitor({ output = "desc:Samsung Display Corp. 0x4193", mode = "preferred", position = "1920x0", scale = "2" }) -- eDP-1, center
|
||||
hl.monitor({ output = "desc:Ancor Communications Inc ASUS VS228 E3LMTF071391", mode = "preferred", position = "3360x0", scale = "1" }) -- DP-8, right
|
||||
hl.monitor({ output = "desc:Stargate Technology FHD", mode = "preferred", position = "auto", scale = "auto" }) -- portable monitor
|
||||
|
||||
|
||||
-----------------------------------------------------
|
||||
-- Environment Variables (from env.conf)
|
||||
-----------------------------------------------------
|
||||
hl.env("GDK_BACKEND", "wayland,x11,*")
|
||||
hl.env("GUI_ENABLE_WAYLAND", "1")
|
||||
hl.env("HYPRCURSOR_SIZE", "18")
|
||||
hl.env("QT_QPA_PLATFORM", "wayland;xcb")
|
||||
hl.env("QT_QPA_PLATFORMTHEME", "qt6ct")
|
||||
hl.env("QT_AUTO_SCREEN_SCALE_FACTOR", "1")
|
||||
hl.env("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1")
|
||||
hl.env("XCURSOR_SIZE", "18")
|
||||
hl.env("XDG_CURRENT_DESKTOP", "Hyprland")
|
||||
hl.env("XDG_SESSION_TYPE", "wayland")
|
||||
hl.env("XDG_SESSION_DESKTOP", "Hyprland")
|
||||
|
||||
|
||||
-----------------------------------------------------
|
||||
-- Appearance & Input (from appearance.conf & input.conf)
|
||||
-----------------------------------------------------
|
||||
hl.config({
|
||||
general = {
|
||||
gaps_in = 1,
|
||||
gaps_out = 2,
|
||||
border_size = 2,
|
||||
col = {
|
||||
active_border = "rgba(fabd2f99)",
|
||||
inactive_border = "rgba(595959aa)",
|
||||
},
|
||||
resize_on_border = false,
|
||||
allow_tearing = false,
|
||||
layout = "dwindle"
|
||||
},
|
||||
|
||||
decoration = {
|
||||
rounding = 10,
|
||||
rounding_power = 2,
|
||||
active_opacity = 1.0,
|
||||
inactive_opacity = 1.0,
|
||||
shadow = {
|
||||
enabled = true,
|
||||
range = 4,
|
||||
render_power = 3,
|
||||
color = "rgba(1a1a1aee)"
|
||||
},
|
||||
blur = {
|
||||
enabled = true,
|
||||
size = 3,
|
||||
passes = 1,
|
||||
vibrancy = 0.1696
|
||||
}
|
||||
},
|
||||
|
||||
animations = {
|
||||
enabled = true,
|
||||
bezier = {
|
||||
"easeOutQuint,0.23,1,0.32,1",
|
||||
"easeInOutCubic,0.65,0.05,0.36,1",
|
||||
"linear,0,0,1,1",
|
||||
"almostLinear,0.5,0.5,0.75,1.0",
|
||||
"quick,0.15,0,0.1,1"
|
||||
},
|
||||
animation = {
|
||||
"global, 1, 10, default",
|
||||
"border, 1, 5.39, easeOutQuint",
|
||||
"windows, 1, 4.79, easeOutQuint",
|
||||
"windowsIn, 1, 4.1, easeOutQuint, popin 87%",
|
||||
"windowsOut, 1, 1.49, linear, popin 87%",
|
||||
"fadeIn, 1, 1.73, almostLinear",
|
||||
"fadeOut, 1, 1.46, almostLinear",
|
||||
"fade, 1, 3.03, quick",
|
||||
"layers, 1, 3.81, easeOutQuint",
|
||||
"layersIn, 1, 4, easeOutQuint, fade",
|
||||
"layersOut, 1, 1.5, linear, fade",
|
||||
"fadeLayersIn, 1, 1.79, almostLinear",
|
||||
"fadeLayersOut, 1, 1.39, almostLinear",
|
||||
"workspaces, 1, 1.94, almostLinear, fade",
|
||||
"workspacesIn, 1, 1.21, almostLinear, fade",
|
||||
"workspacesOut, 1, 1.94, almostLinear, fade"
|
||||
}
|
||||
},
|
||||
|
||||
dwindle = { preserve_split = true },
|
||||
master = { new_status = "master" },
|
||||
misc = {
|
||||
on_focus_under_fullscreen = 1,
|
||||
force_default_wallpaper = 0,
|
||||
disable_hyprland_logo = true
|
||||
},
|
||||
|
||||
input = {
|
||||
resolve_binds_by_sym = 1,
|
||||
kb_layout = "us, us",
|
||||
kb_variant = "colemak,",
|
||||
kb_options = "ctrl:nocaps, compose:ralt, grp:ctrls_toggle",
|
||||
follow_mouse = 1,
|
||||
sensitivity = 0,
|
||||
touchpad = { natural_scroll = false }
|
||||
}})
|
||||
|
||||
hl.device({
|
||||
name = "epic-mouse-v1",
|
||||
sensitivity = -0.5
|
||||
})
|
||||
|
||||
|
||||
-----------------------------------------------------
|
||||
-- Window Rules (from windowrules.conf)
|
||||
-----------------------------------------------------
|
||||
-- XWayland dragging
|
||||
hl.window_rule({
|
||||
no_focus = true,
|
||||
match = { xwayland = true, float = true, fullscreen = false, pin = false }
|
||||
})
|
||||
|
||||
-- Floating rules
|
||||
local float_class_regex = "(gcr-prompter|qt5ct|qt6ct|simple-scan|espanso|nm-applet)"
|
||||
local float_title_regex = "(\"HP Device Manager - Plug-in Installer\")"
|
||||
local float_regex = "(" .. float_class_regex .. "|" .. float_title_regex .. ")"
|
||||
|
||||
hl.window_rule({ float = true, match = { class = float_class_regex } })
|
||||
hl.window_rule({ float = true, match = { title = float_title_regex } })
|
||||
|
||||
-- Pin rules
|
||||
local pin_regex = "(gcr-prompter|nm-applet)"
|
||||
hl.window_rule({ pin = true, match = { class = pin_regex } })
|
||||
|
||||
-- Maximize everything else (fixed typo fioat_regex -> float_regex)
|
||||
hl.window_rule({
|
||||
maximize = true,
|
||||
match = { class = "negative:" .. float_regex }
|
||||
})
|
||||
|
||||
-- Espanso on special
|
||||
hl.window_rule({
|
||||
workspace = "special",
|
||||
match = { title = "Espanso Sync Tool" }
|
||||
})
|
||||
|
||||
-- App-specific workspaces
|
||||
local browsers = "(.*qutebrowser.*|.*[Ff]irefox.*)"
|
||||
local meeting = "(.*[Zz]oom.*)"
|
||||
|
||||
hl.window_rule({ workspace = "name:shell", match = { class = ".*[Aa]lacritty.*" } })
|
||||
hl.window_rule({ workspace = "name:browser silent", match = { class = browsers } })
|
||||
hl.window_rule({ workspace = "name:jobs silent", match = { class = ".*[Vv]ivaldi-stable.*" } })
|
||||
hl.window_rule({ workspace = "name:meeting silent", match = { class = meeting } })
|
||||
|
||||
|
||||
-----------------------------------------------------
|
||||
-- Workspaces (from workspaces.conf)
|
||||
-----------------------------------------------------
|
||||
require("workspaces")
|
||||
|
||||
|
||||
-----------------------------------------------------
|
||||
-- Keybindings & Macros (from keybindings.conf & macros.conf)
|
||||
-----------------------------------------------------
|
||||
local bind = hl.bind
|
||||
local dsp = hl.dsp
|
||||
local fn = require("functions")
|
||||
|
||||
bind("SUPER + Q", dsp.exec_cmd("hyprctl reload && hyprctl eval 'require(\"functions\").setupMonitors()' && notify-send 'Hyprland' 'Config Reloaded' -u low -t 2000"))
|
||||
-- BUG FIX: SUPER + SHIFT + Q was bound to both tmux kill and uwsm stop.
|
||||
-- bind("SUPER + SHIFT + Q", dsp.exec_cmd("tmux kill-server"))
|
||||
bind("SUPER + SHIFT + Q", dsp.exec_cmd("killall -q signal-desktop; uwsm stop"))
|
||||
bind("CTRL + ALT + Delete", dsp.exec_cmd("bash ~/.config/hypr/scripts/sysmenu.sh"))
|
||||
|
||||
bind("SUPER + L", dsp.exec_cmd("hyprlock"))
|
||||
bind("switch:Lid Switch", dsp.exec_cmd("hyprlock"))
|
||||
|
||||
-- Screenshots (evaluated natively in Lua at keypress time)
|
||||
bind("CTRL + SHIFT + 3", function()
|
||||
local cmd = string.format("grim 'images/screenshots/%s_screenshot.png' && paplay ~/wav/camera.wav", os.date("%FT%H%M%S"))
|
||||
hl.dispatch(hl.dsp.exec_cmd(cmd))
|
||||
end)
|
||||
bind("CTRL + SHIFT + 4", function()
|
||||
local cmd = string.format("slurp | grim -g - '%s_screenshot.png' && paplay ~/wav/camera.wav", os.date("%FT%H%M%S"))
|
||||
hl.dispatch(hl.dsp.exec_cmd(cmd))
|
||||
end)
|
||||
|
||||
-- App launchers using our custom Lua focusOrLaunch function
|
||||
bind("SUPER + return", function() fn.focusOrLaunch("alacritty", "Alacritty") end)
|
||||
bind("SUPER + SHIFT + A", function() fn.focusOrLaunch("slack", "Slack", "Slack") end)
|
||||
bind("SUPER + SHIFT + D", function() fn.focusOrLaunch("gnome-dictionary", "org.gnome.Dictionary", "org.gnome.Dictionary") end)
|
||||
bind("SUPER + G", function() fn.focusOrLaunch("vivaldi-stable", "vivaldi-stable", "vivaldi-stable") end)
|
||||
bind("SUPER + ALT + H", function() fn.focusOrLaunch("qutebrowser", "org.qutebrowser.qutebrowser") end)
|
||||
|
||||
-- Windows 11 equivalent shortcuts
|
||||
bind("SUPER + S", dsp.exec_cmd(launcher)) -- Win+S for Search/Launcher
|
||||
bind("SUPER + R", dsp.exec_cmd(launcher)) -- Win+R for Run
|
||||
bind("SUPER + E", dsp.exec_cmd("nautilus")) -- Win+E for Explorer
|
||||
bind("SUPER + V", dsp.exec_cmd("cliphist list | rofi -dmenu -p 'paste' | cliphist decode | " .. copy .. " && " .. paste)) -- Win+V for Clipboard
|
||||
bind("SUPER + SHIFT + S", function() fn.focusOrLaunch("pavucontrol", "org.pulseaudio.pavucontrol", "org.pulseaudio.pavucontrol") end)
|
||||
|
||||
-- Window control
|
||||
bind("SUPER + C", dsp.window.close())
|
||||
bind("ALT + F4", dsp.window.close())
|
||||
bind("SUPER + T", dsp.window.float({ action = "toggle" }))
|
||||
bind("SUPER + space", dsp.window.fullscreen({ mode = 1 }))
|
||||
|
||||
-- Cycle Layouts
|
||||
local layouts = { "dwindle", "master", "scrolling" }
|
||||
local layout_icons = { dwindle = "", master = "", scrolling = "" }
|
||||
local layout_idx = 1
|
||||
|
||||
local function cycle_layout()
|
||||
layout_idx = (layout_idx % #layouts) + 1
|
||||
local new_layout = layouts[layout_idx]
|
||||
|
||||
hl.config({ general = { layout = new_layout } })
|
||||
|
||||
os.execute("echo '" .. layout_icons[new_layout] .. "' > /tmp/hypr_layout.txt")
|
||||
os.execute("pkill -RTMIN+8 waybar")
|
||||
end
|
||||
|
||||
bind("SUPER + right", function() cycle_layout() end)
|
||||
bind("SUPER + left", function() cycle_layout() end)
|
||||
bind("SUPER + up", dsp.window.fullscreen({ mode = 1 }))
|
||||
bind("SUPER + down", hl.dsp.window.cycle_next())
|
||||
|
||||
-- XMonad-style cycle & Alt+Tab (using native dsp dispatchers)
|
||||
bind("SUPER + J", hl.dsp.window.cycle_next())
|
||||
bind("SUPER + K", hl.dsp.window.cycle_next({ prev = true }))
|
||||
bind("ALT + Tab", hl.dsp.window.cycle_next())
|
||||
bind("ALT + SHIFT + Tab", hl.dsp.window.cycle_next({ prev = true }))
|
||||
|
||||
bind("SUPER + X", dsp.exec_cmd("dunstctl close"))
|
||||
bind("SUPER + Y", dsp.exec_cmd("dunstctl close-all"))
|
||||
|
||||
-- Workspace control
|
||||
bind("SUPER + CTRL + right", function() hl.dispatch(hl.dsp.focus({ workspace = "m+1" })) end)
|
||||
bind("SUPER + CTRL + left", function() hl.dispatch(hl.dsp.focus({ workspace = "m-1" })) end)
|
||||
bind("SUPER + SHIFT + H", function() hl.dispatch(hl.dsp.focus({ workspace = "m-1" })) end)
|
||||
bind("SUPER + SHIFT + L", function() hl.dispatch(hl.dsp.focus({ workspace = "m+1" })) end)
|
||||
bind("SUPER + SHIFT + M", function() fn.mv2workspace() end)
|
||||
bind("SUPER + SHIFT + N", function() fn.createWorkspace() end)
|
||||
bind("SUPER + SHIFT + X", function() fn.deleteWorkspace() end)
|
||||
bind("SUPER + SHIFT + Z", function() fn.createWorkspace(fn.getActiveWorkspaceName()) end)
|
||||
bind("SUPER + SHIFT + left", function() fn.moveWorkspace(-1) end)
|
||||
bind("SUPER + SHIFT + right", function() fn.moveWorkspace(1) end)
|
||||
bind("SUPER + ALT + DOWN", function() fn.moveWorkspace(nil, "desc:Ancor Communications Inc ASUS VS228 E3LMTF071391") end)
|
||||
|
||||
-- Laptop keys
|
||||
bind("XF86MonBrightnessUp", dsp.exec_cmd("brightnessctl -- set +10%"))
|
||||
bind("XF86MonBrightnessDown", dsp.exec_cmd("brightnessctl -- set -10%"))
|
||||
|
||||
-- Macros (uses fn.pasteText and native Lua os.time/os.date instead of bash scripts)
|
||||
bind("SUPER + CTRL + S", function() fn.pasteText(os.date("%F")) end)
|
||||
bind("SUPER + CTRL + N", function() fn.pasteText(os.date("%FT%T %z")) end)
|
||||
bind("SUPER + CTRL + Y", function() fn.pasteText(os.date("%F", os.time() - 86400)) end)
|
||||
bind("SUPER + CTRL + T", function() fn.pasteText(os.date("%F", os.time() + 86400)) end)
|
||||
|
||||
-- Timetracker Macro
|
||||
bind("CTRL + SHIFT + S", function() fn.timetracker() end)
|
||||
|
||||
-- Bitwarden Macro
|
||||
bind("SUPER + CTRL + 1", function() fn.pasteMacro("secret-tool lookup app bw") end)
|
||||
|
||||
|
||||
-----------------------------------------------------
|
||||
-- Autostart (from autostart.conf)
|
||||
-----------------------------------------------------
|
||||
hl.on("hyprland.start", function()
|
||||
hl.exec_cmd("dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP")
|
||||
hl.exec_cmd("hyprpolkitagent")
|
||||
hl.exec_cmd("uwsm app -- hypridle")
|
||||
hl.exec_cmd("hyprpaper &")
|
||||
-- Waybar is now managed entirely by functions.setupMonitors()
|
||||
hl.exec_cmd("uwsm app -- espanso start")
|
||||
hl.exec_cmd("uwsm app -- dunst")
|
||||
hl.exec_cmd("nm-applet")
|
||||
hl.exec_cmd("signal-desktop")
|
||||
hl.exec_cmd("hp-systray")
|
||||
hl.exec_cmd("blueman-applet")
|
||||
hl.exec_cmd("wl-paste --watch cliphist store")
|
||||
hl.exec_cmd("wl-clip-persist --clipboard regular")
|
||||
hl.exec_cmd("qutebrowser")
|
||||
hl.exec_cmd("vivaldi-stable")
|
||||
hl.exec_cmd("alacritty")
|
||||
|
||||
-- Start the battery low-level notifier
|
||||
hl.exec_cmd("bash ~/.config/hypr/scripts/battery-notify.sh")
|
||||
|
||||
-- Randomize wallpapers after hyprpaper has time to start
|
||||
hl.exec_cmd("sleep 2 && hyprctl eval 'require(\"functions\").randomizeWallpaper()'")
|
||||
end)
|
||||
|
||||
-----------------------------------------------------
|
||||
-- Monitor Hotplug Events
|
||||
-----------------------------------------------------
|
||||
hl.on("monitor.added", function()
|
||||
require("functions").setupMonitors()
|
||||
end)
|
||||
|
||||
hl.on("monitor.removed", function()
|
||||
require("functions").setupMonitors()
|
||||
end)
|
||||
+1
-10
@@ -46,7 +46,7 @@ label {
|
||||
}
|
||||
|
||||
label {
|
||||
text = cmd[update:60] uptime -p
|
||||
text = cmd[update:60000] uptime -p
|
||||
color = rgb(ebdbb2)
|
||||
offont_size = 10
|
||||
font_family = monospace
|
||||
@@ -56,15 +56,6 @@ label {
|
||||
valign = center
|
||||
}
|
||||
|
||||
listener {
|
||||
timeout = 300 # 5 minutes
|
||||
on-timeout = sleep 60 && busctl --user call org.freedesktop.secrets /org/freedesktop/secrets org.freedesktop.Secret.Service Lock "as" 1 "/org/freedesktop/secrets/aliases/default" && hyprlock
|
||||
}
|
||||
|
||||
listener {
|
||||
timeout = 330 # 5.5 minutes
|
||||
on-timeout = hyprctl dispatch dpms off # screen off
|
||||
on-resume = hyprctl dispatch dpms on # screen on
|
||||
}
|
||||
|
||||
# vim:ft=hyprlang
|
||||
+7
-12
@@ -1,25 +1,20 @@
|
||||
ipc = on
|
||||
splash = false
|
||||
|
||||
wallpaper {
|
||||
monitor = eDP-1
|
||||
path = /home/trey/images/black.png
|
||||
path = /home/trey/images/Seven Beats Music/2025-02-24.jpg
|
||||
fit_mode = cover
|
||||
}
|
||||
|
||||
wallpaper {
|
||||
monitor = DP-7
|
||||
path = /home/trey/images/Seven Beats Music/2024-09-16.jpg
|
||||
monitor = DP-9
|
||||
path = /home/trey/images/Seven Beats Music/2024-09-09.jpg
|
||||
fit_mode = cover
|
||||
}
|
||||
|
||||
wallpaper {
|
||||
monitor = DP-8
|
||||
path = /home/trey/images/Seven Beats Music/2024-10-14.jpg
|
||||
monitor = DP-10
|
||||
path = /home/trey/images/Seven Beats Music/2026-01-26.jpg
|
||||
fit_mode = cover
|
||||
}
|
||||
|
||||
wallpaper {
|
||||
monitor =
|
||||
path = /home/trey/images/black.png
|
||||
fit_mode = cover
|
||||
}
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,42 @@
|
||||
general {
|
||||
lock_cmd = pidof hyprlock || hyprlock # avoid starting multiple hyprlock instances.
|
||||
before_sleep_cmd = loginctl lock-session # lock before suspend.
|
||||
after_sleep_cmd = hyprctl dispatch dpms on # to avoid having to press a key twice to turn on the display.
|
||||
}
|
||||
|
||||
listener {
|
||||
timeout = 150 # 2.5min.
|
||||
on-timeout = brightnessctl -s set 10 # set monitor backlight to minimum, avoid 0 on OLED monitor.
|
||||
on-resume = brightnessctl -r # monitor backlight restore.
|
||||
}
|
||||
|
||||
# turn off keyboard backlight, comment out this section if you dont have a keyboard backlight.
|
||||
listener {
|
||||
timeout = 150 # 2.5min.
|
||||
on-timeout = brightnessctl -sd rgb:kbd_backlight set 0 # turn off keyboard backlight.
|
||||
on-resume = brightnessctl -rd rgb:kbd_backlight # turn on keyboard backlight.
|
||||
}
|
||||
|
||||
#listener {
|
||||
# timeout = 300 # 5min
|
||||
# on-timeout = loginctl lock-session # lock screen when timeout has passed
|
||||
#}
|
||||
|
||||
listener {
|
||||
timeout = 300
|
||||
# 1. Lock the vault via DBus, 2. Start the lock screen
|
||||
on-timeout = busctl --user call org.freedesktop.secrets /org/freedesktop/secrets org.freedesktop.Secret.Service Lock "as" 1 "/org/freedesktop/secrets/aliases/default" && hyprlock
|
||||
# When hyprlock exits (via fingerprint or password), instantly run the unlock script
|
||||
on-resume = ~/.local/bin/unlock-ring.sh
|
||||
}
|
||||
|
||||
listener {
|
||||
timeout = 330 # 5.5min
|
||||
on-timeout = hyprctl dispatch dpms off # screen off when timeout has passed
|
||||
on-resume = hyprctl dispatch dpms on # screen on when activity is detected after timeout has fired.
|
||||
}
|
||||
|
||||
listener {
|
||||
timeout = 900 # 10min
|
||||
on-timeout = systemd-ac-power || systemctl suspend # only suspend pc on battery
|
||||
}
|
||||
File renamed without changes.
@@ -0,0 +1,70 @@
|
||||
auth {
|
||||
fingerprint {
|
||||
enabled = true
|
||||
}
|
||||
}
|
||||
|
||||
background {
|
||||
# path = screenshot
|
||||
color = rgb(000000)
|
||||
}
|
||||
|
||||
input-field {
|
||||
size = 200, 30
|
||||
outline_thickness = 1
|
||||
rounding = 10
|
||||
outer_color = rgb(665c54)
|
||||
inner_color = rgb(3c3836)
|
||||
font_color = rgb(ebdbb2)
|
||||
check_color = rgb(d79921)
|
||||
fail_color = rgb(cc241d)
|
||||
fade_on_empty = false
|
||||
placeholder_text = password
|
||||
fail_text =
|
||||
}
|
||||
|
||||
label {
|
||||
text = cmd[update:500]date +"%FT%H:%M:%S"
|
||||
color = rgb(ebdbb2)
|
||||
font_size = 45
|
||||
font_family = monospace
|
||||
|
||||
position = 0, 60
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
|
||||
label {
|
||||
text = cmd[update:3000]pidof spotify > /dev/null && echo "<span foreground='##b8bb26' size='25000' rise='-4.5pt'> </span>$(playerctl -p spotify metadata xesam:title) - $(playerctl -p spotify metadata xesam:artist)"
|
||||
color = rgb(ebdbb2)
|
||||
font_size = 14
|
||||
font_family = JetBrains Mono Nerd Font Mono Semibold
|
||||
|
||||
position = 0, -420
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
|
||||
label {
|
||||
text = cmd[update:60] uptime -p
|
||||
color = rgb(ebdbb2)
|
||||
offont_size = 10
|
||||
font_family = monospace
|
||||
|
||||
position = 0, -450
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
|
||||
listener {
|
||||
timeout = 300 # 5 minutes
|
||||
on-timeout = sleep 60 && busctl --user call org.freedesktop.secrets /org/freedesktop/secrets org.freedesktop.Secret.Service Lock "as" 1 "/org/freedesktop/secrets/aliases/default" && hyprlock
|
||||
}
|
||||
|
||||
listener {
|
||||
timeout = 330 # 5.5 minutes
|
||||
on-timeout = hyprctl dispatch dpms off # screen off
|
||||
on-resume = hyprctl dispatch dpms on # screen on
|
||||
}
|
||||
|
||||
# vim:ft=hyprlang
|
||||
@@ -0,0 +1,25 @@
|
||||
splash = false
|
||||
wallpaper {
|
||||
monitor = eDP-1
|
||||
path = /home/trey/images/black.png
|
||||
fit_mode = cover
|
||||
}
|
||||
|
||||
wallpaper {
|
||||
monitor = DP-7
|
||||
path = /home/trey/images/Seven Beats Music/2024-09-16.jpg
|
||||
fit_mode = cover
|
||||
}
|
||||
|
||||
wallpaper {
|
||||
monitor = DP-8
|
||||
path = /home/trey/images/Seven Beats Music/2024-10-14.jpg
|
||||
fit_mode = cover
|
||||
}
|
||||
|
||||
wallpaper {
|
||||
monitor =
|
||||
path = /home/trey/images/black.png
|
||||
fit_mode = cover
|
||||
}
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,7 @@
|
||||
workspace = 1, defaultName:shell, monitor:eDP-1, persistent:true, default:true
|
||||
workspace = 3, defaultName:browser, monitor:eDP-1, persistent:true, default:true
|
||||
workspace = 4, defaultName:work, monitor:eDP-1, persistent:true, default:true
|
||||
workspace = 5, defaultName:jobs, monitor:eDP-1, persistent:true, default:true
|
||||
workspace = 6, defaultName:meeting, monitor:eDP-1, persistent:true, default:true
|
||||
workspace = 7, defaultName:monitoring, monitor:eDP-1, persistent:true, default:true
|
||||
workspace = 8, defaultName:ai, monitor:eDP-1, persistent:true, default:true
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Background loop to monitor battery status and trigger dunstify on low power.
|
||||
while true; do
|
||||
if [ ! -d /sys/class/power_supply/BAT0 ]; then
|
||||
sleep 60
|
||||
continue
|
||||
fi
|
||||
|
||||
STATUS=$(cat /sys/class/power_supply/BAT0/status 2>/dev/null)
|
||||
# Using the native kernel capacity file instead of relying on ibam
|
||||
CAPACITY=$(cat /sys/class/power_supply/BAT0/capacity 2>/dev/null)
|
||||
|
||||
if [ -z "$CAPACITY" ]; then
|
||||
sleep 60
|
||||
continue
|
||||
fi
|
||||
|
||||
# Trigger notification at 5% or below
|
||||
if [ "$STATUS" == "Discharging" ] && [ "$CAPACITY" -le 5 ]; then
|
||||
if [ ! -f "/run/user/${UID}/battery_low" ]; then
|
||||
logger "Low power! Triggering notification...."
|
||||
dunstify --urgency=critical \
|
||||
--icon=/usr/share/icons/breeze-dark/emblems/16/emblem-warning.svg \
|
||||
"LOW BATTERY!" \
|
||||
"Battery level is at ${CAPACITY}%, plug power quick!"
|
||||
touch "/run/user/${UID}/battery_low"
|
||||
fi
|
||||
|
||||
# Clear the notification if we plug back in and rise above 5%
|
||||
elif [ "$STATUS" == "Charging" ] && [ "$CAPACITY" -gt 5 ]; then
|
||||
if [ -f "/run/user/${UID}/battery_low" ]; then
|
||||
logger "Power reconnected and above 5 percent, clearing notification state."
|
||||
rm -f "/run/user/${UID}/battery_low"
|
||||
|
||||
# Find and close the specific dunst notification by ID
|
||||
for id in $(dunstctl history | jq '.data[0][] | select(.summary.data == "LOW BATTERY!") | .id.data'); do
|
||||
dunstify --close=${id}
|
||||
done
|
||||
fi
|
||||
fi
|
||||
|
||||
sleep 60
|
||||
done
|
||||
@@ -1,35 +0,0 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
#set -x
|
||||
old_profile="$(kanshictl status | jq -r '.current_profile')"
|
||||
new_profile="${1}"
|
||||
shift
|
||||
|
||||
if [[ "${old_profile}" == "${new_profile}" ]]; then
|
||||
if [[ "${1}" != "--force" ]] && [[ "${1}" != '-f' ]]; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
case "${new_profile}" in
|
||||
home_office)
|
||||
perl -pi -e 'if (/shell/) {s/monitor:.*?,/monitor:DP-6,/}' ${XDG_CONFIG_HOME}/hypr/workspaces.conf
|
||||
perl -pi -e 'if (/browser/) {s/monitor:.*?,/monitor:DP-6,/}' ${XDG_CONFIG_HOME}/hypr/workspaces.conf
|
||||
perl -pi -e 'if (/work/) {s/monitor:.*?,/monitor:HDMI-A-1,/}' ${XDG_CONFIG_HOME}/hypr/workspaces.conf
|
||||
perl -pi -e 'if (/jobs/) {s/monitor:.*?,/monitor:HDMI-A-1,/}' ${XDG_CONFIG_HOME}/hypr/workspaces.conf
|
||||
kanshictl switch home_office
|
||||
hyprctl reload
|
||||
killall -s USR2 waybar
|
||||
;;
|
||||
single_headed)
|
||||
perl -pi -e 's/monitor:.*?,/monitor:eDP-1,/' ${XDG_CONFIG_HOME}/hypr/workspaces.conf
|
||||
kanshictl switch single_headed
|
||||
hyprctl reload
|
||||
killall -s USR2 waybar
|
||||
;;
|
||||
*)
|
||||
print "Invalid profile!" >&2
|
||||
;;
|
||||
esac
|
||||
|
||||
#set +x
|
||||
@@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Options for the menu
|
||||
lock="Lock"
|
||||
logout="Sign-Out"
|
||||
reboot="Reboot"
|
||||
poweroff="Power Off"
|
||||
|
||||
options="$lock\n$logout\n$reboot\n$poweroff"
|
||||
|
||||
# Fullscreen rofi menu with large centered text mimicking Windows 11
|
||||
chosen=$(echo -e "$options" | rofi -dmenu -i -p "CTRL-ALT-DEL" \
|
||||
-theme-str 'window { fullscreen: true; background-color: #000000cc; }' \
|
||||
-theme-str 'mainbox { children: [listview]; padding: 25% 35%; }' \
|
||||
-theme-str 'listview { columns: 1; lines: 4; spacing: 15px; scrollbar: false; }' \
|
||||
-theme-str 'element { padding: 15px; border-radius: 10px; }' \
|
||||
-theme-str 'element-text { horizontal-align: 0.5; vertical-align: 0.5; font: "sans-serif 20"; }' \
|
||||
-theme-str 'element selected { background-color: #3366ff; text-color: white; }')
|
||||
|
||||
case $chosen in
|
||||
$lock)
|
||||
loginctl lock-session
|
||||
;;
|
||||
$logout)
|
||||
hyprctl dispatch exit
|
||||
;;
|
||||
$reboot)
|
||||
zsh -c 'source ~/.zsh_functions && reboot'
|
||||
;;
|
||||
$poweroff)
|
||||
systemctl poweroff
|
||||
;;
|
||||
esac
|
||||
@@ -0,0 +1,9 @@
|
||||
return {
|
||||
{ name = "shell", monitor = "desc:Ancor Communications Inc ASUS VS228 E3LMTF071391" },
|
||||
{ name = "browser", monitor = "desc:Ancor Communications Inc ASUS VS228 E3LMTF071391" },
|
||||
{ name = "jobs", monitor = "desc:Ancor Communications Inc ASUS VS228 E3LMTF071438" },
|
||||
{ name = "work", monitor = "desc:Ancor Communications Inc ASUS VS228 E3LMTF071438" },
|
||||
{ name = "meeting", monitor = "eDP-1" },
|
||||
{ name = "monitoring", monitor = "eDP-1" },
|
||||
{ name = "blah", monitor = "DP-8" },
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
workspace = 1, defaultName:shell, monitor:DP-8, persistent:true, default:true
|
||||
workspace = 3, defaultName:browser, monitor:DP-8, persistent:true, default:true
|
||||
workspace = 4, defaultName:work, monitor:DP-7, persistent:true, default:true
|
||||
workspace = 5, defaultName:jobs, monitor:DP-7, persistent:true, default:true
|
||||
workspace = 6, defaultName:meeting, monitor:eDP-1, persistent:true, default:true
|
||||
workspace = 7, defaultName:monitoring, monitor:eDP-1, persistent:true, default:true
|
||||
workspace = 8, defaultName:ai, monitor:eDP-1, persistent:true, default:true
|
||||
@@ -0,0 +1,44 @@
|
||||
-- ~/.config/hypr/workspaces.lua
|
||||
-- Dynamic workspace assignment: replaces kanshi + scripts
|
||||
-- Detects monitor configuration and assigns workspaces accordingly.
|
||||
|
||||
local function get_monitor_names()
|
||||
local names = {}
|
||||
for _, m in ipairs(hl.get_monitors()) do
|
||||
names[m.name] = m.name
|
||||
if m.description then
|
||||
local clean_desc = m.description:gsub(" %([^%)]+%)$", "")
|
||||
names["desc:" .. clean_desc] = m.name
|
||||
end
|
||||
end
|
||||
return names
|
||||
end
|
||||
|
||||
local function assign_workspaces()
|
||||
local monitors = get_monitor_names()
|
||||
local has_dock = monitors["desc:Ancor Communications Inc ASUS VS228 E3LMTF071438"] and monitors["desc:Ancor Communications Inc ASUS VS228 E3LMTF071391"]
|
||||
|
||||
-- Read workspace configurations
|
||||
package.loaded["workspace_config"] = nil -- force reload in case it changed
|
||||
local ws_config = require("workspace_config")
|
||||
|
||||
-- Iterate in REVERSE to assign the most negative IDs to the first items, counteracting Waybar's low-to-high sorting!
|
||||
for i = #ws_config, 1, -1 do
|
||||
local ws = ws_config[i]
|
||||
local target_mon = has_dock and monitors[ws.monitor] or "eDP-1"
|
||||
if not target_mon then target_mon = "eDP-1" end
|
||||
hl.workspace_rule({ workspace = "name:" .. ws.name, monitor = target_mon, persistent = true, default = true })
|
||||
end
|
||||
end
|
||||
|
||||
-- Apply on initial load
|
||||
assign_workspaces()
|
||||
|
||||
-- Re-apply when monitors change
|
||||
hl.on("monitor.added", function(monitor)
|
||||
assign_workspaces()
|
||||
end)
|
||||
|
||||
hl.on("monitor.removed", function(monitor)
|
||||
assign_workspaces()
|
||||
end)
|
||||
Reference in new issue
Block a user