+++ /dev/null
-#!/usr/bin/python
-"""
-Parse xrandr current information
-
-TODO:
-* Cannot seem to undock notebook then recover displays without causing a logout
- event. Could it be that i3 is finding there are no displays?
-"""
-
-import sys
-import subprocess
-import re
-
-dry_run = False
-
-class OutputInfo():
- def __init__(self):
- self.clear()
-
- def clear(self):
- self.name = None
- self.connected = False
- self.enabled = False
- self.width = -1
- self.height = -1
- self.posx = -1
- self.posy = -1
-
- def complete(self):
- if self.name and (self.connected == False or self.width != -1):
- return True
- else:
- return False
-
- def asDict(self):
- if self.complete():
- return {'name':self.name, 'enabled':self.enabled,
- 'connected':self.connected, 'width':self.width,
- 'height':self.height, 'posx':self.posx, 'posy':self.posy,
- 'use':False, 'done':False}
- else:
- raise ValueError
-
- def parse(self, line):
- tokens = line.split()
- if len(tokens):
- if tokens[1] == 'connected' or tokens[1] == 'disconnected':
- self.clear()
- self.name = tokens[0]
- if tokens[1] == 'connected':
- self.connected = True
- token = 2
- size = []
- while token < len(tokens) and len(size) != 4:
- # skip other tokens like 'primary'
- size = re.split('[x+]', tokens[token])
- token += 1
- if len(size) == 4:
- self.enabled = True
- #self.width = int(size[0])
- #self.height = int(size[1])
- #self.posx = int(size[2])
- #self.posy = int(size[3])
- elif self.connected and self.width < 0:
- size = re.split('x', tokens[0])
- if len(size) == 2:
- self.width = int(size[0])
- self.height = int(size[1])
-
-
-def parse():
- outputs = []
- output = OutputInfo()
- p = subprocess.check_output('xrandr')
- for line in p.split('\n'):
- output.parse(line)
- if output.complete():
- outputs.append(output.asDict())
- output.clear()
- return outputs
-
-
-def xrandr_on(output):
- command = ['xrandr', '--output', output['name'], '--auto', '--pos',
- '%dx0' % output['posx']]
- if output['posx'] == 0:
- command += ['--primary']
- if not dry_run:
- print 'xrandr_on:', command
- subprocess.call(command)
- else:
- print '(dry-run) xrandr_on:', command
-
-
-def xrandr_off(output):
- command = ['xrandr', '--output', output['name'], '--off']
- if not dry_run:
- subprocess.call(command)
- print 'xrandr_off:', command
- else:
- print '(dry-run) xrandr_off:', command
-
-
-def output_by_name(outputs, name):
- for output in outputs:
- if output['name'] == name:
- return output
- return None
-
-
-if __name__ == '__main__':
- def print_output(output):
- print 'name:%s connected:%r enabled:%r width:%d height:%d pos:%dx%d' % (
- output['name'], output['connected'], output['enabled'],
- output['width'], output['height'], output['posx'],
- output['posy'])
-
- def print_outputs(header, outputs):
- print '%s:' % header
- for output in outputs:
- print_output(output)
- print
-
- def all_done(outputs):
- for output in outputs:
- if not output['done']:
- return False
- return True
-
- def disable_an_entry(outputs):
- for output in outputs:
- if not output['done'] and not output['use'] and output['enabled']:
- xrandr_off(output)
- output['done'] = True
- return 1
- return 0
-
- def enable_an_entry(outputs):
- enables = 0
- for output in reversed(outputs):
- if not output['done'] and output['use']:
- xrandr_on(output)
- output['done'] = True
- return 1
- return 0
-
- def main(argv):
- global dry_run
- if len(argv) >= 2 and argv[1] == '--dry-run':
- dry_run = True
-
- outputs = parse()
- print_outputs('Outputs', outputs)
-
- # Find the first two connected devices, in reverse list order. On the
- # Thinkpad X201, the reversed list order is the preferred order of
- # precedence, highest quality external display first, down to internal
- # LVDS panel used as a last resort. Also find new posx values.
- use_count = 0
- posx = 0
- for output in reversed(outputs):
- if output['connected']:
- print 'use', output['name']
- output['use'] = True
- output['posx'] = posx
- posx += output['width']
- use_count += 1
- if use_count >= 2:
- break
-
- # How many outputs are currently enabled?
- enabled_count = 0
- for output in outputs:
- if output['enabled']:
- enabled_count += 1
-
- # Mark outputs that receive no change as done
- for output in outputs:
- if not output['use'] and not output['enabled']:
- # Nothing to do for this output, mark as done
- output['done'] = True
-
- while not all_done(outputs):
- if enabled_count > 1:
- enabled_count -= disable_an_entry(outputs)
- if enabled_count < 2:
- enabled_count += enable_an_entry(outputs)
-
-
- main(sys.argv)