anvil: Fuse InputHandler into AnvilState

This commit is contained in:
Victor Berger 2020-05-04 15:04:30 +02:00 committed by Victor Berger
parent 8f543eb597
commit b708f88da6
4 changed files with 95 additions and 168 deletions

View File

@ -1,17 +1,9 @@
use std::{ use std::{process::Command, sync::atomic::Ordering};
cell::RefCell,
process::Command,
rc::Rc,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
};
use slog::Logger; use crate::AnvilState;
#[cfg(feature = "udev")] #[cfg(feature = "udev")]
use smithay::backend::session::{auto::AutoSession, Session}; 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,
@ -19,66 +11,13 @@ use smithay::{
}, },
reexports::wayland_server::protocol::wl_pointer, reexports::wayland_server::protocol::wl_pointer,
wayland::{ wayland::{
seat::{keysyms as xkb, AxisFrame, KeyboardHandle, Keysym, ModifiersState, PointerHandle}, seat::{keysyms as xkb, AxisFrame, Keysym, ModifiersState},
SERIAL_COUNTER as SCOUNTER, SERIAL_COUNTER as SCOUNTER,
}, },
}; };
use crate::shell::MyWindowMap; impl AnvilState {
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
pub struct AnvilInputHandler {
log: Logger,
pointer: PointerHandle,
keyboard: KeyboardHandle,
window_map: Rc<RefCell<MyWindowMap>>,
pointer_location: Rc<RefCell<(f64, f64)>>,
screen_size: (u32, u32),
#[cfg(feature = "udev")]
session: Option<AutoSession>,
running: Arc<AtomicBool>,
}
pub struct InputInitData {
pub pointer: PointerHandle,
pub keyboard: KeyboardHandle,
pub window_map: Rc<RefCell<MyWindowMap>>,
pub screen_size: (u32, u32),
pub running: Arc<AtomicBool>,
pub pointer_location: Rc<RefCell<(f64, f64)>>,
}
impl AnvilInputHandler {
pub fn new(log: Logger, data: InputInitData) -> AnvilInputHandler {
AnvilInputHandler {
log,
pointer: data.pointer,
keyboard: data.keyboard,
window_map: data.window_map,
screen_size: data.screen_size,
running: data.running,
pointer_location: data.pointer_location,
#[cfg(feature = "udev")]
session: None,
}
}
#[cfg(feature = "udev")]
pub fn new_with_session(log: Logger, data: InputInitData, session: AutoSession) -> AnvilInputHandler {
AnvilInputHandler {
log,
pointer: data.pointer,
keyboard: data.keyboard,
window_map: data.window_map,
screen_size: data.screen_size,
running: data.running,
pointer_location: data.pointer_location,
session: Some(session),
}
}
}
impl AnvilInputHandler {
pub fn process_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
match event { match event {
InputEvent::Keyboard { event, .. } => self.on_keyboard_key::<B>(event), InputEvent::Keyboard { event, .. } => self.on_keyboard_key::<B>(event),
InputEvent::PointerMotion { event, .. } => self.on_pointer_move::<B>(event), InputEvent::PointerMotion { event, .. } => self.on_pointer_move::<B>(event),

View File

@ -8,6 +8,7 @@ use std::{
}; };
use smithay::{ use smithay::{
backend::session::auto::AutoSession,
reexports::{ reexports::{
calloop::{ calloop::{
generic::{Fd, Generic}, generic::{Fd, Generic},
@ -17,11 +18,15 @@ use smithay::{
}, },
wayland::{ wayland::{
compositor::CompositorToken, compositor::CompositorToken,
data_device::{default_action_chooser, init_data_device, DataDeviceEvent}, data_device::{default_action_chooser, init_data_device, set_data_device_focus, DataDeviceEvent},
seat::{CursorImageStatus, KeyboardHandle, PointerHandle, Seat, XkbConfig},
shm::init_shm_global, shm::init_shm_global,
}, },
}; };
#[cfg(feature = "udev")]
use smithay::backend::session::Session;
use crate::{buffer_utils::BufferUtils, shell::init_shell}; use crate::{buffer_utils::BufferUtils, shell::init_shell};
pub struct AnvilState { pub struct AnvilState {
@ -33,6 +38,15 @@ pub struct AnvilState {
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>>>,
pub log: slog::Logger, 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>>,
pub screen_size: (u32, u32),
pub seat_name: String,
#[cfg(feature = "udev")]
pub session: Option<AutoSession>,
// things we must keep alive // things we must keep alive
_wayland_event_source: Source<Generic<Fd>>, _wayland_event_source: Source<Generic<Fd>>,
} }
@ -42,6 +56,8 @@ impl AnvilState {
display: Rc<RefCell<Display>>, display: Rc<RefCell<Display>>,
handle: LoopHandle<AnvilState>, handle: LoopHandle<AnvilState>,
buffer_utils: BufferUtils, buffer_utils: BufferUtils,
#[cfg(feature = "udev")] session: Option<AutoSession>,
#[cfg(not(feature = "udev"))] _session: Option<()>,
log: slog::Logger, log: slog::Logger,
) -> AnvilState { ) -> AnvilState {
// init the wayland connection // init the wayland connection
@ -102,6 +118,37 @@ impl AnvilState {
log.clone(), 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"))]
let seat_name = "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();
let pointer = seat.add_pointer(shell_handles.token.clone(), 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");
AnvilState { AnvilState {
running: Arc::new(AtomicBool::new(true)), running: Arc::new(AtomicBool::new(true)),
display, display,
@ -111,6 +158,14 @@ impl AnvilState {
dnd_icon, dnd_icon,
log, log,
socket_name, socket_name,
pointer,
keyboard,
cursor_status,
pointer_location: Rc::new(RefCell::new((0.0, 0.0))),
screen_size: (1920, 1080),
seat_name,
#[cfg(feature = "udev")]
session,
_wayland_event_source, _wayland_event_source,
} }
} }

View File

@ -50,16 +50,14 @@ use smithay::{
}, },
wayland::{ wayland::{
compositor::CompositorToken, compositor::CompositorToken,
data_device::set_data_device_focus,
output::{Mode, Output, PhysicalProperties}, output::{Mode, Output, PhysicalProperties},
seat::{CursorImageStatus, Seat, XkbConfig}, seat::CursorImageStatus,
SERIAL_COUNTER as SCOUNTER, SERIAL_COUNTER as SCOUNTER,
}, },
}; };
use crate::buffer_utils::BufferUtils; use crate::buffer_utils::BufferUtils;
use crate::glium_drawer::GliumDrawer; use crate::glium_drawer::GliumDrawer;
use crate::input_handler::{AnvilInputHandler, InputInitData};
use crate::shell::{MyWindowMap, Roles}; use crate::shell::{MyWindowMap, Roles};
use crate::state::AnvilState; use crate::state::AnvilState;
@ -100,11 +98,6 @@ pub fn run_udev(
#[cfg(not(feature = "egl"))] #[cfg(not(feature = "egl"))]
let buffer_utils = BufferUtils::new(log.clone()); let buffer_utils = BufferUtils::new(log.clone());
/*
* Initialize the compositor
*/
let mut state = AnvilState::init(display.clone(), event_loop.handle(), buffer_utils, log.clone());
/* /*
* Initialize session * Initialize session
*/ */
@ -112,56 +105,43 @@ pub fn run_udev(
let (udev_observer, udev_notifier) = notify_multiplexer(); let (udev_observer, udev_notifier) = notify_multiplexer();
let udev_session_id = notifier.register(udev_observer); let udev_session_id = notifier.register(udev_observer);
let pointer_location = Rc::new(RefCell::new((0.0, 0.0))); /*
let cursor_status = Arc::new(Mutex::new(CursorImageStatus::Default)); * Initialize the compositor
*/
let mut state = AnvilState::init(
display.clone(),
event_loop.handle(),
buffer_utils,
Some(session),
log.clone(),
);
/* /*
* Initialize the udev backend * Initialize the udev backend
*/ */
let seat = session.seat(); let primary_gpu = primary_gpu(&state.seat_name).unwrap_or_default();
let primary_gpu = primary_gpu(&seat).unwrap_or_default();
let bytes = include_bytes!("../resources/cursor2.rgba"); let bytes = include_bytes!("../resources/cursor2.rgba");
let udev_backend = UdevBackend::new(seat.clone(), log.clone()).map_err(|_| ())?; let udev_backend = UdevBackend::new(state.seat_name.clone(), log.clone()).map_err(|_| ())?;
let mut udev_handler = UdevHandlerImpl { let mut udev_handler = UdevHandlerImpl {
compositor_token: state.ctoken, compositor_token: state.ctoken,
#[cfg(feature = "egl")] #[cfg(feature = "egl")]
egl_buffer_reader, egl_buffer_reader,
session: session.clone(), session: state.session.clone().unwrap(),
backends: HashMap::new(), backends: HashMap::new(),
display: display.clone(), display: display.clone(),
primary_gpu, primary_gpu,
window_map: state.window_map.clone(), window_map: state.window_map.clone(),
pointer_location: pointer_location.clone(), pointer_location: state.pointer_location.clone(),
pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(), pointer_image: ImageBuffer::from_raw(64, 64, bytes.to_vec()).unwrap(),
cursor_status: cursor_status.clone(), cursor_status: state.cursor_status.clone(),
dnd_icon: state.dnd_icon.clone(), dnd_icon: state.dnd_icon.clone(),
loop_handle: event_loop.handle(), loop_handle: event_loop.handle(),
notifier: udev_notifier, notifier: udev_notifier,
logger: log.clone(), logger: log.clone(),
}; };
/*
* Initialize wayland input object
*/
let (mut w_seat, _) = Seat::new(
&mut display.borrow_mut(),
session.seat(),
state.ctoken,
log.clone(),
);
let pointer = w_seat.add_pointer(state.ctoken.clone(), move |new_status| {
*cursor_status.lock().unwrap() = new_status;
});
let keyboard = w_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");
/* /*
* 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)
*/ */
@ -197,31 +177,20 @@ pub fn run_udev(
/* /*
* Initialize libinput backend * Initialize libinput backend
*/ */
let mut libinput_context = let mut libinput_context = Libinput::new_with_udev::<LibinputSessionInterface<AutoSession>>(
Libinput::new_with_udev::<LibinputSessionInterface<AutoSession>>(session.clone().into()); state.session.clone().unwrap().into(),
let libinput_session_id = notifier.register(libinput_context.observer());
libinput_context.udev_assign_seat(&seat).unwrap();
let libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
let mut input_handler = AnvilInputHandler::new_with_session(
log.clone(),
InputInitData {
pointer,
keyboard,
window_map: state.window_map.clone(),
screen_size: (w, h),
running: state.running.clone(),
pointer_location,
},
session,
); );
let libinput_session_id = notifier.register(libinput_context.observer());
libinput_context.udev_assign_seat(&state.seat_name).unwrap();
let libinput_backend = LibinputInputBackend::new(libinput_context, log.clone());
/* /*
* Bind all our objects that get driven by the event loop * Bind all our objects that get driven by the event loop
*/ */
let libinput_event_source = event_loop let libinput_event_source = event_loop
.handle() .handle()
.insert_source(libinput_backend, move |event, _, _anvil_state| { .insert_source(libinput_backend, move |event, _, anvil_state| {
input_handler.process_event(event) anvil_state.process_input_event(event)
}) })
.unwrap(); .unwrap();
let session_event_source = auto_session_bind(notifier, event_loop.handle()) let session_event_source = auto_session_bind(notifier, event_loop.handle())

View File

@ -1,9 +1,4 @@
use std::{ use std::{cell::RefCell, rc::Rc, sync::atomic::Ordering, time::Duration};
cell::RefCell,
rc::Rc,
sync::{atomic::Ordering, Arc, Mutex},
time::Duration,
};
use smithay::{ use smithay::{
backend::{egl::EGLGraphicsBackend, graphics::gl::GLGraphicsBackend, input::InputBackend, winit}, backend::{egl::EGLGraphicsBackend, graphics::gl::GLGraphicsBackend, input::InputBackend, winit},
@ -12,9 +7,8 @@ use smithay::{
wayland_server::{protocol::wl_output, Display}, wayland_server::{protocol::wl_output, Display},
}, },
wayland::{ wayland::{
data_device::set_data_device_focus,
output::{Mode, Output, PhysicalProperties}, output::{Mode, Output, PhysicalProperties},
seat::{CursorImageStatus, Seat, XkbConfig}, seat::CursorImageStatus,
SERIAL_COUNTER as SCOUNTER, SERIAL_COUNTER as SCOUNTER,
}, },
}; };
@ -23,7 +17,6 @@ use slog::Logger;
use crate::buffer_utils::BufferUtils; use crate::buffer_utils::BufferUtils;
use crate::glium_drawer::GliumDrawer; use crate::glium_drawer::GliumDrawer;
use crate::input_handler::{AnvilInputHandler, InputInitData};
use crate::state::AnvilState; use crate::state::AnvilState;
pub fn run_winit( pub fn run_winit(
@ -60,29 +53,14 @@ pub fn run_winit(
* Initialize the globals * Initialize the globals
*/ */
let mut state = AnvilState::init(display.clone(), event_loop.handle(), buffer_utils, log.clone()); let mut state = AnvilState::init(
display.clone(),
let (mut seat, _) = Seat::new( event_loop.handle(),
&mut display.borrow_mut(), buffer_utils,
"winit".into(), None,
state.ctoken,
log.clone(), log.clone(),
); );
let cursor_status = Arc::new(Mutex::new(CursorImageStatus::Default));
let cursor_status2 = cursor_status.clone();
let pointer = seat.add_pointer(state.ctoken.clone(), 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");
let (output, _) = Output::new( let (output, _) = Output::new(
&mut display.borrow_mut(), &mut display.borrow_mut(),
"Winit".into(), "Winit".into(),
@ -111,25 +89,11 @@ pub fn run_winit(
refresh: 60_000, refresh: 60_000,
}); });
let pointer_location = Rc::new(RefCell::new((0.0, 0.0)));
let mut input_handler = AnvilInputHandler::new(
log.clone(),
InputInitData {
pointer,
keyboard,
window_map: state.window_map.clone(),
screen_size: (0, 0),
running: state.running.clone(),
pointer_location: pointer_location.clone(),
},
);
info!(log, "Initialization completed, starting the main loop."); info!(log, "Initialization completed, starting the main loop.");
while state.running.load(Ordering::SeqCst) { while state.running.load(Ordering::SeqCst) {
input input
.dispatch_new_events(|event, _| input_handler.process_event(event)) .dispatch_new_events(|event, _| state.process_input_event(event))
.unwrap(); .unwrap();
// drawing logic // drawing logic
@ -141,7 +105,7 @@ pub fn run_winit(
// draw the windows // draw the windows
drawer.draw_windows(&mut frame, &*state.window_map.borrow(), state.ctoken); drawer.draw_windows(&mut frame, &*state.window_map.borrow(), state.ctoken);
let (x, y) = *pointer_location.borrow(); let (x, y) = *state.pointer_location.borrow();
// draw the dnd icon if any // draw the dnd icon if any
{ {
let guard = state.dnd_icon.lock().unwrap(); let guard = state.dnd_icon.lock().unwrap();
@ -153,7 +117,7 @@ pub fn run_winit(
} }
// draw the cursor as relevant // draw the cursor as relevant
{ {
let mut guard = cursor_status.lock().unwrap(); let mut guard = state.cursor_status.lock().unwrap();
// reset the cursor if the surface is no longer alive // reset the cursor if the surface is no longer alive
let mut reset = false; let mut reset = false;
if let CursorImageStatus::Image(ref surface) = *guard { if let CursorImageStatus::Image(ref surface) = *guard {