]> git.donarmstrong.com Git - deb_pkgs/autorandr.git/blobdiff - autorandr.py
Release bug fixes as 1.13.2
[deb_pkgs/autorandr.git] / autorandr.py
index d9b853b6fb97ef2ba9f5aa9df462571b5159cb04..1dea4bc35b53fbf64543d523aed71a6527a9299e 100755 (executable)
@@ -44,17 +44,13 @@ from collections import OrderedDict
 from functools import reduce
 from itertools import chain
 
-try:
-    from packaging.version import Version
-except ModuleNotFoundError:
-    from distutils.version import LooseVersion as Version
 
 if sys.version_info.major == 2:
     import ConfigParser as configparser
 else:
     import configparser
 
-__version__ = "1.12.1"
+__version__ = "1.13.2"
 
 try:
     input = raw_input
@@ -68,6 +64,8 @@ virtual_profiles = [
     ("clone-largest", "Clone all connected outputs with the largest resolution (scaled down if necessary)", None),
     ("horizontal", "Stack all connected outputs horizontally at their largest resolution", None),
     ("vertical", "Stack all connected outputs vertically at their largest resolution", None),
+    ("horizontal-reverse", "Stack all connected outputs horizontally at their largest resolution in reverse order", None),
+    ("vertical-reverse", "Stack all connected outputs vertically at their largest resolution in reverse order", None),
 ]
 
 properties = [
@@ -120,6 +118,35 @@ Usage: autorandr [options]
 """.strip()
 
 
+class Version(object):
+    def __init__(self, version):
+        self._version = version
+        self._version_parts = re.split("([0-9]+)", version)
+
+    def __eq__(self, other):
+        return self._version_parts == other._version_parts
+
+    def __lt__(self, other):
+        for my, theirs in zip(self._version_parts, other._version_parts):
+            if my.isnumeric() and theirs.isnumeric():
+                my = int(my)
+                theirs = int(theirs)
+            if my < theirs:
+                return True
+        return len(theirs) > len(my)
+
+    def __ge__(self, other):
+        return not (self < other)
+
+    def __ne__(self, other):
+        return not (self == other)
+
+    def __le__(self, other):
+        return (self < other) or (self == other)
+
+    def __gt__(self, other):
+        return self >= other and not (self == other)
+
 def is_closed_lid(output):
     if not re.match(r'(eDP(-?[0-9]\+)*|LVDS(-?[0-9]\+)*)', output):
         return False
@@ -332,6 +359,8 @@ class XrandrOutput(object):
         if self.edid:
             if self.EDID_UNAVAILABLE in self.edid:
                 return
+            if "*" 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)
@@ -987,6 +1016,13 @@ def apply_configuration(new_configuration, current_configuration, dry_run=False)
         if call_and_retry(argv, dry_run=dry_run) != 0:
             raise AutorandrException("Command failed: %s" % " ".join(map(shlex.quote, argv)))
 
+    # Adjust the frame buffer to match (see #319)
+    if fb_args:
+        argv = base_argv
+        if call_and_retry(argv, dry_run=dry_run) != 0:
+            raise AutorandrException("Command failed: %s" % " ".join(map(shlex.quote, argv)))
+
+
 
 def is_equal_configuration(source_configuration, target_configuration):
     """
@@ -1050,16 +1086,18 @@ def generate_virtual_profile(configuration, modes, profile_name):
                     configuration[output].options["pos"] = "0x0"
                 else:
                     configuration[output].options["off"] = None
-    elif profile_name in ("horizontal", "vertical"):
+    elif profile_name in ("horizontal", "vertical", "horizontal-reverse", "vertical-reverse"):
         shift = 0
-        if profile_name == "horizontal":
+        if profile_name.startswith("horizontal"):
             shift_index = "width"
             pos_specifier = "%sx0"
         else:
             shift_index = "height"
             pos_specifier = "0x%s"
-
-        for output in configuration:
+            
+        config_iter = reversed(configuration) if "reverse" in profile_name else iter(configuration)
+            
+        for output in config_iter:
             configuration[output].options = {}
             if output in modes and configuration[output].edid:
                 def key(a):
@@ -1181,21 +1219,21 @@ def exec_scripts(profile_path, script_name, meta_information=None):
             if os.access(script, os.X_OK | os.F_OK):
                 try:
                     all_ok &= subprocess.call(script, env=env) != 0
-                except:
-                    raise AutorandrException("Failed to execute user command: %s" % (script,))
+                except Exception as e:
+                    raise AutorandrException("Failed to execute user command: %s. Error: %s" % (script, str(e)))
                 ran_scripts.add(script_name)
 
         script_folder = os.path.join(folder, "%s.d" % script_name)
         if os.access(script_folder, os.R_OK | os.X_OK) and os.path.isdir(script_folder):
-            for file_name in os.listdir(script_folder):
+            for file_name in sorted(os.listdir(script_folder)):
                 check_name = "d/%s" % (file_name,)
                 if check_name not in ran_scripts:
                     script = os.path.join(script_folder, file_name)
                     if os.access(script, os.X_OK | os.F_OK):
                         try:
                             all_ok &= subprocess.call(script, env=env) != 0
-                        except:
-                            raise AutorandrException("Failed to execute user command: %s" % (script,))
+                        except Exception as e:
+                            raise AutorandrException("Failed to execute user command: %s. Error: %s" % (script, str(e)))
                         ran_scripts.add(check_name)
 
     return all_ok