]> git.donarmstrong.com Git - deb_pkgs/autorandr.git/blobdiff - autorandr.py
Quote arguments in failed command output
[deb_pkgs/autorandr.git] / autorandr.py
index fe1906d16e83b2fed2f71ddbee8592eee1ce6ff9..d9b853b6fb97ef2ba9f5aa9df462571b5159cb04 100755 (executable)
@@ -257,12 +257,17 @@ class XrandrOutput(object):
         if xrandr_version() >= Version("1.2"):
             options.update(self.XRANDR_12_DEFAULTS)
         options.update(self.options)
+        if "set" in self.ignored_options:
+            options = {a: b for a, b in options.items() if not a.startswith("x-prop")}
         return {a: b for a, b in options.items() if a not in self.ignored_options}
 
     @property
     def filtered_options(self):
         "Return a dictionary of options without ignored options"
-        return {a: b for a, b in self.options.items() if a not in self.ignored_options}
+        options = {a: b for a, b in self.options.items() if a not in self.ignored_options}
+        if "set" in self.ignored_options:
+            options = {a: b for a, b in options.items() if not a.startswith("x-prop")}
+        return options
 
     @property
     def option_vector(self):
@@ -325,6 +330,8 @@ class XrandrOutput(object):
     def parse_serial_from_edid(self):
         self.serial = None
         if self.edid:
+            if self.EDID_UNAVAILABLE in self.edid:
+                return
             # Thx to pyedid project, the following code was
             # copied (and modified) from pyedid/__init__py:21 [parse_edid()]
             raw = bytes.fromhex(self.edid)
@@ -466,7 +473,7 @@ class XrandrOutput(object):
         return XrandrOutput(match["output"], edid, options), modes
 
     @classmethod
-    def from_config_file(cls, edid_map, configuration):
+    def from_config_file(cls, profile, edid_map, configuration):
         "Instanciate an XrandrOutput from the contents of a configuration file"
         options = {}
         for line in configuration.split("\n"):
@@ -487,8 +494,8 @@ class XrandrOutput(object):
             if fuzzy_output in fuzzy_edid_map:
                 edid = edid_map[list(edid_map.keys())[fuzzy_edid_map.index(fuzzy_output)]]
             elif "off" not in options:
-                raise AutorandrException("Failed to find an EDID for output `%s' in setup file, required as `%s' "
-                                         "is not off in config file." % (options["output"], options["output"]))
+                raise AutorandrException("Profile `%s': Failed to find an EDID for output `%s' in setup file, required "
+                                         "as `%s' is not off in config file." % (profile, options["output"], options["output"]))
         output = options["output"]
         del options["output"]
 
@@ -634,7 +641,7 @@ def load_profiles(profile_path):
         buffer = []
         for line in chain(open(config_name).readlines(), ["output"]):
             if line[:6] == "output" and buffer:
-                config[buffer[0].strip().split()[-1]] = XrandrOutput.from_config_file(edids, "".join(buffer))
+                config[buffer[0].strip().split()[-1]] = XrandrOutput.from_config_file(profile, edids, "".join(buffer))
                 buffer = [line]
             else:
                 buffer.append(line)
@@ -889,10 +896,10 @@ def apply_configuration(new_configuration, current_configuration, dry_run=False)
 
     fb_dimensions = get_fb_dimensions(new_configuration)
     try:
-        base_argv += ["--fb", "%dx%d" % fb_dimensions]
+        fb_args = ["--fb", "%dx%d" % fb_dimensions]
     except:
         # Failed to obtain frame-buffer size. Doesn't matter, xrandr will choose for the user.
-        pass
+        fb_args = []
 
     auxiliary_changes_pre = []
     disable_outputs = []
@@ -940,7 +947,12 @@ def apply_configuration(new_configuration, current_configuration, dry_run=False)
     if auxiliary_changes_pre:
         argv = base_argv + list(chain.from_iterable(auxiliary_changes_pre))
         if call_and_retry(argv, dry_run=dry_run) != 0:
-            raise AutorandrException("Command failed: %s" % " ".join(argv))
+            raise AutorandrException("Command failed: %s" % " ".join(map(shlex.quote, argv)))
+
+    # Starting here, fix the frame buffer size
+    # Do not do this earlier, as disabling scaling might temporarily make the framebuffer
+    # dimensions larger than they will finally be.
+    base_argv += fb_args
 
     # Disable unused outputs, but make sure that there always is at least one active screen
     disable_keep = 0 if remain_active_count else 1
@@ -973,7 +985,7 @@ def apply_configuration(new_configuration, current_configuration, dry_run=False)
     for index in range(0, len(operations), 2):
         argv = base_argv + list(chain.from_iterable(operations[index:index + 2]))
         if call_and_retry(argv, dry_run=dry_run) != 0:
-            raise AutorandrException("Command failed: %s" % " ".join(argv))
+            raise AutorandrException("Command failed: %s" % " ".join(map(shlex.quote, argv)))
 
 
 def is_equal_configuration(source_configuration, target_configuration):
@@ -1613,6 +1625,9 @@ def main(argv):
             new_config, _ = parse_xrandr_output(
                 ignore_lid=ignore_lid,
             )
+            if "--skip-options" in options:
+                for output in new_config.values():
+                    output.set_ignored_options(skip_options)
             if not is_equal_configuration(new_config, load_config):
                 print("The configuration change did not go as expected:")
                 print_profile_differences(new_config, load_config)