197 lines
7.4 KiB
Python
197 lines
7.4 KiB
Python
|
#
|
||
|
# Copyright (C) 2019 Red Hat, Inc.
|
||
|
#
|
||
|
# This copyrighted material is made available to anyone wishing to use,
|
||
|
# modify, copy, or redistribute it subject to the terms and conditions of
|
||
|
# the GNU General Public License v.2, or (at your option) any later version.
|
||
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||
|
# ANY WARRANTY expressed or implied, including the implied warranties of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||
|
# Public License for more details. You should have received a copy of the
|
||
|
# GNU General Public License along with this program; if not, write to the
|
||
|
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||
|
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
|
||
|
# source code or documentation are not subject to the GNU General Public
|
||
|
# License and may only be used or replicated with the express permission of
|
||
|
# Red Hat, Inc.
|
||
|
#
|
||
|
from pyanaconda.core.util import execWithRedirect
|
||
|
from pyanaconda.core.configuration.anaconda import conf
|
||
|
from pyanaconda.modules.common.errors.configuration import KeyboardConfigurationError
|
||
|
from pyanaconda.modules.common.task import Task
|
||
|
from pyanaconda.modules.localization.utils import get_missing_keyboard_configuration
|
||
|
from pyanaconda.anaconda_loggers import get_module_logger
|
||
|
from pyanaconda.modules.localization.installation import write_vc_configuration
|
||
|
|
||
|
log = get_module_logger(__name__)
|
||
|
|
||
|
|
||
|
class AssignGenericKeyboardSettingTask(Task):
|
||
|
"""Task for assignment of generic keyboard specification to a specific configuration."""
|
||
|
|
||
|
def __init__(self, keyboard):
|
||
|
"""Create a new task.
|
||
|
|
||
|
:param keyboard: generic system keyboard specification
|
||
|
:type keyboard: str
|
||
|
"""
|
||
|
super().__init__()
|
||
|
self._keyboard = keyboard
|
||
|
|
||
|
@property
|
||
|
def name(self):
|
||
|
return "Assign generic keyboard setting value."
|
||
|
|
||
|
def run(self):
|
||
|
"""Run assignment of generic keyboard setting value.
|
||
|
|
||
|
:returns: tuple of X layouts and VC keyboard settings
|
||
|
:rtype: (list(str), str))
|
||
|
"""
|
||
|
x_layouts = []
|
||
|
vc_keymap = ""
|
||
|
|
||
|
if conf.system.can_activate_keyboard:
|
||
|
is_keymap = try_to_load_keymap(self._keyboard)
|
||
|
if is_keymap:
|
||
|
vc_keymap = self._keyboard
|
||
|
else:
|
||
|
x_layouts.append(self._keyboard)
|
||
|
else:
|
||
|
vc_keymap = self._keyboard
|
||
|
|
||
|
return x_layouts, vc_keymap
|
||
|
|
||
|
|
||
|
class GetMissingKeyboardConfigurationTask(Task):
|
||
|
"""Task for getting missing keyboard settings by conversion and default values."""
|
||
|
|
||
|
def __init__(self, localed_wrapper, x_layouts, vc_keymap):
|
||
|
"""Create a new task.
|
||
|
|
||
|
:param localed_wrapper: instance of systemd-localed service wrapper
|
||
|
:type localed_wrapper: LocaledWrapper
|
||
|
:param x_layouts: list of x layout specifications
|
||
|
:type x_layouts: list(str)
|
||
|
:param vc_keymap: virtual console keyboard mapping name
|
||
|
:type vc_keymap: str
|
||
|
"""
|
||
|
super().__init__()
|
||
|
self._localed_wrapper = localed_wrapper
|
||
|
self._x_layouts = x_layouts
|
||
|
self._vc_keymap = vc_keymap
|
||
|
|
||
|
@property
|
||
|
def name(self):
|
||
|
return "Get missing keyboard settings."
|
||
|
|
||
|
def run(self):
|
||
|
"""Run getting of missing keyboard settings.
|
||
|
|
||
|
:returns: tuple of X layouts and VC keyboard settings
|
||
|
:rtype: (list(str), str))
|
||
|
"""
|
||
|
return get_missing_keyboard_configuration(self._localed_wrapper,
|
||
|
self._x_layouts,
|
||
|
self._vc_keymap)
|
||
|
|
||
|
|
||
|
class ApplyKeyboardTask(Task):
|
||
|
"""Task for applying keyboard settings to current system."""
|
||
|
|
||
|
def __init__(self, localed_wrapper, x_layouts, vc_keymap, switch_options):
|
||
|
"""Create a new task.
|
||
|
|
||
|
:param localed_wrapper: instance of systemd-localed service wrapper
|
||
|
:type localed_wrapper: LocaledWrapper
|
||
|
:param x_layouts: list of x layout specifications
|
||
|
:type x_layouts: list(str)
|
||
|
:param vc_keymap: virtual console keyboard mapping name
|
||
|
:type vc_keymap: str
|
||
|
:param switch_options: list of options for layout switching
|
||
|
:type switch_options: list(str)
|
||
|
"""
|
||
|
super().__init__()
|
||
|
self._localed_wrapper = localed_wrapper
|
||
|
self._x_layouts = x_layouts
|
||
|
self._vc_keymap = vc_keymap
|
||
|
self._switch_options = switch_options
|
||
|
|
||
|
@property
|
||
|
def name(self):
|
||
|
return "Apply keyboard configuration."
|
||
|
|
||
|
def run(self):
|
||
|
"""Run application of keyboard settings.
|
||
|
|
||
|
:returns: tuple of X layouts and VC keyboard settings after application
|
||
|
:rtype: (list(str), str))
|
||
|
"""
|
||
|
if not conf.system.can_activate_keyboard:
|
||
|
log.debug("Activating of keyboard configuration is disabled on this system.")
|
||
|
return self._x_layouts, self._vc_keymap
|
||
|
|
||
|
if not self._vc_keymap and not self._x_layouts:
|
||
|
log.debug("Not applying keyboard configuration:"
|
||
|
"neither VConsole not X Layouts are set.")
|
||
|
return self._x_layouts, self._vc_keymap
|
||
|
|
||
|
vc_keymap = self._vc_keymap
|
||
|
x_layouts = self._x_layouts
|
||
|
x_layouts_from_conversion = None
|
||
|
|
||
|
if vc_keymap:
|
||
|
valid_keymap = try_to_load_keymap(vc_keymap)
|
||
|
if not valid_keymap:
|
||
|
log.error("'%s' is not a valid VConsole keymap, not loading", vc_keymap)
|
||
|
vc_keymap = ""
|
||
|
else:
|
||
|
# activate VConsole keymap and get converted layout and variant
|
||
|
x_layouts_from_conversion = self._localed_wrapper.set_and_convert_keymap(vc_keymap)
|
||
|
|
||
|
if not x_layouts:
|
||
|
if x_layouts_from_conversion:
|
||
|
# suggested by systemd-localed for a requested VConsole keymap
|
||
|
x_layouts += x_layouts_from_conversion
|
||
|
elif vc_keymap:
|
||
|
# nothing suggested by systemd-localed, but we may try to use the
|
||
|
# same string for both VConsole keymap and X layout (will fail
|
||
|
# safely if it doesn't work)
|
||
|
x_layouts.append(vc_keymap)
|
||
|
|
||
|
if x_layouts:
|
||
|
if not vc_keymap:
|
||
|
vc_keymap = self._localed_wrapper.set_and_convert_layouts(x_layouts)
|
||
|
|
||
|
self._localed_wrapper.set_layouts(x_layouts, self._switch_options)
|
||
|
|
||
|
# FIXME: is this really needed?
|
||
|
# Only because of configuration of the FONT, if at all.
|
||
|
write_vc_configuration(vc_keymap, root="/")
|
||
|
|
||
|
return x_layouts, vc_keymap
|
||
|
|
||
|
|
||
|
def try_to_load_keymap(keymap):
|
||
|
"""
|
||
|
Method that tries to load keymap and returns boolean indicating if it was
|
||
|
successfull or not. It can be used to test if given string is VConsole
|
||
|
keymap or not, but in case it is given valid keymap, IT REALLY LOADS IT!.
|
||
|
|
||
|
:type keymap: string
|
||
|
:raise KeyboardConfigurationError: if loadkeys command is not available
|
||
|
:return: True if given string was a valid keymap and thus was loaded,
|
||
|
False otherwise
|
||
|
"""
|
||
|
# BUG: systemd-localed should be able to tell us if we are trying to
|
||
|
# activate invalid keymap. Then we will be able to get rid of this
|
||
|
# fuction
|
||
|
|
||
|
ret = 0
|
||
|
try:
|
||
|
ret = execWithRedirect("loadkeys", [keymap])
|
||
|
except OSError as oserr:
|
||
|
msg = "'loadkeys' command not available (%s)" % oserr.strerror
|
||
|
raise KeyboardConfigurationError(msg) from oserr
|
||
|
return ret == 0
|