Massive refactor (Zed wouldn't stop complaining about formatting) and

beginning of proper GNOME implementation.
This commit is contained in:
2026-08-15 23:56:17 +12:00
parent a4aa721a59
commit 19b7b89453
15 changed files with 346 additions and 148 deletions
+38 -23
View File
@@ -1,46 +1,58 @@
from ..structs import MonitorInfo, Modeline
from ..abstracts import AbstractDisplay
import json
import os
import re
import subprocess
import json
from ..abstracts import AbstractDisplay
from ..structs import Modeline, MonitorInfo
# Matches "1920x1080 @ 60.000 Hz" or "1920x1080@60.000"
MODE_REGEX = re.compile(r'(\d+)x(\d+)@(\d+\.\d+)')
MODE_REGEX = re.compile(r"(\d+)x(\d+)@(\d+\.\d+)")
class Display(AbstractDisplay):
def get_modes(self):
# wlr-randr --json is the 'civilized' way to do this on Trixie
result = subprocess.run(["wlr-randr", "--json"], capture_output=True, text=True, check=True)
result = subprocess.run(
["wlr-randr", "--json"], capture_output=True, text=True, check=True
)
data = json.loads(result.stdout)
monitors = []
for output in data:
modes = []
for m in output.get("modes", []):
modes.append(Modeline(
width=int(m["width"]),
height=int(m["height"]),
refresh_rate=float(m["refresh"])
))
monitors.append(MonitorInfo(
connector=output["name"], # Usually 'HEADLESS-1' in Cage
primary=output.get("focused", False),
modes=modes
))
modes.append(
Modeline(
width=int(m["width"]),
height=int(m["height"]),
refresh_rate=float(m["refresh"]),
)
)
monitors.append(
MonitorInfo(
connector=output["name"], # Usually 'HEADLESS-1' in Cage
primary=output.get("focused", False),
modes=modes,
)
)
return monitors
def set_mode(self, modeline, requested_connector="HEADLESS-1") -> None:
# Format: 1920x1080@60Hz
mode_str = f"{modeline.width}x{modeline.height}@{modeline.refresh_rate}Hz"
subprocess.run(["wlr-randr", "--output", requested_connector, "--mode", mode_str], check=True)
subprocess.run(
["wlr-randr", "--output", requested_connector, "--mode", mode_str],
check=True,
)
def save_current_mode(self, location):
# Implementation similar to your GNOME one but using wlr-randr
result = subprocess.run(["wlr-randr", "--json"], capture_output=True, text=True, check=True)
data = json.loads(result.stdout)[0] # Grab first monitor
result = subprocess.run(
["wlr-randr", "--json"], capture_output=True, text=True, check=True
)
data = json.loads(result.stdout)[0] # Grab first monitor
curr = data["current_mode"]
with open(location, "w") as f:
f.write(f"{curr['width']}x{curr['height']}@{curr['refresh']}")
@@ -53,4 +65,7 @@ class Display(AbstractDisplay):
@staticmethod
def detect():
# Cage doesn't always set XDG_CURRENT_DESKTOP, but it's a wlroots compositor
return os.environ.get("WLR_BACKENDS") == "headless" or "cage" in os.environ.get("XDG_CURRENT_DESKTOP", "").lower()
return (
os.environ.get("WLR_BACKENDS") == "headless"
or "cage" in os.environ.get("XDG_CURRENT_DESKTOP", "").lower()
)