Update smithay to wayland-server 0.23

This commit is contained in:
Victor Berger 2019-02-22 17:55:00 +01:00 committed by Victor Berger
parent d6625b4b49
commit 3f2857fbf3
20 changed files with 726 additions and 799 deletions

View File

@ -11,9 +11,9 @@ edition = "2018"
members = [ "anvil" ] members = [ "anvil" ]
[dependencies] [dependencies]
wayland-server = { version = "0.21.6", optional = true } wayland-server = { version = "0.23", optional = true }
wayland-commons = { version = "0.21.1", optional = true } wayland-commons = { version = "0.23", optional = true }
wayland-sys = { version = "0.21.6", optional = true } wayland-sys = { version = "0.23", optional = true }
calloop = "0.4.2" calloop = "0.4.2"
nix = "0.11" nix = "0.11"
xkbcommon = "0.2.1" xkbcommon = "0.2.1"
@ -21,7 +21,7 @@ tempfile = "2.1.5"
slog = "2.1.1" slog = "2.1.1"
slog-stdlog = "3.0.2" slog-stdlog = "3.0.2"
libloading = "0.4.0" libloading = "0.4.0"
wayland-client = { version = "0.21.1", features = ["egl"], optional = true } wayland-client = { version = "0.23", features = ["egl"], optional = true }
winit = { version = "0.18.0", optional = true } winit = { version = "0.18.0", optional = true }
drm = { version = "^0.3.4", optional = true } drm = { version = "^0.3.4", optional = true }
gbm = { version = "^0.5.0", optional = true, default-features = false, features = ["drm-support"] } gbm = { version = "^0.5.0", optional = true, default-features = false, features = ["drm-support"] }
@ -30,7 +30,7 @@ input = { version = "0.4.1", optional = true }
udev = { version = "0.2.0", optional = true } udev = { version = "0.2.0", optional = true }
dbus = { version = "0.6.1", optional = true } dbus = { version = "0.6.1", optional = true }
systemd = { version = "^0.2.0", optional = true } systemd = { version = "^0.2.0", optional = true }
wayland-protocols = { version = "0.21.3", features = ["unstable_protocols", "server"], optional = true } wayland-protocols = { version = "0.23", features = ["unstable_protocols", "server"], optional = true }
image = { version = "0.17.0", optional = true } image = { version = "0.17.0", optional = true }
error-chain = "0.11.0" error-chain = "0.11.0"
lazy_static = "1.0.0" lazy_static = "1.0.0"
@ -55,7 +55,7 @@ backend_udev = ["udev"]
backend_session_logind = ["dbus", "systemd", "backend_session"] backend_session_logind = ["dbus", "systemd", "backend_session"]
renderer_gl = ["gl_generator"] renderer_gl = ["gl_generator"]
renderer_glium = ["renderer_gl", "glium"] renderer_glium = ["renderer_gl", "glium"]
native_lib = ["wayland_frontend", "wayland-sys", "wayland-server/native_lib", "wayland-protocols/native_server"] native_lib = ["wayland_frontend", "wayland-sys", "wayland-server/native_lib"]
wayland_frontend = ["wayland-server", "wayland-commons", "wayland-protocols"] wayland_frontend = ["wayland-server", "wayland-commons", "wayland-protocols"]
xwayland = ["wayland_frontend"] xwayland = ["wayland_frontend"]

View File

@ -12,7 +12,7 @@ slog-term = "2.3"
slog-async = "2.2" slog-async = "2.2"
rand = "0.3" rand = "0.3"
glium = { version = "0.19.0", default-features = false } glium = { version = "0.19.0", default-features = false }
wayland-server = "0.21" wayland-server = "0.23"
xkbcommon = "0.2.1" xkbcommon = "0.2.1"
[dependencies.smithay] [dependencies.smithay]

View File

@ -45,14 +45,14 @@
//! for notifications are the [`Libinput`](input::Libinput) context or the [`Device`](::backend::drm::Device). //! for notifications are the [`Libinput`](input::Libinput) context or the [`Device`](::backend::drm::Device).
use super::{AsErrno, Session, SessionNotifier, SessionObserver}; use super::{AsErrno, Session, SessionNotifier, SessionObserver};
use calloop::{signals::Signals, LoopHandle, Source}; use calloop::{
signals::{Signal, Signals},
LoopHandle, Source,
};
use nix::{ use nix::{
fcntl::{self, open, OFlag}, fcntl::{self, open, OFlag},
libc::c_int, libc::c_int,
sys::{ sys::stat::{dev_t, fstat, major, minor, Mode},
signal::{self, Signal},
stat::{dev_t, fstat, major, minor, Mode},
},
unistd::{close, dup}, unistd::{close, dup},
Error as NixError, Result as NixResult, Error as NixError, Result as NixResult,
}; };
@ -257,7 +257,7 @@ impl DirectSession {
} else { } else {
tty::__libc_current_sigrtmin() tty::__libc_current_sigrtmin()
};*/ };*/
let signal = signal::SIGUSR2; let signal = ::nix::sys::signal::SIGUSR2;
let mode = tty::VtMode { let mode = tty::VtMode {
mode: tty::VT_PROCESS, mode: tty::VT_PROCESS,
@ -270,7 +270,7 @@ impl DirectSession {
tty::vt_set_mode(tty, &mode).chain_err(|| ErrorKind::FailedToTakeControlOfTTY(vt_num))?; tty::vt_set_mode(tty, &mode).chain_err(|| ErrorKind::FailedToTakeControlOfTTY(vt_num))?;
} }
Ok((vt_num, old_keyboard_mode, signal)) Ok((vt_num, old_keyboard_mode, Signal::SIGUSR2))
} }
/// Get the number of the virtual terminal used by this session /// Get the number of the virtual terminal used by this session

View File

@ -2,7 +2,7 @@ use std::{cell::RefCell, rc::Rc, sync::Mutex};
use wayland_server::{ use wayland_server::{
protocol::{wl_compositor, wl_region, wl_subcompositor, wl_subsurface, wl_surface}, protocol::{wl_compositor, wl_region, wl_subcompositor, wl_subsurface, wl_surface},
DisplayToken, NewResource, Resource, NewResource, Resource,
}; };
use super::{ use super::{
@ -17,30 +17,28 @@ use super::{
pub(crate) fn implement_compositor<U, R, Impl>( pub(crate) fn implement_compositor<U, R, Impl>(
compositor: NewResource<wl_compositor::WlCompositor>, compositor: NewResource<wl_compositor::WlCompositor>,
token: DisplayToken,
log: ::slog::Logger, log: ::slog::Logger,
implem: Rc<RefCell<Impl>>, implem: Rc<RefCell<Impl>>,
) -> Resource<wl_compositor::WlCompositor> ) -> wl_compositor::WlCompositor
where where
U: Default + 'static, U: Default + 'static,
R: Default + 'static, R: Default + 'static,
Impl: FnMut(SurfaceEvent, Resource<wl_surface::WlSurface>, CompositorToken<U, R>) + 'static, Impl: FnMut(SurfaceEvent, wl_surface::WlSurface, CompositorToken<U, R>) + 'static,
{ {
let my_token = token.clone(); compositor.implement_closure(
compositor.implement_nonsend(
move |request, _compositor| match request { move |request, _compositor| match request {
wl_compositor::Request::CreateSurface { id } => { wl_compositor::Request::CreateSurface { id } => {
trace!(log, "Creating a new wl_surface."); trace!(log, "Creating a new wl_surface.");
implement_surface(id, &token, log.clone(), implem.clone()); implement_surface(id, log.clone(), implem.clone());
} }
wl_compositor::Request::CreateRegion { id } => { wl_compositor::Request::CreateRegion { id } => {
trace!(log, "Creating a new wl_region."); trace!(log, "Creating a new wl_region.");
implement_region(id, &token); implement_region(id);
} }
_ => unreachable!(),
}, },
None::<fn(_)>, None::<fn(_)>,
(), (),
&my_token,
) )
} }
@ -51,13 +49,13 @@ where
// Internal implementation data of surfaces // Internal implementation data of surfaces
pub(crate) struct SurfaceImplem<U, R> { pub(crate) struct SurfaceImplem<U, R> {
log: ::slog::Logger, log: ::slog::Logger,
implem: Rc<RefCell<dyn FnMut(SurfaceEvent, Resource<wl_surface::WlSurface>, CompositorToken<U, R>)>>, implem: Rc<RefCell<dyn FnMut(SurfaceEvent, wl_surface::WlSurface, CompositorToken<U, R>)>>,
} }
impl<U, R> SurfaceImplem<U, R> { impl<U, R> SurfaceImplem<U, R> {
fn make<Impl>(log: ::slog::Logger, implem: Rc<RefCell<Impl>>) -> SurfaceImplem<U, R> fn make<Impl>(log: ::slog::Logger, implem: Rc<RefCell<Impl>>) -> SurfaceImplem<U, R>
where where
Impl: FnMut(SurfaceEvent, Resource<wl_surface::WlSurface>, CompositorToken<U, R>) + 'static, Impl: FnMut(SurfaceEvent, wl_surface::WlSurface, CompositorToken<U, R>) + 'static,
{ {
SurfaceImplem { log, implem } SurfaceImplem { log, implem }
} }
@ -68,11 +66,7 @@ where
U: 'static, U: 'static,
R: 'static, R: 'static,
{ {
fn receive_surface_request( fn receive_surface_request(&mut self, req: wl_surface::Request, surface: wl_surface::WlSurface) {
&mut self,
req: wl_surface::Request,
surface: Resource<wl_surface::WlSurface>,
) {
match req { match req {
wl_surface::Request::Attach { buffer, x, y } => { wl_surface::Request::Attach { buffer, x, y } => {
SurfaceData::<U, R>::with_data(&surface, |d| { SurfaceData::<U, R>::with_data(&surface, |d| {
@ -91,14 +85,14 @@ where
} }
wl_surface::Request::SetOpaqueRegion { region } => { wl_surface::Request::SetOpaqueRegion { region } => {
let attributes = region.map(|r| { let attributes = region.map(|r| {
let attributes_mutex = r.user_data::<Mutex<RegionAttributes>>().unwrap(); let attributes_mutex = r.as_ref().user_data::<Mutex<RegionAttributes>>().unwrap();
attributes_mutex.lock().unwrap().clone() attributes_mutex.lock().unwrap().clone()
}); });
SurfaceData::<U, R>::with_data(&surface, |d| d.opaque_region = attributes); SurfaceData::<U, R>::with_data(&surface, |d| d.opaque_region = attributes);
} }
wl_surface::Request::SetInputRegion { region } => { wl_surface::Request::SetInputRegion { region } => {
let attributes = region.map(|r| { let attributes = region.map(|r| {
let attributes_mutex = r.user_data::<Mutex<RegionAttributes>>().unwrap(); let attributes_mutex = r.as_ref().user_data::<Mutex<RegionAttributes>>().unwrap();
attributes_mutex.lock().unwrap().clone() attributes_mutex.lock().unwrap().clone()
}); });
SurfaceData::<U, R>::with_data(&surface, |d| d.input_region = attributes); SurfaceData::<U, R>::with_data(&surface, |d| d.input_region = attributes);
@ -122,29 +116,28 @@ where
wl_surface::Request::Destroy => { wl_surface::Request::Destroy => {
// All is already handled by our destructor // All is already handled by our destructor
} }
_ => unreachable!(),
} }
} }
} }
fn implement_surface<U, R, Impl>( fn implement_surface<U, R, Impl>(
surface: NewResource<wl_surface::WlSurface>, surface: NewResource<wl_surface::WlSurface>,
token: &DisplayToken,
log: ::slog::Logger, log: ::slog::Logger,
implem: Rc<RefCell<Impl>>, implem: Rc<RefCell<Impl>>,
) -> Resource<wl_surface::WlSurface> ) -> wl_surface::WlSurface
where where
U: Default + 'static, U: Default + 'static,
R: Default + 'static, R: Default + 'static,
Impl: FnMut(SurfaceEvent, Resource<wl_surface::WlSurface>, CompositorToken<U, R>) + 'static, Impl: FnMut(SurfaceEvent, wl_surface::WlSurface, CompositorToken<U, R>) + 'static,
{ {
let surface = surface.implement_nonsend( let surface = surface.implement_closure(
{ {
let mut implem = SurfaceImplem::make(log, implem); let mut implem = SurfaceImplem::make(log, implem);
move |req, surface| implem.receive_surface_request(req, surface) move |req, surface| implem.receive_surface_request(req, surface)
}, },
Some(|surface| SurfaceData::<U, R>::cleanup(&surface)), Some(|surface| SurfaceData::<U, R>::cleanup(&surface)),
SurfaceData::<U, R>::new(), SurfaceData::<U, R>::new(),
token,
); );
surface surface
} }
@ -153,8 +146,8 @@ where
* wl_region * wl_region
*/ */
fn region_implem(request: wl_region::Request, region: Resource<wl_region::WlRegion>) { fn region_implem(request: wl_region::Request, region: wl_region::WlRegion) {
let attributes_mutex = region.user_data::<Mutex<RegionAttributes>>().unwrap(); let attributes_mutex = region.as_ref().user_data::<Mutex<RegionAttributes>>().unwrap();
let mut guard = attributes_mutex.lock().unwrap(); let mut guard = attributes_mutex.lock().unwrap();
match request { match request {
wl_region::Request::Add { x, y, width, height } => guard wl_region::Request::Add { x, y, width, height } => guard
@ -166,18 +159,15 @@ fn region_implem(request: wl_region::Request, region: Resource<wl_region::WlRegi
wl_region::Request::Destroy => { wl_region::Request::Destroy => {
// all is handled by our destructor // all is handled by our destructor
} }
_ => unreachable!(),
} }
} }
fn implement_region( fn implement_region(region: NewResource<wl_region::WlRegion>) -> wl_region::WlRegion {
region: NewResource<wl_region::WlRegion>, region.implement_closure(
token: &DisplayToken,
) -> Resource<wl_region::WlRegion> {
region.implement_nonsend(
region_implem, region_implem,
None::<fn(_)>, None::<fn(_)>,
Mutex::new(RegionAttributes::default()), Mutex::new(RegionAttributes::default()),
token,
) )
} }
@ -187,30 +177,28 @@ fn implement_region(
pub(crate) fn implement_subcompositor<U, R>( pub(crate) fn implement_subcompositor<U, R>(
subcompositor: NewResource<wl_subcompositor::WlSubcompositor>, subcompositor: NewResource<wl_subcompositor::WlSubcompositor>,
token: DisplayToken, ) -> wl_subcompositor::WlSubcompositor
) -> Resource<wl_subcompositor::WlSubcompositor>
where where
R: RoleType + Role<SubsurfaceRole> + 'static, R: RoleType + Role<SubsurfaceRole> + 'static,
U: 'static, U: 'static,
{ {
let my_token = token.clone(); subcompositor.implement_closure(
subcompositor.implement_nonsend( move |request, subcompositor| match request {
move |request, subcompositor: Resource<_>| match request {
wl_subcompositor::Request::GetSubsurface { id, surface, parent } => { wl_subcompositor::Request::GetSubsurface { id, surface, parent } => {
if let Err(()) = SurfaceData::<U, R>::set_parent(&surface, &parent) { if let Err(()) = SurfaceData::<U, R>::set_parent(&surface, &parent) {
subcompositor.post_error( subcompositor.as_ref().post_error(
wl_subcompositor::Error::BadSurface as u32, wl_subcompositor::Error::BadSurface as u32,
"Surface already has a role.".into(), "Surface already has a role.".into(),
); );
return; return;
} }
implement_subsurface::<U, R>(id, surface.clone(), &token); implement_subsurface::<U, R>(id, surface.clone());
} }
wl_subcompositor::Request::Destroy => {} wl_subcompositor::Request::Destroy => {}
_ => unreachable!(),
}, },
None::<fn(_)>, None::<fn(_)>,
(), (),
&my_token,
) )
} }
@ -218,27 +206,26 @@ where
* wl_subsurface * wl_subsurface
*/ */
fn with_subsurface_attributes<U, R, F>(subsurface: &Resource<wl_subsurface::WlSubsurface>, f: F) fn with_subsurface_attributes<U, R, F>(subsurface: &wl_subsurface::WlSubsurface, f: F)
where where
F: FnOnce(&mut SubsurfaceRole), F: FnOnce(&mut SubsurfaceRole),
U: 'static, U: 'static,
R: RoleType + Role<SubsurfaceRole> + 'static, R: RoleType + Role<SubsurfaceRole> + 'static,
{ {
let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap(); let surface = subsurface.as_ref().user_data::<wl_surface::WlSurface>().unwrap();
SurfaceData::<U, R>::with_role_data::<SubsurfaceRole, _, _>(surface, |d| f(d)) 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?!"); .expect("The surface does not have a subsurface role while it has a wl_subsurface?!");
} }
fn implement_subsurface<U, R>( fn implement_subsurface<U, R>(
subsurface: NewResource<wl_subsurface::WlSubsurface>, subsurface: NewResource<wl_subsurface::WlSubsurface>,
surface: Resource<wl_surface::WlSurface>, surface: wl_surface::WlSurface,
token: &DisplayToken, ) -> wl_subsurface::WlSubsurface
) -> Resource<wl_subsurface::WlSubsurface>
where where
U: 'static, U: 'static,
R: RoleType + Role<SubsurfaceRole> + 'static, R: RoleType + Role<SubsurfaceRole> + 'static,
{ {
subsurface.implement_nonsend( subsurface.implement_closure(
|request, subsurface| { |request, subsurface| {
match request { match request {
wl_subsurface::Request::SetPosition { x, y } => { wl_subsurface::Request::SetPosition { x, y } => {
@ -247,18 +234,18 @@ where
}) })
} }
wl_subsurface::Request::PlaceAbove { sibling } => { wl_subsurface::Request::PlaceAbove { sibling } => {
let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap(); let surface = subsurface.as_ref().user_data::<wl_surface::WlSurface>().unwrap();
if let Err(()) = SurfaceData::<U, R>::reorder(surface, Location::After, &sibling) { if let Err(()) = SurfaceData::<U, R>::reorder(surface, Location::After, &sibling) {
subsurface.post_error( subsurface.as_ref().post_error(
wl_subsurface::Error::BadSurface as u32, wl_subsurface::Error::BadSurface as u32,
"Provided surface is not a sibling or parent.".into(), "Provided surface is not a sibling or parent.".into(),
) )
} }
} }
wl_subsurface::Request::PlaceBelow { sibling } => { wl_subsurface::Request::PlaceBelow { sibling } => {
let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap(); let surface = subsurface.as_ref().user_data::<wl_surface::WlSurface>().unwrap();
if let Err(()) = SurfaceData::<U, R>::reorder(surface, Location::Before, &sibling) { if let Err(()) = SurfaceData::<U, R>::reorder(surface, Location::Before, &sibling) {
subsurface.post_error( subsurface.as_ref().post_error(
wl_subsurface::Error::BadSurface as u32, wl_subsurface::Error::BadSurface as u32,
"Provided surface is not a sibling or parent.".into(), "Provided surface is not a sibling or parent.".into(),
) )
@ -277,21 +264,21 @@ where
wl_subsurface::Request::Destroy => { wl_subsurface::Request::Destroy => {
// Our destructor already handles it // Our destructor already handles it
} }
_ => unreachable!(),
} }
}, },
Some(|subsurface| destroy_subsurface::<U, R>(&subsurface)), Some(|subsurface| destroy_subsurface::<U, R>(&subsurface)),
surface, surface,
token,
) )
} }
fn destroy_subsurface<U, R>(subsurface: &Resource<wl_subsurface::WlSubsurface>) fn destroy_subsurface<U, R>(subsurface: &wl_subsurface::WlSubsurface)
where where
U: 'static, U: 'static,
R: RoleType + Role<SubsurfaceRole> + 'static, R: RoleType + Role<SubsurfaceRole> + 'static,
{ {
let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap(); let surface = subsurface.as_ref().user_data::<wl_surface::WlSurface>().unwrap();
if surface.is_alive() { if surface.as_ref().is_alive() {
SurfaceData::<U, R>::unset_parent(&surface); SurfaceData::<U, R>::unset_parent(&surface);
} }
} }

View File

@ -137,7 +137,7 @@ pub struct SurfaceAttributes<U> {
/// You are free to set this field to `None` to avoid processing it several /// 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 /// times. It'll be set to `Some(...)` if the user attaches a buffer (or `NULL`) to
/// the surface. /// the surface.
pub buffer: Option<Option<(Resource<wl_buffer::WlBuffer>, (i32, i32))>>, pub buffer: Option<Option<(wl_buffer::WlBuffer, (i32, i32))>>,
/// Scale of the contents of the buffer, for higher-resolution contents. /// Scale of the contents of the buffer, for higher-resolution contents.
/// ///
/// If it matches the one of the output displaying this surface, no change /// If it matches the one of the output displaying this surface, no change
@ -272,7 +272,7 @@ impl<U: 'static, R: 'static> CompositorToken<U, R> {
/// ///
/// 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).
pub fn with_surface_data<F, T>(&self, surface: &Resource<WlSurface>, f: F) -> T pub fn with_surface_data<F, T>(&self, surface: &WlSurface, f: F) -> T
where where
F: FnOnce(&mut SurfaceAttributes<U>) -> T, F: FnOnce(&mut SurfaceAttributes<U>) -> T,
{ {
@ -301,14 +301,9 @@ where
/// ///
/// If the surface not managed by the `CompositorGlobal` that provided this token, this /// If the surface 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).
pub fn with_surface_tree_upward<F, T>( pub fn with_surface_tree_upward<F, T>(&self, surface: &WlSurface, initial: T, f: F) -> Result<(), ()>
&self,
surface: &Resource<WlSurface>,
initial: T,
f: F,
) -> Result<(), ()>
where where
F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>, F: FnMut(&WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
{ {
SurfaceData::<U, R>::map_tree(surface, initial, f, false); SurfaceData::<U, R>::map_tree(surface, initial, f, false);
Ok(()) Ok(())
@ -321,14 +316,9 @@ where
/// supposed to be drawn: top-most first. /// supposed to be drawn: top-most first.
/// ///
/// Behavior is the same as [`with_surface_tree_upward`](CompositorToken::with_surface_tree_upward). /// Behavior is the same as [`with_surface_tree_upward`](CompositorToken::with_surface_tree_upward).
pub fn with_surface_tree_downward<F, T>( pub fn with_surface_tree_downward<F, T>(&self, surface: &WlSurface, initial: T, f: F) -> Result<(), ()>
&self,
surface: &Resource<WlSurface>,
initial: T,
f: F,
) -> Result<(), ()>
where where
F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>, F: FnMut(&WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
{ {
SurfaceData::<U, R>::map_tree(surface, initial, f, true); SurfaceData::<U, R>::map_tree(surface, initial, f, true);
Ok(()) Ok(())
@ -340,7 +330,7 @@ where
/// ///
/// 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).
pub fn get_parent(&self, surface: &Resource<WlSurface>) -> Option<Resource<WlSurface>> { pub fn get_parent(&self, surface: &WlSurface) -> Option<WlSurface> {
SurfaceData::<U, R>::get_parent(surface) SurfaceData::<U, R>::get_parent(surface)
} }
@ -348,7 +338,7 @@ where
/// ///
/// 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).
pub fn get_children(&self, surface: &Resource<WlSurface>) -> Vec<Resource<WlSurface>> { pub fn get_children(&self, surface: &WlSurface) -> Vec<WlSurface> {
SurfaceData::<U, R>::get_children(surface) SurfaceData::<U, R>::get_children(surface)
} }
} }
@ -358,7 +348,7 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
/// ///
/// 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).
pub fn has_a_role(&self, surface: &Resource<WlSurface>) -> bool { pub fn has_a_role(&self, surface: &WlSurface) -> bool {
SurfaceData::<U, R>::has_a_role(surface) SurfaceData::<U, R>::has_a_role(surface)
} }
@ -366,7 +356,7 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
/// ///
/// 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).
pub fn has_role<RoleData>(&self, surface: &Resource<WlSurface>) -> bool pub fn has_role<RoleData>(&self, surface: &WlSurface) -> bool
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
@ -379,7 +369,7 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
/// ///
/// 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).
pub fn give_role<RoleData>(&self, surface: &Resource<WlSurface>) -> Result<(), ()> pub fn give_role<RoleData>(&self, surface: &WlSurface) -> Result<(), ()>
where where
R: Role<RoleData>, R: Role<RoleData>,
RoleData: Default, RoleData: Default,
@ -393,11 +383,7 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
/// ///
/// 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).
pub fn give_role_with<RoleData>( pub fn give_role_with<RoleData>(&self, surface: &WlSurface, data: RoleData) -> Result<(), RoleData>
&self,
surface: &Resource<WlSurface>,
data: RoleData,
) -> Result<(), RoleData>
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
@ -410,7 +396,7 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
/// ///
/// 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).
pub fn with_role_data<RoleData, F, T>(&self, surface: &Resource<WlSurface>, f: F) -> Result<T, WrongRole> pub fn with_role_data<RoleData, F, T>(&self, surface: &WlSurface, f: F) -> Result<T, WrongRole>
where where
R: Role<RoleData>, R: Role<RoleData>,
F: FnOnce(&mut RoleData) -> T, F: FnOnce(&mut RoleData) -> T,
@ -424,7 +410,7 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
/// ///
/// 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).
pub fn remove_role<RoleData>(&self, surface: &Resource<WlSurface>) -> Result<RoleData, WrongRole> pub fn remove_role<RoleData>(&self, surface: &WlSurface) -> Result<RoleData, WrongRole>
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
@ -435,8 +421,8 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
/// ///
/// If the region is not managed by the `CompositorGlobal` that provided this token, this /// If the region 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).
pub fn get_region_attributes(&self, region: &Resource<wl_region::WlRegion>) -> RegionAttributes { pub fn get_region_attributes(&self, region: &wl_region::WlRegion) -> RegionAttributes {
match region.user_data::<Mutex<RegionAttributes>>() { match region.as_ref().user_data::<Mutex<RegionAttributes>>() {
Some(mutex) => mutex.lock().unwrap().clone(), Some(mutex) => mutex.lock().unwrap().clone(),
None => panic!("Accessing the data of foreign regions is not supported."), None => panic!("Accessing the data of foreign regions is not supported."),
} }
@ -465,25 +451,17 @@ where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
U: Default + 'static, U: Default + 'static,
R: Default + RoleType + Role<SubsurfaceRole> + 'static, R: Default + RoleType + Role<SubsurfaceRole> + 'static,
Impl: FnMut(SurfaceEvent, Resource<WlSurface>, CompositorToken<U, R>) + 'static, Impl: FnMut(SurfaceEvent, WlSurface, CompositorToken<U, R>) + 'static,
{ {
let log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "compositor_handler")); let log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "compositor_handler"));
let implem = Rc::new(RefCell::new(implem)); let implem = Rc::new(RefCell::new(implem));
let comp_token = display.get_token();
let sub_token = display.get_token();
let compositor = display.create_global(4, move |new_compositor, _version| { let compositor = display.create_global(4, move |new_compositor, _version| {
self::handlers::implement_compositor::<U, R, Impl>( self::handlers::implement_compositor::<U, R, Impl>(new_compositor, log.clone(), implem.clone());
new_compositor,
comp_token.clone(),
log.clone(),
implem.clone(),
);
}); });
let subcompositor = display.create_global(1, move |new_subcompositor, _version| { let subcompositor = display.create_global(1, move |new_subcompositor, _version| {
self::handlers::implement_subcompositor::<U, R>(new_subcompositor, sub_token.clone()); self::handlers::implement_subcompositor::<U, R>(new_subcompositor);
}); });
(CompositorToken::make(), compositor, subcompositor) (CompositorToken::make(), compositor, subcompositor)

View File

@ -19,8 +19,8 @@ use wayland_server::{protocol::wl_surface::WlSurface, Resource};
/// have a failure case to forbid this. Note that if any node in such a graph does not /// have a failure case to forbid this. Note that if any node in such a graph does not
/// have a parent, then the graph is a tree and this node is its root. /// have a parent, then the graph is a tree and this node is its root.
pub struct SurfaceData<U, R> { pub struct SurfaceData<U, R> {
parent: Option<Resource<WlSurface>>, parent: Option<WlSurface>,
children: Vec<Resource<WlSurface>>, children: Vec<WlSurface>,
role: R, role: R,
attributes: SurfaceAttributes<U>, attributes: SurfaceAttributes<U>,
} }
@ -56,25 +56,30 @@ where
U: 'static, U: 'static,
R: 'static, R: 'static,
{ {
/// Cleans the `user_data` of that surface, must be called when it is destroyed /// Cleans the `as_ref().user_data` of that surface, must be called when it is destroyed
pub fn cleanup(surface: &Resource<WlSurface>) { pub fn cleanup(surface: &WlSurface) {
let my_data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let my_data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut my_data = my_data_mutex.lock().unwrap(); let mut my_data = my_data_mutex.lock().unwrap();
if let Some(old_parent) = my_data.parent.take() { if let Some(old_parent) = my_data.parent.take() {
if !old_parent.equals(surface) { if !old_parent.as_ref().equals(surface.as_ref()) {
// We had a parent that is not ourselves, lets unregister ourselves from it // We had a parent that is not ourselves, lets unregister ourselves from it
let old_parent_mutex = old_parent.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let old_parent_mutex = old_parent
.as_ref()
.user_data::<Mutex<SurfaceData<U, R>>>()
.unwrap();
let mut old_parent_guard = old_parent_mutex.lock().unwrap(); let mut old_parent_guard = old_parent_mutex.lock().unwrap();
old_parent_guard.children.retain(|c| !c.equals(surface)); old_parent_guard
.children
.retain(|c| !c.as_ref().equals(surface.as_ref()));
} }
} }
// orphan all our children // orphan all our children
for child in &my_data.children { for child in &my_data.children {
// don't do anything if this child is ourselves // don't do anything if this child is ourselves
if child.equals(surface) { if child.as_ref().equals(surface.as_ref()) {
continue; continue;
} }
let child_mutex = child.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut child_guard = child_mutex.lock().unwrap(); let mut child_guard = child_mutex.lock().unwrap();
child_guard.parent = None; child_guard.parent = None;
} }
@ -82,32 +87,32 @@ where
} }
impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> { impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
pub fn has_a_role(surface: &Resource<WlSurface>) -> bool { pub fn has_a_role(surface: &WlSurface) -> bool {
debug_assert!(surface.is_alive()); debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let data_guard = data_mutex.lock().unwrap(); let data_guard = data_mutex.lock().unwrap();
<R as RoleType>::has_role(&data_guard.role) <R as RoleType>::has_role(&data_guard.role)
} }
/// Check whether a surface has a given role /// Check whether a surface has a given role
pub fn has_role<RoleData>(surface: &Resource<WlSurface>) -> bool pub fn has_role<RoleData>(surface: &WlSurface) -> bool
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
debug_assert!(surface.is_alive()); debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let data_guard = data_mutex.lock().unwrap(); let data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::has(&data_guard.role) <R as Role<RoleData>>::has(&data_guard.role)
} }
/// Register that this surface has a role, fails if it already has one /// Register that this surface has a role, fails if it already has one
pub fn give_role<RoleData>(surface: &Resource<WlSurface>) -> Result<(), ()> pub fn give_role<RoleData>(surface: &WlSurface) -> Result<(), ()>
where where
R: Role<RoleData>, R: Role<RoleData>,
RoleData: Default, RoleData: Default,
{ {
debug_assert!(surface.is_alive()); debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::set(&mut data_guard.role) <R as Role<RoleData>>::set(&mut data_guard.role)
} }
@ -115,12 +120,12 @@ impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
/// Register that this surface has a role with given data /// Register that this surface has a role with given data
/// ///
/// Fails if it already has one and returns the data /// Fails if it already has one and returns the data
pub fn give_role_with<RoleData>(surface: &Resource<WlSurface>, data: RoleData) -> Result<(), RoleData> pub fn give_role_with<RoleData>(surface: &WlSurface, data: RoleData) -> Result<(), RoleData>
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
debug_assert!(surface.is_alive()); debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::set_with(&mut data_guard.role, data) <R as Role<RoleData>>::set_with(&mut data_guard.role, data)
} }
@ -129,24 +134,24 @@ impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
/// ///
/// It is a noop if this surface already didn't have one, but fails if /// 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. /// the role was "subsurface", it must be removed by the `unset_parent` method.
pub fn remove_role<RoleData>(surface: &Resource<WlSurface>) -> Result<RoleData, WrongRole> pub fn remove_role<RoleData>(surface: &WlSurface) -> Result<RoleData, WrongRole>
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
debug_assert!(surface.is_alive()); debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::unset(&mut data_guard.role) <R as Role<RoleData>>::unset(&mut data_guard.role)
} }
/// Access to the role data /// Access to the role data
pub fn with_role_data<RoleData, F, T>(surface: &Resource<WlSurface>, f: F) -> Result<T, WrongRole> pub fn with_role_data<RoleData, F, T>(surface: &WlSurface, f: F) -> Result<T, WrongRole>
where where
R: Role<RoleData>, R: Role<RoleData>,
F: FnOnce(&mut RoleData) -> T, F: FnOnce(&mut RoleData) -> T,
{ {
debug_assert!(surface.is_alive()); debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
let data = <R as Role<RoleData>>::data_mut(&mut data_guard.role)?; let data = <R as Role<RoleData>>::data_mut(&mut data_guard.role)?;
Ok(f(data)) Ok(f(data))
@ -158,13 +163,13 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
/// ///
/// if this surface already has a role, does nothing and fails, otherwise /// if this surface already has a role, does nothing and fails, otherwise
/// its role is now to be a subsurface /// its role is now to be a subsurface
pub fn set_parent(child: &Resource<WlSurface>, parent: &Resource<WlSurface>) -> Result<(), ()> { pub fn set_parent(child: &WlSurface, parent: &WlSurface) -> Result<(), ()> {
debug_assert!(child.is_alive()); debug_assert!(child.as_ref().is_alive());
debug_assert!(parent.is_alive()); debug_assert!(parent.as_ref().is_alive());
// change child's parent // change child's parent
{ {
let child_mutex = child.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut child_guard = child_mutex.lock().unwrap(); let mut child_guard = child_mutex.lock().unwrap();
// if surface already has a role, it cannot become a subsurface // if surface already has a role, it cannot become a subsurface
<R as Role<SubsurfaceRole>>::set(&mut child_guard.role)?; <R as Role<SubsurfaceRole>>::set(&mut child_guard.role)?;
@ -174,7 +179,7 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
// register child to new parent // register child to new parent
// double scoping is to be robust to have a child be its own parent // double scoping is to be robust to have a child be its own parent
{ {
let parent_mutex = parent.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut parent_guard = parent_mutex.lock().unwrap(); let mut parent_guard = parent_mutex.lock().unwrap();
parent_guard.children.push(child.clone()) parent_guard.children.push(child.clone())
} }
@ -184,10 +189,10 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
/// Remove a pre-existing parent of this child /// Remove a pre-existing parent of this child
/// ///
/// Does nothing if it has no parent /// Does nothing if it has no parent
pub fn unset_parent(child: &Resource<WlSurface>) { pub fn unset_parent(child: &WlSurface) {
debug_assert!(child.is_alive()); debug_assert!(child.as_ref().is_alive());
let old_parent = { let old_parent = {
let child_mutex = child.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut child_guard = child_mutex.lock().unwrap(); let mut child_guard = child_mutex.lock().unwrap();
let old_parent = child_guard.parent.take(); let old_parent = child_guard.parent.take();
if old_parent.is_some() { if old_parent.is_some() {
@ -199,22 +204,27 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
}; };
// unregister from our parent // unregister from our parent
if let Some(old_parent) = old_parent { if let Some(old_parent) = old_parent {
let parent_mutex = old_parent.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let parent_mutex = old_parent
.as_ref()
.user_data::<Mutex<SurfaceData<U, R>>>()
.unwrap();
let mut parent_guard = parent_mutex.lock().unwrap(); let mut parent_guard = parent_mutex.lock().unwrap();
parent_guard.children.retain(|c| !c.equals(child)); parent_guard
.children
.retain(|c| !c.as_ref().equals(child.as_ref()));
} }
} }
/// Retrieve the parent surface (if any) of this surface /// Retrieve the parent surface (if any) of this surface
pub fn get_parent(child: &Resource<WlSurface>) -> Option<Resource<WlSurface>> { pub fn get_parent(child: &WlSurface) -> Option<WlSurface> {
let child_mutex = child.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let child_guard = child_mutex.lock().unwrap(); let child_guard = child_mutex.lock().unwrap();
child_guard.parent.as_ref().cloned() child_guard.parent.as_ref().cloned()
} }
/// Retrieve the parent surface (if any) of this surface /// Retrieve the parent surface (if any) of this surface
pub fn get_children(child: &Resource<WlSurface>) -> Vec<Resource<WlSurface>> { pub fn get_children(child: &WlSurface) -> Vec<WlSurface> {
let child_mutex = child.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let child_guard = child_mutex.lock().unwrap(); let child_guard = child_mutex.lock().unwrap();
child_guard.children.to_vec() child_guard.children.to_vec()
} }
@ -222,31 +232,27 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
/// Reorders a surface relative to one of its sibling /// Reorders a surface relative to one of its sibling
/// ///
/// Fails if `relative_to` is not a sibling or parent of `surface`. /// Fails if `relative_to` is not a sibling or parent of `surface`.
pub fn reorder( pub fn reorder(surface: &WlSurface, to: Location, relative_to: &WlSurface) -> Result<(), ()> {
surface: &Resource<WlSurface>,
to: Location,
relative_to: &Resource<WlSurface>,
) -> Result<(), ()> {
let parent = { let parent = {
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let data_guard = data_mutex.lock().unwrap(); let data_guard = data_mutex.lock().unwrap();
data_guard.parent.as_ref().cloned().unwrap() data_guard.parent.as_ref().cloned().unwrap()
}; };
if parent.equals(relative_to) { if parent.as_ref().equals(relative_to.as_ref()) {
// TODO: handle positioning relative to parent // TODO: handle positioning relative to parent
return Ok(()); return Ok(());
} }
fn index_of(surface: &Resource<WlSurface>, slice: &[Resource<WlSurface>]) -> Option<usize> { fn index_of(surface: &WlSurface, slice: &[WlSurface]) -> Option<usize> {
for (i, s) in slice.iter().enumerate() { for (i, s) in slice.iter().enumerate() {
if s.equals(surface) { if s.as_ref().equals(surface.as_ref()) {
return Some(i); return Some(i);
} }
} }
None None
} }
let parent_mutex = parent.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut parent_guard = parent_mutex.lock().unwrap(); let mut parent_guard = parent_mutex.lock().unwrap();
let my_index = index_of(surface, &parent_guard.children).unwrap(); let my_index = index_of(surface, &parent_guard.children).unwrap();
let mut other_index = match index_of(surface, &parent_guard.children) { let mut other_index = match index_of(surface, &parent_guard.children) {
@ -271,11 +277,12 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
/// ///
/// Note that an internal lock is taken during access of this data, /// Note that an internal lock is taken during access of this data,
/// so the tree cannot be manipulated at the same time /// so the tree cannot be manipulated at the same time
pub fn with_data<T, F>(surface: &Resource<WlSurface>, f: F) -> T pub fn with_data<T, F>(surface: &WlSurface, f: F) -> T
where where
F: FnOnce(&mut SurfaceAttributes<U>) -> T, F: FnOnce(&mut SurfaceAttributes<U>) -> T,
{ {
let data_mutex = surface let data_mutex = surface
.as_ref()
.user_data::<Mutex<SurfaceData<U, R>>>() .user_data::<Mutex<SurfaceData<U, R>>>()
.expect("Accessing the data of foreign surfaces is not supported."); .expect("Accessing the data of foreign surfaces is not supported.");
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
@ -290,27 +297,27 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
/// ///
/// The callback returns whether the traversal should continue or not. Returning /// The callback returns whether the traversal should continue or not. Returning
/// false will cause an early-stopping. /// false will cause an early-stopping.
pub fn map_tree<F, T>(root: &Resource<WlSurface>, initial: T, mut f: F, reverse: bool) pub fn map_tree<F, T>(root: &WlSurface, initial: T, mut f: F, reverse: bool)
where where
F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>, F: FnMut(&WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
{ {
// helper function for recursion // helper function for recursion
fn map<U: 'static, R: 'static, F, T>( fn map<U: 'static, R: 'static, F, T>(
surface: &Resource<WlSurface>, surface: &WlSurface,
root: &Resource<WlSurface>, root: &WlSurface,
initial: &T, initial: &T,
f: &mut F, f: &mut F,
reverse: bool, reverse: bool,
) -> bool ) -> bool
where where
F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>, F: FnMut(&WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
{ {
// stop if we met the root, so to not deadlock/inifinte loop // stop if we met the root, so to not deadlock/inifinte loop
if surface.equals(root) { if surface.as_ref().equals(root.as_ref()) {
return true; return true;
} }
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
let data_guard = &mut *data_guard; let data_guard = &mut *data_guard;
// call the callback on ourselves // call the callback on ourselves
@ -337,7 +344,7 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
} }
} }
let data_mutex = root.user_data::<Mutex<SurfaceData<U, R>>>().unwrap(); let data_mutex = root.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
let data_guard = &mut *data_guard; let data_guard = &mut *data_guard;
// call the callback on ourselves // call the callback on ourselves

View File

@ -17,10 +17,10 @@ pub struct SourceMetadata {
pub dnd_action: DndAction, pub dnd_action: DndAction,
} }
pub(crate) fn implement_data_source(src: NewResource<WlDataSource>) -> Resource<WlDataSource> { pub(crate) fn implement_data_source(src: NewResource<WlDataSource>) -> WlDataSource {
src.implement( src.implement_closure(
|req, me| { |req, me| {
let data: &Mutex<SourceMetadata> = me.user_data().unwrap(); let data: &Mutex<SourceMetadata> = me.as_ref().user_data().unwrap();
let mut guard = data.lock().unwrap(); let mut guard = data.lock().unwrap();
match req { match req {
Request::Offer { mime_type } => guard.mime_types.push(mime_type), Request::Offer { mime_type } => guard.mime_types.push(mime_type),
@ -28,6 +28,7 @@ pub(crate) fn implement_data_source(src: NewResource<WlDataSource>) -> Resource<
guard.dnd_action = DndAction::from_bits_truncate(dnd_actions); guard.dnd_action = DndAction::from_bits_truncate(dnd_actions);
} }
Request::Destroy => {} Request::Destroy => {}
_ => unreachable!(),
} }
}, },
None::<fn(_)>, None::<fn(_)>,
@ -40,10 +41,10 @@ pub(crate) fn implement_data_source(src: NewResource<WlDataSource>) -> Resource<
/// Access the metadata of a data source /// Access the metadata of a data source
pub fn with_source_metadata<T, F: FnOnce(&SourceMetadata) -> T>( pub fn with_source_metadata<T, F: FnOnce(&SourceMetadata) -> T>(
source: &Resource<WlDataSource>, source: &WlDataSource,
f: F, f: F,
) -> Result<T, ()> { ) -> Result<T, ()> {
match source.user_data::<Mutex<SourceMetadata>>() { match source.as_ref().user_data::<Mutex<SourceMetadata>>() {
Some(data) => Ok(f(&data.lock().unwrap())), Some(data) => Ok(f(&data.lock().unwrap())),
None => Err(()), None => Err(()),
} }

View File

@ -16,12 +16,12 @@ use crate::wayland::{
use super::{with_source_metadata, DataDeviceData, DnDIconRole, SeatData}; use super::{with_source_metadata, DataDeviceData, DnDIconRole, SeatData};
pub(crate) struct DnDGrab<U, R> { pub(crate) struct DnDGrab<U, R> {
data_source: Option<Resource<wl_data_source::WlDataSource>>, data_source: Option<wl_data_source::WlDataSource>,
current_focus: Option<Resource<wl_surface::WlSurface>>, current_focus: Option<wl_surface::WlSurface>,
pending_offers: Vec<Resource<wl_data_offer::WlDataOffer>>, pending_offers: Vec<wl_data_offer::WlDataOffer>,
offer_data: Option<Arc<Mutex<OfferData>>>, offer_data: Option<Arc<Mutex<OfferData>>>,
icon: Option<Resource<wl_surface::WlSurface>>, icon: Option<wl_surface::WlSurface>,
origin: Resource<wl_surface::WlSurface>, origin: wl_surface::WlSurface,
callback: Arc<Mutex<dyn FnMut(super::DataDeviceEvent) + Send>>, callback: Arc<Mutex<dyn FnMut(super::DataDeviceEvent) + Send>>,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
seat: Seat, seat: Seat,
@ -29,10 +29,10 @@ pub(crate) struct DnDGrab<U, R> {
impl<U: 'static, R: Role<DnDIconRole> + 'static> DnDGrab<U, R> { impl<U: 'static, R: Role<DnDIconRole> + 'static> DnDGrab<U, R> {
pub(crate) fn new( pub(crate) fn new(
source: Option<Resource<wl_data_source::WlDataSource>>, source: Option<wl_data_source::WlDataSource>,
origin: Resource<wl_surface::WlSurface>, origin: wl_surface::WlSurface,
seat: Seat, seat: Seat,
icon: Option<Resource<wl_surface::WlSurface>>, icon: Option<wl_surface::WlSurface>,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
callback: Arc<Mutex<dyn FnMut(super::DataDeviceEvent) + Send>>, callback: Arc<Mutex<dyn FnMut(super::DataDeviceEvent) + Send>>,
) -> DnDGrab<U, R> { ) -> DnDGrab<U, R> {
@ -55,7 +55,7 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
&mut self, &mut self,
_handle: &mut PointerInnerHandle<'_>, _handle: &mut PointerInnerHandle<'_>,
location: (f64, f64), location: (f64, f64),
focus: Option<(Resource<wl_surface::WlSurface>, (f64, f64))>, focus: Option<(wl_surface::WlSurface, (f64, f64))>,
serial: u32, serial: u32,
time: u32, time: u32,
) { ) {
@ -71,10 +71,10 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
// focus changed, we need to make a leave if appropriate // focus changed, we need to make a leave if appropriate
if let Some(surface) = self.current_focus.take() { if let Some(surface) = self.current_focus.take() {
// only leave if there is a data source or we are on the original client // only leave if there is a data source or we are on the original client
if self.data_source.is_some() || self.origin.same_client_as(&surface) { if self.data_source.is_some() || self.origin.as_ref().same_client_as(&surface.as_ref()) {
for device in &seat_data.known_devices { for device in &seat_data.known_devices {
if device.same_client_as(&surface) { if device.as_ref().same_client_as(&surface.as_ref()) {
device.send(wl_data_device::Event::Leave); device.leave();
} }
} }
// disable the offers // disable the offers
@ -87,7 +87,7 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
} }
if let Some((surface, (sx, sy))) = focus { if let Some((surface, (sx, sy))) = focus {
// early return if the surface is no longer valid // early return if the surface is no longer valid
let client = match surface.client() { let client = match surface.as_ref().client() {
Some(c) => c, Some(c) => c,
None => return, None => return,
}; };
@ -103,16 +103,17 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
for device in seat_data for device in seat_data
.known_devices .known_devices
.iter() .iter()
.filter(|d| d.same_client_as(&surface)) .filter(|d| d.as_ref().same_client_as(&surface.as_ref()))
{ {
let action_choice = device let action_choice = device
.as_ref()
.user_data::<DataDeviceData>() .user_data::<DataDeviceData>()
.unwrap() .unwrap()
.action_choice .action_choice
.clone(); .clone();
// create a data offer // create a data offer
let offer = client let offer = client
.create_resource::<wl_data_offer::WlDataOffer>(device.version()) .create_resource::<wl_data_offer::WlDataOffer>(device.as_ref().version())
.map(|offer| { .map(|offer| {
implement_dnd_data_offer( implement_dnd_data_offer(
offer, offer,
@ -123,38 +124,24 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
}) })
.unwrap(); .unwrap();
// advertize the offer to the client // advertize the offer to the client
device.send(wl_data_device::Event::DataOffer { id: offer.clone() }); device.data_offer(&offer);
with_source_metadata(source, |meta| { with_source_metadata(source, |meta| {
for mime_type in meta.mime_types.iter().cloned() { for mime_type in meta.mime_types.iter().cloned() {
offer.send(wl_data_offer::Event::Offer { mime_type }) offer.offer(mime_type);
} }
offer.send(wl_data_offer::Event::SourceActions { offer.source_actions(meta.dnd_action.to_raw());
source_actions: meta.dnd_action.to_raw(),
});
}) })
.unwrap(); .unwrap();
device.send(wl_data_device::Event::Enter { device.enter(serial, &surface, x - sx, y - sy, Some(&offer));
serial,
x: x - sx,
y: y - sy,
surface: surface.clone(),
id: Some(offer.clone()),
});
self.pending_offers.push(offer); self.pending_offers.push(offer);
} }
self.offer_data = Some(offer_data); self.offer_data = Some(offer_data);
} else { } else {
// only send if we are on a surface of the same client // only send if we are on a surface of the same client
if self.origin.same_client_as(&surface) { if self.origin.as_ref().same_client_as(&surface.as_ref()) {
for device in &seat_data.known_devices { for device in &seat_data.known_devices {
if device.same_client_as(&surface) { if device.as_ref().same_client_as(&surface.as_ref()) {
device.send(wl_data_device::Event::Enter { device.enter(serial, &surface, x - sx, y - sy, None);
serial,
x: x - sx,
y: y - sy,
surface: surface.clone(),
id: None,
});
} }
} }
} }
@ -162,14 +149,10 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
self.current_focus = Some(surface); self.current_focus = Some(surface);
} else { } else {
// make a move // make a move
if self.data_source.is_some() || self.origin.same_client_as(&surface) { if self.data_source.is_some() || self.origin.as_ref().same_client_as(&surface.as_ref()) {
for device in &seat_data.known_devices { for device in &seat_data.known_devices {
if device.same_client_as(&surface) { if device.as_ref().same_client_as(&surface.as_ref()) {
device.send(wl_data_device::Event::Motion { device.motion(time, x - sx, y - sy);
time,
x: x - sx,
y: y - sy,
});
} }
} }
} }
@ -201,13 +184,13 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
false false
}; };
if let Some(ref surface) = self.current_focus { if let Some(ref surface) = self.current_focus {
if self.data_source.is_some() || self.origin.same_client_as(&surface) { if self.data_source.is_some() || self.origin.as_ref().same_client_as(&surface.as_ref()) {
for device in &seat_data.known_devices { for device in &seat_data.known_devices {
if device.same_client_as(surface) { if device.as_ref().same_client_as(surface.as_ref()) {
if validated { if validated {
device.send(wl_data_device::Event::Drop); device.drop();
} else { } else {
device.send(wl_data_device::Event::Leave); device.leave();
} }
} }
} }
@ -222,14 +205,14 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
} }
} }
if let Some(ref source) = self.data_source { if let Some(ref source) = self.data_source {
source.send(wl_data_source::Event::DndDropPerformed); source.dnd_drop_performed();
if !validated { if !validated {
source.send(wl_data_source::Event::Cancelled); source.cancelled();
} }
} }
(&mut *self.callback.lock().unwrap())(super::DataDeviceEvent::DnDDropped); (&mut *self.callback.lock().unwrap())(super::DataDeviceEvent::DnDDropped);
if let Some(icon) = self.icon.take() { if let Some(icon) = self.icon.take() {
if icon.is_alive() { if icon.as_ref().is_alive() {
self.token.remove_role::<super::DnDIconRole>(&icon).unwrap(); self.token.remove_role::<super::DnDIconRole>(&icon).unwrap();
} }
} }
@ -254,12 +237,12 @@ struct OfferData {
fn implement_dnd_data_offer( fn implement_dnd_data_offer(
offer: NewResource<wl_data_offer::WlDataOffer>, offer: NewResource<wl_data_offer::WlDataOffer>,
source: Resource<wl_data_source::WlDataSource>, source: wl_data_source::WlDataSource,
offer_data: Arc<Mutex<OfferData>>, offer_data: Arc<Mutex<OfferData>>,
action_choice: Arc<Mutex<dyn FnMut(DndAction, DndAction) -> DndAction + Send + 'static>>, action_choice: Arc<Mutex<dyn FnMut(DndAction, DndAction) -> DndAction + Send + 'static>>,
) -> Resource<wl_data_offer::WlDataOffer> { ) -> wl_data_offer::WlDataOffer {
use self::wl_data_offer::Request; use self::wl_data_offer::Request;
offer.implement( offer.implement_closure(
move |req, offer| { move |req, offer| {
let mut data = offer_data.lock().unwrap(); let mut data = offer_data.lock().unwrap();
match req { match req {
@ -278,40 +261,40 @@ fn implement_dnd_data_offer(
// check if the source and associated mime type is still valid // check if the source and associated mime type is still valid
let valid = with_source_metadata(&source, |meta| meta.mime_types.contains(&mime_type)) let valid = with_source_metadata(&source, |meta| meta.mime_types.contains(&mime_type))
.unwrap_or(false) .unwrap_or(false)
&& source.is_alive() && source.as_ref().is_alive()
&& data.active; && data.active;
if valid { if valid {
source.send(wl_data_source::Event::Send { mime_type, fd }); source.send(mime_type, fd);
} }
let _ = ::nix::unistd::close(fd); let _ = ::nix::unistd::close(fd);
} }
Request::Destroy => {} Request::Destroy => {}
Request::Finish => { Request::Finish => {
if !data.active { if !data.active {
offer.post_error( offer.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32, wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer that is no longer active.".into(), "Cannot finish a data offer that is no longer active.".into(),
); );
} }
if !data.accepted { if !data.accepted {
offer.post_error( offer.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32, wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer that has not been accepted.".into(), "Cannot finish a data offer that has not been accepted.".into(),
); );
} }
if !data.dropped { if !data.dropped {
offer.post_error( offer.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32, wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer that has not been dropped.".into(), "Cannot finish a data offer that has not been dropped.".into(),
); );
} }
if data.chosen_action.is_empty() { if data.chosen_action.is_empty() {
offer.post_error( offer.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32, wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer with no valid action.".into(), "Cannot finish a data offer with no valid action.".into(),
); );
} }
source.send(wl_data_source::Event::DndFinished); source.dnd_finished();
data.active = false; data.active = false;
} }
Request::SetActions { Request::SetActions {
@ -320,7 +303,7 @@ fn implement_dnd_data_offer(
} => { } => {
let preferred_action = DndAction::from_bits_truncate(preferred_action); let preferred_action = DndAction::from_bits_truncate(preferred_action);
if ![DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&preferred_action) { if ![DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&preferred_action) {
offer.post_error( offer.as_ref().post_error(
wl_data_offer::Error::InvalidAction as u32, wl_data_offer::Error::InvalidAction as u32,
"Invalid preferred action.".into(), "Invalid preferred action.".into(),
); );
@ -334,13 +317,10 @@ fn implement_dnd_data_offer(
debug_assert!( debug_assert!(
[DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&data.chosen_action) [DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&data.chosen_action)
); );
offer.send(wl_data_offer::Event::Action { offer.action(data.chosen_action.to_raw());
dnd_action: data.chosen_action.to_raw(), source.action(data.chosen_action.to_raw());
});
source.send(wl_data_source::Event::Action {
dnd_action: data.chosen_action.to_raw(),
});
} }
_ => unreachable!(),
} }
}, },
None::<fn(_)>, None::<fn(_)>,

View File

@ -83,17 +83,17 @@ pub use self::server_dnd_grab::ServerDndEvent;
/// Events that are generated by interactions of the clients with the data device /// Events that are generated by interactions of the clients with the data device
pub enum DataDeviceEvent { pub enum DataDeviceEvent {
/// A client has set the selection /// A client has set the selection
NewSelection(Option<Resource<wl_data_source::WlDataSource>>), NewSelection(Option<wl_data_source::WlDataSource>),
/// A client started a drag'n'drop as response to a user pointer action /// A client started a drag'n'drop as response to a user pointer action
DnDStarted { DnDStarted {
/// The data source provided by the client /// The data source provided by the client
/// ///
/// If it is `None`, this means the DnD is restricted to surfaces of the /// If it is `None`, this means the DnD is restricted to surfaces of the
/// same client and the client will manage data transfert by itself. /// same client and the client will manage data transfert by itself.
source: Option<Resource<wl_data_source::WlDataSource>>, source: Option<wl_data_source::WlDataSource>,
/// The icon the client requested to be used to be associated with the cursor icon /// The icon the client requested to be used to be associated with the cursor icon
/// during the drag'n'drop. /// during the drag'n'drop.
icon: Option<Resource<wl_surface::WlSurface>>, icon: Option<wl_surface::WlSurface>,
}, },
/// The drag'n'drop action was finished by the user releasing the buttons /// The drag'n'drop action was finished by the user releasing the buttons
/// ///
@ -116,12 +116,12 @@ pub struct DnDIconRole;
enum Selection { enum Selection {
Empty, Empty,
Client(Resource<wl_data_source::WlDataSource>), Client(wl_data_source::WlDataSource),
Compositor(SourceMetadata), Compositor(SourceMetadata),
} }
struct SeatData { struct SeatData {
known_devices: Vec<Resource<wl_data_device::WlDataDevice>>, known_devices: Vec<wl_data_device::WlDataDevice>,
selection: Selection, selection: Selection,
log: ::slog::Logger, log: ::slog::Logger,
current_focus: Option<Client>, current_focus: Option<Client>,
@ -146,7 +146,7 @@ impl SeatData {
// first sanitize the selection, reseting it to null if the client holding // first sanitize the selection, reseting it to null if the client holding
// it dropped it // it dropped it
let cleanup = if let Selection::Client(ref data_source) = self.selection { let cleanup = if let Selection::Client(ref data_source) = self.selection {
!data_source.is_alive() !data_source.as_ref().is_alive()
} else { } else {
false false
}; };
@ -159,25 +159,25 @@ impl SeatData {
// send an empty selection // send an empty selection
for dd in &self.known_devices { for dd in &self.known_devices {
// skip data devices not belonging to our client // skip data devices not belonging to our client
if dd.client().map(|c| !c.equals(client)).unwrap_or(true) { if dd.as_ref().client().map(|c| !c.equals(client)).unwrap_or(true) {
continue; continue;
} }
dd.send(wl_data_device::Event::Selection { id: None }); dd.selection(None);
} }
} }
Selection::Client(ref data_source) => { Selection::Client(ref data_source) => {
for dd in &self.known_devices { for dd in &self.known_devices {
// skip data devices not belonging to our client // skip data devices not belonging to our client
if dd.client().map(|c| !c.equals(client)).unwrap_or(true) { if dd.as_ref().client().map(|c| !c.equals(client)).unwrap_or(true) {
continue; continue;
} }
let source = data_source.clone(); let source = data_source.clone();
let log = self.log.clone(); let log = self.log.clone();
// create a corresponding data offer // create a corresponding data offer
let offer = client let offer = client
.create_resource::<wl_data_offer::WlDataOffer>(dd.version()) .create_resource::<wl_data_offer::WlDataOffer>(dd.as_ref().version())
.unwrap() .unwrap()
.implement( .implement_closure(
move |req, _offer| match req { move |req, _offer| match req {
wl_data_offer::Request::Receive { fd, mime_type } => { wl_data_offer::Request::Receive { fd, mime_type } => {
// check if the source and associated mime type is still valid // check if the source and associated mime type is still valid
@ -185,12 +185,12 @@ impl SeatData {
meta.mime_types.contains(&mime_type) meta.mime_types.contains(&mime_type)
}) })
.unwrap_or(false) .unwrap_or(false)
&& source.is_alive(); && source.as_ref().is_alive();
if !valid { if !valid {
// deny the receive // deny the receive
debug!(log, "Denying a wl_data_offer.receive with invalid source."); debug!(log, "Denying a wl_data_offer.receive with invalid source.");
} else { } else {
source.send(wl_data_source::Event::Send { mime_type, fd }); source.send(mime_type, fd);
} }
let _ = ::nix::unistd::close(fd); let _ = ::nix::unistd::close(fd);
} }
@ -200,30 +200,35 @@ impl SeatData {
(), (),
); );
// advertize the offer to the client // advertize the offer to the client
dd.send(wl_data_device::Event::DataOffer { id: offer.clone() }); dd.data_offer(&offer);
with_source_metadata(data_source, |meta| { with_source_metadata(data_source, |meta| {
for mime_type in meta.mime_types.iter().cloned() { for mime_type in meta.mime_types.iter().cloned() {
offer.send(wl_data_offer::Event::Offer { mime_type }) offer.offer(mime_type);
} }
}) })
.unwrap(); .unwrap();
dd.send(wl_data_device::Event::Selection { id: Some(offer) }); dd.selection(Some(&offer));
} }
} }
Selection::Compositor(ref meta) => { Selection::Compositor(ref meta) => {
for dd in &self.known_devices { for dd in &self.known_devices {
// skip data devices not belonging to our client // skip data devices not belonging to our client
if dd.client().map(|c| !c.equals(client)).unwrap_or(true) { if dd.as_ref().client().map(|c| !c.equals(client)).unwrap_or(true) {
continue; continue;
} }
let log = self.log.clone(); let log = self.log.clone();
let offer_meta = meta.clone(); let offer_meta = meta.clone();
let callback = dd.user_data::<DataDeviceData>().unwrap().callback.clone(); let callback = dd
.as_ref()
.user_data::<DataDeviceData>()
.unwrap()
.callback
.clone();
// create a corresponding data offer // create a corresponding data offer
let offer = client let offer = client
.create_resource::<wl_data_offer::WlDataOffer>(dd.version()) .create_resource::<wl_data_offer::WlDataOffer>(dd.as_ref().version())
.unwrap() .unwrap()
.implement( .implement_closure(
move |req, _offer| match req { move |req, _offer| match req {
wl_data_offer::Request::Receive { fd, mime_type } => { wl_data_offer::Request::Receive { fd, mime_type } => {
// check if the associated mime type is valid // check if the associated mime type is valid
@ -244,11 +249,11 @@ impl SeatData {
(), (),
); );
// advertize the offer to the client // advertize the offer to the client
dd.send(wl_data_device::Event::DataOffer { id: offer.clone() }); dd.data_offer(&offer);
for mime_type in meta.mime_types.iter().cloned() { for mime_type in meta.mime_types.iter().cloned() {
offer.send(wl_data_offer::Event::Offer { mime_type }) offer.offer(mime_type);
} }
dd.send(wl_data_device::Event::Selection { id: Some(offer) }); dd.selection(Some(&offer));
} }
} }
} }
@ -379,7 +384,7 @@ fn implement_ddm<F, C, U, R>(
action_choice: Arc<Mutex<F>>, action_choice: Arc<Mutex<F>>,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
log: ::slog::Logger, log: ::slog::Logger,
) -> Resource<wl_data_device_manager::WlDataDeviceManager> ) -> wl_data_device_manager::WlDataDeviceManager
where where
F: FnMut(DndAction, DndAction) -> DndAction + Send + 'static, F: FnMut(DndAction, DndAction) -> DndAction + Send + 'static,
C: FnMut(DataDeviceEvent) + Send + 'static, C: FnMut(DataDeviceEvent) + Send + 'static,
@ -387,7 +392,7 @@ where
U: 'static, U: 'static,
{ {
use self::wl_data_device_manager::Request; use self::wl_data_device_manager::Request;
new_ddm.implement( new_ddm.implement_closure(
move |req, _ddm| match req { move |req, _ddm| match req {
Request::CreateDataSource { id } => { Request::CreateDataSource { id } => {
self::data_source::implement_data_source(id); self::data_source::implement_data_source(id);
@ -412,6 +417,7 @@ where
error!(log, "Unmanaged seat given to a data device."); error!(log, "Unmanaged seat given to a data device.");
} }
}, },
_ => unreachable!(),
}, },
None::<fn(_)>, None::<fn(_)>,
(), (),
@ -430,7 +436,7 @@ fn implement_data_device<F, C, U, R>(
action_choice: Arc<Mutex<F>>, action_choice: Arc<Mutex<F>>,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
log: ::slog::Logger, log: ::slog::Logger,
) -> Resource<wl_data_device::WlDataDevice> ) -> wl_data_device::WlDataDevice
where where
F: FnMut(DndAction, DndAction) -> DndAction + Send + 'static, F: FnMut(DndAction, DndAction) -> DndAction + Send + 'static,
C: FnMut(DataDeviceEvent) + Send + 'static, C: FnMut(DataDeviceEvent) + Send + 'static,
@ -442,7 +448,7 @@ where
callback: callback.clone(), callback: callback.clone(),
action_choice, action_choice,
}; };
new_dd.implement( new_dd.implement_closure(
move |req, dd| match req { move |req, dd| match req {
Request::StartDrag { Request::StartDrag {
source, source,
@ -455,7 +461,7 @@ where
if pointer.has_grab(serial) { if pointer.has_grab(serial) {
if let Some(ref icon) = icon { if let Some(ref icon) = icon {
if token.give_role::<DnDIconRole>(icon).is_err() { if token.give_role::<DnDIconRole>(icon).is_err() {
dd.post_error( dd.as_ref().post_error(
wl_data_device::Error::Role as u32, wl_data_device::Error::Role as u32,
"Given surface already has an other role".into(), "Given surface already has an other role".into(),
); );
@ -486,6 +492,7 @@ where
Request::SetSelection { source, serial: _ } => { Request::SetSelection { source, serial: _ } => {
if let Some(keyboard) = seat.get_keyboard() { if let Some(keyboard) = seat.get_keyboard() {
if dd if dd
.as_ref()
.client() .client()
.as_ref() .as_ref()
.map(|c| keyboard.has_focus(c)) .map(|c| keyboard.has_focus(c))
@ -511,8 +518,9 @@ where
.lock() .lock()
.unwrap() .unwrap()
.known_devices .known_devices
.retain(|ndd| ndd.is_alive() && (!ndd.equals(&dd))) .retain(|ndd| ndd.as_ref().is_alive() && (!ndd.as_ref().equals(&dd.as_ref())))
} }
_ => unreachable!(),
}, },
None::<fn(_)>, None::<fn(_)>,
dd_data, dd_data,

View File

@ -37,8 +37,8 @@ pub enum ServerDndEvent {
pub(crate) struct ServerDnDGrab<C: 'static> { pub(crate) struct ServerDnDGrab<C: 'static> {
metadata: super::SourceMetadata, metadata: super::SourceMetadata,
current_focus: Option<Resource<wl_surface::WlSurface>>, current_focus: Option<wl_surface::WlSurface>,
pending_offers: Vec<Resource<wl_data_offer::WlDataOffer>>, pending_offers: Vec<wl_data_offer::WlDataOffer>,
offer_data: Option<Arc<Mutex<OfferData>>>, offer_data: Option<Arc<Mutex<OfferData>>>,
seat: Seat, seat: Seat,
callback: Arc<Mutex<C>>, callback: Arc<Mutex<C>>,
@ -69,7 +69,7 @@ where
&mut self, &mut self,
_handle: &mut PointerInnerHandle<'_>, _handle: &mut PointerInnerHandle<'_>,
location: (f64, f64), location: (f64, f64),
focus: Option<(Resource<wl_surface::WlSurface>, (f64, f64))>, focus: Option<(wl_surface::WlSurface, (f64, f64))>,
serial: u32, serial: u32,
time: u32, time: u32,
) { ) {
@ -85,8 +85,8 @@ where
// focus changed, we need to make a leave if appropriate // focus changed, we need to make a leave if appropriate
if let Some(surface) = self.current_focus.take() { if let Some(surface) = self.current_focus.take() {
for device in &seat_data.known_devices { for device in &seat_data.known_devices {
if device.same_client_as(&surface) { if device.as_ref().same_client_as(&surface.as_ref()) {
device.send(wl_data_device::Event::Leave); device.leave();
} }
} }
// disable the offers // disable the offers
@ -98,7 +98,7 @@ where
} }
if let Some((surface, (sx, sy))) = focus { if let Some((surface, (sx, sy))) = focus {
// early return if the surface is no longer valid // early return if the surface is no longer valid
let client = match surface.client() { let client = match surface.as_ref().client() {
Some(c) => c, Some(c) => c,
None => return, None => return,
}; };
@ -113,16 +113,17 @@ where
for device in seat_data for device in seat_data
.known_devices .known_devices
.iter() .iter()
.filter(|d| d.same_client_as(&surface)) .filter(|d| d.as_ref().same_client_as(&surface.as_ref()))
{ {
let action_choice = device let action_choice = device
.as_ref()
.user_data::<DataDeviceData>() .user_data::<DataDeviceData>()
.unwrap() .unwrap()
.action_choice .action_choice
.clone(); .clone();
// create a data offer // create a data offer
let offer = client let offer = client
.create_resource::<wl_data_offer::WlDataOffer>(device.version()) .create_resource::<wl_data_offer::WlDataOffer>(device.as_ref().version())
.map(|offer| { .map(|offer| {
implement_dnd_data_offer( implement_dnd_data_offer(
offer, offer,
@ -134,20 +135,12 @@ where
}) })
.unwrap(); .unwrap();
// advertize the offer to the client // advertize the offer to the client
device.send(wl_data_device::Event::DataOffer { id: offer.clone() }); device.data_offer(&offer);
for mime_type in self.metadata.mime_types.iter().cloned() { for mime_type in self.metadata.mime_types.iter().cloned() {
offer.send(wl_data_offer::Event::Offer { mime_type }) offer.offer(mime_type);
} }
offer.send(wl_data_offer::Event::SourceActions { offer.source_actions(self.metadata.dnd_action.to_raw());
source_actions: self.metadata.dnd_action.to_raw(), device.enter(serial, &surface, x - sx, y - sy, Some(&offer));
});
device.send(wl_data_device::Event::Enter {
serial,
x: x - sx,
y: y - sy,
surface: surface.clone(),
id: Some(offer.clone()),
});
self.pending_offers.push(offer); self.pending_offers.push(offer);
} }
self.offer_data = Some(offer_data); self.offer_data = Some(offer_data);
@ -155,12 +148,8 @@ where
} else { } else {
// make a move // make a move
for device in &seat_data.known_devices { for device in &seat_data.known_devices {
if device.same_client_as(&surface) { if device.as_ref().same_client_as(&surface.as_ref()) {
device.send(wl_data_device::Event::Motion { device.motion(time, x - sx, y - sy);
time,
x: x - sx,
y: y - sy,
});
} }
} }
} }
@ -192,11 +181,11 @@ where
}; };
if let Some(ref surface) = self.current_focus { if let Some(ref surface) = self.current_focus {
for device in &seat_data.known_devices { for device in &seat_data.known_devices {
if device.same_client_as(surface) { if device.as_ref().same_client_as(surface.as_ref()) {
if validated { if validated {
device.send(wl_data_device::Event::Drop); device.drop();
} else { } else {
device.send(wl_data_device::Event::Leave); device.leave();
} }
} }
} }
@ -239,12 +228,12 @@ fn implement_dnd_data_offer<C>(
offer_data: Arc<Mutex<OfferData>>, offer_data: Arc<Mutex<OfferData>>,
callback: Arc<Mutex<C>>, callback: Arc<Mutex<C>>,
action_choice: Arc<Mutex<dyn FnMut(DndAction, DndAction) -> DndAction + Send + 'static>>, action_choice: Arc<Mutex<dyn FnMut(DndAction, DndAction) -> DndAction + Send + 'static>>,
) -> Resource<wl_data_offer::WlDataOffer> ) -> wl_data_offer::WlDataOffer
where where
C: FnMut(ServerDndEvent) + Send + 'static, C: FnMut(ServerDndEvent) + Send + 'static,
{ {
use self::wl_data_offer::Request; use self::wl_data_offer::Request;
offer.implement( offer.implement_closure(
move |req, offer| { move |req, offer| {
let mut data = offer_data.lock().unwrap(); let mut data = offer_data.lock().unwrap();
match req { match req {
@ -264,25 +253,25 @@ where
Request::Destroy => {} Request::Destroy => {}
Request::Finish => { Request::Finish => {
if !data.active { if !data.active {
offer.post_error( offer.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32, wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer that is no longer active.".into(), "Cannot finish a data offer that is no longer active.".into(),
); );
} }
if !data.accepted { if !data.accepted {
offer.post_error( offer.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32, wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer that has not been accepted.".into(), "Cannot finish a data offer that has not been accepted.".into(),
); );
} }
if !data.dropped { if !data.dropped {
offer.post_error( offer.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32, wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer that has not been dropped.".into(), "Cannot finish a data offer that has not been dropped.".into(),
); );
} }
if data.chosen_action.is_empty() { if data.chosen_action.is_empty() {
offer.post_error( offer.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32, wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer with no valid action.".into(), "Cannot finish a data offer with no valid action.".into(),
); );
@ -296,7 +285,7 @@ where
} => { } => {
let preferred_action = DndAction::from_bits_truncate(preferred_action); let preferred_action = DndAction::from_bits_truncate(preferred_action);
if ![DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&preferred_action) { if ![DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&preferred_action) {
offer.post_error( offer.as_ref().post_error(
wl_data_offer::Error::InvalidAction as u32, wl_data_offer::Error::InvalidAction as u32,
"Invalid preferred action.".into(), "Invalid preferred action.".into(),
); );
@ -308,11 +297,10 @@ where
debug_assert!( debug_assert!(
[DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&data.chosen_action) [DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&data.chosen_action)
); );
offer.send(wl_data_offer::Event::Action { offer.action(data.chosen_action.to_raw());
dnd_action: data.chosen_action.to_raw(),
});
(&mut *callback.lock().unwrap())(ServerDndEvent::Action(data.chosen_action)); (&mut *callback.lock().unwrap())(ServerDndEvent::Action(data.chosen_action));
} }
_ => unreachable!(),
} }
}, },
None::<fn(_)>, None::<fn(_)>,

View File

@ -94,7 +94,7 @@ pub struct PhysicalProperties {
struct Inner { struct Inner {
name: String, name: String,
log: ::slog::Logger, log: ::slog::Logger,
instances: Vec<Resource<WlOutput>>, instances: Vec<WlOutput>,
physical: PhysicalProperties, physical: PhysicalProperties,
location: (i32, i32), location: (i32, i32),
transform: Transform, transform: Transform,
@ -105,7 +105,7 @@ struct Inner {
} }
impl Inner { impl Inner {
fn new_global(&mut self, output: Resource<WlOutput>) { fn new_global(&mut self, output: WlOutput) {
trace!(self.log, "New global instantiated."); trace!(self.log, "New global instantiated.");
if self.modes.is_empty() { if self.modes.is_empty() {
@ -127,32 +127,27 @@ impl Inner {
if Some(mode) == self.preferred_mode { if Some(mode) == self.preferred_mode {
flags |= WMode::Preferred; flags |= WMode::Preferred;
} }
output.send(Event::Mode { output.mode(flags, mode.width, mode.height, mode.refresh);
flags,
width: mode.width,
height: mode.height,
refresh: mode.refresh,
});
} }
if output.version() >= 2 { if output.as_ref().version() >= 2 {
output.send(Event::Scale { factor: self.scale }); output.scale(self.scale);
output.send(Event::Done); output.done();
} }
self.instances.push(output); self.instances.push(output);
} }
fn send_geometry(&self, output: &Resource<WlOutput>) { fn send_geometry(&self, output: &WlOutput) {
output.send(Event::Geometry { output.geometry(
x: self.location.0, self.location.0,
y: self.location.1, self.location.1,
physical_width: self.physical.width, self.physical.width,
physical_height: self.physical.height, self.physical.height,
subpixel: self.physical.subpixel, self.physical.subpixel,
make: self.physical.make.clone(), self.physical.make.clone(),
model: self.physical.model.clone(), self.physical.model.clone(),
transform: self.transform, self.transform,
}); );
} }
} }
@ -199,14 +194,15 @@ impl Output {
let output = Output { inner: inner.clone() }; let output = Output { inner: inner.clone() };
let global = display.create_global(3, move |new_output: NewResource<_>, _version| { let global = display.create_global(3, move |new_output: NewResource<_>, _version| {
let output = new_output.implement( let output = new_output.implement_closure(
|req, _| { |_, _| {},
// this will break if new variants are added :) Some(|output: WlOutput| {
let Request::Release = req; let inner = output.as_ref().user_data::<Arc<Mutex<Inner>>>().unwrap();
}, inner
Some(|output: Resource<WlOutput>| { .lock()
let inner = output.user_data::<Arc<Mutex<Inner>>>().unwrap(); .unwrap()
inner.lock().unwrap().instances.retain(|o| !o.equals(&output)); .instances
.retain(|o| !o.as_ref().equals(&output.as_ref()));
}), }),
inner.clone(), inner.clone(),
); );
@ -285,34 +281,29 @@ impl Output {
} }
for output in &inner.instances { for output in &inner.instances {
if let Some(mode) = new_mode { if let Some(mode) = new_mode {
output.send(Event::Mode { output.mode(flags, mode.width, mode.height, mode.refresh);
flags,
width: mode.width,
height: mode.height,
refresh: mode.refresh,
});
} }
if new_transform.is_some() { if new_transform.is_some() {
inner.send_geometry(output); inner.send_geometry(output);
} }
if let Some(scale) = new_scale { if let Some(scale) = new_scale {
if output.version() >= 2 { if output.as_ref().version() >= 2 {
output.send(Event::Scale { factor: scale }); output.scale(scale);
} }
} }
if output.version() >= 2 { if output.as_ref().version() >= 2 {
output.send(Event::Done); output.done();
} }
} }
} }
/// Check is given [`wl_output`](WlOutput) instance is managed by this [`Output`]. /// Check is given [`wl_output`](WlOutput) instance is managed by this [`Output`].
pub fn owns(&self, output: &Resource<WlOutput>) -> bool { pub fn owns(&self, output: &WlOutput) -> bool {
self.inner self.inner
.lock() .lock()
.unwrap() .unwrap()
.instances .instances
.iter() .iter()
.any(|o| o.equals(output)) .any(|o| o.as_ref().equals(output.as_ref()))
} }
} }

View File

@ -104,15 +104,15 @@ impl<'a> Default for XkbConfig<'a> {
} }
struct KbdInternal { struct KbdInternal {
known_kbds: Vec<Resource<WlKeyboard>>, known_kbds: Vec<WlKeyboard>,
focus: Option<Resource<WlSurface>>, focus: Option<WlSurface>,
pressed_keys: Vec<u32>, pressed_keys: Vec<u32>,
mods_state: ModifiersState, mods_state: ModifiersState,
keymap: xkb::Keymap, keymap: xkb::Keymap,
state: xkb::State, state: xkb::State,
repeat_rate: i32, repeat_rate: i32,
repeat_delay: i32, repeat_delay: i32,
focus_hook: Box<dyn FnMut(Option<&Resource<WlSurface>>)>, focus_hook: Box<dyn FnMut(Option<&WlSurface>)>,
} }
// This is OK because all parts of `xkb` will remain on the // This is OK because all parts of `xkb` will remain on the
@ -124,7 +124,7 @@ impl KbdInternal {
xkb_config: XkbConfig<'_>, xkb_config: XkbConfig<'_>,
repeat_rate: i32, repeat_rate: i32,
repeat_delay: i32, repeat_delay: i32,
focus_hook: Box<dyn FnMut(Option<&Resource<WlSurface>>)>, focus_hook: Box<dyn FnMut(Option<&WlSurface>)>,
) -> Result<KbdInternal, ()> { ) -> Result<KbdInternal, ()> {
// we create a new contex for each keyboard because libxkbcommon is actually NOT threadsafe // we create a new contex for each keyboard because libxkbcommon is actually NOT threadsafe
// so confining it inside the KbdInternal allows us to use Rusts mutability rules to make // so confining it inside the KbdInternal allows us to use Rusts mutability rules to make
@ -205,11 +205,11 @@ impl KbdInternal {
fn with_focused_kbds<F>(&self, mut f: F) fn with_focused_kbds<F>(&self, mut f: F)
where where
F: FnMut(&Resource<WlKeyboard>, &Resource<WlSurface>), F: FnMut(&WlKeyboard, &WlSurface),
{ {
if let Some(ref surface) = self.focus { if let Some(ref surface) = self.focus {
for kbd in &self.known_kbds { for kbd in &self.known_kbds {
if kbd.same_client_as(surface) { if kbd.as_ref().same_client_as(surface.as_ref()) {
f(kbd, surface); f(kbd, surface);
} }
} }
@ -235,7 +235,7 @@ pub(crate) fn create_keyboard_handler<F>(
focus_hook: F, focus_hook: F,
) -> Result<KeyboardHandle, Error> ) -> Result<KeyboardHandle, Error>
where where
F: FnMut(Option<&Resource<WlSurface>>) + 'static, F: FnMut(Option<&WlSurface>) + 'static,
{ {
let log = logger.new(o!("smithay_module" => "xkbcommon_handler")); let log = logger.new(o!("smithay_module" => "xkbcommon_handler"));
info!(log, "Initializing a xkbcommon handler with keymap query"; info!(log, "Initializing a xkbcommon handler with keymap query";
@ -332,20 +332,9 @@ impl KeyboardHandle {
}; };
guard.with_focused_kbds(|kbd, _| { guard.with_focused_kbds(|kbd, _| {
if let Some((dep, la, lo, gr)) = modifiers { if let Some((dep, la, lo, gr)) = modifiers {
kbd.send(Event::Modifiers { kbd.modifiers(serial, dep, la, lo, gr);
serial,
mods_depressed: dep,
mods_latched: la,
mods_locked: lo,
group: gr,
});
} }
kbd.send(Event::Key { kbd.key(serial, time, keycode, wl_state);
serial,
time,
key: keycode,
state: wl_state,
});
}); });
if guard.focus.is_some() { if guard.focus.is_some() {
trace!(self.arc.logger, "Input forwarded to client"); trace!(self.arc.logger, "Input forwarded to client");
@ -360,22 +349,19 @@ impl KeyboardHandle {
/// will be sent a [`wl_keyboard::Event::Leave`](wayland_server::protocol::wl_keyboard::Event::Leave) /// will be sent a [`wl_keyboard::Event::Leave`](wayland_server::protocol::wl_keyboard::Event::Leave)
/// event, and if the new focus is not `None`, /// event, and if the new focus is not `None`,
/// a [`wl_keyboard::Event::Enter`](wayland_server::protocol::wl_keyboard::Event::Enter) event will be sent. /// a [`wl_keyboard::Event::Enter`](wayland_server::protocol::wl_keyboard::Event::Enter) event will be sent.
pub fn set_focus(&self, focus: Option<&Resource<WlSurface>>, serial: u32) { pub fn set_focus(&self, focus: Option<&WlSurface>, serial: u32) {
let mut guard = self.arc.internal.lock().unwrap(); let mut guard = self.arc.internal.lock().unwrap();
let same = guard let same = guard
.focus .focus
.as_ref() .as_ref()
.and_then(|f| focus.map(|s| s.equals(f))) .and_then(|f| focus.map(|s| s.as_ref().equals(f.as_ref())))
.unwrap_or(false); .unwrap_or(false);
if !same { if !same {
// unset old focus // unset old focus
guard.with_focused_kbds(|kbd, s| { guard.with_focused_kbds(|kbd, s| {
kbd.send(Event::Leave { kbd.leave(serial, &s);
serial,
surface: s.clone(),
});
}); });
// set new focus // set new focus
@ -383,18 +369,8 @@ impl KeyboardHandle {
let (dep, la, lo, gr) = guard.serialize_modifiers(); let (dep, la, lo, gr) = guard.serialize_modifiers();
let keys = guard.serialize_pressed_keys(); let keys = guard.serialize_pressed_keys();
guard.with_focused_kbds(|kbd, surface| { guard.with_focused_kbds(|kbd, surface| {
kbd.send(Event::Modifiers { kbd.modifiers(serial, dep, la, lo, gr);
serial, kbd.enter(serial, &surface, keys.clone());
mods_depressed: dep,
mods_latched: la,
mods_locked: lo,
group: gr,
});
kbd.send(Event::Enter {
serial,
surface: surface.clone(),
keys: keys.clone(),
});
}); });
{ {
let KbdInternal { let KbdInternal {
@ -422,7 +398,7 @@ impl KeyboardHandle {
.unwrap() .unwrap()
.focus .focus
.as_ref() .as_ref()
.and_then(|f| f.client()) .and_then(|f| f.as_ref().client())
.map(|c| c.equals(client)) .map(|c| c.equals(client))
.unwrap_or(false) .unwrap_or(false)
} }
@ -432,18 +408,18 @@ impl KeyboardHandle {
/// The keymap will automatically be sent to it /// The keymap will automatically be sent to it
/// ///
/// This should be done first, before anything else is done with this keyboard. /// This should be done first, before anything else is done with this keyboard.
pub(crate) fn new_kbd(&self, kbd: Resource<WlKeyboard>) { pub(crate) fn new_kbd(&self, kbd: WlKeyboard) {
trace!(self.arc.logger, "Sending keymap to client"); trace!(self.arc.logger, "Sending keymap to client");
// prepare a tempfile with the keymap, to send it to the client // prepare a tempfile with the keymap, to send it to the client
let ret = tempfile().and_then(|mut f| { let ret = tempfile().and_then(|mut f| {
f.write_all(self.arc.keymap.as_bytes())?; f.write_all(self.arc.keymap.as_bytes())?;
f.flush()?; f.flush()?;
kbd.send(Event::Keymap { kbd.keymap(
format: KeymapFormat::XkbV1, KeymapFormat::XkbV1,
fd: f.as_raw_fd(), f.as_raw_fd(),
size: self.arc.keymap.as_bytes().len() as u32, self.arc.keymap.as_bytes().len() as u32,
}); );
Ok(()) Ok(())
}); });
@ -456,11 +432,8 @@ impl KeyboardHandle {
}; };
let mut guard = self.arc.internal.lock().unwrap(); let mut guard = self.arc.internal.lock().unwrap();
if kbd.version() >= 4 { if kbd.as_ref().version() >= 4 {
kbd.send(Event::RepeatInfo { kbd.repeat_info(guard.repeat_rate, guard.repeat_delay);
rate: guard.repeat_rate,
delay: guard.repeat_delay,
});
} }
guard.known_kbds.push(kbd); guard.known_kbds.push(kbd);
} }
@ -471,7 +444,7 @@ impl KeyboardHandle {
guard.repeat_delay = delay; guard.repeat_delay = delay;
guard.repeat_rate = rate; guard.repeat_rate = rate;
for kbd in &guard.known_kbds { for kbd in &guard.known_kbds {
kbd.send(Event::RepeatInfo { rate, delay }); kbd.repeat_info(rate, delay);
} }
} }
} }
@ -479,26 +452,27 @@ impl KeyboardHandle {
pub(crate) fn implement_keyboard( pub(crate) fn implement_keyboard(
new_keyboard: NewResource<WlKeyboard>, new_keyboard: NewResource<WlKeyboard>,
handle: Option<&KeyboardHandle>, handle: Option<&KeyboardHandle>,
) -> Resource<WlKeyboard> { ) -> WlKeyboard {
let destructor = match handle { let destructor = match handle {
Some(h) => { Some(h) => {
let arc = h.arc.clone(); let arc = h.arc.clone();
Some(move |keyboard: Resource<_>| { Some(move |keyboard: WlKeyboard| {
arc.internal arc.internal
.lock() .lock()
.unwrap() .unwrap()
.known_kbds .known_kbds
.retain(|k| !k.equals(&keyboard)) .retain(|k| !k.as_ref().equals(&keyboard.as_ref()))
}) })
} }
None => None, None => None,
}; };
new_keyboard.implement( new_keyboard.implement_closure(
|request, _keyboard| { |request, _keyboard| {
match request { match request {
Request::Release => { Request::Release => {
// Our destructors already handle it // Our destructors already handle it
} }
_ => unreachable!(),
} }
}, },
destructor, destructor,

View File

@ -67,7 +67,7 @@ use wayland_server::{
struct Inner { struct Inner {
pointer: Option<PointerHandle>, pointer: Option<PointerHandle>,
keyboard: Option<KeyboardHandle>, keyboard: Option<KeyboardHandle>,
known_seats: Vec<Resource<wl_seat::WlSeat>>, known_seats: Vec<wl_seat::WlSeat>,
} }
pub(crate) struct SeatArc { pub(crate) struct SeatArc {
@ -92,7 +92,7 @@ impl Inner {
fn send_all_caps(&self) { fn send_all_caps(&self) {
let capabilities = self.compute_caps(); let capabilities = self.compute_caps();
for seat in &self.known_seats { for seat in &self.known_seats {
seat.send(wl_seat::Event::Capabilities { capabilities }); seat.capabilities(capabilities);
} }
} }
} }
@ -148,22 +148,21 @@ impl Seat {
let global = display.create_global(5, move |new_seat, _version| { let global = display.create_global(5, move |new_seat, _version| {
let seat = implement_seat(new_seat, arc.clone(), token.clone()); let seat = implement_seat(new_seat, arc.clone(), token.clone());
let mut inner = arc.inner.lock().unwrap(); let mut inner = arc.inner.lock().unwrap();
if seat.version() >= 2 { if seat.as_ref().version() >= 2 {
seat.send(wl_seat::Event::Name { seat.name(arc.name.clone());
name: arc.name.clone(),
});
} }
seat.send(wl_seat::Event::Capabilities { seat.capabilities(inner.compute_caps());
capabilities: inner.compute_caps(),
});
inner.known_seats.push(seat); inner.known_seats.push(seat);
}); });
(seat, global) (seat, global)
} }
/// Attempt to retrieve a [`Seat`] from an existing resource /// Attempt to retrieve a [`Seat`] from an existing resource
pub fn from_resource(seat: &Resource<wl_seat::WlSeat>) -> Option<Seat> { pub fn from_resource(seat: &wl_seat::WlSeat) -> Option<Seat> {
seat.user_data::<Arc<SeatArc>>().cloned().map(|arc| Seat { arc }) seat.as_ref()
.user_data::<Arc<SeatArc>>()
.cloned()
.map(|arc| Seat { arc })
} }
/// Acces the `UserDataMap` associated with this `Seat` /// Acces the `UserDataMap` associated with this `Seat`
@ -287,7 +286,7 @@ impl Seat {
mut focus_hook: F, mut focus_hook: F,
) -> Result<KeyboardHandle, KeyboardError> ) -> Result<KeyboardHandle, KeyboardError>
where where
F: FnMut(&Seat, Option<&Resource<wl_surface::WlSurface>>) + 'static, F: FnMut(&Seat, Option<&wl_surface::WlSurface>) + 'static,
{ {
let me = self.clone(); let me = self.clone();
let mut inner = self.arc.inner.lock().unwrap(); let mut inner = self.arc.inner.lock().unwrap();
@ -326,9 +325,9 @@ impl Seat {
} }
/// Checks whether a given [`WlSeat`](wl_seat::WlSeat) is associated with this [`Seat`] /// Checks whether a given [`WlSeat`](wl_seat::WlSeat) is associated with this [`Seat`]
pub fn owns(&self, seat: &Resource<wl_seat::WlSeat>) -> bool { pub fn owns(&self, seat: &wl_seat::WlSeat) -> bool {
let inner = self.arc.inner.lock().unwrap(); let inner = self.arc.inner.lock().unwrap();
inner.known_seats.iter().any(|s| s.equals(seat)) inner.known_seats.iter().any(|s| s.as_ref().equals(seat.as_ref()))
} }
} }
@ -342,15 +341,15 @@ fn implement_seat<U, R>(
new_seat: NewResource<wl_seat::WlSeat>, new_seat: NewResource<wl_seat::WlSeat>,
arc: Arc<SeatArc>, arc: Arc<SeatArc>,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
) -> Resource<wl_seat::WlSeat> ) -> wl_seat::WlSeat
where where
R: Role<CursorImageRole> + 'static, R: Role<CursorImageRole> + 'static,
U: 'static, U: 'static,
{ {
let dest_arc = arc.clone(); let dest_arc = arc.clone();
new_seat.implement( new_seat.implement_closure(
move |request, seat| { move |request, seat| {
let arc = seat.user_data::<Arc<SeatArc>>().unwrap(); let arc = seat.as_ref().user_data::<Arc<SeatArc>>().unwrap();
let inner = arc.inner.lock().unwrap(); let inner = arc.inner.lock().unwrap();
match request { match request {
wl_seat::Request::GetPointer { id } => { wl_seat::Request::GetPointer { id } => {
@ -376,15 +375,16 @@ where
wl_seat::Request::Release => { wl_seat::Request::Release => {
// Our destructors already handle it // Our destructors already handle it
} }
_ => unreachable!(),
} }
}, },
Some(move |seat| { Some(move |seat: wl_seat::WlSeat| {
dest_arc dest_arc
.inner .inner
.lock() .lock()
.unwrap() .unwrap()
.known_seats .known_seats
.retain(|s| !s.equals(&seat)); .retain(|s| !s.as_ref().equals(&seat.as_ref()));
}), }),
arc, arc,
) )

View File

@ -24,7 +24,7 @@ pub enum CursorImageStatus {
/// The compositor should draw its cursor /// The compositor should draw its cursor
Default, Default,
/// The cursor should be drawn using this surface as an image /// The cursor should be drawn using this surface as an image
Image(Resource<WlSurface>), Image(WlSurface),
} }
enum GrabStatus { enum GrabStatus {
@ -34,13 +34,13 @@ enum GrabStatus {
} }
struct PointerInternal { struct PointerInternal {
known_pointers: Vec<Resource<WlPointer>>, known_pointers: Vec<WlPointer>,
focus: Option<(Resource<WlSurface>, (f64, f64))>, focus: Option<(WlSurface, (f64, f64))>,
pending_focus: Option<(Resource<WlSurface>, (f64, f64))>, pending_focus: Option<(WlSurface, (f64, f64))>,
location: (f64, f64), location: (f64, f64),
grab: GrabStatus, grab: GrabStatus,
pressed_buttons: Vec<u32>, pressed_buttons: Vec<u32>,
image_callback: Box<dyn FnMut(CursorImageStatus) + Send>, image_callback: Box<dyn FnMut(CursorImageStatus)>,
} }
impl PointerInternal { impl PointerInternal {
@ -60,7 +60,7 @@ impl PointerInternal {
// don't remove the role, we are just re-binding the same surface // don't remove the role, we are just re-binding the same surface
} }
_ => { _ => {
if surface.is_alive() { if surface.as_ref().is_alive() {
token.remove_role::<CursorImageRole>(&surface).unwrap(); token.remove_role::<CursorImageRole>(&surface).unwrap();
} }
} }
@ -82,11 +82,11 @@ impl PointerInternal {
fn with_focused_pointers<F>(&self, mut f: F) fn with_focused_pointers<F>(&self, mut f: F)
where where
F: FnMut(&Resource<WlPointer>, &Resource<WlSurface>), F: FnMut(&WlPointer, &WlSurface),
{ {
if let Some((ref focus, _)) = self.focus { if let Some((ref focus, _)) = self.focus {
for ptr in &self.known_pointers { for ptr in &self.known_pointers {
if ptr.same_client_as(focus) { if ptr.as_ref().same_client_as(focus.as_ref()) {
f(ptr, focus) f(ptr, focus)
} }
} }
@ -131,7 +131,7 @@ pub struct PointerHandle {
} }
impl PointerHandle { impl PointerHandle {
pub(crate) fn new_pointer(&self, pointer: Resource<WlPointer>) { pub(crate) fn new_pointer(&self, pointer: WlPointer) {
let mut guard = self.inner.lock().unwrap(); let mut guard = self.inner.lock().unwrap();
guard.known_pointers.push(pointer); guard.known_pointers.push(pointer);
} }
@ -180,7 +180,7 @@ impl PointerHandle {
pub fn motion( pub fn motion(
&self, &self,
location: (f64, f64), location: (f64, f64),
focus: Option<(Resource<WlSurface>, (f64, f64))>, focus: Option<(WlSurface, (f64, f64))>,
serial: u32, serial: u32,
time: u32, time: u32,
) { ) {
@ -204,6 +204,7 @@ impl PointerHandle {
ButtonState::Released => { ButtonState::Released => {
inner.pressed_buttons.retain(|b| *b != button); inner.pressed_buttons.retain(|b| *b != button);
} }
_ => unreachable!(),
} }
inner.with_grab(|mut handle, grab| { inner.with_grab(|mut handle, grab| {
grab.button(&mut handle, button, state, serial, time); grab.button(&mut handle, button, state, serial, time);
@ -235,13 +236,13 @@ impl PointerHandle {
/// When your grab ends (either as you requested it or if it was forcefully cancelled by the server), /// When your grab ends (either as you requested it or if it was forcefully cancelled by the server),
/// the struct implementing this trait will be dropped. As such you should put clean-up logic in the destructor, /// the struct implementing this trait will be dropped. As such you should put clean-up logic in the destructor,
/// rather than trying to guess when the grab will end. /// rather than trying to guess when the grab will end.
pub trait PointerGrab: Send + Sync { pub trait PointerGrab {
/// A motion was reported /// A motion was reported
fn motion( fn motion(
&mut self, &mut self,
handle: &mut PointerInnerHandle<'_>, handle: &mut PointerInnerHandle<'_>,
location: (f64, f64), location: (f64, f64),
focus: Option<(Resource<WlSurface>, (f64, f64))>, focus: Option<(WlSurface, (f64, f64))>,
serial: u32, serial: u32,
time: u32, time: u32,
); );
@ -284,7 +285,7 @@ impl<'a> PointerInnerHandle<'a> {
} }
/// Access the current focus of this pointer /// Access the current focus of this pointer
pub fn current_focus(&self) -> Option<&(Resource<WlSurface>, (f64, f64))> { pub fn current_focus(&self) -> Option<&(WlSurface, (f64, f64))> {
self.inner.focus.as_ref() self.inner.focus.as_ref()
} }
@ -315,7 +316,7 @@ impl<'a> PointerInnerHandle<'a> {
pub fn motion( pub fn motion(
&mut self, &mut self,
(x, y): (f64, f64), (x, y): (f64, f64),
focus: Option<(Resource<WlSurface>, (f64, f64))>, focus: Option<(WlSurface, (f64, f64))>,
serial: u32, serial: u32,
time: u32, time: u32,
) { ) {
@ -324,19 +325,16 @@ impl<'a> PointerInnerHandle<'a> {
self.inner.location = (x, y); self.inner.location = (x, y);
if let Some((ref current_focus, _)) = self.inner.focus { if let Some((ref current_focus, _)) = self.inner.focus {
if let Some((ref surface, _)) = focus { if let Some((ref surface, _)) = focus {
if current_focus.equals(surface) { if current_focus.as_ref().equals(surface.as_ref()) {
leave = false; leave = false;
} }
} }
} }
if leave { if leave {
self.inner.with_focused_pointers(|pointer, surface| { self.inner.with_focused_pointers(|pointer, surface| {
pointer.send(Event::Leave { pointer.leave(serial, &surface);
serial, if pointer.as_ref().version() >= 5 {
surface: surface.clone(), pointer.frame();
});
if pointer.version() >= 5 {
pointer.send(Event::Frame);
} }
}); });
self.inner.focus = None; self.inner.focus = None;
@ -351,26 +349,17 @@ impl<'a> PointerInnerHandle<'a> {
self.inner.focus = Some((surface.clone(), (sx, sy))); self.inner.focus = Some((surface.clone(), (sx, sy)));
if entered { if entered {
self.inner.with_focused_pointers(|pointer, surface| { self.inner.with_focused_pointers(|pointer, surface| {
pointer.send(Event::Enter { pointer.enter(serial, &surface, x - sx, y - sy);
serial, if pointer.as_ref().version() >= 5 {
surface: surface.clone(), pointer.frame();
surface_x: x - sx,
surface_y: y - sy,
});
if pointer.version() >= 5 {
pointer.send(Event::Frame);
} }
}) })
} else { } else {
// we were on top of a surface and remained on it // we were on top of a surface and remained on it
self.inner.with_focused_pointers(|pointer, _| { self.inner.with_focused_pointers(|pointer, _| {
pointer.send(Event::Motion { pointer.motion(time, x - sx, y - sy);
time, if pointer.as_ref().version() >= 5 {
surface_x: x - sx, pointer.frame();
surface_y: y - sy,
});
if pointer.version() >= 5 {
pointer.send(Event::Frame);
} }
}) })
} }
@ -383,14 +372,9 @@ impl<'a> PointerInnerHandle<'a> {
/// objects matching with the currently focused surface. /// objects matching with the currently focused surface.
pub fn button(&self, button: u32, state: ButtonState, serial: u32, time: u32) { pub fn button(&self, button: u32, state: ButtonState, serial: u32, time: u32) {
self.inner.with_focused_pointers(|pointer, _| { self.inner.with_focused_pointers(|pointer, _| {
pointer.send(Event::Button { pointer.button(serial, time, button, state);
serial, if pointer.as_ref().version() >= 5 {
time, pointer.frame();
button,
state,
});
if pointer.version() >= 5 {
pointer.send(Event::Frame);
} }
}) })
} }
@ -403,52 +387,32 @@ impl<'a> PointerInnerHandle<'a> {
self.inner.with_focused_pointers(|pointer, _| { self.inner.with_focused_pointers(|pointer, _| {
// axis // axis
if details.axis.0 != 0.0 { if details.axis.0 != 0.0 {
pointer.send(Event::Axis { pointer.axis(details.time, Axis::HorizontalScroll, details.axis.0);
time: details.time,
axis: Axis::HorizontalScroll,
value: details.axis.0,
});
} }
if details.axis.1 != 0.0 { if details.axis.1 != 0.0 {
pointer.send(Event::Axis { pointer.axis(details.time, Axis::VerticalScroll, details.axis.1);
time: details.time,
axis: Axis::VerticalScroll,
value: details.axis.1,
});
} }
if pointer.version() >= 5 { if pointer.as_ref().version() >= 5 {
// axis source // axis source
if let Some(source) = details.source { if let Some(source) = details.source {
pointer.send(Event::AxisSource { axis_source: source }); pointer.axis_source(source);
} }
// axis discrete // axis discrete
if details.discrete.0 != 0 { if details.discrete.0 != 0 {
pointer.send(Event::AxisDiscrete { pointer.axis_discrete(Axis::HorizontalScroll, details.discrete.0);
axis: Axis::HorizontalScroll,
discrete: details.discrete.0,
});
} }
if details.discrete.1 != 0 { if details.discrete.1 != 0 {
pointer.send(Event::AxisDiscrete { pointer.axis_discrete(Axis::VerticalScroll, details.discrete.1);
axis: Axis::VerticalScroll,
discrete: details.discrete.1,
});
} }
// stop // stop
if details.stop.0 { if details.stop.0 {
pointer.send(Event::AxisStop { pointer.axis_stop(details.time, Axis::HorizontalScroll);
time: details.time,
axis: Axis::HorizontalScroll,
});
} }
if details.stop.1 { if details.stop.1 {
pointer.send(Event::AxisStop { pointer.axis_stop(details.time, Axis::VerticalScroll);
time: details.time,
axis: Axis::VerticalScroll,
});
} }
// frame // frame
pointer.send(Event::Frame); pointer.frame();
} }
}); });
} }
@ -511,6 +475,7 @@ impl AxisFrame {
Axis::VerticalScroll => { Axis::VerticalScroll => {
self.discrete.1 = steps; self.discrete.1 = steps;
} }
_ => unreachable!(),
}; };
self self
} }
@ -525,6 +490,7 @@ impl AxisFrame {
Axis::VerticalScroll => { Axis::VerticalScroll => {
self.axis.1 = value; self.axis.1 = value;
} }
_ => unreachable!(),
}; };
self self
} }
@ -541,6 +507,7 @@ impl AxisFrame {
Axis::VerticalScroll => { Axis::VerticalScroll => {
self.stop.1 = true; self.stop.1 = true;
} }
_ => unreachable!(),
}; };
self self
} }
@ -561,24 +528,24 @@ pub(crate) fn implement_pointer<U, R>(
new_pointer: NewResource<WlPointer>, new_pointer: NewResource<WlPointer>,
handle: Option<&PointerHandle>, handle: Option<&PointerHandle>,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
) -> Resource<WlPointer> ) -> WlPointer
where where
R: Role<CursorImageRole> + 'static, R: Role<CursorImageRole> + 'static,
U: 'static, U: 'static,
{ {
let inner = handle.map(|h| h.inner.clone()); let inner = handle.map(|h| h.inner.clone());
let destructor = match inner.clone() { let destructor = match inner.clone() {
Some(inner) => Some(move |pointer: Resource<_>| { Some(inner) => Some(move |pointer: WlPointer| {
inner inner
.lock() .lock()
.unwrap() .unwrap()
.known_pointers .known_pointers
.retain(|p| !p.equals(&pointer)) .retain(|p| !p.as_ref().equals(&pointer.as_ref()))
}), }),
None => None, None => None,
}; };
new_pointer.implement( new_pointer.implement_closure(
move |request, pointer| { move |request, pointer: WlPointer| {
match request { match request {
Request::SetCursor { Request::SetCursor {
serial: _, serial: _,
@ -596,7 +563,7 @@ where
.. ..
} = *guard; } = *guard;
if let Some((ref focus, _)) = *focus { if let Some((ref focus, _)) = *focus {
if focus.same_client_as(&pointer) { if focus.as_ref().same_client_as(&pointer.as_ref()) {
match surface { match surface {
Some(surface) => { Some(surface) => {
let role_data = CursorImageRole { let role_data = CursorImageRole {
@ -608,7 +575,7 @@ where
if token.with_role_data(&surface, |data| *data = role_data).is_err() if token.with_role_data(&surface, |data| *data = role_data).is_err()
&& token.give_role_with(&surface, role_data).is_err() && token.give_role_with(&surface, role_data).is_err()
{ {
pointer.post_error( pointer.as_ref().post_error(
wl_pointer::Error::Role as u32, wl_pointer::Error::Role as u32,
"Given wl_surface has another role.".into(), "Given wl_surface has another role.".into(),
); );
@ -627,6 +594,7 @@ where
Request::Release => { Request::Release => {
// Our destructors already handle it // Our destructors already handle it
} }
_ => unreachable!(),
} }
}, },
destructor, destructor,
@ -646,7 +614,7 @@ impl PointerGrab for DefaultGrab {
&mut self, &mut self,
handle: &mut PointerInnerHandle<'_>, handle: &mut PointerInnerHandle<'_>,
location: (f64, f64), location: (f64, f64),
focus: Option<(Resource<WlSurface>, (f64, f64))>, focus: Option<(WlSurface, (f64, f64))>,
serial: u32, serial: u32,
time: u32, time: u32,
) { ) {
@ -681,8 +649,8 @@ impl PointerGrab for DefaultGrab {
// In case the user maintains several simultaneous clicks, release // In case the user maintains several simultaneous clicks, release
// the grab once all are released. // the grab once all are released.
struct ClickGrab { struct ClickGrab {
current_focus: Option<(Resource<WlSurface>, (f64, f64))>, current_focus: Option<(WlSurface, (f64, f64))>,
pending_focus: Option<(Resource<WlSurface>, (f64, f64))>, pending_focus: Option<(WlSurface, (f64, f64))>,
} }
impl PointerGrab for ClickGrab { impl PointerGrab for ClickGrab {
@ -690,7 +658,7 @@ impl PointerGrab for ClickGrab {
&mut self, &mut self,
handle: &mut PointerInnerHandle<'_>, handle: &mut PointerInnerHandle<'_>,
location: (f64, f64), location: (f64, f64),
focus: Option<(Resource<WlSurface>, (f64, f64))>, focus: Option<(WlSurface, (f64, f64))>,
serial: u32, serial: u32,
time: u32, time: u32,
) { ) {

View File

@ -98,8 +98,8 @@ pub struct ShellSurfaceRole<D: 'static> {
/// A handle to a shell surface /// A handle to a shell surface
pub struct ShellSurface<U, R, D> { pub struct ShellSurface<U, R, D> {
wl_surface: Resource<wl_surface::WlSurface>, wl_surface: wl_surface::WlSurface,
shell_surface: Resource<wl_shell_surface::WlShellSurface>, shell_surface: wl_shell_surface::WlShellSurface,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
_d: ::std::marker::PhantomData<D>, _d: ::std::marker::PhantomData<D>,
} }
@ -112,18 +112,18 @@ where
{ {
/// Is the shell surface referred by this handle still alive? /// Is the shell surface referred by this handle still alive?
pub fn alive(&self) -> bool { pub fn alive(&self) -> bool {
self.shell_surface.is_alive() && self.wl_surface.is_alive() self.shell_surface.as_ref().is_alive() && self.wl_surface.as_ref().is_alive()
} }
/// Do this handle and the other one actually refer to the same shell surface? /// Do this handle and the other one actually refer to the same shell surface?
pub fn equals(&self, other: &Self) -> bool { pub fn equals(&self, other: &Self) -> bool {
self.shell_surface.equals(&other.shell_surface) self.shell_surface.as_ref().equals(&other.shell_surface.as_ref())
} }
/// Access the underlying `wl_surface` of this toplevel surface /// Access the underlying `wl_surface` of this toplevel surface
/// ///
/// Returns `None` if the toplevel surface actually no longer exists. /// Returns `None` if the toplevel surface actually no longer exists.
pub fn get_surface(&self) -> Option<&Resource<wl_surface::WlSurface>> { pub fn get_surface(&self) -> Option<&wl_surface::WlSurface> {
if self.alive() { if self.alive() {
Some(&self.wl_surface) Some(&self.wl_surface)
} else { } else {
@ -153,7 +153,7 @@ where
} }
}); });
if let Ok(true) = ret { if let Ok(true) = ret {
self.shell_surface.send(wl_shell_surface::Event::Ping { serial }); self.shell_surface.ping(serial);
Ok(()) Ok(())
} else { } else {
Err(()) Err(())
@ -162,16 +162,12 @@ where
/// Send a configure event to this toplevel surface to suggest it a new configuration /// Send a configure event to this toplevel surface to suggest it a new configuration
pub fn send_configure(&self, size: (u32, u32), edges: wl_shell_surface::Resize) { pub fn send_configure(&self, size: (u32, u32), edges: wl_shell_surface::Resize) {
self.shell_surface.send(wl_shell_surface::Event::Configure { self.shell_surface.configure(edges, size.0 as i32, size.1 as i32)
edges,
width: size.0 as i32,
height: size.1 as i32,
})
} }
/// Signal a popup surface that it has lost focus /// Signal a popup surface that it has lost focus
pub fn send_popup_done(&self) { pub fn send_popup_done(&self) {
self.shell_surface.send(wl_shell_surface::Event::PopupDone) self.shell_surface.popup_done()
} }
/// Access the user data you associated to this surface /// Access the user data you associated to this surface
@ -195,7 +191,7 @@ pub enum ShellSurfaceKind {
/// and as such should only be visible in their parent window is, and on top of it. /// and as such should only be visible in their parent window is, and on top of it.
Transient { Transient {
/// The surface considered as parent /// The surface considered as parent
parent: Resource<wl_surface::WlSurface>, parent: wl_surface::WlSurface,
/// Location relative to the parent /// Location relative to the parent
location: (i32, i32), location: (i32, i32),
/// Wether this window should be marked as inactive /// Wether this window should be marked as inactive
@ -208,7 +204,7 @@ pub enum ShellSurfaceKind {
/// Framerate (relevant only for driver fullscreen) /// Framerate (relevant only for driver fullscreen)
framerate: u32, framerate: u32,
/// Requested output if any /// Requested output if any
output: Option<Resource<wl_output::WlOutput>>, output: Option<wl_output::WlOutput>,
}, },
/// A popup surface /// A popup surface
/// ///
@ -216,7 +212,7 @@ pub enum ShellSurfaceKind {
/// contexts. /// contexts.
Popup { Popup {
/// The parent surface of this popup /// The parent surface of this popup
parent: Resource<wl_surface::WlSurface>, parent: wl_surface::WlSurface,
/// The serial of the input event triggering the creation of this /// The serial of the input event triggering the creation of this
/// popup /// popup
serial: u32, serial: u32,
@ -226,7 +222,7 @@ pub enum ShellSurfaceKind {
location: (i32, i32), location: (i32, i32),
/// Seat associated this the input that triggered the creation of the /// Seat associated this the input that triggered the creation of the
/// popup. Used to define when the "popup done" event is sent. /// popup. Used to define when the "popup done" event is sent.
seat: Resource<wl_seat::WlSeat>, seat: wl_seat::WlSeat,
}, },
/// A maximized surface /// A maximized surface
/// ///
@ -234,7 +230,7 @@ pub enum ShellSurfaceKind {
/// while keeping any relevant desktop-environment interface visible. /// while keeping any relevant desktop-environment interface visible.
Maximized { Maximized {
/// Requested output for maximization /// Requested output for maximization
output: Option<Resource<wl_output::WlOutput>>, output: Option<wl_output::WlOutput>,
}, },
} }
@ -264,7 +260,7 @@ pub enum ShellRequest<U, R, D> {
/// Serial of the implicit grab that initiated the move /// Serial of the implicit grab that initiated the move
serial: u32, serial: u32,
/// Seat associated with the move /// Seat associated with the move
seat: Resource<wl_seat::WlSeat>, seat: wl_seat::WlSeat,
}, },
/// Start of an interactive resize /// Start of an interactive resize
/// ///
@ -275,7 +271,7 @@ pub enum ShellRequest<U, R, D> {
/// Serial of the implicit grab that initiated the resize /// Serial of the implicit grab that initiated the resize
serial: u32, serial: u32,
/// Seat associated with the resize /// Seat associated with the resize
seat: Resource<wl_seat::WlSeat>, seat: wl_seat::WlSeat,
/// Direction of the resize /// Direction of the resize
edges: wl_shell_surface::Resize, edges: wl_shell_surface::Resize,
}, },
@ -331,21 +327,13 @@ where
let implementation = Rc::new(RefCell::new(implementation)); let implementation = Rc::new(RefCell::new(implementation));
let dtoken = display.get_token();
let state = Arc::new(Mutex::new(ShellState { let state = Arc::new(Mutex::new(ShellState {
known_surfaces: Vec::new(), known_surfaces: Vec::new(),
})); }));
let state2 = state.clone(); let state2 = state.clone();
let global = display.create_global(1, move |shell, _version| { let global = display.create_global(1, move |shell, _version| {
self::wl_handlers::implement_shell( self::wl_handlers::implement_shell(shell, ctoken, implementation.clone(), state2.clone());
shell,
dtoken.clone(),
ctoken,
implementation.clone(),
state2.clone(),
);
}); });
(state, global) (state, global)

View File

@ -6,7 +6,7 @@ use std::{
use wayland_server::{ use wayland_server::{
protocol::{wl_shell, wl_shell_surface, wl_surface}, protocol::{wl_shell, wl_shell_surface, wl_surface},
DisplayToken, NewResource, Resource, NewResource, Resource,
}; };
use crate::wayland::compositor::{roles::Role, CompositorToken}; use crate::wayland::compositor::{roles::Role, CompositorToken};
@ -15,7 +15,6 @@ use super::{ShellRequest, ShellState, ShellSurface, ShellSurfaceKind, ShellSurfa
pub(crate) fn implement_shell<U, R, D, Impl>( pub(crate) fn implement_shell<U, R, D, Impl>(
shell: NewResource<wl_shell::WlShell>, shell: NewResource<wl_shell::WlShell>,
dtoken: DisplayToken,
ctoken: CompositorToken<U, R>, ctoken: CompositorToken<U, R>,
implementation: Rc<RefCell<Impl>>, implementation: Rc<RefCell<Impl>>,
state: Arc<Mutex<ShellState<U, R, D>>>, state: Arc<Mutex<ShellState<U, R, D>>>,
@ -25,10 +24,12 @@ pub(crate) fn implement_shell<U, R, D, Impl>(
R: Role<ShellSurfaceRole<D>> + 'static, R: Role<ShellSurfaceRole<D>> + 'static,
Impl: FnMut(ShellRequest<U, R, D>) + 'static, Impl: FnMut(ShellRequest<U, R, D>) + 'static,
{ {
let dtoken2 = dtoken.clone(); shell.implement_closure(
shell.implement_nonsend( move |req, shell| {
move |req, shell: Resource<_>| { let (id, surface) = match req {
let wl_shell::Request::GetShellSurface { id, surface } = req; wl_shell::Request::GetShellSurface { id, surface } => (id, surface),
_ => unreachable!(),
};
let role_data = ShellSurfaceRole { let role_data = ShellSurfaceRole {
title: "".into(), title: "".into(),
class: "".into(), class: "".into(),
@ -36,17 +37,13 @@ pub(crate) fn implement_shell<U, R, D, Impl>(
user_data: Default::default(), user_data: Default::default(),
}; };
if ctoken.give_role_with(&surface, role_data).is_err() { if ctoken.give_role_with(&surface, role_data).is_err() {
shell.post_error(wl_shell::Error::Role as u32, "Surface already has a role.".into()); shell
.as_ref()
.post_error(wl_shell::Error::Role as u32, "Surface already has a role.".into());
return; return;
} }
let shell_surface = implement_shell_surface( let shell_surface =
id, implement_shell_surface(id, surface, implementation.clone(), ctoken, state.clone());
surface,
implementation.clone(),
dtoken.clone(),
ctoken,
state.clone(),
);
state state
.lock() .lock()
.unwrap() .unwrap()
@ -59,12 +56,11 @@ pub(crate) fn implement_shell<U, R, D, Impl>(
}, },
None::<fn(_)>, None::<fn(_)>,
(), (),
&dtoken2,
); );
} }
fn make_handle<U, R, SD>( fn make_handle<U, R, SD>(
shell_surface: &Resource<wl_shell_surface::WlShellSurface>, shell_surface: &wl_shell_surface::WlShellSurface,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
) -> ShellSurface<U, R, SD> ) -> ShellSurface<U, R, SD>
where where
@ -73,6 +69,7 @@ where
SD: 'static, SD: 'static,
{ {
let data = shell_surface let data = shell_surface
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>() .user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap(); .unwrap();
ShellSurface { ShellSurface {
@ -84,18 +81,17 @@ where
} }
pub(crate) struct ShellSurfaceUserData<U, R, SD> { pub(crate) struct ShellSurfaceUserData<U, R, SD> {
surface: Resource<wl_surface::WlSurface>, surface: wl_surface::WlSurface,
state: Arc<Mutex<ShellState<U, R, SD>>>, state: Arc<Mutex<ShellState<U, R, SD>>>,
} }
fn implement_shell_surface<U, R, Impl, SD>( fn implement_shell_surface<U, R, Impl, SD>(
shell_surface: NewResource<wl_shell_surface::WlShellSurface>, shell_surface: NewResource<wl_shell_surface::WlShellSurface>,
surface: Resource<wl_surface::WlSurface>, surface: wl_surface::WlSurface,
implementation: Rc<RefCell<Impl>>, implementation: Rc<RefCell<Impl>>,
dtoken: DisplayToken,
ctoken: CompositorToken<U, R>, ctoken: CompositorToken<U, R>,
state: Arc<Mutex<ShellState<U, R, SD>>>, state: Arc<Mutex<ShellState<U, R, SD>>>,
) -> Resource<wl_shell_surface::WlShellSurface> ) -> wl_shell_surface::WlShellSurface
where where
U: 'static, U: 'static,
SD: 'static, SD: 'static,
@ -103,9 +99,10 @@ where
Impl: FnMut(ShellRequest<U, R, SD>) + 'static, Impl: FnMut(ShellRequest<U, R, SD>) + 'static,
{ {
use self::wl_shell_surface::Request; use self::wl_shell_surface::Request;
shell_surface.implement_nonsend( shell_surface.implement_closure(
move |req, shell_surface: Resource<_>| { move |req, shell_surface| {
let data = shell_surface let data = shell_surface
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>() .user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap(); .unwrap();
let mut user_impl = implementation.borrow_mut(); let mut user_impl = implementation.borrow_mut();
@ -193,15 +190,16 @@ where
.with_role_data(&data.surface, |data| data.class = class_) .with_role_data(&data.surface, |data| data.class = class_)
.expect("wl_shell_surface exists but surface has not shell_surface role?!"); .expect("wl_shell_surface exists but surface has not shell_surface role?!");
} }
_ => unreachable!(),
} }
}, },
Some(|shell_surface: Resource<_>| { Some(|shell_surface: wl_shell_surface::WlShellSurface| {
let data = shell_surface let data = shell_surface
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>() .user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap(); .unwrap();
data.state.lock().unwrap().cleanup_surfaces(); data.state.lock().unwrap().cleanup_surfaces();
}), }),
ShellSurfaceUserData { surface, state }, ShellSurfaceUserData { surface, state },
&dtoken,
) )
} }

View File

@ -103,7 +103,7 @@ use wayland_protocols::{
}; };
use wayland_server::{ use wayland_server::{
protocol::{wl_output, wl_seat, wl_surface}, protocol::{wl_output, wl_seat, wl_surface},
Display, DisplayToken, Global, Resource, Display, Global, Resource,
}; };
// handlers for the xdg_shell protocol // handlers for the xdg_shell protocol
@ -204,7 +204,7 @@ pub struct ToplevelState {
/// ///
/// If this surface has a parent, it should be hidden /// If this surface has a parent, it should be hidden
/// or displayed, brought up at the same time as it. /// or displayed, brought up at the same time as it.
pub parent: Option<Resource<wl_surface::WlSurface>>, pub parent: Option<wl_surface::WlSurface>,
/// Title of this shell surface /// Title of this shell surface
pub title: String, pub title: String,
/// App id for this shell surface /// App id for this shell surface
@ -238,7 +238,7 @@ impl Clone for ToplevelState {
/// The pending state of a popup surface /// The pending state of a popup surface
pub struct PopupState { pub struct PopupState {
/// Parent of this popup surface /// Parent of this popup surface
pub parent: Option<Resource<wl_surface::WlSurface>>, pub parent: Option<wl_surface::WlSurface>,
/// The positioner specifying how this tooltip should /// The positioner specifying how this tooltip should
/// be placed relative to its parent. /// be placed relative to its parent.
pub positioner: PositionerState, pub positioner: PositionerState,
@ -262,7 +262,6 @@ impl Default for XdgSurfacePendingState {
pub(crate) struct ShellData<U, R, SD> { pub(crate) struct ShellData<U, R, SD> {
log: ::slog::Logger, log: ::slog::Logger,
compositor_token: CompositorToken<U, R>, compositor_token: CompositorToken<U, R>,
display_token: DisplayToken,
user_impl: Rc<RefCell<dyn FnMut(XdgRequest<U, R, SD>)>>, user_impl: Rc<RefCell<dyn FnMut(XdgRequest<U, R, SD>)>>,
shell_state: Arc<Mutex<ShellState<U, R, SD>>>, shell_state: Arc<Mutex<ShellState<U, R, SD>>>,
} }
@ -272,7 +271,6 @@ impl<U, R, SD> Clone for ShellData<U, R, SD> {
ShellData { ShellData {
log: self.log.clone(), log: self.log.clone(),
compositor_token: self.compositor_token, compositor_token: self.compositor_token,
display_token: self.display_token.clone(),
user_impl: self.user_impl.clone(), user_impl: self.user_impl.clone(),
shell_state: self.shell_state.clone(), shell_state: self.shell_state.clone(),
} }
@ -305,7 +303,6 @@ where
let shell_data = ShellData { let shell_data = ShellData {
log: log.new(o!("smithay_module" => "xdg_shell_handler")), log: log.new(o!("smithay_module" => "xdg_shell_handler")),
display_token: display.get_token(),
compositor_token: ctoken, compositor_token: ctoken,
user_impl: Rc::new(RefCell::new(implementation)), user_impl: Rc::new(RefCell::new(implementation)),
shell_state: shell_state.clone(), shell_state: shell_state.clone(),
@ -355,8 +352,8 @@ where
*/ */
enum ShellClientKind { enum ShellClientKind {
Xdg(Resource<xdg_wm_base::XdgWmBase>), Xdg(xdg_wm_base::XdgWmBase),
ZxdgV6(Resource<zxdg_shell_v6::ZxdgShellV6>), ZxdgV6(zxdg_shell_v6::ZxdgShellV6),
} }
pub(crate) struct ShellClientData<SD> { pub(crate) struct ShellClientData<SD> {
@ -396,8 +393,8 @@ where
/// Is the shell client represented by this handle still connected? /// Is the shell client represented by this handle still connected?
pub fn alive(&self) -> bool { pub fn alive(&self) -> bool {
match self.kind { match self.kind {
ShellClientKind::Xdg(ref s) => s.is_alive(), ShellClientKind::Xdg(ref s) => s.as_ref().is_alive(),
ShellClientKind::ZxdgV6(ref s) => s.is_alive(), ShellClientKind::ZxdgV6(ref s) => s.as_ref().is_alive(),
} }
} }
@ -405,8 +402,10 @@ where
/// same shell client /// same shell client
pub fn equals(&self, other: &Self) -> bool { pub fn equals(&self, other: &Self) -> bool {
match (&self.kind, &other.kind) { match (&self.kind, &other.kind) {
(&ShellClientKind::Xdg(ref s1), &ShellClientKind::Xdg(ref s2)) => s1.equals(s2), (&ShellClientKind::Xdg(ref s1), &ShellClientKind::Xdg(ref s2)) => s1.as_ref().equals(s2.as_ref()),
(&ShellClientKind::ZxdgV6(ref s1), &ShellClientKind::ZxdgV6(ref s2)) => s1.equals(s2), (&ShellClientKind::ZxdgV6(ref s1), &ShellClientKind::ZxdgV6(ref s2)) => {
s1.as_ref().equals(s2.as_ref())
}
_ => false, _ => false,
} }
} }
@ -427,6 +426,7 @@ where
match self.kind { match self.kind {
ShellClientKind::Xdg(ref shell) => { ShellClientKind::Xdg(ref shell) => {
let user_data = shell let user_data = shell
.as_ref()
.user_data::<self::xdg_handlers::ShellUserData<U, R, SD>>() .user_data::<self::xdg_handlers::ShellUserData<U, R, SD>>()
.unwrap(); .unwrap();
let mut guard = user_data.client_data.lock().unwrap(); let mut guard = user_data.client_data.lock().unwrap();
@ -434,10 +434,11 @@ where
return Err(()); return Err(());
} }
guard.pending_ping = serial; guard.pending_ping = serial;
shell.send(xdg_wm_base::Event::Ping { serial }); shell.ping(serial);
} }
ShellClientKind::ZxdgV6(ref shell) => { ShellClientKind::ZxdgV6(ref shell) => {
let user_data = shell let user_data = shell
.as_ref()
.user_data::<self::zxdgv6_handlers::ShellUserData<U, R, SD>>() .user_data::<self::zxdgv6_handlers::ShellUserData<U, R, SD>>()
.unwrap(); .unwrap();
let mut guard = user_data.client_data.lock().unwrap(); let mut guard = user_data.client_data.lock().unwrap();
@ -445,7 +446,7 @@ where
return Err(()); return Err(());
} }
guard.pending_ping = serial; guard.pending_ping = serial;
shell.send(zxdg_shell_v6::Event::Ping { serial }); shell.ping(serial);
} }
} }
Ok(()) Ok(())
@ -462,6 +463,7 @@ where
match self.kind { match self.kind {
ShellClientKind::Xdg(ref shell) => { ShellClientKind::Xdg(ref shell) => {
let data = shell let data = shell
.as_ref()
.user_data::<self::xdg_handlers::ShellUserData<U, R, SD>>() .user_data::<self::xdg_handlers::ShellUserData<U, R, SD>>()
.unwrap(); .unwrap();
let mut guard = data.client_data.lock().unwrap(); let mut guard = data.client_data.lock().unwrap();
@ -469,6 +471,7 @@ where
} }
ShellClientKind::ZxdgV6(ref shell) => { ShellClientKind::ZxdgV6(ref shell) => {
let data = shell let data = shell
.as_ref()
.user_data::<self::zxdgv6_handlers::ShellUserData<U, R, SD>>() .user_data::<self::zxdgv6_handlers::ShellUserData<U, R, SD>>()
.unwrap(); .unwrap();
let mut guard = data.client_data.lock().unwrap(); let mut guard = data.client_data.lock().unwrap();
@ -479,13 +482,13 @@ where
} }
pub(crate) enum ToplevelKind { pub(crate) enum ToplevelKind {
Xdg(Resource<xdg_toplevel::XdgToplevel>), Xdg(xdg_toplevel::XdgToplevel),
ZxdgV6(Resource<zxdg_toplevel_v6::ZxdgToplevelV6>), ZxdgV6(zxdg_toplevel_v6::ZxdgToplevelV6),
} }
/// A handle to a toplevel surface /// A handle to a toplevel surface
pub struct ToplevelSurface<U, R, SD> { pub struct ToplevelSurface<U, R, SD> {
wl_surface: Resource<wl_surface::WlSurface>, wl_surface: wl_surface::WlSurface,
shell_surface: ToplevelKind, shell_surface: ToplevelKind,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
_shell_data: ::std::marker::PhantomData<SD>, _shell_data: ::std::marker::PhantomData<SD>,
@ -500,15 +503,15 @@ where
/// Is the toplevel surface referred by this handle still alive? /// Is the toplevel surface referred by this handle still alive?
pub fn alive(&self) -> bool { pub fn alive(&self) -> bool {
let shell_alive = match self.shell_surface { let shell_alive = match self.shell_surface {
ToplevelKind::Xdg(ref s) => s.is_alive(), ToplevelKind::Xdg(ref s) => s.as_ref().is_alive(),
ToplevelKind::ZxdgV6(ref s) => s.is_alive(), ToplevelKind::ZxdgV6(ref s) => s.as_ref().is_alive(),
}; };
shell_alive && self.wl_surface.is_alive() shell_alive && self.wl_surface.as_ref().is_alive()
} }
/// Do this handle and the other one actually refer to the same toplevel surface? /// Do this handle and the other one actually refer to the same toplevel surface?
pub fn equals(&self, other: &Self) -> bool { pub fn equals(&self, other: &Self) -> bool {
self.alive() && other.alive() && self.wl_surface.equals(&other.wl_surface) self.alive() && other.alive() && self.wl_surface.as_ref().equals(&other.wl_surface.as_ref())
} }
/// Retrieve the shell client owning this toplevel surface /// Retrieve the shell client owning this toplevel surface
@ -522,12 +525,14 @@ where
let shell = match self.shell_surface { let shell = match self.shell_surface {
ToplevelKind::Xdg(ref s) => { ToplevelKind::Xdg(ref s) => {
let data = s let data = s
.as_ref()
.user_data::<self::xdg_handlers::ShellSurfaceUserData<U, R, SD>>() .user_data::<self::xdg_handlers::ShellSurfaceUserData<U, R, SD>>()
.unwrap(); .unwrap();
ShellClientKind::Xdg(data.wm_base.clone()) ShellClientKind::Xdg(data.wm_base.clone())
} }
ToplevelKind::ZxdgV6(ref s) => { ToplevelKind::ZxdgV6(ref s) => {
let data = s let data = s
.as_ref()
.user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<U, R, SD>>() .user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<U, R, SD>>()
.unwrap(); .unwrap();
ShellClientKind::ZxdgV6(data.shell.clone()) ShellClientKind::ZxdgV6(data.shell.clone())
@ -574,18 +579,20 @@ where
match self.shell_surface { match self.shell_surface {
ToplevelKind::Xdg(ref s) => { ToplevelKind::Xdg(ref s) => {
let data = s let data = s
.as_ref()
.user_data::<self::xdg_handlers::ShellSurfaceUserData<U, R, SD>>() .user_data::<self::xdg_handlers::ShellSurfaceUserData<U, R, SD>>()
.unwrap(); .unwrap();
data.xdg_surface.post_error( data.xdg_surface.as_ref().post_error(
xdg_surface::Error::NotConstructed as u32, xdg_surface::Error::NotConstructed as u32,
"Surface has not been configured yet.".into(), "Surface has not been configured yet.".into(),
); );
} }
ToplevelKind::ZxdgV6(ref s) => { ToplevelKind::ZxdgV6(ref s) => {
let data = s let data = s
.as_ref()
.user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<U, R, SD>>() .user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<U, R, SD>>()
.unwrap(); .unwrap();
data.xdg_surface.post_error( data.xdg_surface.as_ref().post_error(
zxdg_surface_v6::Error::NotConstructed as u32, zxdg_surface_v6::Error::NotConstructed as u32,
"Surface has not been configured yet.".into(), "Surface has not been configured yet.".into(),
); );
@ -598,15 +605,15 @@ where
/// Send a "close" event to the client /// Send a "close" event to the client
pub fn send_close(&self) { pub fn send_close(&self) {
match self.shell_surface { match self.shell_surface {
ToplevelKind::Xdg(ref s) => s.send(xdg_toplevel::Event::Close), ToplevelKind::Xdg(ref s) => s.close(),
ToplevelKind::ZxdgV6(ref s) => s.send(zxdg_toplevel_v6::Event::Close), ToplevelKind::ZxdgV6(ref s) => s.close(),
} }
} }
/// Access the underlying `wl_surface` of this toplevel surface /// Access the underlying `wl_surface` of this toplevel surface
/// ///
/// Returns `None` if the toplevel surface actually no longer exists. /// Returns `None` if the toplevel surface actually no longer exists.
pub fn get_surface(&self) -> Option<&Resource<wl_surface::WlSurface>> { pub fn get_surface(&self) -> Option<&wl_surface::WlSurface> {
if self.alive() { if self.alive() {
Some(&self.wl_surface) Some(&self.wl_surface)
} else { } else {
@ -632,8 +639,8 @@ where
} }
pub(crate) enum PopupKind { pub(crate) enum PopupKind {
Xdg(Resource<xdg_popup::XdgPopup>), Xdg(xdg_popup::XdgPopup),
ZxdgV6(Resource<zxdg_popup_v6::ZxdgPopupV6>), ZxdgV6(zxdg_popup_v6::ZxdgPopupV6),
} }
/// A handle to a popup surface /// A handle to a popup surface
@ -641,7 +648,7 @@ pub(crate) enum PopupKind {
/// This is an unified abstraction over the popup surfaces /// This is an unified abstraction over the popup surfaces
/// of both `wl_shell` and `xdg_shell`. /// of both `wl_shell` and `xdg_shell`.
pub struct PopupSurface<U, R, SD> { pub struct PopupSurface<U, R, SD> {
wl_surface: Resource<wl_surface::WlSurface>, wl_surface: wl_surface::WlSurface,
shell_surface: PopupKind, shell_surface: PopupKind,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
_shell_data: ::std::marker::PhantomData<SD>, _shell_data: ::std::marker::PhantomData<SD>,
@ -656,15 +663,15 @@ where
/// Is the popup surface referred by this handle still alive? /// Is the popup surface referred by this handle still alive?
pub fn alive(&self) -> bool { pub fn alive(&self) -> bool {
let shell_alive = match self.shell_surface { let shell_alive = match self.shell_surface {
PopupKind::Xdg(ref p) => p.is_alive(), PopupKind::Xdg(ref p) => p.as_ref().is_alive(),
PopupKind::ZxdgV6(ref p) => p.is_alive(), PopupKind::ZxdgV6(ref p) => p.as_ref().is_alive(),
}; };
shell_alive && self.wl_surface.is_alive() shell_alive && self.wl_surface.as_ref().is_alive()
} }
/// Do this handle and the other one actually refer to the same popup surface? /// Do this handle and the other one actually refer to the same popup surface?
pub fn equals(&self, other: &Self) -> bool { pub fn equals(&self, other: &Self) -> bool {
self.alive() && other.alive() && self.wl_surface.equals(&other.wl_surface) self.alive() && other.alive() && self.wl_surface.as_ref().equals(&other.wl_surface.as_ref())
} }
/// Retrieve the shell client owning this popup surface /// Retrieve the shell client owning this popup surface
@ -678,12 +685,14 @@ where
let shell = match self.shell_surface { let shell = match self.shell_surface {
PopupKind::Xdg(ref p) => { PopupKind::Xdg(ref p) => {
let data = p let data = p
.as_ref()
.user_data::<self::xdg_handlers::ShellSurfaceUserData<U, R, SD>>() .user_data::<self::xdg_handlers::ShellSurfaceUserData<U, R, SD>>()
.unwrap(); .unwrap();
ShellClientKind::Xdg(data.wm_base.clone()) ShellClientKind::Xdg(data.wm_base.clone())
} }
PopupKind::ZxdgV6(ref p) => { PopupKind::ZxdgV6(ref p) => {
let data = p let data = p
.as_ref()
.user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<U, R, SD>>() .user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<U, R, SD>>()
.unwrap(); .unwrap();
ShellClientKind::ZxdgV6(data.shell.clone()) ShellClientKind::ZxdgV6(data.shell.clone())
@ -734,18 +743,20 @@ where
match self.shell_surface { match self.shell_surface {
PopupKind::Xdg(ref s) => { PopupKind::Xdg(ref s) => {
let data = s let data = s
.as_ref()
.user_data::<self::xdg_handlers::ShellSurfaceUserData<U, R, SD>>() .user_data::<self::xdg_handlers::ShellSurfaceUserData<U, R, SD>>()
.unwrap(); .unwrap();
data.xdg_surface.post_error( data.xdg_surface.as_ref().post_error(
xdg_surface::Error::NotConstructed as u32, xdg_surface::Error::NotConstructed as u32,
"Surface has not been configured yet.".into(), "Surface has not been configured yet.".into(),
); );
} }
PopupKind::ZxdgV6(ref s) => { PopupKind::ZxdgV6(ref s) => {
let data = s let data = s
.as_ref()
.user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<U, R, SD>>() .user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<U, R, SD>>()
.unwrap(); .unwrap();
data.xdg_surface.post_error( data.xdg_surface.as_ref().post_error(
zxdg_surface_v6::Error::NotConstructed as u32, zxdg_surface_v6::Error::NotConstructed as u32,
"Surface has not been configured yet.".into(), "Surface has not been configured yet.".into(),
); );
@ -761,15 +772,15 @@ where
/// the pointer has left the area of popup grab if there was a grab. /// the pointer has left the area of popup grab if there was a grab.
pub fn send_popup_done(&self) { pub fn send_popup_done(&self) {
match self.shell_surface { match self.shell_surface {
PopupKind::Xdg(ref p) => p.send(xdg_popup::Event::PopupDone), PopupKind::Xdg(ref p) => p.popup_done(),
PopupKind::ZxdgV6(ref p) => p.send(zxdg_popup_v6::Event::PopupDone), PopupKind::ZxdgV6(ref p) => p.popup_done(),
} }
} }
/// Access the underlying `wl_surface` of this toplevel surface /// Access the underlying `wl_surface` of this toplevel surface
/// ///
/// Returns `None` if the toplevel surface actually no longer exists. /// Returns `None` if the toplevel surface actually no longer exists.
pub fn get_surface(&self) -> Option<&Resource<wl_surface::WlSurface>> { pub fn get_surface(&self) -> Option<&wl_surface::WlSurface> {
if self.alive() { if self.alive() {
Some(&self.wl_surface) Some(&self.wl_surface)
} else { } else {
@ -867,7 +878,7 @@ pub enum XdgRequest<U, R, SD> {
/// the surface /// the surface
surface: ToplevelSurface<U, R, SD>, surface: ToplevelSurface<U, R, SD>,
/// the seat associated to this move /// the seat associated to this move
seat: Resource<wl_seat::WlSeat>, seat: wl_seat::WlSeat,
/// the grab serial /// the grab serial
serial: u32, serial: u32,
}, },
@ -876,7 +887,7 @@ pub enum XdgRequest<U, R, SD> {
/// The surface /// The surface
surface: ToplevelSurface<U, R, SD>, surface: ToplevelSurface<U, R, SD>,
/// The seat associated with this resize /// The seat associated with this resize
seat: Resource<wl_seat::WlSeat>, seat: wl_seat::WlSeat,
/// The grab serial /// The grab serial
serial: u32, serial: u32,
/// Specification of which part of the window's border is being dragged /// Specification of which part of the window's border is being dragged
@ -890,7 +901,7 @@ pub enum XdgRequest<U, R, SD> {
/// The surface /// The surface
surface: PopupSurface<U, R, SD>, surface: PopupSurface<U, R, SD>,
/// The seat to grab /// The seat to grab
seat: Resource<wl_seat::WlSeat>, seat: wl_seat::WlSeat,
/// The grab serial /// The grab serial
serial: u32, serial: u32,
}, },
@ -909,7 +920,7 @@ pub enum XdgRequest<U, R, SD> {
/// The surface /// The surface
surface: ToplevelSurface<U, R, SD>, surface: ToplevelSurface<U, R, SD>,
/// The output (if any) on which the fullscreen is requested /// The output (if any) on which the fullscreen is requested
output: Option<Resource<wl_output::WlOutput>>, output: Option<wl_output::WlOutput>,
}, },
/// A toplevel surface request to stop being fullscreen /// A toplevel surface request to stop being fullscreen
UnFullscreen { UnFullscreen {
@ -929,7 +940,7 @@ pub enum XdgRequest<U, R, SD> {
/// The surface /// The surface
surface: ToplevelSurface<U, R, SD>, surface: ToplevelSurface<U, R, SD>,
/// The seat associated with this input grab /// The seat associated with this input grab
seat: Resource<wl_seat::WlSeat>, seat: wl_seat::WlSeat,
/// the grab serial /// the grab serial
serial: u32, serial: u32,
/// location of the menu request /// location of the menu request

View File

@ -4,7 +4,7 @@ use crate::wayland::compositor::{roles::*, CompositorToken};
use wayland_protocols::xdg_shell::server::{ use wayland_protocols::xdg_shell::server::{
xdg_popup, xdg_positioner, xdg_surface, xdg_toplevel, xdg_wm_base, xdg_popup, xdg_positioner, xdg_surface, xdg_toplevel, xdg_wm_base,
}; };
use wayland_server::{protocol::wl_surface, DisplayToken, NewResource, Resource}; use wayland_server::{protocol::wl_surface, NewResource, Resource};
use crate::utils::Rectangle; use crate::utils::Rectangle;
@ -17,20 +17,19 @@ use super::{
pub(crate) fn implement_wm_base<U, R, SD>( pub(crate) fn implement_wm_base<U, R, SD>(
shell: NewResource<xdg_wm_base::XdgWmBase>, shell: NewResource<xdg_wm_base::XdgWmBase>,
shell_data: &ShellData<U, R, SD>, shell_data: &ShellData<U, R, SD>,
) -> Resource<xdg_wm_base::XdgWmBase> ) -> xdg_wm_base::XdgWmBase
where where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: Default + 'static, SD: Default + 'static,
{ {
let shell = shell.implement_nonsend( let shell = shell.implement_closure(
wm_implementation::<U, R, SD>, wm_implementation::<U, R, SD>,
None::<fn(_)>, None::<fn(_)>,
ShellUserData { ShellUserData {
shell_data: shell_data.clone(), shell_data: shell_data.clone(),
client_data: Mutex::new(make_shell_client_data::<SD>()), client_data: Mutex::new(make_shell_client_data::<SD>()),
}, },
&shell_data.display_token,
); );
let mut user_impl = shell_data.user_impl.borrow_mut(); let mut user_impl = shell_data.user_impl.borrow_mut();
(&mut *user_impl)(XdgRequest::NewClient { (&mut *user_impl)(XdgRequest::NewClient {
@ -49,7 +48,7 @@ pub(crate) struct ShellUserData<U, R, SD> {
} }
pub(crate) fn make_shell_client<U, R, SD>( pub(crate) fn make_shell_client<U, R, SD>(
resource: &Resource<xdg_wm_base::XdgWmBase>, resource: &xdg_wm_base::XdgWmBase,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
) -> ShellClient<U, R, SD> { ) -> ShellClient<U, R, SD> {
ShellClient { ShellClient {
@ -59,19 +58,19 @@ pub(crate) fn make_shell_client<U, R, SD>(
} }
} }
fn wm_implementation<U, R, SD>(request: xdg_wm_base::Request, shell: Resource<xdg_wm_base::XdgWmBase>) fn wm_implementation<U, R, SD>(request: xdg_wm_base::Request, shell: xdg_wm_base::XdgWmBase)
where where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = shell.user_data::<ShellUserData<U, R, SD>>().unwrap(); let data = shell.as_ref().user_data::<ShellUserData<U, R, SD>>().unwrap();
match request { match request {
xdg_wm_base::Request::Destroy => { xdg_wm_base::Request::Destroy => {
// all is handled by destructor // all is handled by destructor
} }
xdg_wm_base::Request::CreatePositioner { id } => { xdg_wm_base::Request::CreatePositioner { id } => {
implement_positioner(id, &data.shell_data.display_token); implement_positioner(id);
} }
xdg_wm_base::Request::GetXdgSurface { id, surface } => { xdg_wm_base::Request::GetXdgSurface { id, surface } => {
let role_data = XdgSurfaceRole { let role_data = XdgSurfaceRole {
@ -86,13 +85,13 @@ where
.give_role_with(&surface, role_data) .give_role_with(&surface, role_data)
.is_err() .is_err()
{ {
shell.post_error( shell.as_ref().post_error(
xdg_wm_base::Error::Role as u32, xdg_wm_base::Error::Role as u32,
"Surface already has a role.".into(), "Surface already has a role.".into(),
); );
return; return;
} }
id.implement_nonsend( id.implement_closure(
xdg_surface_implementation::<U, R, SD>, xdg_surface_implementation::<U, R, SD>,
Some(destroy_surface::<U, R, SD>), Some(destroy_surface::<U, R, SD>),
XdgSurfaceUserData { XdgSurfaceUserData {
@ -100,7 +99,6 @@ where
wl_surface: surface, wl_surface: surface,
wm_base: shell.clone(), wm_base: shell.clone(),
}, },
&data.shell_data.display_token,
); );
} }
xdg_wm_base::Request::Pong { serial } => { xdg_wm_base::Request::Pong { serial } => {
@ -120,6 +118,7 @@ where
}); });
} }
} }
_ => unreachable!(),
} }
} }
@ -129,11 +128,13 @@ where
fn implement_positioner( fn implement_positioner(
positioner: NewResource<xdg_positioner::XdgPositioner>, positioner: NewResource<xdg_positioner::XdgPositioner>,
token: &DisplayToken, ) -> xdg_positioner::XdgPositioner {
) -> Resource<xdg_positioner::XdgPositioner> { positioner.implement_closure(
positioner.implement_nonsend( |request, positioner| {
|request, positioner: Resource<_>| { let mutex = positioner
let mutex = positioner.user_data::<RefCell<PositionerState>>().unwrap(); .as_ref()
.user_data::<RefCell<PositionerState>>()
.unwrap();
let mut state = mutex.borrow_mut(); let mut state = mutex.borrow_mut();
match request { match request {
xdg_positioner::Request::Destroy => { xdg_positioner::Request::Destroy => {
@ -141,7 +142,7 @@ fn implement_positioner(
} }
xdg_positioner::Request::SetSize { width, height } => { xdg_positioner::Request::SetSize { width, height } => {
if width < 1 || height < 1 { if width < 1 || height < 1 {
positioner.post_error( positioner.as_ref().post_error(
xdg_positioner::Error::InvalidInput as u32, xdg_positioner::Error::InvalidInput as u32,
"Invalid size for positioner.".into(), "Invalid size for positioner.".into(),
); );
@ -151,7 +152,7 @@ fn implement_positioner(
} }
xdg_positioner::Request::SetAnchorRect { x, y, width, height } => { xdg_positioner::Request::SetAnchorRect { x, y, width, height } => {
if width < 1 || height < 1 { if width < 1 || height < 1 {
positioner.post_error( positioner.as_ref().post_error(
xdg_positioner::Error::InvalidInput as u32, xdg_positioner::Error::InvalidInput as u32,
"Invalid size for positioner's anchor rectangle.".into(), "Invalid size for positioner's anchor rectangle.".into(),
); );
@ -175,11 +176,11 @@ fn implement_positioner(
xdg_positioner::Request::SetOffset { x, y } => { xdg_positioner::Request::SetOffset { x, y } => {
state.offset = (x, y); state.offset = (x, y);
} }
_ => unreachable!(),
} }
}, },
None::<fn(_)>, None::<fn(_)>,
RefCell::new(PositionerState::new()), RefCell::new(PositionerState::new()),
token,
) )
} }
@ -189,18 +190,21 @@ fn implement_positioner(
struct XdgSurfaceUserData<U, R, SD> { struct XdgSurfaceUserData<U, R, SD> {
shell_data: ShellData<U, R, SD>, shell_data: ShellData<U, R, SD>,
wl_surface: Resource<wl_surface::WlSurface>, wl_surface: wl_surface::WlSurface,
wm_base: Resource<xdg_wm_base::XdgWmBase>, wm_base: xdg_wm_base::XdgWmBase,
} }
fn destroy_surface<U, R, SD>(surface: Resource<xdg_surface::XdgSurface>) fn destroy_surface<U, R, SD>(surface: xdg_surface::XdgSurface)
where where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = surface.user_data::<XdgSurfaceUserData<U, R, SD>>().unwrap(); let data = surface
if !data.wl_surface.is_alive() { .as_ref()
.user_data::<XdgSurfaceUserData<U, R, SD>>()
.unwrap();
if !data.wl_surface.as_ref().is_alive() {
// the wl_surface is destroyed, this means the client is not // the wl_surface is destroyed, this means the client is not
// trying to change the role but it's a cleanup (possibly a // trying to change the role but it's a cleanup (possibly a
// disconnecting client), ignore the protocol check. // disconnecting client), ignore the protocol check.
@ -212,7 +216,7 @@ where
if let XdgSurfacePendingState::None = rdata.pending_state { if let XdgSurfacePendingState::None = rdata.pending_state {
// all is good // all is good
} else { } else {
data.wm_base.post_error( data.wm_base.as_ref().post_error(
xdg_wm_base::Error::Role as u32, xdg_wm_base::Error::Role as u32,
"xdg_surface was destroyed before its role object".into(), "xdg_surface was destroyed before its role object".into(),
); );
@ -221,15 +225,16 @@ where
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
} }
fn xdg_surface_implementation<U, R, SD>( fn xdg_surface_implementation<U, R, SD>(request: xdg_surface::Request, xdg_surface: xdg_surface::XdgSurface)
request: xdg_surface::Request, where
xdg_surface: Resource<xdg_surface::XdgSurface>,
) where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = xdg_surface.user_data::<XdgSurfaceUserData<U, R, SD>>().unwrap(); let data = xdg_surface
.as_ref()
.user_data::<XdgSurfaceUserData<U, R, SD>>()
.unwrap();
match request { match request {
xdg_surface::Request::Destroy => { xdg_surface::Request::Destroy => {
// all is handled by our destructor // all is handled by our destructor
@ -247,7 +252,7 @@ fn xdg_surface_implementation<U, R, SD>(
}); });
}) })
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
let toplevel = id.implement_nonsend( let toplevel = id.implement_closure(
toplevel_implementation::<U, R, SD>, toplevel_implementation::<U, R, SD>,
Some(destroy_toplevel::<U, R, SD>), Some(destroy_toplevel::<U, R, SD>),
ShellSurfaceUserData { ShellSurfaceUserData {
@ -256,7 +261,6 @@ fn xdg_surface_implementation<U, R, SD>(
xdg_surface: xdg_surface.clone(), xdg_surface: xdg_surface.clone(),
wm_base: data.wm_base.clone(), wm_base: data.wm_base.clone(),
}, },
&data.shell_data.display_token,
); );
data.shell_data data.shell_data
@ -275,10 +279,16 @@ fn xdg_surface_implementation<U, R, SD>(
parent, parent,
positioner, positioner,
} => { } => {
let positioner_data = positioner.user_data::<RefCell<PositionerState>>().unwrap(); let positioner_data = positioner
.as_ref()
.user_data::<RefCell<PositionerState>>()
.unwrap();
let parent_surface = parent.map(|parent| { let parent_surface = parent.map(|parent| {
let parent_data = parent.user_data::<XdgSurfaceUserData<U, R, SD>>().unwrap(); let parent_data = parent
.as_ref()
.user_data::<XdgSurfaceUserData<U, R, SD>>()
.unwrap();
parent_data.wl_surface.clone() parent_data.wl_surface.clone()
}); });
data.shell_data data.shell_data
@ -290,7 +300,7 @@ fn xdg_surface_implementation<U, R, SD>(
}); });
}) })
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
let popup = id.implement_nonsend( let popup = id.implement_closure(
xg_popup_implementation::<U, R, SD>, xg_popup_implementation::<U, R, SD>,
Some(destroy_popup::<U, R, SD>), Some(destroy_popup::<U, R, SD>),
ShellSurfaceUserData { ShellSurfaceUserData {
@ -299,7 +309,6 @@ fn xdg_surface_implementation<U, R, SD>(
xdg_surface: xdg_surface.clone(), xdg_surface: xdg_surface.clone(),
wm_base: data.wm_base.clone(), wm_base: data.wm_base.clone(),
}, },
&data.shell_data.display_token,
); );
data.shell_data data.shell_data
@ -334,7 +343,7 @@ fn xdg_surface_implementation<U, R, SD>(
}); });
if !found { if !found {
// client responded to a non-existing configure // client responded to a non-existing configure
data.wm_base.post_error( data.wm_base.as_ref().post_error(
xdg_wm_base::Error::InvalidSurfaceState as u32, xdg_wm_base::Error::InvalidSurfaceState as u32,
format!("Wrong configure serial: {}", serial), format!("Wrong configure serial: {}", serial),
); );
@ -343,6 +352,7 @@ fn xdg_surface_implementation<U, R, SD>(
}) })
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
} }
_ => unreachable!(),
} }
} }
@ -352,15 +362,15 @@ fn xdg_surface_implementation<U, R, SD>(
pub(crate) struct ShellSurfaceUserData<U, R, SD> { pub(crate) struct ShellSurfaceUserData<U, R, SD> {
pub(crate) shell_data: ShellData<U, R, SD>, pub(crate) shell_data: ShellData<U, R, SD>,
pub(crate) wl_surface: Resource<wl_surface::WlSurface>, pub(crate) wl_surface: wl_surface::WlSurface,
pub(crate) wm_base: Resource<xdg_wm_base::XdgWmBase>, pub(crate) wm_base: xdg_wm_base::XdgWmBase,
pub(crate) xdg_surface: Resource<xdg_surface::XdgSurface>, pub(crate) xdg_surface: xdg_surface::XdgSurface,
} }
// Utility functions allowing to factor out a lot of the upcoming logic // Utility functions allowing to factor out a lot of the upcoming logic
fn with_surface_toplevel_data<U, R, SD, F>( fn with_surface_toplevel_data<U, R, SD, F>(
shell_data: &ShellData<U, R, SD>, shell_data: &ShellData<U, R, SD>,
toplevel: &Resource<xdg_toplevel::XdgToplevel>, toplevel: &xdg_toplevel::XdgToplevel,
f: F, f: F,
) where ) where
U: 'static, U: 'static,
@ -368,7 +378,10 @@ fn with_surface_toplevel_data<U, R, SD, F>(
SD: 'static, SD: 'static,
F: FnOnce(&mut ToplevelState), F: FnOnce(&mut ToplevelState),
{ {
let toplevel_data = toplevel.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let toplevel_data = toplevel
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
shell_data shell_data
.compositor_token .compositor_token
.with_role_data::<XdgSurfaceRole, _, _>(&toplevel_data.wl_surface, |data| match data.pending_state { .with_role_data::<XdgSurfaceRole, _, _>(&toplevel_data.wl_surface, |data| match data.pending_state {
@ -378,15 +391,16 @@ fn with_surface_toplevel_data<U, R, SD, F>(
.expect("xdg_toplevel exists but surface has not shell_surface role?!"); .expect("xdg_toplevel exists but surface has not shell_surface role?!");
} }
pub fn send_toplevel_configure<U, R, SD>( pub fn send_toplevel_configure<U, R, SD>(resource: &xdg_toplevel::XdgToplevel, configure: ToplevelConfigure)
resource: &Resource<xdg_toplevel::XdgToplevel>, where
configure: ToplevelConfigure,
) where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = resource.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = resource
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
let (width, height) = configure.size.unwrap_or((0, 0)); let (width, height) = configure.size.unwrap_or((0, 0));
// convert the Vec<State> (which is really a Vec<u32>) into Vec<u8> // convert the Vec<State> (which is really a Vec<u32>) into Vec<u8>
let states = { let states = {
@ -398,12 +412,8 @@ pub fn send_toplevel_configure<U, R, SD>(
unsafe { Vec::from_raw_parts(ptr as *mut u8, len * 4, cap * 4) } unsafe { Vec::from_raw_parts(ptr as *mut u8, len * 4, cap * 4) }
}; };
let serial = configure.serial; let serial = configure.serial;
resource.send(xdg_toplevel::Event::Configure { resource.configure(width, height, states);
width, data.xdg_surface.configure(serial);
height,
states,
});
data.xdg_surface.send(xdg_surface::Event::Configure { serial });
// Add the configure as pending // Add the configure as pending
data.shell_data data.shell_data
.compositor_token .compositor_token
@ -412,9 +422,12 @@ pub fn send_toplevel_configure<U, R, SD>(
} }
fn make_toplevel_handle<U: 'static, R: 'static, SD: 'static>( fn make_toplevel_handle<U: 'static, R: 'static, SD: 'static>(
resource: &Resource<xdg_toplevel::XdgToplevel>, resource: &xdg_toplevel::XdgToplevel,
) -> super::ToplevelSurface<U, R, SD> { ) -> super::ToplevelSurface<U, R, SD> {
let data = resource.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = resource
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
super::ToplevelSurface { super::ToplevelSurface {
wl_surface: data.wl_surface.clone(), wl_surface: data.wl_surface.clone(),
shell_surface: ToplevelKind::Xdg(resource.clone()), shell_surface: ToplevelKind::Xdg(resource.clone()),
@ -423,15 +436,16 @@ fn make_toplevel_handle<U: 'static, R: 'static, SD: 'static>(
} }
} }
fn toplevel_implementation<U, R, SD>( fn toplevel_implementation<U, R, SD>(request: xdg_toplevel::Request, toplevel: xdg_toplevel::XdgToplevel)
request: xdg_toplevel::Request, where
toplevel: Resource<xdg_toplevel::XdgToplevel>,
) where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = toplevel.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = toplevel
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
match request { match request {
xdg_toplevel::Request::Destroy => { xdg_toplevel::Request::Destroy => {
// all it done by the destructor // all it done by the destructor
@ -440,6 +454,7 @@ fn toplevel_implementation<U, R, SD>(
with_surface_toplevel_data(&data.shell_data, &toplevel, |toplevel_data| { with_surface_toplevel_data(&data.shell_data, &toplevel, |toplevel_data| {
toplevel_data.parent = parent.map(|toplevel_surface_parent| { toplevel_data.parent = parent.map(|toplevel_surface_parent| {
toplevel_surface_parent toplevel_surface_parent
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>() .user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap() .unwrap()
.wl_surface .wl_surface
@ -525,17 +540,21 @@ fn toplevel_implementation<U, R, SD>(
let mut user_impl = data.shell_data.user_impl.borrow_mut(); let mut user_impl = data.shell_data.user_impl.borrow_mut();
(&mut *user_impl)(XdgRequest::Minimize { surface: handle }); (&mut *user_impl)(XdgRequest::Minimize { surface: handle });
} }
_ => unreachable!(),
} }
} }
fn destroy_toplevel<U, R, SD>(toplevel: Resource<xdg_toplevel::XdgToplevel>) fn destroy_toplevel<U, R, SD>(toplevel: xdg_toplevel::XdgToplevel)
where where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = toplevel.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = toplevel
if !data.wl_surface.is_alive() { .as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
if !data.wl_surface.as_ref().is_alive() {
// the wl_surface is destroyed, this means the client is not // the wl_surface is destroyed, this means the client is not
// trying to change the role but it's a cleanup (possibly a // trying to change the role but it's a cleanup (possibly a
// disconnecting client), ignore the protocol check. // disconnecting client), ignore the protocol check.
@ -561,20 +580,21 @@ where
* xdg_popup * xdg_popup
*/ */
pub(crate) fn send_popup_configure<U, R, SD>( pub(crate) fn send_popup_configure<U, R, SD>(resource: &xdg_popup::XdgPopup, configure: PopupConfigure)
resource: &Resource<xdg_popup::XdgPopup>, where
configure: PopupConfigure,
) where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = resource.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = resource
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
let (x, y) = configure.position; let (x, y) = configure.position;
let (width, height) = configure.size; let (width, height) = configure.size;
let serial = configure.serial; let serial = configure.serial;
resource.send(xdg_popup::Event::Configure { x, y, width, height }); resource.configure(x, y, width, height);
data.xdg_surface.send(xdg_surface::Event::Configure { serial }); data.xdg_surface.configure(serial);
// Add the configure as pending // Add the configure as pending
data.shell_data data.shell_data
.compositor_token .compositor_token
@ -583,9 +603,12 @@ pub(crate) fn send_popup_configure<U, R, SD>(
} }
fn make_popup_handle<U: 'static, R: 'static, SD: 'static>( fn make_popup_handle<U: 'static, R: 'static, SD: 'static>(
resource: &Resource<xdg_popup::XdgPopup>, resource: &xdg_popup::XdgPopup,
) -> super::PopupSurface<U, R, SD> { ) -> super::PopupSurface<U, R, SD> {
let data = resource.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = resource
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
super::PopupSurface { super::PopupSurface {
wl_surface: data.wl_surface.clone(), wl_surface: data.wl_surface.clone(),
shell_surface: PopupKind::Xdg(resource.clone()), shell_surface: PopupKind::Xdg(resource.clone()),
@ -594,13 +617,16 @@ fn make_popup_handle<U: 'static, R: 'static, SD: 'static>(
} }
} }
fn xg_popup_implementation<U, R, SD>(request: xdg_popup::Request, popup: Resource<xdg_popup::XdgPopup>) fn xg_popup_implementation<U, R, SD>(request: xdg_popup::Request, popup: xdg_popup::XdgPopup)
where where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = popup.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = popup
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
match request { match request {
xdg_popup::Request::Destroy => { xdg_popup::Request::Destroy => {
// all is handled by our destructor // all is handled by our destructor
@ -614,17 +640,21 @@ where
serial, serial,
}); });
} }
_ => unreachable!(),
} }
} }
fn destroy_popup<U, R, SD>(popup: Resource<xdg_popup::XdgPopup>) fn destroy_popup<U, R, SD>(popup: xdg_popup::XdgPopup)
where where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = popup.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = popup
if !data.wl_surface.is_alive() { .as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
if !data.wl_surface.as_ref().is_alive() {
// the wl_surface is destroyed, this means the client is not // the wl_surface is destroyed, this means the client is not
// trying to change the role but it's a cleanup (possibly a // trying to change the role but it's a cleanup (possibly a
// disconnecting client), ignore the protocol check. // disconnecting client), ignore the protocol check.

View File

@ -7,7 +7,7 @@ use wayland_protocols::{
}, },
xdg_shell::server::{xdg_positioner, xdg_toplevel}, xdg_shell::server::{xdg_positioner, xdg_toplevel},
}; };
use wayland_server::{protocol::wl_surface, DisplayToken, NewResource, Resource}; use wayland_server::{protocol::wl_surface, NewResource, Resource};
use crate::utils::Rectangle; use crate::utils::Rectangle;
@ -20,20 +20,19 @@ use super::{
pub(crate) fn implement_shell<U, R, SD>( pub(crate) fn implement_shell<U, R, SD>(
shell: NewResource<zxdg_shell_v6::ZxdgShellV6>, shell: NewResource<zxdg_shell_v6::ZxdgShellV6>,
shell_data: &ShellData<U, R, SD>, shell_data: &ShellData<U, R, SD>,
) -> Resource<zxdg_shell_v6::ZxdgShellV6> ) -> zxdg_shell_v6::ZxdgShellV6
where where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: Default + 'static, SD: Default + 'static,
{ {
let shell = shell.implement_nonsend( let shell = shell.implement_closure(
shell_implementation::<U, R, SD>, shell_implementation::<U, R, SD>,
None::<fn(_)>, None::<fn(_)>,
ShellUserData { ShellUserData {
shell_data: shell_data.clone(), shell_data: shell_data.clone(),
client_data: Mutex::new(make_shell_client_data::<SD>()), client_data: Mutex::new(make_shell_client_data::<SD>()),
}, },
&shell_data.display_token,
); );
let mut user_impl = shell_data.user_impl.borrow_mut(); let mut user_impl = shell_data.user_impl.borrow_mut();
(&mut *user_impl)(XdgRequest::NewClient { (&mut *user_impl)(XdgRequest::NewClient {
@ -52,7 +51,7 @@ pub(crate) struct ShellUserData<U, R, SD> {
} }
pub(crate) fn make_shell_client<U, R, SD>( pub(crate) fn make_shell_client<U, R, SD>(
resource: &Resource<zxdg_shell_v6::ZxdgShellV6>, resource: &zxdg_shell_v6::ZxdgShellV6,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
) -> ShellClient<U, R, SD> { ) -> ShellClient<U, R, SD> {
ShellClient { ShellClient {
@ -62,21 +61,19 @@ pub(crate) fn make_shell_client<U, R, SD>(
} }
} }
fn shell_implementation<U, R, SD>( fn shell_implementation<U, R, SD>(request: zxdg_shell_v6::Request, shell: zxdg_shell_v6::ZxdgShellV6)
request: zxdg_shell_v6::Request, where
shell: Resource<zxdg_shell_v6::ZxdgShellV6>,
) where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = shell.user_data::<ShellUserData<U, R, SD>>().unwrap(); let data = shell.as_ref().user_data::<ShellUserData<U, R, SD>>().unwrap();
match request { match request {
zxdg_shell_v6::Request::Destroy => { zxdg_shell_v6::Request::Destroy => {
// all is handled by destructor // all is handled by destructor
} }
zxdg_shell_v6::Request::CreatePositioner { id } => { zxdg_shell_v6::Request::CreatePositioner { id } => {
implement_positioner(id, &data.shell_data.display_token); implement_positioner(id);
} }
zxdg_shell_v6::Request::GetXdgSurface { id, surface } => { zxdg_shell_v6::Request::GetXdgSurface { id, surface } => {
let role_data = XdgSurfaceRole { let role_data = XdgSurfaceRole {
@ -91,13 +88,13 @@ fn shell_implementation<U, R, SD>(
.give_role_with(&surface, role_data) .give_role_with(&surface, role_data)
.is_err() .is_err()
{ {
shell.post_error( shell.as_ref().post_error(
zxdg_shell_v6::Error::Role as u32, zxdg_shell_v6::Error::Role as u32,
"Surface already has a role.".into(), "Surface already has a role.".into(),
); );
return; return;
} }
id.implement_nonsend( id.implement_closure(
xdg_surface_implementation::<U, R, SD>, xdg_surface_implementation::<U, R, SD>,
Some(destroy_surface::<U, R, SD>), Some(destroy_surface::<U, R, SD>),
XdgSurfaceUserData { XdgSurfaceUserData {
@ -105,7 +102,6 @@ fn shell_implementation<U, R, SD>(
wl_surface: surface.clone(), wl_surface: surface.clone(),
shell: shell.clone(), shell: shell.clone(),
}, },
&data.shell_data.display_token,
); );
} }
zxdg_shell_v6::Request::Pong { serial } => { zxdg_shell_v6::Request::Pong { serial } => {
@ -125,6 +121,7 @@ fn shell_implementation<U, R, SD>(
}); });
} }
} }
_ => unreachable!(),
} }
} }
@ -134,11 +131,13 @@ fn shell_implementation<U, R, SD>(
fn implement_positioner( fn implement_positioner(
positioner: NewResource<zxdg_positioner_v6::ZxdgPositionerV6>, positioner: NewResource<zxdg_positioner_v6::ZxdgPositionerV6>,
token: &DisplayToken, ) -> zxdg_positioner_v6::ZxdgPositionerV6 {
) -> Resource<zxdg_positioner_v6::ZxdgPositionerV6> { positioner.implement_closure(
positioner.implement_nonsend( |request, positioner| {
|request, positioner: Resource<_>| { let mutex = positioner
let mutex = positioner.user_data::<RefCell<PositionerState>>().unwrap(); .as_ref()
.user_data::<RefCell<PositionerState>>()
.unwrap();
let mut state = mutex.borrow_mut(); let mut state = mutex.borrow_mut();
match request { match request {
zxdg_positioner_v6::Request::Destroy => { zxdg_positioner_v6::Request::Destroy => {
@ -146,7 +145,7 @@ fn implement_positioner(
} }
zxdg_positioner_v6::Request::SetSize { width, height } => { zxdg_positioner_v6::Request::SetSize { width, height } => {
if width < 1 || height < 1 { if width < 1 || height < 1 {
positioner.post_error( positioner.as_ref().post_error(
zxdg_positioner_v6::Error::InvalidInput as u32, zxdg_positioner_v6::Error::InvalidInput as u32,
"Invalid size for positioner.".into(), "Invalid size for positioner.".into(),
); );
@ -156,7 +155,7 @@ fn implement_positioner(
} }
zxdg_positioner_v6::Request::SetAnchorRect { x, y, width, height } => { zxdg_positioner_v6::Request::SetAnchorRect { x, y, width, height } => {
if width < 1 || height < 1 { if width < 1 || height < 1 {
positioner.post_error( positioner.as_ref().post_error(
zxdg_positioner_v6::Error::InvalidInput as u32, zxdg_positioner_v6::Error::InvalidInput as u32,
"Invalid size for positioner's anchor rectangle.".into(), "Invalid size for positioner's anchor rectangle.".into(),
); );
@ -168,7 +167,7 @@ fn implement_positioner(
if let Some(anchor) = zxdg_anchor_to_xdg(anchor) { if let Some(anchor) = zxdg_anchor_to_xdg(anchor) {
state.anchor_edges = anchor; state.anchor_edges = anchor;
} else { } else {
positioner.post_error( positioner.as_ref().post_error(
zxdg_positioner_v6::Error::InvalidInput as u32, zxdg_positioner_v6::Error::InvalidInput as u32,
"Invalid anchor for positioner.".into(), "Invalid anchor for positioner.".into(),
); );
@ -178,7 +177,7 @@ fn implement_positioner(
if let Some(gravity) = zxdg_gravity_to_xdg(gravity) { if let Some(gravity) = zxdg_gravity_to_xdg(gravity) {
state.gravity = gravity; state.gravity = gravity;
} else { } else {
positioner.post_error( positioner.as_ref().post_error(
zxdg_positioner_v6::Error::InvalidInput as u32, zxdg_positioner_v6::Error::InvalidInput as u32,
"Invalid gravity for positioner.".into(), "Invalid gravity for positioner.".into(),
); );
@ -194,11 +193,11 @@ fn implement_positioner(
zxdg_positioner_v6::Request::SetOffset { x, y } => { zxdg_positioner_v6::Request::SetOffset { x, y } => {
state.offset = (x, y); state.offset = (x, y);
} }
_ => unreachable!(),
} }
}, },
None::<fn(_)>, None::<fn(_)>,
RefCell::new(PositionerState::new()), RefCell::new(PositionerState::new()),
token,
) )
} }
@ -208,18 +207,21 @@ fn implement_positioner(
struct XdgSurfaceUserData<U, R, SD> { struct XdgSurfaceUserData<U, R, SD> {
shell_data: ShellData<U, R, SD>, shell_data: ShellData<U, R, SD>,
wl_surface: Resource<wl_surface::WlSurface>, wl_surface: wl_surface::WlSurface,
shell: Resource<zxdg_shell_v6::ZxdgShellV6>, shell: zxdg_shell_v6::ZxdgShellV6,
} }
fn destroy_surface<U, R, SD>(surface: Resource<zxdg_surface_v6::ZxdgSurfaceV6>) fn destroy_surface<U, R, SD>(surface: zxdg_surface_v6::ZxdgSurfaceV6)
where where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = surface.user_data::<XdgSurfaceUserData<U, R, SD>>().unwrap(); let data = surface
if !data.wl_surface.is_alive() { .as_ref()
.user_data::<XdgSurfaceUserData<U, R, SD>>()
.unwrap();
if !data.wl_surface.as_ref().is_alive() {
// the wl_surface is destroyed, this means the client is not // the wl_surface is destroyed, this means the client is not
// trying to change the role but it's a cleanup (possibly a // trying to change the role but it's a cleanup (possibly a
// disconnecting client), ignore the protocol check. // disconnecting client), ignore the protocol check.
@ -231,7 +233,7 @@ where
if let XdgSurfacePendingState::None = rdata.pending_state { if let XdgSurfacePendingState::None = rdata.pending_state {
// all is good // all is good
} else { } else {
data.shell.post_error( data.shell.as_ref().post_error(
zxdg_shell_v6::Error::Role as u32, zxdg_shell_v6::Error::Role as u32,
"xdg_surface was destroyed before its role object".into(), "xdg_surface was destroyed before its role object".into(),
); );
@ -242,13 +244,16 @@ where
fn xdg_surface_implementation<U, R, SD>( fn xdg_surface_implementation<U, R, SD>(
request: zxdg_surface_v6::Request, request: zxdg_surface_v6::Request,
xdg_surface: Resource<zxdg_surface_v6::ZxdgSurfaceV6>, xdg_surface: zxdg_surface_v6::ZxdgSurfaceV6,
) where ) where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = xdg_surface.user_data::<XdgSurfaceUserData<U, R, SD>>().unwrap(); let data = xdg_surface
.as_ref()
.user_data::<XdgSurfaceUserData<U, R, SD>>()
.unwrap();
match request { match request {
zxdg_surface_v6::Request::Destroy => { zxdg_surface_v6::Request::Destroy => {
// all is handled by our destructor // all is handled by our destructor
@ -266,7 +271,7 @@ fn xdg_surface_implementation<U, R, SD>(
}); });
}) })
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
let toplevel = id.implement_nonsend( let toplevel = id.implement_closure(
toplevel_implementation::<U, R, SD>, toplevel_implementation::<U, R, SD>,
Some(destroy_toplevel::<U, R, SD>), Some(destroy_toplevel::<U, R, SD>),
ShellSurfaceUserData { ShellSurfaceUserData {
@ -275,7 +280,6 @@ fn xdg_surface_implementation<U, R, SD>(
shell: data.shell.clone(), shell: data.shell.clone(),
xdg_surface: xdg_surface.clone(), xdg_surface: xdg_surface.clone(),
}, },
&data.shell_data.display_token,
); );
data.shell_data data.shell_data
@ -294,9 +298,15 @@ fn xdg_surface_implementation<U, R, SD>(
parent, parent,
positioner, positioner,
} => { } => {
let positioner_data = positioner.user_data::<RefCell<PositionerState>>().unwrap(); let positioner_data = positioner
.as_ref()
.user_data::<RefCell<PositionerState>>()
.unwrap();
let parent_data = parent.user_data::<XdgSurfaceUserData<U, R, SD>>().unwrap(); let parent_data = parent
.as_ref()
.user_data::<XdgSurfaceUserData<U, R, SD>>()
.unwrap();
data.shell_data data.shell_data
.compositor_token .compositor_token
.with_role_data::<XdgSurfaceRole, _, _>(&data.wl_surface, |data| { .with_role_data::<XdgSurfaceRole, _, _>(&data.wl_surface, |data| {
@ -306,7 +316,7 @@ fn xdg_surface_implementation<U, R, SD>(
}); });
}) })
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
let popup = id.implement_nonsend( let popup = id.implement_closure(
popup_implementation::<U, R, SD>, popup_implementation::<U, R, SD>,
Some(destroy_popup::<U, R, SD>), Some(destroy_popup::<U, R, SD>),
ShellSurfaceUserData { ShellSurfaceUserData {
@ -315,7 +325,6 @@ fn xdg_surface_implementation<U, R, SD>(
shell: data.shell.clone(), shell: data.shell.clone(),
xdg_surface: xdg_surface.clone(), xdg_surface: xdg_surface.clone(),
}, },
&data.shell_data.display_token,
); );
data.shell_data data.shell_data
@ -350,7 +359,7 @@ fn xdg_surface_implementation<U, R, SD>(
}); });
if !found { if !found {
// client responded to a non-existing configure // client responded to a non-existing configure
data.shell.post_error( data.shell.as_ref().post_error(
zxdg_shell_v6::Error::InvalidSurfaceState as u32, zxdg_shell_v6::Error::InvalidSurfaceState as u32,
format!("Wrong configure serial: {}", serial), format!("Wrong configure serial: {}", serial),
); );
@ -359,6 +368,7 @@ fn xdg_surface_implementation<U, R, SD>(
}) })
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
} }
_ => unreachable!(),
} }
} }
@ -368,20 +378,23 @@ fn xdg_surface_implementation<U, R, SD>(
pub struct ShellSurfaceUserData<U, R, SD> { pub struct ShellSurfaceUserData<U, R, SD> {
pub(crate) shell_data: ShellData<U, R, SD>, pub(crate) shell_data: ShellData<U, R, SD>,
pub(crate) wl_surface: Resource<wl_surface::WlSurface>, pub(crate) wl_surface: wl_surface::WlSurface,
pub(crate) shell: Resource<zxdg_shell_v6::ZxdgShellV6>, pub(crate) shell: zxdg_shell_v6::ZxdgShellV6,
pub(crate) xdg_surface: Resource<zxdg_surface_v6::ZxdgSurfaceV6>, pub(crate) xdg_surface: zxdg_surface_v6::ZxdgSurfaceV6,
} }
// Utility functions allowing to factor out a lot of the upcoming logic // Utility functions allowing to factor out a lot of the upcoming logic
fn with_surface_toplevel_data<U, R, SD, F>(toplevel: &Resource<zxdg_toplevel_v6::ZxdgToplevelV6>, f: F) fn with_surface_toplevel_data<U, R, SD, F>(toplevel: &zxdg_toplevel_v6::ZxdgToplevelV6, f: F)
where where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
F: FnOnce(&mut ToplevelState), F: FnOnce(&mut ToplevelState),
{ {
let data = toplevel.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = toplevel
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
data.shell_data data.shell_data
.compositor_token .compositor_token
.with_role_data::<XdgSurfaceRole, _, _>(&data.wl_surface, |data| match data.pending_state { .with_role_data::<XdgSurfaceRole, _, _>(&data.wl_surface, |data| match data.pending_state {
@ -392,14 +405,17 @@ where
} }
pub fn send_toplevel_configure<U, R, SD>( pub fn send_toplevel_configure<U, R, SD>(
resource: &Resource<zxdg_toplevel_v6::ZxdgToplevelV6>, resource: &zxdg_toplevel_v6::ZxdgToplevelV6,
configure: ToplevelConfigure, configure: ToplevelConfigure,
) where ) where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = resource.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = resource
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
let (width, height) = configure.size.unwrap_or((0, 0)); let (width, height) = configure.size.unwrap_or((0, 0));
// convert the Vec<State> (which is really a Vec<u32>) into Vec<u8> // convert the Vec<State> (which is really a Vec<u32>) into Vec<u8>
let states = { let states = {
@ -411,13 +427,8 @@ pub fn send_toplevel_configure<U, R, SD>(
unsafe { Vec::from_raw_parts(ptr as *mut u8, len * 4, cap * 4) } unsafe { Vec::from_raw_parts(ptr as *mut u8, len * 4, cap * 4) }
}; };
let serial = configure.serial; let serial = configure.serial;
resource.send(zxdg_toplevel_v6::Event::Configure { resource.configure(width, height, states);
width, data.xdg_surface.configure(serial);
height,
states,
});
data.xdg_surface
.send(zxdg_surface_v6::Event::Configure { serial });
// Add the configure as pending // Add the configure as pending
data.shell_data data.shell_data
.compositor_token .compositor_token
@ -426,9 +437,12 @@ pub fn send_toplevel_configure<U, R, SD>(
} }
fn make_toplevel_handle<U: 'static, R: 'static, SD: 'static>( fn make_toplevel_handle<U: 'static, R: 'static, SD: 'static>(
resource: &Resource<zxdg_toplevel_v6::ZxdgToplevelV6>, resource: &zxdg_toplevel_v6::ZxdgToplevelV6,
) -> super::ToplevelSurface<U, R, SD> { ) -> super::ToplevelSurface<U, R, SD> {
let data = resource.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = resource
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
super::ToplevelSurface { super::ToplevelSurface {
wl_surface: data.wl_surface.clone(), wl_surface: data.wl_surface.clone(),
shell_surface: ToplevelKind::ZxdgV6(resource.clone()), shell_surface: ToplevelKind::ZxdgV6(resource.clone()),
@ -439,13 +453,16 @@ fn make_toplevel_handle<U: 'static, R: 'static, SD: 'static>(
fn toplevel_implementation<U, R, SD>( fn toplevel_implementation<U, R, SD>(
request: zxdg_toplevel_v6::Request, request: zxdg_toplevel_v6::Request,
toplevel: Resource<zxdg_toplevel_v6::ZxdgToplevelV6>, toplevel: zxdg_toplevel_v6::ZxdgToplevelV6,
) where ) where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = toplevel.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = toplevel
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
match request { match request {
zxdg_toplevel_v6::Request::Destroy => { zxdg_toplevel_v6::Request::Destroy => {
// all it done by the destructor // all it done by the destructor
@ -454,6 +471,7 @@ fn toplevel_implementation<U, R, SD>(
with_surface_toplevel_data::<U, R, SD, _>(&toplevel, |toplevel_data| { with_surface_toplevel_data::<U, R, SD, _>(&toplevel, |toplevel_data| {
toplevel_data.parent = parent.map(|toplevel_surface_parent| { toplevel_data.parent = parent.map(|toplevel_surface_parent| {
let parent_data = toplevel_surface_parent let parent_data = toplevel_surface_parent
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>() .user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap(); .unwrap();
parent_data.wl_surface.clone() parent_data.wl_surface.clone()
@ -539,17 +557,21 @@ fn toplevel_implementation<U, R, SD>(
let mut user_impl = data.shell_data.user_impl.borrow_mut(); let mut user_impl = data.shell_data.user_impl.borrow_mut();
(&mut *user_impl)(XdgRequest::Minimize { surface: handle }); (&mut *user_impl)(XdgRequest::Minimize { surface: handle });
} }
_ => unreachable!(),
} }
} }
fn destroy_toplevel<U, R, SD>(toplevel: Resource<zxdg_toplevel_v6::ZxdgToplevelV6>) fn destroy_toplevel<U, R, SD>(toplevel: zxdg_toplevel_v6::ZxdgToplevelV6)
where where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = toplevel.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = toplevel
if !data.wl_surface.is_alive() { .as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
if !data.wl_surface.as_ref().is_alive() {
// the wl_surface is destroyed, this means the client is not // the wl_surface is destroyed, this means the client is not
// trying to change the role but it's a cleanup (possibly a // trying to change the role but it's a cleanup (possibly a
// disconnecting client), ignore the protocol check. // disconnecting client), ignore the protocol check.
@ -575,21 +597,21 @@ where
* xdg_popup * xdg_popup
*/ */
pub(crate) fn send_popup_configure<U, R, SD>( pub(crate) fn send_popup_configure<U, R, SD>(resource: &zxdg_popup_v6::ZxdgPopupV6, configure: PopupConfigure)
resource: &Resource<zxdg_popup_v6::ZxdgPopupV6>, where
configure: PopupConfigure,
) where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = resource.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = resource
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
let (x, y) = configure.position; let (x, y) = configure.position;
let (width, height) = configure.size; let (width, height) = configure.size;
let serial = configure.serial; let serial = configure.serial;
resource.send(zxdg_popup_v6::Event::Configure { x, y, width, height }); resource.configure(x, y, width, height);
data.xdg_surface data.xdg_surface.configure(serial);
.send(zxdg_surface_v6::Event::Configure { serial });
// Add the configure as pending // Add the configure as pending
data.shell_data data.shell_data
.compositor_token .compositor_token
@ -598,9 +620,12 @@ pub(crate) fn send_popup_configure<U, R, SD>(
} }
fn make_popup_handle<U: 'static, R: 'static, SD: 'static>( fn make_popup_handle<U: 'static, R: 'static, SD: 'static>(
resource: &Resource<zxdg_popup_v6::ZxdgPopupV6>, resource: &zxdg_popup_v6::ZxdgPopupV6,
) -> super::PopupSurface<U, R, SD> { ) -> super::PopupSurface<U, R, SD> {
let data = resource.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = resource
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
super::PopupSurface { super::PopupSurface {
wl_surface: data.wl_surface.clone(), wl_surface: data.wl_surface.clone(),
shell_surface: PopupKind::ZxdgV6(resource.clone()), shell_surface: PopupKind::ZxdgV6(resource.clone()),
@ -609,15 +634,16 @@ fn make_popup_handle<U: 'static, R: 'static, SD: 'static>(
} }
} }
fn popup_implementation<U, R, SD>( fn popup_implementation<U, R, SD>(request: zxdg_popup_v6::Request, popup: zxdg_popup_v6::ZxdgPopupV6)
request: zxdg_popup_v6::Request, where
popup: Resource<zxdg_popup_v6::ZxdgPopupV6>,
) where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = popup.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = popup
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
match request { match request {
zxdg_popup_v6::Request::Destroy => { zxdg_popup_v6::Request::Destroy => {
// all is handled by our destructor // all is handled by our destructor
@ -631,17 +657,21 @@ fn popup_implementation<U, R, SD>(
serial, serial,
}); });
} }
_ => unreachable!(),
} }
} }
fn destroy_popup<U, R, SD>(popup: Resource<zxdg_popup_v6::ZxdgPopupV6>) fn destroy_popup<U, R, SD>(popup: zxdg_popup_v6::ZxdgPopupV6)
where where
U: 'static, U: 'static,
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static, SD: 'static,
{ {
let data = popup.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap(); let data = popup
if !data.wl_surface.is_alive() { .as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
if !data.wl_surface.as_ref().is_alive() {
// the wl_surface is destroyed, this means the client is not // the wl_surface is destroyed, this means the client is not
// trying to change the role but it's a cleanup (possibly a // trying to change the role but it's a cleanup (possibly a
// disconnecting client), ignore the protocol check. // disconnecting client), ignore the protocol check.
@ -674,6 +704,7 @@ fn zxdg_edges_to_xdg(e: zxdg_toplevel_v6::ResizeEdge) -> xdg_toplevel::ResizeEdg
zxdg_toplevel_v6::ResizeEdge::TopRight => xdg_toplevel::ResizeEdge::TopRight, zxdg_toplevel_v6::ResizeEdge::TopRight => xdg_toplevel::ResizeEdge::TopRight,
zxdg_toplevel_v6::ResizeEdge::BottomLeft => xdg_toplevel::ResizeEdge::BottomLeft, zxdg_toplevel_v6::ResizeEdge::BottomLeft => xdg_toplevel::ResizeEdge::BottomLeft,
zxdg_toplevel_v6::ResizeEdge::BottomRight => xdg_toplevel::ResizeEdge::BottomRight, zxdg_toplevel_v6::ResizeEdge::BottomRight => xdg_toplevel::ResizeEdge::BottomRight,
_ => unreachable!(),
} }
} }

View File

@ -44,8 +44,7 @@
//! # extern crate wayland_server; //! # extern crate wayland_server;
//! # extern crate smithay; //! # extern crate smithay;
//! # use wayland_server::protocol::wl_buffer::WlBuffer; //! # use wayland_server::protocol::wl_buffer::WlBuffer;
//! # use wayland_server::Resource; //! # fn wrap(buffer: &WlBuffer) {
//! # fn wrap(buffer: &Resource<WlBuffer>) {
//! use smithay::wayland::shm::{with_buffer_contents, BufferData, BufferAccessError}; //! use smithay::wayland::shm::{with_buffer_contents, BufferData, BufferAccessError};
//! //!
//! let content = with_buffer_contents(&buffer, //! let content = with_buffer_contents(&buffer,
@ -82,7 +81,7 @@ use self::pool::{Pool, ResizeError};
use std::{rc::Rc, sync::Arc}; use std::{rc::Rc, sync::Arc};
use wayland_server::{ use wayland_server::{
protocol::{wl_buffer, wl_shm, wl_shm_pool}, protocol::{wl_buffer, wl_shm, wl_shm_pool},
Display, DisplayToken, Global, NewResource, Resource, Display, Global, NewResource, Resource,
}; };
mod pool; mod pool;
@ -95,7 +94,6 @@ mod pool;
pub struct ShmGlobalData { pub struct ShmGlobalData {
formats: Rc<Vec<wl_shm::Format>>, formats: Rc<Vec<wl_shm::Format>>,
log: ::slog::Logger, log: ::slog::Logger,
token: DisplayToken,
} }
/// Create a new SHM global advertizing given supported formats. /// Create a new SHM global advertizing given supported formats.
@ -123,22 +121,20 @@ where
let data = ShmGlobalData { let data = ShmGlobalData {
formats: Rc::new(formats), formats: Rc::new(formats),
log: log.new(o!("smithay_module" => "shm_handler")), log: log.new(o!("smithay_module" => "shm_handler")),
token: display.get_token(),
}; };
display.create_global::<wl_shm::WlShm, _>(1, move |shm_new: NewResource<_>, _version| { display.create_global::<wl_shm::WlShm, _>(1, move |shm_new: NewResource<_>, _version| {
let shm = shm_new.implement_nonsend( let shm = shm_new.implement_closure(
{ {
let mut data = data.clone(); let mut data = data.clone();
move |req, shm| data.receive_shm_message(req, shm) move |req, shm| data.receive_shm_message(req, shm)
}, },
None::<fn(_)>, None::<fn(_)>,
(), (),
&data.token,
); );
// send the formats // send the formats
for f in &data.formats[..] { for &f in &data.formats[..] {
shm.send(wl_shm::Event::Format { format: *f }); shm.format(f);
} }
}) })
} }
@ -167,14 +163,11 @@ pub enum BufferAccessError {
/// ///
/// If the buffer is not managed by the provided `ShmGlobal`, the closure is not called /// If the buffer is not managed by the provided `ShmGlobal`, the closure is not called
/// and this method will return `Err(())` (this will be the case for an EGL buffer for example). /// and this method will return `Err(())` (this will be the case for an EGL buffer for example).
pub fn with_buffer_contents<F, T>( pub fn with_buffer_contents<F, T>(buffer: &wl_buffer::WlBuffer, f: F) -> Result<T, BufferAccessError>
buffer: &Resource<wl_buffer::WlBuffer>,
f: F,
) -> Result<T, BufferAccessError>
where where
F: FnOnce(&[u8], BufferData) -> T, F: FnOnce(&[u8], BufferData) -> T,
{ {
let data = match buffer.user_data::<InternalBufferData>() { let data = match buffer.as_ref().user_data::<InternalBufferData>() {
Some(d) => d, Some(d) => d,
None => return Err(BufferAccessError::NotManaged), None => return Err(BufferAccessError::NotManaged),
}; };
@ -183,19 +176,24 @@ where
Ok(t) => Ok(t), Ok(t) => Ok(t),
Err(()) => { Err(()) => {
// SIGBUS error occurred // SIGBUS error occurred
buffer.post_error(wl_shm::Error::InvalidFd as u32, "Bad pool size.".into()); buffer
.as_ref()
.post_error(wl_shm::Error::InvalidFd as u32, "Bad pool size.".into());
Err(BufferAccessError::BadMap) Err(BufferAccessError::BadMap)
} }
} }
} }
impl ShmGlobalData { impl ShmGlobalData {
fn receive_shm_message(&mut self, request: wl_shm::Request, shm: Resource<wl_shm::WlShm>) { fn receive_shm_message(&mut self, request: wl_shm::Request, shm: wl_shm::WlShm) {
use self::wl_shm::{Error, Request}; use self::wl_shm::{Error, Request};
let Request::CreatePool { id: pool, fd, size } = request; let (pool, fd, size) = match request {
Request::CreatePool { id: pool, fd, size } => (pool, fd, size),
_ => unreachable!(),
};
if size <= 0 { if size <= 0 {
shm.post_error( shm.as_ref().post_error(
Error::InvalidFd as u32, Error::InvalidFd as u32,
"Invalid size for a new wl_shm_pool.".into(), "Invalid size for a new wl_shm_pool.".into(),
); );
@ -204,7 +202,7 @@ impl ShmGlobalData {
let mmap_pool = match Pool::new(fd, size as usize, self.log.clone()) { let mmap_pool = match Pool::new(fd, size as usize, self.log.clone()) {
Ok(p) => p, Ok(p) => p,
Err(()) => { Err(()) => {
shm.post_error( shm.as_ref().post_error(
wl_shm::Error::InvalidFd as u32, wl_shm::Error::InvalidFd as u32,
format!("Failed mmap of fd {}.", fd), format!("Failed mmap of fd {}.", fd),
); );
@ -212,14 +210,13 @@ impl ShmGlobalData {
} }
}; };
let arc_pool = Arc::new(mmap_pool); let arc_pool = Arc::new(mmap_pool);
pool.implement_nonsend( pool.implement_closure(
{ {
let mut data = self.clone(); let mut data = self.clone();
move |req, pool| data.receive_pool_message(req, pool) move |req, pool| data.receive_pool_message(req, pool)
}, },
None::<fn(_)>, None::<fn(_)>,
arc_pool, arc_pool,
&self.token,
); );
} }
} }
@ -245,14 +242,10 @@ struct InternalBufferData {
} }
impl ShmGlobalData { impl ShmGlobalData {
fn receive_pool_message( fn receive_pool_message(&mut self, request: wl_shm_pool::Request, pool: wl_shm_pool::WlShmPool) {
&mut self,
request: wl_shm_pool::Request,
pool: Resource<wl_shm_pool::WlShmPool>,
) {
use self::wl_shm_pool::Request; use self::wl_shm_pool::Request;
let arc_pool = pool.user_data::<Arc<Pool>>().unwrap(); let arc_pool = pool.as_ref().user_data::<Arc<Pool>>().unwrap();
match request { match request {
Request::CreateBuffer { Request::CreateBuffer {
@ -264,7 +257,7 @@ impl ShmGlobalData {
format, format,
} => { } => {
if !self.formats.contains(&format) { if !self.formats.contains(&format) {
pool.post_error( pool.as_ref().post_error(
wl_shm::Error::InvalidFormat as u32, wl_shm::Error::InvalidFormat as u32,
format!("SHM format {:?} is not supported.", format), format!("SHM format {:?} is not supported.", format),
); );
@ -280,29 +273,23 @@ impl ShmGlobalData {
format, format,
}, },
}; };
buffer.implement_nonsend( buffer.implement_closure(|_, _| {}, None::<fn(_)>, data);
|req, _| {
// this will break if a variant is added to wl_buffer::Request
let wl_buffer::Request::Destroy = req;
},
None::<fn(_)>,
data,
&self.token,
);
} }
Request::Resize { size } => match arc_pool.resize(size) { Request::Resize { size } => match arc_pool.resize(size) {
Ok(()) => {} Ok(()) => {}
Err(ResizeError::InvalidSize) => { Err(ResizeError::InvalidSize) => {
pool.post_error( pool.as_ref().post_error(
wl_shm::Error::InvalidFd as u32, wl_shm::Error::InvalidFd as u32,
"Invalid new size for a wl_shm_pool.".into(), "Invalid new size for a wl_shm_pool.".into(),
); );
} }
Err(ResizeError::MremapFailed) => { Err(ResizeError::MremapFailed) => {
pool.post_error(wl_shm::Error::InvalidFd as u32, "mremap failed.".into()); pool.as_ref()
.post_error(wl_shm::Error::InvalidFd as u32, "mremap failed.".into());
} }
}, },
Request::Destroy => {} Request::Destroy => {}
_ => unreachable!(),
} }
} }
} }