Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libxklavier removal #5463

Merged
merged 5 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ widgets/doc/xml
widgets/gtk-doc.make
widgets/src/gettext.h
widgets/src/resources.*
widgets/src/an-localization.*
pyanaconda/version.py
.doctrees
_sources
Expand Down
5 changes: 2 additions & 3 deletions anaconda.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ Source0: https://github.com/rhinstaller/%{name}/releases/download/%{name}-%{vers
%define libarchivever 3.0.4
%define libblockdevver 2.1
%define libreportanacondaver 2.0.21-1
%define libxklavierver 5.4
%define mehver 0.23-1
%define nmver 1.0
%define pykickstartver 3.52-1
Expand All @@ -57,7 +56,6 @@ BuildRequires: gobject-introspection-devel
%if %{with glade}
BuildRequires: glade-devel
%endif
BuildRequires: libxklavier-devel >= %{libxklavierver}
BuildRequires: make
BuildRequires: pango-devel
BuildRequires: python3-devel
Expand Down Expand Up @@ -284,7 +282,6 @@ Requires: python3-xkbregistry
Requires: adwaita-icon-theme
Requires: tecla
Requires: tigervnc-server-minimal
Requires: libxklavier >= %{libxklavierver}
Requires: nm-connection-editor
%ifnarch s390 s390x
Requires: NetworkManager-wifi
Expand All @@ -296,6 +293,8 @@ Requires: system-logos

# Needed to compile the gsettings files
BuildRequires: gsettings-desktop-schemas
# Needed for gdbus-codegen
BuildRequires: glib2-devel

%description gui
This package contains graphical user interface for the Anaconda installer.
Expand Down
9 changes: 8 additions & 1 deletion pyanaconda/modules/common/constants/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from pyanaconda.core.dbus import SystemBus, DBus
from pyanaconda.core.dbus import SystemBus, SessionBus, DBus
from dasbus.identifier import DBusServiceIdentifier
from pyanaconda.modules.common.constants.namespaces import BOSS_NAMESPACE, TIMEZONE_NAMESPACE, \
NETWORK_NAMESPACE, LOCALIZATION_NAMESPACE, SECURITY_NAMESPACE, USERS_NAMESPACE, \
Expand Down Expand Up @@ -107,3 +107,10 @@
namespace=NETWORK_MANAGER_NAMESPACE,
message_bus=SystemBus
)

# Session services.

GK_INPUT_SOURCES = DBusServiceIdentifier(
namespace=("org", "gnome", "Kiosk"),
message_bus=SessionBus
)
135 changes: 135 additions & 0 deletions pyanaconda/modules/localization/gk_keyboard_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#
# 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")
jexposit marked this conversation as resolved.
Show resolved Hide resolved
: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)
33 changes: 33 additions & 0 deletions pyanaconda/modules/localization/localization.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
from pyanaconda.modules.localization.runtime import GetMissingKeyboardConfigurationTask, \
ApplyKeyboardTask, AssignGenericKeyboardSettingTask
from pyanaconda.modules.localization.localed import LocaledWrapper
from pyanaconda.modules.localization.gk_keyboard_manager import GkKeyboardManager

from pyanaconda.anaconda_loggers import get_module_logger
log = get_module_logger(__name__)
Expand Down Expand Up @@ -66,7 +67,11 @@ def __init__(self):
self.keyboard_seen_changed = Signal()
self._keyboard_seen = False

self.compositor_selected_layout_changed = Signal()
self.compositor_layouts_changed = Signal()

self._localed_wrapper = None
self._compositor_keyboard_manager = None

def publish(self):
"""Publish the module."""
Expand Down Expand Up @@ -315,3 +320,31 @@ def set_from_generic_keyboard_setting(self, keyboard):
)
result = task.run()
self._update_settings_from_task(result)

@property
def compositor_keyboard_manager(self):
if not self._compositor_keyboard_manager:
self._compositor_keyboard_manager = GkKeyboardManager()
self._compositor_keyboard_manager.compositor_selected_layout_changed.connect(
lambda layout: self.compositor_selected_layout_changed.emit(layout)
)
self._compositor_keyboard_manager.compositor_layouts_changed.connect(
lambda layouts: self.compositor_layouts_changed.emit(layouts)
)

return self._compositor_keyboard_manager

def get_compositor_selected_layout(self):
return self.compositor_keyboard_manager.get_compositor_selected_layout()

def set_compositor_selected_layout(self, layout_variant):
return self.compositor_keyboard_manager.set_compositor_selected_layout(layout_variant)

def select_next_compositor_layout(self):
return self.compositor_keyboard_manager.select_next_compositor_layout()

def get_compositor_layouts(self):
return self.compositor_keyboard_manager.get_compositor_layouts()

def set_compositor_layouts(self, layout_variants, options):
self.compositor_keyboard_manager.set_compositor_layouts(layout_variants, options)
58 changes: 57 additions & 1 deletion pyanaconda/modules/localization/localization_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from dasbus.typing import * # pylint: disable=wildcard-import
from pyanaconda.modules.common.base import KickstartModuleInterface
from pyanaconda.modules.common.containers import TaskContainer
from dasbus.server.interface import dbus_interface
from dasbus.server.interface import dbus_interface, dbus_signal


@dbus_interface(LOCALIZATION.interface_name)
Expand All @@ -40,6 +40,10 @@ def connect_signals(self):
self.watch_property("XLayouts", self.implementation.x_layouts_changed)
self.watch_property("LayoutSwitchOptions", self.implementation.switch_options_changed)
self.watch_property("KeyboardKickstarted", self.implementation.keyboard_seen_changed)
self.implementation.compositor_selected_layout_changed.connect(
self.CompositorSelectedLayoutChanged
)
self.implementation.compositor_layouts_changed.connect(self.CompositorLayoutsChanged)

def GetLanguages(self) -> List[Str]:
"""Get languages with available translations.
Expand Down Expand Up @@ -237,3 +241,55 @@ def ApplyKeyboardWithTask(self) -> ObjPath:
return TaskContainer.to_object_path(
self.implementation.apply_keyboard_with_task()
)

def GetCompositorSelectedLayout(self) -> Str:
"""Get the activated keyboard layout.

:return: Current keyboard layout (e.g. "cz (qwerty)")
:rtype: str
"""
return self.implementation.get_compositor_selected_layout()

def SetCompositorSelectedLayout(self, layout_variant: Str) -> Bool:
"""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
"""
return self.implementation.set_compositor_selected_layout(layout_variant)

def SelectNextCompositorLayout(self):
"""Set the next available layout as active."""
return self.implementation.select_next_compositor_layout()

@dbus_signal
def CompositorSelectedLayoutChanged(self, layout: Str):
"""Signal emitted when the selected keyboard layout changes."""
pass

def GetCompositorLayouts(self) -> List[Str]:
"""Get all available keyboard layouts.

:return: A list of keyboard layouts (e.g. ["cz (qwerty)", cn (mon_todo_galik)])
:rtype: list of strings
"""
return self.implementation.get_compositor_layouts()

def SetCompositorLayouts(self, layout_variants: List[Str], options: List[Str]):
"""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
"""
self.implementation.set_compositor_layouts(layout_variants, options)

@dbus_signal
def CompositorLayoutsChanged(self, layouts: List[Str]):
"""Signal emitted when available layouts change."""
pass
Loading
Loading