2023-08-01 18:06:35 +02:00
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
2023-06-26 00:18:50 +02:00
|
|
|
|
2023-06-15 23:43:33 +02:00
|
|
|
use std::collections::HashMap;
|
|
|
|
|
2023-07-25 01:59:05 +02:00
|
|
|
use crate::{
|
|
|
|
api::msg::{CallbackId, Modifier, ModifierMask, OutgoingMsg},
|
2023-07-28 18:11:35 +02:00
|
|
|
focus::FocusTarget,
|
2023-07-25 01:59:05 +02:00
|
|
|
window::WindowElement,
|
|
|
|
};
|
2023-06-02 19:26:33 +02:00
|
|
|
use smithay::{
|
|
|
|
backend::input::{
|
|
|
|
AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event, InputBackend, InputEvent,
|
2023-06-10 03:29:17 +02:00
|
|
|
KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionEvent,
|
2023-06-02 19:26:33 +02:00
|
|
|
},
|
2023-07-28 22:16:25 +02:00
|
|
|
desktop::space::SpaceElement,
|
2023-06-02 19:26:33 +02:00
|
|
|
input::{
|
|
|
|
keyboard::{keysyms, FilterResult},
|
2023-08-01 17:53:37 +02:00
|
|
|
pointer::{AxisFrame, ButtonEvent, MotionEvent, PointerTarget},
|
2023-06-02 19:26:33 +02:00
|
|
|
},
|
|
|
|
reexports::wayland_protocols::xdg::shell::server::xdg_toplevel::ResizeEdge,
|
2023-06-10 03:29:17 +02:00
|
|
|
utils::{Logical, Point, SERIAL_COUNTER},
|
2023-07-28 22:16:25 +02:00
|
|
|
wayland::{compositor, seat::WaylandFocus},
|
2023-06-02 19:26:33 +02:00
|
|
|
};
|
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
use crate::{
|
|
|
|
backend::{udev::UdevData, winit::WinitData, Backend},
|
|
|
|
state::State,
|
|
|
|
};
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-06-18 04:02:58 +02:00
|
|
|
#[derive(Default)]
|
2023-06-15 23:43:33 +02:00
|
|
|
pub struct InputState {
|
2023-06-18 04:02:58 +02:00
|
|
|
/// A hashmap of modifier keys and keycodes to callback IDs
|
2023-06-25 00:39:40 +02:00
|
|
|
pub keybinds: HashMap<(ModifierMask, u32), CallbackId>,
|
2023-06-18 04:02:58 +02:00
|
|
|
/// A hashmap of modifier keys and mouse button codes to callback IDs
|
2023-06-25 00:39:40 +02:00
|
|
|
pub mousebinds: HashMap<(ModifierMask, u32), CallbackId>,
|
2023-06-18 04:02:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl InputState {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Default::default()
|
|
|
|
}
|
2023-06-15 23:43:33 +02:00
|
|
|
}
|
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
impl<B: Backend> State<B> {
|
2023-07-28 22:16:25 +02:00
|
|
|
pub fn surface_under<P>(&self, point: P) -> Option<(FocusTarget, Point<i32, Logical>)>
|
2023-06-12 00:56:34 +02:00
|
|
|
where
|
|
|
|
P: Into<Point<f64, Logical>>,
|
|
|
|
{
|
|
|
|
// TODO: layer map, popups, fullscreen
|
|
|
|
self.space
|
|
|
|
.element_under(point)
|
2023-07-28 22:16:25 +02:00
|
|
|
.map(|(window, loc)| (window.clone().into(), loc))
|
2023-06-12 00:56:34 +02:00
|
|
|
}
|
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
fn pointer_button<I: InputBackend>(&mut self, event: I::PointerButtonEvent) {
|
2023-06-30 00:41:08 +02:00
|
|
|
let pointer = self.seat.get_pointer().expect("Seat has no pointer"); // FIXME: handle err
|
|
|
|
let keyboard = self.seat.get_keyboard().expect("Seat has no keyboard"); // FIXME: handle err
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
// A serial is a number sent with a event that is sent back to the
|
|
|
|
// server by the clients in further requests. This allows the server to
|
|
|
|
// keep track of which event caused which requests. It is an AtomicU32
|
|
|
|
// that increments when next_serial is called.
|
|
|
|
let serial = SERIAL_COUNTER.next_serial();
|
|
|
|
|
|
|
|
// Returns which button on the pointer was used.
|
|
|
|
let button = event.button_code();
|
|
|
|
|
|
|
|
// The state, either released or pressed.
|
|
|
|
let button_state = event.state();
|
|
|
|
|
|
|
|
let pointer_loc = pointer.current_location();
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
// If the button was clicked, focus on the window below if exists, else
|
|
|
|
// unfocus on windows.
|
|
|
|
if ButtonState::Pressed == button_state {
|
2023-06-12 00:56:34 +02:00
|
|
|
if let Some((window, window_loc)) = self.surface_under(pointer_loc) {
|
2023-07-29 04:38:12 +02:00
|
|
|
// tracing::debug!("button click on {window:?}");
|
2023-06-10 03:29:17 +02:00
|
|
|
const BUTTON_LEFT: u32 = 0x110;
|
|
|
|
const BUTTON_RIGHT: u32 = 0x111;
|
|
|
|
if self.move_mode {
|
|
|
|
if event.button_code() == BUTTON_LEFT {
|
2023-07-25 01:59:05 +02:00
|
|
|
if let Some(wl_surf) = window.wl_surface() {
|
2023-07-28 21:33:14 +02:00
|
|
|
crate::grab::move_grab::move_request_server(
|
2023-07-25 01:59:05 +02:00
|
|
|
self,
|
|
|
|
&wl_surf,
|
|
|
|
&self.seat.clone(),
|
|
|
|
serial,
|
2023-08-02 20:16:17 +02:00
|
|
|
BUTTON_LEFT,
|
2023-07-25 01:59:05 +02:00
|
|
|
);
|
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
return; // TODO: kinda ugly return here
|
|
|
|
} else if event.button_code() == BUTTON_RIGHT {
|
2023-07-28 22:16:25 +02:00
|
|
|
let FocusTarget::Window(window) = window else { return };
|
2023-06-10 03:29:17 +02:00
|
|
|
let window_geometry = window.geometry();
|
|
|
|
let window_x = window_loc.x as f64;
|
|
|
|
let window_y = window_loc.y as f64;
|
|
|
|
let window_width = window_geometry.size.w as f64;
|
|
|
|
let window_height = window_geometry.size.h as f64;
|
|
|
|
let half_width = window_x + window_width / 2.0;
|
|
|
|
let half_height = window_y + window_height / 2.0;
|
|
|
|
let full_width = window_x + window_width;
|
|
|
|
let full_height = window_y + window_height;
|
|
|
|
|
|
|
|
let edges = match pointer_loc {
|
|
|
|
Point { x, y, .. }
|
|
|
|
if (window_x..=half_width).contains(&x)
|
|
|
|
&& (window_y..=half_height).contains(&y) =>
|
|
|
|
{
|
|
|
|
ResizeEdge::TopLeft
|
2023-06-02 19:26:33 +02:00
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
Point { x, y, .. }
|
|
|
|
if (half_width..=full_width).contains(&x)
|
|
|
|
&& (window_y..=half_height).contains(&y) =>
|
|
|
|
{
|
|
|
|
ResizeEdge::TopRight
|
2023-06-02 19:26:33 +02:00
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
Point { x, y, .. }
|
|
|
|
if (window_x..=half_width).contains(&x)
|
|
|
|
&& (half_height..=full_height).contains(&y) =>
|
|
|
|
{
|
|
|
|
ResizeEdge::BottomLeft
|
|
|
|
}
|
|
|
|
Point { x, y, .. }
|
|
|
|
if (half_width..=full_width).contains(&x)
|
|
|
|
&& (half_height..=full_height).contains(&y) =>
|
|
|
|
{
|
|
|
|
ResizeEdge::BottomRight
|
|
|
|
}
|
|
|
|
_ => ResizeEdge::None,
|
|
|
|
};
|
|
|
|
|
2023-07-25 01:59:05 +02:00
|
|
|
if let Some(wl_surf) = window.wl_surface() {
|
2023-07-28 21:33:14 +02:00
|
|
|
crate::grab::resize_grab::resize_request_server(
|
2023-07-25 01:59:05 +02:00
|
|
|
self,
|
|
|
|
&wl_surf,
|
|
|
|
&self.seat.clone(),
|
|
|
|
serial,
|
2023-08-02 20:16:17 +02:00
|
|
|
edges.into(),
|
2023-07-25 01:59:05 +02:00
|
|
|
BUTTON_RIGHT,
|
|
|
|
);
|
|
|
|
}
|
2023-06-02 19:26:33 +02:00
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
} else {
|
|
|
|
// Move window to top of stack.
|
2023-07-28 22:16:25 +02:00
|
|
|
let FocusTarget::Window(window) = window else { return };
|
2023-06-10 03:29:17 +02:00
|
|
|
self.space.raise_element(&window, true);
|
2023-07-25 01:59:05 +02:00
|
|
|
if let WindowElement::X11(surface) = &window {
|
2023-07-29 04:38:12 +02:00
|
|
|
if !surface.is_override_redirect() {
|
|
|
|
self.xwm
|
|
|
|
.as_mut()
|
|
|
|
.expect("no xwm")
|
|
|
|
.raise_window(surface)
|
|
|
|
.expect("failed to raise x11 win");
|
|
|
|
surface
|
|
|
|
.set_activated(true)
|
|
|
|
.expect("failed to set x11 win to activated");
|
|
|
|
}
|
2023-07-25 01:59:05 +02:00
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
|
2023-07-28 18:11:35 +02:00
|
|
|
tracing::debug!(
|
|
|
|
"wl_surface focus is some? {}",
|
|
|
|
window.wl_surface().is_some()
|
|
|
|
);
|
2023-07-29 04:38:12 +02:00
|
|
|
|
|
|
|
// NOTE: *Do not* set keyboard focus to an override redirect window. This leads
|
|
|
|
// | to wonky things like right-click menus not correctly getting pointer
|
|
|
|
// | clicks or showing up at all.
|
2023-08-01 17:53:37 +02:00
|
|
|
|
|
|
|
// TODO: TOMORROW: Firefox needs 2 clicks to open up right-click menu, first
|
|
|
|
// | one immediately dissapears
|
|
|
|
|
2023-07-29 04:38:12 +02:00
|
|
|
if !matches!(&window, WindowElement::X11(surf) if surf.is_override_redirect()) {
|
|
|
|
keyboard.set_focus(self, Some(FocusTarget::Window(window.clone())), serial);
|
|
|
|
}
|
2023-06-18 04:02:58 +02:00
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
self.space.elements().for_each(|window| {
|
2023-07-25 01:59:05 +02:00
|
|
|
if let WindowElement::Wayland(window) = window {
|
|
|
|
window.toplevel().send_configure();
|
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
});
|
2023-07-28 18:11:35 +02:00
|
|
|
|
|
|
|
let focused_name = match &window {
|
|
|
|
WindowElement::Wayland(win) => {
|
|
|
|
compositor::with_states(win.toplevel().wl_surface(), |states| {
|
|
|
|
let lock = states
|
|
|
|
.data_map
|
|
|
|
.get::<smithay::wayland::shell::xdg::XdgToplevelSurfaceData>()
|
|
|
|
.expect("XdgToplevelSurfaceData wasn't in surface's data map")
|
|
|
|
.lock()
|
|
|
|
.expect("failed to acquire lock");
|
|
|
|
lock.app_id.clone().unwrap_or_default()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
WindowElement::X11(surf) => surf.class(),
|
|
|
|
};
|
|
|
|
tracing::debug!("setting keyboard focus to {focused_name}");
|
2023-06-10 03:29:17 +02:00
|
|
|
}
|
|
|
|
} else {
|
2023-07-25 01:59:05 +02:00
|
|
|
self.space.elements().for_each(|window| match window {
|
|
|
|
WindowElement::Wayland(window) => {
|
|
|
|
window.set_activated(false);
|
|
|
|
window.toplevel().send_configure();
|
|
|
|
}
|
|
|
|
WindowElement::X11(surface) => {
|
|
|
|
surface
|
|
|
|
.set_activated(false)
|
|
|
|
.expect("failed to deactivate x11 win");
|
|
|
|
// INFO: do i need to configure this?
|
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
});
|
|
|
|
keyboard.set_focus(self, None, serial);
|
2023-06-02 19:26:33 +02:00
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
};
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
// Send the button event to the client.
|
|
|
|
pointer.button(
|
|
|
|
self,
|
|
|
|
&ButtonEvent {
|
|
|
|
button,
|
|
|
|
state: button_state,
|
|
|
|
serial,
|
|
|
|
time: event.time_msec(),
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
fn pointer_axis<I: InputBackend>(&mut self, event: I::PointerAxisEvent) {
|
|
|
|
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);
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
let vertical_amount = event
|
|
|
|
.amount(Axis::Vertical)
|
|
|
|
.unwrap_or_else(|| event.amount_discrete(Axis::Vertical).unwrap_or(0.0) * 3.0);
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
let horizontal_amount_discrete = event.amount_discrete(Axis::Horizontal);
|
|
|
|
let vertical_amount_discrete = event.amount_discrete(Axis::Vertical);
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
let mut frame = AxisFrame::new(event.time_msec()).source(source);
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
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);
|
|
|
|
}
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2023-07-29 04:38:12 +02:00
|
|
|
// tracing::debug!(
|
|
|
|
// "axis on current focus: {:?}",
|
|
|
|
// self.seat.get_pointer().unwrap().current_focus()
|
|
|
|
// );
|
|
|
|
|
2023-06-30 00:41:08 +02:00
|
|
|
self.seat
|
|
|
|
.get_pointer()
|
|
|
|
.expect("Seat has no pointer")
|
2023-07-29 04:38:12 +02:00
|
|
|
.axis(self, frame);
|
2023-06-10 03:29:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn keyboard<I: InputBackend>(&mut self, event: I::KeyboardKeyEvent) {
|
|
|
|
let serial = SERIAL_COUNTER.next_serial();
|
|
|
|
let time = event.time_msec();
|
|
|
|
let press_state = event.state();
|
|
|
|
let mut move_mode = false;
|
2023-06-30 00:41:08 +02:00
|
|
|
let action = self
|
|
|
|
.seat
|
|
|
|
.get_keyboard()
|
|
|
|
.expect("Seat has no keyboard") // FIXME: handle err
|
|
|
|
.input(
|
|
|
|
self,
|
|
|
|
event.key_code(),
|
|
|
|
press_state,
|
|
|
|
serial,
|
|
|
|
time,
|
|
|
|
|state, modifiers, keysym| {
|
|
|
|
if press_state == KeyState::Pressed {
|
2023-07-11 18:59:38 +02:00
|
|
|
let mut modifier_mask = Vec::<Modifier>::new();
|
2023-06-30 00:41:08 +02:00
|
|
|
if modifiers.alt {
|
2023-07-11 18:59:38 +02:00
|
|
|
modifier_mask.push(Modifier::Alt);
|
2023-06-30 00:41:08 +02:00
|
|
|
}
|
|
|
|
if modifiers.shift {
|
2023-07-11 18:59:38 +02:00
|
|
|
modifier_mask.push(Modifier::Shift);
|
2023-06-30 00:41:08 +02:00
|
|
|
}
|
|
|
|
if modifiers.ctrl {
|
2023-07-11 18:59:38 +02:00
|
|
|
modifier_mask.push(Modifier::Ctrl);
|
2023-06-30 00:41:08 +02:00
|
|
|
}
|
|
|
|
if modifiers.logo {
|
2023-07-11 18:59:38 +02:00
|
|
|
modifier_mask.push(Modifier::Super);
|
2023-06-30 00:41:08 +02:00
|
|
|
}
|
2023-07-01 04:34:07 +02:00
|
|
|
let raw_sym = if keysym.raw_syms().len() == 1 {
|
|
|
|
keysym.raw_syms()[0]
|
|
|
|
} else {
|
|
|
|
keysyms::KEY_NoSymbol
|
|
|
|
};
|
2023-06-30 00:41:08 +02:00
|
|
|
if let Some(callback_id) = state
|
|
|
|
.input_state
|
|
|
|
.keybinds
|
2023-07-01 04:34:07 +02:00
|
|
|
.get(&(modifier_mask.into(), raw_sym))
|
2023-06-30 00:41:08 +02:00
|
|
|
{
|
|
|
|
return FilterResult::Intercept(*callback_id);
|
2023-07-03 01:15:44 +02:00
|
|
|
} else if modifiers.ctrl
|
|
|
|
&& modifiers.shift
|
|
|
|
&& modifiers.alt
|
|
|
|
&& keysym.modified_sym() == keysyms::KEY_Escape
|
|
|
|
{
|
|
|
|
return FilterResult::Intercept(CallbackId(999999));
|
2023-06-30 00:41:08 +02:00
|
|
|
}
|
2023-06-15 23:43:33 +02:00
|
|
|
}
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-06-30 00:41:08 +02:00
|
|
|
if keysym.modified_sym() == keysyms::KEY_Control_L {
|
|
|
|
match press_state {
|
|
|
|
KeyState::Pressed => {
|
|
|
|
move_mode = true;
|
|
|
|
}
|
|
|
|
KeyState::Released => {
|
|
|
|
move_mode = false;
|
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
}
|
2023-06-02 19:26:33 +02:00
|
|
|
}
|
2023-07-04 22:20:41 +02:00
|
|
|
FilterResult::Forward
|
2023-06-30 00:41:08 +02:00
|
|
|
},
|
|
|
|
);
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
self.move_mode = move_mode;
|
|
|
|
|
2023-06-22 00:36:51 +02:00
|
|
|
if let Some(callback_id) = action {
|
2023-07-03 01:15:44 +02:00
|
|
|
if callback_id.0 == 999999 {
|
|
|
|
self.loop_signal.stop();
|
|
|
|
}
|
2023-06-22 00:36:51 +02:00
|
|
|
if let Some(stream) = self.api_state.stream.as_ref() {
|
|
|
|
if let Err(err) = crate::api::send_to_client(
|
2023-06-30 00:41:08 +02:00
|
|
|
&mut stream.lock().expect("Could not lock stream mutex"),
|
2023-06-22 00:36:51 +02:00
|
|
|
&OutgoingMsg::CallCallback {
|
2023-06-25 00:39:40 +02:00
|
|
|
callback_id,
|
2023-06-22 00:36:51 +02:00
|
|
|
args: None,
|
|
|
|
},
|
|
|
|
) {
|
2023-06-25 00:39:40 +02:00
|
|
|
tracing::warn!("error sending msg to client: {err}");
|
2023-06-18 01:55:04 +02:00
|
|
|
}
|
|
|
|
}
|
2023-06-22 00:36:51 +02:00
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl State<WinitData> {
|
|
|
|
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
|
|
|
|
match event {
|
|
|
|
// TODO: rest of input events
|
|
|
|
|
|
|
|
// InputEvent::DeviceAdded { device } => todo!(),
|
|
|
|
// InputEvent::DeviceRemoved { device } => todo!(),
|
|
|
|
InputEvent::Keyboard { event } => self.keyboard::<B>(event),
|
2023-06-25 00:39:40 +02:00
|
|
|
// InputEvent::PointerMotion { event } => {}
|
2023-06-10 03:29:17 +02:00
|
|
|
InputEvent::PointerMotionAbsolute { event } => self.pointer_motion_absolute::<B>(event),
|
|
|
|
InputEvent::PointerButton { event } => self.pointer_button::<B>(event),
|
|
|
|
InputEvent::PointerAxis { event } => self.pointer_axis::<B>(event),
|
2023-06-02 19:26:33 +02:00
|
|
|
|
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
|
|
|
|
fn pointer_motion_absolute<I: InputBackend>(&mut self, event: I::PointerMotionAbsoluteEvent) {
|
2023-06-30 00:41:08 +02:00
|
|
|
let Some(output) = self.space.outputs().next() else { return; };
|
|
|
|
let output_geo = self
|
|
|
|
.space
|
|
|
|
.output_geometry(output)
|
|
|
|
.expect("Output geometry doesn't exist");
|
2023-06-10 03:29:17 +02:00
|
|
|
let pointer_loc = event.position_transformed(output_geo.size) + output_geo.loc.to_f64();
|
|
|
|
let serial = SERIAL_COUNTER.next_serial();
|
2023-06-30 00:41:08 +02:00
|
|
|
let pointer = self.seat.get_pointer().expect("Seat has no pointer"); // FIXME: handle err
|
2023-06-10 03:29:17 +02:00
|
|
|
|
|
|
|
// tracing::info!("pointer_loc: {:?}", pointer_loc);
|
|
|
|
|
|
|
|
self.pointer_location = pointer_loc;
|
|
|
|
|
2023-06-25 00:39:40 +02:00
|
|
|
match self.focus_state.focused_output {
|
|
|
|
Some(_) => {
|
|
|
|
if let Some(output) = self
|
|
|
|
.space
|
|
|
|
.output_under(self.pointer_location)
|
|
|
|
.next()
|
|
|
|
.cloned()
|
|
|
|
{
|
|
|
|
self.focus_state.focused_output = Some(output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
self.focus_state.focused_output = self.space.outputs().next().cloned();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-28 22:16:25 +02:00
|
|
|
let surface_under_pointer = self
|
|
|
|
.space
|
|
|
|
.element_under(pointer_loc)
|
|
|
|
.map(|(window, loc)| (FocusTarget::Window(window.clone()), loc));
|
|
|
|
|
2023-07-29 04:38:12 +02:00
|
|
|
// tracing::debug!("surface_under_pointer: {surface_under_pointer:?}");
|
|
|
|
// tracing::debug!("pointer focus: {:?}", pointer.current_focus());
|
2023-08-01 17:53:37 +02:00
|
|
|
if let Some((focus, _point)) = &surface_under_pointer {
|
|
|
|
focus.motion(
|
|
|
|
&self.seat.clone(),
|
|
|
|
self,
|
|
|
|
&MotionEvent {
|
|
|
|
location: pointer_loc,
|
|
|
|
serial,
|
|
|
|
time: event.time_msec(),
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
pointer.motion(
|
|
|
|
self,
|
|
|
|
surface_under_pointer,
|
|
|
|
&MotionEvent {
|
|
|
|
location: pointer_loc,
|
|
|
|
serial,
|
|
|
|
time: event.time_msec(),
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl State<UdevData> {
|
|
|
|
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
|
|
|
|
match event {
|
|
|
|
// TODO: rest of input events
|
|
|
|
|
|
|
|
// InputEvent::DeviceAdded { device } => todo!(),
|
|
|
|
// InputEvent::DeviceRemoved { device } => todo!(),
|
|
|
|
InputEvent::Keyboard { event } => self.keyboard::<B>(event),
|
|
|
|
InputEvent::PointerMotion { event } => self.pointer_motion::<B>(event),
|
2023-08-04 20:45:38 +02:00
|
|
|
// currently does not seem to use absolute
|
2023-06-10 03:29:17 +02:00
|
|
|
InputEvent::PointerMotionAbsolute { event } => self.pointer_motion_absolute::<B>(event),
|
|
|
|
InputEvent::PointerButton { event } => self.pointer_button::<B>(event),
|
|
|
|
InputEvent::PointerAxis { event } => self.pointer_axis::<B>(event),
|
|
|
|
|
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn pointer_motion<I: InputBackend>(&mut self, event: I::PointerMotionEvent) {
|
|
|
|
let serial = SERIAL_COUNTER.next_serial();
|
|
|
|
self.pointer_location += event.delta();
|
|
|
|
|
|
|
|
// clamp to screen limits
|
|
|
|
// this event is never generated by winit
|
|
|
|
self.pointer_location = self.clamp_coords(self.pointer_location);
|
2023-06-25 00:39:40 +02:00
|
|
|
match self.focus_state.focused_output {
|
|
|
|
Some(_) => {
|
|
|
|
if let Some(output) = self
|
|
|
|
.space
|
|
|
|
.output_under(self.pointer_location)
|
|
|
|
.next()
|
|
|
|
.cloned()
|
|
|
|
{
|
|
|
|
self.focus_state.focused_output = Some(output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
self.focus_state.focused_output = self.space.outputs().next().cloned();
|
|
|
|
}
|
|
|
|
}
|
2023-06-10 03:29:17 +02:00
|
|
|
|
2023-07-28 22:16:25 +02:00
|
|
|
let surface_under = self.surface_under(self.pointer_location);
|
2023-06-12 00:56:34 +02:00
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
// tracing::info!("{:?}", self.pointer_location);
|
|
|
|
if let Some(ptr) = self.seat.get_pointer() {
|
|
|
|
ptr.motion(
|
|
|
|
self,
|
2023-06-12 00:56:34 +02:00
|
|
|
surface_under,
|
2023-06-10 03:29:17 +02:00
|
|
|
&MotionEvent {
|
|
|
|
location: self.pointer_location,
|
|
|
|
serial,
|
|
|
|
time: event.time_msec(),
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
// ptr.relative_motion(
|
|
|
|
// self,
|
|
|
|
// under,
|
|
|
|
// &RelativeMotionEvent {
|
|
|
|
// delta: event.delta(),
|
|
|
|
// delta_unaccel: event.delta_unaccel(),
|
|
|
|
// utime: event.time(),
|
|
|
|
// },
|
|
|
|
// )
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn pointer_motion_absolute<I: InputBackend>(&mut self, event: I::PointerMotionAbsoluteEvent) {
|
|
|
|
let serial = SERIAL_COUNTER.next_serial();
|
|
|
|
|
|
|
|
let max_x = self.space.outputs().fold(0, |acc, o| {
|
2023-06-30 00:41:08 +02:00
|
|
|
acc + self
|
|
|
|
.space
|
|
|
|
.output_geometry(o)
|
|
|
|
.expect("Output geometry doesn't exist")
|
|
|
|
.size
|
|
|
|
.w
|
2023-06-10 03:29:17 +02:00
|
|
|
});
|
|
|
|
|
2023-06-30 00:41:08 +02:00
|
|
|
let Some(max_h_output) = self
|
2023-06-10 03:29:17 +02:00
|
|
|
.space
|
|
|
|
.outputs()
|
2023-06-30 00:41:08 +02:00
|
|
|
.max_by_key(|o| {
|
|
|
|
self.space
|
|
|
|
.output_geometry(o)
|
|
|
|
.expect("Output geometry doesn't exist")
|
|
|
|
.size
|
|
|
|
.h
|
|
|
|
})
|
|
|
|
else {
|
|
|
|
tracing::warn!("Pointer moved, but there was no output");
|
|
|
|
return;
|
|
|
|
};
|
2023-06-10 03:29:17 +02:00
|
|
|
|
2023-06-30 00:41:08 +02:00
|
|
|
let max_y = self
|
|
|
|
.space
|
|
|
|
.output_geometry(max_h_output)
|
|
|
|
.expect("Output geometry doesn't exist")
|
|
|
|
.size
|
|
|
|
.h;
|
2023-06-10 03:29:17 +02:00
|
|
|
|
|
|
|
self.pointer_location.x = event.x_transformed(max_x);
|
|
|
|
self.pointer_location.y = event.y_transformed(max_y);
|
|
|
|
|
|
|
|
self.pointer_location = self.clamp_coords(self.pointer_location);
|
|
|
|
|
2023-07-28 22:16:25 +02:00
|
|
|
let surface_under = self.surface_under(self.pointer_location);
|
2023-06-10 03:29:17 +02:00
|
|
|
|
|
|
|
if let Some(ptr) = self.seat.get_pointer() {
|
|
|
|
ptr.motion(
|
|
|
|
self,
|
2023-06-12 00:56:34 +02:00
|
|
|
surface_under,
|
2023-06-10 03:29:17 +02:00
|
|
|
&MotionEvent {
|
|
|
|
location: self.pointer_location,
|
|
|
|
serial,
|
|
|
|
time: event.time_msec(),
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn clamp_coords(&self, pos: Point<f64, Logical>) -> Point<f64, Logical> {
|
|
|
|
if self.space.outputs().next().is_none() {
|
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
let (pos_x, pos_y) = pos.into();
|
2023-08-04 20:45:38 +02:00
|
|
|
|
|
|
|
let nearest_points = self.space.outputs().map(|op| {
|
|
|
|
let size = self
|
2023-06-30 00:41:08 +02:00
|
|
|
.space
|
2023-08-04 20:45:38 +02:00
|
|
|
.output_geometry(op)
|
|
|
|
.expect("called output_geometry on unmapped output")
|
|
|
|
.size;
|
|
|
|
let loc = op.current_location();
|
|
|
|
let pos_x = pos_x.clamp(loc.x as f64, (loc.x + size.w) as f64);
|
|
|
|
let pos_y = pos_y.clamp(loc.y as f64, (loc.y + size.h) as f64);
|
|
|
|
(pos_x, pos_y)
|
2023-06-10 03:29:17 +02:00
|
|
|
});
|
|
|
|
|
2023-08-04 20:45:38 +02:00
|
|
|
let nearest_point = nearest_points.min_by(|(x1, y1), (x2, y2)| {
|
|
|
|
f64::total_cmp(
|
|
|
|
&((pos_x - x1).powi(2) + (pos_y - y1).powi(2)).sqrt(),
|
|
|
|
&((pos_x - x2).powi(2) + (pos_y - y2).powi(2)).sqrt(),
|
|
|
|
)
|
|
|
|
});
|
|
|
|
|
|
|
|
nearest_point.map(|point| point.into()).unwrap_or(pos)
|
2023-06-10 03:29:17 +02:00
|
|
|
}
|
2023-06-02 19:26:33 +02:00
|
|
|
}
|