import os import re import subprocess from typing import override from ..abstracts import AbstractDisplay from ..structs import Modeline, MonitorInfo from ._gnome_types import GNOMEDisplayConfig # Half replaced implementation. More refactoring needs to be done in regards to setting the display. # Everything will be replaced with dorkbus Mutter stuff. MODE_REGEX_PATTERN = re.compile(r"(\d+)x(\d+)@(\d+\.\d+)") class Display(AbstractDisplay): @override def get_modes(self): mutter_display_state = GNOMEDisplayConfig() mutter_display_state.get_dbus_info() primary_connectors = { m[0] for lm in mutter_display_state.logical_monitors if lm.is_primary for m in lm.monitors } result = [] for monitor in mutter_display_state.monitors: modes = [ Modeline( mode.width, mode.height, mode.refresh_rate, ) for mode in monitor.modes ] result.append( MonitorInfo( monitor.connector, monitor.connector in primary_connectors, modes ) ) return result @override def set_mode(self, modeline, requested_connector=None) -> None: subprocess.run( [ "gdctl", "set", "--logical-monitor", "--primary", "--monitor", requested_connector, "--mode", str(modeline), ] ) @override def save_current_mode(self, location): gdctl_output = subprocess.run( ["gdctl", "show"], capture_output=True, text=True, check=True ) match = MODE_REGEX_PATTERN.search(gdctl_output.stdout) w, h, r = match.groups() with open(location, "w") as file: file.write(f"{w}x{h}@{r}") @override def read_saved_mode(self, location): with open(location, "r") as file: config_file_content = file.read() match = MODE_REGEX_PATTERN.search(config_file_content) w, h, r = match.groups() return Modeline(width=int(w), height=int(h), refresh_rate=float(r)) @staticmethod @override def detect(): return "gnome" in os.environ.get("XDG_CURRENT_DESKTOP", "").lower()