def disable_output(self, output): enabled_outputs = [o for o in self.outputs if o['crtc']] if len(enabled_outputs) <= 1 and output in enabled_outputs: # Yeah, I know most users are stupid, but at least don't let them disable all outputs return False # disable the output if output['crtc']: randr.set_crtc_config(self.d, output['crtc_id'], 0, 0, 0, 0, randr.Rotate_0, []) if self.mirror_state == 0: res = self.configure_extend(None) if res: if not self.bar_needs_resize: self.bar_needs_resize = [] self.bar_needs_resize += [output['name']] return res elif self.mirror_state == 1: res = self.configure_mirror(None) if res: if not self.bar_needs_resize: self.bar_needs_resize = [] self.bar_needs_resize += [output['name']] return res return False
def configure_mirror(self, output=None): with self.lock: self.outputs = [ o for o in get_randr_outputs(self.d, self.window) if o['connection'] ] used_crtc = [o['crtc_id'] for o in self.outputs if o['crtc_id']] if output: free_crtc = [c for c in output['crtcs'] if c not in used_crtc] if len(free_crtc) < 1: # No crtc available, so we cannot enable this output return False # We need to find a mode that every connected output supports enabled_outputs = [o for o in self.outputs if o['crtc']] if len(enabled_outputs) == 0: return False if output: mode = output['mode_ids'] else: mode = enabled_outputs[0]['mode_ids'] for e in enabled_outputs: mode = [m for m in mode if m in e['mode_ids']] if not len(mode): # Outputs couldn't agree on mode return False if output: randr.set_crtc_config(self.d, free_crtc[0], 0, 0, 0, mode[0], randr.Rotate_0, [output['id']]) for o in enabled_outputs: randr.set_crtc_config(self.d, o['crtc_id'], 0, 0, 0, mode[0], o['crtc'].rotation, [o['id']]) with self.lock: self.outputs = [ o for o in get_randr_outputs(self.d, self.window) if o['connection'] ] enabled_outputs = [o for o in self.outputs if o['crtc']] # Everything worked (hopefully), so redraw the bar self.bar_needs_resize = [o['name'] for o in enabled_outputs] self.resize_randr_screen() if self.redraw_hook: run(self.redraw_hook, shell=True) return True
def configure(self): # Look for a matching configuration in the registered layouts # The edids of the connected screens edids = [output['meta']['edid'] for output in self.outputs] edids.sort() for layout in self.configManager.layouts(): layoutEDID = [output['edid'] for output in layout['outputs']] layoutEDID.sort() if edids == layoutEDID: self.logger.debug('Found matching configuration : [{}]'.format( layout['id'])) # Go through each output and configure their CRTC. for output in self.outputs: # Get the corresponding output in the registered layout referenceOutput = [ refOut for refOut in layout['outputs'] if refOut['edid'] == output['meta']['edid'] ][0] result = randr.set_crtc_config( self.window, output['info'].crtc, output['info'].timestamp, int(referenceOutput['x']), int(referenceOutput['y']), int(referenceOutput['mode']), int(referenceOutput['rotation']), [output['output']]) return # At this point, we've not been able to find a correct configuration self.logger.info('No matching configuration found. Exiting.') return
def configure_extend(self, output=None): with self.lock: outs = get_randr_outputs(self.d, self.window) if outs == None: return False self.outputs = [o for o in outs if o['connection']] used_crtc = [o['crtc_id'] for o in self.outputs if o['crtc_id']] if output: free_crtc = [c for c in output['crtcs'] if c not in used_crtc] if len(free_crtc) < 1: # No crtc available, so we cannot enable this output return False enabled_outputs = [o for o in self.outputs if o['crtc']] if len(enabled_outputs) == 0: return False wd = 0 for o in enabled_outputs: randr.set_crtc_config(self.d, o['crtc_id'], 0, wd, 0, o['mode_ids'][0], o['crtc'].rotation, [o['id']]) wd += [ m['width'] for m in o['modes'] if m['id'] == o['mode_ids'][0] ][0] if output: randr.set_crtc_config(self.d, free_crtc[0], 0, wd, 0, output['mode_ids'][0], randr.Rotate_0, [output['id']]) with self.lock: outs = get_randr_outputs(self.d, self.window) if outs == None: return False self.outputs = [o for o in outs if o['connection']] enabled_outputs = [o for o in self.outputs if o['crtc']] # Everything worked (hopefully), so redraw the bar if not self.bar_needs_resize: self.bar_needs_resize = [] self.bar_needs_resize += [o['name'] for o in enabled_outputs] self.resize_randr_screen() if self.redraw_hook: run(self.redraw_hook, shell=True) return True
def resize_randr_screen(self): outs = [o for o in self.outputs if o['crtc']] for o in outs: randr.set_crtc_config(self.d, o['crtc_id'], 0, 0, 0, 0, 1, []) mx_x = 0 mx_y = 0 mx_mm_x = 0.0 mx_mm_y = 0.0 ratio = 1 for o in outs: if o['width']: mx_x = max(mx_x, o['x'] + o['width']) if o['height']: mx_y = max(mx_y, o['y'] + o['height']) if o['width'] and o['height']: ratio = max( ratio, max(o['width'] / o['height'], o['height'] / o['width'])) if not o['crtc'].rotation in [ xlib_rots['left'], xlib_rots['right'] ]: if o['mm_width'] and o['width']: mx_mm_x = max(mx_mm_x, o['width'] * 1.0 / o['mm_width']) if o['mm_height'] and o['height']: mx_mm_y = max(mx_mm_y, o['height'] * 1.0 / o['mm_height']) else: if o['mm_width'] and o['height']: mx_mm_y = max(mx_mm_y, o['height'] * 1.0 / o['mm_width']) if o['mm_height'] and o['width']: mx_mm_x = max(mx_mm_x, o['width'] * 1.0 / o['mm_height']) if mx_x and mx_y and mx_mm_x and mx_mm_y: self.window.xrandr_set_screen_size(mx_x, mx_y, int(mx_x / mx_mm_x * ratio), int(mx_y / mx_mm_y * ratio)) for o in outs: randr.set_crtc_config(self.d, o['crtc_id'], 0, o['x'], o['y'], o['current_mode'], o['crtc'].rotation, [o['id']])
def resize_randr_screen(self): outs = [o for o in self.outputs if o['crtc']] for o in outs: randr.set_crtc_config(self.d, o['crtc_id'], 0, 0, 0, 0, 1, []) mx_x = 0 mx_y = 0 mx_mm_x = 0.0 mx_mm_y = 0.0 for o in outs: if o['width']: mx_x = max(mx_x, o['x'] + o['width']) if o['height']: mx_y = max(mx_y, o['y'] + o['height']) if not o['crtc'].rotation in [ xlib_rots['left'], xlib_rots['right'] ]: if o['mm_width'] and o['width']: mx_mm_x = max(mx_mm_x, o['width'] * 1.0 / o['mm_width']) if o['mm_height'] and o['height']: mx_mm_y = max(mx_mm_y, o['height'] * 1.0 / o['mm_height']) else: if o['mm_width'] and o['height']: mx_mm_y = max(mx_mm_y, o['height'] * 1.0 / o['mm_width']) if o['mm_height'] and o['width']: mx_mm_x = max(mx_mm_x, o['width'] * 1.0 / o['mm_height']) # Don't ask where these magic numbers come from if mx_x and mx_y and mx_mm_x and mx_mm_y: self.window.xrandr_set_screen_size(mx_x, mx_y, int(mx_x / mx_mm_x * 1.75), int(mx_y / mx_mm_y * 1.75)) for o in outs: randr.set_crtc_config(self.d, o['crtc_id'], 0, o['x'], o['y'], o['current_mode'], o['crtc'].rotation, [o['id']])
def configure_mirror(self, output=None): with self.lock: outs = get_randr_outputs(self.d, self.window) if outs == None: return False self.outputs = [o for o in outs if o['connection']] used_crtc = [o['crtc_id'] for o in self.outputs if o['crtc_id']] if output: free_crtc = [c for c in output['crtcs'] if c not in used_crtc] if len(free_crtc) < 1: # No crtc available, so we cannot enable this output return False # We need to find a mode that every connected output supports enabled_outputs = [o for o in self.outputs if o['crtc']] # print([o['name'] for o in enabled_outputs]) if len(enabled_outputs) == 0: return False def resolutions(modes): return {(m['width'], m['height']) for m in modes} ress = {} mode_map = {} if output: # print(output['modes']) ress = resolutions(output['modes']) # print(ress) mode_map.update({output['name']: output['modes']}) else: ress = resolutions(enabled_outputs[0]['modes']) # print(ress) for e in enabled_outputs: mode_map.update({e['name']: e['modes']}) ress = [m for m in ress if m in resolutions(e['modes'])] if len(ress) > 0: # Outputs could agree on a resolution, so pick the largest one ress = sorted(ress, reverse=True) # print(ress) if output: mode_map.update({output['name']: \ [o for o in output['modes'] if (o['width'], o['height']) == ress[0]]}) for e in enabled_outputs: mode_map.update({e['name']: \ [o for o in e['modes'] if (o['width'], o['height']) == ress[0]]}) if output: randr.set_crtc_config(self.d, free_crtc[0], 0, 0, 0, mode_map[output['name']][0]['id'], randr.Rotate_0, [output['id']]) for o in enabled_outputs: randr.set_crtc_config(self.d, o['crtc_id'], 0, 0, 0, mode_map[o['name']][0]['id'], o['crtc'].rotation, [o['id']]) with self.lock: outs = get_randr_outputs(self.d, self.window) if outs == None: return False self.outputs = [o for o in outs if o['connection']] enabled_outputs = [o for o in self.outputs if o['crtc']] # Everything worked (hopefully), so redraw the bar if not self.bar_needs_resize: self.bar_needs_resize = [] self.bar_needs_resize += [o['name'] for o in enabled_outputs] self.resize_randr_screen() if self.redraw_hook: run(self.redraw_hook, shell=True) return True
def rotate(self, state): outs = get_randr_outputs(self.d, self.window) if outs == None: return False outs = [o for o in outs if o['crtc']] op = [o for o in outs if o['name'] == self.output] if not len(op): # The output to be rotated doesn't exist :( return False op = op[0] # Get all outputs that are mirrored to the output we shall rotate # (We must also rotate these outputs) current_mode = op['current_mode'] mirrored_outs = [ o for o in outs if o['x'] == op['x'] and o['y'] == op['y'] and o['current_mode'] == op['current_mode'] ] if (self.STATES[self.current_state] in [ 'left', 'right' ]) != (self.STATES[state] in ['left', 'right']): # If the user has some non-mirrored setup, only normal and inverted # layouts are implemented for now. # Anything else requires work . . . if len(outs) != len(mirrored_outs): return False # Disable all screens to be rotated for o in mirrored_outs: randr.set_crtc_config(self.d, o['crtc_id'], 0, 0, 0, 0, 1, []) mx_x = 0 mx_y = 0 mx_mm_x = 0.0 mx_mm_y = 0.0 ratio = 1 for o in outs: if o['width']: mx_x = max(mx_x, o['x'] + o['width']) if o['height']: mx_y = max(mx_y, o['y'] + o['height']) if o['width'] and o['height']: ratio = max( ratio, max(o['width'] / o['height'], o['height'] / o['width'])) if o in mirrored_outs and o['crtc'].rotation in [ xlib_rots['left'], xlib_rots['right'] ]: if o['mm_width'] and o['width']: mx_mm_x = max(mx_mm_x, o['width'] * 1.0 / o['mm_width']) if o['mm_height'] and o['height']: mx_mm_y = max(mx_mm_y, o['height'] * 1.0 / o['mm_height']) else: if o['mm_width'] and o['height']: mx_mm_y = max(mx_mm_y, o['height'] * 1.0 / o['mm_width']) if o['mm_height'] and o['width']: mx_mm_x = max(mx_mm_x, o['width'] * 1.0 / o['mm_height']) if mx_x and mx_y and mx_mm_x and mx_mm_y: self.window.xrandr_set_screen_size(mx_y, mx_x, int(mx_x / mx_mm_x * ratio), int(mx_y / mx_mm_y * ratio)) # Actually rotate these outputs, don't change anything besides the rotation for o in mirrored_outs: randr.set_crtc_config(self.d, o['crtc_id'], 0, o['x'], o['y'], current_mode, xlib_rots[self.STATES[state]], [o['id']]) if (self.STATES[self.current_state] in [ 'left', 'right' ]) != (self.STATES[state] in ['left', 'right']): self.bar_needs_resize = self.output if self.rotation_hook: run(self.rotation_hook, shell=True) needs_map = [ i.decode('utf-8') for i in self.devices if len([j for j in self.mapped_inputs if j in i.decode('utf-8')]) ] ids = [ check_output(['xinput', '--list', '--id-only', i]).splitlines()[0].decode() for i in needs_map ] for i in ids: check_call(['xinput', '--map-to-output', i, self.touch_output]) return True