This commit is contained in:
Drakulix 2018-01-27 13:50:24 +01:00
parent 20e10612b9
commit 525c9b60c4
7 changed files with 211 additions and 151 deletions

View File

@ -105,7 +105,9 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
self.keyboard self.keyboard
.input(keycode, state, serial, move |modifiers, keysym| { .input(keycode, state, serial, move |modifiers, keysym| {
debug!(log, "keysym"; "state" => format!("{:?}", state), "mods" => format!("{:?}", modifiers), "keysym" => xkbcommon::xkb::keysym_get_name(keysym)); debug!(log, "keysym"; "state" => format!("{:?}", state), "mods" => format!("{:?}", modifiers), "keysym" => xkbcommon::xkb::keysym_get_name(keysym));
if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace && state == KeyState::Pressed { if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace
&& state == KeyState::Pressed
{
info!(log, "Stopping example using Ctrl+Alt+Backspace"); info!(log, "Stopping example using Ctrl+Alt+Backspace");
running.store(false, Ordering::SeqCst); running.store(false, Ordering::SeqCst);
false false
@ -113,7 +115,9 @@ impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
info!(log, "Stopping example using Logo+Q"); info!(log, "Stopping example using Logo+Q");
running.store(false, Ordering::SeqCst); running.store(false, Ordering::SeqCst);
false false
} else if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_XF86Switch_VT_1 && state == KeyState::Pressed { } else if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_XF86Switch_VT_1
&& state == KeyState::Pressed
{
info!(log, "Trying to switch to vt 1"); info!(log, "Trying to switch to vt 1");
if let Err(err) = session.change_vt(1) { if let Err(err) = session.change_vt(1) {
error!(log, "Error switching to vt 1: {}", err); error!(log, "Error switching to vt 1: {}", err);
@ -337,9 +341,8 @@ fn main() {
/* /*
* Initialize libinput backend * Initialize libinput backend
*/ */
let mut libinput_context = Libinput::new_from_udev::< let mut libinput_context =
LibinputSessionInterface<AutoSession>, Libinput::new_from_udev::<LibinputSessionInterface<AutoSession>>(session.clone().into(), &context);
>(session.clone().into(), &context);
let libinput_session_id = notifier.register(libinput_context.clone()); let libinput_session_id = notifier.register(libinput_context.clone());
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());

View File

@ -96,14 +96,17 @@ impl<A: Device + 'static> DrmBackend<A> {
})?; })?;
front_bo.set_userdata(fb).unwrap(); front_bo.set_userdata(fb).unwrap();
let cursor = Cell::new((context let cursor = Cell::new((
context
.create_buffer_object( .create_buffer_object(
1, 1,
1, 1,
GbmFormat::ARGB8888, GbmFormat::ARGB8888,
BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE, BufferObjectFlags::CURSOR | BufferObjectFlags::WRITE,
) )
.chain_err(|| ErrorKind::GbmInitFailed)?, (0,0))); .chain_err(|| ErrorKind::GbmInitFailed)?,
(0, 0),
));
Ok(DrmBackend { Ok(DrmBackend {
backend: Rc::new(DrmBackendInternal { backend: Rc::new(DrmBackendInternal {

View File

@ -219,7 +219,7 @@ use drm::control::{connector, crtc, encoder, Mode, ResourceInfo};
use drm::control::Device as ControlDevice; use drm::control::Device as ControlDevice;
use drm::control::framebuffer; use drm::control::framebuffer;
use drm::result::Error as DrmError; use drm::result::Error as DrmError;
use gbm::{Device as GbmDevice, BufferObject}; use gbm::{BufferObject, Device as GbmDevice};
use nix; use nix;
use nix::sys::stat::{self, dev_t, fstat}; use nix::sys::stat::{self, dev_t, fstat};
use std::collections::HashMap; use std::collections::HashMap;
@ -328,7 +328,10 @@ impl<A: ControlDevice + 'static> DrmDevice<A> {
// we want to mode-set, so we better be the master, if we run via a tty session // we want to mode-set, so we better be the master, if we run via a tty session
if let Err(_) = drm.set_master() { if let Err(_) = drm.set_master() {
warn!(log, "Unable to become drm master, assuming unpriviledged mode"); warn!(
log,
"Unable to become drm master, assuming unpriviledged mode"
);
drm.priviledged = false; drm.priviledged = false;
}; };
@ -607,8 +610,8 @@ impl<A: ControlDevice + 'static> SessionObserver for StateToken<DrmDevice<A>> {
fn pause<'a>(&mut self, state: &mut StateProxy<'a>, devnum: Option<(u32, u32)>) { fn pause<'a>(&mut self, state: &mut StateProxy<'a>, devnum: Option<(u32, u32)>) {
let device = state.get_mut(self); let device = state.get_mut(self);
if let Some((major, minor)) = devnum { if let Some((major, minor)) = devnum {
if major as u64 != stat::major(device.device_id) || if major as u64 != stat::major(device.device_id) || minor as u64 != stat::minor(device.device_id)
minor as u64 != stat::minor(device.device_id) { {
return; return;
} }
} }
@ -626,13 +629,13 @@ impl<A: ControlDevice + 'static> SessionObserver for StateToken<DrmDevice<A>> {
fn activate<'a>(&mut self, state: &mut StateProxy<'a>, devnum: Option<(u32, u32, Option<RawFd>)>) { fn activate<'a>(&mut self, state: &mut StateProxy<'a>, devnum: Option<(u32, u32, Option<RawFd>)>) {
let device = state.get_mut(self); let device = state.get_mut(self);
if let Some((major, minor, fd)) = devnum { if let Some((major, minor, fd)) = devnum {
if major as u64 != stat::major(device.device_id) || if major as u64 != stat::major(device.device_id) || minor as u64 != stat::minor(device.device_id)
minor as u64 != stat::minor(device.device_id)
{ {
return; return;
} else if let Some(fd) = fd { } else if let Some(fd) = fd {
info!(device.logger, "Replacing fd"); info!(device.logger, "Replacing fd");
nix::unistd::dup2(device.as_raw_fd(), fd).expect("Failed to replace file descriptor of drm device"); nix::unistd::dup2(device.as_raw_fd(), fd)
.expect("Failed to replace file descriptor of drm device");
} }
} }
device.active = true; device.active = true;
@ -657,8 +660,8 @@ impl<A: ControlDevice + 'static> SessionObserver for StateToken<DrmDevice<A>> {
} }
// reset cursor // reset cursor
{ {
let &(ref cursor, ref hotspot) : &(BufferObject<()>, (u32, u32)) let &(ref cursor, ref hotspot): &(BufferObject<()>, (u32, u32)) =
= unsafe { &*backend.cursor.as_ptr() }; unsafe { &*backend.cursor.as_ptr() };
if crtc::set_cursor2( if crtc::set_cursor2(
&*backend.context, &*backend.context,
*crtc, *crtc,
@ -667,10 +670,7 @@ impl<A: ControlDevice + 'static> SessionObserver for StateToken<DrmDevice<A>> {
).is_err() ).is_err()
{ {
if let Err(err) = crtc::set_cursor(&*backend.context, *crtc, cursor) { if let Err(err) = crtc::set_cursor(&*backend.context, *crtc, cursor) {
error!( error!(device.logger, "Failed to reset cursor. Error: {}", err);
device.logger,
"Failed to reset cursor. Error: {}", err
);
} }
} }
} }

View File

@ -29,20 +29,19 @@
//! automatically by the `UdevBackend`, if not done manually). //! automatically by the `UdevBackend`, if not done manually).
//! ``` //! ```
use std::io::{Result as IoResult}; use super::{AsErrno, Session, SessionNotifier, SessionObserver};
use std::rc::Rc; use super::direct::{self, direct_session_bind, DirectSession, DirectSessionNotifier};
#[cfg(feature = "backend_session_logind")]
use super::logind::{self, logind_session_bind, BoundLogindSession, LogindSession, LogindSessionNotifier};
use nix::fcntl::OFlag;
use std::cell::RefCell; use std::cell::RefCell;
use std::io::Result as IoResult;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use std::path::Path; use std::path::Path;
use nix::fcntl::OFlag; use std::rc::Rc;
use wayland_server::{EventLoopHandle}; use wayland_server::EventLoopHandle;
use wayland_server::sources::SignalEventSource; 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};
/// `Session` using the best available inteface /// `Session` using the best available inteface
#[derive(Clone)] #[derive(Clone)]
pub enum AutoSession { pub enum AutoSession {
@ -80,8 +79,7 @@ pub enum BoundAutoSession {
pub struct AutoId(AutoIdInternal); pub struct AutoId(AutoIdInternal);
#[derive(PartialEq, Eq)] #[derive(PartialEq, Eq)]
enum AutoIdInternal { enum AutoIdInternal {
#[cfg(feature = "backend_session_logind")] #[cfg(feature = "backend_session_logind")] Logind(logind::Id),
Logind(logind::Id),
Direct(direct::Id), Direct(direct::Id),
} }
@ -89,22 +87,32 @@ 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")] #[cfg(feature = "backend_session_logind")]
pub fn new<L>(logger: L) -> Option<(AutoSession, AutoSessionNotifier)> pub fn new<L>(logger: L) -> Option<(AutoSession, AutoSessionNotifier)>
where L: Into<Option<::slog::Logger>> where
L: Into<Option<::slog::Logger>>,
{ {
let logger = ::slog_or_stdlog(logger) let logger = ::slog_or_stdlog(logger)
.new(o!("smithay_module" => "backend_session_auto", "session_type" => "auto")); .new(o!("smithay_module" => "backend_session_auto", "session_type" => "auto"));
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((AutoSession::Logind(session), AutoSessionNotifier::Logind(notifier))), Ok((session, notifier)) => Some((
AutoSession::Logind(session),
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"); info!(logger, "Falling back to create tty session");
match DirectSession::new(None, logger.clone()) { match DirectSession::new(None, logger.clone()) {
Ok((session, notifier)) => Some((AutoSession::Direct(Rc::new(RefCell::new(session))), AutoSessionNotifier::Direct(notifier))), Ok((session, notifier)) => Some((
AutoSession::Direct(Rc::new(RefCell::new(session))),
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
} }
} }
@ -114,17 +122,24 @@ impl AutoSession {
#[cfg(not(feature = "backend_session_logind"))] #[cfg(not(feature = "backend_session_logind"))]
pub fn new<L>(logger: L) -> Option<(AutoSession, AutoSessionNotifier)> pub fn new<L>(logger: L) -> Option<(AutoSession, AutoSessionNotifier)>
where L: Into<Option<::slog::Logger>> where
L: Into<Option<::slog::Logger>>,
{ {
let logger = ::slog_or_stdlog(logger) let logger = ::slog_or_stdlog(logger)
.new(o!("smithay_module" => "backend_session_auto", "session_type" => "auto")); .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((AutoSession::Direct(Rc::new(RefCell::new(session))), AutoSessionNotifier::Direct(notifier))), Ok((session, notifier)) => Some((
AutoSession::Direct(Rc::new(RefCell::new(session))),
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
} }
} }
@ -136,7 +151,9 @@ impl AutoSession {
/// Allows the `AutoSessionNotifier` to listen for incoming signals signalling the session state. /// Allows the `AutoSessionNotifier` to listen for incoming signals signalling the session state.
/// If you don't use this function `AutoSessionNotifier` will not correctly tell you the /// If you don't use this function `AutoSessionNotifier` will not correctly tell you the
/// session state and call it's `SessionObservers`. /// session state and call it's `SessionObservers`.
pub fn auto_session_bind(notifier: AutoSessionNotifier, evlh: &mut EventLoopHandle) -> IoResult<BoundAutoSession> { pub fn auto_session_bind(
notifier: AutoSessionNotifier, evlh: &mut EventLoopHandle
) -> IoResult<BoundAutoSession> {
Ok(match notifier { Ok(match notifier {
#[cfg(feature = "backend_session_logind")] #[cfg(feature = "backend_session_logind")]
AutoSessionNotifier::Logind(logind) => BoundAutoSession::Logind(logind_session_bind(logind, evlh)?), AutoSessionNotifier::Logind(logind) => BoundAutoSession::Logind(logind_session_bind(logind, evlh)?),
@ -192,15 +209,23 @@ impl SessionNotifier for AutoSessionNotifier {
fn register<S: SessionObserver + 'static>(&mut self, signal: S) -> Self::Id { fn register<S: SessionObserver + 'static>(&mut self, signal: S) -> Self::Id {
match self { match self {
#[cfg(feature = "backend_session_logind")] #[cfg(feature = "backend_session_logind")]
&mut AutoSessionNotifier::Logind(ref mut logind) => AutoId(AutoIdInternal::Logind(logind.register(signal))), &mut AutoSessionNotifier::Logind(ref mut logind) => {
&mut AutoSessionNotifier::Direct(ref mut direct) => AutoId(AutoIdInternal::Direct(direct.register(signal))), 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) { fn unregister(&mut self, signal: Self::Id) {
match (self, signal) { match (self, signal) {
#[cfg(feature = "backend_session_logind")] #[cfg(feature = "backend_session_logind")]
(&mut AutoSessionNotifier::Logind(ref mut logind), AutoId(AutoIdInternal::Logind(signal))) => logind.unregister(signal), (&mut AutoSessionNotifier::Logind(ref mut logind), AutoId(AutoIdInternal::Logind(signal))) => {
(&mut AutoSessionNotifier::Direct(ref mut direct), AutoId(AutoIdInternal::Direct(signal))) => direct.unregister(signal), logind.unregister(signal)
}
(&mut AutoSessionNotifier::Direct(ref mut direct), AutoId(AutoIdInternal::Direct(signal))) => {
direct.unregister(signal)
}
_ => unreachable!(), _ => unreachable!(),
} }
} }

View File

@ -30,17 +30,18 @@
//! automatically by the `UdevBackend`, if not done manually). //! automatically by the `UdevBackend`, if not done manually).
//! ``` //! ```
use ::backend::session::{AsErrno, Session, SessionNotifier, SessionObserver}; use backend::session::{AsErrno, Session, SessionNotifier, SessionObserver};
use dbus::{BusName, BusType, Connection, ConnectionItem, ConnectionItems, Interface, Member, Message,
MessageItem, OwnedFd, Path as DbusPath, Watch, WatchEvent};
use nix::fcntl::OFlag; use nix::fcntl::OFlag;
use nix::sys::stat::{stat, fstat, major, minor}; use nix::sys::stat::{fstat, major, minor, stat};
use std::cell::RefCell; use std::cell::RefCell;
use std::io::Result as IoResult; use std::io::Result as IoResult;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use std::rc::{Rc, Weak};
use std::path::Path; use std::path::Path;
use std::rc::{Rc, Weak};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use systemd::login; use systemd::login;
use dbus::{BusType, Connection, ConnectionItems, ConnectionItem, Message, BusName, Interface, Member, Path as DbusPath, OwnedFd, MessageItem, Watch, WatchEvent};
use wayland_server::EventLoopHandle; use wayland_server::EventLoopHandle;
use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest}; use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};
@ -62,14 +63,14 @@ pub struct LogindSession {
/// `SessionNotifier` via the logind dbus interface /// `SessionNotifier` via the logind dbus interface
pub struct LogindSessionNotifier { pub struct LogindSessionNotifier {
internal: Rc<LogindSessionImpl> internal: Rc<LogindSessionImpl>,
} }
impl LogindSession { impl LogindSession {
/// Tries to create a new session via the logind dbus interface. /// Tries to create a new session via the logind dbus interface.
pub fn new<L>(logger: L) -> Result<(LogindSession, LogindSessionNotifier)> pub fn new<L>(logger: L) -> Result<(LogindSession, LogindSessionNotifier)>
where where
L: Into<Option<::slog::Logger>> L: Into<Option<::slog::Logger>>,
{ {
let logger = ::slog_or_stdlog(logger) let logger = ::slog_or_stdlog(logger)
.new(o!("smithay_module" => "backend_session", "session_type" => "logind")); .new(o!("smithay_module" => "backend_session", "session_type" => "logind"));
@ -88,35 +89,50 @@ impl LogindSession {
"/org/freedesktop/login1", "/org/freedesktop/login1",
"org.freedesktop.login1.Manager", "org.freedesktop.login1.Manager",
"GetSession", "GetSession",
Some(vec![session_id.clone().into()]) Some(vec![session_id.clone().into()]),
)?.get1::<DbusPath<'static>>() )?.get1::<DbusPath<'static>>()
.chain_err(|| ErrorKind::UnexpectedMethodReturn)?; .chain_err(|| ErrorKind::UnexpectedMethodReturn)?;
// Match all signals that we want to receive and handle // Match all signals that we want to receive and handle
let match1 = String::from("type='signal',\ let match1 = String::from(
"type='signal',\
sender='org.freedesktop.login1',\ sender='org.freedesktop.login1',\
interface='org.freedesktop.login1.Manager',\ interface='org.freedesktop.login1.Manager',\
member='SessionRemoved',\ member='SessionRemoved',\
path='/org/freedesktop/login1'"); path='/org/freedesktop/login1'",
conn.add_match(&match1).chain_err(|| ErrorKind::DbusMatchFailed(match1))?; );
let match2 = format!("type='signal',\ conn.add_match(&match1)
.chain_err(|| ErrorKind::DbusMatchFailed(match1))?;
let match2 = format!(
"type='signal',\
sender='org.freedesktop.login1',\ sender='org.freedesktop.login1',\
interface='org.freedesktop.login1.Session',\ interface='org.freedesktop.login1.Session',\
member='PauseDevice',\ member='PauseDevice',\
path='{}'", &session_path); path='{}'",
conn.add_match(&match2).chain_err(|| ErrorKind::DbusMatchFailed(match2))?; &session_path
let match3 = format!("type='signal',\ );
conn.add_match(&match2)
.chain_err(|| ErrorKind::DbusMatchFailed(match2))?;
let match3 = format!(
"type='signal',\
sender='org.freedesktop.login1',\ sender='org.freedesktop.login1',\
interface='org.freedesktop.login1.Session',\ interface='org.freedesktop.login1.Session',\
member='ResumeDevice',\ member='ResumeDevice',\
path='{}'", &session_path); path='{}'",
conn.add_match(&match3).chain_err(|| ErrorKind::DbusMatchFailed(match3))?; &session_path
let match4 = format!("type='signal',\ );
conn.add_match(&match3)
.chain_err(|| ErrorKind::DbusMatchFailed(match3))?;
let match4 = format!(
"type='signal',\
sender='org.freedesktop.login1',\ sender='org.freedesktop.login1',\
interface='org.freedesktop.DBus.Properties',\ interface='org.freedesktop.DBus.Properties',\
member='PropertiesChanged',\ member='PropertiesChanged',\
path='{}'", &session_path); path='{}'",
conn.add_match(&match4).chain_err(|| ErrorKind::DbusMatchFailed(match4))?; &session_path
);
conn.add_match(&match4)
.chain_err(|| ErrorKind::DbusMatchFailed(match4))?;
// Activate (switch to) the session and take control // Activate (switch to) the session and take control
LogindSessionImpl::blocking_call( LogindSessionImpl::blocking_call(
@ -153,9 +169,7 @@ impl LogindSession {
internal: Rc::downgrade(&internal), internal: Rc::downgrade(&internal),
seat, seat,
}, },
LogindSessionNotifier { LogindSessionNotifier { internal },
internal,
}
)) ))
} }
} }
@ -171,14 +185,9 @@ impl LogindSessionNotifier {
} }
impl LogindSessionImpl { impl LogindSessionImpl {
fn blocking_call<'d, 'p, 'i, 'm, D, P, I, M> fn blocking_call<'d, 'p, 'i, 'm, D, P, I, M>(
( conn: &Connection, destination: D, path: P, interface: I, method: M,
conn: &Connection, arguments: Option<Vec<MessageItem>>,
destination: D,
path: P,
interface: I,
method: M,
arguments: Option<Vec<MessageItem>>
) -> Result<Message> ) -> Result<Message>
where where
D: Into<BusName<'d>>, D: Into<BusName<'d>>,
@ -198,21 +207,26 @@ impl LogindSessionImpl {
}; };
let mut message = conn.send_with_reply_and_block(message, 1000) let mut message = conn.send_with_reply_and_block(message, 1000)
.chain_err(|| ErrorKind::FailedToSendDbusCall( .chain_err(|| {
ErrorKind::FailedToSendDbusCall(
destination.clone(), destination.clone(),
path.clone(), path.clone(),
interface.clone(), interface.clone(),
method.clone() method.clone(),
))?; )
})?;
match message.as_result() { match message.as_result() {
Ok(_) => Ok(message), Ok(_) => Ok(message),
Err(err) => Err(Error::with_chain(err, ErrorKind::DbusCallFailed( Err(err) => Err(Error::with_chain(
err,
ErrorKind::DbusCallFailed(
destination.clone(), destination.clone(),
path.clone(), path.clone(),
interface.clone(), interface.clone(),
method.clone() method.clone(),
))) ),
)),
} }
} }
@ -221,7 +235,7 @@ impl LogindSessionImpl {
let message = if let ConnectionItem::Signal(ref s) = item { let message = if let ConnectionItem::Signal(ref s) = item {
s s
} else { } else {
continue continue;
}; };
if &*message.interface().unwrap() == "org.freedesktop.login1.Manager" if &*message.interface().unwrap() == "org.freedesktop.login1.Manager"
&& &*message.member().unwrap() == "SessionRemoved" && &*message.member().unwrap() == "SessionRemoved"
@ -243,7 +257,10 @@ impl LogindSessionImpl {
let major = major.chain_err(|| ErrorKind::UnexpectedMethodReturn)?; let major = major.chain_err(|| ErrorKind::UnexpectedMethodReturn)?;
let minor = minor.chain_err(|| ErrorKind::UnexpectedMethodReturn)?; let minor = minor.chain_err(|| ErrorKind::UnexpectedMethodReturn)?;
let pause_type = pause_type.chain_err(|| ErrorKind::UnexpectedMethodReturn)?; let pause_type = pause_type.chain_err(|| ErrorKind::UnexpectedMethodReturn)?;
debug!(self.logger, "Request of type \"{}\" to close device ({},{})", pause_type, major, minor); debug!(
self.logger,
"Request of type \"{}\" to close device ({},{})", pause_type, major, minor
);
for signal in &mut *self.signals.borrow_mut() { for signal in &mut *self.signals.borrow_mut() {
if let &mut Some(ref mut signal) = signal { if let &mut Some(ref mut signal) = signal {
signal.pause(&mut evlh.state().as_proxy(), Some((major, minor))); signal.pause(&mut evlh.state().as_proxy(), Some((major, minor)));
@ -260,14 +277,15 @@ impl LogindSessionImpl {
self.session_path.clone(), self.session_path.clone(),
"org.freedesktop.login1.Session", "org.freedesktop.login1.Session",
"PauseDeviceComplete", "PauseDeviceComplete",
Some(vec![major.into(), minor.into()]) Some(vec![major.into(), minor.into()]),
)?; )?;
} }
} else if &*message.member().unwrap() == "ResumeDevice" { } else if &*message.member().unwrap() == "ResumeDevice" {
let (major, minor, fd) = message.get3::<u32, u32, OwnedFd>(); let (major, minor, fd) = message.get3::<u32, u32, OwnedFd>();
let major = major.chain_err(|| ErrorKind::UnexpectedMethodReturn)?; let major = major.chain_err(|| ErrorKind::UnexpectedMethodReturn)?;
let minor = minor.chain_err(|| ErrorKind::UnexpectedMethodReturn)?; let minor = minor.chain_err(|| ErrorKind::UnexpectedMethodReturn)?;
let fd = fd.chain_err(|| ErrorKind::UnexpectedMethodReturn)?.into_fd(); let fd = fd.chain_err(|| ErrorKind::UnexpectedMethodReturn)?
.into_fd();
debug!(self.logger, "Reactivating device ({},{})", major, minor); debug!(self.logger, "Reactivating device ({},{})", major, minor);
for signal in &mut *self.signals.borrow_mut() { for signal in &mut *self.signals.borrow_mut() {
if let &mut Some(ref mut signal) = signal { if let &mut Some(ref mut signal) = signal {
@ -278,9 +296,10 @@ impl LogindSessionImpl {
} else if &*message.interface().unwrap() == "org.freedesktop.DBus.Properties" } else if &*message.interface().unwrap() == "org.freedesktop.DBus.Properties"
&& &*message.member().unwrap() == "PropertiesChanged" && &*message.member().unwrap() == "PropertiesChanged"
{ {
use dbus::arg::{Array, Dict, Iter, Variant, Get}; use dbus::arg::{Array, Dict, Get, Iter, Variant};
let (_, changed, _) = message.get3::<String, Dict<String, Variant<Iter>, Iter>, Array<String, Iter>>(); let (_, changed, _) =
message.get3::<String, Dict<String, Variant<Iter>, Iter>, Array<String, Iter>>();
let mut changed = changed.chain_err(|| ErrorKind::UnexpectedMethodReturn)?; let mut changed = changed.chain_err(|| ErrorKind::UnexpectedMethodReturn)?;
if let Some((_, mut value)) = changed.find(|&(ref key, _)| &*key == "Active") { if let Some((_, mut value)) = changed.find(|&(ref key, _)| &*key == "Active") {
if let Some(active) = Get::get(&mut value.0) { if let Some(active) = Get::get(&mut value.0) {
@ -309,9 +328,10 @@ impl Session for LogindSession {
Some(vec![ Some(vec![
(major(stat.st_rdev) as u32).into(), (major(stat.st_rdev) as u32).into(),
(minor(stat.st_rdev) as u32).into(), (minor(stat.st_rdev) as u32).into(),
]) ]),
)?.get2::<OwnedFd, bool>(); )?.get2::<OwnedFd, bool>();
let fd = fd.chain_err(|| ErrorKind::UnexpectedMethodReturn)?.into_fd(); let fd = fd.chain_err(|| ErrorKind::UnexpectedMethodReturn)?
.into_fd();
Ok(fd) Ok(fd)
} else { } else {
bail!(ErrorKind::SessionLost) bail!(ErrorKind::SessionLost)
@ -330,7 +350,7 @@ impl Session for LogindSession {
Some(vec![ Some(vec![
(major(stat.st_rdev) as u32).into(), (major(stat.st_rdev) as u32).into(),
(minor(stat.st_rdev) as u32).into(), (minor(stat.st_rdev) as u32).into(),
]) ]),
).map(|_| ()) ).map(|_| ())
} else { } else {
bail!(ErrorKind::SessionLost) bail!(ErrorKind::SessionLost)
@ -357,9 +377,7 @@ impl Session for LogindSession {
"/org/freedesktop/login1/seat/self", "/org/freedesktop/login1/seat/self",
"org.freedesktop.login1.Seat", "org.freedesktop.login1.Seat",
"SwitchTo", "SwitchTo",
Some(vec![ Some(vec![(vt_num as u32).into()]),
(vt_num as u32).into(),
])
).map(|_| ()) ).map(|_| ())
} else { } else {
bail!(ErrorKind::SessionLost) bail!(ErrorKind::SessionLost)
@ -375,7 +393,10 @@ impl SessionNotifier for LogindSessionNotifier {
type Id = Id; type Id = Id;
fn register<S: SessionObserver + 'static>(&mut self, signal: S) -> Id { fn register<S: SessionObserver + 'static>(&mut self, signal: S) -> Id {
self.internal.signals.borrow_mut().push(Some(Box::new(signal))); self.internal
.signals
.borrow_mut()
.push(Some(Box::new(signal)));
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) {
@ -409,10 +430,12 @@ pub struct BoundLogindSession {
/// session state and call it's `SessionObservers`. /// session state and call it's `SessionObservers`.
pub fn logind_session_bind( pub fn logind_session_bind(
notifier: LogindSessionNotifier, evlh: &mut EventLoopHandle notifier: LogindSessionNotifier, evlh: &mut EventLoopHandle
) -> IoResult<BoundLogindSession> ) -> IoResult<BoundLogindSession> {
{
let watches = notifier.internal.conn.borrow().watch_fds(); let watches = notifier.internal.conn.borrow().watch_fds();
let sources = watches.clone().into_iter().map(|watch| { let sources = watches
.clone()
.into_iter()
.map(|watch| {
let mut interest = FdInterest::empty(); let mut interest = FdInterest::empty();
interest.set(FdInterest::READ, watch.readable()); interest.set(FdInterest::READ, watch.readable());
interest.set(FdInterest::WRITE, watch.writable()); interest.set(FdInterest::WRITE, watch.writable());
@ -420,9 +443,10 @@ pub fn logind_session_bind(
watch.fd(), watch.fd(),
fd_event_source_implementation(), fd_event_source_implementation(),
notifier.internal.clone(), notifier.internal.clone(),
interest interest,
) )
}).collect::<IoResult<Vec<FdEventSource<Rc<LogindSessionImpl>>>>>()?; })
.collect::<IoResult<Vec<FdEventSource<Rc<LogindSessionImpl>>>>>()?;
Ok(BoundLogindSession { Ok(BoundLogindSession {
notifier, notifier,
@ -460,13 +484,17 @@ fn fd_event_source_implementation() -> FdEventSourceImpl<Rc<LogindSessionImpl>>
FdEventSourceImpl { FdEventSourceImpl {
ready: |evlh, session, fd, interest| { ready: |evlh, session, fd, interest| {
let conn = session.conn.borrow(); let conn = session.conn.borrow();
let items = conn.watch_handle(fd, match interest { let items = conn.watch_handle(
x if x.contains(FdInterest::READ) && x.contains(FdInterest::WRITE) => fd,
WatchEvent::Readable as u32 | WatchEvent::Writable as u32, match interest {
x if x.contains(FdInterest::READ) && x.contains(FdInterest::WRITE) => {
WatchEvent::Readable as u32 | WatchEvent::Writable as u32
}
x if x.contains(FdInterest::READ) => WatchEvent::Readable as u32, x if x.contains(FdInterest::READ) => WatchEvent::Readable as u32,
x if x.contains(FdInterest::WRITE) => WatchEvent::Writable as u32, x if x.contains(FdInterest::WRITE) => WatchEvent::Writable as u32,
_ => return, _ => return,
}); },
);
if let Err(err) = session.handle_signals(evlh, items) { if let Err(err) = session.handle_signals(evlh, items) {
error!(session.logger, "Error handling dbus signals: {}", err); error!(session.logger, "Error handling dbus signals: {}", err);
} }

View File

@ -178,7 +178,8 @@ impl<
H: DrmHandler<SessionFdDrmDevice> + 'static, H: DrmHandler<SessionFdDrmDevice> + 'static,
S: Session + 'static, S: Session + 'static,
T: UdevHandler<H> + 'static, T: UdevHandler<H> + 'static,
> SessionObserver for StateToken<UdevBackend<H, S, T>> { > SessionObserver for StateToken<UdevBackend<H, S, T>>
{
fn pause<'a>(&mut self, state: &mut StateProxy<'a>, devnum: Option<(u32, u32)>) { fn pause<'a>(&mut self, state: &mut StateProxy<'a>, devnum: Option<(u32, u32)>) {
state.with_value(self, |state, udev| { state.with_value(self, |state, udev| {
for &mut (ref mut device, _) in udev.devices.values_mut() { for &mut (ref mut device, _) in udev.devices.values_mut() {

View File

@ -16,18 +16,18 @@ extern crate wayland_server;
extern crate wayland_sys; extern crate wayland_sys;
extern crate xkbcommon; extern crate xkbcommon;
#[cfg(feature = "dbus")]
extern crate dbus;
#[cfg(feature = "backend_drm")] #[cfg(feature = "backend_drm")]
extern crate drm; extern crate drm;
#[cfg(feature = "backend_drm")] #[cfg(feature = "backend_drm")]
extern crate gbm; extern crate gbm;
#[cfg(feature = "backend_libinput")] #[cfg(feature = "backend_libinput")]
extern crate input; extern crate input;
#[cfg(feature = "udev")]
extern crate udev;
#[cfg(feature = "dbus")]
extern crate dbus;
#[cfg(feature = "backend_session_logind")] #[cfg(feature = "backend_session_logind")]
extern crate systemd; extern crate systemd;
#[cfg(feature = "udev")]
extern crate udev;
#[cfg(feature = "backend_winit")] #[cfg(feature = "backend_winit")]
extern crate wayland_client; extern crate wayland_client;
#[cfg(feature = "backend_winit")] #[cfg(feature = "backend_winit")]