get app icons for each workspace
This commit is contained in:
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)
|
||||
fi
|
||||
|
||||
emit() {
|
||||
local active urgent result
|
||||
|
||||
active=$(hyprctl activeworkspace -j 2>/dev/null | jq -r '.id')
|
||||
urgent=$(hyprctl clients -j 2>/dev/null \
|
||||
| jq -r '[.[] | select(.urgent==true) | .workspace.id] | unique | .[]')
|
||||
|
||||
result="["
|
||||
for id in "${IDS[@]}"; do
|
||||
local is_active="false"
|
||||
local is_urgent="false"
|
||||
[[ "$id" == "$active" ]] && is_active="true"
|
||||
grep -qx "$id" <<< "$urgent" && is_urgent="true"
|
||||
result+="{\"id\":$id,\"label\":\"$id\",\"active\":$is_active,\"urgent\":$is_urgent,\"output\":\"$OUTPUT\"},"
|
||||
done
|
||||
|
||||
printf '%s\n' "${result%,}]"
|
||||
# find the socket dynamically instead of relying on env var
|
||||
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 active urgent_ids json
|
||||
|
||||
active=$(hyprctl activeworkspace -j 2>/dev/null | jq -r '.id')
|
||||
urgent_ids=$(hyprctl clients -j 2>/dev/null \
|
||||
| jq -r '[.[] | select(.urgent==true) | .workspace.id] | unique | .[]')
|
||||
|
||||
json=$(for id in "${IDS[@]}"; do
|
||||
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
|
||||
|
||||
# listen for events and re-emit
|
||||
socat -u "UNIX-CONNECT:/tmp/hypr/${HYPRLAND_INSTANCE_SIGNATURE}/.socket2.sock" - \
|
||||
SOCKET=$(get_socket)
|
||||
echo "Using socket: $SOCKET" >&2
|
||||
|
||||
socat -u "UNIX-CONNECT:$SOCKET" - \
|
||||
| stdbuf -oL grep -E "^(workspace|focusedmon|activewindow|urgent|createworkspace|destroyworkspace)>" \
|
||||
| while IFS= read -r _; do
|
||||
sleep 0.05
|
||||
|
||||
Reference in New Issue
Block a user