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-12-14 03:33:16 +01:00
|
|
|
pub mod libinput;
|
|
|
|
|
2023-06-15 23:43:33 +02:00
|
|
|
use std::collections::HashMap;
|
|
|
|
|
2023-07-25 01:59:05 +02:00
|
|
|
use crate::{
|
2024-01-10 02:25:51 +01:00
|
|
|
api::msg::{CallbackId, Modifier, MouseEdge, OutgoingMsg},
|
2023-07-28 18:11:35 +02:00
|
|
|
focus::FocusTarget,
|
2023-10-02 21:06:39 +02:00
|
|
|
state::WithState,
|
2023-07-25 01:59:05 +02:00
|
|
|
window::WindowElement,
|
|
|
|
};
|
2024-01-10 02:25:51 +01:00
|
|
|
use pinnacle_api_defs::pinnacle::input::v0alpha1::SetKeybindResponse;
|
2023-06-02 19:26:33 +02:00
|
|
|
use smithay::{
|
2023-12-14 03:33:16 +01:00
|
|
|
backend::input::{
|
|
|
|
AbsolutePositionEvent, Axis, AxisSource, ButtonState, Event, InputBackend, InputEvent,
|
|
|
|
KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionEvent,
|
2023-08-08 17:55:06 +02:00
|
|
|
},
|
2023-08-06 03:49:39 +02:00
|
|
|
desktop::{layer_map_for_output, space::SpaceElement},
|
2023-06-02 19:26:33 +02:00
|
|
|
input::{
|
|
|
|
keyboard::{keysyms, FilterResult},
|
2023-09-15 09:50:42 +02:00
|
|
|
pointer::{AxisFrame, ButtonEvent, MotionEvent, RelativeMotionEvent},
|
2023-06-02 19:26:33 +02:00
|
|
|
},
|
2023-12-14 03:33:16 +01:00
|
|
|
reexports::input::{self, Led},
|
2023-06-10 03:29:17 +02:00
|
|
|
utils::{Logical, Point, SERIAL_COUNTER},
|
2023-09-10 11:49:31 +02:00
|
|
|
wayland::{seat::WaylandFocus, shell::wlr_layer},
|
2023-06-02 19:26:33 +02:00
|
|
|
};
|
2024-01-10 02:25:51 +01:00
|
|
|
use tokio::sync::mpsc::UnboundedSender;
|
2023-10-13 00:10:23 +02:00
|
|
|
use xkbcommon::xkb::Keysym;
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-08-29 05:53:24 +02:00
|
|
|
use crate::state::State;
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-12-14 03:33:16 +01:00
|
|
|
use self::libinput::LibinputSetting;
|
|
|
|
|
2024-01-10 02:25:51 +01:00
|
|
|
bitflags::bitflags! {
|
|
|
|
#[derive(Debug, Hash, Copy, Clone, PartialEq, Eq)]
|
|
|
|
pub struct ModifierMask: u8 {
|
|
|
|
const SHIFT = 1;
|
|
|
|
const CTRL = 1 << 1;
|
|
|
|
const ALT = 1 << 2;
|
|
|
|
const SUPER = 1 << 3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-22 01:07:56 +02:00
|
|
|
#[derive(Default, Debug)]
|
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
|
2024-01-10 02:25:51 +01:00
|
|
|
pub keybinds: HashMap<(crate::api::msg::ModifierMask, Keysym), CallbackId>,
|
2023-06-18 04:02:58 +02:00
|
|
|
/// A hashmap of modifier keys and mouse button codes to callback IDs
|
2024-01-10 02:25:51 +01:00
|
|
|
pub mousebinds: HashMap<(crate::api::msg::ModifierMask, u32, MouseEdge), CallbackId>,
|
|
|
|
pub reload_keybind: Option<(crate::api::msg::ModifierMask, Keysym)>,
|
|
|
|
pub kill_keybind: Option<(crate::api::msg::ModifierMask, Keysym)>,
|
2023-12-17 04:20:29 +01:00
|
|
|
/// User defined libinput settings that will be applied
|
2023-09-29 01:46:08 +02:00
|
|
|
pub libinput_settings: Vec<LibinputSetting>,
|
2023-12-17 04:20:29 +01:00
|
|
|
/// All libinput devices that have been connected
|
2023-09-29 01:46:08 +02:00
|
|
|
pub libinput_devices: Vec<input::Device>,
|
2024-01-10 02:25:51 +01:00
|
|
|
|
|
|
|
pub grpc_keybinds:
|
|
|
|
HashMap<(ModifierMask, Keysym), UnboundedSender<Result<SetKeybindResponse, tonic::Status>>>,
|
2023-06-18 04:02:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl InputState {
|
2023-09-22 01:07:56 +02:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Default::default()
|
2023-06-18 04:02:58 +02:00
|
|
|
}
|
2023-06-15 23:43:33 +02:00
|
|
|
}
|
|
|
|
|
2023-08-08 19:50:43 +02:00
|
|
|
#[derive(Debug)]
|
|
|
|
enum KeyAction {
|
2023-12-17 04:20:29 +01:00
|
|
|
/// Call a callback from a config process
|
2023-08-08 19:50:43 +02:00
|
|
|
CallCallback(CallbackId),
|
2024-01-10 02:25:51 +01:00
|
|
|
CallGrpcCallback(ModifierMask, Keysym),
|
2023-08-08 19:50:43 +02:00
|
|
|
Quit,
|
|
|
|
SwitchVt(i32),
|
2023-08-16 00:26:17 +02:00
|
|
|
ReloadConfig,
|
2023-08-08 19:50:43 +02:00
|
|
|
}
|
|
|
|
|
2023-08-29 05:53:24 +02:00
|
|
|
impl State {
|
|
|
|
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),
|
|
|
|
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-09-02 23:51:39 +02:00
|
|
|
/// Get the [`FocusTarget`] under `point`.
|
2023-12-24 05:03:20 +01:00
|
|
|
pub fn focus_target_under<P>(&self, point: P) -> Option<(FocusTarget, Point<i32, Logical>)>
|
2023-06-12 00:56:34 +02:00
|
|
|
where
|
|
|
|
P: Into<Point<f64, Logical>>,
|
|
|
|
{
|
2023-08-06 03:49:39 +02:00
|
|
|
let point: Point<f64, Logical> = point.into();
|
|
|
|
|
|
|
|
let output = self.space.outputs().find(|op| {
|
|
|
|
self.space
|
|
|
|
.output_geometry(op)
|
|
|
|
.expect("called output_geometry on unmapped output (this shouldn't happen here)")
|
|
|
|
.contains(point.to_i32_round())
|
|
|
|
})?;
|
|
|
|
|
|
|
|
let output_geo = self
|
|
|
|
.space
|
|
|
|
.output_geometry(output)
|
|
|
|
.expect("called output_geometry on unmapped output");
|
|
|
|
|
|
|
|
let layers = layer_map_for_output(output);
|
|
|
|
|
2023-08-12 19:01:55 +02:00
|
|
|
let top_fullscreen_window = self.focus_state.focus_stack.iter().rev().find(|win| {
|
|
|
|
win.with_state(|state| {
|
2023-08-14 20:54:50 +02:00
|
|
|
state.fullscreen_or_maximized.is_fullscreen()
|
2023-12-24 05:03:20 +01:00
|
|
|
&& output.with_state(|op_state| {
|
|
|
|
op_state
|
|
|
|
.focused_tags()
|
|
|
|
.any(|op_tag| state.tags.contains(op_tag))
|
|
|
|
})
|
2023-08-12 19:01:55 +02:00
|
|
|
})
|
|
|
|
});
|
|
|
|
|
2023-12-17 04:20:29 +01:00
|
|
|
if let Some(window) = top_fullscreen_window {
|
|
|
|
Some((FocusTarget::from(window.clone()), output_geo.loc))
|
|
|
|
} else if let (Some(layer), _) | (None, Some(layer)) = (
|
|
|
|
layers.layer_under(wlr_layer::Layer::Overlay, point),
|
|
|
|
layers.layer_under(wlr_layer::Layer::Top, point),
|
|
|
|
) {
|
|
|
|
let layer_loc = layers.layer_geometry(layer).expect("no layer geo").loc;
|
|
|
|
Some((FocusTarget::from(layer.clone()), output_geo.loc + layer_loc))
|
|
|
|
} else if let Some(ret) = self
|
|
|
|
.space
|
|
|
|
.elements()
|
|
|
|
.rev()
|
|
|
|
.filter(|win| win.is_on_active_tag(self.space.outputs()))
|
|
|
|
.find_map(|win| {
|
|
|
|
let loc = self
|
|
|
|
.space
|
|
|
|
.element_location(win)
|
|
|
|
.expect("called elem loc on unmapped win")
|
|
|
|
- win.geometry().loc;
|
|
|
|
|
|
|
|
win.is_in_input_region(&(point - loc.to_f64()))
|
|
|
|
.then(|| (win.clone().into(), loc))
|
2023-08-06 03:49:39 +02:00
|
|
|
})
|
2023-12-17 04:20:29 +01:00
|
|
|
{
|
|
|
|
Some(ret)
|
|
|
|
} else if let (Some(layer), _) | (None, Some(layer)) = (
|
|
|
|
layers.layer_under(wlr_layer::Layer::Overlay, point),
|
|
|
|
layers.layer_under(wlr_layer::Layer::Top, point),
|
|
|
|
) {
|
|
|
|
let layer_loc = layers.layer_geometry(layer).expect("no layer geo").loc;
|
|
|
|
Some((FocusTarget::from(layer.clone()), output_geo.loc + layer_loc))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
2023-06-12 00:56:34 +02:00
|
|
|
}
|
|
|
|
|
2023-08-08 17:55:06 +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();
|
2023-08-16 00:26:17 +02:00
|
|
|
|
|
|
|
let reload_keybind = self.input_state.reload_keybind;
|
|
|
|
let kill_keybind = self.input_state.kill_keybind;
|
|
|
|
|
2023-09-29 02:10:36 +02:00
|
|
|
let keyboard = self.seat.get_keyboard().expect("Seat has no keyboard");
|
2023-08-16 00:26:17 +02:00
|
|
|
|
2023-09-29 02:10:36 +02:00
|
|
|
let modifiers = keyboard.modifier_state();
|
2023-09-10 03:41:21 +02:00
|
|
|
|
2023-09-29 02:10:36 +02:00
|
|
|
let mut leds = Led::empty();
|
|
|
|
if modifiers.num_lock {
|
|
|
|
leds |= Led::NUMLOCK;
|
|
|
|
}
|
|
|
|
if modifiers.caps_lock {
|
|
|
|
leds |= Led::CAPSLOCK;
|
|
|
|
}
|
2023-09-10 03:41:21 +02:00
|
|
|
|
2023-09-29 02:10:36 +02:00
|
|
|
// FIXME: Leds only update once another key is pressed.
|
|
|
|
for device in self.input_state.libinput_devices.iter_mut() {
|
|
|
|
device.led_update(leds);
|
|
|
|
}
|
2023-09-10 03:41:21 +02:00
|
|
|
|
2023-09-29 02:10:36 +02:00
|
|
|
let action = keyboard.input(
|
|
|
|
self,
|
|
|
|
event.key_code(),
|
|
|
|
press_state,
|
|
|
|
serial,
|
|
|
|
time,
|
|
|
|
|state, modifiers, keysym| {
|
2024-01-10 02:25:51 +01:00
|
|
|
tracing::debug!(keysym = ?keysym, raw_keysyms = ?keysym.raw_syms(), modified_syms = ?keysym.modified_syms());
|
2023-09-29 02:10:36 +02:00
|
|
|
if press_state == KeyState::Pressed {
|
|
|
|
let mut modifier_mask = Vec::<Modifier>::new();
|
|
|
|
if modifiers.alt {
|
|
|
|
modifier_mask.push(Modifier::Alt);
|
|
|
|
}
|
|
|
|
if modifiers.shift {
|
|
|
|
modifier_mask.push(Modifier::Shift);
|
|
|
|
}
|
|
|
|
if modifiers.ctrl {
|
|
|
|
modifier_mask.push(Modifier::Ctrl);
|
|
|
|
}
|
|
|
|
if modifiers.logo {
|
|
|
|
modifier_mask.push(Modifier::Super);
|
|
|
|
}
|
2024-01-10 02:25:51 +01:00
|
|
|
let modifier_mask = crate::api::msg::ModifierMask::from(modifier_mask);
|
|
|
|
|
|
|
|
let mut grpc_modifiers = ModifierMask::empty();
|
|
|
|
if modifiers.alt {
|
|
|
|
grpc_modifiers |= ModifierMask::ALT;
|
|
|
|
}
|
|
|
|
if modifiers.shift {
|
|
|
|
grpc_modifiers |= ModifierMask::SHIFT;
|
|
|
|
}
|
|
|
|
if modifiers.ctrl {
|
|
|
|
grpc_modifiers |= ModifierMask::CTRL;
|
|
|
|
}
|
|
|
|
if modifiers.logo {
|
|
|
|
grpc_modifiers |= ModifierMask::SUPER;
|
|
|
|
}
|
|
|
|
|
2023-12-17 04:20:29 +01:00
|
|
|
|
2023-09-29 02:10:36 +02:00
|
|
|
let raw_sym = keysym.raw_syms().iter().next();
|
|
|
|
let mod_sym = keysym.modified_sym();
|
|
|
|
|
2024-01-10 02:25:51 +01:00
|
|
|
if state.input_state.grpc_keybinds.get(&(grpc_modifiers, keysym.modified_sym())).is_some() {
|
|
|
|
return FilterResult::Intercept(KeyAction::CallGrpcCallback(grpc_modifiers, keysym.modified_sym()));
|
|
|
|
}
|
|
|
|
|
2023-09-29 02:10:36 +02:00
|
|
|
let cb_id_mod = state.input_state.keybinds.get(&(modifier_mask, mod_sym));
|
|
|
|
|
2023-12-17 04:20:29 +01:00
|
|
|
let cb_id_raw = raw_sym.and_then(|raw_sym| {
|
2023-09-29 02:10:36 +02:00
|
|
|
state.input_state.keybinds.get(&(modifier_mask, *raw_sym))
|
2023-12-17 04:20:29 +01:00
|
|
|
});
|
2023-09-29 02:10:36 +02:00
|
|
|
|
|
|
|
match (cb_id_mod, cb_id_raw) {
|
|
|
|
(Some(cb_id), _) | (None, Some(cb_id)) => {
|
|
|
|
return FilterResult::Intercept(KeyAction::CallCallback(*cb_id));
|
2023-08-08 17:55:06 +02:00
|
|
|
}
|
2023-09-29 02:10:36 +02:00
|
|
|
(None, None) => (),
|
|
|
|
}
|
2023-08-08 17:55:06 +02:00
|
|
|
|
2023-12-17 04:20:29 +01:00
|
|
|
if kill_keybind == Some((modifier_mask, mod_sym)) {
|
2023-09-29 02:10:36 +02:00
|
|
|
return FilterResult::Intercept(KeyAction::Quit);
|
2023-12-17 04:20:29 +01:00
|
|
|
} else if reload_keybind == Some((modifier_mask, mod_sym)) {
|
2023-09-29 02:10:36 +02:00
|
|
|
return FilterResult::Intercept(KeyAction::ReloadConfig);
|
|
|
|
} else if let mut vt @ keysyms::KEY_XF86Switch_VT_1
|
2023-10-13 00:10:23 +02:00
|
|
|
..=keysyms::KEY_XF86Switch_VT_12 = keysym.modified_sym().raw()
|
2023-09-29 02:10:36 +02:00
|
|
|
{
|
|
|
|
vt = vt - keysyms::KEY_XF86Switch_VT_1 + 1;
|
|
|
|
tracing::info!("Switching to vt {vt}");
|
|
|
|
return FilterResult::Intercept(KeyAction::SwitchVt(vt as i32));
|
2023-08-08 17:55:06 +02:00
|
|
|
}
|
2023-09-29 02:10:36 +02:00
|
|
|
}
|
2023-08-08 17:55:06 +02:00
|
|
|
|
2023-09-29 02:10:36 +02:00
|
|
|
FilterResult::Forward
|
|
|
|
},
|
|
|
|
);
|
2023-08-08 17:55:06 +02:00
|
|
|
|
2023-08-08 19:50:43 +02:00
|
|
|
match action {
|
|
|
|
Some(KeyAction::CallCallback(callback_id)) => {
|
|
|
|
if let Some(stream) = self.api_state.stream.as_ref() {
|
2023-12-15 05:00:04 +01:00
|
|
|
if let Err(err) = crate::api::send_to_client(
|
2023-08-08 19:50:43 +02:00
|
|
|
&mut stream.lock().expect("Could not lock stream mutex"),
|
|
|
|
&OutgoingMsg::CallCallback {
|
|
|
|
callback_id,
|
|
|
|
args: None,
|
|
|
|
},
|
|
|
|
) {
|
|
|
|
tracing::error!("error sending msg to client: {err}");
|
|
|
|
}
|
|
|
|
}
|
2023-08-08 17:55:06 +02:00
|
|
|
}
|
2024-01-10 02:25:51 +01:00
|
|
|
Some(KeyAction::CallGrpcCallback(mods, keysym)) => {
|
|
|
|
if let Some(sender) = self.input_state.grpc_keybinds.get(&(mods, keysym)) {
|
|
|
|
let _ = sender.send(Ok(SetKeybindResponse {}));
|
|
|
|
}
|
|
|
|
}
|
2023-08-08 19:50:43 +02:00
|
|
|
Some(KeyAction::SwitchVt(vt)) => {
|
2023-12-17 04:20:29 +01:00
|
|
|
self.switch_vt(vt);
|
2023-08-08 17:55:06 +02:00
|
|
|
}
|
2023-08-08 19:50:43 +02:00
|
|
|
Some(KeyAction::Quit) => {
|
2023-12-17 04:20:29 +01:00
|
|
|
tracing::info!("Quitting Pinnacle");
|
2023-08-08 19:50:43 +02:00
|
|
|
self.loop_signal.stop();
|
2023-08-08 17:55:06 +02:00
|
|
|
}
|
2023-08-16 00:26:17 +02:00
|
|
|
Some(KeyAction::ReloadConfig) => {
|
2023-09-22 01:07:56 +02:00
|
|
|
self.start_config(crate::config::get_config_dir())
|
2023-09-22 00:12:16 +02:00
|
|
|
.expect("failed to restart config");
|
2023-08-16 00:26:17 +02:00
|
|
|
}
|
2023-12-17 04:20:29 +01:00
|
|
|
None => (),
|
2023-08-08 17:55:06 +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
|
|
|
let serial = SERIAL_COUNTER.next_serial();
|
|
|
|
|
|
|
|
let button = event.button_code();
|
|
|
|
|
|
|
|
let button_state = event.state();
|
|
|
|
|
|
|
|
let pointer_loc = pointer.current_location();
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-12-17 04:20:29 +01:00
|
|
|
let mouse_edge = match button_state {
|
2023-09-11 04:54:58 +02:00
|
|
|
ButtonState::Released => MouseEdge::Release,
|
|
|
|
ButtonState::Pressed => MouseEdge::Press,
|
|
|
|
};
|
2024-01-10 02:25:51 +01:00
|
|
|
let modifier_mask = crate::api::msg::ModifierMask::from(keyboard.modifier_state());
|
2023-09-11 04:54:58 +02:00
|
|
|
|
|
|
|
// If any mousebinds are detected, call the config's callback and return.
|
2023-12-17 04:20:29 +01:00
|
|
|
if let Some(&callback_id) =
|
|
|
|
self.input_state
|
|
|
|
.mousebinds
|
|
|
|
.get(&(modifier_mask, button, mouse_edge))
|
2023-09-11 04:54:58 +02:00
|
|
|
{
|
2023-12-15 05:00:04 +01:00
|
|
|
if let Some(stream) = self.api_state.stream.as_ref() {
|
|
|
|
crate::api::send_to_client(
|
|
|
|
&mut stream.lock().expect("failed to lock api stream"),
|
2023-09-11 04:54:58 +02:00
|
|
|
&OutgoingMsg::CallCallback {
|
|
|
|
callback_id,
|
|
|
|
args: None,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.expect("failed to call callback");
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
// If the button was clicked, focus on the window below if exists, else
|
|
|
|
// unfocus on windows.
|
2023-12-17 04:20:29 +01:00
|
|
|
if button_state == ButtonState::Pressed {
|
2023-12-24 05:03:20 +01:00
|
|
|
if let Some((focus, _)) = self.focus_target_under(pointer_loc) {
|
2023-09-11 04:54:58 +02:00
|
|
|
// Move window to top of stack.
|
|
|
|
if let FocusTarget::Window(window) = &focus {
|
|
|
|
self.space.raise_element(window, true);
|
|
|
|
if let WindowElement::X11(surface) = &window {
|
2023-12-17 04:20:29 +01:00
|
|
|
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-06-02 19:26:33 +02:00
|
|
|
}
|
2023-09-11 04:54:58 +02:00
|
|
|
}
|
2023-07-29 04:38:12 +02:00
|
|
|
|
2023-09-11 04:54:58 +02:00
|
|
|
tracing::debug!("wl_surface focus is some? {}", focus.wl_surface().is_some());
|
2023-08-01 17:53:37 +02:00
|
|
|
|
2023-09-11 04:54:58 +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
|
|
|
|
2023-09-11 04:54:58 +02:00
|
|
|
// TODO: use update_keyboard_focus from anvil
|
2023-06-18 04:02:58 +02:00
|
|
|
|
2023-12-14 03:07:19 +01:00
|
|
|
if !matches!(
|
|
|
|
&focus,
|
|
|
|
FocusTarget::Window(WindowElement::X11OverrideRedirect(_))
|
|
|
|
) {
|
2023-09-11 04:54:58 +02:00
|
|
|
keyboard.set_focus(self, Some(focus.clone()), serial);
|
|
|
|
}
|
2023-07-28 18:11:35 +02:00
|
|
|
|
2023-09-11 04:54:58 +02:00
|
|
|
self.space.elements().for_each(|window| {
|
|
|
|
if let WindowElement::Wayland(window) = window {
|
|
|
|
window.toplevel().send_configure();
|
2023-08-08 00:23:09 +02:00
|
|
|
}
|
2023-09-11 04:54:58 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
if let FocusTarget::Window(window) = &focus {
|
|
|
|
tracing::debug!("setting keyboard focus to {:?}", window.class());
|
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-12-14 03:07:19 +01:00
|
|
|
WindowElement::X11OverrideRedirect(_) => (),
|
2023-12-24 05:17:35 +01:00
|
|
|
_ => unreachable!(),
|
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
|
|
|
pointer.button(
|
|
|
|
self,
|
|
|
|
&ButtonEvent {
|
|
|
|
button,
|
|
|
|
state: button_state,
|
|
|
|
serial,
|
|
|
|
time: event.time_msec(),
|
|
|
|
},
|
|
|
|
);
|
2023-10-13 02:15:47 +02:00
|
|
|
pointer.frame(self);
|
2023-06-10 03:29:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn pointer_axis<I: InputBackend>(&mut self, event: I::PointerAxisEvent) {
|
|
|
|
let source = event.source();
|
|
|
|
|
|
|
|
let horizontal_amount = event
|
|
|
|
.amount(Axis::Horizontal)
|
2023-12-19 12:08:52 +01:00
|
|
|
.unwrap_or_else(|| event.amount_v120(Axis::Horizontal).unwrap_or(0.0) * 3.0 / 120.);
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-12-17 04:20:29 +01:00
|
|
|
let vertical_amount = event
|
2023-06-10 03:29:17 +02:00
|
|
|
.amount(Axis::Vertical)
|
2023-12-19 12:08:52 +01:00
|
|
|
.unwrap_or_else(|| event.amount_v120(Axis::Vertical).unwrap_or(0.0) * 3.0 / 120.);
|
2023-06-02 19:26:33 +02:00
|
|
|
|
2023-12-19 12:08:52 +01:00
|
|
|
let horizontal_amount_discrete = event.amount_v120(Axis::Horizontal);
|
|
|
|
let vertical_amount_discrete = event.amount_v120(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 {
|
2023-12-19 12:08:52 +01:00
|
|
|
frame = frame.v120(Axis::Horizontal, discrete as i32);
|
2023-06-10 03:29:17 +02:00
|
|
|
}
|
|
|
|
} 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 {
|
2023-12-19 12:08:52 +01:00
|
|
|
frame = frame.v120(Axis::Vertical, discrete as i32);
|
2023-06-10 03:29:17 +02:00
|
|
|
}
|
|
|
|
} else if source == AxisSource::Finger {
|
|
|
|
frame = frame.stop(Axis::Vertical);
|
|
|
|
}
|
|
|
|
|
2023-10-13 02:15:47 +02:00
|
|
|
let pointer = self.seat.get_pointer().expect("Seat has no pointer");
|
|
|
|
|
|
|
|
pointer.axis(self, frame);
|
|
|
|
pointer.frame(self);
|
2023-06-10 03:29:17 +02:00
|
|
|
}
|
2023-08-08 02:48:18 +02:00
|
|
|
|
2023-12-17 04:20:29 +01:00
|
|
|
/// Clamp pointer coordinates inside outputs.
|
|
|
|
///
|
|
|
|
/// This returns the nearest point inside an output.
|
2023-08-29 05:53:24 +02:00
|
|
|
fn clamp_coords(&self, pos: Point<f64, Logical>) -> Point<f64, Logical> {
|
|
|
|
if self.space.outputs().next().is_none() {
|
|
|
|
return pos;
|
|
|
|
}
|
2023-08-08 02:48:18 +02:00
|
|
|
|
2023-08-29 05:53:24 +02:00
|
|
|
let (pos_x, pos_y) = pos.into();
|
2023-08-08 02:48:18 +02:00
|
|
|
|
2023-08-29 05:53:24 +02:00
|
|
|
let nearest_points = self.space.outputs().map(|op| {
|
|
|
|
let size = self
|
|
|
|
.space
|
|
|
|
.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)
|
|
|
|
});
|
|
|
|
|
|
|
|
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-08-08 02:48:18 +02:00
|
|
|
}
|
|
|
|
|
2023-06-10 03:29:17 +02:00
|
|
|
fn pointer_motion_absolute<I: InputBackend>(&mut self, event: I::PointerMotionAbsoluteEvent) {
|
2023-09-20 10:36:50 +02:00
|
|
|
let Some(output) = self.space.outputs().next() else {
|
|
|
|
return;
|
|
|
|
};
|
2023-12-17 04:20:29 +01:00
|
|
|
|
2023-06-30 00:41:08 +02:00
|
|
|
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
|
|
|
|
|
|
|
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-06-10 03:29:17 +02:00
|
|
|
pointer.motion(
|
|
|
|
self,
|
2023-12-24 05:03:20 +01:00
|
|
|
self.focus_target_under(pointer_loc),
|
2023-06-10 03:29:17 +02:00
|
|
|
&MotionEvent {
|
|
|
|
location: pointer_loc,
|
|
|
|
serial,
|
|
|
|
time: event.time_msec(),
|
|
|
|
},
|
|
|
|
);
|
2023-10-13 02:15:47 +02:00
|
|
|
|
|
|
|
pointer.frame(self);
|
2023-06-10 03:29:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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-12-24 05:03:20 +01:00
|
|
|
let surface_under = self.focus_target_under(self.pointer_location);
|
2023-06-12 00:56:34 +02:00
|
|
|
|
2023-10-15 09:27:41 +02:00
|
|
|
if let Some(pointer) = self.seat.get_pointer() {
|
|
|
|
pointer.motion(
|
2023-06-10 03:29:17 +02:00
|
|
|
self,
|
2023-09-15 09:50:42 +02:00
|
|
|
surface_under.clone(),
|
2023-06-10 03:29:17 +02:00
|
|
|
&MotionEvent {
|
|
|
|
location: self.pointer_location,
|
|
|
|
serial,
|
|
|
|
time: event.time_msec(),
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
2023-10-15 09:27:41 +02:00
|
|
|
pointer.relative_motion(
|
2023-09-15 09:50:42 +02:00
|
|
|
self,
|
|
|
|
surface_under,
|
|
|
|
&RelativeMotionEvent {
|
|
|
|
delta: event.delta(),
|
|
|
|
delta_unaccel: event.delta_unaccel(),
|
|
|
|
utime: event.time(),
|
|
|
|
},
|
2023-10-13 02:15:47 +02:00
|
|
|
);
|
|
|
|
|
2023-10-15 09:27:41 +02:00
|
|
|
pointer.frame(self);
|
|
|
|
|
|
|
|
self.schedule_render(
|
|
|
|
&self
|
|
|
|
.focus_state
|
|
|
|
.focused_output
|
|
|
|
.clone()
|
|
|
|
.expect("no focused output"),
|
|
|
|
);
|
2023-06-10 03:29:17 +02:00
|
|
|
}
|
|
|
|
}
|
2023-06-02 19:26:33 +02:00
|
|
|
}
|