4 Commits

Author SHA1 Message Date
alex b14290fffe extensions from laptop 2026-08-03 21:57:14 +02:00
alex b93b27e43a feat(hypr): add non-locking idle blanker
Blank all displays after five minutes without using DPMS or locking the session.
2026-08-03 17:54:53 +02:00
alex a91c8cf8f2 feat(pi-status): integrate desktop status bridge
Expose the persistent Pi session controls through the desktop launcher, Noctalia, and user service.
2026-08-03 17:54:53 +02:00
alex b220b21509 extensions from laptop 2026-08-03 17:47:58 +02:00
12 changed files with 122 additions and 9 deletions
@@ -0,0 +1,2 @@
# Used by the Noctalia Pi Status Bridge adapter and the Hyprland launcher.
PI_STATUS_UI_BINARY=/home/alex/.local/bin/pi-status-ui
+6
View File
@@ -0,0 +1,6 @@
# Non-locking Wayland screen blanker. It covers every monitor in black and
# dismisses itself on any key press or mouse click; it never changes DPMS.
listener {
timeout = 300
on-timeout = /home/alex/.local/bin/wayshell-blanker
}
+2 -2
View File
@@ -62,7 +62,7 @@ hl.workspace_rule({
-- Application and session bindings. -- Application and session bindings.
local noctalia_ipc = "noctalia msg " local noctalia_ipc = "noctalia msg "
local pi_status_ui_toggle = 'ui="${PI_STATUS_UI_BINARY:-$HOME/projects/pi-status-bridge/ui/src-tauri/target/release/pi-status-ui}"; if test -x "$ui"; then setsid -f env TMPDIR=/tmp "$ui" --toggle >/tmp/pi-status-ui.log 2>&1; fi' local pi_status_ui_toggle = 'ui="${PI_STATUS_UI_BINARY:-$HOME/.local/bin/pi-status-ui}"; if test -x "$ui"; then setsid -f env TMPDIR=/tmp "$ui" --toggle >/tmp/pi-status-ui.log 2>&1; fi'
-- Tap and release Super on its own to open Noctalia's control-center home. -- Tap and release Super on its own to open Noctalia's control-center home.
hl.bind(main_mod .. " + SUPER_L", hl.dsp.exec_cmd(noctalia_ipc .. "panel-toggle control-center"), { release = true }) hl.bind(main_mod .. " + SUPER_L", hl.dsp.exec_cmd(noctalia_ipc .. "panel-toggle control-center"), { release = true })
hl.bind(main_mod .. " + RETURN", hl.dsp.exec_cmd(terminal)) hl.bind(main_mod .. " + RETURN", hl.dsp.exec_cmd(terminal))
@@ -139,7 +139,7 @@ local function float_rule(name, match, border_size)
end end
hl.window_rule({ name = "thunderbird-workspace", match = { class = "^Thunderbird$" }, workspace = "9" }) hl.window_rule({ name = "thunderbird-workspace", match = { class = "^Thunderbird$" }, workspace = "9" })
float_rule("pi-status-ui", { class = "^pi-status-ui$" }, 1) float_rule("pi-status-ui", { class = "^(pi-status-ui|Pi-status-ui)$" }, 1)
float_rule("alsamixer", { title = "^alsamixer$" }, 1) float_rule("alsamixer", { title = "^alsamixer$" }, 1)
float_rule("qalculate", { title = "^Qalculate!$" }) float_rule("qalculate", { title = "^Qalculate!$" })
float_rule("psensor", { class = "^Psensor$" }) float_rule("psensor", { class = "^Psensor$" })
+45
View File
@@ -0,0 +1,45 @@
# Minimal Hyprlock screen using the current desktop as a blurred backdrop.
$font = Sans
general {
hide_cursor = true
}
background {
monitor =
path = screenshot
blur_passes = 3
}
input-field {
monitor =
size = 20%, 5%
outline_thickness = 2
inner_color = rgba(0, 0, 0, 0.25)
outer_color = rgba(eeeeeecc)
check_color = rgba(8ec07ccc)
fail_color = rgba(fb4934cc)
font_color = rgb(eeeeee)
fade_on_empty = false
rounding = 12
font_family = $font
placeholder_text = Input password...
fail_text = $PAMFAIL
position = 0, -20
halign = center
valign = center
}
label {
monitor =
text = $TIME
font_size = 72
font_family = $font
position = 0, 120
halign = center
valign = center
}
@@ -10,6 +10,7 @@ return {
}, },
startup = { startup = {
"noctalia", "noctalia",
"hypridle",
-- Electron's tray icon registers only when the SNI watcher already exists. -- Electron's tray icon registers only when the SNI watcher already exists.
"sh -c 'sleep 2; exec mullvad-vpn'", "sh -c 'sleep 2; exec mullvad-vpn'",
"thunderbird", "thunderbird",
+23
View File
@@ -5,6 +5,29 @@ offline_mode = true
external_ip_enabled = false external_ip_enabled = false
telemetry_enabled = false telemetry_enabled = false
# Noctalia owns idle handling so ScreenSaver/Wayland idle inhibitors (such as
# browser video playback) prevent these actions. Power displays down after five
# minutes, lock after ten minutes, then suspend-then-hibernate after thirty.
[idle]
behavior_order = ["lock", "screen-off", "suspend-then-hibernate"]
pre_action_fade_seconds = 2.0
[idle.behavior.lock]
action = "lock"
enabled = true
timeout = 600
[idle.behavior.screen-off]
action = "screen_off"
enabled = true
timeout = 300
[idle.behavior.suspend-then-hibernate]
action = "command"
command = "loginctl lock-session && systemctl suspend-then-hibernate"
enabled = true
timeout = 1800
[theme] [theme]
mode = "dark" mode = "dark"
source = "custom" source = "custom"
@@ -1,10 +1,18 @@
# Desktop-specific shell layout and hardware telemetry. # Desktop-specific shell layout and hardware telemetry.
# Pi Status Bridge is installed locally from ~/projects/pi-gui.
[plugins]
enabled = ["alex/system-status", "alex/pi-status-bridge"]
[widget.pi-status]
type = "alex/pi-status-bridge:bridge"
[bar.main] [bar.main]
position = "bottom" position = "bottom"
layer = "top" layer = "top"
scale = 0.95
capsule_radius = 5 capsule_radius = 5
center = ["group:g3", "notifications"] center = ["group:g3", "notifications"]
end = ["bluetooth", "input_volume", "volume", "control-center", "group:g1", "session"] end = ["group:g2", "group:g6", "group:g1", "session"]
font_weight = 400 font_weight = 400
margin_ends = 0 margin_ends = 0
padding = 0 padding = 0
@@ -15,7 +23,7 @@ shadow = false
auto_hide = false auto_hide = false
smart_auto_hide = false smart_auto_hide = false
reserve_space = true reserve_space = true
start = ["tray", "group:g4", "group:g2", "privacy"] start = ["tray", "group:g4", "privacy"]
thickness = 39 thickness = 39
widget_spacing = 10 widget_spacing = 10
@@ -31,7 +39,7 @@ padding = 6.0
enabled = true enabled = true
fill = "surface_variant" fill = "surface_variant"
id = "g2" id = "g2"
members = ["network_rx", "network_tx", "network"] members = ["network", "bluetooth"]
opacity = 1.0 opacity = 1.0
padding = 6.0 padding = 6.0
@@ -48,10 +56,19 @@ radius = 5.0
enabled = true enabled = true
fill = "surface_variant" fill = "surface_variant"
id = "g4" id = "g4"
members = ["cpu", "temp", "ram", "gpu", "gpu_temp", "disk"] members = ["pi-status", "cpu", "temp", "ram", "gpu", "gpu_temp", "disk"]
opacity = 1.0 opacity = 1.0
padding = 6.0 padding = 6.0
[[bar.main.capsule_group]]
enabled = true
fill = "surface_variant"
id = "g6"
members = ["input_volume", "volume"]
opacity = 1.0
padding = 6.0
radius = 5.0
[widget.gpu] [widget.gpu]
type = "sysmon" type = "sysmon"
stat = "gpu_usage" stat = "gpu_usage"
@@ -32,7 +32,7 @@ padding = 6.0
enabled = true enabled = true
fill = "surface_variant" fill = "surface_variant"
id = "g2" id = "g2"
members = ["network-rate", "network", "bluetooth"] members = ["network", "bluetooth"]
opacity = 1.0 opacity = 1.0
padding = 6.0 padding = 6.0
@@ -0,0 +1,13 @@
[Unit]
Description=Pi Status Bridge home agent
After=graphical-session.target
[Service]
Type=simple
Environment=PATH=/home/alex/.local/bin:/usr/local/bin:/usr/bin:/bin
ExecStart=/home/alex/.local/bin/pi-status-bridge --session-root %h/.local/state/pi-status-bridge/sessions
Restart=on-failure
RestartSec=3
[Install]
WantedBy=default.target
+4
View File
@@ -0,0 +1,4 @@
#!/bin/sh
# The opaque release window runs natively on Wayland; disable WebKit DMABUF,
# which is unreliable with this NVIDIA desktop's compositor path.
exec env WEBKIT_DISABLE_DMABUF_RENDERER=1 "$HOME/projects/pi-gui/ui/src-tauri/target/release/pi-status-ui" "$@"
+1
View File
@@ -0,0 +1 @@
../../../../projects/pi-gui/noctalia-v5-plugin/pi-status-bridge
+3 -2
View File
@@ -18,10 +18,11 @@
"npm:bigpowers", "npm:bigpowers",
"npm:@gotgenes/pi-permission-system", "npm:@gotgenes/pi-permission-system",
"npm:pi-intercom", "npm:pi-intercom",
"npm:gentle-engram", "npm:gentle-engram@0.1.8",
"npm:pi-lens", "npm:pi-lens",
"npm:@juicesharp/rpiv-todo", "npm:@juicesharp/rpiv-todo",
"npm:@majorgilles/pi-grill-me" "npm:@majorgilles/pi-grill-me",
"npm:pi-mcp-adapter"
], ],
"powerline": "full", "powerline": "full",
"hideThinkingBlock": false, "hideThinkingBlock": false,