Skip to main content

Overview

The primary screencasting interface that niri offers is through portals and pipewire. It is supported by:
  • OBS Studio
  • Firefox
  • Chromium
  • Electron apps
  • Telegram
  • Other apps using xdg-desktop-portal
You can screencast both monitors and individual windows.

Requirements

1

D-Bus Session

You need a working D-Bus session
2

PipeWire

Install and configure PipeWire
3

Desktop Portal

Install xdg-desktop-portal-gnome
4

Session Mode

Run niri as a session through niri-session or from a display manager
On widely used distros, this should all “just work”.

Alternative Methods

Alternatively, you can use tools that rely on the wlr-screencopy protocol, which niri also supports.

Blocking Windows from Screencasts

You can block out specific windows from screencasts, replacing them with solid black rectangles. This is useful for password managers, messengers, or any sensitive content. Screenshot showing a window visible normally, but blocked out on OBS.

Window Rules

Block windows using the block-out-from window rule:
// Block out password managers from screencasts.
window-rule {
    match app-id=r#"^org\.keepassxc\.KeePassXC$"#
    match app-id=r#"^org\.gnome\.World\.Secrets$"#

    block-out-from "screencast"
}

Layer Rules

You can similarly block out layer surfaces:
// Block out mako notifications from screencasts.
layer-rule {
    match namespace="^notifications$"

    block-out-from "screencast"
}

Learn More

Check the window rules documentation for more details and examples

Dynamic Screencast Target

Available since version 25.05
Niri provides a special screencast stream that you can change dynamically. It shows up as “niri Dynamic Cast Target” in the screencast window dialog. Screencast dialog showing niri Dynamic Cast Target

How It Works

When you select it, it will start as an empty, transparent video stream. Then, you can use the following binds to change what it shows:

Cast Window

set-dynamic-cast-window - Cast the focused window

Cast Monitor

set-dynamic-cast-monitor - Cast the focused monitor

Clear Target

clear-dynamic-cast-target - Go back to empty stream

Configuration Example

binds {
    Mod+Shift+C { set-dynamic-cast-window; }
    Mod+Shift+M { set-dynamic-cast-monitor; }
    Mod+Shift+X { clear-dynamic-cast-target; }
}

Command Line Usage

You can also use these actions from the command line, for example to interactively pick which window to cast:
niri msg action set-dynamic-cast-window --id $(niri msg --json pick-window | jq .id)

Behavior Notes

  • If the cast target disappears (e.g., the target window closes), the stream goes back to empty
  • All dynamic casts share the same target
  • New casts start out empty until the next time you change the target (to avoid surprises)

Indicating Screencasted Windows

Available since version 25.02
The is-window-cast-target=true window rule matches windows targeted by an ongoing window screencast. You can use it with a special border color to clearly indicate screencasted windows.
This works for windows targeted by dynamic screencasts, but will not work for windows that just happen to be visible in a full-monitor screencast.

Example Configuration

// Indicate screencasted windows with red colors.
window-rule {
    match is-window-cast-target=true

    focus-ring {
        active-color "#f38ba8"
        inactive-color "#7d0d2d"
    }

    border {
        inactive-color "#7d0d2d"
    }

    shadow {
        color "#7d0d2d70"
    }

    tab-indicator {
        active-color "#f38ba8"
        inactive-color "#7d0d2d"
    }
}
Screencasted window indicated with a red border and shadow

Windowed (Fake) Fullscreen

Available since version 25.05
When screencasting browser-based presentations like Google Slides, you usually want to hide the browser UI, which requires making the browser fullscreen. This is not always convenient, especially if you have an ultrawide monitor or just want to leave the browser as a smaller window. The toggle-windowed-fullscreen bind helps with this. It tells the app that it went fullscreen, while in reality leaving it as a normal window that you can resize and put wherever you want.

Configuration

binds {
    Mod+Ctrl+Shift+F { toggle-windowed-fullscreen; }
}
Keep in mind that not all apps react to fullscreening, so it may sometimes look as if the bind did nothing.

Use Case Example

Here’s an example showing a windowed-fullscreen Google Slides presentation, along with the presenter view and a meeting app: Windowed Google Slides presentation with presenter view and Zoom

Screen Mirroring

For presentations it can be useful to mirror an output to another. Currently, niri doesn’t have built-in output mirroring, but you can use wl-mirror that mirrors an output to a window.
The command below requires jq to be installed.

Configuration

binds {
    Mod+P repeat=false { spawn-sh "wl-mirror $(niri msg --json focused-output | jq -r .name)"; }
}

Usage Steps

1

Focus Source Output

Focus the output you want to mirror
2

Start Mirroring

Press Mod+P to start wl-mirror
3

Move Window

Move the wl-mirror window to the target output
4

Fullscreen

Fullscreen the wl-mirror window (by default, Mod+Shift+F)

Build docs developers (and LLMs) love