Scratchpad support for Niri: a scrollable-tiling Wayland compositor.
eve_video.mp4
Add this flake to your inputs.
inputs = {
niri-scratchpad-flake = {
url = "github:gvolpe/niri-scratchpad";
inputs.nixpkgs.follows = "nixpkgs";
};
}Install the package via niri-scratchpad or default, e.g.
let
inherit (inputs.ns-flake.packages.${system}) niri-scratchpad;
in
{
home.packages = [ niri-scratchpad ];
}Only available for Linux systems, see nix flake show for more.
If Nix is not your jam, simply copy the ns.py script into your system and give it execution permissions (chmod +x ns.py). You'll need Python 3 installed.
See nscratch --help for the available commands.
$ nscratch --help
usage: nscratch [-h] (-id APP_ID | -t TITLE) [-s SPAWN] [-a] [-m]
Niri Scratchpad support
options:
-h, --help show this help message and exit
-id, --app-id APP_ID The application identifier
-t, --title TITLE The application title
-s, --spawn SPAWN The process name to spawn when non-existing
-a, --animations Enable animations
-m, --multi-monitor Multi-monitor supportScratchpad windows can be searched either by app-id or title.
The workspace "scratch" must exist, the rest is optional.
workspace "scratch"
window-rule {
match app-id=r#"^spotify|nemo$"#
open-on-workspace "scratch"
open-floating true
}
spawn-at-startup "spotify"
spawn-at-startup "nemo"For a better experience, declare all your workspaces explicitly and add the "scratch" one last. Example.
In this example, we create a window rule so that both spotify and nemo are spawned in the "scratch" workspace. Additionally, we spawn these processes at startup.
Next, we have our scratchpad keybindings.
binds {
Mod+Ctrl+S { spawn-sh "nscratch -id spotify"; }
Mod+Ctrl+F { spawn-sh "nscratch -id nemo"; }
}Both spotify and nemo are spawned at startup by Niri (via spawn-at-startup).
To further enhance your experience, consider setting the size of your scratchpad windows, e.g.
window-rule {
match app-id="nemo"
open-on-workspace "scratch"
open-floating true
default-column-width { fixed 1157; }
default-window-height { fixed 736; }
}In the following example, we have a keybinding for the Audacious application, which is not spawned by Niri. So we can indicate that if the process does not yet exist, it should be spawned by nscratch (internally done via niri msg spawn).
binds {
Mod+Ctrl+A { spawn-sh "nscratch -id Audacious -s audacious"; }
}NOTE: a spawned window via the --spawn (or -s) flag can't be made floating the first time it's brought up, but it will be from the second time onwards, due to a known limitation. If you would like to avoid this, you can either fix it via a window rule, or by letting Niri start the process at startup instead.
Scratchpad animations are disabled by default. To enable them, set the --animations or -a flag, e.g.
$ nscratch -id nemo -aThe animation is achieved by switching the scratchpad window to tiling mode when it's moved to the scratch workspace, and subsequently making it a floating window when it's summoned.
Multi-monitor support can be enabled via the --multi-monitor or -m flags, e.g.
$ nscratch -id nemo -mIt is disabled by default because it requires an extra IPC command, which is best to avoid on a single screen.
Given the fact that Niri doesn't support "hidden" workspaces, this solution imposes a few caveats. First of all, the "scratch" workspace will always be visible if you scroll all the way down to your last workspace; it can't be hidden.
If you rely on accessing your workspaces by index (e.g. Mod+2, Mod+3) and don't explicitly declare your workspaces in your configuration, then it means you're relying on dynamic workspaces, which is the default in Niri.
Declaring only the "scratch" workspace and leaving everything else as dynamic still works, but you can't expect your indices to remain the same. So always declare all your workspaces explicitly (see Named Workspaces) if you'd like the indices to be predictable.
Nevertheless, a better approach is to access your workspaces by name instead, e.g.
workspace "web"
workspace "dev"
workspace "scratch"
binds {
Mod+1 { focus-workspace "web"; }
Mod+2 { focus-workspace "dev"; }
Mod+Shift+1 { move-window-to-workspace "web"; }
Mod+Shift+2 { move-window-to-workspace "dev"; }
}By using named workspaces, we also get to enjoy dynamic workspaces. See addressing workspaces by index in the official docs for more.