get app icons for each workspace
This commit is contained in:
28
eww/eww.scss
28
eww/eww.scss
@@ -26,15 +26,14 @@ $red: #f38ba8;
|
|||||||
// Window margin (replaces calc() in geometry)
|
// Window margin (replaces calc() in geometry)
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
.eww-bar {
|
.eww-bar {
|
||||||
margin: 8px 10px 0 10px;
|
margin: 0 0 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
// Bar root
|
// Bar root
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
.bar-left{
|
.bar-left{
|
||||||
background: $bg;
|
background: transparent;
|
||||||
border-radius: 8px;
|
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
min-height: 24px;
|
min-height: 24px;
|
||||||
}
|
}
|
||||||
@@ -52,18 +51,15 @@ $red: #f38ba8;
|
|||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
// Workspaces
|
// Workspaces
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
.workspaces {
|
|
||||||
padding: 0 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.workspace-btn {
|
.workspace-btn {
|
||||||
background: transparent;
|
min-width: 32px;
|
||||||
border-radius: 5px;
|
padding: 2px 8px;
|
||||||
|
background: rgba(0, 0, 0, 0.35);
|
||||||
|
border-radius: 8px;
|
||||||
color: $subtext;
|
color: $subtext;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
padding: 2px 7px;
|
|
||||||
margin: 2px 0px;
|
|
||||||
transition: all 200ms ease;
|
transition: all 200ms ease;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -72,7 +68,7 @@ $red: #f38ba8;
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
background: rgba(23, 142, 21, 0.778);
|
background: rgba(90, 148, 22, 0.85);
|
||||||
color: $accent;
|
color: $accent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,12 +78,16 @@ $red: #f38ba8;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
// Window title
|
// Window title
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
.window-title {
|
.window-title {
|
||||||
padding-left: 4px;
|
padding: 0px 8px;
|
||||||
color: $subtext;
|
color: $subtext;
|
||||||
|
background: $bg;
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
.window-icon {
|
.window-icon {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
@@ -100,6 +100,7 @@ $red: #f38ba8;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
// Clock
|
// Clock
|
||||||
// ─────────────────────────────────────────────
|
// ─────────────────────────────────────────────
|
||||||
@@ -184,3 +185,6 @@ $red: #f38ba8;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.center-btn.active {
|
||||||
|
background: rgba(90, 148, 22, 0.85);
|
||||||
|
}
|
||||||
174
eww/eww.yuck
174
eww/eww.yuck
@@ -4,11 +4,11 @@
|
|||||||
|
|
||||||
(deflisten workspaces-dp2
|
(deflisten workspaces-dp2
|
||||||
:initial "[]"
|
:initial "[]"
|
||||||
"bash ~/.config/eww/scripts/get-workspaces.sh DP-2")
|
"python3 ~/.config/eww/scripts/get-workspaces.py DP-2")
|
||||||
|
|
||||||
(deflisten workspaces-hdmi
|
(deflisten workspaces-hdmi
|
||||||
:initial "[]"
|
:initial "[]"
|
||||||
"bash ~/.config/eww/scripts/get-workspaces.sh HDMI-A-1")
|
"python3 ~/.config/eww/scripts/get-workspaces.py HDMI-A-1")
|
||||||
|
|
||||||
(deflisten active-window-dp2
|
(deflisten active-window-dp2
|
||||||
:initial ""
|
:initial ""
|
||||||
@@ -50,12 +50,26 @@
|
|||||||
;;; Helper Widgets
|
;;; Helper Widgets
|
||||||
;;; ─────────────────────────────────────────────
|
;;; ─────────────────────────────────────────────
|
||||||
|
|
||||||
(defwidget workspace-btn [id label active urgent output]
|
(defwidget workspace-btn [id label active urgent output icons pxwidth]
|
||||||
|
(box
|
||||||
|
:orientation "h"
|
||||||
|
:width pxwidth
|
||||||
(button
|
(button
|
||||||
:class {active ? "workspace-btn active" : urgent ? "workspace-btn urgent" : "workspace-btn"}
|
:class {active ? "workspace-btn active" : urgent ? "workspace-btn urgent" : "workspace-btn"}
|
||||||
:onclick "hyprctl dispatch workspace ${id}"
|
:onclick "hyprctl dispatch workspace ${id}"
|
||||||
:width 32
|
:hexpand true
|
||||||
label))
|
(box
|
||||||
|
:orientation "h"
|
||||||
|
:spacing 3
|
||||||
|
:halign "center"
|
||||||
|
:valign "center"
|
||||||
|
(label :text label :class "ws-label")
|
||||||
|
(for icon in icons
|
||||||
|
(image
|
||||||
|
:path icon
|
||||||
|
:image-width 16
|
||||||
|
:image-height 16))))))
|
||||||
|
|
||||||
|
|
||||||
(defwidget workspaces-widget [workspaces]
|
(defwidget workspaces-widget [workspaces]
|
||||||
(box
|
(box
|
||||||
@@ -68,25 +82,21 @@
|
|||||||
:label {ws.label}
|
:label {ws.label}
|
||||||
:active {ws.active}
|
:active {ws.active}
|
||||||
:urgent {ws.urgent}
|
:urgent {ws.urgent}
|
||||||
:output {ws.output}))))
|
:output {ws.output}
|
||||||
|
:icons {ws.icons}
|
||||||
|
:pxwidth {ws.pxwidth}))))
|
||||||
|
|
||||||
(defwidget window-widget [title]
|
;;; add this with your variables
|
||||||
(box
|
(defvar clock-show-date false)
|
||||||
:class "window-title"
|
|
||||||
:orientation "h"
|
|
||||||
:space-evenly false
|
|
||||||
(label
|
|
||||||
:class "window-text"
|
|
||||||
:text {title}
|
|
||||||
:limit-width 20)))
|
|
||||||
|
|
||||||
|
;;; replace your clock-widget
|
||||||
(defwidget clock-widget []
|
(defwidget clock-widget []
|
||||||
(box
|
(button
|
||||||
:class "clock"
|
:class "clock"
|
||||||
:orientation "h"
|
:onclick "eww update clock-show-date=${clock-show-date == 'true' ? 'false' : 'true'}"
|
||||||
:spacing 2
|
(label
|
||||||
(label :text clock-time :class "clock-time")
|
:class "clock-time"
|
||||||
))
|
:text {clock-show-date == "true" ? clock-date : clock-time})))
|
||||||
|
|
||||||
(defwidget cpu-widget []
|
(defwidget cpu-widget []
|
||||||
(box
|
(box
|
||||||
@@ -155,17 +165,15 @@
|
|||||||
(defwidget bar-dp2 []
|
(defwidget bar-dp2 []
|
||||||
(centerbox
|
(centerbox
|
||||||
:orientation "h"
|
:orientation "h"
|
||||||
(box :class "bar-left" :orientation "h" :spacing 2 :space-evenly false :halign "start"
|
(box :class "bar-left" :orientation "h" :spacing 8 :space-evenly false :halign "start"
|
||||||
(workspaces-widget :workspaces workspaces-dp2)
|
(workspaces-widget :workspaces workspaces-dp2))
|
||||||
(window-widget :title active-window-dp2))
|
|
||||||
(box :class "bar-center" :orientation "h" :spacing 12 :space-evenly false
|
(box :class "bar-center" :orientation "h" :spacing 12 :space-evenly false
|
||||||
(logout-btn)
|
|
||||||
(clock-widget)
|
(clock-widget)
|
||||||
(settings-btn))
|
)
|
||||||
(box :class "bar-right" :orientation "h" :spacing 6 :space-evenly false :halign "end"
|
(box :class "bar-right" :orientation "h" :spacing 8 :space-evenly false :halign "end"
|
||||||
(theme-widget)
|
(settings-menu)
|
||||||
(volume-widget :on-click "bash ~/.config/eww/scripts/toggle-mixer.sh")
|
(logout-menu)
|
||||||
(network-widget)
|
|
||||||
(cpu-widget)
|
(cpu-widget)
|
||||||
(mem-widget))))
|
(mem-widget))))
|
||||||
|
|
||||||
@@ -174,7 +182,7 @@
|
|||||||
:geometry (geometry
|
:geometry (geometry
|
||||||
:x "10px"
|
:x "10px"
|
||||||
:y "8px"
|
:y "8px"
|
||||||
:width "1900px"
|
:width "1920px"
|
||||||
:height "24px"
|
:height "24px"
|
||||||
:anchor "top center")
|
:anchor "top center")
|
||||||
:exclusive true
|
:exclusive true
|
||||||
@@ -189,17 +197,13 @@
|
|||||||
(defwidget bar-hdmi []
|
(defwidget bar-hdmi []
|
||||||
(centerbox
|
(centerbox
|
||||||
:orientation "h"
|
:orientation "h"
|
||||||
(box :class "bar-left" :orientation "h" :spacing 8 :space-evenly false :max-width 300
|
(box :class "bar-left" :orientation "h" :spacing 8 :space-evenly false
|
||||||
(workspaces-widget :workspaces workspaces-hdmi)
|
(workspaces-widget :workspaces workspaces-hdmi))
|
||||||
(window-widget :title active-window-hdmi))
|
|
||||||
(box :class "bar-center" :orientation "h" :spacing 12 :space-evenly false
|
(box :class "bar-center" :orientation "h" :spacing 12 :space-evenly false
|
||||||
(logout-btn)
|
(logout-btn)
|
||||||
(clock-widget)
|
(clock-widget))
|
||||||
(settings-btn))
|
(box :class "bar-right" :orientation "h" :spacing 2 :space-evenly false :halign "end"
|
||||||
(box :class "bar-right" :orientation "h" :spacing 6 :space-evenly false :halign "end"
|
(settings-btn)
|
||||||
(theme-widget)
|
|
||||||
(volume-widget :on-click "pavucontrol")
|
|
||||||
(network-widget)
|
|
||||||
(cpu-widget)
|
(cpu-widget)
|
||||||
(mem-widget))))
|
(mem-widget))))
|
||||||
|
|
||||||
@@ -208,10 +212,100 @@
|
|||||||
:geometry (geometry
|
:geometry (geometry
|
||||||
:x "10px"
|
:x "10px"
|
||||||
:y "8px"
|
:y "8px"
|
||||||
:width "1900px"
|
:width "1920px"
|
||||||
:height "24px"
|
:height "24px"
|
||||||
:anchor "top center")
|
:anchor "top center")
|
||||||
:exclusive true
|
:exclusive true
|
||||||
:layer "top"
|
:layer "top"
|
||||||
:namespace "eww-bar"
|
:namespace "eww-bar"
|
||||||
(bar-hdmi))
|
(bar-hdmi))
|
||||||
|
|
||||||
|
|
||||||
|
(defvar logout-menu-open false)
|
||||||
|
(defvar settings-menu-open false)
|
||||||
|
|
||||||
|
(defwidget logout-menu []
|
||||||
|
(box
|
||||||
|
:class "center-menu-wrap"
|
||||||
|
:orientation "h"
|
||||||
|
:spacing 4
|
||||||
|
:space-evenly false
|
||||||
|
|
||||||
|
(revealer
|
||||||
|
:reveal {logout-menu-open == "true"}
|
||||||
|
:transition "slideright"
|
||||||
|
:duration "200ms"
|
||||||
|
(box
|
||||||
|
:class "center-menu"
|
||||||
|
:orientation "h"
|
||||||
|
:spacing 4
|
||||||
|
:space-evenly false
|
||||||
|
|
||||||
|
(button
|
||||||
|
:class "center-btn"
|
||||||
|
:tooltip "Lock"
|
||||||
|
:onclick "eww update logout-menu-open=false && hyprlock"
|
||||||
|
(label :text ""))
|
||||||
|
|
||||||
|
(button
|
||||||
|
:class "center-btn"
|
||||||
|
:tooltip "Reboot"
|
||||||
|
:onclick "eww update logout-menu-open=false && systemctl reboot"
|
||||||
|
(label :text ""))
|
||||||
|
|
||||||
|
(button
|
||||||
|
:class "center-btn"
|
||||||
|
:tooltip "Shutdown"
|
||||||
|
:onclick "eww update logout-menu-open=false && systemctl poweroff"
|
||||||
|
(label :text ""))
|
||||||
|
|
||||||
|
(button
|
||||||
|
:class "center-btn"
|
||||||
|
:tooltip "Logout"
|
||||||
|
:onclick "eww update logout-menu-open=false && hyprctl dispatch exit"
|
||||||
|
(label :text ""))))
|
||||||
|
(button
|
||||||
|
:class "center-btn"
|
||||||
|
:onclick "eww update logout-menu-open=${logout-menu-open == 'true' ? 'false' : 'true'} && eww update settings-menu-open=false"
|
||||||
|
(label :text {logout-menu-open == "true" ? "" : ""}))
|
||||||
|
|
||||||
|
))
|
||||||
|
|
||||||
|
(defwidget settings-menu []
|
||||||
|
(box
|
||||||
|
:class "center-menu-wrap"
|
||||||
|
:orientation "h"
|
||||||
|
:spacing 4
|
||||||
|
:space-evenly false
|
||||||
|
|
||||||
|
(revealer
|
||||||
|
:reveal {settings-menu-open == "true"}
|
||||||
|
:transition "slideright"
|
||||||
|
:duration "200ms"
|
||||||
|
(box
|
||||||
|
:class "center-menu"
|
||||||
|
:orientation "h"
|
||||||
|
:spacing 4
|
||||||
|
:space-evenly false
|
||||||
|
|
||||||
|
|
||||||
|
(theme-widget)
|
||||||
|
|
||||||
|
(volume-widget :on-click "bash ~/.config/eww/scripts/toggle-mixer.sh")
|
||||||
|
|
||||||
|
(network-widget)
|
||||||
|
|
||||||
|
(button
|
||||||
|
:class "center-btn"
|
||||||
|
:tooltip "Displays"
|
||||||
|
:onclick "eww update settings-menu-open=false && wdisplays"
|
||||||
|
(label :text ""))
|
||||||
|
|
||||||
|
))
|
||||||
|
|
||||||
|
(button
|
||||||
|
:class {settings-menu-open == "true" ? "center-btn active" : "center-btn"}
|
||||||
|
:onclick "eww update settings-menu-open=${settings-menu-open == 'true' ? 'false' : 'true'} && eww update logout-menu-open=false"
|
||||||
|
(label :text {settings-menu-open == "true" ? "" : ""}))
|
||||||
|
|
||||||
|
))
|
||||||
33
eww/scripts/get-active-window.sh
Executable file
33
eww/scripts/get-active-window.sh
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
OUTPUT="${1:-DP-2}"
|
||||||
|
|
||||||
|
get_socket() {
|
||||||
|
local runtime="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
|
||||||
|
local sig
|
||||||
|
sig=$(ls "$runtime/hypr/" 2>/dev/null | head -n1)
|
||||||
|
echo "$runtime/hypr/$sig/.socket2.sock"
|
||||||
|
}
|
||||||
|
|
||||||
|
emit() {
|
||||||
|
local monitor_ws title
|
||||||
|
|
||||||
|
monitor_ws=$(hyprctl monitors -j 2>/dev/null \
|
||||||
|
| jq -r ".[] | select(.name==\"$OUTPUT\") | .activeWorkspace.id")
|
||||||
|
|
||||||
|
title=$(hyprctl clients -j 2>/dev/null \
|
||||||
|
| jq -r ".[] | select(.workspace.id==$monitor_ws and .focusHistoryID==0) | .title" \
|
||||||
|
| head -n1)
|
||||||
|
|
||||||
|
printf '%s\n' "${title:-}"
|
||||||
|
}
|
||||||
|
|
||||||
|
emit
|
||||||
|
|
||||||
|
SOCKET=$(get_socket)
|
||||||
|
|
||||||
|
socat -u "UNIX-CONNECT:$SOCKET" - \
|
||||||
|
| stdbuf -oL grep -E "^(activewindow|focusedmon|workspace|closewindow)>" \
|
||||||
|
| while IFS= read -r _; do
|
||||||
|
sleep 0.05
|
||||||
|
emit
|
||||||
|
done
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
OUTPUT="${1:-DP-2}"
|
|
||||||
|
|
||||||
emit() {
|
|
||||||
local monitor title
|
|
||||||
|
|
||||||
monitor=$(hyprctl monitors -j 2>/dev/null \
|
|
||||||
| jq -r ".[] | select(.name==\"$OUTPUT\") | .activeWorkspace.id")
|
|
||||||
|
|
||||||
title=$(hyprctl clients -j 2>/dev/null \
|
|
||||||
| jq -r ".[] | select(.workspace.id==$monitor and .focusHistoryID==0) | .title" \
|
|
||||||
| head -n1)
|
|
||||||
|
|
||||||
printf '%s\n' "${title:-}"
|
|
||||||
}
|
|
||||||
|
|
||||||
emit
|
|
||||||
|
|
||||||
socat -u "UNIX-CONNECT:/tmp/hypr/${HYPRLAND_INSTANCE_SIGNATURE}/.socket2.sock" - \
|
|
||||||
| stdbuf -oL grep -E "^(activewindow|focusedmon|workspace|closewindow)>" \
|
|
||||||
| while IFS= read -r _; do
|
|
||||||
sleep 0.05
|
|
||||||
emit
|
|
||||||
done
|
|
||||||
32
eww/scripts/get-workspace-icons.sh
Normal file
32
eww/scripts/get-workspace-icons.sh
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# get-workspace-icons.sh <workspace_id>
|
||||||
|
|
||||||
|
WORKSPACE=${1:-1}
|
||||||
|
|
||||||
|
# Get app classes on the workspace
|
||||||
|
CLASSES=$(hyprctl clients -j | jq -r \
|
||||||
|
"[.[] | select(.workspace.id == $WORKSPACE) | .class] | unique[]")
|
||||||
|
|
||||||
|
for class in $CLASSES; do
|
||||||
|
echo "=== $class ==="
|
||||||
|
|
||||||
|
# Find matching .desktop file (case-insensitive)
|
||||||
|
DESKTOP=$(find /usr/share/applications ~/.local/share/applications \
|
||||||
|
-name "*.desktop" 2>/dev/null | \
|
||||||
|
xargs grep -li "^Name.*=$class\|^Exec.*$class\|^\[Desktop Entry\]" 2>/dev/null | \
|
||||||
|
head -1)
|
||||||
|
|
||||||
|
if [[ -n "$DESKTOP" ]]; then
|
||||||
|
ICON_NAME=$(grep "^Icon=" "$DESKTOP" | cut -d= -f2)
|
||||||
|
echo " Icon name: $ICON_NAME"
|
||||||
|
|
||||||
|
# Find actual icon file
|
||||||
|
ICON_FILE=$(find /usr/share/icons ~/.local/share/icons /usr/share/pixmaps \
|
||||||
|
-name "${ICON_NAME}.*" \( -name "*.png" -o -name "*.svg" \) \
|
||||||
|
2>/dev/null | sort | tail -1)
|
||||||
|
|
||||||
|
echo " Icon file: ${ICON_FILE:-not found}"
|
||||||
|
else
|
||||||
|
echo " .desktop file not found"
|
||||||
|
fi
|
||||||
|
done
|
||||||
79
eww/scripts/get-workspaces.py
Normal file
79
eww/scripts/get-workspaces.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import subprocess, json, os, socket
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
OUTPUT = None # set via argv, e.g. "DP-2"
|
||||||
|
|
||||||
|
def get_icon(cls: str) -> str | None:
|
||||||
|
theme = Gtk.IconTheme.get_default()
|
||||||
|
for name in [cls, cls.lower(), cls.lower().rstrip("0123456789")]:
|
||||||
|
info = theme.lookup_icon(name, 16, 0)
|
||||||
|
if info:
|
||||||
|
return info.get_filename()
|
||||||
|
return None
|
||||||
|
# Define which workspace IDs belong to each monitor
|
||||||
|
MONITOR_WORKSPACES = {
|
||||||
|
"DP-2": [1, 2, 3, 4, 5],
|
||||||
|
"HDMI-A-1": [6, 7, 8, 9, 10],
|
||||||
|
}
|
||||||
|
|
||||||
|
def build():
|
||||||
|
clients = json.loads(subprocess.check_output(["hyprctl", "clients", "-j"]))
|
||||||
|
workspaces = json.loads(subprocess.check_output(["hyprctl", "workspaces", "-j"]))
|
||||||
|
active = json.loads(subprocess.check_output(["hyprctl", "activeworkspace", "-j"]))
|
||||||
|
|
||||||
|
# existing workspace IDs on this monitor (Hyprland only lists non-empty ones)
|
||||||
|
existing = {w["id"] for w in workspaces if w["monitor"] == OUTPUT}
|
||||||
|
|
||||||
|
# all IDs we want to show, including empty ones
|
||||||
|
all_ids = sorted(set(MONITOR_WORKSPACES.get(OUTPUT, [])) | existing)
|
||||||
|
|
||||||
|
# build icon map
|
||||||
|
amount = {}
|
||||||
|
icons: dict[int, list[str]] = {}
|
||||||
|
for c in clients:
|
||||||
|
wid = c["workspace"]["id"]
|
||||||
|
cls = c.get("class") or c.get("initialClass", "")
|
||||||
|
path = get_icon(cls)
|
||||||
|
if path and path not in icons.get(wid, []):
|
||||||
|
icons.setdefault(wid, []).append(path)
|
||||||
|
amount[c["workspace"]["id"]] =+ 1
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for wid in all_ids:
|
||||||
|
result.append({
|
||||||
|
"id": wid,
|
||||||
|
"label": str(wid),
|
||||||
|
"active": wid == active["id"],
|
||||||
|
"urgent": any(c.get("urgent") and c["workspace"]["id"] == wid for c in clients),
|
||||||
|
"output": OUTPUT,
|
||||||
|
"icons": icons.get(wid, []),
|
||||||
|
"pxwidth": 32 + len(icons.get(wid, [])) * 20,
|
||||||
|
})
|
||||||
|
|
||||||
|
print(json.dumps(result), flush=True)
|
||||||
|
|
||||||
|
def watch():
|
||||||
|
xdg = os.environ.get("XDG_RUNTIME_DIR", f"/run/user/{os.getuid()}")
|
||||||
|
sig = os.environ.get("HYPRLAND_INSTANCE_SIGNATURE", "")
|
||||||
|
sock = f"{xdg}/hypr/{sig}/.socket2.sock"
|
||||||
|
|
||||||
|
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s:
|
||||||
|
s.connect(sock)
|
||||||
|
buf = ""
|
||||||
|
while True:
|
||||||
|
buf += s.recv(4096).decode()
|
||||||
|
while "\n" in buf:
|
||||||
|
line, buf = buf.split("\n", 1)
|
||||||
|
ev = line.split(">>")[0]
|
||||||
|
if ev in {"workspace", "openwindow", "closewindow",
|
||||||
|
"movewindow", "urgent", "focusedmon", "activelayout"}:
|
||||||
|
build()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
OUTPUT = sys.argv[1] if len(sys.argv) > 1 else None
|
||||||
|
build()
|
||||||
|
watch()
|
||||||
@@ -7,30 +7,39 @@ else
|
|||||||
IDS=(6 7 8 9 10)
|
IDS=(6 7 8 9 10)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
emit() {
|
# find the socket dynamically instead of relying on env var
|
||||||
local active urgent result
|
get_socket() {
|
||||||
|
local runtime="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
|
||||||
active=$(hyprctl activeworkspace -j 2>/dev/null | jq -r '.id')
|
local sig
|
||||||
urgent=$(hyprctl clients -j 2>/dev/null \
|
sig=$(ls "$runtime/hypr/" 2>/dev/null | head -n1)
|
||||||
| jq -r '[.[] | select(.urgent==true) | .workspace.id] | unique | .[]')
|
echo "$runtime/hypr/$sig/.socket2.sock"
|
||||||
|
}
|
||||||
result="["
|
|
||||||
for id in "${IDS[@]}"; do
|
emit() {
|
||||||
local is_active="false"
|
local active urgent_ids json
|
||||||
local is_urgent="false"
|
|
||||||
[[ "$id" == "$active" ]] && is_active="true"
|
active=$(hyprctl activeworkspace -j 2>/dev/null | jq -r '.id')
|
||||||
grep -qx "$id" <<< "$urgent" && is_urgent="true"
|
urgent_ids=$(hyprctl clients -j 2>/dev/null \
|
||||||
result+="{\"id\":$id,\"label\":\"$id\",\"active\":$is_active,\"urgent\":$is_urgent,\"output\":\"$OUTPUT\"},"
|
| jq -r '[.[] | select(.urgent==true) | .workspace.id] | unique | .[]')
|
||||||
done
|
|
||||||
|
json=$(for id in "${IDS[@]}"; do
|
||||||
printf '%s\n' "${result%,}]"
|
is_active=false
|
||||||
|
is_urgent=false
|
||||||
|
[[ "$id" == "$active" ]] && is_active=true
|
||||||
|
grep -qx "$id" <<< "$urgent_ids" && is_urgent=true
|
||||||
|
printf '{"id":%s,"label":"%s","active":%s,"urgent":%s,"output":"%s"}\n' \
|
||||||
|
"$id" "$id" "$is_active" "$is_urgent" "$OUTPUT"
|
||||||
|
done | jq -sc '.')
|
||||||
|
|
||||||
|
printf '%s\n' "$json"
|
||||||
}
|
}
|
||||||
|
|
||||||
# emit once on start
|
|
||||||
emit
|
emit
|
||||||
|
|
||||||
# listen for events and re-emit
|
SOCKET=$(get_socket)
|
||||||
socat -u "UNIX-CONNECT:/tmp/hypr/${HYPRLAND_INSTANCE_SIGNATURE}/.socket2.sock" - \
|
echo "Using socket: $SOCKET" >&2
|
||||||
|
|
||||||
|
socat -u "UNIX-CONNECT:$SOCKET" - \
|
||||||
| stdbuf -oL grep -E "^(workspace|focusedmon|activewindow|urgent|createworkspace|destroyworkspace)>" \
|
| stdbuf -oL grep -E "^(workspace|focusedmon|activewindow|urgent|createworkspace|destroyworkspace)>" \
|
||||||
| while IFS= read -r _; do
|
| while IFS= read -r _; do
|
||||||
sleep 0.05
|
sleep 0.05
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ DEPS=(
|
|||||||
fastfetch
|
fastfetch
|
||||||
waybar
|
waybar
|
||||||
jq
|
jq
|
||||||
|
python-gobject # arch
|
||||||
)
|
)
|
||||||
|
|
||||||
PASS=0
|
PASS=0
|
||||||
|
|||||||
@@ -317,7 +317,7 @@ windowrule {
|
|||||||
|
|
||||||
# env stuff
|
# env stuff
|
||||||
#exec-once = waybar --style ~/.config/waybar/style.css
|
#exec-once = waybar --style ~/.config/waybar/style.css
|
||||||
exec-once = ~/.config/eww/scipts/launch.sh
|
exec-once = bash ~/.config/eww/scripts/launch.sh
|
||||||
exec-once = hyprpaper
|
exec-once = hyprpaper
|
||||||
exec-once = ~/.config/hypr/theme-cycle.sh
|
exec-once = ~/.config/hypr/theme-cycle.sh
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user