From 50d8125b1b0c74fc1fd6d2aa79c337c227cf1a3c Mon Sep 17 00:00:00 2001 From: Gabriel Arazas Date: Tue, 9 Jul 2024 16:03:30 +0800 Subject: [PATCH] wrapper-manager-fds/modules: init setting XDG desktop entries --- .../modules/wrapper-manager/base.nix | 1 + .../modules/wrapper-manager/build.nix | 8 +- .../modules/wrapper-manager/default.nix | 1 + .../wrapper-manager/xdg-desktop-entries.nix | 137 ++++++++++++++++++ .../tests/lib/env/wrapper-fastfetch.nix | 1 + 5 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 subprojects/wrapper-manager-fds/modules/wrapper-manager/xdg-desktop-entries.nix diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/base.nix b/subprojects/wrapper-manager-fds/modules/wrapper-manager/base.nix index 1d8e6b34..eeb92182 100644 --- a/subprojects/wrapper-manager-fds/modules/wrapper-manager/base.nix +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/base.nix @@ -6,6 +6,7 @@ type = with lib.types; attrsOf (submoduleWith { modules = [ ./shared/wrappers.nix ]; specialArgs.envConfig = config; + shorthandOnlyDefinesConfig = true; }); description = '' A set of wrappers to be included in the resulting derivation from diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/build.nix b/subprojects/wrapper-manager-fds/modules/wrapper-manager/build.nix index 6ac94901..ff2827eb 100644 --- a/subprojects/wrapper-manager-fds/modules/wrapper-manager/build.nix +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/build.nix @@ -36,6 +36,9 @@ lib.concatMapStrings (v: '' makeWrapper "${v.arg0}" "${builtins.placeholder "out"}/bin/${v.executableName}" ${lib.concatStringsSep " " v.makeWrapperArgs} '') wrappers; + + mkDesktopEntries = desktopEntries: + builtins.map (entry: pkgs.makeDesktopItem entry) desktopEntries; in pkgs.symlinkJoin { name = "wrapper-manager-fds-wrapped-package"; @@ -43,11 +46,14 @@ nativeBuildInputs = if config.build.isBinary then [ pkgs.makeBinaryWrapper ] - else [ pkgs.makeWrapper ]; + else [ pkgs.makeWrapper ] + ++ lib.optionals (pkgs.stdenv.isLinux && config.xdg.desktopEntries != { }) [ pkgs.copyDesktopItems ]; postBuild = '' ${config.build.extraSetup} ${mkWrapBuild (lib.attrValues config.wrappers)} ''; + desktopItems = + mkDesktopEntries (lib.attrValues config.xdg.desktopEntries); }; }; }; diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/default.nix b/subprojects/wrapper-manager-fds/modules/wrapper-manager/default.nix index f43ff1bf..9dedd0e5 100644 --- a/subprojects/wrapper-manager-fds/modules/wrapper-manager/default.nix +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/default.nix @@ -1,6 +1,7 @@ { imports = [ ./base.nix + ./xdg-desktop-entries.nix ./build.nix ./extra-args.nix ]; diff --git a/subprojects/wrapper-manager-fds/modules/wrapper-manager/xdg-desktop-entries.nix b/subprojects/wrapper-manager-fds/modules/wrapper-manager/xdg-desktop-entries.nix new file mode 100644 index 00000000..486d542c --- /dev/null +++ b/subprojects/wrapper-manager-fds/modules/wrapper-manager/xdg-desktop-entries.nix @@ -0,0 +1,137 @@ +{ config, lib, pkgs, ... }: + +let + # We're only setting up options for the most common keys typically used to + # set up a desktop entry. Everything else is acceptable under a freeform + # module anyways. + xdgDesktopEntry = { name, lib, pkgs, ... }: { + freeformType = with lib.types; attrsOf anything; + + options = { + name = lib.mkOption { + type = lib.types.nonEmptyStr; + description = "The name of the desktop file."; + default = name; + example = "firefox"; + }; + + desktopName = lib.mkOption { + type = lib.types.nonEmptyStr; + description = "Specific name of the application"; + default = name; + example = "Firefox"; + }; + + exec = lib.mkOption { + type = with lib.types; nullOr nonEmptyStr; + description = "Program with execute along with its arguments."; + default = null; + example = "firefox %U"; + }; + + genericName = lib.mkOption { + type = with lib.types; nullOr nonEmptyStr; + description = "Generic name of the application"; + default = null; + example = "Web browser"; + }; + + terminal = lib.mkOption { + type = lib.types.bool; + description = "Whether the program runs in a terminal window."; + default = false; + example = true; + }; + + categories = lib.mkOption { + type = with lib.types; listOf nonEmptyStr; + description = "List of categories should the application be shown in a menu."; + default = [ ]; + example = [ "Applications" "Network" ]; + }; + + mimeTypes = lib.mkOption { + type = with lib.types; listOf nonEmptyStr; + description = "The MIME types supported by the application."; + default = [ ]; + example = [ "text/html" "text/xml" ]; + }; + }; + }; +in +{ + options.xdg.desktopEntries = lib.mkOption { + type = with lib.types; attrsOf (submodule xdgDesktopEntry); + description = '' + A set of desktop entries to be exported along with the wrapped package. + ''; + default = { }; + example = lib.literalExpression '' + { + firefox = { + name = "Firefox"; + genericName = "Web browser"; + exec = "firefox %u"; + terminal = false; + categories = [ "Application" "Network" "WebBrowser" ]; + mimeTypes = [ "text/html" "text/xml" ]; + extraConfig."X-GNOME-Autostart-Phase" = "WindowManager"; + keywords = [ "Web" "Browser" ]; + startupNotify = false; + startupWMClass = "MyOwnClass"; + }; + } + ''; + }; + + options.wrappers = lib.mkOption { + type = + let + xdgDesktopEntryWrapperSubmodule = { name, config, lib, ... }: { + options.xdg.desktopEntry = { + enable = + lib.mkEnableOption "automatic creation of a desktop entry for the wrapper"; + settings = lib.mkOption { + type = lib.types.submodule xdgDesktopEntry; + description = '' + Settings to be passed to the `makeDesktopItem` builder. + ''; + example = lib.literalExpression '' + { + mimeTypes = [ "text/html" "text/xml" ]; + categories = [ "Applications" "Network" ]; + } + ''; + }; + }; + + config.xdg.desktopEntry.settings = lib.mkIf config.xdg.desktopEntry.enable { + name = lib.mkDefault name; + desktopName = lib.mkDefault name; + type = lib.mkDefault "Application"; + + # Welp, we could set it to the absolute location of the wrapper + # executable in the final output but it's a big pain the ass to do + # so but we're opting to the executable name instead. This current + # way of doing it is simply the next (and the simplest) best thing. + # We just have to make sure the build step for the wrapper script + # is consistent throughout the entire module environment. + # + # Besides, if the user wants a desktop entry along with the wrapper + # script, it will be included alongside in whatever environment + # they are using it for anyways. + exec = config.executableName; + }; + }; + in + with lib.types; attrsOf (submodule xdgDesktopEntryWrapperSubmodule); + }; + + config = { + xdg.desktopEntries = + let + wrappersWithDesktopEntries = lib.filterAttrs (_: v: v.xdg.desktopEntry.enable) config.wrappers; + in + lib.mapAttrs (_: v: v.xdg.desktopEntry.settings) wrappersWithDesktopEntries; + }; +} diff --git a/subprojects/wrapper-manager-fds/tests/lib/env/wrapper-fastfetch.nix b/subprojects/wrapper-manager-fds/tests/lib/env/wrapper-fastfetch.nix index d967c930..b9e71a06 100644 --- a/subprojects/wrapper-manager-fds/tests/lib/env/wrapper-fastfetch.nix +++ b/subprojects/wrapper-manager-fds/tests/lib/env/wrapper-fastfetch.nix @@ -5,5 +5,6 @@ arg0 = lib.getExe' pkgs.fastfetch "fastfetch"; appendArgs = [ "--logo" "Guix" ]; env.NO_COLOR = "1"; + xdg.desktopEntry.enable = true; }; }