<NME> udev.rs
<BEF> //! `udev` related functionality for automated device scanning
//!
//! This module mainly provides the [`UdevBackend`], which monitors available DRM devices and acts as
//! an event source to be inserted in [`calloop`], generating events whenever these devices change.
//!
//! *Note:* Once inserted into the event loop, the [`UdevBackend`] will only notify you about *changes*
//! in the device list. To get an initial snapshot of the state during your initialization, you need to
//! call its `device_list` method.
//!
//! backend.

use backend::drm::{drm_device_bind, DrmDevice, DrmHandler};
use backend::session::{Session, SessionObserver};
use drm::Device as BasicDevice;
use drm::control::Device as ControlDevice;
use nix::fcntl;
use nix::sys::stat::dev_t;
use std::collections::HashMap;
use std::ffi::OsString;
use std::io::{Error as IoError, Result as IoResult};
use std::mem::drop;
use std::os::unix::io::{AsRawFd, RawFd};
use std::path::{Path, PathBuf};
use udev::{Context, Enumerator, Event, EventType, MonitorBuilder, MonitorSocket, Result as UdevResult};
use wayland_server::{EventLoopHandle, StateProxy, StateToken};
use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};

/// Udev's `DrmDevice` type based on the underlying session
pub struct SessionFdDrmDevice(RawFd);
//! }).expect("Failed to insert the udev source into the event loop");
//! ```
//!
//! Additionally this contains some utility functions related to scanning.
//!
//! See also `anvil/src/udev.rs` for pure hardware backed example of a compositor utilizing this
//! backend.

use nix::sys::stat::{dev_t, stat};
use std::{
    collections::HashMap,
    ffi::OsString,
    fmt, io,
    os::unix::io::{AsRawFd, RawFd},
    path::{Path, PathBuf},
};
    S: Session + 'static,
    T: UdevHandler<H> + 'static,
> {
    devices: HashMap<
        dev_t,
        (
            StateToken<DrmDevice<SessionFdDrmDevice>>,
            FdEventSource<(StateToken<DrmDevice<SessionFdDrmDevice>>, H)>,
        ),
    >,
    monitor: MonitorSocket,
    session: S,
    handler: T,
///
/// Provides a way to automatically scan for available gpus and notifies the
/// given handler of any changes. Can be used to provide hot-plug functionality for gpus and
/// attached monitors.
pub struct UdevBackend {
    devices: HashMap<dev_t, PathBuf>,
    monitor: MonitorSocket,
    token: Option<Token>,
    logger: ::slog::Logger,
}

// MonitorSocket does not implement debug, so we have to impl Debug manually
impl fmt::Debug for UdevBackend {
    /// `logger`  - slog Logger to be used by the backend and its `DrmDevices`.
    pub fn new<'a, L>(
        mut evlh: &mut EventLoopHandle, context: &Context, mut session: S, mut handler: T, logger: L
    ) -> Result<StateToken<UdevBackend<H, S, T>>>
    where
        L: Into<Option<::slog::Logger>>,
    {
    }
}

impl AsRawFd for UdevBackend {
    fn as_raw_fd(&self) -> RawFd {
        self.monitor.as_raw_fd()
    }
}

impl UdevBackend {
    /// Creates a new [`UdevBackend`]
    ///
    /// ## Arguments
    /// `seat`    - system seat which should be bound
    /// `logger`  - slog Logger to be used by the backend and its `DrmDevices`.
    pub fn new<L, S: AsRef<str>>(seat: S, logger: L) -> io::Result<UdevBackend>
    where
                ) {
                    // Call the handler, which might add it to the runloop
                    Ok(mut device) => {
                        let fd = device.as_raw_fd();
                        let devnum = device.device_id();
                        match handler.device_added(&mut evlh.state().as_proxy(), &mut device) {
                            Some(drm_handler) => {
                                let token = evlh.state().insert(device);
                                if let Ok(event_source) = drm_device_bind(&mut evlh, token.clone(), drm_handler) {
                                    Some((devnum, (token, event_source)))
                                } else {
                                    handler.device_removed(evlh.state(), &token);
                                    let device = evlh.state().remove(token);
                                    drop(device);
                                    if let Err(err) = session.close(fd) {
                                        warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);
                                    };
                                    None
                                }
                            },
                            None => {
            token: None,
            logger: log,
        })
    }

    /// Get a list of DRM devices currently known to the backend
    ///
    /// You should call this once before inserting the event source into your
    /// event loop, to get an initial snapshot of the device state.
    pub fn device_list(&self) -> impl Iterator<Item = (dev_t, &Path)> {
        self.devices.iter().map(|(&id, path)| (id, path.as_ref()))
                    }
                }
            })
            .collect::<HashMap<dev_t, (StateToken<DrmDevice<SessionFdDrmDevice>>, FdEventSource<(StateToken<DrmDevice<SessionFdDrmDevice>>, H)>)>>();

        let mut builder = MonitorBuilder::new(context).chain_err(|| ErrorKind::FailedToInitMonitor)?;
        builder
    type Error = io::Error;

    fn process_events<F>(
            .listen()
            .chain_err(|| ErrorKind::FailedToInitMonitor)?;

        Ok(evlh.state().insert(UdevBackend {
            devices,
            monitor,
            session,
            handler,
            logger,
        }))
    }

    /// Closes the udev backend and frees all remaining open devices.
    ///
    /// Needs to be called after the `FdEventSource` was removed and the backend was removed from
    /// the `EventLoop`'s `State`.
    ///
    /// ## Panics
    /// The given state might be passed to the registered `UdevHandler::device_removed` callback.
    /// Make sure not to borrow any tokens twice.
    pub fn close<'a, ST: Into<StateProxy<'a>>>(mut self, state: ST) {
        let mut state = state.into();
        for (_, (device, event_source)) in self.devices.drain() {
            event_source.remove();
            self.handler.device_removed(&mut state, &device);
            let device = state.remove(device);
            let fd = device.as_raw_fd();
            drop(device);
            if let Err(err) = self.session.close(fd) {
                // New device
                EventType::Add => {
                    if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) {
                        info!(self.logger, "New device: #{} at {}", devnum, path.display());
                        if self.devices.insert(devnum, path.to_path_buf()).is_none() {
                            callback(
                                UdevEvent::Added {
    }
}

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

    fn activate<'a>(&mut self, state: &mut StateProxy<'a>, devnum: Option<(u32, u32, Option<RawFd>)>) {
        state.with_value(self, |state, udev| {
            for &mut (ref mut device, _) in udev.devices.values_mut() {
                device.activate(state, devnum);
            }
        });
    }
}


/// Events generated by the [`UdevBackend`], notifying you of changes in system devices
/// Allows the backend to recieve kernel events and thus to drive the `UdevHandler`.
/// No runtime functionality can be provided without using this function.
pub fn udev_backend_bind<S, H, T>(
    evlh: &mut EventLoopHandle, udev: StateToken<UdevBackend<H, S, T>>
) -> IoResult<FdEventSource<StateToken<UdevBackend<H, S, T>>>>
where
    H: DrmHandler<SessionFdDrmDevice> + 'static,
    T: UdevHandler<H> + 'static,
    S: Session + 'static,
{
    let fd = evlh.state().get(&udev).monitor.as_raw_fd();
    evlh.add_fd_event_source(fd, fd_event_source_implementation(), udev, FdInterest::READ)
}

fn fd_event_source_implementation<S, H, T>() -> FdEventSourceImpl<StateToken<UdevBackend<H, S, T>>>
where
    H: DrmHandler<SessionFdDrmDevice> + 'static,
    T: UdevHandler<H> + 'static,
    S: Session + 'static,
{
    FdEventSourceImpl {
        ready: |mut evlh, token, _, _| {
            let events = evlh.state()
                .get(token)
                .monitor
                .clone()
                .collect::<Vec<Event>>();
            for event in events {
                match event.event_type() {
                    // New device
                    EventType::Add => {
                        info!(evlh.state().get(token).logger, "Device Added");
                        if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) {
                            let mut device = {
                                match DrmDevice::new(
                                    {
                                        let logger = evlh.state().get(token).logger.clone();
                                        match evlh.state().get_mut(token).session.open(
                                            path,
                                            fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY
                                                | fcntl::O_NONBLOCK,
            if seat_name == *seat.as_ref() {
                if let Ok(Some(pci)) = device.parent_with_subsystem(Path::new("pci")) {
                    if let Some(id) = pci.attribute_value("boot_vga") {
                        return id == "1";
                    }
                }
            }
            false
        })
        .flat_map(|device| device.devnode().map(PathBuf::from))
                                            }
                                        }
                                    },
                                    evlh.state().get(token).logger.clone(),
                                ) {
                                    Ok(dev) => dev,
                                    Err(err) => {
                                        warn!(
                                            evlh.state().get(token).logger,
                                            "Failed to initialize device {:?}. Error: {}. Skipping",
                                            path,
                                            err
pub fn all_gpus<S: AsRef<str>>(seat: S) -> io::Result<Vec<PathBuf>> {
    let mut enumerator = Enumerator::new()?;
    enumerator.match_subsystem("drm")?;
                                }
                            };
                            let fd = device.as_raw_fd();
                            match evlh.state().with_value(token, |state, udev| {
                                udev.handler.device_added(state, &mut device)
                            }) {
                                Some(drm_handler) => {
                                    let dev_token = evlh.state().insert(device);
                                    if let Ok(fd_event_source) =
                                        drm_device_bind(&mut evlh, dev_token.clone(), drm_handler)
                                    {
                                        evlh.state()
                                            .get_mut(token)
                                            .devices
                                            .insert(devnum, (dev_token, fd_event_source));
                                    } else {
                                        evlh.state().with_value(token, |state, udev| {
                                            let mut state: StateProxy = state.into();
                                            udev.handler.device_removed(&mut state, &dev_token);
                                            let device = state.remove(dev_token);
                                            drop(device);
                                            if let Err(err) = udev.session.close(fd) {
                                                warn!(
                                                    udev.logger,
                                                    "Failed to close dropped device. Error: {:?}. Ignoring",
                                                    err
                                                );
                                            };
                                        })
                                    }
                                }
                                None => {
                                    drop(device);
                                    evlh.state().with_value(token, |_state, udev| {
                                        if let Err(err) = udev.session.close(fd) {
                                            warn!(
                                                udev.logger,
                                                "Failed to close unused device. Error: {:?}", err
                                            );
                                        }
                                    })
                                }
                            };
                        }
                    }
                    // Device removed
                    EventType::Remove => evlh.state().with_value(token, |state, udev| {
                        info!(udev.logger, "Device Remove");
                        if let Some(devnum) = event.devnum() {
                            if let Some((device, fd_event_source)) = udev.devices.remove(&devnum) {
                                fd_event_source.remove();
                                let mut state: StateProxy = state.into();
                                udev.handler.device_removed(&mut state, &device);
                                let device = state.remove(device);
                                let fd = device.as_raw_fd();
                                drop(device);
                                if let Err(err) = udev.session.close(fd) {
                                };
                            }
                        }
                    }),
                    // New connector
                    EventType::Change => evlh.state().with_value(token, |state, udev| {
                        info!(udev.logger, "Device Changed");
                        if let Some(devnum) = event.devnum() {
                            info!(udev.logger, "Devnum: {:b}", devnum);
                            if let Some(&(ref device, _)) = udev.devices.get(&devnum) {
                                info!(udev.logger, "changed successful");
                                udev.handler.device_changed(state, device);
                            } else {
                                info!(udev.logger, "changed, but device not tracked by backend");
                            }
                        } else {
                            info!(udev.logger, "changed, but no devnum");
                        }
                    }),
                    _ => {}
                }
            }
        },
        error: |evlh, token, _, err| {
            evlh.state()
                .with_value(token, |state, udev| udev.handler.error(state, err))
        },
    }
}

    ///
    /// ## Panics
    /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
    fn device_added<'a, S: Into<StateProxy<'a>>>(
        &mut self, state: S, device: &mut DrmDevice<SessionFdDrmDevice>
    ) -> Option<H>;
    /// Called when an open device is changed.
    ///
    ///
    /// ## Panics
    /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
    fn device_changed<'a, S: Into<StateProxy<'a>>>(
        &mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>
    );
    /// Called when a device was removed.
    ///
    /// The device will not accept any operations anymore and its file descriptor will be closed once
    ///
    /// ## Panics
    /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
    fn device_removed<'a, S: Into<StateProxy<'a>>>(
        &mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>
    );
    /// Called when the udev context has encountered and error.
    ///
    /// ## Panics
    /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
    fn error<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, error: IoError);
}

/// Returns the path of the primary gpu device if any

<MSG> Merge pull request #64 from Smithay/feature/udev_handler_evlh

Introduce SessionObserver
<DFF> @@ -10,20 +10,22 @@
 //! backend.
 
 use backend::drm::{drm_device_bind, DrmDevice, DrmHandler};
-use backend::session::{Session, SessionObserver};
+use backend::session::{AsSessionObserver, Session, SessionObserver};
 use drm::Device as BasicDevice;
 use drm::control::Device as ControlDevice;
 use nix::fcntl;
 use nix::sys::stat::dev_t;
+use std::cell::RefCell;
 use std::collections::HashMap;
 use std::ffi::OsString;
-use std::io::{Error as IoError, Result as IoResult};
+use std::io::Error as IoError;
 use std::mem::drop;
 use std::os::unix::io::{AsRawFd, RawFd};
 use std::path::{Path, PathBuf};
+use std::rc::{Rc, Weak};
 use udev::{Context, Enumerator, Event, EventType, MonitorBuilder, MonitorSocket, Result as UdevResult};
-use wayland_server::{EventLoopHandle, StateProxy, StateToken};
-use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};
+use wayland_server::EventLoopHandle;
+use wayland_server::sources::{EventSource, FdEventSource, FdEventSourceImpl, FdInterest};
 
 /// Udev's `DrmDevice` type based on the underlying session
 pub struct SessionFdDrmDevice(RawFd);
@@ -46,13 +48,7 @@ pub struct UdevBackend<
     S: Session + 'static,
     T: UdevHandler<H> + 'static,
 > {
-    devices: HashMap<
-        dev_t,
-        (
-            StateToken<DrmDevice<SessionFdDrmDevice>>,
-            FdEventSource<(StateToken<DrmDevice<SessionFdDrmDevice>>, H)>,
-        ),
-    >,
+    devices: Rc<RefCell<HashMap<dev_t, FdEventSource<(DrmDevice<SessionFdDrmDevice>, H)>>>>,
     monitor: MonitorSocket,
     session: S,
     handler: T,
@@ -72,7 +68,7 @@ impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevH
     /// `logger`  - slog Logger to be used by the backend and its `DrmDevices`.
     pub fn new<'a, L>(
         mut evlh: &mut EventLoopHandle, context: &Context, mut session: S, mut handler: T, logger: L
-    ) -> Result<StateToken<UdevBackend<H, S, T>>>
+    ) -> Result<UdevBackend<H, S, T>>
     where
         L: Into<Option<::slog::Logger>>,
     {
@@ -96,21 +92,21 @@ impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevH
                 ) {
                     // Call the handler, which might add it to the runloop
                     Ok(mut device) => {
-                        let fd = device.as_raw_fd();
                         let devnum = device.device_id();
-                        match handler.device_added(&mut evlh.state().as_proxy(), &mut device) {
+                        let fd = device.as_raw_fd();
+                        match handler.device_added(evlh, &mut device) {
                             Some(drm_handler) => {
-                                let token = evlh.state().insert(device);
-                                if let Ok(event_source) = drm_device_bind(&mut evlh, token.clone(), drm_handler) {
-                                    Some((devnum, (token, event_source)))
-                                } else {
-                                    handler.device_removed(evlh.state(), &token);
-                                    let device = evlh.state().remove(token);
-                                    drop(device);
-                                    if let Err(err) = session.close(fd) {
-                                        warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);
-                                    };
-                                    None
+                                match drm_device_bind(&mut evlh, device, drm_handler) {
+                                    Ok(event_source) => Some((devnum, event_source)),
+                                    Err((err, (mut device, _))) => {
+                                        warn!(logger, "Failed to bind device. Error: {:?}.", err);
+                                        handler.device_removed(evlh, &mut device);
+                                        drop(device);
+                                        if let Err(err) = session.close(fd) {
+                                            warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);
+                                        };
+                                        None
+                                    }
                                 }
                             },
                             None => {
@@ -128,7 +124,7 @@ impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevH
                     }
                 }
             })
-            .collect::<HashMap<dev_t, (StateToken<DrmDevice<SessionFdDrmDevice>>, FdEventSource<(StateToken<DrmDevice<SessionFdDrmDevice>>, H)>)>>();
+            .collect::<HashMap<dev_t, FdEventSource<(DrmDevice<SessionFdDrmDevice>, H)>>>();
 
         let mut builder = MonitorBuilder::new(context).chain_err(|| ErrorKind::FailedToInitMonitor)?;
         builder
@@ -138,29 +134,21 @@ impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevH
             .listen()
             .chain_err(|| ErrorKind::FailedToInitMonitor)?;
 
-        Ok(evlh.state().insert(UdevBackend {
-            devices,
+        Ok(UdevBackend {
+            devices: Rc::new(RefCell::new(devices)),
             monitor,
             session,
             handler,
             logger,
-        }))
+        })
     }
 
     /// Closes the udev backend and frees all remaining open devices.
-    ///
-    /// Needs to be called after the `FdEventSource` was removed and the backend was removed from
-    /// the `EventLoop`'s `State`.
-    ///
-    /// ## Panics
-    /// The given state might be passed to the registered `UdevHandler::device_removed` callback.
-    /// Make sure not to borrow any tokens twice.
-    pub fn close<'a, ST: Into<StateProxy<'a>>>(mut self, state: ST) {
-        let mut state = state.into();
-        for (_, (device, event_source)) in self.devices.drain() {
-            event_source.remove();
-            self.handler.device_removed(&mut state, &device);
-            let device = state.remove(device);
+    pub fn close(&mut self, evlh: &mut EventLoopHandle) {
+        let mut devices = self.devices.borrow_mut();
+        for (_, event_source) in devices.drain() {
+            let (mut device, _) = event_source.remove();
+            self.handler.device_removed(evlh, &mut device);
             let fd = device.as_raw_fd();
             drop(device);
             if let Err(err) = self.session.close(fd) {
@@ -174,26 +162,47 @@ impl<H: DrmHandler<SessionFdDrmDevice> + 'static, S: Session + 'static, T: UdevH
     }
 }
 
+/// `SessionObserver` linked to the `UdevBackend` it was created from.
+pub struct UdevBackendObserver<H: DrmHandler<SessionFdDrmDevice> + 'static> {
+    devices: Weak<RefCell<HashMap<dev_t, FdEventSource<(DrmDevice<SessionFdDrmDevice>, H)>>>>,
+    logger: ::slog::Logger,
+}
+
 impl<
     H: DrmHandler<SessionFdDrmDevice> + 'static,
     S: Session + 'static,
     T: UdevHandler<H> + 'static,
-> SessionObserver for StateToken<UdevBackend<H, S, T>>
+> AsSessionObserver<UdevBackendObserver<H>> for UdevBackend<H, S, T>
 {
-    fn pause<'a>(&mut self, state: &mut StateProxy<'a>, devnum: Option<(u32, u32)>) {
-        state.with_value(self, |state, udev| {
-            for &mut (ref mut device, _) in udev.devices.values_mut() {
-                device.pause(state, devnum);
+    fn observer(&mut self) -> UdevBackendObserver<H> {
+        UdevBackendObserver {
+            devices: Rc::downgrade(&self.devices),
+            logger: self.logger.clone(),
+        }
+    }
+}
+
+impl<H: DrmHandler<SessionFdDrmDevice> + 'static> SessionObserver for UdevBackendObserver<H> {
+    fn pause<'a>(&mut self, evlh: &mut EventLoopHandle, devnum: Option<(u32, u32)>) {
+        if let Some(devices) = self.devices.upgrade() {
+            for fd_event_source in devices.borrow_mut().values_mut() {
+                fd_event_source.with_idata(evlh, |&mut (ref mut device, _), evlh| {
+                    info!(self.logger, "changed successful");
+                    device.observer().pause(evlh, devnum);
+                })
             }
-        });
+        }
     }
 
-    fn activate<'a>(&mut self, state: &mut StateProxy<'a>, devnum: Option<(u32, u32, Option<RawFd>)>) {
-        state.with_value(self, |state, udev| {
-            for &mut (ref mut device, _) in udev.devices.values_mut() {
-                device.activate(state, devnum);
+    fn activate<'a>(&mut self, evlh: &mut EventLoopHandle, devnum: Option<(u32, u32, Option<RawFd>)>) {
+        if let Some(devices) = self.devices.upgrade() {
+            for fd_event_source in devices.borrow_mut().values_mut() {
+                fd_event_source.with_idata(evlh, |&mut (ref mut device, _), evlh| {
+                    info!(self.logger, "changed successful");
+                    device.observer().activate(evlh, devnum);
+                })
             }
-        });
+        }
     }
 }
 
@@ -202,41 +211,37 @@ impl<
 /// Allows the backend to recieve kernel events and thus to drive the `UdevHandler`.
 /// No runtime functionality can be provided without using this function.
 pub fn udev_backend_bind<S, H, T>(
-    evlh: &mut EventLoopHandle, udev: StateToken<UdevBackend<H, S, T>>
-) -> IoResult<FdEventSource<StateToken<UdevBackend<H, S, T>>>>
+    evlh: &mut EventLoopHandle, udev: UdevBackend<H, S, T>
+) -> ::std::result::Result<FdEventSource<UdevBackend<H, S, T>>, (IoError, UdevBackend<H, S, T>)>
 where
     H: DrmHandler<SessionFdDrmDevice> + 'static,
     T: UdevHandler<H> + 'static,
     S: Session + 'static,
 {
-    let fd = evlh.state().get(&udev).monitor.as_raw_fd();
+    let fd = udev.monitor.as_raw_fd();
     evlh.add_fd_event_source(fd, fd_event_source_implementation(), udev, FdInterest::READ)
 }
 
-fn fd_event_source_implementation<S, H, T>() -> FdEventSourceImpl<StateToken<UdevBackend<H, S, T>>>
+fn fd_event_source_implementation<S, H, T>() -> FdEventSourceImpl<UdevBackend<H, S, T>>
 where
     H: DrmHandler<SessionFdDrmDevice> + 'static,
     T: UdevHandler<H> + 'static,
     S: Session + 'static,
 {
     FdEventSourceImpl {
-        ready: |mut evlh, token, _, _| {
-            let events = evlh.state()
-                .get(token)
-                .monitor
-                .clone()
-                .collect::<Vec<Event>>();
+        ready: |mut evlh, udev, _, _| {
+            let events = udev.monitor.clone().collect::<Vec<Event>>();
             for event in events {
                 match event.event_type() {
                     // New device
                     EventType::Add => {
-                        info!(evlh.state().get(token).logger, "Device Added");
+                        info!(udev.logger, "Device Added");
                         if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) {
                             let mut device = {
                                 match DrmDevice::new(
                                     {
-                                        let logger = evlh.state().get(token).logger.clone();
-                                        match evlh.state().get_mut(token).session.open(
+                                        let logger = udev.logger.clone();
+                                        match udev.session.open(
                                             path,
                                             fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY
                                                 | fcntl::O_NONBLOCK,
@@ -253,12 +258,12 @@ where
                                             }
                                         }
                                     },
-                                    evlh.state().get(token).logger.clone(),
+                                    udev.logger.clone(),
                                 ) {
                                     Ok(dev) => dev,
                                     Err(err) => {
                                         warn!(
-                                            evlh.state().get(token).logger,
+                                            udev.logger,
                                             "Failed to initialize device {:?}. Error: {}. Skipping",
                                             path,
                                             err
@@ -268,57 +273,43 @@ where
                                 }
                             };
                             let fd = device.as_raw_fd();
-                            match evlh.state().with_value(token, |state, udev| {
-                                udev.handler.device_added(state, &mut device)
-                            }) {
-                                Some(drm_handler) => {
-                                    let dev_token = evlh.state().insert(device);
-                                    if let Ok(fd_event_source) =
-                                        drm_device_bind(&mut evlh, dev_token.clone(), drm_handler)
-                                    {
-                                        evlh.state()
-                                            .get_mut(token)
-                                            .devices
-                                            .insert(devnum, (dev_token, fd_event_source));
-                                    } else {
-                                        evlh.state().with_value(token, |state, udev| {
-                                            let mut state: StateProxy = state.into();
-                                            udev.handler.device_removed(&mut state, &dev_token);
-                                            let device = state.remove(dev_token);
-                                            drop(device);
-                                            if let Err(err) = udev.session.close(fd) {
-                                                warn!(
-                                                    udev.logger,
-                                                    "Failed to close dropped device. Error: {:?}. Ignoring",
-                                                    err
-                                                );
-                                            };
-                                        })
+                            match udev.handler.device_added(evlh, &mut device) {
+                                Some(drm_handler) => match drm_device_bind(&mut evlh, device, drm_handler) {
+                                    Ok(fd_event_source) => {
+                                        udev.devices.borrow_mut().insert(devnum, fd_event_source);
                                     }
-                                }
-                                None => {
-                                    drop(device);
-                                    evlh.state().with_value(token, |_state, udev| {
+                                    Err((err, (mut device, _))) => {
+                                        warn!(udev.logger, "Failed to bind device. Error: {:?}.", err);
+                                        udev.handler.device_removed(evlh, &mut device);
+                                        drop(device);
                                         if let Err(err) = udev.session.close(fd) {
                                             warn!(
                                                 udev.logger,
-                                                "Failed to close unused device. Error: {:?}", err
+                                                "Failed to close dropped device. Error: {:?}. Ignoring", err
                                             );
-                                        }
-                                    })
+                                        };
+                                    }
+                                },
+                                None => {
+                                    udev.handler.device_removed(evlh, &mut device);
+                                    drop(device);
+                                    if let Err(err) = udev.session.close(fd) {
+                                        warn!(
+                                            udev.logger,
+                                            "Failed to close unused device. Error: {:?}", err
+                                        );
+                                    }
                                 }
                             };
                         }
                     }
                     // Device removed
-                    EventType::Remove => evlh.state().with_value(token, |state, udev| {
+                    EventType::Remove => {
                         info!(udev.logger, "Device Remove");
                         if let Some(devnum) = event.devnum() {
-                            if let Some((device, fd_event_source)) = udev.devices.remove(&devnum) {
-                                fd_event_source.remove();
-                                let mut state: StateProxy = state.into();
-                                udev.handler.device_removed(&mut state, &device);
-                                let device = state.remove(device);
+                            if let Some(fd_event_source) = udev.devices.borrow_mut().remove(&devnum) {
+                                let (mut device, _) = fd_event_source.remove();
+                                udev.handler.device_removed(evlh, &mut device);
                                 let fd = device.as_raw_fd();
                                 drop(device);
                                 if let Err(err) = udev.session.close(fd) {
@@ -331,30 +322,31 @@ where
                                 };
                             }
                         }
-                    }),
+                    }
                     // New connector
-                    EventType::Change => evlh.state().with_value(token, |state, udev| {
+                    EventType::Change => {
                         info!(udev.logger, "Device Changed");
                         if let Some(devnum) = event.devnum() {
                             info!(udev.logger, "Devnum: {:b}", devnum);
-                            if let Some(&(ref device, _)) = udev.devices.get(&devnum) {
-                                info!(udev.logger, "changed successful");
-                                udev.handler.device_changed(state, device);
+                            if let Some(fd_event_source) = udev.devices.borrow_mut().get_mut(&devnum) {
+                                let handler = &mut udev.handler;
+                                let logger = &udev.logger;
+                                fd_event_source.with_idata(evlh, move |&mut (ref mut device, _), evlh| {
+                                    info!(logger, "changed successful");
+                                    handler.device_changed(evlh, device);
+                                })
                             } else {
                                 info!(udev.logger, "changed, but device not tracked by backend");
-                            }
+                            };
                         } else {
                             info!(udev.logger, "changed, but no devnum");
                         }
-                    }),
+                    }
                     _ => {}
                 }
             }
         },
-        error: |evlh, token, _, err| {
-            evlh.state()
-                .with_value(token, |state, udev| udev.handler.error(state, err))
-        },
+        error: |evlh, udev, _, err| udev.handler.error(evlh, err),
     }
 }
 
@@ -366,8 +358,8 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + 'static> {
     ///
     /// ## Panics
     /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
-    fn device_added<'a, S: Into<StateProxy<'a>>>(
-        &mut self, state: S, device: &mut DrmDevice<SessionFdDrmDevice>
+    fn device_added(
+        &mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>
     ) -> Option<H>;
     /// Called when an open device is changed.
     ///
@@ -376,9 +368,7 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + 'static> {
     ///
     /// ## Panics
     /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
-    fn device_changed<'a, S: Into<StateProxy<'a>>>(
-        &mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>
-    );
+    fn device_changed(&mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>);
     /// Called when a device was removed.
     ///
     /// The device will not accept any operations anymore and its file descriptor will be closed once
@@ -386,14 +376,12 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + 'static> {
     ///
     /// ## Panics
     /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
-    fn device_removed<'a, S: Into<StateProxy<'a>>>(
-        &mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>
-    );
+    fn device_removed(&mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>);
     /// Called when the udev context has encountered and error.
     ///
     /// ## Panics
     /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.
-    fn error<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, error: IoError);
+    fn error(&mut self, evlh: &mut EventLoopHandle, error: IoError);
 }
 
 /// Returns the path of the primary gpu device if any

{'commit': 'diff --git a/Cargo.toml b/Cargo.toml\nindex c01f8a7e..4f99f5b0 100644\n--- a/Cargo.toml\n+++ b/Cargo.toml\n@@ -7,8 +7,8 @@ description = "Smithay is a library for writing wayland compositors."\n repository = "https://github.com/Smithay/smithay"\n \n [dependencies]\n-wayland-server = "0.12.5"\n-wayland-sys = "0.12.5"\n+wayland-server = "0.14.0"\n+wayland-sys = "0.14.0"\n nix = "0.9.0"\n xkbcommon = "0.2.1"\n tempfile = "2.1.5"\n@@ -24,7 +24,7 @@ input = { version = "0.4.0", optional = true }\n udev = { version = "0.2.0", optional = true }\n dbus = { version = "0.6.1", optional = true }\n systemd = { version = "^0.2.0", optional = true }\n-wayland-protocols = { version = "0.12.5", features = ["unstable_protocols", "server"] }\n+wayland-protocols = { version = "0.14.0", features = ["unstable_protocols", "server"] }\n image = "0.17.0"\n error-chain = "0.11.0"\n lazy_static = "1.0.0"\ndiff --git a/examples/drm.rs b/examples/drm.rs\nindex ad1e4182..86e81b90 100644\n--- a/examples/drm.rs\n+++ b/examples/drm.rs\n@@ -34,6 +34,7 @@ use std::os::unix::io::AsRawFd;\n use std::os::unix::io::RawFd;\n use std::rc::Rc;\n use std::time::Duration;\n+use wayland_server::EventLoopHandle;\n \n #[derive(Debug)]\n pub struct Card(File);\n@@ -137,17 +138,17 @@ fn main() {\n     /*\n      * Register the DrmDevice on the EventLoop\n      */\n-    let device_token = event_loop.state().insert(device);\n     let _source = drm_device_bind(\n         &mut event_loop,\n-        device_token,\n+        device,\n         DrmHandlerImpl {\n             compositor_token,\n             window_map: window_map.clone(),\n             drawer: renderer,\n             logger: log,\n         },\n-    ).unwrap();\n+    ).map_err(|(err, _)| err)\n+        .unwrap();\n \n     loop {\n         event_loop.dispatch(Some(16)).unwrap();\n@@ -166,7 +167,8 @@ pub struct DrmHandlerImpl {\n \n impl DrmHandler<Card> for DrmHandlerImpl {\n     fn ready(\n-        &mut self, _device: &mut DrmDevice<Card>, _crtc: crtc::Handle, _frame: u32, _duration: Duration\n+        &mut self, _evlh: &mut EventLoopHandle, _device: &mut DrmDevice<Card>, _crtc: crtc::Handle,\n+        _frame: u32, _duration: Duration,\n     ) {\n         let mut frame = self.drawer.draw();\n         frame.clear_color(0.8, 0.8, 0.9, 1.0);\n@@ -246,7 +248,7 @@ impl DrmHandler<Card> for DrmHandlerImpl {\n         frame.finish().unwrap();\n     }\n \n-    fn error(&mut self, _device: &mut DrmDevice<Card>, error: DrmError) {\n+    fn error(&mut self, _evlh: &mut EventLoopHandle, _device: &mut DrmDevice<Card>, error: DrmError) {\n         panic!("{:?}", error);\n     }\n }\ndiff --git a/examples/udev.rs b/examples/udev.rs\nindex 4fd1a66d..cfe51343 100644\n--- a/examples/udev.rs\n+++ b/examples/udev.rs\n@@ -54,8 +54,9 @@ use std::rc::Rc;\n use std::sync::Arc;\n use std::sync::atomic::{AtomicBool, Ordering};\n use std::time::Duration;\n-use wayland_server::{Display, EventLoopHandle, StateProxy, StateToken};\n+use wayland_server::{Display, EventLoopHandle};\n use wayland_server::protocol::{wl_output, wl_pointer};\n+use wayland_server::sources::EventSource;\n use xkbcommon::xkb::keysyms as xkb;\n \n struct LibinputInputHandler {\n@@ -270,7 +271,7 @@ fn main() {\n     let primary_gpu = primary_gpu(&context, &seat).unwrap_or_default();\n \n     let bytes = include_bytes!("resources/cursor2.rgba");\n-    let udev_token = UdevBackend::new(\n+    let mut udev_backend = UdevBackend::new(\n         &mut event_loop,\n         &context,\n         session.clone(),\n@@ -288,7 +289,7 @@ fn main() {\n         log.clone(),\n     ).unwrap();\n \n-    let udev_session_id = notifier.register(udev_token.clone());\n+    let udev_session_id = notifier.register(&mut udev_backend);\n \n     let (seat_token, _) = Seat::new(&mut event_loop, session.seat().into(), log.clone());\n \n@@ -339,7 +340,7 @@ fn main() {\n      */\n     let mut libinput_context =\n         Libinput::new_from_udev::<LibinputSessionInterface<AutoSession>>(session.clone().into(), &context);\n-    let libinput_session_id = notifier.register(libinput_context.clone());\n+    let libinput_session_id = notifier.register(&mut libinput_context);\n     libinput_context.udev_assign_seat(&seat).unwrap();\n     let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());\n     libinput_backend.set_handler(\n@@ -356,10 +357,16 @@ fn main() {\n             running: running.clone(),\n         },\n     );\n-    let libinput_event_source = libinput_bind(libinput_backend, &mut event_loop).unwrap();\n+    let libinput_event_source = libinput_bind(libinput_backend, &mut event_loop)\n+        .map_err(|(err, _)| err)\n+        .unwrap();\n \n-    let session_event_source = auto_session_bind(notifier, &mut event_loop).unwrap();\n-    let udev_event_source = udev_backend_bind(&mut event_loop, udev_token).unwrap();\n+    let session_event_source = auto_session_bind(notifier, &mut event_loop)\n+        .map_err(|(err, _)| err)\n+        .unwrap();\n+    let udev_event_source = udev_backend_bind(&mut event_loop, udev_backend)\n+        .map_err(|(err, _)| err)\n+        .unwrap();\n \n     while running.load(Ordering::SeqCst) {\n         if let Err(_) = event_loop.dispatch(Some(16)) {\n@@ -378,9 +385,8 @@ fn main() {\n \n     libinput_event_source.remove();\n \n-    let udev_token = udev_event_source.remove();\n-    let udev = event_loop.state().remove(udev_token);\n-    udev.close(event_loop.state());\n+    // destroy the udev backend freeing the drm devices\n+    udev_event_source.remove().close(&mut event_loop)\n }\n \n struct UdevHandlerImpl {\n@@ -455,8 +461,8 @@ impl UdevHandlerImpl {\n }\n \n impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {\n-    fn device_added<\'a, S: Into<StateProxy<\'a>>>(\n-        &mut self, _state: S, device: &mut DrmDevice<SessionFdDrmDevice>\n+    fn device_added(\n+        &mut self, _evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>\n     ) -> Option<DrmHandlerImpl> {\n         // init hardware acceleration on the primary gpu.\n         if device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {\n@@ -475,21 +481,13 @@ impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {\n         })\n     }\n \n-    fn device_changed<\'a, S: Into<StateProxy<\'a>>>(\n-        &mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>\n-    ) {\n+    fn device_changed(&mut self, _evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>) {\n         //quick and dirt, just re-init all backends\n-        let mut state = state.into();\n-        let backends = self.backends.get(&state.get(device).device_id()).unwrap();\n-        *backends.borrow_mut() = self.scan_connectors(state.get_mut(device));\n+        let backends = self.backends.get(&device.device_id()).unwrap();\n+        *backends.borrow_mut() = self.scan_connectors(device);\n     }\n \n-    fn device_removed<\'a, S: Into<StateProxy<\'a>>>(\n-        &mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>\n-    ) {\n-        let state = state.into();\n-        let device = state.get(device);\n-\n+    fn device_removed(&mut self, _evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>) {\n         // drop the backends on this side\n         self.backends.remove(&device.device_id());\n \n@@ -499,7 +497,7 @@ impl UdevHandler<DrmHandlerImpl> for UdevHandlerImpl {\n         }\n     }\n \n-    fn error<\'a, S: Into<StateProxy<\'a>>>(&mut self, _state: S, error: IoError) {\n+    fn error(&mut self, _evlh: &mut EventLoopHandle, error: IoError) {\n         error!(self.logger, "{:?}", error);\n     }\n }\n@@ -514,8 +512,8 @@ pub struct DrmHandlerImpl {\n \n impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {\n     fn ready(\n-        &mut self, _device: &mut DrmDevice<SessionFdDrmDevice>, crtc: crtc::Handle, _frame: u32,\n-        _duration: Duration,\n+        &mut self, _evlh: &mut EventLoopHandle, _device: &mut DrmDevice<SessionFdDrmDevice>,\n+        crtc: crtc::Handle, _frame: u32, _duration: Duration,\n     ) {\n         if let Some(drawer) = self.backends.borrow().get(&crtc) {\n             {\n@@ -605,7 +603,9 @@ impl DrmHandler<SessionFdDrmDevice> for DrmHandlerImpl {\n         }\n     }\n \n-    fn error(&mut self, _device: &mut DrmDevice<SessionFdDrmDevice>, error: DrmError) {\n+    fn error(\n+        &mut self, _evlh: &mut EventLoopHandle, _device: &mut DrmDevice<SessionFdDrmDevice>, error: DrmError\n+    ) {\n         error!(self.logger, "{:?}", error);\n     }\n }\ndiff --git a/src/backend/drm/mod.rs b/src/backend/drm/mod.rs\nindex d4260e5a..91fe4b3c 100644\n--- a/src/backend/drm/mod.rs\n+++ b/src/backend/drm/mod.rs\n@@ -52,7 +52,6 @@\n //! use std::os::unix::io::RawFd;\n //! use std::os::unix::io::AsRawFd;\n //! use smithay::backend::drm::{DrmDevice, DrmBackend};\n-//! use wayland_server::StateToken;\n //!\n //! #[derive(Debug)]\n //! pub struct Card(File);\n@@ -140,6 +139,7 @@\n //! # use std::time::Duration;\n //! use smithay::backend::drm::{DrmDevice, DrmBackend, DrmHandler, drm_device_bind};\n //! use smithay::backend::graphics::egl::EGLGraphicsBackend;\n+//! use wayland_server::EventLoopHandle;\n //! #\n //! # #[derive(Debug)]\n //! # pub struct Card(File);\n@@ -181,6 +181,7 @@\n //! impl DrmHandler<Card> for MyDrmHandler {\n //!     fn ready(\n //!         &mut self,\n+//!         _evlh: &mut EventLoopHandle,\n //!         _device: &mut DrmDevice<Card>,\n //!         _crtc: CrtcHandle,\n //!         _frame: u32,\n@@ -191,6 +192,7 @@\n //!     }\n //!     fn error(\n //!         &mut self,\n+//!         _evlh: &mut EventLoopHandle,\n //!         device: &mut DrmDevice<Card>,\n //!         error: DrmError)\n //!     {\n@@ -201,8 +203,7 @@\n //! // render something (like clear_color)\n //! backend.swap_buffers().unwrap();\n //!\n-//! let device_token = event_loop.state().insert(device);\n-//! let _source = drm_device_bind(&mut event_loop, device_token, MyDrmHandler(backend)).unwrap();\n+//! let _source = drm_device_bind(&mut event_loop, device, MyDrmHandler(backend)).map_err(|(err, _)| err).unwrap();\n //!\n //! event_loop.run().unwrap();\n //! # }\n@@ -213,7 +214,7 @@ use backend::graphics::egl::error::Result as EGLResult;\n use backend::graphics::egl::native::Gbm;\n use backend::graphics::egl::wayland::{EGLDisplay, EGLWaylandExtensions};\n #[cfg(feature = "backend_session")]\n-use backend::session::SessionObserver;\n+use backend::session::{AsSessionObserver, SessionObserver};\n use drm::Device as BasicDevice;\n use drm::control::{connector, crtc, encoder, Mode, ResourceInfo};\n use drm::control::Device as ControlDevice;\n@@ -222,17 +223,17 @@ use drm::result::Error as DrmError;\n use gbm::{BufferObject, Device as GbmDevice};\n use nix;\n use nix::sys::stat::{self, dev_t, fstat};\n+use std::cell::RefCell;\n use std::collections::HashMap;\n use std::hash::{Hash, Hasher};\n-use std::io::Result as IoResult;\n+use std::io::Error as IoError;\n use std::os::unix::io::{AsRawFd, RawFd};\n use std::path::PathBuf;\n use std::rc::{Rc, Weak};\n-use std::sync::{Once, ONCE_INIT};\n+use std::sync::{Arc, Once, ONCE_INIT};\n+use std::sync::atomic::{AtomicBool, Ordering};\n use std::time::Duration;\n-use wayland_server::{Display, EventLoopHandle, StateToken};\n-#[cfg(feature = "backend_session")]\n-use wayland_server::StateProxy;\n+use wayland_server::{Display, EventLoopHandle};\n use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};\n \n mod backend;\n@@ -249,8 +250,8 @@ pub struct DrmDevice<A: ControlDevice + \'static> {\n     context: Rc<EGLContext<Gbm<framebuffer::Info>, GbmDevice<A>>>,\n     old_state: HashMap<crtc::Handle, (crtc::Info, Vec<connector::Handle>)>,\n     device_id: dev_t,\n-    backends: HashMap<crtc::Handle, Weak<DrmBackendInternal<A>>>,\n-    active: bool,\n+    backends: Rc<RefCell<HashMap<crtc::Handle, Weak<DrmBackendInternal<A>>>>>,\n+    active: Arc<AtomicBool>,\n     priviledged: bool,\n     logger: ::slog::Logger,\n }\n@@ -316,10 +317,10 @@ impl<A: ControlDevice + \'static> DrmDevice<A> {\n                 Default::default(),\n                 log.clone(),\n             ).map_err(Error::from)?),\n-            backends: HashMap::new(),\n+            backends: Rc::new(RefCell::new(HashMap::new())),\n             device_id,\n             old_state: HashMap::new(),\n-            active: true,\n+            active: Arc::new(AtomicBool::new(true)),\n             priviledged: true,\n             logger: log.clone(),\n         };\n@@ -382,11 +383,11 @@ impl<A: ControlDevice + \'static> DrmDevice<A> {\n     where\n         I: Into<Vec<connector::Handle>>,\n     {\n-        if self.backends.contains_key(&crtc) {\n+        if self.backends.borrow().contains_key(&crtc) {\n             bail!(ErrorKind::CrtcAlreadyInUse(crtc));\n         }\n \n-        if !self.active {\n+        if !self.active.load(Ordering::SeqCst) {\n             bail!(ErrorKind::DeviceInactive);\n         }\n \n@@ -441,7 +442,7 @@ impl<A: ControlDevice + \'static> DrmDevice<A> {\n \n         let logger = self.logger.new(o!("crtc" => format!("{:?}", crtc)));\n         let backend = DrmBackend::new(self.context.clone(), crtc, mode, connectors, logger)?;\n-        self.backends.insert(crtc, backend.weak());\n+        self.backends.borrow_mut().insert(crtc, backend.weak());\n         Ok(backend)\n     }\n \n@@ -531,25 +532,28 @@ impl<A: ControlDevice + \'static> Drop for DrmDevice<A> {\n pub trait DrmHandler<A: ControlDevice + \'static> {\n     /// The `DrmBackend` of crtc has finished swapping buffers and new frame can now\n     /// (and should be immediately) be rendered.\n-    fn ready(&mut self, device: &mut DrmDevice<A>, crtc: crtc::Handle, frame: u32, duration: Duration);\n+    fn ready(\n+        &mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice<A>, crtc: crtc::Handle, frame: u32,\n+        duration: Duration,\n+    );\n     /// The `DrmDevice` has thrown an error.\n     ///\n     /// The related backends are most likely *not* usable anymore and\n     /// the whole stack has to be recreated..\n-    fn error(&mut self, device: &mut DrmDevice<A>, error: DrmError);\n+    fn error(&mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice<A>, error: DrmError);\n }\n \n /// Bind a `DrmDevice` to an `EventLoop`,\n ///\n /// This will cause it to recieve events and feed them into an `DrmHandler`\n pub fn drm_device_bind<A, H>(\n-    evlh: &mut EventLoopHandle, device: StateToken<DrmDevice<A>>, handler: H\n-) -> IoResult<FdEventSource<(StateToken<DrmDevice<A>>, H)>>\n+    evlh: &mut EventLoopHandle, device: DrmDevice<A>, handler: H\n+) -> ::std::result::Result<FdEventSource<(DrmDevice<A>, H)>, (IoError, (DrmDevice<A>, H))>\n where\n     A: ControlDevice + \'static,\n     H: DrmHandler<A> + \'static,\n {\n-    let fd = evlh.state().get(&device).as_raw_fd();\n+    let fd = device.as_raw_fd();\n     evlh.add_fd_event_source(\n         fd,\n         fd_event_source_implementation(),\n@@ -558,26 +562,19 @@ where\n     )\n }\n \n-fn fd_event_source_implementation<A, H>() -> FdEventSourceImpl<(StateToken<DrmDevice<A>>, H)>\n+fn fd_event_source_implementation<A, H>() -> FdEventSourceImpl<(DrmDevice<A>, H)>\n where\n     A: ControlDevice + \'static,\n     H: DrmHandler<A> + \'static,\n {\n     FdEventSourceImpl {\n-        ready: |evlh, &mut (ref mut dev_token, ref mut handler), _, _| {\n-            let (events, logger) = {\n-                let dev = evlh.state().get(dev_token);\n-                let events = crtc::receive_events(dev);\n-                let logger = dev.logger.clone();\n-                (events, logger)\n-            };\n-\n-            match events {\n+        ready: |evlh, &mut (ref mut device, ref mut handler), _, _| {\n+            match crtc::receive_events(device) {\n                 Ok(events) => for event in events {\n                     if let crtc::Event::PageFlip(event) = event {\n-                        let dev = evlh.state().get_mut(dev_token);\n-                        if dev.active {\n-                            if let Some(backend) = dev.backends\n+                        if device.active.load(Ordering::SeqCst) {\n+                            let backends = device.backends.borrow().clone();\n+                            if let Some(backend) = backends\n                                 .get(&event.crtc)\n                                 .iter()\n                                 .flat_map(|x| x.upgrade())\n@@ -585,91 +582,120 @@ where\n                             {\n                                 // we can now unlock the buffer\n                                 backend.unlock_buffer();\n-                                trace!(logger, "Handling event for backend {:?}", event.crtc);\n+                                trace!(device.logger, "Handling event for backend {:?}", event.crtc);\n                                 // and then call the user to render the next frame\n-                                handler.ready(dev, event.crtc, event.frame, event.duration);\n+                                handler.ready(evlh, device, event.crtc, event.frame, event.duration);\n                             } else {\n-                                dev.backends.remove(&event.crtc);\n+                                device.backends.borrow_mut().remove(&event.crtc);\n                             }\n                         }\n                     }\n                 },\n-                Err(err) => handler.error(evlh.state().get_mut(dev_token), err),\n+                Err(err) => handler.error(evlh, device, err),\n             };\n         },\n-        error: |evlh, &mut (ref mut dev_token, ref mut handler), _, error| {\n-            let mut dev = evlh.state().get_mut(dev_token);\n-            warn!(dev.logger, "DrmDevice errored: {}", error);\n-            handler.error(&mut dev, error.into());\n+        error: |evlh, &mut (ref mut device, ref mut handler), _, error| {\n+            warn!(device.logger, "DrmDevice errored: {}", error);\n+            handler.error(evlh, device, error.into());\n         },\n     }\n }\n \n+/// `SessionObserver` linked to the `DrmDevice` it was created from.\n+pub struct DrmDeviceObserver<A: ControlDevice + \'static> {\n+    context: Weak<EGLContext<Gbm<framebuffer::Info>, GbmDevice<A>>>,\n+    device_id: dev_t,\n+    backends: Rc<RefCell<HashMap<crtc::Handle, Weak<DrmBackendInternal<A>>>>>,\n+    old_state: HashMap<crtc::Handle, (crtc::Info, Vec<connector::Handle>)>,\n+    active: Arc<AtomicBool>,\n+    priviledged: bool,\n+    logger: ::slog::Logger,\n+}\n+\n+#[cfg(feature = "backend_session")]\n+impl<A: ControlDevice + \'static> AsSessionObserver<DrmDeviceObserver<A>> for DrmDevice<A> {\n+    fn observer(&mut self) -> DrmDeviceObserver<A> {\n+        DrmDeviceObserver {\n+            context: Rc::downgrade(&self.context),\n+            device_id: self.device_id.clone(),\n+            backends: self.backends.clone(),\n+            old_state: self.old_state.clone(),\n+            active: self.active.clone(),\n+            priviledged: self.priviledged,\n+            logger: self.logger.clone(),\n+        }\n+    }\n+}\n+\n #[cfg(feature = "backend_session")]\n-impl<A: ControlDevice + \'static> SessionObserver for StateToken<DrmDevice<A>> {\n-    fn pause<\'a>(&mut self, state: &mut StateProxy<\'a>, devnum: Option<(u32, u32)>) {\n-        let device = state.get_mut(self);\n+impl<A: ControlDevice + \'static> SessionObserver for DrmDeviceObserver<A> {\n+    fn pause(&mut self, _evlh: &mut EventLoopHandle, devnum: Option<(u32, u32)>) {\n         if let Some((major, minor)) = devnum {\n-            if major as u64 != stat::major(device.device_id) || minor as u64 != stat::minor(device.device_id)\n-            {\n+            if major as u64 != stat::major(self.device_id) || minor as u64 != stat::minor(self.device_id) {\n                 return;\n             }\n         }\n-        for (handle, &(ref info, ref connectors)) in device.old_state.iter() {\n-            if let Err(err) = crtc::set(\n-                &*device.context,\n-                *handle,\n-                info.fb(),\n-                connectors,\n-                info.position(),\n-                info.mode(),\n-            ) {\n-                error!(\n-                    device.logger,\n-                    "Failed to reset crtc ({:?}). Error: {}", handle, err\n-                );\n+        if let Some(device) = self.context.upgrade() {\n+            for (handle, &(ref info, ref connectors)) in self.old_state.iter() {\n+                if let Err(err) = crtc::set(\n+                    &*device,\n+                    *handle,\n+                    info.fb(),\n+                    connectors,\n+                    info.position(),\n+                    info.mode(),\n+                ) {\n+                    error!(\n+                        self.logger,\n+                        "Failed to reset crtc ({:?}). Error: {}", handle, err\n+                    );\n+                }\n             }\n         }\n-        device.active = false;\n-        if device.priviledged {\n-            if let Err(err) = device.drop_master() {\n-                error!(\n-                    device.logger,\n-                    "Failed to drop drm master state. Error: {}", err\n-                );\n+        self.active.store(false, Ordering::SeqCst);\n+        if self.priviledged {\n+            if let Some(device) = self.context.upgrade() {\n+                if let Err(err) = device.drop_master() {\n+                    error!(\n+                        self.logger,\n+                        "Failed to drop drm master state. Error: {}", err\n+                    );\n+                }\n             }\n         }\n     }\n \n-    fn activate<\'a>(&mut self, state: &mut StateProxy<\'a>, devnum: Option<(u32, u32, Option<RawFd>)>) {\n-        let device = state.get_mut(self);\n+    fn activate(&mut self, _evlh: &mut EventLoopHandle, devnum: Option<(u32, u32, Option<RawFd>)>) {\n         if let Some((major, minor, fd)) = devnum {\n-            if major as u64 != stat::major(device.device_id) || minor as u64 != stat::minor(device.device_id)\n-            {\n+            if major as u64 != stat::major(self.device_id) || minor as u64 != stat::minor(self.device_id) {\n                 return;\n             } else if let Some(fd) = fd {\n-                info!(device.logger, "Replacing fd");\n-                nix::unistd::dup2(device.as_raw_fd(), fd)\n-                    .expect("Failed to replace file descriptor of drm device");\n+                info!(self.logger, "Replacing fd");\n+                if let Some(device) = self.context.upgrade() {\n+                    nix::unistd::dup2(device.as_raw_fd(), fd)\n+                        .expect("Failed to replace file descriptor of drm device");\n+                }\n             }\n         }\n-        device.active = true;\n-        if device.priviledged {\n-            if let Err(err) = device.set_master() {\n-                crit!(\n-                    device.logger,\n-                    "Failed to acquire drm master again. Error: {}",\n-                    err\n-                );\n+        self.active.store(true, Ordering::SeqCst);\n+        if self.priviledged {\n+            if let Some(device) = self.context.upgrade() {\n+                if let Err(err) = device.set_master() {\n+                    crit!(\n+                        self.logger,\n+                        "Failed to acquire drm master again. Error: {}",\n+                        err\n+                    );\n+                }\n             }\n         }\n         let mut crtcs = Vec::new();\n-        for (crtc, backend) in device.backends.iter() {\n+        for (crtc, backend) in self.backends.borrow().iter() {\n             if let Some(backend) = backend.upgrade() {\n                 backend.unlock_buffer();\n                 if let Err(err) = backend.page_flip(None) {\n                     error!(\n-                        device.logger,\n+                        self.logger,\n                         "Failed to activate crtc ({:?}) again. Error: {}", crtc, err\n                     );\n                 }\n@@ -685,7 +711,7 @@ impl<A: ControlDevice + \'static> SessionObserver for StateToken<DrmDevice<A>> {\n                     ).is_err()\n                     {\n                         if let Err(err) = crtc::set_cursor(&*backend.context, *crtc, cursor) {\n-                            error!(device.logger, "Failed to reset cursor. Error: {}", err);\n+                            error!(self.logger, "Failed to reset cursor. Error: {}", err);\n                         }\n                     }\n                 }\n@@ -694,7 +720,7 @@ impl<A: ControlDevice + \'static> SessionObserver for StateToken<DrmDevice<A>> {\n             }\n         }\n         for crtc in crtcs {\n-            device.backends.remove(&crtc);\n+            self.backends.borrow_mut().remove(&crtc);\n         }\n     }\n }\ndiff --git a/src/backend/libinput.rs b/src/backend/libinput.rs\nindex c43dc96f..07f6561a 100644\n--- a/src/backend/libinput.rs\n+++ b/src/backend/libinput.rs\n@@ -7,11 +7,11 @@ use input as libinput;\n use input::event;\n use std::collections::hash_map::{DefaultHasher, Entry, HashMap};\n use std::hash::{Hash, Hasher};\n-use std::io::{Error as IoError, Result as IoResult};\n+use std::io::Error as IoError;\n use std::os::unix::io::RawFd;\n use std::path::Path;\n use std::rc::Rc;\n-use wayland_server::{EventLoopHandle, StateProxy};\n+use wayland_server::EventLoopHandle;\n use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};\n \n // No idea if this is the same across unix platforms\n@@ -586,7 +586,7 @@ impl From<event::pointer::ButtonState> for backend::MouseButtonState {\n \n #[cfg(feature = "backend_session")]\n impl SessionObserver for libinput::Libinput {\n-    fn pause<\'a>(&mut self, _state: &mut StateProxy<\'a>, device: Option<(u32, u32)>) {\n+    fn pause(&mut self, _state: &mut EventLoopHandle, device: Option<(u32, u32)>) {\n         if let Some((major, _)) = device {\n             if major != INPUT_MAJOR {\n                 return;\n@@ -596,7 +596,7 @@ impl SessionObserver for libinput::Libinput {\n         self.suspend()\n     }\n \n-    fn activate<\'a>(&mut self, _state: &mut StateProxy<\'a>, _device: Option<(u32, u32, Option<RawFd>)>) {\n+    fn activate(&mut self, _state: &mut EventLoopHandle, _device: Option<(u32, u32, Option<RawFd>)>) {\n         // libinput closes the devices on suspend, so we should not get any INPUT_MAJOR calls\n         // also lets hope multiple resumes are okay in case of logind\n         self.resume().expect("Unable to resume libinput context");\n@@ -635,7 +635,7 @@ impl<S: Session> libinput::LibinputInterface for LibinputSessionInterface<S> {\n /// `dispatch_new_events`. Should be used to achieve the smallest possible latency.\n pub fn libinput_bind(\n     backend: LibinputInputBackend, evlh: &mut EventLoopHandle\n-) -> IoResult<FdEventSource<LibinputInputBackend>> {\n+) -> ::std::result::Result<FdEventSource<LibinputInputBackend>, (IoError, LibinputInputBackend)> {\n     let fd = unsafe { backend.context.fd() };\n     evlh.add_fd_event_source(\n         fd,\ndiff --git a/src/backend/session/auto.rs b/src/backend/session/auto.rs\nindex 7c6530a4..c65d5ad3 100644\n--- a/src/backend/session/auto.rs\n+++ b/src/backend/session/auto.rs\n@@ -29,18 +29,18 @@\n //! automatically by the `UdevBackend`, if not done manually).\n //! ```\n \n-use super::{AsErrno, Session, SessionNotifier, SessionObserver};\n+use super::{AsErrno, AsSessionObserver, Session, SessionNotifier, SessionObserver};\n use super::direct::{self, direct_session_bind, DirectSession, DirectSessionNotifier};\n #[cfg(feature = "backend_session_logind")]\n use super::logind::{self, logind_session_bind, BoundLogindSession, LogindSession, LogindSessionNotifier};\n use nix::fcntl::OFlag;\n use std::cell::RefCell;\n-use std::io::Result as IoResult;\n+use std::io::Error as IoError;\n use std::os::unix::io::RawFd;\n use std::path::Path;\n use std::rc::Rc;\n use wayland_server::EventLoopHandle;\n-use wayland_server::sources::SignalEventSource;\n+use wayland_server::sources::{EventSource, SignalEventSource};\n \n /// `Session` using the best available inteface\n #[derive(Clone)]\n@@ -154,11 +154,13 @@ impl AutoSession {\n /// session state and call it\'s `SessionObservers`.\n pub fn auto_session_bind(\n     notifier: AutoSessionNotifier, evlh: &mut EventLoopHandle\n-) -> IoResult<BoundAutoSession> {\n+) -> ::std::result::Result<BoundAutoSession, (IoError, AutoSessionNotifier)> {\n     Ok(match notifier {\n         #[cfg(feature = "backend_session_logind")]\n-        AutoSessionNotifier::Logind(logind) => BoundAutoSession::Logind(logind_session_bind(logind, evlh)?),\n-        AutoSessionNotifier::Direct(direct) => BoundAutoSession::Direct(direct_session_bind(direct, evlh)?),\n+        AutoSessionNotifier::Logind(logind) => BoundAutoSession::Logind(logind_session_bind(logind, evlh)\n+            .map_err(|(error, notifier)| (error, AutoSessionNotifier::Logind(notifier)))?),\n+        AutoSessionNotifier::Direct(direct) => BoundAutoSession::Direct(direct_session_bind(direct, evlh)\n+            .map_err(|(error, notifier)| (error, AutoSessionNotifier::Direct(notifier)))?),\n     })\n }\n \n@@ -207,7 +209,9 @@ impl Session for AutoSession {\n impl SessionNotifier for AutoSessionNotifier {\n     type Id = AutoId;\n \n-    fn register<S: SessionObserver + \'static>(&mut self, signal: S) -> Self::Id {\n+    fn register<S: SessionObserver + \'static, A: AsSessionObserver<S>>(\n+        &mut self, signal: &mut A\n+    ) -> Self::Id {\n         match self {\n             #[cfg(feature = "backend_session_logind")]\n             &mut AutoSessionNotifier::Logind(ref mut logind) => {\ndiff --git a/src/backend/session/dbus/logind.rs b/src/backend/session/dbus/logind.rs\nindex 84918a36..54a3e4cb 100644\n--- a/src/backend/session/dbus/logind.rs\n+++ b/src/backend/session/dbus/logind.rs\n@@ -30,20 +30,20 @@\n //! automatically by the `UdevBackend`, if not done manually).\n //! ```\n \n-use backend::session::{AsErrno, Session, SessionNotifier, SessionObserver};\n+use backend::session::{AsErrno, AsSessionObserver, Session, SessionNotifier, SessionObserver};\n use dbus::{BusName, BusType, Connection, ConnectionItem, ConnectionItems, Interface, Member, Message,\n            MessageItem, OwnedFd, Path as DbusPath, Watch, WatchEvent};\n use nix::fcntl::OFlag;\n use nix::sys::stat::{fstat, major, minor, stat};\n use std::cell::RefCell;\n-use std::io::Result as IoResult;\n+use std::io::Error as IoError;\n use std::os::unix::io::RawFd;\n use std::path::Path;\n use std::rc::{Rc, Weak};\n use std::sync::atomic::{AtomicBool, Ordering};\n use systemd::login;\n use wayland_server::EventLoopHandle;\n-use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};\n+use wayland_server::sources::{EventSource, FdEventSource, FdEventSourceImpl, FdInterest};\n \n struct LogindSessionImpl {\n     conn: RefCell<Connection>,\n@@ -246,7 +246,7 @@ impl LogindSessionImpl {\n                 //So lets just put it to sleep.. forever\n                 for signal in &mut *self.signals.borrow_mut() {\n                     if let &mut Some(ref mut signal) = signal {\n-                        signal.pause(&mut evlh.state().as_proxy(), None);\n+                        signal.pause(evlh, None);\n                     }\n                 }\n                 self.active.store(false, Ordering::SeqCst);\n@@ -263,7 +263,7 @@ impl LogindSessionImpl {\n                     );\n                     for signal in &mut *self.signals.borrow_mut() {\n                         if let &mut Some(ref mut signal) = signal {\n-                            signal.pause(&mut evlh.state().as_proxy(), Some((major, minor)));\n+                            signal.pause(evlh, Some((major, minor)));\n                         }\n                     }\n                     // the other possible types are "force" or "gone" (unplugged),\n@@ -289,7 +289,7 @@ impl LogindSessionImpl {\n                     debug!(self.logger, "Reactivating device ({},{})", major, minor);\n                     for signal in &mut *self.signals.borrow_mut() {\n                         if let &mut Some(ref mut signal) = signal {\n-                            signal.activate(&mut evlh.state().as_proxy(), Some((major, minor, Some(fd))));\n+                            signal.activate(evlh, Some((major, minor, Some(fd))));\n                         }\n                     }\n                 }\n@@ -392,11 +392,13 @@ pub struct Id(usize);\n impl SessionNotifier for LogindSessionNotifier {\n     type Id = Id;\n \n-    fn register<S: SessionObserver + \'static>(&mut self, signal: S) -> Id {\n+    fn register<S: SessionObserver + \'static, A: AsSessionObserver<S>>(\n+        &mut self, signal: &mut A\n+    ) -> Self::Id {\n         self.internal\n             .signals\n             .borrow_mut()\n-            .push(Some(Box::new(signal)));\n+            .push(Some(Box::new(signal.observer())));\n         Id(self.internal.signals.borrow().len() - 1)\n     }\n     fn unregister(&mut self, signal: Id) {\n@@ -430,8 +432,10 @@ pub struct BoundLogindSession {\n /// session state and call it\'s `SessionObservers`.\n pub fn logind_session_bind(\n     notifier: LogindSessionNotifier, evlh: &mut EventLoopHandle\n-) -> IoResult<BoundLogindSession> {\n+) -> ::std::result::Result<BoundLogindSession, (IoError, LogindSessionNotifier)> {\n     let watches = notifier.internal.conn.borrow().watch_fds();\n+\n+    let internal_for_error = notifier.internal.clone();\n     let sources = watches\n         .clone()\n         .into_iter()\n@@ -446,7 +450,15 @@ pub fn logind_session_bind(\n                 interest,\n             )\n         })\n-        .collect::<IoResult<Vec<FdEventSource<Rc<LogindSessionImpl>>>>>()?;\n+        .collect::<::std::result::Result<Vec<FdEventSource<Rc<LogindSessionImpl>>>, (IoError, _)>>()\n+        .map_err(|(err, _)| {\n+            (\n+                err,\n+                LogindSessionNotifier {\n+                    internal: internal_for_error,\n+                },\n+            )\n+        })?;\n \n     Ok(BoundLogindSession {\n         notifier,\ndiff --git a/src/backend/session/direct.rs b/src/backend/session/direct.rs\nindex e8c8e271..eaeded8e 100644\n--- a/src/backend/session/direct.rs\n+++ b/src/backend/session/direct.rs\n@@ -45,14 +45,14 @@\n //! for notifications are the `Libinput` context, the `UdevBackend` or a `DrmDevice` (handled\n //! automatically by the `UdevBackend`, if not done manually).\n \n-use super::{AsErrno, Session, SessionNotifier, SessionObserver};\n+use super::{AsErrno, AsSessionObserver, Session, SessionNotifier, SessionObserver};\n use nix::{Error as NixError, Result as NixResult};\n use nix::fcntl::{self, open, OFlag};\n use nix::libc::c_int;\n use nix::sys::signal::{self, Signal};\n use nix::sys::stat::{dev_t, fstat, major, minor, Mode};\n use nix::unistd::{close, dup};\n-use std::io::Result as IoResult;\n+use std::io::Error as IoError;\n use std::os::unix::io::RawFd;\n use std::path::Path;\n use std::sync::Arc;\n@@ -344,8 +344,10 @@ pub struct Id(usize);\n impl SessionNotifier for DirectSessionNotifier {\n     type Id = Id;\n \n-    fn register<S: SessionObserver + \'static>(&mut self, signal: S) -> Id {\n-        self.signals.push(Some(Box::new(signal)));\n+    fn register<S: SessionObserver + \'static, A: AsSessionObserver<S>>(\n+        &mut self, signal: &mut A\n+    ) -> Self::Id {\n+        self.signals.push(Some(Box::new(signal.observer())));\n         Id(self.signals.len() - 1)\n     }\n     fn unregister(&mut self, signal: Id) {\n@@ -367,7 +369,7 @@ impl SessionNotifier for DirectSessionNotifier {\n /// session state and call it\'s `SessionObservers`.\n pub fn direct_session_bind(\n     notifier: DirectSessionNotifier, evlh: &mut EventLoopHandle\n-) -> IoResult<SignalEventSource<DirectSessionNotifier>> {\n+) -> ::std::result::Result<SignalEventSource<DirectSessionNotifier>, (IoError, DirectSessionNotifier)> {\n     let signal = notifier.signal;\n \n     evlh.add_signal_event_source(\n@@ -376,7 +378,7 @@ pub fn direct_session_bind(\n                 info!(notifier.logger, "Session shall become inactive");\n                 for signal in &mut notifier.signals {\n                     if let &mut Some(ref mut signal) = signal {\n-                        signal.pause(&mut evlh.state().as_proxy(), None);\n+                        signal.pause(evlh, None);\n                     }\n                 }\n                 notifier.active.store(false, Ordering::SeqCst);\n@@ -391,7 +393,7 @@ pub fn direct_session_bind(\n                 }\n                 for signal in &mut notifier.signals {\n                     if let &mut Some(ref mut signal) = signal {\n-                        signal.activate(&mut evlh.state().as_proxy(), None);\n+                        signal.activate(evlh, None);\n                     }\n                 }\n                 notifier.active.store(true, Ordering::SeqCst);\ndiff --git a/src/backend/session/mod.rs b/src/backend/session/mod.rs\nindex d0a3320f..a11c6d33 100644\n--- a/src/backend/session/mod.rs\n+++ b/src/backend/session/mod.rs\n@@ -16,7 +16,7 @@ use std::os::unix::io::RawFd;\n use std::path::Path;\n use std::rc::Rc;\n use std::sync::{Arc, Mutex};\n-use wayland_server::StateProxy;\n+use wayland_server::EventLoopHandle;\n \n /// General session interface.\n ///\n@@ -53,7 +53,8 @@ pub trait SessionNotifier {\n     /// Registers a given `SessionObserver`.\n     ///\n     /// Returns an id of the inserted observer, can be used to remove it again.\n-    fn register<S: SessionObserver + \'static>(&mut self, signal: S) -> Self::Id;\n+    fn register<S: SessionObserver + \'static, A: AsSessionObserver<S>>(&mut self, signal: &mut A)\n+        -> Self::Id;\n     /// Removes an observer by its given id from `SessionNotifier::register`.\n     fn unregister(&mut self, signal: Self::Id);\n \n@@ -63,6 +64,20 @@ pub trait SessionNotifier {\n     fn seat(&self) -> &str;\n }\n \n+/// Trait describing the ability to return a `SessionObserver` related to Self.\n+///\n+/// The returned `SessionObserver` is responsible to handle the `pause` and `activate` signals.\n+pub trait AsSessionObserver<S: SessionObserver + \'static> {\n+    /// Create a `SessionObserver` linked to this object\n+    fn observer(&mut self) -> S;\n+}\n+\n+impl<T: SessionObserver + Clone + \'static> AsSessionObserver<T> for T {\n+    fn observer(&mut self) -> T {\n+        self.clone()\n+    }\n+}\n+\n /// Trait describing the ability to be notified when the session pauses or becomes active again.\n ///\n /// It might be impossible to interact with devices while the session is disabled.\n@@ -70,24 +85,18 @@ pub trait SessionNotifier {\n pub trait SessionObserver {\n     /// Session/Device is about to be paused.\n     ///\n-    /// In case the implementor is a `StateToken` the state of the `EventLoop`\n-    /// is provided via a `StateProxy`.\n-    ///\n     /// If only a specific device shall be closed a device number in the form of\n     /// (major, minor) is provided. All observers not using the specified device should\n     /// ignore the signal in that case.\n-    fn pause<\'a>(&mut self, state: &mut StateProxy<\'a>, device: Option<(u32, u32)>);\n+    fn pause(&mut self, evlh: &mut EventLoopHandle, device: Option<(u32, u32)>);\n     /// Session/Device got active again\n     ///\n-    /// In case the implementor is a `StateToken` the state of the `EventLoop`\n-    /// is provided via a `StateProxy`.\n-    ///\n     /// If only a specific device shall be activated again a device number in the form of\n     /// (major, major, Option<RawFd>) is provided. Optionally the session may decide to replace\n     /// the currently open file descriptor of the device with a new one. In that case the old one\n     /// should not be used anymore and be closed. All observers not using the specified device should\n     /// ignore the signal in that case.\n-    fn activate<\'a>(&mut self, state: &mut StateProxy<\'a>, device: Option<(u32, u32, Option<RawFd>)>);\n+    fn activate(&mut self, evlh: &mut EventLoopHandle, device: Option<(u32, u32, Option<RawFd>)>);\n }\n \n impl Session for () {\ndiff --git a/src/backend/udev.rs b/src/backend/udev.rs\nindex aad9472a..c849d271 100644\n--- a/src/backend/udev.rs\n+++ b/src/backend/udev.rs\n@@ -10,20 +10,22 @@\n //! backend.\n \n use backend::drm::{drm_device_bind, DrmDevice, DrmHandler};\n-use backend::session::{Session, SessionObserver};\n+use backend::session::{AsSessionObserver, Session, SessionObserver};\n use drm::Device as BasicDevice;\n use drm::control::Device as ControlDevice;\n use nix::fcntl;\n use nix::sys::stat::dev_t;\n+use std::cell::RefCell;\n use std::collections::HashMap;\n use std::ffi::OsString;\n-use std::io::{Error as IoError, Result as IoResult};\n+use std::io::Error as IoError;\n use std::mem::drop;\n use std::os::unix::io::{AsRawFd, RawFd};\n use std::path::{Path, PathBuf};\n+use std::rc::{Rc, Weak};\n use udev::{Context, Enumerator, Event, EventType, MonitorBuilder, MonitorSocket, Result as UdevResult};\n-use wayland_server::{EventLoopHandle, StateProxy, StateToken};\n-use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};\n+use wayland_server::EventLoopHandle;\n+use wayland_server::sources::{EventSource, FdEventSource, FdEventSourceImpl, FdInterest};\n \n /// Udev\'s `DrmDevice` type based on the underlying session\n pub struct SessionFdDrmDevice(RawFd);\n@@ -46,13 +48,7 @@ pub struct UdevBackend<\n     S: Session + \'static,\n     T: UdevHandler<H> + \'static,\n > {\n-    devices: HashMap<\n-        dev_t,\n-        (\n-            StateToken<DrmDevice<SessionFdDrmDevice>>,\n-            FdEventSource<(StateToken<DrmDevice<SessionFdDrmDevice>>, H)>,\n-        ),\n-    >,\n+    devices: Rc<RefCell<HashMap<dev_t, FdEventSource<(DrmDevice<SessionFdDrmDevice>, H)>>>>,\n     monitor: MonitorSocket,\n     session: S,\n     handler: T,\n@@ -72,7 +68,7 @@ impl<H: DrmHandler<SessionFdDrmDevice> + \'static, S: Session + \'static, T: UdevH\n     /// `logger`  - slog Logger to be used by the backend and its `DrmDevices`.\n     pub fn new<\'a, L>(\n         mut evlh: &mut EventLoopHandle, context: &Context, mut session: S, mut handler: T, logger: L\n-    ) -> Result<StateToken<UdevBackend<H, S, T>>>\n+    ) -> Result<UdevBackend<H, S, T>>\n     where\n         L: Into<Option<::slog::Logger>>,\n     {\n@@ -96,21 +92,21 @@ impl<H: DrmHandler<SessionFdDrmDevice> + \'static, S: Session + \'static, T: UdevH\n                 ) {\n                     // Call the handler, which might add it to the runloop\n                     Ok(mut device) => {\n-                        let fd = device.as_raw_fd();\n                         let devnum = device.device_id();\n-                        match handler.device_added(&mut evlh.state().as_proxy(), &mut device) {\n+                        let fd = device.as_raw_fd();\n+                        match handler.device_added(evlh, &mut device) {\n                             Some(drm_handler) => {\n-                                let token = evlh.state().insert(device);\n-                                if let Ok(event_source) = drm_device_bind(&mut evlh, token.clone(), drm_handler) {\n-                                    Some((devnum, (token, event_source)))\n-                                } else {\n-                                    handler.device_removed(evlh.state(), &token);\n-                                    let device = evlh.state().remove(token);\n-                                    drop(device);\n-                                    if let Err(err) = session.close(fd) {\n-                                        warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);\n-                                    };\n-                                    None\n+                                match drm_device_bind(&mut evlh, device, drm_handler) {\n+                                    Ok(event_source) => Some((devnum, event_source)),\n+                                    Err((err, (mut device, _))) => {\n+                                        warn!(logger, "Failed to bind device. Error: {:?}.", err);\n+                                        handler.device_removed(evlh, &mut device);\n+                                        drop(device);\n+                                        if let Err(err) = session.close(fd) {\n+                                            warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);\n+                                        };\n+                                        None\n+                                    }\n                                 }\n                             },\n                             None => {\n@@ -128,7 +124,7 @@ impl<H: DrmHandler<SessionFdDrmDevice> + \'static, S: Session + \'static, T: UdevH\n                     }\n                 }\n             })\n-            .collect::<HashMap<dev_t, (StateToken<DrmDevice<SessionFdDrmDevice>>, FdEventSource<(StateToken<DrmDevice<SessionFdDrmDevice>>, H)>)>>();\n+            .collect::<HashMap<dev_t, FdEventSource<(DrmDevice<SessionFdDrmDevice>, H)>>>();\n \n         let mut builder = MonitorBuilder::new(context).chain_err(|| ErrorKind::FailedToInitMonitor)?;\n         builder\n@@ -138,29 +134,21 @@ impl<H: DrmHandler<SessionFdDrmDevice> + \'static, S: Session + \'static, T: UdevH\n             .listen()\n             .chain_err(|| ErrorKind::FailedToInitMonitor)?;\n \n-        Ok(evlh.state().insert(UdevBackend {\n-            devices,\n+        Ok(UdevBackend {\n+            devices: Rc::new(RefCell::new(devices)),\n             monitor,\n             session,\n             handler,\n             logger,\n-        }))\n+        })\n     }\n \n     /// Closes the udev backend and frees all remaining open devices.\n-    ///\n-    /// Needs to be called after the `FdEventSource` was removed and the backend was removed from\n-    /// the `EventLoop`\'s `State`.\n-    ///\n-    /// ## Panics\n-    /// The given state might be passed to the registered `UdevHandler::device_removed` callback.\n-    /// Make sure not to borrow any tokens twice.\n-    pub fn close<\'a, ST: Into<StateProxy<\'a>>>(mut self, state: ST) {\n-        let mut state = state.into();\n-        for (_, (device, event_source)) in self.devices.drain() {\n-            event_source.remove();\n-            self.handler.device_removed(&mut state, &device);\n-            let device = state.remove(device);\n+    pub fn close(&mut self, evlh: &mut EventLoopHandle) {\n+        let mut devices = self.devices.borrow_mut();\n+        for (_, event_source) in devices.drain() {\n+            let (mut device, _) = event_source.remove();\n+            self.handler.device_removed(evlh, &mut device);\n             let fd = device.as_raw_fd();\n             drop(device);\n             if let Err(err) = self.session.close(fd) {\n@@ -174,26 +162,47 @@ impl<H: DrmHandler<SessionFdDrmDevice> + \'static, S: Session + \'static, T: UdevH\n     }\n }\n \n+/// `SessionObserver` linked to the `UdevBackend` it was created from.\n+pub struct UdevBackendObserver<H: DrmHandler<SessionFdDrmDevice> + \'static> {\n+    devices: Weak<RefCell<HashMap<dev_t, FdEventSource<(DrmDevice<SessionFdDrmDevice>, H)>>>>,\n+    logger: ::slog::Logger,\n+}\n+\n impl<\n     H: DrmHandler<SessionFdDrmDevice> + \'static,\n     S: Session + \'static,\n     T: UdevHandler<H> + \'static,\n-> SessionObserver for StateToken<UdevBackend<H, S, T>>\n+> AsSessionObserver<UdevBackendObserver<H>> for UdevBackend<H, S, T>\n {\n-    fn pause<\'a>(&mut self, state: &mut StateProxy<\'a>, devnum: Option<(u32, u32)>) {\n-        state.with_value(self, |state, udev| {\n-            for &mut (ref mut device, _) in udev.devices.values_mut() {\n-                device.pause(state, devnum);\n+    fn observer(&mut self) -> UdevBackendObserver<H> {\n+        UdevBackendObserver {\n+            devices: Rc::downgrade(&self.devices),\n+            logger: self.logger.clone(),\n+        }\n+    }\n+}\n+\n+impl<H: DrmHandler<SessionFdDrmDevice> + \'static> SessionObserver for UdevBackendObserver<H> {\n+    fn pause<\'a>(&mut self, evlh: &mut EventLoopHandle, devnum: Option<(u32, u32)>) {\n+        if let Some(devices) = self.devices.upgrade() {\n+            for fd_event_source in devices.borrow_mut().values_mut() {\n+                fd_event_source.with_idata(evlh, |&mut (ref mut device, _), evlh| {\n+                    info!(self.logger, "changed successful");\n+                    device.observer().pause(evlh, devnum);\n+                })\n             }\n-        });\n+        }\n     }\n \n-    fn activate<\'a>(&mut self, state: &mut StateProxy<\'a>, devnum: Option<(u32, u32, Option<RawFd>)>) {\n-        state.with_value(self, |state, udev| {\n-            for &mut (ref mut device, _) in udev.devices.values_mut() {\n-                device.activate(state, devnum);\n+    fn activate<\'a>(&mut self, evlh: &mut EventLoopHandle, devnum: Option<(u32, u32, Option<RawFd>)>) {\n+        if let Some(devices) = self.devices.upgrade() {\n+            for fd_event_source in devices.borrow_mut().values_mut() {\n+                fd_event_source.with_idata(evlh, |&mut (ref mut device, _), evlh| {\n+                    info!(self.logger, "changed successful");\n+                    device.observer().activate(evlh, devnum);\n+                })\n             }\n-        });\n+        }\n     }\n }\n \n@@ -202,41 +211,37 @@ impl<\n /// Allows the backend to recieve kernel events and thus to drive the `UdevHandler`.\n /// No runtime functionality can be provided without using this function.\n pub fn udev_backend_bind<S, H, T>(\n-    evlh: &mut EventLoopHandle, udev: StateToken<UdevBackend<H, S, T>>\n-) -> IoResult<FdEventSource<StateToken<UdevBackend<H, S, T>>>>\n+    evlh: &mut EventLoopHandle, udev: UdevBackend<H, S, T>\n+) -> ::std::result::Result<FdEventSource<UdevBackend<H, S, T>>, (IoError, UdevBackend<H, S, T>)>\n where\n     H: DrmHandler<SessionFdDrmDevice> + \'static,\n     T: UdevHandler<H> + \'static,\n     S: Session + \'static,\n {\n-    let fd = evlh.state().get(&udev).monitor.as_raw_fd();\n+    let fd = udev.monitor.as_raw_fd();\n     evlh.add_fd_event_source(fd, fd_event_source_implementation(), udev, FdInterest::READ)\n }\n \n-fn fd_event_source_implementation<S, H, T>() -> FdEventSourceImpl<StateToken<UdevBackend<H, S, T>>>\n+fn fd_event_source_implementation<S, H, T>() -> FdEventSourceImpl<UdevBackend<H, S, T>>\n where\n     H: DrmHandler<SessionFdDrmDevice> + \'static,\n     T: UdevHandler<H> + \'static,\n     S: Session + \'static,\n {\n     FdEventSourceImpl {\n-        ready: |mut evlh, token, _, _| {\n-            let events = evlh.state()\n-                .get(token)\n-                .monitor\n-                .clone()\n-                .collect::<Vec<Event>>();\n+        ready: |mut evlh, udev, _, _| {\n+            let events = udev.monitor.clone().collect::<Vec<Event>>();\n             for event in events {\n                 match event.event_type() {\n                     // New device\n                     EventType::Add => {\n-                        info!(evlh.state().get(token).logger, "Device Added");\n+                        info!(udev.logger, "Device Added");\n                         if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) {\n                             let mut device = {\n                                 match DrmDevice::new(\n                                     {\n-                                        let logger = evlh.state().get(token).logger.clone();\n-                                        match evlh.state().get_mut(token).session.open(\n+                                        let logger = udev.logger.clone();\n+                                        match udev.session.open(\n                                             path,\n                                             fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY\n                                                 | fcntl::O_NONBLOCK,\n@@ -253,12 +258,12 @@ where\n                                             }\n                                         }\n                                     },\n-                                    evlh.state().get(token).logger.clone(),\n+                                    udev.logger.clone(),\n                                 ) {\n                                     Ok(dev) => dev,\n                                     Err(err) => {\n                                         warn!(\n-                                            evlh.state().get(token).logger,\n+                                            udev.logger,\n                                             "Failed to initialize device {:?}. Error: {}. Skipping",\n                                             path,\n                                             err\n@@ -268,57 +273,43 @@ where\n                                 }\n                             };\n                             let fd = device.as_raw_fd();\n-                            match evlh.state().with_value(token, |state, udev| {\n-                                udev.handler.device_added(state, &mut device)\n-                            }) {\n-                                Some(drm_handler) => {\n-                                    let dev_token = evlh.state().insert(device);\n-                                    if let Ok(fd_event_source) =\n-                                        drm_device_bind(&mut evlh, dev_token.clone(), drm_handler)\n-                                    {\n-                                        evlh.state()\n-                                            .get_mut(token)\n-                                            .devices\n-                                            .insert(devnum, (dev_token, fd_event_source));\n-                                    } else {\n-                                        evlh.state().with_value(token, |state, udev| {\n-                                            let mut state: StateProxy = state.into();\n-                                            udev.handler.device_removed(&mut state, &dev_token);\n-                                            let device = state.remove(dev_token);\n-                                            drop(device);\n-                                            if let Err(err) = udev.session.close(fd) {\n-                                                warn!(\n-                                                    udev.logger,\n-                                                    "Failed to close dropped device. Error: {:?}. Ignoring",\n-                                                    err\n-                                                );\n-                                            };\n-                                        })\n+                            match udev.handler.device_added(evlh, &mut device) {\n+                                Some(drm_handler) => match drm_device_bind(&mut evlh, device, drm_handler) {\n+                                    Ok(fd_event_source) => {\n+                                        udev.devices.borrow_mut().insert(devnum, fd_event_source);\n                                     }\n-                                }\n-                                None => {\n-                                    drop(device);\n-                                    evlh.state().with_value(token, |_state, udev| {\n+                                    Err((err, (mut device, _))) => {\n+                                        warn!(udev.logger, "Failed to bind device. Error: {:?}.", err);\n+                                        udev.handler.device_removed(evlh, &mut device);\n+                                        drop(device);\n                                         if let Err(err) = udev.session.close(fd) {\n                                             warn!(\n                                                 udev.logger,\n-                                                "Failed to close unused device. Error: {:?}", err\n+                                                "Failed to close dropped device. Error: {:?}. Ignoring", err\n                                             );\n-                                        }\n-                                    })\n+                                        };\n+                                    }\n+                                },\n+                                None => {\n+                                    udev.handler.device_removed(evlh, &mut device);\n+                                    drop(device);\n+                                    if let Err(err) = udev.session.close(fd) {\n+                                        warn!(\n+                                            udev.logger,\n+                                            "Failed to close unused device. Error: {:?}", err\n+                                        );\n+                                    }\n                                 }\n                             };\n                         }\n                     }\n                     // Device removed\n-                    EventType::Remove => evlh.state().with_value(token, |state, udev| {\n+                    EventType::Remove => {\n                         info!(udev.logger, "Device Remove");\n                         if let Some(devnum) = event.devnum() {\n-                            if let Some((device, fd_event_source)) = udev.devices.remove(&devnum) {\n-                                fd_event_source.remove();\n-                                let mut state: StateProxy = state.into();\n-                                udev.handler.device_removed(&mut state, &device);\n-                                let device = state.remove(device);\n+                            if let Some(fd_event_source) = udev.devices.borrow_mut().remove(&devnum) {\n+                                let (mut device, _) = fd_event_source.remove();\n+                                udev.handler.device_removed(evlh, &mut device);\n                                 let fd = device.as_raw_fd();\n                                 drop(device);\n                                 if let Err(err) = udev.session.close(fd) {\n@@ -331,30 +322,31 @@ where\n                                 };\n                             }\n                         }\n-                    }),\n+                    }\n                     // New connector\n-                    EventType::Change => evlh.state().with_value(token, |state, udev| {\n+                    EventType::Change => {\n                         info!(udev.logger, "Device Changed");\n                         if let Some(devnum) = event.devnum() {\n                             info!(udev.logger, "Devnum: {:b}", devnum);\n-                            if let Some(&(ref device, _)) = udev.devices.get(&devnum) {\n-                                info!(udev.logger, "changed successful");\n-                                udev.handler.device_changed(state, device);\n+                            if let Some(fd_event_source) = udev.devices.borrow_mut().get_mut(&devnum) {\n+                                let handler = &mut udev.handler;\n+                                let logger = &udev.logger;\n+                                fd_event_source.with_idata(evlh, move |&mut (ref mut device, _), evlh| {\n+                                    info!(logger, "changed successful");\n+                                    handler.device_changed(evlh, device);\n+                                })\n                             } else {\n                                 info!(udev.logger, "changed, but device not tracked by backend");\n-                            }\n+                            };\n                         } else {\n                             info!(udev.logger, "changed, but no devnum");\n                         }\n-                    }),\n+                    }\n                     _ => {}\n                 }\n             }\n         },\n-        error: |evlh, token, _, err| {\n-            evlh.state()\n-                .with_value(token, |state, udev| udev.handler.error(state, err))\n-        },\n+        error: |evlh, udev, _, err| udev.handler.error(evlh, err),\n     }\n }\n \n@@ -366,8 +358,8 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + \'static> {\n     ///\n     /// ## Panics\n     /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.\n-    fn device_added<\'a, S: Into<StateProxy<\'a>>>(\n-        &mut self, state: S, device: &mut DrmDevice<SessionFdDrmDevice>\n+    fn device_added(\n+        &mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>\n     ) -> Option<H>;\n     /// Called when an open device is changed.\n     ///\n@@ -376,9 +368,7 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + \'static> {\n     ///\n     /// ## Panics\n     /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.\n-    fn device_changed<\'a, S: Into<StateProxy<\'a>>>(\n-        &mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>\n-    );\n+    fn device_changed(&mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>);\n     /// Called when a device was removed.\n     ///\n     /// The device will not accept any operations anymore and its file descriptor will be closed once\n@@ -386,14 +376,12 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + \'static> {\n     ///\n     /// ## Panics\n     /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.\n-    fn device_removed<\'a, S: Into<StateProxy<\'a>>>(\n-        &mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>\n-    );\n+    fn device_removed(&mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>);\n     /// Called when the udev context has encountered and error.\n     ///\n     /// ## Panics\n     /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.\n-    fn error<\'a, S: Into<StateProxy<\'a>>>(&mut self, state: S, error: IoError);\n+    fn error(&mut self, evlh: &mut EventLoopHandle, error: IoError);\n }\n \n /// Returns the path of the primary gpu device if any\n', 'commit_subject': 'Merge pull request #64 from Smithay/feature/udev_handler_evlh', 'repo_name': 'Smithay/smithay', 'committer': {'name': 'GitHub', 'email': '1505422b2465e9a84f6fdfaa161078890c593f06@github.com', 'time_sec': '1519288764', 'tz_offset': '60', 'date': {'seconds': '1519288764'}}, 'commit_tree': 'e39b16efb7f393f77b0c08b531d7ed3169e0b1cf', 'commit_message': 'Merge pull request #64 from Smithay/feature/udev_handler_evlh\n\nIntroduce SessionObserver', 'language_name': 'HTML', 'license': 'mit', 'hunks': '@@ -10,20 +10,22 @@\n //! backend.\n \n use backend::drm::{drm_device_bind, DrmDevice, DrmHandler};\n-use backend::session::{Session, SessionObserver};\n+use backend::session::{AsSessionObserver, Session, SessionObserver};\n use drm::Device as BasicDevice;\n use drm::control::Device as ControlDevice;\n use nix::fcntl;\n use nix::sys::stat::dev_t;\n+use std::cell::RefCell;\n use std::collections::HashMap;\n use std::ffi::OsString;\n-use std::io::{Error as IoError, Result as IoResult};\n+use std::io::Error as IoError;\n use std::mem::drop;\n use std::os::unix::io::{AsRawFd, RawFd};\n use std::path::{Path, PathBuf};\n+use std::rc::{Rc, Weak};\n use udev::{Context, Enumerator, Event, EventType, MonitorBuilder, MonitorSocket, Result as UdevResult};\n-use wayland_server::{EventLoopHandle, StateProxy, StateToken};\n-use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};\n+use wayland_server::EventLoopHandle;\n+use wayland_server::sources::{EventSource, FdEventSource, FdEventSourceImpl, FdInterest};\n \n /// Udev\'s `DrmDevice` type based on the underlying session\n pub struct SessionFdDrmDevice(RawFd);\n@@ -46,13 +48,7 @@ pub struct UdevBackend<\n     S: Session + \'static,\n     T: UdevHandler<H> + \'static,\n > {\n-    devices: HashMap<\n-        dev_t,\n-        (\n-            StateToken<DrmDevice<SessionFdDrmDevice>>,\n-            FdEventSource<(StateToken<DrmDevice<SessionFdDrmDevice>>, H)>,\n-        ),\n-    >,\n+    devices: Rc<RefCell<HashMap<dev_t, FdEventSource<(DrmDevice<SessionFdDrmDevice>, H)>>>>,\n     monitor: MonitorSocket,\n     session: S,\n     handler: T,\n@@ -72,7 +68,7 @@ impl<H: DrmHandler<SessionFdDrmDevice> + \'static, S: Session + \'static, T: UdevH\n     /// `logger`  - slog Logger to be used by the backend and its `DrmDevices`.\n     pub fn new<\'a, L>(\n         mut evlh: &mut EventLoopHandle, context: &Context, mut session: S, mut handler: T, logger: L\n-    ) -> Result<StateToken<UdevBackend<H, S, T>>>\n+    ) -> Result<UdevBackend<H, S, T>>\n     where\n         L: Into<Option<::slog::Logger>>,\n     {\n@@ -96,21 +92,21 @@ impl<H: DrmHandler<SessionFdDrmDevice> + \'static, S: Session + \'static, T: UdevH\n                 ) {\n                     // Call the handler, which might add it to the runloop\n                     Ok(mut device) => {\n-                        let fd = device.as_raw_fd();\n                         let devnum = device.device_id();\n-                        match handler.device_added(&mut evlh.state().as_proxy(), &mut device) {\n+                        let fd = device.as_raw_fd();\n+                        match handler.device_added(evlh, &mut device) {\n                             Some(drm_handler) => {\n-                                let token = evlh.state().insert(device);\n-                                if let Ok(event_source) = drm_device_bind(&mut evlh, token.clone(), drm_handler) {\n-                                    Some((devnum, (token, event_source)))\n-                                } else {\n-                                    handler.device_removed(evlh.state(), &token);\n-                                    let device = evlh.state().remove(token);\n-                                    drop(device);\n-                                    if let Err(err) = session.close(fd) {\n-                                        warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);\n-                                    };\n-                                    None\n+                                match drm_device_bind(&mut evlh, device, drm_handler) {\n+                                    Ok(event_source) => Some((devnum, event_source)),\n+                                    Err((err, (mut device, _))) => {\n+                                        warn!(logger, "Failed to bind device. Error: {:?}.", err);\n+                                        handler.device_removed(evlh, &mut device);\n+                                        drop(device);\n+                                        if let Err(err) = session.close(fd) {\n+                                            warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);\n+                                        };\n+                                        None\n+                                    }\n                                 }\n                             },\n                             None => {\n@@ -128,7 +124,7 @@ impl<H: DrmHandler<SessionFdDrmDevice> + \'static, S: Session + \'static, T: UdevH\n                     }\n                 }\n             })\n-            .collect::<HashMap<dev_t, (StateToken<DrmDevice<SessionFdDrmDevice>>, FdEventSource<(StateToken<DrmDevice<SessionFdDrmDevice>>, H)>)>>();\n+            .collect::<HashMap<dev_t, FdEventSource<(DrmDevice<SessionFdDrmDevice>, H)>>>();\n \n         let mut builder = MonitorBuilder::new(context).chain_err(|| ErrorKind::FailedToInitMonitor)?;\n         builder\n@@ -138,29 +134,21 @@ impl<H: DrmHandler<SessionFdDrmDevice> + \'static, S: Session + \'static, T: UdevH\n             .listen()\n             .chain_err(|| ErrorKind::FailedToInitMonitor)?;\n \n-        Ok(evlh.state().insert(UdevBackend {\n-            devices,\n+        Ok(UdevBackend {\n+            devices: Rc::new(RefCell::new(devices)),\n             monitor,\n             session,\n             handler,\n             logger,\n-        }))\n+        })\n     }\n \n     /// Closes the udev backend and frees all remaining open devices.\n-    ///\n-    /// Needs to be called after the `FdEventSource` was removed and the backend was removed from\n-    /// the `EventLoop`\'s `State`.\n-    ///\n-    /// ## Panics\n-    /// The given state might be passed to the registered `UdevHandler::device_removed` callback.\n-    /// Make sure not to borrow any tokens twice.\n-    pub fn close<\'a, ST: Into<StateProxy<\'a>>>(mut self, state: ST) {\n-        let mut state = state.into();\n-        for (_, (device, event_source)) in self.devices.drain() {\n-            event_source.remove();\n-            self.handler.device_removed(&mut state, &device);\n-            let device = state.remove(device);\n+    pub fn close(&mut self, evlh: &mut EventLoopHandle) {\n+        let mut devices = self.devices.borrow_mut();\n+        for (_, event_source) in devices.drain() {\n+            let (mut device, _) = event_source.remove();\n+            self.handler.device_removed(evlh, &mut device);\n             let fd = device.as_raw_fd();\n             drop(device);\n             if let Err(err) = self.session.close(fd) {\n@@ -174,26 +162,47 @@ impl<H: DrmHandler<SessionFdDrmDevice> + \'static, S: Session + \'static, T: UdevH\n     }\n }\n \n+/// `SessionObserver` linked to the `UdevBackend` it was created from.\n+pub struct UdevBackendObserver<H: DrmHandler<SessionFdDrmDevice> + \'static> {\n+    devices: Weak<RefCell<HashMap<dev_t, FdEventSource<(DrmDevice<SessionFdDrmDevice>, H)>>>>,\n+    logger: ::slog::Logger,\n+}\n+\n impl<\n     H: DrmHandler<SessionFdDrmDevice> + \'static,\n     S: Session + \'static,\n     T: UdevHandler<H> + \'static,\n-> SessionObserver for StateToken<UdevBackend<H, S, T>>\n+> AsSessionObserver<UdevBackendObserver<H>> for UdevBackend<H, S, T>\n {\n-    fn pause<\'a>(&mut self, state: &mut StateProxy<\'a>, devnum: Option<(u32, u32)>) {\n-        state.with_value(self, |state, udev| {\n-            for &mut (ref mut device, _) in udev.devices.values_mut() {\n-                device.pause(state, devnum);\n+    fn observer(&mut self) -> UdevBackendObserver<H> {\n+        UdevBackendObserver {\n+            devices: Rc::downgrade(&self.devices),\n+            logger: self.logger.clone(),\n+        }\n+    }\n+}\n+\n+impl<H: DrmHandler<SessionFdDrmDevice> + \'static> SessionObserver for UdevBackendObserver<H> {\n+    fn pause<\'a>(&mut self, evlh: &mut EventLoopHandle, devnum: Option<(u32, u32)>) {\n+        if let Some(devices) = self.devices.upgrade() {\n+            for fd_event_source in devices.borrow_mut().values_mut() {\n+                fd_event_source.with_idata(evlh, |&mut (ref mut device, _), evlh| {\n+                    info!(self.logger, "changed successful");\n+                    device.observer().pause(evlh, devnum);\n+                })\n             }\n-        });\n+        }\n     }\n \n-    fn activate<\'a>(&mut self, state: &mut StateProxy<\'a>, devnum: Option<(u32, u32, Option<RawFd>)>) {\n-        state.with_value(self, |state, udev| {\n-            for &mut (ref mut device, _) in udev.devices.values_mut() {\n-                device.activate(state, devnum);\n+    fn activate<\'a>(&mut self, evlh: &mut EventLoopHandle, devnum: Option<(u32, u32, Option<RawFd>)>) {\n+        if let Some(devices) = self.devices.upgrade() {\n+            for fd_event_source in devices.borrow_mut().values_mut() {\n+                fd_event_source.with_idata(evlh, |&mut (ref mut device, _), evlh| {\n+                    info!(self.logger, "changed successful");\n+                    device.observer().activate(evlh, devnum);\n+                })\n             }\n-        });\n+        }\n     }\n }\n \n@@ -202,41 +211,37 @@ impl<\n /// Allows the backend to recieve kernel events and thus to drive the `UdevHandler`.\n /// No runtime functionality can be provided without using this function.\n pub fn udev_backend_bind<S, H, T>(\n-    evlh: &mut EventLoopHandle, udev: StateToken<UdevBackend<H, S, T>>\n-) -> IoResult<FdEventSource<StateToken<UdevBackend<H, S, T>>>>\n+    evlh: &mut EventLoopHandle, udev: UdevBackend<H, S, T>\n+) -> ::std::result::Result<FdEventSource<UdevBackend<H, S, T>>, (IoError, UdevBackend<H, S, T>)>\n where\n     H: DrmHandler<SessionFdDrmDevice> + \'static,\n     T: UdevHandler<H> + \'static,\n     S: Session + \'static,\n {\n-    let fd = evlh.state().get(&udev).monitor.as_raw_fd();\n+    let fd = udev.monitor.as_raw_fd();\n     evlh.add_fd_event_source(fd, fd_event_source_implementation(), udev, FdInterest::READ)\n }\n \n-fn fd_event_source_implementation<S, H, T>() -> FdEventSourceImpl<StateToken<UdevBackend<H, S, T>>>\n+fn fd_event_source_implementation<S, H, T>() -> FdEventSourceImpl<UdevBackend<H, S, T>>\n where\n     H: DrmHandler<SessionFdDrmDevice> + \'static,\n     T: UdevHandler<H> + \'static,\n     S: Session + \'static,\n {\n     FdEventSourceImpl {\n-        ready: |mut evlh, token, _, _| {\n-            let events = evlh.state()\n-                .get(token)\n-                .monitor\n-                .clone()\n-                .collect::<Vec<Event>>();\n+        ready: |mut evlh, udev, _, _| {\n+            let events = udev.monitor.clone().collect::<Vec<Event>>();\n             for event in events {\n                 match event.event_type() {\n                     // New device\n                     EventType::Add => {\n-                        info!(evlh.state().get(token).logger, "Device Added");\n+                        info!(udev.logger, "Device Added");\n                         if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) {\n                             let mut device = {\n                                 match DrmDevice::new(\n                                     {\n-                                        let logger = evlh.state().get(token).logger.clone();\n-                                        match evlh.state().get_mut(token).session.open(\n+                                        let logger = udev.logger.clone();\n+                                        match udev.session.open(\n                                             path,\n                                             fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY\n                                                 | fcntl::O_NONBLOCK,\n@@ -253,12 +258,12 @@ where\n                                             }\n                                         }\n                                     },\n-                                    evlh.state().get(token).logger.clone(),\n+                                    udev.logger.clone(),\n                                 ) {\n                                     Ok(dev) => dev,\n                                     Err(err) => {\n                                         warn!(\n-                                            evlh.state().get(token).logger,\n+                                            udev.logger,\n                                             "Failed to initialize device {:?}. Error: {}. Skipping",\n                                             path,\n                                             err\n@@ -268,57 +273,43 @@ where\n                                 }\n                             };\n                             let fd = device.as_raw_fd();\n-                            match evlh.state().with_value(token, |state, udev| {\n-                                udev.handler.device_added(state, &mut device)\n-                            }) {\n-                                Some(drm_handler) => {\n-                                    let dev_token = evlh.state().insert(device);\n-                                    if let Ok(fd_event_source) =\n-                                        drm_device_bind(&mut evlh, dev_token.clone(), drm_handler)\n-                                    {\n-                                        evlh.state()\n-                                            .get_mut(token)\n-                                            .devices\n-                                            .insert(devnum, (dev_token, fd_event_source));\n-                                    } else {\n-                                        evlh.state().with_value(token, |state, udev| {\n-                                            let mut state: StateProxy = state.into();\n-                                            udev.handler.device_removed(&mut state, &dev_token);\n-                                            let device = state.remove(dev_token);\n-                                            drop(device);\n-                                            if let Err(err) = udev.session.close(fd) {\n-                                                warn!(\n-                                                    udev.logger,\n-                                                    "Failed to close dropped device. Error: {:?}. Ignoring",\n-                                                    err\n-                                                );\n-                                            };\n-                                        })\n+                            match udev.handler.device_added(evlh, &mut device) {\n+                                Some(drm_handler) => match drm_device_bind(&mut evlh, device, drm_handler) {\n+                                    Ok(fd_event_source) => {\n+                                        udev.devices.borrow_mut().insert(devnum, fd_event_source);\n                                     }\n-                                }\n-                                None => {\n-                                    drop(device);\n-                                    evlh.state().with_value(token, |_state, udev| {\n+                                    Err((err, (mut device, _))) => {\n+                                        warn!(udev.logger, "Failed to bind device. Error: {:?}.", err);\n+                                        udev.handler.device_removed(evlh, &mut device);\n+                                        drop(device);\n                                         if let Err(err) = udev.session.close(fd) {\n                                             warn!(\n                                                 udev.logger,\n-                                                "Failed to close unused device. Error: {:?}", err\n+                                                "Failed to close dropped device. Error: {:?}. Ignoring", err\n                                             );\n-                                        }\n-                                    })\n+                                        };\n+                                    }\n+                                },\n+                                None => {\n+                                    udev.handler.device_removed(evlh, &mut device);\n+                                    drop(device);\n+                                    if let Err(err) = udev.session.close(fd) {\n+                                        warn!(\n+                                            udev.logger,\n+                                            "Failed to close unused device. Error: {:?}", err\n+                                        );\n+                                    }\n                                 }\n                             };\n                         }\n                     }\n                     // Device removed\n-                    EventType::Remove => evlh.state().with_value(token, |state, udev| {\n+                    EventType::Remove => {\n                         info!(udev.logger, "Device Remove");\n                         if let Some(devnum) = event.devnum() {\n-                            if let Some((device, fd_event_source)) = udev.devices.remove(&devnum) {\n-                                fd_event_source.remove();\n-                                let mut state: StateProxy = state.into();\n-                                udev.handler.device_removed(&mut state, &device);\n-                                let device = state.remove(device);\n+                            if let Some(fd_event_source) = udev.devices.borrow_mut().remove(&devnum) {\n+                                let (mut device, _) = fd_event_source.remove();\n+                                udev.handler.device_removed(evlh, &mut device);\n                                 let fd = device.as_raw_fd();\n                                 drop(device);\n                                 if let Err(err) = udev.session.close(fd) {\n@@ -331,30 +322,31 @@ where\n                                 };\n                             }\n                         }\n-                    }),\n+                    }\n                     // New connector\n-                    EventType::Change => evlh.state().with_value(token, |state, udev| {\n+                    EventType::Change => {\n                         info!(udev.logger, "Device Changed");\n                         if let Some(devnum) = event.devnum() {\n                             info!(udev.logger, "Devnum: {:b}", devnum);\n-                            if let Some(&(ref device, _)) = udev.devices.get(&devnum) {\n-                                info!(udev.logger, "changed successful");\n-                                udev.handler.device_changed(state, device);\n+                            if let Some(fd_event_source) = udev.devices.borrow_mut().get_mut(&devnum) {\n+                                let handler = &mut udev.handler;\n+                                let logger = &udev.logger;\n+                                fd_event_source.with_idata(evlh, move |&mut (ref mut device, _), evlh| {\n+                                    info!(logger, "changed successful");\n+                                    handler.device_changed(evlh, device);\n+                                })\n                             } else {\n                                 info!(udev.logger, "changed, but device not tracked by backend");\n-                            }\n+                            };\n                         } else {\n                             info!(udev.logger, "changed, but no devnum");\n                         }\n-                    }),\n+                    }\n                     _ => {}\n                 }\n             }\n         },\n-        error: |evlh, token, _, err| {\n-            evlh.state()\n-                .with_value(token, |state, udev| udev.handler.error(state, err))\n-        },\n+        error: |evlh, udev, _, err| udev.handler.error(evlh, err),\n     }\n }\n \n@@ -366,8 +358,8 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + \'static> {\n     ///\n     /// ## Panics\n     /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.\n-    fn device_added<\'a, S: Into<StateProxy<\'a>>>(\n-        &mut self, state: S, device: &mut DrmDevice<SessionFdDrmDevice>\n+    fn device_added(\n+        &mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>\n     ) -> Option<H>;\n     /// Called when an open device is changed.\n     ///\n@@ -376,9 +368,7 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + \'static> {\n     ///\n     /// ## Panics\n     /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.\n-    fn device_changed<\'a, S: Into<StateProxy<\'a>>>(\n-        &mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>\n-    );\n+    fn device_changed(&mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>);\n     /// Called when a device was removed.\n     ///\n     /// The device will not accept any operations anymore and its file descriptor will be closed once\n@@ -386,14 +376,12 @@ pub trait UdevHandler<H: DrmHandler<SessionFdDrmDevice> + \'static> {\n     ///\n     /// ## Panics\n     /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.\n-    fn device_removed<\'a, S: Into<StateProxy<\'a>>>(\n-        &mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>\n-    );\n+    fn device_removed(&mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice<SessionFdDrmDevice>);\n     /// Called when the udev context has encountered and error.\n     ///\n     /// ## Panics\n     /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.\n-    fn error<\'a, S: Into<StateProxy<\'a>>>(&mut self, state: S, error: IoError);\n+    fn error(&mut self, evlh: &mut EventLoopHandle, error: IoError);\n }\n \n /// Returns the path of the primary gpu device if any\n', 'addition_count': 115, 'deletion_count': 127, 'src_file': 'a/src/backend/udev.rs', 'tgt_file': 'b/src/backend/udev.rs', 'file_extension': '.rs', 'before_file': '//! `udev` related functionality for automated device scanning\n//!\n//! This module mainly provides the [`UdevBackend`], which monitors available DRM devices and acts as\n//! an event source to be inserted in [`calloop`], generating events whenever these devices change.\n//!\n//! *Note:* Once inserted into the event loop, the [`UdevBackend`] will only notify you about *changes*\n//! in the device list. To get an initial snapshot of the state during your initialization, you need to\n//! call its `device_list` method.\n//!\n//! backend.\n\nuse backend::drm::{drm_device_bind, DrmDevice, DrmHandler};\nuse backend::session::{Session, SessionObserver};\nuse drm::Device as BasicDevice;\nuse drm::control::Device as ControlDevice;\nuse nix::fcntl;\nuse nix::sys::stat::dev_t;\nuse std::collections::HashMap;\nuse std::ffi::OsString;\nuse std::io::{Error as IoError, Result as IoResult};\nuse std::mem::drop;\nuse std::os::unix::io::{AsRawFd, RawFd};\nuse std::path::{Path, PathBuf};\nuse udev::{Context, Enumerator, Event, EventType, MonitorBuilder, MonitorSocket, Result as UdevResult};\nuse wayland_server::{EventLoopHandle, StateProxy, StateToken};\nuse wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};\n\n/// Udev\'s `DrmDevice` type based on the underlying session\npub struct SessionFdDrmDevice(RawFd);\n//! }).expect("Failed to insert the udev source into the event loop");\n//! ```\n//!\n//! Additionally this contains some utility functions related to scanning.\n//!\n//! See also `anvil/src/udev.rs` for pure hardware backed example of a compositor utilizing this\n//! backend.\n\nuse nix::sys::stat::{dev_t, stat};\nuse std::{\n    collections::HashMap,\n    ffi::OsString,\n    fmt, io,\n    os::unix::io::{AsRawFd, RawFd},\n    path::{Path, PathBuf},\n};\n    S: Session + \'static,\n    T: UdevHandler<H> + \'static,\n> {\n    devices: HashMap<\n        dev_t,\n        (\n            StateToken<DrmDevice<SessionFdDrmDevice>>,\n            FdEventSource<(StateToken<DrmDevice<SessionFdDrmDevice>>, H)>,\n        ),\n    >,\n    monitor: MonitorSocket,\n    session: S,\n    handler: T,\n///\n/// Provides a way to automatically scan for available gpus and notifies the\n/// given handler of any changes. Can be used to provide hot-plug functionality for gpus and\n/// attached monitors.\npub struct UdevBackend {\n    devices: HashMap<dev_t, PathBuf>,\n    monitor: MonitorSocket,\n    token: Option<Token>,\n    logger: ::slog::Logger,\n}\n\n// MonitorSocket does not implement debug, so we have to impl Debug manually\nimpl fmt::Debug for UdevBackend {\n    /// `logger`  - slog Logger to be used by the backend and its `DrmDevices`.\n    pub fn new<\'a, L>(\n        mut evlh: &mut EventLoopHandle, context: &Context, mut session: S, mut handler: T, logger: L\n    ) -> Result<StateToken<UdevBackend<H, S, T>>>\n    where\n        L: Into<Option<::slog::Logger>>,\n    {\n    }\n}\n\nimpl AsRawFd for UdevBackend {\n    fn as_raw_fd(&self) -> RawFd {\n        self.monitor.as_raw_fd()\n    }\n}\n\nimpl UdevBackend {\n    /// Creates a new [`UdevBackend`]\n    ///\n    /// ## Arguments\n    /// `seat`    - system seat which should be bound\n    /// `logger`  - slog Logger to be used by the backend and its `DrmDevices`.\n    pub fn new<L, S: AsRef<str>>(seat: S, logger: L) -> io::Result<UdevBackend>\n    where\n                ) {\n                    // Call the handler, which might add it to the runloop\n                    Ok(mut device) => {\n                        let fd = device.as_raw_fd();\n                        let devnum = device.device_id();\n                        match handler.device_added(&mut evlh.state().as_proxy(), &mut device) {\n                            Some(drm_handler) => {\n                                let token = evlh.state().insert(device);\n                                if let Ok(event_source) = drm_device_bind(&mut evlh, token.clone(), drm_handler) {\n                                    Some((devnum, (token, event_source)))\n                                } else {\n                                    handler.device_removed(evlh.state(), &token);\n                                    let device = evlh.state().remove(token);\n                                    drop(device);\n                                    if let Err(err) = session.close(fd) {\n                                        warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);\n                                    };\n                                    None\n                                }\n                            },\n                            None => {\n            token: None,\n            logger: log,\n        })\n    }\n\n    /// Get a list of DRM devices currently known to the backend\n    ///\n    /// You should call this once before inserting the event source into your\n    /// event loop, to get an initial snapshot of the device state.\n    pub fn device_list(&self) -> impl Iterator<Item = (dev_t, &Path)> {\n        self.devices.iter().map(|(&id, path)| (id, path.as_ref()))\n                    }\n                }\n            })\n            .collect::<HashMap<dev_t, (StateToken<DrmDevice<SessionFdDrmDevice>>, FdEventSource<(StateToken<DrmDevice<SessionFdDrmDevice>>, H)>)>>();\n\n        let mut builder = MonitorBuilder::new(context).chain_err(|| ErrorKind::FailedToInitMonitor)?;\n        builder\n    type Error = io::Error;\n\n    fn process_events<F>(\n            .listen()\n            .chain_err(|| ErrorKind::FailedToInitMonitor)?;\n\n        Ok(evlh.state().insert(UdevBackend {\n            devices,\n            monitor,\n            session,\n            handler,\n            logger,\n        }))\n    }\n\n    /// Closes the udev backend and frees all remaining open devices.\n    ///\n    /// Needs to be called after the `FdEventSource` was removed and the backend was removed from\n    /// the `EventLoop`\'s `State`.\n    ///\n    /// ## Panics\n    /// The given state might be passed to the registered `UdevHandler::device_removed` callback.\n    /// Make sure not to borrow any tokens twice.\n    pub fn close<\'a, ST: Into<StateProxy<\'a>>>(mut self, state: ST) {\n        let mut state = state.into();\n        for (_, (device, event_source)) in self.devices.drain() {\n            event_source.remove();\n            self.handler.device_removed(&mut state, &device);\n            let device = state.remove(device);\n            let fd = device.as_raw_fd();\n            drop(device);\n            if let Err(err) = self.session.close(fd) {\n                // New device\n                EventType::Add => {\n                    if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) {\n                        info!(self.logger, "New device: #{} at {}", devnum, path.display());\n                        if self.devices.insert(devnum, path.to_path_buf()).is_none() {\n                            callback(\n                                UdevEvent::Added {\n    }\n}\n\nimpl<\n    H: DrmHandler<SessionFdDrmDevice> + \'static,\n    S: Session + \'static,\n    T: UdevHandler<H> + \'static,\n> SessionObserver for StateToken<UdevBackend<H, S, T>>\n{\n    fn pause<\'a>(&mut self, state: &mut StateProxy<\'a>, devnum: Option<(u32, u32)>) {\n        state.with_value(self, |state, udev| {\n            for &mut (ref mut device, _) in udev.devices.values_mut() {\n                device.pause(state, devnum);\n            }\n        });\n    }\n\n    fn activate<\'a>(&mut self, state: &mut StateProxy<\'a>, devnum: Option<(u32, u32, Option<RawFd>)>) {\n        state.with_value(self, |state, udev| {\n            for &mut (ref mut device, _) in udev.devices.values_mut() {\n                device.activate(state, devnum);\n            }\n        });\n    }\n}\n\n\n/// Events generated by the [`UdevBackend`], notifying you of changes in system devices\n/// Allows the backend to recieve kernel events and thus to drive the `UdevHandler`.\n/// No runtime functionality can be provided without using this function.\npub fn udev_backend_bind<S, H, T>(\n    evlh: &mut EventLoopHandle, udev: StateToken<UdevBackend<H, S, T>>\n) -> IoResult<FdEventSource<StateToken<UdevBackend<H, S, T>>>>\nwhere\n    H: DrmHandler<SessionFdDrmDevice> + \'static,\n    T: UdevHandler<H> + \'static,\n    S: Session + \'static,\n{\n    let fd = evlh.state().get(&udev).monitor.as_raw_fd();\n    evlh.add_fd_event_source(fd, fd_event_source_implementation(), udev, FdInterest::READ)\n}\n\nfn fd_event_source_implementation<S, H, T>() -> FdEventSourceImpl<StateToken<UdevBackend<H, S, T>>>\nwhere\n    H: DrmHandler<SessionFdDrmDevice> + \'static,\n    T: UdevHandler<H> + \'static,\n    S: Session + \'static,\n{\n    FdEventSourceImpl {\n        ready: |mut evlh, token, _, _| {\n            let events = evlh.state()\n                .get(token)\n                .monitor\n                .clone()\n                .collect::<Vec<Event>>();\n            for event in events {\n                match event.event_type() {\n                    // New device\n                    EventType::Add => {\n                        info!(evlh.state().get(token).logger, "Device Added");\n                        if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) {\n                            let mut device = {\n                                match DrmDevice::new(\n                                    {\n                                        let logger = evlh.state().get(token).logger.clone();\n                                        match evlh.state().get_mut(token).session.open(\n                                            path,\n                                            fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY\n                                                | fcntl::O_NONBLOCK,\n            if seat_name == *seat.as_ref() {\n                if let Ok(Some(pci)) = device.parent_with_subsystem(Path::new("pci")) {\n                    if let Some(id) = pci.attribute_value("boot_vga") {\n                        return id == "1";\n                    }\n                }\n            }\n            false\n        })\n        .flat_map(|device| device.devnode().map(PathBuf::from))\n                                            }\n                                        }\n                                    },\n                                    evlh.state().get(token).logger.clone(),\n                                ) {\n                                    Ok(dev) => dev,\n                                    Err(err) => {\n                                        warn!(\n                                            evlh.state().get(token).logger,\n                                            "Failed to initialize device {:?}. Error: {}. Skipping",\n                                            path,\n                                            err\npub fn all_gpus<S: AsRef<str>>(seat: S) -> io::Result<Vec<PathBuf>> {\n    let mut enumerator = Enumerator::new()?;\n    enumerator.match_subsystem("drm")?;\n                                }\n                            };\n                            let fd = device.as_raw_fd();\n                            match evlh.state().with_value(token, |state, udev| {\n                                udev.handler.device_added(state, &mut device)\n                            }) {\n                                Some(drm_handler) => {\n                                    let dev_token = evlh.state().insert(device);\n                                    if let Ok(fd_event_source) =\n                                        drm_device_bind(&mut evlh, dev_token.clone(), drm_handler)\n                                    {\n                                        evlh.state()\n                                            .get_mut(token)\n                                            .devices\n                                            .insert(devnum, (dev_token, fd_event_source));\n                                    } else {\n                                        evlh.state().with_value(token, |state, udev| {\n                                            let mut state: StateProxy = state.into();\n                                            udev.handler.device_removed(&mut state, &dev_token);\n                                            let device = state.remove(dev_token);\n                                            drop(device);\n                                            if let Err(err) = udev.session.close(fd) {\n                                                warn!(\n                                                    udev.logger,\n                                                    "Failed to close dropped device. Error: {:?}. Ignoring",\n                                                    err\n                                                );\n                                            };\n                                        })\n                                    }\n                                }\n                                None => {\n                                    drop(device);\n                                    evlh.state().with_value(token, |_state, udev| {\n                                        if let Err(err) = udev.session.close(fd) {\n                                            warn!(\n                                                udev.logger,\n                                                "Failed to close unused device. Error: {:?}", err\n                                            );\n                                        }\n                                    })\n                                }\n                            };\n                        }\n                    }\n                    // Device removed\n                    EventType::Remove => evlh.state().with_value(token, |state, udev| {\n                        info!(udev.logger, "Device Remove");\n                        if let Some(devnum) = event.devnum() {\n                            if let Some((device, fd_event_source)) = udev.devices.remove(&devnum) {\n                                fd_event_source.remove();\n                                let mut state: StateProxy = state.into();\n                                udev.handler.device_removed(&mut state, &device);\n                                let device = state.remove(device);\n                                let fd = device.as_raw_fd();\n                                drop(device);\n                                if let Err(err) = udev.session.close(fd) {\n                                };\n                            }\n                        }\n                    }),\n                    // New connector\n                    EventType::Change => evlh.state().with_value(token, |state, udev| {\n                        info!(udev.logger, "Device Changed");\n                        if let Some(devnum) = event.devnum() {\n                            info!(udev.logger, "Devnum: {:b}", devnum);\n                            if let Some(&(ref device, _)) = udev.devices.get(&devnum) {\n                                info!(udev.logger, "changed successful");\n                                udev.handler.device_changed(state, device);\n                            } else {\n                                info!(udev.logger, "changed, but device not tracked by backend");\n                            }\n                        } else {\n                            info!(udev.logger, "changed, but no devnum");\n                        }\n                    }),\n                    _ => {}\n                }\n            }\n        },\n        error: |evlh, token, _, err| {\n            evlh.state()\n                .with_value(token, |state, udev| udev.handler.error(state, err))\n        },\n    }\n}\n\n    ///\n    /// ## Panics\n    /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.\n    fn device_added<\'a, S: Into<StateProxy<\'a>>>(\n        &mut self, state: S, device: &mut DrmDevice<SessionFdDrmDevice>\n    ) -> Option<H>;\n    /// Called when an open device is changed.\n    ///\n    ///\n    /// ## Panics\n    /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.\n    fn device_changed<\'a, S: Into<StateProxy<\'a>>>(\n        &mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>\n    );\n    /// Called when a device was removed.\n    ///\n    /// The device will not accept any operations anymore and its file descriptor will be closed once\n    ///\n    /// ## Panics\n    /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.\n    fn device_removed<\'a, S: Into<StateProxy<\'a>>>(\n        &mut self, state: S, device: &StateToken<DrmDevice<SessionFdDrmDevice>>\n    );\n    /// Called when the udev context has encountered and error.\n    ///\n    /// ## Panics\n    /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`.\n    fn error<\'a, S: Into<StateProxy<\'a>>>(&mut self, state: S, error: IoError);\n}\n\n/// Returns the path of the primary gpu device if any\n', 'message': 'Merge pull request #64 from Smithay/feature/udev_handler_evlh\n\nIntroduce SessionObserver', 'author_name': 'GitHub', 'lang': 'rs'}