2017-09-20 07:57:43 +00:00
|
|
|
use super::{CompositorToken, Damage, Rectangle, RectangleKind, Role, RoleType, SubsurfaceRole,
|
|
|
|
SurfaceUserImplementation};
|
2017-06-04 15:47:37 +00:00
|
|
|
use super::region::RegionData;
|
2017-06-04 20:41:42 +00:00
|
|
|
use super::tree::{Location, SurfaceData};
|
2017-09-20 07:57:43 +00:00
|
|
|
use std::cell::RefCell;
|
|
|
|
use std::rc::Rc;
|
|
|
|
use wayland_server::{Client, EventLoopHandle, Liveness, Resource};
|
|
|
|
use wayland_server::protocol::{wl_compositor, wl_region, wl_subcompositor, wl_subsurface, wl_surface};
|
2017-06-04 15:47:37 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* wl_compositor
|
|
|
|
*/
|
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
pub(crate) fn compositor_bind<U, R, ID>(evlh: &mut EventLoopHandle, idata: &mut SurfaceIData<U, R, ID>,
|
|
|
|
_: &Client, compositor: wl_compositor::WlCompositor)
|
2017-06-23 13:40:28 +00:00
|
|
|
where
|
2017-09-20 07:57:43 +00:00
|
|
|
U: Default + 'static,
|
|
|
|
R: Default + 'static,
|
|
|
|
ID: 'static,
|
2017-06-04 20:12:22 +00:00
|
|
|
{
|
2017-09-20 07:57:43 +00:00
|
|
|
trace!(idata.log, "Binding a new wl_compositor.");
|
|
|
|
evlh.register(
|
|
|
|
&compositor,
|
|
|
|
compositor_implementation::<U, R, ID>(),
|
|
|
|
idata.clone(),
|
|
|
|
None,
|
|
|
|
);
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
fn compositor_implementation<U, R, ID>() -> wl_compositor::Implementation<SurfaceIData<U, R, ID>>
|
|
|
|
where
|
|
|
|
U: Default + 'static,
|
|
|
|
R: Default + 'static,
|
|
|
|
ID: 'static,
|
|
|
|
{
|
|
|
|
wl_compositor::Implementation {
|
|
|
|
create_surface: |evlh, idata, _, _, surface| {
|
|
|
|
unsafe { SurfaceData::<U, R>::init(&surface) };
|
|
|
|
evlh.register(
|
|
|
|
&surface,
|
|
|
|
surface_implementation::<U, R, ID>(),
|
|
|
|
idata.clone(),
|
|
|
|
Some(destroy_surface::<U, R>),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
create_region: |evlh, _, _, _, region| {
|
|
|
|
unsafe { RegionData::init(®ion) };
|
|
|
|
evlh.register(®ion, region_implementation(), (), Some(destroy_region));
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2017-06-04 15:47:37 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* wl_surface
|
|
|
|
*/
|
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
/// Internal implementation data of surfaces
|
|
|
|
///
|
|
|
|
/// This type is only visible as type parameter of
|
|
|
|
/// the `Global` handle you are provided.
|
|
|
|
pub struct SurfaceIData<U, R, ID> {
|
|
|
|
log: ::slog::Logger,
|
|
|
|
implem: SurfaceUserImplementation<U, R, ID>,
|
|
|
|
idata: Rc<RefCell<ID>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<U, R, ID> SurfaceIData<U, R, ID> {
|
|
|
|
pub(crate) fn make(log: ::slog::Logger, implem: SurfaceUserImplementation<U, R, ID>, idata: ID)
|
|
|
|
-> SurfaceIData<U, R, ID> {
|
|
|
|
SurfaceIData {
|
|
|
|
log: log,
|
|
|
|
implem: implem,
|
|
|
|
idata: Rc::new(RefCell::new(idata)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<U, R, ID> Clone for SurfaceIData<U, R, ID> {
|
|
|
|
fn clone(&self) -> SurfaceIData<U, R, ID> {
|
|
|
|
SurfaceIData {
|
|
|
|
log: self.log.clone(),
|
|
|
|
implem: self.implem.clone(),
|
|
|
|
idata: self.idata.clone(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn surface_implementation<U: 'static, R: 'static, ID: 'static>(
|
|
|
|
)
|
|
|
|
-> wl_surface::Implementation<SurfaceIData<U, R, ID>>
|
|
|
|
{
|
|
|
|
wl_surface::Implementation {
|
|
|
|
attach: |_, _, _, surface, buffer, x, y| unsafe {
|
2017-09-03 17:53:29 +00:00
|
|
|
SurfaceData::<U, R>::with_data(surface, |d| {
|
2017-06-13 15:39:25 +00:00
|
|
|
d.buffer = Some(buffer.map(|b| (b.clone_unchecked(), (x, y))))
|
|
|
|
});
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
|
|
|
damage: |_, _, _, surface, x, y, width, height| unsafe {
|
2017-09-03 17:53:29 +00:00
|
|
|
SurfaceData::<U, R>::with_data(surface, |d| {
|
2017-06-04 20:12:22 +00:00
|
|
|
d.damage = Damage::Surface(Rectangle {
|
2017-06-23 13:40:28 +00:00
|
|
|
x,
|
|
|
|
y,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
})
|
2017-06-04 20:12:22 +00:00
|
|
|
});
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
|
|
|
frame: |evlh, idata, _, surface, callback| {
|
|
|
|
let mut user_idata = idata.idata.borrow_mut();
|
|
|
|
trace!(idata.log, "Calling user callback for wl_surface.frame");
|
|
|
|
(idata.implem.frame)(
|
|
|
|
evlh,
|
|
|
|
&mut *user_idata,
|
|
|
|
surface,
|
|
|
|
callback,
|
|
|
|
CompositorToken::make(),
|
|
|
|
)
|
|
|
|
},
|
|
|
|
set_opaque_region: |_, _, _, surface, region| unsafe {
|
2017-06-04 15:47:37 +00:00
|
|
|
let attributes = region.map(|r| RegionData::get_attributes(r));
|
2017-09-03 17:53:29 +00:00
|
|
|
SurfaceData::<U, R>::with_data(surface, |d| d.opaque_region = attributes);
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
|
|
|
set_input_region: |_, _, _, surface, region| unsafe {
|
2017-06-04 15:47:37 +00:00
|
|
|
let attributes = region.map(|r| RegionData::get_attributes(r));
|
2017-09-03 17:53:29 +00:00
|
|
|
SurfaceData::<U, R>::with_data(surface, |d| d.input_region = attributes);
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
|
|
|
commit: |evlh, idata, _, surface| {
|
|
|
|
let mut user_idata = idata.idata.borrow_mut();
|
|
|
|
trace!(idata.log, "Calling user callback for wl_surface.commit");
|
|
|
|
(idata.implem.commit)(evlh, &mut *user_idata, surface, CompositorToken::make())
|
|
|
|
},
|
|
|
|
set_buffer_transform: |_, _, _, surface, transform| unsafe {
|
2017-09-03 17:53:29 +00:00
|
|
|
SurfaceData::<U, R>::with_data(surface, |d| d.buffer_transform = transform);
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
|
|
|
set_buffer_scale: |_, _, _, surface, scale| unsafe {
|
2017-09-03 17:53:29 +00:00
|
|
|
SurfaceData::<U, R>::with_data(surface, |d| d.buffer_scale = scale);
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
|
|
|
damage_buffer: |_, _, _, surface, x, y, width, height| unsafe {
|
2017-09-03 17:53:29 +00:00
|
|
|
SurfaceData::<U, R>::with_data(surface, |d| {
|
2017-06-04 20:12:22 +00:00
|
|
|
d.damage = Damage::Buffer(Rectangle {
|
2017-06-23 13:40:28 +00:00
|
|
|
x,
|
|
|
|
y,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
})
|
2017-06-04 20:12:22 +00:00
|
|
|
});
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
|
|
|
destroy: |_, _, _, _| {},
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
fn destroy_surface<U: 'static, R: 'static>(surface: &wl_surface::WlSurface) {
|
|
|
|
unsafe { SurfaceData::<U, R>::cleanup(surface) }
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* wl_region
|
|
|
|
*/
|
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
pub(crate) fn region_implementation() -> wl_region::Implementation<()> {
|
|
|
|
wl_region::Implementation {
|
|
|
|
add: |_, _, _, region, x, y, width, height| {
|
|
|
|
unsafe {
|
|
|
|
RegionData::add_rectangle(
|
|
|
|
region,
|
|
|
|
RectangleKind::Add,
|
|
|
|
Rectangle {
|
|
|
|
x,
|
|
|
|
y,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
};
|
|
|
|
},
|
|
|
|
subtract: |_, _, _, region, x, y, width, height| {
|
|
|
|
unsafe {
|
|
|
|
RegionData::add_rectangle(
|
|
|
|
region,
|
|
|
|
RectangleKind::Subtract,
|
|
|
|
Rectangle {
|
|
|
|
x,
|
|
|
|
y,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
};
|
|
|
|
},
|
|
|
|
destroy: |_, _, _, _| {},
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
fn destroy_region(region: &wl_region::WlRegion) {
|
|
|
|
unsafe { RegionData::cleanup(region) };
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* wl_subcompositor
|
|
|
|
*/
|
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
pub(crate) fn subcompositor_bind<U, R>(evlh: &mut EventLoopHandle, _: &mut (), _: &Client,
|
|
|
|
subcompositor: wl_subcompositor::WlSubcompositor)
|
|
|
|
where
|
|
|
|
R: RoleType + Role<SubsurfaceRole> + 'static,
|
|
|
|
U: 'static,
|
|
|
|
{
|
|
|
|
evlh.register(
|
|
|
|
&subcompositor,
|
|
|
|
subcompositor_implementation::<U, R>(),
|
|
|
|
(),
|
|
|
|
None,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn subcompositor_implementation<U, R>() -> wl_subcompositor::Implementation<()>
|
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
|
|
|
{
|
2017-09-20 07:57:43 +00:00
|
|
|
wl_subcompositor::Implementation {
|
|
|
|
get_subsurface: |evlh, _, _, subcompositor, subsurface, surface, parent| {
|
|
|
|
if let Err(()) = unsafe { SurfaceData::<U, R>::set_parent(surface, parent) } {
|
|
|
|
subcompositor.post_error(
|
|
|
|
wl_subcompositor::Error::BadSurface as u32,
|
|
|
|
"Surface already has a role.".into(),
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
2017-09-21 18:50:10 +00:00
|
|
|
subsurface.set_user_data(Box::into_raw(Box::new(unsafe { surface.clone_unchecked() })) as *mut _);
|
2017-09-20 07:57:43 +00:00
|
|
|
evlh.register(
|
|
|
|
&subsurface,
|
|
|
|
subsurface_implementation::<U, R>(),
|
|
|
|
(),
|
|
|
|
Some(destroy_subsurface::<U, R>),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
destroy: |_, _, _, _| {},
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* wl_subsurface
|
|
|
|
*/
|
|
|
|
|
2017-09-03 17:53:29 +00:00
|
|
|
unsafe fn with_subsurface_attributes<U, R, F>(subsurface: &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
|
|
|
{
|
|
|
|
let ptr = subsurface.get_user_data();
|
|
|
|
let surface = &*(ptr as *mut wl_surface::WlSurface);
|
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
|
|
|
}
|
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
fn subsurface_implementation<U, R>() -> wl_subsurface::Implementation<()>
|
2017-09-03 17:53:29 +00:00
|
|
|
where
|
2017-09-20 07:57:43 +00:00
|
|
|
R: RoleType + Role<SubsurfaceRole> + 'static,
|
|
|
|
U: 'static,
|
2017-09-03 17:53:29 +00:00
|
|
|
{
|
2017-09-20 07:57:43 +00:00
|
|
|
wl_subsurface::Implementation {
|
|
|
|
set_position: |_, _, _, subsurface, x, y| unsafe {
|
2017-09-03 17:53:29 +00:00
|
|
|
with_subsurface_attributes::<U, R, _>(subsurface, |attrs| {
|
2017-06-04 15:47:37 +00:00
|
|
|
attrs.x = x;
|
|
|
|
attrs.y = y;
|
|
|
|
});
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
|
|
|
place_above: |_, _, _, subsurface, sibling| unsafe {
|
2017-06-04 20:41:42 +00:00
|
|
|
let ptr = subsurface.get_user_data();
|
|
|
|
let surface = &*(ptr as *mut wl_surface::WlSurface);
|
2017-09-03 17:53:29 +00:00
|
|
|
if let Err(()) = SurfaceData::<U, R>::reorder(surface, Location::After, sibling) {
|
2017-09-05 17:51:05 +00:00
|
|
|
subsurface.post_error(
|
|
|
|
wl_subsurface::Error::BadSurface as u32,
|
|
|
|
"Provided surface is not a sibling or parent.".into(),
|
|
|
|
);
|
2017-06-04 20:41:42 +00:00
|
|
|
}
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
|
|
|
place_below: |_, _, _, subsurface, sibling| unsafe {
|
2017-06-04 20:41:42 +00:00
|
|
|
let ptr = subsurface.get_user_data();
|
|
|
|
let surface = &*(ptr as *mut wl_surface::WlSurface);
|
2017-09-03 17:53:29 +00:00
|
|
|
if let Err(()) = SurfaceData::<U, R>::reorder(surface, Location::Before, sibling) {
|
2017-09-05 17:51:05 +00:00
|
|
|
subsurface.post_error(
|
|
|
|
wl_subsurface::Error::BadSurface as u32,
|
|
|
|
"Provided surface is not a sibling or parent.".into(),
|
|
|
|
);
|
2017-06-04 20:41:42 +00:00
|
|
|
}
|
2017-09-20 07:57:43 +00:00
|
|
|
},
|
|
|
|
set_sync: |_, _, _, subsurface| unsafe {
|
|
|
|
with_subsurface_attributes::<U, R, _>(subsurface, |attrs| {
|
|
|
|
attrs.sync = true;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
set_desync: |_, _, _, subsurface| unsafe {
|
|
|
|
with_subsurface_attributes::<U, R, _>(subsurface, |attrs| {
|
|
|
|
attrs.sync = false;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
destroy: |_, _, _, _| {},
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
fn destroy_subsurface<U, R>(subsurface: &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
|
|
|
{
|
2017-09-20 07:57:43 +00:00
|
|
|
let ptr = subsurface.get_user_data();
|
|
|
|
subsurface.set_user_data(::std::ptr::null_mut());
|
|
|
|
unsafe {
|
|
|
|
let surface = Box::from_raw(ptr as *mut wl_surface::WlSurface);
|
|
|
|
if surface.status() == Liveness::Alive {
|
|
|
|
SurfaceData::<U, R>::unset_parent(&surface);
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|