Screenshots
kiln has no screenshot object, format menu, or naming scheme. A screenshot is one function call: core.screenshot(name[, path]) reads back the composed scene of one output, everything the frame holds (clients, widgets, wallpaper). Everything else (which screen, which file, which key) is your config.
Snippets assume the standard config preamble:
local kiln = require("kiln")
local ui, key = kiln.ui, kiln.key
The primitive
local key = core.screenshot(screen.focused.name)
-- key == "screenshot:3", or nil if the output name is stale
The return value is an image-cache key: anywhere a file path works as an image source, this key works too. An unknown or unplugged output name returns nil; it never errors.
With a second argument, the capture is also written out as a PNG:
core.screenshot(screen.focused.name, "/tmp/shot.png")
Files land exactly where the path points. There is no default directory, so build the path yourself.
Full output on Print
Bind a key, stamp a filename with os.date, and call the save form:
key { mods = {}, key = "Print", desc = "screenshot", group = "screenshot",
press = function()
local dir = os.getenv("HOME") .. "/Pictures"
local dest = dir .. os.date("/screenshot-%Y%m%d-%H%M%S.png")
core.screenshot(screen.focused.name, dest)
end }
The directory, the timestamp format, and the trigger key are all yours to change. Add a kiln.spawn("notify-send ...") after the call if you want confirmation, or pipe the path to a clipboard tool.
core.screenshot is the one place these recipes reach below the kiln API into the core boundary. That is by design: reading back composed pixels is a compositor fact, and this is its single entry point.
Region capture with grim and slurp
For a region, use the standard Wayland pair: slurp draws an interactive selection, grim captures the geometry it prints. Spawn them as one shell pipeline:
key { mods = { "shift" }, key = "Print", desc = "screenshot region",
group = "screenshot",
press = function()
kiln.spawn("mkdir -p ~/Pictures && slurp | grim -g - " ..
"~/Pictures/screenshot-$(date +%Y%m%d-%H%M%S).png")
end }
kiln.spawn with a string runs the command through sh -c, so the pipe, the &&, and the $(date ...) stamp all work as written. This is the bundled config's binding.
An interactive-ish region bind
If you prefer a dedicated chord for deliberate, mouse-driven captures (separate from the reflex Shift+Print), bind the same pipeline to something like mod+ctrl+p:
key { mods = { "mod", "ctrl" }, key = "p", desc = "interactive screenshot",
group = "screenshot",
press = function()
kiln.spawn("mkdir -p ~/Pictures && slurp | grim -g - " ..
"~/Pictures/screenshot-$(date +%Y%m%d-%H%M%S).png")
end }
When it fires, the desktop dims under slurp's selection overlay; drag a rectangle and the file appears in ~/Pictures. Press Escape in slurp to abort, in which case grim never runs and nothing is written.
The capture as a live image
Because the return value is a cache key, a screenshot is usable as an image in the very frame it was taken, with no file at all. Capture the screen, then declare the key as a float's image fill:
local frozen = core.screenshot(s.name)
if frozen ~= nil then
ui.box({
id = "freeze",
image = { path = frozen },
float = { to = "root", band = "overlay" },
w = s.width, h = s.height,
})
end
That is the substrate for a freeze-frame to draw over: a dimmed backdrop for a custom lock screen, a zoom loupe, or a transition that holds the old scene while a new one builds. The wallpaper recipe is the same move in the other direction: an image into a band. Here the image is the screen itself.
See also
- core reference
- Wallpaper
- Keybindings tutorial
- Testing headless, where screenshots verify what a config drew