2020-05-04 13:04:30 +00:00
|
|
|
use std::{process::Command, sync::atomic::Ordering};
|
2018-05-08 10:47:09 +00:00
|
|
|
|
2021-06-05 17:58:51 +00:00
|
|
|
#[cfg(feature = "udev")]
|
|
|
|
use crate::udev::UdevData;
|
|
|
|
#[cfg(feature = "winit")]
|
|
|
|
use crate::winit::WinitData;
|
2021-06-09 20:12:35 +00:00
|
|
|
use crate::AnvilState;
|
2018-05-08 10:47:09 +00:00
|
|
|
|
2018-10-02 21:37:24 +00:00
|
|
|
use smithay::{
|
|
|
|
backend::input::{
|
2021-06-30 14:58:59 +00:00
|
|
|
self, Device, DeviceCapability, Event, InputBackend, InputEvent, KeyState, KeyboardKeyEvent,
|
|
|
|
PointerAxisEvent, PointerButtonEvent, ProximityState, TabletToolButtonEvent, TabletToolEvent,
|
|
|
|
TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState,
|
2018-10-02 21:37:24 +00:00
|
|
|
},
|
2018-12-15 21:01:24 +00:00
|
|
|
reexports::wayland_server::protocol::wl_pointer,
|
2021-07-05 17:21:15 +00:00
|
|
|
utils::{Logical, Point},
|
2018-10-04 21:37:45 +00:00
|
|
|
wayland::{
|
2021-06-21 19:29:40 +00:00
|
|
|
output::Mode,
|
2020-05-04 13:04:30 +00:00
|
|
|
seat::{keysyms as xkb, AxisFrame, Keysym, ModifiersState},
|
2021-07-05 21:57:25 +00:00
|
|
|
tablet_manager::{TabletDescriptor, TabletSeatTrait},
|
2018-10-04 21:37:45 +00:00
|
|
|
SERIAL_COUNTER as SCOUNTER,
|
|
|
|
},
|
2018-10-02 21:37:24 +00:00
|
|
|
};
|
2018-05-08 10:47:09 +00:00
|
|
|
|
2021-06-23 18:01:28 +00:00
|
|
|
#[cfg(feature = "winit")]
|
|
|
|
use smithay::backend::input::PointerMotionAbsoluteEvent;
|
|
|
|
|
2021-05-31 19:06:58 +00:00
|
|
|
#[cfg(feature = "udev")]
|
2021-06-23 18:01:28 +00:00
|
|
|
use smithay::backend::{input::PointerMotionEvent, session::Session};
|
2021-05-31 19:06:58 +00:00
|
|
|
|
2021-05-30 20:01:36 +00:00
|
|
|
impl<Backend> AnvilState<Backend> {
|
2021-05-30 22:56:37 +00:00
|
|
|
fn keyboard_key_to_action<B: InputBackend>(&mut self, evt: B::KeyboardKeyEvent) -> KeyAction {
|
2018-05-08 10:47:09 +00:00
|
|
|
let keycode = evt.key_code();
|
|
|
|
let state = evt.state();
|
|
|
|
debug!(self.log, "key"; "keycode" => keycode, "state" => format!("{:?}", state));
|
2018-10-04 21:37:45 +00:00
|
|
|
let serial = SCOUNTER.next_serial();
|
2018-05-08 10:47:09 +00:00
|
|
|
let log = &self.log;
|
|
|
|
let time = Event::time(&evt);
|
|
|
|
let mut action = KeyAction::None;
|
2021-06-19 17:32:22 +00:00
|
|
|
let suppressed_keys = &mut self.suppressed_keys;
|
2018-05-08 10:47:09 +00:00
|
|
|
self.keyboard
|
|
|
|
.input(keycode, state, serial, time, |modifiers, keysym| {
|
|
|
|
debug!(log, "keysym";
|
|
|
|
"state" => format!("{:?}", state),
|
|
|
|
"mods" => format!("{:?}", modifiers),
|
|
|
|
"keysym" => ::xkbcommon::xkb::keysym_get_name(keysym)
|
|
|
|
);
|
2021-06-19 17:32:22 +00:00
|
|
|
|
|
|
|
// If the key is pressed and triggered a action
|
|
|
|
// we will not forward the key to the client.
|
|
|
|
// Additionally add the key to the suppressed keys
|
|
|
|
// so that we can decide on a release if the key
|
|
|
|
// should be forwarded to the client or not.
|
|
|
|
if let KeyState::Pressed = state {
|
|
|
|
action = process_keyboard_shortcut(*modifiers, keysym);
|
|
|
|
|
|
|
|
// forward to client only if action == KeyAction::Forward
|
|
|
|
let forward = matches!(action, KeyAction::Forward);
|
|
|
|
|
|
|
|
if !forward {
|
|
|
|
suppressed_keys.push(keysym);
|
|
|
|
}
|
|
|
|
|
|
|
|
forward
|
|
|
|
} else {
|
|
|
|
let suppressed = suppressed_keys.contains(&keysym);
|
|
|
|
|
|
|
|
if suppressed {
|
|
|
|
suppressed_keys.retain(|k| *k != keysym);
|
|
|
|
}
|
|
|
|
|
|
|
|
!suppressed
|
|
|
|
}
|
2018-05-08 10:47:09 +00:00
|
|
|
});
|
2021-06-09 20:46:09 +00:00
|
|
|
action
|
2020-06-11 17:36:57 +00:00
|
|
|
}
|
|
|
|
|
2020-05-04 11:03:36 +00:00
|
|
|
fn on_pointer_button<B: InputBackend>(&mut self, evt: B::PointerButtonEvent) {
|
2018-10-04 21:37:45 +00:00
|
|
|
let serial = SCOUNTER.next_serial();
|
2018-05-08 10:47:09 +00:00
|
|
|
let button = match evt.button() {
|
|
|
|
input::MouseButton::Left => 0x110,
|
|
|
|
input::MouseButton::Right => 0x111,
|
|
|
|
input::MouseButton::Middle => 0x112,
|
|
|
|
input::MouseButton::Other(b) => b as u32,
|
|
|
|
};
|
|
|
|
let state = match evt.state() {
|
2021-06-30 14:58:23 +00:00
|
|
|
input::ButtonState::Pressed => {
|
2018-10-04 15:40:03 +00:00
|
|
|
// change the keyboard focus unless the pointer is grabbed
|
|
|
|
if !self.pointer.is_grabbed() {
|
|
|
|
let under = self
|
|
|
|
.window_map
|
|
|
|
.borrow_mut()
|
2021-05-31 19:06:58 +00:00
|
|
|
.get_surface_and_bring_to_top(self.pointer_location);
|
2018-10-04 15:40:03 +00:00
|
|
|
self.keyboard
|
|
|
|
.set_focus(under.as_ref().map(|&(ref s, _)| s), serial);
|
|
|
|
}
|
2018-05-08 10:47:09 +00:00
|
|
|
wl_pointer::ButtonState::Pressed
|
|
|
|
}
|
2021-06-30 14:58:23 +00:00
|
|
|
input::ButtonState::Released => wl_pointer::ButtonState::Released,
|
2018-05-08 10:47:09 +00:00
|
|
|
};
|
|
|
|
self.pointer.button(button, state, serial, evt.time());
|
|
|
|
}
|
|
|
|
|
2020-05-04 11:03:36 +00:00
|
|
|
fn on_pointer_axis<B: InputBackend>(&mut self, evt: B::PointerAxisEvent) {
|
2018-05-08 10:47:09 +00:00
|
|
|
let source = match evt.source() {
|
|
|
|
input::AxisSource::Continuous => wl_pointer::AxisSource::Continuous,
|
|
|
|
input::AxisSource::Finger => wl_pointer::AxisSource::Finger,
|
|
|
|
input::AxisSource::Wheel | input::AxisSource::WheelTilt => wl_pointer::AxisSource::Wheel,
|
|
|
|
};
|
2018-09-24 22:32:09 +00:00
|
|
|
let horizontal_amount = evt
|
2020-01-01 10:43:16 +00:00
|
|
|
.amount(input::Axis::Horizontal)
|
|
|
|
.unwrap_or_else(|| evt.amount_discrete(input::Axis::Horizontal).unwrap() * 3.0);
|
2018-09-24 22:32:09 +00:00
|
|
|
let vertical_amount = evt
|
2020-01-01 10:43:16 +00:00
|
|
|
.amount(input::Axis::Vertical)
|
|
|
|
.unwrap_or_else(|| evt.amount_discrete(input::Axis::Vertical).unwrap() * 3.0);
|
|
|
|
let horizontal_amount_discrete = evt.amount_discrete(input::Axis::Horizontal);
|
|
|
|
let vertical_amount_discrete = evt.amount_discrete(input::Axis::Vertical);
|
2018-05-08 10:47:09 +00:00
|
|
|
|
|
|
|
{
|
2018-10-04 15:40:03 +00:00
|
|
|
let mut frame = AxisFrame::new(evt.time()).source(source);
|
2018-05-08 10:47:09 +00:00
|
|
|
if horizontal_amount != 0.0 {
|
2018-10-04 15:40:03 +00:00
|
|
|
frame = frame.value(wl_pointer::Axis::HorizontalScroll, horizontal_amount);
|
2018-05-08 10:47:09 +00:00
|
|
|
if let Some(discrete) = horizontal_amount_discrete {
|
2018-10-04 15:40:03 +00:00
|
|
|
frame = frame.discrete(wl_pointer::Axis::HorizontalScroll, discrete as i32);
|
2018-05-08 10:47:09 +00:00
|
|
|
}
|
|
|
|
} else if source == wl_pointer::AxisSource::Finger {
|
2018-10-04 15:40:03 +00:00
|
|
|
frame = frame.stop(wl_pointer::Axis::HorizontalScroll);
|
2018-05-08 10:47:09 +00:00
|
|
|
}
|
|
|
|
if vertical_amount != 0.0 {
|
2018-10-04 15:40:03 +00:00
|
|
|
frame = frame.value(wl_pointer::Axis::VerticalScroll, vertical_amount);
|
2018-05-08 10:47:09 +00:00
|
|
|
if let Some(discrete) = vertical_amount_discrete {
|
2018-10-04 15:40:03 +00:00
|
|
|
frame = frame.discrete(wl_pointer::Axis::VerticalScroll, discrete as i32);
|
2018-05-08 10:47:09 +00:00
|
|
|
}
|
|
|
|
} else if source == wl_pointer::AxisSource::Finger {
|
2018-10-04 15:40:03 +00:00
|
|
|
frame = frame.stop(wl_pointer::Axis::VerticalScroll);
|
2018-05-08 10:47:09 +00:00
|
|
|
}
|
2018-10-04 15:40:03 +00:00
|
|
|
self.pointer.axis(frame);
|
2018-05-08 10:47:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-30 22:56:37 +00:00
|
|
|
#[cfg(feature = "winit")]
|
|
|
|
impl AnvilState<WinitData> {
|
2021-06-21 19:29:40 +00:00
|
|
|
pub fn process_input_event<B>(&mut self, event: InputEvent<B>)
|
|
|
|
where
|
|
|
|
B: InputBackend<SpecialEvent = smithay::backend::winit::WinitEvent>,
|
|
|
|
{
|
|
|
|
use smithay::backend::winit::WinitEvent;
|
|
|
|
|
2021-05-30 22:56:37 +00:00
|
|
|
match event {
|
|
|
|
InputEvent::Keyboard { event, .. } => match self.keyboard_key_to_action::<B>(event) {
|
2021-05-31 19:06:58 +00:00
|
|
|
KeyAction::None | KeyAction::Forward => {}
|
2021-05-30 22:56:37 +00:00
|
|
|
KeyAction::Quit => {
|
|
|
|
info!(self.log, "Quitting.");
|
|
|
|
self.running.store(false, Ordering::SeqCst);
|
|
|
|
}
|
|
|
|
KeyAction::Run(cmd) => {
|
|
|
|
info!(self.log, "Starting program"; "cmd" => cmd.clone());
|
|
|
|
if let Err(e) = Command::new(&cmd).spawn() {
|
|
|
|
error!(self.log,
|
|
|
|
"Failed to start program";
|
|
|
|
"cmd" => cmd,
|
|
|
|
"err" => format!("{:?}", e)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-07-01 17:51:06 +00:00
|
|
|
KeyAction::ScaleUp => {
|
|
|
|
let current_scale = {
|
|
|
|
self.output_map
|
|
|
|
.borrow()
|
|
|
|
.find_by_name(crate::winit::OUTPUT_NAME)
|
|
|
|
.map(|o| o.scale())
|
|
|
|
.unwrap_or(1.0)
|
|
|
|
};
|
|
|
|
self.output_map
|
|
|
|
.borrow_mut()
|
|
|
|
.update_scale_by_name(current_scale + 0.25f32, crate::winit::OUTPUT_NAME);
|
|
|
|
}
|
|
|
|
KeyAction::ScaleDown => {
|
|
|
|
let current_scale = {
|
|
|
|
self.output_map
|
|
|
|
.borrow()
|
|
|
|
.find_by_name(crate::winit::OUTPUT_NAME)
|
|
|
|
.map(|o| o.scale())
|
|
|
|
.unwrap_or(1.0)
|
|
|
|
};
|
|
|
|
|
|
|
|
self.output_map.borrow_mut().update_scale_by_name(
|
|
|
|
f32::max(1.0f32, current_scale - 0.25f32),
|
|
|
|
crate::winit::OUTPUT_NAME,
|
|
|
|
);
|
|
|
|
}
|
2021-05-30 22:56:37 +00:00
|
|
|
action => {
|
|
|
|
warn!(self.log, "Key action {:?} unsupported on winit backend.", action);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
InputEvent::PointerMotionAbsolute { event, .. } => self.on_pointer_move_absolute::<B>(event),
|
|
|
|
InputEvent::PointerButton { event, .. } => self.on_pointer_button::<B>(event),
|
|
|
|
InputEvent::PointerAxis { event, .. } => self.on_pointer_axis::<B>(event),
|
2021-06-21 19:29:40 +00:00
|
|
|
InputEvent::Special(WinitEvent::Resized { size, .. }) => {
|
2021-07-01 17:51:06 +00:00
|
|
|
self.output_map.borrow_mut().update_mode_by_name(
|
2021-06-21 19:29:40 +00:00
|
|
|
Mode {
|
2021-07-05 17:21:15 +00:00
|
|
|
size,
|
2021-06-21 19:29:40 +00:00
|
|
|
refresh: 60_000,
|
|
|
|
},
|
2021-07-01 17:51:06 +00:00
|
|
|
crate::winit::OUTPUT_NAME,
|
2021-06-21 19:29:40 +00:00
|
|
|
);
|
|
|
|
}
|
2021-05-30 22:56:37 +00:00
|
|
|
_ => {
|
|
|
|
// other events are not handled in anvil (yet)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn on_pointer_move_absolute<B: InputBackend>(&mut self, evt: B::PointerMotionAbsoluteEvent) {
|
2021-07-05 17:21:15 +00:00
|
|
|
let output_size = self
|
|
|
|
.output_map
|
|
|
|
.borrow()
|
2021-07-01 17:51:06 +00:00
|
|
|
.find_by_name(crate::winit::OUTPUT_NAME)
|
|
|
|
.map(|o| (o.size().w as u32, o.size().h as u32).into())
|
2021-07-05 17:21:15 +00:00
|
|
|
.unwrap();
|
|
|
|
let pos = evt.position_transformed(output_size);
|
|
|
|
self.pointer_location = pos;
|
2021-05-30 22:56:37 +00:00
|
|
|
let serial = SCOUNTER.next_serial();
|
2021-07-05 17:21:15 +00:00
|
|
|
let under = self.window_map.borrow().get_surface_under(pos);
|
|
|
|
self.pointer.motion(pos, under, serial, evt.time());
|
2021-05-30 22:56:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(feature = "udev")]
|
|
|
|
impl AnvilState<UdevData> {
|
|
|
|
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
|
|
|
|
match event {
|
|
|
|
InputEvent::Keyboard { event, .. } => match self.keyboard_key_to_action::<B>(event) {
|
2021-05-31 19:06:58 +00:00
|
|
|
KeyAction::None | KeyAction::Forward => {}
|
2021-05-30 22:56:37 +00:00
|
|
|
KeyAction::Quit => {
|
|
|
|
info!(self.log, "Quitting.");
|
|
|
|
self.running.store(false, Ordering::SeqCst);
|
|
|
|
}
|
2021-05-31 19:06:58 +00:00
|
|
|
#[cfg(feature = "udev")]
|
|
|
|
KeyAction::VtSwitch(vt) => {
|
|
|
|
info!(self.log, "Trying to switch to vt {}", vt);
|
|
|
|
if let Err(err) = self.backend_data.session.change_vt(vt) {
|
|
|
|
error!(self.log, "Error switching to vt {}: {}", vt, err);
|
|
|
|
}
|
|
|
|
}
|
2021-05-30 22:56:37 +00:00
|
|
|
KeyAction::Run(cmd) => {
|
|
|
|
info!(self.log, "Starting program"; "cmd" => cmd.clone());
|
|
|
|
if let Err(e) = Command::new(&cmd).spawn() {
|
|
|
|
error!(self.log,
|
|
|
|
"Failed to start program";
|
|
|
|
"cmd" => cmd,
|
|
|
|
"err" => format!("{:?}", e)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-05-31 19:06:58 +00:00
|
|
|
KeyAction::Screen(num) => {
|
2021-07-01 17:51:06 +00:00
|
|
|
let geometry = self.output_map.borrow().find_by_index(num).map(|o| o.geometry());
|
2021-06-21 19:29:40 +00:00
|
|
|
|
|
|
|
if let Some(geometry) = geometry {
|
2021-07-05 17:21:15 +00:00
|
|
|
let x = geometry.loc.x as f64 + geometry.size.w as f64 / 2.0;
|
|
|
|
let y = geometry.size.h as f64 / 2.0;
|
|
|
|
self.pointer_location = (x, y).into()
|
2021-05-31 19:06:58 +00:00
|
|
|
}
|
2021-05-30 22:56:37 +00:00
|
|
|
}
|
2021-07-01 17:51:06 +00:00
|
|
|
KeyAction::ScaleUp => {
|
|
|
|
let mut output_map = self.output_map.borrow_mut();
|
|
|
|
|
|
|
|
let output = output_map
|
|
|
|
.find_by_position(self.pointer_location.to_i32_round())
|
|
|
|
.map(|o| (o.name().to_owned(), o.location(), o.scale()));
|
|
|
|
|
|
|
|
if let Some((name, output_location, scale)) = output {
|
|
|
|
let new_scale = scale + 0.25;
|
|
|
|
|
|
|
|
output_map.update_scale_by_name(new_scale, name);
|
|
|
|
|
|
|
|
let rescale = scale as f64 / new_scale as f64;
|
|
|
|
let output_location = output_location.to_f64();
|
|
|
|
let mut pointer_output_location = self.pointer_location - output_location;
|
|
|
|
pointer_output_location.x *= rescale;
|
|
|
|
pointer_output_location.y *= rescale;
|
|
|
|
self.pointer_location = output_location + pointer_output_location;
|
|
|
|
|
|
|
|
let under = self.window_map.borrow().get_surface_under(self.pointer_location);
|
|
|
|
self.pointer
|
|
|
|
.motion(self.pointer_location, under, SCOUNTER.next_serial(), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
KeyAction::ScaleDown => {
|
|
|
|
let mut output_map = self.output_map.borrow_mut();
|
|
|
|
|
|
|
|
let output = output_map
|
|
|
|
.find_by_position(self.pointer_location.to_i32_round())
|
|
|
|
.map(|o| (o.name().to_owned(), o.location(), o.scale()));
|
|
|
|
|
|
|
|
if let Some((name, output_location, scale)) = output {
|
|
|
|
let new_scale = f32::max(1.0, scale - 0.25);
|
|
|
|
output_map.update_scale_by_name(new_scale, name);
|
|
|
|
|
|
|
|
let rescale = scale as f64 / new_scale as f64;
|
|
|
|
let output_location = output_location.to_f64();
|
|
|
|
let mut pointer_output_location = self.pointer_location - output_location;
|
|
|
|
pointer_output_location.x *= rescale;
|
|
|
|
pointer_output_location.y *= rescale;
|
|
|
|
self.pointer_location = output_location + pointer_output_location;
|
|
|
|
|
|
|
|
let under = self.window_map.borrow().get_surface_under(self.pointer_location);
|
|
|
|
self.pointer
|
|
|
|
.motion(self.pointer_location, under, SCOUNTER.next_serial(), 0);
|
|
|
|
}
|
|
|
|
}
|
2021-05-30 22:56:37 +00:00
|
|
|
},
|
|
|
|
InputEvent::PointerMotion { event, .. } => self.on_pointer_move::<B>(event),
|
|
|
|
InputEvent::PointerButton { event, .. } => self.on_pointer_button::<B>(event),
|
|
|
|
InputEvent::PointerAxis { event, .. } => self.on_pointer_axis::<B>(event),
|
2021-06-30 14:58:59 +00:00
|
|
|
InputEvent::TabletToolAxis { event, .. } => self.on_tablet_tool_axis::<B>(event),
|
|
|
|
InputEvent::TabletToolProximity { event, .. } => self.on_tablet_tool_proximity::<B>(event),
|
|
|
|
InputEvent::TabletToolTip { event, .. } => self.on_tablet_tool_tip::<B>(event),
|
|
|
|
InputEvent::TabletToolButton { event, .. } => self.on_tablet_button::<B>(event),
|
|
|
|
InputEvent::DeviceAdded { device } => {
|
|
|
|
if device.has_capability(DeviceCapability::TabletTool) {
|
2021-07-05 21:57:25 +00:00
|
|
|
self.seat
|
|
|
|
.tablet_seat()
|
|
|
|
.add_tablet(&TabletDescriptor::from(&device));
|
2021-06-30 14:58:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
InputEvent::DeviceRemoved { device } => {
|
|
|
|
if device.has_capability(DeviceCapability::TabletTool) {
|
|
|
|
let tablet_seat = self.seat.tablet_seat();
|
|
|
|
|
2021-07-05 21:57:25 +00:00
|
|
|
tablet_seat.remove_tablet(&TabletDescriptor::from(&device));
|
2021-06-30 14:58:59 +00:00
|
|
|
|
|
|
|
// If there are no tablets in seat we can remove all tools
|
|
|
|
if tablet_seat.count_tablets() == 0 {
|
|
|
|
tablet_seat.clear_tools();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-05-30 22:56:37 +00:00
|
|
|
_ => {
|
|
|
|
// other events are not handled in anvil (yet)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn on_pointer_move<B: InputBackend>(&mut self, evt: B::PointerMotionEvent) {
|
|
|
|
let serial = SCOUNTER.next_serial();
|
2021-07-05 17:21:15 +00:00
|
|
|
self.pointer_location += evt.delta();
|
2021-05-30 22:56:37 +00:00
|
|
|
|
|
|
|
// clamp to screen limits
|
|
|
|
// this event is never generated by winit
|
2021-05-31 19:06:58 +00:00
|
|
|
self.pointer_location = self.clamp_coords(self.pointer_location);
|
2021-05-30 22:56:37 +00:00
|
|
|
|
2021-05-31 19:06:58 +00:00
|
|
|
let under = self.window_map.borrow().get_surface_under(self.pointer_location);
|
|
|
|
self.pointer
|
|
|
|
.motion(self.pointer_location, under, serial, evt.time());
|
2021-05-30 22:56:37 +00:00
|
|
|
}
|
|
|
|
|
2021-06-30 14:58:59 +00:00
|
|
|
fn on_tablet_tool_axis<B: InputBackend>(&mut self, evt: B::TabletToolAxisEvent) {
|
2021-07-05 21:57:25 +00:00
|
|
|
let output_map = self.output_map.borrow();
|
|
|
|
let pointer_location = &mut self.pointer_location;
|
|
|
|
let tablet_seat = self.seat.tablet_seat();
|
|
|
|
let window_map = self.window_map.borrow();
|
|
|
|
|
2021-07-01 17:51:06 +00:00
|
|
|
let output_geometry = output_map.with_primary().map(|o| o.geometry());
|
2021-07-05 21:57:25 +00:00
|
|
|
|
2021-07-01 17:51:06 +00:00
|
|
|
if let Some(rect) = output_geometry {
|
|
|
|
let rect_size = (rect.size.w as u32, rect.size.h as u32).into();
|
|
|
|
*pointer_location = evt.position_transformed(rect_size) + rect.loc.to_f64();
|
2021-07-05 21:57:25 +00:00
|
|
|
|
2021-07-01 17:51:06 +00:00
|
|
|
let under = window_map.get_surface_under(*pointer_location);
|
|
|
|
let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&evt.device()));
|
|
|
|
let tool = tablet_seat.get_tool(&evt.tool());
|
2021-06-30 14:58:59 +00:00
|
|
|
|
2021-07-01 17:51:06 +00:00
|
|
|
if let (Some(tablet), Some(tool)) = (tablet, tool) {
|
|
|
|
if evt.pressure_has_changed() {
|
|
|
|
tool.pressure(evt.pressure());
|
2021-06-30 14:58:59 +00:00
|
|
|
}
|
2021-07-01 17:51:06 +00:00
|
|
|
if evt.distance_has_changed() {
|
|
|
|
tool.distance(evt.distance());
|
|
|
|
}
|
|
|
|
if evt.tilt_has_changed() {
|
|
|
|
tool.tilt(evt.tilt());
|
|
|
|
}
|
|
|
|
if evt.slider_has_changed() {
|
|
|
|
tool.slider_position(evt.slider_position());
|
|
|
|
}
|
|
|
|
if evt.rotation_has_changed() {
|
|
|
|
tool.rotation(evt.rotation());
|
|
|
|
}
|
|
|
|
if evt.wheel_has_changed() {
|
|
|
|
tool.wheel(evt.wheel_delta(), evt.wheel_delta_discrete());
|
|
|
|
}
|
|
|
|
|
|
|
|
tool.motion(
|
|
|
|
*pointer_location,
|
|
|
|
under,
|
|
|
|
&tablet,
|
|
|
|
SCOUNTER.next_serial(),
|
|
|
|
evt.time(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2021-07-05 21:57:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn on_tablet_tool_proximity<B: InputBackend>(&mut self, evt: B::TabletToolProximityEvent) {
|
|
|
|
let output_map = self.output_map.borrow();
|
|
|
|
let pointer_location = &mut self.pointer_location;
|
|
|
|
let tablet_seat = self.seat.tablet_seat();
|
|
|
|
let window_map = self.window_map.borrow();
|
|
|
|
|
2021-07-01 17:51:06 +00:00
|
|
|
let output_geometry = output_map.with_primary().map(|o| o.geometry());
|
|
|
|
|
|
|
|
if let Some(rect) = output_geometry {
|
|
|
|
let tool = evt.tool();
|
|
|
|
tablet_seat.add_tool(&tool);
|
|
|
|
|
|
|
|
let rect_size = (rect.size.h as u32, rect.size.w as u32).into();
|
|
|
|
*pointer_location = evt.position_transformed(rect_size) + rect.loc.to_f64();
|
|
|
|
|
|
|
|
let under = window_map.get_surface_under(*pointer_location);
|
|
|
|
let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&evt.device()));
|
|
|
|
let tool = tablet_seat.get_tool(&tool);
|
|
|
|
|
|
|
|
if let (Some(under), Some(tablet), Some(tool)) = (under, tablet, tool) {
|
|
|
|
match evt.state() {
|
|
|
|
ProximityState::In => tool.proximity_in(
|
|
|
|
*pointer_location,
|
|
|
|
under,
|
|
|
|
&tablet,
|
|
|
|
SCOUNTER.next_serial(),
|
|
|
|
evt.time(),
|
|
|
|
),
|
|
|
|
ProximityState::Out => tool.proximity_out(evt.time()),
|
2021-07-05 21:57:25 +00:00
|
|
|
}
|
2021-07-01 17:51:06 +00:00
|
|
|
}
|
|
|
|
}
|
2021-06-30 14:58:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn on_tablet_tool_tip<B: InputBackend>(&mut self, evt: B::TabletToolTipEvent) {
|
|
|
|
let tool = self.seat.tablet_seat().get_tool(&evt.tool());
|
|
|
|
|
|
|
|
if let Some(tool) = tool {
|
|
|
|
match evt.tip_state() {
|
|
|
|
TabletToolTipState::Down => {
|
|
|
|
tool.tip_down(SCOUNTER.next_serial(), evt.time());
|
|
|
|
|
|
|
|
// change the keyboard focus unless the pointer is grabbed
|
|
|
|
if !self.pointer.is_grabbed() {
|
|
|
|
let under = self
|
|
|
|
.window_map
|
|
|
|
.borrow_mut()
|
|
|
|
.get_surface_and_bring_to_top(self.pointer_location);
|
|
|
|
|
|
|
|
let serial = SCOUNTER.next_serial();
|
|
|
|
self.keyboard
|
|
|
|
.set_focus(under.as_ref().map(|&(ref s, _)| s), serial);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
TabletToolTipState::Up => {
|
|
|
|
tool.tip_up(evt.time());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn on_tablet_button<B: InputBackend>(&mut self, evt: B::TabletToolButtonEvent) {
|
|
|
|
let tool = self.seat.tablet_seat().get_tool(&evt.tool());
|
|
|
|
|
|
|
|
if let Some(tool) = tool {
|
|
|
|
tool.button(
|
|
|
|
evt.button(),
|
|
|
|
evt.button_state(),
|
|
|
|
SCOUNTER.next_serial(),
|
|
|
|
evt.time(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-05 17:21:15 +00:00
|
|
|
fn clamp_coords(&self, pos: Point<f64, Logical>) -> Point<f64, Logical> {
|
2021-06-21 19:29:40 +00:00
|
|
|
if self.output_map.borrow().is_empty() {
|
2021-05-30 22:56:37 +00:00
|
|
|
return pos;
|
|
|
|
}
|
|
|
|
|
2021-07-05 17:21:15 +00:00
|
|
|
let (pos_x, pos_y) = pos.into();
|
2021-06-30 17:58:13 +00:00
|
|
|
let output_map = self.output_map.borrow();
|
|
|
|
let max_x = output_map.width();
|
2021-06-21 19:29:40 +00:00
|
|
|
let clamped_x = pos_x.max(0.0).min(max_x as f64);
|
2021-06-30 17:58:13 +00:00
|
|
|
let max_y = output_map.height(clamped_x as i32);
|
2021-05-30 22:56:37 +00:00
|
|
|
|
2021-06-30 17:58:13 +00:00
|
|
|
if let Some(max_y) = max_y {
|
|
|
|
let clamped_y = pos_y.max(0.0).min(max_y as f64);
|
|
|
|
|
2021-07-05 17:21:15 +00:00
|
|
|
(clamped_x, clamped_y).into()
|
2021-06-30 17:58:13 +00:00
|
|
|
} else {
|
2021-07-05 17:21:15 +00:00
|
|
|
(clamped_x, pos_y).into()
|
2021-06-30 17:58:13 +00:00
|
|
|
}
|
2021-05-30 22:56:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-08 10:47:09 +00:00
|
|
|
/// Possible results of a keyboard action
|
2021-05-30 22:56:37 +00:00
|
|
|
#[derive(Debug)]
|
2018-05-08 10:47:09 +00:00
|
|
|
enum KeyAction {
|
|
|
|
/// Quit the compositor
|
|
|
|
Quit,
|
|
|
|
/// Trigger a vt-switch
|
|
|
|
VtSwitch(i32),
|
|
|
|
/// run a command
|
|
|
|
Run(String),
|
2020-06-11 17:46:29 +00:00
|
|
|
/// Switch the current screen
|
|
|
|
Screen(usize),
|
2021-07-01 17:51:06 +00:00
|
|
|
ScaleUp,
|
|
|
|
ScaleDown,
|
2018-05-08 10:47:09 +00:00
|
|
|
/// Forward the key to the client
|
|
|
|
Forward,
|
|
|
|
/// Do nothing more
|
|
|
|
None,
|
|
|
|
}
|
|
|
|
|
2020-01-01 10:43:16 +00:00
|
|
|
fn process_keyboard_shortcut(modifiers: ModifiersState, keysym: Keysym) -> KeyAction {
|
2018-06-27 12:04:29 +00:00
|
|
|
if modifiers.ctrl && modifiers.alt && keysym == xkb::KEY_BackSpace
|
2018-09-24 22:32:09 +00:00
|
|
|
|| modifiers.logo && keysym == xkb::KEY_q
|
|
|
|
{
|
|
|
|
// ctrl+alt+backspace = quit
|
|
|
|
// logo + q = quit
|
|
|
|
KeyAction::Quit
|
2021-04-28 22:31:49 +00:00
|
|
|
} else if (xkb::KEY_XF86Switch_VT_1..=xkb::KEY_XF86Switch_VT_12).contains(&keysym) {
|
2018-05-08 10:47:09 +00:00
|
|
|
// VTSwicth
|
|
|
|
KeyAction::VtSwitch((keysym - xkb::KEY_XF86Switch_VT_1 + 1) as i32)
|
|
|
|
} else if modifiers.logo && keysym == xkb::KEY_Return {
|
|
|
|
// run terminal
|
|
|
|
KeyAction::Run("weston-terminal".into())
|
2020-06-11 17:46:29 +00:00
|
|
|
} else if modifiers.logo && keysym >= xkb::KEY_1 && keysym <= xkb::KEY_9 {
|
|
|
|
KeyAction::Screen((keysym - xkb::KEY_1) as usize)
|
2021-07-01 17:51:06 +00:00
|
|
|
} else if modifiers.logo && modifiers.shift && keysym == xkb::KEY_M {
|
|
|
|
KeyAction::ScaleDown
|
|
|
|
} else if modifiers.logo && modifiers.shift && keysym == xkb::KEY_P {
|
|
|
|
KeyAction::ScaleUp
|
2018-05-08 10:47:09 +00:00
|
|
|
} else {
|
|
|
|
KeyAction::Forward
|
|
|
|
}
|
|
|
|
}
|