smithay/anvil/src/state.rs

201 lines
6.8 KiB
Rust
Raw Normal View History

use std::{
cell::RefCell,
rc::Rc,
sync::{
atomic::{AtomicBool, Ordering},
Arc, Mutex,
},
};
use smithay::{
reexports::{
calloop::{generic::Generic, Interest, LoopHandle, Mode, RegistrationToken},
wayland_server::{protocol::wl_surface::WlSurface, Display},
},
wayland::{
compositor::CompositorToken,
data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent},
seat::{CursorImageStatus, KeyboardHandle, PointerHandle, Seat, XkbConfig},
shm::init_shm_global,
},
};
2021-05-15 16:17:43 +00:00
#[cfg(feature = "egl")]
use smithay::backend::egl::display::EGLBufferReader;
#[cfg(feature = "udev")]
2020-06-27 22:07:48 +00:00
use smithay::backend::session::{auto::AutoSession, Session};
#[cfg(feature = "xwayland")]
use smithay::xwayland::XWayland;
2021-05-15 16:17:43 +00:00
use crate::shell::init_shell;
2020-06-27 16:27:47 +00:00
#[cfg(feature = "udev")]
use crate::udev::MyOutput;
#[cfg(feature = "xwayland")]
use crate::xwayland::XWm;
pub struct AnvilState<Backend> {
pub backend: Backend,
pub socket_name: String,
pub running: Arc<AtomicBool>,
pub display: Rc<RefCell<Display>>,
pub handle: LoopHandle<'static, AnvilState<Backend>>,
pub ctoken: CompositorToken<crate::shell::Roles>,
pub window_map: Rc<RefCell<crate::window_map::WindowMap<crate::shell::Roles>>>,
pub dnd_icon: Arc<Mutex<Option<WlSurface>>>,
pub log: slog::Logger,
// input-related fields
pub pointer: PointerHandle,
pub keyboard: KeyboardHandle,
pub pointer_location: Rc<RefCell<(f64, f64)>>,
pub cursor_status: Arc<Mutex<CursorImageStatus>>,
#[cfg(feature = "udev")]
pub output_map: Option<Rc<RefCell<Vec<MyOutput>>>>,
pub seat_name: String,
#[cfg(feature = "udev")]
pub session: Option<AutoSession>,
// things we must keep alive
_wayland_event_source: RegistrationToken,
#[cfg(feature = "xwayland")]
_xwayland: XWayland<XWm<Backend>>,
}
impl<Backend: Default + 'static> AnvilState<Backend> {
pub fn init(
display: Rc<RefCell<Display>>,
handle: LoopHandle<'static, AnvilState<Backend>>,
2021-05-13 17:59:47 +00:00
#[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,
) -> AnvilState<Backend> {
// init the wayland connection
let _wayland_event_source = handle
.insert_source(
Generic::from_fd(display.borrow().get_poll_fd(), Interest::READ, Mode::Level),
{
let display = display.clone();
let log = log.clone();
move |_, _, state: &mut AnvilState<Backend>| {
let mut display = display.borrow_mut();
match display.dispatch(std::time::Duration::from_millis(0), state) {
2020-04-25 17:10:02 +00:00
Ok(_) => Ok(()),
Err(e) => {
error!(log, "I/O error on the Wayland display: {}", e);
state.running.store(false, Ordering::SeqCst);
2020-04-25 17:10:02 +00:00
Err(e)
}
}
}
},
)
.expect("Failed to init the wayland event source.");
// Init the basic compositor globals
init_shm_global(&mut display.borrow_mut(), vec![], log.clone());
2021-05-13 17:59:47 +00:00
#[cfg(feature = "egl")]
let shell_handles = init_shell::<Backend>(&mut display.borrow_mut(), egl_reader, log.clone());
2021-05-13 17:59:47 +00:00
#[cfg(not(feature = "egl"))]
let shell_handles = init_shell(&mut display.borrow_mut(), log.clone());
let socket_name = display
.borrow_mut()
.add_socket_auto()
.unwrap()
.into_string()
.unwrap();
info!(log, "Listening on wayland socket"; "name" => socket_name.clone());
::std::env::set_var("WAYLAND_DISPLAY", &socket_name);
// init data device
let dnd_icon = Arc::new(Mutex::new(None));
let dnd_icon2 = dnd_icon.clone();
init_data_device(
&mut display.borrow_mut(),
move |event| match event {
DataDeviceEvent::DnDStarted { icon, .. } => {
*dnd_icon2.lock().unwrap() = icon;
}
DataDeviceEvent::DnDDropped => {
*dnd_icon2.lock().unwrap() = None;
}
_ => {}
},
default_action_chooser,
shell_handles.token,
log.clone(),
);
// init input
#[cfg(feature = "udev")]
let seat_name = if let Some(ref session) = session {
session.seat()
} else {
"anvil".into()
};
#[cfg(not(feature = "udev"))]
2020-06-27 16:27:47 +00:00
let seat_name: String = "anvil".into();
let (mut seat, _) = Seat::new(
&mut display.borrow_mut(),
seat_name.clone(),
shell_handles.token,
log.clone(),
);
let cursor_status = Arc::new(Mutex::new(CursorImageStatus::Default));
let cursor_status2 = cursor_status.clone();
2020-06-07 13:29:37 +00:00
let pointer = seat.add_pointer(shell_handles.token, move |new_status| {
// TODO: hide winit system cursor when relevant
*cursor_status2.lock().unwrap() = new_status
});
let keyboard = seat
.add_keyboard(XkbConfig::default(), 200, 25, |seat, focus| {
set_data_device_focus(seat, focus.and_then(|s| s.as_ref().client()))
})
.expect("Failed to initialize the keyboard");
#[cfg(feature = "xwayland")]
let _xwayland = {
let xwm = XWm::new(
handle.clone(),
shell_handles.token,
shell_handles.window_map.clone(),
log.clone(),
);
XWayland::init(xwm, handle.clone(), display.clone(), &mut (), log.clone()).unwrap()
};
AnvilState {
backend: Default::default(),
running: Arc::new(AtomicBool::new(true)),
display,
handle,
ctoken: shell_handles.token,
window_map: shell_handles.window_map,
dnd_icon,
log,
socket_name,
pointer,
keyboard,
cursor_status,
pointer_location: Rc::new(RefCell::new((0.0, 0.0))),
#[cfg(feature = "udev")]
output_map,
seat_name,
#[cfg(feature = "udev")]
session,
_wayland_event_source,
#[cfg(feature = "xwayland")]
_xwayland,
}
}
}