# Niri Desktop Environment

Niri is a scrollable-tiling Wayland compositor written in Rust. Unlike Hyprland's dwindle/master layouts, Niri arranges windows in **columns that scroll horizontally** within each workspace — think a continuous horizontal strip instead of a fixed grid.

---

## Overview

| Component | Role |
|-----------|------|
| **Niri** | Wayland scrollable-tiling compositor |
| **Kitty** | Primary terminal emulator |
| **EWW** | Status bar (three device variants) |
| **Waybar** | Alternative status bar |
| **Wofi** | App launcher (keyboard-driven) |
| **Walker** | Fast CLI launcher |
| **uLauncher** | GUI app launcher |
| **Dunst** | Notification daemon |
| **swaylock** | Screen locker |
| **swaybg** | Wallpaper daemon |
| **swayidle** | Idle management (lock, suspend) |
| **gammastep** | Colour temperature (night light) |
| **nwg-drawer** | Application drawer |
| **nwg-panel** | Desktop menu |
| **Vicinae** | Gesture-triggered context launcher |
| **xfce-polkit** | PolicyKit authentication agent |
| **ly** | TUI login manager |

---

## Config File Map

```
desktopenvs/niri/
├── niri/
│   └── config.kdl             # Single KDL config — everything in one file
├── greetd-tuigreet/
│   └── config.toml            # Greeter → launches niri
├── scripts/                   # Utility scripts (niri-adapted)
│   ├── ewwstart.sh            # Start EWW bar (niri monitor detection)
│   ├── togglebar.sh           # Show/hide EWW bar
│   ├── monitorhandler.sh      # swaybg wallpaper + eww bar on startup
│   ├── caffeine.sh            # Toggle swayidle (prevent sleep)
│   ├── activewindow           # Focused window title for EWW
│   ├── workspace              # Workspace widget (niri event-stream)
│   ├── wallpaper-picker       # swaybg-based wallpaper picker
│   ├── unified-rotate.sh      # Screen rotation via niri IPC
│   ├── niri-toggle-touchpad.sh # Touchpad on/off (xinput)
│   ├── windowswitcher         # Window list via niri msg + wofi
│   ├── drawer.sh              # nwg-drawer launcher
│   └── [shared with hyprlua]  # screenshot.sh, screenrec.sh, etc.
├── eww/                       # EWW bar (PC, no battery)
├── eww-nobattery/             # EWW bar (desktop alias)
├── eww-touch/                 # EWW bar (laptop/tablet + battery)
├── config-updater/
│   └── updater.conf           # Config sync manifest
│
│   # Shared configs — symlinked from desktopenvs/hyprlua/
├── kitty → ../hyprlua/kitty
├── dunst → ../hyprlua/dunst
├── wofi  → ../hyprlua/wofi
├── btop  → ../hyprlua/btop
├── walker → ../hyprlua/walker
├── vicinae → ../hyprlua/vicinae
└── [alacritty, gtk-3.0, ulauncher, xfce4, waybar, nwg-drawer, ...]
```

---

## Niri vs Hyprland — Key Differences

| Feature | HyprLua | Niri |
|---------|---------|------|
| Layout model | Dwindle / Master | Scrollable columns |
| Config format | Lua (`hyprland.lua`) | KDL (`config.kdl`) |
| Workspace direction | Horizontal (1→9) | Vertical (stacked) |
| Wallpaper | hyprpaper | swaybg |
| Screen locker | hyprlock | swaylock |
| Idle daemon | hypridle | swayidle |
| Colour temp | hyprsunset | gammastep |
| Polkit agent | hyprpolkitagent | xfce-polkit |
| Dock | nwg-dock-hyprland | — (not compatible) |
| IPC tool | `hyprctl` | `niri msg` |

> **No dock:** nwg-dock-hyprland uses the `wlr-foreign-toplevel-management` protocol which niri does not implement. The app drawer (`nwg-drawer`) and launcher (`vicinae`) serve the same role.

---

## Keybindings

All bindings are defined in `niri/config.kdl` under the `binds { }` section. Edit with `Mod+Shift+F1`.

### Applications

| Binding | Action |
|---------|--------|
| `Super + T` | Kitty terminal |
| `Super + Shift + T` | Cool Retro Term |
| `Super + M` | Kitty + Neovim |
| `Super + E` | Thunar file manager |
| `Super + Alt + E` | PCManFM-Qt |
| `Super + X` | Wofi run launcher |
| `Super + R` / `Super + Return` | Vicinae launcher |
| `Super + Shift + R` | Wofi drun |
| `Super + F` | File search |
| `Super + Shift + F` | Folder search |
| `Super + Alt + F` | Wofi calculator |
| `Super + S` | PulseAudio mixer (pavucontrol) |
| `Super + U` | btop system monitor |
| `Super + W` | Wallpaper picker |
| `Super + D` | App drawer (nwg-drawer) |
| `Super + I` | Network menu (iwmenu) |
| `Super + N` | Nextcloud |

### Window Management

| Binding | Action |
|---------|--------|
| `Super + Q` | Close window |
| `Super + V` | Toggle floating |
| `Super + Shift + V` / `Super + C` | Centre column |
| `Super + Backspace` | Cycle preset column width |
| `Super + Shift + Backspace` | Maximise column |
| `Super + Ctrl + Backspace` | Fullscreen |
| `Super + A` | Consume window into column |
| `Super + Y` | Expel window from column |

### Focus & Move

| Binding | Action |
|---------|--------|
| `Super + H / L / J / K` | Focus column left/right, window up/down |
| `Super + Arrow keys` | Same as above |
| `Super + Tab` | Focus next window/column |
| `Super + Shift + H/L/J/K` | Move column/window |
| `Super + Alt + H/L/J/K` | Resize column/window |

### Workspaces

> Niri workspaces are **vertical** — they stack top-to-bottom on each output.
> `Ctrl+L` goes **down** (next workspace), `Ctrl+H` goes **up** (previous).

| Binding | Action |
|---------|--------|
| `Super + [1–9]` | Switch to workspace N |
| `Super + Shift + [1–9]` | Move column to workspace N |
| `Super + Ctrl + L / Right` | Next workspace (down) |
| `Super + Ctrl + H / Left` | Previous workspace (up) |
| `Super + Ctrl + Shift + L/H` | Move column to next/prev workspace |
| `Super + Scroll up/down` | Navigate workspaces |
| `Super + Space` | Focus workspace with recent window |

### System

| Binding | Action |
|---------|--------|
| `Super + O` | Lock screen (swaylock) |
| `Super + Shift + O` | Quit niri |
| `Super + Ctrl + O` | Shutdown |
| `Super + Alt + O` | Power menu |
| `Super + Z` | Toggle EWW bar |
| `Super + Ctrl + B` | Reload EWW |
| `Super + Shift + C` | Toggle caffeine (swayidle) |
| `Super + Ctrl + P` | Start/stop screen recording |
| `Print` / `Super + P` | Screenshot (region) |
| `Super + Shift + P` | Screenshot full screen |

### Audio / Brightness

| Binding | Action |
|---------|--------|
| `XF86AudioRaiseVolume` | Volume +5% |
| `XF86AudioLowerVolume` | Volume -5% |
| `XF86AudioMute` | Mute toggle |
| `XF86AudioPlay` | Play/pause |
| `XF86MonBrightnessUp/Down` | Brightness |

### Colour Temperature (gammastep)

Unlike hyprsunset, gammastep has no runtime IPC. Each binding kills and restarts it at a preset:

| Binding | Temperature |
|---------|-------------|
| `Super + Ctrl + X` | 6500 K (neutral / reset) |
| `Super + Ctrl + W` | 5000 K (warm) |
| `Super + Ctrl + A` | 4000 K (warmer) |
| `Super + Ctrl + Q` | 3000 K (very warm) |
| `Super + Ctrl + S` | 2700 K (night mode) |

---

## Status Bar (EWW)

Three EWW bar variants — installed during setup:

| Variant | Target device | Battery widget |
|---------|---------------|----------------|
| `eww/` | Desktop PC | No |
| `eww-nobattery/` | Desktop PC | No |
| `eww-touch/` | Laptop / tablet | Yes |

The workspace widget uses `~/.config/scripts/workspace` — a bash script that listens to `niri msg event-stream` and outputs EWW Yuck literals whenever workspaces change.

The EWW style (`eww.scss`) is shared with hyprlua via symlink — CyberQueer colours apply identically.

---

## Wallpaper

The wallpaper is managed by `swaybg`. At startup `monitorhandler.sh` runs:

```bash
swaybg -m fill -i ~/Pictures/background.jpg &
```

To pick a wallpaper interactively:

```
Super + W
```

This opens `wallpaper-picker` in a Kitty terminal — navigate with `h/l`, apply with `Enter`, quit with `q`. The selected image is reloaded via `swaybg` and saved to `~/.config/niri-wallpaper`.

---

## Screen Lock & Idle

**swaylock** is the screen locker (`Super + O` or via swayidle timeout).

**swayidle** launches at startup with:
- 5 min idle → `swaylock -f`
- 10 min idle → `systemctl suspend`
- before sleep → `swaylock -f`

**Caffeine mode** (`Super + Shift + C`) kills swayidle and restarts it when toggled off.

---

## Screen Rotation

`Super + Ctrl + E` (clockwise) and `Super + Ctrl + D` (anti-clockwise) call `unified-rotate.sh`, which uses `niri msg action set-output-transform` on the currently focused output.

---

## Config Updater

The config updater syncs `desktopenvs/niri/` into `~/.config/`:

```bash
~/update-configs.sh
```

Config: `~/.config/config-updater/updater.conf`  
Managed entries: `niri`, `kitty`, `dunst`, `wofi`, `scripts`, and more.

---

## Installing Niri

```bash
# Via the TUI installer
bash ~/Dotfiles/setup/tui-install.sh
# → select "Niri" in the Desktop Environment dialog

# Direct script (on an existing Arch system)
bash ~/Dotfiles/setup/modules/Desktop-Environments/niri.sh
```

The installer:

1. Installs all packages (niri, swaybg, swaylock, swayidle, gammastep, xfce-polkit, etc.)
2. Compiles EWW from source (requires Rust)
3. Copies all configs to `~/.config/`
4. Deploys greetd config to `/etc/greetd/config.toml`
5. Installs CyberQueer GTK theme and Nordzy-cursors-lefthand
6. Enables `ly@tty1`, `NetworkManager`, `bluetooth`, `iwd`, `udisks2`
7. Installs Python venv for scripts
8. Sets up the config-updater symlinks
