Skip to content

Commit

Permalink
Fallback to Wayland if Xorg is not available
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
M4rtinK committed Nov 20, 2023
1 parent a70ac7c commit 2d18dfa
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 11 deletions.
7 changes: 7 additions & 0 deletions anaconda.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,13 @@ def setup_environment():
print("anaconda must be run as root.")
sys.exit(1)

# FIXME: try setting XDG_RUNTIME_DIR early
os.environ["XDG_RUNTIME_DIR"] = "/run/user/0"
# FIXME: enable GTK startup debugging
os.environ["G_MESSAGES_DEBUG"] = "all"
os.environ["GDK_DEBUG"] = "all"
os.environ["GTK_DEBUG"] = "all"

print("Starting installer, one moment...")

# Allow a file to be loaded as early as possible
Expand Down
5 changes: 5 additions & 0 deletions anaconda.spec.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
116 changes: 105 additions & 11 deletions pyanaconda/display.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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()
Expand Down
4 changes: 4 additions & 0 deletions pyanaconda/ui/gui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,10 @@ def __init__(self, fullscreen=False, decorated=False):
:param bool fullscreen: if True, fullscreen the window, if false maximize
"""
super().__init__()

# FIXME: try to force wayland
Gdk.set_allowed_backends("wayland")

# Keep the latest main window.
self.__class__.__instance = self

Expand Down

0 comments on commit 2d18dfa

Please sign in to comment.