backend.session: migrate to wayland_rs-0.20

This commit is contained in:
Victor Berger 2018-04-17 18:39:07 +02:00
parent 6dfcef1f49
commit b80093ffda
7 changed files with 118 additions and 97 deletions

View File

@ -9,7 +9,7 @@ repository = "https://github.com/Smithay/smithay"
[dependencies] [dependencies]
wayland-server = "0.20.0" wayland-server = "0.20.0"
wayland-sys = "0.20.0" wayland-sys = "0.20.0"
nix = "0.9.0" nix = "0.10.0"
xkbcommon = "0.2.1" xkbcommon = "0.2.1"
tempfile = "2.1.5" tempfile = "2.1.5"
slog = { version = "2.1.1" } slog = { version = "2.1.1" }

View File

@ -23,7 +23,7 @@ pub mod input;
//pub mod drm; //pub mod drm;
//#[cfg(feature = "backend_libinput")] //#[cfg(feature = "backend_libinput")]
//pub mod libinput; //pub mod libinput;
//#[cfg(feature = "backend_session")] #[cfg(feature = "backend_session")]
//pub mod session; pub mod session;
//#[cfg(feature = "backend_udev")] //#[cfg(feature = "backend_udev")]
//pub mod udev; //pub mod udev;

View File

@ -39,8 +39,9 @@ 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::EventLoopHandle; use wayland_server::LoopToken;
use wayland_server::sources::{EventSource, SignalEventSource}; use wayland_server::commons::downcast_impl;
use wayland_server::sources::{SignalEvent, Source};
/// `Session` using the best available inteface /// `Session` using the best available inteface
#[derive(Clone)] #[derive(Clone)]
@ -71,7 +72,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(SignalEventSource<DirectSessionNotifier>), Direct(Source<SignalEvent>),
} }
/// Id's used by the `AutoSessionNotifier` internally. /// Id's used by the `AutoSessionNotifier` internally.
@ -153,13 +154,14 @@ impl AutoSession {
/// 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(
notifier: AutoSessionNotifier, evlh: &mut EventLoopHandle notifier: AutoSessionNotifier,
token: &LoopToken,
) -> ::std::result::Result<BoundAutoSession, (IoError, AutoSessionNotifier)> { ) -> ::std::result::Result<BoundAutoSession, (IoError, AutoSessionNotifier)> {
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, evlh) AutoSessionNotifier::Logind(logind) => BoundAutoSession::Logind(logind_session_bind(logind, token)
.map_err(|(error, notifier)| (error, AutoSessionNotifier::Logind(notifier)))?), .map_err(|(error, notifier)| (error, AutoSessionNotifier::Logind(notifier)))?),
AutoSessionNotifier::Direct(direct) => BoundAutoSession::Direct(direct_session_bind(direct, evlh) AutoSessionNotifier::Direct(direct) => BoundAutoSession::Direct(direct_session_bind(direct, token)
.map_err(|(error, notifier)| (error, AutoSessionNotifier::Direct(notifier)))?), .map_err(|(error, notifier)| (error, AutoSessionNotifier::Direct(notifier)))?),
}) })
} }
@ -210,7 +212,8 @@ impl SessionNotifier for AutoSessionNotifier {
type Id = AutoId; type Id = AutoId;
fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>( fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>(
&mut self, signal: &mut A &mut self,
signal: &mut A,
) -> Self::Id { ) -> Self::Id {
match self { match self {
#[cfg(feature = "backend_session_logind")] #[cfg(feature = "backend_session_logind")]
@ -257,7 +260,9 @@ 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) => AutoSessionNotifier::Direct(source.remove()), BoundAutoSession::Direct(source) => {
AutoSessionNotifier::Direct(*downcast_impl(source.remove()).unwrap_or_else(|_| unreachable!()))
}
} }
} }
} }

View File

@ -42,8 +42,8 @@ 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::EventLoopHandle; use wayland_server::LoopToken;
use wayland_server::sources::{EventSource, FdEventSource, FdEventSourceImpl, FdInterest}; use wayland_server::sources::{FdEvent, FdInterest, Source};
struct LogindSessionImpl { struct LogindSessionImpl {
conn: RefCell<Connection>, conn: RefCell<Connection>,
@ -62,6 +62,7 @@ pub struct LogindSession {
} }
/// `SessionNotifier` via the logind dbus interface /// `SessionNotifier` via the logind dbus interface
#[derive(Clone)]
pub struct LogindSessionNotifier { pub struct LogindSessionNotifier {
internal: Rc<LogindSessionImpl>, internal: Rc<LogindSessionImpl>,
} }
@ -186,7 +187,11 @@ impl LogindSessionNotifier {
impl LogindSessionImpl { impl LogindSessionImpl {
fn blocking_call<'d, 'p, 'i, 'm, D, P, I, M>( fn blocking_call<'d, 'p, 'i, 'm, D, P, I, M>(
conn: &Connection, destination: D, path: P, interface: I, method: M, conn: &Connection,
destination: D,
path: P,
interface: I,
method: M,
arguments: Option<Vec<MessageItem>>, arguments: Option<Vec<MessageItem>>,
) -> Result<Message> ) -> Result<Message>
where where
@ -230,7 +235,7 @@ impl LogindSessionImpl {
} }
} }
fn handle_signals(&self, evlh: &mut EventLoopHandle, signals: ConnectionItems) -> Result<()> { fn handle_signals(&self, signals: ConnectionItems) -> Result<()> {
for item in signals { for item in signals {
let message = if let ConnectionItem::Signal(ref s) = item { let message = if let ConnectionItem::Signal(ref s) = item {
s s
@ -246,7 +251,7 @@ impl LogindSessionImpl {
//So lets just put it to sleep.. forever //So lets just put it to sleep.. forever
for signal in &mut *self.signals.borrow_mut() { for signal in &mut *self.signals.borrow_mut() {
if let &mut Some(ref mut signal) = signal { if let &mut Some(ref mut signal) = signal {
signal.pause(evlh, None); signal.pause(None);
} }
} }
self.active.store(false, Ordering::SeqCst); self.active.store(false, Ordering::SeqCst);
@ -263,7 +268,7 @@ impl LogindSessionImpl {
); );
for signal in &mut *self.signals.borrow_mut() { for signal in &mut *self.signals.borrow_mut() {
if let &mut Some(ref mut signal) = signal { if let &mut Some(ref mut signal) = signal {
signal.pause(evlh, Some((major, minor))); signal.pause(Some((major, minor)));
} }
} }
// the other possible types are "force" or "gone" (unplugged), // the other possible types are "force" or "gone" (unplugged),
@ -289,7 +294,7 @@ impl LogindSessionImpl {
debug!(self.logger, "Reactivating device ({},{})", major, minor); debug!(self.logger, "Reactivating device ({},{})", major, minor);
for signal in &mut *self.signals.borrow_mut() { for signal in &mut *self.signals.borrow_mut() {
if let &mut Some(ref mut signal) = signal { if let &mut Some(ref mut signal) = signal {
signal.activate(evlh, Some((major, minor, Some(fd)))); signal.activate(Some((major, minor, Some(fd))));
} }
} }
} }
@ -393,7 +398,8 @@ impl SessionNotifier for LogindSessionNotifier {
type Id = Id; type Id = Id;
fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>( fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>(
&mut self, signal: &mut A &mut self,
signal: &mut A,
) -> Self::Id { ) -> Self::Id {
self.internal self.internal
.signals .signals
@ -422,7 +428,7 @@ impl SessionNotifier for LogindSessionNotifier {
pub struct BoundLogindSession { pub struct BoundLogindSession {
notifier: LogindSessionNotifier, notifier: LogindSessionNotifier,
_watches: Vec<Watch>, _watches: Vec<Watch>,
sources: Vec<FdEventSource<Rc<LogindSessionImpl>>>, sources: Vec<Source<FdEvent>>,
} }
/// Bind a `LogindSessionNotifier` to an `EventLoop`. /// Bind a `LogindSessionNotifier` to an `EventLoop`.
@ -431,7 +437,8 @@ pub struct BoundLogindSession {
/// 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(
notifier: LogindSessionNotifier, evlh: &mut EventLoopHandle notifier: LogindSessionNotifier,
token: &LoopToken,
) -> ::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();
@ -443,11 +450,10 @@ pub fn logind_session_bind(
let mut interest = FdInterest::empty(); let mut interest = FdInterest::empty();
interest.set(FdInterest::READ, watch.readable()); interest.set(FdInterest::READ, watch.readable());
interest.set(FdInterest::WRITE, watch.writable()); interest.set(FdInterest::WRITE, watch.writable());
evlh.add_fd_event_source( token.add_fd_event_source(
watch.fd(), watch.fd(),
fd_event_source_implementation(),
notifier.internal.clone(),
interest, interest,
notifier.clone(),
) )
}) })
.collect::<::std::result::Result<Vec<FdEventSource<Rc<LogindSessionImpl>>>, (IoError, _)>>() .collect::<::std::result::Result<Vec<FdEventSource<Rc<LogindSessionImpl>>>, (IoError, _)>>()
@ -492,13 +498,14 @@ impl Drop for LogindSessionNotifier {
} }
} }
fn fd_event_source_implementation() -> FdEventSourceImpl<Rc<LogindSessionImpl>> { impl Implementation<(), FdEvent> for LogindSessionNotifier {
FdEventSourceImpl { fn receive(&mut self, event: FdEvent, (): ()) {
ready: |evlh, session, fd, interest| { match event {
let conn = session.conn.borrow(); FdEvent::Ready { fd, mask } => {
let conn = self.internal.conn.borrow();
let items = conn.watch_handle( let items = conn.watch_handle(
fd, fd,
match interest { match mask {
x if x.contains(FdInterest::READ) && x.contains(FdInterest::WRITE) => { 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
} }
@ -507,20 +514,24 @@ fn fd_event_source_implementation() -> FdEventSourceImpl<Rc<LogindSessionImpl>>
_ => return, _ => return,
}, },
); );
if let Err(err) = session.handle_signals(evlh, items) { if let Err(err) = self.internal.handle_signals(items) {
error!(session.logger, "Error handling dbus signals: {}", err); error!(self.internal.logger, "Error handling dbus signals: {}", err);
} }
}, }
error: |evlh, session, fd, error| { FdEvent::Error { fd, error } => {
warn!(session.logger, "Error on dbus connection: {:?}", error); warn!(
self.internal.logger,
"Error on dbus connection: {:?}", error
);
// handle the remaining messages, they might contain the SessionRemoved event // handle the remaining messages, they might contain the SessionRemoved event
// in case the server did close the connection. // in case the server did close the connection.
let conn = session.conn.borrow(); let conn = self.internal.conn.borrow();
let items = conn.watch_handle(fd, WatchEvent::Error as u32); let items = conn.watch_handle(fd, WatchEvent::Error as u32);
if let Err(err) = session.handle_signals(evlh, items) { if let Err(err) = self.internal.handle_signals(items) {
error!(session.logger, "Error handling dbus signals: {}", err); error!(session.logger, "Error handling dbus signals: {}", err);
} }
}, }
}
} }
} }

View File

@ -59,8 +59,9 @@ 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::EventLoopHandle; use wayland_server::LoopToken;
use wayland_server::sources::SignalEventSource; use wayland_server::commons::Implementation;
use wayland_server::sources::{SignalEvent, Source};
#[allow(dead_code)] #[allow(dead_code)]
mod tty { mod tty {
@ -171,8 +172,11 @@ impl DirectSession {
.new(o!("smithay_module" => "backend_session", "session_type" => "direct/vt")); .new(o!("smithay_module" => "backend_session", "session_type" => "direct/vt"));
let fd = tty.map(|path| { let fd = tty.map(|path| {
open(path, fcntl::O_RDWR | fcntl::O_CLOEXEC, Mode::empty()) open(
.chain_err(|| ErrorKind::FailedToOpenTTY(String::from(path.to_string_lossy()))) path,
fcntl::OFlag::O_RDWR | fcntl::OFlag::O_CLOEXEC,
Mode::empty(),
).chain_err(|| ErrorKind::FailedToOpenTTY(String::from(path.to_string_lossy())))
}).unwrap_or(dup(0 /*stdin*/).chain_err(|| ErrorKind::FailedToOpenTTY(String::from("<stdin>"))))?; }).unwrap_or(dup(0 /*stdin*/).chain_err(|| ErrorKind::FailedToOpenTTY(String::from("<stdin>"))))?;
let active = Arc::new(AtomicBool::new(true)); let active = Arc::new(AtomicBool::new(true));
@ -345,7 +349,8 @@ impl SessionNotifier for DirectSessionNotifier {
type Id = Id; type Id = Id;
fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>( fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>(
&mut self, signal: &mut A &mut self,
signal: &mut A,
) -> Self::Id { ) -> Self::Id {
self.signals.push(Some(Box::new(signal.observer()))); self.signals.push(Some(Box::new(signal.observer())));
Id(self.signals.len() - 1) Id(self.signals.len() - 1)
@ -362,47 +367,48 @@ impl SessionNotifier for DirectSessionNotifier {
} }
} }
impl Implementation<(), SignalEvent> for DirectSessionNotifier {
fn receive(&mut self, _signal: SignalEvent, (): ()) {
if self.is_active() {
info!(self.logger, "Session shall become inactive.");
for signal in &mut self.signals {
if let &mut Some(ref mut signal) = signal {
signal.pause(None);
}
}
self.active.store(false, Ordering::SeqCst);
unsafe {
tty::vt_rel_disp(self.tty, 1).expect("Unable to release tty lock");
}
debug!(self.logger, "Session is now inactive");
} else {
debug!(self.logger, "Session will become active again");
unsafe {
tty::vt_rel_disp(self.tty, tty::VT_ACKACQ).expect("Unable to acquire tty lock");
}
for signal in &mut self.signals {
if let &mut Some(ref mut signal) = signal {
signal.activate(None);
}
}
self.active.store(true, Ordering::SeqCst);
info!(self.logger, "Session is now active again");
}
}
}
/// 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(
notifier: DirectSessionNotifier, evlh: &mut EventLoopHandle notifier: DirectSessionNotifier,
) -> ::std::result::Result<SignalEventSource<DirectSessionNotifier>, (IoError, DirectSessionNotifier)> { token: &LoopToken,
) -> ::std::result::Result<Source<SignalEvent>, (IoError, DirectSessionNotifier)> {
let signal = notifier.signal; let signal = notifier.signal;
evlh.add_signal_event_source( token.add_signal_event_source(signal, notifier)
|evlh, notifier, _| {
if notifier.is_active() {
info!(notifier.logger, "Session shall become inactive");
for signal in &mut notifier.signals {
if let &mut Some(ref mut signal) = signal {
signal.pause(evlh, None);
}
}
notifier.active.store(false, Ordering::SeqCst);
unsafe {
tty::vt_rel_disp(notifier.tty, 1).expect("Unable to release tty lock");
}
debug!(notifier.logger, "Session is now inactive");
} else {
debug!(notifier.logger, "Session will become active again");
unsafe {
tty::vt_rel_disp(notifier.tty, tty::VT_ACKACQ).expect("Unable to acquire tty lock");
}
for signal in &mut notifier.signals {
if let &mut Some(ref mut signal) = signal {
signal.activate(evlh, None);
}
}
notifier.active.store(true, Ordering::SeqCst);
info!(notifier.logger, "Session is now active again");
}
},
notifier,
signal,
)
} }
error_chain! { error_chain! {

View File

@ -16,7 +16,6 @@ use std::os::unix::io::RawFd;
use std::path::Path; use std::path::Path;
use std::rc::Rc; use std::rc::Rc;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use wayland_server::EventLoopHandle;
/// General session interface. /// General session interface.
/// ///
@ -88,7 +87,7 @@ pub trait SessionObserver {
/// If only a specific device shall be closed a device number in the form of /// If only a specific device shall be closed a device number in the form of
/// (major, minor) is provided. All observers not using the specified device should /// (major, minor) is provided. All observers not using the specified device should
/// ignore the signal in that case. /// ignore the signal in that case.
fn pause(&mut self, evlh: &mut EventLoopHandle, device: Option<(u32, u32)>); fn pause(&mut self, device: Option<(u32, u32)>);
/// Session/Device got active again /// Session/Device got active again
/// ///
/// If only a specific device shall be activated again a device number in the form of /// If only a specific device shall be activated again a device number in the form of
@ -96,7 +95,7 @@ pub trait SessionObserver {
/// the currently open file descriptor of the device with a new one. In that case the old one /// the currently open file descriptor of the device with a new one. In that case the old one
/// should not be used anymore and be closed. All observers not using the specified device should /// should not be used anymore and be closed. All observers not using the specified device should
/// ignore the signal in that case. /// ignore the signal in that case.
fn activate(&mut self, evlh: &mut EventLoopHandle, device: Option<(u32, u32, Option<RawFd>)>); fn activate(&mut self, device: Option<(u32, u32, Option<RawFd>)>);
} }
impl Session for () { impl Session for () {

View File

@ -161,8 +161,8 @@ unsafe fn map(fd: RawFd, size: usize) -> Result<*mut u8, ()> {
let ret = mman::mmap( let ret = mman::mmap(
ptr::null_mut(), ptr::null_mut(),
size, size,
mman::PROT_READ, mman::ProtFlags::PROT_READ,
mman::MAP_SHARED, mman::MapFlags::MAP_SHARED,
fd, fd,
0, 0,
); );
@ -179,8 +179,8 @@ unsafe fn nullify_map(ptr: *mut u8, size: usize) -> Result<(), ()> {
let ret = mman::mmap( let ret = mman::mmap(
ptr as *mut _, ptr as *mut _,
size, size,
mman::PROT_READ, mman::ProtFlags::PROT_READ,
mman::MAP_ANONYMOUS | mman::MAP_PRIVATE | mman::MAP_FIXED, mman::MapFlags::MAP_ANONYMOUS | mman::MapFlags::MAP_PRIVATE | mman::MapFlags::MAP_FIXED,
-1, -1,
0, 0,
); );
@ -191,7 +191,7 @@ unsafe fn place_sigbus_handler() {
// create our sigbus handler // create our sigbus handler
let action = SigAction::new( let action = SigAction::new(
SigHandler::SigAction(sigbus_handler), SigHandler::SigAction(sigbus_handler),
signal::SA_NODEFER, signal::SaFlags::SA_NODEFER,
signal::SigSet::empty(), signal::SigSet::empty(),
); );
match signal::sigaction(Signal::SIGBUS, &action) { match signal::sigaction(Signal::SIGBUS, &action) {