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:
parent
fbe20d6c1f
commit
b8c20ebf30
14
Cargo.toml
14
Cargo.toml
|
@ -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"]
|
||||
|
||||
|
|
|
@ -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" ]
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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[..]) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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>>>>,
|
||||
),
|
||||
>,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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>,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(()),
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(()) => {}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue