← Otto User GuideTheming
Otto’s look is set entirely from the config file. There is no theme picker GUI.
Light and dark
theme_scheme = "Light" # or "Dark"
This drives the compositor’s own chrome — the dock, app switcher, exposé,
workspace selector — and is also exported to applications through the XDG
Desktop Portal Settings interface as org.freedesktop.appearance color-scheme.
That means GTK apps, Firefox, Chromium, Electron apps and the top bar all follow this one setting, and switch within about a second when you change it. No restart needed for clients that listen for the change signal.
For this to work, the Otto portal backend must be selected for the Settings
interface — see Screen Sharing, which covers
the same portals.conf.
# gtk_theme = "Adwaita"
gtk_theme is recorded for reference only; Otto does not apply it. Set your GTK
theme the usual way (gsettings, ~/.config/gtk-3.0/settings.ini).
Accent colour
accent_color = "blue"
The accent tints selection borders in the workspace selector, the exposé window
highlight, and the controls in Otto’s own apps — toggles, sliders, focus rings
and selected rows. Applications outside Otto can follow it too: it is published
as accent-color in the org.freedesktop.appearance portal namespace.
Changing it takes effect immediately; no restart is needed. Available values:
red, orange, yellow, green, mint, teal, cyan, blue, indigo,
purple, pink, gray, brown
A named accent follows the light and dark palettes, shifting to the right shade for the current scheme. You can also give a hex literal for a colour the palette has no name for:
accent_color = "#7fd4e6"
#RGB and #RRGGBB are both accepted, and the # is required — it is what
tells a colour from a name. A literal is used exactly as written in both
schemes.
Rounded corners
rounded_corners = true
Rounds the corners of the dock, the top bar, Otto-drawn window decorations and
the desktop’s own panels. Set it to false for square corners throughout. It
takes effect after a restart.
Wallpaper
background_image = "/usr/share/otto/background.jpg"
background_color = "#2c2ca0"
background_image is an absolute path to the image shown on the desktop.
It is scaled to cover the screen, and decoded at the resolution of the largest
monitor, so a wallpaper at least as large as your display stays sharp; a much
larger one is resampled down once at load rather than kept at full size.
background_color is the fallback: when the image is missing or fails to load,
Otto draws a gradient using this as the bottom colour. It is worth setting to
something you like even if you use an image.
The wallpaper is global — the same on every monitor and every workspace.
Otto also supports the wlr-layer-shell background layer, so wallpaper daemons
like swaybg and swww work if you want animated or per-monitor backgrounds:
[[exec_once]]
cmd = "swaybg"
args = ["-i", "/path/to/wallpaper.jpg", "-m", "fill"]
Fonts
font_family = "Inter"
The font used by Otto’s own UI — dock tooltips, exposé window titles, the app switcher. Applications use their own font settings; this does not change them.
Otto ships with Inter as its default. Any font installed on the system works.
Cursor
cursor_theme = "Notwaita-Black"
cursor_size = 24
Cursor theme names are the directory names under /usr/share/icons/ and
~/.local/share/icons/, and they are case-sensitive. Check what you have:
ls /usr/share/icons ~/.local/share/icons
Otto also implements wp-cursor-shape-v1, so applications that use the modern
cursor-shape protocol get themed cursors without shipping their own bitmaps.
Icon theme
icon_theme = "Adwaita"
Used for application icons in the dock, the app switcher and notification islands. Commented out or absent, Otto auto-detects a reasonable theme from what is installed.
Popular choices: Adwaita, Papirus, WhiteSur, Fluent. Otto’s own
screenshots use the
Fluent icon theme.
Icons are looked up per the freedesktop icon theme specification, including inheritance — a theme that lacks an icon falls back to its parent.
Language
locales = ["en_US", "en"]
Preferred languages for application names and descriptions read from .desktop
files. Use standard locale identifiers, most specific first, and prefer the
region-qualified form (lang_COUNTRY): ["fr_FR", "fr"] means “French (France)
if the entry has that variant, plain French otherwise, English as the ultimate
fallback from the entry’s untranslated name”. Matching follows the freedesktop
Desktop Entry spec and falls back automatically from region to bare language, so
listing both zh_CN and zh catches entries that localize either form.
This affects names shown in the dock, app switcher and menus. It does not change Otto’s own UI language.
A worked example
A dark HiDPI setup:
screen_scale = 2.0
theme_scheme = "Dark"
accent_color = "purple"
font_family = "Inter"
background_image = "/home/me/Pictures/wallpaper.jpg"
background_color = "#101018"
cursor_theme = "Adwaita"
cursor_size = 32
icon_theme = "Papirus-Dark"
locales = ["en_US", "en"]
Troubleshooting
Icon or cursor theme not found. Names are case-sensitive and must match the
directory name exactly. Check with ls /usr/share/icons/. Some themes need a
separate package for their cursor variant.
Applications ignore light/dark. They read it from the XDG Settings portal,
which needs xdg-desktop-portal running with Otto selected for
org.freedesktop.impl.portal.Settings in your portals.conf. Verify with:
gdbus call --session --dest org.freedesktop.portal.Desktop \
--object-path /org/freedesktop/portal/desktop \
--method org.freedesktop.portal.Settings.Read \
org.freedesktop.appearance color-scheme
1 means dark, 2 means light, 0 means no preference.
The wallpaper is a gradient instead of my image. The path is wrong or
unreadable. Check the log — Otto reports the failure and falls back to
background_color.
Not yet supported
- Per-monitor or per-workspace wallpaper
- Automatic light/dark switching by time of day
- Animated wallpaper without an external daemon