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 | //! This crate can implement [`HasRawWindowHandle`](raw_window_handle::HasRawWindowHandle) for the client |
37 | //! module [`Backend`](client::Backend) type if you activate the `raw-window-handle` feature. |
38 | //! |
39 | //! Note that the `client_system` feature must also be enabled for the implementation to be activated. |
40 | |
41 | #![forbid (improper_ctypes)] |
42 | #![deny (unsafe_op_in_unsafe_fn)] |
43 | #![warn (missing_docs, missing_debug_implementations)] |
44 | // The api modules are imported two times each, this is not accidental |
45 | #![allow (clippy::duplicate_mod)] |
46 | #![cfg_attr (coverage, feature(coverage_attribute))] |
47 | // Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc -p <crate> |
48 | #![cfg_attr (docsrs, feature(doc_auto_cfg))] |
49 | |
50 | /// Reexport of the `smallvec` crate, which is part of `wayland-backend`'s public API. |
51 | pub extern crate smallvec; |
52 | |
53 | /// Helper macro for quickly making a [`Message`](crate::protocol::Message) |
54 | #[macro_export ] |
55 | macro_rules! message { |
56 | ($sender_id: expr, $opcode: expr, [$($args: expr),* $(,)?] $(,)?) => { |
57 | $crate::protocol::Message { |
58 | sender_id: $sender_id, |
59 | opcode: $opcode, |
60 | args: $crate::smallvec::smallvec![$($args),*], |
61 | } |
62 | } |
63 | } |
64 | |
65 | // internal imports for dispatching logging depending on the `log` feature |
66 | #[cfg (feature = "log" )] |
67 | #[allow (unused_imports)] |
68 | use log::{debug as log_debug, error as log_error, info as log_info, warn as log_warn}; |
69 | #[cfg (not(feature = "log" ))] |
70 | #[allow (unused_imports)] |
71 | use std::{ |
72 | eprintln as log_error, eprintln as log_warn, eprintln as log_info, eprintln as log_debug, |
73 | }; |
74 | |
75 | #[cfg (any(test, feature = "client_system" , feature = "server_system" ))] |
76 | pub mod sys; |
77 | |
78 | pub mod rs; |
79 | |
80 | #[cfg (not(feature = "client_system" ))] |
81 | pub use rs::client; |
82 | #[cfg (feature = "client_system" )] |
83 | pub use sys::client; |
84 | |
85 | #[cfg (not(feature = "server_system" ))] |
86 | pub use rs::server; |
87 | #[cfg (feature = "server_system" )] |
88 | pub use sys::server; |
89 | |
90 | #[cfg (test)] |
91 | mod test; |
92 | |
93 | mod core_interfaces; |
94 | mod debug; |
95 | pub mod protocol; |
96 | mod types; |
97 | |
98 | /* |
99 | * These trampoline functions need to always be here because the build script cannot |
100 | * conditionally build their C counterparts on whether the crate is tested or not... |
101 | * They'll be optimized out when unused. |
102 | */ |
103 | |
104 | #[cfg (feature = "log" )] |
105 | #[no_mangle ] |
106 | extern "C" fn wl_log_rust_logger_client(msg: *const std::os::raw::c_char) { |
107 | let cstr = unsafe { std::ffi::CStr::from_ptr(msg) }; |
108 | let text = cstr.to_string_lossy(); |
109 | log::error!("{}" , text); |
110 | } |
111 | |
112 | #[cfg (feature = "log" )] |
113 | #[no_mangle ] |
114 | extern "C" fn wl_log_rust_logger_server(msg: *const std::os::raw::c_char) { |
115 | let cstr = unsafe { std::ffi::CStr::from_ptr(msg) }; |
116 | let text = cstr.to_string_lossy(); |
117 | log::error!("{}" , text); |
118 | } |
119 | |