Gaming: raise HDT overlay in X so its buttons get clicks

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-10-08 11:20:10 +01:00
parent 4d559ad7eb
commit 8ac1d19cc6
2 changed files with 83 additions and 53 deletions

View file

@ -147,6 +147,63 @@
# Not "Proton-CachyOS Latest": Faugus owns that name and, on every
# launch, re-downloaded 330MB trying to replace this symlink with its
# own copy. Faugus entries use this as runner "Proton-CachyOS Nix".
# Hearthstone Deck Tracker's overlay buttons (apps/hdt-wine-overlay for
# the rest of the overlay fixes). XWayland gives a click to the topmost
# X window under the pointer, and Hyprland raises the game above the
# override-redirect overlay in X whenever it focuses it, so the buttons'
# clicks landed in the game. Wine never passes the overlay's own
# restacks on to X, so raise it from outside while the game is active.
systemd.user.services.hdt-overlay-raise = {
Unit = {
Description = "Keep HDT's overlay above Hearthstone in X";
After = [ "graphical-session.target" ];
PartOf = [ "graphical-session.target" ];
};
Service = {
ExecStart = lib.getExe (pkgs.writers.writePython3Bin "hdt-overlay-raise" {
libraries = [ pkgs.python3Packages.xlib ];
} ''
import time
from Xlib import X, display
d = display.Display()
root = d.screen().root
active_atom = d.intern_atom("_NET_ACTIVE_WINDOW")
names = {}
while True:
kids = root.query_tree().children # bottom -> top
ids = [w.id for w in kids]
for gone in set(names) - set(ids):
del names[gone]
found = {}
for w in kids:
if w.id not in names:
try:
names[w.id] = w.get_wm_name()
except Exception:
names[w.id] = None
if names[w.id] in ("Hearthstone", "HearthstoneOverlay"):
found[names[w.id]] = w
overlay = found.get("HearthstoneOverlay")
game = found.get("Hearthstone")
if not (overlay and game):
time.sleep(1)
continue
prop = root.get_full_property(active_atom, X.AnyPropertyType)
active = prop.value[0] if prop else 0
if active == game.id and ids.index(overlay.id) < ids.index(game.id):
overlay.configure(stack_mode=X.Above)
d.sync()
time.sleep(0.1)
'');
# X connection lost (Hyprland/XWayland restart): start over.
Restart = "always";
RestartSec = 5;
};
Install.WantedBy = [ "graphical-session.target" ];
};
home.file.".local/share/Steam/compatibilitytools.d/Proton-CachyOS Nix".source =
inputs.proton-cachyos-nix.packages.x86_64-linux.proton-cachyos-x86_64-v3.steamcompattool;
};