diff --git a/pyprland/common.py b/pyprland/common.py index 8c5947fb..e291e580 100644 --- a/pyprland/common.py +++ b/pyprland/common.py @@ -1,5 +1,6 @@ """ Shared utilities: logging """ import logging +import time import os __all__ = ["DEBUG", "get_logger", "init_logger"] @@ -7,6 +8,27 @@ DEBUG = os.environ.get("DEBUG", False) +def cache50ms(func): + """Caches an async function so it can't be called more than once every 50ms + + Doesn't support handling of the parameters + """ + last_result = None + last_update = 0.0 + + async def _cached_fn(*args): + nonlocal last_result, last_update + + t = time.time() + if last_update + 0.05 > t: + return last_result + last_result = await func(*args) + last_update = t + return last_result + + return _cached_fn + + class PyprError(Exception): """Used for errors which already triggered logging""" diff --git a/pyprland/plugins/scratchpads.py b/pyprland/plugins/scratchpads.py index c635be50..53074a26 100644 --- a/pyprland/plugins/scratchpads.py +++ b/pyprland/plugins/scratchpads.py @@ -57,6 +57,12 @@ def convert(size, dim): raise e +@cache50ms +async def get_clients(): + "Cached 'clients' IPC call" + return await hyprctlJSON("clients") + + async def get_client_props(addr: str | None = None, pid: int | None = None): "Returns client properties given its address" assert addr or pid @@ -66,7 +72,7 @@ async def get_client_props(addr: str | None = None, pid: int | None = None): assert pid, "Client pid is invalid" prop_name = "address" if addr else "pid" prop_value = addr if addr else pid - for client in await hyprctlJSON("clients"): + for client in await get_clients(): assert isinstance(client, dict) if client.get(prop_name) == prop_value: return client @@ -489,7 +495,7 @@ async def updateScratchInfo(self, orig_scratch: Scratch | None = None) -> None: """Update every scratchpads information if no `scratch` given, else update a specific scratchpad info""" pid = orig_scratch.pid if orig_scratch else None - for client in await hyprctlJSON("clients"): + for client in await get_clients(): assert isinstance(client, dict) if pid and pid != client["pid"]: continue @@ -544,7 +550,7 @@ async def _alternative_lookup(self): return False self.log.debug("Lookup hack triggered") # hack to update the client info from the provided class - for client in await hyprctlJSON("clients"): + for client in await get_clients(): assert isinstance(client, dict) for pending_scratch in class_lookup_hack: if pending_scratch.conf["class"] == client["class"]: