diff --git a/src/backend/drm/backend.rs b/src/backend/drm/backend.rs index 0f8b3ca..3410e55 100644 --- a/src/backend/drm/backend.rs +++ b/src/backend/drm/backend.rs @@ -37,8 +37,11 @@ pub(crate) struct DrmBackendInternal { impl DrmBackend { pub(crate) fn new( - context: Rc, GbmDevice>>, crtc: crtc::Handle, mode: Mode, - connectors: Vec, log: ::slog::Logger, + context: Rc, GbmDevice>>, + crtc: crtc::Handle, + mode: Mode, + connectors: Vec, + log: ::slog::Logger, ) -> Result { // logger already initialized by the DrmDevice info!(log, "Initializing DrmBackend"); @@ -351,7 +354,8 @@ impl DrmBackendInternal { } pub(crate) fn page_flip( - &self, fb: Option<&framebuffer::Info> + &self, + fb: Option<&framebuffer::Info>, ) -> ::std::result::Result<(), SwapBuffersError> { trace!(self.logger, "Queueing Page flip"); @@ -421,7 +425,9 @@ impl GraphicsBackend for DrmBackend { } fn set_cursor_representation( - &self, buffer: &ImageBuffer, Vec>, hotspot: (u32, u32) + &self, + buffer: &ImageBuffer, Vec>, + hotspot: (u32, u32), ) -> Result<()> { let (w, h) = buffer.dimensions(); debug!(self.backend.logger, "Importing cursor"); diff --git a/src/backend/drm/mod.rs b/src/backend/drm/mod.rs index 91fe4b3..130cebf 100644 --- a/src/backend/drm/mod.rs +++ b/src/backend/drm/mod.rs @@ -233,8 +233,9 @@ use std::rc::{Rc, Weak}; use std::sync::{Arc, Once, ONCE_INIT}; use std::sync::atomic::{AtomicBool, Ordering}; use std::time::Duration; -use wayland_server::{Display, EventLoopHandle}; -use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest}; +use wayland_server::{Display, LoopToken}; +use wayland_server::commons::{downcast_impl, Implementation}; +use wayland_server::sources::{FdEvent, FdInterest, Source}; mod backend; pub mod error; @@ -378,7 +379,10 @@ impl DrmDevice { /// Errors if initialization fails or the mode is not available on all given /// connectors. pub fn create_backend( - &mut self, crtc: crtc::Handle, mode: Mode, connectors: I + &mut self, + crtc: crtc::Handle, + mode: Mode, + connectors: I, ) -> Result> where I: Into>, @@ -532,44 +536,66 @@ impl Drop for DrmDevice { pub trait DrmHandler { /// The `DrmBackend` of crtc has finished swapping buffers and new frame can now /// (and should be immediately) be rendered. - fn ready( - &mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice, crtc: crtc::Handle, frame: u32, - duration: Duration, - ); + fn ready(&mut self, device: &mut DrmDevice, crtc: crtc::Handle, frame: u32, duration: Duration); /// The `DrmDevice` has thrown an error. /// /// The related backends are most likely *not* usable anymore and /// the whole stack has to be recreated.. - fn error(&mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice, error: DrmError); + fn error(&mut self, device: &mut DrmDevice, error: DrmError); } /// Bind a `DrmDevice` to an `EventLoop`, /// /// This will cause it to recieve events and feed them into an `DrmHandler` pub fn drm_device_bind( - evlh: &mut EventLoopHandle, device: DrmDevice, handler: H -) -> ::std::result::Result, H)>, (IoError, (DrmDevice, H))> + token: &LoopToken, + device: DrmDevice, + handler: H, +) -> ::std::result::Result<(Source, Rc>>), (IoError, (DrmDevice, H))> where A: ControlDevice + 'static, H: DrmHandler + 'static, { let fd = device.as_raw_fd(); - evlh.add_fd_event_source( + let device = Rc::new(RefCell::new(device)); + match token.add_fd_event_source( fd, - fd_event_source_implementation(), - (device, handler), FdInterest::READ, - ) + DrmFdImpl { + device: device.clone(), + handler, + }, + ) { + Ok(source) => Ok((source, device)), + Err(( + ioerror, + DrmFdImpl { + device: device2, + handler, + }, + )) => { + // make the Rc unique again + ::std::mem::drop(device2); + let device = Rc::try_unwrap(device).unwrap_or_else(|_| unreachable!()); + Err((ioerror, (device.into_inner(), handler))) + } + } } -fn fd_event_source_implementation() -> FdEventSourceImpl<(DrmDevice, H)> +struct DrmFdImpl { + device: Rc>>, + handler: H, +} + +impl Implementation<(), FdEvent> for DrmFdImpl where A: ControlDevice + 'static, H: DrmHandler + 'static, { - FdEventSourceImpl { - ready: |evlh, &mut (ref mut device, ref mut handler), _, _| { - match crtc::receive_events(device) { + fn receive(&mut self, event: FdEvent, (): ()) { + let mut device = self.device.borrow_mut(); + match event { + FdEvent::Ready { .. } => match crtc::receive_events(&mut *device) { Ok(events) => for event in events { if let crtc::Event::PageFlip(event) = event { if device.active.load(Ordering::SeqCst) { @@ -584,20 +610,21 @@ where backend.unlock_buffer(); trace!(device.logger, "Handling event for backend {:?}", event.crtc); // and then call the user to render the next frame - handler.ready(evlh, device, event.crtc, event.frame, event.duration); + self.handler + .ready(&mut device, event.crtc, event.frame, event.duration); } else { device.backends.borrow_mut().remove(&event.crtc); } } } }, - Err(err) => handler.error(evlh, device, err), - }; - }, - error: |evlh, &mut (ref mut device, ref mut handler), _, error| { - warn!(device.logger, "DrmDevice errored: {}", error); - handler.error(evlh, device, error.into()); - }, + Err(err) => self.handler.error(&mut device, err), + }, + FdEvent::Error { error, .. } => { + warn!(device.logger, "DrmDevice errored: {}", error); + self.handler.error(&mut device, error.into()); + } + } } } @@ -629,7 +656,7 @@ impl AsSessionObserver> for Drm #[cfg(feature = "backend_session")] impl SessionObserver for DrmDeviceObserver { - fn pause(&mut self, _evlh: &mut EventLoopHandle, devnum: Option<(u32, u32)>) { + fn pause(&mut self, devnum: Option<(u32, u32)>) { if let Some((major, minor)) = devnum { if major as u64 != stat::major(self.device_id) || minor as u64 != stat::minor(self.device_id) { return; @@ -665,7 +692,7 @@ impl SessionObserver for DrmDeviceObserver { } } - fn activate(&mut self, _evlh: &mut EventLoopHandle, devnum: Option<(u32, u32, Option)>) { + fn activate(&mut self, devnum: Option<(u32, u32, Option)>) { if let Some((major, minor, fd)) = devnum { if major as u64 != stat::major(self.device_id) || minor as u64 != stat::minor(self.device_id) { return; diff --git a/src/backend/graphics/egl/context.rs b/src/backend/graphics/egl/context.rs index b564a94..d1abf19 100644 --- a/src/backend/graphics/egl/context.rs +++ b/src/backend/graphics/egl/context.rs @@ -50,7 +50,10 @@ impl> DerefMut for EGLContext> EGLContext { /// Create a new `EGLContext` from a given `NativeDisplay` pub fn new( - native: N, attributes: GlAttributes, reqs: PixelFormatRequirements, logger: L + native: N, + attributes: GlAttributes, + reqs: PixelFormatRequirements, + logger: L, ) -> Result> where L: Into>, @@ -82,7 +85,9 @@ impl> EGLContext { } unsafe fn new_internal( - ptr: ffi::NativeDisplayType, mut attributes: GlAttributes, reqs: PixelFormatRequirements, + ptr: ffi::NativeDisplayType, + mut attributes: GlAttributes, + reqs: PixelFormatRequirements, log: ::slog::Logger, ) -> Result< ( diff --git a/src/backend/graphics/egl/ffi.rs b/src/backend/graphics/egl/ffi.rs index 304506e..2dc0181 100644 --- a/src/backend/graphics/egl/ffi.rs +++ b/src/backend/graphics/egl/ffi.rs @@ -42,7 +42,8 @@ pub mod egl { #[allow(non_snake_case, unused_variables, dead_code)] #[inline] pub unsafe fn BindWaylandDisplayWL( - dpy: types::EGLDisplay, display: *mut __gl_imports::raw::c_void + dpy: types::EGLDisplay, + display: *mut __gl_imports::raw::c_void, ) -> types::EGLBoolean { __gl_imports::mem::transmute::< _, @@ -53,7 +54,8 @@ pub mod egl { #[allow(non_snake_case, unused_variables, dead_code)] #[inline] pub unsafe fn UnbindWaylandDisplayWL( - dpy: types::EGLDisplay, display: *mut __gl_imports::raw::c_void + dpy: types::EGLDisplay, + display: *mut __gl_imports::raw::c_void, ) -> types::EGLBoolean { __gl_imports::mem::transmute::< _, @@ -64,7 +66,9 @@ pub mod egl { #[allow(non_snake_case, unused_variables, dead_code)] #[inline] pub unsafe fn QueryWaylandBufferWL( - dpy: types::EGLDisplay, buffer: *mut __gl_imports::raw::c_void, attribute: types::EGLint, + dpy: types::EGLDisplay, + buffer: *mut __gl_imports::raw::c_void, + attribute: types::EGLint, value: *mut types::EGLint, ) -> types::EGLBoolean { __gl_imports::mem::transmute::< diff --git a/src/backend/graphics/egl/native.rs b/src/backend/graphics/egl/native.rs index b58c72c..cb8a54b 100644 --- a/src/backend/graphics/egl/native.rs +++ b/src/backend/graphics/egl/native.rs @@ -31,7 +31,9 @@ pub trait Backend { /// The returned `EGLDisplay` needs to be a valid ptr for egl, /// but there is no way to test that. unsafe fn get_display bool>( - display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger + display: ffi::NativeDisplayType, + has_dp_extension: F, + log: ::slog::Logger, ) -> ffi::egl::types::EGLDisplay; } @@ -43,7 +45,9 @@ impl Backend for Wayland { type Surface = wegl::WlEglSurface; unsafe fn get_display( - display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger + display: ffi::NativeDisplayType, + has_dp_extension: F, + log: ::slog::Logger, ) -> ffi::egl::types::EGLDisplay where F: Fn(&str) -> bool, @@ -87,7 +91,9 @@ impl Backend for X11 { type Surface = XlibWindow; unsafe fn get_display( - display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger + display: ffi::NativeDisplayType, + has_dp_extension: F, + log: ::slog::Logger, ) -> ffi::egl::types::EGLDisplay where F: Fn(&str) -> bool, @@ -114,7 +120,9 @@ impl Backend for Gbm { type Surface = GbmSurface; unsafe fn get_display( - display: ffi::NativeDisplayType, has_dp_extension: F, log: ::slog::Logger + display: ffi::NativeDisplayType, + has_dp_extension: F, + log: ::slog::Logger, ) -> ffi::egl::types::EGLDisplay where F: Fn(&str) -> bool, diff --git a/src/backend/graphics/egl/surface.rs b/src/backend/graphics/egl/surface.rs index 419c92a..f754e20 100644 --- a/src/backend/graphics/egl/surface.rs +++ b/src/backend/graphics/egl/surface.rs @@ -30,7 +30,8 @@ impl DerefMut for EGLSurface { impl EGLSurface { pub(crate) fn new, D: native::NativeDisplay>( - context: &EGLContext, native: N + context: &EGLContext, + native: N, ) -> Result> { let surface = unsafe { ffi::egl::CreateWindowSurface( diff --git a/src/backend/graphics/egl/wayland.rs b/src/backend/graphics/egl/wayland.rs index 9b9360f..7382837 100644 --- a/src/backend/graphics/egl/wayland.rs +++ b/src/backend/graphics/egl/wayland.rs @@ -192,7 +192,9 @@ impl EGLImages { /// /// The given `tex_id` needs to be a valid GL texture otherwise undefined behavior might occur. pub unsafe fn bind_to_texture( - &self, plane: usize, tex_id: c_uint + &self, + plane: usize, + tex_id: c_uint, ) -> ::std::result::Result<(), TextureCreationError> { if self.display.upgrade().is_some() { let mut old_tex_id: i32 = 0; @@ -255,7 +257,8 @@ pub struct EGLDisplay(Weak, *mut wl_display); impl EGLDisplay { fn new>( - context: &EGLContext, display: *mut wl_display + context: &EGLContext, + display: *mut wl_display, ) -> EGLDisplay { EGLDisplay(Rc::downgrade(&context.display), display) } @@ -266,7 +269,8 @@ impl EGLDisplay { /// a `BufferAccessError::NotManaged(WlBuffer)` is returned with the original buffer /// to render it another way. pub fn egl_buffer_contents( - &self, buffer: Resource + &self, + buffer: Resource, ) -> ::std::result::Result { if let Some(display) = self.0.upgrade() { let mut format: i32 = 0; diff --git a/src/backend/graphics/mod.rs b/src/backend/graphics/mod.rs index 05d276e..6da8e5b 100644 --- a/src/backend/graphics/mod.rs +++ b/src/backend/graphics/mod.rs @@ -30,7 +30,9 @@ pub trait GraphicsBackend { /// from raw image buffers over a fixed list of possible cursor types to simply the /// void type () to represent no possible customization of the cursor itself. fn set_cursor_representation( - &self, cursor: &Self::CursorFormat, hotspot: (u32, u32) + &self, + cursor: &Self::CursorFormat, + hotspot: (u32, u32), ) -> Result<(), Self::Error>; } diff --git a/src/backend/mod.rs b/src/backend/mod.rs index bb2b5c6..92083cd 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -19,11 +19,11 @@ pub mod graphics; //#[cfg(feature = "backend_winit")] //pub mod winit; -//#[cfg(feature = "backend_drm")] -//pub mod drm; +#[cfg(feature = "backend_drm")] +pub mod drm; //#[cfg(feature = "backend_libinput")] //pub mod libinput; #[cfg(feature = "backend_session")] pub mod session; -//#[cfg(feature = "backend_udev")] -//pub mod udev; +#[cfg(feature = "backend_udev")] +pub mod udev; diff --git a/src/backend/session/dbus/logind.rs b/src/backend/session/dbus/logind.rs index dbb13ef..959c373 100644 --- a/src/backend/session/dbus/logind.rs +++ b/src/backend/session/dbus/logind.rs @@ -451,11 +451,7 @@ pub fn logind_session_bind( let mut interest = FdInterest::empty(); interest.set(FdInterest::READ, watch.readable()); interest.set(FdInterest::WRITE, watch.writable()); - token.add_fd_event_source( - watch.fd(), - interest, - notifier.clone(), - ) + token.add_fd_event_source(watch.fd(), interest, notifier.clone()) }) .collect::<::std::result::Result>, (IoError, _)>>() .map_err(|(err, _)| { diff --git a/src/backend/udev.rs b/src/backend/udev.rs index c849d27..a959e49 100644 --- a/src/backend/udev.rs +++ b/src/backend/udev.rs @@ -24,8 +24,9 @@ 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; -use wayland_server::sources::{EventSource, FdEventSource, FdEventSourceImpl, FdInterest}; +use wayland_server::LoopToken; +use wayland_server::commons::Implementation; +use wayland_server::sources::{FdEvent, FdInterest, Source}; /// Udev's `DrmDevice` type based on the underlying session pub struct SessionFdDrmDevice(RawFd); @@ -48,11 +49,13 @@ pub struct UdevBackend< S: Session + 'static, T: UdevHandler + 'static, > { - devices: Rc, H)>>>>, + _handler: ::std::marker::PhantomData, + devices: Rc, Rc>>)>>>, monitor: MonitorSocket, session: S, handler: T, logger: ::slog::Logger, + token: LoopToken, } impl + 'static, S: Session + 'static, T: UdevHandler + 'static> @@ -67,7 +70,11 @@ impl + 'static, S: Session + 'static, T: UdevH /// `handler` - User-provided handler to respond to any detected changes /// `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 + token: LoopToken, + context: &Context, + mut session: S, + mut handler: T, + logger: L, ) -> Result> where L: Into>, @@ -81,7 +88,7 @@ impl + 'static, S: Session + 'static, T: UdevH .flat_map(|path| { match DrmDevice::new( { - match session.open(&path, fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY | fcntl::O_NONBLOCK) { + match session.open(&path, fcntl::OFlag::O_RDWR | fcntl::OFlag::O_CLOEXEC | fcntl::OFlag::O_NOCTTY | fcntl::OFlag::O_NONBLOCK) { Ok(fd) => SessionFdDrmDevice(fd), Err(err) => { warn!(logger, "Unable to open drm device {:?}, Error: {:?}. Skipping", path, err); @@ -94,13 +101,13 @@ impl + 'static, S: Session + 'static, T: UdevH Ok(mut device) => { let devnum = device.device_id(); let fd = device.as_raw_fd(); - match handler.device_added(evlh, &mut device) { + match handler.device_added(&mut device) { Some(drm_handler) => { - match drm_device_bind(&mut evlh, device, drm_handler) { - Ok(event_source) => Some((devnum, event_source)), + match drm_device_bind(&token, device, drm_handler) { + Ok((event_source, device)) => Some((devnum, (event_source, device))), Err((err, (mut device, _))) => { warn!(logger, "Failed to bind device. Error: {:?}.", err); - handler.device_removed(evlh, &mut device); + handler.device_removed(&mut device); drop(device); if let Err(err) = session.close(fd) { warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err); @@ -124,7 +131,7 @@ impl + 'static, S: Session + 'static, T: UdevH } } }) - .collect::, H)>>>(); + .collect::>(); let mut builder = MonitorBuilder::new(context).chain_err(|| ErrorKind::FailedToInitMonitor)?; builder @@ -135,20 +142,25 @@ impl + 'static, S: Session + 'static, T: UdevH .chain_err(|| ErrorKind::FailedToInitMonitor)?; Ok(UdevBackend { + _handler: ::std::marker::PhantomData, devices: Rc::new(RefCell::new(devices)), monitor, session, handler, logger, + token, }) } /// Closes the udev backend and frees all remaining open devices. - pub fn close(&mut self, evlh: &mut EventLoopHandle) { + pub fn close(&mut self) { 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); + for (_, (event_source, device)) in devices.drain() { + event_source.remove(); + let mut device = Rc::try_unwrap(device) + .unwrap_or_else(|_| unreachable!()) + .into_inner(); + self.handler.device_removed(&mut device); let fd = device.as_raw_fd(); drop(device); if let Err(err) = self.session.close(fd) { @@ -163,8 +175,8 @@ impl + 'static, S: Session + 'static, T: UdevH } /// `SessionObserver` linked to the `UdevBackend` it was created from. -pub struct UdevBackendObserver + 'static> { - devices: Weak, H)>>>>, +pub struct UdevBackendObserver { + devices: Weak, Rc>>)>>>, logger: ::slog::Logger, } @@ -172,9 +184,9 @@ impl< H: DrmHandler + 'static, S: Session + 'static, T: UdevHandler + 'static, -> AsSessionObserver> for UdevBackend +> AsSessionObserver for UdevBackend { - fn observer(&mut self) -> UdevBackendObserver { + fn observer(&mut self) -> UdevBackendObserver { UdevBackendObserver { devices: Rc::downgrade(&self.devices), logger: self.logger.clone(), @@ -182,25 +194,21 @@ impl< } } -impl + 'static> SessionObserver for UdevBackendObserver { - fn pause<'a>(&mut self, evlh: &mut EventLoopHandle, devnum: Option<(u32, u32)>) { +impl SessionObserver for UdevBackendObserver { + fn pause<'a>(&mut self, 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); - }) + for &mut (_, ref device) in devices.borrow_mut().values_mut() { + info!(self.logger, "changed successful"); + device.borrow_mut().observer().pause(devnum); } } } - fn activate<'a>(&mut self, evlh: &mut EventLoopHandle, devnum: Option<(u32, u32, Option)>) { + fn activate<'a>(&mut self, devnum: Option<(u32, u32, Option)>) { 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); - }) + for &mut (_, ref device) in devices.borrow_mut().values_mut() { + info!(self.logger, "changed successful"); + device.borrow_mut().observer().activate(devnum); } } } @@ -210,143 +218,154 @@ impl + 'static> SessionObserver for UdevBacken /// /// 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( - evlh: &mut EventLoopHandle, udev: UdevBackend -) -> ::std::result::Result>, (IoError, UdevBackend)> +pub fn udev_backend_bind( + token: &LoopToken, + udev: UdevBackend, +) -> ::std::result::Result, (IoError, UdevBackend)> where H: DrmHandler + 'static, T: UdevHandler + 'static, S: Session + 'static, { let fd = udev.monitor.as_raw_fd(); - evlh.add_fd_event_source(fd, fd_event_source_implementation(), udev, FdInterest::READ) + token.add_fd_event_source(fd, FdInterest::READ, udev) } -fn fd_event_source_implementation() -> FdEventSourceImpl> +impl Implementation<(), FdEvent> for UdevBackend where H: DrmHandler + 'static, T: UdevHandler + 'static, S: Session + 'static, { - FdEventSourceImpl { - ready: |mut evlh, udev, _, _| { - let events = udev.monitor.clone().collect::>(); - for event in events { - match event.event_type() { - // New device - EventType::Add => { - info!(udev.logger, "Device Added"); - if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) { - let mut device = { - match DrmDevice::new( - { - let logger = udev.logger.clone(); - match udev.session.open( - path, - fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY - | fcntl::O_NONBLOCK, - ) { - Ok(fd) => SessionFdDrmDevice(fd), - Err(err) => { + fn receive(&mut self, event: FdEvent, (): ()) { + match event { + FdEvent::Ready { .. } => { + let events = self.monitor.clone().collect::>(); + for event in events { + match event.event_type() { + // New device + EventType::Add => { + info!(self.logger, "Device Added"); + if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) { + let mut device = { + match DrmDevice::new( + { + let logger = self.logger.clone(); + match self.session.open( + path, + fcntl::OFlag::O_RDWR | fcntl::OFlag::O_CLOEXEC + | fcntl::OFlag::O_NOCTTY + | fcntl::OFlag::O_NONBLOCK, + ) { + Ok(fd) => SessionFdDrmDevice(fd), + Err(err) => { + warn!( + logger, + "Unable to open drm device {:?}, Error: {:?}. Skipping", + path, + err + ); + continue; + } + } + }, + self.logger.clone(), + ) { + Ok(dev) => dev, + Err(err) => { + warn!( + self.logger, + "Failed to initialize device {:?}. Error: {}. Skipping", + path, + err + ); + continue; + } + } + }; + let fd = device.as_raw_fd(); + match self.handler.device_added(&mut device) { + Some(drm_handler) => { + match drm_device_bind(&self.token, device, drm_handler) { + Ok(fd_event_source) => { + self.devices.borrow_mut().insert(devnum, fd_event_source); + } + Err((err, (mut device, _))) => { warn!( - logger, - "Unable to open drm device {:?}, Error: {:?}. Skipping", - path, - err + self.logger, + "Failed to bind device. Error: {:?}.", err ); - continue; + self.handler.device_removed(&mut device); + drop(device); + if let Err(err) = self.session.close(fd) { + warn!( + self.logger, + "Failed to close dropped device. Error: {:?}. Ignoring", err + ); + }; } } - }, - udev.logger.clone(), - ) { - Ok(dev) => dev, - Err(err) => { - warn!( - udev.logger, - "Failed to initialize device {:?}. Error: {}. Skipping", - path, - err - ); - continue; } - } - }; - let fd = device.as_raw_fd(); - 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); - } - Err((err, (mut device, _))) => { - warn!(udev.logger, "Failed to bind device. Error: {:?}.", err); - udev.handler.device_removed(evlh, &mut device); + None => { + self.handler.device_removed(&mut device); drop(device); - if let Err(err) = udev.session.close(fd) { + if let Err(err) = self.session.close(fd) { warn!( - udev.logger, - "Failed to close dropped device. Error: {:?}. Ignoring", err + self.logger, + "Failed to close unused device. Error: {:?}", 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 => { - info!(udev.logger, "Device Remove"); - if let Some(devnum) = event.devnum() { - 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) { - warn!( - udev.logger, - "Failed to close device {:?}. Error: {:?}. Ignoring", - event.sysname(), - err - ); }; } } - } - // New connector - EventType::Change => { - info!(udev.logger, "Device Changed"); - if let Some(devnum) = event.devnum() { - info!(udev.logger, "Devnum: {:b}", devnum); - 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"); + // Device removed + EventType::Remove => { + info!(self.logger, "Device Remove"); + if let Some(devnum) = event.devnum() { + if let Some((fd_event_source, device)) = + self.devices.borrow_mut().remove(&devnum) + { + fd_event_source.remove(); + let mut device = Rc::try_unwrap(device) + .unwrap_or_else(|_| unreachable!()) + .into_inner(); + self.handler.device_removed(&mut device); + let fd = device.as_raw_fd(); + drop(device); + if let Err(err) = self.session.close(fd) { + warn!( + self.logger, + "Failed to close device {:?}. Error: {:?}. Ignoring", + event.sysname(), + err + ); + }; + } + } } + // New connector + EventType::Change => { + info!(self.logger, "Device Changed"); + if let Some(devnum) = event.devnum() { + info!(self.logger, "Devnum: {:b}", devnum); + if let Some(&(_, ref device)) = self.devices.borrow_mut().get(&devnum) { + let handler = &mut self.handler; + let logger = &self.logger; + handler.device_changed(&mut device.borrow_mut()); + } else { + info!(self.logger, "changed, but device not tracked by backend"); + }; + } else { + info!(self.logger, "changed, but no devnum"); + } + } + _ => {} } - _ => {} } } - }, - error: |evlh, udev, _, err| udev.handler.error(evlh, err), + FdEvent::Error { error, .. } => self.handler.error(error), + } } } @@ -358,9 +377,7 @@ pub trait UdevHandler + 'static> { /// /// ## Panics /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`. - fn device_added( - &mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice - ) -> Option; + fn device_added(&mut self, device: &mut DrmDevice) -> Option; /// Called when an open device is changed. /// /// This usually indicates that some connectors did become available or were unplugged. The handler @@ -368,7 +385,7 @@ pub trait UdevHandler + 'static> { /// /// ## Panics /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`. - fn device_changed(&mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice); + fn device_changed(&mut self, device: &mut DrmDevice); /// Called when a device was removed. /// /// The device will not accept any operations anymore and its file descriptor will be closed once @@ -376,12 +393,12 @@ pub trait UdevHandler + 'static> { /// /// ## Panics /// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`. - fn device_removed(&mut self, evlh: &mut EventLoopHandle, device: &mut DrmDevice); + fn device_removed(&mut self, device: &mut DrmDevice); /// 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(&mut self, evlh: &mut EventLoopHandle, error: IoError); + fn error(&mut self, error: IoError); } /// Returns the path of the primary gpu device if any