1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8let
9 cfg = config.programs.sway;
10
11 wayland-lib = import ./lib.nix { inherit lib; };
12in
13{
14 options.programs.sway = {
15 enable = lib.mkEnableOption ''
16 Sway, the i3-compatible tiling Wayland compositor. You can manually launch
17 Sway by executing "exec sway" on a TTY. Copy /etc/sway/config to
18 ~/.config/sway/config to modify the default configuration. See
19 <https://github.com/swaywm/sway/wiki> and
20 "man 5 sway" for more information'';
21
22 package =
23 lib.mkPackageOption pkgs "sway" {
24 nullable = true;
25 extraDescription = ''
26 If the package is not overridable with `extraSessionCommands`, `extraOptions`,
27 `withBaseWrapper`, `withGtkWrapper`, `enableXWayland` and `isNixOS`,
28 then the module options {option}`wrapperFeatures`, {option}`extraSessionCommands`,
29 {option}`extraOptions` and {option}`xwayland` will have no effect.
30
31 Set to `null` to not add any Sway package to your path.
32 This should be done if you want to use the Home Manager Sway module to install Sway.
33 '';
34 }
35 // {
36 apply =
37 p:
38 if p == null then
39 null
40 else
41 wayland-lib.genFinalPackage p {
42 extraSessionCommands = cfg.extraSessionCommands;
43 extraOptions = cfg.extraOptions;
44 withBaseWrapper = cfg.wrapperFeatures.base;
45 withGtkWrapper = cfg.wrapperFeatures.gtk;
46 enableXWayland = cfg.xwayland.enable;
47 isNixOS = true;
48 };
49 };
50
51 wrapperFeatures = {
52 base =
53 lib.mkEnableOption ''
54 the base wrapper to execute extra session commands and prepend a
55 dbus-run-session to the sway command''
56 // {
57 default = true;
58 };
59 gtk = lib.mkEnableOption ''
60 the wrapGAppsHook wrapper to execute sway with required environment
61 variables for GTK applications'';
62 };
63
64 extraSessionCommands = lib.mkOption {
65 type = lib.types.lines;
66 default = "";
67 example = ''
68 # SDL:
69 export SDL_VIDEODRIVER=wayland
70 # QT (needs qt5.qtwayland in systemPackages):
71 export QT_QPA_PLATFORM=wayland-egl
72 export QT_WAYLAND_DISABLE_WINDOWDECORATION="1"
73 # Fix for some Java AWT applications (e.g. Android Studio),
74 # use this if they aren't displayed properly:
75 export _JAVA_AWT_WM_NONREPARENTING=1
76 '';
77 description = ''
78 Shell commands executed just before Sway is started. See
79 <https://github.com/swaywm/sway/wiki/Running-programs-natively-under-wayland>
80 and <https://github.com/swaywm/wlroots/blob/master/docs/env_vars.md>
81 for some useful environment variables.
82 '';
83 };
84
85 extraOptions = lib.mkOption {
86 type = lib.types.listOf lib.types.str;
87 default = [ ];
88 example = [
89 "--verbose"
90 "--debug"
91 "--unsupported-gpu"
92 ];
93 description = ''
94 Command line arguments passed to launch Sway. Please DO NOT report
95 issues if you use an unsupported GPU (proprietary drivers).
96 '';
97 };
98
99 xwayland.enable = lib.mkEnableOption "XWayland" // {
100 default = true;
101 };
102
103 extraPackages = lib.mkOption {
104 type = with lib.types; listOf package;
105 # Packages used in default config
106 default = with pkgs; [
107 brightnessctl
108 foot
109 grim
110 pulseaudio
111 swayidle
112 swaylock
113 wmenu
114 ];
115 defaultText = lib.literalExpression ''
116 with pkgs; [ brightnessctl foot grim pulseaudio swayidle swaylock wmenu ];
117 '';
118 example = lib.literalExpression ''
119 with pkgs; [ i3status i3status-rust termite rofi light ]
120 '';
121 description = ''
122 Extra packages to be installed system wide. See
123 <https://github.com/swaywm/sway/wiki/Useful-add-ons-for-sway> and
124 <https://github.com/swaywm/sway/wiki/i3-Migration-Guide#common-x11-apps-used-on-i3-with-wayland-alternatives>
125 for a list of useful software.
126 '';
127 };
128 };
129
130 config = lib.mkIf cfg.enable (
131 lib.mkMerge [
132 {
133 assertions = [
134 {
135 assertion = cfg.extraSessionCommands != "" -> cfg.wrapperFeatures.base;
136 message = ''
137 The extraSessionCommands for Sway will not be run if wrapperFeatures.base is disabled.
138 '';
139 }
140 ];
141
142 warnings =
143 lib.mkIf
144 (
145 (lib.elem "nvidia" config.services.xserver.videoDrivers)
146 && (lib.versionOlder (lib.versions.major (lib.getVersion config.hardware.nvidia.package)) "551")
147 )
148 [
149 "Using Sway with Nvidia driver version <= 550 may result in a broken system. Configure hardware.nvidia.package to use a newer version."
150 ];
151
152 environment = {
153 systemPackages = lib.optional (cfg.package != null) cfg.package ++ cfg.extraPackages;
154
155 # Needed for the default wallpaper:
156 pathsToLink = lib.optional (cfg.package != null) "/share/backgrounds/sway";
157
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 # enable systemd-integration
164 exec "systemctl --user import-environment {,WAYLAND_}DISPLAY SWAYSOCK; systemctl --user start sway-session.target"
165 exec swaymsg -t subscribe '["shutdown"]' && systemctl --user stop sway-session.target
166 '';
167 }
168 // lib.optionalAttrs (cfg.package != null) {
169 "sway/config".source = lib.mkOptionDefault "${cfg.package}/etc/sway/config";
170 };
171 };
172
173 systemd.user.targets.sway-session = {
174 description = "sway compositor session";
175 documentation = [ "man:systemd.special(7)" ];
176 bindsTo = [ "graphical-session.target" ];
177 wants = [ "graphical-session-pre.target" ];
178 after = [ "graphical-session-pre.target" ];
179 };
180
181 # To make a Sway session available if a display manager like SDDM is enabled:
182 services.displayManager.sessionPackages = lib.optional (cfg.package != null) cfg.package;
183
184 # https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050913
185 # https://github.com/emersion/xdg-desktop-portal-wlr/blob/master/contrib/wlroots-portals.conf
186 # https://github.com/emersion/xdg-desktop-portal-wlr/pull/315
187 xdg.portal.config.sway = {
188 # Use xdg-desktop-portal-gtk for every portal interface...
189 default = [ "gtk" ];
190 # ... except for the ScreenCast, Screenshot and Secret
191 "org.freedesktop.impl.portal.ScreenCast" = "wlr";
192 "org.freedesktop.impl.portal.Screenshot" = "wlr";
193 # ignore inhibit bc gtk portal always returns as success,
194 # despite sway/the wlr portal not having an implementation,
195 # stopping firefox from using wayland idle-inhibit
196 "org.freedesktop.impl.portal.Inhibit" = "none";
197 };
198 }
199
200 (import ./wayland-session.nix {
201 inherit lib pkgs;
202 enableXWayland = cfg.xwayland.enable;
203 })
204 ]
205 );
206
207 meta.maintainers = with lib.maintainers; [ ];
208}