Sway

From NixOS Wiki
Revision as of 23:56, 1 January 2022 by imported>Svrana (add i3-ratiosplit info (works for i3 and sway))

Sway is a tiling Wayland compositor and a drop-in replacement for the i3 window manager for X11. It works with your existing i3 configuration and supports most of i3's features, plus a few extras. i3 migration guide

Installation

NixOS

NixOS options for sway

programs.sway = {
  enable = true;
  wrapperFeatures.gtk = true; # so that gtk works properly
  extraPackages = with pkgs; [
    swaylock
    swayidle
    wl-clipboard
    mako # notification daemon
    alacritty # Alacritty is the default terminal in the config
    dmenu # Dmenu is the default in the config but i recommend wofi since its wayland native
  ];
};

Home Manager

Home Manager options for sway

wayland.windowManager.sway = {
  enable = true;
  wrapperFeatures.gtk = true ;
};
home.packages = with pkgs; [
  swaylock
  swayidle
  wl-clipboard
  mako # notification daemon
  alacritty # Alacritty is the default terminal in the config
  dmenu # Dmenu is the default in the config but i recommend wofi since its wayland native
];

Info

Clipboard

For clipboard support

environment.systemPackages = with pkgs; [ wl-clipboard ];

to use wl-clipboard-x11 which is a wrapper to use wl-clipboard as a drop-in replacement to X11 clipboard tools

nixpkgs.overlays = [
  (self: super: {
    wl-clipboard-x11 = super.stdenv.mkDerivation rec {
    pname = "wl-clipboard-x11";
    version = "5";
  
    src = super.fetchFromGitHub {
      owner = "brunelli";
      repo = "wl-clipboard-x11";
      rev = "v${version}";
      sha256 = "1y7jv7rps0sdzmm859wn2l8q4pg2x35smcrm7mbfxn5vrga0bslb";
    };
  
    dontBuild = true;
    dontConfigure = true;
    propagatedBuildInputs = [ super.wl-clipboard ];
    makeFlags = [ "PREFIX=$(out)" ];
    };
  
    xsel = self.wl-clipboard-x11;
    xclip = self.wl-clipboard-x11;
  })
];
Note: This will recompile all packages that have xclip or xsel in their dependencies

Brightness and volume

Brightnessctl has worked better for me than light

/etc/nixos/configuration.nix
environment.systemPackages = with pkgs; [ brightnessctl ];
users.users.yourusername.extraGroups = [ "video" ];
# or
programs.light.enable = true;

environment.systemPackages = with pkgs; [ pactl ];
sway config
# Brightness
bindsym XF86MonBrightnessDown exec "brightnessctl set 2%-"
bindsym XF86MonBrightnessUp exec "brightnessctl set +2%"

# Volume
bindsym XF86AudioRaiseVolume exec 'pactl set-sink-volume @DEFAULT_SINK@ +1%'
bindsym XF86AudioLowerVolume exec 'pactl set-sink-volume @DEFAULT_SINK@ -1%'
bindsym XF86AudioMute exec 'pactl set-sink-mute @DEFAULT_SINK@ toggle'

Polkit

nix generated sway config

${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1

normal sway config

environment.systemPackages = with pkgs; [ polkit_gnome ];
environment.pathsToLink = [ "/libexec" ];
# NixOS
exec /run/current-system/sw/libexec/polkit-gnome-authentication-agent-1
# Home Manager | pathsToLink is not needed
exec ~/.nix-profile/libexec/polkit-gnome-authentication-agent-1


Theming

Gtk

environment.systemPackages = with pkgs; [
  gtk-engine-murrine
  gtk_engines
  gsettings-desktop-schemas
  lxappearance
];

open lxappearance and pick your themes

read GTK3 settings on Wayland

Qt

programs.qt5ct.enable = true;

open qt5ct and pick your theme

Additional packages

  • waybar — Highly customizable Wayland bar for Sway and Wlroots based compositors
https://github.com/Alexays/Waybar || waybar
  • autotiling — Script for sway and i3 to automatically switch the horizontal / vertical window split orientation
https://github.com/nwg-piotr/autotiling || autotiling
  • gammastep — Reduces bluelight and saves your eyes
https://gitlab.com/chinstrap/gammastep || gammastep
  • clipman — Simple clipboard manager for Wayland
https://github.com/yory8/clipman/ || clipman
  • wofi — Launcher/menu program for wlroots based wayland compositors such as sway
https://hg.sr.ht/~scoopta/wofi || wofi
  • flashfocus — Simple focus animations for tiling window managers
https://github.com/fennerm/flashfocus || flashfocus
  • wf-recorder — Screen recorder for wlroots-based compositors such as sway
https://github.com/ammen99/wf-recorder || wf-recorder
  • i3-ratiosplit — Configurable window size on creation
https://github.com/333fred/i3-ratiosplit || i3-ratiosplit

more packages here i3 migration guide


Systemd integration

In an article on the sway wiki [1], a way to integrate Sway with systemd user services is proposed. Starting sway that way has some benefits:

  • Logging for Sway is done the same way it is done for every other user service.
  • Services like Waybar, kanshi, redshift can depend on graphical-session.target and can therefore be started as their own user service, including convenient service management and logging.

Don't forget to additionally start sway-session.targetwith one of the methods described in the sway wiki.

{ config, pkgs, lib, ... }: {

  programs.sway = {
    enable = true;
    extraPackages = with pkgs; [
      swaylock # lockscreen
      swayidle
      xwayland # for legacy apps
      waybar # status bar
      mako # notification daemon
      kanshi # autorandr
    ];
  };

  environment = {
    etc = {
      # Put config files in /etc. Note that you also can put these in ~/.config, but then you can't manage them with NixOS anymore!
      "sway/config".source = ./dotfiles/sway/config;
      "xdg/waybar/config".source = ./dotfiles/waybar/config;
      "xdg/waybar/style.css".source = ./dotfiles/waybar/style.css;
    };
  };

  # Here we but a shell script into path, which lets us start sway.service (after importing the environment of the login shell).
  environment.systemPackages = with pkgs; [
    (
      pkgs.writeTextFile {
        name = "startsway";
        destination = "/bin/startsway";
        executable = true;
        text = ''
          #! ${pkgs.bash}/bin/bash

          # first import environment variables from the login manager
          systemctl --user import-environment
          # then start the service
          exec systemctl --user start sway.service
        '';
      }
    )
  ];

  systemd.user.targets.sway-session = {
    description = "Sway compositor session";
    documentation = [ "man:systemd.special(7)" ];
    bindsTo = [ "graphical-session.target" ];
    wants = [ "graphical-session-pre.target" ];
    after = [ "graphical-session-pre.target" ];
  };

  systemd.user.services.sway = {
    description = "Sway - Wayland window manager";
    documentation = [ "man:sway(5)" ];
    bindsTo = [ "graphical-session.target" ];
    wants = [ "graphical-session-pre.target" ];
    after = [ "graphical-session-pre.target" ];
    # We explicitly unset PATH here, as we want it to be set by
    # systemctl --user import-environment in startsway
    environment.PATH = lib.mkForce null;
    serviceConfig = {
      Type = "simple";
      ExecStart = ''
        ${pkgs.dbus}/bin/dbus-run-session ${pkgs.sway}/bin/sway --debug
      '';
      Restart = "on-failure";
      RestartSec = 1;
      TimeoutStopSec = 10;
    };
  };

  services.redshift = {
    enable = true;
    # Redshift with wayland support isn't present in nixos-19.09 atm. You have to cherry-pick the commit from https://github.com/NixOS/nixpkgs/pull/68285 to do that.
    package = pkgs.redshift-wlr;
  };

  programs.waybar.enable = true;

  systemd.user.services.kanshi = {
    description = "Kanshi output autoconfig ";
    wantedBy = [ "graphical-session.target" ];
    partOf = [ "graphical-session.target" ];
    serviceConfig = {
      # kanshi doesn't have an option to specifiy config file yet, so it looks
      # at .config/kanshi/config
      ExecStart = ''
        ${pkgs.kanshi}/bin/kanshi
      '';
      RestartSec = 5;
      Restart = "always";
    };
  };

}

Note: swayidle will fail cryptically if it cannot find sh in PATH, so you must provide this if you create a service file for it. An example is below:

  systemd.user.services.swayidle = {
    description = "Idle Manager for Wayland";
    documentation = [ "man:swayidle(1)" ];
    wantedBy = [ "sway-session.target" ];
    partOf = [ "graphical-session.target" ];
    path = [ pkgs.bash ];
    serviceConfig = {
      ExecStart = '' ${pkgs.swayidle}/bin/swayidle -w -d \
        timeout 300 '${pkgs.sway}/bin/swaymsg "output * dpms off"' \
        resume '${pkgs.sway}/bin/swaymsg "output * dpms on"'
      '';
    };
  };