diff --git a/modules/home/wayland/apps/eww/bar/eww.scss b/modules/home/wayland/apps/eww/bar/eww.scss index 927d3dc..b8dd830 100644 --- a/modules/home/wayland/apps/eww/bar/eww.scss +++ b/modules/home/wayland/apps/eww/bar/eww.scss @@ -93,6 +93,10 @@ tooltip { .green { color: $base0B; } .blue { color: $base0C; } +.workspace-sep { + border-top: 2px solid $base03; +} + /* WINDOW WRAPPER CSS */ .winevent { diff --git a/modules/home/wayland/apps/eww/bar/modules/workspaces.yuck b/modules/home/wayland/apps/eww/bar/modules/workspaces.yuck index 806f807..94c979d 100644 --- a/modules/home/wayland/apps/eww/bar/modules/workspaces.yuck +++ b/modules/home/wayland/apps/eww/bar/modules/workspaces.yuck @@ -1,24 +1,24 @@ (deflisten workspace :initial '[]' "scripts/workspaces") (defwidget workspace-mod [] - (module - (eventbox + (module + (eventbox :onscroll "echo {} | sed -e 's/up/-1/' -e 's/down/+1/' | xargs -I % hyprctl eval \"hl.dispatch(hl.dsp.focus({ workspace = '%' }))\"" - (box :class "module workspaces" :orientation "v" (for ws in workspace (button - :onclick "hyprctl eval \"hl.dispatch(hl.dsp.focus({ workspace = '${ws.number}' }))\"" - (label + :class `${ws.sep ? "workspace-sep" : ""}` + :onclick "hyprctl eval \"hl.dispatch(hl.dsp.focus({ workspace = '${ws.target}' }))\"" + (label :show-truncated false - :class "icon-text ${ws.color}" - :text `${ws.focused ? "󰜗" : "󰝥"}` + :class `icon-text ${ws.color}` + :text `${ws.state == "focused" ? "󰜗" : ws.state == "active" ? "󰝥" : "○"}` ) ) ) ) - ) + ) ) ) diff --git a/modules/home/wayland/apps/eww/bar/scripts/workspaces b/modules/home/wayland/apps/eww/bar/scripts/workspaces index 7ef1fc3..c3948d8 100755 --- a/modules/home/wayland/apps/eww/bar/scripts/workspaces +++ b/modules/home/wayland/apps/eww/bar/scripts/workspaces @@ -1,86 +1,174 @@ #!/usr/bin/env bash -colors=("blue" "blue" "green" "red") -empty="grey" +declare -A ws_windows=() +declare -A ws_name=() +declare -A ws_urgent=() +declare -A mon_active=() +focused_ws="" +focused_monitor="" +_state="" +_color="" -# get initial focused workspace -focusedws=$(hyprctl -j monitors | jaq -r '.[] | select(.focused == true) | .activeWorkspace.id') +load_workspaces() { + local raw + raw=$(hyprctl -j workspaces 2>/dev/null) || return + ws_windows=() + ws_name=() + while read -r id windows name; do + ws_windows[$id]=$windows + ws_name[$id]=$name + done < <(printf '%s' "$raw" | jaq -jr '.[] | (.id | tostring), " ", (.windows | tostring), " ", .name, "\n"' 2>/dev/null) +} -declare -A o=([1]=0 [2]=0 [3]=0 [4]=0 [5]=0 [6]=0 [7]=0 [8]=0 [9]=0 [10]=0) -declare -A monitormap -declare -A workspaces +load_monitors() { + local raw + raw=$(hyprctl -j monitors 2>/dev/null) || return + mon_active=() + focused_ws="" + focused_monitor="" + while read -r name active_id is_focused; do + mon_active[$name]=$active_id + if [ "$is_focused" = "true" ]; then + focused_ws=$active_id + focused_monitor=$name + fi + done < <(printf '%s' "$raw" | jaq -jr '.[] | .name, " ", (.activeWorkspace.id | tostring), " ", (.focused | tostring), "\n"' 2>/dev/null) +} -# set color for each workspace -status() { - if [ "${o[$1]}" -eq 1 ]; then - mon=${monitormap[${workspaces[$1]}]} - echo -n "${colors[$mon]}" +load_urgent() { + local raw + raw=$(hyprctl -j clients 2>/dev/null) || return + ws_urgent=() + while read -r wsid; do + ws_urgent[$wsid]=1 + done < <(printf '%s' "$raw" | jaq -r '.[] | select(.urgent == true) | (.workspace.id | tostring)' 2>/dev/null) +} + +ws_state_color() { + local id=$1 + _state="empty" + _color="grey" + + if [ "$id" = "$focused_ws" ]; then + _state="focused" else - echo -n "$empty" + local mon + for mon in "${!mon_active[@]}"; do + if [ "${mon_active[$mon]}" = "$id" ]; then + _state="active" + break + fi + done + if [ "$_state" = "empty" ] && [ "${ws_windows[$id]:-0}" -gt 0 ]; then + _state="running" + fi + fi + + if [ "$_state" != "empty" ]; then + if [ "${ws_urgent[$id]:-0}" -eq 1 ]; then + _color="red" + else + _color="blue" + fi fi } -# handle workspace create/destroy -workspace_event() { - while read -r k v; do workspaces[$k]="$v"; done < <(hyprctl -j workspaces | jaq -jr '.[] | .id, " ", .monitor, "\n"') -} -# handle monitor (dis)connects -monitor_event() { - while read -r k v; do monitormap["$k"]=$v; done < <(hyprctl -j monitors | jaq -jr '.[] | .name, " ", .id, "\n"') +ws_entry() { + local id=$1 name=$2 target=$3 sep=${4:-false} + ws_state_color "$id" + printf '{"id":%s,"name":"%s","target":"%s","state":"%s","color":"%s","sep":%s}' \ + "$id" "$name" "$target" "$_state" "$_color" "$sep" } -# get all apps titles in a workspace -applist() { - ws="$1" - - apps=$(hyprctl -j clients | jaq -jr '.[] | select(.workspace.id == '"$ws"') | .title + "\\n"') - echo -En "${apps%"\n"}" -} - -# generate the json for eww generate() { - echo -n '[' + printf '[' + local first=true - for i in {1..10}; do - echo -n ''"$([ "$i" -eq 1 ] || echo ,)" '{"number": "'"$i"'", "color": "'"$(status "$i")"'", "focused": '"$([ "$focusedws" = "$i" ] && echo "true" || echo "false")"'}' #, "tooltip": "'$(applist "$i")'" }' + local neg_ids=() id + for id in "${!ws_name[@]}"; do + if [[ "$id" == -* ]] && [ "${ws_name[$id]}" != "special:magic" ]; then + neg_ids+=("$id") + fi done - echo ']' + local has_neg=false + if [ ${#neg_ids[@]} -gt 0 ]; then + has_neg=true + IFS=$'\n' sorted_neg=($(printf '%s\n' "${neg_ids[@]}" | sort -n)); unset IFS + for id in "${sorted_neg[@]}"; do + $first || printf ',' + first=false + ws_entry "$id" "${ws_name[$id]}" "name:${ws_name[$id]}" + done + fi + + local first_pos=true + for i in {1..9}; do + $first || printf ',' + first=false + if $first_pos && $has_neg; then + ws_entry "$i" "$i" "$i" true + else + ws_entry "$i" "$i" "$i" + fi + first_pos=false + done + + printf ']\n' } -# setup - -# add monitors -monitor_event - -# add workspaces -workspace_event - -# check occupied workspaces -for num in "${!workspaces[@]}"; do - o[$num]=1 -done -# generate initial widget +load_workspaces +load_monitors +load_urgent generate -# main loop -socat -u UNIX-CONNECT:$XDG_RUNTIME_DIR/hypr/"$HYPRLAND_INSTANCE_SIGNATURE"/.socket2.sock - | rg --line-buffered "workspace|mon(itor)?" | while read -r line; do - case ${line%>>*} in +while read -r line; do + event="${line%>>*}" + data="${line#*>>}" + case "$event" in "workspace") - focusedws=${line#*>>} + # data is the workspace name, not id — resolve to id for named workspaces + focused_ws="$data" + for _k in "${!ws_name[@]}"; do + [ "${ws_name[$_k]}" = "$data" ] && { focused_ws="$_k"; break; } + done + unset "ws_urgent[$focused_ws]" + [ -n "$focused_monitor" ] && mon_active[$focused_monitor]="$focused_ws" + ;; + "workspacev2") + focused_ws="${data%%,*}" + unset "ws_urgent[$focused_ws]" + [ -n "$focused_monitor" ] && mon_active[$focused_monitor]="$focused_ws" ;; "focusedmon") - focusedws=${line#*,} + focused_monitor="${data%%,*}" + _wsname="${data#*,}" + focused_ws="$_wsname" + for _k in "${!ws_name[@]}"; do + [ "${ws_name[$_k]}" = "$_wsname" ] && { focused_ws="$_k"; break; } + done + unset "ws_urgent[$focused_ws]" + mon_active[$focused_monitor]="$focused_ws" ;; - "createworkspace") - o[${line#*>>}]=1 + "urgent") + wsid=$(hyprctl -j clients 2>/dev/null | jaq -r --arg addr "$data" '.[] | select(.address == $addr) | (.workspace.id | tostring)' 2>/dev/null) + [ -n "$wsid" ] && ws_urgent[$wsid]=1 ;; - "destroyworkspace") - o[${line#*>>}]=0 + "createworkspace"*|"destroyworkspace"*|"moveworkspace"*) + load_workspaces + load_monitors + ;; + "openwindow"|"movewindow"*) + load_workspaces + ;; + "closewindow") + load_workspaces + load_urgent ;; "monitor"*) - monitor_event + load_monitors ;; esac generate -done \ No newline at end of file +done < <(socat -u UNIX-CONNECT:"$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock" - | \ + rg --line-buffered "^(workspace|focusedmon|createworkspace|destroyworkspace|openwindow|closewindow|movewindow|moveworkspace|monitor|urgent)") diff --git a/modules/home/wayland/apps/kanshi/default.nix b/modules/home/wayland/apps/kanshi/default.nix index 5216f39..1ef6b3b 100644 --- a/modules/home/wayland/apps/kanshi/default.nix +++ b/modules/home/wayland/apps/kanshi/default.nix @@ -18,6 +18,7 @@ in { {output = baseOutput//{ criteria = "LG Electronics LG ULTRAGEAR+ 511NTDVGC194"; mode = "2560x1440@480.168"; + # mode = "2560x1440x240.083"; # mode = "1920x1080x240.084"; };} {output = baseOutput//{ @@ -64,16 +65,25 @@ in { ]; exec = [ "${pkgs.eww}/bin/eww open bar --screen 0" - "${pkgs.hyprland}/bin/hyprctl eval \"hl.workspace_rule({ workspace = '1', monitor = 'DP-1', default = true });\"" - "${pkgs.hyprland}/bin/hyprctl eval \"hl.workspace_rule({ workspace = '2', monitor = 'DP-2', default = true });\"" - "${pkgs.hyprland}/bin/hyprctl eval \"hl.workspace_rule({ workspace = '3', monitor = 'DP-1', default = true });\"" - "${pkgs.hyprland}/bin/hyprctl eval \"hl.workspace_rule({ workspace = '4', monitor = 'DP-1', default = true });\"" - "${pkgs.hyprland}/bin/hyprctl eval \"hl.workspace_rule({ workspace = '5', monitor = 'DP-1', default = true });\"" - "${pkgs.hyprland}/bin/hyprctl eval \"hl.workspace_rule({ workspace = '6', monitor = 'DP-1', default = true });\"" - "${pkgs.hyprland}/bin/hyprctl eval \"hl.workspace_rule({ workspace = '7', monitor = 'DP-1', default = true });\"" - "${pkgs.hyprland}/bin/hyprctl eval \"hl.workspace_rule({ workspace = '8', monitor = 'DP-1', default = true });\"" - "${pkgs.hyprland}/bin/hyprctl eval \"hl.workspace_rule({ workspace = '9', monitor = 'DP-1', default = true });\"" - "${pkgs.hyprland}/bin/hyprctl eval \"hl.workspace_rule({ workspace = '0', monitor = 'DP-3', default = true });\"" + "${pkgs.writeShellScript "kanshi-hyprland-init" '' + #!/usr/bin/env bash + ${pkgs.hyprland}/bin/hyprctl eval ' + hl.workspace_rule({ workspace = "1", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "2", monitor = "DP-2", default = true }) + hl.workspace_rule({ workspace = "3", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "4", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "5", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "6", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "7", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "8", monitor = "DP-2", default = true }) + hl.workspace_rule({ workspace = "9", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "name:X", monitor = "DP-3", default = true }) + ' + ${pkgs.hyprland}/bin/hyprctl eval 'hl.dispatch(hl.dsp.focus({ monitor = "DP-2" })); hl.dispatch(hl.dsp.focus({ workspace = "2" }));' + ${pkgs.hyprland}/bin/hyprctl eval 'hl.dispatch(hl.dsp.focus({ monitor = "DP-3" })); hl.dispatch(hl.dsp.focus({ workspace = "name:X" }));' + #${pkgs.hyprland}/bin/hyprctl eval 'hl.monitor({ output = "DP-3", cm = "hdr" });' + + ''}" "${pkgs.awww}/bin/awww restore" ]; };} @@ -82,14 +92,34 @@ in { outputs = [ { criteria = "AOC 24E1W1 GNSKCHA086899"; + transform = "180"; position = "0,0"; } { criteria = "AOC 24E1W1 GNSKBHA080346"; - position = "1920,0"; + position = "0,1080"; } ]; - exec = [ "${pkgs.eww}/bin/eww open bar --screen 1" ]; + exec = [ + "${pkgs.eww}/bin/eww open bar --screen 0" + "${pkgs.writeShellScript "kanshi-hyprland-init" '' + #!/usr/bin/env bash + ${pkgs.hyprland}/bin/hyprctl eval ' + hl.workspace_rule({ workspace = "1", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "2", monitor = "DP-2", default = true }) + hl.workspace_rule({ workspace = "3", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "4", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "5", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "6", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "7", monitor = "DP-1", default = true }) + hl.workspace_rule({ workspace = "8", monitor = "DP-2", default = true }) + hl.workspace_rule({ workspace = "9", monitor = "DP-1", default = true }) + ' + ${pkgs.hyprland}/bin/hyprctl eval 'hl.dispatch(hl.dsp.focus({ monitor = "DP-2" })); hl.dispatch(hl.dsp.focus({ workspace = "2" }));' + + ''}" + "${pkgs.awww}/bin/awww restore" + ]; };} {profile = { name = "tower_1"; diff --git a/modules/home/wayland/hyprland/config.nix b/modules/home/wayland/hyprland/config.nix index 526fd17..5408616 100644 --- a/modules/home/wayland/hyprland/config.nix +++ b/modules/home/wayland/hyprland/config.nix @@ -69,6 +69,10 @@ in { scale = "auto"; bitdepth = 10; cm = "auto"; #dcip3 + sdrbrightness = 1.4; + # sdrsaturation = 1.0; + # sdr_max_luminance = 220; + # sdr_min_luminance = 0.005; }]; #Fullscreen HDR is possible without the hdr cm setting if "render:cm_auto_hdr" is enabled. @@ -100,7 +104,7 @@ in { disable_splash_rendering = true; animate_mouse_windowdragging = false; animate_manual_resizes = false; - vrr = 2; + vrr = 0; #vrr=2; }; debug = { vfr = false; @@ -253,37 +257,6 @@ in { ]; - # windowrule = [ "noshadow, floating:0" ]; - - # windowrulev2 = [ - # "workspace 2 silent, class:^(org.telegram.desktop)$" - # "workspace 2 silent, class:^(discord)$" - # "workspace 8 silent, class:^(org.keepassxc.KeePassXC)$" - # "workspace 8 silent, title:^(Nextcloud)$" - # "workspace 8 silent, class:^(Tk)$,title:^(Server Configuration)$" - # "float,class:^(org.keepassxc.KeePassXC)$,title:^(KeePassXC - Access Request)$" - # "pin,class:^(org.keepassxc.KeePassXC)$,title:^(KeePassXC - Access Request)$" - # "float,class:^(org.keepassxc.KeePassXC)$,title:^(Unlock Database - KeePassXC)$" - # "pin,class:^(org.keepassxc.KeePassXC)$,title:^(Unlock Database - KeePassXC)$" - # "float,title:^(Open)$" - # "float,title:^(Choose Files)$" - # "float,title:^(Save As)$" - # "float,title:^(Confirm to replace files)$" - # "float,title:^(File Operation Progress)$" - # "float,class:^(firefox)$,title:^(Picture-in-Picture)$" - # "pin,class:^(firefox)$,title:^(Picture-in-Picture)$" - # "suppressevent fullscreen,class:^(firefox)$,title:^(Picture-in-Picture)$" - # "float,class:^(firefox)$,title:^(Firefox — Sharing Indicator)$" - # "suppressevent fullscreen,class:^(firefox)$,title:^(Firefox — Sharing Indicator)$" - # "float,class:^(firefox)$,title:^(Extension:.* Mozilla Firefox)$" - # "suppressevent fullscreen,class:^(firefox)$,title:^(Extension:.* Mozilla Firefox)$" - # "float,class:^(org.telegram.desktop)$,title:^(Media viewer)$" - # "center,class:^(org.telegram.desktop)$,title:^(Media viewer)$" - # "idleinhibit fullscreen, class:^(.*)" - # "idleinhibit focus, class:^(steam_app_.*)$" - # "idleinhibit focus, class:^(mpv)$" - # ]; - layer_rule = [ { match.namespace = "^eww%-blur$"; blur = true; @@ -329,8 +302,6 @@ in { (bind "SUPER + SHIFT + 8" (dsp.moveToWorkspace 8)) (bind "SUPER + 9" (dsp.focusWorkspace 9)) (bind "SUPER + SHIFT + 9" (dsp.moveToWorkspace 9)) - (bind "SUPER + 0" (dsp.focusWorkspace 0)) - (bind "SUPER + SHIFT + 0" (dsp.moveToWorkspace 0)) (bind "XF86AudioPlay" (dsp.exec "${lib.getExe pkgs.playerctl} play-pause")) (bind "XF86AudioPrev" (dsp.exec "${lib.getExe pkgs.playerctl} previous")) (bind "XF86AudioNext" (dsp.exec "${lib.getExe pkgs.playerctl} next"))