Let's try something else (wayland)

This commit is contained in:
jess 2026-04-25 13:49:11 -07:00
parent 6f31cf779b
commit 24054058ad
2 changed files with 145 additions and 18 deletions

View File

@ -27,18 +27,33 @@ fn main() {
tracing::info!(
plugin_root = ?plugin_root,
log_dir = ?layers::paths::log_dir(),
"layers shell: starting native event loop",
);
log_session_env();
#[cfg(target_os = "linux")]
{
if std::env::var_os("WAYLAND_DISPLAY").is_some() {
if layers::wayland_shell::try_run() {
return;
let wayland_display = std::env::var("WAYLAND_DISPLAY").ok();
match wayland_display.as_deref() {
Some(name) => {
tracing::info!(
wayland_display = name,
"shell route: WAYLAND_DISPLAY set; trying sctk + wlr-layer-shell"
);
if layers::wayland_shell::try_run() {
tracing::info!("shell route: wayland branch handled the session");
return;
}
tracing::warn!(
"shell route: wayland branch declined (no layer-shell?); forcing WINIT_UNIX_BACKEND=x11 and falling through to winit"
);
std::env::set_var("WINIT_UNIX_BACKEND", "x11");
}
None => {
tracing::info!("shell route: no WAYLAND_DISPLAY; using winit directly (X11 path)");
}
// Wayland up but no layer-shell (mutter/GNOME): use XWayland via winit's
// X11 backend so the existing X11 always-on-top path applies.
std::env::set_var("WINIT_UNIX_BACKEND", "x11");
}
}
@ -48,6 +63,52 @@ fn main() {
}
}
fn log_window_kind(handle: &raw_window_handle::RawWindowHandle) -> &'static str {
use raw_window_handle::RawWindowHandle::*;
match handle {
Wayland(_) => "wayland",
Xlib(_) => "xlib",
Xcb(_) => "xcb",
Win32(_) => "win32",
AppKit(_) => "appkit",
UiKit(_) => "uikit",
_ => "other",
}
}
fn log_display_kind(handle: &raw_window_handle::RawDisplayHandle) -> &'static str {
use raw_window_handle::RawDisplayHandle::*;
match handle {
Wayland(_) => "wayland",
Xlib(_) => "xlib",
Xcb(_) => "xcb",
Windows(_) => "windows",
AppKit(_) => "appkit",
UiKit(_) => "uikit",
_ => "other",
}
}
fn log_session_env() {
let keys = [
"WAYLAND_DISPLAY",
"DISPLAY",
"XDG_SESSION_TYPE",
"XDG_CURRENT_DESKTOP",
"XDG_SESSION_DESKTOP",
"DESKTOP_SESSION",
"WINIT_UNIX_BACKEND",
"GDK_BACKEND",
"QT_QPA_PLATFORM",
];
for k in keys {
match std::env::var(k) {
Ok(v) => tracing::info!(env = k, value = %v, "session env"),
Err(_) => tracing::info!(env = k, value = "<unset>", "session env"),
}
}
}
fn run() {
let event_loop = EventLoop::new().expect("winit: create event loop");
event_loop.set_control_flow(ControlFlow::Wait);
@ -122,6 +183,12 @@ impl ApplicationHandler for ShellApp {
.expect("winit: display handle")
.as_raw();
tracing::info!(
window_handle = log_window_kind(&raw_window),
display_handle = log_display_kind(&raw_display),
"winit window up"
);
tracing::info!(
"creating viewport handle: {}x{} @ {}",
inner.width,

View File

@ -24,7 +24,7 @@ use smithay_client_toolkit::{
};
use std::ptr::NonNull;
use wayland_client::{
globals::registry_queue_init,
globals::{registry_queue_init, GlobalList},
protocol::{wl_keyboard, wl_output, wl_pointer, wl_seat, wl_surface},
Connection, Proxy, QueueHandle,
};
@ -38,16 +38,23 @@ const ANCHOR_MARGIN: i32 = 24;
/// available or the compositor doesn't advertise wlr-layer-shell, so the caller can
/// fall through to the winit/X11 path.
pub fn try_run() -> bool {
tracing::info!("wayland: try_run entered");
let conn = match Connection::connect_to_env() {
Ok(c) => c,
Err(_) => {
tracing::info!("wayland: no WAYLAND_DISPLAY, falling through to X11");
Ok(c) => {
tracing::info!("wayland: Connection::connect_to_env OK");
c
}
Err(e) => {
tracing::info!("wayland: connect_to_env failed ({e}); falling through to X11");
return false;
}
};
let (globals, mut event_queue) = match registry_queue_init::<State>(&conn) {
Ok(pair) => pair,
Ok(pair) => {
tracing::info!("wayland: registry_queue_init OK");
pair
}
Err(e) => {
tracing::warn!("wayland: registry init failed ({e}); falling through to X11");
return false;
@ -55,19 +62,27 @@ pub fn try_run() -> bool {
};
let qh = event_queue.handle();
log_globals(&globals);
let compositor = match CompositorState::bind(&globals, &qh) {
Ok(c) => c,
Err(_) => {
tracing::warn!("wayland: wl_compositor missing; falling through to X11");
Ok(c) => {
tracing::info!("wayland: bound wl_compositor");
c
}
Err(e) => {
tracing::warn!("wayland: wl_compositor missing ({e}); falling through to X11");
return false;
}
};
let layer_shell = match LayerShell::bind(&globals, &qh) {
Ok(l) => l,
Err(_) => {
Ok(l) => {
tracing::info!("wayland: bound zwlr_layer_shell_v1");
l
}
Err(e) => {
tracing::warn!(
"wayland: zwlr_layer_shell_v1 not advertised (likely GNOME/mutter); falling through to X11"
"wayland: zwlr_layer_shell_v1 not advertised ({e}; likely GNOME/mutter); falling through to X11"
);
return false;
}
@ -86,6 +101,13 @@ pub fn try_run() -> bool {
layer.set_margin(ANCHOR_MARGIN, ANCHOR_MARGIN, 0, 0);
layer.set_keyboard_interactivity(KeyboardInteractivity::OnDemand);
layer.commit();
tracing::info!(
anchor = "TOP|RIGHT",
size = ?(DEFAULT_LOGICAL_SIZE.0, DEFAULT_LOGICAL_SIZE.1),
margin_top = ANCHOR_MARGIN,
margin_right = ANCHOR_MARGIN,
"wayland: layer surface committed (waiting for first configure)"
);
let raw_display = RawDisplayHandle::Wayland(WaylandDisplayHandle::new(
match NonNull::new(conn.backend().display_ptr() as *mut _) {
@ -264,12 +286,21 @@ impl LayerShellHandler for State {
qh: &QueueHandle<Self>,
_layer: &LayerSurface,
configure: LayerSurfaceConfigure,
_serial: u32,
serial: u32,
) {
let (w, h) = configure.new_size;
let new_w = if w == 0 { self.width } else { w };
let new_h = if h == 0 { self.height } else { h };
let resized = new_w != self.width || new_h != self.height;
tracing::info!(
serial,
requested_w = w,
requested_h = h,
applied_w = new_w,
applied_h = new_h,
first = self.first_configure,
"wayland: configure"
);
self.width = new_w;
self.height = new_h;
@ -282,6 +313,7 @@ impl LayerShellHandler for State {
if self.first_configure {
self.first_configure = false;
tracing::info!("wayland: first configure → kicking initial render");
self.render(qh);
}
}
@ -462,6 +494,34 @@ impl PointerHandler for State {
}
}
fn log_globals(globals: &GlobalList) {
let list = globals.contents().clone_list();
tracing::info!("wayland: registry advertises {} globals", list.len());
let mut seen_layer_shell = false;
let mut seen_compositor = false;
let mut seen_seat = false;
for g in &list {
tracing::debug!(
interface = %g.interface,
name = g.name,
version = g.version,
"wayland global"
);
match g.interface.as_str() {
"zwlr_layer_shell_v1" => seen_layer_shell = true,
"wl_compositor" => seen_compositor = true,
"wl_seat" => seen_seat = true,
_ => {}
}
}
tracing::info!(
layer_shell = seen_layer_shell,
compositor = seen_compositor,
seat = seen_seat,
"wayland: protocol summary"
);
}
fn map_button(button: u32) -> Option<u32> {
match button {
0x110 => Some(0), // BTN_LEFT