diff --git a/src/scripts/python/setupmonitor.py b/src/scripts/python/setupmonitor.py index 0be74ca..501bb5a 100644 --- a/src/scripts/python/setupmonitor.py +++ b/src/scripts/python/setupmonitor.py @@ -31,12 +31,12 @@ Date: 2023 Mar 04 import Xlib.display import Xlib.ext.randr import configparser -from operator import itemgetter from util import edit_distance from util.egalax import get_egalax_drm_pure_name +import subprocess CONFIG_NAME = "conf/desktop.conf" - +XRANDR = "/usr/bin/xrandr" def read_config(): """Reads config file of desktop setup @@ -69,7 +69,11 @@ def all_connected_monitor(): def get_edid_name(drm_name: str): - """Change eGalax DRM name to atom name""" + """Change eGalax DRM name to atom name + + This function is very sensitive to kernel version and might not work + with some kernels. + """ card_num, name = drm_name[4:].split("-", maxsplit=1) first, second = name.rsplit("-", maxsplit=1) return first + "-" + card_num + "-" + second @@ -101,7 +105,7 @@ def prepare_monitors(config): main = config["DEFAULT"]["MainDisplay"] all_monitors = list(all_connected_monitor()) egalax_drm = get_egalax_drm_pure_name() - egalax_name = get_edid_name(egalax_drm) + egalax_name = get_edid_name(egalax_drm) if egalax_drm else None egalax_monitor = None main_monitor = None for mon in all_monitors: @@ -126,6 +130,80 @@ def prepare_monitors(config): return main_monitor, egalax_monitor, all_monitors +def baseline(main, egalax): + """Base of xrandr arguments + + Both main and egalax are monitor tuples mentioned in prepare_monitors""" + if not main and not egalax: + return [], None + elif not main and egalax: + return ["--output", egalax[0], "--primary", + "--mode", f"{egalax[1]}x{egalax[2]}"], None + elif main and not egalax: + return ["--output", main[0], "--primary", + "--mode", f"{main[1]}x{main[2]}"], main[0] + else: + return ["--output", main[0], "--primary", + "--mode", f"{main[1]}x{main[2]}", + "--output", egalax[0], "--right-of", main[0], + "--mode", f"{egalax[1]}x{egalax[1]}"], egalax[0] + + +def mirror_displays(main, egalax, others: list): + base, should_mirror = baseline(main, egalax) + if should_mirror: + for name, width, height in others: + base.extend(["--output", name, "--mode", f"{width}x{height}", + "--same-as", main[0], + "--scale-from", f"{main[1]}x{main[2]}"]) + return base + + +def off_displays(main, egalax, others: list): + base, should_off = baseline(main, egalax) + if should_off: + for name, width, height in others: + base.extend(["--output", name, "--off"]) + return base + + +def stand_alone_displays(main, egalax, others: list): + base, rightmost = baseline(main, egalax) + if rightmost: + for name, width, height in others: + base.extend(["--output", name, "--mode", f"{width}x{height}", + "--right-of", rightmost]) + rightmost = name + return base + + +POLICY = { + 'Off': off_displays, + 'Mirror': mirror_displays, + 'StandAlone': stand_alone_displays +} + + +def config_xrandr(conf, main, egalax, others: list): + """Executes xrandr with policy in the conf + + Policies: + Policies are about monitors other than main and touch panel monitors. + There are three supported policies: + - Off: Disables other monitors (default policy if not in config) + - Mirror: Mirror other displays from main monitor. + - StandAlone: Each monitor is mapped to the right of each other + """ + try: + policy = conf['DEFAULT']['Policy'] + except: + policy = 'Off' + args = POLICY[policy](main, egalax, others) + cmd = [XRANDR] + args + subprocess.run(cmd) + + if __name__ == "__main__": conf = read_config() - print(prepare_monitors(conf)) + main, egalax, others = prepare_monitors(conf) + config_xrandr(conf, main, egalax, others)