/usr/share/disper/src/switcher/swxrandr.py is in disper 0.3.1-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | ##############################################################################
# swxrandr.py - display switching using XRandR
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License at http://www.gnu.org/licenses/gpl.txt
# By using, editing and/or distributing this software you agree to
# the terms and conditions of this license.
import logging
import xrandr
from resolutions import *
class XRandrSwitcher:
def __init__(self):
self.log = logging.getLogger('disper.switcher.xrandr')
self.screen = xrandr.get_current_screen()
if not xrandr.has_extension():
raise Exception('No XRandR extension found')
def get_displays(self):
'''return an array of connected displays'''
displays = self.screen.get_outputs()
displays = filter(lambda o: o.is_connected(), displays)
displays = map(lambda o: o.name, displays)
return displays
def get_primary_display(self):
# no idea, just return first one for now
return self.get_displays()[0]
def get_display_name(self, ndisp):
'''return the name of a display'''
# nothing more as of now
return ndisp
def get_display_supported_res(self, ndisp):
'''return a set of supported resolutions for a display.'''
o = self.screen.get_output_by_name(ndisp)
return o.get_available_resolutions()
def get_display_preferred_res(self, ndisp):
'''return the preferred resolution for a display.'''
o = self.screen.get_output_by_name(ndisp)
m = o.get_available_modes()[o.get_preferred_mode()]
return [m.width,m.height]
def get_display_edid(self, ndisp):
'''return the EDID data for a display.'''
# not available now
return None
def switch_clone(self, displays, res):
'''switch to resolution and clone all displays'''
ress = ResolutionSelection(res, displays)
return self._switch(displays, ress, xrandr.RELATION_SAME_AS)
def switch_extend(self, displays, direction, ress):
'''extend desktop across all displays. direction is one of
'left'/'right'/'bottom'/'top', and ress a dict of a resolution
for each display.'''
relation = None
if direction=='left':
relation = xrandr.RELATION_LEFT_OF
elif direction=='right':
relation = xrandr.RELATION_RIGHT_OF
elif direction=='top':
relation = xrandr.RELATION_ABOVE
elif direction=='bottom':
relation = xrandr.RELATION_BELOW
else:
raise ValueError('extend direction must be left/right/bottom/top')
return self._switch(displays, ress, relation)
def import_config(self, cfg):
'''restore a display configuration as exported by export_config()'''
raise NotImplementedError('import not yet implemented')
def export_config(self):
'''return a string that contains all information to set the current
display configuration using import_config().'''
raise NotImplementedError('export not yet implemented')
def _switch(self, displays, ress, relation):
'''switch displays to the specified resolution according to XRandR relation'''
dprev = None
old_displays = self.get_displays()
for d in displays:
res = ress[d]
s = res.size()
# for each display, select mode with highest refresh rate at res
o = self.screen.get_output_by_name(d)
modes = []
for i,mode in enumerate(o.get_available_modes()):
if mode.width != s[0]: continue
if mode.height != s[1]: continue
refresh = mode.dotClock/(mode.hTotal*mode.vTotal)
modes.append([i, refresh])
modes.sort(lambda x,y: x[1]-y[1])
if len(modes) > 1:
self.log.info(str(d)+': available refresh rates for resolution '+
str(res)+': '+', '.join(map(lambda o: '%d'%(o[1]), modes)))
if len(modes) == 0:
raise ValueError('Mode %dx%d is invalid for display %s'%(s[0], s[1], d))
mode = modes[-1]
self.log.info(str(d)+': selecting XRandR mode #%d: %s %dHz'%(mode[0],res,mode[1]))
o.set_to_mode(mode[0])
if dprev:
o.set_relation(dprev, relation)
dprev = d
if d in old_displays: old_displays.remove(d)
if len(old_displays)>0:
for d in old_displays:
o = self.screen.get_output_by_name(d)
o.disable()
self.screen.apply_output_config()
def set_scaling(self, displays, scaling):
if scaling == "default" : return
raise NotImplementedError('scaling not implemented for XRandR')
# vim:ts=4:sw=4:expandtab:
|