;; --------- Variables ;; --------- Listeners (deflisten hyprland-window ` socat -U - /tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock | \ grep 'activewindow>>' --line-buffered | \ sed 's/^activewindow>>[^,]*,//' --unbuffered `) (deflisten hyprland-submap ` socat -U - /tmp/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock | \ grep 'submap>>' --line-buffered | \ sed 's/^submap>>//' --unbuffered `) (deflisten workspace-list :initial '[]' `hyprland-workspaces _ | jq --compact-output --unbuffered '[ .[] | select(.id > 0) ]'`) (deflisten current-workspace :initial '[]' `hyprland-workspaces _ | jq --compact-output --unbuffered ' .[] | select(.id > 0) | select(.class | contains("active")) | .id '`) (deflisten audio-out-volume :initial 0 ` pamixer --get-volume pactl subscribe | grep --line-buffered "'change' on sink" | xargs -I {} pamixer --get-volume ` ) (deflisten audio-out-mute :initial false ` pamixer --get-mute pactl subscribe | grep --line-buffered "'change' on sink" | xargs -I {} pamixer --get-mute ` ) (deflisten audio-in-mute :initial false ` pamixer --get-mute --source @DEFAULT_SOURCE@ pactl subscribe | grep --line-buffered "'change' on source" | xargs -I {} pamixer --get-mute --source @DEFAULT_SOURCE@ ` ) (deflisten playerctl-status :initial "" `playerctl status --player strawberry --follow --format '{{lc(status)}}'`) (deflisten playerctl-title `playerctl metadata --player strawberry --follow --format '{{title}}'`) (deflisten playerctl-artist `playerctl metadata --player strawberry --follow --format '{{artist}}'`) (deflisten playerctl-album `playerctl metadata --player strawberry --follow --format '{{album}}'`) (deflisten playerctl-position `playerctl metadata --player strawberry --follow --format '{{duration(position)}}'`) (deflisten playerctl-length `playerctl metadata --player strawberry --follow --format '{{duration(mpris:length)}}'`) ;; -------------- Widgets (defwidget window-title [?limit-width] (label :visible {strlength(hyprland-window) > 0} :text hyprland-window :class "window-title" :tooltip hyprland-window :limit-width {limit-width ?: 999} ) ) (defwidget wm-mode [] (eventbox :class "wm-mode" :visible {strlength(hyprland-submap) > 0} :onclick `hyprctl dispatch submap '' >/dev/null` (label :text hyprland-submap :tooltip hyprland-submap ) ) ) (defwidget workspaces [monitor] (box :class "workspaces" (eventbox :onscroll `~/.config/eww/hyprworkspace {} ${monitor} ${current-workspace}` (box (for i in {jq(workspace-list, '[ .[] | select (.monitor == "${monitor}") ]')} (button :onclick "bash -c 'hyprctl dispatch workspace ${i.id} >/dev/null'" :class "item ${i.class}" "${i.name}" ) ) ) ) ) ) (defwidget clock [] (label :class "clock" :text {formattime(EWW_TIME, "%H:%M")} ) ) (defwidget battery [bat] (box :class {"battery " + (EWW_BATTERY[bat].capacity < 15 && EWW_BATTERY[bat].status != "Charging" ? "critical" : "") } :style {EWW_BATTERY[bat].status == "Charging" ? "padding-left: 8px" : "padding-left: 3px"} :space-evenly false (box :visible {EWW_BATTERY[bat].status == 'Charging'} :style "margin-right: 3px" (transform :rotate 75 :translate-x "-19px" :translate-y "-4px" (label :text "")) ) (transform :visible {EWW_BATTERY[bat].status != 'Charging'} :rotate 75 :translate-x "-21px" (label :text { EWW_BATTERY[bat].capacity < 10 ? "" : EWW_BATTERY[bat].capacity < 20 ? "" : EWW_BATTERY[bat].capacity < 30 ? "" : EWW_BATTERY[bat].capacity < 40 ? "" : EWW_BATTERY[bat].capacity < 50 ? "" : EWW_BATTERY[bat].capacity < 60 ? "" : EWW_BATTERY[bat].capacity < 70 ? "" : EWW_BATTERY[bat].capacity < 80 ? "" : EWW_BATTERY[bat].capacity < 90 ? "" : "" })) (label :text "100%") ) ) (defwidget volume-control [] (eventbox :onclick `pamixer --toggle-mute` ;;:onclick `notify-send "handler triggered"` :onscroll ` amt=1 if [ "{}" = "up" ]; then pamixer --increase $amt else pamixer --decrease $amt fi ` (box :space-evenly false :class {"volume-control " + (audio-out-mute ? "muted " : "")} (label :class "icon" :text { audio-out-mute ? "󰸈" : ( audio-out-volume < 10 ? "󰕿" : audio-out-volume < 60 ? "󰖀" : "󰕾" ) } ) (label :class "value" :text "${audio-out-volume}%") ) ) ) (defwidget mic-control [] (eventbox :class {"mic-control " + (audio-in-mute ? "muted " : "")} :onclick `pamixer --toggle-mute --source @DEFAULT_SOURCE@` (label :class "icon" :text {audio-in-mute ? "" : ""} ) ) ) (defwidget audio-controls [] (box :class "container audio-controls" :space-evenly false (volume-control) (mic-control)) ) (defwidget playerctl [?limit-width] (box :space-evenly false :class "container playerctl ${playerctl-status}" (eventbox (label :class "music-icon" :text "") ) (eventbox :visible { playerctl-status != '' } :onclick 'playerctl --player strawberry play-pause' :onrightclick 'playerctl --player strawberry next' :onmiddleclick 'playerctl --player strawberry previous' (box :class "details" :space-evenly false :tooltip `${playerctl-title} - ${playerctl-artist} - ${playerctl-album}` (label :class "status-icon" :text { (playerctl-status == 'playing') ? '' : '' } ) (label :class "track-info" :limit-width limit-width :text `${playerctl-title} - ${playerctl-artist} - ${playerctl-album}` ) (label :class "position" :markup `[${playerctl-position}/${playerctl-length}]` ) ) ) ) ) ;; ---------- Bars (defwidget bar [monitor ?title-limit-width] (centerbox :class "bar" :class "bar" (box :class "modules modules-left" :space-evenly false :halign "start" (workspaces :monitor monitor) (wm-mode) (playerctl :limit-width 60) ) (box :class "modules modules-center" :space-evenly false :halign "center" (window-title :limit-width title-limit-width) ) (box :class "modules modules-right" :space-evenly false :halign "end" (audio-controls) (battery :bat "BAT0") (clock) ) ) ) (defwindow bar-window-0 :monitor 0 :geometry (geometry :x "0%" :width "100%" :height "30px" :anchor "top center") :stacking "fg" ;; :reserve (struts :distance "80px" :side "top") :exclusive true :windowtype "dock" (box (bar :monitor "eDP-1" :title-limit-width 100)) ) (defwindow bar-window-1 :monitor 1 :geometry (geometry :x "0%" :width "100%" :height "30px" :anchor "top center") :stacking "fg" ;; :reserve (struts :distance "80px" :side "top") :exclusive true :windowtype "dock" (box (bar :monitor "DP-3")) ) (defwindow bar-window-2 :monitor 2 :geometry (geometry :x "0%" :width "100%" :height "30px" :anchor "top center") :stacking "fg" ;; :reserve (struts :distance "80px" :side "top") :exclusive true :windowtype "dock" (box (bar :monitor "DP-2" :title-limit-width 60)) )