aboutsummaryrefslogtreecommitdiffstats
path: root/deckit/server.py
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-11-09 20:37:01 +0100
committerDanilo M. <danix@danix.xyz>2026-11-09 20:37:01 +0100
commit853f1ed1928aaeca9ea956c24bee12cd56a7cfdd (patch)
treec0ec5e0a1fcc3461d1d063139a77c428f4dce072 /deckit/server.py
parentedaad8e9f6e918c783fd8fb9237fa33032194ed5 (diff)
downloaddeck-it-853f1ed1928aaeca9ea956c24bee12cd56a7cfdd.tar.gz
deck-it-853f1ed1928aaeca9ea956c24bee12cd56a7cfdd.zip
feat: launcher icons follow the icon theme Keystone sets
Diffstat (limited to 'deckit/server.py')
-rw-r--r--deckit/server.py20
1 files changed, 17 insertions, 3 deletions
diff --git a/deckit/server.py b/deckit/server.py
index 01e7ec1..c6cc7e8 100644
--- a/deckit/server.py
+++ b/deckit/server.py
@@ -14,6 +14,7 @@ import secrets
import socketserver
import subprocess
import threading
+import time
from http.cookies import CookieError, SimpleCookie
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from pathlib import Path
@@ -29,7 +30,8 @@ ICON = re.compile(r"[A-Za-z0-9._-]{1,64}")
ICON_BASES = (Path.home() / ".local/share/icons", Path("/usr/share/icons"), Path.home() / ".icons")
CFG = config.load_config()
-ICON_THEME = CFG.get("icons", {}).get("theme", "candy-icons")
+FALLBACK_ICON_THEME = CFG.get("icons", {}).get("theme", "candy-icons")
+_theme_cache = {"t": 0.0, "v": None}
MONITOR = CFG.get("display", {}).get("name", "TAB")
PORT = CFG.get("ports", {}).get("command_center", 8765)
VNC_PORT = CFG.get("ports", {}).get("display", 5900)
@@ -51,10 +53,22 @@ def _run(cmd, timeout=2):
return ""
-def icon_path(name: str, theme: str = ICON_THEME, bases=ICON_BASES):
+def icon_theme() -> str:
+ """The icon theme Keystone's appearance drawer sets via gsettings."""
+ now = time.monotonic()
+ if _theme_cache["v"] and now - _theme_cache["t"] < 5:
+ return _theme_cache["v"]
+ out = _run(["gsettings", "get", "org.gnome.desktop.interface", "icon-theme"])
+ theme = out.strip().strip("'\"") or FALLBACK_ICON_THEME
+ _theme_cache.update(t=now, v=theme)
+ return theme
+
+
+def icon_path(name: str, theme: str | None = None, bases=ICON_BASES):
"""An app icon from the installed icon theme, so launchers follow the theme."""
if not ICON.fullmatch(name):
return None
+ theme = theme or icon_theme()
for base in bases:
for sub in ("apps/scalable", "apps/64", "apps/48", "apps/32"):
path = Path(base) / theme / sub / f"{name}.svg"
@@ -133,7 +147,7 @@ class Handler(BaseHTTPRequestHandler):
if path.startswith("/icons/"):
name = path[len("/icons/"):].removesuffix(".svg")
icon = icon_path(name)
- return self._send(200, icon.read_bytes(), "image/svg+xml", cache=True) if icon else self._send(404)
+ return self._send(200, icon.read_bytes(), "image/svg+xml") if icon else self._send(404)
if path.startswith("/api/"):
if not self._authed():
return self._send(401)