2017-06-11 12:33:03 +00:00
//! Utilities for handling surfaces, subsurfaces and regions
//!
2018-10-30 12:56:30 +00:00
//! This module provides automatic handling of surfaces, subsurfaces
//! and region Wayland objects, by registering an implementation for
2018-12-08 12:40:07 +00:00
//! for the [`wl_compositor`](wayland_server::protocol::wl_compositor)
//! and [`wl_subcompositor`](wayland_server::protocol::wl_subcompositor) globals.
2017-06-11 12:33:03 +00:00
//!
2017-09-20 07:57:43 +00:00
//! ## Why use this implementation
2017-06-11 12:33:03 +00:00
//!
2017-09-20 07:57:43 +00:00
//! This implementation does a simple job: it stores in a coherent way the state of
2017-06-11 12:33:03 +00:00
//! surface trees with subsurfaces, to provide you a direct access to the tree
//! structure and all surface metadata.
//!
//! As such, you can, given a root surface with a role requiring it to be displayed,
//! you can iterate over the whole tree of subsurfaces to recover all the metadata you
//! need to display the subsurface tree.
//!
2017-09-20 07:57:43 +00:00
//! This implementation will not do anything more than present you the metadata specified by the
2017-06-11 12:33:03 +00:00
//! client in a coherent and practical way. All the logic regarding to drawing itself, and
2018-10-30 12:56:30 +00:00
//! the positioning of windows (surface trees) one relative to another is out of its scope.
2017-06-11 12:33:03 +00:00
//!
//! ## How to use it
//!
//! ### Initialization
//!
2018-12-08 12:40:07 +00:00
//! To initialize this implementation, use the [`compositor_init`](::wayland::compositor::compositor_init)
//! method provided by this module. It'll require you to first define as few things, as shown in
2017-09-20 07:57:43 +00:00
//! this example:
2017-06-11 12:33:03 +00:00
//!
//! ```
//! # extern crate wayland_server;
2017-09-03 17:53:29 +00:00
//! # #[macro_use] extern crate smithay;
2018-04-17 09:03:42 +00:00
//! use smithay::wayland::compositor::compositor_init;
2017-06-11 12:33:03 +00:00
//!
2017-09-03 17:53:29 +00:00
//! // Declare the roles enum
//! define_roles!(MyRoles);
//!
2018-09-24 22:30:39 +00:00
//! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
2017-09-20 07:57:43 +00:00
//! // Call the init function:
2019-04-23 20:46:11 +00:00
//! let (token, _, _) = compositor_init::<MyRoles, _, _>(
2018-04-17 09:03:42 +00:00
//! &mut display,
2018-09-24 22:30:39 +00:00
//! |request, surface, compositor_token| {
2018-04-17 09:03:42 +00:00
//! /*
2018-09-24 22:30:39 +00:00
//! Your handling of the user requests.
2018-04-17 09:03:42 +00:00
//! */
//! },
//! None // put a logger here
2017-06-11 12:33:03 +00:00
//! );
//!
2017-09-20 07:57:43 +00:00
//! // this `token` is what you'll use to access the surface associated data
2017-06-11 12:33:03 +00:00
//!
//! // You're now ready to go!
//! ```
//!
//! ### Use the surface metadata
//!
//! As you can see in the previous example, in the end we are retrieving a token from
2018-10-30 12:56:30 +00:00
//! the `init` function. This token is necessary to retrieve the metadata associated with
2018-12-08 12:40:07 +00:00
//! a surface. It can be cloned. See [`CompositorToken`](::wayland::compositor::CompositorToken)
//! for the details of what it enables you.
2017-06-11 12:33:03 +00:00
//!
2018-12-08 12:40:07 +00:00
//! The surface metadata is held in the [`SurfaceAttributes`](::wayland::compositor::SurfaceAttributes)
//! struct. In contains double-buffered state pending from the client as defined by the protocol for
//! [`wl_surface`](wayland_server::protocol::wl_surface), as well as your user-defined type holding
//! any data you need to have associated with a struct. See its documentation for details.
2017-09-03 17:53:29 +00:00
//!
2018-12-08 12:40:07 +00:00
//! This [`CompositorToken`](::wayland::compositor::CompositorToken) also provides access to the metadata associated with the role of the
//! surfaces. See the documentation of the [`roles`](::wayland::compositor::roles) submodule
//! for a detailed explanation.
2017-06-11 12:33:03 +00:00
2018-10-04 22:37:43 +00:00
use std ::{ cell ::RefCell , rc ::Rc , sync ::Mutex } ;
2018-04-17 09:03:42 +00:00
2017-06-04 15:47:37 +00:00
mod handlers ;
2017-09-03 17:53:29 +00:00
pub mod roles ;
2018-09-24 22:30:39 +00:00
mod tree ;
2017-06-04 15:47:37 +00:00
2017-09-03 17:53:29 +00:00
pub use self ::tree ::TraversalAction ;
2018-10-04 22:37:43 +00:00
use self ::{
roles ::{ Role , RoleType , WrongRole } ,
tree ::SurfaceData ,
} ;
2018-12-15 20:32:28 +00:00
use crate ::utils ::Rectangle ;
2018-10-04 22:37:43 +00:00
use wayland_server ::{
protocol ::{
wl_buffer , wl_callback , wl_compositor , wl_output , wl_region , wl_subcompositor , wl_surface ::WlSurface ,
} ,
2019-02-22 20:46:26 +00:00
Display , Global , NewResource ,
2018-09-24 22:30:39 +00:00
} ;
2017-06-04 15:47:37 +00:00
/// Description of which part of a surface
/// should be considered damaged and needs to be redrawn
pub enum Damage {
/// The whole surface must be considered damaged (this is the default)
Full ,
/// A rectangle containing the damaged zone, in surface coordinates
Surface ( Rectangle ) ,
2017-06-11 20:47:27 +00:00
/// A rectangle containing the damaged zone, in buffer coordinates
2017-06-04 15:47:37 +00:00
///
/// Note: Buffer scaling must be taken into consideration
2017-06-04 20:12:22 +00:00
Buffer ( Rectangle ) ,
2017-06-04 15:47:37 +00:00
}
2017-09-20 07:57:43 +00:00
#[ derive(Copy, Clone, Default) ]
2019-04-23 20:46:11 +00:00
struct Marker < R > {
2017-09-20 07:57:43 +00:00
_r : ::std ::marker ::PhantomData < R > ,
}
2018-10-30 12:56:30 +00:00
/// Data associated with a surface, aggregated by the handlers
2017-06-04 15:47:37 +00:00
///
/// Most of the fields of this struct represent a double-buffered state, which
2018-12-08 12:40:07 +00:00
/// should only be applied once a [`commit`](::wayland::compositor::SurfaceEvent::Commit)
/// request is received from the surface.
2017-06-04 15:47:37 +00:00
///
/// You are responsible for setting those values as you see fit to avoid
/// processing them two times.
2019-04-23 20:46:11 +00:00
pub struct SurfaceAttributes {
2017-06-04 15:47:37 +00:00
/// Buffer defining the contents of the surface
///
/// The tuple represent the coordinates of this buffer
/// relative to the location of the current buffer.
///
/// If set to `Some(None)`, it means the user specifically asked for the
/// surface to be unmapped.
///
/// You are free to set this field to `None` to avoid processing it several
2018-10-30 12:56:30 +00:00
/// times. It'll be set to `Some(...)` if the user attaches a buffer (or `NULL`) to
2017-06-04 15:47:37 +00:00
/// the surface.
2019-02-22 16:55:00 +00:00
pub buffer : Option < Option < ( wl_buffer ::WlBuffer , ( i32 , i32 ) ) > > ,
2017-06-04 15:47:37 +00:00
/// Scale of the contents of the buffer, for higher-resolution contents.
///
/// If it matches the one of the output displaying this surface, no change
/// is necessary.
pub buffer_scale : i32 ,
/// Transform under which interpret the contents of the buffer
///
/// If it matches the one of the output displaying this surface, no change
/// is necessary.
pub buffer_transform : wl_output ::Transform ,
/// Region of the surface that is guaranteed to be opaque
///
/// By default the whole surface is potentially transparent
pub opaque_region : Option < RegionAttributes > ,
/// Region of the surface that is sensitive to user input
///
/// By default the whole surface should be sensitive
pub input_region : Option < RegionAttributes > ,
/// Damage rectangle
///
/// Hint provided by the client to suggest that only this part
/// of the surface was changed and needs to be redrawn
pub damage : Damage ,
/// User-controlled data
///
/// This is your field to host whatever you need.
2019-04-23 20:46:11 +00:00
pub user_data : ::wayland_commons ::utils ::UserDataMap ,
2017-06-04 15:47:37 +00:00
}
2019-04-23 20:46:11 +00:00
impl Default for SurfaceAttributes {
fn default ( ) -> SurfaceAttributes {
2017-06-04 15:47:37 +00:00
SurfaceAttributes {
buffer : None ,
buffer_scale : 1 ,
buffer_transform : wl_output ::Transform ::Normal ,
opaque_region : None ,
input_region : None ,
damage : Damage ::Full ,
2019-04-23 20:46:11 +00:00
user_data : ::wayland_commons ::utils ::UserDataMap ::new ( ) ,
2017-06-04 15:47:37 +00:00
}
}
}
/// Attributes defining the behaviour of a sub-surface relative to its parent
2017-09-03 17:53:29 +00:00
#[ derive(Copy, Clone, Debug) ]
pub struct SubsurfaceRole {
2018-04-17 09:03:42 +00:00
/// Location of the top-left corner of this sub-surface relative to
2017-06-04 15:47:37 +00:00
/// the top-left corner of its parent
2018-04-17 09:03:42 +00:00
pub location : ( i32 , i32 ) ,
2017-06-04 15:47:37 +00:00
/// Sync status of this sub-surface
///
/// If `true`, this surface should be repainted synchronously with its parent
2018-10-30 12:56:30 +00:00
/// if `false`, it should be considered independent of its parent regarding
2017-06-04 15:47:37 +00:00
/// repaint timings.
pub sync : bool ,
}
2017-09-03 17:53:29 +00:00
impl Default for SubsurfaceRole {
fn default ( ) -> SubsurfaceRole {
SubsurfaceRole {
2018-04-17 09:03:42 +00:00
location : ( 0 , 0 ) ,
2017-06-04 15:47:37 +00:00
sync : true ,
}
}
}
/// Kind of a rectangle part of a region
2017-09-03 17:53:29 +00:00
#[ derive(Copy, Clone, Debug) ]
2017-06-04 15:47:37 +00:00
pub enum RectangleKind {
/// This rectangle should be added to the region
Add ,
/// The intersection of this rectangle with the region should
/// be removed from the region
Subtract ,
}
/// Description of the contents of a region
///
/// A region is defined as an union and difference of rectangle.
///
2018-10-30 12:56:30 +00:00
/// This struct contains an ordered `Vec` containing the rectangles defining
/// a region. They should be added or subtracted in this order to compute the
2017-06-04 15:47:37 +00:00
/// actual contents of the region.
2017-09-03 17:53:29 +00:00
#[ derive(Clone, Debug) ]
2017-06-04 15:47:37 +00:00
pub struct RegionAttributes {
/// List of rectangle part of this region
pub rects : Vec < ( RectangleKind , Rectangle ) > ,
}
impl Default for RegionAttributes {
fn default ( ) -> RegionAttributes {
RegionAttributes { rects : Vec ::new ( ) }
}
}
2020-01-22 05:03:18 +00:00
impl RegionAttributes {
/// Checks whether given point is inside the region.
pub fn contains ( & self , point : ( i32 , i32 ) ) -> bool {
let mut contains = false ;
for ( kind , rect ) in & self . rects {
if rect . contains ( point ) {
match kind {
RectangleKind ::Add = > contains = true ,
RectangleKind ::Subtract = > contains = false ,
}
}
}
contains
}
}
2017-06-04 15:47:37 +00:00
/// A Compositor global token
///
/// This token can be cloned at will, and is the entry-point to
2018-12-08 12:40:07 +00:00
/// access data associated with the [`wl_surface`](wayland_server::protocol::wl_surface)
/// and [`wl_region`](wayland_server::protocol::wl_region) managed
2017-06-04 15:47:37 +00:00
/// by the `CompositorGlobal` that provided it.
2019-04-23 20:46:11 +00:00
pub struct CompositorToken < R > {
2017-09-03 17:53:29 +00:00
_role : ::std ::marker ::PhantomData < * mut R > ,
2017-06-04 15:47:37 +00:00
}
2019-04-23 20:46:11 +00:00
// we implement them manually because #[derive(..)] would require R: Clone
impl < R > Copy for CompositorToken < R > { }
impl < R > Clone for CompositorToken < R > {
fn clone ( & self ) -> CompositorToken < R > {
2017-06-13 14:46:31 +00:00
* self
}
}
2019-04-23 20:46:11 +00:00
unsafe impl < R > Send for CompositorToken < R > { }
unsafe impl < R > Sync for CompositorToken < R > { }
2018-05-13 08:24:24 +00:00
2019-04-23 20:46:11 +00:00
impl < R > CompositorToken < R > {
pub ( crate ) fn make ( ) -> CompositorToken < R > {
2017-09-20 07:57:43 +00:00
CompositorToken {
_role : ::std ::marker ::PhantomData ,
}
}
}
2019-04-23 20:46:11 +00:00
impl < R : 'static > CompositorToken < R > {
2017-06-04 15:47:37 +00:00
/// Access the data of a surface
///
/// The closure will be called with the contents of the data associated with this surface.
///
2018-10-30 12:56:30 +00:00
/// If the surface is not managed by the `CompositorGlobal` that provided this token, this
2017-06-04 15:47:37 +00:00
/// will panic (having more than one compositor is not supported).
2020-01-01 10:43:16 +00:00
pub fn with_surface_data < F , T > ( self , surface : & WlSurface , f : F ) -> T
2017-06-23 13:40:28 +00:00
where
2019-04-23 20:46:11 +00:00
F : FnOnce ( & mut SurfaceAttributes ) -> T ,
2017-06-04 15:47:37 +00:00
{
2019-04-23 20:46:11 +00:00
SurfaceData ::< R > ::with_data ( surface , f )
2017-06-04 15:47:37 +00:00
}
2017-09-03 17:53:29 +00:00
}
2017-06-04 15:47:37 +00:00
2019-04-23 20:46:11 +00:00
impl < R > CompositorToken < R >
2017-09-03 17:53:29 +00:00
where
2017-09-20 07:57:43 +00:00
R : RoleType + Role < SubsurfaceRole > + 'static ,
2017-09-03 17:53:29 +00:00
{
2017-09-22 09:12:49 +00:00
/// Access the data of a surface tree from bottom to top
2017-06-04 15:47:37 +00:00
///
2019-04-10 13:22:06 +00:00
/// You provide three closures, a "filter", a "processor" and a "post filter".
2017-06-04 15:47:37 +00:00
///
2019-04-10 13:22:06 +00:00
/// The first closure is initially called on a surface to determine if its children
/// should be processed as well. It returns a `TraversalAction<T>` reflecting that.
///
/// The second closure is supposed to do the actual processing. The processing closure for
/// a surface may be called after the processing closure of some of its children, depending
/// on the stack ordering the client requested. Here the surfaces are processed in the same
/// order as they are supposed to be drawn: from the farthest of the screen to the nearest.
///
/// The third closure is called once all the subtree of a node has been processed, and gives
/// an opportunity for early-stopping. If it returns `true` the processing will continue,
/// while if it returns `false` it'll stop.
///
/// The arguments provided to the closures are, in this order:
2017-09-03 17:53:29 +00:00
///
/// - The surface object itself
/// - a mutable reference to its surface attribute data
/// - a mutable reference to its role data,
2018-10-30 12:56:30 +00:00
/// - a custom value that is passed in a fold-like manner, but only from the output of a parent
2018-12-08 12:40:07 +00:00
/// to its children. See [`TraversalAction`] for details.
2017-09-03 17:53:29 +00:00
///
2018-10-30 12:56:30 +00:00
/// If the surface not managed by the `CompositorGlobal` that provided this token, this
2017-06-04 15:47:37 +00:00
/// will panic (having more than one compositor is not supported).
2019-04-10 13:22:06 +00:00
pub fn with_surface_tree_upward < F1 , F2 , F3 , T > (
2020-01-01 10:43:16 +00:00
self ,
2019-04-10 13:22:06 +00:00
surface : & WlSurface ,
initial : T ,
filter : F1 ,
processor : F2 ,
post_filter : F3 ,
) where
2019-04-23 20:46:11 +00:00
F1 : FnMut ( & WlSurface , & mut SurfaceAttributes , & mut R , & T ) -> TraversalAction < T > ,
F2 : FnMut ( & WlSurface , & mut SurfaceAttributes , & mut R , & T ) ,
F3 : FnMut ( & WlSurface , & mut SurfaceAttributes , & mut R , & T ) -> bool ,
2017-06-04 15:47:37 +00:00
{
2019-04-23 20:46:11 +00:00
SurfaceData ::< R > ::map_tree ( surface , & initial , filter , processor , post_filter , false ) ;
2017-09-22 09:12:49 +00:00
}
/// Access the data of a surface tree from top to bottom
///
2019-04-10 13:22:06 +00:00
/// Behavior is the same as [`with_surface_tree_upward`](CompositorToken::with_surface_tree_upward), but
/// the processing is done in the reverse order, from the nearest of the screen to the deepest.
2017-09-22 09:12:49 +00:00
///
2019-04-10 13:22:06 +00:00
/// This would typically be used to find out which surface of a subsurface tree has been clicked for example.
pub fn with_surface_tree_downward < F1 , F2 , F3 , T > (
2020-01-01 10:43:16 +00:00
self ,
2019-04-10 13:22:06 +00:00
surface : & WlSurface ,
initial : T ,
filter : F1 ,
processor : F2 ,
post_filter : F3 ,
) where
2019-04-23 20:46:11 +00:00
F1 : FnMut ( & WlSurface , & mut SurfaceAttributes , & mut R , & T ) -> TraversalAction < T > ,
F2 : FnMut ( & WlSurface , & mut SurfaceAttributes , & mut R , & T ) ,
F3 : FnMut ( & WlSurface , & mut SurfaceAttributes , & mut R , & T ) -> bool ,
2017-09-22 09:12:49 +00:00
{
2019-04-23 20:46:11 +00:00
SurfaceData ::< R > ::map_tree ( surface , & initial , filter , processor , post_filter , true ) ;
2017-06-04 15:47:37 +00:00
}
/// Retrieve the parent of this surface
///
/// Returns `None` is this surface is a root surface
///
2018-10-30 12:56:30 +00:00
/// If the surface is not managed by the `CompositorGlobal` that provided this token, this
2017-06-04 15:47:37 +00:00
/// will panic (having more than one compositor is not supported).
2020-01-01 10:43:16 +00:00
pub fn get_parent ( self , surface : & WlSurface ) -> Option < WlSurface > {
2019-04-23 20:46:11 +00:00
SurfaceData ::< R > ::get_parent ( surface )
2017-06-04 15:47:37 +00:00
}
2017-06-04 20:12:22 +00:00
2017-06-11 12:31:42 +00:00
/// Retrieve the children of this surface
///
2018-10-30 12:56:30 +00:00
/// If the surface is not managed by the `CompositorGlobal` that provided this token, this
2017-06-11 12:31:42 +00:00
/// will panic (having more than one compositor is not supported).
2020-01-01 10:43:16 +00:00
pub fn get_children ( self , surface : & WlSurface ) -> Vec < WlSurface > {
2019-04-23 20:46:11 +00:00
SurfaceData ::< R > ::get_children ( surface )
2017-06-11 12:31:42 +00:00
}
2017-09-03 17:53:29 +00:00
}
2017-06-11 12:31:42 +00:00
2019-04-23 20:46:11 +00:00
impl < R : RoleType + 'static > CompositorToken < R > {
2018-10-30 12:56:30 +00:00
/// Check whether this surface as a role or not
2017-06-04 15:47:37 +00:00
///
2018-10-30 12:56:30 +00:00
/// If the surface is not managed by the `CompositorGlobal` that provided this token, this
2017-06-04 15:47:37 +00:00
/// will panic (having more than one compositor is not supported).
2020-01-01 10:43:16 +00:00
pub fn has_a_role ( self , surface : & WlSurface ) -> bool {
2019-04-23 20:46:11 +00:00
SurfaceData ::< R > ::has_a_role ( surface )
2017-06-04 15:47:37 +00:00
}
2018-10-30 12:56:30 +00:00
/// Check whether this surface as a specific role
2017-06-04 15:47:37 +00:00
///
2018-10-30 12:56:30 +00:00
/// If the surface is not managed by the `CompositorGlobal` that provided this token, this
2017-09-03 17:53:29 +00:00
/// will panic (having more than one compositor is not supported).
2020-01-01 10:43:16 +00:00
pub fn has_role < RoleData > ( self , surface : & WlSurface ) -> bool
2017-09-03 17:53:29 +00:00
where
R : Role < RoleData > ,
{
2019-04-23 20:46:11 +00:00
SurfaceData ::< R > ::has_role ::< RoleData > ( surface )
2017-09-03 17:53:29 +00:00
}
/// Register that this surface has given role with default data
2017-06-04 15:47:37 +00:00
///
/// Fails if the surface already has a role.
///
2018-10-30 12:56:30 +00:00
/// If the surface is not managed by the `CompositorGlobal` that provided this token, this
2017-06-04 15:47:37 +00:00
/// will panic (having more than one compositor is not supported).
2020-01-01 10:43:16 +00:00
pub fn give_role < RoleData > ( self , surface : & WlSurface ) -> Result < ( ) , ( ) >
2017-09-03 17:53:29 +00:00
where
R : Role < RoleData > ,
RoleData : Default ,
{
2019-04-23 20:46:11 +00:00
SurfaceData ::< R > ::give_role ::< RoleData > ( surface )
2017-06-04 15:47:37 +00:00
}
2017-09-03 17:53:29 +00:00
/// Register that this surface has given role with given data
2017-06-04 15:47:37 +00:00
///
2017-09-03 17:53:29 +00:00
/// Fails if the surface already has a role and returns the data.
2017-06-04 15:47:37 +00:00
///
2018-10-30 12:56:30 +00:00
/// If the surface is not managed by the `CompositorGlobal` that provided this token, this
2017-06-04 15:47:37 +00:00
/// will panic (having more than one compositor is not supported).
2020-01-01 10:43:16 +00:00
pub fn give_role_with < RoleData > ( self , surface : & WlSurface , data : RoleData ) -> Result < ( ) , RoleData >
2017-09-03 17:53:29 +00:00
where
R : Role < RoleData > ,
{
2019-04-23 20:46:11 +00:00
SurfaceData ::< R > ::give_role_with ::< RoleData > ( surface , data )
2017-09-03 17:53:29 +00:00
}
2017-09-05 10:05:42 +00:00
/// Access the role data of a surface
///
/// Fails and don't call the closure if the surface doesn't have this role
///
2018-10-30 12:56:30 +00:00
/// If the surface is not managed by the `CompositorGlobal` that provided this token, this
2017-09-05 10:05:42 +00:00
/// will panic (having more than one compositor is not supported).
2020-01-01 10:43:16 +00:00
pub fn with_role_data < RoleData , F , T > ( self , surface : & WlSurface , f : F ) -> Result < T , WrongRole >
2017-09-05 10:05:42 +00:00
where
R : Role < RoleData > ,
2017-09-05 17:51:05 +00:00
F : FnOnce ( & mut RoleData ) -> T ,
2017-09-05 10:05:42 +00:00
{
2019-04-23 20:46:11 +00:00
SurfaceData ::< R > ::with_role_data ::< RoleData , _ , _ > ( surface , f )
2017-09-05 10:05:42 +00:00
}
2017-09-03 17:53:29 +00:00
/// Register that this surface does not have a role any longer and retrieve the data
///
/// Fails if the surface didn't already have this role.
///
2018-10-30 12:56:30 +00:00
/// If the surface is not managed by the `CompositorGlobal` that provided this token, this
2017-09-03 17:53:29 +00:00
/// will panic (having more than one compositor is not supported).
2020-01-01 10:43:16 +00:00
pub fn remove_role < RoleData > ( self , surface : & WlSurface ) -> Result < RoleData , WrongRole >
2017-09-03 17:53:29 +00:00
where
R : Role < RoleData > ,
{
2019-04-23 20:46:11 +00:00
SurfaceData ::< R > ::remove_role ::< RoleData > ( surface )
2017-06-04 15:47:37 +00:00
}
2017-06-11 12:31:42 +00:00
2018-10-30 12:56:30 +00:00
/// Retrieve the metadata associated with a `wl_region`
2017-06-11 12:31:42 +00:00
///
2018-10-30 12:56:30 +00:00
/// If the region is not managed by the `CompositorGlobal` that provided this token, this
2017-06-11 12:31:42 +00:00
/// will panic (having more than one compositor is not supported).
2020-01-01 10:43:16 +00:00
pub fn get_region_attributes ( self , region : & wl_region ::WlRegion ) -> RegionAttributes {
2019-02-22 16:55:00 +00:00
match region . as_ref ( ) . user_data ::< Mutex < RegionAttributes > > ( ) {
2018-09-24 22:30:39 +00:00
Some ( mutex ) = > mutex . lock ( ) . unwrap ( ) . clone ( ) ,
None = > panic! ( " Accessing the data of foreign regions is not supported. " ) ,
}
2017-06-11 12:31:42 +00:00
}
2017-06-04 15:47:37 +00:00
}
2017-06-04 19:36:18 +00:00
2018-12-08 12:40:07 +00:00
/// Create new [`wl_compositor`](wayland_server::protocol::wl_compositor)
/// and [`wl_subcompositor`](wayland_server::protocol::wl_subcompositor) globals.
2017-06-11 12:33:03 +00:00
///
2018-10-30 12:56:30 +00:00
/// The globals are directly registered into the event loop, and this function
2018-12-08 12:40:07 +00:00
/// returns a [`CompositorToken`] which you'll need access the data associated to
/// the [`wl_surface`](wayland_server::protocol::wl_surface)s.
2017-06-11 12:33:03 +00:00
///
2018-10-30 12:56:30 +00:00
/// It also returns the two global handles, in case you wish to remove these
2017-09-20 07:57:43 +00:00
/// globals from the event loop in the future.
2019-04-23 20:46:11 +00:00
pub fn compositor_init < R , Impl , L > (
2018-04-17 09:03:42 +00:00
display : & mut Display ,
implem : Impl ,
logger : L ,
2017-12-15 17:38:10 +00:00
) -> (
2019-04-23 20:46:11 +00:00
CompositorToken < R > ,
2018-04-17 09:03:42 +00:00
Global < wl_compositor ::WlCompositor > ,
Global < wl_subcompositor ::WlSubcompositor > ,
2017-12-15 17:38:10 +00:00
)
2017-09-20 07:57:43 +00:00
where
L : Into < Option < ::slog ::Logger > > ,
R : Default + RoleType + Role < SubsurfaceRole > + 'static ,
2019-04-23 20:46:11 +00:00
Impl : FnMut ( SurfaceEvent , WlSurface , CompositorToken < R > ) + 'static ,
2017-09-20 07:57:43 +00:00
{
2018-12-15 20:32:28 +00:00
let log = crate ::slog_or_stdlog ( logger ) . new ( o! ( " smithay_module " = > " compositor_handler " ) ) ;
2018-04-17 09:03:42 +00:00
let implem = Rc ::new ( RefCell ::new ( implem ) ) ;
2018-09-24 22:30:39 +00:00
let compositor = display . create_global ( 4 , move | new_compositor , _version | {
2019-04-23 20:46:11 +00:00
self ::handlers ::implement_compositor ::< R , Impl > ( new_compositor , log . clone ( ) , implem . clone ( ) ) ;
2018-04-17 09:03:42 +00:00
} ) ;
2018-09-24 22:30:39 +00:00
let subcompositor = display . create_global ( 1 , move | new_subcompositor , _version | {
2019-04-23 20:46:11 +00:00
self ::handlers ::implement_subcompositor ::< R > ( new_subcompositor ) ;
2018-04-17 09:03:42 +00:00
} ) ;
( CompositorToken ::make ( ) , compositor , subcompositor )
2017-06-04 20:12:22 +00:00
}
2018-04-17 09:03:42 +00:00
/// User-handled events for surfaces
2017-06-04 20:12:22 +00:00
///
2018-04-17 09:03:42 +00:00
/// The global provided by smithay cannot process these events for you, so
/// they are forwarded directly via your provided implementation, and are
/// described by this global.
pub enum SurfaceEvent {
2017-06-11 20:47:27 +00:00
/// The double-buffered state has been validated by the client
///
2018-12-08 12:40:07 +00:00
/// At this point, the pending state that has been accumulated in the [`SurfaceAttributes`] associated
2017-06-11 20:47:27 +00:00
/// to this surface should be integrated into the current state of the surface.
///
2017-09-20 07:57:43 +00:00
/// See [`wayland_server::protocol::wl_surface::Implementation::commit`](https://docs.rs/wayland-server/0.10.1/wayland_server/protocol/wl_surface/struct.Implementation.html#structfield.commit)
2017-06-11 20:47:27 +00:00
/// for more details
2018-04-17 09:03:42 +00:00
Commit ,
2017-06-11 20:47:27 +00:00
/// The client asks to be notified when would be a good time to update the contents of this surface
///
2018-12-08 12:40:07 +00:00
/// You must keep the provided [`WlCallback`](wayland_server::protocol::wl_callback::WlCallback)
/// and trigger it at the appropriate time by calling its `done()` method.
2017-06-11 20:47:27 +00:00
///
2017-09-20 07:57:43 +00:00
/// See [`wayland_server::protocol::wl_surface::Implementation::frame`](https://docs.rs/wayland-server/0.10.1/wayland_server/protocol/wl_surface/struct.Implementation.html#structfield.frame)
2017-06-11 20:47:27 +00:00
/// for more details
2018-04-17 09:03:42 +00:00
Frame {
/// The created `WlCallback`
callback : NewResource < wl_callback ::WlCallback > ,
} ,
2017-06-04 19:36:18 +00:00
}
2020-01-22 05:03:18 +00:00
#[ cfg(test) ]
mod tests {
use super ::* ;
#[ test ]
fn region_attributes_empty ( ) {
let region = RegionAttributes { rects : vec ! [ ] } ;
assert_eq! ( region . contains ( ( 0 , 0 ) ) , false ) ;
}
#[ test ]
fn region_attributes_add ( ) {
let region = RegionAttributes {
rects : vec ! [ (
RectangleKind ::Add ,
Rectangle {
x : 0 ,
y : 0 ,
width : 10 ,
height : 10 ,
} ,
) ] ,
} ;
assert_eq! ( region . contains ( ( 0 , 0 ) ) , true ) ;
}
#[ test ]
fn region_attributes_add_subtract ( ) {
let region = RegionAttributes {
rects : vec ! [
(
RectangleKind ::Add ,
Rectangle {
x : 0 ,
y : 0 ,
width : 10 ,
height : 10 ,
} ,
) ,
(
RectangleKind ::Subtract ,
Rectangle {
x : 0 ,
y : 0 ,
width : 5 ,
height : 5 ,
} ,
) ,
] ,
} ;
assert_eq! ( region . contains ( ( 0 , 0 ) ) , false ) ;
assert_eq! ( region . contains ( ( 5 , 5 ) ) , true ) ;
}
#[ test ]
fn region_attributes_add_subtract_add ( ) {
let region = RegionAttributes {
rects : vec ! [
(
RectangleKind ::Add ,
Rectangle {
x : 0 ,
y : 0 ,
width : 10 ,
height : 10 ,
} ,
) ,
(
RectangleKind ::Subtract ,
Rectangle {
x : 0 ,
y : 0 ,
width : 5 ,
height : 5 ,
} ,
) ,
(
RectangleKind ::Add ,
Rectangle {
x : 2 ,
y : 2 ,
width : 2 ,
height : 2 ,
} ,
) ,
] ,
} ;
assert_eq! ( region . contains ( ( 0 , 0 ) ) , false ) ;
assert_eq! ( region . contains ( ( 5 , 5 ) ) , true ) ;
assert_eq! ( region . contains ( ( 2 , 2 ) ) , true ) ;
}
}