diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix index f435e85f6b8..cce35aa28ba 100644 --- a/nixos/modules/services/x11/desktop-managers/default.nix +++ b/nixos/modules/services/x11/desktop-managers/default.nix @@ -96,13 +96,13 @@ in else if any (w: w.name == defaultDM) cfg.session.list then defaultDM else - throw '' - Default desktop manager (${defaultDM}) not found. - Probably you want to change - services.xserver.desktopManager.default = "${defaultDM}"; - to one of + builtins.trace '' + Default desktop manager (${defaultDM}) not found at evaluation time. + These are the known valid session names: ${concatMapStringsSep "\n " (w: "services.xserver.desktopManager.default = \"${w.name}\";") cfg.session.list} - ''; + It's also possible the default can be found in one of these packages: + ${concatMapStringsSep "\n " (p: p.name) config.services.xserver.displayManager.extraSessionFilePackages} + '' defaultDM; }; }; diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix index 9fb8f44b242..ee9b11928ae 100644 --- a/nixos/modules/services/x11/desktop-managers/gnome3.nix +++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix @@ -57,8 +57,12 @@ in { sessionPath = mkOption { default = []; example = literalExample "[ pkgs.gnome3.gpaste ]"; - description = "Additional list of packages to be added to the session search path. - Useful for gnome shell extensions or gsettings-conditionated autostart."; + description = '' + Additional list of packages to be added to the session search path. + Useful for GNOME Shell extensions or GSettings-conditional autostart. + + Note that this should be a last resort; patching the package is preferred (see GPaste). + ''; apply = list: list ++ [ pkgs.gnome3.gnome-shell pkgs.gnome3.gnome-shell-extensions ]; }; @@ -126,18 +130,10 @@ in { fonts.fonts = [ pkgs.dejavu_fonts pkgs.cantarell-fonts ]; - services.xserver.desktopManager.session = singleton - { name = "gnome3"; - bgSupport = true; - start = '' - # Set GTK_DATA_PREFIX so that GTK+ can find the themes - export GTK_DATA_PREFIX=${config.system.path} - - # find theme engines - export GTK_PATH=${config.system.path}/lib/gtk-3.0:${config.system.path}/lib/gtk-2.0 - - export XDG_MENU_PREFIX=gnome- + services.xserver.displayManager.extraSessionFilePackages = [ pkgs.gnome3.gnome-session ]; + services.xserver.displayManager.sessionCommands = '' + if test "$XDG_CURRENT_DESKTOP" = "GNOME"; then ${concatMapStrings (p: '' if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name} @@ -148,34 +144,28 @@ in { export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib fi '') cfg.sessionPath} + fi + ''; - # Override default mimeapps - export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${mimeAppsList}/share + environment.variables.GNOME_SESSION_DEBUG = optionalString cfg.debug "1"; - # Override gsettings-desktop-schema - export NIX_GSETTINGS_OVERRIDES_DIR=${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas + # Override default mimeapps + environment.variables.XDG_DATA_DIRS = [ "${mimeAppsList}/share" ]; - # Let nautilus find extensions - export NAUTILUS_EXTENSION_DIR=${config.system.path}/lib/nautilus/extensions-3.0/ + # Override GSettings schemas + environment.variables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas"; - # Find the mouse - export XCURSOR_PATH=~/.icons:${config.system.path}/share/icons - - # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/ - ${pkgs.xdg-user-dirs}/bin/xdg-user-dirs-update - - ${pkgs.gnome3.gnome-session}/bin/gnome-session ${optionalString cfg.debug "--debug"} & - waitPID=$! - ''; - }; - - services.xserver.updateDbusEnvironment = true; + # Let nautilus find extensions + # TODO: Create nautilus-with-extensions package + environment.variables.NAUTILUS_EXTENSION_DIR = "${config.system.path}/lib/nautilus/extensions-3.0"; environment.variables.GIO_EXTRA_MODULES = [ "${lib.getLib pkgs.gnome3.dconf}/lib/gio/modules" "${pkgs.gnome3.glib-networking.out}/lib/gio/modules" "${pkgs.gnome3.gvfs}/lib/gio/modules" ]; environment.systemPackages = pkgs.gnome3.corePackages ++ cfg.sessionPath - ++ (removePackagesByName pkgs.gnome3.optionalPackages config.environment.gnome3.excludePackages); + ++ (removePackagesByName pkgs.gnome3.optionalPackages config.environment.gnome3.excludePackages) ++ [ + pkgs.xdg-user-dirs # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/ + ]; # Use the correct gnome3 packageSet networking.networkmanager.basePackages = diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix index 43ed21c95fe..72a567cc7ca 100644 --- a/nixos/modules/services/x11/display-managers/default.nix +++ b/nixos/modules/services/x11/display-managers/default.nix @@ -27,55 +27,26 @@ let Xft.hintstyle: hintslight ''; - # file provided by services.xserver.displayManager.session.script - xsession = wm: dm: pkgs.writeScript "xsession" + # file provided by services.xserver.displayManager.session.wrapper + xsessionWrapper = pkgs.writeScript "xsession-wrapper" '' #! ${pkgs.bash}/bin/bash - # Expected parameters: - # $1 = + - - # Actual parameters (FIXME): - # SDDM is calling this script like the following: - # $1 = /nix/store/xxx-xsession (= $0) - # $2 = + - # SLiM is using the following parameter: - # $1 = /nix/store/xxx-xsession + - # LightDM keeps the double quotes: - # $1 = /nix/store/xxx-xsession "+" - # The fake/auto display manager doesn't use any parameters and GDM is - # broken. - # If you want to "debug" this script don't print the parameters to stdout - # or stderr because this script will be executed multiple times and the - # output won't be visible in the log when the script is executed for the - # first time (e.g. append them to a file instead)! - - # All of the above cases are handled by the following hack (FIXME). - # Since this line is *very important* for *all display managers* it is - # very important to test changes to the following line with all display - # managers: - if [ "''${1:0:1}" = "/" ]; then eval exec "$1" "$2" ; fi - - # Now it should be safe to assume that the script was called with the - # expected parameters. + # Shared environment setup for graphical sessions. . /etc/profile cd "$HOME" - # The first argument of this script is the session type. - sessionType="$1" - if [ "$sessionType" = default ]; then sessionType=""; fi - ${optionalString cfg.startDbusSession '' if test -z "$DBUS_SESSION_BUS_ADDRESS"; then - exec ${pkgs.dbus.dbus-launch} --exit-with-session "$0" "$sessionType" + exec ${pkgs.dbus.dbus-launch} --exit-with-session "$0" "$@" fi ''} ${optionalString cfg.displayManager.job.logToJournal '' if [ -z "$_DID_SYSTEMD_CAT" ]; then export _DID_SYSTEMD_CAT=1 - exec ${config.systemd.package}/bin/systemd-cat -t xsession "$0" "$sessionType" + exec ${config.systemd.package}/bin/systemd-cat -t xsession "$0" "$@" fi ''} @@ -101,6 +72,7 @@ let ${config.systemd.package}/bin/systemctl --user import-environment DISPLAY XAUTHORITY DBUS_SESSION_BUS_ADDRESS # Load X defaults. + # FIXME: Check XDG_SESSION_TYPE against x11 ${xorg.xrdb}/bin/xrdb -merge ${xresourcesXft} if test -e ~/.Xresources; then ${xorg.xrdb}/bin/xrdb -merge ~/.Xresources @@ -132,12 +104,33 @@ let # Allow the user to setup a custom session type. if test -x ~/.xsession; then exec ~/.xsession - else - if test "$sessionType" = "custom"; then - sessionType="" # fall-thru if there is no ~/.xsession - fi fi + if test "$1"; then + # Run the supplied session command. Remove any double quotes with eval. + eval exec "$@" + else + # Fall back to the default window/desktopManager + exec ${cfg.displayManager.session.script} + fi + ''; + + # file provided by services.xserver.displayManager.session.script + xsession = wm: dm: pkgs.writeScript "xsession" + '' + #! ${pkgs.bash}/bin/bash + + # Legacy session script used to construct .desktop files from + # `services.xserver.displayManager.session` entries. Called from + # `sessionWrapper`. + + # Expected parameters: + # $1 = + + + # The first argument of this script is the session type. + sessionType="$1" + if [ "$sessionType" = default ]; then sessionType=""; fi + # The session type is "+", so # extract those (see: # http://wiki.bash-hackers.org/syntax/pe#substring_removal). @@ -186,19 +179,22 @@ let allowSubstitutes = false; } '' - mkdir -p "$out" + mkdir -p "$out/share/xsessions" ${concatMapStrings (n: '' - cat - > "$out/${n}.desktop" << EODESKTOP + cat - > "$out/share/xsessions/${n}.desktop" << EODESKTOP [Desktop Entry] Version=1.0 Type=XSession TryExec=${cfg.displayManager.session.script} Exec=${cfg.displayManager.session.script} "${n}" - X-GDM-BypassXsession=true Name=${n} Comment= EODESKTOP '') names} + + ${concatMapStrings (pkg: '' + ${xorg.lndir}/bin/lndir ${pkg}/share/xsessions $out/share/xsessions + '') cfg.displayManager.extraSessionFilePackages} ''; in @@ -245,6 +241,14 @@ in ''; }; + extraSessionFilePackages = mkOption { + type = types.listOf types.package; + default = []; + description = '' + A list of packages containing xsession files to be passed to the display manager. + ''; + }; + session = mkOption { default = []; example = literalExample @@ -280,6 +284,7 @@ in (filter (w: d.name != "none" || w.name != "none") wm)); desktops = mkDesktops names; script = xsession wm dm; + wrapper = xsessionWrapper; }; }; diff --git a/nixos/modules/services/x11/display-managers/gdm.nix b/nixos/modules/services/x11/display-managers/gdm.nix index 8b08c01ea0d..78dc39f7f62 100644 --- a/nixos/modules/services/x11/display-managers/gdm.nix +++ b/nixos/modules/services/x11/display-managers/gdm.nix @@ -109,7 +109,7 @@ in environment = { GDM_X_SERVER_EXTRA_ARGS = toString (filter (arg: arg != "-terminate") cfg.xserverArgs); - GDM_SESSIONS_DIR = "${cfg.session.desktops}"; + GDM_SESSIONS_DIR = "${cfg.session.desktops}/share/xsessions"; # Find the mouse XCURSOR_PATH = "~/.icons:${pkgs.gnome3.adwaita-icon-theme}/share/icons"; }; @@ -173,6 +173,8 @@ in ${optionalString cfg.gdm.debug "Enable=true"} ''; + environment.etc."gdm/Xsession".source = config.services.xserver.displayManager.session.wrapper; + # GDM LFS PAM modules, adapted somehow to NixOS security.pam.services = { gdm-launch-environment.text = '' diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix index 54d4520a0c8..6be15d8cdf4 100644 --- a/nixos/modules/services/x11/display-managers/lightdm.nix +++ b/nixos/modules/services/x11/display-managers/lightdm.nix @@ -45,11 +45,11 @@ let greeter-user = ${config.users.users.lightdm.name} greeters-directory = ${cfg.greeter.package} ''} - sessions-directory = ${dmcfg.session.desktops} + sessions-directory = ${dmcfg.session.desktops}/share/xsessions [Seat:*] xserver-command = ${xserverWrapper} - session-wrapper = ${dmcfg.session.script} + session-wrapper = ${dmcfg.session.wrapper} ${optionalString cfg.greeter.enable '' greeter-session = ${cfg.greeter.name} ''} @@ -176,21 +176,13 @@ in LightDM auto-login requires services.xserver.displayManager.lightdm.autoLogin.user to be set ''; } - { assertion = cfg.autoLogin.enable -> elem defaultSessionName dmcfg.session.names; + { assertion = cfg.autoLogin.enable -> dmDefault != "none" || wmDefault != "none"; message = '' LightDM auto-login requires that services.xserver.desktopManager.default and services.xserver.windowMananger.default are set to valid values. The current default session: ${defaultSessionName} is not valid. ''; } - { assertion = hasDefaultUserSession -> elem defaultSessionName dmcfg.session.names; - message = '' - services.xserver.desktopManager.default and - services.xserver.windowMananger.default are not set to valid - values. The current default session: ${defaultSessionName} - is not valid. - ''; - } { assertion = !cfg.greeter.enable -> (cfg.autoLogin.enable && cfg.autoLogin.timeout == 0); message = '' LightDM can only run without greeter if automatic login is enabled and the timeout for it diff --git a/nixos/modules/services/x11/display-managers/sddm.nix b/nixos/modules/services/x11/display-managers/sddm.nix index 426b899586f..1b347803932 100644 --- a/nixos/modules/services/x11/display-managers/sddm.nix +++ b/nixos/modules/services/x11/display-managers/sddm.nix @@ -49,8 +49,8 @@ let MinimumVT=${toString (if xcfg.tty != null then xcfg.tty else 7)} ServerPath=${xserverWrapper} XephyrPath=${pkgs.xorg.xorgserver.out}/bin/Xephyr - SessionCommand=${dmcfg.session.script} - SessionDir=${dmcfg.session.desktops} + SessionCommand=${dmcfg.session.wrapper} + SessionDir=${dmcfg.session.desktops}/share/xsessions XauthPath=${pkgs.xorg.xauth}/bin/xauth DisplayCommand=${Xsetup} DisplayStopCommand=${Xstop} diff --git a/nixos/modules/services/x11/display-managers/slim.nix b/nixos/modules/services/x11/display-managers/slim.nix index f645a5c2f07..51ce5f4e243 100644 --- a/nixos/modules/services/x11/display-managers/slim.nix +++ b/nixos/modules/services/x11/display-managers/slim.nix @@ -13,8 +13,8 @@ let xauth_path ${dmcfg.xauthBin} default_xserver ${dmcfg.xserverBin} xserver_arguments ${toString dmcfg.xserverArgs} - sessiondir ${dmcfg.session.desktops} - login_cmd exec ${pkgs.runtimeShell} ${dmcfg.session.script} "%session" + sessiondir ${dmcfg.session.desktops}/share/xsessions + login_cmd exec ${pkgs.runtimeShell} ${dmcfg.session.wrapper} "%session" halt_cmd ${config.systemd.package}/sbin/shutdown -h now reboot_cmd ${config.systemd.package}/sbin/shutdown -r now logfile /dev/stderr diff --git a/nixos/tests/gnome3.nix b/nixos/tests/gnome3.nix index 3f51d04163a..af2404bf530 100644 --- a/nixos/tests/gnome3.nix +++ b/nixos/tests/gnome3.nix @@ -15,6 +15,7 @@ import ./make-test.nix ({ pkgs, ...} : { services.xserver.displayManager.lightdm.autoLogin.enable = true; services.xserver.displayManager.lightdm.autoLogin.user = "alice"; services.xserver.desktopManager.gnome3.enable = true; + services.xserver.desktopManager.default = "gnome"; virtualisation.memorySize = 1024; }; diff --git a/pkgs/desktops/gnome-3/core/gdm/default.nix b/pkgs/desktops/gnome-3/core/gdm/default.nix index 5ceba1a7719..24eff547fe9 100644 --- a/pkgs/desktops/gnome-3/core/gdm/default.nix +++ b/pkgs/desktops/gnome-3/core/gdm/default.nix @@ -21,6 +21,7 @@ stdenv.mkDerivation rec { "--sysconfdir=/etc" "--localstatedir=/var" "--with-plymouth=yes" + "--enable-gdm-xsession" "--with-initial-vt=7" "--with-systemdsystemunitdir=$(out)/etc/systemd/system" ]; diff --git a/pkgs/desktops/gnome-3/core/gnome-session/default.nix b/pkgs/desktops/gnome-3/core/gnome-session/default.nix index 7b407aad506..1882f19bb22 100644 --- a/pkgs/desktops/gnome-3/core/gnome-session/default.nix +++ b/pkgs/desktops/gnome-3/core/gnome-session/default.nix @@ -1,4 +1,4 @@ -{ fetchurl, stdenv, meson, ninja, pkgconfig, gnome3, glib, gtk, gsettings-desktop-schemas +{ fetchurl, stdenv, substituteAll, meson, ninja, pkgconfig, gnome3, glib, gtk, gsettings-desktop-schemas , gnome-desktop, dbus, json-glib, libICE, xmlto, docbook_xsl, docbook_xml_dtd_412 , libxslt, gettext, makeWrapper, systemd, xorg, epoxy }: @@ -11,6 +11,15 @@ stdenv.mkDerivation rec { sha256 = "14nmbirgrp2nm16khbz109saqdlinlbrlhjnbjydpnrlimfgg4xq"; }; + patches = [ + (substituteAll { + src = ./fix-paths.patch; + # FIXME: glib binaries shouldn't be in .dev! + gsettings = "${glib.dev}/bin/gsettings"; + dbusLaunch = "${dbus.lib}/bin/dbus-launch"; + }) + ]; + mesonFlags = [ "-Dsystemd=true" ]; nativeBuildInputs = [ @@ -29,15 +38,13 @@ stdenv.mkDerivation rec { patchShebangs meson_post_install.py ''; - # FIXME: glib binaries shouldn't be in .dev! preFixup = '' for desktopFile in $(grep -rl "Exec=gnome-session" $out/share) do echo "Patching gnome-session path in: $desktopFile" - sed -i "s,^Exec=gnome-session,Exec=$out/bin/gnome-session," $desktopFile + sed -i "s,Exec=gnome-session,Exec=$out/bin/gnome-session," $desktopFile done wrapProgram "$out/bin/gnome-session" \ - --prefix PATH : "${glib.dev}/bin" \ --prefix GI_TYPELIB_PATH : "$GI_TYPELIB_PATH" \ --suffix XDG_DATA_DIRS : "$out/share:$GSETTINGS_SCHEMAS_PATH" \ --suffix XDG_DATA_DIRS : "${gnome3.gnome-shell}/share"\ diff --git a/pkgs/desktops/gnome-3/core/gnome-session/fix-paths.patch b/pkgs/desktops/gnome-3/core/gnome-session/fix-paths.patch new file mode 100644 index 00000000000..3c56fd730e4 --- /dev/null +++ b/pkgs/desktops/gnome-3/core/gnome-session/fix-paths.patch @@ -0,0 +1,22 @@ +--- a/gnome-session/gnome-session.in ++++ b/gnome-session/gnome-session.in +@@ -13,7 +13,7 @@ + fi + fi + +-SETTING=$(gsettings get org.gnome.system.locale region) ++SETTING=$(@gsettings@ get org.gnome.system.locale region) + REGION=${SETTING#\'} + REGION=${REGION%\'} + +--- a/gnome-session/main.c ++++ b/gnome-session/main.c +@@ -203,7 +203,7 @@ + } + new_argv[i + 2] = NULL; + +- if (!execvp ("dbus-launch", new_argv)) { ++ if (!execvp ("@dbusLaunch@", new_argv)) { + g_set_error (error, + G_SPAWN_ERROR, + G_SPAWN_ERROR_FAILED, diff --git a/pkgs/desktops/gnome-3/misc/gpaste/default.nix b/pkgs/desktops/gnome-3/misc/gpaste/default.nix index a0182057873..add6addaec0 100644 --- a/pkgs/desktops/gnome-3/misc/gpaste/default.nix +++ b/pkgs/desktops/gnome-3/misc/gpaste/default.nix @@ -10,6 +10,22 @@ stdenv.mkDerivation rec { sha256 = "1zfx73qpw976hyzp5k569lywsq2b6dbnnzf2cvhjvn3mvkw8pin2"; }; + patches = [ + ./fix-paths.patch + ]; + + # TODO: switch to substituteAll with placeholder + # https://github.com/NixOS/nix/issues/1846 + # https://github.com/NixOS/nixpkgs/pull/37693 + postPatch = '' + substituteInPlace src/gnome-shell/extension.js \ + --subst-var-by typelibPath "$out/lib/girepository-1.0" + substituteInPlace src/gnome-shell/prefs.js \ + --subst-var-by typelibPath "$out/lib/girepository-1.0" + substituteInPlace src/libgpaste/settings/gpaste-settings.c \ + --subst-var-by gschemasCompiled "$out/share/gsettings-schemas/${name}/glib-2.0/schemas" + ''; + nativeBuildInputs = [ autoreconfHook pkgconfig vala wrapGAppsHook ]; buildInputs = [ glib gjs mutter gnome3.adwaita-icon-theme gtk3 gnome3.gnome-control-center dbus diff --git a/pkgs/desktops/gnome-3/misc/gpaste/fix-paths.patch b/pkgs/desktops/gnome-3/misc/gpaste/fix-paths.patch new file mode 100644 index 00000000000..ca6b9a5b22e --- /dev/null +++ b/pkgs/desktops/gnome-3/misc/gpaste/fix-paths.patch @@ -0,0 +1,55 @@ +--- a/src/gnome-shell/extension.js ++++ b/src/gnome-shell/extension.js +@@ -7,6 +7,8 @@ + + const Config = imports.misc.config; + ++imports.gi.GIRepository.Repository.prepend_search_path('@typelibPath@'); ++ + imports.gi.versions.Clutter = Config.LIBMUTTER_API_VERSION; + imports.gi.versions.GLib = '2.0'; + imports.gi.versions.GPaste = '1.0'; +--- a/src/gnome-shell/prefs.js ++++ b/src/gnome-shell/prefs.js +@@ -7,6 +7,8 @@ + + const Gettext = imports.gettext; + ++imports.gi.GIRepository.Repository.prepend_search_path('@typelibPath@'); ++ + const GPaste = imports.gi.GPaste; + + const ExtensionUtils = imports.misc.extensionUtils; +--- a/src/libgpaste/settings/gpaste-settings.c ++++ b/src/libgpaste/settings/gpaste-settings.c +@@ -22,6 +22,8 @@ + + typedef struct + { ++ GSettingsSchemaSource *schema_source; ++ GSettingsSchema *schema; + GSettings *settings; + GSettings *shell_settings; + +@@ -919,6 +921,8 @@ + { + g_signal_handler_disconnect (settings, priv->c_signals[C_CHANGED]); + g_clear_object (&priv->settings); ++ g_settings_schema_unref (priv->schema); ++ g_settings_schema_source_unref (priv->schema_source); + } + + if (shell_settings) +@@ -1000,7 +1004,11 @@ + g_paste_settings_init (GPasteSettings *self) + { + GPasteSettingsPrivate *priv = g_paste_settings_get_instance_private (self); +- GSettings *settings = priv->settings = g_settings_new (G_PASTE_SETTINGS_NAME); ++ ++ // library used by introspection requires schemas but we cannot set XDG_DATA_DIRS for the library ++ GSettingsSchemaSource *schema_source = priv->schema_source = g_settings_schema_source_new_from_directory ("@gschemasCompiled@", NULL, FALSE, NULL); ++ priv->schema = g_settings_schema_source_lookup (schema_source, G_PASTE_SETTINGS_NAME, FALSE); ++ GSettings *settings = priv->settings = g_settings_new_full (priv->schema, NULL, NULL); + + priv->history_name = NULL; + priv->launch_ui = NULL;