Appease X11 users with niri/wayland specific postfixup wrapper (#212)
* Appease X11 users with niri/wayland specific postfixup wrapper * Linux: stay on native Wayland under niri in the app, not the Nix wrapper Move the niri check from the flake's wrapper into apps/solvecraft/src/main.rs next to the XWayland default, so it applies to every niri user, not only Nix builds (flake.nix is back to main's, which also clears the conflict with #210). SOLVECRAFT_WAYLAND=1 still keeps native Wayland, and =0 now forces XWayland. docs/nix.md notes the trade-off: no file drag-and-drop on native Wayland. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT --------- Co-authored-by: bherbruck <[email protected]> Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
2 files changed
+58
-4
No files matched your search
@@ -175,10 +175,12 @@ fn main() -> eframe::Result {
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
let mut options = options;
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
// winit has no file drag-and-drop on Wayland (only on X11), so dropping files from the file
|
||||
// manager showed a "no" cursor. Run through XWayland when it's there; SOLVECRAFT_WAYLAND=1
|
||||
// keeps the native Wayland backend.
|
||||
if std::env::var_os("DISPLAY").is_some() && std::env::var_os("SOLVECRAFT_WAYLAND").is_none() {
|
||||
if prefer_x11(
|
||||
std::env::var_os("DISPLAY").is_some(),
|
||||
std::env::var_os("WAYLAND_DISPLAY").is_some(),
|
||||
std::env::var("XDG_CURRENT_DESKTOP").ok().as_deref(),
|
||||
std::env::var("SOLVECRAFT_WAYLAND").ok().as_deref(),
|
||||
) {
|
||||
options.event_loop_builder = Some(Box::new(|b| {
|
||||
use winit::platform::x11::EventLoopBuilderExtX11;
|
||||
b.with_x11();
|
||||
@@ -236,6 +238,45 @@ fn main() -> eframe::Result {
|
||||
)
|
||||
}
|
||||
|
||||
/// Whether to run through XWayland rather than native Wayland. winit has no file drag-and-drop
|
||||
/// on Wayland (only on X11), so dropping files from the file manager showed a "no" cursor: use
|
||||
/// XWayland when it's there. Except on niri, whose XWayland (xwayland-satellite) breaks window
|
||||
/// management (maximize/restore), so it stays on native Wayland and gives up file drops.
|
||||
/// `SOLVECRAFT_WAYLAND=1` keeps native Wayland, `SOLVECRAFT_WAYLAND=0` forces XWayland.
|
||||
#[cfg(all(unix, not(target_os = "macos")))]
|
||||
fn prefer_x11(display: bool, wayland_display: bool, desktop: Option<&str>, wayland_override: Option<&str>) -> bool {
|
||||
match wayland_override.map(str::trim) {
|
||||
Some("0") => return display,
|
||||
Some(_) => return false,
|
||||
None => {}
|
||||
}
|
||||
let niri = desktop.is_some_and(|d| d.split(':').any(|name| name.trim().eq_ignore_ascii_case("niri")));
|
||||
display && !(niri && wayland_display)
|
||||
}
|
||||
|
||||
#[cfg(all(test, unix, not(target_os = "macos")))]
|
||||
mod backend_tests {
|
||||
use super::prefer_x11;
|
||||
|
||||
#[test]
|
||||
fn xwayland_by_default_native_wayland_on_niri_and_the_override_wins() {
|
||||
// XWayland whenever there's an X display, for file drag-and-drop.
|
||||
assert!(prefer_x11(true, true, Some("GNOME"), None));
|
||||
assert!(prefer_x11(true, false, None, None));
|
||||
assert!(!prefer_x11(false, true, Some("KDE"), None));
|
||||
// niri (alone or in a desktop list) under Wayland stays native.
|
||||
assert!(!prefer_x11(true, true, Some("niri"), None));
|
||||
assert!(!prefer_x11(true, true, Some("niri:GNOME"), None));
|
||||
// niri without a Wayland socket (nested X session) still uses X11.
|
||||
assert!(prefer_x11(true, false, Some("niri"), None));
|
||||
// SOLVECRAFT_WAYLAND: anything but 0 keeps Wayland, 0 forces XWayland (when present).
|
||||
assert!(!prefer_x11(true, true, Some("GNOME"), Some("1")));
|
||||
assert!(!prefer_x11(true, true, Some("GNOME"), Some("")));
|
||||
assert!(prefer_x11(true, true, Some("niri"), Some("0")));
|
||||
assert!(!prefer_x11(false, true, Some("niri"), Some("0")));
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod icon_tests {
|
||||
#[test]
|
||||
|
||||
+13
@@ -87,6 +87,19 @@ For older builds, including 0.3.0, set Anti-aliasing to 1x and restart when usin
|
||||
If that window cannot show the settings dialog, edit only the `msaa` field to `1` in
|
||||
`~/.local/share/solvecraft/graphics.json`; preserve any other settings.
|
||||
|
||||
## Wayland, XWayland and niri
|
||||
|
||||
On Linux the app runs through XWayland whenever an X display is available, because
|
||||
winit only supports dragging files from a file manager into the window on X11. On
|
||||
niri (detected from `XDG_CURRENT_DESKTOP` with a Wayland socket present) it stays on
|
||||
native Wayland instead, since window management such as maximize/restore misbehaves
|
||||
under niri's XWayland. The trade-off: **on native Wayland, dropping files onto the
|
||||
window does not work**; use File > Open or pass the file on the command line.
|
||||
This applies to every build, not only the Nix package.
|
||||
|
||||
Override the choice with `SOLVECRAFT_WAYLAND=1` (always native Wayland) or
|
||||
`SOLVECRAFT_WAYLAND=0` (XWayland whenever an X display is available).
|
||||
|
||||
## Development shells
|
||||
|
||||
`nix develop` supplies runtime libraries and uses the Rust/C toolchain already on
|
||||
|
||||
Reference in new issue
Block a user