1{ config, pkgs, lib, ... }:
2
3let
4 cfg = config.programs.sway;
5
6 wrapperOptions = lib.types.submodule {
7 options =
8 let
9 mkWrapperFeature = default: description: lib.mkOption {
10 type = lib.types.bool;
11 inherit default;
12 example = !default;
13 description = "Whether to make use of the ${description}";
14 };
15 in {
16 base = mkWrapperFeature true ''
17 base wrapper to execute extra session commands and prepend a
18 dbus-run-session to the sway command.
19 '';
20 gtk = mkWrapperFeature false ''
21 wrapGAppsHook wrapper to execute sway with required environment
22 variables for GTK applications.
23 '';
24 };
25 };
26
27 genFinalPackage = pkg:
28 let
29 expectedArgs = lib.naturalSort [
30 "extraSessionCommands"
31 "extraOptions"
32 "withBaseWrapper"
33 "withGtkWrapper"
34 "isNixOS"
35 ];
36 existedArgs = with lib;
37 naturalSort
38 (intersectLists expectedArgs (attrNames (functionArgs pkg.override)));
39 in if existedArgs != expectedArgs then
40 pkg
41 else
42 pkg.override {
43 extraSessionCommands = cfg.extraSessionCommands;
44 extraOptions = cfg.extraOptions;
45 withBaseWrapper = cfg.wrapperFeatures.base;
46 withGtkWrapper = cfg.wrapperFeatures.gtk;
47 isNixOS = true;
48 };
49in {
50 options.programs.sway = {
51 enable = lib.mkEnableOption ''
52 Sway, the i3-compatible tiling Wayland compositor. You can manually launch
53 Sway by executing "exec sway" on a TTY. Copy /etc/sway/config to
54 ~/.config/sway/config to modify the default configuration. See
55 <https://github.com/swaywm/sway/wiki> and
56 "man 5 sway" for more information'';
57
58 package = lib.mkOption {
59 type = with lib.types; nullOr package;
60 default = pkgs.sway;
61 apply = p: if p == null then null else genFinalPackage p;
62 defaultText = lib.literalExpression "pkgs.sway";
63 description = ''
64 Sway package to use. If the package does not contain the override arguments
65 `extraSessionCommands`, `extraOptions`, `withBaseWrapper`, `withGtkWrapper`,
66 `isNixOS`, then the module options {option}`wrapperFeatures`,
67 {option}`wrapperFeatures` and {option}`wrapperFeatures` will have no effect.
68 Set to `null` to not add any Sway package to your path. This should be done if
69 you want to use the Home Manager Sway module to install Sway.
70 '';
71 };
72
73 wrapperFeatures = lib.mkOption {
74 type = wrapperOptions;
75 default = { };
76 example = { gtk = true; };
77 description = ''
78 Attribute set of features to enable in the wrapper.
79 '';
80 };
81
82 extraSessionCommands = lib.mkOption {
83 type = lib.types.lines;
84 default = "";
85 example = ''
86 # SDL:
87 export SDL_VIDEODRIVER=wayland
88 # QT (needs qt5.qtwayland in systemPackages):
89 export QT_QPA_PLATFORM=wayland-egl
90 export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
91 # Fix for some Java AWT applications (e.g. Android Studio),
92 # use this if they aren't displayed properly:
93 export _JAVA_AWT_WM_NONREPARENTING=1
94 '';
95 description = ''
96 Shell commands executed just before Sway is started. See
97 <https://github.com/swaywm/sway/wiki/Running-programs-natively-under-wayland>
98 and <https://github.com/swaywm/wlroots/blob/master/docs/env_vars.md>
99 for some useful environment variables.
100 '';
101 };
102
103 extraOptions = lib.mkOption {
104 type = lib.types.listOf lib.types.str;
105 default = [];
106 example = [
107 "--verbose"
108 "--debug"
109 "--unsupported-gpu"
110 ];
111 description = ''
112 Command line arguments passed to launch Sway. Please DO NOT report
113 issues if you use an unsupported GPU (proprietary drivers).
114 '';
115 };
116
117 extraPackages = lib.mkOption {
118 type = with lib.types; listOf package;
119 default = with pkgs; [
120 swaylock swayidle foot dmenu wmenu
121 ];
122 defaultText = lib.literalExpression ''
123 with pkgs; [ swaylock swayidle foot dmenu wmenu ];
124 '';
125 example = lib.literalExpression ''
126 with pkgs; [
127 i3status i3status-rust
128 termite rofi light
129 ]
130 '';
131 description = ''
132 Extra packages to be installed system wide. See
133 <https://github.com/swaywm/sway/wiki/Useful-add-ons-for-sway> and
134 <https://github.com/swaywm/sway/wiki/i3-Migration-Guide#common-x11-apps-used-on-i3-with-wayland-alternatives>
135 for a list of useful software.
136 '';
137 };
138
139 };
140
141 config = lib.mkIf cfg.enable
142 (lib.mkMerge [
143 {
144 assertions = [
145 {
146 assertion = cfg.extraSessionCommands != "" -> cfg.wrapperFeatures.base;
147 message = ''
148 The extraSessionCommands for Sway will not be run if
149 wrapperFeatures.base is disabled.
150 '';
151 }
152 ];
153
154 environment = {
155 systemPackages = lib.optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
156 # Needed for the default wallpaper:
157 pathsToLink = lib.optionals (cfg.package != null) [ "/share/backgrounds/sway" ];
158 etc = {
159 "sway/config.d/nixos.conf".source = pkgs.writeText "nixos.conf" ''
160 # Import the most important environment variables into the D-Bus and systemd
161 # user environments (e.g. required for screen sharing and Pinentry prompts):
162 exec dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY SWAYSOCK XDG_CURRENT_DESKTOP
163 '';
164 } // lib.optionalAttrs (cfg.package != null) {
165 "sway/config".source = lib.mkOptionDefault "${cfg.package}/etc/sway/config";
166 };
167 };
168
169 programs.gnupg.agent.pinentryPackage = lib.mkDefault pkgs.pinentry-gnome3;
170
171 # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
172 xdg.portal.config.sway.default = lib.mkDefault [ "wlr" "gtk" ];
173
174 # To make a Sway session available if a display manager like SDDM is enabled:
175 services.displayManager.sessionPackages = lib.optionals (cfg.package != null) [ cfg.package ]; }
176 (import ./wayland-session.nix { inherit lib pkgs; })
177 ]);
178
179 meta.maintainers = with lib.maintainers; [ primeos colemickens ];
180}