Skip to content

Shell, Island and Launcher

Gaps in the Island, the Dock, the Launcher, notifications, the Desk and rendering.

  • niri and Umbriel are supported; Hyprland and Sway are not. Kanade selects a reachable Umbriel IPC socket first, then niri, and follows only the selected compositor’s event stream. Window and Strip Surfaces, the Dock, running apps, Launcher window selection, keybindings and compositor Settings support both. Under Umbriel the Dock lists and focuses those windows; closing one from the Dock does nothing, since Umbriel’s IPC client has no close that names a window. Umbriel screenshots use grim (and slurp for an area); window screenshots, the color picker, dynamic cast targets and Stop sharing through niri IPC remain niri-specific. Screen and window recording still require niri IPC for the focused output and window casts; area recording under Umbriel is unverified. The installer’s service activation remains tied to niri.service; Umbriel’s default config keeps autostart = ["kanade"]. Under Umbriel that entry starts kanade-recover, a non-rendering parent that restarts one rendering child and keeps acknowledged lock intent in memory so a locked replacement relocks without logind’s LockedHint. A persisted lock Module disable takes full effect after any inherited lock ends: recovery restores that lock with new lock controls, sleep handling and lock/unlock hooks off, then restarts once confirmed unlocked or refused. The parent itself is not restarted: abrupt parent death kills its child and loses intent, and a locked session stays blank. A hung child is not detected. Restart delay caps at 8 s; a crash before an unlock confirmation reaches the parent can conservatively relock. Live locked renderer-crash recovery and replacement-lock authentication were observed with the lock Module enabled and with a persisted disable on candidate 6ad11434ca099666dddf13ea32a519864503437d, binary SHA-256 43e16923ee0834fa297dfec0f4aa7862912e1747bd7522cb140c77bd77f22e2b. Replacement screenshots showed the lock, UI requests refused while locked, and the same parent retained ownership. In the disabled run, kanade lock status refused with module lock is off as the dispatch gate requires; that diagnostic cannot report the inherited lock. Replacement lock/unlock hooks added nothing to the pre-crash marker, and authentication led to a child with the Module fully off. Both runs restored the exact original shell after unlocking and left real settings untouched. No frames covered the short replacement gap: continuous privacy and no-desktop-flash remain unobserved. Live logout/compositor shutdown and niri acceptance remain NOT RUN; process-lifetime fixtures are automated evidence only. See ADR 0149. See Installation and ADR 0147.
  • No screen reader support. Kanade draws with the GPU and builds no accessibility tree, so the island never registers on the AT-SPI bus and Orca cannot see it. Checked on niri with Atspi.get_desktop(0): every other app is listed, Kanade is not. kanade ui (the ui Module) reads the same controls as a named tree for scripts, but it is not an AT-SPI tree and no screen reader reads it.
  • A fullscreen window covers the island, Critical Activities like low battery and a pomodoro moving on to its next phase included; only the OSD and an open Surface show over it. The island sits on the Top layer, which niri draws below fullscreen windows; maximized and windowed-fullscreen windows do not cover it. On Umbriel an open Surface raises the same way once the shown window is fullscreen and fills its output. See ADR 0006 and ADR 0021.
  • Files dropped on a Dock icon start the app with them only when its .desktop Exec has a %f, %F, %u or %U argument of its own and no Path; an app that takes one file at a time starts once per file, up to 8, and otherwise nothing starts and stderr says why. Paths go as they are, not as file:// links.
  • The Launcher closes as soon as an app is pressed, so an app that fails to start says why only on stderr, as the Dock’s does.
  • A Launcher query nothing answers offers Search Google for <query> and Open <query> in the browser, and pressing one is the only thing the Launcher does that leaves the machine: the query goes to Google, or to the browser as an address, in whatever xdg-open starts as the default browser. Kanade names no browser, reads no $BROWSER and keeps no setting for the search’s address, which is https://www.google.com/search?q= in the binary. Nothing is logged or remembered: the query and the address go nowhere but the opener, and no recents entry is kept. Without xdg-open neither row shows and the state says Needs xdg-open. Only a query of two letters or more is offered, and never one starting ?. See ADR 0130.
  • A Launcher command (caffeine, screenshot area, lock, dictate and the rest of its closed table) runs the Kanade verb of that name and waits for its answer before the island closes, up to 6 seconds; it takes no typed text, so a timed caffeine or a Do Not Disturb duration is the CLI’s. A refusal shows on the row as Not run: <why>; an answer that is unclear or late shows Not confirmed, may have run: <why>, so check before pressing it again. The screenshot and recording-start commands close the island first and run a moment later, so a refusal then shows as a failed Activity. Dictation from the Launcher may only copy its text, as the focused window is unknown while the Launcher holds the keyboard.
  • The Launcher calculator converts lengths, masses, volumes (US customary), areas, speeds, times, data sizes (KB is 1000 bytes, KiB 1024) and temperatures from a fixed table, and writes whole numbers up to 2^53 in hex, binary or octal. There is no currency, as that needs rates from the network, and no month or year, whose length varies. A % after a number is a percent, never a remainder. Sums show twelve significant digits, whole numbers below 1e15 in full.
  • Emoji show only from a color emoji font that holds them as pictures (CBDT or sbix), like Noto Color Emoji or Twemoji. Kanade’s text draws only outlined letters, so it draws the font’s picture instead; a COLR or SVG emoji font shows none, though copying still works. The Emoji Surface draws one where it can and the emoji as text where it cannot.
  • The charge limit needs UPower 1.90 or later and a battery whose driver supports charge thresholds; elsewhere its Controls tile does not show, and it is off by default (add charge-limit to controls.tiles) and kanade battery limit says it is unavailable. Kanade cannot set the threshold itself: UPower uses the one already set, or its default.
  • Without pactl, udevadm or dbus-monitor, the OSD, notification Banners and battery reads poll instead of waiting for the system to announce a change, adding up to about 23 CPU wakeups a second at idle. A backlight changed by firmware without a kernel uevent shows no brightness OSD. See ADR 0004.
  • Without setpriv from util-linux, helper processes like pactl, udevadm, dbus-monitor and pw-dump still work but may survive Kanade being killed abruptly. See ADR 0004.
  • Notification sounds: per-urgency sounds and per-rule sounds are set in config files only; Settings shows the switch, the default sound and the volume. The volume is the sound’s own stream (pw-play --volume, canberra-gtk-play -V in dB), never the system’s, and has not been checked against a live player. A rule’s sound beats a sender’s suppress-sound. There is no verb to play a test sound; notify-send does.
  • Inline reply (the KDE inline-reply action) works on Banners only, not in the Notifications Surface list. A click on the reply field gives the Banners window the keyboard until the Banner closes; Escape leaves the field, a click in another window returns the keyboard. Enter sends; the sender’s submit button text is ignored. A reply is cut to 2000 characters, held in memory only and never logged. A Banner with text typed stays until sent or closed, and moving focus to another output while typing drops the text. Without the banners Module the capability is not advertised.
  • The blur finish needs compositor support: niri 26.04 or later (ext-background-effect), or Umbriel with the blur-kanade layer rule (included in its supplied config). Without compositor blur support the panes are the opaque tinted solid. On niri, kanade doctor reports missing protocol support; niri blurs only the wallpaper behind a layer unless your config has the layer rule in Installation (xray false), and calls the effect it then makes experimental. The compositor’s blur has no rounded corners, so Kanade gives it rows of rects a pixel tall along each pane’s outline. A Banner blurs once its fade in is over, and stops as it fades out. Its ramp follows appearance.tone, dark with light text or light with dark ink; there is no ink flip over a bright or dark window, the pane’s fill alone keeps the text readable. See ADR 0057.
  • A failed reload of niri’s config (a parse error) shows on the Island for a few seconds as niri config: Failed - run niri validate, the failed form of a live Activity, so it needs the live Module on and says nothing more than that; niri’s own message and niri validate say what is wrong. It also shows when Kanade starts or reconnects after the last load failed. See ADR 0071.
  • The audio visualizer follows the default sink as a whole, not one player, and needs cava built with PulseAudio support. It is untested against a live cava in this release; without cava the synthetic bars draw. See ADR 0056.
  • Synced lyrics (media.lyrics) show on the Media Surface only, not on the Island’s Peek. A streaming player gives no file, so only lrclib can serve it, and only when it reports an album and a length. The lrclib lookup is untested against the live service in this release.
  • The desktop’s accessibility preferences come from the settings portal only (appearance.accessibility, ADR 0080): reduced motion and higher contrast, the latter only as a solid finish for the Island, Dock and Banners. It is untested against a live portal in this release. A file’s reduced_motion = false does not override a desktop that asks for less motion.
  • Moving an app to another output (the Route row in the Audio sub-surface, shown with two outputs) sets target.object in PipeWire’s default metadata with pw-metadata, which WirePlumber honours. It is untested against a live PipeWire in this release, and the choice is WirePlumber’s to keep or forget. See ADR 0081.
  • Brightness of an external monitor (brightness.backend) goes over DDC/CI, the monitor’s I2C bus. It needs the i2c-dev module and write access to /dev/i2c-*, and some monitors or docks do not answer. A monitor’s level is read once and kept, so its own buttons are not seen, and it can lag a new monitor by up to 10 s. One level is shown: that of the monitor under the focused output. It found no monitor on the NVIDIA card here, whose connector has no ddc link in /sys/class/drm (ddcutil reaches it); with the bus given, a read and a write worked on a Dell P1917S. See ADR 0082.
  • Apps’ launcher entry progress (launcher-entry Module, the Unity LauncherEntry signal) shows as a live Activity titled with the app’s name, at most 2 at once. Only progress-visible and progress are read: counts and the urgent flag are not shown. The signal is not authenticated, so any program on the session bus can claim to be an app; the name shown is the .desktop entry’s, not the signal’s. Few apps send it (Chromium and Firefox downloads, Nautilus, some others); it is untested against a live app in this release. See ADR 0083.
  • Input methods (fcitx5, ibus) work in Kanade’s text fields through the compositor’s text-input-v3: composing text shows inline with an underline, the candidate popup sits at the caret, and commits go in at the cursor. A password field is told its purpose and nothing of its text, and the lock screen has no input method. Without that protocol, keys and xkb compose (dead keys) are all there is. A field never scrolls, so a caret past its right edge is placed at the edge. Untested against a live input method in this release. See ADR 0090.
  • appearance.scale (80% to 200%) scales the whole shell live, at the runtime’s scale seam. A normal window already open (Settings) keeps its size and its content scales inside it, and the lock screen is not scaled. The Island’s canvas is cut to the output as ever. Untested against a live session in this release. See ADR 0091.
  • kanade ui names the controls of the Island (hover, action pill), the Dock and its menu, the Launcher, every Surface (Controls with its Wi-Fi, Bluetooth and Sound sub-surfaces and arrange mode, Notifications, Tray, Session, Timer, Capture, Clipboard, Calendar, Media, Weather, Wallpapers, Keys), Banners, the Desk’s media buttons and notes card (window desk: media/previous, media/play-pause, media/next, notes), the Settings window (pages, switches, choices, steppers, list entries, Reset, Undo, Inspect, the Weather place finder’s find place and use my location buttons and the place buttons of its matches, and a page’s scroll area) and every text field. A name is the control’s own (wifi, back, clear) or the key it sets in Settings (dock.merge/switch, appearance.tone/dark); the items of a list are row, entry, card, picture and the like, numbered (row#2) and renumbered as the list changes, since a network, device, app, title or file name is never a node’s name (under ui.describe = "content" it shows as the node’s content). Not covered: a control that takes a hold (the Clipboard’s Clear) has a node, but press is a tap and does nothing, as does key; an owned Calendar event’s remove button likewise takes a hold, so press on it removes nothing (its edit button is a plain press); what takes no click is described at most as a list or an event (the Keys’ rows, the Weather’s days) or not at all (a Bluetooth pairing code or PIN, which key can still answer); the Wi-Fi password field is a secret input that type can fill but describe never shows; the gesture overlay and the lock screen are never described. A slider is pressed at its middle. A control whose click is on a parent of what is named is reported covered. ui is refused while locked. press on a Bluetooth pair pill can accept a passkey confirmation without the code being readable from the tree (the code is never described); this is within the model that only you can reach the socket.
  • The gesture launcher (kanade gesture) takes the pointer on the focused output only, with the grab held until the stroke ends, Escape, a right click, 8 seconds or a lock. It recognizes one stroke with the $1 recognizer: the stroke’s start and direction matter (a circle drawn clockwise is not one drawn counterclockwise), a line drawn in any direction matches a line (turning is forgiven, so one gesture cannot be a line up and another a line across), and a gesture of several strokes is not supported. A stroke under 60 px long matches nothing. gestures.<name> is split on spaces with no quoting and runs only Kanade verbs; only verbs that act on the shell or the session’s state are accepted; ui and any verb added later are refused, as are those that wait on you (dmenu, capture color), run a program (activity run, activity hook), or belong to a program’s own Activity (activity actions|pressed|wait) or end the session (session logout|reboot|poweroff) are refused when the config is read. Your own commands go through hooks or a verb. A verb that needs keyboard focus runs just after the overlay lets go of it, which is untested on every compositor setup.
  • The buttons a program puts on a live Activity (kanade activity actions) are pointer-only and on Peek only: there is no Live Surface, so no key reaches them (kanade ui press does). On a 300 pt Peek the percent gives way and as many buttons as leave the title room are drawn, so a third may not show. Kanade runs nothing for a press; the program must read it back (activity pressed or wait). A press nobody reads waits (4 at most) until the Activity ends. activity run hears only a cancel action.
  • The Desk (desk.clock, desk.weather, desk.agenda, desk.media, desk.notes) is white text with no plate on the wallpaper, so it can be hard to read on a light one; move it with desk.clock_corner. It takes no click except the media buttons, the notes card and each face’s handle, and it is under every window and hidden in the selected compositor’s overview (niri or Umbriel). Weather is the forecast already fetched (needs the weather Module); the agenda is the next event’s time (needs calendar), and its title only with desk.agenda_titles. The track’s title and artist show only with desk.media_titles. The media buttons (desk.media, needs the media Module) are previous, play or pause and next for the player kanade media would ask; a button the player cannot act on is faded and passes the click through. With the pointer already over a button that can act, Left or Right draws a ring on those buttons and presses nothing; a later Enter or Space runs that button, and Escape clears the ring and drops the keyboard ask. A keybind does not focus the Desk. A note being typed and a held drag take their keys first. Otherwise use kanade media or the Media Surface. The ring is untested against a live session in this release. See ADR 0137.
  • A Desk face moves by the small faded bar at its inner edge, on the side away from the corner: a drag on it carries the face with the pointer, Escape puts it back, and a release keeps the place in desk.place per output, whole on the output a 48 px margin from its edges. Anything else on a face is what it was, so a click on the notes card still types into it; the bar takes no click, so kanade ui does not name it. A dragged face is kept clear of the Island’s current area when the output has room. Untested against a live niri in this release. See ADR 0143.
  • The notes card (desk.notes) is the Desk’s one face typed into in place, and the only part of the shell that asks niri to focus a Bottom layer surface: a click on the card takes the keyboard, which, untested against a live niri in this release, may not arrive. It shows the 5 newest notes, one line each, with an ellipsis on one too long for its line; the file keeps it whole. An empty card says Add a note, and the caret is a steady bar, not a blinking one, so a card nobody types into wakes nothing. A click starts a new note rather than editing an older one, so the notes are the ones typed, trimmed to 500 characters, the newest last, and a file another program writes over is read only when a card first draws, not followed. The text is white, so a light wallpaper can make it hard to read. It takes only keys, with no input method and no text-input-v3, so text an IME would compose never reaches it. Escape keeps what was typed; what the file holds lags the card by up to about a second, and a monitor unplugged mid-edit is saved as its card goes, so only a shell stopped at that moment loses that second. See ADR 0140.
  • A moving wallpaper (wallpaper.moving, off) moves only what the file itself says: a GIF or APNG of two pictures or more, told by its bytes rather than its name, paused while the session is locked, the selected compositor’s overview (niri or Umbriel) is open or a fullscreen window covers its output, and drawn on its own window behind everything but ahead of what awww drew. A file over 64 MiB or with more than 3000 pictures, or one that fails to decode, stays with awww once, without its path; a still wallpaper goes through awww exactly as before, as do the palette, the lock screen’s reading of the file and every wallpaper hook. No per-frame file is read or encoded, and no second process draws a frame.