| 1 | //! Backend API for wayland crates |
| 2 | //! |
| 3 | //! This crate provide low-level APIs for interacting with the Wayland protocol, |
| 4 | //! both client-side and server-side. |
| 5 | //! |
| 6 | //! Two possible backends are provided by this crate: the system backend ([`sys`] module) |
| 7 | //! which relies on the system-provided wayland libraries, and the rust backend ([`rs`] module) |
| 8 | //! which is an alternative rust implementation of the protocol. The rust backend is always |
| 9 | //! available, and the system backend is controlled by the `client_system` and `server_system` |
| 10 | //! cargo features. The `dlopen` cargo feature ensures that the system wayland |
| 11 | //! libraries are loaded dynamically at runtime, so that your executable does not link them and |
| 12 | //! can gracefully handle their absence (for example by falling back to X11). |
| 13 | //! |
| 14 | //! Additionally the default backends are reexported as toplevel `client` and `server` modules |
| 15 | //! in this crate. For both client and server, the default backend is the system one if the |
| 16 | //! associated cargo feature is enabled, and the rust one otherwise. |
| 17 | //! |
| 18 | //! Using these reexports is the recommended way to use the crate: |
| 19 | //! - If you don't need the `*_system` features, an other crate enabling them will not impact your code in |
| 20 | //! any way as both backends have the same API (the system backend only has more methods) |
| 21 | //! - If your code needs to do FFI, you just need to directly depend on `wayland-backend` with the |
| 22 | //! appropriate `*_system` feature enabled, and all the other crates in your dependency tree will |
| 23 | //! automatically use the `sys` backend. |
| 24 | //! |
| 25 | //! Both the `wayland-client` and `wayland-server` crates follow this principle, so everything will "Just |
| 26 | //! Work" when using them. |
| 27 | //! |
| 28 | //! ## Logging |
| 29 | //! |
| 30 | //! This crate can generate some runtime error message (notably when a protocol error occurs). By default |
| 31 | //! those messages are printed to stderr. If you activate the `log` cargo feature, they will instead be |
| 32 | //! piped through the `log` crate. |
| 33 | //! |
| 34 | //! ## raw-window-handle integration |
| 35 | //! |
| 36 | //! The `rwh_06` feature activates the [`HasDisplayHandle`][raw_window_handle::HasDisplayHandle] implementation |
| 37 | //! for the client module [`Backend`][client::Backend]. |
| 38 | //! |
| 39 | //! ### Deprecated raw-window-handle versions |
| 40 | //! |
| 41 | //! While raw-window-handle 0.5 is supported via the `raw-window-handle` feature, it is deprecated and will be removed in the future. |
| 42 | //! |
| 43 | //! Note that the `client_system` feature must also be enabled for the implementation to be activated. |
| 44 | |
| 45 | #![forbid (improper_ctypes)] |
| 46 | #![deny (unsafe_op_in_unsafe_fn)] |
| 47 | #![warn (missing_docs, missing_debug_implementations)] |
| 48 | // The api modules are imported two times each, this is not accidental |
| 49 | #![allow (clippy::duplicate_mod)] |
| 50 | #![cfg_attr (coverage, feature(coverage_attribute))] |
| 51 | // Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc -p <crate> |
| 52 | #![cfg_attr (docsrs, feature(doc_auto_cfg))] |
| 53 | |
| 54 | /// Reexport of the `smallvec` crate, which is part of `wayland-backend`'s public API. |
| 55 | pub extern crate smallvec; |
| 56 | |
| 57 | /// Helper macro for quickly making a [`Message`][crate::protocol::Message] |
| 58 | #[macro_export ] |
| 59 | macro_rules! message { |
| 60 | ($sender_id: expr, $opcode: expr, [$($args: expr),* $(,)?] $(,)?) => { |
| 61 | $crate::protocol::Message { |
| 62 | sender_id: $sender_id, |
| 63 | opcode: $opcode, |
| 64 | args: $crate::smallvec::smallvec![$($args),*], |
| 65 | } |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | // internal imports for dispatching logging depending on the `log` feature |
| 70 | #[cfg (feature = "log" )] |
| 71 | #[allow (unused_imports)] |
| 72 | use log::{debug as log_debug, error as log_error, info as log_info, warn as log_warn}; |
| 73 | #[cfg (not(feature = "log" ))] |
| 74 | #[allow (unused_imports)] |
| 75 | use std::{ |
| 76 | eprintln as log_error, eprintln as log_warn, eprintln as log_info, eprintln as log_debug, |
| 77 | }; |
| 78 | |
| 79 | #[cfg (any(test, feature = "client_system" , feature = "server_system" ))] |
| 80 | pub mod sys; |
| 81 | |
| 82 | pub mod rs; |
| 83 | |
| 84 | #[cfg (not(feature = "client_system" ))] |
| 85 | pub use rs::client; |
| 86 | #[cfg (feature = "client_system" )] |
| 87 | pub use sys::client; |
| 88 | |
| 89 | #[cfg (not(feature = "server_system" ))] |
| 90 | pub use rs::server; |
| 91 | #[cfg (feature = "server_system" )] |
| 92 | pub use sys::server; |
| 93 | |
| 94 | #[cfg (test)] |
| 95 | mod test; |
| 96 | |
| 97 | mod core_interfaces; |
| 98 | mod debug; |
| 99 | pub mod protocol; |
| 100 | mod types; |
| 101 | |
| 102 | /* |
| 103 | * These trampoline functions need to always be here because the build script cannot |
| 104 | * conditionally build their C counterparts on whether the crate is tested or not... |
| 105 | * They'll be optimized out when unused. |
| 106 | */ |
| 107 | |
| 108 | #[cfg (feature = "log" )] |
| 109 | #[no_mangle ] |
| 110 | extern "C" fn wl_log_rust_logger_client(msg: *const std::os::raw::c_char) { |
| 111 | let cstr = unsafe { std::ffi::CStr::from_ptr(msg) }; |
| 112 | let text = cstr.to_string_lossy(); |
| 113 | log::error!("{}" , text); |
| 114 | } |
| 115 | |
| 116 | #[cfg (feature = "log" )] |
| 117 | #[no_mangle ] |
| 118 | extern "C" fn wl_log_rust_logger_server(msg: *const std::os::raw::c_char) { |
| 119 | let cstr = unsafe { std::ffi::CStr::from_ptr(msg) }; |
| 120 | let text = cstr.to_string_lossy(); |
| 121 | log::error!("{}" , text); |
| 122 | } |
| 123 | |