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
//! Server-side Wayland connector
//!
//! # Overview
//!
//! Setting up the listening socket is done by the `create_display`
//! function, providing you a `Display` object and an `EventLoop`.
//!
//! On the event loop, you'll be able to register the globals
//! you want to advertize, as well as handlers for all ressources
//! created by the clients.
//!
//! You then integrate the wayland event loop in your main event
//! loop to run your compositor.
//!
//! # Implementation and event loop
//!
//! This crate mirrors the callback-oriented design of the
//! Wayland C library by using implementation structs: each wayland
//! type defines an `Implementation` struct in its module, with
//! one function field for each possible event this object can receive.
//!
//! When registering an object on an event loop, you need to provide an
//! implementation for this object. You can also provide some
//! "implementation data": a value that will be provided as second
//! argument to all the callback methods of your implementation.
//!
//! A typical use of implementation data is to store here one or more
//! state tokens to access some part of the shared state from your
//! callback.
//!
//! ## Example of implementation
//!
//! You can register your wayland objects to an event queue:
//!
//! ```ignore
//! event_loop.register(&my_object, implementation, impl_data);
//! ```
//!
//! A given wayland object can only be registered to an event
//! loop at a given time, re-registering it will overwrite
//! the previous configuration.
//!
//! Objects can be registered to event loop using the `&EventLoopHandle`
//! argument, available from withing an event callback.
//!
//! ## Globals definition
//!
//! Some wayland objects are special and can be directly created by the
//! clients from their registry. To handle them your must declare
//! which globals you want to make available to your clients, like this:
//!
//! ```ignore
//! event_loop.register_global(version, callback, idata);
//! ```
//!
//! Where `callback` is a function or non-capturing closure, provided as
//! an implementation for when this global is instanciated by a client.
//! See the method documentation for details.
//!
//! ## Event loop integration
//!
//! Once the setup phase is done, you can integrate the
//! event loop in the main event loop of your program.
//!
//! Either all you need is for it to run indefinitely (external
//! events are checked in an other thread?):
//!
//! ```ignore
//! event_loop.run();
//! ```
//!
//! Or you can integrate it with more control:
//!
//! ```ignore
//! loop {
//!     // flush events to client sockets
//!     display.flush_clients();
//!     // receive request from clients and dispatch them
//!     // blocking if no request is pending for at most
//!     // 10ms
//!     event_loop.dispatch(Some(10)).unwrap();
//!     // then you can check events from other sources if
//!     // you need to
//! }
//! ```
//!
//! # Protocols integration
//!
//! This crate provides the basic primitives as well as the
//! core wayland protocol (in the `protocol` module), but
//! other protocols can be integrated from XML descriptions.
//!
//! The the crate `wayland_scanner` and its documentation for
//! details about how to do so.

#![warn(missing_docs)]

#[macro_use]
extern crate bitflags;
extern crate libc;
extern crate nix;
extern crate token_store;
#[macro_use]
extern crate wayland_sys;

pub use client::Client;
pub use display::{create_display, Display};
pub use event_loop::{resource_is_registered, EventLoop, EventLoopHandle, Global, GlobalCallback,
                     RegisterStatus, State, StateProxy, StateToken};
pub use generated::interfaces as protocol_interfaces;
pub use generated::server as protocol;
use wayland_sys::common::{wl_argument, wl_interface};
use wayland_sys::server::*;

mod client;
mod display;
mod event_loop;
mod event_sources;

pub mod sources {
    //! Secondary event sources
    // This module contains the types & traits to work with
    // different kind of event sources that can be registered to and
    // event loop, other than the wayland protocol sockets.

    pub use event_sources::{FdEventSource, FdEventSourceImpl, FdInterest};
    pub use event_sources::{IdleEventSource, IdleEventSourceImpl};
    pub use event_sources::{SignalEventSource, SignalEventSourceImpl};
    pub use event_sources::{TimerEventSource, TimerEventSourceImpl};
}

/// Common routines for wayland resource objects.
///
/// All wayland objects automatically implement this trait
/// as generated by the scanner.
///
/// It is mostly used for internal use by the library, and you
/// should only need these methods for interfacing with C library
/// working on wayland objects.
pub unsafe trait Resource {
    /// Pointer to the underlying wayland proxy object
    fn ptr(&self) -> *mut wl_resource;
    /// Create an instance from a wayland pointer
    ///
    /// The pointer must refer to a valid wayland resource
    /// of the appropriate interface, but that have not yet
    /// been seen by the library.
    ///
    /// The library will take control of the object (notably
    /// overwrite its user_data).
    unsafe fn from_ptr_new(*mut wl_resource) -> Self;
    /// Create an instance from a wayland pointer
    ///
    /// The pointer must refer to a valid wayland resource
    /// of the appropriate interface. The library will detect if the
    /// resource is already managed by it or not. If it is not, this
    /// resource will be considered as "unmanaged", and should then
    /// be handled with care.
    unsafe fn from_ptr_initialized(*mut wl_resource) -> Self;
    /// Pointer to the interface representation
    fn interface_ptr() -> *const wl_interface;
    /// Internal wayland name of this interface
    fn interface_name() -> &'static str;
    /// Max version of this interface supported
    fn supported_version() -> u32;
    /// Current version of the interface this resource is instantiated with
    fn version(&self) -> i32;
    /// Check if the resource behind this handle is actually still alive
    fn status(&self) -> Liveness;
    /// Check of two handles are actually the same wayland object
    ///
    /// Returns `false` if any of the objects has already been destroyed
    fn equals(&self, &Self) -> bool;
    /// Set a pointer associated as user data on this resource
    ///
    /// All handles to the same wayland object share the same user data pointer.
    ///
    /// The get/set operations are atomic, no more guarantee is given. If you need
    /// to synchronise access to this data, it is your responsibility to add a Mutex
    /// or any other similar mechanism.
    fn set_user_data(&self, ptr: *mut ());
    /// Get the pointer associated as user data on this resource
    ///
    /// All handles to the same wayland object share the same user data pointer.
    ///
    /// See `set_user_data` for synchronisation guarantee.
    fn get_user_data(&self) -> *mut ();
    /// Posts a protocol error to this resource
    ///
    /// The error code can be obtained from the various `Error` enums of the protocols.
    ///
    /// An error is fatal to the client that caused it.
    fn post_error(&self, error_code: u32, msg: String) {
        // If `str` contains an interior null, the actuall transmitted message will
        // be truncated at this point.
        unsafe {
            let cstring = ::std::ffi::CString::from_vec_unchecked(msg.into());
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_resource_post_error,
                self.ptr(),
                error_code,
                cstring.as_ptr()
            )
        }
    }
    /// Clone this resource handle
    ///
    /// Will only succeed if the resource is managed by this library and
    /// is still alive.
    fn clone(&self) -> Option<Self>
    where
        Self: Sized,
    {
        if self.status() == Liveness::Alive {
            Some(unsafe { self.clone_unchecked() })
        } else {
            None
        }
    }
    /// Unsafely clone this resource handle
    ///
    /// This function is unsafe because if the resource is unmanaged, the lib
    /// has no knowledge of its lifetime, and cannot ensure that the new handle
    /// will not outlive the object.
    unsafe fn clone_unchecked(&self) -> Self;
    /// Checks wether this resource and the other are from the same client
    ///
    /// Returns `true` if both are alive and belong to the same client, `false`
    /// otherwise.
    fn same_client_as<R: Resource>(&self, other: &R) -> bool {
        // comparing client pointers for equality is only meaningfull
        // if resources are alive
        if !(self.status() == Liveness::Alive && other.status() == Liveness::Alive) {
            false
        } else {
            let my_client =
                unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_client, self.ptr()) };
            let other_client =
                unsafe { ffi_dispatch!(WAYLAND_SERVER_HANDLE, wl_resource_get_client, other.ptr()) };
            my_client == other_client
        }
    }
}

/// Common trait for wayland objects that can be registered to an EventQueue
pub unsafe trait Implementable<ID: 'static>: Resource {
    /// The type containing the implementation for the event callbacks
    type Implementation: PartialEq + Copy + 'static;
    #[doc(hidden)]
    unsafe fn __dispatch_msg(&self, client: &Client, opcode: u32, args: *const wl_argument)
                             -> Result<(), ()>;
}

/// Possible outcome of the call of a event on a resource
#[derive(Debug)]
pub enum EventResult<T> {
    /// Message has been buffered and will be sent to client
    Sent(T),
    /// This resource is already destroyed, request has been ignored
    Destroyed,
}

impl<T> EventResult<T> {
    /// Assert that result is successfull and extract the value.
    ///
    /// Panics with provided error message if the result was `Destroyed`.
    pub fn expect(self, error: &str) -> T {
        match self {
            EventResult::Sent(v) => v,
            EventResult::Destroyed => panic!("{}", error),
        }
    }
}

/// Represents the state of liveness of a wayland object
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Liveness {
    /// This object is alive and events can be sent to it
    Alive,
    /// This object is dead, sending it events will do nothing and
    /// return and error.
    Dead,
    /// This object is not managed by `wayland-server`, you can send it events
    /// but this might crash the program if it was actually dead.
    Unmanaged,
}

mod generated {
    #![allow(dead_code, non_camel_case_types, unused_unsafe, unused_variables)]
    #![allow(non_upper_case_globals, non_snake_case, unused_imports)]
    #![allow(missing_docs)]

    pub mod interfaces {
        //! Interfaces for the core protocol
        // You might need them for the bindings generated for protocol extensions
        include!(concat!(env!("OUT_DIR"), "/wayland_interfaces.rs"));
    }

    pub mod server {
        //! The wayland core protocol
        // This module contains all objects of the core wayland protocol.
        //
        // It has been generated from the `wayland.xml` protocol file
        // using `wayland_scanner`.
        // Imports that need to be available to submodules
        // but should not be in public API.
        // Will be fixable with pub(restricted).

        #[doc(hidden)]
        pub use super::interfaces;
        #[doc(hidden)]
        pub use {Client, EventLoopHandle, EventResult, Implementable, Liveness, Resource};

        include!(concat!(env!("OUT_DIR"), "/wayland_api.rs"));
    }
}

pub mod sys {
    //! Reexports of types and objects from wayland-sys

    pub use wayland_sys::common::*;
    pub use wayland_sys::server::*;
}