qubes/ext/gui: fix sending monitor layout at VM startup

Based on marmarek's commit 4edb42c1 under the same name.
This commit is contained in:
Wojtek Porczyk 2016-03-17 11:52:52 +01:00
parent 15e032cddb
commit a4fa1adb82
2 changed files with 49 additions and 38 deletions

View File

@ -25,11 +25,46 @@
#
import os
import re
import subprocess
import qubes.config
import qubes.ext
# "LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm"
REGEX_OUTPUT = re.compile(r'''
(?x) # ignore whitespace
^ # start of string
(?P<output>[A-Za-z0-9\-]*)[ ] # LVDS VGA etc
(?P<connect>(dis)?connected)[ ]# dis/connected
(?P<primary>(primary)?)[ ]?
(( # a group
(?P<width>\d+)x # either 1024x768+0+0
(?P<height>\d+)[+]
(?P<x>\d+)[+]
(?P<y>\d+)
)|[\D]) # or not a digit
.* # ignore rest of line
''')
def get_monitor_layout():
outputs = []
for line in subprocess.Popen(
['xrandr', '-q'], stdout=subprocess.PIPE).stdout:
if not line.startswith("Screen") and not line.startswith(" "):
output_params = REGEX_OUTPUT.match(line).groupdict()
if output_params['width']:
outputs.append("%s %s %s %s\n" % (
output_params['width'],
output_params['height'],
output_params['x'],
output_params['y']))
return outputs
class GUI(qubes.ext.Extension):
@qubes.ext.handler('domain-start', 'domain-cmd-pre-run')
def start_guid(self, vm, event, preparing_dvm=False, start_guid=True,
@ -43,6 +78,10 @@ class GUI(qubes.ext.Extension):
or not os.path.exists('/var/run/shm.id'):
return
# FIXME move this method to this extension, plugged to event
if vm.is_guid_running():
return
if not vm.features.check_with_template('gui', not vm.hvm):
vm.log.debug('Not starting gui daemon, disabled by features')
return
@ -85,7 +124,7 @@ class GUI(qubes.ext.Extension):
raise qubes.exc.QubesVMError(vm,
'Cannot start qubes-guid for domain {!r}'.format(vm.name))
vm.notify_monitor_layout()
vm.fire_event('monitor-layout-change')
vm.wait_for_session()
@ -146,12 +185,17 @@ class GUI(qubes.ext.Extension):
@qubes.ext.handler('monitor-layout-change')
def on_monitor_layout_change(self, vm, event, monitor_layout):
def on_monitor_layout_change(self, vm, event, monitor_layout=None):
# pylint: disable=no-self-use
if vm.features.check_with_template('no-monitor-layout', False) \
or not vm.is_running():
return
if monitor_layout is None:
monitor_layout = get_monitor_layout()
if not monitor_layout:
return
pipe = vm.run('QUBESRPC qubes.SetMonitorLayout dom0',
passio_popen=True, wait=True)

View File

@ -26,44 +26,11 @@
# TODO allow to set properties and create domains
import re
import subprocess
import threading
import qubes.ext.gui
import qubes.tools
# "LVDS connected 1024x768+0+0 (normal left inverted right) 304mm x 228mm"
REGEX_OUTPUT = re.compile(r'''
(?x) # ignore whitespace
^ # start of string
(?P<output>[A-Za-z0-9\-]*)[ ] # LVDS VGA etc
(?P<connect>(dis)?connected)[ ]# dis/connected
(?P<primary>(primary)?)[ ]?
(( # a group
(?P<width>\d+)x # either 1024x768+0+0
(?P<height>\d+)[+]
(?P<x>\d+)[+]
(?P<y>\d+)
)|[\D]) # or not a digit
.* # ignore rest of line
''')
def get_monitor_layout():
outputs = []
for line in subprocess.Popen(
['xrandr', '-q'], stdout=subprocess.PIPE).stdout:
if not line.startswith("Screen") and not line.startswith(" "):
output_params = REGEX_OUTPUT.match(line).groupdict()
if output_params['width']:
outputs.append("%s %s %s %s\n" % (
output_params['width'],
output_params['height'],
output_params['x'],
output_params['y']))
return outputs
parser = qubes.tools.QubesArgumentParser(
description='Send monitor layout to one qube or to all of them',
@ -80,7 +47,7 @@ def main(args=None):
'''
args = parser.parse_args(args)
monitor_layout = get_monitor_layout()
monitor_layout = qubes.ext.gui.get_monitor_layout()
# notify only if we've got a non-empty monitor_layout or else we
# break proper qube resolution set by gui-agent
@ -88,10 +55,10 @@ def main(args=None):
args.app.log.error('cannot get monitor layout')
return 1
subprocess.check_call(['killall', '-HUP', 'qubes-guid'])
if args.vm:
args.vm.fire_event('monitor-layout-change', monitor_layout)
else:
subprocess.check_call(['killall', '-HUP', 'qubes-guid'])
threads = []
for vm in args.app.domains: