🔒 Repository is read-only – file editing is disabled.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
//! Abstraction of different session APIs.
//!
//! Sessions provide a way for multiple graphical systems to run in parallel by providing
//! mechanisms to switch between and handle device access and permissions for every running
//! instance. They are crucial to allow unprivileged processes to use graphical or input
//! devices.
//!
//! The functions of the provided interfaces lies in two main components: the ability to
//! open privileged devices, and be notified about when the session is paused and resumed
//! (for example when the user switches to an other TTY, or is the computer goes to sleep).
//!
//! ## General use
//!
//! Session handling in Smithay is done through a pair of types that each session provider implements.
//!
//! The first is a handle implementing the [`Session`] trait, which allows you to request the opening
//! of devices, a VT change, or information about the session state.
//!
//! The second is a notifier which informs you when the session is enabled or disabled by the system.
//! This notifier takes the form of a [`calloop`] event source to deliver pause and activation events.
//!
//! ## Available providers
//!
//! This module provides just one session implementation, through [libseat](https://sr.ht/~kennylevinsen/seatd/),
//! gated by the `backend_session_libseat` cargo feature.
//!
//! Other implementations can be provided out-of-tree.
use rustix::fs::OFlags;
use std::{
cell::RefCell,
os::unix::io::OwnedFd,
path::Path,
rc::Rc,
sync::{Arc, Mutex},
};
/// General session interface.
///
/// Provides a way to open and close devices and change the active vt.
pub trait Session {
/// Error type of the implementation
type Error: AsErrno;
/// Opens a device at the given `path` with the given flags.
///
/// Returns a raw file descriptor
fn open(&mut self, path: &Path, flags: OFlags) -> Result<OwnedFd, Self::Error>;
/// Close a previously opened file descriptor
fn close(&mut self, fd: OwnedFd) -> Result<(), Self::Error>;
/// Change the currently active virtual terminal
fn change_vt(&mut self, vt: i32) -> Result<(), Self::Error>;
/// Check if this session is currently active
fn is_active(&self) -> bool;
/// Which seat this session is on
fn seat(&self) -> String;
}
/// Events that can be generated by a session
#[derive(Copy, Clone, Debug)]
pub enum Event {
/// The whole session has been paused
///
/// All devices should be considered as paused
PauseSession,
/// The whole session has been activated
ActivateSession,
}
impl Session for () {
type Error = ();
fn open(&mut self, _path: &Path, _flags: OFlags) -> Result<OwnedFd, Self::Error> {
Err(())
}
fn close(&mut self, _fd: OwnedFd) -> Result<(), Self::Error> {
Err(())
}
fn change_vt(&mut self, _vt: i32) -> Result<(), Self::Error> {
Err(())
}
fn is_active(&self) -> bool {
false
}
fn seat(&self) -> String {
String::from("seat0")
}
}
impl<S: Session> Session for Rc<RefCell<S>> {
type Error = S::Error;
fn open(&mut self, path: &Path, flags: OFlags) -> Result<OwnedFd, Self::Error> {
self.borrow_mut().open(path, flags)
}
fn close(&mut self, fd: OwnedFd) -> Result<(), Self::Error> {
self.borrow_mut().close(fd)
}
fn change_vt(&mut self, vt: i32) -> Result<(), Self::Error> {
self.borrow_mut().change_vt(vt)
}
fn is_active(&self) -> bool {
self.borrow().is_active()
}
fn seat(&self) -> String {
self.borrow().seat()
}
}
impl<S: Session> Session for Arc<Mutex<S>> {
type Error = S::Error;
fn open(&mut self, path: &Path, flags: OFlags) -> Result<OwnedFd, Self::Error> {
self.lock().unwrap().open(path, flags)
}
fn close(&mut self, fd: OwnedFd) -> Result<(), Self::Error> {
self.lock().unwrap().close(fd)
}
fn change_vt(&mut self, vt: i32) -> Result<(), Self::Error> {
self.lock().unwrap().change_vt(vt)
}
fn is_active(&self) -> bool {
self.lock().unwrap().is_active()
}
fn seat(&self) -> String {
self.lock().unwrap().seat()
}
}
/// Allows errors to be described by an error number
pub trait AsErrno: ::std::fmt::Debug {
/// Returns the error number representing this error if any
fn as_errno(&self) -> Option<i32>;
}
impl AsErrno for () {
fn as_errno(&self) -> Option<i32> {
None
}
}
#[cfg(feature = "backend_session_libseat")]
pub mod libseat;