i3-companion: switch to Xlib to query XRandR state

This commit is contained in:
Vincent Bernat 2021-07-15 15:26:17 +02:00
parent 753eca739c
commit 550ad9deac

View file

@ -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<output>\S+) connected"
r"(?: (?P<primary>primary))? "
r"(?P<geometry>\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",