Sway: Difference between revisions

From NixOS Wiki
imported>O8opi
m pactl is not in the nixpkgs, enable pulseaudio instead
imported>Danielbarter
No edit summary
Line 1: Line 1:
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.  
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.  
[https://github.com/swaywm/sway/wiki/i3-Migration-Guide i3 migration guide]
[https://github.com/swaywm/sway/wiki/i3-Migration-Guide i3 migration guide]


== Installation ==
== Installation ==


=== NixOS ===
Here is a minimal configuration where everything you would expect (like screen sharing and gtk themes) work:
[https://search.nixos.org/options?query=sway NixOS options for sway]
<syntaxhighlight lang="nix">
{ config, pkgs, lib, ... }:
 
let
  # bash script to let dbus know about important env variables and
  # propogate them to relevent services run at the end of sway config
  # see
  # https://github.com/emersion/xdg-desktop-portal-wlr/wiki/"It-doesn't-work"-Troubleshooting-Checklist
  # note: this is pretty much the same as  /etc/sway/config.d/nixos.conf but also restarts 
  # some user services to make sure they have the correct environment variables
  dbus-sway-environment = pkgs.writeTextFile {
    name = "dbus-sway-environment";
    destination = "/bin/dbus-sway-environment";
    executable = true;
 
    text = ''
  dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway
  systemctl --user stop pipewire pipewire-media-session xdg-desktop-portal xdg-desktop-portal-wlr
  systemctl --user start pipewire pipewire-media-session xdg-desktop-portal xdg-desktop-portal-wlr
      '';
  };
 
  # currently, there is some friction between sway and gtk:
  # https://github.com/swaywm/sway/wiki/GTK-3-settings-on-Wayland
  # the suggested way to set gtk settings is with gsettings
  # for gsettings to work, we need to tell it where the schemas are
  # using the XDG_DATA_DIR environment variable
  # run at the end of sway config
  configure-gtk = pkgs.writeTextFile {
      name = "configure-gtk";
      destination = "/bin/configure-gtk";
      executable = true;
      text = let
        schema = pkgs.gsettings-desktop-schemas;
        datadir = "${schema}/share/gsettings-schemas/${schema.name}";
      in ''
        export XDG_DATA_DIRS=${datadir}:$XDG_DATA_DIRS
        gnome_schema=org.gnome.desktop.interface
        gsettings set $gnome_schema gtk-theme 'Dracula'
        '';
  };


<syntaxhighlight lang="nix">
 
programs.sway = {
in
   enable = true;
{
  wrapperFeatures.gtk = true; # so that gtk works properly
   environment.systemPackages = with pkgs; [
  extraPackages = with pkgs; [
    alacritty # gpu accelerated terminal
    sway
    dbus-sway-environment
    configure-gtk
    wayland
    glib # gsettings
    dracula-theme # gtk theme
    gnome3.adwaita-icon-theme  # default gnome cursors
     swaylock
     swaylock
     swayidle
     swayidle
     wl-clipboard
    grim # screenshot functionality
    mako # notification daemon
    slurp # screenshot functionality
     alacritty # Alacritty is the default terminal in the config
     wl-clipboard # wl-copy and wl-paste for copy/paste from stdin / stdout
     dmenu # Dmenu is the default in the config but i recommend wofi since its wayland native
     bemenu # wayland clone of dmenu
     mako # notification system developed by swaywm maintainer
   ];
   ];
};


  services.pipewire = {
    enable = true;
    alsa.enable = true;
    pulse.enable = true;
  };
  # xdg-desktop-portal works by exposing a series of D-Bus interfaces
  # known as portals under a well-known name
  # (org.freedesktop.portal.Desktop) and object path
  # (/org/freedesktop/portal/desktop).
  # The portal interfaces include APIs for file access, opening URIs,
  # printing and others.
  services.dbus.enable = true;
  xdg.portal = {
    enable = true;
    wlr.enable = true;
    # gtk portal needed to make gtk apps happy
    extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
    gtkUsePortal = true;
  };
  # enable sway window manager
  programs.sway = {
    enable = true;
    wrapperFeatures.gtk = true;
  };
</syntaxhighlight>
</syntaxhighlight>


=== Home Manager ===
and here are the relevent things you should add to your sway config:
[https://rycee.gitlab.io/home-manager/options.html#opt-wayland.windowManager.sway.enable Home Manager options for sway]


<syntaxhighlight lang="nix">
{{file|sway config|bash|
wayland.windowManager.sway = {
 
  enable = true;
set $menu bemenu-run
  wrapperFeatures.gtk = true ;
 
};
# screenshots
home.packages = with pkgs; [
bindsym $mod+c exec grim  -g "$(slurp)" /tmp/$(date +'%H:%M:%S.png')
  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
];
</syntaxhighlight>


== Info ==


=== Clipboard ===
exec dbus-sway-environment
exec configure-gtk


For clipboard support
}}
<syntaxhighlight lang="nix">
environment.systemPackages = with pkgs; [ wl-clipboard ];
</syntaxhighlight>


to use [https://github.com/brunelli/wl-clipboard-x11/ wl-clipboard-x11] which is a wrapper to use wl-clipboard as a drop-in replacement to X11 clipboard tools


<syntaxhighlight lang="nix">
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;
  })
];
</syntaxhighlight>
{{Note|This will recompile all packages that have xclip or xsel in their dependencies|warn}}


=== Brightness and volume ===
=== Brightness and volume ===


Brightnessctl has worked better for me than light
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
environment.systemPackages = with pkgs; [ brightnessctl ];
users.users.yourusername.extraGroups = [ "video" ];
users.users.yourusername.extraGroups = [ "video" ];
# or
# or
Line 94: Line 128:


# Brightness
# Brightness
bindsym XF86MonBrightnessDown exec "brightnessctl set 2%-"
bindsym XF86MonBrightnessDown exec light -U 10
bindsym XF86MonBrightnessUp exec "brightnessctl set +2%"
bindsym XF86MonBrightnessUp exec light -A 10


# Volume
# Volume
Line 103: Line 137:
}}
}}


=== Autostart Sway ===
It is possible to use [[greetd]], a minimal login manager, to autostart Sway. In this example, <code>myuser</code> needs to be replaced with the username which should execute Sway:
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
services.greetd = {
  enable = true;
  settings = rec {
    initial_session = {
      command = "${pkgs.sway}/bin/sway";
      user = "myuser";
    };
    default_session = initial_session;
  };
};
</nowiki>}}
Note that this approach starts Sway without asking for a user password. See [[greetd]] for alternative configuration examples.
Alternatively, using <code>loginShellInit</code> Sway will automatically get started after user login. Use <code>getty</code> if you also want to skip the login and automatically get into <code>tty1</code> with <code>myuser</code>:
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
services.getty.autologinUser = "myuser";
environment.loginShellInit = ''
  if [ -z $DISPLAY ] && [ "$(tty)" = "/dev/tty1" ]; then
    exec sway
  fi
'';
</nowiki>}}
=== Polkit ===
nix generated sway config
<syntaxhighlight lang="nix">
${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1
</syntaxhighlight>
normal sway config
<syntaxhighlight lang="nix">
environment.systemPackages = with pkgs; [ polkit_gnome ];
environment.pathsToLink = [ "/libexec" ];
</syntaxhighlight>
<syntaxhighlight lang="bash">
# 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
</syntaxhighlight>
=== Theming ===
==== Gtk ====
<syntaxhighlight lang="nix">
environment.systemPackages = with pkgs; [
  gtk-engine-murrine
  gtk_engines
  gsettings-desktop-schemas
  lxappearance
];
</syntaxhighlight>
open lxappearance and pick your themes
read [https://github.com/swaywm/sway/wiki/GTK-3-settings-on-Wayland GTK3 settings on Wayland]
==== Qt ====
<syntaxhighlight lang="nix">
programs.qt5ct.enable = true;
</syntaxhighlight>
open qt5ct and pick your theme


=== Additional packages ===
=== Additional packages ===
Line 187: Line 147:
{{app|wofi|Launcher/menu program for wlroots based wayland compositors such as sway|https://hg.sr.ht/~scoopta/wofi|wofi}}
{{app|wofi|Launcher/menu program for wlroots based wayland compositors such as sway|https://hg.sr.ht/~scoopta/wofi|wofi}}
{{app|flashfocus|Simple focus animations for tiling window managers|https://github.com/fennerm/flashfocus|flashfocus}}
{{app|flashfocus|Simple focus animations for tiling window managers|https://github.com/fennerm/flashfocus|flashfocus}}
{{app|wf-recorder|Screen recorder for wlroots-based compositors such as sway|https://github.com/ammen99/wf-recorder|wf-recorder}}
{{app|i3-ratiosplit|Configurable window size on creation|https://github.com/333fred/i3-ratiosplit|i3-ratiosplit}}
{{app|i3-ratiosplit|Configurable window size on creation|https://github.com/333fred/i3-ratiosplit|i3-ratiosplit}}


Line 193: Line 152:




=== Systemd integration ===
In an article on the sway wiki [https://github.com/swaywm/sway/wiki/Systemd-integration], a way to integrate Sway with systemd user services is proposed. Starting sway that way has some benefits:
* Services like Waybar, kanshi, redshift can depend on <code>graphical-session.target</code> and can therefore be started as their own user service, including convenient service management and logging.
<syntaxhighlight lang="nix">
{ 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;
    };
  };
  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" ];
  };
  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";
    };
  };
}
</syntaxhighlight>
And then simply add the following to the ''end'' of your sway configuration
<syntaxhighlight>
exec "systemctl --user import-environment; systemctl --user start sway-session.target"
</syntaxhighlight>


Note: swayidle will fail cryptically if it cannot find {{ic|sh}} in {{ic|PATH}}, so you must provide this if you create a service file for it. An example is below:
<syntaxhighlight lang="nix">
  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"'
      '';
    };
  };
</syntaxhighlight>
[[Category:Window managers]]
[[Category:Window managers]]

Revision as of 15:54, 4 June 2022

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

Here is a minimal configuration where everything you would expect (like screen sharing and gtk themes) work:

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

let
  # bash script to let dbus know about important env variables and
  # propogate them to relevent services run at the end of sway config
  # see
  # https://github.com/emersion/xdg-desktop-portal-wlr/wiki/"It-doesn't-work"-Troubleshooting-Checklist
  # note: this is pretty much the same as  /etc/sway/config.d/nixos.conf but also restarts  
  # some user services to make sure they have the correct environment variables
  dbus-sway-environment = pkgs.writeTextFile {
    name = "dbus-sway-environment";
    destination = "/bin/dbus-sway-environment";
    executable = true;

    text = ''
  dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP=sway
  systemctl --user stop pipewire pipewire-media-session xdg-desktop-portal xdg-desktop-portal-wlr
  systemctl --user start pipewire pipewire-media-session xdg-desktop-portal xdg-desktop-portal-wlr
      '';
  };

  # currently, there is some friction between sway and gtk:
  # https://github.com/swaywm/sway/wiki/GTK-3-settings-on-Wayland
  # the suggested way to set gtk settings is with gsettings
  # for gsettings to work, we need to tell it where the schemas are
  # using the XDG_DATA_DIR environment variable
  # run at the end of sway config
  configure-gtk = pkgs.writeTextFile {
      name = "configure-gtk";
      destination = "/bin/configure-gtk";
      executable = true;
      text = let
        schema = pkgs.gsettings-desktop-schemas;
        datadir = "${schema}/share/gsettings-schemas/${schema.name}";
      in ''
        export XDG_DATA_DIRS=${datadir}:$XDG_DATA_DIRS
        gnome_schema=org.gnome.desktop.interface
        gsettings set $gnome_schema gtk-theme 'Dracula'
        '';
  };


in
{
  environment.systemPackages = with pkgs; [
    alacritty # gpu accelerated terminal
    sway
    dbus-sway-environment
    configure-gtk
    wayland
    glib # gsettings
    dracula-theme # gtk theme
    gnome3.adwaita-icon-theme  # default gnome cursors
    swaylock
    swayidle
    grim # screenshot functionality
    slurp # screenshot functionality
    wl-clipboard # wl-copy and wl-paste for copy/paste from stdin / stdout
    bemenu # wayland clone of dmenu
    mako # notification system developed by swaywm maintainer
  ];


  services.pipewire = {
    enable = true;
    alsa.enable = true;
    pulse.enable = true;
  };


  # xdg-desktop-portal works by exposing a series of D-Bus interfaces
  # known as portals under a well-known name
  # (org.freedesktop.portal.Desktop) and object path
  # (/org/freedesktop/portal/desktop).
  # The portal interfaces include APIs for file access, opening URIs,
  # printing and others.
  services.dbus.enable = true;
  xdg.portal = {
    enable = true;
    wlr.enable = true;
    # gtk portal needed to make gtk apps happy
    extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
    gtkUsePortal = true;
  };

  # enable sway window manager
  programs.sway = {
    enable = true;
    wrapperFeatures.gtk = true;
  };

and here are the relevent things you should add to your sway config:

sway config
set $menu bemenu-run

# screenshots
bindsym $mod+c exec grim  -g "$(slurp)" /tmp/$(date +'%H:%M:%S.png')


exec dbus-sway-environment
exec configure-gtk


Brightness and volume

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

hardware.pulseaudio.enable = true;
sway config
# Brightness
bindsym XF86MonBrightnessDown exec light -U 10
bindsym XF86MonBrightnessUp exec light -A 10

# 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'


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
  • i3-ratiosplit — Configurable window size on creation
https://github.com/333fred/i3-ratiosplit || i3-ratiosplit

more packages here i3 migration guide