mirror of
https://git.srhtnin.garden/sarah/SaraSuite.git
synced 2026-10-14 10:28:11 +02:00
Per-program Flet client app IDs so the dock shows the right icons
This commit is contained in:
1 parent
19bbad33a4
commit
56f10885de
12 files changed
+114
-18
No files matched your search
@@ -0,0 +1,67 @@
|
||||
"""Give a Flet program's window its own app ID on Linux, so the desktop can
|
||||
match it to the program's .desktop entry (icon, name) instead of showing
|
||||
every Flet program as "com.appveyor.flet" with a generic icon.
|
||||
|
||||
The Flet client's ID is a string built into its small launcher binary
|
||||
(`flet`, ~24 KB); the client sets it as both its GTK application ID and its
|
||||
process name, so Flet's own FLET_APP_ID (which only changes argv[0]) can't
|
||||
override it, on Wayland or X11. Instead this makes a per-program copy of the
|
||||
client in ~/.cache/SaraSuite/FletClient/ with that string replaced; the big
|
||||
parts (lib/, data/, share/) are symlinks to the original, so a copy costs
|
||||
~24 KB. Pointing FLET_VIEW_PATH at it makes Flet use the copy.
|
||||
|
||||
Used two ways:
|
||||
- SaraSuite imports it and calls ClientFor() before ft.run.
|
||||
- Installed programs' launchers run it with their own venv's python:
|
||||
export FLET_VIEW_PATH="$(python FletIdentity.py srhtnin.SaraFem)"
|
||||
It prints the copy's folder, or nothing if anything goes wrong, in which
|
||||
case Flet just uses its normal client.
|
||||
"""
|
||||
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
OriginalId = b"com.appveyor.flet"
|
||||
CopiesDir = Path.home() / ".cache" / "SaraSuite" / "FletClient"
|
||||
|
||||
|
||||
def ClientFor(AppId: str) -> str:
|
||||
"""Folder of a client copy whose app ID is AppId ("" if not possible).
|
||||
AppId needs a dot (a GTK rule) and at most 17 characters, the length of
|
||||
the original it replaces in place."""
|
||||
try:
|
||||
Encoded = AppId.encode("ascii")
|
||||
if "." not in AppId or not 0 < len(Encoded) <= len(OriginalId):
|
||||
return ""
|
||||
from flet_desktop import ensure_client_cached # the program's own Flet version
|
||||
|
||||
Original = Path(ensure_client_cached()) / "flet"
|
||||
Binary = (Original / "flet").read_bytes()
|
||||
Copy = CopiesDir / f"{Original.parent.name}-{AppId}" / "flet"
|
||||
Patched = Binary.replace(
|
||||
b"\x00" + OriginalId + b"\x00",
|
||||
b"\x00" + Encoded.ljust(len(OriginalId), b"\x00") + b"\x00",
|
||||
)
|
||||
if Binary.count(b"\x00" + OriginalId + b"\x00") != 1:
|
||||
return "" # not the client layout this was written for
|
||||
|
||||
Target = Copy / "flet"
|
||||
if not (Target.exists() and Target.read_bytes() == Patched):
|
||||
Copy.mkdir(parents=True, exist_ok=True)
|
||||
for Part in ("lib", "data", "share"):
|
||||
Link = Copy / Part
|
||||
if Link.is_symlink() or Link.exists():
|
||||
Link.unlink()
|
||||
if (Original / Part).exists():
|
||||
Link.symlink_to(Original / Part)
|
||||
Temporary = Target.with_suffix(".new")
|
||||
Temporary.write_bytes(Patched)
|
||||
Temporary.chmod(0o755)
|
||||
Temporary.replace(Target)
|
||||
return str(Copy)
|
||||
except Exception:
|
||||
return ""
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(ClientFor(sys.argv[1]) if len(sys.argv) > 1 else "")
|
||||
Reference in new issue
Block a user