Get input working
This commit is contained in:
parent
c7682e77de
commit
96bb3570ba
|
@ -19,7 +19,7 @@ winit = { version = "0.8.2", optional = true }
|
||||||
drm = { version = "^0.3.0", optional = true }
|
drm = { version = "^0.3.0", optional = true }
|
||||||
gbm = { version = "^0.3.0", optional = true }
|
gbm = { version = "^0.3.0", optional = true }
|
||||||
glium = { version = "0.17.1", optional = true, default-features = false }
|
glium = { version = "0.17.1", optional = true, default-features = false }
|
||||||
input = { version = "0.3.0", optional = true }
|
input = { version = "0.4.0", git = "https://github.com/Smithay/input.rs.git", branch = "feature/udev", optional = true }
|
||||||
libudev = { git = "https://github.com/Drakulix/libudev-rs.git", branch = "feature/raw_ffi_access", optional = true }
|
libudev = { git = "https://github.com/Drakulix/libudev-rs.git", branch = "feature/raw_ffi_access", optional = true }
|
||||||
rental = "0.4.11"
|
rental = "0.4.11"
|
||||||
wayland-protocols = { version = "0.12.0", features = ["unstable_protocols", "server"] }
|
wayland-protocols = { version = "0.12.0", features = ["unstable_protocols", "server"] }
|
||||||
|
|
Binary file not shown.
Binary file not shown.
227
examples/udev.rs
227
examples/udev.rs
|
@ -2,6 +2,8 @@ extern crate drm;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate glium;
|
extern crate glium;
|
||||||
extern crate rand;
|
extern crate rand;
|
||||||
|
extern crate input as libinput;
|
||||||
|
extern crate image;
|
||||||
extern crate libudev;
|
extern crate libudev;
|
||||||
#[macro_use(define_roles)]
|
#[macro_use(define_roles)]
|
||||||
extern crate smithay;
|
extern crate smithay;
|
||||||
|
@ -22,15 +24,24 @@ use drm::control::encoder::Info as EncoderInfo;
|
||||||
use drm::control::crtc;
|
use drm::control::crtc;
|
||||||
use drm::result::Error as DrmError;
|
use drm::result::Error as DrmError;
|
||||||
use glium::Surface;
|
use glium::Surface;
|
||||||
|
use image::{ImageBuffer, Rgba};
|
||||||
|
use libinput::{Libinput, Device as LibinputDevice, event};
|
||||||
|
use libinput::event::keyboard::KeyboardEventTrait;
|
||||||
use helpers::{init_shell, GliumDrawer, MyWindowMap, Roles, SurfaceData};
|
use helpers::{init_shell, GliumDrawer, MyWindowMap, Roles, SurfaceData};
|
||||||
use slog::{Drain, Logger};
|
use slog::{Drain, Logger};
|
||||||
use smithay::backend::drm::{DrmBackend, DrmDevice, DrmHandler};
|
use smithay::backend::drm::{DrmBackend, DrmDevice, DrmHandler};
|
||||||
|
use smithay::backend::graphics::GraphicsBackend;
|
||||||
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
use smithay::backend::graphics::egl::EGLGraphicsBackend;
|
||||||
|
use smithay::backend::input::{self, Event, InputBackend, InputHandler, KeyboardKeyEvent, KeyState, PointerButtonEvent,
|
||||||
|
PointerAxisEvent};
|
||||||
|
use smithay::backend::libinput::{LibinputInputBackend, libinput_bind, PointerAxisEvent as LibinputPointerAxisEvent, LibinputSessionInterface};
|
||||||
use smithay::backend::udev::{UdevBackend, UdevHandler, udev_backend_bind};
|
use smithay::backend::udev::{UdevBackend, UdevHandler, udev_backend_bind};
|
||||||
use smithay::backend::session::SessionNotifier;
|
use smithay::backend::session::{Session, SessionNotifier};
|
||||||
use smithay::backend::session::direct::{direct_session_bind, DirectSession};
|
use smithay::backend::session::direct::{direct_session_bind, DirectSession};
|
||||||
use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction};
|
use smithay::wayland::compositor::{CompositorToken, SubsurfaceRole, TraversalAction};
|
||||||
use smithay::wayland::compositor::roles::Role;
|
use smithay::wayland::compositor::roles::Role;
|
||||||
|
use smithay::wayland::output::{Mode, Output, PhysicalProperties};
|
||||||
|
use smithay::wayland::seat::{KeyboardHandle, PointerHandle, Seat};
|
||||||
use smithay::wayland::shell::ShellState;
|
use smithay::wayland::shell::ShellState;
|
||||||
use smithay::wayland::shm::init_shm_global;
|
use smithay::wayland::shm::init_shm_global;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
|
@ -38,9 +49,121 @@ use std::collections::HashSet;
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Mutex};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use wayland_server::{StateToken, StateProxy};
|
use wayland_server::{StateToken, StateProxy};
|
||||||
|
use wayland_server::protocol::{wl_output, wl_pointer};
|
||||||
|
|
||||||
|
struct LibinputInputHandler {
|
||||||
|
log: Logger,
|
||||||
|
pointer: PointerHandle,
|
||||||
|
keyboard: KeyboardHandle,
|
||||||
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
|
pointer_location: Arc<Mutex<(f64, f64)>>,
|
||||||
|
screen_size: (u32, u32),
|
||||||
|
serial: u32,
|
||||||
|
running: Arc<AtomicBool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LibinputInputHandler {
|
||||||
|
fn next_serial(&mut self) -> u32 {
|
||||||
|
self.serial += 1;
|
||||||
|
self.serial
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InputHandler<LibinputInputBackend> for LibinputInputHandler {
|
||||||
|
fn on_seat_created(&mut self, _: &input::Seat) {
|
||||||
|
/* we just create a single static one */
|
||||||
|
}
|
||||||
|
fn on_seat_destroyed(&mut self, _: &input::Seat) {
|
||||||
|
/* we just create a single static one */
|
||||||
|
}
|
||||||
|
fn on_seat_changed(&mut self, _: &input::Seat) {
|
||||||
|
/* we just create a single static one */
|
||||||
|
}
|
||||||
|
fn on_keyboard_key(&mut self, _: &input::Seat, evt: event::keyboard::KeyboardKeyEvent) {
|
||||||
|
let keycode = evt.key();
|
||||||
|
let state = evt.state();
|
||||||
|
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
|
||||||
|
|
||||||
|
match (keycode, state) {
|
||||||
|
(1 /*ESC*/, KeyState::Pressed) => {
|
||||||
|
self.running.store(false, Ordering::SeqCst);
|
||||||
|
},
|
||||||
|
(keycode, state) => {
|
||||||
|
let serial = self.next_serial();
|
||||||
|
self.keyboard.input(keycode, state, serial, |_, _| true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn on_pointer_move(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionEvent) {
|
||||||
|
let (x, y) = (evt.dx(), evt.dy());
|
||||||
|
let serial = self.next_serial();
|
||||||
|
let mut location = self.pointer_location.lock().unwrap();
|
||||||
|
location.0 += x;
|
||||||
|
location.1 += y;
|
||||||
|
let under = self.window_map.borrow().get_surface_under((location.0, location.1));
|
||||||
|
self.pointer.motion(
|
||||||
|
under.as_ref().map(|&(ref s, (x, y))| (s, x, y)),
|
||||||
|
serial,
|
||||||
|
evt.time(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fn on_pointer_move_absolute(&mut self, _: &input::Seat, evt: event::pointer::PointerMotionAbsoluteEvent) {
|
||||||
|
let (x, y) = (evt.absolute_x_transformed(self.screen_size.0), evt.absolute_y_transformed(self.screen_size.1));
|
||||||
|
*self.pointer_location.lock().unwrap() = (x, y);
|
||||||
|
let serial = self.next_serial();
|
||||||
|
let under = self.window_map.borrow().get_surface_under((x, y));
|
||||||
|
self.pointer.motion(
|
||||||
|
under.as_ref().map(|&(ref s, (x, y))| (s, x, y)),
|
||||||
|
serial,
|
||||||
|
evt.time(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
fn on_pointer_button(&mut self, _: &input::Seat, evt: event::pointer::PointerButtonEvent) {
|
||||||
|
let serial = self.next_serial();
|
||||||
|
let button = evt.button();
|
||||||
|
let state = match evt.state() {
|
||||||
|
input::MouseButtonState::Pressed => {
|
||||||
|
// change the keyboard focus
|
||||||
|
let under = self.window_map
|
||||||
|
.borrow_mut()
|
||||||
|
.get_surface_and_bring_to_top(*self.pointer_location.lock().unwrap());
|
||||||
|
self.keyboard
|
||||||
|
.set_focus(under.as_ref().map(|&(ref s, _)| s), serial);
|
||||||
|
wl_pointer::ButtonState::Pressed
|
||||||
|
}
|
||||||
|
input::MouseButtonState::Released => wl_pointer::ButtonState::Released,
|
||||||
|
};
|
||||||
|
self.pointer.button(button, state, serial, evt.time());
|
||||||
|
}
|
||||||
|
fn on_pointer_axis(&mut self, _: &input::Seat, evt: LibinputPointerAxisEvent) {
|
||||||
|
let axis = match evt.axis() {
|
||||||
|
input::Axis::Vertical => wayland_server::protocol::wl_pointer::Axis::VerticalScroll,
|
||||||
|
input::Axis::Horizontal => wayland_server::protocol::wl_pointer::Axis::HorizontalScroll,
|
||||||
|
};
|
||||||
|
self.pointer.axis(axis, evt.amount(), evt.time());
|
||||||
|
}
|
||||||
|
fn on_touch_down(&mut self, _: &input::Seat, _: event::touch::TouchDownEvent) {
|
||||||
|
/* not done in this example */
|
||||||
|
}
|
||||||
|
fn on_touch_motion(&mut self, _: &input::Seat, _: event::touch::TouchMotionEvent) {
|
||||||
|
/* not done in this example */
|
||||||
|
}
|
||||||
|
fn on_touch_up(&mut self, _: &input::Seat, _: event::touch::TouchUpEvent) {
|
||||||
|
/* not done in this example */
|
||||||
|
}
|
||||||
|
fn on_touch_cancel(&mut self, _: &input::Seat, _: event::touch::TouchCancelEvent) {
|
||||||
|
/* not done in this example */
|
||||||
|
}
|
||||||
|
fn on_touch_frame(&mut self, _: &input::Seat, _: event::touch::TouchFrameEvent) {
|
||||||
|
/* not done in this example */
|
||||||
|
}
|
||||||
|
fn on_input_config_changed(&mut self, _: &mut [LibinputDevice]) {
|
||||||
|
/* not done in this example */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// A logger facility, here we use the terminal for this example
|
// A logger facility, here we use the terminal for this example
|
||||||
|
@ -63,7 +186,7 @@ fn main() {
|
||||||
* Initialize session on the current tty
|
* Initialize session on the current tty
|
||||||
*/
|
*/
|
||||||
let (session, mut notifier) = DirectSession::new(None, log.clone()).unwrap();
|
let (session, mut notifier) = DirectSession::new(None, log.clone()).unwrap();
|
||||||
let session_token = event_loop.state().insert(session);
|
let session = Arc::new(Mutex::new(session));
|
||||||
|
|
||||||
let running = Arc::new(AtomicBool::new(true));
|
let running = Arc::new(AtomicBool::new(true));
|
||||||
let r = running.clone();
|
let r = running.clone();
|
||||||
|
@ -71,48 +194,124 @@ fn main() {
|
||||||
r.store(false, Ordering::SeqCst);
|
r.store(false, Ordering::SeqCst);
|
||||||
}).expect("Error setting Ctrl-C handler");
|
}).expect("Error setting Ctrl-C handler");
|
||||||
|
|
||||||
|
let pointer_location = Arc::new(Mutex::new((0.0, 0.0)));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the udev backend
|
* Initialize the udev backend
|
||||||
*/
|
*/
|
||||||
let context = libudev::Context::new().unwrap();
|
let context = libudev::Context::new().unwrap();
|
||||||
|
let bytes = include_bytes!("resources/cursor2.rgba");
|
||||||
let udev
|
let udev
|
||||||
= UdevBackend::new(&mut event_loop, &context, &session_token, UdevHandlerImpl {
|
= UdevBackend::new(&mut event_loop, &context, session.clone(), UdevHandlerImpl {
|
||||||
shell_state_token,
|
shell_state_token,
|
||||||
compositor_token,
|
compositor_token,
|
||||||
window_map: window_map.clone(),
|
window_map: window_map.clone(),
|
||||||
|
pointer_location: pointer_location.clone(),
|
||||||
|
pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(),
|
||||||
logger: log.clone(),
|
logger: log.clone(),
|
||||||
}, log.clone()).unwrap();
|
}, log.clone()).unwrap();
|
||||||
|
|
||||||
let udev_token = event_loop.state().insert(udev);
|
let udev_token = event_loop.state().insert(udev);
|
||||||
let udev_session_id = notifier.register(udev_token.clone());
|
let udev_session_id = notifier.register(udev_token.clone());
|
||||||
|
|
||||||
|
let (seat_token, _) = Seat::new(&mut event_loop, session.seat().into(), log.clone());
|
||||||
|
|
||||||
|
let pointer = event_loop.state().get_mut(&seat_token).add_pointer();
|
||||||
|
let keyboard = event_loop
|
||||||
|
.state()
|
||||||
|
.get_mut(&seat_token)
|
||||||
|
.add_keyboard("", "", "", None, 1000, 500)
|
||||||
|
.expect("Failed to initialize the keyboard");
|
||||||
|
|
||||||
|
let (output_token, _output_global) = Output::new(
|
||||||
|
&mut event_loop,
|
||||||
|
"Drm".into(),
|
||||||
|
PhysicalProperties {
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
subpixel: wl_output::Subpixel::Unknown,
|
||||||
|
maker: "Smithay".into(),
|
||||||
|
model: "Generic DRM".into(),
|
||||||
|
},
|
||||||
|
log.clone(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let (w, h) = (1920, 1080); // Hardcode full-hd res
|
||||||
|
event_loop
|
||||||
|
.state()
|
||||||
|
.get_mut(&output_token)
|
||||||
|
.change_current_state(
|
||||||
|
Some(Mode {
|
||||||
|
width: w as i32,
|
||||||
|
height: h as i32,
|
||||||
|
refresh: 60_000,
|
||||||
|
}),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
event_loop
|
||||||
|
.state()
|
||||||
|
.get_mut(&output_token)
|
||||||
|
.set_preferred(Mode {
|
||||||
|
width: w as i32,
|
||||||
|
height: h as i32,
|
||||||
|
refresh: 60_000,
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize libinput backend
|
||||||
|
*/
|
||||||
|
let seat = session.seat();
|
||||||
|
let mut libinput_context = Libinput::new_from_udev::<LibinputSessionInterface<Arc<Mutex<DirectSession>>>>(session.into(), &context);
|
||||||
|
let libinput_session_id = notifier.register(libinput_context.clone());
|
||||||
|
libinput_context.udev_assign_seat(&seat);
|
||||||
|
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
|
||||||
|
libinput_backend.set_handler(LibinputInputHandler {
|
||||||
|
log: log.clone(),
|
||||||
|
pointer,
|
||||||
|
keyboard,
|
||||||
|
window_map: window_map.clone(),
|
||||||
|
pointer_location,
|
||||||
|
screen_size: (w, h),
|
||||||
|
serial: 0,
|
||||||
|
running: running.clone(),
|
||||||
|
});
|
||||||
|
let libinput_event_source = libinput_bind(libinput_backend, &mut event_loop).unwrap();
|
||||||
|
|
||||||
let session_event_source = direct_session_bind(notifier, &mut event_loop, log.clone()).unwrap();
|
let session_event_source = direct_session_bind(notifier, &mut event_loop, log.clone()).unwrap();
|
||||||
let udev_event_source = udev_backend_bind(&mut event_loop, udev_token).unwrap();
|
let udev_event_source = udev_backend_bind(&mut event_loop, udev_token).unwrap();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add a listening socket:
|
* Add a listening socket
|
||||||
*/
|
*/
|
||||||
let name = display.add_socket_auto().unwrap().into_string().unwrap();
|
let name = display.add_socket_auto().unwrap().into_string().unwrap();
|
||||||
println!("Listening on socket: {}", name);
|
println!("Listening on socket: {}", name);
|
||||||
|
|
||||||
while running.load(Ordering::SeqCst) {
|
while running.load(Ordering::SeqCst) {
|
||||||
event_loop.dispatch(Some(16)).unwrap();
|
event_loop.dispatch(Some(16));
|
||||||
display.flush_clients();
|
display.flush_clients();
|
||||||
window_map.borrow_mut().refresh();
|
window_map.borrow_mut().refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("Bye Bye");
|
||||||
|
|
||||||
let mut notifier = session_event_source.remove();
|
let mut notifier = session_event_source.remove();
|
||||||
notifier.unregister(udev_session_id);
|
notifier.unregister(udev_session_id);
|
||||||
|
notifier.unregister(libinput_session_id);
|
||||||
|
|
||||||
|
libinput_event_source.remove();
|
||||||
|
|
||||||
let udev_token = udev_event_source.remove();
|
let udev_token = udev_event_source.remove();
|
||||||
let udev = event_loop.state().remove(udev_token);
|
let udev = event_loop.state().remove(udev_token);
|
||||||
udev.close(event_loop.state());
|
udev.close(event_loop.state());
|
||||||
|
|
||||||
event_loop.state().remove(session_token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UdevHandlerImpl {
|
struct UdevHandlerImpl {
|
||||||
shell_state_token: StateToken<ShellState<SurfaceData, Roles, (), ()>>,
|
shell_state_token: StateToken<ShellState<SurfaceData, Roles, (), ()>>,
|
||||||
compositor_token: CompositorToken<SurfaceData, Roles, ()>,
|
compositor_token: CompositorToken<SurfaceData, Roles, ()>,
|
||||||
window_map: Rc<RefCell<MyWindowMap>>,
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
|
pointer_location: Arc<Mutex<(f64, f64)>>,
|
||||||
|
pointer_image: ImageBuffer<Rgba<u8>, Vec<u8>>,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,6 +345,12 @@ impl UdevHandlerImpl {
|
||||||
// create a backend
|
// create a backend
|
||||||
let renderer_token = device.create_backend(&mut state, crtc, mode, vec![connector_info.handle()]).unwrap();
|
let renderer_token = device.create_backend(&mut state, crtc, mode, vec![connector_info.handle()]).unwrap();
|
||||||
|
|
||||||
|
// create cursor
|
||||||
|
{
|
||||||
|
let renderer = state.get_mut(renderer_token);
|
||||||
|
renderer.set_cursor_representation(&self.pointer_image, (2, 2)).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
// render first frame
|
// render first frame
|
||||||
{
|
{
|
||||||
let renderer = state.get_mut(renderer_token);
|
let renderer = state.get_mut(renderer_token);
|
||||||
|
@ -172,6 +377,7 @@ impl UdevHandler<GliumDrawer<DrmBackend>, DrmHandlerImpl> for UdevHandlerImpl {
|
||||||
shell_state_token: self.shell_state_token.clone(),
|
shell_state_token: self.shell_state_token.clone(),
|
||||||
compositor_token: self.compositor_token.clone(),
|
compositor_token: self.compositor_token.clone(),
|
||||||
window_map: self.window_map.clone(),
|
window_map: self.window_map.clone(),
|
||||||
|
pointer_location: self.pointer_location.clone(),
|
||||||
logger: self.logger.clone(),
|
logger: self.logger.clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -202,6 +408,7 @@ pub struct DrmHandlerImpl {
|
||||||
shell_state_token: StateToken<ShellState<SurfaceData, Roles, (), ()>>,
|
shell_state_token: StateToken<ShellState<SurfaceData, Roles, (), ()>>,
|
||||||
compositor_token: CompositorToken<SurfaceData, Roles, ()>,
|
compositor_token: CompositorToken<SurfaceData, Roles, ()>,
|
||||||
window_map: Rc<RefCell<MyWindowMap>>,
|
window_map: Rc<RefCell<MyWindowMap>>,
|
||||||
|
pointer_location: Arc<Mutex<(f64, f64)>>,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,6 +417,10 @@ impl DrmHandler<GliumDrawer<DrmBackend>> for DrmHandlerImpl {
|
||||||
backend: &StateToken<GliumDrawer<DrmBackend>>, _crtc: crtc::Handle, _frame: u32, _duration: Duration) {
|
backend: &StateToken<GliumDrawer<DrmBackend>>, _crtc: crtc::Handle, _frame: u32, _duration: Duration) {
|
||||||
let state = state.into();
|
let state = state.into();
|
||||||
let drawer = state.get(backend);
|
let drawer = state.get(backend);
|
||||||
|
{
|
||||||
|
let (x, y) = *self.pointer_location.lock().unwrap();
|
||||||
|
let _ = (**drawer).set_cursor_position(x.trunc().abs() as u32, y.trunc().abs() as u32);
|
||||||
|
}
|
||||||
let mut frame = drawer.draw();
|
let mut frame = drawer.draw();
|
||||||
frame.clear_color(0.8, 0.8, 0.9, 1.0);
|
frame.clear_color(0.8, 0.8, 0.9, 1.0);
|
||||||
// redraw the frame, in a simple but inneficient way
|
// redraw the frame, in a simple but inneficient way
|
||||||
|
|
|
@ -424,7 +424,7 @@ impl GraphicsBackend for DrmBackend {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_cursor_representation(&self, buffer: ImageBuffer<Rgba<u8>, Vec<u8>>, hotspot: (u32, u32))
|
fn set_cursor_representation(&self, buffer: &ImageBuffer<Rgba<u8>, Vec<u8>>, hotspot: (u32, u32))
|
||||||
-> Result<()> {
|
-> Result<()> {
|
||||||
let (w, h) = buffer.dimensions();
|
let (w, h) = buffer.dimensions();
|
||||||
|
|
||||||
|
@ -445,7 +445,7 @@ impl GraphicsBackend for DrmBackend {
|
||||||
)
|
)
|
||||||
.chain_err(|| ErrorKind::GbmInitFailed)?;
|
.chain_err(|| ErrorKind::GbmInitFailed)?;
|
||||||
cursor
|
cursor
|
||||||
.write(&*buffer.into_raw())
|
.write(&**buffer)
|
||||||
.chain_err(|| ErrorKind::GbmInitFailed)?;
|
.chain_err(|| ErrorKind::GbmInitFailed)?;
|
||||||
|
|
||||||
trace!(self.logger, "Set the new imported cursor");
|
trace!(self.logger, "Set the new imported cursor");
|
||||||
|
|
|
@ -29,7 +29,7 @@ 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(&self, cursor: &Self::CursorFormat, hotspot: (u32, u32))
|
||||||
-> Result<(), Self::Error>;
|
-> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,18 @@
|
||||||
//! Implementation of input backend trait for types provided by `libinput`
|
//! Implementation of input backend trait for types provided by `libinput`
|
||||||
|
|
||||||
|
#[cfg(feature = "backend_session")]
|
||||||
|
use backend::session::{AsErrno, Session, SessionObserver};
|
||||||
use backend::input as backend;
|
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;
|
use std::io::{Error as IoError, Result as IoResult};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::os::unix::io::RawFd;
|
||||||
|
use wayland_server::{EventLoopHandle, StateProxy};
|
||||||
|
use wayland_server::sources::{FdEventSource, FdEventSourceImpl, FdInterest};
|
||||||
|
|
||||||
/// Libinput based `InputBackend`.
|
/// Libinput based `InputBackend`.
|
||||||
///
|
///
|
||||||
|
@ -260,7 +266,7 @@ impl backend::InputBackend for LibinputInputBackend {
|
||||||
if self.handler.is_some() {
|
if self.handler.is_some() {
|
||||||
self.clear_handler();
|
self.clear_handler();
|
||||||
}
|
}
|
||||||
info!(self.logger, "New input handler set.");
|
info!(self.logger, "New input handler set");
|
||||||
for seat in self.seats.values() {
|
for seat in self.seats.values() {
|
||||||
trace!(self.logger, "Calling on_seat_created with {:?}", seat);
|
trace!(self.logger, "Calling on_seat_created with {:?}", seat);
|
||||||
handler.on_seat_created(seat);
|
handler.on_seat_created(seat);
|
||||||
|
@ -548,3 +554,59 @@ impl From<event::pointer::ButtonState> for backend::MouseButtonState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SessionObserver for libinput::Libinput {
|
||||||
|
fn pause<'a>(&mut self, _state: &mut StateProxy<'a>) {
|
||||||
|
self.suspend()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn activate<'a>(&mut self, _state: &mut StateProxy<'a>) {
|
||||||
|
// TODO Is this the best way to handle this failure?
|
||||||
|
self.resume().expect("Unable to resume libinput context");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LibinputSessionInterface<S: Session>(S);
|
||||||
|
|
||||||
|
impl<S: Session> From<S> for LibinputSessionInterface<S> {
|
||||||
|
fn from(session: S) -> LibinputSessionInterface<S> {
|
||||||
|
LibinputSessionInterface(session)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Session> libinput::LibinputInterface for LibinputSessionInterface<S> {
|
||||||
|
fn open_restricted(&mut self, path: &Path, flags: i32) -> Result<RawFd, i32> {
|
||||||
|
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*/))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close_restricted(&mut self, fd: RawFd) {
|
||||||
|
let _ = self.0.close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn libinput_bind(backend: LibinputInputBackend, evlh: &mut EventLoopHandle)
|
||||||
|
-> IoResult<FdEventSource<LibinputInputBackend>>
|
||||||
|
{
|
||||||
|
let fd = unsafe { backend.context.fd() };
|
||||||
|
evlh.add_fd_event_source(
|
||||||
|
fd,
|
||||||
|
fd_event_source_implementation(),
|
||||||
|
backend,
|
||||||
|
FdInterest::READ,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fd_event_source_implementation() -> FdEventSourceImpl<LibinputInputBackend> {
|
||||||
|
FdEventSourceImpl {
|
||||||
|
ready: |_evlh, ref mut backend, _, _| {
|
||||||
|
use ::backend::input::InputBackend;
|
||||||
|
if let Err(error) = backend.dispatch_new_events() {
|
||||||
|
warn!(backend.logger, "Libinput errored: {}", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: |_evlh, ref backend, _, error| {
|
||||||
|
warn!(backend.logger, "Libinput fd errored: {}", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::os::unix::io::RawFd;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
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};
|
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, major, minor, Mode, fstat};
|
||||||
|
@ -15,7 +15,7 @@ use wayland_server::sources::SignalEventSource;
|
||||||
#[cfg(feature = "backend_session_udev")]
|
#[cfg(feature = "backend_session_udev")]
|
||||||
use libudev::Context;
|
use libudev::Context;
|
||||||
|
|
||||||
use super::{Session, SessionNotifier, SessionObserver};
|
use super::{AsErrno, Session, SessionNotifier, SessionObserver};
|
||||||
|
|
||||||
mod tty {
|
mod tty {
|
||||||
ioctl!(bad read kd_get_mode with 0x4B3B; i16);
|
ioctl!(bad read kd_get_mode with 0x4B3B; i16);
|
||||||
|
@ -34,6 +34,7 @@ mod tty {
|
||||||
ioctl!(bad write_int vt_activate with 0x5606);
|
ioctl!(bad write_int vt_activate with 0x5606);
|
||||||
ioctl!(bad write_int vt_wait_active with 0x5607);
|
ioctl!(bad write_int vt_wait_active with 0x5607);
|
||||||
ioctl!(bad write_ptr vt_set_mode with 0x5602; VtMode);
|
ioctl!(bad write_ptr vt_set_mode with 0x5602; VtMode);
|
||||||
|
ioctl!(bad write_int vt_rel_disp with 0x5605);
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
pub struct VtMode {
|
pub struct VtMode {
|
||||||
|
@ -50,7 +51,7 @@ mod tty {
|
||||||
}
|
}
|
||||||
pub const VT_AUTO: i8 = 0x00;
|
pub const VT_AUTO: i8 = 0x00;
|
||||||
pub const VT_PROCESS: i8 = 0x01;
|
pub const VT_PROCESS: i8 = 0x01;
|
||||||
pub const VT_ACKACQ: i8 = 0x02;
|
pub const VT_ACKACQ: i32 = 0x02;
|
||||||
|
|
||||||
extern {
|
extern {
|
||||||
pub fn __libc_current_sigrtmin() -> i8;
|
pub fn __libc_current_sigrtmin() -> i8;
|
||||||
|
@ -146,6 +147,7 @@ pub struct DirectSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DirectSessionNotifier {
|
pub struct DirectSessionNotifier {
|
||||||
|
tty: RawFd,
|
||||||
active: Arc<AtomicBool>,
|
active: Arc<AtomicBool>,
|
||||||
signals: Vec<Option<Box<SessionObserver>>>,
|
signals: Vec<Option<Box<SessionObserver>>>,
|
||||||
signal: Signal,
|
signal: Signal,
|
||||||
|
@ -175,6 +177,7 @@ impl DirectSession {
|
||||||
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,
|
||||||
active,
|
active,
|
||||||
signals: Vec::new(),
|
signals: Vec::new(),
|
||||||
signal,
|
signal,
|
||||||
|
@ -194,7 +197,7 @@ impl DirectSession {
|
||||||
bail!(ErrorKind::NotRunningFromTTY);
|
bail!(ErrorKind::NotRunningFromTTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
let vt_num = minor(stat.st_dev) as i32 - 1;
|
let vt_num = minor(stat.st_rdev) as i32;
|
||||||
info!(logger, "Running from tty: {}", vt_num);
|
info!(logger, "Running from tty: {}", vt_num);
|
||||||
|
|
||||||
let mut mode = 0;
|
let mut mode = 0;
|
||||||
|
@ -246,8 +249,9 @@ impl DirectSession {
|
||||||
impl Session for DirectSession {
|
impl Session for DirectSession {
|
||||||
type Error = NixError;
|
type Error = NixError;
|
||||||
|
|
||||||
fn open(&mut self, path: &Path) -> NixResult<RawFd> {
|
fn open(&mut self, path: &Path, flags: OFlag) -> NixResult<RawFd> {
|
||||||
open(path, fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY | fcntl::O_NONBLOCK, Mode::empty())
|
info!(self.logger, "Opening device: {:?}", path);
|
||||||
|
open(path, flags, Mode::empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close(&mut self, fd: RawFd) -> NixResult<()> {
|
fn close(&mut self, fd: RawFd) -> NixResult<()> {
|
||||||
|
@ -258,9 +262,9 @@ impl Session for DirectSession {
|
||||||
self.active.load(Ordering::SeqCst)
|
self.active.load(Ordering::SeqCst)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn seat(&self) -> &str {
|
fn seat(&self) -> String {
|
||||||
// The VT api can only be used on seat0
|
// The VT api can only be used on seat0
|
||||||
return "seat0"
|
String::from("seat0")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_vt(&mut self, vt_num: i32) -> NixResult<()> {
|
fn change_vt(&mut self, vt_num: i32) -> NixResult<()> {
|
||||||
|
@ -268,8 +272,19 @@ impl Session for DirectSession {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl AsErrno for NixError {
|
||||||
|
fn as_errno(&self) -> Option<i32> {
|
||||||
|
match *self {
|
||||||
|
NixError::Sys(errno) => Some(errno as i32),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Drop for DirectSession {
|
impl Drop for DirectSession {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
@ -318,7 +333,13 @@ where
|
||||||
if let &mut Some(ref mut signal) = signal {signal.pause(&mut evlh.state().as_proxy()); }
|
if let &mut Some(ref mut signal) = signal {signal.pause(&mut evlh.state().as_proxy()); }
|
||||||
}
|
}
|
||||||
notifier.active.store(false, Ordering::SeqCst);
|
notifier.active.store(false, Ordering::SeqCst);
|
||||||
|
unsafe {
|
||||||
|
tty::vt_rel_disp(notifier.tty, 1).expect("Unable to release tty lock");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
|
unsafe {
|
||||||
|
tty::vt_rel_disp(notifier.tty, tty::VT_ACKACQ).expect("Unable to acquire tty lock");
|
||||||
|
}
|
||||||
for signal in &mut notifier.signals {
|
for signal in &mut notifier.signals {
|
||||||
if let &mut Some(ref mut signal) = signal { signal.activate(&mut evlh.state().as_proxy()); }
|
if let &mut Some(ref mut signal) = signal { signal.activate(&mut evlh.state().as_proxy()); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
use std::os::unix::io::RawFd;
|
use std::os::unix::io::RawFd;
|
||||||
|
use nix::fcntl::OFlag;
|
||||||
use wayland_server::StateProxy;
|
use wayland_server::StateProxy;
|
||||||
|
|
||||||
pub trait Session {
|
pub trait Session {
|
||||||
type Error: ::std::fmt::Debug;
|
type Error: AsErrno;
|
||||||
|
|
||||||
fn open(&mut self, path: &Path) -> Result<RawFd, Self::Error>;
|
fn open(&mut self, path: &Path, flags: OFlag) -> Result<RawFd, Self::Error>;
|
||||||
fn close(&mut self, fd: RawFd) -> Result<(), Self::Error>;
|
fn close(&mut self, fd: RawFd) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
fn change_vt(&mut self, vt: i32) -> Result<(), Self::Error>;
|
fn change_vt(&mut self, vt: i32) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
fn is_active(&self) -> bool;
|
fn is_active(&self) -> bool;
|
||||||
fn seat(&self) -> &str;
|
fn seat(&self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait SessionNotifier {
|
pub trait SessionNotifier {
|
||||||
|
@ -30,13 +32,47 @@ pub trait SessionObserver {
|
||||||
impl Session for () {
|
impl Session for () {
|
||||||
type Error = ();
|
type Error = ();
|
||||||
|
|
||||||
fn open(&mut self, _path: &Path) -> Result<RawFd, Self::Error> { Err(()) }
|
fn open(&mut self, _path: &Path, _flags: OFlag) -> Result<RawFd, Self::Error> { Err(()) }
|
||||||
fn close(&mut self, _fd: RawFd) -> Result<(), Self::Error> { 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 { false }
|
||||||
fn seat(&self) -> &str { "seat0" }
|
fn seat(&self) -> String { String::from("seat0") }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Session> Session for Arc<Mutex<S>> {
|
||||||
|
type Error = S::Error;
|
||||||
|
|
||||||
|
fn open(&mut self, path: &Path, flags: OFlag) -> Result<RawFd, Self::Error> {
|
||||||
|
self.lock().unwrap().open(path, flags)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn close(&mut self, fd: RawFd) -> Result<(), Self::Error> {
|
||||||
|
self.lock().unwrap().close(fd)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_vt(&mut self, vt: i32) -> Result<(), Self::Error> {
|
||||||
|
self.lock().unwrap().change_vt(vt)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_active(&self) -> bool {
|
||||||
|
self.lock().unwrap().is_active()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn seat(&self) -> String {
|
||||||
|
self.lock().unwrap().seat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait AsErrno: ::std::fmt::Debug {
|
||||||
|
fn as_errno(&self) -> Option<i32>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsErrno for () {
|
||||||
|
fn as_errno(&self) -> Option<i32> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod direct;
|
pub mod direct;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use libudev::{Context, MonitorBuilder, MonitorSocket, Event, EventType, Enumerator, Result as UdevResult};
|
use libudev::{Context, MonitorBuilder, MonitorSocket, Event, EventType, Enumerator, Result as UdevResult};
|
||||||
|
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;
|
||||||
|
@ -16,7 +17,7 @@ use ::backend::session::{Session, SessionObserver};
|
||||||
pub struct UdevBackend<B: Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'static, S: Session + 'static, T: UdevHandler<B, H> + 'static> {
|
pub struct UdevBackend<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)>)>,
|
devices: HashMap<dev_t, (StateToken<DrmDevice<B>>, FdEventSource<(StateToken<DrmDevice<B>>, H)>)>,
|
||||||
monitor: MonitorSocket,
|
monitor: MonitorSocket,
|
||||||
session: StateToken<S>,
|
session: S,
|
||||||
handler: T,
|
handler: T,
|
||||||
logger: ::slog::Logger,
|
logger: ::slog::Logger,
|
||||||
}
|
}
|
||||||
|
@ -24,7 +25,7 @@ pub struct UdevBackend<B: Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'stat
|
||||||
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> {
|
||||||
pub fn new<'a, L>(mut evlh: &mut EventLoopHandle,
|
pub fn new<'a, L>(mut evlh: &mut EventLoopHandle,
|
||||||
context: &Context,
|
context: &Context,
|
||||||
session_token: &StateToken<S>,
|
mut session: S,
|
||||||
mut handler: T,
|
mut handler: T,
|
||||||
logger: L)
|
logger: L)
|
||||||
-> Result<UdevBackend<B, H, S, T>>
|
-> Result<UdevBackend<B, H, S, T>>
|
||||||
|
@ -32,7 +33,7 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'sta
|
||||||
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 = String::from(evlh.state().get(&session_token).seat());
|
let seat = session.seat();
|
||||||
let devices = all_gpus(context, seat)
|
let devices = all_gpus(context, seat)
|
||||||
.chain_err(|| ErrorKind::FailedToScan)?
|
.chain_err(|| ErrorKind::FailedToScan)?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -40,8 +41,7 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'sta
|
||||||
.flat_map(|path| {
|
.flat_map(|path| {
|
||||||
match unsafe { DrmDevice::new_from_fd(
|
match unsafe { DrmDevice::new_from_fd(
|
||||||
{
|
{
|
||||||
let session = evlh.state().get_mut(session_token);
|
match session.open(&path, fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY | fcntl::O_NONBLOCK) {
|
||||||
match session.open(&path) {
|
|
||||||
Ok(fd) => fd,
|
Ok(fd) => fd,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(logger, "Unable to open drm device {:?}, Error: {:?}. Skipping", path, err);
|
warn!(logger, "Unable to open drm device {:?}, Error: {:?}. Skipping", path, err);
|
||||||
|
@ -63,7 +63,6 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'sta
|
||||||
let device = evlh.state().remove(token);
|
let device = evlh.state().remove(token);
|
||||||
let fd = device.as_raw_fd();
|
let fd = device.as_raw_fd();
|
||||||
drop(device);
|
drop(device);
|
||||||
let session = evlh.state().get_mut(session_token);
|
|
||||||
if let Err(err) = session.close(fd) {
|
if let Err(err) = session.close(fd) {
|
||||||
warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);
|
warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);
|
||||||
};
|
};
|
||||||
|
@ -78,7 +77,6 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'sta
|
||||||
let device = evlh.state().remove(token);
|
let device = evlh.state().remove(token);
|
||||||
let fd = device.as_raw_fd();
|
let fd = device.as_raw_fd();
|
||||||
drop(device);
|
drop(device);
|
||||||
let session = evlh.state().get_mut(session_token);
|
|
||||||
if let Err(err) = session.close(fd) {
|
if let Err(err) = session.close(fd) {
|
||||||
warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);
|
warn!(logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);
|
||||||
};
|
};
|
||||||
|
@ -88,7 +86,6 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'sta
|
||||||
None => {
|
None => {
|
||||||
let fd = device.as_raw_fd();
|
let fd = device.as_raw_fd();
|
||||||
drop(device); //drops master
|
drop(device); //drops master
|
||||||
let session = evlh.state().get_mut(session_token);
|
|
||||||
if let Err(err) = session.close(fd) {
|
if let Err(err) = session.close(fd) {
|
||||||
warn!(logger, "Failed to close device. Error: {:?}. Ignoring", err);
|
warn!(logger, "Failed to close device. Error: {:?}. Ignoring", err);
|
||||||
}
|
}
|
||||||
|
@ -110,7 +107,7 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'sta
|
||||||
Ok(UdevBackend {
|
Ok(UdevBackend {
|
||||||
devices,
|
devices,
|
||||||
monitor,
|
monitor,
|
||||||
session: session_token.clone(),
|
session,
|
||||||
handler,
|
handler,
|
||||||
logger,
|
logger,
|
||||||
})
|
})
|
||||||
|
@ -124,11 +121,11 @@ impl<B: From<DrmBackend> + Borrow<DrmBackend> + 'static, H: DrmHandler<B> + 'sta
|
||||||
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);
|
||||||
let session = state.get_mut(&self.session);
|
if let Err(err) = self.session.close(fd) {
|
||||||
if let Err(err) = 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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,10 +184,8 @@ where
|
||||||
let mut device = {
|
let mut device = {
|
||||||
match unsafe { DrmDevice::new_from_fd(
|
match unsafe { DrmDevice::new_from_fd(
|
||||||
{
|
{
|
||||||
let session_token = evlh.state().get(token).session.clone();
|
|
||||||
let logger = evlh.state().get(token).logger.clone();
|
let logger = evlh.state().get(token).logger.clone();
|
||||||
let session = evlh.state().get_mut(&session_token);
|
match evlh.state().get_mut(token).session.open(path, fcntl::O_RDWR | fcntl::O_CLOEXEC | fcntl::O_NOCTTY | fcntl::O_NONBLOCK) {
|
||||||
match session.open(path) {
|
|
||||||
Ok(fd) => fd,
|
Ok(fd) => fd,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(logger, "Unable to open drm device {:?}, Error: {:?}. Skipping", path, err);
|
warn!(logger, "Unable to open drm device {:?}, Error: {:?}. Skipping", path, err);
|
||||||
|
@ -213,29 +208,24 @@ where
|
||||||
evlh.state().get_mut(token).devices.insert(devnum, (dev_token, fd_event_source));
|
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 session_token = udev.session.clone();
|
let mut state: StateProxy = state.into();
|
||||||
state.with_value(&session_token, |state, session| {
|
udev.handler.device_removed(&mut state, &dev_token);
|
||||||
let mut state: StateProxy = state.into();
|
let device = state.remove(dev_token);
|
||||||
udev.handler.device_removed(&mut state, &dev_token);
|
let fd = device.as_raw_fd();
|
||||||
let device = state.remove(dev_token);
|
drop(device);
|
||||||
let fd = device.as_raw_fd();
|
if let Err(err) = udev.session.close(fd) {
|
||||||
drop(device);
|
warn!(udev.logger, "Failed to close dropped device. Error: {:?}. Ignoring", err);
|
||||||
if let Err(err) = session.close(fd) {
|
};
|
||||||
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| {
|
||||||
state.with_value(&udev.session, |_, session| {
|
if let Err(err) = udev.session.close(fd) {
|
||||||
if let Err(err) = session.close(fd) {
|
warn!(udev.logger, "Failed to close unused device. Error: {:?}", err);
|
||||||
warn!(udev.logger, "Failed to close unused device. Error: {:?}", err);
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -244,23 +234,20 @@ where
|
||||||
// Device removed
|
// Device removed
|
||||||
EventType::Remove => {
|
EventType::Remove => {
|
||||||
evlh.state().with_value(token, |state, udev| {
|
evlh.state().with_value(token, |state, udev| {
|
||||||
let session_token = udev.session.clone();
|
info!(udev.logger, "Device Remove");
|
||||||
state.with_value(&session_token, |state, session| {
|
if let Some(devnum) = event.devnum() {
|
||||||
info!(udev.logger, "Device Remove");
|
if let Some((device, fd_event_source)) = udev.devices.remove(&devnum) {
|
||||||
if let Some(devnum) = event.devnum() {
|
fd_event_source.remove();
|
||||||
if let Some((device, fd_event_source)) = udev.devices.remove(&devnum) {
|
let mut state: StateProxy = state.into();
|
||||||
fd_event_source.remove();
|
udev.handler.device_removed(&mut state, &device);
|
||||||
let mut state: StateProxy = state.into();
|
let device = state.remove(device);
|
||||||
udev.handler.device_removed(&mut state, &device);
|
let fd = device.as_raw_fd();
|
||||||
let device = state.remove(device);
|
drop(device);
|
||||||
let fd = device.as_raw_fd();
|
if let Err(err) = udev.session.close(fd) {
|
||||||
drop(device);
|
warn!(udev.logger, "Failed to close device {:?}. Error: {:?}. Ignoring", event.sysname(), err);
|
||||||
if let Err(err) = session.close(fd) {
|
};
|
||||||
warn!(udev.logger, "Failed to close device {:?}. Error: {:?}. Ignoring", event.sysname(), err);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
// New connector
|
// New connector
|
||||||
|
|
|
@ -190,11 +190,11 @@ 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(&self, cursor: &Self::CursorFormat, _hotspot: (u32, u32))
|
||||||
-> ::std::result::Result<(), ()> {
|
-> ::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);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue