From 29c51ce57edcb86c941d871bcd8573fa89d64148 Mon Sep 17 00:00:00 2001 From: Martin Kolman Date: Thu, 9 Nov 2023 17:52:44 +0100 Subject: [PATCH] Fallback to Wayland if Xorg is not available In environments where Anaconda handles the overall GUI environment setup (eq. netinst/boot.iso) try to use Wayland compositor if Xorg server is not found. Also add support for a (temporary?) boot inst.wayland boot option, that can be used to force Wayland compositor to be used. This makes it possible to check if Waland can be used in the given environment even if the given installation image still contains Xorg. --- anaconda.spec.in | 5 ++ pyanaconda/display.py | 116 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 110 insertions(+), 11 deletions(-) diff --git a/anaconda.spec.in b/anaconda.spec.in index 0afd56b88044..d73eeecfcba9 100644 --- a/anaconda.spec.in +++ b/anaconda.spec.in @@ -256,6 +256,11 @@ Requires: nm-connection-editor Requires: librsvg2 Requires: gnome-kiosk Requires: brltty +# Wayland support dependecies +# FIXME: conditionalize this ? +Requires: python3-pam +Requires: sssd-client +Requires: xorg-x11-server-Xwayland # dependencies for rpm-ostree payload module Requires: rpm-ostree >= %{rpmostreever} Requires: ostree diff --git a/pyanaconda/display.py b/pyanaconda/display.py index 2b67b9af3c04..7760268bb56c 100644 --- a/pyanaconda/display.py +++ b/pyanaconda/display.py @@ -28,6 +28,7 @@ from pyanaconda.core.configuration.anaconda import conf from pyanaconda.core.process_watchers import WatchProcesses +from pyanaconda.core.kernel import kernel_arguments from pyanaconda import startup_utils from pyanaconda.core import util, constants, hw from pyanaconda import vnc @@ -245,6 +246,74 @@ def write_xdriver(driver, root=None): f.close() +# Wayland + +def start_wayland_compositor(): + """Start Wayland compositor for the Anaconda GUI. + + Add XDG_DATA_DIRS to the environment to pull in our overridden schema + files. + + FIXME: Will XDG_DATA_DIRS work with Wayland compositor ? + """ + datadir = os.environ.get('ANACONDA_DATADIR', '/usr/share/anaconda') + if 'XDG_DATA_DIRS' in os.environ: + xdg_data_dirs = datadir + '/window-manager:' + os.environ['XDG_DATA_DIRS'] + else: + xdg_data_dirs = datadir + '/window-manager:/usr/share' + + def wayland_preexec(): + # to set GUI subprocess SIGINT handler + # FIXME: does this even work with a Wayland compoitor ? + signal.signal(signal.SIGINT, signal.SIG_IGN) + +# childproc = util.startProgram(["gnome-kiosk", "--sm-disable", "--wayland"], +# env_add={ +# 'XDG_DATA_DIRS': xdg_data_dirs, +# 'XDG_RUNTIME_DIR': "/run/user/0"}, +# preexec_fn=wayland_preexec) + + +#"/run-in-new-session.py --user root --service anaconda-session --session-type wayland --session-class user /bin/gnome-kiosk --wayland --sm-disable" + + childproc = util.startProgram(["run-in-new-session.py", "--user", "root", + "--service", "anaconda-session", + "--vt", "6", + "--session-type", "wayland", "--session-class", "user", + "gnome-kiosk", "--sm-disable"], + env_add={ + 'XDG_DATA_DIRS': xdg_data_dirs, + 'XDG_RUNTIME_DIR': "/run/user/0"}, + preexec_fn=wayland_preexec) + + #WatchProcesses.watch_process(childproc, "gnome-kiosk") + + WatchProcesses.watch_process(childproc, "run-in-new-session.py") + + +def set_wayland_resolution(runres): + """Set Wayland server screen resolution. + + FIXME: implement this using Mutter DBus API + FIXME: keep runres or use horizontal/vertical resolution instead ? + + :param str runres: a resolution specification string + """ + log.error("FIXME: set screen resolution - not yet implemented on Wayland") + + +def do_extra_wayland_actions(runres, gui_mode): + """Perform Wayland related actions not related to startup. + + :param str runres: a resolution specification string + :param gui_mode: an Anaconda display mode + """ + if runres and gui_mode and not flags.usevnc: + set_wayland_resolution(runres) + + start_user_systemd() + + # general display startup def setup_display(anaconda, options): """Setup the display for the installation environment. @@ -319,16 +388,35 @@ def setup_display(anaconda, options): for error_message in vnc_error_messages: stdout_log.warning(error_message) - # Should we try to start Xorg? - want_x = anaconda.gui_mode and not (flags.preexisting_x11 or flags.usevnc) - - # Is Xorg is actually available? - if want_x and not os.access("/usr/bin/Xorg", os.X_OK): - stdout_log.warning(_("Graphical installation is not available. " - "Starting text mode.")) - time.sleep(2) - anaconda.display_mode = constants.DisplayModes.TUI - want_x = False + # Xorg or Wayland? + want_x = False + want_wayland = False + + # try to run in local GUI mode + if anaconda.gui_mode and not (flags.preexisting_x11 or flags.usevnc): + # is Xorg actually available? + xorg_server_available = os.access("/usr/bin/Xorg", os.X_OK) + + # is our Wayland compositor available ? + wayland_compositor_available = os.access("/usr/bin/gnome-kiosk", os.X_OK) + + # do we have at least one of the needed deps we need to run in graphical mode ? + if xorg_server_available: + # check for Wayland override + if "wayland" in kernel_arguments and wayland_compositor_available: + # this way we can test if insaller on Wayland works on a given system + want_wayland = True + else: + # no Wayland override or no Wayland, just use X + want_x = True + elif wayland_compositor_available: + want_wayland = True + else: + # neither X or Wayland is available + anaconda.display_mode = constants.DisplayModes.TUI + stdout_log.warning(_("Graphical installation is not available. " + "Starting text mode.")) + time.sleep(2) if anaconda.tui_mode and flags.vncquestion: # we prefer vnc over text mode, so ask about that @@ -346,7 +434,13 @@ def setup_display(anaconda, options): # check_memory may have changed the display mode want_x = want_x and (anaconda.gui_mode) - if want_x: + want_wayland = want_wayland and (anaconda.gui_mode) + + if want_wayland: + log.debug("Using Wayland compositor to provide locally running graphical interface.") + start_wayland_compositor() + elif want_x: + log.debug("Using Xorg server to provide locally running graphical interface.") try: start_x11(xtimeout) do_startup_x11_actions()