Update wayland-rs to 0.25 (#171)

Update wayland-rs to 0.25 and calloop to 0.5

Co-authored-by: Victor Berger <victor.berger@m4x.org>
This commit is contained in:
Jonas Platte 2020-04-05 19:01:08 +02:00 committed by GitHub
parent fbe20d6c1f
commit b8c20ebf30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 1241 additions and 1008 deletions

View File

@ -11,10 +11,10 @@ edition = "2018"
members = [ "anvil" ]
[dependencies]
wayland-server = { version = "0.23.4", optional = true }
wayland-commons = { version = "0.23.4", optional = true }
wayland-sys = { version = "0.23.4", optional = true }
calloop = "0.4.2"
wayland-server = { version = "0.25.0", optional = true }
wayland-commons = { version = "0.25.0", optional = true }
wayland-sys = { version = "0.25.0", optional = true }
calloop = "0.5.1"
bitflags = "1"
nix = "0.13"
xkbcommon = "0.4.0"
@ -31,7 +31,7 @@ input = { version = "0.4.1", optional = true }
udev = { version = "0.2.0", optional = true }
dbus = { version = "0.8", optional = true }
systemd = { version = "0.4.0", optional = true }
wayland-protocols = { version = "0.23.4", features = ["unstable_protocols", "server"], optional = true }
wayland-protocols = { version = "0.25.0", features = ["unstable_protocols", "server"], optional = true }
image = { version = "0.21.0", optional = true }
error-chain = "0.12.0"
lazy_static = "1.0.0"
@ -44,7 +44,7 @@ gl_generator = { version = "0.10", optional = true }
[features]
default = ["backend_winit", "backend_drm_legacy", "backend_drm_gbm", "backend_drm_egl", "backend_libinput", "backend_udev", "backend_session", "renderer_glium", "xwayland", "wayland_frontend"]
backend_winit = ["winit", "wayland-server/dlopen", "wayland-client/dlopen", "backend_egl", "renderer_gl", "native_lib"]
backend_winit = ["winit", "wayland-server/dlopen", "wayland-client/dlopen", "backend_egl", "renderer_gl", "use_system_lib"]
backend_drm = ["drm"]
backend_drm_legacy = ["backend_drm"]
backend_drm_gbm = ["backend_drm", "gbm", "image"]
@ -56,7 +56,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"]
use_system_lib = ["wayland_frontend", "wayland-sys", "wayland-server/use_system_lib"]
wayland_frontend = ["wayland-server", "wayland-commons", "wayland-protocols"]
xwayland = ["wayland_frontend"]

View File

@ -12,7 +12,7 @@ slog-term = "2.3"
slog-async = "2.2"
rand = "0.6"
glium = { version = "0.23.0", default-features = false }
wayland-server = "0.23"
wayland-server = "0.25.0"
xkbcommon = "0.4.0"
bitflags = "1.2.1"
@ -26,7 +26,7 @@ gl_generator = "0.10"
[features]
default = [ "winit", "egl", "udev" ]
egl = [ "smithay/native_lib" ]
egl = [ "smithay/use_system_lib" ]
winit = [ "smithay/backend_winit" ]
udev = [ "smithay/backend_libinput", "smithay/backend_drm_legacy", "smithay/backend_drm_gbm", "smithay/backend_drm_egl", "smithay/backend_udev", "smithay/backend_session" ]
logind = [ "smithay/backend_session_logind" ]

View File

@ -299,7 +299,8 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
location,
|_surface, attributes, role, &(mut x, mut y)| {
// Pull a new buffer if available
if let Some(data) = attributes.user_data.get_mut::<SurfaceData>() {
if let Some(data) = attributes.user_data.get::<RefCell<SurfaceData>>() {
let mut data = data.borrow_mut();
if data.texture.is_none() {
if let Some(buffer) = data.buffer.take() {
if let Ok(m) = self.texture_from_buffer(buffer.clone()) {
@ -341,8 +342,8 @@ impl<F: GLGraphicsBackend + 'static> GliumDrawer<F> {
}
},
|_surface, attributes, role, &(mut x, mut y)| {
if let Some(ref data) = attributes.user_data.get::<SurfaceData>() {
if let Some(ref metadata) = data.texture {
if let Some(ref data) = attributes.user_data.get::<RefCell<SurfaceData>>() {
if let Some(ref metadata) = data.borrow().texture {
// we need to re-extract the subsurface offset, as the previous closure
// only passes it to our children
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {

View File

@ -8,7 +8,7 @@ extern crate slog;
extern crate smithay;
use slog::Drain;
use smithay::reexports::{calloop::EventLoop, wayland_server::Display};
use smithay::reexports::{calloop::{EventLoop, generic::Generic, mio::Interest}, wayland_server::Display};
#[macro_use]
mod shaders;
@ -30,6 +30,20 @@ static POSSIBLE_BACKENDS: &[&str] = &[
"--tty-udev : Run anvil as a tty udev client (requires root if without logind).",
];
pub struct AnvilState {
pub need_wayland_dispatch: bool,
pub running: bool,
}
impl Default for AnvilState {
fn default() -> AnvilState {
AnvilState {
need_wayland_dispatch: false,
running: true,
}
}
}
fn main() {
// A logger facility, here we use the terminal here
let log = slog::Logger::root(
@ -37,8 +51,16 @@ fn main() {
o!(),
);
let mut event_loop = EventLoop::<()>::new().unwrap();
let mut display = Display::new(event_loop.handle());
let mut event_loop = EventLoop::<AnvilState>::new().unwrap();
let mut display = Display::new();
// Glue for event dispatching
let mut wayland_event_source = Generic::from_raw_fd(display.get_poll_fd());
wayland_event_source.set_interest(Interest::READABLE);
let _wayland_source = event_loop.handle().insert_source(
wayland_event_source,
|_, state: &mut AnvilState| { state.need_wayland_dispatch = true; }
);
let arg = ::std::env::args().nth(1);
match arg.as_ref().map(|s| &s[..]) {

View File

@ -187,7 +187,7 @@ impl PointerGrab for ResizeSurfaceGrab {
let (min_size, max_size) =
self.ctoken
.with_surface_data(self.toplevel.get_surface().unwrap(), |attrs| {
let data = attrs.user_data.get::<SurfaceData>().unwrap();
let data = attrs.user_data.get::<RefCell<SurfaceData>>().unwrap().borrow();
(data.min_size, data.max_size)
});
@ -245,7 +245,7 @@ impl PointerGrab for ResizeSurfaceGrab {
self.ctoken
.with_surface_data(self.toplevel.get_surface().unwrap(), |attrs| {
let data = attrs.user_data.get_mut::<SurfaceData>().unwrap();
let mut data = attrs.user_data.get::<RefCell<SurfaceData>>().unwrap().borrow_mut();
if let ResizeState::Resizing(resize_data) = data.resize_state {
data.resize_state = ResizeState::WaitingForFinalAck(resize_data, serial);
} else {
@ -255,7 +255,7 @@ impl PointerGrab for ResizeSurfaceGrab {
} else {
self.ctoken
.with_surface_data(self.toplevel.get_surface().unwrap(), |attrs| {
let data = attrs.user_data.get_mut::<SurfaceData>().unwrap();
let mut data = attrs.user_data.get::<RefCell<SurfaceData>>().unwrap().borrow_mut();
if let ResizeState::Resizing(resize_data) = data.resize_state {
data.resize_state = ResizeState::WaitingForCommit(resize_data);
} else {
@ -298,9 +298,10 @@ pub fn init_shell(
let window_map = window_map.as_ref().unwrap();
surface_commit(&surface, ctoken, &buffer_utils, &*window_map)
}
SurfaceEvent::Frame { callback } => callback
.implement_closure(|_, _| unreachable!(), None::<fn(_)>, ())
.done(0),
SurfaceEvent::Frame { callback } => {
callback.quick_assign(|_, _, _| unreachable!());
callback.done(0)
}
},
log.clone(),
);
@ -413,7 +414,7 @@ pub fn init_shell(
let initial_window_size = (geometry.width, geometry.height);
compositor_token.with_surface_data(surface.get_surface().unwrap(), move |attrs| {
attrs.user_data.get_mut::<SurfaceData>().unwrap().resize_state =
attrs.user_data.get::<RefCell<SurfaceData>>().unwrap().borrow_mut().resize_state =
ResizeState::Resizing(ResizeData {
edges: edges.into(),
initial_window_location,
@ -434,8 +435,8 @@ pub fn init_shell(
}
XdgRequest::AckConfigure { surface, .. } => {
let waiting_for_serial = compositor_token.with_surface_data(&surface, |attrs| {
if let Some(data) = attrs.user_data.get_mut::<SurfaceData>() {
if let ResizeState::WaitingForFinalAck(_, serial) = data.resize_state {
if let Some(data) = attrs.user_data.get::<RefCell<SurfaceData>>() {
if let ResizeState::WaitingForFinalAck(_, serial) = data.borrow().resize_state {
return Some(serial);
}
}
@ -452,7 +453,7 @@ pub fn init_shell(
if acked {
compositor_token.with_surface_data(&surface, |attrs| {
let data = attrs.user_data.get_mut::<SurfaceData>().unwrap();
let mut data = attrs.user_data.get::<RefCell<SurfaceData>>().unwrap().borrow_mut();
if let ResizeState::WaitingForFinalAck(resize_data, _) = data.resize_state {
data.resize_state = ResizeState::WaitingForCommit(resize_data);
} else {
@ -565,7 +566,7 @@ pub fn init_shell(
let initial_window_size = (geometry.width, geometry.height);
compositor_token.with_surface_data(surface.get_surface().unwrap(), move |attrs| {
attrs.user_data.get_mut::<SurfaceData>().unwrap().resize_state =
attrs.user_data.get::<RefCell<SurfaceData>>().unwrap().borrow_mut().resize_state =
ResizeState::Resizing(ResizeData {
edges: edges.into(),
initial_window_location,
@ -697,8 +698,8 @@ fn surface_commit(
});
let refresh = token.with_surface_data(surface, |attributes| {
attributes.user_data.insert_if_missing(SurfaceData::default);
let data = attributes.user_data.get_mut::<SurfaceData>().unwrap();
attributes.user_data.insert_if_missing(|| RefCell::new(SurfaceData::default()));
let mut data = attributes.user_data.get::<RefCell<SurfaceData>>().unwrap().borrow_mut();
data.geometry = geometry;
data.input_region = attributes.input_region.clone();
@ -738,7 +739,7 @@ fn surface_commit(
let Rectangle { width, height, .. } = window_map.geometry(&toplevel).unwrap();
let new_location = token.with_surface_data(surface, |attributes| {
let data = attributes.user_data.get_mut::<SurfaceData>().unwrap();
let mut data = attributes.user_data.get::<RefCell<SurfaceData>>().unwrap().borrow_mut();
let mut new_location = None;

View File

@ -35,6 +35,10 @@ use smithay::{
udev::{primary_gpu, udev_backend_bind, UdevBackend, UdevHandler},
},
reexports::{
calloop::{
generic::{SourceFd, Generic},
EventLoop, LoopHandle, Source,
},
drm::control::{
connector::{Info as ConnectorInfo, State as ConnectorState},
crtc,
@ -44,10 +48,6 @@ use smithay::{
input::Libinput,
nix::{fcntl::OFlag, sys::stat::dev_t},
wayland_server::{
calloop::{
generic::{EventedFd, Generic},
EventLoop, LoopHandle, Source,
},
protocol::{wl_output, wl_surface},
Display,
},
@ -65,6 +65,7 @@ use crate::buffer_utils::BufferUtils;
use crate::glium_drawer::GliumDrawer;
use crate::input_handler::AnvilInputHandler;
use crate::shell::{init_shell, MyWindowMap, Roles};
use crate::AnvilState;
pub struct SessionFd(RawFd);
impl AsRawFd for SessionFd {
@ -78,7 +79,7 @@ type RenderDevice =
type RenderSurface =
EglSurface<EglGbmBackend<LegacyDrmDevice<SessionFd>>, GbmDevice<LegacyDrmDevice<SessionFd>>>;
pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger) -> Result<(), ()> {
pub fn run_udev(mut display: Display, mut event_loop: EventLoop<AnvilState>, log: Logger) -> Result<(), ()> {
let name = display.add_socket_auto().unwrap().into_string().unwrap();
info!(log, "Listening on wayland socket"; "name" => name.clone());
::std::env::set_var("WAYLAND_DISPLAY", name);
@ -253,14 +254,19 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
/*
* And run our loop
*/
let mut state = AnvilState::default();
while running.load(Ordering::SeqCst) {
if event_loop
.dispatch(Some(::std::time::Duration::from_millis(16)), &mut ())
.dispatch(Some(::std::time::Duration::from_millis(16)), &mut state)
.is_err()
{
running.store(false, Ordering::SeqCst);
} else {
display.borrow_mut().flush_clients();
if state.need_wayland_dispatch {
display.borrow_mut().dispatch(std::time::Duration::from_millis(0), &mut state);
}
display.borrow_mut().flush_clients(&mut state);
window_map.borrow_mut().refresh();
}
}
@ -287,7 +293,7 @@ struct UdevHandlerImpl<S: SessionNotifier, Data: 'static> {
dev_t,
(
S::Id,
Source<Generic<EventedFd<RenderDevice>>>,
Source<Generic<SourceFd<RenderDevice>>>,
Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<RenderSurface>>>>,
),
>,

View File

@ -87,7 +87,7 @@ where
wl_surface,
self.location,
|wl_surface, attributes, role, &(mut x, mut y)| {
let data = attributes.user_data.get::<SurfaceData>();
let data = attributes.user_data.get::<RefCell<SurfaceData>>();
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
x += subdata.location.0;
@ -96,7 +96,7 @@ where
let surface_local_point = (point.0 - x as f64, point.1 - y as f64);
if data
.map(|data| data.contains_point(surface_local_point))
.map(|data| data.borrow().contains_point(surface_local_point))
.unwrap_or(false)
{
*found.borrow_mut() = Some((wl_surface.clone(), (x as f64, y as f64)));
@ -122,9 +122,9 @@ where
wl_surface,
(base_x, base_y),
|_, attributes, role, &(mut x, mut y)| {
let data = attributes.user_data.get::<SurfaceData>();
let data = attributes.user_data.get::<RefCell<SurfaceData>>();
if let Some((w, h)) = data.and_then(SurfaceData::size) {
if let Some((w, h)) = data.and_then(|d| d.borrow().size()) {
if let Ok(subdata) = Role::<SubsurfaceRole>::data(role) {
x += subdata.location.0;
y += subdata.location.1;
@ -160,7 +160,7 @@ where
// It's the set geometry with the full bounding box as the fallback.
ctoken
.with_surface_data(self.toplevel.get_surface().unwrap(), |attributes| {
attributes.user_data.get::<SurfaceData>().unwrap().geometry
attributes.user_data.get::<RefCell<SurfaceData>>().unwrap().borrow().geometry
})
.unwrap_or(self.bbox)
}

View File

@ -27,8 +27,9 @@ use crate::buffer_utils::BufferUtils;
use crate::glium_drawer::GliumDrawer;
use crate::input_handler::AnvilInputHandler;
use crate::shell::init_shell;
use crate::AnvilState;
pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Logger) -> Result<(), ()> {
pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<AnvilState>, log: Logger) -> Result<(), ()> {
let (renderer, mut input) = winit::init(log.clone()).map_err(|_| ())?;
#[cfg(feature = "egl")]
@ -187,13 +188,18 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop<()>, log: Log
}
}
let mut state = AnvilState::default();
if event_loop
.dispatch(Some(::std::time::Duration::from_millis(16)), &mut ())
.dispatch(Some(::std::time::Duration::from_millis(16)), &mut state)
.is_err()
{
running.store(false, Ordering::SeqCst);
} else {
display.flush_clients();
if state.need_wayland_dispatch {
display.dispatch(std::time::Duration::from_millis(0), &mut state);
}
display.flush_clients(&mut state);
window_map.borrow_mut().refresh();
}
}

View File

@ -12,7 +12,7 @@ use drm::control::{crtc, ResourceHandles, ResourceInfo};
use nix::libc::dev_t;
use std::os::unix::io::{AsRawFd, RawFd};
use std::rc::Rc;
#[cfg(feature = "native_lib")]
#[cfg(feature = "use_system_lib")]
use wayland_server::Display;
use super::{Device, DeviceHandler, Surface};
@ -20,7 +20,7 @@ use crate::backend::egl::context::GlAttributes;
use crate::backend::egl::error::Result as EGLResult;
use crate::backend::egl::native::{Backend, NativeDisplay, NativeSurface};
use crate::backend::egl::EGLContext;
#[cfg(feature = "native_lib")]
#[cfg(feature = "use_system_lib")]
use crate::backend::egl::{EGLDisplay, EGLGraphicsBackend};
pub mod error;
@ -181,7 +181,7 @@ where
}
}
#[cfg(feature = "native_lib")]
#[cfg(feature = "use_system_lib")]
impl<B, D> EGLGraphicsBackend for EglDevice<B, D>
where
B: Backend<Surface = <D as Device>::Surface> + 'static,

View File

@ -46,8 +46,8 @@ use std::iter::IntoIterator;
use std::os::unix::io::AsRawFd;
use std::path::PathBuf;
use calloop::generic::{EventedFd, Generic};
use calloop::mio::Ready;
use calloop::generic::{SourceFd, Generic};
use calloop::mio::Interest;
use calloop::InsertError;
use calloop::{LoopHandle, Source};
@ -229,13 +229,13 @@ impl<A: AsRawFd> DevPath for A {
pub fn device_bind<D: Device + 'static, Data>(
handle: &LoopHandle<Data>,
device: D,
) -> ::std::result::Result<Source<Generic<EventedFd<D>>>, InsertError<Generic<EventedFd<D>>>>
) -> ::std::result::Result<Source<Generic<SourceFd<D>>>, InsertError<Generic<SourceFd<D>>>>
where
D: Device,
Data: 'static,
{
let mut source = Generic::from_fd_source(device);
source.set_interest(Ready::readable());
source.set_interest(Interest::READABLE);
handle.insert_source(source, |evt, _| {
evt.source.borrow_mut().0.process_events();

View File

@ -28,7 +28,7 @@ use std::{
};
#[cfg(feature = "wayland_frontend")]
use wayland_server::{protocol::wl_buffer::WlBuffer, Display};
#[cfg(feature = "native_lib")]
#[cfg(feature = "use_system_lib")]
use wayland_sys::server::wl_display;
pub mod context;
@ -306,7 +306,7 @@ impl Drop for EGLImages {
/// Trait any backend type may implement that allows binding a [`Display`](wayland_server::Display)
/// to create an [`EGLDisplay`] for EGL-based [`WlBuffer`]s.
#[cfg(feature = "native_lib")]
#[cfg(feature = "use_system_lib")]
pub trait EGLGraphicsBackend {
/// Binds this EGL context to the given Wayland display.
///
@ -326,7 +326,7 @@ pub trait EGLGraphicsBackend {
/// Type to receive [`EGLImages`] for EGL-based [`WlBuffer`]s.
///
/// Can be created by using [`EGLGraphicsBackend::bind_wl_display`].
#[cfg(feature = "native_lib")]
#[cfg(feature = "use_system_lib")]
pub struct EGLDisplay {
egl: Weak<ffi::egl::types::EGLDisplay>,
wayland: *mut wl_display,
@ -336,7 +336,7 @@ pub struct EGLDisplay {
egl_to_texture_support: bool,
}
#[cfg(feature = "native_lib")]
#[cfg(feature = "use_system_lib")]
impl EGLDisplay {
fn new<B: native::Backend, N: native::NativeDisplay<B>>(
context: &EGLContext<B, N>,
@ -510,7 +510,7 @@ impl EGLDisplay {
}
}
#[cfg(feature = "native_lib")]
#[cfg(feature = "use_system_lib")]
impl Drop for EGLDisplay {
fn drop(&mut self) {
if let Some(display) = self.egl.upgrade() {
@ -523,14 +523,14 @@ impl Drop for EGLDisplay {
}
}
#[cfg(feature = "native_lib")]
#[cfg(feature = "use_system_lib")]
impl<E: EGLGraphicsBackend> EGLGraphicsBackend for Rc<E> {
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
(**self).bind_wl_display(display)
}
}
#[cfg(feature = "native_lib")]
#[cfg(feature = "use_system_lib")]
impl<B: native::Backend, N: native::NativeDisplay<B>> EGLGraphicsBackend for EGLContext<B, N> {
fn bind_wl_display(&self, display: &Display) -> Result<EGLDisplay> {
if !self.wl_drm_support {

View File

@ -16,8 +16,8 @@ use std::{
};
use calloop::{
generic::{EventedFd, Generic},
mio::Ready,
generic::{SourceFd, Generic},
mio::Interest,
InsertError, LoopHandle, Source,
};
@ -608,11 +608,11 @@ pub fn libinput_bind<Data: 'static>(
backend: LibinputInputBackend,
handle: LoopHandle<Data>,
) -> ::std::result::Result<
Source<Generic<EventedFd<LibinputInputBackend>>>,
InsertError<Generic<EventedFd<LibinputInputBackend>>>,
Source<Generic<SourceFd<LibinputInputBackend>>>,
InsertError<Generic<SourceFd<LibinputInputBackend>>>,
> {
let mut source = Generic::from_fd_source(backend);
source.set_interest(Ready::readable());
source.set_interest(Interest::READABLE);
handle.insert_source(source, move |evt, _| {
let mut backend = evt.source.borrow_mut();

View File

@ -53,8 +53,8 @@ use std::{
use systemd::login;
use calloop::{
generic::{Event, EventedRawFd, Generic},
mio::Ready,
generic::{Event, SourceRawFd, Generic},
mio::Interest,
InsertError, LoopHandle, Source,
};
@ -431,7 +431,7 @@ impl SessionNotifier for LogindSessionNotifier {
pub struct BoundLogindSession {
notifier: LogindSessionNotifier,
_watches: Vec<Watch>,
sources: Vec<Source<Generic<EventedRawFd>>>,
sources: Vec<Source<Generic<SourceRawFd>>>,
}
/// Bind a [`LogindSessionNotifier`] to an [`EventLoop`](calloop::EventLoop).
@ -449,17 +449,21 @@ pub fn logind_session_bind<Data: 'static>(
let sources = watches
.clone()
.into_iter()
.map(|watch| {
.filter_map(|watch| {
let interest = match (watch.writable(), watch.readable()) {
(true, true) => Interest::WRITABLE | Interest::READABLE,
(true, false) => Interest::WRITABLE,
(false, true) => Interest::READABLE,
(false, false) => return None
};
let mut source = Generic::from_raw_fd(watch.fd());
source.set_interest(
if watch.readable() { Ready::readable() } else { Ready::empty() }
| if watch.writable() { Ready::writable() } else { Ready::empty() }
);
handle.insert_source(source, {
source.set_interest(interest);
let source = handle.insert_source(source, {
let mut notifier = notifier.clone();
move |evt, _| notifier.event(evt)
})
}).collect::<::std::result::Result<Vec<Source<Generic<EventedRawFd>>>, InsertError<Generic<EventedRawFd>>>>()
});
Some(source)
}).collect::<::std::result::Result<Vec<Source<Generic<SourceRawFd>>>, InsertError<Generic<SourceRawFd>>>>()
.map_err(|err| {
(
err.into(),
@ -502,17 +506,17 @@ impl Drop for LogindSessionNotifier {
}
impl LogindSessionNotifier {
fn event(&mut self, event: Event<EventedRawFd>) {
fn event(&mut self, event: Event<SourceRawFd>) {
let fd = event.source.borrow().0;
let readiness = event.readiness;
let conn = self.internal.conn.borrow();
let items = conn.watch_handle(
fd,
if readiness.is_readable() && readiness.is_writable() {
if readiness.readable && readiness.writable {
WatchEvent::Readable as u32 | WatchEvent::Writable as u32
} else if readiness.is_readable() {
} else if readiness.readable {
WatchEvent::Readable as u32
} else if readiness.is_writable() {
} else if readiness.writable {
WatchEvent::Writable as u32
} else {
return;

View File

@ -19,8 +19,8 @@ use std::{
use udev::{Context, Enumerator, EventType, MonitorBuilder, MonitorSocket, Result as UdevResult};
use calloop::{
generic::{EventedFd, Generic},
mio::Ready,
generic::{SourceFd, Generic},
mio::Interest,
InsertError, LoopHandle, Source,
};
@ -104,9 +104,9 @@ impl<T: UdevHandler + 'static> Drop for UdevBackend<T> {
pub fn udev_backend_bind<T: UdevHandler + 'static, Data: 'static>(
udev: UdevBackend<T>,
handle: &LoopHandle<Data>,
) -> Result<Source<Generic<EventedFd<UdevBackend<T>>>>, InsertError<Generic<EventedFd<UdevBackend<T>>>>> {
) -> Result<Source<Generic<SourceFd<UdevBackend<T>>>>, InsertError<Generic<SourceFd<UdevBackend<T>>>>> {
let mut source = Generic::from_fd_source(udev);
source.set_interest(Ready::readable());
source.set_interest(Interest::READABLE);
handle.insert_source(source, |evt, _| {
evt.source.borrow_mut().0.process_events();

View File

@ -1,8 +1,8 @@
use std::{cell::RefCell, rc::Rc, sync::Mutex};
use std::{cell::RefCell, ops::Deref as _, rc::Rc, sync::Mutex};
use wayland_server::{
protocol::{wl_compositor, wl_region, wl_subcompositor, wl_subsurface, wl_surface},
NewResource,
Filter, Main,
};
use super::{
@ -16,29 +16,26 @@ use super::{
*/
pub(crate) fn implement_compositor<R, Impl>(
compositor: NewResource<wl_compositor::WlCompositor>,
compositor: Main<wl_compositor::WlCompositor>,
log: ::slog::Logger,
implem: Rc<RefCell<Impl>>,
) -> wl_compositor::WlCompositor
where
R: Default + 'static,
R: Default + Send + 'static,
Impl: FnMut(SurfaceEvent, wl_surface::WlSurface, CompositorToken<R>) + 'static,
{
compositor.implement_closure(
move |request, _compositor| match request {
wl_compositor::Request::CreateSurface { id } => {
trace!(log, "Creating a new wl_surface.");
implement_surface(id, log.clone(), implem.clone());
}
wl_compositor::Request::CreateRegion { id } => {
trace!(log, "Creating a new wl_region.");
implement_region(id);
}
_ => unreachable!(),
},
None::<fn(_)>,
(),
)
compositor.quick_assign(move |_compositor, request, _| match request {
wl_compositor::Request::CreateSurface { id } => {
trace!(log, "Creating a new wl_surface.");
implement_surface(id, log.clone(), implem.clone());
}
wl_compositor::Request::CreateRegion { id } => {
trace!(log, "Creating a new wl_region.");
implement_region(id);
}
_ => unreachable!(),
});
compositor.deref().clone()
}
/*
@ -81,14 +78,14 @@ where
}
wl_surface::Request::SetOpaqueRegion { region } => {
let attributes = region.map(|r| {
let attributes_mutex = r.as_ref().user_data::<Mutex<RegionAttributes>>().unwrap();
let attributes_mutex = r.as_ref().user_data().get::<Mutex<RegionAttributes>>().unwrap();
attributes_mutex.lock().unwrap().clone()
});
SurfaceData::<R>::with_data(&surface, |d| d.opaque_region = attributes);
}
wl_surface::Request::SetInputRegion { region } => {
let attributes = region.map(|r| {
let attributes_mutex = r.as_ref().user_data::<Mutex<RegionAttributes>>().unwrap();
let attributes_mutex = r.as_ref().user_data().get::<Mutex<RegionAttributes>>().unwrap();
attributes_mutex.lock().unwrap().clone()
});
SurfaceData::<R>::with_data(&surface, |d| d.input_region = attributes);
@ -118,24 +115,25 @@ where
}
fn implement_surface<R, Impl>(
surface: NewResource<wl_surface::WlSurface>,
surface: Main<wl_surface::WlSurface>,
log: ::slog::Logger,
implem: Rc<RefCell<Impl>>,
) -> wl_surface::WlSurface
where
R: Default + 'static,
R: Default + Send + 'static,
Impl: FnMut(SurfaceEvent, wl_surface::WlSurface, CompositorToken<R>) + 'static,
{
let surface = surface.implement_closure(
{
let mut implem = SurfaceImplem::make(log, implem);
move |req, surface| implem.receive_surface_request(req, surface)
},
Some(|surface| SurfaceData::<R>::cleanup(&surface)),
SurfaceData::<R>::new(),
);
SurfaceData::<R>::init(&surface);
surface.quick_assign({
let mut implem = SurfaceImplem::make(log, implem);
move |surface, req, _| implem.receive_surface_request(req, surface.deref().clone())
});
surface.assign_destructor(Filter::new(|surface, _, _| SurfaceData::<R>::cleanup(&surface)));
surface
.as_ref()
.user_data()
.set_threadsafe(|| SurfaceData::<R>::new());
SurfaceData::<R>::init(&surface);
surface.deref().clone()
}
/*
@ -143,7 +141,11 @@ where
*/
fn region_implem(request: wl_region::Request, region: wl_region::WlRegion) {
let attributes_mutex = region.as_ref().user_data::<Mutex<RegionAttributes>>().unwrap();
let attributes_mutex = region
.as_ref()
.user_data()
.get::<Mutex<RegionAttributes>>()
.unwrap();
let mut guard = attributes_mutex.lock().unwrap();
match request {
wl_region::Request::Add { x, y, width, height } => guard
@ -159,12 +161,13 @@ fn region_implem(request: wl_region::Request, region: wl_region::WlRegion) {
}
}
fn implement_region(region: NewResource<wl_region::WlRegion>) -> wl_region::WlRegion {
region.implement_closure(
region_implem,
None::<fn(_)>,
Mutex::new(RegionAttributes::default()),
)
fn implement_region(region: Main<wl_region::WlRegion>) -> wl_region::WlRegion {
region.quick_assign(|region, req, _| region_implem(req, region.deref().clone()));
region
.as_ref()
.user_data()
.set_threadsafe(|| Mutex::new(RegionAttributes::default()));
region.deref().clone()
}
/*
@ -172,29 +175,26 @@ fn implement_region(region: NewResource<wl_region::WlRegion>) -> wl_region::WlRe
*/
pub(crate) fn implement_subcompositor<R>(
subcompositor: NewResource<wl_subcompositor::WlSubcompositor>,
subcompositor: Main<wl_subcompositor::WlSubcompositor>,
) -> wl_subcompositor::WlSubcompositor
where
R: RoleType + Role<SubsurfaceRole> + 'static,
{
subcompositor.implement_closure(
move |request, subcompositor| match request {
wl_subcompositor::Request::GetSubsurface { id, surface, parent } => {
if let Err(()) = SurfaceData::<R>::set_parent(&surface, &parent) {
subcompositor.as_ref().post_error(
wl_subcompositor::Error::BadSurface as u32,
"Surface already has a role.".into(),
);
return;
}
implement_subsurface::<R>(id, surface);
subcompositor.quick_assign(move |subcompositor, request, _| match request {
wl_subcompositor::Request::GetSubsurface { id, surface, parent } => {
if let Err(()) = SurfaceData::<R>::set_parent(&surface, &parent) {
subcompositor.as_ref().post_error(
wl_subcompositor::Error::BadSurface as u32,
"Surface already has a role.".into(),
);
return;
}
wl_subcompositor::Request::Destroy => {}
_ => unreachable!(),
},
None::<fn(_)>,
(),
)
implement_subsurface::<R>(id, surface);
}
wl_subcompositor::Request::Destroy => {}
_ => unreachable!(),
});
subcompositor.deref().clone()
}
/*
@ -206,68 +206,83 @@ where
F: FnOnce(&mut SubsurfaceRole),
R: RoleType + Role<SubsurfaceRole> + 'static,
{
let surface = subsurface.as_ref().user_data::<wl_surface::WlSurface>().unwrap();
let surface = subsurface
.as_ref()
.user_data()
.get::<wl_surface::WlSurface>()
.unwrap();
SurfaceData::<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<R>(
subsurface: NewResource<wl_subsurface::WlSubsurface>,
subsurface: Main<wl_subsurface::WlSubsurface>,
surface: wl_surface::WlSurface,
) -> wl_subsurface::WlSubsurface
where
R: RoleType + Role<SubsurfaceRole> + 'static,
{
subsurface.implement_closure(
|request, subsurface| {
match request {
wl_subsurface::Request::SetPosition { x, y } => {
with_subsurface_attributes::<R, _>(&subsurface, |attrs| {
attrs.location = (x, y);
})
}
wl_subsurface::Request::PlaceAbove { sibling } => {
let surface = subsurface.as_ref().user_data::<wl_surface::WlSurface>().unwrap();
if let Err(()) = SurfaceData::<R>::reorder(surface, Location::After, &sibling) {
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.as_ref().user_data::<wl_surface::WlSurface>().unwrap();
if let Err(()) = SurfaceData::<R>::reorder(surface, Location::Before, &sibling) {
subsurface.as_ref().post_error(
wl_subsurface::Error::BadSurface as u32,
"Provided surface is not a sibling or parent.".into(),
)
}
}
wl_subsurface::Request::SetSync => with_subsurface_attributes::<R, _>(&subsurface, |attrs| {
attrs.sync = true;
}),
wl_subsurface::Request::SetDesync => {
with_subsurface_attributes::<R, _>(&subsurface, |attrs| {
attrs.sync = false;
})
}
wl_subsurface::Request::Destroy => {
// Our destructor already handles it
}
_ => unreachable!(),
subsurface.quick_assign(|subsurface, request, _| {
match request {
wl_subsurface::Request::SetPosition { x, y } => {
with_subsurface_attributes::<R, _>(&subsurface, |attrs| {
attrs.location = (x, y);
})
}
},
Some(|subsurface| destroy_subsurface::<R>(&subsurface)),
surface,
)
wl_subsurface::Request::PlaceAbove { sibling } => {
let surface = subsurface
.as_ref()
.user_data()
.get::<wl_surface::WlSurface>()
.unwrap();
if let Err(()) = SurfaceData::<R>::reorder(surface, Location::After, &sibling) {
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
.as_ref()
.user_data()
.get::<wl_surface::WlSurface>()
.unwrap();
if let Err(()) = SurfaceData::<R>::reorder(surface, Location::Before, &sibling) {
subsurface.as_ref().post_error(
wl_subsurface::Error::BadSurface as u32,
"Provided surface is not a sibling or parent.".into(),
)
}
}
wl_subsurface::Request::SetSync => with_subsurface_attributes::<R, _>(&subsurface, |attrs| {
attrs.sync = true;
}),
wl_subsurface::Request::SetDesync => with_subsurface_attributes::<R, _>(&subsurface, |attrs| {
attrs.sync = false;
}),
wl_subsurface::Request::Destroy => {
// Our destructor already handles it
}
_ => unreachable!(),
}
});
subsurface.assign_destructor(Filter::new(|subsurface, _, _| {
destroy_subsurface::<R>(&subsurface)
}));
subsurface.as_ref().user_data().set_threadsafe(|| surface);
subsurface.deref().clone()
}
fn destroy_subsurface<R>(subsurface: &wl_subsurface::WlSubsurface)
where
R: RoleType + Role<SubsurfaceRole> + 'static,
{
let surface = subsurface.as_ref().user_data::<wl_surface::WlSurface>().unwrap();
let surface = subsurface
.as_ref()
.user_data()
.get::<wl_surface::WlSurface>()
.unwrap();
if surface.as_ref().is_alive() {
SurfaceData::<R>::unset_parent(&surface);
}

View File

@ -35,8 +35,7 @@
//! // Declare the roles enum
//! define_roles!(MyRoles);
//!
//! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # let mut display = wayland_server::Display::new();
//! // Call the init function:
//! let (token, _, _) = compositor_init::<MyRoles, _, _>(
//! &mut display,
@ -85,7 +84,7 @@ use wayland_server::{
protocol::{
wl_buffer, wl_callback, wl_compositor, wl_output, wl_region, wl_subcompositor, wl_surface::WlSurface,
},
Display, Global, NewResource,
Display, Filter, Global, Main, UserDataMap,
};
/// Description of which part of a surface
@ -153,7 +152,7 @@ pub struct SurfaceAttributes {
/// User-controlled data
///
/// This is your field to host whatever you need.
pub user_data: ::wayland_commons::utils::UserDataMap,
pub user_data: UserDataMap,
}
impl Default for SurfaceAttributes {
@ -165,7 +164,7 @@ impl Default for SurfaceAttributes {
opaque_region: None,
input_region: None,
damage: Damage::Full,
user_data: ::wayland_commons::utils::UserDataMap::new(),
user_data: UserDataMap::new(),
}
}
}
@ -446,7 +445,7 @@ impl<R: RoleType + 'static> CompositorToken<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: &wl_region::WlRegion) -> RegionAttributes {
match region.as_ref().user_data::<Mutex<RegionAttributes>>() {
match region.as_ref().user_data().get::<Mutex<RegionAttributes>>() {
Some(mutex) => mutex.lock().unwrap().clone(),
None => panic!("Accessing the data of foreign regions is not supported."),
}
@ -473,19 +472,25 @@ pub fn compositor_init<R, Impl, L>(
)
where
L: Into<Option<::slog::Logger>>,
R: Default + RoleType + Role<SubsurfaceRole> + 'static,
R: Default + RoleType + Role<SubsurfaceRole> + Send + 'static,
Impl: FnMut(SurfaceEvent, WlSurface, CompositorToken<R>) + 'static,
{
let log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "compositor_handler"));
let implem = Rc::new(RefCell::new(implem));
let compositor = display.create_global(4, move |new_compositor, _version| {
self::handlers::implement_compositor::<R, Impl>(new_compositor, log.clone(), implem.clone());
});
let compositor = display.create_global(
4,
Filter::new(move |(new_compositor, _version), _, _| {
self::handlers::implement_compositor::<R, Impl>(new_compositor, log.clone(), implem.clone());
}),
);
let subcompositor = display.create_global(1, move |new_subcompositor, _version| {
self::handlers::implement_subcompositor::<R>(new_subcompositor);
});
let subcompositor = display.create_global(
1,
Filter::new(move |(new_subcompositor, _version), _, _| {
self::handlers::implement_subcompositor::<R>(new_subcompositor);
}),
);
(CompositorToken::make(), compositor, subcompositor)
}
@ -513,7 +518,7 @@ pub enum SurfaceEvent {
/// for more details
Frame {
/// The created `WlCallback`
callback: NewResource<wl_callback::WlCallback>,
callback: Main<wl_callback::WlCallback>,
},
}

View File

@ -54,7 +54,11 @@ where
{
/// Initializes the surface, must be called at creation for state coherence
pub fn init(surface: &WlSurface) {
let my_data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let my_data_mutex = surface
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let mut my_data = my_data_mutex.lock().unwrap();
debug_assert!(my_data.children.is_empty());
my_data.children.push(surface.clone());
@ -62,11 +66,19 @@ where
/// 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<R>>>().unwrap();
let my_data_mutex = surface
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let mut my_data = my_data_mutex.lock().unwrap();
if let Some(old_parent) = my_data.parent.take() {
// We had a parent, lets unregister ourselves from it
let old_parent_mutex = old_parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let old_parent_mutex = old_parent
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let mut old_parent_guard = old_parent_mutex.lock().unwrap();
old_parent_guard
.children
@ -74,7 +86,7 @@ where
}
// orphan all our children
for child in &my_data.children {
let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let child_mutex = child.as_ref().user_data().get::<Mutex<SurfaceData<R>>>().unwrap();
if std::ptr::eq(child_mutex, my_data_mutex) {
// This child is ourselves, don't do anything.
continue;
@ -89,7 +101,11 @@ where
impl<R: RoleType + 'static> SurfaceData<R> {
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<R>>>().unwrap();
let data_mutex = surface
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let data_guard = data_mutex.lock().unwrap();
<R as RoleType>::has_role(&data_guard.role)
}
@ -100,7 +116,11 @@ impl<R: RoleType + 'static> SurfaceData<R> {
R: Role<RoleData>,
{
debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let data_mutex = surface
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::has(&data_guard.role)
}
@ -112,7 +132,11 @@ impl<R: RoleType + 'static> SurfaceData<R> {
RoleData: Default,
{
debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let data_mutex = surface
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let mut data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::set(&mut data_guard.role)
}
@ -125,7 +149,11 @@ impl<R: RoleType + 'static> SurfaceData<R> {
R: Role<RoleData>,
{
debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let data_mutex = surface
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let mut data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::set_with(&mut data_guard.role, data)
}
@ -139,7 +167,11 @@ impl<R: RoleType + 'static> SurfaceData<R> {
R: Role<RoleData>,
{
debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let data_mutex = surface
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let mut data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::unset(&mut data_guard.role)
}
@ -151,7 +183,11 @@ impl<R: RoleType + 'static> SurfaceData<R> {
F: FnOnce(&mut RoleData) -> T,
{
debug_assert!(surface.as_ref().is_alive());
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let data_mutex = surface
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<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))
@ -161,7 +197,7 @@ impl<R: RoleType + 'static> SurfaceData<R> {
impl<R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<R> {
/// Checks if the first surface is an ancestor of the second
pub fn is_ancestor(a: &WlSurface, b: &WlSurface) -> bool {
let b_mutex = b.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let b_mutex = b.as_ref().user_data().get::<Mutex<SurfaceData<R>>>().unwrap();
let b_guard = b_mutex.lock().unwrap();
if let Some(ref parent) = b_guard.parent {
if parent.as_ref().equals(a.as_ref()) {
@ -188,7 +224,7 @@ impl<R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<R> {
// change child's parent
{
let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let child_mutex = child.as_ref().user_data().get::<Mutex<SurfaceData<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)?;
@ -197,7 +233,11 @@ impl<R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<R> {
}
// register child to new parent
{
let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let parent_mutex = parent
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let mut parent_guard = parent_mutex.lock().unwrap();
parent_guard.children.push(child.clone())
}
@ -210,7 +250,7 @@ impl<R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<R> {
pub fn unset_parent(child: &WlSurface) {
debug_assert!(child.as_ref().is_alive());
let old_parent = {
let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let child_mutex = child.as_ref().user_data().get::<Mutex<SurfaceData<R>>>().unwrap();
let mut child_guard = child_mutex.lock().unwrap();
let old_parent = child_guard.parent.take();
if old_parent.is_some() {
@ -222,7 +262,11 @@ impl<R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<R> {
};
// unregister from our parent
if let Some(old_parent) = old_parent {
let parent_mutex = old_parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let parent_mutex = old_parent
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let mut parent_guard = parent_mutex.lock().unwrap();
parent_guard
.children
@ -232,14 +276,18 @@ impl<R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<R> {
/// Retrieve the parent surface (if any) of this surface
pub fn get_parent(child: &WlSurface) -> Option<WlSurface> {
let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let child_mutex = child.as_ref().user_data().get::<Mutex<SurfaceData<R>>>().unwrap();
let child_guard = child_mutex.lock().unwrap();
child_guard.parent.as_ref().cloned()
}
/// Retrieve the children surface (if any) of this surface
pub fn get_children(parent: &WlSurface) -> Vec<WlSurface> {
let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let parent_mutex = parent
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let parent_guard = parent_mutex.lock().unwrap();
parent_guard
.children
@ -254,7 +302,11 @@ impl<R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<R> {
/// Fails if `relative_to` is not a sibling or parent of `surface`.
pub fn reorder(surface: &WlSurface, to: Location, relative_to: &WlSurface) -> Result<(), ()> {
let parent = {
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let data_mutex = surface
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let data_guard = data_mutex.lock().unwrap();
data_guard.parent.as_ref().cloned().unwrap()
};
@ -268,7 +320,11 @@ impl<R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<R> {
None
}
let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let parent_mutex = parent
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<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(relative_to, &parent_guard.children) {
@ -299,7 +355,8 @@ impl<R: 'static> SurfaceData<R> {
{
let data_mutex = surface
.as_ref()
.user_data::<Mutex<SurfaceData<R>>>()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.expect("Accessing the data of foreign surfaces is not supported.");
let mut data_guard = data_mutex.lock().unwrap();
f(&mut data_guard.attributes)
@ -354,7 +411,11 @@ impl<R: 'static> SurfaceData<R> {
F2: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T),
F3: FnMut(&WlSurface, &mut SurfaceAttributes, &mut R, &T) -> bool,
{
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<R>>>().unwrap();
let data_mutex = surface
.as_ref()
.user_data()
.get::<Mutex<SurfaceData<R>>>()
.unwrap();
let mut data_guard = data_mutex.lock().unwrap();
let data_guard = &mut *data_guard;
// call the filter on ourselves

View File

@ -1,11 +1,11 @@
use std::cell::RefCell;
use std::{cell::RefCell, ops::Deref as _};
use wayland_server::{
protocol::{
wl_data_device_manager::DndAction,
wl_data_source::{Request, WlDataSource},
},
NewResource,
Main,
};
/// The metadata describing a data source
@ -17,26 +17,27 @@ pub struct SourceMetadata {
pub dnd_action: DndAction,
}
pub(crate) fn implement_data_source(src: NewResource<WlDataSource>) -> WlDataSource {
src.implement_closure(
|req, me| {
let data: &RefCell<SourceMetadata> = me.as_ref().user_data().unwrap();
let mut guard = data.borrow_mut();
match req {
Request::Offer { mime_type } => guard.mime_types.push(mime_type),
Request::SetActions { dnd_actions } => {
guard.dnd_action = DndAction::from_bits_truncate(dnd_actions);
}
Request::Destroy => {}
_ => unreachable!(),
pub(crate) fn implement_data_source(src: Main<WlDataSource>) -> WlDataSource {
src.quick_assign(|me, req, _| {
let data: &RefCell<SourceMetadata> = me.as_ref().user_data().get().unwrap();
let mut guard = data.borrow_mut();
match req {
Request::Offer { mime_type } => guard.mime_types.push(mime_type),
Request::SetActions { dnd_actions } => {
guard.dnd_action = DndAction::from_bits_truncate(dnd_actions);
}
},
None::<fn(_)>,
Request::Destroy => {}
_ => unreachable!(),
}
});
src.as_ref().user_data().set(|| {
RefCell::new(SourceMetadata {
mime_types: Vec::new(),
dnd_action: DndAction::None,
}),
)
})
});
src.deref().clone()
}
/// Access the metadata of a data source
@ -44,7 +45,7 @@ pub fn with_source_metadata<T, F: FnOnce(&SourceMetadata) -> T>(
source: &WlDataSource,
f: F,
) -> Result<T, ()> {
match source.as_ref().user_data::<RefCell<SourceMetadata>>() {
match source.as_ref().user_data().get::<RefCell<SourceMetadata>>() {
Some(data) => Ok(f(&data.borrow())),
None => Err(()),
}

View File

@ -1,9 +1,8 @@
use std::cell::RefCell;
use std::rc::Rc;
use std::{cell::RefCell, ops::Deref as _, rc::Rc};
use wayland_server::{
protocol::{wl_data_device_manager::DndAction, wl_data_offer, wl_data_source, wl_pointer, wl_surface},
NewResource,
Main,
};
use crate::wayland::{
@ -107,7 +106,8 @@ impl<R: Role<DnDIconRole> + 'static> PointerGrab for DnDGrab<R> {
{
let action_choice = device
.as_ref()
.user_data::<DataDeviceData>()
.user_data()
.get::<DataDeviceData>()
.unwrap()
.action_choice
.clone();
@ -239,94 +239,91 @@ struct OfferData {
}
fn implement_dnd_data_offer(
offer: NewResource<wl_data_offer::WlDataOffer>,
offer: Main<wl_data_offer::WlDataOffer>,
source: wl_data_source::WlDataSource,
offer_data: Rc<RefCell<OfferData>>,
action_choice: Rc<RefCell<dyn FnMut(DndAction, DndAction) -> DndAction + 'static>>,
) -> wl_data_offer::WlDataOffer {
use self::wl_data_offer::Request;
offer.implement_closure(
move |req, offer| {
let mut data = offer_data.borrow_mut();
match req {
Request::Accept { mime_type, .. } => {
if let Some(mtype) = mime_type {
if let Err(()) = with_source_metadata(&source, |meta| {
data.accepted = meta.mime_types.contains(&mtype);
}) {
data.accepted = false;
}
} else {
offer.quick_assign(move |offer, req, _| {
let mut data = offer_data.borrow_mut();
match req {
Request::Accept { mime_type, .. } => {
if let Some(mtype) = mime_type {
if let Err(()) = with_source_metadata(&source, |meta| {
data.accepted = meta.mime_types.contains(&mtype);
}) {
data.accepted = false;
}
} else {
data.accepted = false;
}
Request::Receive { mime_type, fd } => {
// 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.as_ref().is_alive()
&& data.active;
if valid {
source.send(mime_type, fd);
}
let _ = ::nix::unistd::close(fd);
}
Request::Destroy => {}
Request::Finish => {
if !data.active {
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.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.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.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer with no valid action.".into(),
);
}
source.dnd_finished();
data.active = false;
}
Request::SetActions {
dnd_actions,
preferred_action,
} => {
let preferred_action = DndAction::from_bits_truncate(preferred_action);
if ![DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&preferred_action) {
offer.as_ref().post_error(
wl_data_offer::Error::InvalidAction as u32,
"Invalid preferred action.".into(),
);
}
let source_actions = with_source_metadata(&source, |meta| meta.dnd_action)
.unwrap_or_else(|_| DndAction::empty());
let possible_actions = source_actions & DndAction::from_bits_truncate(dnd_actions);
data.chosen_action =
(&mut *action_choice.borrow_mut())(possible_actions, preferred_action);
// check that the user provided callback respects that one precise action should be chosen
debug_assert!(
[DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&data.chosen_action)
);
offer.action(data.chosen_action.to_raw());
source.action(data.chosen_action.to_raw());
}
_ => unreachable!(),
}
},
None::<fn(_)>,
(),
)
Request::Receive { mime_type, fd } => {
// 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.as_ref().is_alive()
&& data.active;
if valid {
source.send(mime_type, fd);
}
let _ = ::nix::unistd::close(fd);
}
Request::Destroy => {}
Request::Finish => {
if !data.active {
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.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.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.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer with no valid action.".into(),
);
}
source.dnd_finished();
data.active = false;
}
Request::SetActions {
dnd_actions,
preferred_action,
} => {
let preferred_action = DndAction::from_bits_truncate(preferred_action);
if ![DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&preferred_action) {
offer.as_ref().post_error(
wl_data_offer::Error::InvalidAction as u32,
"Invalid preferred action.".into(),
);
}
let source_actions = with_source_metadata(&source, |meta| meta.dnd_action)
.unwrap_or_else(|_| DndAction::empty());
let possible_actions = source_actions & DndAction::from_bits_truncate(dnd_actions);
data.chosen_action = (&mut *action_choice.borrow_mut())(possible_actions, preferred_action);
// check that the user provided callback respects that one precise action should be chosen
debug_assert!(
[DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&data.chosen_action)
);
offer.action(data.chosen_action.to_raw());
source.action(data.chosen_action.to_raw());
}
_ => unreachable!(),
}
});
offer.deref().clone()
}

View File

@ -40,8 +40,7 @@
//! // to set a surface as a dnd icon
//! define_roles!(Roles => [DnDIcon, DnDIconRole]);
//!
//! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # let mut display = wayland_server::Display::new();
//! # let (compositor_token, _, _) = compositor_init::<Roles, _, _>(&mut display, |_, _, _| {}, None);
//! // init the data device:
//! init_data_device(
@ -54,9 +53,7 @@
//! );
//! ```
use std::cell::RefCell;
use std::os::unix::io::RawFd;
use std::rc::Rc;
use std::{cell::RefCell, ops::Deref as _, os::unix::io::RawFd, rc::Rc};
use wayland_server::{
protocol::{
@ -64,7 +61,7 @@ use wayland_server::{
wl_data_device_manager::{self, DndAction},
wl_data_offer, wl_data_source, wl_surface,
},
Client, Display, Global, NewResource,
Client, Display, Filter, Global, Main,
};
use crate::wayland::{
@ -175,29 +172,24 @@ impl SeatData {
// create a corresponding data offer
let offer = client
.create_resource::<wl_data_offer::WlDataOffer>(dd.as_ref().version())
.unwrap()
.implement_closure(
move |req, _offer| {
// selection data offers only care about the `receive` event
if let wl_data_offer::Request::Receive { fd, mime_type } = req {
// 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();
offer.quick_assign(move |_offer, req, _| {
// selection data offers only care about the `receive` event
if let wl_data_offer::Request::Receive { fd, mime_type } = req {
// 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.as_ref().is_alive();
if !valid {
// deny the receive
debug!(log, "Denying a wl_data_offer.receive with invalid source.");
} else {
source.send(mime_type, fd);
}
let _ = ::nix::unistd::close(fd);
}
},
None::<fn(_)>,
(),
);
&& source.as_ref().is_alive();
if !valid {
// deny the receive
debug!(log, "Denying a wl_data_offer.receive with invalid source.");
} else {
source.send(mime_type, fd);
}
let _ = ::nix::unistd::close(fd);
}
});
// advertize the offer to the client
dd.data_offer(&offer);
with_source_metadata(data_source, |meta| {
@ -219,34 +211,31 @@ impl SeatData {
let offer_meta = meta.clone();
let callback = dd
.as_ref()
.user_data::<DataDeviceData>()
.user_data()
.get::<DataDeviceData>()
.unwrap()
.callback
.clone();
// create a corresponding data offer
let offer = client
.create_resource::<wl_data_offer::WlDataOffer>(dd.as_ref().version())
.unwrap()
.implement_closure(
move |req, _offer| {
// selection data offers only care about the `receive` event
if let wl_data_offer::Request::Receive { fd, mime_type } = req {
// check if the associated mime type is valid
if !offer_meta.mime_types.contains(&mime_type) {
// deny the receive
debug!(log, "Denying a wl_data_offer.receive with invalid source.");
let _ = ::nix::unistd::close(fd);
} else {
(&mut *callback.borrow_mut())(DataDeviceEvent::SendSelection {
mime_type,
fd,
});
}
}
},
None::<fn(_)>,
(),
);
.unwrap();
offer.quick_assign(move |_offer, req, _| {
// selection data offers only care about the `receive` event
if let wl_data_offer::Request::Receive { fd, mime_type } = req {
// check if the associated mime type is valid
if !offer_meta.mime_types.contains(&mime_type) {
// deny the receive
debug!(log, "Denying a wl_data_offer.receive with invalid source.");
let _ = ::nix::unistd::close(fd);
} else {
(&mut *callback.borrow_mut())(DataDeviceEvent::SendSelection {
mime_type,
fd,
});
}
}
});
// advertize the offer to the client
dd.data_offer(&offer);
for mime_type in meta.mime_types.iter().cloned() {
@ -300,15 +289,12 @@ where
let log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "data_device_mgr"));
let action_choice = Rc::new(RefCell::new(action_choice));
let callback = Rc::new(RefCell::new(callback));
display.create_global(3, move |new_ddm, _version| {
implement_ddm(
new_ddm,
callback.clone(),
action_choice.clone(),
token,
log.clone(),
);
})
display.create_global(
3,
Filter::new(move |(ddm, _version), _, _| {
implement_ddm(ddm, callback.clone(), action_choice.clone(), token, log.clone());
}),
)
}
/// Set the data device focus to a certain client for a given seat
@ -384,7 +370,7 @@ pub fn start_dnd<C>(
}
fn implement_ddm<F, C, R>(
new_ddm: NewResource<wl_data_device_manager::WlDataDeviceManager>,
ddm: Main<wl_data_device_manager::WlDataDeviceManager>,
callback: Rc<RefCell<C>>,
action_choice: Rc<RefCell<F>>,
token: CompositorToken<R>,
@ -396,36 +382,34 @@ where
R: Role<DnDIconRole> + 'static,
{
use self::wl_data_device_manager::Request;
new_ddm.implement_closure(
move |req, _ddm| match req {
Request::CreateDataSource { id } => {
self::data_source::implement_data_source(id);
ddm.quick_assign(move |_ddm, req, _data| match req {
Request::CreateDataSource { id } => {
self::data_source::implement_data_source(id);
}
Request::GetDataDevice { id, seat } => match Seat::from_resource(&seat) {
Some(seat) => {
// ensure the seat user_data is ready
seat.user_data()
.insert_if_missing(|| RefCell::new(SeatData::new(log.clone())));
let seat_data = seat.user_data().get::<RefCell<SeatData>>().unwrap();
let data_device = implement_data_device(
id,
seat.clone(),
callback.clone(),
action_choice.clone(),
token,
log.clone(),
);
seat_data.borrow_mut().known_devices.push(data_device);
}
None => {
error!(log, "Unmanaged seat given to a data device.");
}
Request::GetDataDevice { id, seat } => match Seat::from_resource(&seat) {
Some(seat) => {
// ensure the seat user_data is ready
seat.user_data()
.insert_if_missing(|| RefCell::new(SeatData::new(log.clone())));
let seat_data = seat.user_data().get::<RefCell<SeatData>>().unwrap();
let data_device = implement_data_device(
id,
seat.clone(),
callback.clone(),
action_choice.clone(),
token,
log.clone(),
);
seat_data.borrow_mut().known_devices.push(data_device);
}
None => {
error!(log, "Unmanaged seat given to a data device.");
}
},
_ => unreachable!(),
},
None::<fn(_)>,
(),
)
_ => unreachable!(),
});
ddm.deref().clone()
}
struct DataDeviceData {
@ -434,7 +418,7 @@ struct DataDeviceData {
}
fn implement_data_device<F, C, R>(
new_dd: NewResource<wl_data_device::WlDataDevice>,
dd: Main<wl_data_device::WlDataDevice>,
seat: Seat,
callback: Rc<RefCell<C>>,
action_choice: Rc<RefCell<F>>,
@ -451,83 +435,82 @@ where
callback: callback.clone(),
action_choice,
};
new_dd.implement_closure(
move |req, dd| match req {
Request::StartDrag {
source,
origin,
icon,
serial,
} => {
/* TODO: handle the icon */
if let Some(pointer) = seat.get_pointer() {
if pointer.has_grab(serial) {
if let Some(ref icon) = icon {
if token.give_role::<DnDIconRole>(icon).is_err() {
dd.as_ref().post_error(
wl_data_device::Error::Role as u32,
"Given surface already has an other role".into(),
);
return;
}
dd.quick_assign(move |dd, req, _| match req {
Request::StartDrag {
source,
origin,
icon,
serial,
} => {
/* TODO: handle the icon */
if let Some(pointer) = seat.get_pointer() {
if pointer.has_grab(serial) {
if let Some(ref icon) = icon {
if token.give_role::<DnDIconRole>(icon).is_err() {
dd.as_ref().post_error(
wl_data_device::Error::Role as u32,
"Given surface already has an other role".into(),
);
return;
}
// The StartDrag is in response to a pointer implicit grab, all is good
(&mut *callback.borrow_mut())(DataDeviceEvent::DnDStarted {
source: source.clone(),
icon: icon.clone(),
});
let start_data = pointer.grab_start_data().unwrap();
pointer.set_grab(
dnd_grab::DnDGrab::new(
start_data,
source,
origin,
seat.clone(),
icon,
token,
callback.clone(),
),
serial,
);
return;
}
// The StartDrag is in response to a pointer implicit grab, all is good
(&mut *callback.borrow_mut())(DataDeviceEvent::DnDStarted {
source: source.clone(),
icon: icon.clone(),
});
let start_data = pointer.grab_start_data().unwrap();
pointer.set_grab(
dnd_grab::DnDGrab::new(
start_data,
source,
origin,
seat.clone(),
icon,
token,
callback.clone(),
),
serial,
);
return;
}
debug!(log, "denying drag from client without implicit grab");
}
Request::SetSelection { source, .. } => {
if let Some(keyboard) = seat.get_keyboard() {
if dd
.as_ref()
.client()
.as_ref()
.map(|c| keyboard.has_focus(c))
.unwrap_or(false)
{
let seat_data = seat.user_data().get::<RefCell<SeatData>>().unwrap();
(&mut *callback.borrow_mut())(DataDeviceEvent::NewSelection(source.clone()));
// The client has kbd focus, it can set the selection
seat_data
.borrow_mut()
.set_selection(source.map(Selection::Client).unwrap_or(Selection::Empty));
return;
}
debug!(log, "denying drag from client without implicit grab");
}
Request::SetSelection { source, .. } => {
if let Some(keyboard) = seat.get_keyboard() {
if dd
.as_ref()
.client()
.as_ref()
.map(|c| keyboard.has_focus(c))
.unwrap_or(false)
{
let seat_data = seat.user_data().get::<RefCell<SeatData>>().unwrap();
(&mut *callback.borrow_mut())(DataDeviceEvent::NewSelection(source.clone()));
// The client has kbd focus, it can set the selection
seat_data
.borrow_mut()
.set_selection(source.map(Selection::Client).unwrap_or(Selection::Empty));
return;
}
debug!(log, "denying setting selection by a non-focused client");
}
Request::Release => {
// Clean up the known devices
seat.user_data()
.get::<RefCell<SeatData>>()
.unwrap()
.borrow_mut()
.known_devices
.retain(|ndd| ndd.as_ref().is_alive() && (!ndd.as_ref().equals(&dd.as_ref())))
}
_ => unreachable!(),
},
None::<fn(_)>,
dd_data,
)
debug!(log, "denying setting selection by a non-focused client");
}
Request::Release => {
// Clean up the known devices
seat.user_data()
.get::<RefCell<SeatData>>()
.unwrap()
.borrow_mut()
.known_devices
.retain(|ndd| ndd.as_ref().is_alive() && (!ndd.as_ref().equals(&dd.as_ref())))
}
_ => unreachable!(),
});
dd.as_ref().user_data().set(|| dd_data);
dd.deref().clone()
}
/// A simple action chooser for DnD negociation

View File

@ -1,10 +1,8 @@
use std::cell::RefCell;
use std::os::unix::io::RawFd;
use std::rc::Rc;
use std::{cell::RefCell, ops::Deref as _, os::unix::io::RawFd, rc::Rc};
use wayland_server::{
protocol::{wl_data_device_manager::DndAction, wl_data_offer, wl_pointer, wl_surface},
NewResource,
Main,
};
use crate::wayland::seat::{AxisFrame, GrabStartData, PointerGrab, PointerInnerHandle, Seat};
@ -120,7 +118,8 @@ where
{
let action_choice = device
.as_ref()
.user_data::<DataDeviceData>()
.user_data()
.get::<DataDeviceData>()
.unwrap()
.action_choice
.clone();
@ -229,7 +228,7 @@ struct OfferData {
}
fn implement_dnd_data_offer<C>(
offer: NewResource<wl_data_offer::WlDataOffer>,
offer: Main<wl_data_offer::WlDataOffer>,
metadata: super::SourceMetadata,
offer_data: Rc<RefCell<OfferData>>,
callback: Rc<RefCell<C>>,
@ -239,77 +238,74 @@ where
C: FnMut(ServerDndEvent) + 'static,
{
use self::wl_data_offer::Request;
offer.implement_closure(
move |req, offer| {
let mut data = offer_data.borrow_mut();
match req {
Request::Accept { mime_type, .. } => {
if let Some(mtype) = mime_type {
data.accepted = metadata.mime_types.contains(&mtype);
} else {
data.accepted = false;
}
offer.quick_assign(move |offer, req, _| {
let mut data = offer_data.borrow_mut();
match req {
Request::Accept { mime_type, .. } => {
if let Some(mtype) = mime_type {
data.accepted = metadata.mime_types.contains(&mtype);
} else {
data.accepted = false;
}
Request::Receive { mime_type, fd } => {
// check if the source and associated mime type is still valid
if metadata.mime_types.contains(&mime_type) && data.active {
(&mut *callback.borrow_mut())(ServerDndEvent::Send { mime_type, fd });
}
}
Request::Destroy => {}
Request::Finish => {
if !data.active {
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.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.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.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer with no valid action.".into(),
);
}
(&mut *callback.borrow_mut())(ServerDndEvent::Finished);
data.active = false;
}
Request::SetActions {
dnd_actions,
preferred_action,
} => {
let preferred_action = DndAction::from_bits_truncate(preferred_action);
if ![DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&preferred_action) {
offer.as_ref().post_error(
wl_data_offer::Error::InvalidAction as u32,
"Invalid preferred action.".into(),
);
}
let possible_actions = metadata.dnd_action & DndAction::from_bits_truncate(dnd_actions);
data.chosen_action =
(&mut *action_choice.borrow_mut())(possible_actions, preferred_action);
// check that the user provided callback respects that one precise action should be chosen
debug_assert!(
[DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&data.chosen_action)
);
offer.action(data.chosen_action.to_raw());
(&mut *callback.borrow_mut())(ServerDndEvent::Action(data.chosen_action));
}
_ => unreachable!(),
}
},
None::<fn(_)>,
(),
)
Request::Receive { mime_type, fd } => {
// check if the source and associated mime type is still valid
if metadata.mime_types.contains(&mime_type) && data.active {
(&mut *callback.borrow_mut())(ServerDndEvent::Send { mime_type, fd });
}
}
Request::Destroy => {}
Request::Finish => {
if !data.active {
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.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.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.as_ref().post_error(
wl_data_offer::Error::InvalidFinish as u32,
"Cannot finish a data offer with no valid action.".into(),
);
}
(&mut *callback.borrow_mut())(ServerDndEvent::Finished);
data.active = false;
}
Request::SetActions {
dnd_actions,
preferred_action,
} => {
let preferred_action = DndAction::from_bits_truncate(preferred_action);
if ![DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&preferred_action) {
offer.as_ref().post_error(
wl_data_offer::Error::InvalidAction as u32,
"Invalid preferred action.".into(),
);
}
let possible_actions = metadata.dnd_action & DndAction::from_bits_truncate(dnd_actions);
data.chosen_action = (&mut *action_choice.borrow_mut())(possible_actions, preferred_action);
// check that the user provided callback respects that one precise action should be chosen
debug_assert!(
[DndAction::Move, DndAction::Copy, DndAction::Ask].contains(&data.chosen_action)
);
offer.action(data.chosen_action.to_raw());
(&mut *callback.borrow_mut())(ServerDndEvent::Action(data.chosen_action));
}
_ => unreachable!(),
}
});
offer.deref().clone()
}

View File

@ -51,8 +51,7 @@
//!
//! // Once this is defined, you can in your setup initialize the dmabuf global:
//!
//! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # let mut display = wayland_server::Display::new();
//! // define your supported formats
//! let formats = vec![
//! /* ... */
@ -70,11 +69,11 @@ use std::{cell::RefCell, os::unix::io::RawFd, rc::Rc};
pub use wayland_protocols::unstable::linux_dmabuf::v1::server::zwp_linux_buffer_params_v1::Flags;
use wayland_protocols::unstable::linux_dmabuf::v1::server::{
zwp_linux_buffer_params_v1::{
Error as ParamError, RequestHandler as ParamRequestHandler, ZwpLinuxBufferParamsV1 as BufferParams,
Error as ParamError, Request as ParamsRequest, ZwpLinuxBufferParamsV1 as BufferParams,
},
zwp_linux_dmabuf_v1,
};
use wayland_server::{protocol::wl_buffer, Display, Global, NewResource};
use wayland_server::{protocol::wl_buffer, Display, Global, Main, Filter};
/// Representation of a Dmabuf format, as advertized to the client
pub struct Format {
@ -161,9 +160,11 @@ pub trait DmabufHandler {
fn create_buffer(
&mut self,
data: Self::BufferData,
buffer: NewResource<wl_buffer::WlBuffer>,
buffer: Main<wl_buffer::WlBuffer>,
) -> wl_buffer::WlBuffer {
buffer.implement_closure(|_, _| {}, None::<fn(_)>, data)
buffer.quick_assign(|_, _, _| {});
buffer.as_ref().user_data().set(|| data);
(*buffer).clone()
}
}
@ -193,29 +194,35 @@ where
formats.len()
);
display.create_global(3, move |new_dmabuf, version| {
display.create_global(3, Filter::new(move |(dmabuf, version): (Main<zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1>, u32), _, _| {
let dma_formats = formats.clone();
let dma_handler = handler.clone();
let dma_log = log.clone();
let dmabuf: zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1 = new_dmabuf.implement_closure(
move |req, _| {
dmabuf.quick_assign(
move |_, req, _| {
if let zwp_linux_dmabuf_v1::Request::CreateParams { params_id } = req {
params_id.implement(
ParamsHandler {
pending_planes: Vec::new(),
max_planes,
used: false,
formats: dma_formats.clone(),
handler: dma_handler.clone(),
log: dma_log.clone(),
let mut handler = ParamsHandler {
pending_planes: Vec::new(),
max_planes,
used: false,
formats: dma_formats.clone(),
handler: dma_handler.clone(),
log: dma_log.clone(),
};
params_id.quick_assign(move |params, req, _| match req {
ParamsRequest::Add { fd, plane_idx, offset, stride, modifier_hi, modifier_lo } => {
handler.add(&*params, fd, plane_idx, offset, stride, modifier_hi, modifier_lo)
},
None::<fn(_)>,
(),
);
ParamsRequest::Create { width, height, format, flags } => {
handler.create(&*params, width, height, format, flags)
},
ParamsRequest::CreateImmed { buffer_id, width, height, format, flags } => {
handler.create_immed(&*params, buffer_id, width, height, format, flags)
}
_ => {}
});
}
},
None::<fn(_)>,
(),
}
);
// send the supported formats
@ -225,7 +232,7 @@ where
dmabuf.modifier(f.format.as_raw(), (f.modifier >> 32) as u32, f.modifier as u32);
}
}
})
}))
}
struct ParamsHandler<H: DmabufHandler> {
@ -237,10 +244,10 @@ struct ParamsHandler<H: DmabufHandler> {
log: ::slog::Logger,
}
impl<H: DmabufHandler> ParamRequestHandler for ParamsHandler<H> {
impl<H: DmabufHandler> ParamsHandler<H> {
fn add(
&mut self,
params: BufferParams,
params: &BufferParams,
fd: RawFd,
plane_idx: u32,
offset: u32,
@ -284,7 +291,7 @@ impl<H: DmabufHandler> ParamRequestHandler for ParamsHandler<H> {
});
}
fn create(&mut self, params: BufferParams, width: i32, height: i32, format: u32, flags: u32) {
fn create(&mut self, params: &BufferParams, width: i32, height: i32, format: u32, flags: u32) {
// Cannot reuse a params:
if self.used {
params.as_ref().post_error(
@ -331,8 +338,8 @@ impl<H: DmabufHandler> ParamRequestHandler for ParamsHandler<H> {
fn create_immed(
&mut self,
params: BufferParams,
buffer_id: NewResource<wl_buffer::WlBuffer>,
params: &BufferParams,
buffer_id: Main<wl_buffer::WlBuffer>,
width: i32,
height: i32,
format: u32,

View File

@ -28,8 +28,7 @@
//! use smithay::wayland::explicit_synchronization::*;
//! # define_roles!(MyRoles);
//! #
//! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # let mut display = wayland_server::Display::new();
//! # let (compositor_token, _, _) = smithay::wayland::compositor::compositor_init::<MyRoles, _, _>(
//! # &mut display,
//! # |_, _, _| {},
@ -71,16 +70,24 @@
//! # }
//! ```
use std::os::unix::io::RawFd;
use std::{
cell::RefCell,
ops::{Deref as _, DerefMut as _},
os::unix::io::RawFd,
};
use wayland_protocols::unstable::linux_explicit_synchronization::v1::server::*;
use wayland_server::{protocol::wl_surface::WlSurface, Display, Global, NewResource};
use wayland_protocols::unstable::linux_explicit_synchronization::v1::server::{
zwp_linux_buffer_release_v1::ZwpLinuxBufferReleaseV1,
zwp_linux_explicit_synchronization_v1::{self, ZwpLinuxExplicitSynchronizationV1},
zwp_linux_surface_synchronization_v1::{self, ZwpLinuxSurfaceSynchronizationV1},
};
use wayland_server::{protocol::wl_surface::WlSurface, Display, Filter, Global, Main};
use crate::wayland::compositor::{CompositorToken, SurfaceAttributes};
/// An object to signal end of use of a buffer
pub struct ExplicitBufferRelease {
release: zwp_linux_buffer_release_v1::ZwpLinuxBufferReleaseV1,
release: ZwpLinuxBufferReleaseV1,
}
impl ExplicitBufferRelease {
@ -115,16 +122,16 @@ pub struct ExplicitSyncState {
struct InternalState {
sync_state: ExplicitSyncState,
sync_resource: zwp_linux_surface_synchronization_v1::ZwpLinuxSurfaceSynchronizationV1,
sync_resource: ZwpLinuxSurfaceSynchronizationV1,
}
struct ESUserData {
state: Option<InternalState>,
state: RefCell<Option<InternalState>>,
}
impl ESUserData {
fn take_state(&mut self) -> Option<ExplicitSyncState> {
if let Some(ref mut state) = self.state {
fn take_state(&self) -> Option<ExplicitSyncState> {
if let Some(state) = self.state.borrow_mut().deref_mut() {
Some(ExplicitSyncState {
acquire: state.sync_state.acquire.take(),
release: state.sync_state.release.take(),
@ -156,7 +163,7 @@ pub enum ExplicitSyncError {
pub fn get_explicit_synchronization_state(attrs: &mut SurfaceAttributes) -> Result<ExplicitSyncState, ()> {
attrs
.user_data
.get_mut::<ESUserData>()
.get::<ESUserData>()
.and_then(|s| s.take_state())
.ok_or(())
}
@ -168,7 +175,7 @@ pub fn get_explicit_synchronization_state(attrs: &mut SurfaceAttributes) -> Resu
/// function.
pub fn send_explicit_synchronization_error(attrs: &SurfaceAttributes, error: ExplicitSyncError) {
if let Some(ref data) = attrs.user_data.get::<ESUserData>() {
if let Some(ref state) = data.state {
if let Some(state) = data.state.borrow().deref() {
match error {
ExplicitSyncError::InvalidFence => state.sync_resource.as_ref().post_error(
zwp_linux_surface_synchronization_v1::Error::InvalidFence as u32,
@ -194,29 +201,31 @@ pub fn init_explicit_synchronization_global<R, L>(
display: &mut Display,
compositor: CompositorToken<R>,
logger: L,
) -> Global<zwp_linux_explicit_synchronization_v1::ZwpLinuxExplicitSynchronizationV1>
) -> Global<ZwpLinuxExplicitSynchronizationV1>
where
L: Into<Option<::slog::Logger>>,
R: 'static,
{
let _log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "wayland_explicit_synchronization"));
display.create_global::<zwp_linux_explicit_synchronization_v1::ZwpLinuxExplicitSynchronizationV1, _>(
display.create_global::<ZwpLinuxExplicitSynchronizationV1, _>(
2,
move |new_sync, _version| {
new_sync.implement_closure(
move |req, explicit_sync| {
Filter::new(
move |(sync, _version): (Main<ZwpLinuxExplicitSynchronizationV1>, _), _, _| {
sync.quick_assign(move |explicit_sync, req, _| {
if let zwp_linux_explicit_synchronization_v1::Request::GetSynchronization {
id,
surface,
} = req
{
let exists = compositor.with_surface_data(&surface, |attrs| {
attrs.user_data.insert_if_missing(|| ESUserData { state: None });
attrs.user_data.insert_if_missing(|| ESUserData {
state: RefCell::new(None),
});
attrs
.user_data
.get::<ESUserData>()
.map(|ud| ud.state.is_some())
.map(|ud| ud.state.borrow().is_some())
.unwrap()
});
if exists {
@ -228,8 +237,8 @@ where
}
let surface_sync = implement_surface_sync(id, surface.clone(), compositor);
compositor.with_surface_data(&surface, |attrs| {
let data = attrs.user_data.get_mut::<ESUserData>().unwrap();
data.state = Some(InternalState {
let data = attrs.user_data.get::<ESUserData>().unwrap();
*data.state.borrow_mut() = Some(InternalState {
sync_state: ExplicitSyncState {
acquire: None,
release: None,
@ -238,79 +247,75 @@ where
});
});
}
},
None::<fn(_)>,
(),
);
},
});
},
),
)
}
fn implement_surface_sync<R>(
id: NewResource<zwp_linux_surface_synchronization_v1::ZwpLinuxSurfaceSynchronizationV1>,
id: Main<ZwpLinuxSurfaceSynchronizationV1>,
surface: WlSurface,
compositor: CompositorToken<R>,
) -> zwp_linux_surface_synchronization_v1::ZwpLinuxSurfaceSynchronizationV1
) -> ZwpLinuxSurfaceSynchronizationV1
where
R: 'static,
{
id.implement_closure(
move |req, surface_sync| match req {
zwp_linux_surface_synchronization_v1::Request::SetAcquireFence { fd } => {
if !surface.as_ref().is_alive() {
surface_sync.as_ref().post_error(
zwp_linux_surface_synchronization_v1::Error::NoSurface as u32,
"The associated wl_surface was destroyed.".into(),
)
id.quick_assign(move |surface_sync, req, _| match req {
zwp_linux_surface_synchronization_v1::Request::SetAcquireFence { fd } => {
if !surface.as_ref().is_alive() {
surface_sync.as_ref().post_error(
zwp_linux_surface_synchronization_v1::Error::NoSurface as u32,
"The associated wl_surface was destroyed.".into(),
)
}
compositor.with_surface_data(&surface, |attrs| {
let data = attrs.user_data.get::<ESUserData>().unwrap();
if let Some(state) = data.state.borrow_mut().deref_mut() {
if state.sync_state.acquire.is_some() {
surface_sync.as_ref().post_error(
zwp_linux_surface_synchronization_v1::Error::DuplicateFence as u32,
"Multiple fences added for a single surface commit.".into(),
)
} else {
state.sync_state.acquire = Some(fd);
}
}
compositor.with_surface_data(&surface, |attrs| {
let data = attrs.user_data.get_mut::<ESUserData>().unwrap();
if let Some(ref mut state) = data.state {
if state.sync_state.acquire.is_some() {
surface_sync.as_ref().post_error(
zwp_linux_surface_synchronization_v1::Error::DuplicateFence as u32,
"Multiple fences added for a single surface commit.".into(),
)
} else {
state.sync_state.acquire = Some(fd);
}
}
});
});
}
zwp_linux_surface_synchronization_v1::Request::GetRelease { release } => {
if !surface.as_ref().is_alive() {
surface_sync.as_ref().post_error(
zwp_linux_surface_synchronization_v1::Error::NoSurface as u32,
"The associated wl_surface was destroyed.".into(),
)
}
zwp_linux_surface_synchronization_v1::Request::GetRelease { release } => {
if !surface.as_ref().is_alive() {
surface_sync.as_ref().post_error(
zwp_linux_surface_synchronization_v1::Error::NoSurface as u32,
"The associated wl_surface was destroyed.".into(),
)
compositor.with_surface_data(&surface, |attrs| {
let data = attrs.user_data.get::<ESUserData>().unwrap();
if let Some(state) = data.state.borrow_mut().deref_mut() {
if state.sync_state.acquire.is_some() {
surface_sync.as_ref().post_error(
zwp_linux_surface_synchronization_v1::Error::DuplicateRelease as u32,
"Multiple releases added for a single surface commit.".into(),
)
} else {
release.quick_assign(|_, _, _| {});
state.sync_state.release = Some(ExplicitBufferRelease {
release: release.deref().clone(),
});
}
}
compositor.with_surface_data(&surface, |attrs| {
let data = attrs.user_data.get_mut::<ESUserData>().unwrap();
if let Some(ref mut state) = data.state {
if state.sync_state.acquire.is_some() {
surface_sync.as_ref().post_error(
zwp_linux_surface_synchronization_v1::Error::DuplicateRelease as u32,
"Multiple releases added for a single surface commit.".into(),
)
} else {
state.sync_state.release = Some(ExplicitBufferRelease {
release: release.implement_dummy(),
});
}
}
});
}
zwp_linux_surface_synchronization_v1::Request::Destroy => {
// disable the ESUserData
compositor.with_surface_data(&surface, |attrs| {
if let Some(ref mut data) = attrs.user_data.get_mut::<ESUserData>() {
data.state = None;
}
});
}
_ => (),
},
None::<fn(_)>,
(),
)
});
}
zwp_linux_surface_synchronization_v1::Request::Destroy => {
// disable the ESUserData
compositor.with_surface_data(&surface, |attrs| {
if let Some(ref mut data) = attrs.user_data.get::<ESUserData>() {
*data.state.borrow_mut() = None;
}
});
}
_ => (),
});
id.deref().clone()
}

View File

@ -21,8 +21,7 @@
//! use smithay::wayland::output::{Output, PhysicalProperties, Mode};
//! use wayland_server::protocol::wl_output;
//!
//! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # let mut display = wayland_server::Display::new();
//! // Create the Output with given name and physical properties
//! let (output, _output_global) = Output::new(
//! &mut display, // the display
@ -49,12 +48,15 @@
//! output.add_mode(Mode { width: 1024, height: 768, refresh: 60000 });
//! ```
use std::sync::{Arc, Mutex};
use std::{
ops::Deref as _,
sync::{Arc, Mutex},
};
use wayland_server::protocol::wl_output::{Subpixel, Transform};
use wayland_server::{
protocol::wl_output::{Mode as WMode, WlOutput},
Display, Global, NewResource,
Display, Filter, Global, Main,
};
/// An output mode
@ -191,21 +193,24 @@ impl Output {
let output = Output { inner: inner.clone() };
let global = display.create_global(3, move |new_output: NewResource<_>, _version| {
let output = new_output.implement_closure(
|_, _| {},
Some(|output: WlOutput| {
let inner = output.as_ref().user_data::<Arc<Mutex<Inner>>>().unwrap();
let global = display.create_global(
3,
Filter::new(move |(output, _version): (Main<WlOutput>, _), _, _| {
output.assign_destructor(Filter::new(|output: WlOutput, _, _| {
let inner = output.as_ref().user_data().get::<Arc<Mutex<Inner>>>().unwrap();
inner
.lock()
.unwrap()
.instances
.retain(|o| !o.as_ref().equals(&output.as_ref()));
}),
inner.clone(),
);
inner.lock().unwrap().new_global(output);
});
}));
output.as_ref().user_data().set_threadsafe({
let inner = inner.clone();
move || inner
});
inner.lock().unwrap().new_global(output.deref().clone());
}),
);
(output, global)
}

View File

@ -3,6 +3,7 @@ use std::{
cell::RefCell,
default::Default,
io::{Error as IoError, Write},
ops::Deref as _,
os::unix::io::AsRawFd,
rc::Rc,
};
@ -12,7 +13,7 @@ use wayland_server::{
wl_keyboard::{KeyState as WlKeyState, KeymapFormat, Request, WlKeyboard},
wl_surface::WlSurface,
},
Client, NewResource,
Client, Filter, Main,
};
use xkbcommon::xkb;
pub use xkbcommon::xkb::{keysyms, Keysym};
@ -448,32 +449,25 @@ impl KeyboardHandle {
}
}
pub(crate) fn implement_keyboard(
new_keyboard: NewResource<WlKeyboard>,
handle: Option<&KeyboardHandle>,
) -> WlKeyboard {
let destructor = match handle {
Some(h) => {
let arc = h.arc.clone();
Some(move |keyboard: WlKeyboard| {
arc.internal
.borrow_mut()
.known_kbds
.retain(|k| !k.as_ref().equals(&keyboard.as_ref()))
})
}
None => None,
};
new_keyboard.implement_closure(
|request, _keyboard| {
match request {
Request::Release => {
// Our destructors already handle it
}
_ => unreachable!(),
pub(crate) fn implement_keyboard(keyboard: Main<WlKeyboard>, handle: Option<&KeyboardHandle>) -> WlKeyboard {
keyboard.quick_assign(|_keyboard, request, _data| {
match request {
Request::Release => {
// Our destructors already handle it
}
},
destructor,
(),
)
_ => unreachable!(),
}
});
if let Some(h) = handle {
let arc = h.arc.clone();
keyboard.assign_destructor(Filter::new(move |keyboard: WlKeyboard, _, _| {
arc.internal
.borrow_mut()
.known_kbds
.retain(|k| !k.as_ref().equals(&keyboard.as_ref()))
}));
}
keyboard.deref().clone()
}

View File

@ -17,8 +17,7 @@
//! // to set a surface as a cursor image
//! define_roles!(Roles => [CursorImage, CursorImageRole]);
//!
//! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # let mut display = wayland_server::Display::new();
//! # let (compositor_token, _, _) = compositor_init::<Roles, _, _>(&mut display, |_, _, _| {}, None);
//! // insert the seat:
//! let (seat, seat_global) = Seat::new(
@ -41,7 +40,7 @@
//! These methods return handles that can be cloned and sent across thread, so you can keep one around
//! in your event-handling code to forward inputs to your clients.
use std::{cell::RefCell, rc::Rc};
use std::{cell::RefCell, ops::Deref as _, rc::Rc};
mod keyboard;
mod pointer;
@ -56,11 +55,9 @@ pub use self::{
use crate::wayland::compositor::{roles::Role, CompositorToken};
use wayland_commons::utils::UserDataMap;
use wayland_server::{
protocol::{wl_seat, wl_surface},
Display, Global, NewResource,
Display, Filter, Global, Main, UserDataMap,
};
struct Inner {
@ -142,22 +139,26 @@ impl Seat {
user_data: UserDataMap::new(),
});
let seat = Seat { arc: arc.clone() };
let global = display.create_global(5, move |new_seat, _version| {
let seat = implement_seat(new_seat, arc.clone(), token);
let mut inner = arc.inner.borrow_mut();
if seat.as_ref().version() >= 2 {
seat.name(arc.name.clone());
}
seat.capabilities(inner.compute_caps());
inner.known_seats.push(seat);
});
let global = display.create_global(
5,
Filter::new(move |(new_seat, _version), _, _| {
let seat = implement_seat(new_seat, arc.clone(), token);
let mut inner = arc.inner.borrow_mut();
if seat.as_ref().version() >= 2 {
seat.name(arc.name.clone());
}
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: &wl_seat::WlSeat) -> Option<Seat> {
seat.as_ref()
.user_data::<Rc<SeatRc>>()
.user_data()
.get::<Rc<SeatRc>>()
.cloned()
.map(|arc| Seat { arc })
}
@ -189,8 +190,7 @@ impl Seat {
/// #
/// # define_roles!(Roles => [CursorImage, CursorImageRole]);
/// #
/// # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
/// # let mut display = wayland_server::Display::new(event_loop.handle());
/// # let mut display = wayland_server::Display::new();
/// # let (compositor_token, _, _) = compositor_init::<Roles, _, _>(&mut display, |_, _, _| {}, None);
/// # let (mut seat, seat_global) = Seat::new(
/// # &mut display,
@ -332,7 +332,7 @@ impl ::std::cmp::PartialEq for Seat {
}
fn implement_seat<R>(
new_seat: NewResource<wl_seat::WlSeat>,
seat: Main<wl_seat::WlSeat>,
arc: Rc<SeatRc>,
token: CompositorToken<R>,
) -> wl_seat::WlSeat
@ -340,44 +340,44 @@ where
R: Role<CursorImageRole> + 'static,
{
let dest_arc = arc.clone();
new_seat.implement_closure(
move |request, seat| {
let arc = seat.as_ref().user_data::<Rc<SeatRc>>().unwrap();
let inner = arc.inner.borrow_mut();
match request {
wl_seat::Request::GetPointer { id } => {
let pointer = self::pointer::implement_pointer(id, inner.pointer.as_ref(), token);
if let Some(ref ptr_handle) = inner.pointer {
ptr_handle.new_pointer(pointer);
} else {
// we should send a protocol error... but the protocol does not allow
// us, so this pointer will just remain inactive ¯\_(ツ)_/¯
}
seat.quick_assign(move |seat, request, _| {
let arc = seat.as_ref().user_data().get::<Rc<SeatRc>>().unwrap();
let inner = arc.inner.borrow_mut();
match request {
wl_seat::Request::GetPointer { id } => {
let pointer = self::pointer::implement_pointer(id, inner.pointer.as_ref(), token);
if let Some(ref ptr_handle) = inner.pointer {
ptr_handle.new_pointer(pointer);
} else {
// we should send a protocol error... but the protocol does not allow
// us, so this pointer will just remain inactive ¯\_(ツ)_/¯
}
wl_seat::Request::GetKeyboard { id } => {
let keyboard = self::keyboard::implement_keyboard(id, inner.keyboard.as_ref());
if let Some(ref kbd_handle) = inner.keyboard {
kbd_handle.new_kbd(keyboard);
} else {
// same as pointer, should error but cannot
}
}
wl_seat::Request::GetTouch { id: _ } => {
// TODO
}
wl_seat::Request::Release => {
// Our destructors already handle it
}
_ => unreachable!(),
}
},
Some(move |seat: wl_seat::WlSeat| {
dest_arc
.inner
.borrow_mut()
.known_seats
.retain(|s| !s.as_ref().equals(&seat.as_ref()));
}),
arc,
)
wl_seat::Request::GetKeyboard { id } => {
let keyboard = self::keyboard::implement_keyboard(id, inner.keyboard.as_ref());
if let Some(ref kbd_handle) = inner.keyboard {
kbd_handle.new_kbd(keyboard);
} else {
// same as pointer, should error but cannot
}
}
wl_seat::Request::GetTouch { id: _ } => {
// TODO
}
wl_seat::Request::Release => {
// Our destructors already handle it
}
_ => unreachable!(),
}
});
seat.assign_destructor(Filter::new(move |seat: wl_seat::WlSeat, _, _| {
dest_arc
.inner
.borrow_mut()
.known_seats
.retain(|s| !s.as_ref().equals(&seat.as_ref()));
}));
seat.as_ref().user_data().set(move || arc);
seat.deref().clone()
}

View File

@ -1,12 +1,11 @@
use std::cell::RefCell;
use std::rc::Rc;
use std::{cell::RefCell, ops::Deref as _, rc::Rc};
use wayland_server::{
protocol::{
wl_pointer::{self, Axis, AxisSource, ButtonState, Request, WlPointer},
wl_surface::WlSurface,
},
NewResource,
Filter, Main,
};
use crate::wayland::compositor::{roles::Role, CompositorToken};
@ -553,7 +552,7 @@ where
}
pub(crate) fn implement_pointer<R>(
new_pointer: NewResource<WlPointer>,
pointer: Main<WlPointer>,
handle: Option<&PointerHandle>,
token: CompositorToken<R>,
) -> WlPointer
@ -561,71 +560,70 @@ where
R: Role<CursorImageRole> + 'static,
{
let inner = handle.map(|h| h.inner.clone());
let destructor = match inner.clone() {
Some(inner) => Some(move |pointer: WlPointer| {
inner
.borrow_mut()
.known_pointers
.retain(|p| !p.as_ref().equals(&pointer.as_ref()))
}),
None => None,
};
new_pointer.implement_closure(
move |request, pointer: WlPointer| {
match request {
Request::SetCursor {
surface,
hotspot_x,
hotspot_y,
..
} => {
if let Some(ref inner) = inner {
let mut guard = inner.borrow_mut();
// only allow setting the cursor icon if the current pointer focus
// is of the same client
let PointerInternal {
ref mut image_callback,
ref focus,
..
} = *guard;
if let Some((ref focus, _)) = *focus {
if focus.as_ref().same_client_as(&pointer.as_ref()) {
match surface {
Some(surface) => {
let role_data = CursorImageRole {
hotspot: (hotspot_x, hotspot_y),
};
// we gracefully tolerate the client to provide a surface that
// already had the "CursorImage" role, as most clients will
// always reuse the same surface (and they are right to do so!)
if token.with_role_data(&surface, |data| *data = role_data).is_err()
&& token.give_role_with(&surface, role_data).is_err()
{
pointer.as_ref().post_error(
wl_pointer::Error::Role as u32,
"Given wl_surface has another role.".into(),
);
return;
}
image_callback(CursorImageStatus::Image(surface));
}
None => {
image_callback(CursorImageStatus::Hidden);
pointer.quick_assign(move |pointer, request, _data| {
match request {
Request::SetCursor {
surface,
hotspot_x,
hotspot_y,
..
} => {
if let Some(ref inner) = inner {
let mut guard = inner.borrow_mut();
// only allow setting the cursor icon if the current pointer focus
// is of the same client
let PointerInternal {
ref mut image_callback,
ref focus,
..
} = *guard;
if let Some((ref focus, _)) = *focus {
if focus.as_ref().same_client_as(&pointer.as_ref()) {
match surface {
Some(surface) => {
let role_data = CursorImageRole {
hotspot: (hotspot_x, hotspot_y),
};
// we gracefully tolerate the client to provide a surface that
// already had the "CursorImage" role, as most clients will
// always reuse the same surface (and they are right to do so!)
if token.with_role_data(&surface, |data| *data = role_data).is_err()
&& token.give_role_with(&surface, role_data).is_err()
{
pointer.as_ref().post_error(
wl_pointer::Error::Role as u32,
"Given wl_surface has another role.".into(),
);
return;
}
image_callback(CursorImageStatus::Image(surface));
}
None => {
image_callback(CursorImageStatus::Hidden);
}
}
}
}
}
Request::Release => {
// Our destructors already handle it
}
_ => unreachable!(),
}
},
destructor,
(),
)
Request::Release => {
// Our destructors already handle it
}
_ => unreachable!(),
}
});
if let Some(h) = handle {
let inner = h.inner.clone();
pointer.assign_destructor(Filter::new(move |pointer: WlPointer, _, _| {
inner
.borrow_mut()
.known_pointers
.retain(|p| !p.as_ref().equals(&pointer.as_ref()))
}))
}
pointer.deref().clone()
}
/*

View File

@ -42,8 +42,7 @@
//! [ShellSurface, ShellSurfaceRole]
//! );
//!
//! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # let mut display = wayland_server::Display::new();
//! # let (compositor_token, _, _) = smithay::wayland::compositor::compositor_init::<MyRoles, _, _>(
//! # &mut display,
//! # |_, _, _| {},
@ -71,7 +70,7 @@ use crate::wayland::compositor::{roles::Role, CompositorToken};
use wayland_server::{
protocol::{wl_output, wl_seat, wl_shell, wl_shell_surface, wl_surface},
Display, Global,
Display, Filter, Global,
};
mod wl_handlers;
@ -315,9 +314,9 @@ where
}));
let state2 = state.clone();
let global = display.create_global(1, move |shell, _version| {
let global = display.create_global(1, Filter::new(move |(shell, _version), _, _data| {
self::wl_handlers::implement_shell(shell, ctoken, implementation.clone(), state2.clone());
});
}));
(state, global)
}

View File

@ -1,12 +1,13 @@
use std::{
cell::RefCell,
ops::Deref as _,
rc::Rc,
sync::{Arc, Mutex},
};
use wayland_server::{
protocol::{wl_shell, wl_shell_surface, wl_surface},
NewResource,
Filter, Main,
};
use crate::wayland::compositor::{roles::Role, CompositorToken};
@ -14,7 +15,7 @@ use crate::wayland::compositor::{roles::Role, CompositorToken};
use super::{ShellRequest, ShellState, ShellSurface, ShellSurfaceKind, ShellSurfaceRole};
pub(crate) fn implement_shell<R, Impl>(
shell: NewResource<wl_shell::WlShell>,
shell: Main<wl_shell::WlShell>,
ctoken: CompositorToken<R>,
implementation: Rc<RefCell<Impl>>,
state: Arc<Mutex<ShellState<R>>>,
@ -22,8 +23,8 @@ pub(crate) fn implement_shell<R, Impl>(
R: Role<ShellSurfaceRole> + 'static,
Impl: FnMut(ShellRequest<R>) + 'static,
{
shell.implement_closure(
move |req, shell| {
shell.quick_assign(
move |shell, req, _data| {
let (id, surface) = match req {
wl_shell::Request::GetShellSurface { id, surface } => (id, surface),
_ => unreachable!(),
@ -51,8 +52,6 @@ pub(crate) fn implement_shell<R, Impl>(
surface: make_handle(&shell_surface, ctoken),
});
},
None::<fn(_)>,
(),
);
}
@ -65,7 +64,8 @@ where
{
let data = shell_surface
.as_ref()
.user_data::<ShellSurfaceUserData<R>>()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
ShellSurface {
wl_surface: data.surface.clone(),
@ -80,7 +80,7 @@ pub(crate) struct ShellSurfaceUserData<R> {
}
fn implement_shell_surface<R, Impl>(
shell_surface: NewResource<wl_shell_surface::WlShellSurface>,
shell_surface: Main<wl_shell_surface::WlShellSurface>,
surface: wl_surface::WlSurface,
implementation: Rc<RefCell<Impl>>,
ctoken: CompositorToken<R>,
@ -91,11 +91,12 @@ where
Impl: FnMut(ShellRequest<R>) + 'static,
{
use self::wl_shell_surface::Request;
shell_surface.implement_closure(
move |req, shell_surface| {
shell_surface.quick_assign(
move |shell_surface, req, _data| {
let data = shell_surface
.as_ref()
.user_data::<ShellSurfaceUserData<R>>()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
let mut user_impl = implementation.borrow_mut();
match req {
@ -185,13 +186,18 @@ where
_ => unreachable!(),
}
},
Some(|shell_surface: wl_shell_surface::WlShellSurface| {
let data = shell_surface
.as_ref()
.user_data::<ShellSurfaceUserData<R>>()
.unwrap();
data.state.lock().unwrap().cleanup_surfaces();
}),
ShellSurfaceUserData { surface, state },
)
);
shell_surface.assign_destructor(Filter::new(|shell_surface: wl_shell_surface::WlShellSurface, _, _data| {
let data = shell_surface
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
data.state.lock().unwrap().cleanup_surfaces();
}));
shell_surface.as_ref().user_data().set_threadsafe(|| ShellSurfaceUserData { surface, state });
shell_surface.deref().clone()
}

View File

@ -47,8 +47,7 @@
//! /* ... */
//! }
//!
//! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # let mut display = wayland_server::Display::new();
//! # let (compositor_token, _, _) = smithay::wayland::compositor::compositor_init::<MyRoles, _, _>(
//! # &mut display,
//! # |_, _, _| {},
@ -94,14 +93,13 @@ use std::{
rc::Rc,
sync::{Arc, Mutex},
};
use wayland_commons::utils::UserDataMap;
use wayland_protocols::{
unstable::xdg_shell::v6::server::{zxdg_popup_v6, zxdg_shell_v6, zxdg_surface_v6, zxdg_toplevel_v6},
xdg_shell::server::{xdg_popup, xdg_positioner, xdg_surface, xdg_toplevel, xdg_wm_base},
};
use wayland_server::{
protocol::{wl_output, wl_seat, wl_surface},
Display, Global,
Display, Filter, Global, UserDataMap,
};
// handlers for the xdg_shell protocol
@ -306,13 +304,13 @@ where
let shell_data_z = shell_data.clone();
let xdg_shell_global = display.create_global(1, move |shell, _version| {
let xdg_shell_global = display.create_global(1, Filter::new(move |(shell, _version), _, _data| {
self::xdg_handlers::implement_wm_base(shell, &shell_data);
});
}));
let zxdgv6_shell_global = display.create_global(1, move |shell, _version| {
let zxdgv6_shell_global = display.create_global(1, Filter::new(move |(shell, _version), _, _data| {
self::zxdgv6_handlers::implement_shell(shell, &shell_data_z);
});
}));
(shell_state, xdg_shell_global, zxdgv6_shell_global)
}
@ -418,7 +416,8 @@ where
ShellClientKind::Xdg(ref shell) => {
let user_data = shell
.as_ref()
.user_data::<self::xdg_handlers::ShellUserData<R>>()
.user_data()
.get::<self::xdg_handlers::ShellUserData<R>>()
.unwrap();
let mut guard = user_data.client_data.lock().unwrap();
if guard.pending_ping == 0 {
@ -430,7 +429,8 @@ where
ShellClientKind::ZxdgV6(ref shell) => {
let user_data = shell
.as_ref()
.user_data::<self::zxdgv6_handlers::ShellUserData<R>>()
.user_data()
.get::<self::zxdgv6_handlers::ShellUserData<R>>()
.unwrap();
let mut guard = user_data.client_data.lock().unwrap();
if guard.pending_ping == 0 {
@ -455,7 +455,8 @@ where
ShellClientKind::Xdg(ref shell) => {
let data = shell
.as_ref()
.user_data::<self::xdg_handlers::ShellUserData<R>>()
.user_data()
.get::<self::xdg_handlers::ShellUserData<R>>()
.unwrap();
let mut guard = data.client_data.lock().unwrap();
Ok(f(&mut guard.data))
@ -463,7 +464,8 @@ where
ShellClientKind::ZxdgV6(ref shell) => {
let data = shell
.as_ref()
.user_data::<self::zxdgv6_handlers::ShellUserData<R>>()
.user_data()
.get::<self::zxdgv6_handlers::ShellUserData<R>>()
.unwrap();
let mut guard = data.client_data.lock().unwrap();
Ok(f(&mut guard.data))
@ -526,14 +528,16 @@ where
ToplevelKind::Xdg(ref s) => {
let data = s
.as_ref()
.user_data::<self::xdg_handlers::ShellSurfaceUserData<R>>()
.user_data()
.get::<self::xdg_handlers::ShellSurfaceUserData<R>>()
.unwrap();
ShellClientKind::Xdg(data.wm_base.clone())
}
ToplevelKind::ZxdgV6(ref s) => {
let data = s
.as_ref()
.user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<R>>()
.user_data()
.get::<self::zxdgv6_handlers::ShellSurfaceUserData<R>>()
.unwrap();
ShellClientKind::ZxdgV6(data.shell.clone())
}
@ -579,7 +583,8 @@ where
ToplevelKind::Xdg(ref s) => {
let data = s
.as_ref()
.user_data::<self::xdg_handlers::ShellSurfaceUserData<R>>()
.user_data()
.get::<self::xdg_handlers::ShellSurfaceUserData<R>>()
.unwrap();
data.xdg_surface.as_ref().post_error(
xdg_surface::Error::NotConstructed as u32,
@ -589,7 +594,8 @@ where
ToplevelKind::ZxdgV6(ref s) => {
let data = s
.as_ref()
.user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<R>>()
.user_data()
.get::<self::zxdgv6_handlers::ShellSurfaceUserData<R>>()
.unwrap();
data.xdg_surface.as_ref().post_error(
zxdg_surface_v6::Error::NotConstructed as u32,
@ -682,14 +688,16 @@ where
PopupKind::Xdg(ref p) => {
let data = p
.as_ref()
.user_data::<self::xdg_handlers::ShellSurfaceUserData<R>>()
.user_data()
.get::<self::xdg_handlers::ShellSurfaceUserData<R>>()
.unwrap();
ShellClientKind::Xdg(data.wm_base.clone())
}
PopupKind::ZxdgV6(ref p) => {
let data = p
.as_ref()
.user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<R>>()
.user_data()
.get::<self::zxdgv6_handlers::ShellSurfaceUserData<R>>()
.unwrap();
ShellClientKind::ZxdgV6(data.shell.clone())
}
@ -739,7 +747,8 @@ where
PopupKind::Xdg(ref s) => {
let data = s
.as_ref()
.user_data::<self::xdg_handlers::ShellSurfaceUserData<R>>()
.user_data()
.get::<self::xdg_handlers::ShellSurfaceUserData<R>>()
.unwrap();
data.xdg_surface.as_ref().post_error(
xdg_surface::Error::NotConstructed as u32,
@ -749,7 +758,8 @@ where
PopupKind::ZxdgV6(ref s) => {
let data = s
.as_ref()
.user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<R>>()
.user_data()
.get::<self::zxdgv6_handlers::ShellSurfaceUserData<R>>()
.unwrap();
data.xdg_surface.as_ref().post_error(
zxdg_surface_v6::Error::NotConstructed as u32,

View File

@ -1,10 +1,10 @@
use std::{cell::RefCell, sync::Mutex};
use std::{cell::RefCell, ops::Deref as _, sync::Mutex};
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, NewResource};
use wayland_server::{protocol::wl_surface, Filter, Main};
use crate::utils::Rectangle;
@ -15,15 +15,14 @@ use super::{
};
pub(crate) fn implement_wm_base<R>(
shell: NewResource<xdg_wm_base::XdgWmBase>,
shell: Main<xdg_wm_base::XdgWmBase>,
shell_data: &ShellData<R>,
) -> xdg_wm_base::XdgWmBase
where
R: Role<XdgSurfaceRole> + 'static,
{
let shell = shell.implement_closure(
wm_implementation::<R>,
None::<fn(_)>,
shell.quick_assign(|shell, req, _data| wm_implementation::<R>(req, shell.deref().clone()));
shell.as_ref().user_data().set(||
ShellUserData {
shell_data: shell_data.clone(),
client_data: Mutex::new(make_shell_client_data()),
@ -33,7 +32,7 @@ where
(&mut *user_impl)(XdgRequest::NewClient {
client: make_shell_client(&shell, shell_data.compositor_token),
});
shell
shell.deref().clone()
}
/*
@ -59,7 +58,7 @@ fn wm_implementation<R>(request: xdg_wm_base::Request, shell: xdg_wm_base::XdgWm
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = shell.as_ref().user_data::<ShellUserData<R>>().unwrap();
let data = shell.as_ref().user_data().get::<ShellUserData<R>>().unwrap();
match request {
xdg_wm_base::Request::Destroy => {
// all is handled by destructor
@ -86,9 +85,11 @@ where
);
return;
}
id.implement_closure(
xdg_surface_implementation::<R>,
Some(destroy_surface::<R>),
id.quick_assign(|surface, req, _data| {
xdg_surface_implementation::<R>(req, surface.deref().clone())
});
id.assign_destructor(Filter::new(|surface, _, _data| destroy_surface::<R>(surface)));
id.as_ref().user_data().set(||
XdgSurfaceUserData {
shell_data: data.shell_data.clone(),
wl_surface: surface,
@ -121,14 +122,13 @@ where
* xdg_positioner
*/
fn implement_positioner(
positioner: NewResource<xdg_positioner::XdgPositioner>,
) -> xdg_positioner::XdgPositioner {
positioner.implement_closure(
|request, positioner| {
fn implement_positioner(positioner: Main<xdg_positioner::XdgPositioner>) -> xdg_positioner::XdgPositioner {
positioner.quick_assign(
|positioner, request, _data| {
let mutex = positioner
.as_ref()
.user_data::<RefCell<PositionerState>>()
.user_data()
.get::<RefCell<PositionerState>>()
.unwrap();
let mut state = mutex.borrow_mut();
match request {
@ -174,9 +174,12 @@ fn implement_positioner(
_ => unreachable!(),
}
},
None::<fn(_)>,
);
positioner.as_ref().user_data().set(||
RefCell::new(PositionerState::new()),
)
);
positioner.deref().clone()
}
/*
@ -193,7 +196,11 @@ fn destroy_surface<R>(surface: xdg_surface::XdgSurface)
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = surface.as_ref().user_data::<XdgSurfaceUserData<R>>().unwrap();
let data = surface
.as_ref()
.user_data()
.get::<XdgSurfaceUserData<R>>()
.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
@ -219,7 +226,11 @@ fn xdg_surface_implementation<R>(request: xdg_surface::Request, xdg_surface: xdg
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = xdg_surface.as_ref().user_data::<XdgSurfaceUserData<R>>().unwrap();
let data = xdg_surface
.as_ref()
.user_data()
.get::<XdgSurfaceUserData<R>>()
.unwrap();
match request {
xdg_surface::Request::Destroy => {
// all is handled by our destructor
@ -237,9 +248,11 @@ where
});
})
.expect("xdg_surface exists but surface has not shell_surface role?!");
let toplevel = id.implement_closure(
toplevel_implementation::<R>,
Some(destroy_toplevel::<R>),
id.quick_assign(
|toplevel, req, _data| toplevel_implementation::<R>(req, toplevel.deref().clone()),
);
id.assign_destructor(Filter::new(|toplevel, _, _data| destroy_toplevel::<R>(toplevel)));
id.as_ref().user_data().set(||
ShellSurfaceUserData {
shell_data: data.shell_data.clone(),
wl_surface: data.wl_surface.clone(),
@ -253,9 +266,9 @@ where
.lock()
.unwrap()
.known_toplevels
.push(make_toplevel_handle(&toplevel));
.push(make_toplevel_handle(&id));
let handle = make_toplevel_handle(&toplevel);
let handle = make_toplevel_handle(&id);
let mut user_impl = data.shell_data.user_impl.borrow_mut();
(&mut *user_impl)(XdgRequest::NewToplevel { surface: handle });
}
@ -266,11 +279,16 @@ where
} => {
let positioner_data = positioner
.as_ref()
.user_data::<RefCell<PositionerState>>()
.user_data()
.get::<RefCell<PositionerState>>()
.unwrap();
let parent_surface = parent.map(|parent| {
let parent_data = parent.as_ref().user_data::<XdgSurfaceUserData<R>>().unwrap();
let parent_data = parent
.as_ref()
.user_data()
.get::<XdgSurfaceUserData<R>>()
.unwrap();
parent_data.wl_surface.clone()
});
data.shell_data
@ -282,9 +300,9 @@ where
});
})
.expect("xdg_surface exists but surface has not shell_surface role?!");
let popup = id.implement_closure(
xg_popup_implementation::<R>,
Some(destroy_popup::<R>),
id.quick_assign(|popup, req, _data| xg_popup_implementation::<R>(req, popup.deref().clone()));
id.assign_destructor(Filter::new(|popup, _, _data| destroy_popup::<R>(popup)));
id.as_ref().user_data().set(||
ShellSurfaceUserData {
shell_data: data.shell_data.clone(),
wl_surface: data.wl_surface.clone(),
@ -298,9 +316,9 @@ where
.lock()
.unwrap()
.known_popups
.push(make_popup_handle(&popup));
.push(make_popup_handle(&id));
let handle = make_popup_handle(&popup);
let handle = make_popup_handle(&id);
let mut user_impl = data.shell_data.user_impl.borrow_mut();
(&mut *user_impl)(XdgRequest::NewPopup { surface: handle });
}
@ -361,7 +379,11 @@ where
R: Role<XdgSurfaceRole> + 'static,
F: FnOnce(&mut ToplevelState),
{
let toplevel_data = toplevel.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let toplevel_data = toplevel
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
shell_data
.compositor_token
.with_role_data::<XdgSurfaceRole, _, _>(&toplevel_data.wl_surface, |data| match data.pending_state {
@ -375,7 +397,11 @@ pub fn send_toplevel_configure<R>(resource: &xdg_toplevel::XdgToplevel, configur
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = resource
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.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 = {
@ -397,7 +423,11 @@ where
}
fn make_toplevel_handle<R: 'static>(resource: &xdg_toplevel::XdgToplevel) -> super::ToplevelSurface<R> {
let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = resource
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
super::ToplevelSurface {
wl_surface: data.wl_surface.clone(),
shell_surface: ToplevelKind::Xdg(resource.clone()),
@ -409,7 +439,11 @@ fn toplevel_implementation<R>(request: xdg_toplevel::Request, toplevel: xdg_topl
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = toplevel.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = toplevel
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
match request {
xdg_toplevel::Request::Destroy => {
// all it done by the destructor
@ -419,7 +453,8 @@ where
toplevel_data.parent = parent.map(|toplevel_surface_parent| {
toplevel_surface_parent
.as_ref()
.user_data::<ShellSurfaceUserData<R>>()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap()
.wl_surface
.clone()
@ -456,7 +491,6 @@ where
});
}
xdg_toplevel::Request::Resize { seat, serial, edges } => {
let edges = xdg_toplevel::ResizeEdge::from_raw(edges).unwrap_or(xdg_toplevel::ResizeEdge::None);
let handle = make_toplevel_handle(&toplevel);
let mut user_impl = data.shell_data.user_impl.borrow_mut();
(&mut *user_impl)(XdgRequest::Resize {
@ -512,7 +546,11 @@ fn destroy_toplevel<R>(toplevel: xdg_toplevel::XdgToplevel)
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = toplevel.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = toplevel
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.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
@ -543,7 +581,11 @@ pub(crate) fn send_popup_configure<R>(resource: &xdg_popup::XdgPopup, configure:
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = resource
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
let (x, y) = configure.position;
let (width, height) = configure.size;
let serial = configure.serial;
@ -557,7 +599,11 @@ where
}
fn make_popup_handle<R: 'static>(resource: &xdg_popup::XdgPopup) -> super::PopupSurface<R> {
let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = resource
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
super::PopupSurface {
wl_surface: data.wl_surface.clone(),
shell_surface: PopupKind::Xdg(resource.clone()),
@ -569,7 +615,11 @@ fn xg_popup_implementation<R>(request: xdg_popup::Request, popup: xdg_popup::Xdg
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = popup.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = popup
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
match request {
xdg_popup::Request::Destroy => {
// all is handled by our destructor
@ -591,7 +641,11 @@ fn destroy_popup<R>(popup: xdg_popup::XdgPopup)
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = popup.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = popup
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.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

View File

@ -1,4 +1,4 @@
use std::{cell::RefCell, sync::Mutex};
use std::{cell::RefCell, ops::Deref as _, sync::Mutex};
use crate::wayland::compositor::{roles::*, CompositorToken};
use wayland_protocols::{
@ -7,7 +7,7 @@ use wayland_protocols::{
},
xdg_shell::server::{xdg_positioner, xdg_toplevel},
};
use wayland_server::{protocol::wl_surface, NewResource};
use wayland_server::{protocol::wl_surface, Filter, Main};
use crate::utils::Rectangle;
@ -18,15 +18,14 @@ use super::{
};
pub(crate) fn implement_shell<R>(
shell: NewResource<zxdg_shell_v6::ZxdgShellV6>,
shell: Main<zxdg_shell_v6::ZxdgShellV6>,
shell_data: &ShellData<R>,
) -> zxdg_shell_v6::ZxdgShellV6
where
R: Role<XdgSurfaceRole> + 'static,
{
let shell = shell.implement_closure(
shell_implementation::<R>,
None::<fn(_)>,
shell.quick_assign(|shell, req, _data| shell_implementation::<R>(req, shell.deref().clone()));
shell.as_ref().user_data().set(||
ShellUserData {
shell_data: shell_data.clone(),
client_data: Mutex::new(make_shell_client_data()),
@ -36,7 +35,7 @@ where
(&mut *user_impl)(XdgRequest::NewClient {
client: make_shell_client(&shell, shell_data.compositor_token),
});
shell
shell.deref().clone()
}
/*
@ -62,7 +61,7 @@ fn shell_implementation<R>(request: zxdg_shell_v6::Request, shell: zxdg_shell_v6
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = shell.as_ref().user_data::<ShellUserData<R>>().unwrap();
let data = shell.as_ref().user_data().get::<ShellUserData<R>>().unwrap();
match request {
zxdg_shell_v6::Request::Destroy => {
// all is handled by destructor
@ -89,9 +88,9 @@ where
);
return;
}
id.implement_closure(
xdg_surface_implementation::<R>,
Some(destroy_surface::<R>),
id.quick_assign(|surface, req, _data| xdg_surface_implementation::<R>(req, surface.deref().clone()));
id.assign_destructor(Filter::new(|surface, _, _data| destroy_surface::<R>(surface)));
id.as_ref().user_data().set(||
XdgSurfaceUserData {
shell_data: data.shell_data.clone(),
wl_surface: surface,
@ -125,13 +124,14 @@ where
*/
fn implement_positioner(
positioner: NewResource<zxdg_positioner_v6::ZxdgPositionerV6>,
positioner: Main<zxdg_positioner_v6::ZxdgPositionerV6>,
) -> zxdg_positioner_v6::ZxdgPositionerV6 {
positioner.implement_closure(
|request, positioner| {
positioner.quick_assign(
|positioner, request, _data| {
let mutex = positioner
.as_ref()
.user_data::<RefCell<PositionerState>>()
.user_data()
.get::<RefCell<PositionerState>>()
.unwrap();
let mut state = mutex.borrow_mut();
match request {
@ -191,9 +191,12 @@ fn implement_positioner(
_ => unreachable!(),
}
},
None::<fn(_)>,
);
positioner.as_ref().user_data().set(||
RefCell::new(PositionerState::new()),
)
);
positioner.deref().clone()
}
/*
@ -210,7 +213,11 @@ fn destroy_surface<R>(surface: zxdg_surface_v6::ZxdgSurfaceV6)
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = surface.as_ref().user_data::<XdgSurfaceUserData<R>>().unwrap();
let data = surface
.as_ref()
.user_data()
.get::<XdgSurfaceUserData<R>>()
.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
@ -238,7 +245,11 @@ fn xdg_surface_implementation<R>(
) where
R: Role<XdgSurfaceRole> + 'static,
{
let data = xdg_surface.as_ref().user_data::<XdgSurfaceUserData<R>>().unwrap();
let data = xdg_surface
.as_ref()
.user_data()
.get::<XdgSurfaceUserData<R>>()
.unwrap();
match request {
zxdg_surface_v6::Request::Destroy => {
// all is handled by our destructor
@ -256,9 +267,9 @@ fn xdg_surface_implementation<R>(
});
})
.expect("xdg_surface exists but surface has not shell_surface role?!");
let toplevel = id.implement_closure(
toplevel_implementation::<R>,
Some(destroy_toplevel::<R>),
id.quick_assign(|toplevel, req, _data| toplevel_implementation::<R>(req, toplevel.deref().clone()));
id.assign_destructor(Filter::new(|toplevel, _, _data| destroy_toplevel::<R>(toplevel)));
id.as_ref().user_data().set(||
ShellSurfaceUserData {
shell_data: data.shell_data.clone(),
wl_surface: data.wl_surface.clone(),
@ -272,9 +283,9 @@ fn xdg_surface_implementation<R>(
.lock()
.unwrap()
.known_toplevels
.push(make_toplevel_handle(&toplevel));
.push(make_toplevel_handle(&id));
let handle = make_toplevel_handle(&toplevel);
let handle = make_toplevel_handle(&id);
let mut user_impl = data.shell_data.user_impl.borrow_mut();
(&mut *user_impl)(XdgRequest::NewToplevel { surface: handle });
}
@ -285,10 +296,15 @@ fn xdg_surface_implementation<R>(
} => {
let positioner_data = positioner
.as_ref()
.user_data::<RefCell<PositionerState>>()
.user_data()
.get::<RefCell<PositionerState>>()
.unwrap();
let parent_data = parent.as_ref().user_data::<XdgSurfaceUserData<R>>().unwrap();
let parent_data = parent
.as_ref()
.user_data()
.get::<XdgSurfaceUserData<R>>()
.unwrap();
data.shell_data
.compositor_token
.with_role_data::<XdgSurfaceRole, _, _>(&data.wl_surface, |data| {
@ -298,9 +314,9 @@ fn xdg_surface_implementation<R>(
});
})
.expect("xdg_surface exists but surface has not shell_surface role?!");
let popup = id.implement_closure(
popup_implementation::<R>,
Some(destroy_popup::<R>),
id.quick_assign(|popup, req, _data| popup_implementation::<R>(req, popup.deref().clone()));
id.assign_destructor(Filter::new(|popup, _, _data| destroy_popup::<R>(popup)));
id.as_ref().user_data().set(||
ShellSurfaceUserData {
shell_data: data.shell_data.clone(),
wl_surface: data.wl_surface.clone(),
@ -314,9 +330,9 @@ fn xdg_surface_implementation<R>(
.lock()
.unwrap()
.known_popups
.push(make_popup_handle(&popup));
.push(make_popup_handle(&id));
let handle = make_popup_handle(&popup);
let handle = make_popup_handle(&id);
let mut user_impl = data.shell_data.user_impl.borrow_mut();
(&mut *user_impl)(XdgRequest::NewPopup { surface: handle });
}
@ -377,7 +393,11 @@ where
R: Role<XdgSurfaceRole> + 'static,
F: FnOnce(&mut ToplevelState),
{
let data = toplevel.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = toplevel
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
data.shell_data
.compositor_token
.with_role_data::<XdgSurfaceRole, _, _>(&data.wl_surface, |data| match data.pending_state {
@ -391,7 +411,11 @@ pub fn send_toplevel_configure<R>(resource: &zxdg_toplevel_v6::ZxdgToplevelV6, c
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = resource
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.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 = {
@ -415,7 +439,11 @@ where
fn make_toplevel_handle<R: 'static>(
resource: &zxdg_toplevel_v6::ZxdgToplevelV6,
) -> super::ToplevelSurface<R> {
let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = resource
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
super::ToplevelSurface {
wl_surface: data.wl_surface.clone(),
shell_surface: ToplevelKind::ZxdgV6(resource.clone()),
@ -427,7 +455,11 @@ fn toplevel_implementation<R>(request: zxdg_toplevel_v6::Request, toplevel: zxdg
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = toplevel.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = toplevel
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
match request {
zxdg_toplevel_v6::Request::Destroy => {
// all it done by the destructor
@ -437,7 +469,8 @@ where
toplevel_data.parent = parent.map(|toplevel_surface_parent| {
let parent_data = toplevel_surface_parent
.as_ref()
.user_data::<ShellSurfaceUserData<R>>()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
parent_data.wl_surface.clone()
})
@ -530,7 +563,11 @@ fn destroy_toplevel<R>(toplevel: zxdg_toplevel_v6::ZxdgToplevelV6)
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = toplevel.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = toplevel
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.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
@ -561,7 +598,11 @@ pub(crate) fn send_popup_configure<R>(resource: &zxdg_popup_v6::ZxdgPopupV6, con
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = resource
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
let (x, y) = configure.position;
let (width, height) = configure.size;
let serial = configure.serial;
@ -575,7 +616,11 @@ where
}
fn make_popup_handle<R: 'static>(resource: &zxdg_popup_v6::ZxdgPopupV6) -> super::PopupSurface<R> {
let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = resource
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
super::PopupSurface {
wl_surface: data.wl_surface.clone(),
shell_surface: PopupKind::ZxdgV6(resource.clone()),
@ -587,7 +632,11 @@ fn popup_implementation<R>(request: zxdg_popup_v6::Request, popup: zxdg_popup_v6
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = popup.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = popup
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.unwrap();
match request {
zxdg_popup_v6::Request::Destroy => {
// all is handled by our destructor
@ -609,7 +658,11 @@ fn destroy_popup<R>(popup: zxdg_popup_v6::ZxdgPopupV6)
where
R: Role<XdgSurfaceRole> + 'static,
{
let data = popup.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
let data = popup
.as_ref()
.user_data()
.get::<ShellSurfaceUserData<R>>()
.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

View File

@ -22,8 +22,7 @@
//! use smithay::wayland::shm::init_shm_global;
//! use wayland_server::protocol::wl_shm::Format;
//!
//! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # let mut display = wayland_server::Display::new();
//! // Insert the ShmGlobal into your event loop
//! // Here, we specify that Yuyv and C8 format are supported
//! // additionally to the standard Argb8888 and Xrgb8888.
@ -75,10 +74,10 @@
//! If you are already using an handler for this signal, you probably don't want to use this handler.
use self::pool::{Pool, ResizeError};
use std::{rc::Rc, sync::Arc};
use std::{ops::Deref as _, rc::Rc, sync::Arc};
use wayland_server::{
protocol::{wl_buffer, wl_shm, wl_shm_pool},
Display, Global, NewResource,
Display, Filter, Global, Main,
};
mod pool;
@ -120,20 +119,20 @@ where
log: log.new(o!("smithay_module" => "shm_handler")),
};
display.create_global::<wl_shm::WlShm, _>(1, move |shm_new: NewResource<_>, _version| {
let shm = shm_new.implement_closure(
{
display.create_global::<wl_shm::WlShm, _>(
1,
Filter::new(move |(shm, _version): (Main<wl_shm::WlShm>, _), _, _| {
shm.quick_assign({
let mut data = data.clone();
move |req, shm| data.receive_shm_message(req, shm)
},
None::<fn(_)>,
(),
);
// send the formats
for &f in &data.formats[..] {
shm.format(f);
}
})
move |shm, req, _| data.receive_shm_message(req, shm.deref().clone())
});
// send the formats
for &f in &data.formats[..] {
shm.format(f);
}
}),
)
}
/// Error that can occur when accessing an SHM buffer
@ -164,7 +163,7 @@ pub fn with_buffer_contents<F, T>(buffer: &wl_buffer::WlBuffer, f: F) -> Result<
where
F: FnOnce(&[u8], BufferData) -> T,
{
let data = match buffer.as_ref().user_data::<InternalBufferData>() {
let data = match buffer.as_ref().user_data().get::<InternalBufferData>() {
Some(d) => d,
None => return Err(BufferAccessError::NotManaged),
};
@ -207,14 +206,11 @@ impl ShmGlobalData {
}
};
let arc_pool = Arc::new(mmap_pool);
pool.implement_closure(
{
let mut data = self.clone();
move |req, pool| data.receive_pool_message(req, pool)
},
None::<fn(_)>,
arc_pool,
);
pool.quick_assign({
let mut data = self.clone();
move |pool, req, _| data.receive_pool_message(req, pool.deref().clone())
});
pool.as_ref().user_data().set(move || arc_pool);
}
}
@ -242,7 +238,7 @@ impl ShmGlobalData {
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.as_ref().user_data::<Arc<Pool>>().unwrap();
let arc_pool = pool.as_ref().user_data().get::<Arc<Pool>>().unwrap();
match request {
Request::CreateBuffer {
@ -270,7 +266,8 @@ impl ShmGlobalData {
format,
},
};
buffer.implement_closure(|_, _| {}, None::<fn(_)>, data);
buffer.quick_assign(|_,_,_| {});
buffer.as_ref().user_data().set(|| data);
}
Request::Resize { size } => match arc_pool.resize(size) {
Ok(()) => {}

View File

@ -25,6 +25,7 @@
*
*/
use std::{
any::Any,
cell::RefCell,
env,
ffi::CString,
@ -33,6 +34,12 @@ use std::{
net::UnixStream,
},
rc::Rc,
sync::Arc,
};
use calloop::{
signals::{Signal, Signals},
LoopHandle, Source,
};
use nix::{
@ -42,13 +49,7 @@ use nix::{
Error as NixError, Result as NixResult,
};
use wayland_server::{
calloop::{
signals::{Signal, Signals},
LoopHandle, Source,
},
Client, Display,
};
use wayland_server::{Client, Display, Filter};
use super::x11_sockets::{prepare_x11_sockets, X11Lock};
@ -77,10 +78,11 @@ pub trait XWindowManager {
impl<WM: XWindowManager + 'static> XWayland<WM> {
/// Start the XWayland server
pub fn init<L, Data: 'static>(
pub fn init<L, T: Any, Data: 'static>(
wm: WM,
handle: LoopHandle<Data>,
display: Rc<RefCell<Display>>,
data: &mut T,
logger: L,
) -> Result<XWayland<WM>, ()>
where
@ -104,7 +106,7 @@ impl<WM: XWindowManager + 'static> XWayland<WM> {
instance: None,
log: log.new(o!("smithay_module" => "XWayland")),
}));
launch(&inner)?;
launch(&inner, data)?;
Ok(XWayland { inner })
}
}
@ -136,7 +138,10 @@ struct Inner<WM: XWindowManager> {
// Launch an XWayland server
//
// Does nothing if there is already a launched instance
fn launch<WM: XWindowManager + 'static>(inner: &Rc<RefCell<Inner<WM>>>) -> Result<(), ()> {
fn launch<WM: XWindowManager + 'static, T: Any>(
inner: &Rc<RefCell<Inner<WM>>>,
data: &mut T,
) -> Result<(), ()> {
let mut guard = inner.borrow_mut();
if guard.instance.is_some() {
return Ok(());
@ -159,10 +164,12 @@ fn launch<WM: XWindowManager + 'static>(inner: &Rc<RefCell<Inner<WM>>>) -> Resul
guard
.wayland_display
.borrow_mut()
.create_client(wl_me.into_raw_fd())
.create_client(wl_me.into_raw_fd(), data)
};
client.data_map().insert_if_missing(|| inner.clone());
client.add_destructor(client_destroy::<WM>);
client.add_destructor(Filter::new(|e: Arc<_>, _, mut data| {
client_destroy::<WM, T>(&e, data.get().unwrap())
}));
// setup the SIGUSR1 handler
let sigusr1_handler = (&mut *guard.source_maker)(inner.clone())?;
@ -245,7 +252,7 @@ impl<WM: XWindowManager> Inner<WM> {
if let Some(s) = instance.sigusr1_handler.take() {
s.remove();
}
// All connexions and lockfiles are cleaned by their destructors
// All connections and lockfiles are cleaned by their destructors
// Remove DISPLAY from the env
::std::env::remove_var("DISPLAY");
@ -257,7 +264,7 @@ impl<WM: XWindowManager> Inner<WM> {
}
}
fn client_destroy<WM: XWindowManager + 'static>(map: &::wayland_server::UserDataMap) {
fn client_destroy<WM: XWindowManager + 'static, T: Any>(map: &::wayland_server::UserDataMap, data: &mut T) {
let inner = map.get::<Rc<RefCell<Inner<WM>>>>().unwrap();
// shutdown the server
@ -268,7 +275,7 @@ fn client_destroy<WM: XWindowManager + 'static>(map: &::wayland_server::UserData
// at startup there is no point
if started_at.map(|t| t.elapsed().as_secs()).unwrap_or(10) > 5 {
warn!(inner.borrow().log, "XWayland crashed, restarting.");
let _ = launch(&inner);
let _ = launch(&inner, data);
} else {
warn!(
inner.borrow().log,