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"))]
|
#[cfg(all(target_os = "linux", feature = "wayland"))]
|
||||||
{
|
{
|
||||||
layers::wayland_shell::run();
|
if layers::wayland_shell::try_run() {
|
||||||
return;
|
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)) {
|
if let Err(e) = std::panic::catch_unwind(std::panic::AssertUnwindSafe(run)) {
|
||||||
tracing::error!("layers shell panicked: {e:?}");
|
tracing::error!("layers shell panicked: {e:?}");
|
||||||
std::process::exit(1);
|
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 caps = surface.get_capabilities(&adapter);
|
||||||
let format = caps.formats.first().copied()?;
|
let format = caps.formats.first().copied()?;
|
||||||
|
|
||||||
// PostMultiplied so the Metal layer's alpha blends against the transparent NSWindow.
|
|
||||||
let alpha_mode = if caps
|
let alpha_mode = if caps
|
||||||
.alpha_modes
|
.alpha_modes
|
||||||
.contains(&wgpu::CompositeAlphaMode::PostMultiplied)
|
.contains(&wgpu::CompositeAlphaMode::PostMultiplied)
|
||||||
|
|
@ -445,6 +444,27 @@ fn finalise_handle(
|
||||||
.unwrap_or(wgpu::CompositeAlphaMode::Auto)
|
.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(
|
surface.configure(
|
||||||
&device,
|
&device,
|
||||||
&wgpu::SurfaceConfiguration {
|
&wgpu::SurfaceConfiguration {
|
||||||
|
|
|
||||||
|
|
@ -33,19 +33,21 @@ const DEFAULT_LOGICAL_SIZE: (u32, u32) = (480, 640);
|
||||||
const MIN_LOGICAL_SIZE: (u32, u32) = (380, 220);
|
const MIN_LOGICAL_SIZE: (u32, u32) = (380, 220);
|
||||||
const ANCHOR_MARGIN: i32 = 24;
|
const ANCHOR_MARGIN: i32 = 24;
|
||||||
|
|
||||||
/// Run the Wayland (sctk + wlr-layer-shell) front end. Compiled in only when the
|
/// Run the Wayland (sctk + wlr-layer-shell) front end. Returns `true` if it took
|
||||||
/// `wayland` feature is enabled — the build script picks the provider based on the
|
/// over the session, `false` if init failed (wayland socket unreachable, no
|
||||||
/// running compositor.
|
/// layer-shell, etc.) so the caller can fall through to the winit path. Hard
|
||||||
pub fn run() {
|
/// exiting here would silently kill the plugin process inside KiCad — which the
|
||||||
tracing::info!("wayland: run entered");
|
/// user sees as "didn't load."
|
||||||
let conn = match Connection::connect_to_env() {
|
pub fn try_run() -> bool {
|
||||||
Ok(c) => {
|
tracing::info!("wayland: try_run entered");
|
||||||
tracing::info!("wayland: Connection::connect_to_env OK");
|
|
||||||
c
|
let conn = match probe_connection() {
|
||||||
}
|
Some(c) => c,
|
||||||
Err(e) => {
|
None => {
|
||||||
tracing::error!("wayland: connect_to_env failed ({e}); aborting");
|
tracing::warn!(
|
||||||
std::process::exit(1);
|
"wayland: no reachable compositor socket; falling through to winit"
|
||||||
|
);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -55,8 +57,8 @@ pub fn run() {
|
||||||
pair
|
pair
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("wayland: registry init failed ({e}); aborting");
|
tracing::warn!("wayland: registry init failed ({e}); falling through to winit");
|
||||||
std::process::exit(1);
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let qh = event_queue.handle();
|
let qh = event_queue.handle();
|
||||||
|
|
@ -69,8 +71,8 @@ pub fn run() {
|
||||||
c
|
c
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!("wayland: wl_compositor missing ({e}); aborting");
|
tracing::warn!("wayland: wl_compositor missing ({e}); falling through to winit");
|
||||||
std::process::exit(1);
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -80,10 +82,10 @@ pub fn run() {
|
||||||
l
|
l
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
tracing::error!(
|
tracing::warn!(
|
||||||
"wayland: zwlr_layer_shell_v1 not advertised ({e}); compositor doesn't support layer-shell. Rebuild with --features x11."
|
"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 _) {
|
match NonNull::new(conn.backend().display_ptr() as *mut _) {
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
None => {
|
None => {
|
||||||
tracing::error!("wayland: null display ptr");
|
tracing::warn!("wayland: null display ptr; falling through to winit");
|
||||||
std::process::exit(1);
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
@ -121,8 +123,8 @@ pub fn run() {
|
||||||
match NonNull::new(layer.wl_surface().id().as_ptr() as *mut _) {
|
match NonNull::new(layer.wl_surface().id().as_ptr() as *mut _) {
|
||||||
Some(p) => p,
|
Some(p) => p,
|
||||||
None => {
|
None => {
|
||||||
tracing::error!("wayland: null surface ptr");
|
tracing::warn!("wayland: null surface ptr; falling through to winit");
|
||||||
std::process::exit(1);
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
));
|
));
|
||||||
|
|
@ -153,6 +155,7 @@ pub fn run() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State {
|
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) {
|
fn log_globals(globals: &GlobalList) {
|
||||||
let list = globals.contents().clone_list();
|
let list = globals.contents().clone_list();
|
||||||
tracing::info!("wayland: registry advertises {} globals", list.len());
|
tracing::info!("wayland: registry advertises {} globals", list.len());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue