168 lines
5.2 KiB
Markdown
168 lines
5.2 KiB
Markdown
# niri-tag
|
|
|
|
## tag-based window management for the [niri](https://github.com/YaLTeR/niri) compositor
|
|
|
|
niri-tag allows you to use a simple tagging-based system to manage your windows.
|
|
|
|
## how tags work
|
|
|
|
tag based management is relatively intuitive - sets of windows are assigned numeric tags. \
|
|
these tags are then de/activated to raise and lower the windows. \
|
|
only a single workspace is ever in active use per output.
|
|
|
|
# usage
|
|
|
|
## typical unix
|
|
|
|
first,\
|
|
clone the repo.\
|
|
clone a niri source tree into a subdirectory called niri - make sure it is the same release you are running.
|
|
build and install with cargo as per usual for rust projects on your platform.
|
|
|
|
next,\
|
|
set up niri-tag as a user-level service.\
|
|
for systemd users, something like the following should suffice:
|
|
|
|
````ini
|
|
# /etc/systemd/user/niri-tag.service
|
|
[Unit]
|
|
Description=Niri Tag Manager
|
|
PartOf=graphical-session.target
|
|
|
|
[Service]
|
|
ExecStart=/usr/bin/niri-tag
|
|
PrivateTmp=true
|
|
Restart=always
|
|
Type=notify
|
|
|
|
[Install]
|
|
WantedBy=graphical-session.target
|
|
````
|
|
|
|
niri's `exec-once` *should* also be okay, but the use of a service manager is highly recommended.
|
|
|
|
finally,\
|
|
set up niri binds using `tagctl` to control windows and tags as you see fit.
|
|
|
|
## nixos (flakes)
|
|
|
|
first,\
|
|
add the following to your flake inputs:
|
|
````nix
|
|
niri-tag = {
|
|
url = "git+https://git.atagen.co/atagen/niri-tag";
|
|
inputs.niri-flake.follows = "niri-flake";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
}
|
|
````
|
|
it is assumed you use niri-flake, or else will use the `stable` package output; this is important for the niri IPC definitions.
|
|
|
|
next,
|
|
- add `inputs.niri-tag.nixosModules.niri-tag` to your module imports
|
|
- add `services.niri-tag.enable = true;` somewhere in your config
|
|
- if you wish to use a stable niri instead of unstable from niri-flake (default), set `services.niri-tag.package = inputs.niri-tag.packages.${pkgs.system}.stable;`
|
|
|
|
finally,\
|
|
add binds to your niri configuration.
|
|
|
|
you will need the path of `tagctl`, which you can get with something like the following:
|
|
````nix
|
|
let
|
|
niri-tag = inputs.niri-tag.packages.${pkgs.system}.unstable; # or stable
|
|
tagctl = lib.getExe' niri-tag "tagctl";
|
|
in
|
|
...
|
|
````
|
|
|
|
## bindings
|
|
|
|
first,\
|
|
it is recommended that you unset all workspace related binds, as
|
|
switching workspaces or moving windows between them
|
|
while using tag management can cause unexpected behaviours.
|
|
|
|
next,\
|
|
set up:
|
|
- `Mod+Shift+$number` as a spawn bind for `tagctl toggle $number`
|
|
- `Mod+$number` as `tagctl toggle-tag $number`.
|
|
|
|
alternatively,\
|
|
you may bind as you see fit the tagctl commands `add` `remove` `toggle` for window tagging,
|
|
and `enable-tag` `disable-tag` `toggle-tag` `exclusive-tag` for managing tags.
|
|
|
|
all commands (except `remove`) take a tag number from 1-255 after their command.
|
|
|
|
finally,\
|
|
you may now use the aforementioned binds to assign tags to windows and toggle the tags on and off to hide/reveal them.
|
|
|
|
## config
|
|
|
|
configs are expected to be located at `$XDG_CONFIG_DIR/niri-tag/config.toml`.\
|
|
they are simple, headerless toml files.
|
|
|
|
the current config options (and their defaults) are:
|
|
````toml
|
|
# prepopulates a certain number of tags, from 1-255.
|
|
# this is useful for getting the full number of tags you intend to use
|
|
# premade and sent in any initial event stream connection.
|
|
prepopulate = 3
|
|
|
|
# strict workspaces
|
|
# this prevents you from switching away from the workspaces that were on each monitor
|
|
# when niri-tag was started, ensuring you don't accidentally break the window management
|
|
# paradigm, or get your desktop stuck in a weird state.
|
|
strict = true
|
|
|
|
````
|
|
|
|
## ipc
|
|
|
|
### command socket
|
|
`tagctl` is a simple wrapper over a one-shot socket connection to the niri-tag ipc, a socket which should be available at `$XDG_RUNTIME_DIR/niri-tag.sock`.\
|
|
this socket accepts all the `tagctl` commands, as formatted in PascalCase rather than kebab-case, and sent as a single JSON object per connection (for now) followed by a line ending.
|
|
|
|
as an example,
|
|
````json
|
|
{"EnableTag":4}
|
|
|
|
|
|
````
|
|
|
|
### event stream socket
|
|
there is a stream of events available via `$XDG_RUNTIME_DIR/niri-tag-events.sock`.
|
|
|
|
on initial connection, you will be sent your first and only `TagFullState` event, a JSON object summarising the entire state of the tag system, sent in similar fashion to the command socket.
|
|
|
|
following that, a stream of tag events with one JSON object per line will be sent for every niri-tag operation, until you close the connection.
|
|
|
|
#### events
|
|
|
|
here is a summary of possible events:
|
|
|
|
````json
|
|
{"TagEmpty": int} // tag no longer contains any windows
|
|
{"TagOccupied": int} // tag now contains window/s
|
|
{"TagUrgent": int} // tag has window signaling urgency
|
|
{"TagEnabled": int} // tag now enabled
|
|
{"TagDisabled": int} // tag now disabled
|
|
{"TagExclusive": int} // tag has been enabled to exclusion of all others
|
|
{"TagFullState": {
|
|
"1": {
|
|
"enabled": bool,
|
|
"occupied": bool,
|
|
"urgent": bool
|
|
},
|
|
... // more tags detailed in similar fashion
|
|
}
|
|
} // a full account of the tag state, sent only once on connection
|
|
````
|
|
|
|
## acknowledgements
|
|
- YaLTeR - for creating niri and blessing it with excellent IPC
|
|
- sodiboo - for niri-flake
|
|
- outfoxxed - for advice on XDG, IPC, and other TLA
|
|
- notashelf - a man so bald he can blind you at a glancing angle
|
|
- me - for writing this excellent program
|
|
|
|
enjoy !
|