wayland - ARE YOU IN THERE? (im not angry, im cupping my hands like im speaking into a cave)
This commit is contained in:
parent
af5f80da2c
commit
06c7ec0f4d
|
|
@ -37,11 +37,14 @@ fn main() {
|
|||
|
||||
#[cfg(all(target_os = "linux", feature = "wayland"))]
|
||||
{
|
||||
layers::wayland_shell::run();
|
||||
return;
|
||||
if layers::wayland_shell::try_run() {
|
||||
return;
|
||||
}
|
||||
tracing::warn!(
|
||||
"wayland provider failed to start; falling through to winit so the plugin still loads"
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(all(target_os = "linux", feature = "wayland")))]
|
||||
if let Err(e) = std::panic::catch_unwind(std::panic::AssertUnwindSafe(run)) {
|
||||
tracing::error!("layers shell panicked: {e:?}");
|
||||
std::process::exit(1);
|
||||
|
|
|
|||
22
src/ffi.rs
22
src/ffi.rs
|
|
@ -427,7 +427,6 @@ fn finalise_handle(
|
|||
let caps = surface.get_capabilities(&adapter);
|
||||
let format = caps.formats.first().copied()?;
|
||||
|
||||
// PostMultiplied so the Metal layer's alpha blends against the transparent NSWindow.
|
||||
let alpha_mode = if caps
|
||||
.alpha_modes
|
||||
.contains(&wgpu::CompositeAlphaMode::PostMultiplied)
|
||||
|
|
@ -445,6 +444,27 @@ fn finalise_handle(
|
|||
.unwrap_or(wgpu::CompositeAlphaMode::Auto)
|
||||
};
|
||||
|
||||
let adapter_info = adapter.get_info();
|
||||
tracing::info!(
|
||||
backend = ?adapter_info.backend,
|
||||
device_name = %adapter_info.name,
|
||||
format = ?format,
|
||||
all_formats = ?caps.formats,
|
||||
all_alpha_modes = ?caps.alpha_modes,
|
||||
chosen_alpha_mode = ?alpha_mode,
|
||||
"wgpu surface configured"
|
||||
);
|
||||
if matches!(
|
||||
alpha_mode,
|
||||
wgpu::CompositeAlphaMode::Opaque | wgpu::CompositeAlphaMode::Auto
|
||||
) {
|
||||
tracing::warn!(
|
||||
"wgpu chose {alpha_mode:?} — surface won't be transparent. \
|
||||
X11 needs PreMultiplied/PostMultiplied. Try a different wgpu backend (set WGPU_BACKEND=gl or =vulkan) \
|
||||
or check that the WM has a compositor running."
|
||||
);
|
||||
}
|
||||
|
||||
surface.configure(
|
||||
&device,
|
||||
&wgpu::SurfaceConfiguration {
|
||||
|
|
|
|||
|
|
@ -33,19 +33,21 @@ const DEFAULT_LOGICAL_SIZE: (u32, u32) = (480, 640);
|
|||
const MIN_LOGICAL_SIZE: (u32, u32) = (380, 220);
|
||||
const ANCHOR_MARGIN: i32 = 24;
|
||||
|
||||
/// Run the Wayland (sctk + wlr-layer-shell) front end. Compiled in only when the
|
||||
/// `wayland` feature is enabled — the build script picks the provider based on the
|
||||
/// running compositor.
|
||||
pub fn run() {
|
||||
tracing::info!("wayland: run entered");
|
||||
let conn = match Connection::connect_to_env() {
|
||||
Ok(c) => {
|
||||
tracing::info!("wayland: Connection::connect_to_env OK");
|
||||
c
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("wayland: connect_to_env failed ({e}); aborting");
|
||||
std::process::exit(1);
|
||||
/// Run the Wayland (sctk + wlr-layer-shell) front end. Returns `true` if it took
|
||||
/// over the session, `false` if init failed (wayland socket unreachable, no
|
||||
/// layer-shell, etc.) so the caller can fall through to the winit path. Hard
|
||||
/// exiting here would silently kill the plugin process inside KiCad — which the
|
||||
/// user sees as "didn't load."
|
||||
pub fn try_run() -> bool {
|
||||
tracing::info!("wayland: try_run entered");
|
||||
|
||||
let conn = match probe_connection() {
|
||||
Some(c) => c,
|
||||
None => {
|
||||
tracing::warn!(
|
||||
"wayland: no reachable compositor socket; falling through to winit"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -55,8 +57,8 @@ pub fn run() {
|
|||
pair
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("wayland: registry init failed ({e}); aborting");
|
||||
std::process::exit(1);
|
||||
tracing::warn!("wayland: registry init failed ({e}); falling through to winit");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
let qh = event_queue.handle();
|
||||
|
|
@ -69,8 +71,8 @@ pub fn run() {
|
|||
c
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!("wayland: wl_compositor missing ({e}); aborting");
|
||||
std::process::exit(1);
|
||||
tracing::warn!("wayland: wl_compositor missing ({e}); falling through to winit");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -80,10 +82,10 @@ pub fn run() {
|
|||
l
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::error!(
|
||||
"wayland: zwlr_layer_shell_v1 not advertised ({e}); compositor doesn't support layer-shell. Rebuild with --features x11."
|
||||
tracing::warn!(
|
||||
"wayland: zwlr_layer_shell_v1 not advertised ({e}); falling through to winit"
|
||||
);
|
||||
std::process::exit(1);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -112,8 +114,8 @@ pub fn run() {
|
|||
match NonNull::new(conn.backend().display_ptr() as *mut _) {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
tracing::error!("wayland: null display ptr");
|
||||
std::process::exit(1);
|
||||
tracing::warn!("wayland: null display ptr; falling through to winit");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
));
|
||||
|
|
@ -121,8 +123,8 @@ pub fn run() {
|
|||
match NonNull::new(layer.wl_surface().id().as_ptr() as *mut _) {
|
||||
Some(p) => p,
|
||||
None => {
|
||||
tracing::error!("wayland: null surface ptr");
|
||||
std::process::exit(1);
|
||||
tracing::warn!("wayland: null surface ptr; falling through to winit");
|
||||
return false;
|
||||
}
|
||||
},
|
||||
));
|
||||
|
|
@ -153,6 +155,7 @@ pub fn run() {
|
|||
break;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
struct State {
|
||||
|
|
@ -491,6 +494,69 @@ impl PointerHandler for State {
|
|||
}
|
||||
}
|
||||
|
||||
/// Find a wayland socket and connect, regardless of whether `WAYLAND_DISPLAY` is set.
|
||||
/// Inside flatpak the env var is often stripped even when the socket itself is bind-
|
||||
/// mounted into the sandbox at `$XDG_RUNTIME_DIR/wayland-*`. We list candidates,
|
||||
/// log everything we find, and try each in order.
|
||||
fn probe_connection() -> Option<Connection> {
|
||||
let runtime_dir = std::env::var_os("XDG_RUNTIME_DIR").map(std::path::PathBuf::from);
|
||||
tracing::info!(
|
||||
xdg_runtime_dir = ?runtime_dir,
|
||||
wayland_display_env = ?std::env::var_os("WAYLAND_DISPLAY"),
|
||||
"wayland: probing for compositor socket"
|
||||
);
|
||||
|
||||
if let Ok(c) = Connection::connect_to_env() {
|
||||
tracing::info!("wayland: connected via $WAYLAND_DISPLAY");
|
||||
return Some(c);
|
||||
}
|
||||
|
||||
let Some(dir) = runtime_dir else {
|
||||
tracing::warn!("wayland: $XDG_RUNTIME_DIR is unset; cannot scan for sockets");
|
||||
return None;
|
||||
};
|
||||
|
||||
let entries = match std::fs::read_dir(&dir) {
|
||||
Ok(e) => e,
|
||||
Err(e) => {
|
||||
tracing::warn!(dir = %dir.display(), "wayland: cannot list runtime dir: {e}");
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
let mut candidates: Vec<String> = Vec::new();
|
||||
for entry in entries.flatten() {
|
||||
let name = entry.file_name();
|
||||
let Some(name_str) = name.to_str() else { continue; };
|
||||
if !name_str.starts_with("wayland-") {
|
||||
continue;
|
||||
}
|
||||
// Skip lock files; we want the socket itself.
|
||||
if name_str.ends_with(".lock") {
|
||||
continue;
|
||||
}
|
||||
candidates.push(name_str.to_string());
|
||||
}
|
||||
candidates.sort();
|
||||
tracing::info!(?candidates, "wayland: socket candidates in $XDG_RUNTIME_DIR");
|
||||
|
||||
for name in &candidates {
|
||||
// Connection::connect_to_env reads $WAYLAND_DISPLAY; set it for one attempt.
|
||||
std::env::set_var("WAYLAND_DISPLAY", name);
|
||||
match Connection::connect_to_env() {
|
||||
Ok(c) => {
|
||||
tracing::info!(socket = name, "wayland: connected via probed socket");
|
||||
return Some(c);
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::debug!(socket = name, "wayland: probe failed: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn log_globals(globals: &GlobalList) {
|
||||
let list = globals.contents().clone_list();
|
||||
tracing::info!("wayland: registry advertises {} globals", list.len());
|
||||
|
|
|
|||
Loading…
Reference in New Issue