rustfmt code

This commit is contained in:
Drakulix 2017-12-15 18:38:10 +01:00
parent b0d4bdc36d
commit 4207611e6d
21 changed files with 648 additions and 500 deletions

View File

@ -60,7 +60,6 @@ rental! {
} }
use self::graphics::{Graphics, Surface}; use self::graphics::{Graphics, Surface};
/// Backend based on a `DrmDevice` and a given crtc /// Backend based on a `DrmDevice` and a given crtc
pub struct DrmBackend { pub struct DrmBackend {
graphics: Graphics, graphics: Graphics,
@ -71,9 +70,10 @@ pub struct DrmBackend {
} }
impl DrmBackend { impl DrmBackend {
pub(crate) fn new(context: Rc<devices::Context>, crtc: crtc::Handle, mode: Mode, pub(crate) fn new(
connectors: Vec<connector::Handle>, logger: ::slog::Logger) context: Rc<devices::Context>, crtc: crtc::Handle, mode: Mode, connectors: Vec<connector::Handle>,
-> Result<DrmBackend> { logger: ::slog::Logger,
) -> Result<DrmBackend> {
// logger already initialized by the DrmDevice // logger already initialized by the DrmDevice
let log = ::slog_or_stdlog(logger); let log = ::slog_or_stdlog(logger);
info!(log, "Initializing DrmBackend"); info!(log, "Initializing DrmBackend");
@ -145,9 +145,7 @@ impl DrmBackend {
&connectors, &connectors,
(0, 0), (0, 0),
Some(mode), Some(mode),
).chain_err( ).chain_err(|| ErrorKind::DrmDev(format!("{:?}", context.devices.drm)))?;
|| ErrorKind::DrmDev(format!("{:?}", context.devices.drm)),
)?;
front_bo.set_userdata(fb); front_bo.set_userdata(fb);
Ok(EGL { Ok(EGL {
@ -193,9 +191,7 @@ impl DrmBackend {
/// Errors if the new connector does not support the currently set `Mode` /// Errors if the new connector does not support the currently set `Mode`
pub fn add_connector(&mut self, connector: connector::Handle) -> Result<()> { pub fn add_connector(&mut self, connector: connector::Handle) -> Result<()> {
let info = connector::Info::load_from_device(self.graphics.head().head().head(), connector) let info = connector::Info::load_from_device(self.graphics.head().head().head(), connector)
.chain_err(|| { .chain_err(|| ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head())))?;
ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head()))
})?;
// check if the connector can handle the current mode // check if the connector can handle the current mode
if info.modes().contains(&self.mode) { if info.modes().contains(&self.mode) {
@ -203,9 +199,8 @@ impl DrmBackend {
let encoders = info.encoders() let encoders = info.encoders()
.iter() .iter()
.map(|encoder| { .map(|encoder| {
encoder::Info::load_from_device(self.graphics.head().head().head(), *encoder).chain_err( encoder::Info::load_from_device(self.graphics.head().head().head(), *encoder)
|| ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head())), .chain_err(|| ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head())))
)
}) })
.collect::<Result<Vec<encoder::Info>>>()?; .collect::<Result<Vec<encoder::Info>>>()?;
@ -215,9 +210,7 @@ impl DrmBackend {
.head() .head()
.head() .head()
.resource_handles() .resource_handles()
.chain_err(|| { .chain_err(|| ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head())))?;
ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head()))
})?;
if !encoders if !encoders
.iter() .iter()
.map(|encoder| encoder.possible_crtcs()) .map(|encoder| encoder.possible_crtcs())
@ -272,9 +265,7 @@ impl DrmBackend {
// check the connectors // check the connectors
for connector in &self.connectors { for connector in &self.connectors {
if !connector::Info::load_from_device(self.graphics.head().head().head(), *connector) if !connector::Info::load_from_device(self.graphics.head().head().head(), *connector)
.chain_err(|| { .chain_err(|| ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head())))?
ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head()))
})?
.modes() .modes()
.contains(&mode) .contains(&mode)
{ {
@ -295,9 +286,7 @@ impl DrmBackend {
// resolution. // resolution.
debug!( debug!(
logger_ref, logger_ref,
"Reinitializing surface for new mode: {}:{}", "Reinitializing surface for new mode: {}:{}", w, h
w,
h
); );
graphics.gbm.surface = Surface::try_new( graphics.gbm.surface = Surface::try_new(
{ {
@ -340,9 +329,8 @@ impl DrmBackend {
front_bo.format() front_bo.format()
); );
// we need a framebuffer per front_buffer // we need a framebuffer per front_buffer
let fb = framebuffer::create(graphics.context.devices.drm, &*front_bo).chain_err(|| { let fb = framebuffer::create(graphics.context.devices.drm, &*front_bo)
ErrorKind::DrmDev(format!("{:?}", graphics.context.devices.drm)) .chain_err(|| ErrorKind::DrmDev(format!("{:?}", graphics.context.devices.drm)))?;
})?;
debug!(logger_ref, "Initialize screen"); debug!(logger_ref, "Initialize screen");
crtc::set( crtc::set(
@ -352,9 +340,7 @@ impl DrmBackend {
connectors_ref, connectors_ref,
(0, 0), (0, 0),
Some(mode), Some(mode),
).chain_err(|| { ).chain_err(|| ErrorKind::DrmDev(format!("{:?}", graphics.context.devices.drm)))?;
ErrorKind::DrmDev(format!("{:?}", graphics.context.devices.drm))
})?;
front_bo.set_userdata(fb); front_bo.set_userdata(fb);
Ok(EGL { Ok(EGL {
@ -424,13 +410,12 @@ impl GraphicsBackend for DrmBackend {
self.graphics.head().head().head(), self.graphics.head().head().head(),
self.crtc, self.crtc,
(x as i32, y as i32), (x as i32, y as i32),
).chain_err(|| { ).chain_err(|| ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head())))
ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head()))
})
} }
fn set_cursor_representation(&self, buffer: &ImageBuffer<Rgba<u8>, Vec<u8>>, hotspot: (u32, u32)) fn set_cursor_representation(
-> Result<()> { &self, buffer: &ImageBuffer<Rgba<u8>, Vec<u8>>, hotspot: (u32, u32)
) -> Result<()> {
let (w, h) = buffer.dimensions(); let (w, h) = buffer.dimensions();
debug!(self.logger, "Importing cursor"); debug!(self.logger, "Importing cursor");
@ -463,9 +448,9 @@ impl GraphicsBackend for DrmBackend {
(hotspot.0 as i32, hotspot.1 as i32), (hotspot.0 as i32, hotspot.1 as i32),
).is_err() ).is_err()
{ {
crtc::set_cursor(self.graphics.head().head().head(), self.crtc, &cursor).chain_err(|| { crtc::set_cursor(self.graphics.head().head().head(), self.crtc, &cursor).chain_err(
ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head())) || ErrorKind::DrmDev(format!("{:?}", self.graphics.head().head().head())),
})?; )?;
} }
// and store it // and store it
@ -498,7 +483,10 @@ impl EGLGraphicsBackend for DrmBackend {
// would most likely result in a lot of flickering. // would most likely result in a lot of flickering.
// neither weston, wlc or wlroots bother with that as well. // neither weston, wlc or wlroots bother with that as well.
// so we just assume we got at least two buffers to do flipping // so we just assume we got at least two buffers to do flipping
let mut next_bo = surface.gbm.lock_front_buffer().expect("Surface only has one front buffer. Not supported by smithay"); let mut next_bo = surface
.gbm
.lock_front_buffer()
.expect("Surface only has one front buffer. Not supported by smithay");
// create a framebuffer if the front buffer does not have one already // create a framebuffer if the front buffer does not have one already
// (they are reused by gbm) // (they are reused by gbm)
@ -506,7 +494,8 @@ impl EGLGraphicsBackend for DrmBackend {
let fb = if let Some(info) = maybe_fb { let fb = if let Some(info) = maybe_fb {
info info
} else { } else {
let fb = framebuffer::create(graphics.context.devices.drm, &*next_bo).map_err(|_| SwapBuffersError::ContextLost)?; let fb = framebuffer::create(graphics.context.devices.drm, &*next_bo)
.map_err(|_| SwapBuffersError::ContextLost)?;
next_bo.set_userdata(fb); next_bo.set_userdata(fb);
fb fb
}; };
@ -515,7 +504,12 @@ impl EGLGraphicsBackend for DrmBackend {
trace!(self.logger, "Queueing Page flip"); trace!(self.logger, "Queueing Page flip");
// and flip // and flip
crtc::page_flip(graphics.context.devices.drm, self.crtc, fb.handle(), &[crtc::PageFlipFlags::PageFlipEvent]).map_err(|_| SwapBuffersError::ContextLost) crtc::page_flip(
graphics.context.devices.drm,
self.crtc,
fb.handle(),
&[crtc::PageFlipFlags::PageFlipEvent],
).map_err(|_| SwapBuffersError::ContextLost)
}) })
}) })
} }
@ -532,7 +526,9 @@ impl EGLGraphicsBackend for DrmBackend {
} }
fn is_current(&self) -> bool { fn is_current(&self) -> bool {
self.graphics.rent_all(|graphics| graphics.context.egl.is_current() && graphics.gbm.surface.rent(|egl| egl.surface.is_current())) self.graphics.rent_all(|graphics| {
graphics.context.egl.is_current() && graphics.gbm.surface.rent(|egl| egl.surface.is_current())
})
} }
unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError> { unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError> {

View File

@ -188,9 +188,9 @@
//! ``` //! ```
use backend::graphics::egl::{EGLContext, GlAttributes, PixelFormatRequirements}; use backend::graphics::egl::{EGLContext, GlAttributes, PixelFormatRequirements};
use backend::graphics::egl::EGLGraphicsBackend;
#[cfg(feature = "backend_session")] #[cfg(feature = "backend_session")]
use backend::session::SessionObserver; use backend::session::SessionObserver;
use backend::graphics::egl::EGLGraphicsBackend;
use drm::Device as BasicDevice; use drm::Device as BasicDevice;
use drm::control::{connector, crtc, encoder, Mode, ResourceInfo}; use drm::control::{connector, crtc, encoder, Mode, ResourceInfo};
use drm::control::Device as ControlDevice; use drm::control::Device as ControlDevice;
@ -204,11 +204,11 @@ use std::collections::HashMap;
use std::fs::File; use std::fs::File;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::io::Result as IoResult; use std::io::Result as IoResult;
use std::os::unix::io::{IntoRawFd, AsRawFd, RawFd};
use std::rc::Rc;
use std::mem; use std::mem;
use std::os::unix::io::{AsRawFd, IntoRawFd, RawFd};
use std::rc::Rc;
use std::time::Duration; use std::time::Duration;
use wayland_server::{EventLoopHandle, StateToken, StateProxy}; use wayland_server::{EventLoopHandle, StateProxy, StateToken};
use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest}; use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};
mod backend; mod backend;
@ -369,25 +369,21 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
let mut old_state = HashMap::new(); let mut old_state = HashMap::new();
let res_handles = drm.resource_handles() let res_handles = drm.resource_handles()
.chain_err(|| { .chain_err(|| ErrorKind::DrmDev(format!("Loading drm resources on {:?}", drm)))?;
ErrorKind::DrmDev(format!("Loading drm resources on {:?}", drm))
})?;
for &con in res_handles.connectors() { for &con in res_handles.connectors() {
let con_info = connector::Info::load_from_device(&drm, con) let con_info = connector::Info::load_from_device(&drm, con)
.chain_err(|| { .chain_err(|| ErrorKind::DrmDev(format!("Loading connector info on {:?}", drm)))?;
ErrorKind::DrmDev(format!("Loading connector info on {:?}", drm))
})?;
if let Some(enc) = con_info.current_encoder() { if let Some(enc) = con_info.current_encoder() {
let enc_info = encoder::Info::load_from_device(&drm, enc) let enc_info = encoder::Info::load_from_device(&drm, enc)
.chain_err(|| { .chain_err(|| ErrorKind::DrmDev(format!("Loading encoder info on {:?}", drm)))?;
ErrorKind::DrmDev(format!("Loading encoder info on {:?}", drm))
})?;
if let Some(crtc) = enc_info.current_crtc() { if let Some(crtc) = enc_info.current_crtc() {
let info = crtc::Info::load_from_device(&drm, crtc) let info = crtc::Info::load_from_device(&drm, crtc)
.chain_err(|| { .chain_err(|| ErrorKind::DrmDev(format!("Loading crtc info on {:?}", drm)))?;
ErrorKind::DrmDev(format!("Loading crtc info on {:?}", drm)) old_state
})?; .entry(crtc)
old_state.entry(crtc).or_insert((info, Vec::new())).1.push(con); .or_insert((info, Vec::new()))
.1
.push(con);
} }
} }
} }
@ -426,8 +422,9 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
/// ///
/// Errors if initialization fails or the mode is not available on all given /// Errors if initialization fails or the mode is not available on all given
/// connectors. /// connectors.
pub fn create_backend<'a, I, S>(&mut self, state: S, crtc: crtc::Handle, mode: Mode, connectors: I) pub fn create_backend<'a, I, S>(
-> Result<&StateToken<B>> &mut self, state: S, crtc: crtc::Handle, mode: Mode, connectors: I
) -> Result<&StateToken<B>>
where where
I: Into<Vec<connector::Handle>>, I: Into<Vec<connector::Handle>>,
S: Into<StateProxy<'a>>, S: Into<StateProxy<'a>>,
@ -447,7 +444,10 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
for connector in &connectors { for connector in &connectors {
let con_info = connector::Info::load_from_device(self.context.head().head(), *connector) let con_info = connector::Info::load_from_device(self.context.head().head(), *connector)
.chain_err(|| { .chain_err(|| {
ErrorKind::DrmDev(format!("Loading connector info on {:?}", self.context.head().head())) ErrorKind::DrmDev(format!(
"Loading connector info on {:?}",
self.context.head().head()
))
})?; })?;
// check the mode // check the mode
@ -461,21 +461,26 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
.iter() .iter()
.map(|encoder| { .map(|encoder| {
encoder::Info::load_from_device(self.context.head().head(), *encoder).chain_err(|| { encoder::Info::load_from_device(self.context.head().head(), *encoder).chain_err(|| {
ErrorKind::DrmDev(format!("Loading encoder info on {:?}", self.context.head().head())) ErrorKind::DrmDev(format!(
"Loading encoder info on {:?}",
self.context.head().head()
))
}) })
}) })
.collect::<Result<Vec<encoder::Info>>>()?; .collect::<Result<Vec<encoder::Info>>>()?;
// and if any encoder supports the selected crtc // and if any encoder supports the selected crtc
let resource_handles = self.resource_handles().chain_err(|| { let resource_handles = self.resource_handles().chain_err(|| {
ErrorKind::DrmDev(format!("Loading drm resources on {:?}", self.context.head().head())) ErrorKind::DrmDev(format!(
"Loading drm resources on {:?}",
self.context.head().head()
))
})?; })?;
if !encoders if !encoders
.iter() .iter()
.map(|encoder| encoder.possible_crtcs()) .map(|encoder| encoder.possible_crtcs())
.any(|crtc_list| { .any(|crtc_list| resource_handles.filter_crtcs(crtc_list).contains(&crtc))
resource_handles.filter_crtcs(crtc_list).contains(&crtc) {
}) {
bail!(ErrorKind::NoSuitableEncoder(con_info, crtc)) bail!(ErrorKind::NoSuitableEncoder(con_info, crtc))
} }
} }
@ -484,7 +489,8 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
let logger = self.logger.new(o!("crtc" => format!("{:?}", crtc))); let logger = self.logger.new(o!("crtc" => format!("{:?}", crtc)));
let backend = DrmBackend::new(self.context.clone(), crtc, mode, connectors, logger)?; let backend = DrmBackend::new(self.context.clone(), crtc, mode, connectors, logger)?;
self.backends.insert(crtc, state.into().insert(backend.into())); self.backends
.insert(crtc, state.into().insert(backend.into()));
Ok(self.backends.get(&crtc).unwrap()) Ok(self.backends.get(&crtc).unwrap())
} }
@ -505,7 +511,7 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static> DrmDevice<B> {
/// Panics if the backend is already borrowed from the state /// Panics if the backend is already borrowed from the state
pub fn destroy_backend<'a, S>(&mut self, state: S, crtc: &crtc::Handle) pub fn destroy_backend<'a, S>(&mut self, state: S, crtc: &crtc::Handle)
where where
S: Into<StateProxy<'a>> S: Into<StateProxy<'a>>,
{ {
if let Some(token) = self.backends.remove(crtc) { if let Some(token) = self.backends.remove(crtc) {
state.into().remove(token); state.into().remove(token);
@ -540,12 +546,25 @@ impl<B: Borrow<DrmBackend> + 'static> Drop for DrmDevice<B> {
panic!("Pending DrmBackends. Please free all backends before the DrmDevice gets destroyed"); panic!("Pending DrmBackends. Please free all backends before the DrmDevice gets destroyed");
} }
for (handle, (info, connectors)) in self.old_state.drain() { for (handle, (info, connectors)) in self.old_state.drain() {
if let Err(err) = crtc::set(self.context.head().head(), handle, info.fb(), &connectors, info.position(), info.mode()) { if let Err(err) = crtc::set(
error!(self.logger, "Failed to reset crtc ({:?}). Error: {}", handle, err); self.context.head().head(),
handle,
info.fb(),
&connectors,
info.position(),
info.mode(),
) {
error!(
self.logger,
"Failed to reset crtc ({:?}). Error: {}", handle, err
);
} }
} }
if let Err(err) = self.drop_master() { if let Err(err) = self.drop_master() {
error!(self.logger, "Failed to drop drm master state. Error: {}", err); error!(
self.logger,
"Failed to drop drm master state. Error: {}", err
);
} }
} }
} }
@ -569,8 +588,10 @@ pub trait DrmHandler<B: Borrow<DrmBackend> + 'static> {
/// ## Panics /// ## Panics
/// The device is already borrowed from the given `state`. Borrowing it again will panic /// The device is already borrowed from the given `state`. Borrowing it again will panic
/// and is not necessary as it is already provided via the `device` parameter. /// and is not necessary as it is already provided via the `device` parameter.
fn ready<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, device: &mut DrmDevice<B>, backend: &StateToken<B>, fn ready<'a, S: Into<StateProxy<'a>>>(
crtc: crtc::Handle, frame: u32, duration: Duration); &mut self, state: S, device: &mut DrmDevice<B>, backend: &StateToken<B>, crtc: crtc::Handle,
frame: u32, duration: Duration,
);
/// The `DrmDevice` has thrown an error. /// The `DrmDevice` has thrown an error.
/// ///
/// The related backends are most likely *not* usable anymore and /// The related backends are most likely *not* usable anymore and
@ -585,8 +606,9 @@ pub trait DrmHandler<B: Borrow<DrmBackend> + 'static> {
/// Bind a `DrmDevice` to an `EventLoop`, /// Bind a `DrmDevice` to an `EventLoop`,
/// ///
/// This will cause it to recieve events and feed them into an `DrmHandler` /// This will cause it to recieve events and feed them into an `DrmHandler`
pub fn drm_device_bind<B, H>(evlh: &mut EventLoopHandle, device: StateToken<DrmDevice<B>>, handler: H) pub fn drm_device_bind<B, H>(
-> IoResult<FdEventSource<(StateToken<DrmDevice<B>>, H)>> evlh: &mut EventLoopHandle, device: StateToken<DrmDevice<B>>, handler: H
) -> IoResult<FdEventSource<(StateToken<DrmDevice<B>>, H)>>
where where
B: From<DrmBackend> + Borrow<DrmBackend> + 'static, B: From<DrmBackend> + Borrow<DrmBackend> + 'static,
H: DrmHandler<B> + 'static, H: DrmHandler<B> + 'static,
@ -624,13 +646,22 @@ where
state.get(&backend_token).borrow().unlock_buffer(); state.get(&backend_token).borrow().unlock_buffer();
trace!(logger, "Handling event for backend {:?}", event.crtc); trace!(logger, "Handling event for backend {:?}", event.crtc);
// and then call the user to render the next frame // and then call the user to render the next frame
handler.ready(state, &mut dev, &backend_token, event.crtc, event.frame, event.duration); handler.ready(
state,
&mut dev,
&backend_token,
event.crtc,
event.frame,
event.duration,
);
} }
} }
}); });
} }
}, },
Err(err) => evlh.state().with_value(dev_token, |state, mut dev| handler.error(state, &mut dev, err)), Err(err) => evlh.state().with_value(dev_token, |state, mut dev| {
handler.error(state, &mut dev, err)
}),
}; };
}, },
error: |evlh, &mut (ref mut dev_token, ref mut handler), _, error| { error: |evlh, &mut (ref mut dev_token, ref mut handler), _, error| {
@ -648,7 +679,10 @@ impl<B: Borrow<DrmBackend> + 'static> SessionObserver for StateToken<DrmDevice<B
let device: &mut DrmDevice<B> = state.get_mut(self); let device: &mut DrmDevice<B> = state.get_mut(self);
device.active = false; device.active = false;
if let Err(err) = device.drop_master() { if let Err(err) = device.drop_master() {
error!(device.logger, "Failed to drop drm master state. Error: {}", err); error!(
device.logger,
"Failed to drop drm master state. Error: {}", err
);
} }
} }
@ -656,13 +690,22 @@ impl<B: Borrow<DrmBackend> + 'static> SessionObserver for StateToken<DrmDevice<B
state.with_value(self, |state, device| { state.with_value(self, |state, device| {
device.active = true; device.active = true;
if let Err(err) = device.set_master() { if let Err(err) = device.set_master() {
crit!(device.logger, "Failed to acquire drm master again. Error: {}", err); crit!(
device.logger,
"Failed to acquire drm master again. Error: {}",
err
);
} }
for token in device.backends.values() { for token in device.backends.values() {
let backend = state.get(token); let backend = state.get(token);
if let Err(err) = backend.borrow().swap_buffers() { if let Err(err) = backend.borrow().swap_buffers() {
// TODO handle this better? // TODO handle this better?
error!(device.logger, "Failed to activate crtc ({:?}) again. Error: {}", backend.borrow().crtc(), err); error!(
device.logger,
"Failed to activate crtc ({:?}) again. Error: {}",
backend.borrow().crtc(),
err
);
} }
} }
}) })

View File

@ -238,9 +238,9 @@ pub struct EGLContext<'a, T: NativeSurface> {
impl<'a> EGLContext<'a, ()> { impl<'a> EGLContext<'a, ()> {
/// Create a new context from a given `winit`-`Window` /// Create a new context from a given `winit`-`Window`
#[cfg(feature = "backend_winit")] #[cfg(feature = "backend_winit")]
pub fn new_from_winit<L>(window: &'a WinitWindow, attributes: GlAttributes, pub fn new_from_winit<L>(
reqs: PixelFormatRequirements, logger: L) window: &'a WinitWindow, attributes: GlAttributes, reqs: PixelFormatRequirements, logger: L
-> Result<EGLContext<'a, WinitWindow>> ) -> Result<EGLContext<'a, WinitWindow>>
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
{ {
@ -268,9 +268,9 @@ impl<'a> EGLContext<'a, ()> {
/// Create a new context from a given `gbm::Device` /// Create a new context from a given `gbm::Device`
#[cfg(feature = "backend_drm")] #[cfg(feature = "backend_drm")]
pub fn new_from_gbm<L, U: 'static>(gbm: &'a GbmDevice<'a>, attributes: GlAttributes, pub fn new_from_gbm<L, U: 'static>(
reqs: PixelFormatRequirements, logger: L) gbm: &'a GbmDevice<'a>, attributes: GlAttributes, reqs: PixelFormatRequirements, logger: L
-> Result<EGLContext<'a, GbmSurface<'a, U>>> ) -> Result<EGLContext<'a, GbmSurface<'a, U>>>
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
{ {
@ -288,9 +288,10 @@ impl<'a> EGLContext<'a, ()> {
} }
impl<'a, T: NativeSurface> EGLContext<'a, T> { impl<'a, T: NativeSurface> EGLContext<'a, T> {
unsafe fn new(native: NativeDisplayPtr, mut attributes: GlAttributes, reqs: PixelFormatRequirements, unsafe fn new(
log: ::slog::Logger) native: NativeDisplayPtr, mut attributes: GlAttributes, reqs: PixelFormatRequirements,
-> Result<EGLContext<'a, T>> log: ::slog::Logger,
) -> Result<EGLContext<'a, T>>
where where
T: NativeSurface, T: NativeSurface,
{ {
@ -322,8 +323,7 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> {
Some(version) => { Some(version) => {
error!( error!(
log, log,
"OpenGLES {:?} is unknown and not supported by the EGL renderer backend", "OpenGLES {:?} is unknown and not supported by the EGL renderer backend", version
version
); );
bail!(ErrorKind::OpenGlVersionNotSupported(version)); bail!(ErrorKind::OpenGlVersionNotSupported(version));
} }
@ -423,9 +423,9 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> {
) )
} }
NativeDisplayPtr::X11(display) | NativeDisplayPtr::X11(display)
NativeDisplayPtr::Gbm(display) | | NativeDisplayPtr::Gbm(display)
NativeDisplayPtr::Wayland(display) => { | NativeDisplayPtr::Wayland(display) => {
trace!(log, "Default EGL Display Initialization via GetDisplay"); trace!(log, "Default EGL Display Initialization via GetDisplay");
egl.GetDisplay(display as *mut _) egl.GetDisplay(display as *mut _)
} }
@ -727,9 +727,9 @@ impl<'a, T: NativeSurface> EGLContext<'a, T> {
self.display, self.display,
self.config_id, self.config_id,
match surface { match surface {
NativeSurfacePtr::X11(ptr) | NativeSurfacePtr::X11(ptr)
NativeSurfacePtr::Wayland(ptr) | | NativeSurfacePtr::Wayland(ptr)
NativeSurfacePtr::Gbm(ptr) => ptr, | NativeSurfacePtr::Gbm(ptr) => ptr,
}, },
self.surface_attributes.as_ptr(), self.surface_attributes.as_ptr(),
) )
@ -850,8 +850,10 @@ impl<'context, 'surface, T: NativeSurface> EGLSurface<'context, 'surface, T> {
/// Returns true if the OpenGL surface is the current one in the thread. /// Returns true if the OpenGL surface is the current one in the thread.
pub fn is_current(&self) -> bool { pub fn is_current(&self) -> bool {
unsafe { self.context.egl.GetCurrentSurface(ffi::egl::DRAW as _) == self.surface as *const _ && unsafe {
self.context.egl.GetCurrentSurface(ffi::egl::READ as _) == self.surface as *const _ } self.context.egl.GetCurrentSurface(ffi::egl::DRAW as _) == self.surface as *const _
&& self.context.egl.GetCurrentSurface(ffi::egl::READ as _) == self.surface as *const _
}
} }
} }
@ -905,10 +907,8 @@ impl error::Error for SwapBuffersError {
SwapBuffersError::ContextLost => "The context has been lost, it needs to be recreated", SwapBuffersError::ContextLost => "The context has been lost, it needs to be recreated",
SwapBuffersError::AlreadySwapped => { SwapBuffersError::AlreadySwapped => {
"Buffers are already swapped, swap_buffers was called too many times" "Buffers are already swapped, swap_buffers was called too many times"
},
SwapBuffersError::Unknown(_) => {
"Unknown Open GL error occurred"
} }
SwapBuffersError::Unknown(_) => "Unknown Open GL error occurred",
} }
} }

View File

@ -29,8 +29,9 @@ pub trait GraphicsBackend {
/// The format is entirely dictated by the concrete implementation and might range /// The format is entirely dictated by the concrete implementation and might range
/// from raw image buffers over a fixed list of possible cursor types to simply the /// 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. /// void type () to represent no possible customization of the cursor itself.
fn set_cursor_representation(&self, cursor: &Self::CursorFormat, hotspot: (u32, u32)) fn set_cursor_representation(
-> Result<(), Self::Error>; &self, cursor: &Self::CursorFormat, hotspot: (u32, u32)
) -> Result<(), Self::Error>;
} }
pub mod software; pub mod software;

View File

@ -1,6 +1,5 @@
//! Common traits and types used for software rendering on graphics backends //! Common traits and types used for software rendering on graphics backends
use super::GraphicsBackend; use super::GraphicsBackend;
use std::error::Error; use std::error::Error;
use wayland_server::protocol::wl_shm::Format; use wayland_server::protocol::wl_shm::Format;

View File

@ -1,16 +1,16 @@
//! Implementation of input backend trait for types provided by `libinput` //! Implementation of input backend trait for types provided by `libinput`
use backend::input as backend;
#[cfg(feature = "backend_session")] #[cfg(feature = "backend_session")]
use backend::session::{AsErrno, Session, SessionObserver}; use backend::session::{AsErrno, Session, SessionObserver};
use backend::input as backend;
use input as libinput; use input as libinput;
use input::event; use input::event;
use std::collections::hash_map::{DefaultHasher, Entry, HashMap}; use std::collections::hash_map::{DefaultHasher, Entry, HashMap};
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::io::{Error as IoError, Result as IoResult}; use std::io::{Error as IoError, Result as IoResult};
use std::rc::Rc;
use std::path::Path;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use std::path::Path;
use std::rc::Rc;
use wayland_server::{EventLoopHandle, StateProxy}; use wayland_server::{EventLoopHandle, StateProxy};
use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest}; use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};
@ -583,7 +583,9 @@ impl<S: Session> From<S> for LibinputSessionInterface<S> {
impl<S: Session> libinput::LibinputInterface for LibinputSessionInterface<S> { impl<S: Session> libinput::LibinputInterface for LibinputSessionInterface<S> {
fn open_restricted(&mut self, path: &Path, flags: i32) -> Result<RawFd, i32> { fn open_restricted(&mut self, path: &Path, flags: i32) -> Result<RawFd, i32> {
use nix::fcntl::OFlag; use nix::fcntl::OFlag;
self.0.open(path, OFlag::from_bits_truncate(flags)).map_err(|err| err.as_errno().unwrap_or(1 /*Use EPERM by default*/)) self.0
.open(path, OFlag::from_bits_truncate(flags))
.map_err(|err| err.as_errno().unwrap_or(1 /*Use EPERM by default*/))
} }
fn close_restricted(&mut self, fd: RawFd) { fn close_restricted(&mut self, fd: RawFd) {
@ -595,9 +597,9 @@ impl<S: Session> libinput::LibinputInterface for LibinputSessionInterface<S> {
/// ///
/// Automatically feeds the backend with incoming events without any manual calls to /// Automatically feeds the backend with incoming events without any manual calls to
/// `dispatch_new_events`. Should be used to achieve the smallest possible latency. /// `dispatch_new_events`. Should be used to achieve the smallest possible latency.
pub fn libinput_bind(backend: LibinputInputBackend, evlh: &mut EventLoopHandle) pub fn libinput_bind(
-> IoResult<FdEventSource<LibinputInputBackend>> backend: LibinputInputBackend, evlh: &mut EventLoopHandle
{ ) -> IoResult<FdEventSource<LibinputInputBackend>> {
let fd = unsafe { backend.context.fd() }; let fd = unsafe { backend.context.fd() };
evlh.add_fd_event_source( evlh.add_fd_event_source(
fd, fd,
@ -610,13 +612,13 @@ pub fn libinput_bind(backend: LibinputInputBackend, evlh: &mut EventLoopHandle)
fn fd_event_source_implementation() -> FdEventSourceImpl<LibinputInputBackend> { fn fd_event_source_implementation() -> FdEventSourceImpl<LibinputInputBackend> {
FdEventSourceImpl { FdEventSourceImpl {
ready: |_evlh, ref mut backend, _, _| { ready: |_evlh, ref mut backend, _, _| {
use ::backend::input::InputBackend; use backend::input::InputBackend;
if let Err(error) = backend.dispatch_new_events() { if let Err(error) = backend.dispatch_new_events() {
warn!(backend.logger, "Libinput errored: {}", error); warn!(backend.logger, "Libinput errored: {}", error);
} }
}, },
error: |_evlh, ref backend, _, error| { error: |_evlh, ref backend, _, error| {
warn!(backend.logger, "Libinput fd errored: {}", error); warn!(backend.logger, "Libinput fd errored: {}", error);
} },
} }
} }

View File

@ -46,24 +46,22 @@
//! automatically by the `UdevBackend`, if not done manually). //! automatically by the `UdevBackend`, if not done manually).
//! ``` //! ```
use std::io::Result as IoResult; use super::{AsErrno, Session, SessionNotifier, SessionObserver};
use std::path::Path;
use std::os::unix::io::RawFd;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use nix::{Error as NixError, Result as NixResult}; use nix::{Error as NixError, Result as NixResult};
use nix::fcntl::{self, open, OFlag}; use nix::fcntl::{self, open, OFlag};
use nix::libc::c_int; use nix::libc::c_int;
use nix::sys::signal::{self, Signal}; use nix::sys::signal::{self, Signal};
use nix::sys::stat::{dev_t, major, minor, Mode, fstat}; use nix::sys::stat::{dev_t, fstat, major, minor, Mode};
use nix::unistd::{dup, close}; use nix::unistd::{close, dup};
use wayland_server::EventLoopHandle; use std::io::Result as IoResult;
use wayland_server::sources::SignalEventSource; use std::os::unix::io::RawFd;
use std::path::Path;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
#[cfg(feature = "backend_session_udev")] #[cfg(feature = "backend_session_udev")]
use udev::Context; use udev::Context;
use wayland_server::EventLoopHandle;
use super::{AsErrno, Session, SessionNotifier, SessionObserver}; use wayland_server::sources::SignalEventSource;
#[allow(dead_code)] #[allow(dead_code)]
mod tty { mod tty {
@ -102,7 +100,7 @@ mod tty {
pub const VT_PROCESS: i8 = 0x01; pub const VT_PROCESS: i8 = 0x01;
pub const VT_ACKACQ: i32 = 0x02; pub const VT_ACKACQ: i32 = 0x02;
extern { extern "C" {
pub fn __libc_current_sigrtmin() -> i8; pub fn __libc_current_sigrtmin() -> i8;
pub fn __libc_current_sigrtmax() -> i8; pub fn __libc_current_sigrtmax() -> i8;
} }
@ -139,8 +137,8 @@ fn is_tty_device(dev: dev_t, path: Option<&Path>) -> bool {
major(dev) == TTY_MAJOR major(dev) == TTY_MAJOR
}; };
res || minor(dev) != 0 res || minor(dev) != 0
}, }
None => major(dev) == TTY_MAJOR || minor(dev) != 0 None => major(dev) == TTY_MAJOR || minor(dev) != 0,
} }
} }
@ -167,34 +165,36 @@ impl DirectSession {
/// ///
/// If you do not provide a tty device path, it will try to open the currently active tty if any. /// If you do not provide a tty device path, it will try to open the currently active tty if any.
pub fn new<L>(tty: Option<&Path>, logger: L) -> Result<(DirectSession, DirectSessionNotifier)> pub fn new<L>(tty: Option<&Path>, logger: L) -> Result<(DirectSession, DirectSessionNotifier)>
where where
L: Into<Option<::slog::Logger>> L: Into<Option<::slog::Logger>>,
{ {
let logger = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_session", "session_type" => "direct/vt")); let logger = ::slog_or_stdlog(logger)
.new(o!("smithay_module" => "backend_session", "session_type" => "direct/vt"));
let fd = tty let fd = tty.map(|path| {
.map(|path| open(path, fcntl::O_RDWR | fcntl::O_CLOEXEC, Mode::empty()) open(path, fcntl::O_RDWR | fcntl::O_CLOEXEC, Mode::empty())
.chain_err(|| ErrorKind::FailedToOpenTTY(String::from(path.to_string_lossy())))) .chain_err(|| ErrorKind::FailedToOpenTTY(String::from(path.to_string_lossy())))
.unwrap_or(dup(0 /*stdin*/).chain_err(|| ErrorKind::FailedToOpenTTY(String::from("<stdin>"))))?; }).unwrap_or(dup(0 /*stdin*/).chain_err(|| ErrorKind::FailedToOpenTTY(String::from("<stdin>"))))?;
let active = Arc::new(AtomicBool::new(true)); let active = Arc::new(AtomicBool::new(true));
match DirectSession::setup_tty(tty, fd, logger.clone()) { match DirectSession::setup_tty(tty, fd, logger.clone()) {
Ok((vt, old_keyboard_mode, signal)) => { Ok((vt, old_keyboard_mode, signal)) => Ok((
Ok((DirectSession { DirectSession {
tty: fd, tty: fd,
active: active.clone(), active: active.clone(),
vt, vt,
old_keyboard_mode, old_keyboard_mode,
logger: logger.new(o!("vt" => format!("{}", vt), "component" => "session")), logger: logger.new(o!("vt" => format!("{}", vt), "component" => "session")),
}, DirectSessionNotifier { },
DirectSessionNotifier {
tty: fd, tty: fd,
active, active,
signals: Vec::new(), signals: Vec::new(),
signal, signal,
logger: logger.new(o!("vt" => format!("{}", vt), "component" => "session_notifier")) logger: logger.new(o!("vt" => format!("{}", vt), "component" => "session_notifier")),
})) },
}, )),
Err(err) => { Err(err) => {
let _ = close(fd); let _ = close(fd);
Err(err) Err(err)
@ -226,9 +226,11 @@ impl DirectSession {
let mut old_keyboard_mode = 0; let mut old_keyboard_mode = 0;
unsafe { unsafe {
tty::kd_get_kb_mode(tty, &mut old_keyboard_mode).chain_err(|| ErrorKind::FailedToSaveTTYState(vt_num))?; tty::kd_get_kb_mode(tty, &mut old_keyboard_mode)
.chain_err(|| ErrorKind::FailedToSaveTTYState(vt_num))?;
tty::kd_set_kb_mode(tty, tty::K_OFF).chain_err(|| ErrorKind::FailedToSetTTYKbMode(vt_num))?; tty::kd_set_kb_mode(tty, tty::K_OFF).chain_err(|| ErrorKind::FailedToSetTTYKbMode(vt_num))?;
tty::kd_set_mode(tty, tty::KD_GRAPHICS as i32).chain_err(|| ErrorKind::FailedToSetTTYMode(vt_num))?; tty::kd_set_mode(tty, tty::KD_GRAPHICS as i32)
.chain_err(|| ErrorKind::FailedToSetTTYMode(vt_num))?;
} }
// TODO: Support realtime signals // TODO: Support realtime signals
@ -305,19 +307,33 @@ impl Drop for DirectSession {
info!(self.logger, "Deallocating tty {}", self.tty); info!(self.logger, "Deallocating tty {}", self.tty);
if let Err(err) = unsafe { tty::kd_set_kb_mode(self.tty, self.old_keyboard_mode) } { if let Err(err) = unsafe { tty::kd_set_kb_mode(self.tty, self.old_keyboard_mode) } {
warn!(self.logger, "Unable to restore vt keyboard mode. Error: {}", err); warn!(
self.logger,
"Unable to restore vt keyboard mode. Error: {}", err
);
} }
if let Err(err) = unsafe { tty::kd_set_mode(self.tty, tty::KD_TEXT as i32) } { if let Err(err) = unsafe { tty::kd_set_mode(self.tty, tty::KD_TEXT as i32) } {
warn!(self.logger, "Unable to restore vt text mode. Error: {}", err); warn!(
self.logger,
"Unable to restore vt text mode. Error: {}", err
);
} }
if let Err(err) = unsafe { tty::vt_set_mode(self.tty, &tty::VtMode { if let Err(err) = unsafe {
mode: tty::VT_AUTO, tty::vt_set_mode(
..Default::default() self.tty,
}) } { &tty::VtMode {
mode: tty::VT_AUTO,
..Default::default()
},
)
} {
error!(self.logger, "Failed to reset vt handling. Error: {}", err); error!(self.logger, "Failed to reset vt handling. Error: {}", err);
} }
if let Err(err) = close(self.tty) { if let Err(err) = close(self.tty) {
error!(self.logger, "Failed to close tty file descriptor. Error: {}", err); error!(
self.logger,
"Failed to close tty file descriptor. Error: {}", err
);
} }
} }
} }
@ -350,36 +366,45 @@ impl SessionNotifier for DirectSessionNotifier {
/// Allows the `DirectSessionNotifier` to listen for the incoming signals signalling the session state. /// Allows the `DirectSessionNotifier` to listen for the incoming signals signalling the session state.
/// If you don't use this function `DirectSessionNotifier` will not correctly tell you the current /// If you don't use this function `DirectSessionNotifier` will not correctly tell you the current
/// session state. /// session state.
pub fn direct_session_bind<L>(notifier: DirectSessionNotifier, evlh: &mut EventLoopHandle, _logger: L) pub fn direct_session_bind<L>(
-> IoResult<SignalEventSource<DirectSessionNotifier>> notifier: DirectSessionNotifier, evlh: &mut EventLoopHandle, _logger: L
) -> IoResult<SignalEventSource<DirectSessionNotifier>>
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
{ {
let signal = notifier.signal; let signal = notifier.signal;
evlh.add_signal_event_source(|evlh, notifier, _| { evlh.add_signal_event_source(
if notifier.is_active() { |evlh, notifier, _| {
info!(notifier.logger, "Session shall become inactive"); if notifier.is_active() {
for signal in &mut notifier.signals { info!(notifier.logger, "Session shall become inactive");
if let &mut Some(ref mut signal) = signal {signal.pause(&mut evlh.state().as_proxy()); } for signal in &mut notifier.signals {
if let &mut Some(ref mut signal) = signal {
signal.pause(&mut evlh.state().as_proxy());
}
}
notifier.active.store(false, Ordering::SeqCst);
unsafe {
tty::vt_rel_disp(notifier.tty, 1).expect("Unable to release tty lock");
}
debug!(notifier.logger, "Session is now inactive");
} else {
debug!(notifier.logger, "Session will become active again");
unsafe {
tty::vt_rel_disp(notifier.tty, tty::VT_ACKACQ).expect("Unable to acquire tty lock");
}
for signal in &mut notifier.signals {
if let &mut Some(ref mut signal) = signal {
signal.activate(&mut evlh.state().as_proxy());
}
}
notifier.active.store(true, Ordering::SeqCst);
info!(notifier.logger, "Session is now active again");
} }
notifier.active.store(false, Ordering::SeqCst); },
unsafe { notifier,
tty::vt_rel_disp(notifier.tty, 1).expect("Unable to release tty lock"); signal,
} )
debug!(notifier.logger, "Session is now inactive");
} else {
debug!(notifier.logger, "Session will become active again");
unsafe {
tty::vt_rel_disp(notifier.tty, tty::VT_ACKACQ).expect("Unable to acquire tty lock");
}
for signal in &mut notifier.signals {
if let &mut Some(ref mut signal) = signal { signal.activate(&mut evlh.state().as_proxy()); }
}
notifier.active.store(true, Ordering::SeqCst);
info!(notifier.logger, "Session is now active again");
}
}, notifier, signal)
} }
error_chain! { error_chain! {

View File

@ -10,12 +10,12 @@
//! The following mechanisms are currently provided: //! The following mechanisms are currently provided:
//! - direct - legacy tty / virtual terminal kernel api //! - direct - legacy tty / virtual terminal kernel api
//! //!
use std::path::Path; use nix::fcntl::OFlag;
use std::sync::{Arc, Mutex};
use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use nix::fcntl::OFlag; use std::path::Path;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use wayland_server::StateProxy; use wayland_server::StateProxy;
/// General session interface. /// General session interface.
@ -83,13 +83,23 @@ pub trait SessionObserver {
impl Session for () { impl Session for () {
type Error = (); type Error = ();
fn open(&mut self, _path: &Path, _flags: OFlag) -> Result<RawFd, Self::Error> { Err(()) } fn open(&mut self, _path: &Path, _flags: OFlag) -> Result<RawFd, Self::Error> {
fn close(&mut self, _fd: RawFd) -> Result<(), Self::Error> { Err(()) } Err(())
}
fn close(&mut self, _fd: RawFd) -> Result<(), Self::Error> {
Err(())
}
fn change_vt(&mut self, _vt: i32) -> Result<(), Self::Error> { Err(()) } fn change_vt(&mut self, _vt: i32) -> Result<(), Self::Error> {
Err(())
}
fn is_active(&self) -> bool { false } fn is_active(&self) -> bool {
fn seat(&self) -> String { String::from("seat0") } false
}
fn seat(&self) -> String {
String::from("seat0")
}
} }
impl<S: Session> Session for Rc<RefCell<S>> { impl<S: Session> Session for Rc<RefCell<S>> {

View File

@ -9,36 +9,51 @@
//! See also `examples/udev.rs` for pure hardware backed example of a compositor utilizing this //! See also `examples/udev.rs` for pure hardware backed example of a compositor utilizing this
//! backend. //! backend.
use udev::{Context, MonitorBuilder, MonitorSocket, Event, EventType, Enumerator, Result as UdevResult}; use backend::drm::{drm_device_bind, DrmBackend, DrmDevice, DrmHandler};
use backend::session::{Session, SessionObserver};
use nix::fcntl; use nix::fcntl;
use nix::sys::stat::{dev_t, fstat}; use nix::sys::stat::{dev_t, fstat};
use std::borrow::Borrow; use std::borrow::Borrow;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::{Error as IoError, Result as IoResult};
use std::ffi::OsString; use std::ffi::OsString;
use std::io::{Error as IoError, Result as IoResult};
use std::mem::drop; use std::mem::drop;
use std::path::{PathBuf, Path};
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use wayland_server::{EventLoopHandle, StateToken, StateProxy}; 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}; use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};
use ::backend::drm::{DrmDevice, DrmBackend, DrmHandler, drm_device_bind};
use ::backend::session::{Session, SessionObserver};
/// Graphical backend that monitors available drm devices. /// Graphical backend that monitors available drm devices.
/// ///
/// Provides a way to automatically initialize a `DrmDevice` for available gpus and notifies the /// Provides a way to automatically initialize a `DrmDevice` for available gpus and notifies the
/// given handler of any changes. Can be used to provide hot-plug functionality for gpus and /// given handler of any changes. Can be used to provide hot-plug functionality for gpus and
/// attached monitors. /// attached monitors.
pub struct UdevBackend<B: Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'static, S: Session + 'static, T: UdevHandler<B, H> + 'static> { pub struct UdevBackend<
devices: HashMap<dev_t, (StateToken<DrmDevice<B>>, FdEventSource<(StateToken<DrmDevice<B>>, H)>)>, B: Borrow<DrmBackend> + 'static,
H: DrmHandler<B> + 'static,
S: Session + 'static,
T: UdevHandler<B, H> + 'static,
> {
devices: HashMap<
dev_t,
(
StateToken<DrmDevice<B>>,
FdEventSource<(StateToken<DrmDevice<B>>, H)>,
),
>,
monitor: MonitorSocket, monitor: MonitorSocket,
session: S, session: S,
handler: T, handler: T,
logger: ::slog::Logger, logger: ::slog::Logger,
} }
impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'static, S: Session + 'static, T: UdevHandler<B, H> + 'static> UdevBackend<B, H, S, T> { impl<
B: From<DrmBackend> + Borrow<DrmBackend> + 'static,
H: DrmHandler<B> + 'static,
S: Session + 'static,
T: UdevHandler<B, H> + 'static,
> UdevBackend<B, H, S, T> {
/// Creates a new `UdevBackend` and adds it to the given `EventLoop`'s state. /// Creates a new `UdevBackend` and adds it to the given `EventLoop`'s state.
/// ///
/// ## Arguments /// ## Arguments
@ -47,14 +62,11 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'sta
/// `session` - A session used to open and close devices as they become available /// `session` - A session used to open and close devices as they become available
/// `handler` - User-provided handler to respond to any detected changes /// `handler` - User-provided handler to respond to any detected changes
/// `logger` - slog Logger to be used by the backend and its `DrmDevices`. /// `logger` - slog Logger to be used by the backend and its `DrmDevices`.
pub fn new<'a, L>(mut evlh: &mut EventLoopHandle, pub fn new<'a, L>(
context: &Context, mut evlh: &mut EventLoopHandle, context: &Context, mut session: S, mut handler: T, logger: L
mut session: S, ) -> Result<StateToken<UdevBackend<B, H, S, T>>>
mut handler: T,
logger: L)
-> Result<StateToken<UdevBackend<B, H, S, T>>>
where where
L: Into<Option<::slog::Logger>> L: Into<Option<::slog::Logger>>,
{ {
let logger = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_udev")); let logger = ::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_udev"));
let seat = session.seat(); let seat = session.seat();
@ -125,8 +137,12 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'sta
.collect::<HashMap<dev_t, (StateToken<DrmDevice<B>>, FdEventSource<(StateToken<DrmDevice<B>>, H)>)>>(); .collect::<HashMap<dev_t, (StateToken<DrmDevice<B>>, FdEventSource<(StateToken<DrmDevice<B>>, H)>)>>();
let mut builder = MonitorBuilder::new(context).chain_err(|| ErrorKind::FailedToInitMonitor)?; let mut builder = MonitorBuilder::new(context).chain_err(|| ErrorKind::FailedToInitMonitor)?;
builder.match_subsystem("drm").chain_err(|| ErrorKind::FailedToInitMonitor)?; builder
let monitor = builder.listen().chain_err(|| ErrorKind::FailedToInitMonitor)?; .match_subsystem("drm")
.chain_err(|| ErrorKind::FailedToInitMonitor)?;
let monitor = builder
.listen()
.chain_err(|| ErrorKind::FailedToInitMonitor)?;
Ok(evlh.state().insert(UdevBackend { Ok(evlh.state().insert(UdevBackend {
devices, devices,
@ -154,14 +170,22 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'sta
let fd = device.as_raw_fd(); let fd = device.as_raw_fd();
drop(device); drop(device);
if let Err(err) = self.session.close(fd) { if let Err(err) = self.session.close(fd) {
warn!(self.logger, "Failed to close device. Error: {:?}. Ignoring", err); warn!(
self.logger,
"Failed to close device. Error: {:?}. Ignoring", err
);
}; };
} }
info!(self.logger, "All devices closed"); info!(self.logger, "All devices closed");
} }
} }
impl<B: Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'static, S: Session + 'static, T: UdevHandler<B, H> + 'static> SessionObserver for StateToken<UdevBackend<B, H, S, T>> { impl<
B: Borrow<DrmBackend> + 'static,
H: DrmHandler<B> + 'static,
S: Session + 'static,
T: UdevHandler<B, H> + 'static,
> SessionObserver for StateToken<UdevBackend<B, H, S, T>> {
fn pause<'a>(&mut self, state: &mut StateProxy<'a>) { fn pause<'a>(&mut self, state: &mut StateProxy<'a>) {
state.with_value(self, |state, udev| { state.with_value(self, |state, udev| {
for &mut (ref mut device, _) in udev.devices.values_mut() { for &mut (ref mut device, _) in udev.devices.values_mut() {
@ -183,8 +207,9 @@ impl<B: Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'static, S: Session + '
/// ///
/// Allows the backend to recieve kernel events and thus to drive the `UdevHandler`. /// Allows the backend to recieve kernel events and thus to drive the `UdevHandler`.
/// No runtime functionality can be provided without using this function. /// No runtime functionality can be provided without using this function.
pub fn udev_backend_bind<B, S, H, T>(evlh: &mut EventLoopHandle, udev: StateToken<UdevBackend<B, H, S, T>>) pub fn udev_backend_bind<B, S, H, T>(
-> IoResult<FdEventSource<StateToken<UdevBackend<B, H, S, T>>>> evlh: &mut EventLoopHandle, udev: StateToken<UdevBackend<B, H, S, T>>
) -> IoResult<FdEventSource<StateToken<UdevBackend<B, H, S, T>>>>
where where
B: From<DrmBackend> + Borrow<DrmBackend> + 'static, B: From<DrmBackend> + Borrow<DrmBackend> + 'static,
H: DrmHandler<B> + 'static, H: DrmHandler<B> + 'static,
@ -192,16 +217,10 @@ where
S: Session + 'static, S: Session + 'static,
{ {
let fd = evlh.state().get(&udev).monitor.as_raw_fd(); let fd = evlh.state().get(&udev).monitor.as_raw_fd();
evlh.add_fd_event_source( evlh.add_fd_event_source(fd, fd_event_source_implementation(), udev, FdInterest::READ)
fd,
fd_event_source_implementation(),
udev,
FdInterest::READ,
)
} }
fn fd_event_source_implementation<B, S, H, T>() fn fd_event_source_implementation<B, S, H, T>() -> FdEventSourceImpl<StateToken<UdevBackend<B, H, S, T>>>
-> FdEventSourceImpl<StateToken<UdevBackend<B, H, S, T>>>
where where
B: From<DrmBackend> + Borrow<DrmBackend> + 'static, B: From<DrmBackend> + Borrow<DrmBackend> + 'static,
H: DrmHandler<B> + 'static, H: DrmHandler<B> + 'static,
@ -210,7 +229,11 @@ where
{ {
FdEventSourceImpl { FdEventSourceImpl {
ready: |mut evlh, token, _, _| { ready: |mut evlh, token, _, _| {
let events = evlh.state().get(token).monitor.clone().collect::<Vec<Event>>(); let events = evlh.state()
.get(token)
.monitor
.clone()
.collect::<Vec<Event>>();
for event in events { for event in events {
match event.event_type() { match event.event_type() {
// New device // New device
@ -218,30 +241,49 @@ where
info!(evlh.state().get(token).logger, "Device Added"); info!(evlh.state().get(token).logger, "Device Added");
if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) { if let (Some(path), Some(devnum)) = (event.devnode(), event.devnum()) {
let mut device = { let mut device = {
match unsafe { DrmDevice::new_from_fd( match unsafe {
{ DrmDevice::new_from_fd(
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) { let logger = evlh.state().get(token).logger.clone();
Ok(fd) => fd, match evlh.state().get_mut(token).session.open(
Err(err) => { path,
warn!(logger, "Unable to open drm device {:?}, Error: {:?}. Skipping", path, err); fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY
continue; | fcntl::O_NONBLOCK,
) {
Ok(fd) => fd,
Err(err) => {
warn!(logger, "Unable to open drm device {:?}, Error: {:?}. Skipping", path, err);
continue;
}
} }
} },
}, evlh.state().get(token).logger.clone() evlh.state().get(token).logger.clone(),
) } { )
} {
Ok(dev) => dev, Ok(dev) => dev,
Err(err) => { Err(err) => {
warn!(evlh.state().get(token).logger, "Failed to initialize device {:?}. Error: {}. Skipping", path, err); warn!(
evlh.state().get(token).logger,
"Failed to initialize device {:?}. Error: {}. Skipping",
path,
err
);
continue; continue;
} }
} }
}; };
match evlh.state().with_value(token, |state, udev| udev.handler.device_added(state, &mut device)) { match evlh.state().with_value(token, |state, udev| {
udev.handler.device_added(state, &mut device)
}) {
Some(drm_handler) => { Some(drm_handler) => {
let dev_token = evlh.state().insert(device); let dev_token = evlh.state().insert(device);
if let Ok(fd_event_source) = drm_device_bind(&mut evlh, dev_token.clone(), drm_handler) { if let Ok(fd_event_source) =
evlh.state().get_mut(token).devices.insert(devnum, (dev_token, 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 { } else {
evlh.state().with_value(token, |state, udev| { evlh.state().with_value(token, |state, udev| {
let mut state: StateProxy = state.into(); let mut state: StateProxy = state.into();
@ -250,42 +292,52 @@ where
let fd = device.as_raw_fd(); let fd = device.as_raw_fd();
drop(device); drop(device);
if let Err(err) = udev.session.close(fd) { if let Err(err) = udev.session.close(fd) {
warn!(udev.logger, "Failed to close dropped device. Error: {:?}. Ignoring", err); warn!(
udev.logger,
"Failed to close dropped device. Error: {:?}. Ignoring",
err
);
}; };
}) })
} }
}, }
None => { None => {
let fd = device.as_raw_fd(); let fd = device.as_raw_fd();
drop(device); drop(device);
evlh.state().with_value(token, |_state, udev| { evlh.state().with_value(token, |_state, udev| {
if let Err(err) = udev.session.close(fd) { if let Err(err) = udev.session.close(fd) {
warn!(udev.logger, "Failed to close unused device. Error: {:?}", err); warn!(
udev.logger,
"Failed to close unused device. Error: {:?}", err
);
} }
}) })
}, }
}; };
} }
}, }
// Device removed // Device removed
EventType::Remove => { EventType::Remove => evlh.state().with_value(token, |state, udev| {
evlh.state().with_value(token, |state, udev| { info!(udev.logger, "Device Remove");
info!(udev.logger, "Device Remove"); if let Some(devnum) = event.devnum() {
if let Some(devnum) = event.devnum() { if let Some((device, fd_event_source)) = udev.devices.remove(&devnum) {
if let Some((device, fd_event_source)) = udev.devices.remove(&devnum) { fd_event_source.remove();
fd_event_source.remove(); let mut state: StateProxy = state.into();
let mut state: StateProxy = state.into(); udev.handler.device_removed(&mut state, &device);
udev.handler.device_removed(&mut state, &device); let device = state.remove(device);
let device = state.remove(device); let fd = device.as_raw_fd();
let fd = device.as_raw_fd(); drop(device);
drop(device); if let Err(err) = udev.session.close(fd) {
if let Err(err) = udev.session.close(fd) { warn!(
warn!(udev.logger, "Failed to close device {:?}. Error: {:?}. Ignoring", event.sysname(), err); udev.logger,
}; "Failed to close device {:?}. Error: {:?}. Ignoring",
} event.sysname(),
err
);
};
} }
}) }
}, }),
// New connector // New connector
EventType::Change => evlh.state().with_value(token, |state, udev| { EventType::Change => evlh.state().with_value(token, |state, udev| {
info!(udev.logger, "Device Changed"); info!(udev.logger, "Device Changed");
@ -301,25 +353,28 @@ where
info!(udev.logger, "changed, but no devnum"); info!(udev.logger, "changed, but no devnum");
} }
}), }),
_ => {}, _ => {}
} }
} }
}, },
error: |evlh, token, _, err| { error: |evlh, token, _, err| {
evlh.state().with_value(token, |state, udev| udev.handler.error(state, err)) evlh.state()
.with_value(token, |state, udev| udev.handler.error(state, err))
}, },
} }
} }
/// Handler for the `UdevBackend`, allows to open, close and update drm devices as they change during runtime. /// Handler for the `UdevBackend`, allows to open, close and update drm devices as they change during runtime.
pub trait UdevHandler<B: Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'static> { pub trait UdevHandler<B: Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'static>
{
/// Called on initialization for every known device and when a new device is detected. /// Called on initialization for every known device and when a new device is detected.
/// ///
/// Returning a `DrmHandler` will initialize the device, returning `None` will ignore the device. /// Returning a `DrmHandler` will initialize the device, returning `None` will ignore the device.
/// ///
/// ## Panics /// ## Panics
/// Panics if you try to borrow the token of the belonging `UdevBackend` using this `StateProxy`. /// 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<B>) -> Option<H>; fn device_added<'a, S: Into<StateProxy<'a>>>(&mut self, state: S, device: &mut DrmDevice<B>)
-> Option<H>;
/// Called when an open device is changed. /// Called when an open device is changed.
/// ///
/// This usually indicates that some connectors did become available or were unplugged. The handler /// This usually indicates that some connectors did become available or were unplugged. The handler
@ -353,7 +408,11 @@ pub fn primary_gpu<S: AsRef<str>>(context: &Context, seat: S) -> UdevResult<Opti
let mut result = None; let mut result = None;
for device in enumerator.scan_devices()? { for device in enumerator.scan_devices()? {
if device.property_value("ID_SEAT").map(|x| x.to_os_string()).unwrap_or(OsString::from("seat0")) == *seat.as_ref() { if device
.property_value("ID_SEAT")
.map(|x| x.to_os_string())
.unwrap_or(OsString::from("seat0")) == *seat.as_ref()
{
if let Some(pci) = device.parent_with_subsystem(Path::new("pci"))? { if let Some(pci) = device.parent_with_subsystem(Path::new("pci"))? {
if let Some(id) = pci.attribute_value("boot_vga") { if let Some(id) = pci.attribute_value("boot_vga") {
if id == "1" { if id == "1" {
@ -375,11 +434,16 @@ pub fn all_gpus<S: AsRef<str>>(context: &Context, seat: S) -> UdevResult<Vec<Pat
let mut enumerator = Enumerator::new(context)?; let mut enumerator = Enumerator::new(context)?;
enumerator.match_subsystem("drm")?; enumerator.match_subsystem("drm")?;
enumerator.match_sysname("card[0-9]*")?; enumerator.match_sysname("card[0-9]*")?;
Ok(enumerator.scan_devices()? Ok(enumerator
.filter(|device| device.property_value("ID_SEAT").map(|x| x.to_os_string()).unwrap_or(OsString::from("seat0")) == *seat.as_ref()) .scan_devices()?
.filter(|device| {
device
.property_value("ID_SEAT")
.map(|x| x.to_os_string())
.unwrap_or(OsString::from("seat0")) == *seat.as_ref()
})
.flat_map(|device| device.devnode().map(PathBuf::from)) .flat_map(|device| device.devnode().map(PathBuf::from))
.collect() .collect())
)
} }
error_chain! { error_chain! {

View File

@ -99,8 +99,9 @@ where
/// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend` /// Create a new `WinitGraphicsBackend`, which implements the `EGLGraphicsBackend`
/// graphics backend trait, from a given `WindowBuilder` struct and a corresponding /// graphics backend trait, from a given `WindowBuilder` struct and a corresponding
/// `WinitInputBackend`, which implements the `InputBackend` trait /// `WinitInputBackend`, which implements the `InputBackend` trait
pub fn init_from_builder<L>(builder: WindowBuilder, logger: L) pub fn init_from_builder<L>(
-> Result<(WinitGraphicsBackend, WinitInputBackend)> builder: WindowBuilder, logger: L
) -> Result<(WinitGraphicsBackend, WinitInputBackend)>
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
{ {
@ -120,8 +121,9 @@ where
/// graphics backend trait, from a given `WindowBuilder` struct, as well as given /// graphics backend trait, from a given `WindowBuilder` struct, as well as given
/// `GlAttributes` for further customization of the rendering pipeline and a /// `GlAttributes` for further customization of the rendering pipeline and a
/// corresponding `WinitInputBackend`, which implements the `InputBackend` trait. /// corresponding `WinitInputBackend`, which implements the `InputBackend` trait.
pub fn init_from_builder_with_gl_attr<L>(builder: WindowBuilder, attributes: GlAttributes, logger: L) pub fn init_from_builder_with_gl_attr<L>(
-> Result<(WinitGraphicsBackend, WinitInputBackend)> builder: WindowBuilder, attributes: GlAttributes, logger: L
) -> Result<(WinitGraphicsBackend, WinitInputBackend)>
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
{ {
@ -190,8 +192,9 @@ impl GraphicsBackend for WinitGraphicsBackend {
self.window.head().set_cursor_position(x as i32, y as i32) self.window.head().set_cursor_position(x as i32, y as i32)
} }
fn set_cursor_representation(&self, cursor: &Self::CursorFormat, _hotspot: (u32, u32)) fn set_cursor_representation(
-> ::std::result::Result<(), ()> { &self, cursor: &Self::CursorFormat, _hotspot: (u32, u32)
) -> ::std::result::Result<(), ()> {
// Cannot log this one, as `CursorFormat` is not `Debug` and should not be // Cannot log this one, as `CursorFormat` is not `Debug` and should not be
debug!(self.logger, "Changing cursor representation"); debug!(self.logger, "Changing cursor representation");
self.window.head().set_cursor(*cursor); self.window.head().set_cursor(*cursor);
@ -228,7 +231,8 @@ impl EGLGraphicsBackend for WinitGraphicsBackend {
} }
fn is_current(&self) -> bool { fn is_current(&self) -> bool {
self.window.rent(|egl| egl.rent_all(|egl| egl.context.is_current() && egl.surface.is_current())) self.window
.rent(|egl| egl.rent_all(|egl| egl.context.is_current() && egl.surface.is_current()))
} }
unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError> { unsafe fn make_current(&self) -> ::std::result::Result<(), SwapBuffersError> {
@ -371,10 +375,10 @@ impl PointerAxisEvent for WinitMouseWheelEvent {
fn amount(&self) -> f64 { fn amount(&self) -> f64 {
match (self.axis, self.delta) { match (self.axis, self.delta) {
(Axis::Horizontal, MouseScrollDelta::LineDelta(x, _)) | (Axis::Horizontal, MouseScrollDelta::LineDelta(x, _))
(Axis::Horizontal, MouseScrollDelta::PixelDelta(x, _)) => x as f64, | (Axis::Horizontal, MouseScrollDelta::PixelDelta(x, _)) => x as f64,
(Axis::Vertical, MouseScrollDelta::LineDelta(_, y)) | (Axis::Vertical, MouseScrollDelta::LineDelta(_, y))
(Axis::Vertical, MouseScrollDelta::PixelDelta(_, y)) => y as f64, | (Axis::Vertical, MouseScrollDelta::PixelDelta(_, y)) => y as f64,
} }
} }
} }
@ -624,8 +628,10 @@ impl InputBackend for WinitInputBackend {
trace!(logger, "Resizing window to {:?}", (x, y)); trace!(logger, "Resizing window to {:?}", (x, y));
window.head().set_inner_size(x, y); window.head().set_inner_size(x, y);
window.rent(|egl| { window.rent(|egl| {
egl.rent(|surface| if let Some(wegl_surface) = (**surface).as_ref() { egl.rent(|surface| {
wegl_surface.resize(x as i32, y as i32, 0, 0) if let Some(wegl_surface) = (**surface).as_ref() {
wegl_surface.resize(x as i32, y as i32, 0, 0)
}
}) })
}); });
} }

View File

@ -11,9 +11,10 @@ use wayland_server::protocol::{wl_compositor, wl_region, wl_subcompositor, wl_su
* wl_compositor * wl_compositor
*/ */
pub(crate) fn compositor_bind<U, R, ID>(evlh: &mut EventLoopHandle, idata: &mut SurfaceIData<U, R, ID>, pub(crate) fn compositor_bind<U, R, ID>(
_: &Client, compositor: wl_compositor::WlCompositor) evlh: &mut EventLoopHandle, idata: &mut SurfaceIData<U, R, ID>, _: &Client,
where compositor: wl_compositor::WlCompositor,
) where
U: Default + 'static, U: Default + 'static,
R: Default + 'static, R: Default + 'static,
ID: 'static, ID: 'static,
@ -65,8 +66,9 @@ pub struct SurfaceIData<U, R, ID> {
} }
impl<U, R, ID> SurfaceIData<U, R, ID> { impl<U, R, ID> SurfaceIData<U, R, ID> {
pub(crate) fn make(log: ::slog::Logger, implem: SurfaceUserImplementation<U, R, ID>, idata: ID) pub(crate) fn make(
-> SurfaceIData<U, R, ID> { log: ::slog::Logger, implem: SurfaceUserImplementation<U, R, ID>, idata: ID
) -> SurfaceIData<U, R, ID> {
SurfaceIData { SurfaceIData {
log: log, log: log,
implem: implem, implem: implem,
@ -86,9 +88,7 @@ impl<U, R, ID> Clone for SurfaceIData<U, R, ID> {
} }
pub(crate) fn surface_implementation<U: 'static, R: 'static, ID: 'static>( pub(crate) fn surface_implementation<U: 'static, R: 'static, ID: 'static>(
) ) -> wl_surface::Implementation<SurfaceIData<U, R, ID>> {
-> wl_surface::Implementation<SurfaceIData<U, R, ID>>
{
wl_surface::Implementation { wl_surface::Implementation {
attach: |_, _, _, surface, buffer, x, y| unsafe { attach: |_, _, _, surface, buffer, x, y| unsafe {
SurfaceData::<U, R>::with_data(surface, |d| { SurfaceData::<U, R>::with_data(surface, |d| {
@ -199,9 +199,9 @@ fn destroy_region(region: &wl_region::WlRegion) {
* wl_subcompositor * wl_subcompositor
*/ */
pub(crate) fn subcompositor_bind<U, R>(evlh: &mut EventLoopHandle, _: &mut (), _: &Client, pub(crate) fn subcompositor_bind<U, R>(
subcompositor: wl_subcompositor::WlSubcompositor) evlh: &mut EventLoopHandle, _: &mut (), _: &Client, subcompositor: wl_subcompositor::WlSubcompositor
where ) where
R: RoleType + Role<SubsurfaceRole> + 'static, R: RoleType + Role<SubsurfaceRole> + 'static,
U: 'static, U: 'static,
{ {

View File

@ -314,11 +314,11 @@ where
/// ///
/// If the surface not managed by the CompositorGlobal that provided this token, this /// If the surface not managed by the CompositorGlobal that provided this token, this
/// will panic (having more than one compositor is not supported). /// will panic (having more than one compositor is not supported).
pub fn with_surface_tree_upward<F, T>(&self, surface: &wl_surface::WlSurface, initial: T, f: F) pub fn with_surface_tree_upward<F, T>(
-> Result<(), ()> &self, surface: &wl_surface::WlSurface, initial: T, f: F
) -> Result<(), ()>
where where
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
-> TraversalAction<T>,
{ {
assert!( assert!(
resource_is_registered( resource_is_registered(
@ -340,11 +340,11 @@ where
/// supposed to be drawn: top-most first. /// supposed to be drawn: top-most first.
/// ///
/// Behavior is the same as `with_surface_tree_upward`. /// Behavior is the same as `with_surface_tree_upward`.
pub fn with_surface_tree_downward<F, T>(&self, surface: &wl_surface::WlSurface, initial: T, f: F) pub fn with_surface_tree_downward<F, T>(
-> Result<(), ()> &self, surface: &wl_surface::WlSurface, initial: T, f: F
) -> Result<(), ()>
where where
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
-> TraversalAction<T>,
{ {
assert!( assert!(
resource_is_registered( resource_is_registered(
@ -426,7 +426,6 @@ impl<U: 'static, R: RoleType + 'static, ID: 'static> CompositorToken<U, R, ID> {
unsafe { SurfaceData::<U, R>::has_role::<RoleData>(surface) } unsafe { SurfaceData::<U, R>::has_role::<RoleData>(surface) }
} }
/// Register that this surface has given role with default data /// Register that this surface has given role with default data
/// ///
/// Fails if the surface already has a role. /// Fails if the surface already has a role.
@ -454,8 +453,9 @@ impl<U: 'static, R: RoleType + 'static, ID: 'static> CompositorToken<U, R, ID> {
/// ///
/// If the surface is not managed by the CompositorGlobal that provided this token, this /// If the surface is not managed by the CompositorGlobal that provided this token, this
/// will panic (having more than one compositor is not supported). /// will panic (having more than one compositor is not supported).
pub fn give_role_with<RoleData>(&self, surface: &wl_surface::WlSurface, data: RoleData) pub fn give_role_with<RoleData>(
-> Result<(), RoleData> &self, surface: &wl_surface::WlSurface, data: RoleData
) -> Result<(), RoleData>
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
@ -475,8 +475,9 @@ impl<U: 'static, R: RoleType + 'static, ID: 'static> CompositorToken<U, R, ID> {
/// ///
/// If the surface is not managed by the CompositorGlobal that provided this token, this /// If the surface is not managed by the CompositorGlobal that provided this token, this
/// will panic (having more than one compositor is not supported). /// will panic (having more than one compositor is not supported).
pub fn with_role_data<RoleData, F, T>(&self, surface: &wl_surface::WlSurface, f: F) pub fn with_role_data<RoleData, F, T>(
-> Result<T, WrongRole> &self, surface: &wl_surface::WlSurface, f: F
) -> Result<T, WrongRole>
where where
R: Role<RoleData>, R: Role<RoleData>,
F: FnOnce(&mut RoleData) -> T, F: FnOnce(&mut RoleData) -> T,
@ -533,12 +534,12 @@ impl<U: 'static, R: RoleType + 'static, ID: 'static> CompositorToken<U, R, ID> {
/// It also returns the two global handles, in case you whish to remove these /// It also returns the two global handles, in case you whish to remove these
/// globals from the event loop in the future. /// globals from the event loop in the future.
pub fn compositor_init<U, R, ID, L>( pub fn compositor_init<U, R, ID, L>(
evl: &mut EventLoop, implem: SurfaceUserImplementation<U, R, ID>, idata: ID, logger: L) evl: &mut EventLoop, implem: SurfaceUserImplementation<U, R, ID>, idata: ID, logger: L
-> ( ) -> (
CompositorToken<U, R, ID>, CompositorToken<U, R, ID>,
Global<wl_compositor::WlCompositor, self::handlers::SurfaceIData<U, R, ID>>, Global<wl_compositor::WlCompositor, self::handlers::SurfaceIData<U, R, ID>>,
Global<wl_subcompositor::WlSubcompositor, ()>, Global<wl_subcompositor::WlSubcompositor, ()>,
) )
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
U: Default + 'static, U: Default + 'static,
@ -580,10 +581,10 @@ pub struct SurfaceUserImplementation<U, R, ID> {
/// See [`wayland_server::protocol::wl_surface::Implementation::commit`](https://docs.rs/wayland-server/0.10.1/wayland_server/protocol/wl_surface/struct.Implementation.html#structfield.commit) /// See [`wayland_server::protocol::wl_surface::Implementation::commit`](https://docs.rs/wayland-server/0.10.1/wayland_server/protocol/wl_surface/struct.Implementation.html#structfield.commit)
/// for more details /// for more details
pub commit: fn( pub commit: fn(
evlh: &mut EventLoopHandle, evlh: &mut EventLoopHandle,
idata: &mut ID, idata: &mut ID,
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
token: CompositorToken<U, R, ID>, token: CompositorToken<U, R, ID>,
), ),
/// The client asks to be notified when would be a good time to update the contents of this surface /// The client asks to be notified when would be a good time to update the contents of this surface
/// ///
@ -593,11 +594,11 @@ pub struct SurfaceUserImplementation<U, R, ID> {
/// See [`wayland_server::protocol::wl_surface::Implementation::frame`](https://docs.rs/wayland-server/0.10.1/wayland_server/protocol/wl_surface/struct.Implementation.html#structfield.frame) /// See [`wayland_server::protocol::wl_surface::Implementation::frame`](https://docs.rs/wayland-server/0.10.1/wayland_server/protocol/wl_surface/struct.Implementation.html#structfield.frame)
/// for more details /// for more details
pub frame: fn( pub frame: fn(
evlh: &mut EventLoopHandle, evlh: &mut EventLoopHandle,
idata: &mut ID, idata: &mut ID,
surface: &wl_surface::WlSurface, surface: &wl_surface::WlSurface,
callback: wl_callback::WlCallback, callback: wl_callback::WlCallback,
token: CompositorToken<U, R, ID>, token: CompositorToken<U, R, ID>,
), ),
} }

View File

@ -132,8 +132,9 @@ impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
/// Register that this surface has a role with given data /// Register that this surface has a role with given data
/// ///
/// Fails if it already has one and returns the data /// Fails if it already has one and returns the data
pub unsafe fn give_role_with<RoleData>(surface: &wl_surface::WlSurface, data: RoleData) pub unsafe fn give_role_with<RoleData>(
-> Result<(), RoleData> surface: &wl_surface::WlSurface, data: RoleData
) -> Result<(), RoleData>
where where
R: Role<RoleData>, R: Role<RoleData>,
{ {
@ -158,8 +159,9 @@ impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
} }
/// Access to the role data /// Access to the role data
pub unsafe fn with_role_data<RoleData, F, T>(surface: &wl_surface::WlSurface, f: F) pub unsafe fn with_role_data<RoleData, F, T>(
-> Result<T, WrongRole> surface: &wl_surface::WlSurface, f: F
) -> Result<T, WrongRole>
where where
R: Role<RoleData>, R: Role<RoleData>,
F: FnOnce(&mut RoleData) -> T, F: FnOnce(&mut RoleData) -> T,
@ -177,8 +179,9 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
/// ///
/// if this surface already has a role, does nothing and fails, otherwise /// if this surface already has a role, does nothing and fails, otherwise
/// its role is now to be a subsurface /// its role is now to be a subsurface
pub unsafe fn set_parent(child: &wl_surface::WlSurface, parent: &wl_surface::WlSurface) pub unsafe fn set_parent(
-> Result<(), ()> { child: &wl_surface::WlSurface, parent: &wl_surface::WlSurface
) -> Result<(), ()> {
debug_assert!(child.status() == Liveness::Alive); debug_assert!(child.status() == Liveness::Alive);
debug_assert!(parent.status() == Liveness::Alive); debug_assert!(parent.status() == Liveness::Alive);
@ -246,9 +249,9 @@ impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R>
/// Reorders a surface relative to one of its sibling /// Reorders a surface relative to one of its sibling
/// ///
/// Fails if `relative_to` is not a sibling or parent of `surface`. /// Fails if `relative_to` is not a sibling or parent of `surface`.
pub unsafe fn reorder(surface: &wl_surface::WlSurface, to: Location, pub unsafe fn reorder(
relative_to: &wl_surface::WlSurface) surface: &wl_surface::WlSurface, to: Location, relative_to: &wl_surface::WlSurface
-> Result<(), ()> { ) -> Result<(), ()> {
let parent = { let parent = {
let data_mutex = Self::get_data(surface); let data_mutex = Self::get_data(surface);
let data_guard = data_mutex.lock().unwrap(); let data_guard = data_mutex.lock().unwrap();
@ -316,17 +319,15 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
/// false will cause an early-stopping. /// false will cause an early-stopping.
pub unsafe fn map_tree<F, T>(root: &wl_surface::WlSurface, initial: T, mut f: F, reverse: bool) pub unsafe fn map_tree<F, T>(root: &wl_surface::WlSurface, initial: T, mut f: F, reverse: bool)
where where
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
-> TraversalAction<T>,
{ {
// helper function for recursion // helper function for recursion
unsafe fn map<U: 'static, R: 'static, F, T>(surface: &wl_surface::WlSurface, unsafe fn map<U: 'static, R: 'static, F, T>(
root: &wl_surface::WlSurface, initial: &T, f: &mut F, surface: &wl_surface::WlSurface, root: &wl_surface::WlSurface, initial: &T, f: &mut F,
reverse: bool) reverse: bool,
-> bool ) -> bool
where where
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
-> TraversalAction<T>,
{ {
// stop if we met the root, so to not deadlock/inifinte loop // stop if we met the root, so to not deadlock/inifinte loop
if surface.equals(root) { if surface.equals(root) {

View File

@ -113,11 +113,11 @@ impl Output {
/// returns the state token allowing you to access it, as well as the global handle, /// returns the state token allowing you to access it, as well as the global handle,
/// in case you whish to remove this global in the future. /// in case you whish to remove this global in the future.
pub fn new<L>( pub fn new<L>(
evl: &mut EventLoop, name: String, physical: PhysicalProperties, logger: L) evl: &mut EventLoop, name: String, physical: PhysicalProperties, logger: L
-> ( ) -> (
StateToken<Output>, StateToken<Output>,
Global<wl_output::WlOutput, StateToken<Output>>, Global<wl_output::WlOutput, StateToken<Output>>,
) )
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
{ {
@ -229,8 +229,10 @@ impl Output {
/// internal list. /// internal list.
/// ///
/// By default, transform status is `Normal`, and scale is `1`. /// By default, transform status is `Normal`, and scale is `1`.
pub fn change_current_state(&mut self, new_mode: Option<Mode>, pub fn change_current_state(
new_transform: Option<wl_output::Transform>, new_scale: Option<i32>) { &mut self, new_mode: Option<Mode>, new_transform: Option<wl_output::Transform>,
new_scale: Option<i32>,
) {
if let Some(mode) = new_mode { if let Some(mode) = new_mode {
if self.modes.iter().find(|&m| *m == mode).is_none() { if self.modes.iter().find(|&m| *m == mode).is_none() {
self.modes.push(mode); self.modes.push(mode);
@ -283,8 +285,9 @@ impl Output {
} }
} }
fn output_bind(evlh: &mut EventLoopHandle, token: &mut StateToken<Output>, _: &Client, fn output_bind(
global: wl_output::WlOutput) { evlh: &mut EventLoopHandle, token: &mut StateToken<Output>, _: &Client, global: wl_output::WlOutput
) {
evlh.register(&global, output_implementation(), token.clone(), None); evlh.register(&global, output_implementation(), token.clone(), None);
evlh.state().get_mut(token).new_global(global); evlh.state().get_mut(token).new_global(global);
} }

View File

@ -66,9 +66,10 @@ struct KbdInternal {
} }
impl KbdInternal { impl KbdInternal {
fn new(rules: &str, model: &str, layout: &str, variant: &str, options: Option<String>, fn new(
repeat_rate: i32, repeat_delay: i32) rules: &str, model: &str, layout: &str, variant: &str, options: Option<String>, repeat_rate: i32,
-> Result<KbdInternal, ()> { repeat_delay: i32,
) -> Result<KbdInternal, ()> {
// we create a new contex for each keyboard because libxkbcommon is actually NOT threadsafe // we create a new contex for each keyboard because libxkbcommon is actually NOT threadsafe
// so confining it inside the KbdInternal allows us to use Rusts mutability rules to make // so confining it inside the KbdInternal allows us to use Rusts mutability rules to make
// sure nothing goes wrong. // sure nothing goes wrong.
@ -168,10 +169,10 @@ pub enum Error {
} }
/// Create a keyboard handler from a set of RMLVO rules /// Create a keyboard handler from a set of RMLVO rules
pub(crate) fn create_keyboard_handler(rules: &str, model: &str, layout: &str, variant: &str, pub(crate) fn create_keyboard_handler(
options: Option<String>, repeat_delay: i32, repeat_rate: i32, rules: &str, model: &str, layout: &str, variant: &str, options: Option<String>, repeat_delay: i32,
logger: &::slog::Logger) repeat_rate: i32, logger: &::slog::Logger,
-> Result<KeyboardHandle, Error> { ) -> Result<KeyboardHandle, Error> {
let log = logger.new(o!("smithay_module" => "xkbcommon_handler")); let log = logger.new(o!("smithay_module" => "xkbcommon_handler"));
info!(log, "Initializing a xkbcommon handler with keymap query"; info!(log, "Initializing a xkbcommon handler with keymap query";
"rules" => rules, "model" => model, "layout" => layout, "variant" => variant, "rules" => rules, "model" => model, "layout" => layout, "variant" => variant,
@ -192,7 +193,6 @@ pub(crate) fn create_keyboard_handler(rules: &str, model: &str, layout: &str, va
info!(log, "Loaded Keymap"; "name" => internal.keymap.layouts().next()); info!(log, "Loaded Keymap"; "name" => internal.keymap.layouts().next());
// prepare a tempfile with the keymap, to send it to clients // prepare a tempfile with the keymap, to send it to clients
let mut keymap_file = tempfile().map_err(Error::IoError)?; let mut keymap_file = tempfile().map_err(Error::IoError)?;
let keymap_data = internal.keymap.get_as_string(xkb::KEYMAP_FORMAT_TEXT_V1); let keymap_data = internal.keymap.get_as_string(xkb::KEYMAP_FORMAT_TEXT_V1);

View File

@ -87,8 +87,9 @@ impl Seat {
/// You are provided with the state token to retrieve it (allowing /// You are provided with the state token to retrieve it (allowing
/// you to add or remove capabilities from it), and the global handle, /// you to add or remove capabilities from it), and the global handle,
/// in case you want to remove it. /// in case you want to remove it.
pub fn new<L>(evl: &mut EventLoop, name: String, logger: L) pub fn new<L>(
-> (StateToken<Seat>, Global<wl_seat::WlSeat, StateToken<Seat>>) evl: &mut EventLoop, name: String, logger: L
) -> (StateToken<Seat>, Global<wl_seat::WlSeat, StateToken<Seat>>)
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
{ {
@ -158,9 +159,10 @@ impl Seat {
/// Calling this method on a seat that already has a keyboard capability /// Calling this method on a seat that already has a keyboard capability
/// will overwrite it, and will be seen by the clients as if the /// will overwrite it, and will be seen by the clients as if the
/// keyboard was unplugged and a new one was plugged. /// keyboard was unplugged and a new one was plugged.
pub fn add_keyboard(&mut self, model: &str, layout: &str, variant: &str, options: Option<String>, pub fn add_keyboard(
repeat_delay: i32, repeat_rate: i32) &mut self, model: &str, layout: &str, variant: &str, options: Option<String>, repeat_delay: i32,
-> Result<KeyboardHandle, KeyboardError> { repeat_rate: i32,
) -> Result<KeyboardHandle, KeyboardError> {
let keyboard = self::keyboard::create_keyboard_handler( let keyboard = self::keyboard::create_keyboard_handler(
"evdev", // we need this one "evdev", // we need this one
model, model,
@ -229,8 +231,9 @@ impl Seat {
} }
} }
fn seat_global_bind(evlh: &mut EventLoopHandle, token: &mut StateToken<Seat>, _: &Client, fn seat_global_bind(
seat: wl_seat::WlSeat) { evlh: &mut EventLoopHandle, token: &mut StateToken<Seat>, _: &Client, seat: wl_seat::WlSeat
) {
evlh.register(&seat, seat_implementation(), token.clone(), None); evlh.register(&seat, seat_implementation(), token.clone(), None);
let seat_mgr = evlh.state().get_mut(token); let seat_mgr = evlh.state().get_mut(token);
seat.name(seat_mgr.name.clone()); seat.name(seat_mgr.name.clone());

View File

@ -302,12 +302,12 @@ impl<U, R, CID, SID, SD> Clone for ShellSurfaceIData<U, R, CID, SID, SD> {
/// globals from the event loop in the future. /// globals from the event loop in the future.
pub fn shell_init<U, R, CID, SID, SD, L>( pub fn shell_init<U, R, CID, SID, SD, L>(
evl: &mut EventLoop, token: CompositorToken<U, R, CID>, evl: &mut EventLoop, token: CompositorToken<U, R, CID>,
implementation: ShellSurfaceUserImplementation<U, R, CID, SID, SD>, idata: SID, logger: L) implementation: ShellSurfaceUserImplementation<U, R, CID, SID, SD>, idata: SID, logger: L,
-> ( ) -> (
StateToken<ShellState<U, R, CID, SD>>, StateToken<ShellState<U, R, CID, SD>>,
Global<wl_shell::WlShell, ShellSurfaceIData<U, R, CID, SID, SD>>, Global<wl_shell::WlShell, ShellSurfaceIData<U, R, CID, SID, SD>>,
Global<zxdg_shell_v6::ZxdgShellV6, ShellSurfaceIData<U, R, CID, SID, SD>>, Global<zxdg_shell_v6::ZxdgShellV6, ShellSurfaceIData<U, R, CID, SID, SD>>,
) )
where where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
@ -449,7 +449,8 @@ impl<SD> ShellClient<SD> {
} }
match self.kind { match self.kind {
ShellClientKind::Wl(ref shell) => { ShellClientKind::Wl(ref shell) => {
let mutex = unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) }; let mutex =
unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
let mut guard = mutex.lock().unwrap(); let mut guard = mutex.lock().unwrap();
if guard.0.pending_ping == 0 { if guard.0.pending_ping == 0 {
return Err(()); return Err(());
@ -486,7 +487,8 @@ impl<SD> ShellClient<SD> {
} }
match self.kind { match self.kind {
ShellClientKind::Wl(ref shell) => { ShellClientKind::Wl(ref shell) => {
let mutex = unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) }; let mutex =
unsafe { &*(shell.get_user_data() as *mut self::wl_handlers::ShellUserData<SD>) };
let mut guard = mutex.lock().unwrap(); let mut guard = mutex.lock().unwrap();
Ok(f(&mut guard.0.data)) Ok(f(&mut guard.0.data))
} }
@ -844,46 +846,44 @@ pub struct ShellSurfaceUserImplementation<U, R, CID, SID, SD> {
/// ///
/// You need to return a `ToplevelConfigure` from this function, which will be sent /// You need to return a `ToplevelConfigure` from this function, which will be sent
/// to the client to configure this surface /// to the client to configure this surface
pub new_toplevel: fn( pub new_toplevel:
evlh: &mut EventLoopHandle, fn(evlh: &mut EventLoopHandle, idata: &mut SID, surface: ToplevelSurface<U, R, CID, SD>)
idata: &mut SID, -> ToplevelConfigure,
surface: ToplevelSurface<U, R, CID, SD>,
) -> ToplevelConfigure,
/// A new popup surface was created /// A new popup surface was created
/// ///
/// You need to return a `PopupConfigure` from this function, which will be sent /// You need to return a `PopupConfigure` from this function, which will be sent
/// to the client to configure this surface /// to the client to configure this surface
pub new_popup: fn(evlh: &mut EventLoopHandle, idata: &mut SID, surface: PopupSurface<U, R, CID, SD>) pub new_popup: fn(evlh: &mut EventLoopHandle, idata: &mut SID, surface: PopupSurface<U, R, CID, SD>)
-> PopupConfigure, -> PopupConfigure,
/// The client requested the start of an interactive move for this surface /// The client requested the start of an interactive move for this surface
pub move_: fn( pub move_: fn(
evlh: &mut EventLoopHandle, evlh: &mut EventLoopHandle,
idata: &mut SID, idata: &mut SID,
surface: ToplevelSurface<U, R, CID, SD>, surface: ToplevelSurface<U, R, CID, SD>,
seat: &wl_seat::WlSeat, seat: &wl_seat::WlSeat,
serial: u32, serial: u32,
), ),
/// The client requested the start of an interactive resize for this surface /// The client requested the start of an interactive resize for this surface
/// ///
/// The `edges` argument specifies which part of the window's border is being dragged. /// The `edges` argument specifies which part of the window's border is being dragged.
pub resize: fn( pub resize: fn(
evlh: &mut EventLoopHandle, evlh: &mut EventLoopHandle,
idata: &mut SID, idata: &mut SID,
surface: ToplevelSurface<U, R, CID, SD>, surface: ToplevelSurface<U, R, CID, SD>,
seat: &wl_seat::WlSeat, seat: &wl_seat::WlSeat,
serial: u32, serial: u32,
edges: zxdg_toplevel_v6::ResizeEdge, edges: zxdg_toplevel_v6::ResizeEdge,
), ),
/// This popup requests a grab of the pointer /// This popup requests a grab of the pointer
/// ///
/// This means it requests to be sent a `popup_done` event when the pointer leaves /// This means it requests to be sent a `popup_done` event when the pointer leaves
/// the grab area. /// the grab area.
pub grab: fn( pub grab: fn(
evlh: &mut EventLoopHandle, evlh: &mut EventLoopHandle,
idata: &mut SID, idata: &mut SID,
surface: PopupSurface<U, R, CID, SD>, surface: PopupSurface<U, R, CID, SD>,
seat: &wl_seat::WlSeat, seat: &wl_seat::WlSeat,
serial: u32, serial: u32,
), ),
/// A toplevel surface requested its display state to be changed /// A toplevel surface requested its display state to be changed
/// ///
@ -899,26 +899,26 @@ pub struct ShellSurfaceUserImplementation<U, R, CID, SID, SD> {
/// You are to answer with a `ToplevelConfigure` that will be sent to the client in /// You are to answer with a `ToplevelConfigure` that will be sent to the client in
/// response. /// response.
pub change_display_state: fn( pub change_display_state: fn(
evlh: &mut EventLoopHandle, evlh: &mut EventLoopHandle,
idata: &mut SID, idata: &mut SID,
surface: ToplevelSurface<U, R, CID, SD>, surface: ToplevelSurface<U, R, CID, SD>,
maximized: Option<bool>, maximized: Option<bool>,
minimized: Option<bool>, minimized: Option<bool>,
fullscreen: Option<bool>, fullscreen: Option<bool>,
output: Option<&wl_output::WlOutput>, output: Option<&wl_output::WlOutput>,
) -> ToplevelConfigure, ) -> ToplevelConfigure,
/// The client requests the window menu to be displayed on this surface at this location /// The client requests the window menu to be displayed on this surface at this location
/// ///
/// This menu belongs to the compositor. It is typically expected to contain options for /// This menu belongs to the compositor. It is typically expected to contain options for
/// control of the window (maximize/minimize/close/move/etc...). /// control of the window (maximize/minimize/close/move/etc...).
pub show_window_menu: fn( pub show_window_menu: fn(
evlh: &mut EventLoopHandle, evlh: &mut EventLoopHandle,
idata: &mut SID, idata: &mut SID,
surface: ToplevelSurface<U, R, CID, SD>, surface: ToplevelSurface<U, R, CID, SD>,
seat: &wl_seat::WlSeat, seat: &wl_seat::WlSeat,
serial: u32, serial: u32,
x: i32, x: i32,
y: i32, y: i32,
), ),
} }

View File

@ -10,10 +10,10 @@ use wayland_protocols::unstable::xdg_shell::v6::server::{zxdg_positioner_v6 as x
use wayland_server::{Client, EventLoopHandle, Resource}; use wayland_server::{Client, EventLoopHandle, Resource};
use wayland_server::protocol::{wl_output, wl_shell, wl_shell_surface, wl_surface}; use wayland_server::protocol::{wl_output, wl_shell, wl_shell_surface, wl_surface};
pub(crate) fn wl_shell_bind<U, R, CID, SID, SD>(evlh: &mut EventLoopHandle, pub(crate) fn wl_shell_bind<U, R, CID, SID, SD>(
idata: &mut ShellSurfaceIData<U, R, CID, SID, SD>, evlh: &mut EventLoopHandle, idata: &mut ShellSurfaceIData<U, R, CID, SID, SD>, _: &Client,
_: &Client, shell: wl_shell::WlShell) shell: wl_shell::WlShell,
where ) where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
CID: 'static, CID: 'static,
@ -56,8 +56,7 @@ pub fn make_shell_client<SD>(resource: &wl_shell::WlShell) -> ShellClient<SD> {
} }
fn shell_implementation<U, R, CID, SID, SD>( fn shell_implementation<U, R, CID, SID, SD>(
) ) -> wl_shell::Implementation<ShellSurfaceIData<U, R, CID, SID, SD>>
-> wl_shell::Implementation<ShellSurfaceIData<U, R, CID, SID, SD>>
where where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
@ -122,9 +121,9 @@ fn destroy_shell_surface(shell_surface: &wl_shell_surface::WlShellSurface) {
::std::mem::drop(surface); ::std::mem::drop(surface);
} }
fn make_toplevel_handle<U, R, H, SD>(token: CompositorToken<U, R, H>, fn make_toplevel_handle<U, R, H, SD>(
resource: &wl_shell_surface::WlShellSurface) token: CompositorToken<U, R, H>, resource: &wl_shell_surface::WlShellSurface
-> super::ToplevelSurface<U, R, H, SD> { ) -> super::ToplevelSurface<U, R, H, SD> {
let ptr = resource.get_user_data(); let ptr = resource.get_user_data();
let &(ref wl_surface, _) = unsafe { &*(ptr as *mut ShellSurfaceUserData) }; let &(ref wl_surface, _) = unsafe { &*(ptr as *mut ShellSurfaceUserData) };
super::ToplevelSurface { super::ToplevelSurface {
@ -135,9 +134,9 @@ fn make_toplevel_handle<U, R, H, SD>(token: CompositorToken<U, R, H>,
} }
} }
fn make_popup_handle<U, R, H, SD>(token: CompositorToken<U, R, H>, fn make_popup_handle<U, R, H, SD>(
resource: &wl_shell_surface::WlShellSurface) token: CompositorToken<U, R, H>, resource: &wl_shell_surface::WlShellSurface
-> super::PopupSurface<U, R, H, SD> { ) -> super::PopupSurface<U, R, H, SD> {
let ptr = resource.get_user_data(); let ptr = resource.get_user_data();
let &(ref wl_surface, _) = unsafe { &*(ptr as *mut ShellSurfaceUserData) }; let &(ref wl_surface, _) = unsafe { &*(ptr as *mut ShellSurfaceUserData) };
super::PopupSurface { super::PopupSurface {
@ -158,12 +157,11 @@ pub fn send_popup_configure(resource: &wl_shell_surface::WlShellSurface, configu
resource.configure(wl_shell_surface::Resize::empty(), w, h); resource.configure(wl_shell_surface::Resize::empty(), w, h);
} }
fn wl_handle_display_state_change<U, R, CID, SID, SD>(evlh: &mut EventLoopHandle, fn wl_handle_display_state_change<U, R, CID, SID, SD>(
idata: &ShellSurfaceIData<U, R, CID, SID, SD>, evlh: &mut EventLoopHandle, idata: &ShellSurfaceIData<U, R, CID, SID, SD>,
shell_surface: &wl_shell_surface::WlShellSurface, shell_surface: &wl_shell_surface::WlShellSurface, maximized: Option<bool>, minimized: Option<bool>,
maximized: Option<bool>, minimized: Option<bool>, fullscreen: Option<bool>, output: Option<&wl_output::WlOutput>,
fullscreen: Option<bool>, ) {
output: Option<&wl_output::WlOutput>) {
let handle = make_toplevel_handle(idata.compositor_token, shell_surface); let handle = make_toplevel_handle(idata.compositor_token, shell_surface);
// handler callback // handler callback
let mut user_idata = idata.idata.borrow_mut(); let mut user_idata = idata.idata.borrow_mut();
@ -181,10 +179,10 @@ fn wl_handle_display_state_change<U, R, CID, SID, SD>(evlh: &mut EventLoopHandle
shell_surface.configure(wl_shell_surface::Resize::None, w, h); shell_surface.configure(wl_shell_surface::Resize::None, w, h);
} }
fn wl_set_parent<U, R, CID, SID, SD>(idata: &ShellSurfaceIData<U, R, CID, SID, SD>, fn wl_set_parent<U, R, CID, SID, SD>(
shell_surface: &wl_shell_surface::WlShellSurface, idata: &ShellSurfaceIData<U, R, CID, SID, SD>, shell_surface: &wl_shell_surface::WlShellSurface,
parent: Option<wl_surface::WlSurface>) parent: Option<wl_surface::WlSurface>,
where ) where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
CID: 'static, CID: 'static,
@ -204,10 +202,10 @@ where
.unwrap(); .unwrap();
} }
fn wl_ensure_toplevel<U, R, CID, SID, SD>(evlh: &mut EventLoopHandle, fn wl_ensure_toplevel<U, R, CID, SID, SD>(
idata: &ShellSurfaceIData<U, R, CID, SID, SD>, evlh: &mut EventLoopHandle, idata: &ShellSurfaceIData<U, R, CID, SID, SD>,
shell_surface: &wl_shell_surface::WlShellSurface) shell_surface: &wl_shell_surface::WlShellSurface,
where ) where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
CID: 'static, CID: 'static,
@ -263,8 +261,7 @@ where
} }
fn shell_surface_implementation<U, R, CID, SID, SD>( fn shell_surface_implementation<U, R, CID, SID, SD>(
) ) -> wl_shell_surface::Implementation<ShellSurfaceIData<U, R, CID, SID, SD>>
-> wl_shell_surface::Implementation<ShellSurfaceIData<U, R, CID, SID, SD>>
where where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
@ -274,7 +271,8 @@ where
{ {
wl_shell_surface::Implementation { wl_shell_surface::Implementation {
pong: |evlh, idata, _, shell_surface, serial| { pong: |evlh, idata, _, shell_surface, serial| {
let &(_, ref shell) = unsafe { &*(shell_surface.get_user_data() as *mut ShellSurfaceUserData) }; let &(_, ref shell) =
unsafe { &*(shell_surface.get_user_data() as *mut ShellSurfaceUserData) };
let valid = { let valid = {
let mutex = unsafe { &*(shell.get_user_data() as *mut ShellUserData<SD>) }; let mutex = unsafe { &*(shell.get_user_data() as *mut ShellUserData<SD>) };
let mut guard = mutex.lock().unwrap(); let mut guard = mutex.lock().unwrap();

View File

@ -10,10 +10,10 @@ use wayland_protocols::unstable::xdg_shell::v6::server::{zxdg_popup_v6, zxdg_pos
use wayland_server::{Client, EventLoopHandle, Resource}; use wayland_server::{Client, EventLoopHandle, Resource};
use wayland_server::protocol::{wl_output, wl_surface}; use wayland_server::protocol::{wl_output, wl_surface};
pub(crate) fn xdg_shell_bind<U, R, CID, SID, SD>(evlh: &mut EventLoopHandle, pub(crate) fn xdg_shell_bind<U, R, CID, SID, SD>(
idata: &mut ShellSurfaceIData<U, R, CID, SID, SD>, evlh: &mut EventLoopHandle, idata: &mut ShellSurfaceIData<U, R, CID, SID, SD>, _: &Client,
_: &Client, shell: zxdg_shell_v6::ZxdgShellV6) shell: zxdg_shell_v6::ZxdgShellV6,
where ) where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
CID: 'static, CID: 'static,
@ -53,8 +53,7 @@ pub(crate) fn make_shell_client<SD>(resource: &zxdg_shell_v6::ZxdgShellV6) -> Sh
} }
fn shell_implementation<U, R, CID, SID, SD>( fn shell_implementation<U, R, CID, SID, SD>(
) ) -> zxdg_shell_v6::Implementation<ShellSurfaceIData<U, R, CID, SID, SD>>
-> zxdg_shell_v6::Implementation<ShellSurfaceIData<U, R, CID, SID, SD>>
where where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
@ -104,11 +103,10 @@ where
); );
return; return;
} }
xdg_surface.set_user_data( xdg_surface.set_user_data(Box::into_raw(Box::new((
Box::into_raw(Box::new((unsafe { wl_surface.clone_unchecked() }, unsafe { unsafe { wl_surface.clone_unchecked() },
shell.clone_unchecked() unsafe { shell.clone_unchecked() },
}))) as *mut _, ))) as *mut _);
);
evlh.register( evlh.register(
&xdg_surface, &xdg_surface,
surface_implementation(), surface_implementation(),
@ -151,30 +149,34 @@ fn destroy_positioner(positioner: &zxdg_positioner_v6::ZxdgPositionerV6) {
fn positioner_implementation() -> zxdg_positioner_v6::Implementation<()> { fn positioner_implementation() -> zxdg_positioner_v6::Implementation<()> {
zxdg_positioner_v6::Implementation { zxdg_positioner_v6::Implementation {
destroy: |_, _, _, _| {}, destroy: |_, _, _, _| {},
set_size: |_, _, _, positioner, width, height| if width < 1 || height < 1 { set_size: |_, _, _, positioner, width, height| {
positioner.post_error( if width < 1 || height < 1 {
zxdg_positioner_v6::Error::InvalidInput as u32, positioner.post_error(
"Invalid size for positioner.".into(), zxdg_positioner_v6::Error::InvalidInput as u32,
); "Invalid size for positioner.".into(),
} else { );
let ptr = positioner.get_user_data(); } else {
let state = unsafe { &mut *(ptr as *mut PositionerState) }; let ptr = positioner.get_user_data();
state.rect_size = (width, height); let state = unsafe { &mut *(ptr as *mut PositionerState) };
state.rect_size = (width, height);
}
}, },
set_anchor_rect: |_, _, _, positioner, x, y, width, height| if width < 1 || height < 1 { set_anchor_rect: |_, _, _, positioner, x, y, width, height| {
positioner.post_error( if width < 1 || height < 1 {
zxdg_positioner_v6::Error::InvalidInput as u32, positioner.post_error(
"Invalid size for positioner's anchor rectangle.".into(), zxdg_positioner_v6::Error::InvalidInput as u32,
); "Invalid size for positioner's anchor rectangle.".into(),
} else { );
let ptr = positioner.get_user_data(); } else {
let state = unsafe { &mut *(ptr as *mut PositionerState) }; let ptr = positioner.get_user_data();
state.anchor_rect = Rectangle { let state = unsafe { &mut *(ptr as *mut PositionerState) };
x, state.anchor_rect = Rectangle {
y, x,
width, y,
height, width,
}; height,
};
}
}, },
set_anchor: |_, _, _, positioner, anchor| { set_anchor: |_, _, _, positioner, anchor| {
use self::zxdg_positioner_v6::Anchor; use self::zxdg_positioner_v6::Anchor;
@ -228,15 +230,15 @@ fn destroy_surface(surface: &zxdg_surface_v6::ZxdgSurfaceV6) {
let ptr = surface.get_user_data(); let ptr = surface.get_user_data();
surface.set_user_data(::std::ptr::null_mut()); surface.set_user_data(::std::ptr::null_mut());
// drop the state // drop the state
let data = let data = unsafe {
unsafe { Box::from_raw(ptr as *mut (zxdg_surface_v6::ZxdgSurfaceV6, zxdg_shell_v6::ZxdgShellV6)) }; Box::from_raw(ptr as *mut (zxdg_surface_v6::ZxdgSurfaceV6, zxdg_shell_v6::ZxdgShellV6))
};
// explicit call to drop to not forget what we're doing here // explicit call to drop to not forget what we're doing here
::std::mem::drop(data); ::std::mem::drop(data);
} }
fn surface_implementation<U, R, CID, SID, SD>( fn surface_implementation<U, R, CID, SID, SD>(
) ) -> zxdg_surface_v6::Implementation<ShellSurfaceIData<U, R, CID, SID, SD>>
-> zxdg_surface_v6::Implementation<ShellSurfaceIData<U, R, CID, SID, SD>>
where where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
@ -417,9 +419,9 @@ fn destroy_toplevel(surface: &zxdg_toplevel_v6::ZxdgToplevelV6) {
} }
// Utility functions allowing to factor out a lot of the upcoming logic // Utility functions allowing to factor out a lot of the upcoming logic
fn with_surface_toplevel_data<U, R, CID, SID, SD, F>(idata: &ShellSurfaceIData<U, R, CID, SID, SD>, fn with_surface_toplevel_data<U, R, CID, SID, SD, F>(
toplevel: &zxdg_toplevel_v6::ZxdgToplevelV6, f: F) idata: &ShellSurfaceIData<U, R, CID, SID, SD>, toplevel: &zxdg_toplevel_v6::ZxdgToplevelV6, f: F
where ) where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
CID: 'static, CID: 'static,
@ -438,13 +440,11 @@ where
.expect("xdg_toplevel exists but surface has not shell_surface role?!"); .expect("xdg_toplevel exists but surface has not shell_surface role?!");
} }
fn xdg_handle_display_state_change<U, R, CID, SID, SD>(evlh: &mut EventLoopHandle, fn xdg_handle_display_state_change<U, R, CID, SID, SD>(
idata: &ShellSurfaceIData<U, R, CID, SID, SD>, evlh: &mut EventLoopHandle, idata: &ShellSurfaceIData<U, R, CID, SID, SD>,
toplevel: &zxdg_toplevel_v6::ZxdgToplevelV6, toplevel: &zxdg_toplevel_v6::ZxdgToplevelV6, maximized: Option<bool>, minimized: Option<bool>,
maximized: Option<bool>, minimized: Option<bool>, fullscreen: Option<bool>, output: Option<&wl_output::WlOutput>,
fullscreen: Option<bool>, ) where
output: Option<&wl_output::WlOutput>)
where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
CID: 'static, CID: 'static,
@ -467,11 +467,10 @@ where
send_toplevel_configure(idata.compositor_token, toplevel, configure); send_toplevel_configure(idata.compositor_token, toplevel, configure);
} }
pub fn send_toplevel_configure<U, R, ID>(
pub fn send_toplevel_configure<U, R, ID>(token: CompositorToken<U, R, ID>, token: CompositorToken<U, R, ID>, resource: &zxdg_toplevel_v6::ZxdgToplevelV6,
resource: &zxdg_toplevel_v6::ZxdgToplevelV6, configure: ToplevelConfigure,
configure: ToplevelConfigure) ) where
where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
ID: 'static, ID: 'static,
@ -497,9 +496,9 @@ where
.expect("xdg_toplevel exists but surface has not shell_surface role?!"); .expect("xdg_toplevel exists but surface has not shell_surface role?!");
} }
fn make_toplevel_handle<U, R, H, SD>(token: CompositorToken<U, R, H>, fn make_toplevel_handle<U, R, H, SD>(
resource: &zxdg_toplevel_v6::ZxdgToplevelV6) token: CompositorToken<U, R, H>, resource: &zxdg_toplevel_v6::ZxdgToplevelV6
-> super::ToplevelSurface<U, R, H, SD> { ) -> super::ToplevelSurface<U, R, H, SD> {
let ptr = resource.get_user_data(); let ptr = resource.get_user_data();
let &(ref wl_surface, _, _) = unsafe { &*(ptr as *mut ShellSurfaceUserData) }; let &(ref wl_surface, _, _) = unsafe { &*(ptr as *mut ShellSurfaceUserData) };
super::ToplevelSurface { super::ToplevelSurface {
@ -511,8 +510,7 @@ fn make_toplevel_handle<U, R, H, SD>(token: CompositorToken<U, R, H>,
} }
fn toplevel_implementation<U, R, CID, SID, SD>( fn toplevel_implementation<U, R, CID, SID, SD>(
) ) -> zxdg_toplevel_v6::Implementation<ShellSurfaceIData<U, R, CID, SID, SD>>
-> zxdg_toplevel_v6::Implementation<ShellSurfaceIData<U, R, CID, SID, SD>>
where where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
@ -546,8 +544,9 @@ where
with_surface_toplevel_data(idata, toplevel, |toplevel_data| { with_surface_toplevel_data(idata, toplevel, |toplevel_data| {
toplevel_data.parent = parent.map(|toplevel_surface_parent| { toplevel_data.parent = parent.map(|toplevel_surface_parent| {
let parent_ptr = toplevel_surface_parent.get_user_data(); let parent_ptr = toplevel_surface_parent.get_user_data();
let &(ref parent_surface, _) = let &(ref parent_surface, _) = unsafe {
unsafe { &*(parent_ptr as *mut (wl_surface::WlSurface, zxdg_shell_v6::ZxdgShellV6)) }; &*(parent_ptr as *mut (wl_surface::WlSurface, zxdg_shell_v6::ZxdgShellV6))
};
unsafe { parent_surface.clone_unchecked() } unsafe { parent_surface.clone_unchecked() }
}) })
}); });
@ -620,10 +619,9 @@ fn destroy_popup(surface: &zxdg_popup_v6::ZxdgPopupV6) {
::std::mem::drop(data); ::std::mem::drop(data);
} }
pub(crate) fn send_popup_configure<U, R, ID>(token: CompositorToken<U, R, ID>, pub(crate) fn send_popup_configure<U, R, ID>(
resource: &zxdg_popup_v6::ZxdgPopupV6, token: CompositorToken<U, R, ID>, resource: &zxdg_popup_v6::ZxdgPopupV6, configure: PopupConfigure
configure: PopupConfigure) ) where
where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,
ID: 'static, ID: 'static,
@ -641,8 +639,9 @@ where
.expect("xdg_toplevel exists but surface has not shell_surface role?!"); .expect("xdg_toplevel exists but surface has not shell_surface role?!");
} }
fn make_popup_handle<U, R, H, SD>(token: CompositorToken<U, R, H>, resource: &zxdg_popup_v6::ZxdgPopupV6) fn make_popup_handle<U, R, H, SD>(
-> super::PopupSurface<U, R, H, SD> { token: CompositorToken<U, R, H>, resource: &zxdg_popup_v6::ZxdgPopupV6
) -> super::PopupSurface<U, R, H, SD> {
let ptr = resource.get_user_data(); let ptr = resource.get_user_data();
let &(ref wl_surface, _, _) = unsafe { &*(ptr as *mut ShellSurfaceUserData) }; let &(ref wl_surface, _, _) = unsafe { &*(ptr as *mut ShellSurfaceUserData) };
super::PopupSurface { super::PopupSurface {
@ -654,8 +653,7 @@ fn make_popup_handle<U, R, H, SD>(token: CompositorToken<U, R, H>, resource: &zx
} }
fn popup_implementation<U, R, CID, SID, SD>( fn popup_implementation<U, R, CID, SID, SD>(
) ) -> zxdg_popup_v6::Implementation<ShellSurfaceIData<U, R, CID, SID, SD>>
-> zxdg_popup_v6::Implementation<ShellSurfaceIData<U, R, CID, SID, SD>>
where where
U: 'static, U: 'static,
R: Role<ShellSurfaceRole> + 'static, R: Role<ShellSurfaceRole> + 'static,

View File

@ -61,7 +61,6 @@
//! //!
//! If you are already using an handler for this signal, you probably don't want to use this handler. //! If you are already using an handler for this signal, you probably don't want to use this handler.
use self::pool::{Pool, ResizeError}; use self::pool::{Pool, ResizeError};
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
@ -89,8 +88,9 @@ pub struct ShmGlobalData {
/// The global is directly registered into the eventloop, and this function /// The global is directly registered into the eventloop, and this function
/// returns the global handle, in case you whish to remove this global in /// returns the global handle, in case you whish to remove this global in
/// the future. /// the future.
pub fn init_shm_global<L>(evl: &mut EventLoop, mut formats: Vec<wl_shm::Format>, logger: L) pub fn init_shm_global<L>(
-> Global<wl_shm::WlShm, ShmGlobalData> evl: &mut EventLoop, mut formats: Vec<wl_shm::Format>, logger: L
) -> Global<wl_shm::WlShm, ShmGlobalData>
where where
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
{ {

View File

@ -1,5 +1,3 @@
use nix::{libc, unistd}; use nix::{libc, unistd};
use nix::sys::mman; use nix::sys::mman;
use nix::sys::signal::{self, SigAction, SigHandler, Signal}; use nix::sys::signal::{self, SigAction, SigHandler, Signal};