Skip to content

fix(plugins): open Linux plugin editors in native X11 windows - #66

Merged
Horuse merged 4 commits into
mainfrom
feat/linux-x11-editors
Oct 19, 2026
Merged

Horuse merged 4 commits into
mainfrom
feat/linux-x11-editors

Conversation

@Horuse

@Horuse Horuse commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

What does this PR do?

Plugin editors now open on Linux without forcing the whole app onto XWayland.

VST3 and CLAP editors on Linux can only be parented into an X11 window. The editor window used to be a Tauri/GTK window. On a native Wayland session it has no X11 handle at all. On X11/XWayland it also failed, because the window was hidden and never realized, so GTK had not created the native window yet.

On Linux, editor windows are now plain X11 windows. They are created with x11rb on our own connection to $DISPLAY, which on a Wayland session is XWayland. The main UI stays native Wayland; only plugin editors go through X11.

  • editor_x11.rs: creates, shows, hides and destroys the X11 toplevel; sets the title (_NET_WM_NAME), min size (WM_NORMAL_HINTS) and close (WM_DELETE_WINDOW); scale is Xft.dpi / 96.
  • EditorWindow in editor.rs wraps the platform window. macOS and Windows keep tauri::Window with no behaviour change.
  • PluginHost::embed_editor takes &EditorWindow. CLAP, VST3 and AU are updated.
  • The close request arrives as an X11 event. It is drained on the shared plugin tick and handled like Tauri's CloseRequested.
  • If there is no X display, the app returns an explicit error and does not fall back to anything.
  • editor_x11.rs also sets WM_CLASS, so the WM groups editors with the app; reopening an editor raises and activates it via _NET_ACTIVE_WINDOW; a dropped X connection is logged instead of silently stopping close handling.
  • VST3 views get the display scale through IPlugViewContentScaleSupport::setContentScaleFactor, set before the first getSize, like CLAP's set_scale. Before this, VST3 editors on Linux rendered at 1x. Not called on macOS, where Cocoa scales itself.

Why is this the right approach?

Alternatives considered and rejected:

  • Realizing the GTK window (fix(plugins): realize the Linux editor window before embedding #61): fixes X11/XWayland, but the app would still need GDK_BACKEND=x11.
  • Forcing GDK_BACKEND=x11 for the whole app: the entire UI goes through XWayland and gets blurry under fractional scaling.
  • Hosting editors in a separate helper process: the plugin's GUI and DSP are one object, so the whole instance would have to move out of process and its audio go over IPC. That is a lot more work for the same result.

Plugins on Linux always open their own X connection, whatever host they run in. They only need the XID of the parent window, so which toolkit created that window makes no difference to them.

Dependency: x11rb = "0.13", Linux only. GTK cannot create an X11 window on a Wayland session. x11rb was already in the tree transitively, so Cargo.lock gains one line and no new crates.

Checklist

  • Diff is limited to the change — no unrelated edits
  • bun run check passes
  • cargo check --manifest-path src-tauri/Cargo.toml passes
  • bun run format leaves the tree clean
  • Generated TS types are committed with the Rust change (if any) — none changed
  • No new dependency without a reason in the PR description
  • I read the RT audio path section of docs/CONCEPT.md and confirmed this change adds no allocations, locks, or syscalls to cpal / SCK callbacks or DspWorker::run. Everything runs on the main thread: editor open/close and the existing 16 ms plugin tick

Platform coverage

  • Developed on: macOS
  • Tested on: Fedora 44 aarch64 (VM), GNOME on native Wayland, 3840x2160 HiDPI (Xft.dpi 288), no GDK_BACKEND override
  • What I did to test: opened VST3 and CLAP editors (SimpleTone, nih-plug). They render at the display scale and take input. Before the scale fix the VST3 editor opened at 1x. Closing from the window's close button works, and it reopens. Changing parameters no longer crashes the app. On macOS: cargo check, bun run check
  • Not tested: Windows, KDE, native X11 session on my side

Per-OS files: src-tauri/src/audio/plugins/editor_x11.rs (new, Linux only). editor.rs has #[cfg] branches per platform. On macOS and Windows the window is the same tauri::Window as before. au_host.rs (macOS only) changes only the type and goes through EditorWindow::tauri().

Related

@ushiocheng

ushiocheng commented Oct 19, 2026 •

Copy link
Copy Markdown

Tested with build at commit 020ac18

Works with a VST3 plugin on

  • Ubuntu 22.04, GNOME, X11
  • Debian 13, GNOME, both Wayland and xWayland, with HiDPI

HiDPI: The plugin editor appears to render at 1× scale rather than following GNOME's display scaling. I'm not sure whether this is a host-side issue, a plugin limitation, or something I've missed.
One thing I noticed while digging with Claude is VST3 path doesn't appear to set scale factor like CLAP here. I am not too familiar with linux audio or this codebase to suggest or validate a fix.

let scale = window.scale_factor();
let _ = gui.set_scale(&mut self.instance.plugin_handle(), scale);

@Horuse

Horuse commented Oct 19, 2026

Copy link
Copy Markdown
Owner Author

Fixed and checked on Fedora 44 with GNOME Wayland and HiDPI. The VST3 editor now opens at the right size

@Horuse
Horuse merged commit b9eeebe into main Oct 19, 2026
9 checks passed
@Horuse
Horuse deleted the feat/linux-x11-editors branch October 19, 2026 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants