From 550ad9deac247cb46aa626eaf9c3f7551fb0b222 Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Thu, 15 Jul 2021 15:26:17 +0200 Subject: [PATCH] i3-companion: switch to Xlib to query XRandR state --- bin/i3-companion | 54 +++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/bin/i3-companion b/bin/i3-companion index 8d67e7c..f59b7c9 100755 --- a/bin/i3-companion +++ b/bin/i3-companion @@ -23,6 +23,8 @@ from i3ipc.aio import Connection from systemd import journal import ravel import dbussy +from Xlib import display +from Xlib.ext import randr def icon(font_number, char): @@ -508,32 +510,37 @@ async def workspace_info(i3, event): @on(I3Event.OUTPUT, StartEvent) -@static(last_setup={}) +@static(last_setup=None) @debounce(2) async def output_update(i3, event): """React to a XRandR change.""" - proc = await asyncio.create_subprocess_exec( - "xrandr", "--current", stdout=asyncio.subprocess.PIPE - ) - stdout, _ = await proc.communicate() - if proc.returncode != 0: - logger.warning(f"xrandr exited with {proc.returncode}") - return - stdout = stdout.decode("ascii") - xrandr_re = re.compile( - r"^" - r"(?P\S+) connected" - r"(?: (?Pprimary))? " - r"(?P\d+x\d+\+\d+\+\d+) " - r"\(.*?\) " - r"\d+mm x \d+mm" - r"$" - ) - current_setup = { - mo.groups() - for mo in {xrandr_re.match(line) for line in stdout.split("\n")} - if mo - } + + # Grab current setup. Synchronous, but it's short enough + d = display.Display() + screen = d.screen() + window = screen.root.create_window(0, 0, 1, 1, 1, screen.root_depth) + screen_resources = randr.get_screen_resources_current(window) + current_setup = set() + for output in screen_resources.outputs: + output_info = randr.get_output_info( + window, output, screen_resources.timestamp + ) + if output_info.crtc == 0: + continue + crtc_info = randr.get_crtc_info( + window, output_info.crtc, output_info.timestamp + ) + current_setup.add( + ( + output_info.name, + crtc_info.width, + crtc_info.height, + crtc_info.x, + crtc_info.y, + ) + ) + + # Compare to current setup if current_setup == output_update.last_setup: logger.debug("current xrandr setup unchanged") return @@ -542,6 +549,7 @@ async def output_update(i3, event): if event is StartEvent: return + # Trigger changes logger.info("xrandr change detected") cmds = ( "systemctl --user reload --no-block xsettingsd.service",