anaconda/anaconda-40.22.3.13/pyanaconda/modules/localization/gk_keyboard_manager.py
2024-11-14 21:39:56 -08:00

135 lines
5.6 KiB
Python

#
# Copyright (C) 2024 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.signal import Signal
from pyanaconda.keyboard import join_layout_variant, parse_layout_variant, KeyboardConfigError
from pyanaconda.modules.common.constants.services import GK_INPUT_SOURCES
class GkKeyboardManager(object):
"""Class wrapping GNOME Kiosk's input sources API."""
def __init__(self):
self.compositor_selected_layout_changed = Signal()
self.compositor_layouts_changed = Signal()
object_path = GK_INPUT_SOURCES.object_path + '/InputSources/Manager'
self._proxy = GK_INPUT_SOURCES.get_proxy(object_path=object_path)
self._proxy.PropertiesChanged.connect(self._on_properties_changed)
def _on_properties_changed(self, interface, changed_props, invalid_props):
for prop in changed_props:
if prop == 'SelectedInputSource':
layout_path = changed_props[prop]
layout_variant = self._path_to_layout(layout_path.get_string())
self.compositor_selected_layout_changed.emit(layout_variant)
if prop == 'InputSources':
layout_paths = changed_props[prop]
layout_variants = map(self._path_to_layout, list(layout_paths))
self.compositor_layouts_changed.emit(list(layout_variants))
def _path_to_layout(self, layout_path):
"""Transforms a layout path as returned by GNOME Kiosk to "layout (variant)".
:param layout_path: D-Bus path to the layout.
(e.g. "/org/gnome/Kiosk/InputSources/xkb_cz_2b_mon_5f_todo_5f_galik")
:type layout_path: str
:return: The layout with format "layout (variant)" (e.g. "cn (mon_todo_galik)")
:rtype: str
:raise KeyboardConfigError: if layouts with invalid backend type is found
"""
layout_proxy = GK_INPUT_SOURCES.get_proxy(object_path=layout_path)
if layout_proxy.BackendType != 'xkb':
raise KeyboardConfigError('Failed to get configuration from compositor')
if '+' in layout_proxy.BackendId:
layout, variant = layout_proxy.BackendId.split('+')
return join_layout_variant(layout, variant)
else:
return layout_proxy.BackendId
def _layout_to_xkb(self, layout_variant):
"""Transforms a "layout (variant)" to a "('xkb', 'layout+variant')".
:param layout_variant: The layout with format "layout (variant)" (e.g. "cz (qwerty)")
:type layout_variant: str
:return: The layout with format "('xkb', 'layout+variant')" (e.g. "('xkb', 'cz+qwerty')")
:rtype: str
"""
layout, variant = parse_layout_variant(layout_variant)
if variant:
return ('xkb', '{0}+{1}'.format(layout, variant))
else:
return ('xkb', layout)
def get_compositor_selected_layout(self):
"""Get the activated keyboard layout.
:return: Current keyboard layout (e.g. "cz (qwerty)")
:rtype: str
"""
layout_path = self._proxy.SelectedInputSource
if not layout_path or layout_path == '/':
return ''
return self._path_to_layout(layout_path)
def set_compositor_selected_layout(self, layout_variant):
"""Set the activated keyboard layout.
:param layout_variant: The layout to set, with format "layout (variant)"
(e.g. "cz (qwerty)")
:type layout_variant: str
:return: If the keyboard layout was activated
:rtype: bool
"""
layout_paths = self._proxy.InputSources
for layout_path in layout_paths:
if self._path_to_layout(layout_path) == layout_variant:
self._proxy.SelectInputSource(layout_path)
return True
return False
def select_next_compositor_layout(self):
"""Set the next available layout as active."""
self._proxy.SelectNextInputSource()
def get_compositor_layouts(self):
"""Get all available keyboard layouts.
:return: A list of keyboard layouts (e.g. ["cz (qwerty)", cn (mon_todo_galik)])
:rtype: list of strings
"""
layout_paths = self._proxy.InputSources
layout_variants = map(self._path_to_layout, list(layout_paths))
return list(layout_variants)
def set_compositor_layouts(self, layout_variants, options):
"""Set the available keyboard layouts.
:param layout_variants: A list of keyboard layouts (e.g. ["cz (qwerty)",
cn (mon_todo_galik)])
:type layout_variants: list of strings
:param options: A list of switching options
:type options: list of strings
"""
xkb_layouts = list(map(self._layout_to_xkb, layout_variants))
self._proxy.SetInputSources(xkb_layouts, options)