ltk/event_loop/error.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
// SPDX-License-Identifier: LGPL-2.1-only
// Copyright (C) 2026 Liberux Labs, S. L. <info@liberux.net>
/// Reasons [`crate::try_run`] (and therefore [`crate::run`]) can fail
/// to bring up the event loop.
///
/// Every variant maps to a fatal failure during init: the Wayland
/// connection, the calloop event loop, one of the protocol bindings
/// the runtime cannot operate without (`wl_compositor`, `wl_shm`,
/// `xdg_wm_base`), or on Android the missing `AndroidApp`. Once init succeeds, the compositor disconnecting
/// (`BrokenPipe` / `ConnectionReset`) is treated as a clean exit; any
/// other runtime error during the dispatch loop still panics, since the
/// surface is already on screen and the state machine cannot be unwound
/// from this entry point.
///
/// Embedders that want a software-rendered fallback or that need to
/// degrade gracefully should call [`crate::try_run`] and match on the
/// variants instead of letting [`crate::run`] panic.
#[ derive( Debug ) ]
pub enum RunError
{
/// `WAYLAND_DISPLAY` is unset, the socket is missing, or the
/// compositor refused the handshake. Includes the detailed reason
/// from the underlying `wayland-client` error.
NoWaylandConnection( String ),
/// The Wayland registry could not be enumerated. Almost always a
/// compositor / driver bug — the registry is the first thing every
/// Wayland client touches.
RegistryInit( String ),
/// `calloop`'s `EventLoop::try_new` or its Wayland source insertion
/// failed (typically an `io` error talking to the kernel).
EventLoop( String ),
/// A required Wayland protocol is missing from the compositor.
/// `name` is the wire-format protocol name; `detail` is the
/// underlying bind error.
MissingProtocol
{
name: &'static str,
detail: String,
},
/// On Android, `ltk::run` was called before `android_main` handed
/// its `AndroidApp` to `ltk::set_android_app`.
NoAndroidApp,
/// In a browser, `ltk::run` was called where there is no page:
/// no `window` or `document`, as in a worker.
NoDocument,
/// In a browser, the page's desktop (forge/web) refused the main
/// surface.
Desktop( String ),
/// On Windows, the window class could not be registered or the
/// main window could not be created.
Window( String ),
}
impl std::fmt::Display for RunError
{
fn fmt( &self, f: &mut std::fmt::Formatter<'_> ) -> std::fmt::Result
{
match self
{
Self::NoWaylandConnection( d ) =>
write!( f, "Wayland connection failed: {d}" ),
Self::RegistryInit( d ) =>
write!( f, "Wayland registry init failed: {d}" ),
Self::EventLoop( d ) =>
write!( f, "event-loop setup failed: {d}" ),
Self::MissingProtocol { name, detail } =>
write!( f, "Wayland protocol `{name}` unavailable: {detail}" ),
Self::NoAndroidApp =>
write!( f, "no AndroidApp: call ltk::set_android_app from android_main before ltk::run" ),
Self::NoDocument =>
write!( f, "no window or document: ltk::run runs on a page's main thread" ),
Self::Desktop( d ) =>
write!( f, "the page's desktop refused the main surface: {d}" ),
Self::Window( d ) =>
write!( f, "the main window could not be created: {d}" ),
}
}
}
impl std::error::Error for RunError {}