Implement wl_subsurface.place_{above,below}.

This commit is contained in:
Victor Berger 2017-06-04 22:41:42 +02:00
parent 1e960af5f2
commit a5ae27be84
3 changed files with 83 additions and 17 deletions

View File

@ -1,7 +1,7 @@
use super::{CompositorHandler, Damage, Handler as UserHandler, Rectangle, RectangleKind, use super::{CompositorHandler, Damage, Handler as UserHandler, Rectangle, RectangleKind,
SubsurfaceAttributes}; SubsurfaceAttributes};
use super::region::RegionData; use super::region::RegionData;
use super::tree::SurfaceData; use super::tree::{Location, SurfaceData};
use wayland_server::{Client, Destroy, EventLoopHandle, Resource}; use wayland_server::{Client, Destroy, EventLoopHandle, Resource};
use wayland_server::protocol::{wl_buffer, wl_callback, wl_compositor, wl_output, wl_region, use wayland_server::protocol::{wl_buffer, wl_callback, wl_compositor, wl_output, wl_region,
wl_subcompositor, wl_subsurface, wl_surface}; wl_subcompositor, wl_subsurface, wl_surface};
@ -227,31 +227,43 @@ unsafe fn with_subsurface_attributes<U, F>(subsurface: &wl_subsurface::WlSubsurf
} }
impl<U, H> wl_subsurface::Handler for CompositorHandler<U, H> { impl<U, H> wl_subsurface::Handler for CompositorHandler<U, H> {
fn set_position(&mut self, _: &mut EventLoopHandle, _: &Client, resource: &wl_subsurface::WlSubsurface, fn set_position(&mut self, _: &mut EventLoopHandle, _: &Client,
x: i32, y: i32) { subsurface: &wl_subsurface::WlSubsurface, x: i32, y: i32) {
unsafe { unsafe {
with_subsurface_attributes::<U, _>(resource, |attrs| { with_subsurface_attributes::<U, _>(subsurface, |attrs| {
attrs.x = x; attrs.x = x;
attrs.y = y; attrs.y = y;
}); });
} }
} }
fn place_above(&mut self, _: &mut EventLoopHandle, _: &Client, resource: &wl_subsurface::WlSubsurface, fn place_above(&mut self, _: &mut EventLoopHandle, _: &Client,
sibling: &wl_surface::WlSurface) { subsurface: &wl_subsurface::WlSubsurface, sibling: &wl_surface::WlSurface) {
unimplemented!()
}
fn place_below(&mut self, _: &mut EventLoopHandle, _: &Client, resource: &wl_subsurface::WlSubsurface,
sibling: &wl_surface::WlSurface) {
unimplemented!()
}
fn set_sync(&mut self, _: &mut EventLoopHandle, _: &Client, resource: &wl_subsurface::WlSubsurface) {
unsafe { unsafe {
with_subsurface_attributes::<U, _>(resource, |attrs| { attrs.sync = true; }); let ptr = subsurface.get_user_data();
let surface = &*(ptr as *mut wl_surface::WlSurface);
if let Err(()) = SurfaceData::<U>::reorder(surface, Location::After, sibling) {
subsurface.post_error(wl_subsurface::Error::BadSurface as u32, "Provided surface is not a sibling or parent.".into());
} }
} }
fn set_desync(&mut self, _: &mut EventLoopHandle, _: &Client, resource: &wl_subsurface::WlSubsurface) { }
fn place_below(&mut self, _: &mut EventLoopHandle, _: &Client,
subsurface: &wl_subsurface::WlSubsurface, sibling: &wl_surface::WlSurface) {
unsafe { unsafe {
with_subsurface_attributes::<U, _>(resource, |attrs| { attrs.sync = false; }); let ptr = subsurface.get_user_data();
let surface = &*(ptr as *mut wl_surface::WlSurface);
if let Err(()) = SurfaceData::<U>::reorder(surface, Location::Before, sibling) {
subsurface.post_error(wl_subsurface::Error::BadSurface as u32, "Provided surface is not a sibling or parent.".into());
}
}
}
fn set_sync(&mut self, _: &mut EventLoopHandle, _: &Client, subsurface: &wl_subsurface::WlSubsurface) {
unsafe {
with_subsurface_attributes::<U, _>(subsurface, |attrs| { attrs.sync = true; });
}
}
fn set_desync(&mut self, _: &mut EventLoopHandle, _: &Client, subsurface: &wl_subsurface::WlSubsurface) {
unsafe {
with_subsurface_attributes::<U, _>(subsurface, |attrs| { attrs.sync = false; });
} }
} }
} }

View File

@ -192,7 +192,8 @@ impl<U: Send + 'static, H: Handler + Send + 'static> CompositorToken<U, H> {
/// Access the data of a surface tree /// Access the data of a surface tree
/// ///
/// The provided closure is called successively on the surface and all its child subsurfaces, /// The provided closure is called successively on the surface and all its child subsurfaces,
/// in a depth-first order. /// in a depth-first order. This matches the order in which the surfaces are supposed to be
/// drawn: top-most last.
/// ///
/// If the surface is not managed by the CompositorGlobal that provided this token, this /// If the surface is not managed by the CompositorGlobal that provided this token, this
/// will panic (having more than one compositor is not supported). /// will panic (having more than one compositor is not supported).

View File

@ -43,6 +43,11 @@ pub enum RoleStatus {
HasRole, HasRole,
} }
pub enum Location {
Before,
After,
}
impl<U: Default> SurfaceData<U> { impl<U: Default> SurfaceData<U> {
fn new() -> SurfaceData<U> { fn new() -> SurfaceData<U> {
SurfaceData { SurfaceData {
@ -191,6 +196,54 @@ impl<U> SurfaceData<U> {
child_guard.parent.as_ref().map(|p| p.clone_unchecked()) child_guard.parent.as_ref().map(|p| p.clone_unchecked())
} }
/// 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)
-> 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()
};
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> {
for (i, s) in slice.iter().enumerate() {
if s.equals(surface) {
return Some(i);
}
}
None
}
let parent_mutex = Self::get_data(&parent);
let mut parent_guard = parent_mutex.lock().unwrap();
let my_index = index_of(surface, &parent_guard.children).unwrap();
let mut other_index = match index_of(surface, &parent_guard.children) {
Some(idx) => idx,
None => return Err(()),
};
let me = parent_guard.children.remove(my_index);
if my_index < other_index {
other_index -= 1;
}
let new_index = match to {
Location::Before => other_index,
Location::After => other_index + 1,
};
parent_guard.children.insert(new_index, me);
Ok(())
}
/// Access the attributes associated with a surface /// Access the attributes associated with a surface
/// ///
/// Note that an internal lock is taken during access of this data, /// Note that an internal lock is taken during access of this data,