made aspect ratio accurate
[lilass.git] / screen.py
index 9942e9838296e9a8eecef3d0b8c9475b81d19f8f..b0c657737403be53b1a05ec7b4edef227b76f19c 100644 (file)
--- a/screen.py
+++ b/screen.py
@@ -18,6 +18,7 @@
 
 import re, subprocess
 from enum import Enum
+from fractions import Fraction
 
 ## utility functions
 
@@ -66,13 +67,8 @@ class Resolution:
     
     def __str__(self):
         # get ratio
-        ratio = int(round(16.0*self.height/self.width))
-        if ratio == 12: # 16:12 = 4:3
-            strRatio = '4:3'
-        elif ratio == 13: # 16:12.8 = 5:4
-            strRatio = '5:4'
-        else: # let's just hope this will never be 14 or more...
-            strRatio = '16:%d' % ratio
+        ratio = Fraction(self.width, self.height) # automatically divides by the gcd
+        strRatio = "%d:%d" % (ratio.numerator, ratio.denominator)
         return '%dx%d (%s)' %(self.width, self.height, strRatio)
     
     def __repr__(self):
@@ -126,29 +122,33 @@ class ScreenSetup:
 
 class Connector:
     def __init__(self, name=None):
-        self.name = name         # connector name, e.g. "HDMI1"
-        self.edid = None         # EDID string for the connector, or None if disconnected
-        self.resolutions = set() # list of Resolution objects, empty if disconnected
+        self.name = name # connector name, e.g. "HDMI1"
+        self.edid = None # EDID string for the connector, or None if disconnected
+        self._resolutions = set() # list of Resolution objects, empty if disconnected
+        self.preferredResolution = None
     
     def __str__(self):
         return str(self.name)
     
     def __repr__(self):
-        return """<Connector "%s" EDID="%s" resolutions="%s">""" % (str(self.name), str(self.edid), ", ".join(str(r) for r in self.resolutions))
+        return """<Connector "%s" EDID="%s" resolutions="%s">""" % (str(self.name), str(self.edid), ", ".join(str(r) for r in self.getResolutionList()))
     
     def isConnected(self):
-        assert (self.edid is None) == (len(self.resolutions)==0)
+        assert (self.edid is None) == (len(self._resolutions)==0)
         return self.edid is not None
     
     def addResolution(self, resolution):
         assert isinstance(resolution, Resolution)
-        self.resolutions.add(resolution)
+        self._resolutions.add(resolution)
     
     def appendToEdid(self, s):
         if self.edid is None:
             self.edid = s
         else:
             self.edid += s
+    
+    def getResolutionList(self):
+        return sorted(self._resolutions, key=lambda r: (0 if r==self.preferredResolution else 1, -r.pixelCount()))
 
 class ScreenSituation:
     connectors = [] # contains all the Connector objects
@@ -209,6 +209,8 @@ class ScreenSituation:
                 resolution = Resolution(int(m.group(1)), int(m.group(2)))
                 assert connector is not None
                 connector.addResolution(resolution)
+                if '+preferred' in line:
+                    connector.preferredResolution = resolution
                 continue
             # EDID?
             m = re.search(r'^\s*EDID:\s*$', line)
@@ -227,13 +229,13 @@ class ScreenSituation:
     
     # return available internal resolutions
     def internalResolutions(self):
-        return self.internalConnector.resolutions
+        return self.internalConnector.getResolutionList()
     
     # return available external resolutions (or None, if there is no external screen connected)
     def externalResolutions(self):
         if self.externalConnector is None:
             return None
-        return self.externalConnector.resolutions
+        return self.externalConnector.getResolutionList()
     
     # return resolutions available for both internal and external screen
     def commonResolutions(self):