Better eww

This commit is contained in:
soraefir
2026-07-19 23:11:43 +02:00
parent 887634421c
commit 58492cae22
6 changed files with 78 additions and 8 deletions
@@ -6,13 +6,15 @@ PANEL="$1"
exec 9>"/tmp/eww_panel_toggle.lock"
flock -n 9 || exit 0
CURRENT=$(eww get active-panel 2>/dev/null | tr -d '"')
# Every eww call must run with fd 9 closed (9>&-): `eww open` daemonizes and
# would inherit the fd, holding the flock forever and wedging all later toggles.
CURRENT=$(eww get active-panel 2>/dev/null 9>&- | tr -d '"')
if [ "$CURRENT" = "$PANEL" ]; then
eww update active-panel=""
eww close popup 2>/dev/null
eww update active-panel="" 9>&-
eww close popup 2>/dev/null 9>&-
else
eww update active-panel="$PANEL"
eww close popup 2>/dev/null
eww-open-on-current-screen popup
eww update active-panel="$PANEL" 9>&-
eww close popup 2>/dev/null 9>&-
eww-open-on-current-screen popup 9>&-
fi
+39 -1
View File
@@ -1,9 +1,13 @@
{ lib, config, pkgs, ... }:
let
ensureDaemon = pkgs.custom.eww-ensure-daemon;
openOnCurrentScreen = pkgs.writeShellScriptBin "eww-open-on-current-screen" ''
window="$1"
shift
${ensureDaemon}/bin/eww-ensure-daemon || exit 1
screen="$(hyprctl monitors -j | ${lib.getExe pkgs.jq} -r '.[] | select(.focused == true) | .name' | head -n1)"
if [ -n "$screen" ]; then
@@ -13,6 +17,21 @@ let
exec ${lib.getExe pkgs.eww} open "$window" "$@"
'';
# Escape hatch: tears down every eww process (including orphaned daemons that
# own unreachable surfaces), clears the stale socket, and brings back a single
# daemon with the bar. `pkill -x` matches the process name exactly so it can
# never match a wrapper script or a shell that merely mentions eww.
ewwReset = pkgs.writeShellScriptBin "eww-reset" ''
${pkgs.systemd}/bin/systemctl --user stop eww.service >/dev/null 2>&1 || true
${pkgs.procps}/bin/pkill -x -u "$(id -u)" eww >/dev/null 2>&1 || true
sleep 1
${pkgs.procps}/bin/pkill -9 -x -u "$(id -u)" eww >/dev/null 2>&1 || true
rm -f "''${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"/eww-server_*
${ensureDaemon}/bin/eww-ensure-daemon || exit 1
exec ${lib.getExe pkgs.eww} open bar --screen 0
'';
# Wraps a static script file with a bash launcher that prepends Nix store
# bin dirs to PATH — keeps the source files unchanged.
mkScript = name: src: inputs: pkgs.writeShellScriptBin name ''
@@ -43,7 +62,26 @@ let
in {
config = lib.mkIf (config.usercfg.wm == "Wayland") {
home.packages = [ pkgs.eww openOnCurrentScreen ];
home.packages = [ pkgs.eww openOnCurrentScreen ensureDaemon ewwReset ];
# One explicitly-managed daemon, so no client ever races to spawn a rival.
# ExecStartPre clears a socket left behind by an unclean exit, which would
# otherwise make the fresh daemon look reachable to clients before it binds.
systemd.user.services.eww = {
Unit = {
Description = "eww daemon";
PartOf = [ "graphical-session.target" ];
After = [ "graphical-session.target" ];
};
Service = {
Type = "simple";
ExecStartPre = "${pkgs.bash}/bin/bash -c 'rm -f \"\${XDG_RUNTIME_DIR:-/run/user/$(id -u)}\"/eww-server_*'";
ExecStart = "${lib.getExe pkgs.eww} daemon --no-daemonize";
Restart = "on-failure";
RestartSec = 1;
};
Install.WantedBy = [ "graphical-session.target" ];
};
xdg.configFile = lib.mkMerge [
{
@@ -1,7 +1,12 @@
{ config, lib, pkgs, ... }:
let
# Close the bar if it's already open (wrong screen), then open on the target screen.
# Must go through eww-ensure-daemon: this runs on every monitor hotplug, and a
# bare `eww open` against a busy/dead socket spawns a second daemon, leaving the
# first one's bar and popups on screen with no way to close them.
moveOrOpenBar = screen: "${pkgs.writeShellScript "kanshi-eww-bar-${toString screen}" ''
${pkgs.custom.eww-ensure-daemon}/bin/eww-ensure-daemon || exit 1
if ${pkgs.eww}/bin/eww active-windows 2>/dev/null | grep -qx "bar"; then
${pkgs.eww}/bin/eww close bar
fi
+5 -1
View File
@@ -24,7 +24,11 @@
startupScript = pkgs.writeShellScriptBin "hyprland-start" ''
${pkgs.eww}/bin/eww open bar &
# Wait for the managed daemon rather than letting `eww open` spawn its own:
# at login the socket may not be bound yet, and a self-spawned client daemon
# would orphan the service's one, leaving unclosable windows behind.
(${pkgs.custom.eww-ensure-daemon}/bin/eww-ensure-daemon \
&& ${pkgs.eww}/bin/eww open bar --screen 0) &
${pkgs.awww}/bin/awww-daemon &
${pkgs.awww}/bin/awww restore &