wayland_server/lib.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 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
//! Interface for interacting with the Wayland protocol, server-side.
//!
//! ## General concepts
//!
//! This crate is structured around four main objects: the [`Display`] and [`DisplayHandle`] structs,
//! resources (objects implementing the [`Resource`] trait), and the [`Dispatch`] trait.
//!
//! The [`Display`] is the heart of this crate, it represents the protocol state of your Wayland server, and
//! takes care of processing messages from clients. You'll need to integrate it in your event loop (see its
//! documentation for details). From it you can retrieve the [`DisplayHandle`], which is a clonable handle to
//! the Wayland state and is the type used to actually interact with the protocol.
//!
//! Each of the Wayland object you can manipulate is represented by a struct implementing the [`Resource`]
//! trait. Thos structs are automatically generated from the wayland XML protocol specification. This crate
//! provides the types generated from the core protocol in the [`protocol`] module. For other standard
//! protocols, see the `wayland-protocols` crate.
//!
//! ## Request dispatching and the [`Dispatch`] trait
//!
//! The request dispatching logic provided by this crate is build around the [`Dispatch`] trait. During the
//! dispatching process (in [`Display::dispatch_clients()`]), all requests sent by clients are read from
//! their respective process and delivered to your processing logic, by invoking methods on the various
//! [`Dispatch`] implementations of your `State` struct. In this paradigm, your `State` needs to implement
//! `Dispatch<O, _>` for every Wayland object `O` it needs to process events for.
//!
//! However, implementing all those traits on your own is a lot of (often uninteresting) work. To make this
//! easier a composition mechanism is provided using the [`delegate_dispatch!()`] macro. This way, another
//! library (such as Smithay) can provide generic [`Dispatch`] implementations that you can reuse on your
//! own app by delegating those objects to that provided implementation. See the documentation of those
//! traits and macro for details.
//!
//! ## Globals
//!
//! The entry point of the protocol for clients goes through the protocol globals. Each global represents a
//! capability of your compositor, a peripheral it has access to, or a protocol extension it supports.
//! Globals are created by you using [`DisplayHandle::create_global()`], and require your `State` to
//! implement the [`GlobalDispatch`] trait for the interface associated with that global.
//!
//! ## Logging
//!
//! This crate can generate some runtime error message (notably when a protocol error occurs). By default
//! those messages are printed to stderr. If you activate the `log` cargo feature, they will instead be
//! piped through the `log` crate.
//!
//! ## Advanced use
//!
//! ### Bypassing [`Dispatch`]
//!
//! It may be that for some of your objects, handling them via the [`Dispatch`] trait is impractical. In
//! those contexts, this crate also provides some escape-hatches to directly interface with the low-level
//! APIs from `wayland-backend`, allowing you to register callbacks for those objects by directly providing
//! implementations of the backend [`ObjectData`][backend::ObjectData] trait.
//! See [`Client::create_resource_from_objdata()`] and [`DataInit::custom_init()`].
//!
//! ### Interaction with FFI
//!
//! It can happen that you'll need to interact with Wayland states accross FFI, such as for example when
//! interfacing with the graphics stack for enabling hardware acceleration for clients.
//!
//! In this case, you'll need to do it in two steps, by explicitly working with `wayland-backend`, adding
//! it to your dependencies and enabling its `server_system` feature.
//!
//! Then, you'll generally need:
//!
//! - The `*mut wl_display` pointer, that you can retrieve by first retrieving the
//! [`Backend`][backend::Backend] using [`Display::backend()`], and then invoke
//! [`.handle()`][backend::Backend::handle()][`.display_ptr()`][backend::Handle::display_ptr()].
//! - The `*mut wl_resource` pointers for the objects you need to share, by first getting the
//! [`ObjectId`] using the [`Resource::id()`] method, and then
//! the [`ObjectId::as_ptr()`] method.
//!
//! If you need to receive pointers from FFI, you can make [`ObjectId`]s from the `*mut wl_resource` pointers
//! using [`ObjectId::from_ptr()`], and then make the resources using [`Resource::from_id()`].
#![forbid(improper_ctypes, unsafe_op_in_unsafe_fn)]
// Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc -p <crate>
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
use std::{
fmt,
hash::{Hash, Hasher},
os::unix::io::OwnedFd,
};
use wayland_backend::{
protocol::{Interface, Message},
server::{InvalidId, ObjectId, WeakHandle},
};
mod client;
mod dispatch;
mod display;
mod global;
mod socket;
pub use client::Client;
pub use dispatch::{DataInit, Dispatch, New, ResourceData};
pub use display::{Display, DisplayHandle};
pub use global::GlobalDispatch;
pub use socket::{BindError, ListeningSocket};
/// Backend reexports
pub mod backend {
pub use wayland_backend::protocol;
pub use wayland_backend::server::{
Backend, ClientData, ClientId, Credentials, DisconnectReason, GlobalHandler, GlobalId,
Handle, InitError, InvalidId, ObjectData, ObjectId, WeakHandle,
};
pub use wayland_backend::smallvec;
}
pub use wayland_backend::protocol::WEnum;
/// Generated protocol definitions
///
/// This module is automatically generated from the `wayland.xml` protocol specification, and contains the
/// interface definitions for the core Wayland protocol.
#[allow(missing_docs)]
pub mod protocol {
use self::__interfaces::*;
use crate as wayland_server;
pub mod __interfaces {
wayland_scanner::generate_interfaces!("wayland.xml");
}
wayland_scanner::generate_server_code!("wayland.xml");
}
// internal imports for dispatching logging depending on the `log` feature
#[cfg(feature = "log")]
#[allow(unused_imports)]
use log::{debug as log_debug, error as log_error, info as log_info, warn as log_warn};
#[cfg(not(feature = "log"))]
#[allow(unused_imports)]
use std::{
eprintln as log_error, eprintln as log_warn, eprintln as log_info, eprintln as log_debug,
};
/// Trait representing a Wayland interface
pub trait Resource: Clone + std::fmt::Debug + Sized {
/// The event enum for this interface
type Event<'a>;
/// The request enum for this interface
type Request;
/// The interface description
fn interface() -> &'static Interface;
/// The ID of this object
fn id(&self) -> ObjectId;
/// The client owning this object
///
/// Returns [`None`] if the object is no longer alive.
fn client(&self) -> Option<Client> {
let handle = self.handle().upgrade()?;
let client_id = handle.get_client(self.id()).ok()?;
let dh = DisplayHandle::from(handle);
Client::from_id(&dh, client_id).ok()
}
/// The version of this object
fn version(&self) -> u32;
/// Checks if the Wayland object associated with this proxy is still alive
#[inline]
fn is_alive(&self) -> bool {
if let Some(handle) = self.handle().upgrade() {
handle.object_info(self.id()).is_ok()
} else {
false
}
}
/// Access the user-data associated with this object
fn data<U: 'static>(&self) -> Option<&U>;
/// Access the raw data associated with this object.
///
/// It is given to you as a `dyn Any`, and you are responsible for downcasting it.
///
/// For objects created using the scanner-generated methods, this will be an instance of the
/// [`ResourceData`] type.
fn object_data(&self) -> Option<&std::sync::Arc<dyn std::any::Any + Send + Sync>>;
/// Access the backend handle associated with this object
fn handle(&self) -> &backend::WeakHandle;
/// Create an object resource from its ID
///
/// Returns an error this the provided object ID does not correspond to the `Self` interface.
///
/// **Note:** This method is mostly meant as an implementation detail to be used by code generated by
/// wayland-scanner.
fn from_id(dh: &DisplayHandle, id: ObjectId) -> Result<Self, InvalidId>;
/// Send an event to this object
fn send_event(&self, evt: Self::Event<'_>) -> Result<(), InvalidId>;
/// Trigger a protocol error on this object
///
/// The `code` is intended to be from the `Error` enum declared alongside that object interface.
///
/// A protocol error is fatal to the Wayland connection, and the client will be disconnected.
#[inline]
fn post_error(&self, code: impl Into<u32>, error: impl Into<String>) {
if let Some(dh) = self.handle().upgrade().map(DisplayHandle::from) {
dh.post_error(self, code.into(), error.into());
}
}
/// Parse a event for this object
///
/// **Note:** This method is mostly meant as an implementation detail to be used by code generated by
/// wayland-scanner.
fn parse_request(
dh: &DisplayHandle,
msg: Message<ObjectId, OwnedFd>,
) -> Result<(Self, Self::Request), DispatchError>;
/// Serialize an event for this object
///
/// **Note:** This method is mostly meant as an implementation detail to be used by code generated by
/// wayland-scanner.
fn write_event<'a>(
&self,
dh: &DisplayHandle,
req: Self::Event<'a>,
) -> Result<Message<ObjectId, std::os::unix::io::BorrowedFd<'a>>, InvalidId>;
/// Creates a weak handle to this object
///
/// This weak handle will not keep the user-data associated with the object alive,
/// and can be converted back to a full resource using [`Weak::upgrade()`].
///
/// This can be of use if you need to store resources in the used data of other objects and want
/// to be sure to avoid reference cycles that would cause memory leaks.
#[inline]
fn downgrade(&self) -> Weak<Self> {
Weak { handle: self.handle().clone(), id: self.id(), _iface: std::marker::PhantomData }
}
#[doc(hidden)]
fn __set_object_data(
&mut self,
odata: std::sync::Arc<dyn std::any::Any + Send + Sync + 'static>,
);
}
/// An error generated if an illegal request was received from a client
#[derive(Debug)]
pub enum DispatchError {
/// The received message does not match the specification for the object's interface.
BadMessage {
/// The id of the target object
sender_id: ObjectId,
/// The interface of the target object
interface: &'static str,
/// The opcode number
opcode: u16,
},
}
impl std::error::Error for DispatchError {}
impl fmt::Display for DispatchError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
DispatchError::BadMessage { sender_id, interface, opcode } => {
write!(f, "Bad message for object {interface}@{sender_id} on opcode {opcode}",)
}
}
}
}
/// A weak handle to a Wayland object
///
/// This handle does not keep the underlying user data alive, and can be converted back to a full resource
/// using [`Weak::upgrade()`].
#[derive(Debug, Clone)]
pub struct Weak<I> {
handle: WeakHandle,
id: ObjectId,
_iface: std::marker::PhantomData<I>,
}
impl<I: Resource> Weak<I> {
/// Try to upgrade with weak handle back into a full resource.
///
/// This will fail if either:
/// - the object represented by this handle has already been destroyed at the protocol level
/// - the Wayland connection has already been closed
#[inline]
pub fn upgrade(&self) -> Result<I, InvalidId> {
let handle = self.handle.upgrade().ok_or(InvalidId)?;
// Check if the object has been destroyed
handle.object_info(self.id.clone())?;
let d_handle = DisplayHandle::from(handle);
I::from_id(&d_handle, self.id.clone())
}
/// Check if this resource is still alive
///
/// This will return `false` if either:
/// - the object represented by this handle has already been destroyed at the protocol level
/// - the Wayland connection has already been closed
#[inline]
pub fn is_alive(&self) -> bool {
let Some(handle) = self.handle.upgrade() else {
return false;
};
handle.object_info(self.id.clone()).is_ok()
}
/// The underlying [`ObjectId`]
pub fn id(&self) -> ObjectId {
self.id.clone()
}
}
impl<I> PartialEq for Weak<I> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
impl<I> Eq for Weak<I> {}
impl<I> Hash for Weak<I> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.id.hash(state);
}
}
impl<I: Resource> PartialEq<I> for Weak<I> {
#[inline]
fn eq(&self, other: &I) -> bool {
self.id == other.id()
}
}