anaconda: save keyboard layout to udev

Xorg loads keyboard layout for new devices (or existing one re-detected)
only from its config, ignoring runtime changes done in the meantime
(setxkbmap etc). Since installation process calls udevadm trigger
somewhere, all input devices are re-discovered and reverted to default
keyboard layout (us). Avoid this by configuring current keyboard layout
also as udev rules, which are loaded by Xorg while discovering device.

Fixes QubesOS/qubes-issues#3352
This commit is contained in:
Marek Marczykowski-Górecki 2018-06-27 04:50:49 +02:00
parent 7d5bb6ff81
commit 806f2bc137
No known key found for this signature in database
GPG Key ID: 063938BA42CFA724

View File

@ -307,6 +307,8 @@ class XklWrapper(object):
raise XklWrapperError("Failed to add layout '%s (%s)'" % (layout,
variant))
self.save_layouts_to_udev(self._rec.layouts, self._rec.variants)
@gtk_action_wait
def remove_layout(self, layout):
"""
@ -341,6 +343,8 @@ class XklWrapper(object):
raise XklWrapperError("Failed to remove layout '%s (%s)'" % (layout,
variant))
self.save_layouts_to_udev(new_layouts, new_variants)
@gtk_action_wait
def replace_layouts(self, layouts_list):
"""
@ -368,6 +372,8 @@ class XklWrapper(object):
msg = "Failed to replace layouts with: %s" % ",".join(layouts_list)
raise XklWrapperError(msg)
self.save_layouts_to_udev(new_layouts, new_variants)
@gtk_action_wait
def set_switching_options(self, options):
"""
@ -391,3 +397,26 @@ class XklWrapper(object):
msg = "Failed to set switching options to: %s" % ",".join(options)
raise XklWrapperError(msg)
def save_layouts_to_udev(self, layouts, variants):
"""
Sets layouts to udev, so it will also apply to newly connected
keyboards (or existing after udevadm trigger). Otherwise Xorg setup
them based on xorg.conf with a fallback to hardcoded values.
:param layouts: list of layouts
:param variants: list of layout variants, matching *layouts*
"""
udev_rules_dir = '/run/udev/rules.d'
udev_rules_path = udev_rules_dir + '/90-keyboard-layout.rules'
try:
iutil.mkdirChain(udev_rules_dir)
except FileExistsError:
pass
with open(udev_rules_path, 'w') as rules:
rules.write('ENV{{ID_INPUT_KEYBOARD}}=="1", '
'ENV{{xkblayout}}="{layouts}", '
'ENV{{xkbvariant}}="{variants}"\n'.format(
layouts=','.join(layouts), variants=','.join(variants)))
iutil.startProgram(['udevadm', 'control', '-R']).communicate()