mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +07:00
202 lines
7.8 KiB
Rust
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);
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|