"""Steam-shaped X11 browser and popup fixture for a private X server.""" import json import os import sys from Xlib import X, Xatom, XK, display from Xlib.xobject.drawable import Window def main() -> None: connection = display.Display() root = connection.screen().root activeAtom = connection.intern_atom("_NET_ACTIVE_WINDOW") pidAtom = connection.intern_atom("_NET_WM_PID") def make_window(parent: Window, width: int, height: int) -> Window: window = parent.create_window(0, 0, width, height, 0, connection.screen().root_depth, event_mask=X.KeyPressMask | X.KeyReleaseMask) window.change_property(pidAtom, Xatom.CARDINAL, 32, [os.getpid()]) window.map() return window steam = make_window(root, 800, 600) steam.set_wm_class("steamwebhelper", "steam") mainHost = make_window(steam, 800, 600) browser = make_window(mainHost, 800, 600) popupHost = make_window(steam, 300, 600) popup = make_window(popupHost, 300, 600) other = make_window(root, 800, 600) other.set_wm_class("example", "Example") otherChild = make_window(other, 800, 600) windows = dict(steam=steam, browser=browser, popup=popup, popupHost=popupHost, other=other, otherChild=otherChild) root.change_property(activeAtom, Xatom.WINDOW, 32, [steam.id]) browser.set_input_focus(X.RevertToParent, X.CurrentTime) connection.sync() print(json.dumps({name: window.id for name, window in windows.items()}), flush=True) for line in sys.stdin: command = json.loads(line) action = command["action"] window = windows[command.get("window", "steam")] if action == "activate": root.change_property(activeAtom, Xatom.WINDOW, 32, [window.id]) window.set_input_focus(X.RevertToParent, X.CurrentTime) elif action == "focus": window.set_input_focus(X.RevertToParent, X.CurrentTime) elif action == "unmap": window.unmap() elif action == "map": window.map() elif action == "destroy": window.destroy() elif action == "class": window.set_wm_class("example", "Example") elif action == "xterm": window.set_wm_class("xterm", "XTerm") elif action == "unknown": root.delete_property(activeAtom) elif action == "pid": window.change_property(pidAtom, Xatom.CARDINAL, 32, [os.getpid() + 1]) elif action == "events": connection.sync() events = [] while connection.pending_events(): event = connection.next_event() if event.type in (X.KeyPress, X.KeyRelease): events.append({"window": event.window.id, "pressed": event.type == X.KeyPress, "escape": event.detail == connection.keysym_to_keycode(XK.string_to_keysym("Escape"))}) print(json.dumps(events), flush=True) continue connection.sync() print("ready", flush=True) connection.close() if __name__ == "__main__": main()