diff --git a/crates/wrsrvd/src/main.rs b/crates/wrsrvd/src/main.rs index 5a63215..e5f855e 100644 --- a/crates/wrsrvd/src/main.rs +++ b/crates/wrsrvd/src/main.rs @@ -128,8 +128,8 @@ fn main() -> Result<()> { WinitEvent::Focus(focused) => { info!(focused, "window focus changed"); } - WinitEvent::Input(_event) => { - // Input handling is Task 7 -- ignore for now. + WinitEvent::Input(event) => { + data.state.process_input_event(event); } WinitEvent::Redraw => { render::render_output_frame( diff --git a/crates/wrsrvd/src/state.rs b/crates/wrsrvd/src/state.rs index 3bb1596..ef3e2ec 100644 --- a/crates/wrsrvd/src/state.rs +++ b/crates/wrsrvd/src/state.rs @@ -1,9 +1,19 @@ use smithay::{ - desktop::Space, - input::{Seat, SeatState}, + backend::input::{ + AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event as InputEventTrait, + InputBackend, InputEvent, KeyboardKeyEvent, + PointerAxisEvent as JsonPointerAxisEvent, + PointerButtonEvent as JsonPointerButtonEvent, + }, + desktop::{Space, WindowSurfaceType}, + input::{ + Seat, SeatState, + keyboard::FilterResult, + pointer::{AxisFrame, ButtonEvent, MotionEvent}, + }, output::Output, reexports::wayland_server::{Display, DisplayHandle}, - utils::{Clock, Monotonic}, + utils::{Clock, Monotonic, SERIAL_COUNTER}, wayland::{ compositor::CompositorState, output::OutputManagerState, @@ -43,7 +53,11 @@ impl WayRay { let data_device_state = DataDeviceState::new::(&dh); let mut seat_state = SeatState::new(); - let seat = seat_state.new_wl_seat(&dh, "wayray"); + let mut seat = seat_state.new_wl_seat(&dh, "wayray"); + + seat.add_keyboard(Default::default(), 200, 25) + .expect("failed to add keyboard to seat"); + seat.add_pointer(); let output_manager_state = OutputManagerState::new_with_xdg_output::(&dh); @@ -63,4 +77,116 @@ impl WayRay { output, } } + + /// Process an input event from the backend and forward it to the appropriate + /// Smithay seat device (keyboard or pointer). + pub fn process_input_event(&mut self, event: InputEvent) { + match event { + InputEvent::Keyboard { event } => { + let serial = SERIAL_COUNTER.next_serial(); + let keyboard = self.seat.get_keyboard().unwrap(); + keyboard.input::<(), _>( + self, + event.key_code(), + event.state(), + serial, + event.time_msec(), + |_, _, _| FilterResult::Forward, + ); + } + InputEvent::PointerMotionAbsolute { event } => { + let output_size = self.output.current_mode().unwrap().size; + let pos = event.position_transformed(output_size.to_logical(1)); + + let serial = SERIAL_COUNTER.next_serial(); + let pointer = self.seat.get_pointer().unwrap(); + + // Find the element (window) under the pointer and get its surface. + let under = self.space.element_under(pos).and_then(|(window, loc)| { + window + .surface_under(pos - loc.to_f64(), WindowSurfaceType::ALL) + .map(|(surface, surf_loc)| (surface, (surf_loc + loc).to_f64())) + }); + + pointer.motion( + self, + under, + &MotionEvent { + location: pos, + serial, + time: event.time_msec(), + }, + ); + pointer.frame(self); + } + InputEvent::PointerButton { event } => { + let serial = SERIAL_COUNTER.next_serial(); + let pointer = self.seat.get_pointer().unwrap(); + + // On button press, focus the window under the pointer. + if event.state() == ButtonState::Pressed { + let pos = pointer.current_location(); + if let Some((window, _loc)) = self.space.element_under(pos) { + let window = window.clone(); + self.space.raise_element(&window, true); + + let keyboard = self.seat.get_keyboard().unwrap(); + let wl_surface = window.toplevel().map(|t| t.wl_surface().clone()); + keyboard.set_focus(self, wl_surface, serial); + } + } + + pointer.button( + self, + &ButtonEvent { + serial, + time: event.time_msec(), + button: event.button_code(), + state: event.state(), + }, + ); + pointer.frame(self); + } + InputEvent::PointerAxis { event } => { + let pointer = self.seat.get_pointer().unwrap(); + + let source = event.source(); + + let horizontal_amount = event + .amount(Axis::Horizontal) + .unwrap_or_else(|| event.amount_v120(Axis::Horizontal).unwrap_or(0.0) * 3.0 / 120.0); + let vertical_amount = event + .amount(Axis::Vertical) + .unwrap_or_else(|| event.amount_v120(Axis::Vertical).unwrap_or(0.0) * 3.0 / 120.0); + + let mut frame = AxisFrame::new(event.time_msec()).source(source); + + if horizontal_amount != 0.0 { + frame = frame.value(Axis::Horizontal, horizontal_amount); + if let Some(v120) = event.amount_v120(Axis::Horizontal) { + frame = frame.v120(Axis::Horizontal, v120 as i32); + } + } + if vertical_amount != 0.0 { + frame = frame.value(Axis::Vertical, vertical_amount); + if let Some(v120) = event.amount_v120(Axis::Vertical) { + frame = frame.v120(Axis::Vertical, v120 as i32); + } + } + + if source == AxisSource::Finger { + if horizontal_amount == 0.0 { + frame = frame.stop(Axis::Horizontal); + } + if vertical_amount == 0.0 { + frame = frame.stop(Axis::Vertical); + } + } + + pointer.axis(self, frame); + pointer.frame(self); + } + _ => {} // Ignore other events + } + } }