2020-04-21 16:56:59 +00:00
|
|
|
use std::{
|
|
|
|
cell::RefCell,
|
|
|
|
rc::Rc,
|
|
|
|
sync::{
|
|
|
|
atomic::{AtomicBool, Ordering},
|
|
|
|
Arc, Mutex,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
use smithay::{
|
|
|
|
reexports::{
|
2021-06-29 22:34:47 +00:00
|
|
|
calloop::{generic::Generic, Interest, LoopHandle, Mode, PostAction},
|
2020-04-21 16:56:59 +00:00
|
|
|
wayland_server::{protocol::wl_surface::WlSurface, Display},
|
|
|
|
},
|
2021-07-05 17:21:15 +00:00
|
|
|
utils::{Logical, Point},
|
2020-04-21 16:56:59 +00:00
|
|
|
wayland::{
|
2020-05-04 13:04:30 +00:00
|
|
|
data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent},
|
2021-07-20 02:01:47 +00:00
|
|
|
output::xdg::init_xdg_output_manager,
|
2020-05-04 13:04:30 +00:00
|
|
|
seat::{CursorImageStatus, KeyboardHandle, PointerHandle, Seat, XkbConfig},
|
2020-04-21 16:56:59 +00:00
|
|
|
shm::init_shm_global,
|
2021-06-30 14:58:59 +00:00
|
|
|
tablet_manager::{init_tablet_manager_global, TabletSeatTrait},
|
2020-04-21 16:56:59 +00:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2021-01-03 15:21:22 +00:00
|
|
|
#[cfg(feature = "xwayland")]
|
2021-06-07 17:04:15 +00:00
|
|
|
use smithay::xwayland::{XWayland, XWaylandEvent};
|
2020-05-04 13:04:30 +00:00
|
|
|
|
2021-05-15 16:17:43 +00:00
|
|
|
use crate::shell::init_shell;
|
2020-04-21 16:56:59 +00:00
|
|
|
|
2021-05-30 22:56:37 +00:00
|
|
|
pub struct AnvilState<BackendData> {
|
|
|
|
pub backend_data: BackendData,
|
2020-04-21 16:56:59 +00:00
|
|
|
pub socket_name: String,
|
|
|
|
pub running: Arc<AtomicBool>,
|
|
|
|
pub display: Rc<RefCell<Display>>,
|
2021-05-30 22:56:37 +00:00
|
|
|
pub handle: LoopHandle<'static, AnvilState<BackendData>>,
|
2021-06-23 07:43:53 +00:00
|
|
|
pub window_map: Rc<RefCell<crate::window_map::WindowMap>>,
|
2021-06-21 19:29:40 +00:00
|
|
|
pub output_map: Rc<RefCell<crate::output_map::OutputMap>>,
|
2020-04-21 16:56:59 +00:00
|
|
|
pub dnd_icon: Arc<Mutex<Option<WlSurface>>>,
|
|
|
|
pub log: slog::Logger,
|
2020-05-04 13:04:30 +00:00
|
|
|
// input-related fields
|
|
|
|
pub pointer: PointerHandle,
|
|
|
|
pub keyboard: KeyboardHandle,
|
2021-06-19 17:32:22 +00:00
|
|
|
pub suppressed_keys: Vec<u32>,
|
2021-07-05 17:21:15 +00:00
|
|
|
pub pointer_location: Point<f64, Logical>,
|
2020-05-04 13:04:30 +00:00
|
|
|
pub cursor_status: Arc<Mutex<CursorImageStatus>>,
|
|
|
|
pub seat_name: String,
|
2021-06-30 14:58:59 +00:00
|
|
|
pub seat: Seat,
|
2021-05-31 18:46:08 +00:00
|
|
|
pub start_time: std::time::Instant,
|
2021-06-10 16:13:20 +00:00
|
|
|
// things we must keep alive
|
2021-01-03 15:21:22 +00:00
|
|
|
#[cfg(feature = "xwayland")]
|
2021-06-07 17:04:15 +00:00
|
|
|
pub xwayland: XWayland<AnvilState<BackendData>>,
|
2020-04-21 16:56:59 +00:00
|
|
|
}
|
|
|
|
|
2021-05-30 22:56:37 +00:00
|
|
|
impl<BackendData: Backend + 'static> AnvilState<BackendData> {
|
2020-04-21 16:56:59 +00:00
|
|
|
pub fn init(
|
|
|
|
display: Rc<RefCell<Display>>,
|
2021-05-30 22:56:37 +00:00
|
|
|
handle: LoopHandle<'static, AnvilState<BackendData>>,
|
|
|
|
backend_data: BackendData,
|
2020-04-21 16:56:59 +00:00
|
|
|
log: slog::Logger,
|
2021-05-30 22:56:37 +00:00
|
|
|
) -> AnvilState<BackendData> {
|
2020-04-21 16:56:59 +00:00
|
|
|
// init the wayland connection
|
2021-05-30 22:56:37 +00:00
|
|
|
handle
|
2020-04-21 16:56:59 +00:00
|
|
|
.insert_source(
|
2021-05-30 20:01:36 +00:00
|
|
|
Generic::from_fd(display.borrow().get_poll_fd(), Interest::READ, Mode::Level),
|
2021-05-30 22:56:37 +00:00
|
|
|
move |_, _, state: &mut AnvilState<BackendData>| {
|
|
|
|
let display = state.display.clone();
|
|
|
|
let mut display = display.borrow_mut();
|
|
|
|
match display.dispatch(std::time::Duration::from_millis(0), state) {
|
2021-06-29 22:34:47 +00:00
|
|
|
Ok(_) => Ok(PostAction::Continue),
|
2021-05-30 22:56:37 +00:00
|
|
|
Err(e) => {
|
|
|
|
error!(state.log, "I/O error on the Wayland display: {}", e);
|
|
|
|
state.running.store(false, Ordering::SeqCst);
|
|
|
|
Err(e)
|
2020-04-21 16:56:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.expect("Failed to init the wayland event source.");
|
|
|
|
|
2020-04-21 17:42:03 +00:00
|
|
|
// Init the basic compositor globals
|
|
|
|
|
2021-05-30 22:56:37 +00:00
|
|
|
init_shm_global(&mut (*display).borrow_mut(), vec![], log.clone());
|
2020-04-21 16:56:59 +00:00
|
|
|
|
2021-06-21 19:29:40 +00:00
|
|
|
let shell_handles = init_shell::<BackendData>(display.clone(), log.clone());
|
2020-04-21 16:56:59 +00:00
|
|
|
|
2021-07-20 02:01:47 +00:00
|
|
|
init_xdg_output_manager(&mut display.borrow_mut(), log.clone());
|
|
|
|
|
2020-04-21 16:56:59 +00:00
|
|
|
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);
|
|
|
|
|
2020-04-21 17:42:03 +00:00
|
|
|
// init data device
|
|
|
|
|
2020-04-21 16:56:59 +00:00
|
|
|
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,
|
|
|
|
log.clone(),
|
|
|
|
);
|
|
|
|
|
2020-05-04 13:04:30 +00:00
|
|
|
// init input
|
2021-05-30 22:56:37 +00:00
|
|
|
let seat_name = backend_data.seat_name();
|
2020-05-04 13:04:30 +00:00
|
|
|
|
2021-06-23 07:43:53 +00:00
|
|
|
let (mut seat, _) = Seat::new(&mut display.borrow_mut(), seat_name.clone(), log.clone());
|
2020-05-04 13:04:30 +00:00
|
|
|
|
|
|
|
let cursor_status = Arc::new(Mutex::new(CursorImageStatus::Default));
|
|
|
|
|
|
|
|
let cursor_status2 = cursor_status.clone();
|
2021-06-23 07:43:53 +00:00
|
|
|
let pointer = seat.add_pointer(move |new_status| {
|
2020-05-04 13:04:30 +00:00
|
|
|
// TODO: hide winit system cursor when relevant
|
|
|
|
*cursor_status2.lock().unwrap() = new_status
|
|
|
|
});
|
|
|
|
|
2021-06-30 14:58:59 +00:00
|
|
|
init_tablet_manager_global(&mut display.borrow_mut());
|
|
|
|
|
|
|
|
let cursor_status3 = cursor_status.clone();
|
|
|
|
seat.tablet_seat().on_cursor_surface(move |_tool, new_status| {
|
|
|
|
// TODO: tablet tools should have their own cursors
|
|
|
|
*cursor_status3.lock().unwrap() = new_status;
|
|
|
|
});
|
|
|
|
|
2020-05-04 13:04:30 +00:00
|
|
|
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");
|
|
|
|
|
2021-01-03 15:21:22 +00:00
|
|
|
#[cfg(feature = "xwayland")]
|
2021-06-07 17:04:15 +00:00
|
|
|
let xwayland = {
|
|
|
|
let (xwayland, channel) = XWayland::new(handle.clone(), display.clone(), log.clone());
|
|
|
|
let ret = handle.insert_source(channel, |event, _, anvil_state| match event {
|
|
|
|
XWaylandEvent::Ready { connection, client } => anvil_state.xwayland_ready(connection, client),
|
|
|
|
XWaylandEvent::Exited => anvil_state.xwayland_exited(),
|
|
|
|
});
|
|
|
|
if let Err(e) = ret {
|
|
|
|
error!(
|
|
|
|
log,
|
|
|
|
"Failed to insert the XWaylandSource into the event loop: {}", e
|
|
|
|
);
|
|
|
|
}
|
|
|
|
xwayland
|
2021-01-03 15:21:22 +00:00
|
|
|
};
|
|
|
|
|
2020-04-21 16:56:59 +00:00
|
|
|
AnvilState {
|
2021-05-30 22:56:37 +00:00
|
|
|
backend_data,
|
2020-04-21 16:56:59 +00:00
|
|
|
running: Arc::new(AtomicBool::new(true)),
|
|
|
|
display,
|
|
|
|
handle,
|
2020-05-02 10:42:02 +00:00
|
|
|
window_map: shell_handles.window_map,
|
2021-06-21 19:29:40 +00:00
|
|
|
output_map: shell_handles.output_map,
|
2020-04-21 16:56:59 +00:00
|
|
|
dnd_icon,
|
|
|
|
log,
|
|
|
|
socket_name,
|
2020-05-04 13:04:30 +00:00
|
|
|
pointer,
|
|
|
|
keyboard,
|
2021-06-19 17:32:22 +00:00
|
|
|
suppressed_keys: Vec::new(),
|
2020-05-04 13:04:30 +00:00
|
|
|
cursor_status,
|
2021-07-05 17:21:15 +00:00
|
|
|
pointer_location: (0.0, 0.0).into(),
|
2020-05-04 13:04:30 +00:00
|
|
|
seat_name,
|
2021-06-30 14:58:59 +00:00
|
|
|
seat,
|
2021-05-31 18:46:08 +00:00
|
|
|
start_time: std::time::Instant::now(),
|
2021-01-03 15:21:22 +00:00
|
|
|
#[cfg(feature = "xwayland")]
|
2021-06-07 17:04:15 +00:00
|
|
|
xwayland,
|
2020-04-21 16:56:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-05-30 22:56:37 +00:00
|
|
|
|
|
|
|
pub trait Backend {
|
|
|
|
fn seat_name(&self) -> String;
|
|
|
|
}
|