libseat support (#292)
This commit is contained in:
parent
e9aef7caad
commit
f9f77288c8
|
@ -15,6 +15,7 @@ bitflags = "1"
|
||||||
calloop = "0.8.0"
|
calloop = "0.8.0"
|
||||||
cgmath = "0.18.0"
|
cgmath = "0.18.0"
|
||||||
dbus = { version = "0.9.0", optional = true }
|
dbus = { version = "0.9.0", optional = true }
|
||||||
|
libseat= { version = "0.1.1", optional = true }
|
||||||
drm-fourcc = "^2.1.1"
|
drm-fourcc = "^2.1.1"
|
||||||
drm = { version = "0.4.0", optional = true }
|
drm = { version = "0.4.0", optional = true }
|
||||||
drm-ffi = { version = "0.1.0", optional = true }
|
drm-ffi = { version = "0.1.0", optional = true }
|
||||||
|
@ -57,6 +58,7 @@ backend_session = []
|
||||||
backend_udev = ["udev"]
|
backend_udev = ["udev"]
|
||||||
backend_session_logind = ["dbus", "backend_session", "pkg-config"]
|
backend_session_logind = ["dbus", "backend_session", "pkg-config"]
|
||||||
backend_session_elogind = ["backend_session_logind"]
|
backend_session_elogind = ["backend_session_logind"]
|
||||||
|
backend_session_libseat = ["libseat"]
|
||||||
renderer_gl = ["gl_generator", "backend_egl"]
|
renderer_gl = ["gl_generator", "backend_egl"]
|
||||||
use_system_lib = ["wayland_frontend", "wayland-sys", "wayland-server/use_system_lib"]
|
use_system_lib = ["wayland_frontend", "wayland-sys", "wayland-server/use_system_lib"]
|
||||||
wayland_frontend = ["wayland-server", "wayland-commons", "wayland-protocols", "tempfile"]
|
wayland_frontend = ["wayland-server", "wayland-commons", "wayland-protocols", "tempfile"]
|
||||||
|
|
|
@ -37,5 +37,6 @@ winit = [ "smithay/backend_winit" ]
|
||||||
udev = [ "smithay/backend_libinput", "smithay/backend_udev", "smithay/backend_drm", "smithay/backend_gbm", "smithay/backend_egl", "smithay/backend_session", "input", "image", "smithay/image"]
|
udev = [ "smithay/backend_libinput", "smithay/backend_udev", "smithay/backend_drm", "smithay/backend_gbm", "smithay/backend_egl", "smithay/backend_session", "input", "image", "smithay/image"]
|
||||||
logind = [ "smithay/backend_session_logind" ]
|
logind = [ "smithay/backend_session_logind" ]
|
||||||
elogind = ["logind", "smithay/backend_session_elogind" ]
|
elogind = ["logind", "smithay/backend_session_elogind" ]
|
||||||
|
libseat = ["smithay/backend_session_libseat" ]
|
||||||
xwayland = [ "smithay/xwayland", "x11rb" ]
|
xwayland = [ "smithay/xwayland", "x11rb" ]
|
||||||
test_all_features = ["default"]
|
test_all_features = ["default"]
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
use std::env::var;
|
use std::env::var;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
if var("CARGO_FEATURE_LOGIND").ok().is_none() {
|
if var("CARGO_FEATURE_LOGIND").ok().is_none() && var("CARGO_FEATURE_LIBSEAT").ok().is_none() {
|
||||||
println!("cargo:warning=You are compiling anvil without logind support.");
|
println!("cargo:warning=You are compiling anvil without logind/libseat support.");
|
||||||
println!("cargo:warning=This means that you'll likely need to run it as root if you want to launch it from a tty.");
|
println!("cargo:warning=This means that you'll likely need to run it as root if you want to launch it from a tty.");
|
||||||
println!("cargo:warning=To enable logind support add `--feature logind` to your cargo invocation:");
|
println!("cargo:warning=To enable logind support add `--feature logind` to your cargo invocation.");
|
||||||
println!("cargo:warning=$ cd anvil; cargo run --feature logind");
|
println!("cargo:warning=$ cd anvil; cargo run --feature logind");
|
||||||
|
println!("cargo:warning=To enable libseat support add `--feature libseat` to your cargo invocation.");
|
||||||
|
println!("cargo:warning=$ cd anvil; cargo run --feature libseat");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
//! The [`AutoSessionNotifier`] is to be inserted into
|
//! The [`AutoSessionNotifier`] is to be inserted into
|
||||||
//! a calloop event source to have its events processed.
|
//! a calloop event source to have its events processed.
|
||||||
|
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
use super::libseat::{LibSeatSession, LibSeatSessionNotifier};
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
use super::logind::{self, LogindSession, LogindSessionNotifier};
|
use super::logind::{self, LogindSession, LogindSessionNotifier};
|
||||||
use super::{
|
use super::{
|
||||||
|
@ -51,6 +53,9 @@ pub enum AutoSession {
|
||||||
Logind(LogindSession),
|
Logind(LogindSession),
|
||||||
/// Direct / tty session
|
/// Direct / tty session
|
||||||
Direct(Rc<RefCell<DirectSession>>),
|
Direct(Rc<RefCell<DirectSession>>),
|
||||||
|
/// LibSeat session
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
LibSeat(LibSeatSession),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Notifier using the best available interface
|
/// Notifier using the best available interface
|
||||||
|
@ -61,11 +66,13 @@ pub enum AutoSessionNotifier {
|
||||||
Logind(LogindSessionNotifier),
|
Logind(LogindSessionNotifier),
|
||||||
/// Direct / tty session notifier
|
/// Direct / tty session notifier
|
||||||
Direct(DirectSessionNotifier),
|
Direct(DirectSessionNotifier),
|
||||||
|
/// LibSeat session notifier
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
LibSeat(LibSeatSessionNotifier),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AutoSession {
|
impl AutoSession {
|
||||||
/// Tries to create a new session via the best available interface.
|
/// Tries to create a new session via the best available interface.
|
||||||
#[cfg(feature = "backend_session_logind")]
|
|
||||||
pub fn new<L>(logger: L) -> Option<(AutoSession, AutoSessionNotifier)>
|
pub fn new<L>(logger: L) -> Option<(AutoSession, AutoSessionNotifier)>
|
||||||
where
|
where
|
||||||
L: Into<Option<::slog::Logger>>,
|
L: Into<Option<::slog::Logger>>,
|
||||||
|
@ -73,52 +80,54 @@ impl AutoSession {
|
||||||
let logger = crate::slog_or_fallback(logger)
|
let logger = crate::slog_or_fallback(logger)
|
||||||
.new(o!("smithay_module" => "backend_session_auto", "session_type" => "auto"));
|
.new(o!("smithay_module" => "backend_session_auto", "session_type" => "auto"));
|
||||||
|
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
{
|
||||||
|
info!(logger, "Trying to create libseat session");
|
||||||
|
match LibSeatSession::new(logger.clone()) {
|
||||||
|
Ok((sesstion, notifier)) => {
|
||||||
|
return Some((
|
||||||
|
AutoSession::LibSeat(sesstion),
|
||||||
|
AutoSessionNotifier::LibSeat(notifier),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
warn!(logger, "Failed to create libseat session: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "backend_session_logind")]
|
||||||
|
{
|
||||||
info!(logger, "Trying to create logind session");
|
info!(logger, "Trying to create logind session");
|
||||||
match LogindSession::new(logger.clone()) {
|
match LogindSession::new(logger.clone()) {
|
||||||
Ok((session, notifier)) => Some((
|
Ok((session, notifier)) => {
|
||||||
|
return Some((
|
||||||
AutoSession::Logind(session),
|
AutoSession::Logind(session),
|
||||||
AutoSessionNotifier::Logind(notifier),
|
AutoSessionNotifier::Logind(notifier),
|
||||||
)),
|
))
|
||||||
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(logger, "Failed to create logind session: {}", 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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tries to create a new session via the best available interface.
|
|
||||||
#[cfg(not(feature = "backend_session_logind"))]
|
|
||||||
pub fn new<L>(logger: L) -> Option<(AutoSession, AutoSessionNotifier)>
|
|
||||||
where
|
|
||||||
L: Into<Option<::slog::Logger>>,
|
|
||||||
{
|
|
||||||
let logger = crate::slog_or_fallback(logger)
|
|
||||||
.new(o!("smithay_module" => "backend_session_auto", "session_type" => "auto"));
|
|
||||||
|
|
||||||
info!(logger, "Trying to create tty session");
|
info!(logger, "Trying to create tty session");
|
||||||
match DirectSession::new(None, logger.clone()) {
|
match DirectSession::new(None, logger.clone()) {
|
||||||
Ok((session, notifier)) => Some((
|
Ok((session, notifier)) => {
|
||||||
|
return Some((
|
||||||
AutoSession::Direct(Rc::new(RefCell::new(session))),
|
AutoSession::Direct(Rc::new(RefCell::new(session))),
|
||||||
AutoSessionNotifier::Direct(notifier),
|
AutoSessionNotifier::Direct(notifier),
|
||||||
)),
|
))
|
||||||
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(logger, "Failed to create direct session: {}", err);
|
warn!(logger, "Failed to create direct session: {}", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
error!(logger, "Could not create any session, possibilities exhausted");
|
error!(logger, "Could not create any session, possibilities exhausted");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Session for AutoSession {
|
impl Session for AutoSession {
|
||||||
|
@ -129,6 +138,8 @@ impl Session for AutoSession {
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
AutoSession::Logind(ref mut logind) => logind.open(path, flags).map_err(|e| e.into()),
|
AutoSession::Logind(ref mut logind) => logind.open(path, flags).map_err(|e| e.into()),
|
||||||
AutoSession::Direct(ref mut direct) => direct.open(path, flags).map_err(|e| e.into()),
|
AutoSession::Direct(ref mut direct) => direct.open(path, flags).map_err(|e| e.into()),
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
AutoSession::LibSeat(ref mut logind) => logind.open(path, flags).map_err(|e| e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn close(&mut self, fd: RawFd) -> Result<(), Error> {
|
fn close(&mut self, fd: RawFd) -> Result<(), Error> {
|
||||||
|
@ -136,6 +147,8 @@ impl Session for AutoSession {
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
AutoSession::Logind(ref mut logind) => logind.close(fd).map_err(|e| e.into()),
|
AutoSession::Logind(ref mut logind) => logind.close(fd).map_err(|e| e.into()),
|
||||||
AutoSession::Direct(ref mut direct) => direct.close(fd).map_err(|e| e.into()),
|
AutoSession::Direct(ref mut direct) => direct.close(fd).map_err(|e| e.into()),
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
AutoSession::LibSeat(ref mut direct) => direct.close(fd).map_err(|e| e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,6 +157,8 @@ impl Session for AutoSession {
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
AutoSession::Logind(ref mut logind) => logind.change_vt(vt).map_err(|e| e.into()),
|
AutoSession::Logind(ref mut logind) => logind.change_vt(vt).map_err(|e| e.into()),
|
||||||
AutoSession::Direct(ref mut direct) => direct.change_vt(vt).map_err(|e| e.into()),
|
AutoSession::Direct(ref mut direct) => direct.change_vt(vt).map_err(|e| e.into()),
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
AutoSession::LibSeat(ref mut direct) => direct.change_vt(vt).map_err(|e| e.into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +167,8 @@ impl Session for AutoSession {
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
AutoSession::Logind(ref logind) => logind.is_active(),
|
AutoSession::Logind(ref logind) => logind.is_active(),
|
||||||
AutoSession::Direct(ref direct) => direct.is_active(),
|
AutoSession::Direct(ref direct) => direct.is_active(),
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
AutoSession::LibSeat(ref direct) => direct.is_active(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn seat(&self) -> String {
|
fn seat(&self) -> String {
|
||||||
|
@ -159,6 +176,8 @@ impl Session for AutoSession {
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
AutoSession::Logind(ref logind) => logind.seat(),
|
AutoSession::Logind(ref logind) => logind.seat(),
|
||||||
AutoSession::Direct(ref direct) => direct.seat(),
|
AutoSession::Direct(ref direct) => direct.seat(),
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
AutoSession::LibSeat(ref direct) => direct.seat(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,6 +191,8 @@ impl AutoSessionNotifier {
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
AutoSessionNotifier::Logind(ref logind) => logind.signaler(),
|
AutoSessionNotifier::Logind(ref logind) => logind.signaler(),
|
||||||
AutoSessionNotifier::Direct(ref direct) => direct.signaler(),
|
AutoSessionNotifier::Direct(ref direct) => direct.signaler(),
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
AutoSessionNotifier::LibSeat(ref direct) => direct.signaler(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,6 +210,8 @@ impl EventSource for AutoSessionNotifier {
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
AutoSessionNotifier::Logind(s) => s.process_events(readiness, token, callback),
|
AutoSessionNotifier::Logind(s) => s.process_events(readiness, token, callback),
|
||||||
AutoSessionNotifier::Direct(s) => s.process_events(readiness, token, callback),
|
AutoSessionNotifier::Direct(s) => s.process_events(readiness, token, callback),
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
AutoSessionNotifier::LibSeat(s) => s.process_events(readiness, token, callback),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,6 +220,8 @@ impl EventSource for AutoSessionNotifier {
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
AutoSessionNotifier::Logind(s) => EventSource::register(s, poll, token),
|
AutoSessionNotifier::Logind(s) => EventSource::register(s, poll, token),
|
||||||
AutoSessionNotifier::Direct(s) => EventSource::register(s, poll, token),
|
AutoSessionNotifier::Direct(s) => EventSource::register(s, poll, token),
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
AutoSessionNotifier::LibSeat(s) => EventSource::register(s, poll, token),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,6 +230,8 @@ impl EventSource for AutoSessionNotifier {
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
AutoSessionNotifier::Logind(s) => EventSource::reregister(s, poll, token),
|
AutoSessionNotifier::Logind(s) => EventSource::reregister(s, poll, token),
|
||||||
AutoSessionNotifier::Direct(s) => EventSource::reregister(s, poll, token),
|
AutoSessionNotifier::Direct(s) => EventSource::reregister(s, poll, token),
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
AutoSessionNotifier::LibSeat(s) => EventSource::reregister(s, poll, token),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,6 +240,8 @@ impl EventSource for AutoSessionNotifier {
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
AutoSessionNotifier::Logind(s) => EventSource::unregister(s, poll),
|
AutoSessionNotifier::Logind(s) => EventSource::unregister(s, poll),
|
||||||
AutoSessionNotifier::Direct(s) => EventSource::unregister(s, poll),
|
AutoSessionNotifier::Direct(s) => EventSource::unregister(s, poll),
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
AutoSessionNotifier::LibSeat(s) => EventSource::unregister(s, poll),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,6 +256,11 @@ pub enum Error {
|
||||||
/// Direct session error
|
/// Direct session error
|
||||||
#[error("Direct session error: {0}")]
|
#[error("Direct session error: {0}")]
|
||||||
Direct(#[from] direct::Error),
|
Direct(#[from] direct::Error),
|
||||||
|
/// LibSeat session error
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
#[error("LibSeat session error: {0}")]
|
||||||
|
LibSeat(#[from] super::libseat::Error),
|
||||||
|
|
||||||
/// Nix error
|
/// Nix error
|
||||||
#[error("Nix error: {0}")]
|
#[error("Nix error: {0}")]
|
||||||
Nix(#[from] nix::Error),
|
Nix(#[from] nix::Error),
|
||||||
|
|
|
@ -0,0 +1,281 @@
|
||||||
|
//!
|
||||||
|
//! Implementation of the [`Session`](::backend::session::Session) trait through the libseat.
|
||||||
|
//!
|
||||||
|
//! This requires libseat to be available on the system.
|
||||||
|
|
||||||
|
use libseat::{Seat, SeatEvent};
|
||||||
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
collections::HashMap,
|
||||||
|
os::unix::io::RawFd,
|
||||||
|
path::Path,
|
||||||
|
rc::{Rc, Weak},
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use nix::{errno::Errno, fcntl::OFlag, unistd::close};
|
||||||
|
|
||||||
|
use calloop::{EventSource, Poll, Readiness, Token};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
backend::session::{AsErrno, Session, Signal as SessionSignal},
|
||||||
|
signaling::Signaler,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct LibSeatSessionImpl {
|
||||||
|
seat: RefCell<Seat>,
|
||||||
|
active: Arc<AtomicBool>,
|
||||||
|
devices: RefCell<HashMap<RawFd, i32>>,
|
||||||
|
logger: ::slog::Logger,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for LibSeatSessionImpl {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
debug!(self.logger, "Closing seat")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [`Session`] via the libseat
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct LibSeatSession {
|
||||||
|
internal: Weak<LibSeatSessionImpl>,
|
||||||
|
seat_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [`SessionNotifier`] via the libseat
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LibSeatSessionNotifier {
|
||||||
|
internal: Rc<LibSeatSessionImpl>,
|
||||||
|
signaler: Signaler<SessionSignal>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LibSeatSession {
|
||||||
|
/// Tries to create a new session via libseat.
|
||||||
|
pub fn new<L>(logger: L) -> Result<(LibSeatSession, LibSeatSessionNotifier), Error>
|
||||||
|
where
|
||||||
|
L: Into<Option<::slog::Logger>>,
|
||||||
|
{
|
||||||
|
let logger = crate::slog_or_fallback(logger)
|
||||||
|
.new(o!("smithay_module" => "backend_session", "session_type" => "libseat"));
|
||||||
|
|
||||||
|
let active = Arc::new(AtomicBool::new(false));
|
||||||
|
let signaler = Signaler::new();
|
||||||
|
|
||||||
|
let seat = {
|
||||||
|
let log = logger.clone();
|
||||||
|
let active = active.clone();
|
||||||
|
let signaler = signaler.clone();
|
||||||
|
|
||||||
|
Seat::open(
|
||||||
|
move |seat, event| match event {
|
||||||
|
SeatEvent::Enable => {
|
||||||
|
debug!(log, "Enable callback called");
|
||||||
|
active.store(true, Ordering::SeqCst);
|
||||||
|
signaler.signal(SessionSignal::ActivateSession);
|
||||||
|
}
|
||||||
|
SeatEvent::Disable => {
|
||||||
|
debug!(log, "Disable callback called");
|
||||||
|
active.store(false, Ordering::SeqCst);
|
||||||
|
signaler.signal(SessionSignal::PauseSession);
|
||||||
|
seat.disable().unwrap();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
logger.clone(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
seat.map(|mut seat| {
|
||||||
|
// In some cases enable_seat event is avalible right after startup
|
||||||
|
// so, we can dispatch it
|
||||||
|
seat.dispatch(0).unwrap();
|
||||||
|
|
||||||
|
let seat_name = seat.name().to_owned();
|
||||||
|
|
||||||
|
let internal = Rc::new(LibSeatSessionImpl {
|
||||||
|
seat: RefCell::new(seat),
|
||||||
|
active,
|
||||||
|
devices: RefCell::new(HashMap::new()),
|
||||||
|
logger,
|
||||||
|
});
|
||||||
|
|
||||||
|
(
|
||||||
|
LibSeatSession {
|
||||||
|
internal: Rc::downgrade(&internal),
|
||||||
|
seat_name,
|
||||||
|
},
|
||||||
|
LibSeatSessionNotifier { internal, signaler },
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.map_err(|err| Error::FailedToOpenSession(Errno::from_i32(err.into())))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Session for LibSeatSession {
|
||||||
|
type Error = Error;
|
||||||
|
|
||||||
|
fn open(&mut self, path: &Path, _flags: OFlag) -> Result<RawFd, Self::Error> {
|
||||||
|
if let Some(session) = self.internal.upgrade() {
|
||||||
|
debug!(session.logger, "Opening device: {:?}", path);
|
||||||
|
|
||||||
|
session
|
||||||
|
.seat
|
||||||
|
.borrow_mut()
|
||||||
|
.open_device(&path)
|
||||||
|
.map(|(id, fd)| {
|
||||||
|
session.devices.borrow_mut().insert(fd, id);
|
||||||
|
fd
|
||||||
|
})
|
||||||
|
.map_err(|err| Error::FailedToOpenDevice(Errno::from_i32(err.into())))
|
||||||
|
} else {
|
||||||
|
Err(Error::SessionLost)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(&mut self, fd: RawFd) -> Result<(), Self::Error> {
|
||||||
|
if let Some(session) = self.internal.upgrade() {
|
||||||
|
debug!(session.logger, "Closing device: {:?}", fd);
|
||||||
|
|
||||||
|
let dev = session.devices.borrow().get(&fd).map(|fd| *fd);
|
||||||
|
|
||||||
|
let out = if let Some(dev) = dev {
|
||||||
|
session
|
||||||
|
.seat
|
||||||
|
.borrow_mut()
|
||||||
|
.close_device(dev)
|
||||||
|
.map_err(|err| Error::FailedToCloseDevice(Errno::from_i32(err.into())))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
};
|
||||||
|
|
||||||
|
close(fd).unwrap();
|
||||||
|
|
||||||
|
out
|
||||||
|
} else {
|
||||||
|
Err(Error::SessionLost)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_vt(&mut self, vt: i32) -> Result<(), Self::Error> {
|
||||||
|
if let Some(session) = self.internal.upgrade() {
|
||||||
|
debug!(session.logger, "Session switch: {:?}", vt);
|
||||||
|
session
|
||||||
|
.seat
|
||||||
|
.borrow_mut()
|
||||||
|
.switch_session(vt)
|
||||||
|
.map_err(|err| Error::FailedToChangeVt(Errno::from_i32(err.into())))
|
||||||
|
} else {
|
||||||
|
Err(Error::SessionLost)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_active(&self) -> bool {
|
||||||
|
if let Some(internal) = self.internal.upgrade() {
|
||||||
|
internal.active.load(Ordering::SeqCst)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn seat(&self) -> String {
|
||||||
|
self.seat_name.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LibSeatSessionNotifier {
|
||||||
|
/// Creates a new session object belonging to this notifier.
|
||||||
|
pub fn session(&self) -> LibSeatSession {
|
||||||
|
LibSeatSession {
|
||||||
|
internal: Rc::downgrade(&self.internal),
|
||||||
|
seat_name: self.internal.seat.borrow_mut().name().to_owned(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a handle to the Signaler of this session.
|
||||||
|
///
|
||||||
|
/// You can use it to listen for signals generated by the session.
|
||||||
|
pub fn signaler(&self) -> Signaler<SessionSignal> {
|
||||||
|
self.signaler.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EventSource for LibSeatSessionNotifier {
|
||||||
|
type Event = ();
|
||||||
|
type Metadata = ();
|
||||||
|
type Ret = ();
|
||||||
|
|
||||||
|
fn process_events<F>(&mut self, _readiness: Readiness, _token: Token, _: F) -> std::io::Result<()>
|
||||||
|
where
|
||||||
|
F: FnMut((), &mut ()),
|
||||||
|
{
|
||||||
|
self.internal.seat.borrow_mut().dispatch(0).unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn register(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> {
|
||||||
|
poll.register(
|
||||||
|
self.internal.seat.borrow_mut().get_fd().unwrap(),
|
||||||
|
calloop::Interest::READ,
|
||||||
|
calloop::Mode::Level,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reregister(&mut self, poll: &mut Poll, token: Token) -> std::io::Result<()> {
|
||||||
|
poll.reregister(
|
||||||
|
self.internal.seat.borrow_mut().get_fd().unwrap(),
|
||||||
|
calloop::Interest::READ,
|
||||||
|
calloop::Mode::Level,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unregister(&mut self, poll: &mut Poll) -> std::io::Result<()> {
|
||||||
|
poll.unregister(self.internal.seat.borrow_mut().get_fd().unwrap())
|
||||||
|
.unwrap();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Errors related to direct/tty sessions
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
/// Failed to open session
|
||||||
|
#[error("Failed to open session: {0}")]
|
||||||
|
FailedToOpenSession(Errno),
|
||||||
|
|
||||||
|
/// Failed to open device
|
||||||
|
#[error("Failed to open device: {0}")]
|
||||||
|
FailedToOpenDevice(Errno),
|
||||||
|
|
||||||
|
/// Failed to close device
|
||||||
|
#[error("Failed to close device: {0}")]
|
||||||
|
FailedToCloseDevice(Errno),
|
||||||
|
|
||||||
|
/// Failed to close device
|
||||||
|
#[error("Failed to change vt: {0}")]
|
||||||
|
FailedToChangeVt(Errno),
|
||||||
|
|
||||||
|
/// Session is already closed,
|
||||||
|
#[error("Session is already closed")]
|
||||||
|
SessionLost,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsErrno for Error {
|
||||||
|
fn as_errno(&self) -> Option<i32> {
|
||||||
|
match self {
|
||||||
|
&Self::FailedToOpenSession(errno)
|
||||||
|
| &Self::FailedToOpenDevice(errno)
|
||||||
|
| &Self::FailedToCloseDevice(errno)
|
||||||
|
| &Self::FailedToChangeVt(errno) => Some(errno as i32),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -161,6 +161,8 @@ impl AsErrno for () {
|
||||||
|
|
||||||
pub mod auto;
|
pub mod auto;
|
||||||
pub mod direct;
|
pub mod direct;
|
||||||
|
#[cfg(feature = "backend_session_libseat")]
|
||||||
|
pub mod libseat;
|
||||||
|
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
mod dbus;
|
mod dbus;
|
||||||
|
|
Loading…
Reference in New Issue