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 {}