Files
niri/src/input.rs
T
2023-08-10 14:50:51 +04:00

202 lines
7.8 KiB
Rust

use smithay::backend::input::{
AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event, InputBackend, InputEvent,
KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionEvent,
};
use smithay::input::keyboard::{keysyms, FilterResult};
use smithay::input::pointer::{AxisFrame, ButtonEvent, MotionEvent, RelativeMotionEvent};
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::utils::SERIAL_COUNTER;
use crate::niri::Niri;
enum InputAction {
Quit,
ChangeVt(i32),
}
impl Niri {
pub fn process_input_event<I: InputBackend>(
&mut self,
change_vt: &mut dyn FnMut(i32),
event: InputEvent<I>,
) {
trace!("process_input_event");
match event {
InputEvent::Keyboard { event, .. } => {
let serial = SERIAL_COUNTER.next_serial();
let time = Event::time_msec(&event);
let action = self.seat.get_keyboard().unwrap().input(
self,
event.key_code(),
event.state(),
serial,
time,
|_, _, keysym| match keysym.modified_sym() {
keysyms::KEY_Escape => FilterResult::Intercept(InputAction::Quit),
keysym @ keysyms::KEY_XF86Switch_VT_1..=keysyms::KEY_XF86Switch_VT_12 => {
let vt = (keysym - keysyms::KEY_XF86Switch_VT_1 + 1) as i32;
FilterResult::Intercept(InputAction::ChangeVt(vt))
}
_ => FilterResult::Forward,
},
);
if let Some(action) = action {
match action {
InputAction::Quit => {
info!("quitting because Esc was pressed");
self.stop_signal.stop()
}
InputAction::ChangeVt(vt) => {
(*change_vt)(vt);
}
}
}
}
InputEvent::PointerMotion { event, .. } => {
let serial = SERIAL_COUNTER.next_serial();
let pointer = self.seat.get_pointer().unwrap();
let mut pointer_location = pointer.current_location();
pointer_location += event.delta();
let output = self.space.outputs().next().unwrap();
let output_geo = self.space.output_geometry(output).unwrap();
pointer_location.x = pointer_location.x.clamp(0., output_geo.size.w as f64);
pointer_location.y = pointer_location.y.clamp(0., output_geo.size.h as f64);
let under = self.surface_under(pointer_location);
pointer.motion(
self,
under.clone(),
&MotionEvent {
location: pointer_location,
serial,
time: event.time_msec(),
},
);
pointer.relative_motion(
self,
under,
&RelativeMotionEvent {
delta: event.delta(),
delta_unaccel: event.delta_unaccel(),
utime: event.time(),
},
);
// Redraw to update the cursor position.
self.queue_redraw();
}
InputEvent::PointerMotionAbsolute { event, .. } => {
let output = self.space.outputs().next().unwrap();
let output_geo = self.space.output_geometry(output).unwrap();
let pos = event.position_transformed(output_geo.size) + output_geo.loc.to_f64();
let serial = SERIAL_COUNTER.next_serial();
let pointer = self.seat.get_pointer().unwrap();
let under = self.surface_under(pos);
pointer.motion(
self,
under,
&MotionEvent {
location: pos,
serial,
time: event.time_msec(),
},
);
// Redraw to update the cursor position.
self.queue_redraw();
}
InputEvent::PointerButton { event, .. } => {
let pointer = self.seat.get_pointer().unwrap();
let keyboard = self.seat.get_keyboard().unwrap();
let serial = SERIAL_COUNTER.next_serial();
let button = event.button_code();
let button_state = event.state();
if ButtonState::Pressed == button_state && !pointer.is_grabbed() {
if let Some((window, _loc)) = self
.space
.element_under(pointer.current_location())
.map(|(w, l)| (w.clone(), l))
{
self.space.raise_element(&window, true);
keyboard.set_focus(
self,
Some(window.toplevel().wl_surface().clone()),
serial,
);
self.space.elements().for_each(|window| {
window.toplevel().send_pending_configure();
});
} else {
self.space.elements().for_each(|window| {
window.set_activated(false);
window.toplevel().send_pending_configure();
});
keyboard.set_focus(self, Option::<WlSurface>::None, serial);
}
};
pointer.button(
self,
&ButtonEvent {
button,
state: button_state,
serial,
time: event.time_msec(),
},
);
}
InputEvent::PointerAxis { event, .. } => {
let source = event.source();
let horizontal_amount = event.amount(Axis::Horizontal).unwrap_or_else(|| {
event.amount_discrete(Axis::Horizontal).unwrap_or(0.0) * 3.0
});
let vertical_amount = event
.amount(Axis::Vertical)
.unwrap_or_else(|| event.amount_discrete(Axis::Vertical).unwrap_or(0.0) * 3.0);
let horizontal_amount_discrete = event.amount_discrete(Axis::Horizontal);
let vertical_amount_discrete = event.amount_discrete(Axis::Vertical);
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(discrete) = horizontal_amount_discrete {
frame = frame.discrete(Axis::Horizontal, discrete as i32);
}
} else if source == AxisSource::Finger {
frame = frame.stop(Axis::Horizontal);
}
if vertical_amount != 0.0 {
frame = frame.value(Axis::Vertical, vertical_amount);
if let Some(discrete) = vertical_amount_discrete {
frame = frame.discrete(Axis::Vertical, discrete as i32);
}
} else if source == AxisSource::Finger {
frame = frame.stop(Axis::Vertical);
}
self.seat.get_pointer().unwrap().axis(self, frame);
}
_ => {}
}
}
}