2018-10-04 22:37:43 +00:00
|
|
|
use std::{cell::RefCell, rc::Rc, sync::Mutex};
|
2018-09-24 22:30:39 +00:00
|
|
|
|
2018-10-04 22:37:43 +00:00
|
|
|
use wayland_server::{
|
|
|
|
protocol::{wl_compositor, wl_region, wl_subcompositor, wl_subsurface, wl_surface},
|
|
|
|
DisplayToken, NewResource, Resource,
|
|
|
|
};
|
2018-09-24 22:30:39 +00:00
|
|
|
|
|
|
|
use super::{
|
2018-10-04 22:37:43 +00:00
|
|
|
tree::{Location, SurfaceData},
|
2018-09-24 22:30:39 +00:00
|
|
|
CompositorToken, Damage, Rectangle, RectangleKind, RegionAttributes, Role, RoleType, SubsurfaceRole,
|
|
|
|
SurfaceEvent,
|
|
|
|
};
|
2017-06-04 15:47:37 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* wl_compositor
|
|
|
|
*/
|
|
|
|
|
2018-04-17 09:03:42 +00:00
|
|
|
pub(crate) fn implement_compositor<U, R, Impl>(
|
|
|
|
compositor: NewResource<wl_compositor::WlCompositor>,
|
2018-09-24 22:30:39 +00:00
|
|
|
token: DisplayToken,
|
2018-04-17 09:03:42 +00:00
|
|
|
log: ::slog::Logger,
|
|
|
|
implem: Rc<RefCell<Impl>>,
|
|
|
|
) -> Resource<wl_compositor::WlCompositor>
|
2017-09-20 07:57:43 +00:00
|
|
|
where
|
|
|
|
U: Default + 'static,
|
|
|
|
R: Default + 'static,
|
2018-09-24 22:30:39 +00:00
|
|
|
Impl: FnMut(SurfaceEvent, Resource<wl_surface::WlSurface>, CompositorToken<U, R>) + 'static,
|
2017-09-20 07:57:43 +00:00
|
|
|
{
|
2018-04-17 09:03:42 +00:00
|
|
|
let my_token = token.clone();
|
|
|
|
compositor.implement_nonsend(
|
|
|
|
move |request, _compositor| match request {
|
|
|
|
wl_compositor::Request::CreateSurface { id } => {
|
|
|
|
trace!(log, "Creating a new wl_surface.");
|
|
|
|
implement_surface(id, &token, log.clone(), implem.clone());
|
|
|
|
}
|
|
|
|
wl_compositor::Request::CreateRegion { id } => {
|
|
|
|
trace!(log, "Creating a new wl_region.");
|
|
|
|
implement_region(id, &token);
|
|
|
|
}
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
2018-09-24 22:30:39 +00:00
|
|
|
None::<fn(_)>,
|
|
|
|
(),
|
2018-04-17 09:03:42 +00:00
|
|
|
&my_token,
|
|
|
|
)
|
2017-09-20 07:57:43 +00:00
|
|
|
}
|
2017-06-04 15:47:37 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* wl_surface
|
|
|
|
*/
|
|
|
|
|
2018-04-17 09:03:42 +00:00
|
|
|
// Internal implementation data of surfaces
|
|
|
|
pub(crate) struct SurfaceImplem<U, R> {
|
2017-09-20 07:57:43 +00:00
|
|
|
log: ::slog::Logger,
|
2018-09-24 22:30:39 +00:00
|
|
|
implem: Rc<RefCell<FnMut(SurfaceEvent, Resource<wl_surface::WlSurface>, CompositorToken<U, R>)>>,
|
2017-09-20 07:57:43 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 09:03:42 +00:00
|
|
|
impl<U, R> SurfaceImplem<U, R> {
|
|
|
|
fn make<Impl>(log: ::slog::Logger, implem: Rc<RefCell<Impl>>) -> SurfaceImplem<U, R>
|
|
|
|
where
|
2018-09-24 22:30:39 +00:00
|
|
|
Impl: FnMut(SurfaceEvent, Resource<wl_surface::WlSurface>, CompositorToken<U, R>) + 'static,
|
2018-04-17 09:03:42 +00:00
|
|
|
{
|
2018-09-24 22:30:39 +00:00
|
|
|
SurfaceImplem { log, implem }
|
2017-09-20 07:57:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-24 22:30:39 +00:00
|
|
|
impl<U, R> SurfaceImplem<U, R>
|
2018-04-17 09:03:42 +00:00
|
|
|
where
|
|
|
|
U: 'static,
|
|
|
|
R: 'static,
|
|
|
|
{
|
2018-09-24 22:30:39 +00:00
|
|
|
fn receive_surface_request(
|
|
|
|
&mut self,
|
|
|
|
req: wl_surface::Request,
|
|
|
|
surface: Resource<wl_surface::WlSurface>,
|
|
|
|
) {
|
2018-04-17 09:03:42 +00:00
|
|
|
match req {
|
2018-09-24 22:30:39 +00:00
|
|
|
wl_surface::Request::Attach { buffer, x, y } => {
|
2018-04-17 09:03:42 +00:00
|
|
|
SurfaceData::<U, R>::with_data(&surface, |d| {
|
|
|
|
d.buffer = Some(buffer.map(|b| (b.clone(), (x, y))))
|
|
|
|
});
|
2018-09-24 22:30:39 +00:00
|
|
|
}
|
|
|
|
wl_surface::Request::Damage { x, y, width, height } => {
|
2018-04-17 09:03:42 +00:00
|
|
|
SurfaceData::<U, R>::with_data(&surface, |d| {
|
2018-09-24 22:30:39 +00:00
|
|
|
d.damage = Damage::Surface(Rectangle { x, y, width, height })
|
2018-04-17 09:03:42 +00:00
|
|
|
});
|
2018-09-24 22:30:39 +00:00
|
|
|
}
|
2018-04-17 09:03:42 +00:00
|
|
|
wl_surface::Request::Frame { callback } => {
|
|
|
|
let mut user_impl = self.implem.borrow_mut();
|
|
|
|
trace!(self.log, "Calling user implementation for wl_surface.frame");
|
2018-09-24 22:30:39 +00:00
|
|
|
(&mut *user_impl)(SurfaceEvent::Frame { callback }, surface, CompositorToken::make());
|
2018-04-17 09:03:42 +00:00
|
|
|
}
|
2018-09-24 22:30:39 +00:00
|
|
|
wl_surface::Request::SetOpaqueRegion { region } => {
|
|
|
|
let attributes = region.map(|r| {
|
|
|
|
let attributes_mutex = r.user_data::<Mutex<RegionAttributes>>().unwrap();
|
|
|
|
attributes_mutex.lock().unwrap().clone()
|
|
|
|
});
|
2018-04-17 09:03:42 +00:00
|
|
|
SurfaceData::<U, R>::with_data(&surface, |d| d.opaque_region = attributes);
|
2018-09-24 22:30:39 +00:00
|
|
|
}
|
|
|
|
wl_surface::Request::SetInputRegion { region } => {
|
|
|
|
let attributes = region.map(|r| {
|
|
|
|
let attributes_mutex = r.user_data::<Mutex<RegionAttributes>>().unwrap();
|
|
|
|
attributes_mutex.lock().unwrap().clone()
|
|
|
|
});
|
2018-04-17 09:03:42 +00:00
|
|
|
SurfaceData::<U, R>::with_data(&surface, |d| d.input_region = attributes);
|
2018-09-24 22:30:39 +00:00
|
|
|
}
|
2018-04-17 09:03:42 +00:00
|
|
|
wl_surface::Request::Commit => {
|
|
|
|
let mut user_impl = self.implem.borrow_mut();
|
2018-09-24 22:30:39 +00:00
|
|
|
trace!(self.log, "Calling user implementation for wl_surface.commit");
|
|
|
|
(&mut *user_impl)(SurfaceEvent::Commit, surface, CompositorToken::make());
|
2018-04-17 09:03:42 +00:00
|
|
|
}
|
2018-09-24 22:30:39 +00:00
|
|
|
wl_surface::Request::SetBufferTransform { transform } => {
|
2018-04-17 09:03:42 +00:00
|
|
|
SurfaceData::<U, R>::with_data(&surface, |d| d.buffer_transform = transform);
|
2018-09-24 22:30:39 +00:00
|
|
|
}
|
|
|
|
wl_surface::Request::SetBufferScale { scale } => {
|
2018-04-17 09:03:42 +00:00
|
|
|
SurfaceData::<U, R>::with_data(&surface, |d| d.buffer_scale = scale);
|
2018-09-24 22:30:39 +00:00
|
|
|
}
|
|
|
|
wl_surface::Request::DamageBuffer { x, y, width, height } => {
|
2018-04-17 09:03:42 +00:00
|
|
|
SurfaceData::<U, R>::with_data(&surface, |d| {
|
2018-09-24 22:30:39 +00:00
|
|
|
d.damage = Damage::Buffer(Rectangle { x, y, width, height })
|
2018-04-17 09:03:42 +00:00
|
|
|
});
|
2018-09-24 22:30:39 +00:00
|
|
|
}
|
2018-04-17 09:03:42 +00:00
|
|
|
wl_surface::Request::Destroy => {
|
|
|
|
// All is already handled by our destructor
|
|
|
|
}
|
2017-09-20 07:57:43 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-17 09:03:42 +00:00
|
|
|
fn implement_surface<U, R, Impl>(
|
|
|
|
surface: NewResource<wl_surface::WlSurface>,
|
2018-09-24 22:30:39 +00:00
|
|
|
token: &DisplayToken,
|
2018-04-17 09:03:42 +00:00
|
|
|
log: ::slog::Logger,
|
|
|
|
implem: Rc<RefCell<Impl>>,
|
|
|
|
) -> Resource<wl_surface::WlSurface>
|
|
|
|
where
|
|
|
|
U: Default + 'static,
|
|
|
|
R: Default + 'static,
|
2018-09-24 22:30:39 +00:00
|
|
|
Impl: FnMut(SurfaceEvent, Resource<wl_surface::WlSurface>, CompositorToken<U, R>) + 'static,
|
2018-04-17 09:03:42 +00:00
|
|
|
{
|
|
|
|
let surface = surface.implement_nonsend(
|
2018-09-24 22:30:39 +00:00
|
|
|
{
|
|
|
|
let mut implem = SurfaceImplem::make(log, implem);
|
|
|
|
move |req, surface| implem.receive_surface_request(req, surface)
|
|
|
|
},
|
|
|
|
Some(|surface| SurfaceData::<U, R>::cleanup(&surface)),
|
|
|
|
SurfaceData::<U, R>::new(),
|
2018-04-17 09:03:42 +00:00
|
|
|
token,
|
|
|
|
);
|
|
|
|
surface
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* wl_region
|
|
|
|
*/
|
|
|
|
|
2018-09-24 22:30:39 +00:00
|
|
|
fn region_implem(request: wl_region::Request, region: Resource<wl_region::WlRegion>) {
|
|
|
|
let attributes_mutex = region.user_data::<Mutex<RegionAttributes>>().unwrap();
|
|
|
|
let mut guard = attributes_mutex.lock().unwrap();
|
|
|
|
match request {
|
|
|
|
wl_region::Request::Add { x, y, width, height } => guard
|
|
|
|
.rects
|
|
|
|
.push((RectangleKind::Add, Rectangle { x, y, width, height })),
|
|
|
|
wl_region::Request::Subtract { x, y, width, height } => guard
|
|
|
|
.rects
|
|
|
|
.push((RectangleKind::Subtract, Rectangle { x, y, width, height })),
|
|
|
|
wl_region::Request::Destroy => {
|
|
|
|
// all is handled by our destructor
|
2018-04-17 09:03:42 +00:00
|
|
|
}
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-17 09:03:42 +00:00
|
|
|
fn implement_region(
|
|
|
|
region: NewResource<wl_region::WlRegion>,
|
2018-09-24 22:30:39 +00:00
|
|
|
token: &DisplayToken,
|
2018-04-17 09:03:42 +00:00
|
|
|
) -> Resource<wl_region::WlRegion> {
|
2018-09-24 22:30:39 +00:00
|
|
|
region.implement_nonsend(
|
|
|
|
region_implem,
|
|
|
|
None::<fn(_)>,
|
|
|
|
Mutex::new(RegionAttributes::default()),
|
2018-04-17 09:03:42 +00:00
|
|
|
token,
|
2018-09-24 22:30:39 +00:00
|
|
|
)
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* wl_subcompositor
|
|
|
|
*/
|
|
|
|
|
2018-04-17 09:03:42 +00:00
|
|
|
pub(crate) fn implement_subcompositor<U, R>(
|
|
|
|
subcompositor: NewResource<wl_subcompositor::WlSubcompositor>,
|
2018-09-24 22:30:39 +00:00
|
|
|
token: DisplayToken,
|
2018-04-17 09:03:42 +00:00
|
|
|
) -> Resource<wl_subcompositor::WlSubcompositor>
|
2017-06-23 13:40:28 +00:00
|
|
|
where
|
2017-09-20 07:57:43 +00:00
|
|
|
R: RoleType + Role<SubsurfaceRole> + 'static,
|
|
|
|
U: 'static,
|
2017-06-04 20:12:22 +00:00
|
|
|
{
|
2018-04-17 09:03:42 +00:00
|
|
|
let my_token = token.clone();
|
|
|
|
subcompositor.implement_nonsend(
|
|
|
|
move |request, subcompositor: Resource<_>| match request {
|
2018-09-24 22:30:39 +00:00
|
|
|
wl_subcompositor::Request::GetSubsurface { id, surface, parent } => {
|
|
|
|
if let Err(()) = SurfaceData::<U, R>::set_parent(&surface, &parent) {
|
2018-04-17 09:03:42 +00:00
|
|
|
subcompositor.post_error(
|
|
|
|
wl_subcompositor::Error::BadSurface as u32,
|
|
|
|
"Surface already has a role.".into(),
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
2018-09-24 22:30:39 +00:00
|
|
|
implement_subsurface::<U, R>(id, surface.clone(), &token);
|
2017-09-20 07:57:43 +00:00
|
|
|
}
|
2018-04-17 09:03:42 +00:00
|
|
|
wl_subcompositor::Request::Destroy => {}
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
2018-09-24 22:30:39 +00:00
|
|
|
None::<fn(_)>,
|
|
|
|
(),
|
2018-04-17 09:03:42 +00:00
|
|
|
&my_token,
|
|
|
|
)
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* wl_subsurface
|
|
|
|
*/
|
|
|
|
|
2018-09-24 22:30:39 +00:00
|
|
|
fn with_subsurface_attributes<U, R, F>(subsurface: &Resource<wl_subsurface::WlSubsurface>, f: F)
|
2017-06-23 13:40:28 +00:00
|
|
|
where
|
2017-09-03 17:53:29 +00:00
|
|
|
F: FnOnce(&mut SubsurfaceRole),
|
2017-09-20 07:57:43 +00:00
|
|
|
U: 'static,
|
|
|
|
R: RoleType + Role<SubsurfaceRole> + 'static,
|
2017-06-04 15:47:37 +00:00
|
|
|
{
|
2018-09-24 22:30:39 +00:00
|
|
|
let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap();
|
2017-09-21 18:50:10 +00:00
|
|
|
SurfaceData::<U, R>::with_role_data::<SubsurfaceRole, _, _>(surface, |d| f(d))
|
|
|
|
.expect("The surface does not have a subsurface role while it has a wl_subsurface?!");
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 09:03:42 +00:00
|
|
|
fn implement_subsurface<U, R>(
|
|
|
|
subsurface: NewResource<wl_subsurface::WlSubsurface>,
|
2018-09-24 22:30:39 +00:00
|
|
|
surface: Resource<wl_surface::WlSurface>,
|
|
|
|
token: &DisplayToken,
|
2018-04-17 09:03:42 +00:00
|
|
|
) -> Resource<wl_subsurface::WlSubsurface>
|
2017-09-03 17:53:29 +00:00
|
|
|
where
|
2017-09-20 07:57:43 +00:00
|
|
|
U: 'static,
|
2018-04-17 09:03:42 +00:00
|
|
|
R: RoleType + Role<SubsurfaceRole> + 'static,
|
2017-09-03 17:53:29 +00:00
|
|
|
{
|
2018-04-17 09:03:42 +00:00
|
|
|
subsurface.implement_nonsend(
|
2018-09-24 22:30:39 +00:00
|
|
|
|request, subsurface| {
|
2018-04-17 09:03:42 +00:00
|
|
|
match request {
|
|
|
|
wl_subsurface::Request::SetPosition { x, y } => {
|
|
|
|
with_subsurface_attributes::<U, R, _>(&subsurface, |attrs| {
|
|
|
|
attrs.location = (x, y);
|
|
|
|
})
|
|
|
|
}
|
|
|
|
wl_subsurface::Request::PlaceAbove { sibling } => {
|
2018-09-24 22:30:39 +00:00
|
|
|
let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap();
|
2018-04-17 09:03:42 +00:00
|
|
|
if let Err(()) = SurfaceData::<U, R>::reorder(surface, Location::After, &sibling) {
|
|
|
|
subsurface.post_error(
|
|
|
|
wl_subsurface::Error::BadSurface as u32,
|
|
|
|
"Provided surface is not a sibling or parent.".into(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wl_subsurface::Request::PlaceBelow { sibling } => {
|
2018-09-24 22:30:39 +00:00
|
|
|
let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap();
|
2018-04-17 09:03:42 +00:00
|
|
|
if let Err(()) = SurfaceData::<U, R>::reorder(surface, Location::Before, &sibling) {
|
|
|
|
subsurface.post_error(
|
|
|
|
wl_subsurface::Error::BadSurface as u32,
|
|
|
|
"Provided surface is not a sibling or parent.".into(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wl_subsurface::Request::SetSync => {
|
|
|
|
with_subsurface_attributes::<U, R, _>(&subsurface, |attrs| {
|
|
|
|
attrs.sync = true;
|
|
|
|
})
|
|
|
|
}
|
|
|
|
wl_subsurface::Request::SetDesync => {
|
|
|
|
with_subsurface_attributes::<U, R, _>(&subsurface, |attrs| {
|
|
|
|
attrs.sync = false;
|
|
|
|
})
|
|
|
|
}
|
|
|
|
wl_subsurface::Request::Destroy => {
|
|
|
|
// Our destructor already handles it
|
|
|
|
}
|
2017-06-04 20:41:42 +00:00
|
|
|
}
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
2018-09-24 22:30:39 +00:00
|
|
|
Some(|subsurface| destroy_subsurface::<U, R>(&subsurface)),
|
|
|
|
surface,
|
2018-04-17 09:03:42 +00:00
|
|
|
token,
|
|
|
|
)
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
|
2018-09-24 22:30:39 +00:00
|
|
|
fn destroy_subsurface<U, R>(subsurface: &Resource<wl_subsurface::WlSubsurface>)
|
2017-09-05 17:51:05 +00:00
|
|
|
where
|
2017-09-20 07:57:43 +00:00
|
|
|
U: 'static,
|
|
|
|
R: RoleType + Role<SubsurfaceRole> + 'static,
|
2017-09-03 17:53:29 +00:00
|
|
|
{
|
2018-09-24 22:30:39 +00:00
|
|
|
let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap();
|
2018-04-17 09:03:42 +00:00
|
|
|
if surface.is_alive() {
|
|
|
|
SurfaceData::<U, R>::unset_parent(&surface);
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
}
|