wayland.compositor: migrate to wayland_rs-0.20
This commit is contained in:
parent
e44b0e596e
commit
710d23f51f
|
@ -1,168 +1,188 @@
|
|||
use super::{CompositorToken, Damage, Rectangle, RectangleKind, Role, RoleType, SubsurfaceRole,
|
||||
SurfaceUserImplementation};
|
||||
use super::{CompositorToken, Damage, Rectangle, RectangleKind, Role, RoleType, SubsurfaceRole, SurfaceEvent};
|
||||
use super::region::RegionData;
|
||||
use super::tree::{Location, SurfaceData};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
use wayland_server::{Client, EventLoopHandle, Liveness, Resource};
|
||||
use wayland_server::{LoopToken, NewResource, Resource};
|
||||
use wayland_server::commons::Implementation;
|
||||
use wayland_server::protocol::{wl_compositor, wl_region, wl_subcompositor, wl_subsurface, wl_surface};
|
||||
|
||||
/*
|
||||
* wl_compositor
|
||||
*/
|
||||
|
||||
pub(crate) fn compositor_bind<U, R, ID>(
|
||||
evlh: &mut EventLoopHandle, idata: &mut SurfaceIData<U, R, ID>, _: &Client,
|
||||
compositor: wl_compositor::WlCompositor,
|
||||
) where
|
||||
U: Default + 'static,
|
||||
R: Default + 'static,
|
||||
ID: 'static,
|
||||
{
|
||||
trace!(idata.log, "Binding a new wl_compositor.");
|
||||
evlh.register(
|
||||
&compositor,
|
||||
compositor_implementation::<U, R, ID>(),
|
||||
idata.clone(),
|
||||
None,
|
||||
);
|
||||
}
|
||||
|
||||
fn compositor_implementation<U, R, ID>() -> wl_compositor::Implementation<SurfaceIData<U, R, ID>>
|
||||
pub(crate) fn implement_compositor<U, R, Impl>(
|
||||
compositor: NewResource<wl_compositor::WlCompositor>,
|
||||
token: LoopToken,
|
||||
log: ::slog::Logger,
|
||||
implem: Rc<RefCell<Impl>>,
|
||||
) -> Resource<wl_compositor::WlCompositor>
|
||||
where
|
||||
U: Default + 'static,
|
||||
R: Default + 'static,
|
||||
ID: 'static,
|
||||
Impl: Implementation<(Resource<wl_surface::WlSurface>, CompositorToken<U, R>), SurfaceEvent> + '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>),
|
||||
);
|
||||
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);
|
||||
}
|
||||
},
|
||||
create_region: |evlh, _, _, _, region| {
|
||||
unsafe { RegionData::init(®ion) };
|
||||
evlh.register(®ion, region_implementation(), (), Some(destroy_region));
|
||||
},
|
||||
}
|
||||
None::<fn(_, _)>,
|
||||
&my_token,
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
* wl_surface
|
||||
*/
|
||||
|
||||
/// 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> {
|
||||
// Internal implementation data of surfaces
|
||||
pub(crate) struct SurfaceImplem<U, R> {
|
||||
log: ::slog::Logger,
|
||||
implem: SurfaceUserImplementation<U, R, ID>,
|
||||
idata: Rc<RefCell<ID>>,
|
||||
implem:
|
||||
Rc<RefCell<Implementation<(Resource<wl_surface::WlSurface>, CompositorToken<U, R>), SurfaceEvent>>>,
|
||||
}
|
||||
|
||||
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 {
|
||||
impl<U, R> SurfaceImplem<U, R> {
|
||||
fn make<Impl>(log: ::slog::Logger, implem: Rc<RefCell<Impl>>) -> SurfaceImplem<U, R>
|
||||
where
|
||||
Impl: Implementation<(Resource<wl_surface::WlSurface>, CompositorToken<U, R>), SurfaceEvent>
|
||||
+ 'static,
|
||||
{
|
||||
SurfaceImplem {
|
||||
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,
|
||||
idata: self.idata.clone(),
|
||||
impl<U, R> Implementation<Resource<wl_surface::WlSurface>, wl_surface::Request> for SurfaceImplem<U, R>
|
||||
where
|
||||
U: 'static,
|
||||
R: 'static,
|
||||
{
|
||||
fn receive(&mut self, req: wl_surface::Request, surface: Resource<wl_surface::WlSurface>) {
|
||||
match req {
|
||||
wl_surface::Request::Attach { buffer, x, y } => unsafe {
|
||||
SurfaceData::<U, R>::with_data(&surface, |d| {
|
||||
d.buffer = Some(buffer.map(|b| (b.clone(), (x, y))))
|
||||
});
|
||||
},
|
||||
wl_surface::Request::Damage {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
} => unsafe {
|
||||
SurfaceData::<U, R>::with_data(&surface, |d| {
|
||||
d.damage = Damage::Surface(Rectangle {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
});
|
||||
},
|
||||
wl_surface::Request::Frame { callback } => {
|
||||
let mut user_impl = self.implem.borrow_mut();
|
||||
trace!(self.log, "Calling user implementation for wl_surface.frame");
|
||||
user_impl.receive(
|
||||
SurfaceEvent::Frame { callback },
|
||||
(surface, CompositorToken::make()),
|
||||
);
|
||||
}
|
||||
wl_surface::Request::SetOpaqueRegion { region } => unsafe {
|
||||
let attributes = region.map(|r| RegionData::get_attributes(&r));
|
||||
SurfaceData::<U, R>::with_data(&surface, |d| d.opaque_region = attributes);
|
||||
},
|
||||
wl_surface::Request::SetInputRegion { region } => unsafe {
|
||||
let attributes = region.map(|r| RegionData::get_attributes(&r));
|
||||
SurfaceData::<U, R>::with_data(&surface, |d| d.input_region = attributes);
|
||||
},
|
||||
wl_surface::Request::Commit => {
|
||||
let mut user_impl = self.implem.borrow_mut();
|
||||
trace!(
|
||||
self.log,
|
||||
"Calling user implementation for wl_surface.commit"
|
||||
);
|
||||
user_impl.receive(SurfaceEvent::Commit, (surface, CompositorToken::make()));
|
||||
}
|
||||
wl_surface::Request::SetBufferTransform { transform } => unsafe {
|
||||
SurfaceData::<U, R>::with_data(&surface, |d| d.buffer_transform = transform);
|
||||
},
|
||||
wl_surface::Request::SetBufferScale { scale } => unsafe {
|
||||
SurfaceData::<U, R>::with_data(&surface, |d| d.buffer_scale = scale);
|
||||
},
|
||||
wl_surface::Request::DamageBuffer {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
} => unsafe {
|
||||
SurfaceData::<U, R>::with_data(&surface, |d| {
|
||||
d.damage = Damage::Buffer(Rectangle {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
});
|
||||
},
|
||||
wl_surface::Request::Destroy => {
|
||||
// All is already handled by our destructor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
SurfaceData::<U, R>::with_data(surface, |d| {
|
||||
d.buffer = Some(buffer.map(|b| (b.clone_unchecked(), (x, y))))
|
||||
});
|
||||
},
|
||||
damage: |_, _, _, surface, x, y, width, height| unsafe {
|
||||
SurfaceData::<U, R>::with_data(surface, |d| {
|
||||
d.damage = Damage::Surface(Rectangle {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
});
|
||||
},
|
||||
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 {
|
||||
let attributes = region.map(|r| RegionData::get_attributes(r));
|
||||
SurfaceData::<U, R>::with_data(surface, |d| d.opaque_region = attributes);
|
||||
},
|
||||
set_input_region: |_, _, _, surface, region| unsafe {
|
||||
let attributes = region.map(|r| RegionData::get_attributes(r));
|
||||
SurfaceData::<U, R>::with_data(surface, |d| d.input_region = attributes);
|
||||
},
|
||||
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 {
|
||||
SurfaceData::<U, R>::with_data(surface, |d| d.buffer_transform = transform);
|
||||
},
|
||||
set_buffer_scale: |_, _, _, surface, scale| unsafe {
|
||||
SurfaceData::<U, R>::with_data(surface, |d| d.buffer_scale = scale);
|
||||
},
|
||||
damage_buffer: |_, _, _, surface, x, y, width, height| unsafe {
|
||||
SurfaceData::<U, R>::with_data(surface, |d| {
|
||||
d.damage = Damage::Buffer(Rectangle {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
})
|
||||
});
|
||||
},
|
||||
destroy: |_, _, _, _| {},
|
||||
fn implement_surface<U, R, Impl>(
|
||||
surface: NewResource<wl_surface::WlSurface>,
|
||||
token: &LoopToken,
|
||||
log: ::slog::Logger,
|
||||
implem: Rc<RefCell<Impl>>,
|
||||
) -> Resource<wl_surface::WlSurface>
|
||||
where
|
||||
U: Default + 'static,
|
||||
R: Default + 'static,
|
||||
Impl: Implementation<(Resource<wl_surface::WlSurface>, CompositorToken<U, R>), SurfaceEvent> + 'static,
|
||||
{
|
||||
let surface = surface.implement_nonsend(
|
||||
SurfaceImplem::make(log, implem),
|
||||
Some(|surface, _| unsafe {
|
||||
SurfaceData::<U, R>::cleanup(&surface);
|
||||
}),
|
||||
token,
|
||||
);
|
||||
unsafe {
|
||||
SurfaceData::<U, R>::init(&surface);
|
||||
}
|
||||
}
|
||||
|
||||
fn destroy_surface<U: 'static, R: 'static>(surface: &wl_surface::WlSurface) {
|
||||
unsafe { SurfaceData::<U, R>::cleanup(surface) }
|
||||
surface
|
||||
}
|
||||
|
||||
/*
|
||||
* wl_region
|
||||
*/
|
||||
|
||||
pub(crate) fn region_implementation() -> wl_region::Implementation<()> {
|
||||
wl_region::Implementation {
|
||||
add: |_, _, _, region, x, y, width, height| {
|
||||
unsafe {
|
||||
RegionData::add_rectangle(
|
||||
region,
|
||||
pub(crate) struct RegionImplem;
|
||||
|
||||
impl Implementation<Resource<wl_region::WlRegion>, wl_region::Request> for RegionImplem {
|
||||
fn receive(&mut self, request: wl_region::Request, region: Resource<wl_region::WlRegion>) {
|
||||
unsafe {
|
||||
match request {
|
||||
wl_region::Request::Add {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
} => RegionData::add_rectangle(
|
||||
®ion,
|
||||
RectangleKind::Add,
|
||||
Rectangle {
|
||||
x,
|
||||
|
@ -170,13 +190,14 @@ pub(crate) fn region_implementation() -> wl_region::Implementation<()> {
|
|||
width,
|
||||
height,
|
||||
},
|
||||
)
|
||||
};
|
||||
},
|
||||
subtract: |_, _, _, region, x, y, width, height| {
|
||||
unsafe {
|
||||
RegionData::add_rectangle(
|
||||
region,
|
||||
),
|
||||
wl_region::Request::Subtract {
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
} => RegionData::add_rectangle(
|
||||
®ion,
|
||||
RectangleKind::Subtract,
|
||||
Rectangle {
|
||||
x,
|
||||
|
@ -184,134 +205,148 @@ pub(crate) fn region_implementation() -> wl_region::Implementation<()> {
|
|||
width,
|
||||
height,
|
||||
},
|
||||
)
|
||||
};
|
||||
},
|
||||
destroy: |_, _, _, _| {},
|
||||
),
|
||||
wl_region::Request::Destroy => {
|
||||
// all is handled by our destructor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn destroy_region(region: &wl_region::WlRegion) {
|
||||
unsafe { RegionData::cleanup(region) };
|
||||
fn implement_region(
|
||||
region: NewResource<wl_region::WlRegion>,
|
||||
token: &LoopToken,
|
||||
) -> Resource<wl_region::WlRegion> {
|
||||
let region = region.implement_nonsend(
|
||||
RegionImplem,
|
||||
Some(|region, _| unsafe { RegionData::cleanup(®ion) }),
|
||||
token,
|
||||
);
|
||||
unsafe {
|
||||
RegionData::init(®ion);
|
||||
}
|
||||
region
|
||||
}
|
||||
|
||||
/*
|
||||
* wl_subcompositor
|
||||
*/
|
||||
|
||||
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<()>
|
||||
pub(crate) fn implement_subcompositor<U, R>(
|
||||
subcompositor: NewResource<wl_subcompositor::WlSubcompositor>,
|
||||
token: LoopToken,
|
||||
) -> Resource<wl_subcompositor::WlSubcompositor>
|
||||
where
|
||||
R: RoleType + Role<SubsurfaceRole> + 'static,
|
||||
U: 'static,
|
||||
{
|
||||
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;
|
||||
let my_token = token.clone();
|
||||
subcompositor.implement_nonsend(
|
||||
move |request, subcompositor: Resource<_>| match request {
|
||||
wl_subcompositor::Request::GetSubsurface {
|
||||
id,
|
||||
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;
|
||||
}
|
||||
let subsurface = implement_subsurface::<U, R>(id, &token);
|
||||
subsurface.set_user_data(Box::into_raw(Box::new(surface.clone())) as *mut ());
|
||||
}
|
||||
subsurface.set_user_data(Box::into_raw(Box::new(unsafe { surface.clone_unchecked() })) as *mut _);
|
||||
evlh.register(
|
||||
&subsurface,
|
||||
subsurface_implementation::<U, R>(),
|
||||
(),
|
||||
Some(destroy_subsurface::<U, R>),
|
||||
);
|
||||
wl_subcompositor::Request::Destroy => {}
|
||||
},
|
||||
destroy: |_, _, _, _| {},
|
||||
}
|
||||
None::<fn(_, _)>,
|
||||
&my_token,
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
* wl_subsurface
|
||||
*/
|
||||
|
||||
unsafe fn with_subsurface_attributes<U, R, F>(subsurface: &wl_subsurface::WlSubsurface, f: F)
|
||||
unsafe fn with_subsurface_attributes<U, R, F>(subsurface: &Resource<wl_subsurface::WlSubsurface>, f: F)
|
||||
where
|
||||
F: FnOnce(&mut SubsurfaceRole),
|
||||
U: 'static,
|
||||
R: RoleType + Role<SubsurfaceRole> + 'static,
|
||||
{
|
||||
let ptr = subsurface.get_user_data();
|
||||
let surface = &*(ptr as *mut wl_surface::WlSurface);
|
||||
let surface = &*(ptr as *mut Resource<wl_surface::WlSurface>);
|
||||
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?!");
|
||||
}
|
||||
|
||||
fn subsurface_implementation<U, R>() -> wl_subsurface::Implementation<()>
|
||||
fn implement_subsurface<U, R>(
|
||||
subsurface: NewResource<wl_subsurface::WlSubsurface>,
|
||||
token: &LoopToken,
|
||||
) -> Resource<wl_subsurface::WlSubsurface>
|
||||
where
|
||||
R: RoleType + Role<SubsurfaceRole> + 'static,
|
||||
U: 'static,
|
||||
R: RoleType + Role<SubsurfaceRole> + 'static,
|
||||
{
|
||||
wl_subsurface::Implementation {
|
||||
set_position: |_, _, _, subsurface, x, y| unsafe {
|
||||
with_subsurface_attributes::<U, R, _>(subsurface, |attrs| {
|
||||
attrs.x = x;
|
||||
attrs.y = y;
|
||||
});
|
||||
},
|
||||
place_above: |_, _, _, subsurface, sibling| unsafe {
|
||||
let ptr = subsurface.get_user_data();
|
||||
let surface = &*(ptr as *mut wl_surface::WlSurface);
|
||||
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(),
|
||||
);
|
||||
subsurface.implement_nonsend(
|
||||
|request, subsurface| unsafe {
|
||||
match request {
|
||||
wl_subsurface::Request::SetPosition { x, y } => {
|
||||
with_subsurface_attributes::<U, R, _>(&subsurface, |attrs| {
|
||||
attrs.location = (x, y);
|
||||
})
|
||||
}
|
||||
wl_subsurface::Request::PlaceAbove { sibling } => {
|
||||
let surface = &*(subsurface.get_user_data() as *mut Resource<wl_surface::WlSurface>);
|
||||
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 } => {
|
||||
let surface = &*(subsurface.get_user_data() as *mut Resource<wl_surface::WlSurface>);
|
||||
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
|
||||
}
|
||||
}
|
||||
},
|
||||
place_below: |_, _, _, subsurface, sibling| unsafe {
|
||||
let ptr = subsurface.get_user_data();
|
||||
let surface = &*(ptr as *mut wl_surface::WlSurface);
|
||||
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(),
|
||||
);
|
||||
}
|
||||
},
|
||||
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: |_, _, _, _| {},
|
||||
}
|
||||
Some(|subsurface, _| unsafe {
|
||||
destroy_subsurface::<U, R>(&subsurface);
|
||||
}),
|
||||
token,
|
||||
)
|
||||
}
|
||||
|
||||
fn destroy_subsurface<U, R>(subsurface: &wl_subsurface::WlSubsurface)
|
||||
unsafe fn destroy_subsurface<U, R>(subsurface: &Resource<wl_subsurface::WlSubsurface>)
|
||||
where
|
||||
U: 'static,
|
||||
R: RoleType + Role<SubsurfaceRole> + 'static,
|
||||
{
|
||||
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);
|
||||
}
|
||||
let surface = Box::from_raw(ptr as *mut Resource<wl_surface::WlSurface>);
|
||||
if surface.is_alive() {
|
||||
SurfaceData::<U, R>::unset_parent(&surface);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,9 +29,7 @@
|
|||
//! ```
|
||||
//! # extern crate wayland_server;
|
||||
//! # #[macro_use] extern crate smithay;
|
||||
//! use wayland_server::protocol::wl_compositor::WlCompositor;
|
||||
//! use wayland_server::protocol::wl_subcompositor::WlSubcompositor;
|
||||
//! use smithay::wayland::compositor::{compositor_init, SurfaceUserImplementation};
|
||||
//! use smithay::wayland::compositor::compositor_init;
|
||||
//!
|
||||
//! // Define some user data to be associated with the surfaces.
|
||||
//! // It must implement the Default trait, which will represent the state of a surface which
|
||||
|
@ -45,21 +43,18 @@
|
|||
//! define_roles!(MyRoles);
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! # let (_display, mut event_loop) = wayland_server::create_display();
|
||||
//! // define your implementation for surface
|
||||
//! let my_implementation = SurfaceUserImplementation {
|
||||
//! commit: |evlh, idata, surface, token| { /* ... */ },
|
||||
//! frame: |evlh, idata, surface, callback, token| { /* ... */ }
|
||||
//! };
|
||||
//! // define your implementation data
|
||||
//! let my_implementation_data = ();
|
||||
//!
|
||||
//! # let (mut display, event_loop) = wayland_server::Display::new();
|
||||
//! // Call the init function:
|
||||
//! let (token, _, _) = compositor_init::<MyData, MyRoles, _, _>(
|
||||
//! &mut event_loop,
|
||||
//! my_implementation, // instance of compositor::SurfaceUserImplementation
|
||||
//! my_implementation_data, // whatever implementation data you need
|
||||
//! None // put a logger here
|
||||
//! &mut display,
|
||||
//! event_loop.token(),
|
||||
//! |request, (surface, compositor_token)| {
|
||||
//! /*
|
||||
//! Your handling of the user requests. This closure can also
|
||||
//! be a struct implementing the appropriate Implementation trait.
|
||||
//! */
|
||||
//! },
|
||||
//! None // put a logger here
|
||||
//! );
|
||||
//!
|
||||
//! // this `token` is what you'll use to access the surface associated data
|
||||
|
@ -82,20 +77,23 @@
|
|||
//! This `CompositorToken` also provides access to the metadata associated with the role of the
|
||||
//! surfaces. See the documentation of the `roles` submodule for a detailed explanation.
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
mod handlers;
|
||||
mod tree;
|
||||
mod region;
|
||||
pub mod roles;
|
||||
|
||||
pub use self::handlers::SurfaceIData;
|
||||
use self::region::RegionData;
|
||||
use self::roles::{Role, RoleType, WrongRole};
|
||||
use self::tree::SurfaceData;
|
||||
pub use self::tree::TraversalAction;
|
||||
use utils::Rectangle;
|
||||
use wayland_server::{resource_is_registered, EventLoopHandle, Global};
|
||||
use wayland_server::protocol::{wl_buffer, wl_callback, wl_compositor, wl_output, wl_region,
|
||||
wl_subcompositor, wl_surface};
|
||||
use wayland_server::{Display, Global, LoopToken, NewResource, Resource};
|
||||
use wayland_server::commons::Implementation;
|
||||
use wayland_server::protocol::{wl_buffer, wl_callback, wl_compositor, wl_output, wl_region, wl_subcompositor};
|
||||
use wayland_server::protocol::wl_surface::{self, WlSurface};
|
||||
|
||||
/// Description of which part of a surface
|
||||
/// should be considered damaged and needs to be redrawn
|
||||
|
@ -135,7 +133,7 @@ pub struct SurfaceAttributes<U> {
|
|||
/// You are free to set this field to `None` to avoid processing it several
|
||||
/// times. It'll be set to `Some(...)` if the user attaches a buffer (or NULL) to
|
||||
/// the surface.
|
||||
pub buffer: Option<Option<(wl_buffer::WlBuffer, (i32, i32))>>,
|
||||
pub buffer: Option<Option<(Resource<wl_buffer::WlBuffer>, (i32, i32))>>,
|
||||
/// Scale of the contents of the buffer, for higher-resolution contents.
|
||||
///
|
||||
/// If it matches the one of the output displaying this surface, no change
|
||||
|
@ -182,12 +180,9 @@ impl<U: Default> Default for SurfaceAttributes<U> {
|
|||
/// Attributes defining the behaviour of a sub-surface relative to its parent
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct SubsurfaceRole {
|
||||
/// Horizontal location of the top-left corner of this sub-surface relative to
|
||||
/// Location of the top-left corner of this sub-surface relative to
|
||||
/// the top-left corner of its parent
|
||||
pub x: i32,
|
||||
/// Vertical location of the top-left corner of this sub-surface relative to
|
||||
/// the top-left corner of its parent
|
||||
pub y: i32,
|
||||
pub location: (i32, i32),
|
||||
/// Sync status of this sub-surface
|
||||
///
|
||||
/// If `true`, this surface should be repainted synchronously with its parent
|
||||
|
@ -199,8 +194,7 @@ pub struct SubsurfaceRole {
|
|||
impl Default for SubsurfaceRole {
|
||||
fn default() -> SubsurfaceRole {
|
||||
SubsurfaceRole {
|
||||
x: 0,
|
||||
y: 0,
|
||||
location: (0, 0),
|
||||
sync: true,
|
||||
}
|
||||
}
|
||||
|
@ -240,58 +234,52 @@ impl Default for RegionAttributes {
|
|||
/// This token can be cloned at will, and is the entry-point to
|
||||
/// access data associated with the `wl_surface` and `wl_region` managed
|
||||
/// by the `CompositorGlobal` that provided it.
|
||||
pub struct CompositorToken<U, R, ID> {
|
||||
pub struct CompositorToken<U, R> {
|
||||
_data: ::std::marker::PhantomData<*mut U>,
|
||||
_role: ::std::marker::PhantomData<*mut R>,
|
||||
_idata: ::std::marker::PhantomData<*mut ID>,
|
||||
}
|
||||
|
||||
// we implement them manually because #[derive(..)] would require
|
||||
// U: Clone and R: Clone
|
||||
impl<U, R, ID> Copy for CompositorToken<U, R, ID> {}
|
||||
impl<U, R, ID> Clone for CompositorToken<U, R, ID> {
|
||||
fn clone(&self) -> CompositorToken<U, R, ID> {
|
||||
impl<U, R> Copy for CompositorToken<U, R> {}
|
||||
impl<U, R> Clone for CompositorToken<U, R> {
|
||||
fn clone(&self) -> CompositorToken<U, R> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl<U, R, ID> CompositorToken<U, R, ID> {
|
||||
pub(crate) fn make() -> CompositorToken<U, R, ID> {
|
||||
impl<U, R> CompositorToken<U, R> {
|
||||
pub(crate) fn make() -> CompositorToken<U, R> {
|
||||
CompositorToken {
|
||||
_data: ::std::marker::PhantomData,
|
||||
_role: ::std::marker::PhantomData,
|
||||
_idata: ::std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: 'static, R: 'static, ID: 'static> CompositorToken<U, R, ID> {
|
||||
impl<U: 'static, R: 'static> CompositorToken<U, R> {
|
||||
/// Access the data of a surface
|
||||
///
|
||||
/// The closure will be called with the contents of the data associated with this surface.
|
||||
///
|
||||
/// If the surface is not managed by the CompositorGlobal that provided this token, this
|
||||
/// will panic (having more than one compositor is not supported).
|
||||
pub fn with_surface_data<F, T>(&self, surface: &wl_surface::WlSurface, f: F) -> T
|
||||
pub fn with_surface_data<F, T>(&self, surface: &Resource<WlSurface>, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&mut SurfaceAttributes<U>) -> T,
|
||||
{
|
||||
assert!(
|
||||
resource_is_registered(
|
||||
surface,
|
||||
&self::handlers::surface_implementation::<U, R, ID>()
|
||||
),
|
||||
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
|
||||
"Accessing the data of foreign surfaces is not supported."
|
||||
);
|
||||
unsafe { SurfaceData::<U, R>::with_data(surface, f) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<U, R, ID> CompositorToken<U, R, ID>
|
||||
impl<U, R> CompositorToken<U, R>
|
||||
where
|
||||
U: 'static,
|
||||
R: RoleType + Role<SubsurfaceRole> + 'static,
|
||||
ID: 'static,
|
||||
{
|
||||
/// Access the data of a surface tree from bottom to top
|
||||
///
|
||||
|
@ -304,22 +292,22 @@ where
|
|||
/// - The surface object itself
|
||||
/// - a mutable reference to its surface attribute data
|
||||
/// - a mutable reference to its role data,
|
||||
/// - a custom value that is passer in a fold-like maneer, but only from the output of a parent
|
||||
/// - a custom value that is passed in a fold-like maneer, but only from the output of a parent
|
||||
/// to its children. See `TraversalAction` for details.
|
||||
///
|
||||
/// If the surface not managed by the CompositorGlobal that provided this token, this
|
||||
/// will panic (having more than one compositor is not supported).
|
||||
pub fn with_surface_tree_upward<F, T>(
|
||||
&self, surface: &wl_surface::WlSurface, initial: T, f: F
|
||||
&self,
|
||||
surface: &Resource<WlSurface>,
|
||||
initial: T,
|
||||
f: F,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
|
||||
F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
|
||||
{
|
||||
assert!(
|
||||
resource_is_registered(
|
||||
surface,
|
||||
&self::handlers::surface_implementation::<U, R, ID>()
|
||||
),
|
||||
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
|
||||
"Accessing the data of foreign surfaces is not supported."
|
||||
);
|
||||
unsafe {
|
||||
|
@ -336,16 +324,16 @@ where
|
|||
///
|
||||
/// Behavior is the same as `with_surface_tree_upward`.
|
||||
pub fn with_surface_tree_downward<F, T>(
|
||||
&self, surface: &wl_surface::WlSurface, initial: T, f: F
|
||||
&self,
|
||||
surface: &Resource<WlSurface>,
|
||||
initial: T,
|
||||
f: F,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
|
||||
F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
|
||||
{
|
||||
assert!(
|
||||
resource_is_registered(
|
||||
surface,
|
||||
&self::handlers::surface_implementation::<U, R, ID>()
|
||||
),
|
||||
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
|
||||
"Accessing the data of foreign surfaces is not supported."
|
||||
);
|
||||
unsafe {
|
||||
|
@ -360,12 +348,9 @@ where
|
|||
///
|
||||
/// If the surface is not managed by the CompositorGlobal that provided this token, this
|
||||
/// will panic (having more than one compositor is not supported).
|
||||
pub fn get_parent(&self, surface: &wl_surface::WlSurface) -> Option<wl_surface::WlSurface> {
|
||||
pub fn get_parent(&self, surface: &Resource<WlSurface>) -> Option<Resource<WlSurface>> {
|
||||
assert!(
|
||||
resource_is_registered(
|
||||
surface,
|
||||
&self::handlers::surface_implementation::<U, R, ID>()
|
||||
),
|
||||
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
|
||||
"Accessing the data of foreign surfaces is not supported."
|
||||
);
|
||||
unsafe { SurfaceData::<U, R>::get_parent(surface) }
|
||||
|
@ -375,29 +360,23 @@ where
|
|||
///
|
||||
/// If the surface is not managed by the CompositorGlobal that provided this token, this
|
||||
/// will panic (having more than one compositor is not supported).
|
||||
pub fn get_children(&self, surface: &wl_surface::WlSurface) -> Vec<wl_surface::WlSurface> {
|
||||
pub fn get_children(&self, surface: &Resource<WlSurface>) -> Vec<Resource<WlSurface>> {
|
||||
assert!(
|
||||
resource_is_registered(
|
||||
surface,
|
||||
&self::handlers::surface_implementation::<U, R, ID>()
|
||||
),
|
||||
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
|
||||
"Accessing the data of foreign surfaces is not supported."
|
||||
);
|
||||
unsafe { SurfaceData::<U, R>::get_children(surface) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<U: 'static, R: RoleType + 'static, ID: 'static> CompositorToken<U, R, ID> {
|
||||
impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
|
||||
/// Check wether this surface as a role or not
|
||||
///
|
||||
/// If the surface is not managed by the CompositorGlobal that provided this token, this
|
||||
/// will panic (having more than one compositor is not supported).
|
||||
pub fn has_a_role(&self, surface: &wl_surface::WlSurface) -> bool {
|
||||
pub fn has_a_role(&self, surface: &Resource<WlSurface>) -> bool {
|
||||
assert!(
|
||||
resource_is_registered(
|
||||
surface,
|
||||
&self::handlers::surface_implementation::<U, R, ID>()
|
||||
),
|
||||
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
|
||||
"Accessing the data of foreign surfaces is not supported."
|
||||
);
|
||||
unsafe { SurfaceData::<U, R>::has_a_role(surface) }
|
||||
|
@ -407,15 +386,12 @@ impl<U: 'static, R: RoleType + 'static, ID: 'static> CompositorToken<U, R, ID> {
|
|||
///
|
||||
/// If the surface is not managed by the CompositorGlobal that provided this token, this
|
||||
/// will panic (having more than one compositor is not supported).
|
||||
pub fn has_role<RoleData>(&self, surface: &wl_surface::WlSurface) -> bool
|
||||
pub fn has_role<RoleData>(&self, surface: &Resource<WlSurface>) -> bool
|
||||
where
|
||||
R: Role<RoleData>,
|
||||
{
|
||||
assert!(
|
||||
resource_is_registered(
|
||||
surface,
|
||||
&self::handlers::surface_implementation::<U, R, ID>()
|
||||
),
|
||||
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
|
||||
"Accessing the data of foreign surfaces is not supported."
|
||||
);
|
||||
unsafe { SurfaceData::<U, R>::has_role::<RoleData>(surface) }
|
||||
|
@ -427,16 +403,13 @@ impl<U: 'static, R: RoleType + 'static, ID: 'static> CompositorToken<U, R, ID> {
|
|||
///
|
||||
/// If the surface is not managed by the CompositorGlobal that provided this token, this
|
||||
/// will panic (having more than one compositor is not supported).
|
||||
pub fn give_role<RoleData>(&self, surface: &wl_surface::WlSurface) -> Result<(), ()>
|
||||
pub fn give_role<RoleData>(&self, surface: &Resource<WlSurface>) -> Result<(), ()>
|
||||
where
|
||||
R: Role<RoleData>,
|
||||
RoleData: Default,
|
||||
{
|
||||
assert!(
|
||||
resource_is_registered(
|
||||
surface,
|
||||
&self::handlers::surface_implementation::<U, R, ID>()
|
||||
),
|
||||
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
|
||||
"Accessing the data of foreign surfaces is not supported."
|
||||
);
|
||||
unsafe { SurfaceData::<U, R>::give_role::<RoleData>(surface) }
|
||||
|
@ -449,16 +422,15 @@ impl<U: 'static, R: RoleType + 'static, ID: 'static> CompositorToken<U, R, ID> {
|
|||
/// If the surface is not managed by the CompositorGlobal that provided this token, this
|
||||
/// will panic (having more than one compositor is not supported).
|
||||
pub fn give_role_with<RoleData>(
|
||||
&self, surface: &wl_surface::WlSurface, data: RoleData
|
||||
&self,
|
||||
surface: &Resource<WlSurface>,
|
||||
data: RoleData,
|
||||
) -> Result<(), RoleData>
|
||||
where
|
||||
R: Role<RoleData>,
|
||||
{
|
||||
assert!(
|
||||
resource_is_registered(
|
||||
surface,
|
||||
&self::handlers::surface_implementation::<U, R, ID>()
|
||||
),
|
||||
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
|
||||
"Accessing the data of foreign surfaces is not supported."
|
||||
);
|
||||
unsafe { SurfaceData::<U, R>::give_role_with::<RoleData>(surface, data) }
|
||||
|
@ -470,18 +442,13 @@ impl<U: 'static, R: RoleType + 'static, ID: 'static> CompositorToken<U, R, ID> {
|
|||
///
|
||||
/// If the surface is not managed by the CompositorGlobal that provided this token, this
|
||||
/// will panic (having more than one compositor is not supported).
|
||||
pub fn with_role_data<RoleData, F, T>(
|
||||
&self, surface: &wl_surface::WlSurface, f: F
|
||||
) -> Result<T, WrongRole>
|
||||
pub fn with_role_data<RoleData, F, T>(&self, surface: &Resource<WlSurface>, f: F) -> Result<T, WrongRole>
|
||||
where
|
||||
R: Role<RoleData>,
|
||||
F: FnOnce(&mut RoleData) -> T,
|
||||
{
|
||||
assert!(
|
||||
resource_is_registered(
|
||||
surface,
|
||||
&self::handlers::surface_implementation::<U, R, ID>()
|
||||
),
|
||||
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
|
||||
"Accessing the data of foreign surfaces is not supported."
|
||||
);
|
||||
unsafe { SurfaceData::<U, R>::with_role_data::<RoleData, _, _>(surface, f) }
|
||||
|
@ -493,15 +460,12 @@ impl<U: 'static, R: RoleType + 'static, ID: 'static> CompositorToken<U, R, ID> {
|
|||
///
|
||||
/// If the surface is not managed by the CompositorGlobal that provided this token, this
|
||||
/// will panic (having more than one compositor is not supported).
|
||||
pub fn remove_role<RoleData>(&self, surface: &wl_surface::WlSurface) -> Result<RoleData, WrongRole>
|
||||
pub fn remove_role<RoleData>(&self, surface: &Resource<WlSurface>) -> Result<RoleData, WrongRole>
|
||||
where
|
||||
R: Role<RoleData>,
|
||||
{
|
||||
assert!(
|
||||
resource_is_registered(
|
||||
surface,
|
||||
&self::handlers::surface_implementation::<U, R, ID>()
|
||||
),
|
||||
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
|
||||
"Accessing the data of foreign surfaces is not supported."
|
||||
);
|
||||
unsafe { SurfaceData::<U, R>::remove_role::<RoleData>(surface) }
|
||||
|
@ -511,10 +475,10 @@ impl<U: 'static, R: RoleType + 'static, ID: 'static> CompositorToken<U, R, ID> {
|
|||
///
|
||||
/// If the region is not managed by the CompositorGlobal that provided this token, this
|
||||
/// will panic (having more than one compositor is not supported).
|
||||
pub fn get_region_attributes(&self, region: &wl_region::WlRegion) -> RegionAttributes {
|
||||
pub fn get_region_attributes(&self, region: &Resource<wl_region::WlRegion>) -> RegionAttributes {
|
||||
assert!(
|
||||
resource_is_registered(region, &self::handlers::region_implementation()),
|
||||
"Accessing the data of foreign surfaces is not supported."
|
||||
region.is_implemented_with::<self::handlers::RegionImplem>(),
|
||||
"Accessing the data of foreign regions is not supported."
|
||||
);
|
||||
unsafe { RegionData::get_attributes(region) }
|
||||
}
|
||||
|
@ -528,46 +492,50 @@ impl<U: 'static, R: RoleType + 'static, ID: 'static> CompositorToken<U, R, ID> {
|
|||
///
|
||||
/// It also returns the two global handles, in case you whish to remove these
|
||||
/// globals from the event loop in the future.
|
||||
pub fn compositor_init<U, R, ID, L>(
|
||||
evlh: &mut EventLoopHandle, implem: SurfaceUserImplementation<U, R, ID>, idata: ID, logger: L
|
||||
pub fn compositor_init<U, R, Impl, L>(
|
||||
display: &mut Display,
|
||||
token: LoopToken,
|
||||
implem: Impl,
|
||||
logger: L,
|
||||
) -> (
|
||||
CompositorToken<U, R, ID>,
|
||||
Global<wl_compositor::WlCompositor, self::handlers::SurfaceIData<U, R, ID>>,
|
||||
Global<wl_subcompositor::WlSubcompositor, ()>,
|
||||
CompositorToken<U, R>,
|
||||
Global<wl_compositor::WlCompositor>,
|
||||
Global<wl_subcompositor::WlSubcompositor>,
|
||||
)
|
||||
where
|
||||
L: Into<Option<::slog::Logger>>,
|
||||
U: Default + 'static,
|
||||
R: Default + RoleType + Role<SubsurfaceRole> + 'static,
|
||||
ID: 'static,
|
||||
Impl: Implementation<(Resource<WlSurface>, CompositorToken<U, R>), SurfaceEvent> + 'static,
|
||||
{
|
||||
let log = ::slog_or_stdlog(logger);
|
||||
let idata = self::handlers::SurfaceIData::make(
|
||||
log.new(o!("smithay_module" => "compositor_handler")),
|
||||
implem,
|
||||
idata,
|
||||
);
|
||||
let compositor_global_token =
|
||||
evlh.register_global::<wl_compositor::WlCompositor, _>(4, self::handlers::compositor_bind, idata);
|
||||
let subcompositor_global_token = evlh.register_global::<wl_subcompositor::WlSubcompositor, _>(
|
||||
1,
|
||||
self::handlers::subcompositor_bind::<U, R>,
|
||||
(),
|
||||
);
|
||||
let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "compositor_handler"));
|
||||
let implem = Rc::new(RefCell::new(implem));
|
||||
|
||||
(
|
||||
CompositorToken::make(),
|
||||
compositor_global_token,
|
||||
subcompositor_global_token,
|
||||
)
|
||||
let comp_token = token.clone();
|
||||
let sub_token = token.clone();
|
||||
|
||||
let compositor = display.create_global(&token, 4, move |_version, new_compositor| {
|
||||
self::handlers::implement_compositor::<U, R, Impl>(
|
||||
new_compositor,
|
||||
comp_token.clone(),
|
||||
log.clone(),
|
||||
implem.clone(),
|
||||
);
|
||||
});
|
||||
|
||||
let subcompositor = display.create_global(&token, 1, move |_version, new_subcompositor| {
|
||||
self::handlers::implement_subcompositor::<U, R>(new_subcompositor, sub_token.clone());
|
||||
});
|
||||
|
||||
(CompositorToken::make(), compositor, subcompositor)
|
||||
}
|
||||
|
||||
/// Sub-implementation for surface event handling
|
||||
/// User-handled events for surfaces
|
||||
///
|
||||
/// The global provided by Smithay cannot process these events for you, so they
|
||||
/// are forwarded directly to this implementation that you must provide
|
||||
/// at creation of the compositor global.
|
||||
pub struct SurfaceUserImplementation<U, R, ID> {
|
||||
/// 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 {
|
||||
/// The double-buffered state has been validated by the client
|
||||
///
|
||||
/// At this point, the pending state that has been accumulated in the `SurfaceAttributes` associated
|
||||
|
@ -575,12 +543,7 @@ pub struct SurfaceUserImplementation<U, R, ID> {
|
|||
///
|
||||
/// 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)
|
||||
/// for more details
|
||||
pub commit: fn(
|
||||
evlh: &mut EventLoopHandle,
|
||||
idata: &mut ID,
|
||||
surface: &wl_surface::WlSurface,
|
||||
token: CompositorToken<U, R, ID>,
|
||||
),
|
||||
Commit,
|
||||
/// The client asks to be notified when would be a good time to update the contents of this surface
|
||||
///
|
||||
/// You must keep the provided `WlCallback` and trigger it at the appropriate time by calling
|
||||
|
@ -588,18 +551,8 @@ pub struct SurfaceUserImplementation<U, R, ID> {
|
|||
///
|
||||
/// 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)
|
||||
/// for more details
|
||||
pub frame: fn(
|
||||
evlh: &mut EventLoopHandle,
|
||||
idata: &mut ID,
|
||||
surface: &wl_surface::WlSurface,
|
||||
callback: wl_callback::WlCallback,
|
||||
token: CompositorToken<U, R, ID>,
|
||||
),
|
||||
}
|
||||
|
||||
impl<U, R, ID> Copy for SurfaceUserImplementation<U, R, ID> {}
|
||||
impl<U, R, ID> Clone for SurfaceUserImplementation<U, R, ID> {
|
||||
fn clone(&self) -> SurfaceUserImplementation<U, R, ID> {
|
||||
*self
|
||||
}
|
||||
Frame {
|
||||
/// The created `WlCallback`
|
||||
callback: NewResource<wl_callback::WlCallback>,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -10,29 +10,33 @@ pub struct RegionData {
|
|||
|
||||
impl RegionData {
|
||||
/// Initialize the user_data of a region, must be called right when the surface is created
|
||||
pub unsafe fn init(region: &wl_region::WlRegion) {
|
||||
pub unsafe fn init(region: &Resource<wl_region::WlRegion>) {
|
||||
region.set_user_data(Box::into_raw(Box::new(Mutex::new(RegionData::default()))) as *mut _)
|
||||
}
|
||||
|
||||
/// Cleans the user_data of that surface, must be called when it is destroyed
|
||||
pub unsafe fn cleanup(region: &wl_region::WlRegion) {
|
||||
pub unsafe fn cleanup(region: &Resource<wl_region::WlRegion>) {
|
||||
let ptr = region.get_user_data();
|
||||
region.set_user_data(::std::ptr::null_mut());
|
||||
let _my_data_mutex: Box<Mutex<RegionData>> = Box::from_raw(ptr as *mut _);
|
||||
}
|
||||
|
||||
unsafe fn get_data(region: &wl_region::WlRegion) -> &Mutex<RegionData> {
|
||||
unsafe fn get_data(region: &Resource<wl_region::WlRegion>) -> &Mutex<RegionData> {
|
||||
let ptr = region.get_user_data();
|
||||
&*(ptr as *mut _)
|
||||
}
|
||||
|
||||
pub unsafe fn get_attributes(region: &wl_region::WlRegion) -> RegionAttributes {
|
||||
pub unsafe fn get_attributes(region: &Resource<wl_region::WlRegion>) -> RegionAttributes {
|
||||
let data_mutex = Self::get_data(region);
|
||||
let data_guard = data_mutex.lock().unwrap();
|
||||
data_guard.attributes.clone()
|
||||
}
|
||||
|
||||
pub unsafe fn add_rectangle(region: &wl_region::WlRegion, kind: RectangleKind, rect: Rectangle) {
|
||||
pub unsafe fn add_rectangle(
|
||||
region: &Resource<wl_region::WlRegion>,
|
||||
kind: RectangleKind,
|
||||
rect: Rectangle,
|
||||
) {
|
||||
let data_mutex = Self::get_data(region);
|
||||
let mut data_guard = data_mutex.lock().unwrap();
|
||||
data_guard.attributes.rects.push((kind, rect));
|
||||
|
|
|
@ -206,7 +206,11 @@ macro_rules! define_roles(
|
|||
}
|
||||
}
|
||||
|
||||
fn data(&self) -> ::std::result::Result<&$role_data, $crate::wayland::compositor::roles::WrongRole> {
|
||||
fn data(&self) -> ::std::result::Result<
|
||||
&$role_data,
|
||||
$crate::wayland::compositor::roles::WrongRole
|
||||
>
|
||||
{
|
||||
if let $enum_name::$role_name(ref data) = *self {
|
||||
Ok(data)
|
||||
} else {
|
||||
|
@ -214,7 +218,11 @@ macro_rules! define_roles(
|
|||
}
|
||||
}
|
||||
|
||||
fn data_mut(&mut self) -> ::std::result::Result<&mut $role_data, $crate::wayland::compositor::roles::WrongRole> {
|
||||
fn data_mut(&mut self) -> ::std::result::Result<
|
||||
&mut $role_data,
|
||||
$crate::wayland::compositor::roles::WrongRole
|
||||
>
|
||||
{
|
||||
if let $enum_name::$role_name(ref mut data) = *self {
|
||||
Ok(data)
|
||||
} else {
|
||||
|
@ -222,7 +230,11 @@ macro_rules! define_roles(
|
|||
}
|
||||
}
|
||||
|
||||
fn unset(&mut self) -> ::std::result::Result<$role_data, $crate::wayland::compositor::roles::WrongRole> {
|
||||
fn unset(&mut self) -> ::std::result::Result<
|
||||
$role_data,
|
||||
$crate::wayland::compositor::roles::WrongRole
|
||||
>
|
||||
{
|
||||
// remove self to make borrow checker happy
|
||||
let temp = ::std::mem::replace(self, $enum_name::NoRole);
|
||||
if let $enum_name::$role_name(data) = temp {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use super::{SubsurfaceRole, SurfaceAttributes};
|
||||
use super::roles::*;
|
||||
use std::sync::Mutex;
|
||||
use wayland_server::{Liveness, Resource};
|
||||
use wayland_server::protocol::wl_surface;
|
||||
use wayland_server::Resource;
|
||||
use wayland_server::protocol::wl_surface::{self, WlSurface};
|
||||
|
||||
/// Node of a subsurface tree, holding some user specified data type U
|
||||
/// at each node
|
||||
|
@ -24,8 +24,8 @@ use wayland_server::protocol::wl_surface;
|
|||
/// All the methods here are unsafe, because they assume the provided `wl_surface` object
|
||||
/// is correctly initialized regarding its `user_data`.
|
||||
pub struct SurfaceData<U, R> {
|
||||
parent: Option<wl_surface::WlSurface>,
|
||||
children: Vec<wl_surface::WlSurface>,
|
||||
parent: Option<Resource<WlSurface>>,
|
||||
children: Vec<Resource<WlSurface>>,
|
||||
role: R,
|
||||
attributes: SurfaceAttributes<U>,
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ impl<U: Default, R: Default> SurfaceData<U, R> {
|
|||
}
|
||||
|
||||
/// Initialize the user_data of a surface, must be called right when the surface is created
|
||||
pub unsafe fn init(surface: &wl_surface::WlSurface) {
|
||||
pub unsafe fn init(surface: &Resource<WlSurface>) {
|
||||
surface.set_user_data(Box::into_raw(Box::new(Mutex::new(SurfaceData::<U, R>::new()))) as *mut _)
|
||||
}
|
||||
}
|
||||
|
@ -66,13 +66,13 @@ where
|
|||
U: 'static,
|
||||
R: 'static,
|
||||
{
|
||||
unsafe fn get_data(surface: &wl_surface::WlSurface) -> &Mutex<SurfaceData<U, R>> {
|
||||
unsafe fn get_data(surface: &Resource<WlSurface>) -> &Mutex<SurfaceData<U, R>> {
|
||||
let ptr = surface.get_user_data();
|
||||
&*(ptr as *mut _)
|
||||
}
|
||||
|
||||
/// Cleans the user_data of that surface, must be called when it is destroyed
|
||||
pub unsafe fn cleanup(surface: &wl_surface::WlSurface) {
|
||||
pub unsafe fn cleanup(surface: &Resource<WlSurface>) {
|
||||
let ptr = surface.get_user_data();
|
||||
surface.set_user_data(::std::ptr::null_mut());
|
||||
let my_data_mutex: Box<Mutex<SurfaceData<U, R>>> = Box::from_raw(ptr as *mut _);
|
||||
|
@ -99,31 +99,31 @@ where
|
|||
}
|
||||
|
||||
impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
|
||||
pub unsafe fn has_a_role(surface: &wl_surface::WlSurface) -> bool {
|
||||
debug_assert!(surface.status() == Liveness::Alive);
|
||||
pub unsafe fn has_a_role(surface: &Resource<WlSurface>) -> bool {
|
||||
debug_assert!(surface.is_alive());
|
||||
let data_mutex = Self::get_data(surface);
|
||||
let data_guard = data_mutex.lock().unwrap();
|
||||
<R as RoleType>::has_role(&data_guard.role)
|
||||
}
|
||||
|
||||
/// Check wether a surface has a given role
|
||||
pub unsafe fn has_role<RoleData>(surface: &wl_surface::WlSurface) -> bool
|
||||
pub unsafe fn has_role<RoleData>(surface: &Resource<WlSurface>) -> bool
|
||||
where
|
||||
R: Role<RoleData>,
|
||||
{
|
||||
debug_assert!(surface.status() == Liveness::Alive);
|
||||
debug_assert!(surface.is_alive());
|
||||
let data_mutex = Self::get_data(surface);
|
||||
let data_guard = data_mutex.lock().unwrap();
|
||||
<R as Role<RoleData>>::has(&data_guard.role)
|
||||
}
|
||||
|
||||
/// Register that this surface has a role, fails if it already has one
|
||||
pub unsafe fn give_role<RoleData>(surface: &wl_surface::WlSurface) -> Result<(), ()>
|
||||
pub unsafe fn give_role<RoleData>(surface: &Resource<WlSurface>) -> Result<(), ()>
|
||||
where
|
||||
R: Role<RoleData>,
|
||||
RoleData: Default,
|
||||
{
|
||||
debug_assert!(surface.status() == Liveness::Alive);
|
||||
debug_assert!(surface.is_alive());
|
||||
let data_mutex = Self::get_data(surface);
|
||||
let mut data_guard = data_mutex.lock().unwrap();
|
||||
<R as Role<RoleData>>::set(&mut data_guard.role)
|
||||
|
@ -133,12 +133,13 @@ impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
|
|||
///
|
||||
/// Fails if it already has one and returns the data
|
||||
pub unsafe fn give_role_with<RoleData>(
|
||||
surface: &wl_surface::WlSurface, data: RoleData
|
||||
surface: &Resource<WlSurface>,
|
||||
data: RoleData,
|
||||
) -> Result<(), RoleData>
|
||||
where
|
||||
R: Role<RoleData>,
|
||||
{
|
||||
debug_assert!(surface.status() == Liveness::Alive);
|
||||
debug_assert!(surface.is_alive());
|
||||
let data_mutex = Self::get_data(surface);
|
||||
let mut data_guard = data_mutex.lock().unwrap();
|
||||
<R as Role<RoleData>>::set_with(&mut data_guard.role, data)
|
||||
|
@ -148,25 +149,23 @@ impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
|
|||
///
|
||||
/// It is a noop if this surface already didn't have one, but fails if
|
||||
/// the role was "subsurface", it must be removed by the `unset_parent` method.
|
||||
pub unsafe fn remove_role<RoleData>(surface: &wl_surface::WlSurface) -> Result<RoleData, WrongRole>
|
||||
pub unsafe fn remove_role<RoleData>(surface: &Resource<WlSurface>) -> Result<RoleData, WrongRole>
|
||||
where
|
||||
R: Role<RoleData>,
|
||||
{
|
||||
debug_assert!(surface.status() == Liveness::Alive);
|
||||
debug_assert!(surface.is_alive());
|
||||
let data_mutex = Self::get_data(surface);
|
||||
let mut data_guard = data_mutex.lock().unwrap();
|
||||
<R as Role<RoleData>>::unset(&mut data_guard.role)
|
||||
}
|
||||
|
||||
/// Access to the role data
|
||||
pub unsafe fn with_role_data<RoleData, F, T>(
|
||||
surface: &wl_surface::WlSurface, f: F
|
||||
) -> Result<T, WrongRole>
|
||||
pub unsafe fn with_role_data<RoleData, F, T>(surface: &Resource<WlSurface>, f: F) -> Result<T, WrongRole>
|
||||
where
|
||||
R: Role<RoleData>,
|
||||
F: FnOnce(&mut RoleData) -> T,
|
||||
{
|
||||
debug_assert!(surface.status() == Liveness::Alive);
|
||||
debug_assert!(surface.is_alive());
|
||||
let data_mutex = Self::get_data(surface);
|
||||
let mut data_guard = data_mutex.lock().unwrap();
|
||||
let data = <R as Role<RoleData>>::data_mut(&mut data_guard.role)?;
|
||||
|
@ -179,11 +178,9 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
|
|||
///
|
||||
/// if this surface already has a role, does nothing and fails, otherwise
|
||||
/// its role is now to be a subsurface
|
||||
pub unsafe fn set_parent(
|
||||
child: &wl_surface::WlSurface, parent: &wl_surface::WlSurface
|
||||
) -> Result<(), ()> {
|
||||
debug_assert!(child.status() == Liveness::Alive);
|
||||
debug_assert!(parent.status() == Liveness::Alive);
|
||||
pub unsafe fn set_parent(child: &Resource<WlSurface>, parent: &Resource<WlSurface>) -> Result<(), ()> {
|
||||
debug_assert!(child.is_alive());
|
||||
debug_assert!(parent.is_alive());
|
||||
|
||||
// change child's parent
|
||||
{
|
||||
|
@ -192,14 +189,14 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
|
|||
// if surface already has a role, it cannot become a subsurface
|
||||
<R as Role<SubsurfaceRole>>::set(&mut child_guard.role)?;
|
||||
debug_assert!(child_guard.parent.is_none());
|
||||
child_guard.parent = Some(parent.clone_unchecked());
|
||||
child_guard.parent = Some(parent.clone());
|
||||
}
|
||||
// register child to new parent
|
||||
// double scoping is to be robust to have a child be its own parent
|
||||
{
|
||||
let parent_mutex = Self::get_data(parent);
|
||||
let mut parent_guard = parent_mutex.lock().unwrap();
|
||||
parent_guard.children.push(child.clone_unchecked())
|
||||
parent_guard.children.push(child.clone())
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -207,8 +204,8 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
|
|||
/// Remove a pre-existing parent of this child
|
||||
///
|
||||
/// Does nothing if it has no parent
|
||||
pub unsafe fn unset_parent(child: &wl_surface::WlSurface) {
|
||||
debug_assert!(child.status() == Liveness::Alive);
|
||||
pub unsafe fn unset_parent(child: &Resource<WlSurface>) {
|
||||
debug_assert!(child.is_alive());
|
||||
let old_parent = {
|
||||
let child_mutex = Self::get_data(child);
|
||||
let mut child_guard = child_mutex.lock().unwrap();
|
||||
|
@ -229,44 +226,38 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
|
|||
}
|
||||
|
||||
/// Retrieve the parent surface (if any) of this surface
|
||||
pub unsafe fn get_parent(child: &wl_surface::WlSurface) -> Option<wl_surface::WlSurface> {
|
||||
pub unsafe fn get_parent(child: &Resource<WlSurface>) -> Option<Resource<WlSurface>> {
|
||||
let child_mutex = Self::get_data(child);
|
||||
let child_guard = child_mutex.lock().unwrap();
|
||||
child_guard.parent.as_ref().map(|p| p.clone_unchecked())
|
||||
child_guard.parent.as_ref().map(|p| p.clone())
|
||||
}
|
||||
|
||||
/// Retrieve the parent surface (if any) of this surface
|
||||
pub unsafe fn get_children(child: &wl_surface::WlSurface) -> Vec<wl_surface::WlSurface> {
|
||||
pub unsafe fn get_children(child: &Resource<WlSurface>) -> Vec<Resource<WlSurface>> {
|
||||
let child_mutex = Self::get_data(child);
|
||||
let child_guard = child_mutex.lock().unwrap();
|
||||
child_guard
|
||||
.children
|
||||
.iter()
|
||||
.map(|p| p.clone_unchecked())
|
||||
.collect()
|
||||
child_guard.children.iter().map(|p| p.clone()).collect()
|
||||
}
|
||||
|
||||
/// Reorders a surface relative to one of its sibling
|
||||
///
|
||||
/// Fails if `relative_to` is not a sibling or parent of `surface`.
|
||||
pub unsafe fn reorder(
|
||||
surface: &wl_surface::WlSurface, to: Location, relative_to: &wl_surface::WlSurface
|
||||
surface: &Resource<WlSurface>,
|
||||
to: Location,
|
||||
relative_to: &Resource<WlSurface>,
|
||||
) -> Result<(), ()> {
|
||||
let parent = {
|
||||
let data_mutex = Self::get_data(surface);
|
||||
let data_guard = data_mutex.lock().unwrap();
|
||||
data_guard
|
||||
.parent
|
||||
.as_ref()
|
||||
.map(|p| p.clone_unchecked())
|
||||
.unwrap()
|
||||
data_guard.parent.as_ref().map(|p| p.clone()).unwrap()
|
||||
};
|
||||
if parent.equals(relative_to) {
|
||||
// TODO: handle positioning relative to parent
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
fn index_of(surface: &wl_surface::WlSurface, slice: &[wl_surface::WlSurface]) -> Option<usize> {
|
||||
fn index_of(surface: &Resource<WlSurface>, slice: &[Resource<WlSurface>]) -> Option<usize> {
|
||||
for (i, s) in slice.iter().enumerate() {
|
||||
if s.equals(surface) {
|
||||
return Some(i);
|
||||
|
@ -300,7 +291,7 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
|
|||
///
|
||||
/// Note that an internal lock is taken during access of this data,
|
||||
/// so the tree cannot be manipulated at the same time
|
||||
pub unsafe fn with_data<T, F>(surface: &wl_surface::WlSurface, f: F) -> T
|
||||
pub unsafe fn with_data<T, F>(surface: &Resource<WlSurface>, f: F) -> T
|
||||
where
|
||||
F: FnOnce(&mut SurfaceAttributes<U>) -> T,
|
||||
{
|
||||
|
@ -317,17 +308,20 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
|
|||
///
|
||||
/// The callback returns wether the traversal should continue or not. Returning
|
||||
/// false will cause an early-stopping.
|
||||
pub unsafe fn map_tree<F, T>(root: &wl_surface::WlSurface, initial: T, mut f: F, reverse: bool)
|
||||
pub unsafe fn map_tree<F, T>(root: &Resource<WlSurface>, initial: T, mut f: F, reverse: bool)
|
||||
where
|
||||
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
|
||||
F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
|
||||
{
|
||||
// helper function for recursion
|
||||
unsafe fn map<U: 'static, R: 'static, F, T>(
|
||||
surface: &wl_surface::WlSurface, root: &wl_surface::WlSurface, initial: &T, f: &mut F,
|
||||
surface: &Resource<WlSurface>,
|
||||
root: &Resource<WlSurface>,
|
||||
initial: &T,
|
||||
f: &mut F,
|
||||
reverse: bool,
|
||||
) -> bool
|
||||
where
|
||||
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
|
||||
F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
|
||||
{
|
||||
// stop if we met the root, so to not deadlock/inifinte loop
|
||||
if surface.equals(root) {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
//! not previously destroyed all the globals using it, otherwise you'll
|
||||
//! quickly encounter a panic.
|
||||
|
||||
//pub mod compositor;
|
||||
pub mod compositor;
|
||||
pub mod output;
|
||||
pub mod seat;
|
||||
pub mod shm;
|
||||
|
|
Loading…
Reference in New Issue