update to wayland-rs 0.21

This commit is contained in:
Victor Berger 2018-09-25 00:30:39 +02:00
parent 824ef5c186
commit 605895e30f
32 changed files with 1692 additions and 2069 deletions

View File

@ -10,12 +10,12 @@ repository = "https://github.com/Smithay/smithay"
members = [ "anvil" ] members = [ "anvil" ]
[dependencies] [dependencies]
wayland-server = "0.20.5" wayland-server = "0.21.1"
wayland-sys = "0.20.5" wayland-sys = "0.21.1"
nix = "0.10.0" nix = "0.11"
xkbcommon = "0.2.1" xkbcommon = "0.2.1"
tempfile = "2.1.5" tempfile = "2.1.5"
slog = { version = "2.1.1" } slog = "2.1.1"
slog-stdlog = "3.0.2" slog-stdlog = "3.0.2"
libloading = "0.4.0" libloading = "0.4.0"
wayland-client = { version = "0.20.5", optional = true } wayland-client = { version = "0.20.5", optional = true }
@ -27,7 +27,7 @@ input = { version = "0.4.0", optional = true }
udev = { version = "0.2.0", optional = true } udev = { version = "0.2.0", optional = true }
dbus = { version = "0.6.1", optional = true } dbus = { version = "0.6.1", optional = true }
systemd = { version = "^0.2.0", optional = true } systemd = { version = "^0.2.0", optional = true }
wayland-protocols = { version = "0.20.5", features = ["unstable_protocols", "server"] } wayland-protocols = { version = "0.21.1", features = ["unstable_protocols", "native_server"] }
image = "0.17.0" image = "0.17.0"
error-chain = "0.11.0" error-chain = "0.11.0"
lazy_static = "1.0.0" lazy_static = "1.0.0"
@ -45,4 +45,4 @@ backend_session_udev = ["udev", "backend_session"]
backend_session_logind = ["dbus", "systemd", "backend_session"] backend_session_logind = ["dbus", "systemd", "backend_session"]
backend_udev = ["udev", "backend_drm", "backend_session_udev"] backend_udev = ["udev", "backend_drm", "backend_session_udev"]
renderer_glium = ["glium"] renderer_glium = ["glium"]
xwayland = [] xwayland = []

View File

@ -11,7 +11,7 @@ slog-term = "2.3"
slog-async = "2.2" slog-async = "2.2"
rand = "0.3" rand = "0.3"
glium = { version = "0.19.0", default-features = false } glium = { version = "0.19.0", default-features = false }
wayland-server = "0.20" wayland-server = "0.21"
xkbcommon = "0.2.1" xkbcommon = "0.2.1"
[dependencies.smithay] [dependencies.smithay]
@ -28,4 +28,3 @@ winit = [ "smithay/backend_winit" ]
tty_launch = [ "smithay/backend_libinput", "smithay/backend_drm" ] tty_launch = [ "smithay/backend_libinput", "smithay/backend_drm" ]
udev = [ "tty_launch", "smithay/backend_udev" ] udev = [ "tty_launch", "smithay/backend_udev" ]
logind = [ "smithay/backend_session_logind" ] logind = [ "smithay/backend_session_logind" ]

View File

@ -11,6 +11,7 @@ extern crate xkbcommon;
use slog::Drain; use slog::Drain;
use smithay::wayland_server::Display; use smithay::wayland_server::Display;
use smithay::wayland_server::calloop::EventLoop;
#[macro_use] #[macro_use]
mod shaders; mod shaders;
@ -42,7 +43,8 @@ fn main() {
o!(), o!(),
); );
let (mut display, mut event_loop) = Display::new(); let mut event_loop = EventLoop::<()>::new().unwrap();
let mut display = Display::new(event_loop.handle());
let arg = ::std::env::args().nth(1); let arg = ::std::env::args().nth(1);
match arg.as_ref().map(|s| &s[..]) { match arg.as_ref().map(|s| &s[..]) {

View File

@ -15,7 +15,8 @@ use smithay::backend::drm::{drm_device_bind, DrmBackend, DrmDevice, DrmHandler};
use smithay::backend::graphics::egl::wayland::EGLWaylandExtensions; use smithay::backend::graphics::egl::wayland::EGLWaylandExtensions;
use smithay::wayland::compositor::CompositorToken; use smithay::wayland::compositor::CompositorToken;
use smithay::wayland::shm::init_shm_global; use smithay::wayland::shm::init_shm_global;
use smithay::wayland_server::{Display, EventLoop}; use smithay::wayland_server::Display;
use smithay::wayland_server::calloop::EventLoop;
use glium::Surface; use glium::Surface;
use slog::Logger; use slog::Logger;
@ -35,7 +36,7 @@ impl AsRawFd for Card {
impl BasicDevice for Card {} impl BasicDevice for Card {}
impl ControlDevice for Card {} impl ControlDevice for Card {}
pub fn run_raw_drm(mut display: Display, mut event_loop: EventLoop, log: Logger) -> Result<(), ()> { pub fn run_raw_drm(mut display: Display, mut event_loop: EventLoop<()>, log: Logger) -> Result<(), ()> {
/* /*
* Initialize the drm backend * Initialize the drm backend
*/ */
@ -100,9 +101,9 @@ pub fn run_raw_drm(mut display: Display, mut event_loop: EventLoop, log: Logger)
* Initialize the globals * Initialize the globals
*/ */
init_shm_global(&mut display, event_loop.token(), vec![], log.clone()); init_shm_global(&mut display, vec![], log.clone());
let (compositor_token, _, _, window_map) = init_shell(&mut display, event_loop.token(), log.clone()); let (compositor_token, _, _, window_map) = init_shell(&mut display, log.clone());
/* /*
* Add a listening socket: * Add a listening socket:
@ -114,7 +115,7 @@ pub fn run_raw_drm(mut display: Display, mut event_loop: EventLoop, log: Logger)
* Register the DrmDevice on the EventLoop * Register the DrmDevice on the EventLoop
*/ */
let _source = drm_device_bind( let _source = drm_device_bind(
&event_loop.token(), &event_loop.handle(),
device, device,
DrmHandlerImpl { DrmHandlerImpl {
compositor_token, compositor_token,
@ -126,7 +127,7 @@ pub fn run_raw_drm(mut display: Display, mut event_loop: EventLoop, log: Logger)
.unwrap(); .unwrap();
loop { loop {
event_loop.dispatch(Some(16)).unwrap(); event_loop.dispatch(Some(::std::time::Duration::from_millis(16)), &mut ()).unwrap();
display.flush_clients(); display.flush_clients();
window_map.borrow_mut().refresh(); window_map.borrow_mut().refresh();

View File

@ -10,7 +10,7 @@ use smithay::wayland::shell::legacy::{wl_shell_init, ShellRequest, ShellState as
use smithay::wayland::shell::xdg::{xdg_shell_init, PopupConfigure, ShellState as XdgShellState, use smithay::wayland::shell::xdg::{xdg_shell_init, PopupConfigure, ShellState as XdgShellState,
ToplevelConfigure, XdgRequest, XdgSurfaceRole}; ToplevelConfigure, XdgRequest, XdgSurfaceRole};
use smithay::wayland_server::protocol::{wl_buffer, wl_callback, wl_shell_surface, wl_surface}; use smithay::wayland_server::protocol::{wl_buffer, wl_callback, wl_shell_surface, wl_surface};
use smithay::wayland_server::{Display, LoopToken, Resource}; use smithay::wayland_server::{Display, Resource};
use window_map::{Kind as SurfaceKind, WindowMap}; use window_map::{Kind as SurfaceKind, WindowMap};
@ -23,7 +23,6 @@ pub type MyCompositorToken = CompositorToken<SurfaceData, Roles>;
pub fn init_shell( pub fn init_shell(
display: &mut Display, display: &mut Display,
looptoken: LoopToken,
log: ::slog::Logger, log: ::slog::Logger,
) -> ( ) -> (
CompositorToken<SurfaceData, Roles>, CompositorToken<SurfaceData, Roles>,
@ -34,11 +33,10 @@ pub fn init_shell(
// Create the compositor // Create the compositor
let (compositor_token, _, _) = compositor_init( let (compositor_token, _, _) = compositor_init(
display, display,
looptoken.clone(), move |request, surface, ctoken| match request {
move |request, (surface, ctoken)| match request {
SurfaceEvent::Commit => surface_commit(&surface, ctoken), SurfaceEvent::Commit => surface_commit(&surface, ctoken),
SurfaceEvent::Frame { callback } => callback SurfaceEvent::Frame { callback } => callback
.implement(|e, _| match e {}, None::<fn(_, _)>) .implement(|e, _| match e {}, None::<fn(_)>, ())
.send(wl_callback::Event::Done { callback_data: 0 }), .send(wl_callback::Event::Done { callback_data: 0 }),
}, },
log.clone(), log.clone(),
@ -54,9 +52,8 @@ pub fn init_shell(
let xdg_window_map = window_map.clone(); let xdg_window_map = window_map.clone();
let (xdg_shell_state, _, _) = xdg_shell_init( let (xdg_shell_state, _, _) = xdg_shell_init(
display, display,
looptoken.clone(),
compositor_token, compositor_token,
move |shell_event, ()| match shell_event { move |shell_event| match shell_event {
XdgRequest::NewToplevel { surface } => { XdgRequest::NewToplevel { surface } => {
// place the window at a random location in the [0;300]x[0;300] square // place the window at a random location in the [0;300]x[0;300] square
use rand::distributions::{IndependentSample, Range}; use rand::distributions::{IndependentSample, Range};
@ -87,9 +84,8 @@ pub fn init_shell(
let shell_window_map = window_map.clone(); let shell_window_map = window_map.clone();
let (wl_shell_state, _) = wl_shell_init( let (wl_shell_state, _) = wl_shell_init(
display, display,
looptoken,
compositor_token, compositor_token,
move |req: ShellRequest<_, _, ()>, ()| move |req: ShellRequest<_, _, ()>|
if let ShellRequest::SetKind { if let ShellRequest::SetKind {
surface, surface,
kind: ShellSurfaceKind::Toplevel, kind: ShellSurfaceKind::Toplevel,

View File

@ -30,8 +30,8 @@ use smithay::wayland::compositor::CompositorToken;
use smithay::wayland::output::{Mode, Output, PhysicalProperties}; use smithay::wayland::output::{Mode, Output, PhysicalProperties};
use smithay::wayland::seat::Seat; use smithay::wayland::seat::Seat;
use smithay::wayland::shm::init_shm_global; use smithay::wayland::shm::init_shm_global;
use smithay::wayland_server::{Display, EventLoop}; use smithay::wayland_server::Display;
use smithay::wayland_server::commons::downcast_impl; use smithay::wayland_server::calloop::EventLoop;
use smithay::wayland_server::protocol::wl_output; use smithay::wayland_server::protocol::wl_output;
use smithay::input::Libinput; use smithay::input::Libinput;
@ -39,7 +39,7 @@ use glium_drawer::GliumDrawer;
use shell::{init_shell, MyWindowMap, Roles, SurfaceData}; use shell::{init_shell, MyWindowMap, Roles, SurfaceData};
use input_handler::AnvilInputHandler; use input_handler::AnvilInputHandler;
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<()>, log: Logger) -> Result<(), ()> {
let name = display.add_socket_auto().unwrap().into_string().unwrap(); let name = display.add_socket_auto().unwrap().into_string().unwrap();
info!(log, "Listening on wayland socket"; "name" => name.clone()); info!(log, "Listening on wayland socket"; "name" => name.clone());
::std::env::set_var("WAYLAND_DISPLAY", name); ::std::env::set_var("WAYLAND_DISPLAY", name);
@ -53,14 +53,12 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop, log: Logger) ->
*/ */
init_shm_global( init_shm_global(
&mut display.borrow_mut(), &mut display.borrow_mut(),
event_loop.token(),
vec![], vec![],
log.clone(), log.clone(),
); );
let (compositor_token, _, _, window_map) = init_shell( let (compositor_token, _, _, window_map) = init_shell(
&mut display.borrow_mut(), &mut display.borrow_mut(),
event_loop.token(),
log.clone(), log.clone(),
); );
@ -83,7 +81,7 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop, log: Logger) ->
let bytes = include_bytes!("../resources/cursor2.rgba"); let bytes = include_bytes!("../resources/cursor2.rgba");
let mut udev_backend = UdevBackend::new( let mut udev_backend = UdevBackend::new(
event_loop.token(), event_loop.handle(),
&context, &context,
session.clone(), session.clone(),
UdevHandlerImpl { UdevHandlerImpl {
@ -104,7 +102,6 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop, log: Logger) ->
let (mut w_seat, _) = Seat::new( let (mut w_seat, _) = Seat::new(
&mut display.borrow_mut(), &mut display.borrow_mut(),
event_loop.token(),
session.seat(), session.seat(),
log.clone(), log.clone(),
); );
@ -116,13 +113,12 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop, log: Logger) ->
let (output, _output_global) = Output::new( let (output, _output_global) = Output::new(
&mut display.borrow_mut(), &mut display.borrow_mut(),
event_loop.token(),
"Drm".into(), "Drm".into(),
PhysicalProperties { PhysicalProperties {
width: 0, width: 0,
height: 0, height: 0,
subpixel: wl_output::Subpixel::Unknown, subpixel: wl_output::Subpixel::Unknown,
maker: "Smithay".into(), make: "Smithay".into(),
model: "Generic DRM".into(), model: "Generic DRM".into(),
}, },
log.clone(), log.clone(),
@ -162,19 +158,16 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop, log: Logger) ->
pointer_location, pointer_location,
session, session,
)); ));
let libinput_event_source = libinput_bind(libinput_backend, event_loop.token()) let libinput_event_source = libinput_bind(libinput_backend, event_loop.handle())
.map_err(|(err, _)| err)
.unwrap(); .unwrap();
let session_event_source = auto_session_bind(notifier, &event_loop.token()) let session_event_source = auto_session_bind(notifier, &event_loop.handle())
.map_err(|(err, _)| err)
.unwrap(); .unwrap();
let udev_event_source = udev_backend_bind(&event_loop.token(), udev_backend) let udev_event_source = udev_backend_bind(udev_backend)
.map_err(|(err, _)| err)
.unwrap(); .unwrap();
while running.load(Ordering::SeqCst) { while running.load(Ordering::SeqCst) {
if event_loop.dispatch(Some(16)).is_err() { if event_loop.dispatch(Some(::std::time::Duration::from_millis(16)), &mut ()).is_err() {
running.store(false, Ordering::SeqCst); running.store(false, Ordering::SeqCst);
} else { } else {
display.borrow_mut().flush_clients(); display.borrow_mut().flush_clients();
@ -187,14 +180,8 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop, log: Logger) ->
notifier.unregister(libinput_session_id); notifier.unregister(libinput_session_id);
libinput_event_source.remove(); libinput_event_source.remove();
udev_event_source.remove();
// destroy the udev backend freeing the drm devices
//
// udev_event_source.remove() returns a Box<Implementation<..>>, downcast_impl
// allows us to cast it back to its original type, storing it back into its original
// variable to simplify type inference.
udev_backend = *(downcast_impl(udev_event_source.remove()).unwrap_or_else(|_| unreachable!()));
udev_backend.close();
Ok(()) Ok(())
} }

View File

@ -10,7 +10,8 @@ use smithay::backend::input::InputBackend;
use smithay::backend::winit; use smithay::backend::winit;
use smithay::backend::graphics::egl::EGLGraphicsBackend; use smithay::backend::graphics::egl::EGLGraphicsBackend;
use smithay::backend::graphics::egl::wayland::EGLWaylandExtensions; use smithay::backend::graphics::egl::wayland::EGLWaylandExtensions;
use smithay::wayland_server::{Display, EventLoop}; use smithay::wayland_server::Display;
use smithay::wayland_server::calloop::EventLoop;
use smithay::wayland_server::protocol::wl_output; use smithay::wayland_server::protocol::wl_output;
use slog::Logger; use slog::Logger;
@ -19,7 +20,7 @@ use glium_drawer::GliumDrawer;
use shell::init_shell; use shell::init_shell;
use input_handler::AnvilInputHandler; use input_handler::AnvilInputHandler;
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<()>, log: Logger) -> Result<(), ()> {
let (renderer, mut input) = winit::init(log.clone()).map_err(|_| ())?; let (renderer, mut input) = winit::init(log.clone()).map_err(|_| ())?;
let egl_display = Rc::new(RefCell::new( let egl_display = Rc::new(RefCell::new(
@ -44,11 +45,11 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger)
* Initialize the globals * Initialize the globals
*/ */
init_shm_global(display, event_loop.token(), vec![], log.clone()); init_shm_global(display, vec![], log.clone());
let (compositor_token, _, _, window_map) = init_shell(display, event_loop.token(), log.clone()); let (compositor_token, _, _, window_map) = init_shell(display, log.clone());
let (mut seat, _) = Seat::new(display, event_loop.token(), "winit".into(), log.clone()); let (mut seat, _) = Seat::new(display, "winit".into(), log.clone());
let pointer = seat.add_pointer(); let pointer = seat.add_pointer();
let keyboard = seat.add_keyboard("", "fr", "oss", None, 1000, 500) let keyboard = seat.add_keyboard("", "fr", "oss", None, 1000, 500)
@ -56,13 +57,12 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger)
let (output, _) = Output::new( let (output, _) = Output::new(
display, display,
event_loop.token(),
"Winit".into(), "Winit".into(),
PhysicalProperties { PhysicalProperties {
width: 0, width: 0,
height: 0, height: 0,
subpixel: wl_output::Subpixel::Unknown, subpixel: wl_output::Subpixel::Unknown,
maker: "Smithay".into(), make: "Smithay".into(),
model: "Winit".into(), model: "Winit".into(),
}, },
log.clone(), log.clone(),
@ -100,7 +100,10 @@ pub fn run_winit(display: &mut Display, event_loop: &mut EventLoop, log: Logger)
drawer.draw_windows(&*window_map.borrow(), compositor_token, &log); drawer.draw_windows(&*window_map.borrow(), compositor_token, &log);
event_loop.dispatch(Some(16)).unwrap(); event_loop.dispatch(
Some(::std::time::Duration::from_millis(16)),
&mut ()
).unwrap();
display.flush_clients(); display.flush_clients();
window_map.borrow_mut().refresh(); window_map.borrow_mut().refresh();

View File

@ -150,7 +150,8 @@
//! # //! #
//! # fn main() { //! # fn main() {
//! # //! #
//! # let (_display, mut event_loop) = wayland_server::Display::new(); //! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # //! #
//! # let mut options = OpenOptions::new(); //! # let mut options = OpenOptions::new();
//! # options.read(true); //! # options.read(true);
@ -199,12 +200,12 @@
//! backend.swap_buffers().unwrap(); //! backend.swap_buffers().unwrap();
//! //!
//! let (_source, _device_rc) = drm_device_bind( //! let (_source, _device_rc) = drm_device_bind(
//! &event_loop.token(), //! &event_loop.handle(),
//! device, //! device,
//! MyDrmHandler(backend) //! MyDrmHandler(backend)
//! ).map_err(|(err, _)| err).unwrap(); //! ).map_err(|(err, _)| err).unwrap();
//! //!
//! event_loop.run().unwrap(); //! /* And then run the event loop once all your setup is done */
//! # } //! # }
//! ``` //! ```
@ -232,9 +233,10 @@ use std::rc::{Rc, Weak};
use std::sync::{Arc, Once, ONCE_INIT}; use std::sync::{Arc, Once, ONCE_INIT};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration; use std::time::Duration;
use wayland_server::{Display, LoopToken};
use wayland_server::commons::Implementation; use wayland_server::Display;
use wayland_server::sources::{FdEvent, FdInterest, Source}; use wayland_server::calloop::{LoopHandle, Source, Ready};
use wayland_server::calloop::generic::{Generic, EventedRawFd};
mod backend; mod backend;
pub mod error; pub mod error;
@ -546,84 +548,69 @@ pub trait DrmHandler<A: ControlDevice + 'static> {
/// Bind a `DrmDevice` to an `EventLoop`, /// Bind a `DrmDevice` to an `EventLoop`,
/// ///
/// This will cause it to recieve events and feed them into an `DrmHandler` /// This will cause it to recieve events and feed them into an `DrmHandler`
pub fn drm_device_bind<A, H>( pub fn drm_device_bind<A, H, Data: 'static>(
token: &LoopToken, handle: &LoopHandle<Data>,
device: DrmDevice<A>, device: DrmDevice<A>,
handler: H, mut handler: H,
) -> ::std::result::Result<(Source<FdEvent>, Rc<RefCell<DrmDevice<A>>>), (IoError, (DrmDevice<A>, H))> ) -> ::std::result::Result<(Source<Generic<EventedRawFd>>, Rc<RefCell<DrmDevice<A>>>), (IoError, DrmDevice<A>)>
where where
A: ControlDevice + 'static, A: ControlDevice + 'static,
H: DrmHandler<A> + 'static, H: DrmHandler<A> + 'static,
{ {
let fd = device.as_raw_fd(); let fd = device.as_raw_fd();
let device = Rc::new(RefCell::new(device)); let device = Rc::new(RefCell::new(device));
match token.add_fd_event_source(
fd, let mut source = Generic::from_raw_fd(fd);
FdInterest::READ, source.set_interest(Ready::readable());
DrmFdImpl {
device: device.clone(), match handle.insert_source(
handler, source,
}, {
let device = device.clone();
move |_evt, _| {
let mut device = device.borrow_mut();
process_events(&mut *device, &mut handler);
}
}
) { ) {
Ok(source) => Ok((source, device)), Ok(source) => Ok((source, device)),
Err(( Err(e) => {
ioerror,
DrmFdImpl {
device: device2,
handler,
},
)) => {
// make the Rc unique again
::std::mem::drop(device2);
let device = Rc::try_unwrap(device).unwrap_or_else(|_| unreachable!()); let device = Rc::try_unwrap(device).unwrap_or_else(|_| unreachable!());
Err((ioerror, (device.into_inner(), handler))) Err((e, device.into_inner()))
} }
} }
} }
struct DrmFdImpl<A: ControlDevice + 'static, H> { fn process_events<A, H>(device: &mut DrmDevice<A>, handler: &mut H)
device: Rc<RefCell<DrmDevice<A>>>, where
handler: H,
}
impl<A, H> Implementation<(), FdEvent> for DrmFdImpl<A, H>
where
A: ControlDevice + 'static, A: ControlDevice + 'static,
H: DrmHandler<A> + 'static, H: DrmHandler<A> + 'static,
{ {
fn receive(&mut self, event: FdEvent, (): ()) { match crtc::receive_events(&*device) {
let mut device = self.device.borrow_mut(); Ok(events) => for event in events {
match event { if let crtc::Event::PageFlip(event) = event {
FdEvent::Ready { .. } => match crtc::receive_events(&*device) { if device.active.load(Ordering::SeqCst) {
Ok(events) => for event in events { let backends = device.backends.borrow().clone();
if let crtc::Event::PageFlip(event) = event { if let Some(backend) = backends
if device.active.load(Ordering::SeqCst) { .get(&event.crtc)
let backends = device.backends.borrow().clone(); .iter()
if let Some(backend) = backends .flat_map(|x| x.upgrade())
.get(&event.crtc) .next()
.iter() {
.flat_map(|x| x.upgrade()) // we can now unlock the buffer
.next() backend.unlock_buffer();
{ trace!(device.logger, "Handling event for backend {:?}", event.crtc);
// we can now unlock the buffer // and then call the user to render the next frame
backend.unlock_buffer(); handler
trace!(device.logger, "Handling event for backend {:?}", event.crtc); .ready(device, event.crtc, event.frame, event.duration);
// and then call the user to render the next frame } else {
self.handler device.backends.borrow_mut().remove(&event.crtc);
.ready(&mut device, event.crtc, event.frame, event.duration);
} else {
device.backends.borrow_mut().remove(&event.crtc);
}
}
} }
}, }
Err(err) => self.handler.error(&mut device, err),
},
FdEvent::Error { error, .. } => {
warn!(device.logger, "DrmDevice errored: {}", error);
self.handler.error(&mut device, error.into());
} }
} },
Err(err) => handler.error(device, err),
} }
} }

View File

@ -11,9 +11,9 @@ use std::hash::{Hash, Hasher};
use std::io::Error as IoError; use std::io::Error as IoError;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use std::path::Path; use std::path::Path;
use wayland_server::LoopToken;
use wayland_server::commons::Implementation; use wayland_server::calloop::{LoopHandle, Source, Ready};
use wayland_server::sources::{FdEvent, FdInterest, Source}; use wayland_server::calloop::generic::{Generic, EventedRawFd};
// No idea if this is the same across unix platforms // No idea if this is the same across unix platforms
// Lets make this linux exclusive for now, once someone tries to build it for // Lets make this linux exclusive for now, once someone tries to build it for
@ -600,26 +600,19 @@ impl<S: Session> libinput::LibinputInterface for LibinputSessionInterface<S> {
/// ///
/// Automatically feeds the backend with incoming events without any manual calls to /// Automatically feeds the backend with incoming events without any manual calls to
/// `dispatch_new_events`. Should be used to achieve the smallest possible latency. /// `dispatch_new_events`. Should be used to achieve the smallest possible latency.
pub fn libinput_bind( pub fn libinput_bind<Data: 'static>(
backend: LibinputInputBackend, mut backend: LibinputInputBackend,
token: LoopToken, handle: LoopHandle<Data>,
) -> ::std::result::Result<Source<FdEvent>, (IoError, LibinputInputBackend)> { ) -> ::std::result::Result<Source<Generic<EventedRawFd>>, IoError> {
let fd = unsafe { backend.context.fd() }; let mut source = Generic::from_raw_fd(unsafe { backend.context.fd() });
token.add_fd_event_source(fd, FdInterest::READ, backend) source.set_interest(Ready::readable());
} handle.insert_source(
source,
impl Implementation<(), FdEvent> for LibinputInputBackend { move |_, _| {
fn receive(&mut self, event: FdEvent, (): ()) { use backend::input::InputBackend;
match event { if let Err(error) = backend.dispatch_new_events() {
FdEvent::Ready { .. } => { warn!(backend.logger, "Libinput errored: {}", error);
use backend::input::InputBackend;
if let Err(error) = self.dispatch_new_events() {
warn!(self.logger, "Libinput errored: {}", error);
}
}
FdEvent::Error { error, .. } => {
warn!(self.logger, "Libinput fd errored: {}", error);
} }
} }
} )
} }

View File

@ -1,4 +1,3 @@
//!
//! Implementation of the `Session` trait through various implementations //! Implementation of the `Session` trait through various implementations
//! automatically choosing the best available interface. //! automatically choosing the best available interface.
//! //!
@ -30,7 +29,7 @@
//! ``` //! ```
use super::{AsErrno, AsSessionObserver, Session, SessionNotifier, SessionObserver}; use super::{AsErrno, AsSessionObserver, Session, SessionNotifier, SessionObserver};
use super::direct::{self, direct_session_bind, DirectSession, DirectSessionNotifier}; use super::direct::{self, direct_session_bind, DirectSession, DirectSessionNotifier, BoundDirectSession};
#[cfg(feature = "backend_session_logind")] #[cfg(feature = "backend_session_logind")]
use super::logind::{self, logind_session_bind, BoundLogindSession, LogindSession, LogindSessionNotifier}; use super::logind::{self, logind_session_bind, BoundLogindSession, LogindSession, LogindSessionNotifier};
use nix::fcntl::OFlag; use nix::fcntl::OFlag;
@ -39,9 +38,8 @@ use std::io::Error as IoError;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use std::path::Path; use std::path::Path;
use std::rc::Rc; use std::rc::Rc;
use wayland_server::LoopToken;
use wayland_server::commons::downcast_impl; use wayland_server::calloop::LoopHandle;
use wayland_server::sources::{SignalEvent, Source};
/// `Session` using the best available inteface /// `Session` using the best available inteface
#[derive(Clone)] #[derive(Clone)]
@ -62,7 +60,7 @@ pub enum AutoSessionNotifier {
Direct(DirectSessionNotifier), Direct(DirectSessionNotifier),
} }
/// Bound session that is driven by the `wayland_server::EventLoop`. /// Bound session that is driven by the `calloop::EventLoop`.
/// ///
/// See `auto_session_bind` for details. /// See `auto_session_bind` for details.
/// ///
@ -72,7 +70,7 @@ pub enum BoundAutoSession {
#[cfg(feature = "backend_session_logind")] #[cfg(feature = "backend_session_logind")]
Logind(BoundLogindSession), Logind(BoundLogindSession),
/// Bound direct / tty session /// Bound direct / tty session
Direct(Source<SignalEvent>), Direct(BoundDirectSession),
} }
/// Id's used by the `AutoSessionNotifier` internally. /// Id's used by the `AutoSessionNotifier` internally.
@ -153,16 +151,14 @@ impl AutoSession {
/// Allows the `AutoSessionNotifier` to listen for incoming signals signalling the session state. /// Allows the `AutoSessionNotifier` to listen for incoming signals signalling the session state.
/// If you don't use this function `AutoSessionNotifier` will not correctly tell you the /// If you don't use this function `AutoSessionNotifier` will not correctly tell you the
/// session state and call it's `SessionObservers`. /// session state and call it's `SessionObservers`.
pub fn auto_session_bind( pub fn auto_session_bind<Data: 'static>(
notifier: AutoSessionNotifier, notifier: AutoSessionNotifier,
token: &LoopToken, handle: &LoopHandle<Data>,
) -> ::std::result::Result<BoundAutoSession, (IoError, AutoSessionNotifier)> { ) -> ::std::result::Result<BoundAutoSession, IoError> {
Ok(match notifier { Ok(match notifier {
#[cfg(feature = "backend_session_logind")] #[cfg(feature = "backend_session_logind")]
AutoSessionNotifier::Logind(logind) => BoundAutoSession::Logind(logind_session_bind(logind, token) AutoSessionNotifier::Logind(logind) => BoundAutoSession::Logind(logind_session_bind(logind, handle)?),
.map_err(|(error, notifier)| (error, AutoSessionNotifier::Logind(notifier)))?), AutoSessionNotifier::Direct(direct) => BoundAutoSession::Direct(direct_session_bind(direct, handle)?),
AutoSessionNotifier::Direct(direct) => BoundAutoSession::Direct(direct_session_bind(direct, token)
.map_err(|(error, notifier)| (error, AutoSessionNotifier::Direct(notifier)))?),
}) })
} }
@ -234,7 +230,6 @@ impl SessionNotifier for AutoSessionNotifier {
(&mut AutoSessionNotifier::Direct(ref mut direct), AutoId(AutoIdInternal::Direct(signal))) => { (&mut AutoSessionNotifier::Direct(ref mut direct), AutoId(AutoIdInternal::Direct(signal))) => {
direct.unregister(signal) direct.unregister(signal)
} }
_ => unreachable!(),
} }
} }
@ -260,9 +255,7 @@ impl BoundAutoSession {
match self { match self {
#[cfg(feature = "backend_session_logind")] #[cfg(feature = "backend_session_logind")]
BoundAutoSession::Logind(logind) => AutoSessionNotifier::Logind(logind.unbind()), BoundAutoSession::Logind(logind) => AutoSessionNotifier::Logind(logind.unbind()),
BoundAutoSession::Direct(source) => { BoundAutoSession::Direct(direct) => AutoSessionNotifier::Direct(direct.unbind())
AutoSessionNotifier::Direct(*downcast_impl(source.remove()).unwrap_or_else(|_| unreachable!()))
}
} }
} }
} }

View File

@ -42,9 +42,9 @@ use std::path::Path;
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use systemd::login; use systemd::login;
use wayland_server::LoopToken;
use wayland_server::commons::Implementation; use wayland_server::calloop::{Loophandle, Source, Ready};
use wayland_server::sources::{FdEvent, FdInterest, Source}; use wayland_server::calloop::generic::{Generic, EventedRawFd, Event};
struct LogindSessionImpl { struct LogindSessionImpl {
conn: RefCell<Connection>, conn: RefCell<Connection>,
@ -429,7 +429,7 @@ impl SessionNotifier for LogindSessionNotifier {
pub struct BoundLogindSession { pub struct BoundLogindSession {
notifier: LogindSessionNotifier, notifier: LogindSessionNotifier,
_watches: Vec<Watch>, _watches: Vec<Watch>,
sources: Vec<Source<FdEvent>>, sources: Vec<Source<Generic<EventedRawFd>>>,
} }
/// Bind a `LogindSessionNotifier` to an `EventLoop`. /// Bind a `LogindSessionNotifier` to an `EventLoop`.
@ -437,9 +437,9 @@ pub struct BoundLogindSession {
/// Allows the `LogindSessionNotifier` to listen for incoming signals signalling the session state. /// Allows the `LogindSessionNotifier` to listen for incoming signals signalling the session state.
/// If you don't use this function `LogindSessionNotifier` will not correctly tell you the logind /// If you don't use this function `LogindSessionNotifier` will not correctly tell you the logind
/// session state and call it's `SessionObservers`. /// session state and call it's `SessionObservers`.
pub fn logind_session_bind( pub fn logind_session_bind<Data: 'static>(
notifier: LogindSessionNotifier, notifier: LogindSessionNotifier,
token: &LoopToken, handle: &LoopHandle<Data>,
) -> ::std::result::Result<BoundLogindSession, (IoError, LogindSessionNotifier)> { ) -> ::std::result::Result<BoundLogindSession, (IoError, LogindSessionNotifier)> {
let watches = notifier.internal.conn.borrow().watch_fds(); let watches = notifier.internal.conn.borrow().watch_fds();
@ -448,13 +448,14 @@ pub fn logind_session_bind(
.clone() .clone()
.into_iter() .into_iter()
.map(|watch| { .map(|watch| {
let mut interest = FdInterest::empty(); let source = Generic::from_raw_fd(watch.fd());
interest.set(FdInterest::READ, watch.readable()); source.set_interest(Ready::readable() | Ready::writable());
interest.set(FdInterest::WRITE, watch.writable()); handle.insert_source(source, {
token.add_fd_event_source(watch.fd(), interest, notifier.clone()) let notifier = notifier.clone();
}) move |evt, _| notifier.event(evt)
.collect::<::std::result::Result<Vec<Source<FdEvent>>, (IoError, _)>>() })
.map_err(|(err, _)| { }).collect::<::std::result::Result<Vec<Source<FdEvent>>, IoError>>()
.map_err(|err| {
( (
err, err,
LogindSessionNotifier { LogindSessionNotifier {
@ -495,39 +496,25 @@ impl Drop for LogindSessionNotifier {
} }
} }
impl Implementation<(), FdEvent> for LogindSessionNotifier { impl LogindSessionNotifier {
fn receive(&mut self, event: FdEvent, (): ()) { fn event(&mut self, event: Event) {
match event { let fd = event.source.borrow().0;
FdEvent::Ready { fd, mask } => { let readiness = event.readiness;
let conn = self.internal.conn.borrow(); let conn = self.internal.conn.borrow();
let items = conn.watch_handle( let items = conn.watch_handle(
fd, fd,
match mask { if readiness.readable() && readiness.writable() {
x if x.contains(FdInterest::READ) && x.contains(FdInterest::WRITE) => { WatchEvent::Readable as u32 | WatchEvent::Writable as u32
WatchEvent::Readable as u32 | WatchEvent::Writable as u32 } else if readiness.readable() {
} WatchEvent::Readable as u32
x if x.contains(FdInterest::READ) => WatchEvent::Readable as u32, } else if readiness.writable() {
x if x.contains(FdInterest::WRITE) => WatchEvent::Writable as u32, WatchEvent::Writable as u32
_ => return, } else {
}, return
);
if let Err(err) = self.internal.handle_signals(items) {
error!(self.internal.logger, "Error handling dbus signals: {}", err);
}
}
FdEvent::Error { fd, error } => {
warn!(
self.internal.logger,
"Error on dbus connection: {:?}", error
);
// handle the remaining messages, they might contain the SessionRemoved event
// in case the server did close the connection.
let conn = self.internal.conn.borrow();
let items = conn.watch_handle(fd, WatchEvent::Error as u32);
if let Err(err) = self.internal.handle_signals(items) {
error!(self.internal.logger, "Error handling dbus signals: {}", err);
}
} }
);
if let Err(err) = self.internal.handle_signals(items) {
error!(self.internal.logger, "Error handling dbus signals: {}", err);
} }
} }
} }

View File

@ -52,6 +52,8 @@ use nix::libc::c_int;
use nix::sys::signal::{self, Signal}; use nix::sys::signal::{self, Signal};
use nix::sys::stat::{dev_t, fstat, major, minor, Mode}; use nix::sys::stat::{dev_t, fstat, major, minor, Mode};
use nix::unistd::{close, dup}; use nix::unistd::{close, dup};
use std::cell::RefCell;
use std::rc::Rc;
use std::io::Error as IoError; use std::io::Error as IoError;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use std::path::Path; use std::path::Path;
@ -59,29 +61,28 @@ use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
#[cfg(feature = "backend_session_udev")] #[cfg(feature = "backend_session_udev")]
use udev::Context; use udev::Context;
use wayland_server::LoopToken; use wayland_server::calloop::{LoopHandle, Source};
use wayland_server::commons::Implementation; use wayland_server::calloop::signals::Signals;
use wayland_server::sources::{SignalEvent, Source};
#[allow(dead_code)] #[allow(dead_code)]
mod tty { mod tty {
ioctl!(bad read kd_get_mode with 0x4B3B; i16); ioctl_read_bad!(kd_get_mode, 0x4B3B, i16);
ioctl!(bad write_int kd_set_mode with 0x4B3A); ioctl_write_int_bad!(kd_set_mode, 0x4B3A);
pub const KD_TEXT: i16 = 0x00; pub const KD_TEXT: i16 = 0x00;
pub const KD_GRAPHICS: i16 = 0x00; pub const KD_GRAPHICS: i16 = 0x00;
ioctl!(bad read kd_get_kb_mode with 0x4B44; i32); ioctl_read_bad!(kd_get_kb_mode, 0x4B44, i32);
ioctl!(bad write_int kd_set_kb_mode with 0x4B45); ioctl_write_int_bad!(kd_set_kb_mode, 0x4B45);
pub const K_RAW: i32 = 0x00; pub const K_RAW: i32 = 0x00;
pub const K_XLATE: i32 = 0x01; pub const K_XLATE: i32 = 0x01;
pub const K_MEDIUMRAW: i32 = 0x02; pub const K_MEDIUMRAW: i32 = 0x02;
pub const K_UNICODE: i32 = 0x03; pub const K_UNICODE: i32 = 0x03;
pub const K_OFF: i32 = 0x04; pub const K_OFF: i32 = 0x04;
ioctl!(bad write_int vt_activate with 0x5606); ioctl_write_int_bad!(vt_activate, 0x5606);
ioctl!(bad write_int vt_wait_active with 0x5607); ioctl_write_int_bad!(vt_wait_active, 0x5607);
ioctl!(bad write_ptr vt_set_mode with 0x5602; VtMode); ioctl_write_ptr_bad!(vt_set_mode, 0x5602, VtMode);
ioctl!(bad write_int vt_rel_disp with 0x5605); ioctl_write_int_bad!(vt_rel_disp, 0x5605);
#[repr(C)] #[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct VtMode { pub struct VtMode {
@ -367,8 +368,8 @@ impl SessionNotifier for DirectSessionNotifier {
} }
} }
impl Implementation<(), SignalEvent> for DirectSessionNotifier { impl DirectSessionNotifier {
fn receive(&mut self, _signal: SignalEvent, (): ()) { fn signal_received(&mut self) {
if self.is_active() { if self.is_active() {
info!(self.logger, "Session shall become inactive."); info!(self.logger, "Session shall become inactive.");
for signal in &mut self.signals { for signal in &mut self.signals {
@ -397,18 +398,47 @@ impl Implementation<(), SignalEvent> for DirectSessionNotifier {
} }
} }
/// Bound logind session that is driven by the `wayland_server::EventLoop`.
///
/// See `direct_session_bind` for details.
pub struct BoundDirectSession {
source: Source<Signals>,
notifier: Rc<RefCell<DirectSessionNotifier>>
}
impl BoundDirectSession {
/// Unbind the logind session from the `EventLoop`
pub fn unbind(self) -> DirectSessionNotifier {
let BoundDirectSession { source, notifier } = self;
source.remove();
match Rc::try_unwrap(notifier) {
Ok(notifier) => notifier.into_inner(),
Err(_) => panic!("Notifier should have been freed from the event loop!")
}
}
}
/// Bind a `DirectSessionNotifier` to an `EventLoop`. /// Bind a `DirectSessionNotifier` to an `EventLoop`.
/// ///
/// Allows the `DirectSessionNotifier` to listen for incoming signals signalling the session state. /// Allows the `DirectSessionNotifier` to listen for incoming signals signalling the session state.
/// If you don't use this function `DirectSessionNotifier` will not correctly tell you the current /// If you don't use this function `DirectSessionNotifier` will not correctly tell you the current
/// session state and call it's `SessionObservers`. /// session state and call it's `SessionObservers`.
pub fn direct_session_bind( pub fn direct_session_bind<Data: 'static>(
notifier: DirectSessionNotifier, notifier: DirectSessionNotifier,
token: &LoopToken, handle: &LoopHandle<Data>,
) -> ::std::result::Result<Source<SignalEvent>, (IoError, DirectSessionNotifier)> { ) -> ::std::result::Result<BoundDirectSession, IoError> {
let signal = notifier.signal; let signal = notifier.signal;
let notifier = Rc::new(RefCell::new(notifier));
token.add_signal_event_source(signal, notifier) let source = handle.insert_source(
Signals::new(&[signal])?,
{
let notifier = notifier.clone();
move |_, _| notifier.borrow_mut().signal_received()
}
)?;
Ok(BoundDirectSession {
source, notifier
})
} }
error_chain! { error_chain! {

View File

@ -24,9 +24,9 @@ use std::os::unix::io::{AsRawFd, RawFd};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
use udev::{Context, Enumerator, Event, EventType, MonitorBuilder, MonitorSocket, Result as UdevResult}; use udev::{Context, Enumerator, Event, EventType, MonitorBuilder, MonitorSocket, Result as UdevResult};
use wayland_server::LoopToken;
use wayland_server::commons::Implementation; use wayland_server::calloop::{LoopHandle, Source, Ready};
use wayland_server::sources::{FdEvent, FdInterest, Source}; use wayland_server::calloop::generic::{Generic, EventedRawFd};
/// Udev's `DrmDevice` type based on the underlying session /// Udev's `DrmDevice` type based on the underlying session
pub struct SessionFdDrmDevice(RawFd); pub struct SessionFdDrmDevice(RawFd);
@ -48,18 +48,19 @@ pub struct UdevBackend<
H: DrmHandler<SessionFdDrmDevice> + 'static, H: DrmHandler<SessionFdDrmDevice> + 'static,
S: Session + 'static, S: Session + 'static,
T: UdevHandler<H> + 'static, T: UdevHandler<H> + 'static,
Data: 'static
> { > {
_handler: ::std::marker::PhantomData<H>, _handler: ::std::marker::PhantomData<H>,
devices: Rc<RefCell<HashMap<dev_t, (Source<FdEvent>, Rc<RefCell<DrmDevice<SessionFdDrmDevice>>>)>>>, devices: Rc<RefCell<HashMap<dev_t, (Source<Generic<EventedRawFd>>, Rc<RefCell<DrmDevice<SessionFdDrmDevice>>>)>>>,
monitor: MonitorSocket, monitor: MonitorSocket,
session: S, session: S,
handler: T, handler: T,
logger: ::slog::Logger, logger: ::slog::Logger,
token: LoopToken, handle: LoopHandle<Data>,
} }
impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevHandler<H> + 'static> impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevHandler<H> + 'static, Data: 'static>
UdevBackend<H, S, T> UdevBackend<H, S, T, Data>
{ {
/// Creates a new `UdevBackend` and adds it to the given `EventLoop`'s state. /// Creates a new `UdevBackend` and adds it to the given `EventLoop`'s state.
/// ///
@ -70,12 +71,12 @@ impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevH
/// `handler` - User-provided handler to respond to any detected changes /// `handler` - User-provided handler to respond to any detected changes
/// `logger` - slog Logger to be used by the backend and its `DrmDevices`. /// `logger` - slog Logger to be used by the backend and its `DrmDevices`.
pub fn new<L>( pub fn new<L>(
token: LoopToken, handle: LoopHandle<Data>,
context: &Context, context: &Context,
mut session: S, mut session: S,
mut handler: T, mut handler: T,
logger: L, logger: L,
) -> Result<UdevBackend<H, S, T>> ) -> Result<UdevBackend<H, S, T, Data>>
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
{ {
@ -103,9 +104,9 @@ impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevH
let fd = device.as_raw_fd(); let fd = device.as_raw_fd();
match handler.device_added(&mut device) { match handler.device_added(&mut device) {
Some(drm_handler) => { Some(drm_handler) => {
match drm_device_bind(&token, device, drm_handler) { match drm_device_bind(&handle, device, drm_handler) {
Ok((event_source, device)) => Some((devnum, (event_source, device))), Ok((event_source, device)) => Some((devnum, (event_source, device))),
Err((err, (mut device, _))) => { Err((err, mut device)) => {
warn!(logger, "Failed to bind device. Error: {:?}.", err); warn!(logger, "Failed to bind device. Error: {:?}.", err);
handler.device_removed(&mut device); handler.device_removed(&mut device);
drop(device); drop(device);
@ -148,7 +149,7 @@ impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevH
session, session,
handler, handler,
logger, logger,
token, handle,
}) })
} }
@ -174,9 +175,20 @@ impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevH
} }
} }
impl<
H: DrmHandler<SessionFdDrmDevice> + 'static,
S: Session + 'static,
T: UdevHandler<H> + 'static,
Data: 'static,
> Drop for UdevBackend<H, S, T, Data> {
fn drop(&mut self) {
self.close();
}
}
/// `SessionObserver` linked to the `UdevBackend` it was created from. /// `SessionObserver` linked to the `UdevBackend` it was created from.
pub struct UdevBackendObserver { pub struct UdevBackendObserver {
devices: Weak<RefCell<HashMap<dev_t, (Source<FdEvent>, Rc<RefCell<DrmDevice<SessionFdDrmDevice>>>)>>>, devices: Weak<RefCell<HashMap<dev_t, (Source<Generic<EventedRawFd>>, Rc<RefCell<DrmDevice<SessionFdDrmDevice>>>)>>>,
logger: ::slog::Logger, logger: ::slog::Logger,
} }
@ -184,7 +196,8 @@ impl<
H: DrmHandler<SessionFdDrmDevice> + 'static, H: DrmHandler<SessionFdDrmDevice> + 'static,
S: Session + 'static, S: Session + 'static,
T: UdevHandler<H> + 'static, T: UdevHandler<H> + 'static,
> AsSessionObserver<UdevBackendObserver> for UdevBackend<H, S, T> Data: 'static,
> AsSessionObserver<UdevBackendObserver> for UdevBackend<H, S, T, Data>
{ {
fn observer(&mut self) -> UdevBackendObserver { fn observer(&mut self) -> UdevBackendObserver {
UdevBackendObserver { UdevBackendObserver {
@ -218,152 +231,155 @@ impl SessionObserver for UdevBackendObserver {
/// ///
/// Allows the backend to recieve kernel events and thus to drive the `UdevHandler`. /// Allows the backend to recieve kernel events and thus to drive the `UdevHandler`.
/// No runtime functionality can be provided without using this function. /// No runtime functionality can be provided without using this function.
pub fn udev_backend_bind<H, S, T>( pub fn udev_backend_bind<H, S, T, Data>(
token: &LoopToken, mut udev: UdevBackend<H, S, T, Data>,
udev: UdevBackend<H, S, T>, ) -> ::std::result::Result<Source<Generic<EventedRawFd>>, IoError>
) -> ::std::result::Result<Source<FdEvent>, (IoError, UdevBackend<H, S, T>)>
where where
H: DrmHandler<SessionFdDrmDevice> + 'static, H: DrmHandler<SessionFdDrmDevice> + 'static,
T: UdevHandler<H> + 'static, T: UdevHandler<H> + 'static,
S: Session + 'static, S: Session + 'static,
{ {
let fd = udev.monitor.as_raw_fd(); let fd = udev.monitor.as_raw_fd();
token.add_fd_event_source(fd, FdInterest::READ, udev) let handle = udev.handle.clone();
let mut source = Generic::from_raw_fd(fd);
source.set_interest(Ready::readable());
handle.insert_source(
source,
move |_, _| {
udev.process_events();
}
)
} }
impl<H, S, T> Implementation<(), FdEvent> for UdevBackend<H, S, T> impl<H, S, T, Data> UdevBackend<H, S, T, Data>
where where
H: DrmHandler<SessionFdDrmDevice> + 'static, H: DrmHandler<SessionFdDrmDevice> + 'static,
T: UdevHandler<H> + 'static, T: UdevHandler<H> + 'static,
S: Session + 'static, S: Session + 'static,
Data: 'static
{ {
fn receive(&mut self, event: FdEvent, (): ()) { fn process_events(&mut self) {
match event { let events = self.monitor.clone().collect::<Vec<Event>>();
FdEvent::Ready { .. } => { for event in events {
let events = self.monitor.clone().collect::<Vec<Event>>(); match event.event_type() {
for event in events { // New device
match event.event_type() { EventType::Add => {
// New device info!(self.logger, "Device Added");
EventType::Add => { if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) {
info!(self.logger, "Device Added"); let mut device = {
if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) { match DrmDevice::new(
let mut device = { {
match DrmDevice::new( let logger = self.logger.clone();
{ match self.session.open(
let logger = self.logger.clone(); path,
match self.session.open( fcntl::OFlag::O_RDWR | fcntl::OFlag::O_CLOEXEC
path, | fcntl::OFlag::O_NOCTTY
fcntl::OFlag::O_RDWR | fcntl::OFlag::O_CLOEXEC | fcntl::OFlag::O_NONBLOCK,
| fcntl::OFlag::O_NOCTTY
| fcntl::OFlag::O_NONBLOCK,
) {
Ok(fd) => SessionFdDrmDevice(fd),
Err(err) => {
warn!(
logger,
"Unable to open drm device {:?}, Error: {:?}. Skipping",
path,
err
);
continue;
}
}
},
self.logger.clone(),
) { ) {
Ok(dev) => dev, Ok(fd) => SessionFdDrmDevice(fd),
Err(err) => { Err(err) => {
warn!( warn!(
self.logger, logger,
"Failed to initialize device {:?}. Error: {}. Skipping", "Unable to open drm device {:?}, Error: {:?}. Skipping",
path, path,
err err
); );
continue; continue;
} }
} }
}; },
let fd = device.as_raw_fd(); self.logger.clone(),
match self.handler.device_added(&mut device) { ) {
Some(drm_handler) => { Ok(dev) => dev,
match drm_device_bind(&self.token, device, drm_handler) { Err(err) => {
Ok(fd_event_source) => { warn!(
self.devices.borrow_mut().insert(devnum, fd_event_source); self.logger,
} "Failed to initialize device {:?}. Error: {}. Skipping",
Err((err, (mut device, _))) => { path,
warn!( err
self.logger, );
"Failed to bind device. Error: {:?}.", err continue;
); }
self.handler.device_removed(&mut device); }
drop(device); };
if let Err(err) = self.session.close(fd) { let fd = device.as_raw_fd();
warn!( match self.handler.device_added(&mut device) {
self.logger, Some(drm_handler) => {
"Failed to close dropped device. Error: {:?}. Ignoring", err match drm_device_bind(&self.handle, device, drm_handler) {
); Ok(fd_event_source) => {
}; self.devices.borrow_mut().insert(devnum, fd_event_source);
}
}
} }
None => { Err((err, mut device)) => {
warn!(
self.logger,
"Failed to bind device. Error: {:?}.", err
);
self.handler.device_removed(&mut device); self.handler.device_removed(&mut device);
drop(device); drop(device);
if let Err(err) = self.session.close(fd) { if let Err(err) = self.session.close(fd) {
warn!( warn!(
self.logger,
"Failed to close unused device. Error: {:?}", err
);
}
}
};
}
}
// Device removed
EventType::Remove => {
info!(self.logger, "Device Remove");
if let Some(devnum) = event.devnum() {
if let Some((fd_event_source, device)) =
self.devices.borrow_mut().remove(&devnum)
{
fd_event_source.remove();
let mut device = Rc::try_unwrap(device)
.unwrap_or_else(|_| unreachable!())
.into_inner();
self.handler.device_removed(&mut device);
let fd = device.as_raw_fd();
drop(device);
if let Err(err) = self.session.close(fd) {
warn!(
self.logger, self.logger,
"Failed to close device {:?}. Error: {:?}. Ignoring", "Failed to close dropped device. Error: {:?}. Ignoring", err
event.sysname(),
err
); );
}; };
}
} }
} }
} None => {
// New connector self.handler.device_removed(&mut device);
EventType::Change => { drop(device);
info!(self.logger, "Device Changed"); if let Err(err) = self.session.close(fd) {
if let Some(devnum) = event.devnum() { warn!(
info!(self.logger, "Devnum: {:b}", devnum); self.logger,
if let Some(&(_, ref device)) = self.devices.borrow_mut().get(&devnum) { "Failed to close unused device. Error: {:?}", err
let handler = &mut self.handler; );
handler.device_changed(&mut device.borrow_mut()); }
} else {
info!(self.logger, "changed, but device not tracked by backend");
};
} else {
info!(self.logger, "changed, but no devnum");
} }
} };
_ => {}
} }
} }
// Device removed
EventType::Remove => {
info!(self.logger, "Device Remove");
if let Some(devnum) = event.devnum() {
if let Some((fd_event_source, device)) =
self.devices.borrow_mut().remove(&devnum)
{
fd_event_source.remove();
let mut device = Rc::try_unwrap(device)
.unwrap_or_else(|_| unreachable!())
.into_inner();
self.handler.device_removed(&mut device);
let fd = device.as_raw_fd();
drop(device);
if let Err(err) = self.session.close(fd) {
warn!(
self.logger,
"Failed to close device {:?}. Error: {:?}. Ignoring",
event.sysname(),
err
);
};
}
}
}
// New connector
EventType::Change => {
info!(self.logger, "Device Changed");
if let Some(devnum) = event.devnum() {
info!(self.logger, "Devnum: {:b}", devnum);
if let Some(&(_, ref device)) = self.devices.borrow_mut().get(&devnum) {
let handler = &mut self.handler;
handler.device_changed(&mut device.borrow_mut());
} else {
info!(self.logger, "changed, but device not tracked by backend");
};
} else {
info!(self.logger, "changed, but no devnum");
}
}
_ => {}
} }
FdEvent::Error { error, .. } => self.handler.error(error),
} }
} }
} }

View File

@ -1,11 +1,15 @@
use super::{CompositorToken, Damage, Rectangle, RectangleKind, Role, RoleType, SubsurfaceRole, SurfaceEvent};
use super::region::RegionData;
use super::tree::{Location, SurfaceData};
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use wayland_server::{LoopToken, NewResource, Resource}; use std::sync::Mutex;
use wayland_server::commons::Implementation;
use wayland_server::protocol::{wl_compositor, wl_region, wl_subcompositor, wl_subsurface, wl_surface}; use wayland_server::protocol::{wl_compositor, wl_region, wl_subcompositor, wl_subsurface, wl_surface};
use wayland_server::{DisplayToken, NewResource, Resource};
use super::tree::{Location, SurfaceData};
use super::{
CompositorToken, Damage, Rectangle, RectangleKind, RegionAttributes, Role, RoleType, SubsurfaceRole,
SurfaceEvent,
};
/* /*
* wl_compositor * wl_compositor
@ -13,14 +17,14 @@ use wayland_server::protocol::{wl_compositor, wl_region, wl_subcompositor, wl_su
pub(crate) fn implement_compositor<U, R, Impl>( pub(crate) fn implement_compositor<U, R, Impl>(
compositor: NewResource<wl_compositor::WlCompositor>, compositor: NewResource<wl_compositor::WlCompositor>,
token: LoopToken, token: DisplayToken,
log: ::slog::Logger, log: ::slog::Logger,
implem: Rc<RefCell<Impl>>, implem: Rc<RefCell<Impl>>,
) -> Resource<wl_compositor::WlCompositor> ) -> Resource<wl_compositor::WlCompositor>
where where
U: Default + 'static, U: Default + 'static,
R: Default + 'static, R: Default + 'static,
Impl: Implementation<(Resource<wl_surface::WlSurface>, CompositorToken<U, R>), SurfaceEvent> + 'static, Impl: FnMut(SurfaceEvent, Resource<wl_surface::WlSurface>, CompositorToken<U, R>) + 'static,
{ {
let my_token = token.clone(); let my_token = token.clone();
compositor.implement_nonsend( compositor.implement_nonsend(
@ -34,7 +38,8 @@ where
implement_region(id, &token); implement_region(id, &token);
} }
}, },
None::<fn(_, _)>, None::<fn(_)>,
(),
&my_token, &my_token,
) )
} }
@ -46,95 +51,74 @@ where
// Internal implementation data of surfaces // Internal implementation data of surfaces
pub(crate) struct SurfaceImplem<U, R> { pub(crate) struct SurfaceImplem<U, R> {
log: ::slog::Logger, log: ::slog::Logger,
implem: implem: Rc<RefCell<FnMut(SurfaceEvent, Resource<wl_surface::WlSurface>, CompositorToken<U, R>)>>,
Rc<RefCell<Implementation<(Resource<wl_surface::WlSurface>, CompositorToken<U, R>), SurfaceEvent>>>,
} }
impl<U, R> SurfaceImplem<U, R> { impl<U, R> SurfaceImplem<U, R> {
fn make<Impl>(log: ::slog::Logger, implem: Rc<RefCell<Impl>>) -> SurfaceImplem<U, R> fn make<Impl>(log: ::slog::Logger, implem: Rc<RefCell<Impl>>) -> SurfaceImplem<U, R>
where where
Impl: Implementation<(Resource<wl_surface::WlSurface>, CompositorToken<U, R>), SurfaceEvent> Impl: FnMut(SurfaceEvent, Resource<wl_surface::WlSurface>, CompositorToken<U, R>) + 'static,
+ 'static,
{ {
SurfaceImplem { SurfaceImplem { log, implem }
log,
implem,
}
} }
} }
impl<U, R> Implementation<Resource<wl_surface::WlSurface>, wl_surface::Request> for SurfaceImplem<U, R> impl<U, R> SurfaceImplem<U, R>
where where
U: 'static, U: 'static,
R: 'static, R: 'static,
{ {
fn receive(&mut self, req: wl_surface::Request, surface: Resource<wl_surface::WlSurface>) { fn receive_surface_request(
&mut self,
req: wl_surface::Request,
surface: Resource<wl_surface::WlSurface>,
) {
match req { match req {
wl_surface::Request::Attach { buffer, x, y } => unsafe { wl_surface::Request::Attach { buffer, x, y } => {
SurfaceData::<U, R>::with_data(&surface, |d| { SurfaceData::<U, R>::with_data(&surface, |d| {
d.buffer = Some(buffer.map(|b| (b.clone(), (x, y)))) d.buffer = Some(buffer.map(|b| (b.clone(), (x, y))))
}); });
}, }
wl_surface::Request::Damage { wl_surface::Request::Damage { x, y, width, height } => {
x,
y,
width,
height,
} => unsafe {
SurfaceData::<U, R>::with_data(&surface, |d| { SurfaceData::<U, R>::with_data(&surface, |d| {
d.damage = Damage::Surface(Rectangle { d.damage = Damage::Surface(Rectangle { x, y, width, height })
x,
y,
width,
height,
})
}); });
}, }
wl_surface::Request::Frame { callback } => { wl_surface::Request::Frame { callback } => {
let mut user_impl = self.implem.borrow_mut(); let mut user_impl = self.implem.borrow_mut();
trace!(self.log, "Calling user implementation for wl_surface.frame"); trace!(self.log, "Calling user implementation for wl_surface.frame");
user_impl.receive( (&mut *user_impl)(SurfaceEvent::Frame { callback }, surface, CompositorToken::make());
SurfaceEvent::Frame { callback },
(surface, CompositorToken::make()),
);
} }
wl_surface::Request::SetOpaqueRegion { region } => unsafe { wl_surface::Request::SetOpaqueRegion { region } => {
let attributes = region.map(|r| RegionData::get_attributes(&r)); let attributes = region.map(|r| {
let attributes_mutex = r.user_data::<Mutex<RegionAttributes>>().unwrap();
attributes_mutex.lock().unwrap().clone()
});
SurfaceData::<U, R>::with_data(&surface, |d| d.opaque_region = attributes); SurfaceData::<U, R>::with_data(&surface, |d| d.opaque_region = attributes);
}, }
wl_surface::Request::SetInputRegion { region } => unsafe { wl_surface::Request::SetInputRegion { region } => {
let attributes = region.map(|r| RegionData::get_attributes(&r)); let attributes = region.map(|r| {
let attributes_mutex = r.user_data::<Mutex<RegionAttributes>>().unwrap();
attributes_mutex.lock().unwrap().clone()
});
SurfaceData::<U, R>::with_data(&surface, |d| d.input_region = attributes); SurfaceData::<U, R>::with_data(&surface, |d| d.input_region = attributes);
}, }
wl_surface::Request::Commit => { wl_surface::Request::Commit => {
let mut user_impl = self.implem.borrow_mut(); let mut user_impl = self.implem.borrow_mut();
trace!( trace!(self.log, "Calling user implementation for wl_surface.commit");
self.log, (&mut *user_impl)(SurfaceEvent::Commit, surface, CompositorToken::make());
"Calling user implementation for wl_surface.commit"
);
user_impl.receive(SurfaceEvent::Commit, (surface, CompositorToken::make()));
} }
wl_surface::Request::SetBufferTransform { transform } => unsafe { wl_surface::Request::SetBufferTransform { transform } => {
SurfaceData::<U, R>::with_data(&surface, |d| d.buffer_transform = transform); SurfaceData::<U, R>::with_data(&surface, |d| d.buffer_transform = transform);
}, }
wl_surface::Request::SetBufferScale { scale } => unsafe { wl_surface::Request::SetBufferScale { scale } => {
SurfaceData::<U, R>::with_data(&surface, |d| d.buffer_scale = scale); SurfaceData::<U, R>::with_data(&surface, |d| d.buffer_scale = scale);
}, }
wl_surface::Request::DamageBuffer { wl_surface::Request::DamageBuffer { x, y, width, height } => {
x,
y,
width,
height,
} => unsafe {
SurfaceData::<U, R>::with_data(&surface, |d| { SurfaceData::<U, R>::with_data(&surface, |d| {
d.damage = Damage::Buffer(Rectangle { d.damage = Damage::Buffer(Rectangle { x, y, width, height })
x,
y,
width,
height,
})
}); });
}, }
wl_surface::Request::Destroy => { wl_surface::Request::Destroy => {
// All is already handled by our destructor // All is already handled by our destructor
} }
@ -144,25 +128,24 @@ where
fn implement_surface<U, R, Impl>( fn implement_surface<U, R, Impl>(
surface: NewResource<wl_surface::WlSurface>, surface: NewResource<wl_surface::WlSurface>,
token: &LoopToken, token: &DisplayToken,
log: ::slog::Logger, log: ::slog::Logger,
implem: Rc<RefCell<Impl>>, implem: Rc<RefCell<Impl>>,
) -> Resource<wl_surface::WlSurface> ) -> Resource<wl_surface::WlSurface>
where where
U: Default + 'static, U: Default + 'static,
R: Default + 'static, R: Default + 'static,
Impl: Implementation<(Resource<wl_surface::WlSurface>, CompositorToken<U, R>), SurfaceEvent> + 'static, Impl: FnMut(SurfaceEvent, Resource<wl_surface::WlSurface>, CompositorToken<U, R>) + 'static,
{ {
let surface = surface.implement_nonsend( let surface = surface.implement_nonsend(
SurfaceImplem::make(log, implem), {
Some(|surface, _| unsafe { let mut implem = SurfaceImplem::make(log, implem);
SurfaceData::<U, R>::cleanup(&surface); move |req, surface| implem.receive_surface_request(req, surface)
}), },
Some(|surface| SurfaceData::<U, R>::cleanup(&surface)),
SurfaceData::<U, R>::new(),
token, token,
); );
unsafe {
SurfaceData::<U, R>::init(&surface);
}
surface surface
} }
@ -170,63 +153,32 @@ where
* wl_region * wl_region
*/ */
pub(crate) struct RegionImplem; fn region_implem(request: wl_region::Request, region: Resource<wl_region::WlRegion>) {
let attributes_mutex = region.user_data::<Mutex<RegionAttributes>>().unwrap();
impl Implementation<Resource<wl_region::WlRegion>, wl_region::Request> for RegionImplem { let mut guard = attributes_mutex.lock().unwrap();
fn receive(&mut self, request: wl_region::Request, region: Resource<wl_region::WlRegion>) { match request {
unsafe { wl_region::Request::Add { x, y, width, height } => guard
match request { .rects
wl_region::Request::Add { .push((RectangleKind::Add, Rectangle { x, y, width, height })),
x, wl_region::Request::Subtract { x, y, width, height } => guard
y, .rects
width, .push((RectangleKind::Subtract, Rectangle { x, y, width, height })),
height, wl_region::Request::Destroy => {
} => RegionData::add_rectangle( // all is handled by our destructor
&region,
RectangleKind::Add,
Rectangle {
x,
y,
width,
height,
},
),
wl_region::Request::Subtract {
x,
y,
width,
height,
} => RegionData::add_rectangle(
&region,
RectangleKind::Subtract,
Rectangle {
x,
y,
width,
height,
},
),
wl_region::Request::Destroy => {
// all is handled by our destructor
}
}
} }
} }
} }
fn implement_region( fn implement_region(
region: NewResource<wl_region::WlRegion>, region: NewResource<wl_region::WlRegion>,
token: &LoopToken, token: &DisplayToken,
) -> Resource<wl_region::WlRegion> { ) -> Resource<wl_region::WlRegion> {
let region = region.implement_nonsend( region.implement_nonsend(
RegionImplem, region_implem,
Some(|region, _| unsafe { RegionData::cleanup(&region) }), None::<fn(_)>,
Mutex::new(RegionAttributes::default()),
token, token,
); )
unsafe {
RegionData::init(&region);
}
region
} }
/* /*
@ -235,7 +187,7 @@ fn implement_region(
pub(crate) fn implement_subcompositor<U, R>( pub(crate) fn implement_subcompositor<U, R>(
subcompositor: NewResource<wl_subcompositor::WlSubcompositor>, subcompositor: NewResource<wl_subcompositor::WlSubcompositor>,
token: LoopToken, token: DisplayToken,
) -> Resource<wl_subcompositor::WlSubcompositor> ) -> Resource<wl_subcompositor::WlSubcompositor>
where where
R: RoleType + Role<SubsurfaceRole> + 'static, R: RoleType + Role<SubsurfaceRole> + 'static,
@ -244,24 +196,20 @@ where
let my_token = token.clone(); let my_token = token.clone();
subcompositor.implement_nonsend( subcompositor.implement_nonsend(
move |request, subcompositor: Resource<_>| match request { move |request, subcompositor: Resource<_>| match request {
wl_subcompositor::Request::GetSubsurface { wl_subcompositor::Request::GetSubsurface { id, surface, parent } => {
id, if let Err(()) = SurfaceData::<U, R>::set_parent(&surface, &parent) {
surface,
parent,
} => {
if let Err(()) = unsafe { SurfaceData::<U, R>::set_parent(&surface, &parent) } {
subcompositor.post_error( subcompositor.post_error(
wl_subcompositor::Error::BadSurface as u32, wl_subcompositor::Error::BadSurface as u32,
"Surface already has a role.".into(), "Surface already has a role.".into(),
); );
return; return;
} }
let subsurface = implement_subsurface::<U, R>(id, &token); implement_subsurface::<U, R>(id, surface.clone(), &token);
subsurface.set_user_data(Box::into_raw(Box::new(surface.clone())) as *mut ());
} }
wl_subcompositor::Request::Destroy => {} wl_subcompositor::Request::Destroy => {}
}, },
None::<fn(_, _)>, None::<fn(_)>,
(),
&my_token, &my_token,
) )
} }
@ -270,28 +218,28 @@ where
* wl_subsurface * wl_subsurface
*/ */
unsafe fn with_subsurface_attributes<U, R, F>(subsurface: &Resource<wl_subsurface::WlSubsurface>, f: F) fn with_subsurface_attributes<U, R, F>(subsurface: &Resource<wl_subsurface::WlSubsurface>, f: F)
where where
F: FnOnce(&mut SubsurfaceRole), F: FnOnce(&mut SubsurfaceRole),
U: 'static, U: 'static,
R: RoleType + Role<SubsurfaceRole> + 'static, R: RoleType + Role<SubsurfaceRole> + 'static,
{ {
let ptr = subsurface.get_user_data(); let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap();
let surface = &*(ptr as *mut Resource<wl_surface::WlSurface>);
SurfaceData::<U, R>::with_role_data::<SubsurfaceRole, _, _>(surface, |d| f(d)) SurfaceData::<U, R>::with_role_data::<SubsurfaceRole, _, _>(surface, |d| f(d))
.expect("The surface does not have a subsurface role while it has a wl_subsurface?!"); .expect("The surface does not have a subsurface role while it has a wl_subsurface?!");
} }
fn implement_subsurface<U, R>( fn implement_subsurface<U, R>(
subsurface: NewResource<wl_subsurface::WlSubsurface>, subsurface: NewResource<wl_subsurface::WlSubsurface>,
token: &LoopToken, surface: Resource<wl_surface::WlSurface>,
token: &DisplayToken,
) -> Resource<wl_subsurface::WlSubsurface> ) -> Resource<wl_subsurface::WlSubsurface>
where where
U: 'static, U: 'static,
R: RoleType + Role<SubsurfaceRole> + 'static, R: RoleType + Role<SubsurfaceRole> + 'static,
{ {
subsurface.implement_nonsend( subsurface.implement_nonsend(
|request, subsurface| unsafe { |request, subsurface| {
match request { match request {
wl_subsurface::Request::SetPosition { x, y } => { wl_subsurface::Request::SetPosition { x, y } => {
with_subsurface_attributes::<U, R, _>(&subsurface, |attrs| { with_subsurface_attributes::<U, R, _>(&subsurface, |attrs| {
@ -299,7 +247,7 @@ where
}) })
} }
wl_subsurface::Request::PlaceAbove { sibling } => { wl_subsurface::Request::PlaceAbove { sibling } => {
let surface = &*(subsurface.get_user_data() as *mut Resource<wl_surface::WlSurface>); let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap();
if let Err(()) = SurfaceData::<U, R>::reorder(surface, Location::After, &sibling) { if let Err(()) = SurfaceData::<U, R>::reorder(surface, Location::After, &sibling) {
subsurface.post_error( subsurface.post_error(
wl_subsurface::Error::BadSurface as u32, wl_subsurface::Error::BadSurface as u32,
@ -308,7 +256,7 @@ where
} }
} }
wl_subsurface::Request::PlaceBelow { sibling } => { wl_subsurface::Request::PlaceBelow { sibling } => {
let surface = &*(subsurface.get_user_data() as *mut Resource<wl_surface::WlSurface>); let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap();
if let Err(()) = SurfaceData::<U, R>::reorder(surface, Location::Before, &sibling) { if let Err(()) = SurfaceData::<U, R>::reorder(surface, Location::Before, &sibling) {
subsurface.post_error( subsurface.post_error(
wl_subsurface::Error::BadSurface as u32, wl_subsurface::Error::BadSurface as u32,
@ -331,21 +279,18 @@ where
} }
} }
}, },
Some(|subsurface, _| unsafe { Some(|subsurface| destroy_subsurface::<U, R>(&subsurface)),
destroy_subsurface::<U, R>(&subsurface); surface,
}),
token, token,
) )
} }
unsafe fn destroy_subsurface<U, R>(subsurface: &Resource<wl_subsurface::WlSubsurface>) fn destroy_subsurface<U, R>(subsurface: &Resource<wl_subsurface::WlSubsurface>)
where where
U: 'static, U: 'static,
R: RoleType + Role<SubsurfaceRole> + 'static, R: RoleType + Role<SubsurfaceRole> + 'static,
{ {
let ptr = subsurface.get_user_data(); let surface = subsurface.user_data::<Resource<wl_surface::WlSurface>>().unwrap();
subsurface.set_user_data(::std::ptr::null_mut());
let surface = Box::from_raw(ptr as *mut Resource<wl_surface::WlSurface>);
if surface.is_alive() { if surface.is_alive() {
SurfaceData::<U, R>::unset_parent(&surface); SurfaceData::<U, R>::unset_parent(&surface);
} }

View File

@ -43,15 +43,14 @@
//! define_roles!(MyRoles); //! define_roles!(MyRoles);
//! //!
//! # fn main() { //! # fn main() {
//! # let (mut display, event_loop) = wayland_server::Display::new(); //! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! // Call the init function: //! // Call the init function:
//! let (token, _, _) = compositor_init::<MyData, MyRoles, _, _>( //! let (token, _, _) = compositor_init::<MyData, MyRoles, _, _>(
//! &mut display, //! &mut display,
//! event_loop.token(), //! |request, surface, compositor_token| {
//! |request, (surface, compositor_token)| {
//! /* //! /*
//! Your handling of the user requests. This closure can also //! Your handling of the user requests.
//! be a struct implementing the appropriate Implementation trait.
//! */ //! */
//! }, //! },
//! None // put a logger here //! None // put a logger here
@ -79,21 +78,21 @@
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Mutex;
mod handlers; mod handlers;
mod tree;
mod region;
pub mod roles; pub mod roles;
mod tree;
use self::region::RegionData;
use self::roles::{Role, RoleType, WrongRole}; use self::roles::{Role, RoleType, WrongRole};
use self::tree::SurfaceData; use self::tree::SurfaceData;
pub use self::tree::TraversalAction; pub use self::tree::TraversalAction;
use utils::Rectangle; use utils::Rectangle;
use wayland_server::{Display, Global, LoopToken, NewResource, Resource};
use wayland_server::commons::Implementation;
use wayland_server::protocol::{wl_buffer, wl_callback, wl_compositor, wl_output, wl_region, wl_subcompositor};
use wayland_server::protocol::wl_surface::WlSurface; use wayland_server::protocol::wl_surface::WlSurface;
use wayland_server::protocol::{
wl_buffer, wl_callback, wl_compositor, wl_output, wl_region, wl_subcompositor,
};
use wayland_server::{Display, Global, NewResource, Resource};
/// Description of which part of a surface /// Description of which part of a surface
/// should be considered damaged and needs to be redrawn /// should be considered damaged and needs to be redrawn
@ -271,11 +270,7 @@ impl<U: 'static, R: 'static> CompositorToken<U, R> {
where where
F: FnOnce(&mut SurfaceAttributes<U>) -> T, F: FnOnce(&mut SurfaceAttributes<U>) -> T,
{ {
assert!( SurfaceData::<U, R>::with_data(surface, f)
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
"Accessing the data of foreign surfaces is not supported."
);
unsafe { SurfaceData::<U, R>::with_data(surface, f) }
} }
} }
@ -309,13 +304,7 @@ where
where where
F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>, F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
{ {
assert!( SurfaceData::<U, R>::map_tree(surface, initial, f, false);
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
"Accessing the data of foreign surfaces is not supported."
);
unsafe {
SurfaceData::<U, R>::map_tree(surface, initial, f, false);
}
Ok(()) Ok(())
} }
@ -335,13 +324,7 @@ where
where where
F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>, F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
{ {
assert!( SurfaceData::<U, R>::map_tree(surface, initial, f, true);
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
"Accessing the data of foreign surfaces is not supported."
);
unsafe {
SurfaceData::<U, R>::map_tree(surface, initial, f, true);
}
Ok(()) Ok(())
} }
@ -352,11 +335,7 @@ where
/// If the surface is not managed by the CompositorGlobal that provided this token, this /// If the surface is not managed by the CompositorGlobal that provided this token, this
/// will panic (having more than one compositor is not supported). /// will panic (having more than one compositor is not supported).
pub fn get_parent(&self, surface: &Resource<WlSurface>) -> Option<Resource<WlSurface>> { pub fn get_parent(&self, surface: &Resource<WlSurface>) -> Option<Resource<WlSurface>> {
assert!( SurfaceData::<U, R>::get_parent(surface)
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
"Accessing the data of foreign surfaces is not supported."
);
unsafe { SurfaceData::<U, R>::get_parent(surface) }
} }
/// Retrieve the children of this surface /// Retrieve the children of this surface
@ -364,11 +343,7 @@ where
/// If the surface is not managed by the CompositorGlobal that provided this token, this /// If the surface is not managed by the CompositorGlobal that provided this token, this
/// will panic (having more than one compositor is not supported). /// will panic (having more than one compositor is not supported).
pub fn get_children(&self, surface: &Resource<WlSurface>) -> Vec<Resource<WlSurface>> { pub fn get_children(&self, surface: &Resource<WlSurface>) -> Vec<Resource<WlSurface>> {
assert!( SurfaceData::<U, R>::get_children(surface)
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
"Accessing the data of foreign surfaces is not supported."
);
unsafe { SurfaceData::<U, R>::get_children(surface) }
} }
} }
@ -378,11 +353,7 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
/// If the surface is not managed by the CompositorGlobal that provided this token, this /// If the surface is not managed by the CompositorGlobal that provided this token, this
/// will panic (having more than one compositor is not supported). /// will panic (having more than one compositor is not supported).
pub fn has_a_role(&self, surface: &Resource<WlSurface>) -> bool { pub fn has_a_role(&self, surface: &Resource<WlSurface>) -> bool {
assert!( SurfaceData::<U, R>::has_a_role(surface)
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
"Accessing the data of foreign surfaces is not supported."
);
unsafe { SurfaceData::<U, R>::has_a_role(surface) }
} }
/// Check wether this surface as a specific role /// Check wether this surface as a specific role
@ -393,11 +364,7 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
assert!( SurfaceData::<U, R>::has_role::<RoleData>(surface)
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
"Accessing the data of foreign surfaces is not supported."
);
unsafe { SurfaceData::<U, R>::has_role::<RoleData>(surface) }
} }
/// Register that this surface has given role with default data /// Register that this surface has given role with default data
@ -411,11 +378,7 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
R: Role<RoleData>, R: Role<RoleData>,
RoleData: Default, RoleData: Default,
{ {
assert!( SurfaceData::<U, R>::give_role::<RoleData>(surface)
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
"Accessing the data of foreign surfaces is not supported."
);
unsafe { SurfaceData::<U, R>::give_role::<RoleData>(surface) }
} }
/// Register that this surface has given role with given data /// Register that this surface has given role with given data
@ -432,11 +395,7 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
assert!( SurfaceData::<U, R>::give_role_with::<RoleData>(surface, data)
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
"Accessing the data of foreign surfaces is not supported."
);
unsafe { SurfaceData::<U, R>::give_role_with::<RoleData>(surface, data) }
} }
/// Access the role data of a surface /// Access the role data of a surface
@ -450,11 +409,7 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
R: Role<RoleData>, R: Role<RoleData>,
F: FnOnce(&mut RoleData) -> T, F: FnOnce(&mut RoleData) -> T,
{ {
assert!( SurfaceData::<U, R>::with_role_data::<RoleData, _, _>(surface, f)
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
"Accessing the data of foreign surfaces is not supported."
);
unsafe { SurfaceData::<U, R>::with_role_data::<RoleData, _, _>(surface, f) }
} }
/// Register that this surface does not have a role any longer and retrieve the data /// Register that this surface does not have a role any longer and retrieve the data
@ -467,11 +422,7 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
assert!( SurfaceData::<U, R>::remove_role::<RoleData>(surface)
surface.is_implemented_with::<self::handlers::SurfaceImplem<U, R>>(),
"Accessing the data of foreign surfaces is not supported."
);
unsafe { SurfaceData::<U, R>::remove_role::<RoleData>(surface) }
} }
/// Retrieve the metadata associated with a wl_region /// Retrieve the metadata associated with a wl_region
@ -479,11 +430,10 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
/// If the region is not managed by the CompositorGlobal that provided this token, this /// If the region is not managed by the CompositorGlobal that provided this token, this
/// will panic (having more than one compositor is not supported). /// will panic (having more than one compositor is not supported).
pub fn get_region_attributes(&self, region: &Resource<wl_region::WlRegion>) -> RegionAttributes { pub fn get_region_attributes(&self, region: &Resource<wl_region::WlRegion>) -> RegionAttributes {
assert!( match region.user_data::<Mutex<RegionAttributes>>() {
region.is_implemented_with::<self::handlers::RegionImplem>(), Some(mutex) => mutex.lock().unwrap().clone(),
"Accessing the data of foreign regions is not supported." None => panic!("Accessing the data of foreign regions is not supported."),
); }
unsafe { RegionData::get_attributes(region) }
} }
} }
@ -497,7 +447,6 @@ impl<U: 'static, R: RoleType + 'static> CompositorToken<U, R> {
/// globals from the event loop in the future. /// globals from the event loop in the future.
pub fn compositor_init<U, R, Impl, L>( pub fn compositor_init<U, R, Impl, L>(
display: &mut Display, display: &mut Display,
token: LoopToken,
implem: Impl, implem: Impl,
logger: L, logger: L,
) -> ( ) -> (
@ -509,15 +458,15 @@ where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
U: Default + 'static, U: Default + 'static,
R: Default + RoleType + Role<SubsurfaceRole> + 'static, R: Default + RoleType + Role<SubsurfaceRole> + 'static,
Impl: Implementation<(Resource<WlSurface>, CompositorToken<U, R>), SurfaceEvent> + 'static, Impl: FnMut(SurfaceEvent, Resource<WlSurface>, CompositorToken<U, R>) + 'static,
{ {
let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "compositor_handler")); let log = ::slog_or_stdlog(logger).new(o!("smithay_module" => "compositor_handler"));
let implem = Rc::new(RefCell::new(implem)); let implem = Rc::new(RefCell::new(implem));
let comp_token = token.clone(); let comp_token = display.get_token();
let sub_token = token.clone(); let sub_token = display.get_token();
let compositor = display.create_global(&token, 4, move |_version, new_compositor| { let compositor = display.create_global(4, move |new_compositor, _version| {
self::handlers::implement_compositor::<U, R, Impl>( self::handlers::implement_compositor::<U, R, Impl>(
new_compositor, new_compositor,
comp_token.clone(), comp_token.clone(),
@ -526,7 +475,7 @@ where
); );
}); });
let subcompositor = display.create_global(&token, 1, move |_version, new_subcompositor| { let subcompositor = display.create_global(1, move |new_subcompositor, _version| {
self::handlers::implement_subcompositor::<U, R>(new_subcompositor, sub_token.clone()); self::handlers::implement_subcompositor::<U, R>(new_subcompositor, sub_token.clone());
}); });

View File

@ -1,44 +0,0 @@
use super::{Rectangle, RectangleKind, RegionAttributes};
use std::sync::Mutex;
use wayland_server::Resource;
use wayland_server::protocol::wl_region;
#[derive(Default)]
pub struct RegionData {
attributes: RegionAttributes,
}
impl RegionData {
/// Initialize the user_data of a region, must be called right when the surface is created
pub unsafe fn init(region: &Resource<wl_region::WlRegion>) {
region.set_user_data(Box::into_raw(Box::new(Mutex::new(RegionData::default()))) as *mut _)
}
/// Cleans the user_data of that surface, must be called when it is destroyed
pub unsafe fn cleanup(region: &Resource<wl_region::WlRegion>) {
let ptr = region.get_user_data();
region.set_user_data(::std::ptr::null_mut());
let _my_data_mutex: Box<Mutex<RegionData>> = Box::from_raw(ptr as *mut _);
}
unsafe fn get_data(region: &Resource<wl_region::WlRegion>) -> &Mutex<RegionData> {
let ptr = region.get_user_data();
&*(ptr as *mut _)
}
pub unsafe fn get_attributes(region: &Resource<wl_region::WlRegion>) -> RegionAttributes {
let data_mutex = Self::get_data(region);
let data_guard = data_mutex.lock().unwrap();
data_guard.attributes.clone()
}
pub unsafe fn add_rectangle(
region: &Resource<wl_region::WlRegion>,
kind: RectangleKind,
rect: Rectangle,
) {
let data_mutex = Self::get_data(region);
let mut data_guard = data_mutex.lock().unwrap();
data_guard.attributes.rects.push((kind, rect));
}
}

View File

@ -1,8 +1,8 @@
use super::{SubsurfaceRole, SurfaceAttributes};
use super::roles::*; use super::roles::*;
use super::{SubsurfaceRole, SurfaceAttributes};
use std::sync::Mutex; use std::sync::Mutex;
use wayland_server::Resource;
use wayland_server::protocol::wl_surface::WlSurface; use wayland_server::protocol::wl_surface::WlSurface;
use wayland_server::Resource;
/// Node of a subsurface tree, holding some user specified data type U /// Node of a subsurface tree, holding some user specified data type U
/// at each node /// at each node
@ -20,9 +20,6 @@ use wayland_server::protocol::wl_surface::WlSurface;
/// a tree, but with loops allowed. This is because the wayland protocol does not /// a tree, but with loops allowed. This is because the wayland protocol does not
/// have a failure case to forbid this. Note that if any node in such a graph does not /// have a failure case to forbid this. Note that if any node in such a graph does not
/// have a parent, then the graph is a tree and this node is its root. /// have a parent, then the graph is a tree and this node is its root.
///
/// All the methods here are unsafe, because they assume the provided `wl_surface` object
/// is correctly initialized regarding its `user_data`.
pub struct SurfaceData<U, R> { pub struct SurfaceData<U, R> {
parent: Option<Resource<WlSurface>>, parent: Option<Resource<WlSurface>>,
children: Vec<Resource<WlSurface>>, children: Vec<Resource<WlSurface>>,
@ -46,18 +43,13 @@ pub enum TraversalAction<T> {
} }
impl<U: Default, R: Default> SurfaceData<U, R> { impl<U: Default, R: Default> SurfaceData<U, R> {
fn new() -> SurfaceData<U, R> { pub fn new() -> Mutex<SurfaceData<U, R>> {
SurfaceData { Mutex::new(SurfaceData {
parent: None, parent: None,
children: Vec::new(), children: Vec::new(),
role: Default::default(), role: Default::default(),
attributes: Default::default(), attributes: Default::default(),
} })
}
/// Initialize the user_data of a surface, must be called right when the surface is created
pub unsafe fn init(surface: &Resource<WlSurface>) {
surface.set_user_data(Box::into_raw(Box::new(Mutex::new(SurfaceData::<U, R>::new()))) as *mut _)
} }
} }
@ -66,21 +58,14 @@ where
U: 'static, U: 'static,
R: 'static, R: 'static,
{ {
unsafe fn get_data(surface: &Resource<WlSurface>) -> &Mutex<SurfaceData<U, R>> {
let ptr = surface.get_user_data();
&*(ptr as *mut _)
}
/// Cleans the user_data of that surface, must be called when it is destroyed /// Cleans the user_data of that surface, must be called when it is destroyed
pub unsafe fn cleanup(surface: &Resource<WlSurface>) { pub fn cleanup(surface: &Resource<WlSurface>) {
let ptr = surface.get_user_data(); let my_data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
surface.set_user_data(::std::ptr::null_mut()); let mut my_data = my_data_mutex.lock().unwrap();
let my_data_mutex: Box<Mutex<SurfaceData<U, R>>> = Box::from_raw(ptr as *mut _);
let mut my_data = my_data_mutex.into_inner().unwrap();
if let Some(old_parent) = my_data.parent.take() { if let Some(old_parent) = my_data.parent.take() {
if !old_parent.equals(surface) { if !old_parent.equals(surface) {
// We had a parent that is not ourselves, lets unregister ourselves from it // We had a parent that is not ourselves, lets unregister ourselves from it
let old_parent_mutex = Self::get_data(&old_parent); let old_parent_mutex = old_parent.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut old_parent_guard = old_parent_mutex.lock().unwrap(); let mut old_parent_guard = old_parent_mutex.lock().unwrap();
old_parent_guard.children.retain(|c| !c.equals(surface)); old_parent_guard.children.retain(|c| !c.equals(surface));
} }
@ -91,7 +76,7 @@ where
if child.equals(surface) { if child.equals(surface) {
continue; continue;
} }
let child_mutex = Self::get_data(child); let child_mutex = child.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut child_guard = child_mutex.lock().unwrap(); let mut child_guard = child_mutex.lock().unwrap();
child_guard.parent = None; child_guard.parent = None;
} }
@ -99,32 +84,32 @@ where
} }
impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> { impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
pub unsafe fn has_a_role(surface: &Resource<WlSurface>) -> bool { pub fn has_a_role(surface: &Resource<WlSurface>) -> bool {
debug_assert!(surface.is_alive()); debug_assert!(surface.is_alive());
let data_mutex = Self::get_data(surface); let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let data_guard = data_mutex.lock().unwrap(); let data_guard = data_mutex.lock().unwrap();
<R as RoleType>::has_role(&data_guard.role) <R as RoleType>::has_role(&data_guard.role)
} }
/// Check wether a surface has a given role /// Check wether a surface has a given role
pub unsafe fn has_role<RoleData>(surface: &Resource<WlSurface>) -> bool pub fn has_role<RoleData>(surface: &Resource<WlSurface>) -> bool
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
debug_assert!(surface.is_alive()); debug_assert!(surface.is_alive());
let data_mutex = Self::get_data(surface); let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let data_guard = data_mutex.lock().unwrap(); let data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::has(&data_guard.role) <R as Role<RoleData>>::has(&data_guard.role)
} }
/// Register that this surface has a role, fails if it already has one /// Register that this surface has a role, fails if it already has one
pub unsafe fn give_role<RoleData>(surface: &Resource<WlSurface>) -> Result<(), ()> pub fn give_role<RoleData>(surface: &Resource<WlSurface>) -> Result<(), ()>
where where
R: Role<RoleData>, R: Role<RoleData>,
RoleData: Default, RoleData: Default,
{ {
debug_assert!(surface.is_alive()); debug_assert!(surface.is_alive());
let data_mutex = Self::get_data(surface); let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::set(&mut data_guard.role) <R as Role<RoleData>>::set(&mut data_guard.role)
} }
@ -132,15 +117,12 @@ impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
/// Register that this surface has a role with given data /// Register that this surface has a role with given data
/// ///
/// Fails if it already has one and returns the data /// Fails if it already has one and returns the data
pub unsafe fn give_role_with<RoleData>( pub fn give_role_with<RoleData>(surface: &Resource<WlSurface>, data: RoleData) -> Result<(), RoleData>
surface: &Resource<WlSurface>,
data: RoleData,
) -> Result<(), RoleData>
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
debug_assert!(surface.is_alive()); debug_assert!(surface.is_alive());
let data_mutex = Self::get_data(surface); let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::set_with(&mut data_guard.role, data) <R as Role<RoleData>>::set_with(&mut data_guard.role, data)
} }
@ -149,24 +131,24 @@ impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
/// ///
/// It is a noop if this surface already didn't have one, but fails if /// It is a noop if this surface already didn't have one, but fails if
/// the role was "subsurface", it must be removed by the `unset_parent` method. /// the role was "subsurface", it must be removed by the `unset_parent` method.
pub unsafe fn remove_role<RoleData>(surface: &Resource<WlSurface>) -> Result<RoleData, WrongRole> pub fn remove_role<RoleData>(surface: &Resource<WlSurface>) -> Result<RoleData, WrongRole>
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
debug_assert!(surface.is_alive()); debug_assert!(surface.is_alive());
let data_mutex = Self::get_data(surface); let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
<R as Role<RoleData>>::unset(&mut data_guard.role) <R as Role<RoleData>>::unset(&mut data_guard.role)
} }
/// Access to the role data /// Access to the role data
pub unsafe fn with_role_data<RoleData, F, T>(surface: &Resource<WlSurface>, f: F) -> Result<T, WrongRole> pub fn with_role_data<RoleData, F, T>(surface: &Resource<WlSurface>, f: F) -> Result<T, WrongRole>
where where
R: Role<RoleData>, R: Role<RoleData>,
F: FnOnce(&mut RoleData) -> T, F: FnOnce(&mut RoleData) -> T,
{ {
debug_assert!(surface.is_alive()); debug_assert!(surface.is_alive());
let data_mutex = Self::get_data(surface); let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
let data = <R as Role<RoleData>>::data_mut(&mut data_guard.role)?; let data = <R as Role<RoleData>>::data_mut(&mut data_guard.role)?;
Ok(f(data)) Ok(f(data))
@ -178,13 +160,13 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
/// ///
/// if this surface already has a role, does nothing and fails, otherwise /// if this surface already has a role, does nothing and fails, otherwise
/// its role is now to be a subsurface /// its role is now to be a subsurface
pub unsafe fn set_parent(child: &Resource<WlSurface>, parent: &Resource<WlSurface>) -> Result<(), ()> { pub fn set_parent(child: &Resource<WlSurface>, parent: &Resource<WlSurface>) -> Result<(), ()> {
debug_assert!(child.is_alive()); debug_assert!(child.is_alive());
debug_assert!(parent.is_alive()); debug_assert!(parent.is_alive());
// change child's parent // change child's parent
{ {
let child_mutex = Self::get_data(child); let child_mutex = child.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut child_guard = child_mutex.lock().unwrap(); let mut child_guard = child_mutex.lock().unwrap();
// if surface already has a role, it cannot become a subsurface // if surface already has a role, it cannot become a subsurface
<R as Role<SubsurfaceRole>>::set(&mut child_guard.role)?; <R as Role<SubsurfaceRole>>::set(&mut child_guard.role)?;
@ -194,7 +176,7 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
// register child to new parent // register child to new parent
// double scoping is to be robust to have a child be its own parent // double scoping is to be robust to have a child be its own parent
{ {
let parent_mutex = Self::get_data(parent); let parent_mutex = parent.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut parent_guard = parent_mutex.lock().unwrap(); let mut parent_guard = parent_mutex.lock().unwrap();
parent_guard.children.push(child.clone()) parent_guard.children.push(child.clone())
} }
@ -204,10 +186,10 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
/// Remove a pre-existing parent of this child /// Remove a pre-existing parent of this child
/// ///
/// Does nothing if it has no parent /// Does nothing if it has no parent
pub unsafe fn unset_parent(child: &Resource<WlSurface>) { pub fn unset_parent(child: &Resource<WlSurface>) {
debug_assert!(child.is_alive()); debug_assert!(child.is_alive());
let old_parent = { let old_parent = {
let child_mutex = Self::get_data(child); let child_mutex = child.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut child_guard = child_mutex.lock().unwrap(); let mut child_guard = child_mutex.lock().unwrap();
let old_parent = child_guard.parent.take(); let old_parent = child_guard.parent.take();
if old_parent.is_some() { if old_parent.is_some() {
@ -219,22 +201,22 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
}; };
// unregister from our parent // unregister from our parent
if let Some(old_parent) = old_parent { if let Some(old_parent) = old_parent {
let parent_mutex = Self::get_data(&old_parent); let parent_mutex = old_parent.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut parent_guard = parent_mutex.lock().unwrap(); let mut parent_guard = parent_mutex.lock().unwrap();
parent_guard.children.retain(|c| !c.equals(child)); parent_guard.children.retain(|c| !c.equals(child));
} }
} }
/// Retrieve the parent surface (if any) of this surface /// Retrieve the parent surface (if any) of this surface
pub unsafe fn get_parent(child: &Resource<WlSurface>) -> Option<Resource<WlSurface>> { pub fn get_parent(child: &Resource<WlSurface>) -> Option<Resource<WlSurface>> {
let child_mutex = Self::get_data(child); let child_mutex = child.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let child_guard = child_mutex.lock().unwrap(); let child_guard = child_mutex.lock().unwrap();
child_guard.parent.as_ref().cloned() child_guard.parent.as_ref().cloned()
} }
/// Retrieve the parent surface (if any) of this surface /// Retrieve the parent surface (if any) of this surface
pub unsafe fn get_children(child: &Resource<WlSurface>) -> Vec<Resource<WlSurface>> { pub fn get_children(child: &Resource<WlSurface>) -> Vec<Resource<WlSurface>> {
let child_mutex = Self::get_data(child); let child_mutex = child.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let child_guard = child_mutex.lock().unwrap(); let child_guard = child_mutex.lock().unwrap();
child_guard.children.to_vec() child_guard.children.to_vec()
} }
@ -242,13 +224,13 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
/// Reorders a surface relative to one of its sibling /// Reorders a surface relative to one of its sibling
/// ///
/// Fails if `relative_to` is not a sibling or parent of `surface`. /// Fails if `relative_to` is not a sibling or parent of `surface`.
pub unsafe fn reorder( pub fn reorder(
surface: &Resource<WlSurface>, surface: &Resource<WlSurface>,
to: Location, to: Location,
relative_to: &Resource<WlSurface>, relative_to: &Resource<WlSurface>,
) -> Result<(), ()> { ) -> Result<(), ()> {
let parent = { let parent = {
let data_mutex = Self::get_data(surface); let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let data_guard = data_mutex.lock().unwrap(); let data_guard = data_mutex.lock().unwrap();
data_guard.parent.as_ref().cloned().unwrap() data_guard.parent.as_ref().cloned().unwrap()
}; };
@ -266,7 +248,7 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
None None
} }
let parent_mutex = Self::get_data(&parent); let parent_mutex = parent.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut parent_guard = parent_mutex.lock().unwrap(); let mut parent_guard = parent_mutex.lock().unwrap();
let my_index = index_of(surface, &parent_guard.children).unwrap(); let my_index = index_of(surface, &parent_guard.children).unwrap();
let mut other_index = match index_of(surface, &parent_guard.children) { let mut other_index = match index_of(surface, &parent_guard.children) {
@ -291,11 +273,13 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
/// ///
/// Note that an internal lock is taken during access of this data, /// Note that an internal lock is taken during access of this data,
/// so the tree cannot be manipulated at the same time /// so the tree cannot be manipulated at the same time
pub unsafe fn with_data<T, F>(surface: &Resource<WlSurface>, f: F) -> T pub fn with_data<T, F>(surface: &Resource<WlSurface>, f: F) -> T
where where
F: FnOnce(&mut SurfaceAttributes<U>) -> T, F: FnOnce(&mut SurfaceAttributes<U>) -> T,
{ {
let data_mutex = Self::get_data(surface); let data_mutex = surface
.user_data::<Mutex<SurfaceData<U, R>>>()
.expect("Accessing the data of foreign surfaces is not supported.");
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
f(&mut data_guard.attributes) f(&mut data_guard.attributes)
} }
@ -308,12 +292,12 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
/// ///
/// The callback returns wether the traversal should continue or not. Returning /// The callback returns wether the traversal should continue or not. Returning
/// false will cause an early-stopping. /// false will cause an early-stopping.
pub unsafe fn map_tree<F, T>(root: &Resource<WlSurface>, initial: T, mut f: F, reverse: bool) pub fn map_tree<F, T>(root: &Resource<WlSurface>, initial: T, mut f: F, reverse: bool)
where where
F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>, F: FnMut(&Resource<WlSurface>, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
{ {
// helper function for recursion // helper function for recursion
unsafe fn map<U: 'static, R: 'static, F, T>( fn map<U: 'static, R: 'static, F, T>(
surface: &Resource<WlSurface>, surface: &Resource<WlSurface>,
root: &Resource<WlSurface>, root: &Resource<WlSurface>,
initial: &T, initial: &T,
@ -328,16 +312,11 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
return true; return true;
} }
let data_mutex = SurfaceData::<U, R>::get_data(surface); let data_mutex = surface.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
let data_guard = &mut *data_guard; let data_guard = &mut *data_guard;
// call the callback on ourselves // call the callback on ourselves
match f( match f(surface, &mut data_guard.attributes, &mut data_guard.role, initial) {
surface,
&mut data_guard.attributes,
&mut data_guard.role,
initial,
) {
TraversalAction::DoChildren(t) => { TraversalAction::DoChildren(t) => {
// loop over children // loop over children
if reverse { if reverse {
@ -360,16 +339,13 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
} }
} }
let data_mutex = Self::get_data(root); let data_mutex = root.user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
let mut data_guard = data_mutex.lock().unwrap(); let mut data_guard = data_mutex.lock().unwrap();
let data_guard = &mut *data_guard; let data_guard = &mut *data_guard;
// call the callback on ourselves // call the callback on ourselves
if let TraversalAction::DoChildren(t) = f( if let TraversalAction::DoChildren(t) =
root, f(root, &mut data_guard.attributes, &mut data_guard.role, &initial)
&mut data_guard.attributes, {
&mut data_guard.role,
&initial,
) {
// loop over children // loop over children
if reverse { if reverse {
for c in data_guard.children.iter().rev() { for c in data_guard.children.iter().rev() {

View File

@ -7,16 +7,10 @@
//! //!
//! - An init function or method will take the event loop as argument and //! - An init function or method will take the event loop as argument and
//! insert one or more globals into it. //! insert one or more globals into it.
//! - These functions will return the `Global` handles and, if applicable,
//! a `StateToken` allowing you to access the associated state value in
//! this event loop.
//! - If you want to remove a previously inserted global, just call the //! - If you want to remove a previously inserted global, just call the
//! `destroy()` method on the associated `Global`. If you don't plan to //! `destroy()` method on the associated `Global`. If you don't plan to
//! destroy the global at all, you don't need to bother keeping the //! destroy the global at all, you don't need to bother keeping the
//! `Global` around. //! `Global` around.
//! - You should not remove a state value from the event loop if you have
//! not previously destroyed all the globals using it, otherwise you'll
//! quickly encounter a panic.
pub mod compositor; pub mod compositor;
pub mod output; pub mod output;

View File

@ -22,18 +22,18 @@
//! use wayland_server::protocol::wl_output; //! use wayland_server::protocol::wl_output;
//! //!
//! # fn main() { //! # fn main() {
//! # let (mut display, event_loop) = wayland_server::Display::new(); //! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! // Create the Output with given name and physical properties //! // Create the Output with given name and physical properties
//! let (output, _output_global) = Output::new( //! let (output, _output_global) = Output::new(
//! &mut display, // the display //! &mut display, // the display
//! event_loop.token(), // the LoopToken
//! "output-0".into(), // the name of this output, //! "output-0".into(), // the name of this output,
//! PhysicalProperties { //! PhysicalProperties {
//! width: 200, // width in mm //! width: 200, // width in mm
//! height: 150, // height in mm, //! height: 150, // height in mm,
//! subpixel: wl_output::Subpixel::HorizontalRgb, // subpixel information //! subpixel: wl_output::Subpixel::HorizontalRgb, // subpixel information
//! maker: "Screens Inc".into(), // manufacturer of the monitor //! make: "Screens Inc".into(), // make of the monitor
//! model: "Monitor Ultra".into(), // model of the monitor //! model: "Monitor Ultra".into(), // model of the monitor
//! }, //! },
//! None // insert a logger here //! None // insert a logger here
//! ); //! );
@ -53,10 +53,9 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use wayland_server::{Display, Global, LoopToken, NewResource, Resource};
use wayland_server::commons::{downcast_impl, Implementation};
use wayland_server::protocol::wl_output::{Event, Mode as WMode, Request, WlOutput}; use wayland_server::protocol::wl_output::{Event, Mode as WMode, Request, WlOutput};
pub use wayland_server::protocol::wl_output::{Subpixel, Transform}; pub use wayland_server::protocol::wl_output::{Subpixel, Transform};
use wayland_server::{Display, Global, NewResource, Resource};
/// An output mode /// An output mode
/// ///
@ -84,8 +83,8 @@ pub struct PhysicalProperties {
pub height: i32, pub height: i32,
/// The subpixel geometry /// The subpixel geometry
pub subpixel: Subpixel, pub subpixel: Subpixel,
/// Textual representation of the manufacturer /// Textual representation of the make
pub maker: String, pub make: String,
/// Textual representation of the model /// Textual representation of the model
pub model: String, pub model: String,
} }
@ -148,27 +147,13 @@ impl Inner {
physical_width: self.physical.width, physical_width: self.physical.width,
physical_height: self.physical.height, physical_height: self.physical.height,
subpixel: self.physical.subpixel, subpixel: self.physical.subpixel,
make: self.physical.maker.clone(), make: self.physical.make.clone(),
model: self.physical.model.clone(), model: self.physical.model.clone(),
transform: self.transform, transform: self.transform,
}); });
} }
} }
struct InnerWrapper {
inner: Arc<Mutex<Inner>>,
}
// This implementation does nothing, we just use it as a stable type to downcast the
// implementation in the destructor of wl_output, in order to retrieve the Arc to the
// inner and remove this output from the list
impl Implementation<Resource<WlOutput>, Request> for InnerWrapper {
fn receive(&mut self, req: Request, _res: Resource<WlOutput>) {
// this will break if new variants are added :)
let Request::Release = req;
}
}
/// An output as seen by the clients /// An output as seen by the clients
/// ///
/// This handle is stored in the events loop, and allows you to notify clients /// This handle is stored in the events loop, and allows you to notify clients
@ -185,7 +170,6 @@ impl Output {
/// in case you whish to remove this global in the future. /// in case you whish to remove this global in the future.
pub fn new<L>( pub fn new<L>(
display: &mut Display, display: &mut Display,
token: LoopToken,
name: String, name: String,
physical: PhysicalProperties, physical: PhysicalProperties,
logger: L, logger: L,
@ -210,25 +194,19 @@ impl Output {
preferred_mode: None, preferred_mode: None,
})); }));
let output = Output { let output = Output { inner: inner.clone() };
inner: inner.clone(),
};
let global = display.create_global(&token, 3, move |_version, new_output: NewResource<_>| { let global = display.create_global(3, move |new_output: NewResource<_>, _version| {
let output = new_output.implement( let output = new_output.implement(
InnerWrapper { |req, _| {
inner: inner.clone(), // this will break if new variants are added :)
let Request::Release = req;
}, },
Some(|output, boxed_impl| { Some(|output: Resource<WlOutput>| {
let wrapper: Box<InnerWrapper> = let inner = output.user_data::<Arc<Mutex<Inner>>>().unwrap();
downcast_impl(boxed_impl).unwrap_or_else(|_| unreachable!()); inner.lock().unwrap().instances.retain(|o| !o.equals(&output));
wrapper
.inner
.lock()
.unwrap()
.instances
.retain(|o| !o.equals(&output));
}), }),
inner.clone(),
); );
inner.lock().unwrap().new_global(output); inner.lock().unwrap().new_global(output);
}); });

View File

@ -3,9 +3,11 @@ use std::io::{Error as IoError, Write};
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use tempfile::tempfile; use tempfile::tempfile;
use wayland_server::{NewResource, Resource}; use wayland_server::protocol::wl_keyboard::{
Event, KeyState as WlKeyState, KeymapFormat, Request, WlKeyboard,
};
use wayland_server::protocol::wl_surface::WlSurface; use wayland_server::protocol::wl_surface::WlSurface;
use wayland_server::protocol::wl_keyboard::{Event, KeyState as WlKeyState, KeymapFormat, Request, WlKeyboard}; use wayland_server::{NewResource, Resource};
use xkbcommon::xkb; use xkbcommon::xkb;
pub use xkbcommon::xkb::{keysyms, Keysym}; pub use xkbcommon::xkb::{keysyms, Keysym};
@ -194,18 +196,11 @@ pub(crate) fn create_keyboard_handler(
"rules" => rules, "model" => model, "layout" => layout, "variant" => variant, "rules" => rules, "model" => model, "layout" => layout, "variant" => variant,
"options" => &options "options" => &options
); );
let internal = KbdInternal::new( let internal = KbdInternal::new(rules, model, layout, variant, options, repeat_rate, repeat_delay)
rules, .map_err(|_| {
model, debug!(log, "Loading keymap failed");
layout, Error::BadKeymap
variant, })?;
options,
repeat_rate,
repeat_delay,
).map_err(|_| {
debug!(log, "Loading keymap failed");
Error::BadKeymap
})?;
info!(log, "Loaded Keymap"; "name" => internal.keymap.layouts().next()); info!(log, "Loaded Keymap"; "name" => internal.keymap.layouts().next());
@ -416,7 +411,7 @@ pub(crate) fn implement_keyboard(
let destructor = match handle { let destructor = match handle {
Some(h) => { Some(h) => {
let arc = h.arc.clone(); let arc = h.arc.clone();
Some(move |keyboard: Resource<_>, _| { Some(move |keyboard: Resource<_>| {
arc.internal arc.internal
.lock() .lock()
.unwrap() .unwrap()
@ -435,5 +430,6 @@ pub(crate) fn implement_keyboard(
} }
}, },
destructor, destructor,
(),
) )
} }

View File

@ -13,13 +13,13 @@
//! use smithay::wayland::seat::Seat; //! use smithay::wayland::seat::Seat;
//! //!
//! # fn main(){ //! # fn main(){
//! # let (mut display, event_loop) = wayland_server::Display::new(); //! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! // insert the seat: //! // insert the seat:
//! let (seat, seat_global) = Seat::new( //! let (seat, seat_global) = Seat::new(
//! &mut display, // the display //! &mut display, // the display
//! event_loop.token(), // a LoopToken //! "seat-0".into(), // the name of the seat, will be advertized to clients
//! "seat-0".into(), // the name of the seat, will be advertize to clients //! None // insert a logger here
//! None /* insert a logger here*/
//! ); //! );
//! # } //! # }
//! ``` //! ```
@ -40,12 +40,12 @@
//! # use smithay::wayland::seat::Seat; //! # use smithay::wayland::seat::Seat;
//! # //! #
//! # fn main(){ //! # fn main(){
//! # let (mut display, event_loop) = wayland_server::Display::new(); //! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # let (mut seat, seat_global) = Seat::new( //! # let (mut seat, seat_global) = Seat::new(
//! # &mut display, //! # &mut display,
//! # event_loop.token(), //! # "seat-0".into(),
//! # "seat-0".into(), // the name of the seat, will be advertize to clients //! # None
//! # None /* insert a logger here*/
//! # ); //! # );
//! let pointer_handle = seat.add_pointer(); //! let pointer_handle = seat.add_pointer();
//! # } //! # }
@ -61,8 +61,8 @@ mod pointer;
pub use self::keyboard::{keysyms, Error as KeyboardError, KeyboardHandle, Keysym, ModifiersState}; pub use self::keyboard::{keysyms, Error as KeyboardError, KeyboardHandle, Keysym, ModifiersState};
pub use self::pointer::{PointerAxisHandle, PointerHandle}; pub use self::pointer::{PointerAxisHandle, PointerHandle};
use wayland_server::{Display, Global, LoopToken, NewResource, Resource};
use wayland_server::protocol::wl_seat; use wayland_server::protocol::wl_seat;
use wayland_server::{Display, Global, NewResource, Resource};
struct Inner { struct Inner {
log: ::slog::Logger, log: ::slog::Logger,
@ -113,12 +113,7 @@ impl Seat {
/// You are provided with the state token to retrieve it (allowing /// You are provided with the state token to retrieve it (allowing
/// you to add or remove capabilities from it), and the global handle, /// you to add or remove capabilities from it), and the global handle,
/// in case you want to remove it. /// in case you want to remove it.
pub fn new<L>( pub fn new<L>(display: &mut Display, name: String, logger: L) -> (Seat, Global<wl_seat::WlSeat>)
display: &mut Display,
token: LoopToken,
name: String,
logger: L,
) -> (Seat, Global<wl_seat::WlSeat>)
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
{ {
@ -130,10 +125,8 @@ impl Seat {
keyboard: None, keyboard: None,
known_seats: Vec::new(), known_seats: Vec::new(),
})); }));
let seat = Seat { let seat = Seat { inner: inner.clone() };
inner: inner.clone(), let global = display.create_global(5, move |new_seat, _version| {
};
let global = display.create_global(&token, 5, move |_version, new_seat| {
let seat = implement_seat(new_seat, inner.clone()); let seat = implement_seat(new_seat, inner.clone());
let mut inner = inner.lock().unwrap(); let mut inner = inner.lock().unwrap();
if seat.version() >= 2 { if seat.version() >= 2 {
@ -277,12 +270,13 @@ fn implement_seat(
} }
} }
}, },
Some(move |seat, _| { Some(move |seat| {
dest_inner dest_inner
.lock() .lock()
.unwrap() .unwrap()
.known_seats .known_seats
.retain(|s| !s.equals(&seat)); .retain(|s| !s.equals(&seat));
}), }),
(),
) )
} }

View File

@ -1,7 +1,7 @@
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
use wayland_server::{NewResource, Resource};
use wayland_server::protocol::wl_surface::WlSurface;
use wayland_server::protocol::wl_pointer::{Axis, AxisSource, ButtonState, Event, Request, WlPointer}; use wayland_server::protocol::wl_pointer::{Axis, AxisSource, ButtonState, Event, Request, WlPointer};
use wayland_server::protocol::wl_surface::WlSurface;
use wayland_server::{NewResource, Resource};
// TODO: handle pointer surface role // TODO: handle pointer surface role
@ -138,7 +138,7 @@ impl PointerHandle {
/// ///
/// A single frame will group multiple scroll events as if they happended in the same instance. /// A single frame will group multiple scroll events as if they happended in the same instance.
/// Dropping the returned `PointerAxisHandle` will group the events together. /// Dropping the returned `PointerAxisHandle` will group the events together.
pub fn axis(& self) -> PointerAxisHandle { pub fn axis(&self) -> PointerAxisHandle {
PointerAxisHandle { PointerAxisHandle {
inner: self.inner.lock().unwrap(), inner: self.inner.lock().unwrap(),
} }
@ -171,9 +171,7 @@ impl<'a> PointerAxisHandle<'a> {
pub fn source(&mut self, source: AxisSource) -> &mut Self { pub fn source(&mut self, source: AxisSource) -> &mut Self {
self.inner.with_focused_pointers(|pointer, _| { self.inner.with_focused_pointers(|pointer, _| {
if pointer.version() >= 5 { if pointer.version() >= 5 {
pointer.send(Event::AxisSource { pointer.send(Event::AxisSource { axis_source: source });
axis_source: source,
});
} }
}); });
self self
@ -245,7 +243,7 @@ pub(crate) fn implement_pointer(
let destructor = match handle { let destructor = match handle {
Some(h) => { Some(h) => {
let inner = h.inner.clone(); let inner = h.inner.clone();
Some(move |pointer: Resource<_>, _| { Some(move |pointer: Resource<_>| {
inner inner
.lock() .lock()
.unwrap() .unwrap()
@ -267,5 +265,6 @@ pub(crate) fn implement_pointer(
} }
}, },
destructor, destructor,
(),
) )
} }

View File

@ -35,7 +35,6 @@
//! use smithay::wayland::compositor::roles::*; //! use smithay::wayland::compositor::roles::*;
//! use smithay::wayland::compositor::CompositorToken; //! use smithay::wayland::compositor::CompositorToken;
//! use smithay::wayland::shell::legacy::{wl_shell_init, ShellSurfaceRole, ShellRequest}; //! use smithay::wayland::shell::legacy::{wl_shell_init, ShellSurfaceRole, ShellRequest};
//! use wayland_server::{EventLoop, LoopToken};
//! # use wayland_server::protocol::{wl_seat, wl_output}; //! # use wayland_server::protocol::{wl_seat, wl_output};
//! # #[derive(Default)] struct MySurfaceData; //! # #[derive(Default)] struct MySurfaceData;
//! //!
@ -51,21 +50,19 @@
//! ); //! );
//! //!
//! # fn main() { //! # fn main() {
//! # let (mut display, event_loop) = wayland_server::Display::new(); //! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # let (compositor_token, _, _) = smithay::wayland::compositor::compositor_init::<(), MyRoles, _, _>( //! # let (compositor_token, _, _) = smithay::wayland::compositor::compositor_init::<(), MyRoles, _, _>(
//! # &mut display, //! # &mut display,
//! # event_loop.token(), //! # |_, _, _| {},
//! # |_, _| {},
//! # None //! # None
//! # ); //! # );
//! let (shell_state, _) = wl_shell_init( //! let (shell_state, _) = wl_shell_init(
//! &mut display, //! &mut display,
//! event_loop.token(),
//! // token from the compositor implementation //! // token from the compositor implementation
//! compositor_token, //! compositor_token,
//! // your implementation, can also be a strucy implementing the //! // your implementation
//! // appropriate Implementation<(), ShellRequest<_, _, _>> trait //! |event: ShellRequest<_, _, MyShellSurfaceData>| { /* ... */ },
//! |event: ShellRequest<_, _, MyShellSurfaceData>, ()| { /* ... */ },
//! None // put a logger if you want //! None // put a logger if you want
//! ); //! );
//! //!
@ -73,16 +70,15 @@
//! # } //! # }
//! ``` //! ```
use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use wayland::compositor::CompositorToken;
use wayland::compositor::roles::Role; use wayland::compositor::roles::Role;
use wayland::compositor::CompositorToken;
use wayland_server::{Display, Global, LoopToken, Resource};
use wayland_server::commons::Implementation;
use wayland_server::protocol::{wl_output, wl_seat, wl_shell, wl_shell_surface, wl_surface}; use wayland_server::protocol::{wl_output, wl_seat, wl_shell, wl_shell_surface, wl_surface};
use wayland_server::{Display, Global, Resource};
mod wl_handlers; mod wl_handlers;
@ -154,8 +150,7 @@ where
} }
}); });
if let Ok(true) = ret { if let Ok(true) = ret {
self.shell_surface self.shell_surface.send(wl_shell_surface::Event::Ping { serial });
.send(wl_shell_surface::Event::Ping { serial });
Ok(()) Ok(())
} else { } else {
Err(()) Err(())
@ -318,7 +313,6 @@ where
/// Create a new `wl_shell` global /// Create a new `wl_shell` global
pub fn wl_shell_init<U, R, D, L, Impl>( pub fn wl_shell_init<U, R, D, L, Impl>(
display: &mut Display, display: &mut Display,
ltoken: LoopToken,
ctoken: CompositorToken<U, R>, ctoken: CompositorToken<U, R>,
implementation: Impl, implementation: Impl,
logger: L, logger: L,
@ -328,23 +322,23 @@ where
D: Default + 'static, D: Default + 'static,
R: Role<ShellSurfaceRole<D>> + 'static, R: Role<ShellSurfaceRole<D>> + 'static,
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
Impl: Implementation<(), ShellRequest<U, R, D>>, Impl: FnMut(ShellRequest<U, R, D>) + 'static,
{ {
let _log = ::slog_or_stdlog(logger); let _log = ::slog_or_stdlog(logger);
let implementation = Rc::new(RefCell::new(implementation)); let implementation = Rc::new(RefCell::new(implementation));
let ltoken2 = ltoken.clone(); let dtoken = display.get_token();
let state = Arc::new(Mutex::new(ShellState { let state = Arc::new(Mutex::new(ShellState {
known_surfaces: Vec::new(), known_surfaces: Vec::new(),
})); }));
let state2 = state.clone(); let state2 = state.clone();
let global = display.create_global(&ltoken2, 1, move |_version, shell| { let global = display.create_global(1, move |shell, _version| {
self::wl_handlers::implement_shell( self::wl_handlers::implement_shell(
shell, shell,
ltoken.clone(), dtoken.clone(),
ctoken, ctoken,
implementation.clone(), implementation.clone(),
state2.clone(), state2.clone(),

View File

@ -2,18 +2,17 @@ use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use wayland_server::{LoopToken, NewResource, Resource};
use wayland_server::commons::Implementation;
use wayland_server::protocol::{wl_shell, wl_shell_surface, wl_surface}; use wayland_server::protocol::{wl_shell, wl_shell_surface, wl_surface};
use wayland_server::{DisplayToken, NewResource, Resource};
use wayland::compositor::CompositorToken;
use wayland::compositor::roles::Role; use wayland::compositor::roles::Role;
use wayland::compositor::CompositorToken;
use super::{ShellRequest, ShellState, ShellSurface, ShellSurfaceKind, ShellSurfaceRole}; use super::{ShellRequest, ShellState, ShellSurface, ShellSurfaceKind, ShellSurfaceRole};
pub(crate) fn implement_shell<U, R, D, Impl>( pub(crate) fn implement_shell<U, R, D, Impl>(
shell: NewResource<wl_shell::WlShell>, shell: NewResource<wl_shell::WlShell>,
ltoken: LoopToken, dtoken: DisplayToken,
ctoken: CompositorToken<U, R>, ctoken: CompositorToken<U, R>,
implementation: Rc<RefCell<Impl>>, implementation: Rc<RefCell<Impl>>,
state: Arc<Mutex<ShellState<U, R, D>>>, state: Arc<Mutex<ShellState<U, R, D>>>,
@ -21,9 +20,9 @@ pub(crate) fn implement_shell<U, R, D, Impl>(
U: 'static, U: 'static,
D: Default + 'static, D: Default + 'static,
R: Role<ShellSurfaceRole<D>> + 'static, R: Role<ShellSurfaceRole<D>> + 'static,
Impl: Implementation<(), ShellRequest<U, R, D>> + 'static, Impl: FnMut(ShellRequest<U, R, D>) + 'static,
{ {
let ltoken2 = ltoken.clone(); let dtoken2 = dtoken.clone();
shell.implement_nonsend( shell.implement_nonsend(
move |req, shell: Resource<_>| { move |req, shell: Resource<_>| {
let wl_shell::Request::GetShellSurface { id, surface } = req; let wl_shell::Request::GetShellSurface { id, surface } = req;
@ -34,17 +33,14 @@ pub(crate) fn implement_shell<U, R, D, Impl>(
user_data: Default::default(), user_data: Default::default(),
}; };
if ctoken.give_role_with(&surface, role_data).is_err() { if ctoken.give_role_with(&surface, role_data).is_err() {
shell.post_error( shell.post_error(wl_shell::Error::Role as u32, "Surface already has a role.".into());
wl_shell::Error::Role as u32,
"Surface already has a role.".into(),
);
return; return;
} }
let shell_surface = implement_shell_surface( let shell_surface = implement_shell_surface(
id, id,
surface, surface,
implementation.clone(), implementation.clone(),
ltoken.clone(), dtoken.clone(),
ctoken, ctoken,
state.clone(), state.clone(),
); );
@ -53,23 +49,29 @@ pub(crate) fn implement_shell<U, R, D, Impl>(
.unwrap() .unwrap()
.known_surfaces .known_surfaces
.push(make_handle(&shell_surface, ctoken)); .push(make_handle(&shell_surface, ctoken));
implementation.borrow_mut().receive( let mut imp = implementation.borrow_mut();
ShellRequest::NewShellSurface { (&mut *imp)(ShellRequest::NewShellSurface {
surface: make_handle(&shell_surface, ctoken), surface: make_handle(&shell_surface, ctoken),
}, });
(),
);
}, },
None::<fn(_, _)>, None::<fn(_)>,
&ltoken2, (),
&dtoken2,
); );
} }
fn make_handle<U, R, D>( fn make_handle<U, R, SD>(
shell_surface: &Resource<wl_shell_surface::WlShellSurface>, shell_surface: &Resource<wl_shell_surface::WlShellSurface>,
token: CompositorToken<U, R>, token: CompositorToken<U, R>,
) -> ShellSurface<U, R, D> { ) -> ShellSurface<U, R, SD>
let data = unsafe { &*(shell_surface.get_user_data() as *mut ShellSurfaceUserData<U, R, D>) }; where
U: 'static,
R: Role<ShellSurfaceRole<SD>> + 'static,
SD: 'static,
{
let data = shell_surface
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
ShellSurface { ShellSurface {
wl_surface: data.surface.clone(), wl_surface: data.surface.clone(),
shell_surface: shell_surface.clone(), shell_surface: shell_surface.clone(),
@ -78,29 +80,31 @@ fn make_handle<U, R, D>(
} }
} }
pub(crate) struct ShellSurfaceUserData<U, R, D> { pub(crate) struct ShellSurfaceUserData<U, R, SD> {
surface: Resource<wl_surface::WlSurface>, surface: Resource<wl_surface::WlSurface>,
state: Arc<Mutex<ShellState<U, R, D>>>, state: Arc<Mutex<ShellState<U, R, SD>>>,
} }
fn implement_shell_surface<U, R, Impl, D>( fn implement_shell_surface<U, R, Impl, SD>(
shell_surface: NewResource<wl_shell_surface::WlShellSurface>, shell_surface: NewResource<wl_shell_surface::WlShellSurface>,
surface: Resource<wl_surface::WlSurface>, surface: Resource<wl_surface::WlSurface>,
implementation: Rc<RefCell<Impl>>, implementation: Rc<RefCell<Impl>>,
ltoken: LoopToken, dtoken: DisplayToken,
ctoken: CompositorToken<U, R>, ctoken: CompositorToken<U, R>,
state: Arc<Mutex<ShellState<U, R, D>>>, state: Arc<Mutex<ShellState<U, R, SD>>>,
) -> Resource<wl_shell_surface::WlShellSurface> ) -> Resource<wl_shell_surface::WlShellSurface>
where where
U: 'static, U: 'static,
D: 'static, SD: 'static,
R: Role<ShellSurfaceRole<D>> + 'static, R: Role<ShellSurfaceRole<SD>> + 'static,
Impl: Implementation<(), ShellRequest<U, R, D>> + 'static, Impl: FnMut(ShellRequest<U, R, SD>) + 'static,
{ {
use self::wl_shell_surface::Request; use self::wl_shell_surface::Request;
let shell_surface = shell_surface.implement_nonsend( shell_surface.implement_nonsend(
move |req, shell_surface: Resource<_>| { move |req, shell_surface: Resource<_>| {
let data = unsafe { &mut *(shell_surface.get_user_data() as *mut ShellSurfaceUserData<U, R, D>) }; let data = shell_surface
.user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
let mut user_impl = implementation.borrow_mut(); let mut user_impl = implementation.borrow_mut();
match req { match req {
Request::Pong { serial } => { Request::Pong { serial } => {
@ -112,76 +116,48 @@ where
} else { } else {
false false
} }
}) }).expect("wl_shell_surface exists but surface has not the right role?");
.expect("wl_shell_surface exists but surface has not the right role?");
if valid { if valid {
user_impl.receive( (&mut *user_impl)(ShellRequest::Pong {
ShellRequest::Pong { surface: make_handle(&shell_surface, ctoken),
surface: make_handle(&shell_surface, ctoken), });
},
(),
);
} }
} }
Request::Move { seat, serial } => user_impl.receive( Request::Move { seat, serial } => (&mut *user_impl)(ShellRequest::Move {
ShellRequest::Move { surface: make_handle(&shell_surface, ctoken),
surface: make_handle(&shell_surface, ctoken),
serial,
seat,
},
(),
),
Request::Resize {
seat,
serial, serial,
seat,
}),
Request::Resize { seat, serial, edges } => (&mut *user_impl)(ShellRequest::Resize {
surface: make_handle(&shell_surface, ctoken),
serial,
seat,
edges, edges,
} => user_impl.receive( }),
ShellRequest::Resize { Request::SetToplevel => (&mut *user_impl)(ShellRequest::SetKind {
surface: make_handle(&shell_surface, ctoken), surface: make_handle(&shell_surface, ctoken),
serial, kind: ShellSurfaceKind::Toplevel,
seat, }),
edges, Request::SetTransient { parent, x, y, flags } => (&mut *user_impl)(ShellRequest::SetKind {
surface: make_handle(&shell_surface, ctoken),
kind: ShellSurfaceKind::Transient {
parent,
location: (x, y),
inactive: flags.contains(wl_shell_surface::Transient::Inactive),
}, },
(), }),
),
Request::SetToplevel => user_impl.receive(
ShellRequest::SetKind {
surface: make_handle(&shell_surface, ctoken),
kind: ShellSurfaceKind::Toplevel,
},
(),
),
Request::SetTransient {
parent,
x,
y,
flags,
} => user_impl.receive(
ShellRequest::SetKind {
surface: make_handle(&shell_surface, ctoken),
kind: ShellSurfaceKind::Transient {
parent,
location: (x, y),
inactive: flags.contains(wl_shell_surface::Transient::Inactive),
},
},
(),
),
Request::SetFullscreen { Request::SetFullscreen {
method, method,
framerate, framerate,
output, output,
} => user_impl.receive( } => (&mut *user_impl)(ShellRequest::SetKind {
ShellRequest::SetKind { surface: make_handle(&shell_surface, ctoken),
surface: make_handle(&shell_surface, ctoken), kind: ShellSurfaceKind::Fullscreen {
kind: ShellSurfaceKind::Fullscreen { method,
method, framerate,
framerate, output,
output,
},
}, },
(), }),
),
Request::SetPopup { Request::SetPopup {
seat, seat,
serial, serial,
@ -189,26 +165,20 @@ where
x, x,
y, y,
flags, flags,
} => user_impl.receive( } => (&mut *user_impl)(ShellRequest::SetKind {
ShellRequest::SetKind { surface: make_handle(&shell_surface, ctoken),
surface: make_handle(&shell_surface, ctoken), kind: ShellSurfaceKind::Popup {
kind: ShellSurfaceKind::Popup { parent,
parent, serial,
serial, seat,
seat, location: (x, y),
location: (x, y), inactive: flags.contains(wl_shell_surface::Transient::Inactive),
inactive: flags.contains(wl_shell_surface::Transient::Inactive),
},
}, },
(), }),
), Request::SetMaximized { output } => (&mut *user_impl)(ShellRequest::SetKind {
Request::SetMaximized { output } => user_impl.receive( surface: make_handle(&shell_surface, ctoken),
ShellRequest::SetKind { kind: ShellSurfaceKind::Maximized { output },
surface: make_handle(&shell_surface, ctoken), }),
kind: ShellSurfaceKind::Maximized { output },
},
(),
),
Request::SetTitle { title } => { Request::SetTitle { title } => {
ctoken ctoken
.with_role_data(&data.surface, |data| data.title = title) .with_role_data(&data.surface, |data| data.title = title)
@ -221,13 +191,13 @@ where
} }
} }
}, },
Some(|shell_surface: Resource<_>, _| { Some(|shell_surface: Resource<_>| {
let data = let data = shell_surface
unsafe { Box::from_raw(shell_surface.get_user_data() as *mut ShellSurfaceUserData<U, R, D>) }; .user_data::<ShellSurfaceUserData<U, R, SD>>()
.unwrap();
data.state.lock().unwrap().cleanup_surfaces(); data.state.lock().unwrap().cleanup_surfaces();
}), }),
&ltoken, ShellSurfaceUserData { surface, state },
); &dtoken,
shell_surface.set_user_data(Box::into_raw(Box::new(ShellSurfaceUserData { surface, state })) as *mut ()); )
shell_surface
} }

View File

@ -34,7 +34,6 @@
//! use smithay::wayland::compositor::CompositorToken; //! use smithay::wayland::compositor::CompositorToken;
//! use smithay::wayland::shell::xdg::{xdg_shell_init, XdgSurfaceRole, XdgRequest}; //! use smithay::wayland::shell::xdg::{xdg_shell_init, XdgSurfaceRole, XdgRequest};
//! use wayland_protocols::unstable::xdg_shell::v6::server::zxdg_shell_v6::ZxdgShellV6; //! use wayland_protocols::unstable::xdg_shell::v6::server::zxdg_shell_v6::ZxdgShellV6;
//! use wayland_server::{EventLoop, LoopToken};
//! # use wayland_server::protocol::{wl_seat, wl_output}; //! # use wayland_server::protocol::{wl_seat, wl_output};
//! # #[derive(Default)] struct MySurfaceData; //! # #[derive(Default)] struct MySurfaceData;
//! //!
@ -50,21 +49,19 @@
//! } //! }
//! //!
//! # fn main() { //! # fn main() {
//! # let (mut display, event_loop) = wayland_server::Display::new(); //! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! # let (compositor_token, _, _) = smithay::wayland::compositor::compositor_init::<(), MyRoles, _, _>( //! # let (compositor_token, _, _) = smithay::wayland::compositor::compositor_init::<(), MyRoles, _, _>(
//! # &mut display, //! # &mut display,
//! # event_loop.token(), //! # |_, _, _| {},
//! # |_, _| {},
//! # None //! # None
//! # ); //! # );
//! let (shell_state, _, _) = xdg_shell_init( //! let (shell_state, _, _) = xdg_shell_init(
//! &mut display, //! &mut display,
//! event_loop.token(),
//! // token from the compositor implementation //! // token from the compositor implementation
//! compositor_token, //! compositor_token,
//! // your implementation, can also be a strucy implementing the //! // your implementation
//! // appropriate Implementation<(), XdgRequest<_, _, _>> trait //! |event: XdgRequest<_, _, MyShellData>| { /* ... */ },
//! |event: XdgRequest<_, _, MyShellData>, ()| { /* ... */ },
//! None // put a logger if you want //! None // put a logger if you want
//! ); //! );
//! //!
@ -92,14 +89,16 @@ use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use utils::Rectangle; use utils::Rectangle;
use wayland::compositor::CompositorToken;
use wayland::compositor::roles::Role; use wayland::compositor::roles::Role;
use wayland_protocols::xdg_shell::server::{xdg_popup, xdg_positioner, xdg_surface, xdg_toplevel, xdg_wm_base}; use wayland::compositor::CompositorToken;
use wayland_protocols::unstable::xdg_shell::v6::server::{zxdg_popup_v6, zxdg_shell_v6, zxdg_surface_v6, use wayland_protocols::unstable::xdg_shell::v6::server::{
zxdg_toplevel_v6}; zxdg_popup_v6, zxdg_shell_v6, zxdg_surface_v6, zxdg_toplevel_v6,
use wayland_server::{Display, Global, LoopToken, Resource}; };
use wayland_server::commons::Implementation; use wayland_protocols::xdg_shell::server::{
xdg_popup, xdg_positioner, xdg_surface, xdg_toplevel, xdg_wm_base,
};
use wayland_server::protocol::{wl_output, wl_seat, wl_surface}; use wayland_server::protocol::{wl_output, wl_seat, wl_surface};
use wayland_server::{Display, DisplayToken, Global, Resource};
// handlers for the xdg_shell protocol // handlers for the xdg_shell protocol
mod xdg_handlers; mod xdg_handlers;
@ -254,20 +253,20 @@ impl Default for XdgSurfacePendingState {
} }
} }
pub(crate) struct ShellImplementation<U, R, SD> { pub(crate) struct ShellData<U, R, SD> {
log: ::slog::Logger, log: ::slog::Logger,
compositor_token: CompositorToken<U, R>, compositor_token: CompositorToken<U, R>,
loop_token: LoopToken, display_token: DisplayToken,
user_impl: Rc<RefCell<Implementation<(), XdgRequest<U, R, SD>>>>, user_impl: Rc<RefCell<FnMut(XdgRequest<U, R, SD>)>>,
shell_state: Arc<Mutex<ShellState<U, R, SD>>>, shell_state: Arc<Mutex<ShellState<U, R, SD>>>,
} }
impl<U, R, SD> Clone for ShellImplementation<U, R, SD> { impl<U, R, SD> Clone for ShellData<U, R, SD> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
ShellImplementation { ShellData {
log: self.log.clone(), log: self.log.clone(),
compositor_token: self.compositor_token, compositor_token: self.compositor_token,
loop_token: self.loop_token.clone(), display_token: self.display_token.clone(),
user_impl: self.user_impl.clone(), user_impl: self.user_impl.clone(),
shell_state: self.shell_state.clone(), shell_state: self.shell_state.clone(),
} }
@ -277,7 +276,6 @@ impl<U, R, SD> Clone for ShellImplementation<U, R, SD> {
/// Create a new `xdg_shell` globals /// Create a new `xdg_shell` globals
pub fn xdg_shell_init<U, R, SD, L, Impl>( pub fn xdg_shell_init<U, R, SD, L, Impl>(
display: &mut Display, display: &mut Display,
ltoken: LoopToken,
ctoken: CompositorToken<U, R>, ctoken: CompositorToken<U, R>,
implementation: Impl, implementation: Impl,
logger: L, logger: L,
@ -291,7 +289,7 @@ where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: Default + 'static, SD: Default + 'static,
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
Impl: Implementation<(), XdgRequest<U, R, SD>>, Impl: FnMut(XdgRequest<U, R, SD>) + 'static,
{ {
let log = ::slog_or_stdlog(logger); let log = ::slog_or_stdlog(logger);
let shell_state = Arc::new(Mutex::new(ShellState { let shell_state = Arc::new(Mutex::new(ShellState {
@ -299,22 +297,22 @@ where
known_popups: Vec::new(), known_popups: Vec::new(),
})); }));
let shell_impl = ShellImplementation { let shell_data = ShellData {
log: log.new(o!("smithay_module" => "xdg_shell_handler")), log: log.new(o!("smithay_module" => "xdg_shell_handler")),
loop_token: ltoken.clone(), display_token: display.get_token(),
compositor_token: ctoken, compositor_token: ctoken,
user_impl: Rc::new(RefCell::new(implementation)), user_impl: Rc::new(RefCell::new(implementation)),
shell_state: shell_state.clone(), shell_state: shell_state.clone(),
}; };
let shell_impl_z = shell_impl.clone(); let shell_data_z = shell_data.clone();
let xdg_shell_global = display.create_global(&ltoken, 1, move |_version, shell| { let xdg_shell_global = display.create_global(1, move |shell, _version| {
self::xdg_handlers::implement_wm_base(shell, &shell_impl); self::xdg_handlers::implement_wm_base(shell, &shell_data);
}); });
let zxdgv6_shell_global = display.create_global(&ltoken, 1, move |_version, shell| { let zxdgv6_shell_global = display.create_global(1, move |shell, _version| {
self::zxdgv6_handlers::implement_shell(shell, &shell_impl_z); self::zxdgv6_handlers::implement_shell(shell, &shell_data_z);
}); });
(shell_state, xdg_shell_global, zxdgv6_shell_global) (shell_state, xdg_shell_global, zxdgv6_shell_global)
@ -377,12 +375,18 @@ fn make_shell_client_data<SD: Default>() -> ShellClientData<SD> {
/// ///
/// You can use this handle to access a storage for any /// You can use this handle to access a storage for any
/// client-specific data you wish to associate with it. /// client-specific data you wish to associate with it.
pub struct ShellClient<SD> { pub struct ShellClient<U, R, SD> {
kind: ShellClientKind, kind: ShellClientKind,
_token: CompositorToken<U, R>,
_data: ::std::marker::PhantomData<*mut SD>, _data: ::std::marker::PhantomData<*mut SD>,
} }
impl<SD> ShellClient<SD> { impl<U, R, SD> ShellClient<U, R, SD>
where
U: 'static,
R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{
/// Is the shell client represented by this handle still connected? /// Is the shell client represented by this handle still connected?
pub fn alive(&self) -> bool { pub fn alive(&self) -> bool {
match self.kind { match self.kind {
@ -416,9 +420,10 @@ impl<SD> ShellClient<SD> {
} }
match self.kind { match self.kind {
ShellClientKind::Xdg(ref shell) => { ShellClientKind::Xdg(ref shell) => {
let mutex = let user_data = shell
unsafe { &*(shell.get_user_data() as *mut self::xdg_handlers::ShellUserData<SD>) }; .user_data::<self::xdg_handlers::ShellUserData<U, R, SD>>()
let mut guard = mutex.lock().unwrap(); .unwrap();
let mut guard = user_data.client_data.lock().unwrap();
if guard.pending_ping == 0 { if guard.pending_ping == 0 {
return Err(()); return Err(());
} }
@ -426,9 +431,10 @@ impl<SD> ShellClient<SD> {
shell.send(xdg_wm_base::Event::Ping { serial }); shell.send(xdg_wm_base::Event::Ping { serial });
} }
ShellClientKind::ZxdgV6(ref shell) => { ShellClientKind::ZxdgV6(ref shell) => {
let mutex = let user_data = shell
unsafe { &*(shell.get_user_data() as *mut self::zxdgv6_handlers::ShellUserData<SD>) }; .user_data::<self::zxdgv6_handlers::ShellUserData<U, R, SD>>()
let mut guard = mutex.lock().unwrap(); .unwrap();
let mut guard = user_data.client_data.lock().unwrap();
if guard.pending_ping == 0 { if guard.pending_ping == 0 {
return Err(()); return Err(());
} }
@ -449,15 +455,17 @@ impl<SD> ShellClient<SD> {
} }
match self.kind { match self.kind {
ShellClientKind::Xdg(ref shell) => { ShellClientKind::Xdg(ref shell) => {
let mutex = let data = shell
unsafe { &*(shell.get_user_data() as *mut self::xdg_handlers::ShellUserData<SD>) }; .user_data::<self::xdg_handlers::ShellUserData<U, R, SD>>()
let mut guard = mutex.lock().unwrap(); .unwrap();
let mut guard = data.client_data.lock().unwrap();
Ok(f(&mut guard.data)) Ok(f(&mut guard.data))
} }
ShellClientKind::ZxdgV6(ref shell) => { ShellClientKind::ZxdgV6(ref shell) => {
let mutex = let data = shell
unsafe { &*(shell.get_user_data() as *mut self::zxdgv6_handlers::ShellUserData<SD>) }; .user_data::<self::zxdgv6_handlers::ShellUserData<U, R, SD>>()
let mut guard = mutex.lock().unwrap(); .unwrap();
let mut guard = data.client_data.lock().unwrap();
Ok(f(&mut guard.data)) Ok(f(&mut guard.data))
} }
} }
@ -500,26 +508,29 @@ where
/// Retrieve the shell client owning this toplevel surface /// Retrieve the shell client owning this toplevel surface
/// ///
/// Returns `None` if the surface does actually no longer exist. /// Returns `None` if the surface does actually no longer exist.
pub fn client(&self) -> Option<ShellClient<SD>> { pub fn client(&self) -> Option<ShellClient<U, R, SD>> {
if !self.alive() { if !self.alive() {
return None; return None;
} }
let shell = match self.shell_surface { let shell = match self.shell_surface {
ToplevelKind::Xdg(ref s) => { ToplevelKind::Xdg(ref s) => {
let &(_, ref shell, _) = let data = s
unsafe { &*(s.get_user_data() as *mut self::xdg_handlers::ShellSurfaceUserData) }; .user_data::<self::xdg_handlers::ShellSurfaceUserData<U, R, SD>>()
ShellClientKind::Xdg(shell.clone()) .unwrap();
ShellClientKind::Xdg(data.wm_base.clone())
} }
ToplevelKind::ZxdgV6(ref s) => { ToplevelKind::ZxdgV6(ref s) => {
let &(_, ref shell, _) = let data = s
unsafe { &*(s.get_user_data() as *mut self::zxdgv6_handlers::ShellSurfaceUserData) }; .user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<U, R, SD>>()
ShellClientKind::ZxdgV6(shell.clone()) .unwrap();
ShellClientKind::ZxdgV6(data.shell.clone())
} }
}; };
Some(ShellClient { Some(ShellClient {
kind: shell, kind: shell,
_token: self.token,
_data: ::std::marker::PhantomData, _data: ::std::marker::PhantomData,
}) })
} }
@ -532,8 +543,8 @@ where
return; return;
} }
match self.shell_surface { match self.shell_surface {
ToplevelKind::Xdg(ref s) => self::xdg_handlers::send_toplevel_configure(self.token, s, cfg), ToplevelKind::Xdg(ref s) => self::xdg_handlers::send_toplevel_configure::<U, R, SD>(s, cfg),
ToplevelKind::ZxdgV6(ref s) => self::zxdgv6_handlers::send_toplevel_configure(self.token, s, cfg), ToplevelKind::ZxdgV6(ref s) => self::zxdgv6_handlers::send_toplevel_configure::<U, R, SD>(s, cfg),
} }
} }
@ -549,25 +560,26 @@ where
if !self.alive() { if !self.alive() {
return false; return false;
} }
let configured = self.token let configured = self
.token
.with_role_data::<XdgSurfaceRole, _, _>(&self.wl_surface, |data| data.configured) .with_role_data::<XdgSurfaceRole, _, _>(&self.wl_surface, |data| data.configured)
.expect("A shell surface object exists but the surface does not have the shell_surface role ?!"); .expect("A shell surface object exists but the surface does not have the shell_surface role ?!");
if !configured { if !configured {
match self.shell_surface { match self.shell_surface {
ToplevelKind::Xdg(ref s) => { ToplevelKind::Xdg(ref s) => {
let ptr = s.get_user_data(); let data = s
let &(_, _, ref xdg_surface) = .user_data::<self::xdg_handlers::ShellSurfaceUserData<U, R, SD>>()
unsafe { &*(ptr as *mut self::xdg_handlers::ShellSurfaceUserData) }; .unwrap();
xdg_surface.post_error( data.xdg_surface.post_error(
xdg_surface::Error::NotConstructed as u32, xdg_surface::Error::NotConstructed as u32,
"Surface has not been configured yet.".into(), "Surface has not been configured yet.".into(),
); );
} }
ToplevelKind::ZxdgV6(ref s) => { ToplevelKind::ZxdgV6(ref s) => {
let ptr = s.get_user_data(); let data = s
let &(_, _, ref xdg_surface) = .user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<U, R, SD>>()
unsafe { &*(ptr as *mut self::zxdgv6_handlers::ShellSurfaceUserData) }; .unwrap();
xdg_surface.post_error( data.xdg_surface.post_error(
zxdg_surface_v6::Error::NotConstructed as u32, zxdg_surface_v6::Error::NotConstructed as u32,
"Surface has not been configured yet.".into(), "Surface has not been configured yet.".into(),
); );
@ -607,8 +619,7 @@ where
.with_role_data::<XdgSurfaceRole, _, _>(&self.wl_surface, |data| match data.pending_state { .with_role_data::<XdgSurfaceRole, _, _>(&self.wl_surface, |data| match data.pending_state {
XdgSurfacePendingState::Toplevel(ref state) => Some(state.clone()), XdgSurfacePendingState::Toplevel(ref state) => Some(state.clone()),
_ => None, _ => None,
}) }).ok()
.ok()
.and_then(|x| x) .and_then(|x| x)
} }
} }
@ -652,26 +663,29 @@ where
/// Retrieve the shell client owning this popup surface /// Retrieve the shell client owning this popup surface
/// ///
/// Returns `None` if the surface does actually no longer exist. /// Returns `None` if the surface does actually no longer exist.
pub fn client(&self) -> Option<ShellClient<SD>> { pub fn client(&self) -> Option<ShellClient<U, R, SD>> {
if !self.alive() { if !self.alive() {
return None; return None;
} }
let shell = match self.shell_surface { let shell = match self.shell_surface {
PopupKind::Xdg(ref p) => { PopupKind::Xdg(ref p) => {
let &(_, ref shell, _) = let data = p
unsafe { &*(p.get_user_data() as *mut self::xdg_handlers::ShellSurfaceUserData) }; .user_data::<self::xdg_handlers::ShellSurfaceUserData<U, R, SD>>()
ShellClientKind::Xdg(shell.clone()) .unwrap();
ShellClientKind::Xdg(data.wm_base.clone())
} }
PopupKind::ZxdgV6(ref p) => { PopupKind::ZxdgV6(ref p) => {
let &(_, ref shell, _) = let data = p
unsafe { &*(p.get_user_data() as *mut self::zxdgv6_handlers::ShellSurfaceUserData) }; .user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<U, R, SD>>()
ShellClientKind::ZxdgV6(shell.clone()) .unwrap();
ShellClientKind::ZxdgV6(data.shell.clone())
} }
}; };
Some(ShellClient { Some(ShellClient {
kind: shell, kind: shell,
_token: self.token,
_data: ::std::marker::PhantomData, _data: ::std::marker::PhantomData,
}) })
} }
@ -685,10 +699,10 @@ where
} }
match self.shell_surface { match self.shell_surface {
PopupKind::Xdg(ref p) => { PopupKind::Xdg(ref p) => {
self::xdg_handlers::send_popup_configure(self.token, p, cfg); self::xdg_handlers::send_popup_configure::<U, R, SD>(p, cfg);
} }
PopupKind::ZxdgV6(ref p) => { PopupKind::ZxdgV6(ref p) => {
self::zxdgv6_handlers::send_popup_configure(self.token, p, cfg); self::zxdgv6_handlers::send_popup_configure::<U, R, SD>(p, cfg);
} }
} }
} }
@ -705,25 +719,26 @@ where
if !self.alive() { if !self.alive() {
return false; return false;
} }
let configured = self.token let configured = self
.token
.with_role_data::<XdgSurfaceRole, _, _>(&self.wl_surface, |data| data.configured) .with_role_data::<XdgSurfaceRole, _, _>(&self.wl_surface, |data| data.configured)
.expect("A shell surface object exists but the surface does not have the shell_surface role ?!"); .expect("A shell surface object exists but the surface does not have the shell_surface role ?!");
if !configured { if !configured {
match self.shell_surface { match self.shell_surface {
PopupKind::Xdg(ref s) => { PopupKind::Xdg(ref s) => {
let ptr = s.get_user_data(); let data = s
let &(_, _, ref xdg_surface) = .user_data::<self::xdg_handlers::ShellSurfaceUserData<U, R, SD>>()
unsafe { &*(ptr as *mut self::xdg_handlers::ShellSurfaceUserData) }; .unwrap();
xdg_surface.post_error( data.xdg_surface.post_error(
xdg_surface::Error::NotConstructed as u32, xdg_surface::Error::NotConstructed as u32,
"Surface has not been confgured yet.".into(), "Surface has not been confgured yet.".into(),
); );
} }
PopupKind::ZxdgV6(ref s) => { PopupKind::ZxdgV6(ref s) => {
let ptr = s.get_user_data(); let data = s
let &(_, _, ref xdg_surface) = .user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<U, R, SD>>()
unsafe { &*(ptr as *mut self::zxdgv6_handlers::ShellSurfaceUserData) }; .unwrap();
xdg_surface.post_error( data.xdg_surface.post_error(
zxdg_surface_v6::Error::NotConstructed as u32, zxdg_surface_v6::Error::NotConstructed as u32,
"Surface has not been confgured yet.".into(), "Surface has not been confgured yet.".into(),
); );
@ -766,8 +781,7 @@ where
.with_role_data::<XdgSurfaceRole, _, _>(&self.wl_surface, |data| match data.pending_state { .with_role_data::<XdgSurfaceRole, _, _>(&self.wl_surface, |data| match data.pending_state {
XdgSurfacePendingState::Popup(ref state) => Some(state.clone()), XdgSurfacePendingState::Popup(ref state) => Some(state.clone()),
_ => None, _ => None,
}) }).ok()
.ok()
.and_then(|x| x) .and_then(|x| x)
} }
} }
@ -814,7 +828,7 @@ pub enum XdgRequest<U, R, SD> {
/// A new shell client was instanciated /// A new shell client was instanciated
NewClient { NewClient {
/// the client /// the client
client: ShellClient<SD>, client: ShellClient<U, R, SD>,
}, },
/// The pong for a pending ping of this shell client was received /// The pong for a pending ping of this shell client was received
/// ///
@ -822,7 +836,7 @@ pub enum XdgRequest<U, R, SD> {
/// from the pending ping. /// from the pending ping.
ClientPong { ClientPong {
/// the client /// the client
client: ShellClient<SD>, client: ShellClient<U, R, SD>,
}, },
/// A new toplevel surface was created /// A new toplevel surface was created
/// ///

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -23,21 +23,21 @@
//! use wayland_server::protocol::wl_shm::Format; //! use wayland_server::protocol::wl_shm::Format;
//! //!
//! # fn main() { //! # fn main() {
//! # let (mut display, mut event_loop) = wayland_server::Display::new(); //! # let mut event_loop = wayland_server::calloop::EventLoop::<()>::new().unwrap();
//! # let mut display = wayland_server::Display::new(event_loop.handle());
//! // Insert the ShmGlobal into your event loop //! // Insert the ShmGlobal into your event loop
//! // Here, we specify that Yuyv and C8 format are supported //! // Here, we specify that Yuyv and C8 format are supported
//! // additionnaly to the standart Argb8888 and Xrgb8888. //! // additionnaly to the standart Argb8888 and Xrgb8888.
//! let shm_global = init_shm_global( //! let shm_global = init_shm_global(
//! &mut display, //! &mut display,
//! event_loop.token(),
//! vec![Format::Yuyv, Format::C8], //! vec![Format::Yuyv, Format::C8],
//! None // we don't provide a logger here //! None // we don't provide a logger here
//! ); //! );
//! # } //! # }
//! ``` //! ```
//! //!
//! Then, when you have a `WlBuffer` and need to retrieve its contents, use the token method to //! Then, when you have a `WlBuffer` and need to retrieve its contents, use the
//! do it: //! `with_buffer_contents` function to do it:
//! //!
//! ``` //! ```
//! # extern crate wayland_server; //! # extern crate wayland_server;
@ -45,13 +45,27 @@
//! # use wayland_server::protocol::wl_buffer::WlBuffer; //! # use wayland_server::protocol::wl_buffer::WlBuffer;
//! # use wayland_server::Resource; //! # use wayland_server::Resource;
//! # fn wrap(buffer: &Resource<WlBuffer>) { //! # fn wrap(buffer: &Resource<WlBuffer>) {
//! use smithay::wayland::shm::{with_buffer_contents, BufferData}; //! use smithay::wayland::shm::{with_buffer_contents, BufferData, BufferAccessError};
//! //!
//! with_buffer_contents(&buffer, //! let content = with_buffer_contents(&buffer,
//! |slice: &[u8], buffer_metadata: BufferData| { //! |slice: &[u8], buffer_metadata: BufferData| {
//! // do something to draw it on the screen //! // do something to extract the contents of the buffer
//! } //! }
//! ); //! );
//!
//! match content {
//! Ok(something) => {
//! /* `something` is the content you returned from the closure */
//! },
//! Err(BufferAccessError::NotManaged) => {
//! /* This buffer is not managed by the SHM global, but by something else */
//! },
//! Err(BufferAccessError::BadMap) => {
//! /* The client supplied invalid content specification for this buffer,
//! and was killed.
//! */
//! }
//! }
//! # } //! # }
//! # fn main() {} //! # fn main() {}
//! ``` //! ```
@ -66,9 +80,8 @@
use self::pool::{Pool, ResizeError}; use self::pool::{Pool, ResizeError};
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
use wayland_server::{Display, Global, LoopToken, NewResource, Resource};
use wayland_server::commons::Implementation;
use wayland_server::protocol::{wl_buffer, wl_shm, wl_shm_pool}; use wayland_server::protocol::{wl_buffer, wl_shm, wl_shm_pool};
use wayland_server::{Display, DisplayToken, Global, NewResource, Resource};
mod pool; mod pool;
@ -80,7 +93,7 @@ mod pool;
pub struct ShmGlobalData { pub struct ShmGlobalData {
formats: Rc<Vec<wl_shm::Format>>, formats: Rc<Vec<wl_shm::Format>>,
log: ::slog::Logger, log: ::slog::Logger,
token: LoopToken, token: DisplayToken,
} }
/// Create a new SHM global advertizing given supported formats. /// Create a new SHM global advertizing given supported formats.
@ -94,7 +107,6 @@ pub struct ShmGlobalData {
/// the future. /// the future.
pub fn init_shm_global<L>( pub fn init_shm_global<L>(
display: &mut Display, display: &mut Display,
token: LoopToken,
mut formats: Vec<wl_shm::Format>, mut formats: Vec<wl_shm::Format>,
logger: L, logger: L,
) -> Global<wl_shm::WlShm> ) -> Global<wl_shm::WlShm>
@ -109,11 +121,19 @@ where
let data = ShmGlobalData { let data = ShmGlobalData {
formats: Rc::new(formats), formats: Rc::new(formats),
log: log.new(o!("smithay_module" => "shm_handler")), log: log.new(o!("smithay_module" => "shm_handler")),
token: token.clone(), token: display.get_token(),
}; };
display.create_global::<wl_shm::WlShm, _>(&token, 1, move |_version, shm_new: NewResource<_>| { display.create_global::<wl_shm::WlShm, _>(1, move |shm_new: NewResource<_>, _version| {
let shm = shm_new.implement_nonsend(data.clone(), None::<fn(_, _)>, &data.token); let shm = shm_new.implement_nonsend(
{
let mut data = data.clone();
move |req, shm| data.receive_shm_message(req, shm)
},
None::<fn(_)>,
(),
&data.token,
);
// send the formats // send the formats
for f in &data.formats[..] { for f in &data.formats[..] {
shm.send(wl_shm::Event::Format { format: *f }); shm.send(wl_shm::Event::Format { format: *f });
@ -152,10 +172,10 @@ pub fn with_buffer_contents<F, T>(
where where
F: FnOnce(&[u8], BufferData) -> T, F: FnOnce(&[u8], BufferData) -> T,
{ {
if !buffer.is_implemented_with::<ShmGlobalData>() { let data = match buffer.user_data::<InternalBufferData>() {
return Err(BufferAccessError::NotManaged); Some(d) => d,
} None => return Err(BufferAccessError::NotManaged),
let data = unsafe { &*(buffer.get_user_data() as *mut InternalBufferData) }; };
match data.pool.with_data_slice(|slice| f(slice, data.data)) { match data.pool.with_data_slice(|slice| f(slice, data.data)) {
Ok(t) => Ok(t), Ok(t) => Ok(t),
@ -167,40 +187,38 @@ where
} }
} }
impl Implementation<Resource<wl_shm::WlShm>, wl_shm::Request> for ShmGlobalData { impl ShmGlobalData {
fn receive(&mut self, request: wl_shm::Request, shm: Resource<wl_shm::WlShm>) { fn receive_shm_message(&mut self, request: wl_shm::Request, shm: Resource<wl_shm::WlShm>) {
use self::wl_shm::{Error, Request}; use self::wl_shm::{Error, Request};
match request { let Request::CreatePool { id: pool, fd, size } = request;
Request::CreatePool { id: pool, fd, size } => { if size <= 0 {
if size <= 0 { shm.post_error(
shm.post_error( Error::InvalidFd as u32,
Error::InvalidFd as u32, "Invalid size for a new wl_shm_pool.".into(),
"Invalid size for a new wl_shm_pool.".into(), );
); return;
return;
}
let mmap_pool = match Pool::new(fd, size as usize, self.log.clone()) {
Ok(p) => p,
Err(()) => {
shm.post_error(
wl_shm::Error::InvalidFd as u32,
format!("Failed mmap of fd {}.", fd),
);
return;
}
};
let arc_pool = Box::new(Arc::new(mmap_pool));
let pool = pool.implement_nonsend(
self.clone(),
Some(|pool: Resource<_>, _| {
drop(unsafe { Box::from_raw(pool.get_user_data() as *mut Arc<Pool>) })
}),
&self.token,
);
pool.set_user_data(Box::into_raw(arc_pool) as *mut ());
}
} }
let mmap_pool = match Pool::new(fd, size as usize, self.log.clone()) {
Ok(p) => p,
Err(()) => {
shm.post_error(
wl_shm::Error::InvalidFd as u32,
format!("Failed mmap of fd {}.", fd),
);
return;
}
};
let arc_pool = Arc::new(mmap_pool);
pool.implement_nonsend(
{
let mut data = self.clone();
move |req, pool| data.receive_pool_message(req, pool)
},
None::<fn(_)>,
arc_pool,
&self.token,
);
} }
} }
@ -224,11 +242,15 @@ struct InternalBufferData {
data: BufferData, data: BufferData,
} }
impl Implementation<Resource<wl_shm_pool::WlShmPool>, wl_shm_pool::Request> for ShmGlobalData { impl ShmGlobalData {
fn receive(&mut self, request: wl_shm_pool::Request, pool: Resource<wl_shm_pool::WlShmPool>) { fn receive_pool_message(
&mut self,
request: wl_shm_pool::Request,
pool: Resource<wl_shm_pool::WlShmPool>,
) {
use self::wl_shm_pool::Request; use self::wl_shm_pool::Request;
let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) }; let arc_pool = pool.user_data::<Arc<Pool>>().unwrap();
match request { match request {
Request::CreateBuffer { Request::CreateBuffer {
@ -246,7 +268,7 @@ impl Implementation<Resource<wl_shm_pool::WlShmPool>, wl_shm_pool::Request> for
); );
return; return;
} }
let data = Box::into_raw(Box::new(InternalBufferData { let data = InternalBufferData {
pool: arc_pool.clone(), pool: arc_pool.clone(),
data: BufferData { data: BufferData {
offset, offset,
@ -255,15 +277,16 @@ impl Implementation<Resource<wl_shm_pool::WlShmPool>, wl_shm_pool::Request> for
stride, stride,
format, format,
}, },
})); };
let buffer = buffer.implement_nonsend( buffer.implement_nonsend(
self.clone(), |req, _| {
Some(|buffer: Resource<_>, _| { // this will break if a variant is added to wl_buffer::Request
drop(unsafe { Box::from_raw(buffer.get_user_data() as *mut InternalBufferData) }) let wl_buffer::Request::Destroy = req;
}), },
None::<fn(_)>,
data,
&self.token, &self.token,
); );
buffer.set_user_data(data as *mut ());
} }
Request::Resize { size } => match arc_pool.resize(size) { Request::Resize { size } => match arc_pool.resize(size) {
Ok(()) => {} Ok(()) => {}
@ -281,10 +304,3 @@ impl Implementation<Resource<wl_shm_pool::WlShmPool>, wl_shm_pool::Request> for
} }
} }
} }
impl Implementation<Resource<wl_buffer::WlBuffer>, wl_buffer::Request> for ShmGlobalData {
fn receive(&mut self, request: wl_buffer::Request, _pool: Resource<wl_buffer::WlBuffer>) {
// this will break if new requests are added to buffer =)
let wl_buffer::Request::Destroy = request;
}
}

View File

@ -1,6 +1,6 @@
use nix::{libc, unistd};
use nix::sys::mman; use nix::sys::mman;
use nix::sys::signal::{self, SigAction, SigHandler, Signal}; use nix::sys::signal::{self, SigAction, SigHandler, Signal};
use nix::{libc, unistd};
use std::cell::Cell; use std::cell::Cell;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use std::ptr; use std::ptr;

View File

@ -1,4 +1,4 @@
mod xserver;
mod x11_sockets; mod x11_sockets;
mod xserver;
pub use self::xserver::{XWayland, XWindowManager}; pub use self::xserver::{XWayland, XWindowManager};

View File

@ -2,9 +2,9 @@ use std::io::{Read, Write};
use std::os::unix::io::FromRawFd; use std::os::unix::io::FromRawFd;
use std::os::unix::net::UnixStream; use std::os::unix::net::UnixStream;
use nix::{Error as NixError, Result as NixResult};
use nix::errno::Errno; use nix::errno::Errno;
use nix::sys::socket; use nix::sys::socket;
use nix::{Error as NixError, Result as NixResult};
/// Find a free X11 display slot and setup /// Find a free X11 display slot and setup
pub(crate) fn prepare_x11_sockets(log: ::slog::Logger) -> Result<(X11Lock, [UnixStream; 2]), ()> { pub(crate) fn prepare_x11_sockets(log: ::slog::Logger) -> Result<(X11Lock, [UnixStream; 2]), ()> {
@ -62,11 +62,13 @@ impl X11Lock {
let mut spid = [0u8; 11]; let mut spid = [0u8; 11];
file.read_exact(&mut spid).map_err(|_| ())?; file.read_exact(&mut spid).map_err(|_| ())?;
::std::mem::drop(file); ::std::mem::drop(file);
let pid = ::nix::unistd::Pid::from_raw(::std::str::from_utf8(&spid) let pid = ::nix::unistd::Pid::from_raw(
.map_err(|_| ())? ::std::str::from_utf8(&spid)
.trim() .map_err(|_| ())?
.parse::<i32>() .trim()
.map_err(|_| ())?); .parse::<i32>()
.map_err(|_| ())?,
);
if let Err(NixError::Sys(Errno::ESRCH)) = ::nix::sys::signal::kill(pid, None) { if let Err(NixError::Sys(Errno::ESRCH)) = ::nix::sys::signal::kill(pid, None) {
// no process whose pid equals the contents of the lockfile exists // no process whose pid equals the contents of the lockfile exists
// remove the lockfile and try grabbing it again // remove the lockfile and try grabbing it again

View File

@ -25,21 +25,22 @@
* *
*/ */
use std::cell::RefCell; use std::cell::RefCell;
use std::rc::Rc;
use std::env; use std::env;
use std::ffi::CString; use std::ffi::CString;
use std::os::unix::io::{AsRawFd, IntoRawFd}; use std::os::unix::io::{AsRawFd, IntoRawFd};
use std::os::unix::net::UnixStream; use std::os::unix::net::UnixStream;
use std::rc::Rc;
use nix::{Error as NixError, Result as NixResult};
use nix::errno::Errno; use nix::errno::Errno;
use nix::unistd::{fork, ForkResult, Pid};
use nix::sys::signal; use nix::sys::signal;
use nix::unistd::{fork, ForkResult, Pid};
use nix::{Error as NixError, Result as NixResult};
use wayland_server::{Client, Display, LoopToken}; use wayland_server::calloop::signals::{Signal, Signals};
use wayland_server::sources::{SignalEvent, Source}; use wayland_server::calloop::{LoopHandle, Source};
use wayland_server::{Client, Display};
use super::x11_sockets::{X11Lock, prepare_x11_sockets}; use super::x11_sockets::{prepare_x11_sockets, X11Lock};
/// The XWayland handle /// The XWayland handle
pub struct XWayland<WM: XWindowManager> { pub struct XWayland<WM: XWindowManager> {
@ -66,9 +67,9 @@ pub trait XWindowManager {
impl<WM: XWindowManager + 'static> XWayland<WM> { impl<WM: XWindowManager + 'static> XWayland<WM> {
/// Start the XWayland server /// Start the XWayland server
pub fn init<L>( pub fn init<L, Data: 'static>(
wm: WM, wm: WM,
token: LoopToken, handle: LoopHandle<Data>,
display: Rc<RefCell<Display>>, display: Rc<RefCell<Display>>,
logger: L, logger: L,
) -> Result<XWayland<WM>, ()> ) -> Result<XWayland<WM>, ()>
@ -78,7 +79,16 @@ impl<WM: XWindowManager + 'static> XWayland<WM> {
let log = ::slog_or_stdlog(logger); let log = ::slog_or_stdlog(logger);
let inner = Rc::new(RefCell::new(Inner { let inner = Rc::new(RefCell::new(Inner {
wm, wm,
token, source_maker: Box::new(move |inner| {
handle
.insert_source(
Signals::new(&[Signal::SIGUSR1]).map_err(|_| ())?,
move |evt, _| {
debug_assert!(evt.signal() == Signal::SIGUSR1);
xwayland_ready(&inner);
},
).map_err(|_| ())
}),
wayland_display: display, wayland_display: display,
instance: None, instance: None,
log: log.new(o!("smithay_module" => "XWayland")), log: log.new(o!("smithay_module" => "XWayland")),
@ -97,7 +107,7 @@ impl<WM: XWindowManager> Drop for XWayland<WM> {
struct XWaylandInstance { struct XWaylandInstance {
display_lock: X11Lock, display_lock: X11Lock,
wayland_client: Client, wayland_client: Client,
sigusr1_handler: Option<Source<SignalEvent>>, sigusr1_handler: Option<Source<Signals>>,
wm_fd: Option<UnixStream>, wm_fd: Option<UnixStream>,
started_at: ::std::time::Instant, started_at: ::std::time::Instant,
child_pid: Option<Pid>, child_pid: Option<Pid>,
@ -106,7 +116,7 @@ struct XWaylandInstance {
// Inner implementation of the XWayland manager // Inner implementation of the XWayland manager
struct Inner<WM: XWindowManager> { struct Inner<WM: XWindowManager> {
wm: WM, wm: WM,
token: LoopToken, source_maker: Box<FnMut(Rc<RefCell<Inner<WM>>>) -> Result<Source<Signals>, ()>>,
wayland_display: Rc<RefCell<Display>>, wayland_display: Rc<RefCell<Display>>,
instance: Option<XWaylandInstance>, instance: Option<XWaylandInstance>,
log: ::slog::Logger, log: ::slog::Logger,
@ -140,17 +150,11 @@ fn launch<WM: XWindowManager + 'static>(inner: &Rc<RefCell<Inner<WM>>>) -> Resul
.borrow_mut() .borrow_mut()
.create_client(wl_me.into_raw_fd()) .create_client(wl_me.into_raw_fd())
}; };
client.set_user_data(Rc::into_raw(inner.clone()) as *const () as *mut ()); client.data_map().insert_if_missing(|| inner.clone());
client.set_destructor(client_destroy::<WM>); client.add_destructor(client_destroy::<WM>);
// setup the SIGUSR1 handler // setup the SIGUSR1 handler
let my_inner = inner.clone(); let sigusr1_handler = (&mut *guard.source_maker)(inner.clone())?;
let sigusr1_handler = guard
.token
.add_signal_event_source(signal::Signal::SIGUSR1, move |_, ()| {
xwayland_ready(&my_inner)
})
.map_err(|_| ())?;
// all is ready, we can do the fork dance // all is ready, we can do the fork dance
let child_pid = match fork() { let child_pid = match fork() {
@ -242,8 +246,8 @@ impl<WM: XWindowManager> Inner<WM> {
} }
} }
fn client_destroy<WM: XWindowManager + 'static>(data: *mut ()) { fn client_destroy<WM: XWindowManager + 'static>(map: &::wayland_server::UserDataMap) {
let inner = unsafe { Rc::from_raw(data as *const () as *const RefCell<Inner<WM>>) }; let inner = map.get::<Rc<RefCell<Inner<WM>>>>().unwrap();
// shutdown the server // shutdown the server
let started_at = inner.borrow().instance.as_ref().map(|i| i.started_at); let started_at = inner.borrow().instance.as_ref().map(|i| i.started_at);