Add module for display resolution detection.

xorg_facts sets the variable xorg with display information parsed from
xrandr's output
This commit is contained in:
Alexander Grothe 2017-03-26 13:57:31 +02:00
parent f80bf44fc6
commit 0ec472d7b2
11 changed files with 1097 additions and 300 deletions

File diff suppressed because it is too large Load Diff

View File

@ -97,13 +97,8 @@ For a headless server installation ~yavdr07-headless.yml~ is a good choice
This playbook can either be used to run the installation on the localhost or any other PC in the network that can be accessed via ssh. Simply add the host names or IP addresses to the hosts file in the respective section:
#+BEGIN_SRC conf :tangle localhost_inventory :mkdirp yes
[yavdr-full]
[localhost]
localhost connection=local
#192.168.1.116
[yavdr-headless]
[yavdr-client]
#+END_SRC
* Group Variables
@ -615,6 +610,30 @@ systemctl --user import-environment
enabled: yes
state: started
#+END_SRC
*** templates
#+BEGIN_SRC conf :tangle roles/yavdr-xorg/templates/x-verbose.service.j2
[Unit]
Description=X with verbose logging on %I
Wants=graphical.target
Before=graphical.target
[Service]
Type=forking
ExecStart=/usr/bin/x-daemon -logverbose 6 -noreset %I
#+END_SRC
** display-data
*** tasks
#+BEGIN_SRC yaml :tangle roles/display-data/tasks/main.yml
---
# file: roles/display-data/tasks/main.yml
- name: "detect xorg configuration"
action: xorg_facts
- debug:
var: xorg
verbosity: 1
#+END_SRC
** nfs-server
*** tasks
#+BEGIN_SRC yaml :tangle roles/nfs-server/tasks/main.yml :mkdirp yes
@ -1375,6 +1394,176 @@ def main():
if __name__ == '__main__':
main()
#+END_SRC
** xorg_facts.py
#+BEGIN_SRC python :tangle library/xorg_facts.py
#!/usr/bin/env python2
DOCUMENTATION = '''
---
module: xorg_facts
short_description: "gather facts about connected monitors and available modelines"
description:
- This script needs a running x-server on a given display in order to successfully call xrandr.
The ranking uses the following factors:
1. preferred_refreshrate
2. preferred_resolution
3. preferred_output
For each element a dictionary of values (up to 4 bit [0 .. 256]) may be passed to the module.
The rank is represented by this order of 4-Bit values:
| rrate | resolution | output | internal score
| 50 | 1920x1080 | HDMI | 0b_0100_0100_0100 = 1092
| 60 | 1280x720 | DP | 0b_0011_0011_0011 = 819
Returns the connected output, monitors and modelines and a suggestion for the most fitting mode in a dictionary 'xorg'
options:
display:
required: False
default: ":0"
description:
- the DISPLAY variable to use when calling xrandr
preferred_outpus:
required: False
default: {"HDMI": 4, "DP": 3, "DVI": 2, "VGA": 1, "TV": 0}
description:
- ranking of the preferred display connectors
preferred_refreshrates:
required: False
default: {"50": 4, "60": 3, "75": 2, "30": 1, "25": 0}
description:
- ranking of the preferred display refreshrate
preferred_resolutions:
required: False
default: {"7680x4320": 8, "3840x2160": 4, "1920x1080": 2, "1280x720": 1, "720x576": 0}
description:
- ranking of the preferred display resolutions
'''
EXAMPLES = '''
- name: "collect facts for connected displays"
action: xserver_facts
display: ":0"
- debug:
var: xorg
'''
import ast
import json
import re
import subprocess
import sys
import time
from collections import OrderedDict, namedtuple
from ansible.module_utils.basic import *
arg_specs = {
'display': dict(default=[":0", ":0.1"], type='list', required=False),
'multi_display': dict(default=True, type='bool', required=False),
'preferred_outputs': dict(default={"HDMI": 8, "DP": 4, "DVI": 2, "VGA": 1, "TV": 0}, type='dict', required=False),
'preferred_refreshrates': dict(default={50: 8, 60: 4, 75: 3, 30: 2, 25: 1}, type='dict', required=False),
'preferred_resolutions': dict(default={"7680x4320": 8, "3840x2160": 4, "1920x1080": 2, "1280x720": 1, "720x576": 0},
type='dict', required=False),
}
Mode = namedtuple('Mode', ['score', 'connection', 'resolution', 'refreshrate'])
class ModelineTools(object):
def __init__(self, preferred_outputs, preferred_resolutions, preferred_refreshrates):
self.preferred_outputs = preferred_outputs
self.preferred_resolutions = preferred_resolutions
self.preferred_refreshrates = preferred_refreshrates
def get_score(self, connection, resolution, refreshrate):
connection = connection.split('-')[0]
score = self.preferred_refreshrates.get(int(refreshrate), 0)
score = score << 4
score += self.preferred_resolutions.get(resolution, 0)
#score = score << 4
#score += self.preferred_outputs.get(connection, 0)
return score
@staticmethod
def cleanup_refreshrate(refreshrate):
rrate = refreshrate.replace('+', '').replace('*', '').replace(' ', '').strip()
return int(round(ast.literal_eval(rrate)))
def sort_mode(self, mode):
x, y = mode.resolution.split('x')
connection = mode.connection.split('-')[0]
return (mode.score, int(x), int(y), self.preferred_outputs.get(connection, 0))
def main():
module = AnsibleModule(argument_spec=arg_specs, supports_check_mode=False,)
display_list = module.params['display']
preferred_outputs = module.params['preferred_outputs']
preferred_resolutions = module.params['preferred_resolutions']
preferred_refreshrates = module.params['preferred_refreshrates']
mtools = ModelineTools(preferred_outputs, preferred_resolutions, preferred_refreshrates)
modes = []
displays = {}
data = {}
for display in display_list:
# call xrandr
try:
xrandr_data = subprocess.check_output(['xrandr', '-q','-d', display],
universal_newlines=True)
except: continue
for line in xrandr_data.splitlines():
if line.startswith('Screen'):
screen = line.split(':')[0].split()[-1]
screen = "Screen{}".format(screen)
displays[screen] = {}
elif 'connected' in line:
connection = line.split()[0]
displays[screen][connection] = {}
if 'disconnected' in line:
displays[screen][connection]['connected'] = False
else:
displays[screen][connection]['connected'] = True
displays[screen][connection]['modes'] = OrderedDict(
sorted({}.items(), key=lambda t: t.split('_')[0]))
elif line.startswith(' '):
fields = filter(None, re.split(r'\s{2,}', line))
resolution = fields[0]
refreshrates = fields[1:]
r = set()
for refreshrate in refreshrates:
refreshrate = refreshrate.strip()
rrate = mtools.cleanup_refreshrate(refreshrate)
if len(refreshrate) < 2:
continue
if '*' in refreshrate:
current_mode = (resolution, rrate)
displays[screen][connection]['current_mode'] = current_mode
if '+' in refreshrate:
preferred_mode = (resolution, rrate)
displays[screen][connection]['preferred_mode'] = preferred_mode
r.add(mtools.cleanup_refreshrate(refreshrate))
modes.append(Mode(score=mtools.get_score(connection, resolution, rrate), connection=connection,
resolution=resolution, refreshrate=rrate))
displays[screen][connection]['modes'][resolution] = sorted(r)
data['displays'] = displays
data['modes'] = modes
best_mode = max(modes, key=mtools.sort_mode)
data["best_mode"] = {
'connection': best_mode.connection,
'resolution': best_mode.resolution,
'refreshrate': best_mode.refreshrate,
}
module.exit_json(changed=False, ansible_facts={'xorg': data})
if __name__ == '__main__':
main()
#+END_SRC
* Handlers
#+BEGIN_SRC yaml :tangle handlers/main.yml :mkdirp yes
- name: Restart Samba

12
displays.yml Normal file
View File

@ -0,0 +1,12 @@
---
# file: yavdr07.yml
# this playbook sets up a complete yaVDR 0.7 installation
- name: set up yaVDR
hosts: all
become: true
roles:
- display-data
handlers:
- include: handlers/main.yml

167
library/xorg_facts.py Normal file
View File

@ -0,0 +1,167 @@
#!/usr/bin/env python2
DOCUMENTATION = '''
---
module: xorg_facts
short_description: "gather facts about connected monitors and available modelines"
description:
- This script needs a running x-server on a given display in order to successfully call xrandr.
The ranking uses the following factors:
1. preferred_refreshrate
2. preferred_resolution
3. preferred_output
For each element a dictionary of values (up to 4 bit [0 .. 256]) may be passed to the module.
The rank is represented by this order of 4-Bit values:
| rrate | resolution | output | internal score
| 50 | 1920x1080 | HDMI | 0b_0100_0100_0100 = 1092
| 60 | 1280x720 | DP | 0b_0011_0011_0011 = 819
Returns the connected output, monitors and modelines and a suggestion for the most fitting mode in a dictionary 'xorg'
options:
display:
required: False
default: ":0"
description:
- the DISPLAY variable to use when calling xrandr
preferred_outpus:
required: False
default: {"HDMI": 4, "DP": 3, "DVI": 2, "VGA": 1, "TV": 0}
description:
- ranking of the preferred display connectors
preferred_refreshrates:
required: False
default: {"50": 4, "60": 3, "75": 2, "30": 1, "25": 0}
description:
- ranking of the preferred display refreshrate
preferred_resolutions:
required: False
default: {"7680x4320": 8, "3840x2160": 4, "1920x1080": 2, "1280x720": 1, "720x576": 0}
description:
- ranking of the preferred display resolutions
'''
EXAMPLES = '''
- name: "collect facts for connected displays"
action: xserver_facts
display: ":0"
- debug:
var: xorg
'''
import ast
import json
import re
import subprocess
import sys
import time
from collections import OrderedDict, namedtuple
from ansible.module_utils.basic import *
arg_specs = {
'display': dict(default=[":0", ":0.1"], type='list', required=False),
'multi_display': dict(default=True, type='bool', required=False),
'preferred_outputs': dict(default={"HDMI": 8, "DP": 4, "DVI": 2, "VGA": 1, "TV": 0}, type='dict', required=False),
'preferred_refreshrates': dict(default={50: 8, 60: 4, 75: 3, 30: 2, 25: 1}, type='dict', required=False),
'preferred_resolutions': dict(default={"7680x4320": 8, "3840x2160": 4, "1920x1080": 2, "1280x720": 1, "720x576": 0},
type='dict', required=False),
}
Mode = namedtuple('Mode', ['score', 'connection', 'resolution', 'refreshrate'])
class ModelineTools(object):
def __init__(self, preferred_outputs, preferred_resolutions, preferred_refreshrates):
self.preferred_outputs = preferred_outputs
self.preferred_resolutions = preferred_resolutions
self.preferred_refreshrates = preferred_refreshrates
def get_score(self, connection, resolution, refreshrate):
connection = connection.split('-')[0]
score = self.preferred_refreshrates.get(int(refreshrate), 0)
score = score << 4
score += self.preferred_resolutions.get(resolution, 0)
#score = score << 4
#score += self.preferred_outputs.get(connection, 0)
return score
@staticmethod
def cleanup_refreshrate(refreshrate):
rrate = refreshrate.replace('+', '').replace('*', '').replace(' ', '').strip()
return int(round(ast.literal_eval(rrate)))
def sort_mode(self, mode):
x, y = mode.resolution.split('x')
connection = mode.connection.split('-')[0]
return (mode.score, int(x), int(y), self.preferred_outputs.get(connection, 0))
def main():
module = AnsibleModule(argument_spec=arg_specs, supports_check_mode=False,)
display_list = module.params['display']
preferred_outputs = module.params['preferred_outputs']
preferred_resolutions = module.params['preferred_resolutions']
preferred_refreshrates = module.params['preferred_refreshrates']
mtools = ModelineTools(preferred_outputs, preferred_resolutions, preferred_refreshrates)
modes = []
displays = {}
data = {}
for display in display_list:
# call xrandr
try:
xrandr_data = subprocess.check_output(['xrandr', '-q','-d', display],
universal_newlines=True)
except: continue
for line in xrandr_data.splitlines():
if line.startswith('Screen'):
screen = line.split(':')[0].split()[-1]
screen = "Screen{}".format(screen)
displays[screen] = {}
elif 'connected' in line:
connection = line.split()[0]
displays[screen][connection] = {}
if 'disconnected' in line:
displays[screen][connection]['connected'] = False
else:
displays[screen][connection]['connected'] = True
displays[screen][connection]['modes'] = OrderedDict(
sorted({}.items(), key=lambda t: t.split('_')[0]))
elif line.startswith(' '):
fields = filter(None, re.split(r'\s{2,}', line))
resolution = fields[0]
refreshrates = fields[1:]
r = set()
for refreshrate in refreshrates:
refreshrate = refreshrate.strip()
rrate = mtools.cleanup_refreshrate(refreshrate)
if len(refreshrate) < 2:
continue
if '*' in refreshrate:
current_mode = (resolution, rrate)
displays[screen][connection]['current_mode'] = current_mode
if '+' in refreshrate:
preferred_mode = (resolution, rrate)
displays[screen][connection]['preferred_mode'] = preferred_mode
r.add(mtools.cleanup_refreshrate(refreshrate))
modes.append(Mode(score=mtools.get_score(connection, resolution, rrate), connection=connection,
resolution=resolution, refreshrate=rrate))
displays[screen][connection]['modes'][resolution] = sorted(r)
data['displays'] = displays
data['modes'] = modes
best_mode = max(modes, key=mtools.sort_mode)
data["best_mode"] = {
'connection': best_mode.connection,
'resolution': best_mode.resolution,
'refreshrate': best_mode.refreshrate,
}
module.exit_json(changed=False, ansible_facts={'xorg': data})
if __name__ == '__main__':
main()

View File

@ -1,7 +1,2 @@
[yavdr-full]
[localhost]
localhost connection=local
#192.168.1.116
[yavdr-headless]
[yavdr-client]

View File

@ -0,0 +1,9 @@
---
# file: roles/display-data/tasks/main.yml
- name: "detect xorg configuration"
action: xorg_facts
- debug:
var: xorg
verbosity: 1

View File

@ -0,0 +1,22 @@
foo:
- bar
- baz
- spam
system:
hardware:
nvidia:
detected: "1"
busid: "000:2304:234"
x11:
dualhead:
enabled: "0"
display:
0:
mode:
- "1920x1080_50"
default: "nvidia-auto"
1:
mode:
- "1280x720_60"

View File

@ -0,0 +1,9 @@
---
- name: show vars
debug:
var: '{{ system }}'
- name: test templates
template:
src: templates/test.j2
dest: /tmp/test.txt

View File

@ -0,0 +1,184 @@
{{ ansible_managed_file | comment }}
Section "ServerLayout"
Identifier "Layout0"
Screen 0 "Screen0"
{% if system.x11.dualhead.enabled %}
Screen 1 "Screen1" RightOf "Screen0"
{% endif %}
InputDevice "Keyboard0" "CoreKeyboard"
InputDevice "Mouse0" "CorePointer"
EndSection
Section "InputDevice"
# generated from default
Identifier "Mouse0"
Driver "mouse"
Option "Protocol" "auto"
Option "Device" "/dev/psaux"
Option "Emulate3Buttons" "no"
Option "ZAxisMapping" "4 5"
EndSection
Section "InputDevice"
# generated from default
Identifier "Keyboard0"
Driver "kbd"
EndSection
Section "Monitor"
Identifier "Monitor0"
VendorName "Unknown"
ModelName "Unknown"
{% if system.x11.display.0.default == "VGA2Scart_4_3" or system.x11.display.0.default == "VGA2Scart_16_9" %}
HorizSync 14-17
VertRefresh 49-61
{% if system.x11.display.0.default == "VGA2Scart_4_3" %}
Modeline "VGA2Scart_4_3" 13.875 720 744 808 888 576 580 585 625 -HSync -Vsync interlace
{% elif system.x11.display.0.default == "VGA2Scart_16_9" %}
Modeline "VGA2Scart_16_9" 19 1024 1032 1120 1216 576 581 586 625 -Hsync -Vsync interlace
{% endif %}
{% endif %}
Option "DPMS"
Option "ExactModeTimingsDVI" "True"
EndSection
{% if system.x11.dualhead.enabled == "1" %}
Section "Monitor"
Identifier "Monitor1"
VendorName "Unknown"
ModelName "Unknown"
{% if system.x11.display.1.default in ("VGA2Scart_4_3", "VGA2Scart_16_9") %}
HorizSync 14-17
VertRefresh 49-61
{% if system.x11.display.1.default == "VGA2Scart_4_3" %}
Modeline "VGA2Scart_4_3" 13.875 720 744 808 888 576 580 585 625 -HSync -Vsync interlace
{% elif system.x11.display.1.default == "VGA2Scart_16_9" %}
Modeline "VGA2Scart_16_9" 19 1024 1032 1120 1216 576 581 586 625 -Hsync -Vsync interlace
{% endif %}
Option "DPMS"
Option "ExactModeTimingsDVI" "True"
{% endif %}
EndSection
{% endif %}
Section "Device"
Identifier "Device0"
{% if system.hardware.nvidia.detected %}
Driver "nvidia"
VendorName "NVIDIA Corporation"
{% endif %}
Screen 0
Option "DPI" "100x100"
{% if system.hardware.nvidia.busid %}
BusID "PCI: {{ system.hardware.nvidia.busid }}"
{% endif %}
Option "NoLogo" "True"
Option "UseEvents" "True"
Option "TripleBuffer" "False"
Option "AddARGBGLXVisuals" "True"
Option "TwinView" "0"
Option "DynamicTwinView" "0"
Option "OnDemandVBlankinterrupts" "on"
Option "FlatPanelProperties" "Scaling = Native"
EndSection
{% if system.x11.dualhead.enabled == "1" %}
Section "Device"
Identifier "Device1"
{% if system.hardware.nvidia.detected %}
Driver "nvidia"
VendorName "NVIDIA Corporation"
{% endif %}
Screen 1
{% if system.hardware.nvidia.busid %}
BusID "PCI: {{ system.hardware.nvidia.busid }}"
{% endif %}
Option "NoLogo" "True"
Option "UseEvents" "True"
Option "TripleBuffer" "False"
Option "AddARGBGLXVisuals" "True"
Option "TwinView" "0"
Option "DynamicTwinView" "0"
EndSection
{% endif %}
Section "Screen"
Identifier "Screen0"
Device "Device0"
Monitor "Monitor0"
DefaultDepth 24
SubSection "Display"
Depth 24
{% if system.x11.display.0.default is defined and system.x11.display.0.default %}
Modes "{{ system.x11.display.0.default }}"{% for mode in system.x11.display.0.mode %}{% if mode != system.x11.display.0.default %} "{{ mode }}"{% endif %}{% endfor %}
{% elif system.hardware.nvidia.detected == 1 %}
Modes "nvidia-auto-select"
{% endif %}
EndSubSection
{% if system.x11.display.0.default or system.x11.default %}
{% if system.x11.display.0.device is definded and system.x11.display.0.device %}
Option "ConnectedMonitor" {{ system.x11.display.0.device }}
{% else %}
Option "ConnectedMonitor" {{ system.x11.default }}
{% endif %}
# Option "ConnectedMonitor" "<?cs if:(?system.x11.display.0.device) ?><?cs call:fix_display_name(system.x11.display.0.device) ?><?cs else ?><?cs var:system.x11.default ?><?cs /if ?><?cs if:(?system.x11.dualhead.enabled && system.x11.dualhead.enabled == 1) ?>, <?cs call:fix_display_name(system.x11.display.1.device) ?><?cs /if ?>"
#Option "ConnectedMonitor"
"<?cs if:(?system.x11.display.0.device) ?>
<?cs call:fix_display_name(system.x11.display.0.device) ?>
<?cs else ?>
<?cs var:system.x11.default ?>
<?cs /if ?>
<?cs if:(?system.x11.dualhead.enabled && system.x11.dualhead.enabled == 1) ?>, <?cs call:fix_display_name(system.x11.display.1.device) ?><?cs /if ?>"
# Option "UseDisplayDevice" "<?cs if:(?system.x11.display.0.device) ?><?cs call:fix_display_name(system.x11.display.0.device) ?><?cs else ?><?cs var:system.x11.default ?><?cs /if ?>"
# <?cs /if ?>
# <?cs if:(?system.hardware.nvidia.0.edid && system.hardware.nvidia.0.edid == "1") ?>
# Option "CustomEDID" "<?cs call:fix_display_name(system.x11.display.0.device) ?>:/etc/X11/edid.0.yavdr"
# <?cs /if ?>
# <?cs if:(system.hardware.nvidia.detected == 1 && ?system.x11.display.0.device) ?>
# Option "MetaModes" "<?cs call:fix_display_name(system.x11.display.0.device) ?>: <?cs var:system.x11.display.0.default ?> { ViewPortIn=<?cs var:system.x11.display.0.viewport.in.x ?>x<?cs var:system.x11.display.0.viewport.in.y ?>, ViewPortOut=<?cs var:system.x11.display.0.viewport.out.x ?>x<?cs var:system.x11.display.0.viewport.out.y ?>+<?cs var:system.x11.display.0.viewport.out.plusx ?>+<?cs var:system.x11.display.0.viewport.out.plusy ?> }"
# <?cs each:mode = system.x11.display.0.mode ?><?cs if:(mode != system.x11.display.0.default) ?>
# Option "MetaModes" "<?cs call:fix_display_name(system.x11.display.0.device) ?>: <?cs var:mode ?> { ViewPortIn=<?cs var:system.x11.display.0.viewport.in.x ?>x<?cs var:system.x11.display.0.viewport.in.y ?>, ViewPortOut=<?cs var:system.x11.display.0.viewport.out.x ?>x<?cs var:system.x11.display.0.viewport.out.y ?>+<?cs var:system.x11.display.0.viewport.out.plusx ?>+<?cs var:system.x11.display.0.viewport.out.plusy ?> }"<?cs /if ?><?cs /each ?>
{% endif %}
EndSection
{% if system.x11.dualhead.enabled == "1" %}
Section "Screen"
Identifier "Screen1"
Device "Device1"
Monitor "Monitor1"
DefaultDepth 24
SubSection "Display"
Depth 24
{% if system.x11.display.0.default is defined and system.x11.display.0.default %}
Modes "{{ system.x11.display.1.default }}"{% for mode in system.x11.display.1.mode %}{% if mode != system.x11.display.1.default %} "{{ mode }}"{% endif %}{% endfor %}
{% elif system.hardware.nvidia.detected == "1" %}
Modes "nvidia-auto-select"
{% endif %}
EndSubSection
# <?cs if:(?system.x11.display.1.default && system.x11.display.1.default != "" && system.x11.display.1.default != "disabled") ?>
# Option "UseDisplayDevice" "<?cs call:fix_display_name(system.x11.display.1.device) ?>"
# <?cs /if ?>
# <?cs if:(?system.hardware.nvidia.1.edid && system.hardware.nvidia.1.edid == "1") ?>
# Option "CustomEDID" "<?cs call:fix_display_name(system.x11.display.1.device) ?>:/etc/X11/edid.1.yavdr"
# <?cs /if ?>
# <?cs if:(system.hardware.nvidia.detected == 1 && ?system.x11.display.1.device) ?>
# Option "MetaModes" "<?cs call:fix_display_name(system.x11.display.1.device) ?>: <?cs var:system.x11.display.1.default ?> { ViewPortIn=<?cs var:system.x11.display.1.viewport.in.x ?>x<?cs var:system.x11.display.1.viewport.in.y ?>, ViewPortOut=<?cs var:system.x11.display.1.viewport.out.x ?>x<?cs var:system.x11.display.1.viewport.out.y ?>+<?cs var:system.x11.display.1.viewport.out.plusx ?>+<?cs var:system.x11.display.1.viewport.out.plusy ?> }"
# <?cs each:mode = system.x11.display.1.mode ?><?cs if:(mode != system.x11.display.1.default) ?>
# Option "MetaModes" "<?cs call:fix_display_name(system.x11.display.1.device) ?>: <?cs var:mode ?> { ViewPortIn=<?cs var:system.x11.display.1.viewport.in.x ?>x<?cs var:system.x11.display.1.viewport.in.y ?>, ViewPortOut=<?cs var:system.x11.display.1.viewport.out.x ?>x<?cs var:system.x11.display.1.viewport.out.y ?>+<?cs var:system.x11.display.1.viewport.out.plusx ?>+<?cs var:system.x11.display.1.viewport.out.plusy ?> }"<?cs /if ?><?cs /each ?>
# <?cs /if ?>
EndSection
{% endif %}
Section "Extensions"
# if no open-gl OSD is needed (e.g. for vdr-sxfe):
Option "Composite" "Disable"
EndSection

View File

@ -0,0 +1,5 @@
vars:
foo:
- bar
- baz
- spam

View File

@ -0,0 +1,8 @@
[Unit]
Description=X with verbose logging on %I
Wants=graphical.target
Before=graphical.target
[Service]
Type=forking
ExecStart=/usr/bin/x-daemon -logverbose 6 -noreset %I