|
#!/usr/bin/env python |
|
|
|
import os |
|
import sys |
|
import subprocess |
|
import re |
|
import json |
|
import pickle |
|
from dataclasses import dataclass |
|
from typing import Tuple, List |
|
|
|
CONF_DIR = os.path.expanduser("~/.config/displayplacer") |
|
P_CONF = re.compile(r'"([^"]+)"', re.IGNORECASE) |
|
P_ATTR = re.compile(r'":"', re.IGNORECASE) |
|
|
|
|
|
@dataclass |
|
class Config: |
|
id_: str |
|
res: Tuple[int, int] |
|
origin: Tuple[int, int] = (0,0) |
|
hz: int = -1 |
|
color_depth: int = -1 |
|
scaling: bool = False |
|
degree: int = 0 |
|
|
|
def to_conf(self): |
|
result = f"id:{self.id_}" |
|
result += f" degree:{self.degree}" |
|
result += f" res:{self.res}" |
|
result += f" hz:{self.hz}" |
|
result += f" scaling:{'on' if self.scaling else 'off'}" |
|
result += f" origin:{self.origin}" |
|
return result |
|
|
|
@staticmethod |
|
def parse(value): |
|
kv = dict(attr.split(':', 1) for attr in value.split(' ')) |
|
kv['id_'] = kv.pop('id') |
|
return Config(**kv) |
|
|
|
|
|
@dataclass |
|
class Layout: |
|
configs: List[Config] |
|
|
|
@staticmethod |
|
def parse(value): |
|
configs = [Config.parse(m.group(1)) |
|
for line in value.split('\n') |
|
if line.startswith("displayplacer") |
|
for m in P_CONF.finditer(line)] |
|
return Layout(configs) |
|
|
|
@property |
|
def footprint(self): |
|
return [(c.id_, c.origin) for c in sorted(self.configs, key=lambda x: hash(x.id_))] |
|
|
|
def to_args(self): |
|
return "displayplacer " + ' '.join([f"\"{c.to_conf()}\"" for c in self.configs]) |
|
|
|
def run(self): |
|
subprocess.run(self.to_args(), shell=True, check=True) |
|
|
|
def switch(self, templates): |
|
if self.footprint == templates[0].footprint: |
|
print("switch to 1") |
|
self.configs = templates[1].configs |
|
else: |
|
print("switch to 0") |
|
self.configs = templates[0].configs |
|
|
|
|
|
def load_templates(folder): |
|
with open(f'{folder}/templates.txt', 'r') as f: |
|
return [Layout.parse(l) |
|
for l in f.readlines() |
|
if l.strip()] |
|
|
|
|
|
def main(): |
|
result = subprocess.run(['displayplacer', 'list'], capture_output=True, text=True) |
|
layout = Layout.parse(result.stdout) |
|
templates = load_templates(CONF_DIR) |
|
layout.switch(templates) |
|
print(layout.to_args()) |
|
layout.run() |
|
|
|
|
|
if __name__ == "__main__": |
|
main() |