From a768e298f2b48cd0f5b225d7336f2a174fc6bc68 Mon Sep 17 00:00:00 2001 From: Drakulix Date: Wed, 24 Jan 2018 01:30:06 +0100 Subject: [PATCH] Add auto backend --- src/backend/session/auto.rs | 198 ++++++++++++++++++++++++++++++++++++ src/backend/session/mod.rs | 1 + 2 files changed, 199 insertions(+) create mode 100644 src/backend/session/auto.rs diff --git a/src/backend/session/auto.rs b/src/backend/session/auto.rs new file mode 100644 index 0000000..3540952 --- /dev/null +++ b/src/backend/session/auto.rs @@ -0,0 +1,198 @@ +use std::io::{Result as IoResult}; +use std::rc::Rc; +use std::cell::RefCell; +use std::os::unix::io::RawFd; +use std::path::Path; +use nix::fcntl::OFlag; +use wayland_server::{EventLoopHandle}; +use wayland_server::sources::SignalEventSource; + +use super::{Session, SessionNotifier, SessionObserver, AsErrno}; +#[cfg(feature = "backend_session_logind")] +use super::logind::{self, LogindSession, LogindSessionNotifier, BoundLogindSession, logind_session_bind}; +use super::direct::{self, DirectSession, DirectSessionNotifier, direct_session_bind}; + +#[derive(Clone)] +pub enum AutoSession { + #[cfg(feature = "backend_session_logind")] + Logind(LogindSession), + Direct(Rc>), +} + +pub enum AutoSessionNotifier { + #[cfg(feature = "backend_session_logind")] + Logind(LogindSessionNotifier), + Direct(DirectSessionNotifier), +} + +pub enum BoundAutoSession { + #[cfg(feature = "backend_session_logind")] + Logind(BoundLogindSession), + Direct(SignalEventSource), +} + +#[derive(PartialEq, Eq)] +pub struct AutoId(AutoIdInternal); +#[derive(PartialEq, Eq)] +enum AutoIdInternal { + #[cfg(feature = "backend_session_logind")] + Logind(logind::Id), + Direct(direct::Id), +} + +impl AutoSession { + #[cfg(feature = "backend_session_logind")] + pub fn new(logger: L) -> Option<(AutoSession, AutoSessionNotifier)> + where L: Into> + { + let logger = ::slog_or_stdlog(logger) + .new(o!("smithay_module" => "backend_session_auto", "session_type" => "auto")); + + info!(logger, "Trying to create logind session"); + match LogindSession::new(logger.clone()) { + Ok((session, notifier)) => Some((AutoSession::Logind(session), AutoSessionNotifier::Logind(notifier))), + Err(err) => { + warn!(logger, "Failed to create logind session: {}", err); + info!(logger, "Falling back to create tty session"); + match DirectSession::new(None, logger.clone()) { + Ok((session, notifier)) => Some((AutoSession::Direct(Rc::new(RefCell::new(session))), AutoSessionNotifier::Direct(notifier))), + Err(err) => { + warn!(logger, "Failed to create direct session: {}", err); + error!(logger, "Could not create any session, possibilities exhausted"); + None + } + } + } + } + } + + #[cfg(not(feature = "backend_session_logind"))] + pub fn new(logger: L) -> Option<(AutoSession, AutoSessionNotifier)> + where L: Into> + { + let logger = ::slog_or_stdlog(logger) + .new(o!("smithay_module" => "backend_session_auto", "session_type" => "auto")); + + info!(logger, "Trying to create tty session"); + match DirectSession::new(None, logger.clone()) { + Ok((session, notifier)) => Some((AutoSession::Direct(Rc::new(RefCell::new(session))), AutoSessionNotifier::Direct(notifier))), + Err(err) => { + warn!(logger, "Failed to create direct session: {}", err); + error!(logger, "Could not create any session, possibilities exhausted"); + None + } + } + } +} + +pub fn auto_session_bind(notifier: AutoSessionNotifier, evlh: &mut EventLoopHandle) -> IoResult { + Ok(match notifier { + #[cfg(feature = "backend_session_logind")] + AutoSessionNotifier::Logind(logind) => BoundAutoSession::Logind(logind_session_bind(logind, evlh)?), + AutoSessionNotifier::Direct(direct) => BoundAutoSession::Direct(direct_session_bind(direct, evlh)?), + }) +} + +impl Session for AutoSession { + type Error = Error; + + fn open(&mut self, path: &Path, flags: OFlag) -> Result { + match self { + #[cfg(feature = "backend_session_logind")] + &mut AutoSession::Logind(ref mut logind) => logind.open(path, flags).map_err(|e| e.into()), + &mut AutoSession::Direct(ref mut direct) => direct.open(path, flags).map_err(|e| e.into()), + } + } + fn close(&mut self, fd: RawFd) -> Result<()> { + match self { + #[cfg(feature = "backend_session_logind")] + &mut AutoSession::Logind(ref mut logind) => logind.close(fd).map_err(|e| e.into()), + &mut AutoSession::Direct(ref mut direct) => direct.close(fd).map_err(|e| e.into()), + } + } + + fn change_vt(&mut self, vt: i32) -> Result<()> { + match self { + #[cfg(feature = "backend_session_logind")] + &mut AutoSession::Logind(ref mut logind) => logind.change_vt(vt).map_err(|e| e.into()), + &mut AutoSession::Direct(ref mut direct) => direct.change_vt(vt).map_err(|e| e.into()), + } + } + + fn is_active(&self) -> bool { + match self { + #[cfg(feature = "backend_session_logind")] + &AutoSession::Logind(ref logind) => logind.is_active(), + &AutoSession::Direct(ref direct) => direct.is_active(), + } + } + fn seat(&self) -> String { + match self { + #[cfg(feature = "backend_session_logind")] + &AutoSession::Logind(ref logind) => logind.seat(), + &AutoSession::Direct(ref direct) => direct.seat(), + } + } +} + +impl SessionNotifier for AutoSessionNotifier { + type Id = AutoId; + + fn register(&mut self, signal: S) -> Self::Id { + match self { + #[cfg(feature = "backend_session_logind")] + &mut AutoSessionNotifier::Logind(ref mut logind) => AutoId(AutoIdInternal::Logind(logind.register(signal))), + &mut AutoSessionNotifier::Direct(ref mut direct) => AutoId(AutoIdInternal::Direct(direct.register(signal))), + } + } + fn unregister(&mut self, signal: Self::Id) { + match (self, signal) { + #[cfg(feature = "backend_session_logind")] + (&mut AutoSessionNotifier::Logind(ref mut logind), AutoId(AutoIdInternal::Logind(signal))) => logind.unregister(signal), + (&mut AutoSessionNotifier::Direct(ref mut direct), AutoId(AutoIdInternal::Direct(signal))) => direct.unregister(signal), + _ => unreachable!(), + } + } + + fn is_active(&self) -> bool { + match self { + #[cfg(feature = "backend_session_logind")] + &AutoSessionNotifier::Logind(ref logind) => logind.is_active(), + &AutoSessionNotifier::Direct(ref direct) => direct.is_active(), + } + } + fn seat(&self) -> &str { + match self { + #[cfg(feature = "backend_session_logind")] + &AutoSessionNotifier::Logind(ref logind) => logind.seat(), + &AutoSessionNotifier::Direct(ref direct) => direct.seat(), + } + } +} + +impl BoundAutoSession { + pub fn remove(self) -> AutoSessionNotifier { + match self { + #[cfg(feature = "backend_session_logind")] + BoundAutoSession::Logind(logind) => AutoSessionNotifier::Logind(logind.close()), + BoundAutoSession::Direct(source) => AutoSessionNotifier::Direct(source.remove()), + } + } +} + +error_chain! { + links { + Logind(logind::Error, logind::ErrorKind) #[cfg(feature = "backend_session_logind")]; + } + + foreign_links { + Direct(::nix::Error); + } +} + +impl AsErrno for Error { + fn as_errno(&self) -> Option { + //TODO figure this out, I don't see a way.. + None + } +} diff --git a/src/backend/session/mod.rs b/src/backend/session/mod.rs index 3fd8ff8..d0a3320 100644 --- a/src/backend/session/mod.rs +++ b/src/backend/session/mod.rs @@ -172,6 +172,7 @@ impl AsErrno for () { } } +pub mod auto; pub mod direct; mod dbus; pub use self::dbus::*;