diff --git a/anaconda.py b/anaconda.py index 7bc7d20c4825..1695e3777d27 100755 --- a/anaconda.py +++ b/anaconda.py @@ -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 @@ -226,6 +233,8 @@ def setup_environment(): if startup_utils.prompt_for_ssh(opts): sys.exit(0) + log.debug("AAA: MAIN PID/PPID %d/%d", os.getpid(), os.getppid()) + log.info("%s %s", sys.argv[0], util.get_anaconda_version_string(build_time_version=True)) log.debug("Image packages list: %s", util.get_image_packages_info()) 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..7aeccbc86f5e 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 @@ -50,6 +51,10 @@ log = get_module_logger(__name__) stdout_log = get_stdout_logger() +import gi +gi.require_version("Gdk", "3.0") +from gi.repository import Gdk + X_TIMEOUT_ADVICE = \ "Do not load the stage2 image over a slow network link.\n" \ "Wait longer for the X server startup with the inst.xtimeout= boot option." \ @@ -245,6 +250,79 @@ 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" + + log.debug("AAA: DISPLAY PID %d %d", os.getpid(), os.getppid()) + + # FIXME: try to force wayland + Gdk.set_allowed_backends("wayland") + + 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 +397,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 +443,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() diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py index 7cddde299002..3a312e566ff1 100644 --- a/pyanaconda/ui/gui/__init__.py +++ b/pyanaconda/ui/gui/__init__.py @@ -288,6 +288,7 @@ def __init__(self, fullscreen=False, decorated=False): :param bool fullscreen: if True, fullscreen the window, if false maximize """ super().__init__() + # Keep the latest main window. self.__class__.__instance = self @@ -705,6 +706,7 @@ def _instantiateAction(self, actionClass): return obj def run(self): + log.debug("AAA: GTK PID/PPID %d/%d", os.getpid(), os.getppid()) (success, _args) = Gtk.init_check(None) if not success: raise RuntimeError("Failed to initialize Gtk")