diff options
| author | Olivier Gayot <olivier.gayot@sigexec.com> | 2023-05-14 17:19:24 +0200 | 
|---|---|---|
| committer | Olivier Gayot <olivier.gayot@sigexec.com> | 2023-05-14 17:23:07 +0200 | 
| commit | 1b96abb10e167dee2e0468a2e20c6b7903c010aa (patch) | |
| tree | e6fe17b526b765ca1d2da6201adaf1af11f02853 | |
| parent | c35ac6f8e56f042f0188a284d85a4700ccf37773 (diff) | |
Add support for wayland (no support for setting background)
Signed-off-by: Olivier Gayot <olivier.gayot@sigexec.com>
| -rw-r--r-- | monitor_menu/__main__.py | 50 | 
1 files changed, 44 insertions, 6 deletions
| diff --git a/monitor_menu/__main__.py b/monitor_menu/__main__.py index d450ba8..e42c440 100644 --- a/monitor_menu/__main__.py +++ b/monitor_menu/__main__.py @@ -2,6 +2,7 @@  import argparse  import dataclasses +import enum  import json  import logging  from os.path import expanduser @@ -23,11 +24,17 @@ class LogLevel:              raise ValueError("invalid value") +class GraphicalServer(enum.StrEnum): +    XORG = enum.auto() +    WAYLAND = enum.auto() + +  @dataclasses.dataclass  class Monitor:      output: str      xrandr_opts: list[str] = dataclasses.field(default_factory=list) +    wlr_randr_opts: list[str] = dataclasses.field(default_factory=list)      position: str | None = None      background: str | None = None      primary: bool = False @@ -47,6 +54,7 @@ class Profile:      identifier: str | None = None      xrandr_opts: list[str] = dataclasses.field(default_factory=list) +    wlr_randr_opts: list[str] = dataclasses.field(default_factory=list)      @classmethod      def from_json_dict(cls, json_dict: dict[str, Any]) -> "Profile": @@ -61,7 +69,20 @@ class Profile:              kwargs[key] = value          return cls(**kwargs) -    def apply(self): +    def apply(self, graphical_server: GraphicalServer | None): +        if graphical_server == "xorg": +            self.apply_xorg() +        elif graphical_server == "wayland": +            self.apply_wayland() +        else: +            try: +                subprocess.run(["xrandr"], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) +            except (subprocess.CalledProcessError, FileNotFoundError): +                self.apply_wayland() +            else: +                self.apply_xorg() + +    def apply_xorg(self):          # We build the command line starting from just "xrandr" and adding          # arguments.          xrandr_cmd = ['xrandr'] @@ -83,13 +104,29 @@ class Profile:          logging.debug("Executing: %s", feh_cmd)          subprocess.run(feh_cmd, check=False) +    def apply_wayland(self): +        # We build the command line starting from just "xrandr" and adding +        # arguments. +        wlr_randr_cmd = ['wlr-randr'] + +        try: +            wlr_randr_cmd += self.wlr_randr_opts +        except KeyError: +            pass + +        for monitor in self.monitors: +            wlr_randr_cmd.extend(monitor.wlr_randr_opts) + +        logging.debug("Executing: %s", wlr_randr_cmd) +        subprocess.run(wlr_randr_cmd, check=False) +  class MonitorMenu:      def __init__(self, profiles: list[Profile]) -> None:          self.profiles = profiles          self.d = dialog.Dialog(autowidgetsize=True) -    def run(self): +    def run(self, graphical_server: GraphicalServer | None = None):          choices = []          i = 0 @@ -105,7 +142,7 @@ class MonitorMenu:              return          try: -            self.profiles[int(profile_idx)].apply() +            self.profiles[int(profile_idx)].apply(graphical_server=graphical_server)          except IndexError:              raise NoMatchingProfile from None @@ -113,6 +150,7 @@ class MonitorMenu:  def main():      parser = argparse.ArgumentParser()      parser.add_argument("--log-level", "--loglevel", type=LogLevel, default="info") +    parser.add_argument("--graphical-server", choices=("wayland", "xorg"))      subparser = parser.add_subparsers(dest="command")      subparser.add_parser("run")      apply_parser = subparser.add_parser("apply") @@ -130,16 +168,16 @@ def main():      match args.command:          case "run" | None: -            MonitorMenu(profiles).run() +            MonitorMenu(profiles).run(graphical_server=args.graphical_server)          case "apply":              if args.index is not None:                  try: -                    profiles[args.index].apply() +                    profiles[args.index].apply(graphical_server=args.graphical_server)                  except IndexError:                      raise NoMatchingProfile from None              else:                  try: -                    next(filter(lambda p: p.identifier == args.id, profiles)).apply() +                    next(filter(lambda p: p.identifier == args.id, profiles)).apply(graphical_server=args.graphical_server)                  except StopIteration:                      raise NoMatchingProfile from None | 
