session: Add multiplexer
This commit is contained in:
parent
5741ccdd46
commit
0ed69bf2da
|
@ -17,7 +17,7 @@ use slog::Logger;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{
|
backend::{
|
||||||
drm::{
|
drm::{
|
||||||
dev_t,
|
dev_t, device_bind,
|
||||||
egl::{EglDevice, EglSurface},
|
egl::{EglDevice, EglSurface},
|
||||||
gbm::{egl::Gbm as EglGbmBackend, GbmDevice},
|
gbm::{egl::Gbm as EglGbmBackend, GbmDevice},
|
||||||
legacy::LegacyDrmDevice,
|
legacy::LegacyDrmDevice,
|
||||||
|
@ -29,7 +29,7 @@ use smithay::{
|
||||||
libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface},
|
libinput::{libinput_bind, LibinputInputBackend, LibinputSessionInterface},
|
||||||
session::{
|
session::{
|
||||||
auto::{auto_session_bind, AutoSession},
|
auto::{auto_session_bind, AutoSession},
|
||||||
OFlag, Session, SessionNotifier,
|
notify_multiplexer, AsSessionObserver, OFlag, Session, SessionNotifier,
|
||||||
},
|
},
|
||||||
udev::{primary_gpu, udev_backend_bind, UdevBackend, UdevHandler},
|
udev::{primary_gpu, udev_backend_bind, UdevBackend, UdevHandler},
|
||||||
},
|
},
|
||||||
|
@ -48,7 +48,14 @@ use smithay::{
|
||||||
seat::{Seat, XkbConfig},
|
seat::{Seat, XkbConfig},
|
||||||
shm::init_shm_global,
|
shm::init_shm_global,
|
||||||
},
|
},
|
||||||
wayland_server::{calloop::EventLoop, protocol::wl_output, Display},
|
wayland_server::{
|
||||||
|
calloop::{
|
||||||
|
generic::{EventedFd, Generic},
|
||||||
|
EventLoop, LoopHandle, Source,
|
||||||
|
},
|
||||||
|
protocol::wl_output,
|
||||||
|
Display,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use glium_drawer::GliumDrawer;
|
use glium_drawer::GliumDrawer;
|
||||||
|
@ -87,6 +94,8 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
||||||
* Initialize session
|
* Initialize session
|
||||||
*/
|
*/
|
||||||
let (session, mut notifier) = AutoSession::new(log.clone()).ok_or(())?;
|
let (session, mut notifier) = AutoSession::new(log.clone()).ok_or(())?;
|
||||||
|
let (udev_observer, udev_notifier) = notify_multiplexer();
|
||||||
|
let udev_session_id = notifier.register(udev_observer);
|
||||||
|
|
||||||
let running = Arc::new(AtomicBool::new(true));
|
let running = Arc::new(AtomicBool::new(true));
|
||||||
|
|
||||||
|
@ -113,6 +122,8 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
||||||
window_map: window_map.clone(),
|
window_map: window_map.clone(),
|
||||||
pointer_location: pointer_location.clone(),
|
pointer_location: pointer_location.clone(),
|
||||||
pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(),
|
pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(),
|
||||||
|
loop_handle: event_loop.handle(),
|
||||||
|
notifier: udev_notifier,
|
||||||
logger: log.clone(),
|
logger: log.clone(),
|
||||||
},
|
},
|
||||||
seat.clone(),
|
seat.clone(),
|
||||||
|
@ -168,7 +179,7 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
||||||
*/
|
*/
|
||||||
let mut libinput_context =
|
let mut libinput_context =
|
||||||
Libinput::new_from_udev::<LibinputSessionInterface<AutoSession>>(session.clone().into(), &context);
|
Libinput::new_from_udev::<LibinputSessionInterface<AutoSession>>(session.clone().into(), &context);
|
||||||
let libinput_session_id = notifier.register(&mut libinput_context);
|
let libinput_session_id = notifier.register(libinput_context.observer());
|
||||||
libinput_context.udev_assign_seat(&seat).unwrap();
|
libinput_context.udev_assign_seat(&seat).unwrap();
|
||||||
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
|
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
|
||||||
libinput_backend.set_handler(AnvilInputHandler::new_with_session(
|
libinput_backend.set_handler(AnvilInputHandler::new_with_session(
|
||||||
|
@ -205,6 +216,7 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
||||||
|
|
||||||
let mut notifier = session_event_source.unbind();
|
let mut notifier = session_event_source.unbind();
|
||||||
notifier.unregister(libinput_session_id);
|
notifier.unregister(libinput_session_id);
|
||||||
|
notifier.unregister(udev_session_id);
|
||||||
|
|
||||||
libinput_event_source.remove();
|
libinput_event_source.remove();
|
||||||
udev_event_source.remove();
|
udev_event_source.remove();
|
||||||
|
@ -212,14 +224,15 @@ pub fn run_udev(mut display: Display, mut event_loop: EventLoop<()>, log: Logger
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UdevHandlerImpl {
|
struct UdevHandlerImpl<S: SessionNotifier, Data: 'static> {
|
||||||
compositor_token: CompositorToken<SurfaceData, Roles>,
|
compositor_token: CompositorToken<SurfaceData, Roles>,
|
||||||
active_egl_context: Rc<RefCell<Option<EGLDisplay>>>,
|
active_egl_context: Rc<RefCell<Option<EGLDisplay>>>,
|
||||||
session: AutoSession,
|
session: AutoSession,
|
||||||
backends: HashMap<
|
backends: HashMap<
|
||||||
dev_t,
|
dev_t,
|
||||||
(
|
(
|
||||||
RenderDevice,
|
S::Id,
|
||||||
|
Source<Generic<EventedFd<RenderDevice>>>,
|
||||||
Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<RenderSurface>>>>,
|
Rc<RefCell<HashMap<crtc::Handle, GliumDrawer<RenderSurface>>>>,
|
||||||
),
|
),
|
||||||
>,
|
>,
|
||||||
|
@ -228,14 +241,15 @@ struct UdevHandlerImpl {
|
||||||
window_map: Rc<RefCell<MyWindowMap>>,
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
pointer_location: Rc<RefCell<(f64, f64)>>,
|
pointer_location: Rc<RefCell<(f64, f64)>>,
|
||||||
pointer_image: ImageBuffer<Rgba<u8>, Vec<u8>>,
|
pointer_image: ImageBuffer<Rgba<u8>, Vec<u8>>,
|
||||||
|
loop_handle: LoopHandle<Data>,
|
||||||
|
notifier: S,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdevHandlerImpl {
|
impl<S: SessionNotifier, Data: 'static> UdevHandlerImpl<S, Data> {
|
||||||
pub fn scan_connectors(
|
pub fn scan_connectors(
|
||||||
device: &mut RenderDevice,
|
device: &mut RenderDevice,
|
||||||
egl_display: Rc<RefCell<Option<EGLDisplay>>>,
|
egl_display: Rc<RefCell<Option<EGLDisplay>>>,
|
||||||
pointer_image: &ImageBuffer<Rgba<u8>, Vec<u8>>,
|
|
||||||
logger: &::slog::Logger,
|
logger: &::slog::Logger,
|
||||||
) -> HashMap<crtc::Handle, GliumDrawer<RenderSurface>> {
|
) -> HashMap<crtc::Handle, GliumDrawer<RenderSurface>> {
|
||||||
// Get a set of all modesetting resource handles (excluding planes):
|
// Get a set of all modesetting resource handles (excluding planes):
|
||||||
|
@ -272,19 +286,6 @@ impl UdevHandlerImpl {
|
||||||
logger.clone(),
|
logger.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// create cursor
|
|
||||||
renderer
|
|
||||||
.borrow()
|
|
||||||
.set_cursor_representation(pointer_image, (2, 2))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// render first frame
|
|
||||||
{
|
|
||||||
let mut frame = renderer.draw();
|
|
||||||
frame.clear_color(0.8, 0.8, 0.9, 1.0);
|
|
||||||
frame.finish().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
backends.insert(crtc, renderer);
|
backends.insert(crtc, renderer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -296,7 +297,7 @@ impl UdevHandlerImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdevHandler for UdevHandlerImpl {
|
impl<S: SessionNotifier, Data: 'static> UdevHandler for UdevHandlerImpl<S, Data> {
|
||||||
fn device_added(&mut self, _device: dev_t, path: PathBuf) {
|
fn device_added(&mut self, _device: dev_t, path: PathBuf) {
|
||||||
if let Some(mut device) = self
|
if let Some(mut device) = self
|
||||||
.session
|
.session
|
||||||
|
@ -313,10 +314,9 @@ impl UdevHandler for UdevHandlerImpl {
|
||||||
*self.active_egl_context.borrow_mut() = device.bind_wl_display(&*self.display.borrow()).ok();
|
*self.active_egl_context.borrow_mut() = device.bind_wl_display(&*self.display.borrow()).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
let backends = Rc::new(RefCell::new(UdevHandlerImpl::scan_connectors(
|
let backends = Rc::new(RefCell::new(UdevHandlerImpl::<S, Data>::scan_connectors(
|
||||||
&mut device,
|
&mut device,
|
||||||
self.active_egl_context.clone(),
|
self.active_egl_context.clone(),
|
||||||
&self.pointer_image,
|
|
||||||
&self.logger,
|
&self.logger,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
|
@ -328,29 +328,72 @@ impl UdevHandler for UdevHandlerImpl {
|
||||||
logger: self.logger.clone(),
|
logger: self.logger.clone(),
|
||||||
});
|
});
|
||||||
|
|
||||||
self.backends.insert(device.device_id(), (device, backends));
|
let device_session_id = self.notifier.register(device.observer());
|
||||||
|
let dev_id = device.device_id();
|
||||||
|
let event_source = device_bind(&self.loop_handle, device)
|
||||||
|
.map_err(|e| -> IoError { e.into() })
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
for renderer in backends.borrow_mut().values() {
|
||||||
|
// create cursor
|
||||||
|
renderer
|
||||||
|
.borrow()
|
||||||
|
.set_cursor_representation(&self.pointer_image, (2, 2))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// render first frame
|
||||||
|
{
|
||||||
|
let mut frame = renderer.draw();
|
||||||
|
frame.clear_color(0.8, 0.8, 0.9, 1.0);
|
||||||
|
frame.finish().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.backends
|
||||||
|
.insert(dev_id, (device_session_id, event_source, backends));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn device_changed(&mut self, device: dev_t) {
|
fn device_changed(&mut self, device: dev_t) {
|
||||||
//quick and dirty, just re-init all backends
|
//quick and dirty, just re-init all backends
|
||||||
if let Some((ref mut device, ref backends)) = self.backends.get_mut(&device) {
|
if let Some((_, ref mut evt_source, ref backends)) = self.backends.get_mut(&device) {
|
||||||
*backends.borrow_mut() = UdevHandlerImpl::scan_connectors(
|
let source = evt_source.clone_inner();
|
||||||
device,
|
let mut evented = source.borrow_mut();
|
||||||
|
let mut backends = backends.borrow_mut();
|
||||||
|
*backends = UdevHandlerImpl::<S, Data>::scan_connectors(
|
||||||
|
&mut (*evented).0,
|
||||||
self.active_egl_context.clone(),
|
self.active_egl_context.clone(),
|
||||||
&self.pointer_image,
|
|
||||||
&self.logger,
|
&self.logger,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
for renderer in backends.values() {
|
||||||
|
// create cursor
|
||||||
|
renderer
|
||||||
|
.borrow()
|
||||||
|
.set_cursor_representation(&self.pointer_image, (2, 2))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// render first frame
|
||||||
|
{
|
||||||
|
let mut frame = renderer.draw();
|
||||||
|
frame.clear_color(0.8, 0.8, 0.9, 1.0);
|
||||||
|
frame.finish().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn device_removed(&mut self, device: dev_t) {
|
fn device_removed(&mut self, device: dev_t) {
|
||||||
// drop the backends on this side
|
// drop the backends on this side
|
||||||
if let Some((dev, _)) = self.backends.remove(&device) {
|
if let Some((id, evt_source, _)) = self.backends.remove(&device) {
|
||||||
// don't use hardware acceleration anymore, if this was the primary gpu
|
// don't use hardware acceleration anymore, if this was the primary gpu
|
||||||
if dev.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {
|
let source = evt_source.clone_inner();
|
||||||
|
let evented = source.borrow();
|
||||||
|
if (*evented).0.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {
|
||||||
*self.active_egl_context.borrow_mut() = None;
|
*self.active_egl_context.borrow_mut() = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.notifier.unregister(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use drm::control::{connector, crtc, Device as ControlDevice};
|
use drm::control::{connector, crtc};
|
||||||
use drm::Device as BasicDevice;
|
use drm::Device as BasicDevice;
|
||||||
use nix::libc::dev_t;
|
use nix::libc::dev_t;
|
||||||
use nix::sys::stat;
|
use nix::sys::stat;
|
||||||
|
@ -23,7 +23,7 @@ pub struct LegacyDrmDeviceObserver<A: AsRawFd + 'static> {
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: ControlDevice + 'static> AsSessionObserver<LegacyDrmDeviceObserver<A>> for LegacyDrmDevice<A> {
|
impl<A: AsRawFd + 'static> AsSessionObserver<LegacyDrmDeviceObserver<A>> for LegacyDrmDevice<A> {
|
||||||
fn observer(&mut self) -> LegacyDrmDeviceObserver<A> {
|
fn observer(&mut self) -> LegacyDrmDeviceObserver<A> {
|
||||||
LegacyDrmDeviceObserver {
|
LegacyDrmDeviceObserver {
|
||||||
dev: Rc::downgrade(&self.dev),
|
dev: Rc::downgrade(&self.dev),
|
||||||
|
@ -37,7 +37,7 @@ impl<A: ControlDevice + 'static> AsSessionObserver<LegacyDrmDeviceObserver<A>> f
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A: ControlDevice + 'static> SessionObserver for LegacyDrmDeviceObserver<A> {
|
impl<A: AsRawFd + 'static> SessionObserver for LegacyDrmDeviceObserver<A> {
|
||||||
fn pause(&mut self, devnum: Option<(u32, u32)>) {
|
fn pause(&mut self, devnum: Option<(u32, u32)>) {
|
||||||
if let Some((major, minor)) = devnum {
|
if let Some((major, minor)) = devnum {
|
||||||
if major as u64 != stat::major(self.dev_id) || minor as u64 != stat::minor(self.dev_id) {
|
if major as u64 != stat::major(self.dev_id) || minor as u64 != stat::minor(self.dev_id) {
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
use super::logind::{self, logind_session_bind, BoundLogindSession, LogindSession, LogindSessionNotifier};
|
use super::logind::{self, logind_session_bind, BoundLogindSession, LogindSession, LogindSessionNotifier};
|
||||||
use super::{
|
use super::{
|
||||||
direct::{self, direct_session_bind, BoundDirectSession, DirectSession, DirectSessionNotifier},
|
direct::{self, direct_session_bind, BoundDirectSession, DirectSession, DirectSessionNotifier},
|
||||||
AsErrno, AsSessionObserver, Session, SessionNotifier, SessionObserver,
|
AsErrno, Session, SessionNotifier, SessionObserver,
|
||||||
};
|
};
|
||||||
use nix::fcntl::OFlag;
|
use nix::fcntl::OFlag;
|
||||||
use std::{cell::RefCell, io::Error as IoError, os::unix::io::RawFd, path::Path, rc::Rc};
|
use std::{cell::RefCell, io::Error as IoError, os::unix::io::RawFd, path::Path, rc::Rc};
|
||||||
|
@ -202,10 +202,7 @@ impl Session for AutoSession {
|
||||||
impl SessionNotifier for AutoSessionNotifier {
|
impl SessionNotifier for AutoSessionNotifier {
|
||||||
type Id = AutoId;
|
type Id = AutoId;
|
||||||
|
|
||||||
fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>(
|
fn register<S: SessionObserver + 'static>(&mut self, signal: S) -> Self::Id {
|
||||||
&mut self,
|
|
||||||
signal: &mut A,
|
|
||||||
) -> Self::Id {
|
|
||||||
match *self {
|
match *self {
|
||||||
#[cfg(feature = "backend_session_logind")]
|
#[cfg(feature = "backend_session_logind")]
|
||||||
AutoSessionNotifier::Logind(ref mut logind) => {
|
AutoSessionNotifier::Logind(ref mut logind) => {
|
||||||
|
@ -231,21 +228,6 @@ impl SessionNotifier for AutoSessionNotifier {
|
||||||
_ => unreachable!(),
|
_ => 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 {
|
impl BoundAutoSession {
|
||||||
|
|
|
@ -404,27 +404,13 @@ pub struct Id(usize);
|
||||||
impl SessionNotifier for LogindSessionNotifier {
|
impl SessionNotifier for LogindSessionNotifier {
|
||||||
type Id = Id;
|
type Id = Id;
|
||||||
|
|
||||||
fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>(
|
fn register<S: SessionObserver + 'static>(&mut self, signal: S) -> Self::Id {
|
||||||
&mut self,
|
self.internal.signals.borrow_mut().push(Some(Box::new(signal)));
|
||||||
signal: &mut A,
|
|
||||||
) -> Self::Id {
|
|
||||||
self.internal
|
|
||||||
.signals
|
|
||||||
.borrow_mut()
|
|
||||||
.push(Some(Box::new(signal.observer())));
|
|
||||||
Id(self.internal.signals.borrow().len() - 1)
|
Id(self.internal.signals.borrow().len() - 1)
|
||||||
}
|
}
|
||||||
fn unregister(&mut self, signal: Id) {
|
fn unregister(&mut self, signal: Id) {
|
||||||
self.internal.signals.borrow_mut()[signal.0] = None;
|
self.internal.signals.borrow_mut()[signal.0] = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_active(&self) -> bool {
|
|
||||||
self.internal.active.load(Ordering::SeqCst)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn seat(&self) -> &str {
|
|
||||||
&self.internal.seat
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bound logind session that is driven by the `wayland_server::EventLoop`.
|
/// Bound logind session that is driven by the `wayland_server::EventLoop`.
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
//! for notifications are the `Libinput` context, the `UdevBackend` or a `DrmDevice` (handled
|
//! for notifications are the `Libinput` context, the `UdevBackend` or a `DrmDevice` (handled
|
||||||
//! automatically by the `UdevBackend`, if not done manually).
|
//! automatically by the `UdevBackend`, if not done manually).
|
||||||
|
|
||||||
use super::{AsErrno, AsSessionObserver, Session, SessionNotifier, SessionObserver};
|
use super::{AsErrno, Session, SessionNotifier, SessionObserver};
|
||||||
use nix::{
|
use nix::{
|
||||||
fcntl::{self, open, OFlag},
|
fcntl::{self, open, OFlag},
|
||||||
libc::c_int,
|
libc::c_int,
|
||||||
|
@ -350,28 +350,18 @@ pub struct Id(usize);
|
||||||
impl SessionNotifier for DirectSessionNotifier {
|
impl SessionNotifier for DirectSessionNotifier {
|
||||||
type Id = Id;
|
type Id = Id;
|
||||||
|
|
||||||
fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>(
|
fn register<S: SessionObserver + 'static>(&mut self, signal: S) -> Self::Id {
|
||||||
&mut self,
|
self.signals.push(Some(Box::new(signal)));
|
||||||
signal: &mut A,
|
|
||||||
) -> Self::Id {
|
|
||||||
self.signals.push(Some(Box::new(signal.observer())));
|
|
||||||
Id(self.signals.len() - 1)
|
Id(self.signals.len() - 1)
|
||||||
}
|
}
|
||||||
fn unregister(&mut self, signal: Id) {
|
fn unregister(&mut self, signal: Id) {
|
||||||
self.signals[signal.0] = None;
|
self.signals[signal.0] = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_active(&self) -> bool {
|
|
||||||
self.active.load(Ordering::SeqCst)
|
|
||||||
}
|
|
||||||
fn seat(&self) -> &str {
|
|
||||||
"seat0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DirectSessionNotifier {
|
impl DirectSessionNotifier {
|
||||||
fn signal_received(&mut self) {
|
fn signal_received(&mut self) {
|
||||||
if self.is_active() {
|
if self.active.load(Ordering::SeqCst) {
|
||||||
info!(self.logger, "Session shall become inactive.");
|
info!(self.logger, "Session shall become inactive.");
|
||||||
for signal in &mut self.signals {
|
for signal in &mut self.signals {
|
||||||
if let Some(ref mut signal) = *signal {
|
if let Some(ref mut signal) = *signal {
|
||||||
|
|
|
@ -54,15 +54,9 @@ pub trait SessionNotifier {
|
||||||
/// Registers a given `SessionObserver`.
|
/// Registers a given `SessionObserver`.
|
||||||
///
|
///
|
||||||
/// Returns an id of the inserted observer, can be used to remove it again.
|
/// Returns an id of the inserted observer, can be used to remove it again.
|
||||||
fn register<S: SessionObserver + 'static, A: AsSessionObserver<S>>(&mut self, signal: &mut A)
|
fn register<S: SessionObserver + 'static>(&mut self, signal: S) -> Self::Id;
|
||||||
-> Self::Id;
|
|
||||||
/// Removes an observer by its given id from `SessionNotifier::register`.
|
/// Removes an observer by its given id from `SessionNotifier::register`.
|
||||||
fn unregister(&mut self, signal: Self::Id);
|
fn unregister(&mut self, signal: Self::Id);
|
||||||
|
|
||||||
/// Check if this session is currently active
|
|
||||||
fn is_active(&self) -> bool;
|
|
||||||
/// Which seat this session is on
|
|
||||||
fn seat(&self) -> &str;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Trait describing the ability to return a `SessionObserver` related to Self.
|
/// Trait describing the ability to return a `SessionObserver` related to Self.
|
||||||
|
@ -186,3 +180,5 @@ pub mod auto;
|
||||||
mod dbus;
|
mod dbus;
|
||||||
pub mod direct;
|
pub mod direct;
|
||||||
pub use self::dbus::*;
|
pub use self::dbus::*;
|
||||||
|
mod multi;
|
||||||
|
pub use self::multi::*;
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
os::unix::io::RawFd,
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicUsize, Ordering},
|
||||||
|
Arc, Mutex,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{SessionNotifier, SessionObserver};
|
||||||
|
|
||||||
|
static ID_COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
|
||||||
|
/// Ids of registered `SessionObserver`s of the `DirectSessionNotifier`
|
||||||
|
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
|
||||||
|
pub struct Id(usize);
|
||||||
|
|
||||||
|
struct MultiObserver {
|
||||||
|
observer: Arc<Mutex<HashMap<Id, Box<SessionObserver>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SessionObserver for MultiObserver {
|
||||||
|
fn pause(&mut self, device: Option<(u32, u32)>) {
|
||||||
|
let mut lock = self.observer.lock().unwrap();
|
||||||
|
for mut observer in lock.values_mut() {
|
||||||
|
observer.pause(device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn activate(&mut self, device: Option<(u32, u32, Option<RawFd>)>) {
|
||||||
|
let mut lock = self.observer.lock().unwrap();
|
||||||
|
for mut observer in lock.values_mut() {
|
||||||
|
observer.activate(device)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MultiNotifier {
|
||||||
|
observer: Arc<Mutex<HashMap<Id, Box<SessionObserver>>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SessionNotifier for MultiNotifier {
|
||||||
|
type Id = Id;
|
||||||
|
|
||||||
|
fn register<S: SessionObserver + 'static>(&mut self, signal: S) -> Self::Id {
|
||||||
|
let id = Id(ID_COUNTER.fetch_add(1, Ordering::SeqCst));
|
||||||
|
self.observer.lock().unwrap().insert(id, Box::new(signal));
|
||||||
|
id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unregister(&mut self, signal: Self::Id) {
|
||||||
|
self.observer.lock().unwrap().remove(&signal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn notify_multiplexer() -> (impl SessionObserver, impl SessionNotifier<Id = Id>) {
|
||||||
|
let observer = Arc::new(Mutex::new(HashMap::new()));
|
||||||
|
|
||||||
|
(
|
||||||
|
MultiObserver {
|
||||||
|
observer: observer.clone(),
|
||||||
|
},
|
||||||
|
MultiNotifier { observer },
|
||||||
|
)
|
||||||
|
}
|
Loading…
Reference in New Issue