From 418e0a5f2fa864f4515f34398791511859b32201 Mon Sep 17 00:00:00 2001 From: clover caruso Date: Thu, 1 Oct 2026 14:09:53 -0700 Subject: [PATCH] fix: without libxkbcommon, Snowbound says what to install instead of crashing winit unwraps its keyboard context, so a missing libxkbcommon (or, on X11, libxkbcommon-x11) panicked at the first key or at start. Snowbound checks first and stops with the package to install. Assisted-by: claude-opus-5.5 --- crates/snowbound/src/linux.rs | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/crates/snowbound/src/linux.rs b/crates/snowbound/src/linux.rs index d2aa5244693dfe963c0f04adac79634b47d745d9..04a4a5b02351d2b5847c7423d84a50ae00d06728 100644 --- a/crates/snowbound/src/linux.rs +++ b/crates/snowbound/src/linux.rs @@ -4,6 +4,7 @@ use canvas::date::DateField; use std::{ + error::Error, ffi::CStr, path::PathBuf, process::Command, @@ -15,7 +16,6 @@ use std::{ }; use ui::{Flags, Spec, Ui, px}; use winit::{ - error::EventLoopError, event_loop::{EventLoop, EventLoopProxy}, platform::{ wayland::{EventLoopExtWayland, WindowAttributesExtWayland}, @@ -41,17 +41,31 @@ static QUIT: OnceLock> = OnceLock::new(); /// KWin leaves windows square. static BREEZE_RADIUS: AtomicU32 = AtomicU32::new(0); -pub fn event_loop(headless: bool) -> Result, EventLoopError> { +pub fn event_loop(headless: bool) -> Result, Box> { // Month and day names and date orders follow the user's locale; other categories stay C. unsafe { libc::setlocale(libc::LC_TIME, c"".as_ptr()) }; let mut builder = EventLoop::with_user_event(); // winit takes Wayland wherever a compositor is named, even without libwayland-client. let named = |names: &[&str]| names.iter().any(|name| std::env::var_os(name).is_some()); - if named(&["WAYLAND_DISPLAY", "WAYLAND_SOCKET"]) - && named(&["DISPLAY"]) - && !crate::loader::loads(c"libwayland-client.so.0") - { + let mut x11 = !named(&["WAYLAND_DISPLAY", "WAYLAND_SOCKET"]); + if !x11 && named(&["DISPLAY"]) && !crate::loader::loads(c"libwayland-client.so.0") { builder.with_x11(); + x11 = true; + } + // winit panics on the keyboard without them. + let keyboard: &[(&CStr, &str)] = if x11 { + &[ + (c"libxkbcommon.so.0", "libxkbcommon"), + (c"libxkbcommon-x11.so.0", "libxkbcommon-x11"), + ] + } else { + &[(c"libxkbcommon.so.0", "libxkbcommon")] + }; + if let Some((_, package)) = keyboard + .iter() + .find(|(library, _)| !crate::loader::loads(library)) + { + return Err(format!("Install {package} to start Snowbound.").into()); } let event_loop = builder.build()?; if !headless { -- 2.54.0