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
//! Implementations of the Wayland backends using the system `libwayland`

use crate::protocol::ArgumentType;
use wayland_sys::common::{wl_argument, wl_array};

#[cfg(any(test, feature = "client_system"))]
mod client_impl;
#[cfg(any(test, feature = "server_system"))]
mod server_impl;

/// Magic static for wayland objects managed by wayland-client or wayland-server
///
/// This static serves no purpose other than existing at a stable address.
static RUST_MANAGED: u8 = 42;

unsafe fn free_arrays(signature: &[ArgumentType], arglist: &[wl_argument]) {
    for (typ, arg) in signature.iter().zip(arglist.iter()) {
        if let ArgumentType::Array(_) = typ {
            // Safety: the arglist provided arglist must be valid for associated signature
            // and contains pointers to boxed arrays as appropriate
            let _ = unsafe { Box::from_raw(arg.a as *mut wl_array) };
        }
    }
}

/// Client-side implementation of a Wayland protocol backend using `libwayland`
#[cfg(any(test, feature = "client_system"))]
#[cfg_attr(docsrs, doc(cfg(feature = "client_system")))]
#[path = "../client_api.rs"]
pub mod client;

// API complements for FFI

#[cfg(any(test, feature = "client_system"))]
impl client::ObjectId {
    /// Creates an object id from a libwayland-client pointer.
    ///
    /// # Errors
    ///
    /// This function returns an [`InvalidId`](client::InvalidId) error if the interface of the proxy does
    /// not match the provided interface.
    ///
    /// # Safety
    ///
    /// The provided pointer must be a valid pointer to a `wl_resource` and remain valid for as
    /// long as the retrieved `ObjectId` is used.
    #[cfg_attr(docsrs, doc(cfg(feature = "client_system")))]
    pub unsafe fn from_ptr(
        interface: &'static crate::protocol::Interface,
        ptr: *mut wayland_sys::client::wl_proxy,
    ) -> Result<Self, client::InvalidId> {
        Ok(Self { id: unsafe { client_impl::InnerObjectId::from_ptr(interface, ptr) }? })
    }

    /// Get the underlying libwayland pointer for this object
    #[cfg_attr(docsrs, doc(cfg(feature = "client_system")))]
    pub fn as_ptr(&self) -> *mut wayland_sys::client::wl_proxy {
        self.id.as_ptr()
    }
}

#[cfg(any(test, feature = "client_system"))]
impl client::Backend {
    /// Creates a Backend from a foreign `*mut wl_display`.
    ///
    /// This is useful if you are writing a library that is expected to plug itself into an existing
    /// Wayland connection.
    ///
    /// This will initialize the [`Backend`] in "guest" mode, meaning it will not close the connection
    /// on drop. After the [`Backend`] is dropped, if the server sends an event to an object that was
    /// created from it, that event will be silently discarded. This may lead to protocol errors if the
    /// server expects an answer to that event, as such you should make sure to cleanup your Wayland
    /// state before dropping the [`Backend`].
    ///
    /// # Safety
    ///
    /// You need to ensure the `*mut wl_display` remains live as lon as the  [`Backend`] (or its clones)
    /// exist.
    #[cfg_attr(docsrs, doc(cfg(feature = "client_system")))]
    pub unsafe fn from_foreign_display(display: *mut wayland_sys::client::wl_display) -> Self {
        Self { backend: unsafe { client_impl::InnerBackend::from_foreign_display(display) } }
    }
}

/// Server-side implementation of a Wayland protocol backend using `libwayland`
#[cfg(any(test, feature = "server_system"))]
#[cfg_attr(docsrs, doc(cfg(feature = "server_system")))]
#[path = "../server_api.rs"]
pub mod server;

#[cfg(any(test, feature = "server_system"))]
impl server::ObjectId {
    /// Creates an object from a C pointer.
    ///
    /// # Errors
    ///
    /// This function returns an [`InvalidId`](server::InvalidId) error if the interface of the
    /// resource does not match the provided interface.
    ///
    /// # Safety
    ///
    /// The provided pointer must be a valid pointer to a `wl_resource` and remain valid for as
    /// long as the retrieved `ObjectId` is used.
    #[cfg_attr(docsrs, doc(cfg(feature = "server_system")))]
    pub unsafe fn from_ptr(
        interface: &'static crate::protocol::Interface,
        ptr: *mut wayland_sys::server::wl_resource,
    ) -> Result<Self, server::InvalidId> {
        Ok(Self { id: unsafe { server_impl::InnerObjectId::from_ptr(interface, ptr) }? })
    }

    /// Returns the pointer that represents this object.
    ///
    /// The pointer may be used to interoperate with libwayland.
    #[cfg_attr(docsrs, doc(cfg(feature = "server_system")))]
    pub fn as_ptr(&self) -> *mut wayland_sys::server::wl_resource {
        self.id.as_ptr()
    }
}

#[cfg(any(test, feature = "server_system"))]
impl server::Handle {
    /// Access the underlying `*mut wl_display` pointer
    #[cfg_attr(docsrs, doc(cfg(feature = "server_system")))]
    pub fn display_ptr(&self) -> *mut wayland_sys::server::wl_display {
        self.handle.display_ptr()
    }
}