2 # DSL - easy Display Setup for Laptops
4 import sys, re, subprocess
5 from PyQt4 import QtGui
6 from selector_window import PositionSelection
7 app = QtGui.QApplication(sys.argv)
9 def getXrandrInformation():
10 p = subprocess.Popen(["xrandr", "-q"], stdout=subprocess.PIPE)
11 connectors = {} # map of connector names to a list of resolutions
12 connector = None # current connector
15 m = re.search(r'^([\w]+) connected ', line)
17 connector = m.groups()[0]
18 assert connector not in connectors
19 connectors[connector] = []
22 m = re.search(r'^ ([\d]+)x([\d]+) +', line)
24 assert connector is not None
25 connectors[connector].append((int(m.groups()[0]), int(m.groups()[1])))
27 if p.returncode != 0: raise Exception("Querying xrandr for data failed")
32 return str(w)+'x'+str(h)
37 ratio = int(round(16.0*h/w))
38 if ratio == 12: # 16:12 = 4:3
40 elif ratio == 13: # 16:12.8 = 5:4
42 else: # let's just hope this will never be 14 or more...
43 strRatio = '16:%d' % ratio
44 return '%dx%d (%s)' %(w, h, strRatio)
47 internalName = "LVDS1"
48 externalNames = ["HDMI1", "DP1", "VGA1"]
49 connectors = getXrandrInformation()
50 internalResolutions = connectors[internalName] # there must be a screen assoicated to the internal connector
51 externalName = None # *the* external connector which is actually used
52 externalResolutions = None # resultions of the external connector
53 args = {} # maps connector names to xrand arguments
55 # look for enabled external screen, disable all the others
56 for name in externalNames:
57 if externalResolutions is None and name in connectors:
59 externalResolutions = connectors[name]
61 args[name] = ["--off"]
64 if externalName is not None: # we need to ask what to do
65 extPosition = PositionSelection(externalName, map(res2user, internalResolutions), map(res2user, externalResolutions))
67 if not extPosition.result(): sys.exit(1) # the user canceled
68 extResolution = res2xrandr(externalResolutions[extPosition.extResolutions.currentIndex()])
69 intResolution = res2xrandr(internalResolutions[extPosition.intResolutions.currentIndex()])
71 args[externalName] = ["--mode", extResolution] # we definitely want an external screen
72 if extPosition.extOnly.isChecked():
73 args[internalName] = ["--off"]
74 args[externalName] += ["--primary"]
76 # there are two screens
77 args[internalName] = ["--mode", intResolution]
78 if extPosition.posLeft.isChecked():
79 args[externalName] += ["--left-of", internalName]
81 args[externalName] += ["--right-of", internalName]
82 if extPosition.primExt.isChecked():
83 args[externalName] += ["--primary"]
85 args[internalName] += ["--primary"]
87 args[internalName] = ["--mode", res2xrandr(internalResolutions[0]), "--primary"]
91 call += ["--output", name] + args[name]
92 print "Call that will be made:",call
93 subprocess.check_call(call)