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]
wayland-server = "0.20.0"
wayland-sys = "0.20.0"
nix = "0.9.0"
nix = "0.10.0"
xkbcommon = "0.2.1"
tempfile = "2.1.5"
slog = { version = "2.1.1" }

View File

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

View File

@ -39,8 +39,9 @@ use std::io::Error as IoError;
use std::os::unix::io::RawFd;
use std::path::Path;
use std::rc::Rc;
use wayland_server::EventLoopHandle;
use wayland_server::sources::{EventSource, SignalEventSource};
use wayland_server::LoopToken;
use wayland_server::commons::downcast_impl;
use wayland_server::sources::{SignalEvent, Source};
/// `Session` using the best available inteface
#[derive(Clone)]
@ -71,7 +72,7 @@ pub enum BoundAutoSession {
#[cfg(feature = "backend_session_logind")]
Logind(BoundLogindSession),
/// Bound direct / tty session
Direct(SignalEventSource<DirectSessionNotifier>),
Direct(Source<SignalEvent>),
}
/// 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
/// session state and call it's `SessionObservers`.
pub fn auto_session_bind(
notifier: AutoSessionNotifier, evlh: &mut EventLoopHandle
notifier: AutoSessionNotifier,
token: &LoopToken,
) -> ::std::result::Result<BoundAutoSession, (IoError, AutoSessionNotifier)> {
Ok(match notifier {
#[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)))?),
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)))?),
})
}
@ -210,7 +212,8 @@ impl SessionNotifier for AutoSessionNotifier {
type Id = AutoId;
fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>(
&mut self, signal: &mut A
&mut self,
signal: &mut A,
) -> Self::Id {
match self {
#[cfg(feature = "backend_session_logind")]
@ -257,7 +260,9 @@ impl BoundAutoSession {
match self {
#[cfg(feature = "backend_session_logind")]
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::sync::atomic::{AtomicBool, Ordering};
use systemd::login;
use wayland_server::EventLoopHandle;
use wayland_server::sources::{EventSource, FdEventSource, FdEventSourceImpl, FdInterest};
use wayland_server::LoopToken;
use wayland_server::sources::{FdEvent, FdInterest, Source};
struct LogindSessionImpl {
conn: RefCell<Connection>,
@ -62,6 +62,7 @@ pub struct LogindSession {
}
/// `SessionNotifier` via the logind dbus interface
#[derive(Clone)]
pub struct LogindSessionNotifier {
internal: Rc<LogindSessionImpl>,
}
@ -186,7 +187,11 @@ impl LogindSessionNotifier {
impl LogindSessionImpl {
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>>,
) -> Result<Message>
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 {
let message = if let ConnectionItem::Signal(ref s) = item {
s
@ -246,7 +251,7 @@ impl LogindSessionImpl {
//So lets just put it to sleep.. forever
for signal in &mut *self.signals.borrow_mut() {
if let &mut Some(ref mut signal) = signal {
signal.pause(evlh, None);
signal.pause(None);
}
}
self.active.store(false, Ordering::SeqCst);
@ -263,7 +268,7 @@ impl LogindSessionImpl {
);
for signal in &mut *self.signals.borrow_mut() {
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),
@ -289,7 +294,7 @@ impl LogindSessionImpl {
debug!(self.logger, "Reactivating device ({},{})", major, minor);
for signal in &mut *self.signals.borrow_mut() {
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;
fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>(
&mut self, signal: &mut A
&mut self,
signal: &mut A,
) -> Self::Id {
self.internal
.signals
@ -422,7 +428,7 @@ impl SessionNotifier for LogindSessionNotifier {
pub struct BoundLogindSession {
notifier: LogindSessionNotifier,
_watches: Vec<Watch>,
sources: Vec<FdEventSource<Rc<LogindSessionImpl>>>,
sources: Vec<Source<FdEvent>>,
}
/// 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
/// session state and call it's `SessionObservers`.
pub fn logind_session_bind(
notifier: LogindSessionNotifier, evlh: &mut EventLoopHandle
notifier: LogindSessionNotifier,
token: &LoopToken,
) -> ::std::result::Result<BoundLogindSession, (IoError, LogindSessionNotifier)> {
let watches = notifier.internal.conn.borrow().watch_fds();
@ -443,11 +450,10 @@ pub fn logind_session_bind(
let mut interest = FdInterest::empty();
interest.set(FdInterest::READ, watch.readable());
interest.set(FdInterest::WRITE, watch.writable());
evlh.add_fd_event_source(
token.add_fd_event_source(
watch.fd(),
fd_event_source_implementation(),
notifier.internal.clone(),
interest,
notifier.clone(),
)
})
.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>> {
FdEventSourceImpl {
ready: |evlh, session, fd, interest| {
let conn = session.conn.borrow();
impl Implementation<(), FdEvent> for LogindSessionNotifier {
fn receive(&mut self, event: FdEvent, (): ()) {
match event {
FdEvent::Ready { fd, mask } => {
let conn = self.internal.conn.borrow();
let items = conn.watch_handle(
fd,
match interest {
match mask {
x if x.contains(FdInterest::READ) && x.contains(FdInterest::WRITE) => {
WatchEvent::Readable as u32 | WatchEvent::Writable as u32
}
@ -507,20 +514,24 @@ fn fd_event_source_implementation() -> FdEventSourceImpl<Rc<LogindSessionImpl>>
_ => return,
},
);
if let Err(err) = session.handle_signals(evlh, items) {
error!(session.logger, "Error handling dbus signals: {}", err);
if let Err(err) = self.internal.handle_signals(items) {
error!(self.internal.logger, "Error handling dbus signals: {}", err);
}
},
error: |evlh, session, fd, error| {
warn!(session.logger, "Error on dbus connection: {:?}", error);
}
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 = session.conn.borrow();
let conn = self.internal.conn.borrow();
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);
}
},
}
}
}
}

View File

@ -59,8 +59,9 @@ use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
#[cfg(feature = "backend_session_udev")]
use udev::Context;
use wayland_server::EventLoopHandle;
use wayland_server::sources::SignalEventSource;
use wayland_server::LoopToken;
use wayland_server::commons::Implementation;
use wayland_server::sources::{SignalEvent, Source};
#[allow(dead_code)]
mod tty {
@ -171,8 +172,11 @@ impl DirectSession {
.new(o!("smithay_module" => "backend_session", "session_type" => "direct/vt"));
let fd = tty.map(|path| {
open(path, fcntl::O_RDWR | fcntl::O_CLOEXEC, Mode::empty())
.chain_err(|| ErrorKind::FailedToOpenTTY(String::from(path.to_string_lossy())))
open(
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>"))))?;
let active = Arc::new(AtomicBool::new(true));
@ -345,7 +349,8 @@ impl SessionNotifier for DirectSessionNotifier {
type Id = Id;
fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>(
&mut self, signal: &mut A
&mut self,
signal: &mut A,
) -> Self::Id {
self.signals.push(Some(Box::new(signal.observer())));
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`.
///
/// 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
/// session state and call it's `SessionObservers`.
pub fn direct_session_bind(
notifier: DirectSessionNotifier, evlh: &mut EventLoopHandle
) -> ::std::result::Result<SignalEventSource<DirectSessionNotifier>, (IoError, DirectSessionNotifier)> {
notifier: DirectSessionNotifier,
token: &LoopToken,
) -> ::std::result::Result<Source<SignalEvent>, (IoError, DirectSessionNotifier)> {
let signal = notifier.signal;
evlh.add_signal_event_source(
|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,
)
token.add_signal_event_source(signal, notifier)
}
error_chain! {

View File

@ -16,7 +16,6 @@ use std::os::unix::io::RawFd;
use std::path::Path;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use wayland_server::EventLoopHandle;
/// 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
/// (major, minor) is provided. All observers not using the specified device should
/// 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
///
/// 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
/// should not be used anymore and be closed. All observers not using the specified device should
/// 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 () {

View File

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