cosmic-comp/src/input/mod.rs

845 lines
43 KiB
Rust
Raw Normal View History

2021-12-21 18:57:09 +01:00
// SPDX-License-Identifier: GPL-3.0-only
2022-07-08 19:15:56 +02:00
use crate::{
2022-07-29 14:23:23 +02:00
config::{Action, Config},
2022-08-30 13:28:36 +02:00
shell::{grabs::SeatMoveGrabState, Workspace},
2022-08-31 13:01:23 +02:00
state::Common,
2022-07-08 19:15:56 +02:00
utils::prelude::*,
};
2021-12-21 18:57:09 +01:00
use smithay::{
2022-08-31 13:01:23 +02:00
backend::input::{
AbsolutePositionEvent, Axis, AxisSource, Device, DeviceCapability, InputBackend,
InputEvent, KeyState, PointerAxisEvent,
},
desktop::{layer_map_for_output, Kind, WindowSurfaceType},
2022-08-31 13:01:23 +02:00
input::{
keyboard::{keysyms, FilterResult, KeysymHandle},
pointer::{AxisFrame, ButtonEvent, CursorImageStatus, MotionEvent},
Seat, SeatState,
2021-12-21 18:57:09 +01:00
},
2022-08-31 13:01:23 +02:00
reexports::wayland_server::{protocol::wl_surface::WlSurface, DisplayHandle},
utils::{Buffer, Logical, Point, Rectangle, Size, SERIAL_COUNTER},
wayland::{output::Output, shell::wlr_layer::Layer as WlrLayer},
2021-12-21 18:57:09 +01:00
};
2022-08-31 13:01:23 +02:00
2021-12-21 18:57:09 +01:00
use std::{cell::RefCell, collections::HashMap};
2022-05-03 13:37:51 +02:00
use xkbcommon::xkb::KEY_XF86Switch_VT_12;
2021-12-21 18:57:09 +01:00
2022-07-08 14:00:13 +02:00
crate::utils::id_gen!(next_seat_id, SEAT_ID, SEAT_IDS);
#[repr(transparent)]
pub struct SeatId(pub usize);
2021-12-21 18:57:09 +01:00
pub struct ActiveOutput(pub RefCell<Output>);
#[derive(Default)]
2022-01-11 17:22:23 +01:00
pub struct SupressedKeys(RefCell<Vec<u32>>);
#[derive(Default)]
2021-12-22 20:14:09 +01:00
pub struct Devices(RefCell<HashMap<String, Vec<DeviceCapability>>>);
2022-07-08 14:00:13 +02:00
impl Default for SeatId {
fn default() -> SeatId {
SeatId(next_seat_id())
}
}
impl Drop for SeatId {
fn drop(&mut self) {
SEAT_IDS.lock().unwrap().remove(&self.0);
}
}
2022-01-11 17:22:23 +01:00
impl SupressedKeys {
fn add(&self, keysym: &KeysymHandle) {
self.0.borrow_mut().push(keysym.raw_code());
}
fn filter(&self, keysym: &KeysymHandle) -> bool {
let mut keys = self.0.borrow_mut();
if let Some(i) = keys.iter().position(|x| *x == keysym.raw_code()) {
keys.remove(i);
true
} else {
false
}
}
}
2021-12-22 20:14:09 +01:00
impl Devices {
fn add_device<D: Device>(&self, device: &D) -> Vec<DeviceCapability> {
let id = device.id();
let mut map = self.0.borrow_mut();
let caps = [DeviceCapability::Keyboard, DeviceCapability::Pointer]
.iter()
.cloned()
.filter(|c| device.has_capability(*c))
.collect::<Vec<_>>();
let new_caps = caps
.iter()
.cloned()
.filter(|c| map.values().flatten().all(|has| *c != *has))
.collect::<Vec<_>>();
map.insert(id, caps);
new_caps
}
pub fn has_device<D: Device>(&self, device: &D) -> bool {
self.0.borrow().contains_key(&device.id())
}
fn remove_device<D: Device>(&self, device: &D) -> Vec<DeviceCapability> {
let id = device.id();
let mut map = self.0.borrow_mut();
map.remove(&id)
.unwrap_or(Vec::new())
.into_iter()
.filter(|c| map.values().flatten().all(|has| *c != *has))
.collect()
}
}
2022-08-31 13:01:23 +02:00
pub fn add_seat(
dh: &DisplayHandle,
seat_state: &mut SeatState<State>,
config: &Config,
name: String,
) -> Seat<State> {
let mut seat = seat_state.new_wl_seat(dh, name, None);
2021-12-22 20:14:09 +01:00
let userdata = seat.user_data();
2022-07-08 14:00:13 +02:00
userdata.insert_if_missing(SeatId::default);
userdata.insert_if_missing(Devices::default);
userdata.insert_if_missing(SupressedKeys::default);
2022-07-08 19:15:56 +02:00
userdata.insert_if_missing(SeatMoveGrabState::default);
2022-03-24 20:32:31 +01:00
userdata.insert_if_missing(|| RefCell::new(CursorImageStatus::Default));
// A lot of clients bind keyboard and pointer unconditionally once on launch..
// Initial clients might race the compositor on adding periheral and
// end up in a state, where they are not able to receive input.
// Additionally a lot of clients don't handle keyboards/pointer objects being
// removed very well either and we don't want to crash applications, because the
// user is replugging their keyboard or mouse.
//
// So instead of doing the right thing (and initialize these capabilities as matching
// devices appear), we have to surrender to reality and just always expose a keyboard and pointer.
2022-07-29 14:23:23 +02:00
let conf = config.xkb_config();
2022-08-31 13:01:23 +02:00
let _ = seat.add_keyboard((&conf).into(), 200, 25);
let _ = seat.add_pointer();
2021-12-21 18:57:09 +01:00
seat
}
2022-04-25 12:35:55 +02:00
impl State {
2022-08-31 13:01:23 +02:00
pub fn process_input_event<B: InputBackend>(&mut self, event: InputEvent<B>) {
2021-12-22 20:14:09 +01:00
use smithay::backend::input::Event;
match event {
InputEvent::DeviceAdded { device } => {
2022-04-25 12:35:55 +02:00
let seat = &mut self.common.last_active_seat;
2021-12-22 20:14:09 +01:00
let userdata = seat.user_data();
let devices = userdata.get::<Devices>().unwrap();
for cap in devices.add_device(&device) {
match cap {
// TODO: Handle touch, tablet
2021-12-22 20:14:09 +01:00
_ => {}
}
}
2022-01-11 17:22:23 +01:00
#[cfg(feature = "debug")]
{
2022-04-25 12:35:55 +02:00
self.common.egui.debug_state.handle_device_added(&device);
self.common.egui.log_state.handle_device_added(&device);
2022-01-11 17:22:23 +01:00
}
2021-12-22 20:14:09 +01:00
}
InputEvent::DeviceRemoved { device } => {
2022-04-25 12:35:55 +02:00
for seat in &mut self.common.seats {
2021-12-22 20:14:09 +01:00
let userdata = seat.user_data();
let devices = userdata.get::<Devices>().unwrap();
if devices.has_device(&device) {
for cap in devices.remove_device(&device) {
match cap {
// TODO: Handle touch, tablet
2022-08-30 13:28:36 +02:00
_ => {}
2021-12-22 20:14:09 +01:00
}
}
break;
}
}
2022-01-11 17:22:23 +01:00
#[cfg(feature = "debug")]
{
2022-04-25 12:35:55 +02:00
self.common.egui.debug_state.handle_device_added(&device);
self.common.egui.log_state.handle_device_added(&device);
2022-01-11 17:22:23 +01:00
}
2021-12-22 20:14:09 +01:00
}
InputEvent::Keyboard { event, .. } => {
use smithay::backend::input::KeyboardKeyEvent;
let device = event.device();
2022-04-25 12:35:55 +02:00
for seat in self.common.seats.clone().iter() {
2021-12-22 20:14:09 +01:00
let userdata = seat.user_data();
let devices = userdata.get::<Devices>().unwrap();
if devices.has_device(&device) {
let keycode = event.key_code();
let state = event.state();
slog_scope::trace!("key"; "keycode" => keycode, "state" => format!("{:?}", state));
let serial = SERIAL_COUNTER.next_serial();
let time = Event::time(&event);
2022-03-30 23:24:29 +02:00
if let Some(action) = seat
.get_keyboard()
.unwrap()
2022-08-31 13:01:23 +02:00
.input(
self,
keycode,
state,
serial,
time,
|data, modifiers, handle| {
if state == KeyState::Released
&& userdata.get::<SupressedKeys>().unwrap().filter(&handle)
2022-01-11 17:22:23 +01:00
{
2022-08-31 13:01:23 +02:00
return FilterResult::Intercept(None);
2022-01-11 17:22:23 +01:00
}
2022-08-31 13:01:23 +02:00
#[cfg(feature = "debug")]
{
if data.common.seats.iter().position(|x| x == seat).unwrap()
== 0
&& data.common.egui.active
{
if data.common.egui.debug_state.wants_keyboard() {
data.common.egui.debug_state.handle_keyboard(
&handle,
state == KeyState::Pressed,
modifiers.clone(),
);
userdata
.get::<SupressedKeys>()
.unwrap()
.add(&handle);
return FilterResult::Intercept(None);
}
if data.common.egui.log_state.wants_keyboard() {
data.common.egui.log_state.handle_keyboard(
&handle,
state == KeyState::Pressed,
modifiers.clone(),
);
userdata
.get::<SupressedKeys>()
.unwrap()
.add(&handle);
return FilterResult::Intercept(None);
}
}
2022-04-25 12:35:55 +02:00
}
2022-03-28 23:45:30 +02:00
if state == KeyState::Pressed
2022-08-31 13:01:23 +02:00
&& (keysyms::KEY_XF86Switch_VT_1..=KEY_XF86Switch_VT_12)
.contains(&handle.modified_sym())
2022-03-28 23:45:30 +02:00
{
2022-08-31 13:01:23 +02:00
if let Err(err) = data.backend.kms().switch_vt(
(handle.modified_sym() - keysyms::KEY_XF86Switch_VT_1
+ 1)
as i32,
) {
slog_scope::error!(
"Failed switching virtual terminal: {}",
err
);
}
2022-03-30 23:24:29 +02:00
userdata.get::<SupressedKeys>().unwrap().add(&handle);
2022-08-31 13:01:23 +02:00
return FilterResult::Intercept(None);
}
// here we can handle global shortcuts and the like
for (binding, action) in
data.common.config.static_conf.key_bindings.iter()
{
if state == KeyState::Pressed
&& binding.modifiers == *modifiers
&& handle.raw_syms().contains(&binding.key)
{
userdata.get::<SupressedKeys>().unwrap().add(&handle);
return FilterResult::Intercept(Some(action.clone()));
}
2022-03-28 23:45:30 +02:00
}
2022-01-11 17:22:23 +01:00
2022-08-31 13:01:23 +02:00
FilterResult::Forward
},
)
2022-03-30 23:24:29 +02:00
.flatten()
{
match action {
Action::Terminate => {
2022-04-25 12:35:55 +02:00
self.common.should_stop = true;
2022-03-30 23:24:29 +02:00
}
#[cfg(feature = "debug")]
Action::Debug => {
2022-04-25 12:35:55 +02:00
self.common.egui.active = !self.common.egui.active;
2022-03-30 23:24:29 +02:00
}
#[cfg(not(feature = "debug"))]
Action::Debug => {
slog_scope::info!("Debug overlay not included in this version")
}
Action::Close => {
2022-04-25 12:35:55 +02:00
let current_output = active_output(seat, &self.common);
2022-05-03 13:37:51 +02:00
let workspace =
self.common.shell.active_space_mut(&current_output);
2022-03-30 23:24:29 +02:00
if let Some(window) = workspace.focus_stack(seat).last() {
#[allow(irrefutable_let_patterns)]
if let Kind::Xdg(xdg) = &window.toplevel() {
xdg.send_close();
}
}
}
Action::Workspace(key_num) => {
2022-04-25 12:35:55 +02:00
let current_output = active_output(seat, &self.common);
2022-03-30 23:24:29 +02:00
let workspace = match key_num {
0 => 9,
x => x - 1,
};
if let Some(motion_event) = self.common.shell.activate(
2022-05-03 13:37:51 +02:00
seat,
&current_output,
workspace as usize,
) {
if let Some(ptr) = seat.get_pointer() {
2022-08-31 13:01:23 +02:00
ptr.motion(self, None, &motion_event);
}
}
2022-03-30 23:24:29 +02:00
}
Action::MoveToWorkspace(key_num) => {
2022-04-25 12:35:55 +02:00
let current_output = active_output(seat, &self.common);
2022-03-30 23:24:29 +02:00
let workspace = match key_num {
0 => 9,
x => x - 1,
};
2022-04-25 12:35:55 +02:00
self.common.shell.move_current_window(
2022-03-30 23:24:29 +02:00
seat,
&current_output,
workspace as usize,
);
}
Action::Focus(focus) => {
2022-04-25 12:35:55 +02:00
let current_output = active_output(seat, &self.common);
2022-07-04 16:00:29 +02:00
let workspace =
self.common.shell.active_space_mut(&current_output);
let focus_stack = workspace.focus_stack(seat);
if let Some(window) = workspace.tiling_layer.move_focus(
2022-08-31 13:01:23 +02:00
focus,
seat,
&mut workspace.space,
2022-07-04 16:00:29 +02:00
focus_stack.iter(),
) {
2022-07-11 22:51:55 +02:00
std::mem::drop(focus_stack);
2022-08-31 13:01:23 +02:00
Common::set_focus(
self,
2022-07-04 16:00:29 +02:00
Some(window.toplevel().wl_surface()),
seat,
None,
);
}
2022-03-30 23:24:29 +02:00
}
2022-04-22 15:18:28 +02:00
Action::Fullscreen => {
2022-04-25 12:35:55 +02:00
let current_output = active_output(seat, &self.common);
2022-05-03 13:37:51 +02:00
let workspace =
self.common.shell.active_space_mut(&current_output);
2022-04-22 15:18:28 +02:00
let focused_window = workspace.focus_stack(seat).last();
if let Some(window) = focused_window {
workspace.fullscreen_toggle(&window, &current_output);
}
}
2022-03-30 23:24:29 +02:00
Action::Orientation(orientation) => {
2022-04-25 12:35:55 +02:00
let output = active_output(seat, &self.common);
2022-07-04 16:00:29 +02:00
let workspace = self.common.shell.active_space_mut(&output);
let focus_stack = workspace.focus_stack(seat);
2022-07-04 16:00:29 +02:00
workspace.tiling_layer.update_orientation(
2022-08-31 13:01:23 +02:00
orientation,
2022-07-04 16:00:29 +02:00
&seat,
&mut workspace.space,
focus_stack.iter(),
);
2022-03-30 23:24:29 +02:00
}
Action::ToggleTiling => {
let output = active_output(seat, &self.common);
let workspace = self.common.shell.active_space_mut(&output);
workspace.toggle_tiling(seat);
}
Action::ToggleWindowFloating => {
let output = active_output(seat, &self.common);
let workspace = self.common.shell.active_space_mut(&output);
workspace.toggle_floating_window(seat);
}
2022-03-30 23:24:29 +02:00
Action::Spawn(command) => {
if let Err(err) = std::process::Command::new("/bin/sh")
.arg("-c")
.arg(command)
2022-04-25 12:35:55 +02:00
.env("WAYLAND_DISPLAY", &self.common.socket)
.env_remove("COSMIC_SESSION_SOCK")
2022-03-30 23:24:29 +02:00
.spawn()
{
slog_scope::warn!("Failed to spawn: {}", err);
}
}
2022-07-20 17:25:36 +02:00
Action::Screenshot => {
let home = match std::env::var("HOME") {
Ok(home) => home,
Err(err) => {
2022-08-30 13:28:36 +02:00
slog_scope::error!(
"$HOME is not set, can't save screenshots: {}",
err
);
2022-07-20 17:25:36 +02:00
break;
}
};
2022-08-30 13:28:36 +02:00
let timestamp = match std::time::SystemTime::UNIX_EPOCH
.elapsed()
{
2022-07-20 17:25:36 +02:00
Ok(duration) => duration.as_secs(),
Err(err) => {
slog_scope::error!("Unable to get timestamp, can't save screenshots: {}", err);
break;
}
};
for output in self.common.shell.outputs.clone().into_iter() {
2022-08-30 13:28:36 +02:00
match self
.backend
.offscreen_for_output(&output, &mut self.common)
{
Ok((buffer, size)) => {
2022-07-20 17:25:36 +02:00
let mut path = std::path::PathBuf::new();
path.push(&home);
2022-08-30 13:28:36 +02:00
path.push(format!(
"{}_{}.png",
output.name(),
timestamp
));
2022-08-30 13:28:36 +02:00
fn write_png(
path: impl AsRef<std::path::Path>,
data: Vec<u8>,
size: Size<i32, Buffer>,
) -> anyhow::Result<()>
{
use std::{fs, io};
2022-08-30 13:28:36 +02:00
let file = io::BufWriter::new(
fs::File::create(&path)?,
);
let mut encoder = png::Encoder::new(
file,
size.w as u32,
size.h as u32,
);
encoder.set_color(png::ColorType::Rgba);
encoder.set_depth(png::BitDepth::Eight);
let mut writer = encoder.write_header()?;
writer.write_image_data(&data)?;
Ok(())
}
if let Err(err) = write_png(&path, buffer, size) {
2022-08-30 13:28:36 +02:00
slog_scope::error!(
"Unable to save screenshot at {}: {}",
path.display(),
err
);
2022-07-20 17:25:36 +02:00
}
2022-08-30 13:28:36 +02:00
}
Err(err) => slog_scope::error!(
"Could not save screenshot for output {}: {}",
output.name(),
err
),
2022-07-20 17:25:36 +02:00
}
}
}
2022-03-30 23:24:29 +02:00
}
}
2021-12-22 20:14:09 +01:00
break;
}
}
}
InputEvent::PointerMotion { event, .. } => {
use smithay::backend::input::PointerMotionEvent;
let device = event.device();
2022-04-25 12:35:55 +02:00
for seat in self.common.seats.clone().iter() {
2021-12-22 20:14:09 +01:00
let userdata = seat.user_data();
let devices = userdata.get::<Devices>().unwrap();
if devices.has_device(&device) {
2022-04-25 12:35:55 +02:00
let current_output = active_output(seat, &self.common);
2021-12-22 20:14:09 +01:00
let mut position = seat.get_pointer().unwrap().current_location();
position += event.delta();
let output = self
2022-04-25 12:35:55 +02:00
.common
2022-03-24 20:32:31 +01:00
.shell
2021-12-22 20:14:09 +01:00
.outputs()
2022-07-04 16:00:29 +02:00
.find(|output| output.geometry().to_f64().contains(position))
2021-12-28 16:23:12 +01:00
.cloned()
.unwrap_or(current_output.clone());
if output != current_output {
set_active_output(seat, &output);
2021-12-22 20:14:09 +01:00
}
let output_geometry = output.geometry();
2021-12-22 20:14:09 +01:00
position.x = 0.0f64
.max(position.x)
.min((output_geometry.loc.x + output_geometry.size.w) as f64);
position.y = 0.0f64
.max(position.y)
.min((output_geometry.loc.y + output_geometry.size.h) as f64);
let serial = SERIAL_COUNTER.next_serial();
2022-05-03 13:37:51 +02:00
let relative_pos = self
.common
.shell
.space_relative_output_geometry(position, &output);
2022-04-25 12:35:55 +02:00
let workspace = self.common.shell.active_space_mut(&output);
let under = State::surface_under(
position,
relative_pos,
&output,
output_geometry,
2022-04-22 15:18:28 +02:00
&workspace,
);
2022-07-04 16:00:29 +02:00
seat.get_pointer().unwrap().motion(
self,
2022-08-31 13:01:23 +02:00
under,
2022-07-04 16:00:29 +02:00
&MotionEvent {
location: position,
serial,
2022-07-04 16:00:29 +02:00
time: event.time(),
},
);
2021-12-28 16:23:12 +01:00
2022-01-11 17:22:23 +01:00
#[cfg(feature = "debug")]
2022-04-25 12:35:55 +02:00
if self.common.seats.iter().position(|x| x == seat).unwrap() == 0 {
2022-05-03 13:37:51 +02:00
self.common
.egui
2022-02-05 00:40:17 +01:00
.debug_state
.handle_pointer_motion(position.to_i32_round());
2022-05-03 13:37:51 +02:00
self.common
.egui
2022-02-05 00:40:17 +01:00
.log_state
2022-01-11 17:22:23 +01:00
.handle_pointer_motion(position.to_i32_round());
}
2021-12-22 20:14:09 +01:00
break;
}
}
}
InputEvent::PointerMotionAbsolute { event, .. } => {
let device = event.device();
2022-04-25 12:35:55 +02:00
for seat in self.common.seats.clone().iter() {
2021-12-22 20:14:09 +01:00
let userdata = seat.user_data();
let devices = userdata.get::<Devices>().unwrap();
if devices.has_device(&device) {
2022-04-25 12:35:55 +02:00
let output = active_output(seat, &self.common);
let geometry = output.geometry();
2021-12-22 20:14:09 +01:00
let position =
geometry.loc.to_f64() + event.position_transformed(geometry.size);
2022-05-03 13:37:51 +02:00
let relative_pos = self
.common
.shell
.space_relative_output_geometry(position, &output);
2022-04-25 12:35:55 +02:00
let workspace = self.common.shell.active_space_mut(&output);
2021-12-22 20:14:09 +01:00
let serial = SERIAL_COUNTER.next_serial();
2022-04-25 12:35:55 +02:00
let under = State::surface_under(
position,
relative_pos,
&output,
geometry,
2022-04-22 15:18:28 +02:00
&workspace,
);
2022-07-04 16:00:29 +02:00
seat.get_pointer().unwrap().motion(
self,
2022-08-31 13:01:23 +02:00
under,
2022-07-04 16:00:29 +02:00
&MotionEvent {
location: position,
serial,
2022-07-04 16:00:29 +02:00
time: event.time(),
},
);
2022-01-11 17:22:23 +01:00
#[cfg(feature = "debug")]
2022-04-25 12:35:55 +02:00
if self.common.seats.iter().position(|x| x == seat).unwrap() == 0 {
2022-05-03 13:37:51 +02:00
self.common
.egui
2022-02-05 00:40:17 +01:00
.debug_state
.handle_pointer_motion(position.to_i32_round());
2022-05-03 13:37:51 +02:00
self.common
.egui
2022-02-05 00:40:17 +01:00
.log_state
2022-01-11 17:22:23 +01:00
.handle_pointer_motion(position.to_i32_round());
}
2021-12-22 20:14:09 +01:00
break;
}
}
}
InputEvent::PointerButton { event, .. } => {
2022-08-31 13:01:23 +02:00
use smithay::backend::input::{ButtonState, PointerButtonEvent};
2021-12-22 20:14:09 +01:00
let device = event.device();
2022-04-25 12:35:55 +02:00
for seat in self.common.seats.clone().iter() {
2021-12-22 20:14:09 +01:00
let userdata = seat.user_data();
let devices = userdata.get::<Devices>().unwrap();
if devices.has_device(&device) {
2022-01-11 17:22:23 +01:00
#[cfg(feature = "debug")]
2022-04-25 12:35:55 +02:00
if self.common.seats.iter().position(|x| x == seat).unwrap() == 0
&& self.common.egui.active
2022-01-11 17:22:23 +01:00
{
2022-04-25 12:35:55 +02:00
if self.common.egui.debug_state.wants_pointer() {
2022-02-05 00:40:17 +01:00
if let Some(button) = event.button() {
2022-04-25 12:35:55 +02:00
self.common.egui.debug_state.handle_pointer_button(
2022-02-05 00:40:17 +01:00
button,
event.state() == ButtonState::Pressed,
2022-04-25 12:35:55 +02:00
self.common.egui.modifiers.clone(),
2022-02-05 00:40:17 +01:00
);
}
break;
}
2022-04-25 12:35:55 +02:00
if self.common.egui.log_state.wants_pointer() {
2022-02-05 00:40:17 +01:00
if let Some(button) = event.button() {
2022-04-25 12:35:55 +02:00
self.common.egui.log_state.handle_pointer_button(
2022-02-05 00:40:17 +01:00
button,
event.state() == ButtonState::Pressed,
2022-04-25 12:35:55 +02:00
self.common.egui.modifiers.clone(),
2022-02-05 00:40:17 +01:00
);
}
break;
2022-01-11 17:22:23 +01:00
}
}
2021-12-22 20:14:09 +01:00
let serial = SERIAL_COUNTER.next_serial();
let button = event.button_code();
2022-08-31 13:01:23 +02:00
if event.state() == ButtonState::Pressed {
// change the keyboard focus unless the pointer or keyboard is grabbed
// We test for any matching surface type here but always use the root
// (in case of a window the toplevel) surface for the focus.
// see: https://gitlab.freedesktop.org/wayland/wayland/-/issues/294
if !seat.get_pointer().unwrap().is_grabbed()
&& !seat.get_keyboard().map(|k| k.is_grabbed()).unwrap_or(false)
{
let output = active_output(seat, &self.common);
let pos = seat.get_pointer().unwrap().current_location();
let output_geo = output.geometry();
let relative_pos = self
.common
.shell
.space_relative_output_geometry(pos, &output);
let workspace = self.common.shell.active_space_mut(&output);
let layers = layer_map_for_output(&output);
let mut under = None;
if let Some(window) = workspace.get_fullscreen(&output) {
if let Some(layer) =
layers.layer_under(WlrLayer::Overlay, relative_pos)
{
if layer.can_receive_keyboard_focus() {
let layer_loc =
layers.layer_geometry(layer).unwrap().loc;
under = layer
2022-05-03 13:37:51 +02:00
.surface_under(
2022-08-31 13:01:23 +02:00
pos - output_geo.loc.to_f64()
- layer_loc.to_f64(),
2022-05-12 14:15:33 +02:00
WindowSurfaceType::ALL,
2022-05-03 13:37:51 +02:00
)
2022-08-31 13:01:23 +02:00
.map(|(_, _)| layer.wl_surface().clone());
2022-04-22 15:18:28 +02:00
}
} else {
2022-08-31 13:01:23 +02:00
under = window
.surface_under(
pos - output_geo.loc.to_f64(),
WindowSurfaceType::ALL,
2022-05-03 13:37:51 +02:00
)
2022-08-31 13:01:23 +02:00
.map(|(_, _)| window.toplevel().wl_surface().clone());
2022-04-22 15:18:28 +02:00
}
2022-08-31 13:01:23 +02:00
} else {
if let Some(layer) = layers
.layer_under(WlrLayer::Overlay, relative_pos)
.or_else(|| layers.layer_under(WlrLayer::Top, relative_pos))
{
if layer.can_receive_keyboard_focus() {
let layer_loc =
layers.layer_geometry(layer).unwrap().loc;
under = layer
.surface_under(
pos - output_geo.loc.to_f64()
- layer_loc.to_f64(),
WindowSurfaceType::ALL,
)
.map(|(_, _)| layer.wl_surface().clone());
}
} else if let Some((window, _, _)) = workspace
.space
.surface_under(relative_pos, WindowSurfaceType::ALL)
{
under = Some(window.toplevel().wl_surface().clone());
} else if let Some(layer) = layers
.layer_under(WlrLayer::Bottom, pos)
.or_else(|| layers.layer_under(WlrLayer::Background, pos))
{
if layer.can_receive_keyboard_focus() {
let layer_loc =
layers.layer_geometry(layer).unwrap().loc;
under = layer
.surface_under(
pos - output_geo.loc.to_f64()
- layer_loc.to_f64(),
WindowSurfaceType::ALL,
)
.map(|(_, _)| layer.wl_surface().clone());
}
};
2021-12-22 20:14:09 +01:00
}
2022-08-31 13:01:23 +02:00
Common::set_focus(self, under.as_ref(), seat, Some(serial));
2021-12-22 20:14:09 +01:00
}
};
2022-07-04 16:00:29 +02:00
seat.get_pointer().unwrap().button(
self,
&ButtonEvent {
button,
2022-08-31 13:01:23 +02:00
state: event.state(),
serial,
2022-07-04 16:00:29 +02:00
time: event.time(),
},
);
2021-12-22 20:14:09 +01:00
break;
}
}
}
InputEvent::PointerAxis { event, .. } => {
let device = event.device();
2022-04-25 12:35:55 +02:00
for seat in self.common.seats.clone().iter() {
2022-01-11 17:22:23 +01:00
#[cfg(feature = "debug")]
2022-05-03 13:37:51 +02:00
if self.common.seats.iter().position(|x| x == seat).unwrap() == 0
&& self.common.egui.active
{
2022-04-25 12:35:55 +02:00
if self.common.egui.debug_state.wants_pointer() {
self.common.egui.debug_state.handle_pointer_axis(
2022-02-05 00:40:17 +01:00
event
.amount_discrete(Axis::Horizontal)
.or_else(|| event.amount(Axis::Horizontal).map(|x| x * 3.0))
.unwrap_or(0.0),
event
.amount_discrete(Axis::Vertical)
.or_else(|| event.amount(Axis::Vertical).map(|x| x * 3.0))
.unwrap_or(0.0),
);
break;
}
2022-04-25 12:35:55 +02:00
if self.common.egui.log_state.wants_pointer() {
self.common.egui.log_state.handle_pointer_axis(
2022-02-05 00:40:17 +01:00
event
.amount_discrete(Axis::Horizontal)
.or_else(|| event.amount(Axis::Horizontal).map(|x| x * 3.0))
.unwrap_or(0.0),
event
.amount_discrete(Axis::Vertical)
.or_else(|| event.amount(Axis::Vertical).map(|x| x * 3.0))
.unwrap_or(0.0),
);
break;
}
2022-01-11 17:22:23 +01:00
}
2021-12-22 20:14:09 +01:00
let userdata = seat.user_data();
let devices = userdata.get::<Devices>().unwrap();
if devices.has_device(&device) {
let horizontal_amount =
event.amount(Axis::Horizontal).unwrap_or_else(|| {
event.amount_discrete(Axis::Horizontal).unwrap_or(0.0) * 3.0
2021-12-22 20:14:09 +01:00
});
let vertical_amount = event.amount(Axis::Vertical).unwrap_or_else(|| {
event.amount_discrete(Axis::Vertical).unwrap_or(0.0) * 3.0
2021-12-22 20:14:09 +01:00
});
let horizontal_amount_discrete = event.amount_discrete(Axis::Horizontal);
let vertical_amount_discrete = event.amount_discrete(Axis::Vertical);
{
2022-08-31 13:01:23 +02:00
let mut frame = AxisFrame::new(event.time()).source(event.source());
2021-12-22 20:14:09 +01:00
if horizontal_amount != 0.0 {
2022-08-31 13:01:23 +02:00
frame = frame.value(Axis::Horizontal, horizontal_amount);
2021-12-22 20:14:09 +01:00
if let Some(discrete) = horizontal_amount_discrete {
2022-08-31 13:01:23 +02:00
frame = frame.discrete(Axis::Horizontal, discrete as i32);
2021-12-22 20:14:09 +01:00
}
2022-08-31 13:01:23 +02:00
} else if event.source() == AxisSource::Finger {
frame = frame.stop(Axis::Horizontal);
2021-12-22 20:14:09 +01:00
}
if vertical_amount != 0.0 {
2022-08-31 13:01:23 +02:00
frame = frame.value(Axis::Vertical, vertical_amount);
2021-12-22 20:14:09 +01:00
if let Some(discrete) = vertical_amount_discrete {
2022-08-31 13:01:23 +02:00
frame = frame.discrete(Axis::Vertical, discrete as i32);
2021-12-22 20:14:09 +01:00
}
2022-08-31 13:01:23 +02:00
} else if event.source() == AxisSource::Finger {
frame = frame.stop(Axis::Vertical);
2021-12-22 20:14:09 +01:00
}
2022-08-31 13:01:23 +02:00
seat.get_pointer().unwrap().axis(self, frame);
2021-12-22 20:14:09 +01:00
}
break;
}
}
}
_ => { /* TODO e.g. tablet or touch events */ }
}
}
pub fn surface_under(
global_pos: Point<f64, Logical>,
relative_pos: Point<f64, Logical>,
2021-12-22 20:14:09 +01:00
output: &Output,
output_geo: Rectangle<i32, Logical>,
2022-04-22 15:18:28 +02:00
workspace: &Workspace,
2021-12-22 20:14:09 +01:00
) -> Option<(WlSurface, Point<i32, Logical>)> {
let layers = layer_map_for_output(output);
2022-04-22 15:18:28 +02:00
if let Some(window) = workspace.get_fullscreen(output) {
if let Some(layer) = layers
.layer_under(WlrLayer::Overlay, relative_pos)
.or_else(|| layers.layer_under(WlrLayer::Top, relative_pos))
{
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
layer
.surface_under(
global_pos - output_geo.loc.to_f64() - layer_loc.to_f64(),
WindowSurfaceType::ALL,
)
2022-04-22 15:18:28 +02:00
.map(|(s, loc)| (s, loc + layer_loc + output_geo.loc))
2022-05-03 13:37:51 +02:00
} else {
2022-04-22 15:18:28 +02:00
window
.surface_under(global_pos - output_geo.loc.to_f64(), WindowSurfaceType::ALL)
2022-05-03 13:37:51 +02:00
.map(|(s, loc)| (s, loc + output_geo.loc))
2022-04-22 15:18:28 +02:00
}
2021-12-22 20:14:09 +01:00
} else {
2022-04-22 15:18:28 +02:00
if let Some(layer) = layers
.layer_under(WlrLayer::Overlay, relative_pos)
.or_else(|| layers.layer_under(WlrLayer::Top, relative_pos))
{
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
layer
.surface_under(
global_pos - output_geo.loc.to_f64() - layer_loc.to_f64(),
WindowSurfaceType::ALL,
)
.map(|(s, loc)| (s, loc + layer_loc + output_geo.loc))
2022-05-03 13:37:51 +02:00
} else if let Some((_, surface, loc)) = workspace
.space
.surface_under(relative_pos, WindowSurfaceType::ALL)
{
Some((surface, loc + (global_pos - relative_pos).to_i32_round()))
2022-04-22 15:18:28 +02:00
} else if let Some(layer) = layers
.layer_under(WlrLayer::Bottom, relative_pos)
.or_else(|| layers.layer_under(WlrLayer::Background, relative_pos))
{
let layer_loc = layers.layer_geometry(layer).unwrap().loc;
layer
.surface_under(
global_pos - output_geo.loc.to_f64() - layer_loc.to_f64(),
WindowSurfaceType::ALL,
)
.map(|(s, loc)| (s, loc + layer_loc + output_geo.loc))
} else {
None
}
2021-12-22 20:14:09 +01:00
}
}
}