Rendering and fonts
Drawing problems inside the sandbox mostly come from three places: WebKitGTK’s rendering paths, apps that work out the screen’s size themselves, and toolkits that look for fonts their own way instead of asking fontconfig. The fixes are environment variables and a fonts configuration shipped with the package; check which toolkit the app uses before copying a fix from another one.
For agents
WebKitGTK (Tauri, Wails): blank, see-through, or crashing
| Symptom | Cause | Fix |
|---|---|---|
| The window opens blank or white on some GPUs | WebKitGTK’s DMABUF renderer fails in the sandbox with many drivers | export WEBKIT_DISABLE_DMABUF_RENDERER=1 in the wrapper (Tabularis) |
On GNOME 51 a transparent: true window shows the desktop through it; content only flashes while scrolling |
Without acceleration, WebKit on GNOME 51 doesn’t paint a transparent window’s background | The opposite of the above: keep acceleration on, WEBKIT_DISABLE_DMABUF_RENDERER="${WEBKIT_DISABLE_DMABUF_RENDERER:-0}" and the same for WEBKIT_DISABLE_COMPOSITING_MODE (Rayburst) |
| On GNOME 51 an opaque window’s web content dies when switching views; afterwards every start shows an empty window | The same unaccelerated path crashes WebKitWebProcess; the crash leaves IndexedDB in a state that kills it on every start |
Same fix. To recover a user, delete ~/.var/app/<id>/data/<tauri identifier>/databases |
- Check the app’s
src-tauri/tauri.conf.jsonfortransparentbefore choosing between the first two rows. - WebKit reads these variables by value, so
0means “don’t disable”. Writing them as${VAR:-0}leavesflatpak override --env=VAR=1to the user. - To see whether the web process is alive:
cat /proc/<app pid>/task/*/children. Only aWebKitNetworkProcessleft means the content process died. - Forcing X11 (
GDK_BACKEND=x11) doesn’t help with any of these; they are not Wayland problems. - Some apps add their own GPU guard that reads a preference and turns
acceleration off by default; setting both variables in the wrapper makes it
stand aside (Rayburst logs
external WebKitGTK rendering override).
The interface is tiny on a HiDPI screen
- GTK apps:
GDK_SCALE=2(integer) or the desktop’s scaling. - Qt apps:
QT_SCALE_FACTOR; a Qt build with only thexcbplugin runs through XWayland and followsXft.dpi. - Java apps:
-Dsun.java2d.uiScale=<n>in the app’s options, or the app’s own variable. - Apps that compute DPI from the screen’s size in millimetres (X11 only)
ignore all of the above: XWayland always reports a size that works out to
96 dpi. An app-specific setting is the fix when one exists; an
LD_PRELOADlibrary that answersXDisplayWidthMMfromXft.dpiworks, but injects code and is for closed-source apps only, declared. - Document the variable in the metainfo as a
flatpak override --env=…command; don’t set a fixed scale for everyone.
Boxes instead of characters (CJK and other scripts)
The runtime has no CJK fonts. The host’s fonts reach the sandbox under
/run/host/fonts, and the runtime’s /etc/fonts/fonts.conf points there
through conf.d/50-flatpak.conf. Toolkits that use libfontconfig find them;
toolkits that read font directories themselves don’t.
| Toolkit | Behaviour | Fix |
|---|---|---|
| GTK, Qt, Electron, Flutter | Real fontconfig, follows includes | Nothing; host fonts work |
| GPUI (Zed-style) and other cosmic-text / fontdb apps (iced, winit) | Parses one fontconfig file and only its <dir> entries, no includes |
Ship a fonts.conf listing every directory: /usr/share/fonts, /run/host/fonts, /run/host/local-fonts, /run/host/user-fonts, <dir prefix="xdg">fonts</dir>, ~/.fonts, and any font shipped as extra-data; export FONTCONFIG_FILE to it unconditionally (Navop) |
| Slint up to 1.16 | Two font databases: the app’s fontdb (as above) and Slint’s own, which scans only /usr/share/fonts and ~/.fonts |
Both: the fonts.conf above, and SLINT_DEFAULT_FONT=<directory with a CJK font> (meatshell) |
| Slint 1.17 and later | Uses real fontconfig, but its fallback chain needs a directory | SLINT_FONT_PATH=<directory>; SLINT_DEFAULT_FONT now takes a single file and silently ignores a directory |
- If a CJK font must ship with the package, pin it as extra-data; it is tens of megabytes.
- Override
FONTCONFIG_FILEunconditionally: a user’s own value is exactly what breaks it. Offer an app-specific escape (NAVOP_FONTCONFIG_FILE). fc-listinside the sandbox listing the font proves nothing for these toolkits; look at the rendered window.- The app’s log often says which font it chose (
RUST_LOG=<crate>=debug); a correct family name with boxes on screen means the second database (Slint) is the problem.
Crash at start inside fontconfig
A SIGSEGV before any window, with FT_Set_Var_Design_Coordinates and
tt_apply_mvar in the stack: the binary carries its own FreeType
(nm -D --defined-only <binary> | grep -c ' FT_' is non-zero), and the
runtime’s fontconfig ends up mixing two FreeTypes. Ordinary fonts work;
variable fonts crash.
Ship a fonts.conf that includes /etc/fonts/fonts.conf and rejects variable
fonts (<rejectfont> with globs *-VF.*, *_VF.*, *[*]*, *Variable*),
point FONTCONFIG_FILE at it, and run fc-cache before the app starts:
<rejectfont> only applies when fonts are added to the set, and the sandbox
rescans host fonts whose cache it can’t use.