nix-community / home-manager

Manage a user environment using Nix [maintainer=@rycee]
https://nix-community.github.io/home-manager/
MIT License
6.4k stars 1.71k forks source link

Add configuration for GNOME Shell autostart (aka startup applications) #3447

Open utybo opened 1 year ago

utybo commented 1 year ago

Description

GNOME Shell supports automatically starting applications when a user logs in.

GNOME Tweaks provides a way to configure this. Under the hood[^1], this is done by adding .desktop files to the ~/.config/autostart/ directory. I am not sure of whether these are strictly the same desktop files as the ones provided in Nix packages, but they don't seem to have anything special.

I don't think Home Manager has support for this atm (other than doing it manually using home.file). It would be very nice to have something like this:

# ~/.config/nixpkgs/home.nix
{
  # Not sure about the naming, maybe gnome, services.gnome or program.gnome
  gnome.autostart = [ pkgs.discord pkgs.slack ];
}

[^1]: Implemented by this class

utybo commented 1 year ago

Here's an example of how this can be done in the mean time:

let
  autostartPrograms = [ pkgs.discord pkgs.slack ];
in
{
  home.file = builtins.listToAttrs (map
    (pkg:
      {
        name = ".config/autostart/" + pkg.pname + ".desktop";
        value =
          if pkg ? desktopItem then {
            # Application has a desktopItem entry. 
            # Assume that it was made with makeDesktopEntry, which exposes a
            # text attribute with the contents of the .desktop file
            text = pkg.desktopItem.text;
          } else {
            # Application does *not* have a desktopItem entry. Try to find a
            # matching .desktop name in /share/apaplications
            source = (pkg + "/share/applications/" + pkg.pname + ".desktop");
          };
      })
    autostartPrograms);
}

This is a pretty dirty way of doing it, but it works well enough for my use case.

stale[bot] commented 1 year ago

Thank you for your contribution! I marked this issue as stale due to inactivity. Please be considerate of people watching this issue and receiving notifications before commenting 'I have this issue too'. We welcome additional information that will help resolve this issue. Please read the relevant sections below before commenting.

If you are the original author of the issue

* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

If you are not the original author of the issue

* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

Memorandum on closing issues

Don't be afraid to manually close an issue, even if it holds valuable information. Closed issues stay in the system for people to search, read, cross-reference, or even reopen – nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.

nixos-discourse commented 8 months ago

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/launching-program-at-startup-pnmixer-alsa-system-tray-mixer/13504/3

ahydronous commented 6 months ago

Not stale

Silveere commented 6 months ago

It's worth noting that this isn't a GNOME exclusive feature, and is actually a freedesktop.org specification, so the option should be named accordingly. Maybe xdg.autostart?

Autoradiowecker commented 4 months ago

Here's an example of how this can be done in the mean time:

let
  autostartPrograms = [ pkgs.discord pkgs.slack ];
in
{
  home.file = builtins.listToAttrs (map
    (pkg:
      {
        name = ".config/autostart/" + pkg.pname + ".desktop";
        value =
          if pkg ? desktopItem then {
            # Application has a desktopItem entry. 
            # Assume that it was made with makeDesktopEntry, which exposes a
            # text attribute with the contents of the .desktop file
            text = pkg.desktopItem.text;
          } else {
            # Application does *not* have a desktopItem entry. Try to find a
            # matching .desktop name in /share/apaplications
            source = (pkg + "/share/applications/" + pkg.pname + ".desktop");
          };
      })
    autostartPrograms);
}

This is a pretty dirty way of doing it, but it works well enough for my use case.

How would you go about launching the applications on a different desktop?

stale[bot] commented 1 month ago

Thank you for your contribution! I marked this issue as stale due to inactivity. Please be considerate of people watching this issue and receiving notifications before commenting 'I have this issue too'. We welcome additional information that will help resolve this issue. Please read the relevant sections below before commenting.

If you are the original author of the issue

* If this is resolved, please consider closing it so that the maintainers know not to focus on this. * If this might still be an issue, but you are not interested in promoting its resolution, please consider closing it while encouraging others to take over and reopen an issue if they care enough. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

If you are not the original author of the issue

* If you are also experiencing this issue, please add details of your situation to help with the debugging process. * If you know how to solve the issue, please consider submitting a Pull Request that addresses this issue.

Memorandum on closing issues

Don't be afraid to manually close an issue, even if it holds valuable information. Closed issues stay in the system for people to search, read, cross-reference, or even reopen – nothing is lost! Closing obsolete issues is an important way to help maintainers focus their time and effort.

L1Z3 commented 2 weeks ago

Here's an example of how this can be done in the mean time:

...

This is a pretty dirty way of doing it, but it works well enough for my use case.

I just threw together a modified version of this that catches some extra cases (e.g. telegram-desktop package, whose desktop file is "org,telegram.desktop.desktop"):

let autostartPrograms = [ pkgs.discord pkgs.slack ];
in {
  home.file = builtins.listToAttrs (map
    (pkg: {
      name = ".config/autostart/" + pkg.pname + ".desktop";
      value =
        if pkg ? desktopItem
        then {
          # Application has a desktopItem entry.
          # Assume that it was made with makeDesktopEntry, which exposes a
          # text attribute with the contents of the .desktop file
          text = pkg.desktopItem.text;
        }
        else {
          # Application does *not* have a desktopItem entry. Try to find a
          # matching .desktop name in /share/applications
          source = with builtins; let
            appsPath = "${pkg}/share/applications";
            # function to filter out subdirs of /share/applications
            filterFiles = dirContents: lib.attrsets.filterAttrs (_: fileType: elem fileType ["regular" "symlink"]) dirContents;
          in (
            # if there's a desktop file by the app's pname, use that
            if (pathExists "${appsPath}/${pkg.pname}.desktop")
            then "${appsPath}/${pkg.pname}.desktop"
            # if there's not, find the first desktop file in the app's directory and assume that's good enough
            else
              (
                if pathExists "${appsPath}"
                then "${appsPath}/${head (attrNames (filterFiles (readDir "${appsPath}")))}"
                else throw "no desktop file for app ${pkg.pname}"
              )
          );
        };
    })
    autostartPrograms);