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" ]
[dependencies]
wayland-server = { version = "0.21.6", optional = true }
wayland-commons = { version = "0.21.1", optional = true }
wayland-sys = { version = "0.21.6", optional = true }
wayland-server = { version = "0.23", optional = true }
wayland-commons = { version = "0.23", optional = true }
wayland-sys = { version = "0.23", optional = true }
calloop = "0.4.2"
nix = "0.11"
xkbcommon = "0.2.1"
@ -21,7 +21,7 @@ tempfile = "2.1.5"
slog = "2.1.1"
slog-stdlog = "3.0.2"
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 }
drm = { version = "^0.3.4", optional = true }
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 }
dbus = { version = "0.6.1", 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 }
error-chain = "0.11.0"
lazy_static = "1.0.0"
@ -55,7 +55,7 @@ backend_udev = ["udev"]
backend_session_logind = ["dbus", "systemd", "backend_session"]
renderer_gl = ["gl_generator"]
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"]
xwayland = ["wayland_frontend"]

View File

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

View File

@ -45,14 +45,14 @@
//! for notifications are the [`Libinput`](input::Libinput) context or the [`Device`](::backend::drm::Device).
use super::{AsErrno, Session, SessionNotifier, SessionObserver};
use calloop::{signals::Signals, LoopHandle, Source};
use calloop::{
signals::{Signal, Signals},
LoopHandle, Source,
};
use nix::{
fcntl::{self, open, OFlag},
libc::c_int,
sys::{
signal::{self, Signal},
stat::{dev_t, fstat, major, minor, Mode},
},
sys::stat::{dev_t, fstat, major, minor, Mode},
unistd::{close, dup},
Error as NixError, Result as NixResult,
};
@ -257,7 +257,7 @@ impl DirectSession {
} else {
tty::__libc_current_sigrtmin()
};*/
let signal = signal::SIGUSR2;
let signal = ::nix::sys::signal::SIGUSR2;
let mode = tty::VtMode {
mode: tty::VT_PROCESS,
@ -270,7 +270,7 @@ impl DirectSession {
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

View File

@ -2,7 +2,7 @@ use std::{cell::RefCell, rc::Rc, sync::Mutex};
use wayland_server::{
protocol::{wl_compositor, wl_region, wl_subcompositor, wl_subsurface, wl_surface},
DisplayToken, NewResource, Resource,
NewResource, Resource,
};
use super::{
@ -17,30 +17,28 @@ use super::{
pub(crate) fn implement_compositor<U, R, Impl>(
compositor: NewResource<wl_compositor::WlCompositor>,
token: DisplayToken,
log: ::slog::Logger,
implem: Rc<RefCell<Impl>>,
) -> Resource<wl_compositor::WlCompositor>
) -> wl_compositor::WlCompositor
where
U: 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_nonsend(
compositor.implement_closure(
move |request, _compositor| match request {
wl_compositor::Request::CreateSurface { id } => {
trace!(log, "Creating a new wl_surface.");
implement_surface(id, &token, log.clone(), implem.clone());
implement_surface(id, log.clone(), implem.clone());
}
wl_compositor::Request::CreateRegion { id } => {
trace!(log, "Creating a new wl_region.");
implement_region(id, &token);
implement_region(id);
}
_ => unreachable!(),
},
None::<fn(_)>,
(),
&my_token,
)
}
@ -51,13 +49,13 @@ where
// Internal implementation data of surfaces
pub(crate) struct SurfaceImplem<U, R> {
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> {
fn make<Impl>(log: ::slog::Logger, implem: Rc<RefCell<Impl>>) -> SurfaceImplem<U, R>
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 }
}
@ -68,11 +66,7 @@ where
U: 'static,
R: 'static,
{
fn receive_surface_request(
&mut self,
req: wl_surface::Request,
surface: Resource<wl_surface::WlSurface>,
) {
fn receive_surface_request(&mut self, req: wl_surface::Request, surface: wl_surface::WlSurface) {
match req {
wl_surface::Request::Attach { buffer, x, y } => {
SurfaceData::<U, R>::with_data(&surface, |d| {
@ -91,14 +85,14 @@ where
}
wl_surface::Request::SetOpaqueRegion { region } => {
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()
});
SurfaceData::<U, R>::with_data(&surface, |d| d.opaque_region = attributes);
}
wl_surface::Request::SetInputRegion { region } => {
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()
});
SurfaceData::<U, R>::with_data(&surface, |d| d.input_region = attributes);
@ -122,29 +116,28 @@ where
wl_surface::Request::Destroy => {
// All is already handled by our destructor
}
_ => unreachable!(),
}
}
}
fn implement_surface<U, R, Impl>(
surface: NewResource<wl_surface::WlSurface>,
token: &DisplayToken,
log: ::slog::Logger,
implem: Rc<RefCell<Impl>>,
) -> Resource<wl_surface::WlSurface>
) -> wl_surface::WlSurface
where
U: 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);
move |req, surface| implem.receive_surface_request(req, surface)
},
Some(|surface| SurfaceData::<U, R>::cleanup(&surface)),
SurfaceData::<U, R>::new(),
token,
);
surface
}
@ -153,8 +146,8 @@ where
* wl_region
*/
fn region_implem(request: wl_region::Request, region: Resource<wl_region::WlRegion>) {
let attributes_mutex = region.user_data::<Mutex<RegionAttributes>>().unwrap();
fn region_implem(request: wl_region::Request, region: wl_region::WlRegion) {
let attributes_mutex = region.as_ref().user_data::<Mutex<RegionAttributes>>().unwrap();
let mut guard = attributes_mutex.lock().unwrap();
match request {
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 => {
// all is handled by our destructor
}
_ => unreachable!(),
}
}
fn implement_region(
region: NewResource<wl_region::WlRegion>,
token: &DisplayToken,
) -> Resource<wl_region::WlRegion> {
region.implement_nonsend(
fn implement_region(region: NewResource<wl_region::WlRegion>) -> wl_region::WlRegion {
region.implement_closure(
region_implem,
None::<fn(_)>,
Mutex::new(RegionAttributes::default()),
token,
)
}
@ -187,30 +177,28 @@ fn implement_region(
pub(crate) fn implement_subcompositor<U, R>(
subcompositor: NewResource<wl_subcompositor::WlSubcompositor>,
token: DisplayToken,
) -> Resource<wl_subcompositor::WlSubcompositor>
) -> wl_subcompositor::WlSubcompositor
where
R: RoleType + Role<SubsurfaceRole> + 'static,
U: 'static,
{
let my_token = token.clone();
subcompositor.implement_nonsend(
move |request, subcompositor: Resource<_>| match request {
subcompositor.implement_closure(
move |request, subcompositor| match request {
wl_subcompositor::Request::GetSubsurface { id, 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,
"Surface already has a role.".into(),
);
return;
}
implement_subsurface::<U, R>(id, surface.clone(), &token);
implement_subsurface::<U, R>(id, surface.clone());
}
wl_subcompositor::Request::Destroy => {}
_ => unreachable!(),
},
None::<fn(_)>,
(),
&my_token,
)
}
@ -218,27 +206,26 @@ where
* 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
F: FnOnce(&mut SubsurfaceRole),
U: '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))
.expect("The surface does not have a subsurface role while it has a wl_subsurface?!");
}
fn implement_subsurface<U, R>(
subsurface: NewResource<wl_subsurface::WlSubsurface>,
surface: Resource<wl_surface::WlSurface>,
token: &DisplayToken,
) -> Resource<wl_subsurface::WlSubsurface>
surface: wl_surface::WlSurface,
) -> wl_subsurface::WlSubsurface
where
U: 'static,
R: RoleType + Role<SubsurfaceRole> + 'static,
{
subsurface.implement_nonsend(
subsurface.implement_closure(
|request, subsurface| {
match request {
wl_subsurface::Request::SetPosition { x, y } => {
@ -247,18 +234,18 @@ where
})
}
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) {
subsurface.post_error(
subsurface.as_ref().post_error(
wl_subsurface::Error::BadSurface as u32,
"Provided surface is not a sibling or parent.".into(),
)
}
}
wl_subsurface::Request::PlaceBelow { sibling } => {
let surface = subsurface.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) {
subsurface.post_error(
subsurface.as_ref().post_error(
wl_subsurface::Error::BadSurface as u32,
"Provided surface is not a sibling or parent.".into(),
)
@ -277,21 +264,21 @@ where
wl_subsurface::Request::Destroy => {
// Our destructor already handles it
}
_ => unreachable!(),
}
},
Some(|subsurface| destroy_subsurface::<U, R>(&subsurface)),
surface,
token,
)
}
fn destroy_subsurface<U, R>(subsurface: &Resource<wl_subsurface::WlSubsurface>)
fn destroy_subsurface<U, R>(subsurface: &wl_subsurface::WlSubsurface)
where
U: 'static,
R: RoleType + Role<SubsurfaceRole> + 'static,
{
let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap();
if surface.is_alive() {
let surface = subsurface.as_ref().user_data::<wl_surface::WlSurface>().unwrap();
if surface.as_ref().is_alive() {
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
/// times. It'll be set to `Some(...)` if the user attaches a buffer (or `NULL`) to
/// 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.
///
/// 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
/// 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
F: FnOnce(&mut SurfaceAttributes<U>) -> T,
{
@ -301,14 +301,9 @@ where
///
/// If the surface not managed by the `CompositorGlobal` that provided this token, this
/// will panic (having more than one compositor is not supported).
pub fn with_surface_tree_upward<F, T>(
&self,
surface: &Resource<WlSurface>,
initial: T,
f: F,
) -> Result<(), ()>
pub fn with_surface_tree_upward<F, T>(&self, surface: &WlSurface, initial: T, f: F) -> Result<(), ()>
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);
Ok(())
@ -321,14 +316,9 @@ where
/// supposed to be drawn: top-most first.
///
/// Behavior is the same as [`with_surface_tree_upward`](CompositorToken::with_surface_tree_upward).
pub fn with_surface_tree_downward<F, T>(
&self,
surface: &Resource<WlSurface>,
initial: T,
f: F,
) -> Result<(), ()>
pub fn with_surface_tree_downward<F, T>(&self, surface: &WlSurface, initial: T, f: F) -> Result<(), ()>
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);
Ok(())
@ -340,7 +330,7 @@ where
///
/// If the surface is not managed by the `CompositorGlobal` that provided this token, this
/// will panic (having more than one compositor is not supported).
pub fn get_parent(&self, surface: &Resource<WlSurface>) -> Option<Resource<WlSurface>> {
pub fn get_parent(&self, surface: &WlSurface) -> Option<WlSurface> {
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
/// 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)
}
}
@ -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
/// 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)
}
@ -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
/// 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
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
/// 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
R: Role<RoleData>,
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
/// will panic (having more than one compositor is not supported).
pub fn give_role_with<RoleData>(
&self,
surface: &Resource<WlSurface>,
data: RoleData,
) -> Result<(), RoleData>
pub fn give_role_with<RoleData>(&self, surface: &WlSurface, data: RoleData) -> Result<(), RoleData>
where
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
/// 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
R: Role<RoleData>,
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
/// 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
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
/// will panic (having more than one compositor is not supported).
pub fn get_region_attributes(&self, region: &Resource<wl_region::WlRegion>) -> RegionAttributes {
match region.user_data::<Mutex<RegionAttributes>>() {
pub fn get_region_attributes(&self, region: &wl_region::WlRegion) -> RegionAttributes {
match region.as_ref().user_data::<Mutex<RegionAttributes>>() {
Some(mutex) => mutex.lock().unwrap().clone(),
None => panic!("Accessing the data of foreign regions is not supported."),
}
@ -465,25 +451,17 @@ where
L: Into<Option<::slog::Logger>>,
U: Default + '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 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| {
self::handlers::implement_compositor::<U, R, Impl>(
new_compositor,
comp_token.clone(),
log.clone(),
implem.clone(),
);
self::handlers::implement_compositor::<U, R, Impl>(new_compositor, log.clone(), implem.clone());
});
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)

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 parent, then the graph is a tree and this node is its root.
pub struct SurfaceData<U, R> {
parent: Option<Resource<WlSurface>>,
children: Vec<Resource<WlSurface>>,
parent: Option<WlSurface>,
children: Vec<WlSurface>,
role: R,
attributes: SurfaceAttributes<U>,
}
@ -56,25 +56,30 @@ where
U: 'static,
R: 'static,
{
/// Cleans the `user_data` of that surface, must be called when it is destroyed
pub fn cleanup(surface: &Resource<WlSurface>) {
let my_data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
/// Cleans the `as_ref().user_data` of that surface, must be called when it is destroyed
pub fn cleanup(surface: &WlSurface) {
let my_data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut my_data = my_data_mutex.lock().unwrap();
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
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();
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
for child in &my_data.children {
// don't do anything if this child is ourselves
if child.equals(surface) {
if child.as_ref().equals(surface.as_ref()) {
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();
child_guard.parent = None;
}
@ -82,32 +87,32 @@ where
}
impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
pub fn has_a_role(surface: &Resource<WlSurface>) -> bool {
debug_assert!(surface.is_alive());
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
pub fn has_a_role(surface: &WlSurface) -> bool {
debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let data_guard = data_mutex.lock().unwrap();
<R as RoleType>::has_role(&data_guard.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
R: Role<RoleData>,
{
debug_assert!(surface.is_alive());
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::has(&data_guard.role)
}
/// Register that this surface has a role, fails if it already has one
pub fn give_role<RoleData>(surface: &Resource<WlSurface>) -> Result<(), ()>
pub fn give_role<RoleData>(surface: &WlSurface) -> Result<(), ()>
where
R: Role<RoleData>,
RoleData: Default,
{
debug_assert!(surface.is_alive());
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap();
<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
///
/// 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
R: Role<RoleData>,
{
debug_assert!(surface.is_alive());
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap();
<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
/// 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
R: Role<RoleData>,
{
debug_assert!(surface.is_alive());
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::unset(&mut data_guard.role)
}
/// 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
R: Role<RoleData>,
F: FnOnce(&mut RoleData) -> T,
{
debug_assert!(surface.is_alive());
let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap();
let data = <R as Role<RoleData>>::data_mut(&mut data_guard.role)?;
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
/// its role is now to be a subsurface
pub fn set_parent(child: &Resource<WlSurface>, parent: &Resource<WlSurface>) -> Result<(), ()> {
debug_assert!(child.is_alive());
debug_assert!(parent.is_alive());
pub fn set_parent(child: &WlSurface, parent: &WlSurface) -> Result<(), ()> {
debug_assert!(child.as_ref().is_alive());
debug_assert!(parent.as_ref().is_alive());
// 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();
// if surface already has a role, it cannot become a subsurface
<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
// 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();
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
///
/// Does nothing if it has no parent
pub fn unset_parent(child: &Resource<WlSurface>) {
debug_assert!(child.is_alive());
pub fn unset_parent(child: &WlSurface) {
debug_assert!(child.as_ref().is_alive());
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 old_parent = child_guard.parent.take();
if old_parent.is_some() {
@ -199,22 +204,27 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
};
// unregister from our 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();
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
pub fn get_parent(child: &Resource<WlSurface>) -> Option<Resource<WlSurface>> {
let child_mutex = child.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
pub fn get_parent(child: &WlSurface) -> Option<WlSurface> {
let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let child_guard = child_mutex.lock().unwrap();
child_guard.parent.as_ref().cloned()
}
/// Retrieve the parent surface (if any) of this surface
pub fn get_children(child: &Resource<WlSurface>) -> Vec<Resource<WlSurface>> {
let child_mutex = child.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
pub fn get_children(child: &WlSurface) -> Vec<WlSurface> {
let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let child_guard = child_mutex.lock().unwrap();
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
///
/// Fails if `relative_to` is not a sibling or parent of `surface`.
pub fn reorder(
surface: &Resource<WlSurface>,
to: Location,
relative_to: &Resource<WlSurface>,
) -> Result<(), ()> {
pub fn reorder(surface: &WlSurface, to: Location, relative_to: &WlSurface) -> Result<(), ()> {
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();
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
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() {
if s.equals(surface) {
if s.as_ref().equals(surface.as_ref()) {
return Some(i);
}
}
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 my_index = index_of(surface, &parent_guard.children).unwrap();
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,
/// 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
F: FnOnce(&mut SurfaceAttributes<U>) -> T,
{
let data_mutex = surface
.as_ref()
.user_data::<Mutex<SurfaceData<U, R>>>()
.expect("Accessing the data of foreign surfaces is not supported.");
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
/// 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
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
fn map<U: 'static, R: 'static, F, T>(
surface: &Resource<WlSurface>,
root: &Resource<WlSurface>,
surface: &WlSurface,
root: &WlSurface,
initial: &T,
f: &mut F,
reverse: bool,
) -> bool
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
if surface.equals(root) {
if surface.as_ref().equals(root.as_ref()) {
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 data_guard = &mut *data_guard;
// 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 data_guard = &mut *data_guard;
// call the callback on ourselves

View File

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

View File

@ -16,12 +16,12 @@ use crate::wayland::{
use super::{with_source_metadata, DataDeviceData, DnDIconRole, SeatData};
pub(crate) struct DnDGrab<U, R> {
data_source: Option<Resource<wl_data_source::WlDataSource>>,
current_focus: Option<Resource<wl_surface::WlSurface>>,
pending_offers: Vec<Resource<wl_data_offer::WlDataOffer>>,
data_source: Option<wl_data_source::WlDataSource>,
current_focus: Option<wl_surface::WlSurface>,
pending_offers: Vec<wl_data_offer::WlDataOffer>,
offer_data: Option<Arc<Mutex<OfferData>>>,
icon: Option<Resource<wl_surface::WlSurface>>,
origin: Resource<wl_surface::WlSurface>,
icon: Option<wl_surface::WlSurface>,
origin: wl_surface::WlSurface,
callback: Arc<Mutex<dyn FnMut(super::DataDeviceEvent) + Send>>,
token: CompositorToken<U, R>,
seat: Seat,
@ -29,10 +29,10 @@ pub(crate) struct DnDGrab<U, R> {
impl<U: 'static, R: Role<DnDIconRole> + 'static> DnDGrab<U, R> {
pub(crate) fn new(
source: Option<Resource<wl_data_source::WlDataSource>>,
origin: Resource<wl_surface::WlSurface>,
source: Option<wl_data_source::WlDataSource>,
origin: wl_surface::WlSurface,
seat: Seat,
icon: Option<Resource<wl_surface::WlSurface>>,
icon: Option<wl_surface::WlSurface>,
token: CompositorToken<U, R>,
callback: Arc<Mutex<dyn FnMut(super::DataDeviceEvent) + Send>>,
) -> DnDGrab<U, R> {
@ -55,7 +55,7 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
&mut self,
_handle: &mut PointerInnerHandle<'_>,
location: (f64, f64),
focus: Option<(Resource<wl_surface::WlSurface>, (f64, f64))>,
focus: Option<(wl_surface::WlSurface, (f64, f64))>,
serial: 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
if let Some(surface) = self.current_focus.take() {
// 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 {
if device.same_client_as(&surface) {
device.send(wl_data_device::Event::Leave);
if device.as_ref().same_client_as(&surface.as_ref()) {
device.leave();
}
}
// 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 {
// early return if the surface is no longer valid
let client = match surface.client() {
let client = match surface.as_ref().client() {
Some(c) => c,
None => return,
};
@ -103,16 +103,17 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
for device in seat_data
.known_devices
.iter()
.filter(|d| d.same_client_as(&surface))
.filter(|d| d.as_ref().same_client_as(&surface.as_ref()))
{
let action_choice = device
.as_ref()
.user_data::<DataDeviceData>()
.unwrap()
.action_choice
.clone();
// create a data offer
let offer = client
.create_resource::<wl_data_offer::WlDataOffer>(device.version())
.create_resource::<wl_data_offer::WlDataOffer>(device.as_ref().version())
.map(|offer| {
implement_dnd_data_offer(
offer,
@ -123,38 +124,24 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
})
.unwrap();
// 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| {
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 {
source_actions: meta.dnd_action.to_raw(),
});
offer.source_actions(meta.dnd_action.to_raw());
})
.unwrap();
device.send(wl_data_device::Event::Enter {
serial,
x: x - sx,
y: y - sy,
surface: surface.clone(),
id: Some(offer.clone()),
});
device.enter(serial, &surface, x - sx, y - sy, Some(&offer));
self.pending_offers.push(offer);
}
self.offer_data = Some(offer_data);
} else {
// 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 {
if device.same_client_as(&surface) {
device.send(wl_data_device::Event::Enter {
serial,
x: x - sx,
y: y - sy,
surface: surface.clone(),
id: None,
});
if device.as_ref().same_client_as(&surface.as_ref()) {
device.enter(serial, &surface, x - sx, y - sy, None);
}
}
}
@ -162,14 +149,10 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
self.current_focus = Some(surface);
} else {
// 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 {
if device.same_client_as(&surface) {
device.send(wl_data_device::Event::Motion {
time,
x: x - sx,
y: y - sy,
});
if device.as_ref().same_client_as(&surface.as_ref()) {
device.motion(time, x - sx, y - sy);
}
}
}
@ -201,13 +184,13 @@ impl<U: 'static, R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<U, R> {
false
};
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 {
if device.same_client_as(surface) {
if device.as_ref().same_client_as(surface.as_ref()) {
if validated {
device.send(wl_data_device::Event::Drop);
device.drop();
} 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 {
source.send(wl_data_source::Event::DndDropPerformed);
source.dnd_drop_performed();
if !validated {
source.send(wl_data_source::Event::Cancelled);
source.cancelled();
}
}
(&mut *self.callback.lock().unwrap())(super::DataDeviceEvent::DnDDropped);
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();
}
}
@ -254,12 +237,12 @@ struct OfferData {
fn implement_dnd_data_offer(
offer: NewResource<wl_data_offer::WlDataOffer>,
source: Resource<wl_data_source::WlDataSource>,
source: wl_data_source::WlDataSource,
offer_data: Arc<Mutex<OfferData>>,
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;
offer.implement(
offer.implement_closure(
move |req, offer| {
let mut data = offer_data.lock().unwrap();
match req {
@ -278,40 +261,40 @@ fn implement_dnd_data_offer(
// check if the source and associated mime type is still valid
let valid = with_source_metadata(&source, |meta| meta.mime_types.contains(&mime_type))
.unwrap_or(false)
&& source.is_alive()
&& source.as_ref().is_alive()
&& data.active;
if valid {
source.send(wl_data_source::Event::Send { mime_type, fd });
source.send(mime_type, fd);
}
let _ = ::nix::unistd::close(fd);
}
Request::Destroy => {}
Request::Finish => {
if !data.active {
offer.post_error(
offer.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer that is no longer active.".into(),
);
}
if !data.accepted {
offer.post_error(
offer.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer that has not been accepted.".into(),
);
}
if !data.dropped {
offer.post_error(
offer.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer that has not been dropped.".into(),
);
}
if data.chosen_action.is_empty() {
offer.post_error(
offer.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer with no valid action.".into(),
);
}
source.send(wl_data_source::Event::DndFinished);
source.dnd_finished();
data.active = false;
}
Request::SetActions {
@ -320,7 +303,7 @@ fn implement_dnd_data_offer(
} => {
let preferred_action = DndAction::from_bits_truncate(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,
"Invalid preferred action.".into(),
);
@ -334,13 +317,10 @@ fn implement_dnd_data_offer(
debug_assert!(
[DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&data.chosen_action)
);
offer.send(wl_data_offer::Event::Action {
dnd_action: data.chosen_action.to_raw(),
});
source.send(wl_data_source::Event::Action {
dnd_action: data.chosen_action.to_raw(),
});
offer.action(data.chosen_action.to_raw());
source.action(data.chosen_action.to_raw());
}
_ => unreachable!(),
}
},
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
pub enum DataDeviceEvent {
/// 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
DnDStarted {
/// The data source provided by the client
///
/// 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.
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
/// 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
///
@ -116,12 +116,12 @@ pub struct DnDIconRole;
enum Selection {
Empty,
Client(Resource<wl_data_source::WlDataSource>),
Client(wl_data_source::WlDataSource),
Compositor(SourceMetadata),
}
struct SeatData {
known_devices: Vec<Resource<wl_data_device::WlDataDevice>>,
known_devices: Vec<wl_data_device::WlDataDevice>,
selection: Selection,
log: ::slog::Logger,
current_focus: Option<Client>,
@ -146,7 +146,7 @@ impl SeatData {
// first sanitize the selection, reseting it to null if the client holding
// it dropped it
let cleanup = if let Selection::Client(ref data_source) = self.selection {
!data_source.is_alive()
!data_source.as_ref().is_alive()
} else {
false
};
@ -159,25 +159,25 @@ impl SeatData {
// send an empty selection
for dd in &self.known_devices {
// 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;
}
dd.send(wl_data_device::Event::Selection { id: None });
dd.selection(None);
}
}
Selection::Client(ref data_source) => {
for dd in &self.known_devices {
// 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;
}
let source = data_source.clone();
let log = self.log.clone();
// create a corresponding data offer
let offer = client
.create_resource::<wl_data_offer::WlDataOffer>(dd.version())
.create_resource::<wl_data_offer::WlDataOffer>(dd.as_ref().version())
.unwrap()
.implement(
.implement_closure(
move |req, _offer| match req {
wl_data_offer::Request::Receive { fd, mime_type } => {
// check if the source and associated mime type is still valid
@ -185,12 +185,12 @@ impl SeatData {
meta.mime_types.contains(&mime_type)
})
.unwrap_or(false)
&& source.is_alive();
&& source.as_ref().is_alive();
if !valid {
// deny the receive
debug!(log, "Denying a wl_data_offer.receive with invalid source.");
} else {
source.send(wl_data_source::Event::Send { mime_type, fd });
source.send(mime_type, fd);
}
let _ = ::nix::unistd::close(fd);
}
@ -200,30 +200,35 @@ impl SeatData {
(),
);
// 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| {
for mime_type in meta.mime_types.iter().cloned() {
offer.send(wl_data_offer::Event::Offer { mime_type })
offer.offer(mime_type);
}
})
.unwrap();
dd.send(wl_data_device::Event::Selection { id: Some(offer) });
dd.selection(Some(&offer));
}
}
Selection::Compositor(ref meta) => {
for dd in &self.known_devices {
// 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;
}
let log = self.log.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
let offer = client
.create_resource::<wl_data_offer::WlDataOffer>(dd.version())
.create_resource::<wl_data_offer::WlDataOffer>(dd.as_ref().version())
.unwrap()
.implement(
.implement_closure(
move |req, _offer| match req {
wl_data_offer::Request::Receive { fd, mime_type } => {
// check if the associated mime type is valid
@ -244,11 +249,11 @@ impl SeatData {
(),
);
// 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() {
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>>,
token: CompositorToken<U, R>,
log: ::slog::Logger,
) -> Resource<wl_data_device_manager::WlDataDeviceManager>
) -> wl_data_device_manager::WlDataDeviceManager
where
F: FnMut(DndAction, DndAction) -> DndAction + Send + 'static,
C: FnMut(DataDeviceEvent) + Send + 'static,
@ -387,7 +392,7 @@ where
U: 'static,
{
use self::wl_data_device_manager::Request;
new_ddm.implement(
new_ddm.implement_closure(
move |req, _ddm| match req {
Request::CreateDataSource { id } => {
self::data_source::implement_data_source(id);
@ -412,6 +417,7 @@ where
error!(log, "Unmanaged seat given to a data device.");
}
},
_ => unreachable!(),
},
None::<fn(_)>,
(),
@ -430,7 +436,7 @@ fn implement_data_device<F, C, U, R>(
action_choice: Arc<Mutex<F>>,
token: CompositorToken<U, R>,
log: ::slog::Logger,
) -> Resource<wl_data_device::WlDataDevice>
) -> wl_data_device::WlDataDevice
where
F: FnMut(DndAction, DndAction) -> DndAction + Send + 'static,
C: FnMut(DataDeviceEvent) + Send + 'static,
@ -442,7 +448,7 @@ where
callback: callback.clone(),
action_choice,
};
new_dd.implement(
new_dd.implement_closure(
move |req, dd| match req {
Request::StartDrag {
source,
@ -455,7 +461,7 @@ where
if pointer.has_grab(serial) {
if let Some(ref icon) = icon {
if token.give_role::<DnDIconRole>(icon).is_err() {
dd.post_error(
dd.as_ref().post_error(
wl_data_device::Error::Role as u32,
"Given surface already has an other role".into(),
);
@ -486,6 +492,7 @@ where
Request::SetSelection { source, serial: _ } => {
if let Some(keyboard) = seat.get_keyboard() {
if dd
.as_ref()
.client()
.as_ref()
.map(|c| keyboard.has_focus(c))
@ -511,8 +518,9 @@ where
.lock()
.unwrap()
.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(_)>,
dd_data,

View File

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

View File

@ -94,7 +94,7 @@ pub struct PhysicalProperties {
struct Inner {
name: String,
log: ::slog::Logger,
instances: Vec<Resource<WlOutput>>,
instances: Vec<WlOutput>,
physical: PhysicalProperties,
location: (i32, i32),
transform: Transform,
@ -105,7 +105,7 @@ struct Inner {
}
impl Inner {
fn new_global(&mut self, output: Resource<WlOutput>) {
fn new_global(&mut self, output: WlOutput) {
trace!(self.log, "New global instantiated.");
if self.modes.is_empty() {
@ -127,32 +127,27 @@ impl Inner {
if Some(mode) == self.preferred_mode {
flags |= WMode::Preferred;
}
output.send(Event::Mode {
flags,
width: mode.width,
height: mode.height,
refresh: mode.refresh,
});
output.mode(flags, mode.width, mode.height, mode.refresh);
}
if output.version() >= 2 {
output.send(Event::Scale { factor: self.scale });
output.send(Event::Done);
if output.as_ref().version() >= 2 {
output.scale(self.scale);
output.done();
}
self.instances.push(output);
}
fn send_geometry(&self, output: &Resource<WlOutput>) {
output.send(Event::Geometry {
x: self.location.0,
y: self.location.1,
physical_width: self.physical.width,
physical_height: self.physical.height,
subpixel: self.physical.subpixel,
make: self.physical.make.clone(),
model: self.physical.model.clone(),
transform: self.transform,
});
fn send_geometry(&self, output: &WlOutput) {
output.geometry(
self.location.0,
self.location.1,
self.physical.width,
self.physical.height,
self.physical.subpixel,
self.physical.make.clone(),
self.physical.model.clone(),
self.transform,
);
}
}
@ -199,14 +194,15 @@ impl Output {
let output = Output { inner: inner.clone() };
let global = display.create_global(3, move |new_output: NewResource<_>, _version| {
let output = new_output.implement(
|req, _| {
// this will break if new variants are added :)
let Request::Release = req;
},
Some(|output: Resource<WlOutput>| {
let inner = output.user_data::<Arc<Mutex<Inner>>>().unwrap();
inner.lock().unwrap().instances.retain(|o| !o.equals(&output));
let output = new_output.implement_closure(
|_, _| {},
Some(|output: WlOutput| {
let inner = output.as_ref().user_data::<Arc<Mutex<Inner>>>().unwrap();
inner
.lock()
.unwrap()
.instances
.retain(|o| !o.as_ref().equals(&output.as_ref()));
}),
inner.clone(),
);
@ -285,34 +281,29 @@ impl Output {
}
for output in &inner.instances {
if let Some(mode) = new_mode {
output.send(Event::Mode {
flags,
width: mode.width,
height: mode.height,
refresh: mode.refresh,
});
output.mode(flags, mode.width, mode.height, mode.refresh);
}
if new_transform.is_some() {
inner.send_geometry(output);
}
if let Some(scale) = new_scale {
if output.version() >= 2 {
output.send(Event::Scale { factor: scale });
if output.as_ref().version() >= 2 {
output.scale(scale);
}
}
if output.version() >= 2 {
output.send(Event::Done);
if output.as_ref().version() >= 2 {
output.done();
}
}
}
/// 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
.lock()
.unwrap()
.instances
.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 {
known_kbds: Vec<Resource<WlKeyboard>>,
focus: Option<Resource<WlSurface>>,
known_kbds: Vec<WlKeyboard>,
focus: Option<WlSurface>,
pressed_keys: Vec<u32>,
mods_state: ModifiersState,
keymap: xkb::Keymap,
state: xkb::State,
repeat_rate: 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
@ -124,7 +124,7 @@ impl KbdInternal {
xkb_config: XkbConfig<'_>,
repeat_rate: i32,
repeat_delay: i32,
focus_hook: Box<dyn FnMut(Option<&Resource<WlSurface>>)>,
focus_hook: Box<dyn FnMut(Option<&WlSurface>)>,
) -> Result<KbdInternal, ()> {
// 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
@ -205,11 +205,11 @@ impl KbdInternal {
fn with_focused_kbds<F>(&self, mut f: F)
where
F: FnMut(&Resource<WlKeyboard>, &Resource<WlSurface>),
F: FnMut(&WlKeyboard, &WlSurface),
{
if let Some(ref surface) = self.focus {
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);
}
}
@ -235,7 +235,7 @@ pub(crate) fn create_keyboard_handler<F>(
focus_hook: F,
) -> Result<KeyboardHandle, Error>
where
F: FnMut(Option<&Resource<WlSurface>>) + 'static,
F: FnMut(Option<&WlSurface>) + 'static,
{
let log = logger.new(o!("smithay_module" => "xkbcommon_handler"));
info!(log, "Initializing a xkbcommon handler with keymap query";
@ -332,20 +332,9 @@ impl KeyboardHandle {
};
guard.with_focused_kbds(|kbd, _| {
if let Some((dep, la, lo, gr)) = modifiers {
kbd.send(Event::Modifiers {
serial,
mods_depressed: dep,
mods_latched: la,
mods_locked: lo,
group: gr,
});
kbd.modifiers(serial, dep, la, lo, gr);
}
kbd.send(Event::Key {
serial,
time,
key: keycode,
state: wl_state,
});
kbd.key(serial, time, keycode, wl_state);
});
if guard.focus.is_some() {
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)
/// 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.
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 same = guard
.focus
.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);
if !same {
// unset old focus
guard.with_focused_kbds(|kbd, s| {
kbd.send(Event::Leave {
serial,
surface: s.clone(),
});
kbd.leave(serial, &s);
});
// set new focus
@ -383,18 +369,8 @@ impl KeyboardHandle {
let (dep, la, lo, gr) = guard.serialize_modifiers();
let keys = guard.serialize_pressed_keys();
guard.with_focused_kbds(|kbd, surface| {
kbd.send(Event::Modifiers {
serial,
mods_depressed: dep,
mods_latched: la,
mods_locked: lo,
group: gr,
});
kbd.send(Event::Enter {
serial,
surface: surface.clone(),
keys: keys.clone(),
});
kbd.modifiers(serial, dep, la, lo, gr);
kbd.enter(serial, &surface, keys.clone());
});
{
let KbdInternal {
@ -422,7 +398,7 @@ impl KeyboardHandle {
.unwrap()
.focus
.as_ref()
.and_then(|f| f.client())
.and_then(|f| f.as_ref().client())
.map(|c| c.equals(client))
.unwrap_or(false)
}
@ -432,18 +408,18 @@ impl KeyboardHandle {
/// The keymap will automatically be sent to it
///
/// 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");
// prepare a tempfile with the keymap, to send it to the client
let ret = tempfile().and_then(|mut f| {
f.write_all(self.arc.keymap.as_bytes())?;
f.flush()?;
kbd.send(Event::Keymap {
format: KeymapFormat::XkbV1,
fd: f.as_raw_fd(),
size: self.arc.keymap.as_bytes().len() as u32,
});
kbd.keymap(
KeymapFormat::XkbV1,
f.as_raw_fd(),
self.arc.keymap.as_bytes().len() as u32,
);
Ok(())
});
@ -456,11 +432,8 @@ impl KeyboardHandle {
};
let mut guard = self.arc.internal.lock().unwrap();
if kbd.version() >= 4 {
kbd.send(Event::RepeatInfo {
rate: guard.repeat_rate,
delay: guard.repeat_delay,
});
if kbd.as_ref().version() >= 4 {
kbd.repeat_info(guard.repeat_rate, guard.repeat_delay);
}
guard.known_kbds.push(kbd);
}
@ -471,7 +444,7 @@ impl KeyboardHandle {
guard.repeat_delay = delay;
guard.repeat_rate = rate;
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(
new_keyboard: NewResource<WlKeyboard>,
handle: Option<&KeyboardHandle>,
) -> Resource<WlKeyboard> {
) -> WlKeyboard {
let destructor = match handle {
Some(h) => {
let arc = h.arc.clone();
Some(move |keyboard: Resource<_>| {
Some(move |keyboard: WlKeyboard| {
arc.internal
.lock()
.unwrap()
.known_kbds
.retain(|k| !k.equals(&keyboard))
.retain(|k| !k.as_ref().equals(&keyboard.as_ref()))
})
}
None => None,
};
new_keyboard.implement(
new_keyboard.implement_closure(
|request, _keyboard| {
match request {
Request::Release => {
// Our destructors already handle it
}
_ => unreachable!(),
}
},
destructor,

View File

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

View File

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

View File

@ -98,8 +98,8 @@ pub struct ShellSurfaceRole<D: 'static> {
/// A handle to a shell surface
pub struct ShellSurface<U, R, D> {
wl_surface: Resource<wl_surface::WlSurface>,
shell_surface: Resource<wl_shell_surface::WlShellSurface>,
wl_surface: wl_surface::WlSurface,
shell_surface: wl_shell_surface::WlShellSurface,
token: CompositorToken<U, R>,
_d: ::std::marker::PhantomData<D>,
}
@ -112,18 +112,18 @@ where
{
/// Is the shell surface referred by this handle still alive?
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?
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
///
/// 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() {
Some(&self.wl_surface)
} else {
@ -153,7 +153,7 @@ where
}
});
if let Ok(true) = ret {
self.shell_surface.send(wl_shell_surface::Event::Ping { serial });
self.shell_surface.ping(serial);
Ok(())
} else {
Err(())
@ -162,16 +162,12 @@ where
/// 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) {
self.shell_surface.send(wl_shell_surface::Event::Configure {
edges,
width: size.0 as i32,
height: size.1 as i32,
})
self.shell_surface.configure(edges, size.0 as i32, size.1 as i32)
}
/// Signal a popup surface that it has lost focus
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
@ -195,7 +191,7 @@ pub enum ShellSurfaceKind {
/// and as such should only be visible in their parent window is, and on top of it.
Transient {
/// The surface considered as parent
parent: Resource<wl_surface::WlSurface>,
parent: wl_surface::WlSurface,
/// Location relative to the parent
location: (i32, i32),
/// Wether this window should be marked as inactive
@ -208,7 +204,7 @@ pub enum ShellSurfaceKind {
/// Framerate (relevant only for driver fullscreen)
framerate: u32,
/// Requested output if any
output: Option<Resource<wl_output::WlOutput>>,
output: Option<wl_output::WlOutput>,
},
/// A popup surface
///
@ -216,7 +212,7 @@ pub enum ShellSurfaceKind {
/// contexts.
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
/// popup
serial: u32,
@ -226,7 +222,7 @@ pub enum ShellSurfaceKind {
location: (i32, i32),
/// Seat associated this the input that triggered the creation of the
/// popup. Used to define when the "popup done" event is sent.
seat: Resource<wl_seat::WlSeat>,
seat: wl_seat::WlSeat,
},
/// A maximized surface
///
@ -234,7 +230,7 @@ pub enum ShellSurfaceKind {
/// while keeping any relevant desktop-environment interface visible.
Maximized {
/// 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: u32,
/// Seat associated with the move
seat: Resource<wl_seat::WlSeat>,
seat: wl_seat::WlSeat,
},
/// 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: u32,
/// Seat associated with the resize
seat: Resource<wl_seat::WlSeat>,
seat: wl_seat::WlSeat,
/// Direction of the resize
edges: wl_shell_surface::Resize,
},
@ -331,21 +327,13 @@ where
let implementation = Rc::new(RefCell::new(implementation));
let dtoken = display.get_token();
let state = Arc::new(Mutex::new(ShellState {
known_surfaces: Vec::new(),
}));
let state2 = state.clone();
let global = display.create_global(1, move |shell, _version| {
self::wl_handlers::implement_shell(
shell,
dtoken.clone(),
ctoken,
implementation.clone(),
state2.clone(),
);
self::wl_handlers::implement_shell(shell, ctoken, implementation.clone(), state2.clone());
});
(state, global)

View File

@ -6,7 +6,7 @@ use std::{
use wayland_server::{
protocol::{wl_shell, wl_shell_surface, wl_surface},
DisplayToken, NewResource, Resource,
NewResource, Resource,
};
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>(
shell: NewResource<wl_shell::WlShell>,
dtoken: DisplayToken,
ctoken: CompositorToken<U, R>,
implementation: Rc<RefCell<Impl>>,
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,
Impl: FnMut(ShellRequest<U, R, D>) + 'static,
{
let dtoken2 = dtoken.clone();
shell.implement_nonsend(
move |req, shell: Resource<_>| {
let wl_shell::Request::GetShellSurface { id, surface } = req;
shell.implement_closure(
move |req, shell| {
let (id, surface) = match req {
wl_shell::Request::GetShellSurface { id, surface } => (id, surface),
_ => unreachable!(),
};
let role_data = ShellSurfaceRole {
title: "".into(),
class: "".into(),
@ -36,17 +37,13 @@ pub(crate) fn implement_shell<U, R, D, Impl>(
user_data: Default::default(),
};
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;
}
let shell_surface = implement_shell_surface(
id,
surface,
implementation.clone(),
dtoken.clone(),
ctoken,
state.clone(),
);
let shell_surface =
implement_shell_surface(id, surface, implementation.clone(), ctoken, state.clone());
state
.lock()
.unwrap()
@ -59,12 +56,11 @@ pub(crate) fn implement_shell<U, R, D, Impl>(
},
None::<fn(_)>,
(),
&dtoken2,
);
}
fn make_handle<U, R, SD>(
shell_surface: &Resource<wl_shell_surface::WlShellSurface>,
shell_surface: &wl_shell_surface::WlShellSurface,
token: CompositorToken<U, R>,
) -> ShellSurface<U, R, SD>
where
@ -73,6 +69,7 @@ where
SD: 'static,
{
let data = shell_surface
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
ShellSurface {
@ -84,18 +81,17 @@ where
}
pub(crate) struct ShellSurfaceUserData<U, R, SD> {
surface: Resource<wl_surface::WlSurface>,
surface: wl_surface::WlSurface,
state: Arc<Mutex<ShellState<U, R, SD>>>,
}
fn implement_shell_surface<U, R, Impl, SD>(
shell_surface: NewResource<wl_shell_surface::WlShellSurface>,
surface: Resource<wl_surface::WlSurface>,
surface: wl_surface::WlSurface,
implementation: Rc<RefCell<Impl>>,
dtoken: DisplayToken,
ctoken: CompositorToken<U, R>,
state: Arc<Mutex<ShellState<U, R, SD>>>,
) -> Resource<wl_shell_surface::WlShellSurface>
) -> wl_shell_surface::WlShellSurface
where
U: 'static,
SD: 'static,
@ -103,9 +99,10 @@ where
Impl: FnMut(ShellRequest<U, R, SD>) + 'static,
{
use self::wl_shell_surface::Request;
shell_surface.implement_nonsend(
move |req, shell_surface: Resource<_>| {
shell_surface.implement_closure(
move |req, shell_surface| {
let data = shell_surface
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
let mut user_impl = implementation.borrow_mut();
@ -193,15 +190,16 @@ where
.with_role_data(&data.surface, |data| data.class = class_)
.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
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
data.state.lock().unwrap().cleanup_surfaces();
}),
ShellSurfaceUserData { surface, state },
&dtoken,
)
}

View File

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

View File

@ -4,7 +4,7 @@ use crate::wayland::compositor::{roles::*, CompositorToken};
use wayland_protocols::xdg_shell::server::{
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;
@ -17,20 +17,19 @@ use super::{
pub(crate) fn implement_wm_base<U, R, SD>(
shell: NewResource<xdg_wm_base::XdgWmBase>,
shell_data: &ShellData<U, R, SD>,
) -> Resource<xdg_wm_base::XdgWmBase>
) -> xdg_wm_base::XdgWmBase
where
U: 'static,
R: Role<XdgSurfaceRole> + 'static,
SD: Default + 'static,
{
let shell = shell.implement_nonsend(
let shell = shell.implement_closure(
wm_implementation::<U, R, SD>,
None::<fn(_)>,
ShellUserData {
shell_data: shell_data.clone(),
client_data: Mutex::new(make_shell_client_data::<SD>()),
},
&shell_data.display_token,
);
let mut user_impl = shell_data.user_impl.borrow_mut();
(&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>(
resource: &Resource<xdg_wm_base::XdgWmBase>,
resource: &xdg_wm_base::XdgWmBase,
token: CompositorToken<U, R>,
) -> ShellClient<U, R, SD> {
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
U: 'static,
R: Role<XdgSurfaceRole> + '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 {
xdg_wm_base::Request::Destroy => {
// all is handled by destructor
}
xdg_wm_base::Request::CreatePositioner { id } => {
implement_positioner(id, &data.shell_data.display_token);
implement_positioner(id);
}
xdg_wm_base::Request::GetXdgSurface { id, surface } => {
let role_data = XdgSurfaceRole {
@ -86,13 +85,13 @@ where
.give_role_with(&surface, role_data)
.is_err()
{
shell.post_error(
shell.as_ref().post_error(
xdg_wm_base::Error::Role as u32,
"Surface already has a role.".into(),
);
return;
}
id.implement_nonsend(
id.implement_closure(
xdg_surface_implementation::<U, R, SD>,
Some(destroy_surface::<U, R, SD>),
XdgSurfaceUserData {
@ -100,7 +99,6 @@ where
wl_surface: surface,
wm_base: shell.clone(),
},
&data.shell_data.display_token,
);
}
xdg_wm_base::Request::Pong { serial } => {
@ -120,6 +118,7 @@ where
});
}
}
_ => unreachable!(),
}
}
@ -129,11 +128,13 @@ where
fn implement_positioner(
positioner: NewResource<xdg_positioner::XdgPositioner>,
token: &DisplayToken,
) -> Resource<xdg_positioner::XdgPositioner> {
positioner.implement_nonsend(
|request, positioner: Resource<_>| {
let mutex = positioner.user_data::<RefCell<PositionerState>>().unwrap();
) -> xdg_positioner::XdgPositioner {
positioner.implement_closure(
|request, positioner| {
let mutex = positioner
.as_ref()
.user_data::<RefCell<PositionerState>>()
.unwrap();
let mut state = mutex.borrow_mut();
match request {
xdg_positioner::Request::Destroy => {
@ -141,7 +142,7 @@ fn implement_positioner(
}
xdg_positioner::Request::SetSize { width, height } => {
if width < 1 || height < 1 {
positioner.post_error(
positioner.as_ref().post_error(
xdg_positioner::Error::InvalidInput as u32,
"Invalid size for positioner.".into(),
);
@ -151,7 +152,7 @@ fn implement_positioner(
}
xdg_positioner::Request::SetAnchorRect { x, y, width, height } => {
if width < 1 || height < 1 {
positioner.post_error(
positioner.as_ref().post_error(
xdg_positioner::Error::InvalidInput as u32,
"Invalid size for positioner's anchor rectangle.".into(),
);
@ -175,11 +176,11 @@ fn implement_positioner(
xdg_positioner::Request::SetOffset { x, y } => {
state.offset = (x, y);
}
_ => unreachable!(),
}
},
None::<fn(_)>,
RefCell::new(PositionerState::new()),
token,
)
}
@ -189,18 +190,21 @@ fn implement_positioner(
struct XdgSurfaceUserData<U, R, SD> {
shell_data: ShellData<U, R, SD>,
wl_surface: Resource<wl_surface::WlSurface>,
wm_base: Resource<xdg_wm_base::XdgWmBase>,
wl_surface: wl_surface::WlSurface,
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
U: 'static,
R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{
let data = surface.user_data::<XdgSurfaceUserData<U, R, SD>>().unwrap();
if !data.wl_surface.is_alive() {
let data = surface
.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
// trying to change the role but it's a cleanup (possibly a
// disconnecting client), ignore the protocol check.
@ -212,7 +216,7 @@ where
if let XdgSurfacePendingState::None = rdata.pending_state {
// all is good
} else {
data.wm_base.post_error(
data.wm_base.as_ref().post_error(
xdg_wm_base::Error::Role as u32,
"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?!");
}
fn xdg_surface_implementation<U, R, SD>(
request: xdg_surface::Request,
xdg_surface: Resource<xdg_surface::XdgSurface>,
) where
fn xdg_surface_implementation<U, R, SD>(request: xdg_surface::Request, xdg_surface: xdg_surface::XdgSurface)
where
U: 'static,
R: Role<XdgSurfaceRole> + '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 {
xdg_surface::Request::Destroy => {
// 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?!");
let toplevel = id.implement_nonsend(
let toplevel = id.implement_closure(
toplevel_implementation::<U, R, SD>,
Some(destroy_toplevel::<U, R, SD>),
ShellSurfaceUserData {
@ -256,7 +261,6 @@ fn xdg_surface_implementation<U, R, SD>(
xdg_surface: xdg_surface.clone(),
wm_base: data.wm_base.clone(),
},
&data.shell_data.display_token,
);
data.shell_data
@ -275,10 +279,16 @@ fn xdg_surface_implementation<U, R, SD>(
parent,
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_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()
});
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?!");
let popup = id.implement_nonsend(
let popup = id.implement_closure(
xg_popup_implementation::<U, R, SD>,
Some(destroy_popup::<U, R, SD>),
ShellSurfaceUserData {
@ -299,7 +309,6 @@ fn xdg_surface_implementation<U, R, SD>(
xdg_surface: xdg_surface.clone(),
wm_base: data.wm_base.clone(),
},
&data.shell_data.display_token,
);
data.shell_data
@ -334,7 +343,7 @@ fn xdg_surface_implementation<U, R, SD>(
});
if !found {
// 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,
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?!");
}
_ => unreachable!(),
}
}
@ -352,15 +362,15 @@ fn xdg_surface_implementation<U, R, SD>(
pub(crate) struct ShellSurfaceUserData<U, R, SD> {
pub(crate) shell_data: ShellData<U, R, SD>,
pub(crate) wl_surface: Resource<wl_surface::WlSurface>,
pub(crate) wm_base: Resource<xdg_wm_base::XdgWmBase>,
pub(crate) xdg_surface: Resource<xdg_surface::XdgSurface>,
pub(crate) wl_surface: wl_surface::WlSurface,
pub(crate) wm_base: xdg_wm_base::XdgWmBase,
pub(crate) xdg_surface: xdg_surface::XdgSurface,
}
// Utility functions allowing to factor out a lot of the upcoming logic
fn with_surface_toplevel_data<U, R, SD, F>(
shell_data: &ShellData<U, R, SD>,
toplevel: &Resource<xdg_toplevel::XdgToplevel>,
toplevel: &xdg_toplevel::XdgToplevel,
f: F,
) where
U: 'static,
@ -368,7 +378,10 @@ fn with_surface_toplevel_data<U, R, SD, F>(
SD: 'static,
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
.compositor_token
.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?!");
}
pub fn send_toplevel_configure<U, R, SD>(
resource: &Resource<xdg_toplevel::XdgToplevel>,
configure: ToplevelConfigure,
) where
pub fn send_toplevel_configure<U, R, SD>(resource: &xdg_toplevel::XdgToplevel, configure: ToplevelConfigure)
where
U: 'static,
R: Role<XdgSurfaceRole> + '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));
// convert the Vec<State> (which is really a Vec<u32>) into Vec<u8>
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) }
};
let serial = configure.serial;
resource.send(xdg_toplevel::Event::Configure {
width,
height,
states,
});
data.xdg_surface.send(xdg_surface::Event::Configure { serial });
resource.configure(width, height, states);
data.xdg_surface.configure(serial);
// Add the configure as pending
data.shell_data
.compositor_token
@ -412,9 +422,12 @@ pub fn send_toplevel_configure<U, R, SD>(
}
fn make_toplevel_handle<U: 'static, R: 'static, SD: 'static>(
resource: &Resource<xdg_toplevel::XdgToplevel>,
resource: &xdg_toplevel::XdgToplevel,
) -> 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 {
wl_surface: data.wl_surface.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>(
request: xdg_toplevel::Request,
toplevel: Resource<xdg_toplevel::XdgToplevel>,
) where
fn toplevel_implementation<U, R, SD>(request: xdg_toplevel::Request, toplevel: xdg_toplevel::XdgToplevel)
where
U: 'static,
R: Role<XdgSurfaceRole> + '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 {
xdg_toplevel::Request::Destroy => {
// 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| {
toplevel_data.parent = parent.map(|toplevel_surface_parent| {
toplevel_surface_parent
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap()
.wl_surface
@ -525,17 +540,21 @@ fn toplevel_implementation<U, R, SD>(
let mut user_impl = data.shell_data.user_impl.borrow_mut();
(&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
U: 'static,
R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{
let data = toplevel.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap();
if !data.wl_surface.is_alive() {
let data = toplevel
.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
// trying to change the role but it's a cleanup (possibly a
// disconnecting client), ignore the protocol check.
@ -561,20 +580,21 @@ where
* xdg_popup
*/
pub(crate) fn send_popup_configure<U, R, SD>(
resource: &Resource<xdg_popup::XdgPopup>,
configure: PopupConfigure,
) where
pub(crate) fn send_popup_configure<U, R, SD>(resource: &xdg_popup::XdgPopup, configure: PopupConfigure)
where
U: 'static,
R: Role<XdgSurfaceRole> + '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 (width, height) = configure.size;
let serial = configure.serial;
resource.send(xdg_popup::Event::Configure { x, y, width, height });
data.xdg_surface.send(xdg_surface::Event::Configure { serial });
resource.configure(x, y, width, height);
data.xdg_surface.configure(serial);
// Add the configure as pending
data.shell_data
.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>(
resource: &Resource<xdg_popup::XdgPopup>,
resource: &xdg_popup::XdgPopup,
) -> 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 {
wl_surface: data.wl_surface.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
U: 'static,
R: Role<XdgSurfaceRole> + '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 {
xdg_popup::Request::Destroy => {
// all is handled by our destructor
@ -614,17 +640,21 @@ where
serial,
});
}
_ => unreachable!(),
}
}
fn destroy_popup<U, R, SD>(popup: Resource<xdg_popup::XdgPopup>)
fn destroy_popup<U, R, SD>(popup: xdg_popup::XdgPopup)
where
U: 'static,
R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{
let data = popup.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap();
if !data.wl_surface.is_alive() {
let data = popup
.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
// trying to change the role but it's a cleanup (possibly a
// disconnecting client), ignore the protocol check.

View File

@ -7,7 +7,7 @@ use wayland_protocols::{
},
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;
@ -20,20 +20,19 @@ use super::{
pub(crate) fn implement_shell<U, R, SD>(
shell: NewResource<zxdg_shell_v6::ZxdgShellV6>,
shell_data: &ShellData<U, R, SD>,
) -> Resource<zxdg_shell_v6::ZxdgShellV6>
) -> zxdg_shell_v6::ZxdgShellV6
where
U: 'static,
R: Role<XdgSurfaceRole> + 'static,
SD: Default + 'static,
{
let shell = shell.implement_nonsend(
let shell = shell.implement_closure(
shell_implementation::<U, R, SD>,
None::<fn(_)>,
ShellUserData {
shell_data: shell_data.clone(),
client_data: Mutex::new(make_shell_client_data::<SD>()),
},
&shell_data.display_token,
);
let mut user_impl = shell_data.user_impl.borrow_mut();
(&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>(
resource: &Resource<zxdg_shell_v6::ZxdgShellV6>,
resource: &zxdg_shell_v6::ZxdgShellV6,
token: CompositorToken<U, R>,
) -> ShellClient<U, R, SD> {
ShellClient {
@ -62,21 +61,19 @@ pub(crate) fn make_shell_client<U, R, SD>(
}
}
fn shell_implementation<U, R, SD>(
request: zxdg_shell_v6::Request,
shell: Resource<zxdg_shell_v6::ZxdgShellV6>,
) where
fn shell_implementation<U, R, SD>(request: zxdg_shell_v6::Request, shell: zxdg_shell_v6::ZxdgShellV6)
where
U: 'static,
R: Role<XdgSurfaceRole> + '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 {
zxdg_shell_v6::Request::Destroy => {
// all is handled by destructor
}
zxdg_shell_v6::Request::CreatePositioner { id } => {
implement_positioner(id, &data.shell_data.display_token);
implement_positioner(id);
}
zxdg_shell_v6::Request::GetXdgSurface { id, surface } => {
let role_data = XdgSurfaceRole {
@ -91,13 +88,13 @@ fn shell_implementation<U, R, SD>(
.give_role_with(&surface, role_data)
.is_err()
{
shell.post_error(
shell.as_ref().post_error(
zxdg_shell_v6::Error::Role as u32,
"Surface already has a role.".into(),
);
return;
}
id.implement_nonsend(
id.implement_closure(
xdg_surface_implementation::<U, R, SD>,
Some(destroy_surface::<U, R, SD>),
XdgSurfaceUserData {
@ -105,7 +102,6 @@ fn shell_implementation<U, R, SD>(
wl_surface: surface.clone(),
shell: shell.clone(),
},
&data.shell_data.display_token,
);
}
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(
positioner: NewResource<zxdg_positioner_v6::ZxdgPositionerV6>,
token: &DisplayToken,
) -> Resource<zxdg_positioner_v6::ZxdgPositionerV6> {
positioner.implement_nonsend(
|request, positioner: Resource<_>| {
let mutex = positioner.user_data::<RefCell<PositionerState>>().unwrap();
) -> zxdg_positioner_v6::ZxdgPositionerV6 {
positioner.implement_closure(
|request, positioner| {
let mutex = positioner
.as_ref()
.user_data::<RefCell<PositionerState>>()
.unwrap();
let mut state = mutex.borrow_mut();
match request {
zxdg_positioner_v6::Request::Destroy => {
@ -146,7 +145,7 @@ fn implement_positioner(
}
zxdg_positioner_v6::Request::SetSize { width, height } => {
if width < 1 || height < 1 {
positioner.post_error(
positioner.as_ref().post_error(
zxdg_positioner_v6::Error::InvalidInput as u32,
"Invalid size for positioner.".into(),
);
@ -156,7 +155,7 @@ fn implement_positioner(
}
zxdg_positioner_v6::Request::SetAnchorRect { x, y, width, height } => {
if width < 1 || height < 1 {
positioner.post_error(
positioner.as_ref().post_error(
zxdg_positioner_v6::Error::InvalidInput as u32,
"Invalid size for positioner's anchor rectangle.".into(),
);
@ -168,7 +167,7 @@ fn implement_positioner(
if let Some(anchor) = zxdg_anchor_to_xdg(anchor) {
state.anchor_edges = anchor;
} else {
positioner.post_error(
positioner.as_ref().post_error(
zxdg_positioner_v6::Error::InvalidInput as u32,
"Invalid anchor for positioner.".into(),
);
@ -178,7 +177,7 @@ fn implement_positioner(
if let Some(gravity) = zxdg_gravity_to_xdg(gravity) {
state.gravity = gravity;
} else {
positioner.post_error(
positioner.as_ref().post_error(
zxdg_positioner_v6::Error::InvalidInput as u32,
"Invalid gravity for positioner.".into(),
);
@ -194,11 +193,11 @@ fn implement_positioner(
zxdg_positioner_v6::Request::SetOffset { x, y } => {
state.offset = (x, y);
}
_ => unreachable!(),
}
},
None::<fn(_)>,
RefCell::new(PositionerState::new()),
token,
)
}
@ -208,18 +207,21 @@ fn implement_positioner(
struct XdgSurfaceUserData<U, R, SD> {
shell_data: ShellData<U, R, SD>,
wl_surface: Resource<wl_surface::WlSurface>,
shell: Resource<zxdg_shell_v6::ZxdgShellV6>,
wl_surface: wl_surface::WlSurface,
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
U: 'static,
R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{
let data = surface.user_data::<XdgSurfaceUserData<U, R, SD>>().unwrap();
if !data.wl_surface.is_alive() {
let data = surface
.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
// trying to change the role but it's a cleanup (possibly a
// disconnecting client), ignore the protocol check.
@ -231,7 +233,7 @@ where
if let XdgSurfacePendingState::None = rdata.pending_state {
// all is good
} else {
data.shell.post_error(
data.shell.as_ref().post_error(
zxdg_shell_v6::Error::Role as u32,
"xdg_surface was destroyed before its role object".into(),
);
@ -242,13 +244,16 @@ where
fn xdg_surface_implementation<U, R, SD>(
request: zxdg_surface_v6::Request,
xdg_surface: Resource<zxdg_surface_v6::ZxdgSurfaceV6>,
xdg_surface: zxdg_surface_v6::ZxdgSurfaceV6,
) where
U: 'static,
R: Role<XdgSurfaceRole> + '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 {
zxdg_surface_v6::Request::Destroy => {
// 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?!");
let toplevel = id.implement_nonsend(
let toplevel = id.implement_closure(
toplevel_implementation::<U, R, SD>,
Some(destroy_toplevel::<U, R, SD>),
ShellSurfaceUserData {
@ -275,7 +280,6 @@ fn xdg_surface_implementation<U, R, SD>(
shell: data.shell.clone(),
xdg_surface: xdg_surface.clone(),
},
&data.shell_data.display_token,
);
data.shell_data
@ -294,9 +298,15 @@ fn xdg_surface_implementation<U, R, SD>(
parent,
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
.compositor_token
.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?!");
let popup = id.implement_nonsend(
let popup = id.implement_closure(
popup_implementation::<U, R, SD>,
Some(destroy_popup::<U, R, SD>),
ShellSurfaceUserData {
@ -315,7 +325,6 @@ fn xdg_surface_implementation<U, R, SD>(
shell: data.shell.clone(),
xdg_surface: xdg_surface.clone(),
},
&data.shell_data.display_token,
);
data.shell_data
@ -350,7 +359,7 @@ fn xdg_surface_implementation<U, R, SD>(
});
if !found {
// client responded to a non-existing configure
data.shell.post_error(
data.shell.as_ref().post_error(
zxdg_shell_v6::Error::InvalidSurfaceState as u32,
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?!");
}
_ => unreachable!(),
}
}
@ -368,20 +378,23 @@ fn xdg_surface_implementation<U, R, SD>(
pub struct ShellSurfaceUserData<U, R, SD> {
pub(crate) shell_data: ShellData<U, R, SD>,
pub(crate) wl_surface: Resource<wl_surface::WlSurface>,
pub(crate) shell: Resource<zxdg_shell_v6::ZxdgShellV6>,
pub(crate) xdg_surface: Resource<zxdg_surface_v6::ZxdgSurfaceV6>,
pub(crate) wl_surface: wl_surface::WlSurface,
pub(crate) shell: zxdg_shell_v6::ZxdgShellV6,
pub(crate) xdg_surface: zxdg_surface_v6::ZxdgSurfaceV6,
}
// 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
U: 'static,
R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
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
.compositor_token
.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>(
resource: &Resource<zxdg_toplevel_v6::ZxdgToplevelV6>,
resource: &zxdg_toplevel_v6::ZxdgToplevelV6,
configure: ToplevelConfigure,
) where
U: 'static,
R: Role<XdgSurfaceRole> + '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));
// convert the Vec<State> (which is really a Vec<u32>) into Vec<u8>
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) }
};
let serial = configure.serial;
resource.send(zxdg_toplevel_v6::Event::Configure {
width,
height,
states,
});
data.xdg_surface
.send(zxdg_surface_v6::Event::Configure { serial });
resource.configure(width, height, states);
data.xdg_surface.configure(serial);
// Add the configure as pending
data.shell_data
.compositor_token
@ -426,9 +437,12 @@ pub fn send_toplevel_configure<U, R, SD>(
}
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> {
let data = resource.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap();
let data = resource
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
super::ToplevelSurface {
wl_surface: data.wl_surface.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>(
request: zxdg_toplevel_v6::Request,
toplevel: Resource<zxdg_toplevel_v6::ZxdgToplevelV6>,
toplevel: zxdg_toplevel_v6::ZxdgToplevelV6,
) where
U: 'static,
R: Role<XdgSurfaceRole> + '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 {
zxdg_toplevel_v6::Request::Destroy => {
// 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| {
toplevel_data.parent = parent.map(|toplevel_surface_parent| {
let parent_data = toplevel_surface_parent
.as_ref()
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
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();
(&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
U: 'static,
R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{
let data = toplevel.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap();
if !data.wl_surface.is_alive() {
let data = toplevel
.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
// trying to change the role but it's a cleanup (possibly a
// disconnecting client), ignore the protocol check.
@ -575,21 +597,21 @@ where
* xdg_popup
*/
pub(crate) fn send_popup_configure<U, R, SD>(
resource: &Resource<zxdg_popup_v6::ZxdgPopupV6>,
configure: PopupConfigure,
) where
pub(crate) fn send_popup_configure<U, R, SD>(resource: &zxdg_popup_v6::ZxdgPopupV6, configure: PopupConfigure)
where
U: 'static,
R: Role<XdgSurfaceRole> + '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 (width, height) = configure.size;
let serial = configure.serial;
resource.send(zxdg_popup_v6::Event::Configure { x, y, width, height });
data.xdg_surface
.send(zxdg_surface_v6::Event::Configure { serial });
resource.configure(x, y, width, height);
data.xdg_surface.configure(serial);
// Add the configure as pending
data.shell_data
.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>(
resource: &Resource<zxdg_popup_v6::ZxdgPopupV6>,
resource: &zxdg_popup_v6::ZxdgPopupV6,
) -> 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 {
wl_surface: data.wl_surface.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>(
request: zxdg_popup_v6::Request,
popup: Resource<zxdg_popup_v6::ZxdgPopupV6>,
) where
fn popup_implementation<U, R, SD>(request: zxdg_popup_v6::Request, popup: zxdg_popup_v6::ZxdgPopupV6)
where
U: 'static,
R: Role<XdgSurfaceRole> + '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 {
zxdg_popup_v6::Request::Destroy => {
// all is handled by our destructor
@ -631,17 +657,21 @@ fn popup_implementation<U, R, SD>(
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
U: 'static,
R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{
let data = popup.user_data::<ShellSurfaceUserData<U, R, SD>>().unwrap();
if !data.wl_surface.is_alive() {
let data = popup
.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
// trying to change the role but it's a cleanup (possibly a
// 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::BottomLeft => xdg_toplevel::ResizeEdge::BottomLeft,
zxdg_toplevel_v6::ResizeEdge::BottomRight => xdg_toplevel::ResizeEdge::BottomRight,
_ => unreachable!(),
}
}

View File

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