Sway: Difference between revisions

imported>Artturin
add to window managers
Tie-ling (talk | contribs)
dimming, screen sharing, inhibit idle
 
(85 intermediate revisions by 48 users not shown)
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]


== Installation ==
== Setup ==
 
You can install Sway by enabling it in NixOS directly, or by using [[Home Manager]], or both.
=== NixOS ===
[https://search.nixos.org/options?query=sway NixOS options for sway]


=== Using NixOS ===
Here is a minimal configuration:
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
programs.sway = {
{ config, pkgs, lib, ... }:
   enable = true;
{
  wrapperFeatures.gtk = true; # so that gtk works properly
   environment.systemPackages = with pkgs; [
  extraPackages = with pkgs; [
     grim # screenshot functionality
     swaylock
     slurp # screenshot functionality
     swayidle
     wl-clipboard # wl-copy and wl-paste for copy/paste from stdin / stdout
     wl-clipboard
     mako # notification system developed by swaywm maintainer
     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
   ];
   ];
};


  # Enable the gnome-keyring secrets vault.
  # Will be exposed through DBus to programs willing to store secrets.
  services.gnome.gnome-keyring.enable = true;
  # enable Sway window manager
  programs.sway = {
    enable = true;
    wrapperFeatures.gtk = true;
  };
}
</syntaxhighlight>By default, the Sway module in NixOS comes with a set of extra packages, including the <code>foot</code> terminal, <code>swayidle</code>, <code>swaylock</code>, and <code>wmenu</code>, which can be configured under  <code>[https://search.nixos.org/options?show=programs.sway.extraPackages programs.sway.extraPackages]</code> option. You may also want to include <code>wl-clipboard</code> for clipboard functionality and <code>slurp</code> for screenshot region selection. Additionally, for a more customizable bar implementation than <code>sway-bar</code>, <code>waybar</code> can be enabled with <code>programs.waybar.enable</code>.
The default Sway configuration is symlinked to <code>/etc/sway/config</code> and <code>/etc/sway/config.d/nixos.conf</code>. The latter file contains dbus and systemd configuration that is critical to using apps that depend on XDG desktop portals with Sway, and should be included in any custom configuration files.
A few general comments:
* There is some friction between GTK theming and Sway. Currently the Sway developers suggest using gsettings to set gtk theme attributes as described here [https://github.com/swaywm/sway/wiki/GTK-3-settings-on-Wayland]. There is currently a plan to allow GTK theme attributes to be set directly in the Sway config.
* Running Sway as a systemd user service is not recommended [https://github.com/swaywm/sway/wiki/Systemd-integration#running-sway-itself-as-a---user-service] [https://github.com/swaywm/sway/issues/5160]
=== Using Home Manager ===
To set up Sway using [[Home Manager]], first you must enable [[Polkit]] in your NixOS configuration:
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
security.polkit.enable = true;
</nowiki>}}
Then you can enable Sway in your home manager configuration. Here is a minimal example:
<syntaxhighlight lang="nix>
  wayland.windowManager.sway = {
    enable = true;
    wrapperFeatures.gtk = true; # Fixes common issues with GTK 3 apps
    config = rec {
      modifier = "Mod4";
      # Use kitty as default terminal
      terminal = "kitty";
      startup = [
        # Launch Firefox on start
        {command = "firefox";}
      ];
    };
  };
</syntaxhighlight>
</syntaxhighlight>


=== Home Manager ===
See [https://nix-community.github.io/home-manager/options.xhtml#opt-wayland.windowManager.sway.enable Home Manager's Options for Sway] for a complete list of configuration options.
[https://rycee.gitlab.io/home-manager/options.html#opt-wayland.windowManager.sway.enable Home Manager options for sway]
 
You might need to active dbus manually from .zshrc to use i.e: dunst, see [https://discourse.nixos.org/t/dunst-crashes-if-run-as-service/27671/2 Dunst crashes if run as service]
 
{{Note|
It's recommended to enable a [[Secret Service]] provider, like GNOME Keyring:
{{file|home.nix|nix|<nowiki>
services.gnome-keyring.enable = true;
</nowiki>}}
}}
 
=== Systemd services ===
Kanshi is an output configuration daemon. As explained above, we don't run Sway itself as a systemd service. There are auxiliary daemons that we do want to run as systemd services, for example Kanshi [https://sr.ht/~emersion/kanshi/], which implements monitor hot swapping. It would be enabled as follows:
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
  # kanshi systemd service
  systemd.user.services.kanshi = {
    description = "kanshi daemon";
    environment = {
      WAYLAND_DISPLAY="wayland-1";
      DISPLAY = ":0";
    };
    serviceConfig = {
      Type = "simple";
      ExecStart = ''${pkgs.kanshi}/bin/kanshi -c kanshi_config_file'';
    };
  };
</nowiki>}}
 
{{file|sway config|bash|
# give Sway a little time to startup before starting kanshi.
exec sleep 5; systemctl --user start kanshi.service
}}
When you launch Sway, the systemd service is started.
 
=== Using greeter ===
Installing a greeter based on [https://search.nixos.org/options?channel=unstable&show=services.greetd.settings&from=0&size=50&sort=relevance&type=packages&query=greetd greetd] is the most straightforward way to launch Sway.
 
Tuigreet does not even need a separate compositor to launch.
 
{{file|||<nowiki>
services.greetd = {                                                     
  enable = true;                                                       
  settings = {                                                         
    default_session = {                                                 
      command = "${pkgs.tuigreet}/bin/tuigreet --time --cmd sway";
      user = "greeter";                                                 
    };                                                                 
  };                                                                   
};                                                                     
</nowiki>|name=/etc/nixos/configuration.nix|lang=nix}}
 
=== Automatic startup on boot ===
The snippet below will start Sway immediately on startup, without a greeter and '''without login prompt'''. Only consider using this in conjunction with [[Full Disk Encryption]]!


<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
wayland.windowManager.sway = {
services.getty = {
   enable = true;
   autologinUser = "your_username";
   wrapperFeatures.gtk = true ;
   autologinOnce = true;
};
};
home.packages = with pkgs; [
environment.loginShellInit = ''
  swaylock
    [[ "$(tty)" == /dev/tty1 ]] && sway
  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>
</syntaxhighlight>


== Info ==
== Configuration ==
Sway can be configured for specific users using Home-Manager or manually through configuration files. Default is <code>/etc/sway/config</code> and custom user configuration in <code>~/.config/sway/config</code>.
 
=== Keyboard layout ===
Changing layout for all keyboards to German (de):<syntaxhighlight lang="console">
input * xkb_layout "de"
</syntaxhighlight>The same thing accomplished in Home Manager:<syntaxhighlight lang="nix">
wayland.windowManager.sway.input."*".xkb_layout = "de";
</syntaxhighlight>
 
=== High-DPI scaling ===
Changing scale for all screens to factor 1.5:<syntaxhighlight lang="console">
output * scale 1.5
</syntaxhighlight>
 
=== Brightness and volume ===
You can set up brightness and volume function keys as follows by binding the key codes to their corresponding commands in your sway config. The following configurations accomplish this using <code>light</code> and <code>pulseaudio</code>:
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
users.users.yourusername.extraGroups = [ "video" ];
programs.light.enable = true;
environment.systemPackages = [ pkgs.pulseaudio ];
</nowiki>}}
 
{{file|sway config|bash|
 
# 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'
}}
 
== Troubleshooting ==


=== Clipboard ===
=== Cursor is missing icons or too tiny on HiDPI displays ===


For clipboard support
==== With programs.sway ====
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix>
environment.systemPackages = with pkgs; [ wl-clipboard ];
{
  programs.sway.extraPackages = with pkgs; [
    adwaita-icon-theme # mouse cursor and icons
    gnome-themes-extra # dark adwaita theme
    ...
  ];
}
</syntaxhighlight>
 
In ~/.config/sway/config
<syntaxhighlight>
seat "*" xcursor_theme Adwaita 32
</syntaxhighlight>
</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
==== With Home Manager ====


<syntaxhighlight lang="nix">
Using [[Home Manager]] try configuring a general mouse cursor size and theme. The reason that your cursor might be missing in some applications, is because <code>XCURSOR_THEME</code>is missing, which will cause applications relying on <code>XWAYLAND</code> to misbehave. Setting <code>sway.enable = true</code>, combined with the <code>name</code>, <code>package</code> and size will set the correct environment variables, which sway will then use.
nixpkgs.overlays = [
 
  (self: super: {
<syntaxhighlight lang="nix">home-manager.users.myUser = {
     wl-clipboard-x11 = super.stdenv.mkDerivation rec {
     home.pointerCursor = {
    pname = "wl-clipboard-x11";
      name = "Adwaita";
    version = "5";
      package = pkgs.adwaita-icon-theme;
 
      size = 24;
    src = super.fetchFromGitHub {
      x11 = {
      owner = "brunelli";
        enable = true;
      repo = "wl-clipboard-x11";
        defaultCursor = "Adwaita";
       rev = "v${version}";
       };
       sha256 = "1y7jv7rps0sdzmm859wn2l8q4pg2x35smcrm7mbfxn5vrga0bslb";
       sway.enable = true;
     };
     };
    
};</syntaxhighlight>
     dontBuild = true;
 
     dontConfigure = true;
Replace <code>myUser</code> with your user running the graphical environment.
     propagatedBuildInputs = [ super.wl-clipboard ];
 
    makeFlags = [ "PREFIX=$(out)" ];
=== Missing fonts on Xorg applications ===
 
If fonts for certain languages are missing in Xorg applications (e.g. Japanese fonts don't appear in Discord) even though they're in the system, you can set them as default fonts in your configuration file.
 
<syntaxhighlight lang="nix>
 
   fonts = {
     packages = with pkgs; [
      noto-fonts
      noto-fonts-cjk
      noto-fonts-emoji
      font-awesome
      source-han-sans
      source-han-sans-japanese
      source-han-serif-japanese
     ];
     fontconfig.defaultFonts = {
      serif = [ "Noto Serif" "Source Han Serif" ];
      sansSerif = [ "Noto Sans" "Source Han Sans" ];
     };
     };
    
   };
    xsel = self.wl-clipboard-x11;
 
    xclip = self.wl-clipboard-x11;
  })
];
</syntaxhighlight>
</syntaxhighlight>
{{Note|This will recompile all packages that have xclip or xsel in their dependencies|warn}}


=== Polkit ===
=== Swaylock cannot be unlocked with the correct password ===


<syntaxhighlight lang="nix">
Add the following to your NixOS configuration.
environment.systemPackages = with pkgs; [ polkit_gnome ];
 
<syntaxhighlight lang="nix>
  security.pam.services.swaylock = {};
</syntaxhighlight>
</syntaxhighlight>


nix generated sway config
The <code>programs.sway.enable</code> option does this automatically.
 
=== Inferior performance compared to other distributions ===
 
Enabling realtime may improve latency and reduce stuttering, specially in high load scenarios.
 
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
${pkgs.polkit_gnome}/libexec/polkit-gnome-authentication-agent-1
security.pam.loginLimits = [
  { domain = "@users"; item = "rtprio"; type = "-"; value = 1; }
];
</syntaxhighlight>
</syntaxhighlight>


normal sway config
Enabling this option allows any program run by the "users" group to request real-time priority.
<syntaxhighlight lang="bash">
# NixOS
exec /run/current-system/sw/libexec/polkit-gnome-authentication-agent-1
# Home Manager
exec ~/.nix-profile/libexec/polkit-gnome-authentication-agent-1
</syntaxhighlight>


=== Systemd integration ===
=== WLR Error when trying to launch Sway ===


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:
When this happens on a new nixos system, enabling opengl in configuration.nix may fix this issue.


* Logging for Sway is done the same way it is done for every other user service.
{{Note|<code>hardware.opengl</code> was renamed to <code>hardware.graphics</code> in NixOS 24.11.}}
* 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.


'''Don't forget to additionally start <code>sway-session.target</code>with one of the methods described in the sway wiki.'''
<syntaxhighlight lang="nix">
<syntaxhighlight lang="nix">
{ config, pkgs, lib, ... }: {
hardware.graphics.enable = true;
</syntaxhighlight>


  programs.sway = {
=== Touchscreen input bound to the wrong monitor in multi-monitor setups ===
    enable = true;
 
    extraPackages = with pkgs; [
See this [https://github.com/swaywm/sway/issues/6590#issue-1021207180 GitHub issue for Sway] and the solution give in [https://github.com/swaywm/sway/issues/6590#issuecomment-938724355 this response].
      swaylock # lockscreen
 
      swayidle
Using [[Home Manager]] add the following to your Sway configuration:
      xwayland # for legacy apps
<syntaxhighlight lang="nix">
      waybar # status bar
  wayland.windowManager.sway = {
      mako # notification daemon
    [...]
      kanshi # autorandr
    config = {
    ];
      [...]
  };
      input = {
        [...]
        "type:touch" = {
          # Replace touchscreen_output_identifier with the identifier of your touchscreen.
          map_to_output = touchscreen_output_identifier;
        };
      };
    };
  };
</syntaxhighlight>


  environment = {
=== GTK apps take an exceptionally long time to start ===
    etc = {
This occurs because GTK apps make blocking calls to freedesktop portals to be displayed. If Sway is not integrated with dbus and systemd, it will not be able to communicate via the <code>org.freedesktop.portal.Desktop</code> portal. To fix this, see the [[Sway#Using NixOS|description]] of default Sway configurations earlier. Adding the following to your sway configuration, if it is not already present, may resolve the issue:
      # Put config files in /etc. Note that you also can put these in ~/.config, but then you can't manage them with NixOS anymore!
include /etc/sway/config.d/*
      "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).
== Tips and tricks ==
  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
=== Toggle monitor modes script ===
          systemctl --user import-environment
Following script toggles screen / monitor modes if executed. It can also be mapped to a specific key in Sway.
          # then start the service
          exec systemctl --user start sway.service
        '';
      }
    )
  ];


  systemd.user.targets.sway-session = {
First add the Flake input required for the script<syntaxhighlight lang="nix">
    description = "Sway compositor session";
{
     documentation = [ "man:systemd.special(7)" ];
  inputs = {
     bindsTo = [ "graphical-session.target" ];
     [...]
    wants = [ "graphical-session-pre.target" ];
     wl-togglescreens.url = "git+https://git.project-insanity.org/onny/wl-togglescreens.git?ref=main";
    after = [ "graphical-session-pre.target" ];
   };
   };


   systemd.user.services.sway = {
   outputs = {self, nixpkgs, ...}@inputs: {
    description = "Sway - Wayland window manager";
    nixosConfigurations.myhost = inputs.nixpkgs.lib.nixosSystem {
    documentation = [ "man:sway(5)" ];
      system = "x86_64-linux";
    bindsTo = [ "graphical-session.target" ];
      specialArgs.inputs = inputs;
     wants = [ "graphical-session-pre.target" ];
      [...]
    after = [ "graphical-session-pre.target" ];
</syntaxhighlight>Map the script binary to a specific key<syntaxhighlight lang="nix">
    # We explicitly unset PATH here, as we want it to be set by
{ config, pkgs, lib, inputs, ... }:{
    # systemctl --user import-environment in startsway
  home-manager.users.onny = {
    environment.PATH = lib.mkForce null;
     programs = {
    serviceConfig = {
      [...]
      Type = "simple";
      wayland.windowManager.sway = {
      ExecStart = ''
        enable = true;
        ${pkgs.dbus}/bin/dbus-run-session ${pkgs.sway}/bin/sway --debug
        config = {
      '';
          [...]
      Restart = "on-failure";
          keybindings = lib.mkOptionDefault{
      RestartSec = 1;
            [...]
       TimeoutStopSec = 10;
            "XF86Display" = "exec ${inputs.wl-togglescreens.packages.x86_64-linux.wl-togglescreens}/bin/wl-togglescreens";
          };
        };
       };
     };
     };
</syntaxhighlight>
=== Screen sharing with Firefox, Chromium ===
<syntaxhighlight lang="nix">
{ pkgs, ... }:
{
  # xdg portal + pipewire = screensharing
  xdg.portal = {
    enable = true;
    wlr.enable = true;
   };
   };
 
   services.pipewire = {
   services.redshift = {
     enable = true;
     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.
     alsa.enable = true;
     package = pkgs.redshift-wlr;
     pulse.enable = true;
   };
   };
}
</syntaxhighlight>


  programs.waybar.enable = true;
=== Screen dimming with  wl-gammarelay-rs ===
Add <code>wl-gammarelay-rs</code> to programs.sway.extraPackages, then add the following to sway config:
<syntaxhighlight>
# start daemon
exec wl-gammarelay-rs


  systemd.user.services.kanshi = {
# bind shortcut to reset brightness
    description = "Kanshi output autoconfig ";
bindsym $mod+Control+0 exec busctl --user set-property rs.wl-gammarelay / rs.wl.gammarelay Brightness d 1
    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";
    };
  };


}
# bind shortcut to dim screen for a particular output
bindsym $mod+Control+Underscore exec busctl --user set-property rs.wl-gammarelay /outputs/DP_1 rs.wl.gammarelay Brightness d 0.5


</syntaxhighlight>
</syntaxhighlight>


=== Inhibit swayidle/suspend when fullscreen ===
Add to sway config:
<syntaxhighlight>
# When you use `for_window` the command you give is not executed
# immediately. It is stored in a list and the command is executed
# every time a window opens or changes (eg. title) in a way that
# matches the criteria.
# inhibit idle for fullscreen apps
for_window [app_id="^.*"] inhibit_idle fullscreen
</syntaxhighlight>
[[Category:Window managers]]
[[Category:Window managers]]
[[Category:Applications]]