Update smithay to wayland-server 0.23
This commit is contained in:
parent
d6625b4b49
commit
3f2857fbf3
12
Cargo.toml
12
Cargo.toml
|
@ -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"]
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(()),
|
||||
}
|
||||
|
|
|
@ -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(_)>,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(_)>,
|
||||
|
|
|
@ -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()))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue