anvil: reorganize platform-specific values
This commit is contained in:
parent
3f01f978f8
commit
4bf6bfa08d
|
@ -12,7 +12,7 @@ members = [ "anvil" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "1"
|
bitflags = "1"
|
||||||
calloop = {version = "0.8.0" }
|
calloop = "0.8.0"
|
||||||
cgmath = "0.18.0"
|
cgmath = "0.18.0"
|
||||||
dbus = { version = "0.9.0", optional = true }
|
dbus = { version = "0.9.0", optional = true }
|
||||||
drm-fourcc = "^2.1.1"
|
drm-fourcc = "^2.1.1"
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
use std::{process::Command, sync::atomic::Ordering};
|
use std::{process::Command, sync::atomic::Ordering};
|
||||||
|
|
||||||
use crate::AnvilState;
|
use crate::{udev::UdevData, winit::WinitData, AnvilState};
|
||||||
|
|
||||||
#[cfg(feature = "udev")]
|
|
||||||
use smithay::backend::session::Session;
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::input::{
|
backend::input::{
|
||||||
self, Event, InputBackend, InputEvent, KeyState, KeyboardKeyEvent, PointerAxisEvent,
|
self, Event, InputBackend, InputEvent, KeyState, KeyboardKeyEvent, PointerAxisEvent,
|
||||||
|
@ -17,20 +15,7 @@ use smithay::{
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<Backend> AnvilState<Backend> {
|
impl<Backend> AnvilState<Backend> {
|
||||||
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
|
fn keyboard_key_to_action<B: InputBackend>(&mut self, evt: B::KeyboardKeyEvent) -> KeyAction {
|
||||||
match event {
|
|
||||||
InputEvent::Keyboard { event, .. } => self.on_keyboard_key::<B>(event),
|
|
||||||
InputEvent::PointerMotion { event, .. } => self.on_pointer_move::<B>(event),
|
|
||||||
InputEvent::PointerMotionAbsolute { event, .. } => self.on_pointer_move_absolute::<B>(event),
|
|
||||||
InputEvent::PointerButton { event, .. } => self.on_pointer_button::<B>(event),
|
|
||||||
InputEvent::PointerAxis { event, .. } => self.on_pointer_axis::<B>(event),
|
|
||||||
_ => {
|
|
||||||
// other events are not handled in anvil (yet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_keyboard_key<B: InputBackend>(&mut self, evt: B::KeyboardKeyEvent) {
|
|
||||||
let keycode = evt.key_code();
|
let keycode = evt.key_code();
|
||||||
let state = evt.state();
|
let state = evt.state();
|
||||||
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
|
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
|
||||||
|
@ -52,8 +37,10 @@ impl<Backend> AnvilState<Backend> {
|
||||||
});
|
});
|
||||||
if let KeyState::Released = state {
|
if let KeyState::Released = state {
|
||||||
// only process special actions on key press, not release
|
// only process special actions on key press, not release
|
||||||
return;
|
return KeyAction::None;
|
||||||
}
|
}
|
||||||
|
return action;
|
||||||
|
/*
|
||||||
match action {
|
match action {
|
||||||
KeyAction::Quit => {
|
KeyAction::Quit => {
|
||||||
info!(self.log, "Quitting.");
|
info!(self.log, "Quitting.");
|
||||||
|
@ -94,113 +81,7 @@ impl<Backend> AnvilState<Backend> {
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
*/
|
||||||
|
|
||||||
fn on_pointer_move<B: InputBackend>(&mut self, evt: B::PointerMotionEvent) {
|
|
||||||
let (x, y) = (evt.delta_x(), evt.delta_y());
|
|
||||||
let serial = SCOUNTER.next_serial();
|
|
||||||
let mut location = self.pointer_location.borrow_mut();
|
|
||||||
location.0 += x as f64;
|
|
||||||
location.1 += y as f64;
|
|
||||||
|
|
||||||
#[cfg(feature = "udev")]
|
|
||||||
{
|
|
||||||
// clamp to screen limits
|
|
||||||
// this event is never generated by winit
|
|
||||||
*location = self.clamp_coords(*location);
|
|
||||||
}
|
|
||||||
|
|
||||||
let under = self
|
|
||||||
.window_map
|
|
||||||
.borrow()
|
|
||||||
.get_surface_under((location.0, location.1));
|
|
||||||
self.pointer.motion(*location, under, serial, evt.time());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_pointer_move_absolute<B: InputBackend>(&mut self, evt: B::PointerMotionAbsoluteEvent) {
|
|
||||||
// different cases depending on the context:
|
|
||||||
let (x, y) = {
|
|
||||||
#[cfg(feature = "udev")]
|
|
||||||
{
|
|
||||||
if self.session.is_some() {
|
|
||||||
// we are started on a tty
|
|
||||||
let x = self.pointer_location.borrow().0;
|
|
||||||
let screen_size = self.current_output_size(x);
|
|
||||||
// monitor coordinates
|
|
||||||
let (ux, uy) = evt.position_transformed(screen_size);
|
|
||||||
(ux + self.current_output_offset(x) as f64, uy as f64)
|
|
||||||
} else {
|
|
||||||
// we are started in winit
|
|
||||||
evt.position()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "udev"))]
|
|
||||||
{
|
|
||||||
evt.position()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
*self.pointer_location.borrow_mut() = (x, y);
|
|
||||||
let serial = SCOUNTER.next_serial();
|
|
||||||
let under = self.window_map.borrow().get_surface_under((x as f64, y as f64));
|
|
||||||
self.pointer.motion((x, y), under, serial, evt.time());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "udev")]
|
|
||||||
fn clamp_coords(&self, pos: (f64, f64)) -> (f64, f64) {
|
|
||||||
let output_map = self.output_map.as_ref().unwrap();
|
|
||||||
let outputs = output_map.borrow();
|
|
||||||
|
|
||||||
if outputs.len() == 0 {
|
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
let (mut x, mut y) = pos;
|
|
||||||
// max_x is the sum of the width of all outputs
|
|
||||||
let max_x = outputs.iter().fold(0u32, |acc, output| acc + output.size.0);
|
|
||||||
x = x.max(0.0).min(max_x as f64);
|
|
||||||
|
|
||||||
// max y depends on the current output
|
|
||||||
let max_y = self.current_output_size(x).1;
|
|
||||||
y = y.max(0.0).min(max_y as f64);
|
|
||||||
|
|
||||||
(x, y)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "udev")]
|
|
||||||
fn current_output_idx(&self, x: f64) -> usize {
|
|
||||||
let output_map = self.output_map.as_ref().unwrap();
|
|
||||||
let outputs = output_map.borrow();
|
|
||||||
|
|
||||||
outputs
|
|
||||||
.iter()
|
|
||||||
// map each output to their x position
|
|
||||||
.scan(0u32, |acc, output| {
|
|
||||||
let curr_x = *acc;
|
|
||||||
*acc += output.size.0;
|
|
||||||
Some(curr_x)
|
|
||||||
})
|
|
||||||
// get an index
|
|
||||||
.enumerate()
|
|
||||||
// find the first one with a greater x
|
|
||||||
.find(|(_idx, x_pos)| *x_pos as f64 > x)
|
|
||||||
// the previous output is the one we are on
|
|
||||||
.map(|(idx, _)| idx - 1)
|
|
||||||
.unwrap_or(outputs.len() - 1)
|
|
||||||
}
|
|
||||||
#[cfg(feature = "udev")]
|
|
||||||
fn current_output_size(&self, x: f64) -> (u32, u32) {
|
|
||||||
let output_map = self.output_map.as_ref().unwrap();
|
|
||||||
let outputs = output_map.borrow();
|
|
||||||
outputs[self.current_output_idx(x)].size
|
|
||||||
}
|
|
||||||
#[cfg(feature = "udev")]
|
|
||||||
fn current_output_offset(&self, x: f64) -> u32 {
|
|
||||||
let output_map = self.output_map.as_ref().unwrap();
|
|
||||||
let outputs = output_map.borrow();
|
|
||||||
outputs
|
|
||||||
.iter()
|
|
||||||
.take(self.current_output_idx(x))
|
|
||||||
.fold(0u32, |acc, output| acc + output.size.0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_pointer_button<B: InputBackend>(&mut self, evt: B::PointerButtonEvent) {
|
fn on_pointer_button<B: InputBackend>(&mut self, evt: B::PointerButtonEvent) {
|
||||||
|
@ -267,7 +148,147 @@ impl<Backend> AnvilState<Backend> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "winit")]
|
||||||
|
impl AnvilState<WinitData> {
|
||||||
|
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
|
||||||
|
match event {
|
||||||
|
InputEvent::Keyboard { event, .. } => match self.keyboard_key_to_action::<B>(event) {
|
||||||
|
KeyAction::None => {}
|
||||||
|
KeyAction::Quit => {
|
||||||
|
info!(self.log, "Quitting.");
|
||||||
|
self.running.store(false, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
KeyAction::Run(cmd) => {
|
||||||
|
info!(self.log, "Starting program"; "cmd" => cmd.clone());
|
||||||
|
if let Err(e) = Command::new(&cmd).spawn() {
|
||||||
|
error!(self.log,
|
||||||
|
"Failed to start program";
|
||||||
|
"cmd" => cmd,
|
||||||
|
"err" => format!("{:?}", e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
action => {
|
||||||
|
warn!(self.log, "Key action {:?} unsupported on winit backend.", action);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
InputEvent::PointerMotionAbsolute { event, .. } => self.on_pointer_move_absolute::<B>(event),
|
||||||
|
InputEvent::PointerButton { event, .. } => self.on_pointer_button::<B>(event),
|
||||||
|
InputEvent::PointerAxis { event, .. } => self.on_pointer_axis::<B>(event),
|
||||||
|
_ => {
|
||||||
|
// other events are not handled in anvil (yet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_pointer_move_absolute<B: InputBackend>(&mut self, evt: B::PointerMotionAbsoluteEvent) {
|
||||||
|
// different cases depending on the context:
|
||||||
|
let (x, y) = evt.position();
|
||||||
|
*self.pointer_location.borrow_mut() = (x, y);
|
||||||
|
let serial = SCOUNTER.next_serial();
|
||||||
|
let under = self.window_map.borrow().get_surface_under((x as f64, y as f64));
|
||||||
|
self.pointer.motion((x, y), under, serial, evt.time());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "udev")]
|
||||||
|
impl AnvilState<UdevData> {
|
||||||
|
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
|
||||||
|
match event {
|
||||||
|
InputEvent::Keyboard { event, .. } => match self.keyboard_key_to_action::<B>(event) {
|
||||||
|
KeyAction::None => {}
|
||||||
|
KeyAction::Quit => {
|
||||||
|
info!(self.log, "Quitting.");
|
||||||
|
self.running.store(false, Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
KeyAction::Run(cmd) => {
|
||||||
|
info!(self.log, "Starting program"; "cmd" => cmd.clone());
|
||||||
|
if let Err(e) = Command::new(&cmd).spawn() {
|
||||||
|
error!(self.log,
|
||||||
|
"Failed to start program";
|
||||||
|
"cmd" => cmd,
|
||||||
|
"err" => format!("{:?}", e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
action => {
|
||||||
|
warn!(self.log, "Key action {:?} unsupported on winit backend.", action);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
InputEvent::PointerMotion { event, .. } => self.on_pointer_move::<B>(event),
|
||||||
|
InputEvent::PointerButton { event, .. } => self.on_pointer_button::<B>(event),
|
||||||
|
InputEvent::PointerAxis { event, .. } => self.on_pointer_axis::<B>(event),
|
||||||
|
_ => {
|
||||||
|
// other events are not handled in anvil (yet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_pointer_move<B: InputBackend>(&mut self, evt: B::PointerMotionEvent) {
|
||||||
|
let (x, y) = (evt.delta_x(), evt.delta_y());
|
||||||
|
let serial = SCOUNTER.next_serial();
|
||||||
|
let mut location = self.pointer_location.borrow_mut();
|
||||||
|
location.0 += x as f64;
|
||||||
|
location.1 += y as f64;
|
||||||
|
|
||||||
|
// clamp to screen limits
|
||||||
|
// this event is never generated by winit
|
||||||
|
*location = self.clamp_coords(*location);
|
||||||
|
|
||||||
|
let under = self
|
||||||
|
.window_map
|
||||||
|
.borrow()
|
||||||
|
.get_surface_under((location.0, location.1));
|
||||||
|
self.pointer.motion(*location, under, serial, evt.time());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clamp_coords(&self, pos: (f64, f64)) -> (f64, f64) {
|
||||||
|
let outputs = self.backend_data.output_map.borrow();
|
||||||
|
|
||||||
|
if outputs.len() == 0 {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
let (mut x, mut y) = pos;
|
||||||
|
// max_x is the sum of the width of all outputs
|
||||||
|
let max_x = outputs.iter().fold(0u32, |acc, output| acc + output.size.0);
|
||||||
|
x = x.max(0.0).min(max_x as f64);
|
||||||
|
|
||||||
|
// max y depends on the current output
|
||||||
|
let max_y = self.current_output_size(x).1;
|
||||||
|
y = y.max(0.0).min(max_y as f64);
|
||||||
|
|
||||||
|
(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_output_idx(&self, x: f64) -> usize {
|
||||||
|
let outputs = self.backend_data.output_map.borrow();
|
||||||
|
|
||||||
|
outputs
|
||||||
|
.iter()
|
||||||
|
// map each output to their x position
|
||||||
|
.scan(0u32, |acc, output| {
|
||||||
|
let curr_x = *acc;
|
||||||
|
*acc += output.size.0;
|
||||||
|
Some(curr_x)
|
||||||
|
})
|
||||||
|
// get an index
|
||||||
|
.enumerate()
|
||||||
|
// find the first one with a greater x
|
||||||
|
.find(|(_idx, x_pos)| *x_pos as f64 > x)
|
||||||
|
// the previous output is the one we are on
|
||||||
|
.map(|(idx, _)| idx - 1)
|
||||||
|
.unwrap_or(outputs.len() - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_output_size(&self, x: f64) -> (u32, u32) {
|
||||||
|
let outputs = self.backend_data.output_map.borrow();
|
||||||
|
outputs[self.current_output_idx(x)].size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Possible results of a keyboard action
|
/// Possible results of a keyboard action
|
||||||
|
#[derive(Debug)]
|
||||||
enum KeyAction {
|
enum KeyAction {
|
||||||
/// Quit the compositor
|
/// Quit the compositor
|
||||||
Quit,
|
Quit,
|
||||||
|
|
|
@ -9,7 +9,7 @@ use std::{
|
||||||
|
|
||||||
use smithay::{
|
use smithay::{
|
||||||
reexports::{
|
reexports::{
|
||||||
calloop::{generic::Generic, Interest, LoopHandle, Mode, RegistrationToken},
|
calloop::{generic::Generic, Interest, LoopHandle, Mode},
|
||||||
wayland_server::{protocol::wl_surface::WlSurface, Display},
|
wayland_server::{protocol::wl_surface::WlSurface, Display},
|
||||||
},
|
},
|
||||||
wayland::{
|
wayland::{
|
||||||
|
@ -22,23 +22,19 @@ use smithay::{
|
||||||
|
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
use smithay::backend::egl::display::EGLBufferReader;
|
use smithay::backend::egl::display::EGLBufferReader;
|
||||||
#[cfg(feature = "udev")]
|
|
||||||
use smithay::backend::session::{auto::AutoSession, Session};
|
|
||||||
#[cfg(feature = "xwayland")]
|
#[cfg(feature = "xwayland")]
|
||||||
use smithay::xwayland::XWayland;
|
use smithay::xwayland::XWayland;
|
||||||
|
|
||||||
use crate::shell::init_shell;
|
use crate::shell::init_shell;
|
||||||
#[cfg(feature = "udev")]
|
|
||||||
use crate::udev::MyOutput;
|
|
||||||
#[cfg(feature = "xwayland")]
|
#[cfg(feature = "xwayland")]
|
||||||
use crate::xwayland::XWm;
|
use crate::xwayland::XWm;
|
||||||
|
|
||||||
pub struct AnvilState<Backend> {
|
pub struct AnvilState<BackendData> {
|
||||||
pub backend: Backend,
|
pub backend_data: BackendData,
|
||||||
pub socket_name: String,
|
pub socket_name: String,
|
||||||
pub running: Arc<AtomicBool>,
|
pub running: Arc<AtomicBool>,
|
||||||
pub display: Rc<RefCell<Display>>,
|
pub display: Rc<RefCell<Display>>,
|
||||||
pub handle: LoopHandle<'static, AnvilState<Backend>>,
|
pub handle: LoopHandle<'static, AnvilState<BackendData>>,
|
||||||
pub ctoken: CompositorToken<crate::shell::Roles>,
|
pub ctoken: CompositorToken<crate::shell::Roles>,
|
||||||
pub window_map: Rc<RefCell<crate::window_map::WindowMap<crate::shell::Roles>>>,
|
pub window_map: Rc<RefCell<crate::window_map::WindowMap<crate::shell::Roles>>>,
|
||||||
pub dnd_icon: Arc<Mutex<Option<WlSurface>>>,
|
pub dnd_icon: Arc<Mutex<Option<WlSurface>>>,
|
||||||
|
@ -48,44 +44,35 @@ pub struct AnvilState<Backend> {
|
||||||
pub keyboard: KeyboardHandle,
|
pub keyboard: KeyboardHandle,
|
||||||
pub pointer_location: Rc<RefCell<(f64, f64)>>,
|
pub pointer_location: Rc<RefCell<(f64, f64)>>,
|
||||||
pub cursor_status: Arc<Mutex<CursorImageStatus>>,
|
pub cursor_status: Arc<Mutex<CursorImageStatus>>,
|
||||||
#[cfg(feature = "udev")]
|
|
||||||
pub output_map: Option<Rc<RefCell<Vec<MyOutput>>>>,
|
|
||||||
pub seat_name: String,
|
pub seat_name: String,
|
||||||
#[cfg(feature = "udev")]
|
#[cfg(feature = "egl")]
|
||||||
pub session: Option<AutoSession>,
|
pub egl_reader: Rc<RefCell<Option<EGLBufferReader>>>,
|
||||||
// things we must keep alive
|
// things we must keep alive
|
||||||
_wayland_event_source: RegistrationToken,
|
|
||||||
#[cfg(feature = "xwayland")]
|
#[cfg(feature = "xwayland")]
|
||||||
_xwayland: XWayland<XWm<Backend>>,
|
_xwayland: XWayland<XWm<BackendData>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Backend: Default + 'static> AnvilState<Backend> {
|
impl<BackendData: Backend + 'static> AnvilState<BackendData> {
|
||||||
pub fn init(
|
pub fn init(
|
||||||
display: Rc<RefCell<Display>>,
|
display: Rc<RefCell<Display>>,
|
||||||
handle: LoopHandle<'static, AnvilState<Backend>>,
|
handle: LoopHandle<'static, AnvilState<BackendData>>,
|
||||||
|
backend_data: BackendData,
|
||||||
#[cfg(feature = "egl")] egl_reader: Rc<RefCell<Option<EGLBufferReader>>>,
|
#[cfg(feature = "egl")] egl_reader: Rc<RefCell<Option<EGLBufferReader>>>,
|
||||||
#[cfg(feature = "udev")] session: Option<AutoSession>,
|
|
||||||
#[cfg(not(feature = "udev"))] _session: Option<()>,
|
|
||||||
#[cfg(feature = "udev")] output_map: Option<Rc<RefCell<Vec<MyOutput>>>>,
|
|
||||||
#[cfg(not(feature = "udev"))] _output_map: Option<()>,
|
|
||||||
log: slog::Logger,
|
log: slog::Logger,
|
||||||
) -> AnvilState<Backend> {
|
) -> AnvilState<BackendData> {
|
||||||
// init the wayland connection
|
// init the wayland connection
|
||||||
let _wayland_event_source = handle
|
handle
|
||||||
.insert_source(
|
.insert_source(
|
||||||
Generic::from_fd(display.borrow().get_poll_fd(), Interest::READ, Mode::Level),
|
Generic::from_fd(display.borrow().get_poll_fd(), Interest::READ, Mode::Level),
|
||||||
{
|
move |_, _, state: &mut AnvilState<BackendData>| {
|
||||||
let display = display.clone();
|
let display = state.display.clone();
|
||||||
let log = log.clone();
|
let mut display = display.borrow_mut();
|
||||||
move |_, _, state: &mut AnvilState<Backend>| {
|
match display.dispatch(std::time::Duration::from_millis(0), state) {
|
||||||
let mut display = display.borrow_mut();
|
Ok(_) => Ok(()),
|
||||||
match display.dispatch(std::time::Duration::from_millis(0), state) {
|
Err(e) => {
|
||||||
Ok(_) => Ok(()),
|
error!(state.log, "I/O error on the Wayland display: {}", e);
|
||||||
Err(e) => {
|
state.running.store(false, Ordering::SeqCst);
|
||||||
error!(log, "I/O error on the Wayland display: {}", e);
|
Err(e)
|
||||||
state.running.store(false, Ordering::SeqCst);
|
|
||||||
Err(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -94,10 +81,11 @@ impl<Backend: Default + 'static> AnvilState<Backend> {
|
||||||
|
|
||||||
// Init the basic compositor globals
|
// Init the basic compositor globals
|
||||||
|
|
||||||
init_shm_global(&mut display.borrow_mut(), vec![], log.clone());
|
init_shm_global(&mut (*display).borrow_mut(), vec![], log.clone());
|
||||||
|
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
let shell_handles = init_shell::<Backend>(&mut display.borrow_mut(), egl_reader, log.clone());
|
let shell_handles =
|
||||||
|
init_shell::<BackendData>(&mut display.borrow_mut(), egl_reader.clone(), log.clone());
|
||||||
#[cfg(not(feature = "egl"))]
|
#[cfg(not(feature = "egl"))]
|
||||||
let shell_handles = init_shell(&mut display.borrow_mut(), log.clone());
|
let shell_handles = init_shell(&mut display.borrow_mut(), log.clone());
|
||||||
|
|
||||||
|
@ -132,14 +120,7 @@ impl<Backend: Default + 'static> AnvilState<Backend> {
|
||||||
);
|
);
|
||||||
|
|
||||||
// init input
|
// init input
|
||||||
#[cfg(feature = "udev")]
|
let seat_name = backend_data.seat_name();
|
||||||
let seat_name = if let Some(ref session) = session {
|
|
||||||
session.seat()
|
|
||||||
} else {
|
|
||||||
"anvil".into()
|
|
||||||
};
|
|
||||||
#[cfg(not(feature = "udev"))]
|
|
||||||
let seat_name: String = "anvil".into();
|
|
||||||
|
|
||||||
let (mut seat, _) = Seat::new(
|
let (mut seat, _) = Seat::new(
|
||||||
&mut display.borrow_mut(),
|
&mut display.borrow_mut(),
|
||||||
|
@ -174,7 +155,7 @@ impl<Backend: Default + 'static> AnvilState<Backend> {
|
||||||
};
|
};
|
||||||
|
|
||||||
AnvilState {
|
AnvilState {
|
||||||
backend: Default::default(),
|
backend_data,
|
||||||
running: Arc::new(AtomicBool::new(true)),
|
running: Arc::new(AtomicBool::new(true)),
|
||||||
display,
|
display,
|
||||||
handle,
|
handle,
|
||||||
|
@ -187,14 +168,14 @@ impl<Backend: Default + 'static> AnvilState<Backend> {
|
||||||
keyboard,
|
keyboard,
|
||||||
cursor_status,
|
cursor_status,
|
||||||
pointer_location: Rc::new(RefCell::new((0.0, 0.0))),
|
pointer_location: Rc::new(RefCell::new((0.0, 0.0))),
|
||||||
#[cfg(feature = "udev")]
|
|
||||||
output_map,
|
|
||||||
seat_name,
|
seat_name,
|
||||||
#[cfg(feature = "udev")]
|
egl_reader,
|
||||||
session,
|
|
||||||
_wayland_event_source,
|
|
||||||
#[cfg(feature = "xwayland")]
|
#[cfg(feature = "xwayland")]
|
||||||
_xwayland,
|
_xwayland,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Backend {
|
||||||
|
fn seat_name(&self) -> String;
|
||||||
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ use smithay::{
|
||||||
|
|
||||||
use crate::drawing::*;
|
use crate::drawing::*;
|
||||||
use crate::shell::{MyWindowMap, Roles};
|
use crate::shell::{MyWindowMap, Roles};
|
||||||
use crate::state::AnvilState;
|
use crate::state::{AnvilState, Backend};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct SessionFd(RawFd);
|
pub struct SessionFd(RawFd);
|
||||||
|
@ -70,11 +70,19 @@ impl AsRawFd for SessionFd {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UdevData {}
|
pub struct UdevData {
|
||||||
|
pub output_map: Rc<RefCell<Vec<MyOutput>>>,
|
||||||
|
pub session: AutoSession,
|
||||||
|
#[cfg(feature = "egl")]
|
||||||
|
primary_gpu: Option<PathBuf>,
|
||||||
|
backends: HashMap<dev_t, BackendData>,
|
||||||
|
signaler: Signaler<SessionSignal>,
|
||||||
|
pointer_image: ImageBuffer<Rgba<u8>, Vec<u8>>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for UdevData {
|
impl Backend for UdevData {
|
||||||
fn default() -> UdevData {
|
fn seat_name(&self) -> String {
|
||||||
UdevData {}
|
self.session.seat()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,42 +114,30 @@ pub fn run_udev(
|
||||||
/*
|
/*
|
||||||
* Initialize the compositor
|
* Initialize the compositor
|
||||||
*/
|
*/
|
||||||
|
let pointer_bytes = include_bytes!("../resources/cursor2.rgba");
|
||||||
|
let primary_gpu = primary_gpu(&session.seat()).unwrap_or_default();
|
||||||
|
let data = UdevData {
|
||||||
|
session,
|
||||||
|
output_map: output_map.clone(),
|
||||||
|
primary_gpu,
|
||||||
|
backends: HashMap::new(),
|
||||||
|
signaler: session_signal.clone(),
|
||||||
|
pointer_image: ImageBuffer::from_raw(64, 64, pointer_bytes.to_vec()).unwrap(),
|
||||||
|
};
|
||||||
let mut state = AnvilState::init(
|
let mut state = AnvilState::init(
|
||||||
display.clone(),
|
display.clone(),
|
||||||
event_loop.handle(),
|
event_loop.handle(),
|
||||||
|
data,
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
egl_buffer_reader.clone(),
|
egl_buffer_reader.clone(),
|
||||||
Some(session),
|
|
||||||
Some(output_map.clone()),
|
|
||||||
log.clone(),
|
log.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the udev backend
|
* Initialize the udev backend
|
||||||
*/
|
*/
|
||||||
let bytes = include_bytes!("../resources/cursor2.rgba");
|
|
||||||
let udev_backend = UdevBackend::new(state.seat_name.clone(), log.clone()).map_err(|_| ())?;
|
let udev_backend = UdevBackend::new(state.seat_name.clone(), log.clone()).map_err(|_| ())?;
|
||||||
|
|
||||||
let mut udev_handler = UdevHandlerImpl {
|
|
||||||
compositor_token: state.ctoken,
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
egl_buffer_reader,
|
|
||||||
session: state.session.clone().unwrap(),
|
|
||||||
backends: HashMap::new(),
|
|
||||||
output_map,
|
|
||||||
display: display.clone(),
|
|
||||||
#[cfg(feature = "egl")]
|
|
||||||
primary_gpu: primary_gpu(&state.seat_name).unwrap_or_default(),
|
|
||||||
window_map: state.window_map.clone(),
|
|
||||||
pointer_location: state.pointer_location.clone(),
|
|
||||||
pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(),
|
|
||||||
cursor_status: state.cursor_status.clone(),
|
|
||||||
dnd_icon: state.dnd_icon.clone(),
|
|
||||||
loop_handle: event_loop.handle(),
|
|
||||||
signaler: session_signal.clone(),
|
|
||||||
logger: log.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize a fake output (we render one screen to every device in this example)
|
* Initialize a fake output (we render one screen to every device in this example)
|
||||||
*/
|
*/
|
||||||
|
@ -150,7 +146,7 @@ pub fn run_udev(
|
||||||
* Initialize libinput backend
|
* Initialize libinput backend
|
||||||
*/
|
*/
|
||||||
let mut libinput_context = Libinput::new_with_udev::<LibinputSessionInterface<AutoSession>>(
|
let mut libinput_context = Libinput::new_with_udev::<LibinputSessionInterface<AutoSession>>(
|
||||||
state.session.clone().unwrap().into(),
|
state.backend_data.session.clone().into(),
|
||||||
);
|
);
|
||||||
libinput_context.udev_assign_seat(&state.seat_name).unwrap();
|
libinput_context.udev_assign_seat(&state.seat_name).unwrap();
|
||||||
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
|
let mut libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
|
||||||
|
@ -170,15 +166,15 @@ pub fn run_udev(
|
||||||
.insert_source(notifier, |(), &mut (), _anvil_state| {})
|
.insert_source(notifier, |(), &mut (), _anvil_state| {})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
for (dev, path) in udev_backend.device_list() {
|
for (dev, path) in udev_backend.device_list() {
|
||||||
udev_handler.device_added(dev, path.into())
|
state.device_added(dev, path.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
let udev_event_source = event_loop
|
let udev_event_source = event_loop
|
||||||
.handle()
|
.handle()
|
||||||
.insert_source(udev_backend, move |event, _, _state| match event {
|
.insert_source(udev_backend, move |event, _, state| match event {
|
||||||
UdevEvent::Added { device_id, path } => udev_handler.device_added(device_id, path),
|
UdevEvent::Added { device_id, path } => state.device_added(device_id, path),
|
||||||
UdevEvent::Changed { device_id } => udev_handler.device_changed(device_id),
|
UdevEvent::Changed { device_id } => state.device_changed(device_id),
|
||||||
UdevEvent::Removed { device_id } => udev_handler.device_removed(device_id),
|
UdevEvent::Removed { device_id } => state.device_removed(device_id),
|
||||||
})
|
})
|
||||||
.map_err(|e| -> IoError { e.into() })
|
.map_err(|e| -> IoError { e.into() })
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -283,127 +279,106 @@ struct BackendData {
|
||||||
event_dispatcher: Dispatcher<'static, DrmDevice<SessionFd>, AnvilState<UdevData>>,
|
event_dispatcher: Dispatcher<'static, DrmDevice<SessionFd>, AnvilState<UdevData>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UdevHandlerImpl {
|
pub fn scan_connectors(
|
||||||
compositor_token: CompositorToken<Roles>,
|
device: &mut DrmDevice<SessionFd>,
|
||||||
#[cfg(feature = "egl")]
|
gbm: &GbmDevice<SessionFd>,
|
||||||
egl_buffer_reader: Rc<RefCell<Option<EGLBufferReader>>>,
|
egl: &EGLDisplay,
|
||||||
session: AutoSession,
|
context: &EGLContext,
|
||||||
backends: HashMap<dev_t, BackendData>,
|
display: &mut Display,
|
||||||
display: Rc<RefCell<Display>>,
|
output_map: &mut Vec<MyOutput>,
|
||||||
#[cfg(feature = "egl")]
|
signaler: &Signaler<SessionSignal>,
|
||||||
primary_gpu: Option<PathBuf>,
|
logger: &::slog::Logger,
|
||||||
window_map: Rc<RefCell<MyWindowMap>>,
|
) -> HashMap<crtc::Handle, Rc<RefCell<RenderSurface>>> {
|
||||||
output_map: Rc<RefCell<Vec<MyOutput>>>,
|
// Get a set of all modesetting resource handles (excluding planes):
|
||||||
pointer_location: Rc<RefCell<(f64, f64)>>,
|
let res_handles = device.resource_handles().unwrap();
|
||||||
pointer_image: ImageBuffer<Rgba<u8>, Vec<u8>>,
|
|
||||||
cursor_status: Arc<Mutex<CursorImageStatus>>,
|
|
||||||
dnd_icon: Arc<Mutex<Option<wl_surface::WlSurface>>>,
|
|
||||||
loop_handle: LoopHandle<'static, AnvilState<UdevData>>,
|
|
||||||
signaler: Signaler<SessionSignal>,
|
|
||||||
logger: ::slog::Logger,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UdevHandlerImpl {
|
// Use first connected connector
|
||||||
pub fn scan_connectors(
|
let connector_infos: Vec<ConnectorInfo> = res_handles
|
||||||
device: &mut DrmDevice<SessionFd>,
|
.connectors()
|
||||||
gbm: &GbmDevice<SessionFd>,
|
.iter()
|
||||||
egl: &EGLDisplay,
|
.map(|conn| device.get_connector(*conn).unwrap())
|
||||||
context: &EGLContext,
|
.filter(|conn| conn.state() == ConnectorState::Connected)
|
||||||
display: &mut Display,
|
.inspect(|conn| info!(logger, "Connected: {:?}", conn.interface()))
|
||||||
output_map: &mut Vec<MyOutput>,
|
.collect();
|
||||||
signaler: &Signaler<SessionSignal>,
|
|
||||||
logger: &::slog::Logger,
|
|
||||||
) -> HashMap<crtc::Handle, Rc<RefCell<RenderSurface>>> {
|
|
||||||
// Get a set of all modesetting resource handles (excluding planes):
|
|
||||||
let res_handles = device.resource_handles().unwrap();
|
|
||||||
|
|
||||||
// Use first connected connector
|
let mut backends = HashMap::new();
|
||||||
let connector_infos: Vec<ConnectorInfo> = res_handles
|
|
||||||
.connectors()
|
// very naive way of finding good crtc/encoder/connector combinations. This problem is np-complete
|
||||||
|
for connector_info in connector_infos {
|
||||||
|
let encoder_infos = connector_info
|
||||||
|
.encoders()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|conn| device.get_connector(*conn).unwrap())
|
.filter_map(|e| *e)
|
||||||
.filter(|conn| conn.state() == ConnectorState::Connected)
|
.flat_map(|encoder_handle| device.get_encoder(encoder_handle))
|
||||||
.inspect(|conn| info!(logger, "Connected: {:?}", conn.interface()))
|
.collect::<Vec<EncoderInfo>>();
|
||||||
.collect();
|
'outer: for encoder_info in encoder_infos {
|
||||||
|
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
|
||||||
|
if let Entry::Vacant(entry) = backends.entry(crtc) {
|
||||||
|
info!(
|
||||||
|
logger,
|
||||||
|
"Trying to setup connector {:?}-{} with crtc {:?}",
|
||||||
|
connector_info.interface(),
|
||||||
|
connector_info.interface_id(),
|
||||||
|
crtc,
|
||||||
|
);
|
||||||
|
let context = match EGLContext::new_shared(egl, context, logger.clone()) {
|
||||||
|
Ok(context) => context,
|
||||||
|
Err(err) => {
|
||||||
|
warn!(logger, "Failed to create EGLContext: {}", err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let renderer = match unsafe { Gles2Renderer::new(context, logger.clone()) } {
|
||||||
|
Ok(renderer) => renderer,
|
||||||
|
Err(err) => {
|
||||||
|
warn!(logger, "Failed to create Gles2 Renderer: {}", err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let mut surface = match device.create_surface(
|
||||||
|
crtc,
|
||||||
|
connector_info.modes()[0],
|
||||||
|
&[connector_info.handle()],
|
||||||
|
) {
|
||||||
|
Ok(surface) => surface,
|
||||||
|
Err(err) => {
|
||||||
|
warn!(logger, "Failed to create drm surface: {}", err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
surface.link(signaler.clone());
|
||||||
|
let renderer = match DrmRenderSurface::new(surface, gbm.clone(), renderer, logger.clone())
|
||||||
|
{
|
||||||
|
Ok(renderer) => renderer,
|
||||||
|
Err(err) => {
|
||||||
|
warn!(logger, "Failed to create rendering surface: {}", err);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut backends = HashMap::new();
|
output_map.push(MyOutput::new(
|
||||||
|
display,
|
||||||
|
device.device_id(),
|
||||||
|
crtc,
|
||||||
|
connector_info,
|
||||||
|
logger.clone(),
|
||||||
|
));
|
||||||
|
|
||||||
// very naive way of finding good crtc/encoder/connector combinations. This problem is np-complete
|
entry.insert(Rc::new(RefCell::new(renderer)));
|
||||||
for connector_info in connector_infos {
|
break 'outer;
|
||||||
let encoder_infos = connector_info
|
|
||||||
.encoders()
|
|
||||||
.iter()
|
|
||||||
.filter_map(|e| *e)
|
|
||||||
.flat_map(|encoder_handle| device.get_encoder(encoder_handle))
|
|
||||||
.collect::<Vec<EncoderInfo>>();
|
|
||||||
'outer: for encoder_info in encoder_infos {
|
|
||||||
for crtc in res_handles.filter_crtcs(encoder_info.possible_crtcs()) {
|
|
||||||
if let Entry::Vacant(entry) = backends.entry(crtc) {
|
|
||||||
info!(
|
|
||||||
logger,
|
|
||||||
"Trying to setup connector {:?}-{} with crtc {:?}",
|
|
||||||
connector_info.interface(),
|
|
||||||
connector_info.interface_id(),
|
|
||||||
crtc,
|
|
||||||
);
|
|
||||||
let context = match EGLContext::new_shared(egl, context, logger.clone()) {
|
|
||||||
Ok(context) => context,
|
|
||||||
Err(err) => {
|
|
||||||
warn!(logger, "Failed to create EGLContext: {}", err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let renderer = match unsafe { Gles2Renderer::new(context, logger.clone()) } {
|
|
||||||
Ok(renderer) => renderer,
|
|
||||||
Err(err) => {
|
|
||||||
warn!(logger, "Failed to create Gles2 Renderer: {}", err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let mut surface = match device.create_surface(
|
|
||||||
crtc,
|
|
||||||
connector_info.modes()[0],
|
|
||||||
&[connector_info.handle()],
|
|
||||||
) {
|
|
||||||
Ok(surface) => surface,
|
|
||||||
Err(err) => {
|
|
||||||
warn!(logger, "Failed to create drm surface: {}", err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
surface.link(signaler.clone());
|
|
||||||
let renderer =
|
|
||||||
match DrmRenderSurface::new(surface, gbm.clone(), renderer, logger.clone()) {
|
|
||||||
Ok(renderer) => renderer,
|
|
||||||
Err(err) => {
|
|
||||||
warn!(logger, "Failed to create rendering surface: {}", err);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
output_map.push(MyOutput::new(
|
|
||||||
display,
|
|
||||||
device.device_id(),
|
|
||||||
crtc,
|
|
||||||
connector_info,
|
|
||||||
logger.clone(),
|
|
||||||
));
|
|
||||||
|
|
||||||
entry.insert(Rc::new(RefCell::new(renderer)));
|
|
||||||
break 'outer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
backends
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backends
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdevHandlerImpl {
|
impl AnvilState<UdevData> {
|
||||||
fn device_added(&mut self, device_id: dev_t, path: PathBuf) {
|
fn device_added(&mut self, device_id: dev_t, path: PathBuf) {
|
||||||
// Try to open the device
|
// Try to open the device
|
||||||
if let Some((mut device, gbm)) = self
|
if let Some((mut device, gbm)) = self
|
||||||
|
.backend_data
|
||||||
.session
|
.session
|
||||||
.open(
|
.open(
|
||||||
&path,
|
&path,
|
||||||
|
@ -414,14 +389,14 @@ impl UdevHandlerImpl {
|
||||||
match {
|
match {
|
||||||
let fd = SessionFd(fd);
|
let fd = SessionFd(fd);
|
||||||
(
|
(
|
||||||
DrmDevice::new(fd.clone(), true, self.logger.clone()),
|
DrmDevice::new(fd.clone(), true, self.log.clone()),
|
||||||
GbmDevice::new(fd),
|
GbmDevice::new(fd),
|
||||||
)
|
)
|
||||||
} {
|
} {
|
||||||
(Ok(drm), Ok(gbm)) => Some((drm, gbm)),
|
(Ok(drm), Ok(gbm)) => Some((drm, gbm)),
|
||||||
(Err(err), _) => {
|
(Err(err), _) => {
|
||||||
warn!(
|
warn!(
|
||||||
self.logger,
|
self.log,
|
||||||
"Skipping device {:?}, because of drm error: {}", device_id, err
|
"Skipping device {:?}, because of drm error: {}", device_id, err
|
||||||
);
|
);
|
||||||
None
|
None
|
||||||
|
@ -429,7 +404,7 @@ impl UdevHandlerImpl {
|
||||||
(_, Err(err)) => {
|
(_, Err(err)) => {
|
||||||
// TODO try DumbBuffer allocator in this case
|
// TODO try DumbBuffer allocator in this case
|
||||||
warn!(
|
warn!(
|
||||||
self.logger,
|
self.log,
|
||||||
"Skipping device {:?}, because of gbm error: {}", device_id, err
|
"Skipping device {:?}, because of gbm error: {}", device_id, err
|
||||||
);
|
);
|
||||||
None
|
None
|
||||||
|
@ -437,11 +412,11 @@ impl UdevHandlerImpl {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
let egl = match EGLDisplay::new(&gbm, self.logger.clone()) {
|
let egl = match EGLDisplay::new(&gbm, self.log.clone()) {
|
||||||
Ok(display) => display,
|
Ok(display) => display,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(
|
warn!(
|
||||||
self.logger,
|
self.log,
|
||||||
"Skipping device {:?}, because of egl display error: {}", device_id, err
|
"Skipping device {:?}, because of egl display error: {}", device_id, err
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
@ -449,48 +424,45 @@ impl UdevHandlerImpl {
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
let is_primary = path.canonicalize().ok() == self.primary_gpu;
|
let is_primary = path.canonicalize().ok() == self.backend_data.primary_gpu;
|
||||||
// init hardware acceleration on the primary gpu.
|
// init hardware acceleration on the primary gpu.
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
{
|
{
|
||||||
if is_primary {
|
if is_primary {
|
||||||
info!(
|
info!(self.log, "Initializing EGL Hardware Acceleration via {:?}", path);
|
||||||
self.logger,
|
*self.egl_reader.borrow_mut() = egl.bind_wl_display(&*self.display.borrow()).ok();
|
||||||
"Initializing EGL Hardware Acceleration via {:?}", path
|
|
||||||
);
|
|
||||||
*self.egl_buffer_reader.borrow_mut() = egl.bind_wl_display(&*self.display.borrow()).ok();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let context = match EGLContext::new(&egl, self.logger.clone()) {
|
let context = match EGLContext::new(&egl, self.log.clone()) {
|
||||||
Ok(context) => context,
|
Ok(context) => context,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(
|
warn!(
|
||||||
self.logger,
|
self.log,
|
||||||
"Skipping device {:?}, because of egl context error: {}", device_id, err
|
"Skipping device {:?}, because of egl context error: {}", device_id, err
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let backends = Rc::new(RefCell::new(UdevHandlerImpl::scan_connectors(
|
let backends = Rc::new(RefCell::new(scan_connectors(
|
||||||
&mut device,
|
&mut device,
|
||||||
&gbm,
|
&gbm,
|
||||||
&egl,
|
&egl,
|
||||||
&context,
|
&context,
|
||||||
&mut *self.display.borrow_mut(),
|
&mut *self.display.borrow_mut(),
|
||||||
&mut *self.output_map.borrow_mut(),
|
&mut *self.backend_data.output_map.borrow_mut(),
|
||||||
&self.signaler,
|
&self.backend_data.signaler,
|
||||||
&self.logger,
|
&self.log,
|
||||||
)));
|
)));
|
||||||
|
|
||||||
// we leak this texture (we would need to call `destroy_texture` on Drop of DrmRenderer),
|
// we leak this texture (we would need to call `destroy_texture` on Drop of DrmRenderer),
|
||||||
// but only on shutdown anyway, because we do not support hot-pluggin, so it does not really matter.
|
// but only on shutdown anyway, because we do not support hot-pluggin, so it does not really matter.
|
||||||
let pointer_image = {
|
let pointer_image = {
|
||||||
let context = EGLContext::new_shared(&egl, &context, self.logger.clone()).unwrap();
|
let context = EGLContext::new_shared(&egl, &context, self.log.clone()).unwrap();
|
||||||
let mut renderer = unsafe { Gles2Renderer::new(context, self.logger.clone()).unwrap() };
|
let mut renderer = unsafe { Gles2Renderer::new(context, self.log.clone()).unwrap() };
|
||||||
renderer
|
renderer
|
||||||
.import_bitmap(&self.pointer_image)
|
.import_bitmap(&self.backend_data.pointer_image)
|
||||||
.expect("Failed to load pointer")
|
.expect("Failed to load pointer")
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -501,35 +473,35 @@ impl UdevHandlerImpl {
|
||||||
device_id,
|
device_id,
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
egl_buffer_reader: if is_primary {
|
egl_buffer_reader: if is_primary {
|
||||||
self.egl_buffer_reader.borrow().clone()
|
self.egl_reader.borrow().clone()
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
compositor_token: self.compositor_token,
|
compositor_token: self.ctoken,
|
||||||
backends: backends.clone(),
|
backends: backends.clone(),
|
||||||
window_map: self.window_map.clone(),
|
window_map: self.window_map.clone(),
|
||||||
output_map: self.output_map.clone(),
|
output_map: self.backend_data.output_map.clone(),
|
||||||
pointer_location: self.pointer_location.clone(),
|
pointer_location: self.pointer_location.clone(),
|
||||||
pointer_image,
|
pointer_image,
|
||||||
cursor_status: self.cursor_status.clone(),
|
cursor_status: self.cursor_status.clone(),
|
||||||
dnd_icon: self.dnd_icon.clone(),
|
dnd_icon: self.dnd_icon.clone(),
|
||||||
logger: self.logger.clone(),
|
logger: self.log.clone(),
|
||||||
start_time: std::time::Instant::now(),
|
start_time: std::time::Instant::now(),
|
||||||
});
|
});
|
||||||
let mut listener = DrmRendererSessionListener {
|
let mut listener = DrmRendererSessionListener {
|
||||||
renderer: renderer.clone(),
|
renderer: renderer.clone(),
|
||||||
loop_handle: self.loop_handle.clone(),
|
loop_handle: self.handle.clone(),
|
||||||
};
|
};
|
||||||
let restart_token = self.signaler.register(move |signal| match signal {
|
let restart_token = self.backend_data.signaler.register(move |signal| match signal {
|
||||||
SessionSignal::ActivateSession | SessionSignal::ActivateDevice { .. } => listener.activate(),
|
SessionSignal::ActivateSession | SessionSignal::ActivateDevice { .. } => listener.activate(),
|
||||||
_ => {}
|
_ => {}
|
||||||
});
|
});
|
||||||
let mut drm_handler = DrmHandlerImpl {
|
let mut drm_handler = DrmHandlerImpl {
|
||||||
renderer,
|
renderer,
|
||||||
loop_handle: self.loop_handle.clone(),
|
loop_handle: self.handle.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
device.link(self.signaler.clone());
|
device.link(self.backend_data.signaler.clone());
|
||||||
let dev_id = device.device_id();
|
let dev_id = device.device_id();
|
||||||
let event_dispatcher = Dispatcher::new(device, move |event, _, _| match event {
|
let event_dispatcher = Dispatcher::new(device, move |event, _, _| match event {
|
||||||
DrmEvent::VBlank(crtc) => drm_handler.vblank(crtc),
|
DrmEvent::VBlank(crtc) => drm_handler.vblank(crtc),
|
||||||
|
@ -537,19 +509,16 @@ impl UdevHandlerImpl {
|
||||||
error!(drm_handler.renderer.logger, "{:?}", error);
|
error!(drm_handler.renderer.logger, "{:?}", error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let registration_token = self
|
let registration_token = self.handle.register_dispatcher(event_dispatcher.clone()).unwrap();
|
||||||
.loop_handle
|
|
||||||
.register_dispatcher(event_dispatcher.clone())
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
trace!(self.logger, "Backends: {:?}", backends.borrow().keys());
|
trace!(self.log, "Backends: {:?}", backends.borrow().keys());
|
||||||
for backend in backends.borrow_mut().values() {
|
for backend in backends.borrow_mut().values() {
|
||||||
// render first frame
|
// render first frame
|
||||||
trace!(self.logger, "Scheduling frame");
|
trace!(self.log, "Scheduling frame");
|
||||||
schedule_initial_render(backend.clone(), &self.loop_handle, self.logger.clone());
|
schedule_initial_render(backend.clone(), &self.handle, self.log.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
self.backends.insert(
|
self.backend_data.backends.insert(
|
||||||
dev_id,
|
dev_id,
|
||||||
BackendData {
|
BackendData {
|
||||||
_restart_token: restart_token,
|
_restart_token: restart_token,
|
||||||
|
@ -566,17 +535,17 @@ impl UdevHandlerImpl {
|
||||||
|
|
||||||
fn device_changed(&mut self, device: dev_t) {
|
fn device_changed(&mut self, device: dev_t) {
|
||||||
//quick and dirty, just re-init all backends
|
//quick and dirty, just re-init all backends
|
||||||
if let Some(ref mut backend_data) = self.backends.get_mut(&device) {
|
if let Some(ref mut backend_data) = self.backend_data.backends.get_mut(&device) {
|
||||||
let logger = self.logger.clone();
|
let logger = self.log.clone();
|
||||||
let loop_handle = self.loop_handle.clone();
|
let loop_handle = self.handle.clone();
|
||||||
let mut display = self.display.borrow_mut();
|
let mut display = self.display.borrow_mut();
|
||||||
let mut output_map = self.output_map.borrow_mut();
|
let mut output_map = self.backend_data.output_map.borrow_mut();
|
||||||
let signaler = self.signaler.clone();
|
let signaler = self.backend_data.signaler.clone();
|
||||||
output_map.retain(|output| output.device_id != device);
|
output_map.retain(|output| output.device_id != device);
|
||||||
|
|
||||||
let mut source = backend_data.event_dispatcher.as_source_mut();
|
let mut source = backend_data.event_dispatcher.as_source_mut();
|
||||||
let mut backends = backend_data.surfaces.borrow_mut();
|
let mut backends = backend_data.surfaces.borrow_mut();
|
||||||
*backends = UdevHandlerImpl::scan_connectors(
|
*backends = scan_connectors(
|
||||||
&mut *source,
|
&mut *source,
|
||||||
&backend_data.gbm,
|
&backend_data.gbm,
|
||||||
&backend_data.egl,
|
&backend_data.egl,
|
||||||
|
@ -597,26 +566,29 @@ impl UdevHandlerImpl {
|
||||||
|
|
||||||
fn device_removed(&mut self, device: dev_t) {
|
fn device_removed(&mut self, device: dev_t) {
|
||||||
// drop the backends on this side
|
// drop the backends on this side
|
||||||
if let Some(backend_data) = self.backends.remove(&device) {
|
if let Some(backend_data) = self.backend_data.backends.remove(&device) {
|
||||||
// drop surfaces
|
// drop surfaces
|
||||||
backend_data.surfaces.borrow_mut().clear();
|
backend_data.surfaces.borrow_mut().clear();
|
||||||
debug!(self.logger, "Surfaces dropped");
|
debug!(self.log, "Surfaces dropped");
|
||||||
// clear outputs
|
// clear outputs
|
||||||
self.output_map
|
self.backend_data
|
||||||
|
.output_map
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.retain(|output| output.device_id != device);
|
.retain(|output| output.device_id != device);
|
||||||
|
|
||||||
let _device = self.loop_handle.remove(backend_data.registration_token);
|
let _device = self.handle.remove(backend_data.registration_token);
|
||||||
let _device = backend_data.event_dispatcher.into_source_inner();
|
let _device = backend_data.event_dispatcher.into_source_inner();
|
||||||
|
|
||||||
// don't use hardware acceleration anymore, if this was the primary gpu
|
// don't use hardware acceleration anymore, if this was the primary gpu
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
{
|
{
|
||||||
if _device.dev_path().and_then(|path| path.canonicalize().ok()) == self.primary_gpu {
|
if _device.dev_path().and_then(|path| path.canonicalize().ok())
|
||||||
*self.egl_buffer_reader.borrow_mut() = None;
|
== self.backend_data.primary_gpu
|
||||||
|
{
|
||||||
|
*self.egl_reader.borrow_mut() = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debug!(self.logger, "Dropping device");
|
debug!(self.log, "Dropping device");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,13 @@ use smithay::{
|
||||||
use slog::Logger;
|
use slog::Logger;
|
||||||
|
|
||||||
use crate::drawing::*;
|
use crate::drawing::*;
|
||||||
use crate::state::AnvilState;
|
use crate::state::{AnvilState, Backend};
|
||||||
|
|
||||||
pub struct WinitData;
|
pub struct WinitData;
|
||||||
|
|
||||||
impl Default for WinitData {
|
impl Backend for WinitData {
|
||||||
fn default() -> WinitData {
|
fn seat_name(&self) -> String {
|
||||||
WinitData
|
String::from("winit")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +54,9 @@ pub fn run_winit(
|
||||||
let mut state = AnvilState::init(
|
let mut state = AnvilState::init(
|
||||||
display.clone(),
|
display.clone(),
|
||||||
event_loop.handle(),
|
event_loop.handle(),
|
||||||
|
WinitData,
|
||||||
#[cfg(feature = "egl")]
|
#[cfg(feature = "egl")]
|
||||||
Rc::new(RefCell::new(reader.clone())),
|
Rc::new(RefCell::new(reader.clone())),
|
||||||
None,
|
|
||||||
None,
|
|
||||||
log.clone(),
|
log.clone(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue