diff --git a/build/enums.rs b/build/enums.rs index f7517361..540b5b24 100644 --- a/build/enums.rs +++ b/build/enums.rs @@ -259,6 +259,16 @@ pub fn main() -> anyhow::Result<()> { )?; write_ty(&mut f, libinput::LIBINPUT_SWITCH, "libinput_switch")?; write_ty(&mut f, libinput::LIBINPUT_EVENT_TYPE, "libinput_event_type")?; + write_ty( + &mut f, + libinput::LIBINPUT_CONFIG_STATUS, + "libinput_config_status", + )?; + write_ty( + &mut f, + libinput::LIBINPUT_CONFIG_ACCEL_PROFILE, + "libinput_config_accel_profile", + )?; let mut f = open("pixman_tys.rs")?; write_ty(&mut f, pixman::FORMATS, "PixmanFormat")?; diff --git a/default-config/src/lib.rs b/default-config/src/lib.rs index ab8b2f6c..dcb52e4d 100644 --- a/default-config/src/lib.rs +++ b/default-config/src/lib.rs @@ -1,4 +1,7 @@ use jay_config::embedded::grab_input_device; +use jay_config::input::{ + InputDevice, CAP_KEYBOARD, CAP_POINTER, +}; use jay_config::keyboard::mods::{Modifiers, ALT, CTRL, SHIFT}; use jay_config::keyboard::syms::{ SYM_Super_L, SYM_b, SYM_comma, SYM_d, SYM_f, SYM_h, SYM_j, SYM_k, SYM_l, SYM_m, SYM_p, @@ -12,7 +15,6 @@ use jay_config::{ config, create_seat, input_devices, on_new_input_device, quit, switch_to_vt, Command, Seat, }; use rand::Rng; -use jay_config::input::CAP_KEYBOARD; const MOD: Modifiers = ALT; @@ -117,10 +119,15 @@ fn configure_seat(s: Seat) { pub fn configure() { let seat = create_seat("default"); configure_seat(seat); - for device in input_devices() { + let handle_input_device = move |device: InputDevice| { + if device.has_capability(CAP_POINTER) { + device.set_left_handed(true); + device.set_transform_matrix([[0.35, 0.0], [0.0, 0.35]]); + } device.set_seat(seat); - } - on_new_input_device(move |device| device.set_seat(seat)); + }; + input_devices().into_iter().for_each(handle_input_device); + on_new_input_device(handle_input_device); } config!(configure); diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index 1ac011a0..55530b98 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -2,6 +2,7 @@ use crate::_private::ipc::{ClientMessage, InitMessage, Response, ServerMessage}; use crate::_private::{bincode_ops, logging, Config, ConfigEntry, ConfigEntryGen, VERSION}; +use crate::input::{AccelProfile, Capability, InputDevice}; use crate::keyboard::keymap::Keymap; use crate::theme::Color; use crate::{Axis, Command, Direction, LogLevel, ModifiedKeySym, Seat}; @@ -11,7 +12,6 @@ use std::collections::HashMap; use std::ops::Deref; use std::rc::Rc; use std::{ptr, slice}; -use crate::input::{Capability, InputDevice}; pub(crate) struct Client { configure: extern "C" fn(), @@ -318,6 +318,25 @@ impl Client { self.send(&ClientMessage::SetSeat { device, seat }) } + pub fn set_left_handed(&self, device: InputDevice, left_handed: bool) { + self.send(&ClientMessage::SetLeftHanded { + device, + left_handed, + }) + } + + pub fn set_accel_profile(&self, device: InputDevice, profile: AccelProfile) { + self.send(&ClientMessage::SetAccelProfile { device, profile }) + } + + pub fn set_accel_speed(&self, device: InputDevice, speed: f64) { + self.send(&ClientMessage::SetAccelSpeed { device, speed }) + } + + pub fn set_transform_matrix(&self, device: InputDevice, matrix: [[f64; 2]; 2]) { + self.send(&ClientMessage::SetTransformMatrix { device, matrix }) + } + pub fn has_capability(&self, device: InputDevice, cap: Capability) -> bool { let res = self.with_response(|| self.send(&ClientMessage::HasCapability { device, cap })); match res { diff --git a/jay-config/src/_private/ipc.rs b/jay-config/src/_private/ipc.rs index d35cc804..5787f02a 100644 --- a/jay-config/src/_private/ipc.rs +++ b/jay-config/src/_private/ipc.rs @@ -1,10 +1,10 @@ +use crate::input::{AccelProfile, Capability, InputDevice}; use crate::keyboard::keymap::Keymap; use crate::keyboard::mods::Modifiers; use crate::keyboard::syms::KeySym; use crate::theme::Color; use crate::{Axis, Direction, LogLevel, Seat}; use bincode::{BorrowDecode, Decode, Encode}; -use crate::input::{Capability, InputDevice}; #[derive(Encode, BorrowDecode, Debug)] pub enum ServerMessage { @@ -141,6 +141,22 @@ pub enum ClientMessage<'a> { device: InputDevice, cap: Capability, }, + SetLeftHanded { + device: InputDevice, + left_handed: bool, + }, + SetAccelProfile { + device: InputDevice, + profile: AccelProfile, + }, + SetAccelSpeed { + device: InputDevice, + speed: f64, + }, + SetTransformMatrix { + device: InputDevice, + matrix: [[f64; 2]; 2], + }, } #[derive(Encode, Decode, Debug)] diff --git a/jay-config/src/input.rs b/jay-config/src/input.rs index 1f15bcd7..466e7ad5 100644 --- a/jay-config/src/input.rs +++ b/jay-config/src/input.rs @@ -1,5 +1,5 @@ -use bincode::{Decode, Encode}; use crate::Seat; +use bincode::{Decode, Encode}; #[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] pub struct InputDevice(pub u64); @@ -12,6 +12,22 @@ impl InputDevice { pub fn has_capability(self, cap: Capability) -> bool { get!(false).has_capability(self, cap) } + + pub fn set_left_handed(self, left_handed: bool) { + get!().set_left_handed(self, left_handed); + } + + pub fn set_accel_profile(self, profile: AccelProfile) { + get!().set_accel_profile(self, profile); + } + + pub fn set_accel_speed(self, speed: f64) { + get!().set_accel_speed(self, speed); + } + + pub fn set_transform_matrix(self, matrix: [[f64; 2]; 2]) { + get!().set_transform_matrix(self, matrix); + } } #[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] @@ -24,3 +40,9 @@ pub const CAP_TABLET_TOOL: Capability = Capability(3); pub const CAP_TABLET_PAD: Capability = Capability(4); pub const CAP_GESTURE: Capability = Capability(5); pub const CAP_SWITCH: Capability = Capability(6); + +#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] +pub struct AccelProfile(pub u32); + +pub const ACCEL_PROFILE_FLAT: AccelProfile = AccelProfile(1 << 0); +pub const ACCEL_PROFILE_ADAPTIVE: AccelProfile = AccelProfile(1 << 1); diff --git a/jay-config/src/lib.rs b/jay-config/src/lib.rs index 76e26a40..20a6085a 100644 --- a/jay-config/src/lib.rs +++ b/jay-config/src/lib.rs @@ -1,17 +1,17 @@ +use crate::input::InputDevice; use crate::keyboard::keymap::Keymap; use crate::keyboard::ModifiedKeySym; use bincode::{Decode, Encode}; use std::collections::HashMap; -use crate::input::InputDevice; #[macro_use] mod macros; #[doc(hidden)] pub mod _private; pub mod embedded; +pub mod input; pub mod keyboard; pub mod theme; -pub mod input; #[derive(Encode, Decode, Copy, Clone, Debug)] pub enum LogLevel { diff --git a/src/backend.rs b/src/backend.rs index b5508047..47b7a791 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -24,6 +24,10 @@ pub trait InputDevice { fn on_change(&self, cb: Rc); fn grab(&self, grab: bool); fn has_capability(&self, cap: InputDeviceCapability) -> bool; + fn set_left_handed(&self, left_handed: bool); + fn set_accel_profile(&self, profile: InputDeviceAccelProfile); + fn set_accel_speed(&self, speed: f64); + fn set_transform_matrix(&self, matrix: [[f64; 2]; 2]); } #[derive(Debug, Copy, Clone)] @@ -37,6 +41,12 @@ pub enum InputDeviceCapability { Switch, } +#[derive(Debug, Copy, Clone)] +pub enum InputDeviceAccelProfile { + Flat, + Adaptive, +} + pub enum BackendEvent { NewOutput(Rc), NewInputDevice(Rc), diff --git a/src/backends/metal.rs b/src/backends/metal.rs index b9354de7..37ac97fa 100644 --- a/src/backends/metal.rs +++ b/src/backends/metal.rs @@ -3,11 +3,19 @@ mod monitor; mod video; use crate::async_engine::{AsyncError, AsyncFd}; -use crate::backend::{Backend, InputDevice, InputDeviceCapability, InputDeviceId, InputEvent}; +use crate::backend::{ + Backend, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent, +}; use crate::backends::metal::video::{MetalDrmDevice, PendingDrmDevice}; use crate::dbus::DbusError; use crate::drm::drm::DrmError; use crate::drm::gbm::GbmError; +use crate::libinput::consts::{ + AccelProfile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, + LIBINPUT_DEVICE_CAP_GESTURE, LIBINPUT_DEVICE_CAP_KEYBOARD, LIBINPUT_DEVICE_CAP_POINTER, + LIBINPUT_DEVICE_CAP_SWITCH, LIBINPUT_DEVICE_CAP_TABLET_PAD, LIBINPUT_DEVICE_CAP_TABLET_TOOL, + LIBINPUT_DEVICE_CAP_TOUCH, +}; use crate::libinput::device::RegisteredDevice; use crate::libinput::{LibInput, LibInputAdapter, LibInputError}; use crate::logind::{LogindError, Session}; @@ -25,7 +33,6 @@ use std::future::pending; use std::rc::Rc; use thiserror::Error; use uapi::{c, OwnedFd}; -use crate::libinput::consts::{LIBINPUT_DEVICE_CAP_GESTURE, LIBINPUT_DEVICE_CAP_KEYBOARD, LIBINPUT_DEVICE_CAP_POINTER, LIBINPUT_DEVICE_CAP_SWITCH, LIBINPUT_DEVICE_CAP_TABLET_PAD, LIBINPUT_DEVICE_CAP_TABLET_TOOL, LIBINPUT_DEVICE_CAP_TOUCH}; #[derive(Debug, Error)] pub enum MetalError { @@ -189,6 +196,12 @@ struct MetalInputDevice { cb: CloneCell>>, hscroll: Cell, vscroll: Cell, + + // config + left_handed: Cell>, + accel_profile: Cell>, + accel_speed: Cell>, + transform_matrix: Cell>, } #[derive(Clone)] @@ -223,6 +236,24 @@ impl LibInputAdapter for DeviceHolder { } } +impl MetalInputDevice { + fn apply_config(&self) { + let dev = match self.inputdev.get() { + Some(dev) => dev, + _ => return, + }; + if let Some(lh) = self.left_handed.get() { + dev.device().set_left_handed(lh); + } + if let Some(profile) = self.accel_profile.get() { + dev.device().set_accel_profile(profile); + } + if let Some(speed) = self.accel_speed.get() { + dev.device().set_accel_speed(speed); + } + } +} + impl InputDevice for MetalInputDevice { fn id(&self) -> InputDeviceId { self.id @@ -259,6 +290,35 @@ impl InputDevice for MetalInputDevice { _ => false, } } + + fn set_left_handed(&self, left_handed: bool) { + self.left_handed.set(Some(left_handed)); + if let Some(dev) = self.inputdev.get() { + dev.device().set_left_handed(left_handed); + } + } + + fn set_accel_profile(&self, profile: InputDeviceAccelProfile) { + let profile = match profile { + InputDeviceAccelProfile::Flat => LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, + InputDeviceAccelProfile::Adaptive => LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE, + }; + self.accel_profile.set(Some(profile)); + if let Some(dev) = self.inputdev.get() { + dev.device().set_accel_profile(profile); + } + } + + fn set_accel_speed(&self, speed: f64) { + self.accel_speed.set(Some(speed)); + if let Some(dev) = self.inputdev.get() { + dev.device().set_accel_speed(speed); + } + } + + fn set_transform_matrix(&self, matrix: [[f64; 2]; 2]) { + self.transform_matrix.set(Some(matrix)); + } } impl MetalInputDevice { diff --git a/src/backends/metal/input.rs b/src/backends/metal/input.rs index 1abb7949..63a7c434 100644 --- a/src/backends/metal/input.rs +++ b/src/backends/metal/input.rs @@ -104,26 +104,28 @@ impl MetalBackend { const PX_PER_SCROLL: f64 = 15.0; const ONE_TWENTRY: f64 = 120.0; let (event, dev) = unpack!(self, event, pointer_event); - let hscroll = event.scroll_value_v120(LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL) - / ONE_TWENTRY - + dev.hscroll.get(); - let vscroll = event.scroll_value_v120(LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL) / ONE_TWENTRY - + dev.vscroll.get(); - let hscroll_used = (PX_PER_SCROLL * hscroll).round(); - let vscroll_used = (PX_PER_SCROLL * vscroll).round(); - dev.hscroll.set(hscroll - hscroll_used / PX_PER_SCROLL); - dev.vscroll.set(vscroll - vscroll_used / PX_PER_SCROLL); - if hscroll_used != 0.0 { - dev.event(InputEvent::Scroll( - hscroll_used as i32, + let axes = [ + ( + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, + &dev.hscroll, ScrollAxis::Horizontal, - )); - } - if vscroll_used != 0.0 { - dev.event(InputEvent::Scroll( - vscroll_used as i32, + ), + ( + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, + &dev.vscroll, ScrollAxis::Vertical, - )); + ), + ]; + for (axis, val, sa) in axes { + if !event.has_axis(axis) { + continue; + } + let scroll = event.scroll_value_v120(axis) / ONE_TWENTRY + val.get(); + let scroll_used = (PX_PER_SCROLL * scroll).round(); + val.set(scroll - scroll_used / PX_PER_SCROLL); + if scroll_used != 0.0 { + dev.event(InputEvent::Scroll(scroll_used as i32, sa)); + } } } @@ -139,6 +141,12 @@ impl MetalBackend { fn handle_pointer_motion(self: &Rc, event: LibInputEvent) { let (event, dev) = unpack!(self, event, pointer_event); - dev.event(InputEvent::Motion(event.dx().into(), event.dy().into())); + let mut dx = event.dx(); + let mut dy = event.dy(); + if let Some(matrix) = dev.transform_matrix.get() { + dx = matrix[0][0] * dx + matrix[0][1] * dy; + dy = matrix[1][0] * dx + matrix[1][1] * dy; + } + dev.event(InputEvent::Motion(dx.into(), dy.into())); } } diff --git a/src/backends/metal/monitor.rs b/src/backends/metal/monitor.rs index 86a0c5b9..a09b0e48 100644 --- a/src/backends/metal/monitor.rs +++ b/src/backends/metal/monitor.rs @@ -100,6 +100,7 @@ impl MetalBackend { }; inputdev.device().set_slot(dev.slot); dev.inputdev.set(Some(inputdev)); + dev.apply_config(); } fn handle_device_removed(self: &Rc, dev: c::dev_t) { @@ -280,6 +281,10 @@ impl MetalBackend { cb: Default::default(), hscroll: Cell::new(0.0), vscroll: Cell::new(0.0), + left_handed: Default::default(), + accel_profile: Default::default(), + accel_speed: Default::default(), + transform_matrix: Default::default(), }); slots[slot] = Some(dev.clone()); self.device_holder @@ -319,6 +324,7 @@ impl MetalBackend { }; inputdev.device().set_slot(slot); dev.inputdev.set(Some(inputdev)); + dev.apply_config(); slf.state .backend_events .push(BackendEvent::NewInputDevice(dev.clone())); diff --git a/src/backends/x.rs b/src/backends/x.rs index 6a08ce3a..fed79472 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -1,5 +1,8 @@ use crate::async_engine::{Phase, SpawnedFuture}; -use crate::backend::{Backend, BackendEvent, InputDevice, InputDeviceCapability, InputDeviceId, InputEvent, KeyState, Output, OutputId, ScrollAxis}; +use crate::backend::{ + Backend, BackendEvent, InputDevice, InputDeviceAccelProfile, InputDeviceCapability, + InputDeviceId, InputEvent, KeyState, Output, OutputId, ScrollAxis, +}; use crate::drm::drm::{Drm, DrmError}; use crate::drm::gbm::{GbmDevice, GbmError, GBM_BO_USE_RENDERING}; use crate::drm::{ModifiedFormat, INVALID_MODIFIER}; @@ -963,6 +966,22 @@ impl InputDevice for XSeatKeyboard { _ => false, } } + + fn set_left_handed(&self, left_handed: bool) { + let _ = left_handed; + } + + fn set_accel_profile(&self, profile: InputDeviceAccelProfile) { + let _ = profile; + } + + fn set_accel_speed(&self, speed: f64) { + let _ = speed; + } + + fn set_transform_matrix(&self, matrix: [[f64; 2]; 2]) { + let _ = matrix; + } } impl InputDevice for XSeatMouse { @@ -992,4 +1011,20 @@ impl InputDevice for XSeatMouse { _ => false, } } + + fn set_left_handed(&self, left_handed: bool) { + let _ = left_handed; + } + + fn set_accel_profile(&self, profile: InputDeviceAccelProfile) { + let _ = profile; + } + + fn set_accel_speed(&self, speed: f64) { + let _ = speed; + } + + fn set_transform_matrix(&self, matrix: [[f64; 2]; 2]) { + let _ = matrix; + } } diff --git a/src/config.rs b/src/config.rs index cb8e2ae3..e78fb057 100644 --- a/src/config.rs +++ b/src/config.rs @@ -8,14 +8,14 @@ use crate::utils::numcell::NumCell; use crate::utils::ptr_ext::PtrExt; use jay_config::_private::ipc::{InitMessage, ServerMessage, V1InitMessage}; use jay_config::_private::{bincode_ops, ConfigEntry, VERSION}; +use jay_config::input::InputDevice; use jay_config::keyboard::ModifiedKeySym; -use jay_config::{Seat}; +use jay_config::Seat; use libloading::Library; use std::cell::Cell; use std::ptr; use std::rc::Rc; use thiserror::Error; -use jay_config::input::InputDevice; #[derive(Debug, Error)] pub enum ConfigError { diff --git a/src/config/handler.rs b/src/config/handler.rs index 967ef05e..ccc8217e 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -1,5 +1,5 @@ use crate::backend; -use crate::backend::{InputDeviceCapability, InputDeviceId}; +use crate::backend::{InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId}; use crate::ifs::wl_seat::{SeatId, WlSeatGlobal}; use crate::state::{DeviceHandlerData, State}; use crate::tree::walker::NodeVisitorBase; @@ -13,6 +13,10 @@ use crate::xkbcommon::XkbKeymap; use bincode::error::DecodeError; use jay_config::_private::bincode_ops; use jay_config::_private::ipc::{ClientMessage, Response, ServerMessage}; +use jay_config::input::{ + AccelProfile, Capability, InputDevice, ACCEL_PROFILE_ADAPTIVE, ACCEL_PROFILE_FLAT, CAP_GESTURE, + CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD, CAP_TABLET_TOOL, CAP_TOUCH, +}; use jay_config::keyboard::keymap::Keymap; use jay_config::keyboard::mods::Modifiers; use jay_config::keyboard::syms::KeySym; @@ -22,7 +26,6 @@ use log::Level; use std::cell::Cell; use std::rc::Rc; use thiserror::Error; -use jay_config::input::{CAP_GESTURE, CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD, CAP_TABLET_TOOL, CAP_TOUCH, Capability, InputDevice}; pub(super) struct ConfigProxyHandler { pub client_data: Cell<*const u8>, @@ -49,9 +52,7 @@ impl ConfigProxyHandler { } pub fn respond(&self, msg: Response) { - self.send(&ServerMessage::Response { - response: msg, - }) + self.send(&ServerMessage::Response { response: msg }) } fn id(&self) -> u64 { @@ -207,8 +208,58 @@ impl ConfigProxyHandler { Ok(()) } - fn handle_has_capability(&self, device: InputDevice, cap: Capability) -> Result<(), HasCapabilityError> { + fn handle_set_left_handed( + &self, + device: InputDevice, + left_handed: bool, + ) -> Result<(), SetLeftHandedError> { let dev = self.get_device_handler_data(device)?; + dev.device.set_left_handed(left_handed); + Ok(()) + } + + fn handle_set_accel_profile( + &self, + device: InputDevice, + accel_profile: AccelProfile, + ) -> Result<(), SetAccelProfileError> { + let dev = self.get_device_handler_data(device)?; + let profile = match accel_profile { + ACCEL_PROFILE_FLAT => InputDeviceAccelProfile::Flat, + ACCEL_PROFILE_ADAPTIVE => InputDeviceAccelProfile::Adaptive, + _ => return Err(SetAccelProfileError::UnknownAccelProfile(accel_profile)), + }; + dev.device.set_accel_profile(profile); + Ok(()) + } + + fn handle_set_accel_speed( + &self, + device: InputDevice, + speed: f64, + ) -> Result<(), SetAccelSpeedError> { + let dev = self.get_device_handler_data(device)?; + dev.device.set_accel_speed(speed); + Ok(()) + } + + fn handle_set_transform_matrix( + &self, + device: InputDevice, + matrix: [[f64; 2]; 2], + ) -> Result<(), SetTransformMatrixError> { + let dev = self.get_device_handler_data(device)?; + dev.device.set_transform_matrix(matrix); + Ok(()) + } + + fn handle_has_capability( + &self, + device: InputDevice, + cap: Capability, + ) -> Result<(), HasCapabilityError> { + let dev = self.get_device_handler_data(device)?; + let mut is_unknown = false; let has_cap = 'has_cap: { let cap = match cap { CAP_KEYBOARD => InputDeviceCapability::Keyboard, @@ -218,14 +269,19 @@ impl ConfigProxyHandler { CAP_TABLET_PAD => InputDeviceCapability::TabletPad, CAP_GESTURE => InputDeviceCapability::Gesture, CAP_SWITCH => InputDeviceCapability::Switch, - _ => break 'has_cap false, + _ => { + is_unknown = true; + break 'has_cap false; + } }; dev.device.has_capability(cap) }; - self.respond(Response::HasCapability { - has: has_cap, - }); - Ok(()) + self.respond(Response::HasCapability { has: has_cap }); + if is_unknown { + Err(HasCapabilityError::UnknownCapability(cap)) + } else { + Ok(()) + } } fn handle_get_mono(&self, seat: Seat) -> Result<(), GetMonoError> { @@ -510,7 +566,22 @@ impl ConfigProxyHandler { ClientMessage::ToggleFloating { seat } => self.handle_toggle_floating(seat)?, ClientMessage::Quit => self.handle_quit(), ClientMessage::SwitchTo { vtnr } => self.handle_switch_to(vtnr), - ClientMessage::HasCapability { device, cap } => self.handle_has_capability(device, cap)?, + ClientMessage::HasCapability { device, cap } => { + self.handle_has_capability(device, cap)? + } + ClientMessage::SetLeftHanded { + device, + left_handed, + } => self.handle_set_left_handed(device, left_handed)?, + ClientMessage::SetAccelProfile { device, profile } => { + self.handle_set_accel_profile(device, profile)? + } + ClientMessage::SetAccelSpeed { device, speed } => { + self.handle_set_accel_speed(device, speed)? + } + ClientMessage::SetTransformMatrix { device, matrix } => { + self.handle_set_transform_matrix(device, matrix)? + } } Ok(()) } @@ -560,6 +631,14 @@ enum CphError { SetBorderWidthError(#[from] SetBorderWidthError), #[error("Could not process a `has_capability` request")] HasCapabilityError(#[from] HasCapabilityError), + #[error("Could not process a `set_left_handed` request")] + SetLeftHandedError(#[from] SetLeftHandedError), + #[error("Could not process a `set_accel_profile` request")] + SetAccelProfileError(#[from] SetAccelProfileError), + #[error("Could not process a `set_accel_speed` request")] + SetAccelSpeedError(#[from] SetAccelSpeedError), + #[error("Could not process a `set_transform_matrix` request")] + SetTransformMatrixError(#[from] SetTransformMatrixError), #[error("Device {0:?} does not exist")] DeviceDoesNotExist(InputDevice), #[error("Device {0:?} does not exist")] @@ -585,10 +664,42 @@ enum SetSeatError { } efrom!(SetSeatError, CphError); +#[derive(Debug, Error)] +enum SetLeftHandedError { + #[error(transparent)] + CphError(#[from] Box), +} +efrom!(SetLeftHandedError, CphError); + +#[derive(Debug, Error)] +enum SetAccelProfileError { + #[error(transparent)] + CphError(#[from] Box), + #[error("Tried to set an unknown accel profile: {}", (.0).0)] + UnknownAccelProfile(AccelProfile), +} +efrom!(SetAccelProfileError, CphError); + +#[derive(Debug, Error)] +enum SetAccelSpeedError { + #[error(transparent)] + CphError(#[from] Box), +} +efrom!(SetAccelSpeedError, CphError); + +#[derive(Debug, Error)] +enum SetTransformMatrixError { + #[error(transparent)] + CphError(#[from] Box), +} +efrom!(SetTransformMatrixError, CphError); + #[derive(Debug, Error)] enum HasCapabilityError { #[error(transparent)] CphError(#[from] Box), + #[error("Queried unknown capability: {}", (.0).0)] + UnknownCapability(Capability), } efrom!(HasCapabilityError, CphError); diff --git a/src/libinput/consts.rs b/src/libinput/consts.rs index 716f35d3..42b2d3ff 100644 --- a/src/libinput/consts.rs +++ b/src/libinput/consts.rs @@ -150,3 +150,19 @@ cenum! { LIBINPUT_EVENT_GESTURE_HOLD_END = 807, LIBINPUT_EVENT_SWITCH_TOGGLE = 900, } + +cenum! { + ConfigStatus, LIBINPUT_CONFIG_STATUS; + + LIBINPUT_CONFIG_STATUS_SUCCESS = 0, + LIBINPUT_CONFIG_STATUS_UNSUPPORTED = 1, + LIBINPUT_CONFIG_STATUS_INVALID = 2, +} + +cenum! { + AccelProfile, LIBINPUT_CONFIG_ACCEL_PROFILE; + + LIBINPUT_CONFIG_ACCEL_PROFILE_NONE = 0, + LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT = 1 << 0, + LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE = 1 << 1, +} diff --git a/src/libinput/device.rs b/src/libinput/device.rs index 1e6ee8ee..8fc01021 100644 --- a/src/libinput/device.rs +++ b/src/libinput/device.rs @@ -1,8 +1,13 @@ -use crate::libinput::sys::{libinput_device, libinput_device_get_user_data, libinput_device_has_capability, libinput_device_set_user_data, libinput_device_unref, libinput_path_remove_device}; +use crate::libinput::consts::{AccelProfile, DeviceCapability}; +use crate::libinput::sys::{ + libinput_device, libinput_device_config_accel_set_profile, + libinput_device_config_accel_set_speed, libinput_device_config_left_handed_set, + libinput_device_get_user_data, libinput_device_has_capability, libinput_device_set_user_data, + libinput_device_unref, libinput_path_remove_device, +}; use crate::libinput::LibInput; use std::marker::PhantomData; use std::rc::Rc; -use crate::libinput::consts::{DeviceCapability}; pub struct LibInputDevice<'a> { pub(super) dev: *mut libinput_device, @@ -42,6 +47,24 @@ impl<'a> LibInputDevice<'a> { let res = unsafe { libinput_device_has_capability(self.dev, cap.raw() as _) }; res != 0 } + + pub fn set_left_handed(&self, left_handed: bool) { + unsafe { + libinput_device_config_left_handed_set(self.dev, left_handed as _); + } + } + + pub fn set_accel_profile(&self, profile: AccelProfile) { + unsafe { + libinput_device_config_accel_set_profile(self.dev, profile.raw() as _); + } + } + + pub fn set_accel_speed(&self, speed: f64) { + unsafe { + libinput_device_config_accel_set_speed(self.dev, speed); + } + } } impl RegisteredDevice { diff --git a/src/libinput/event.rs b/src/libinput/event.rs index 190bb469..79e01db8 100644 --- a/src/libinput/event.rs +++ b/src/libinput/event.rs @@ -8,7 +8,7 @@ use crate::libinput::sys::{ libinput_event_pointer, libinput_event_pointer_get_button, libinput_event_pointer_get_button_state, libinput_event_pointer_get_dx, libinput_event_pointer_get_dy, libinput_event_pointer_get_scroll_value_v120, - libinput_event_pointer_get_time_usec, + libinput_event_pointer_get_time_usec, libinput_event_pointer_has_axis, }; use std::marker::PhantomData; @@ -108,6 +108,10 @@ impl<'a> LibInputEventPointer<'a> { unsafe { libinput_event_pointer_get_scroll_value_v120(self.event, axis.raw() as _) } } + pub fn has_axis(&self, axis: PointerAxis) -> bool { + unsafe { libinput_event_pointer_has_axis(self.event, axis.raw() as _) != 0 } + } + #[allow(dead_code)] pub fn time_usec(&self) -> u64 { unsafe { libinput_event_pointer_get_time_usec(self.event) } diff --git a/src/libinput/sys.rs b/src/libinput/sys.rs index bd33d409..c9507064 100644 --- a/src/libinput/sys.rs +++ b/src/libinput/sys.rs @@ -38,7 +38,22 @@ extern "C" { path: *const c::c_char, ) -> *mut libinput_device; pub fn libinput_path_remove_device(device: *mut libinput_device); - pub fn libinput_device_has_capability(device: *mut libinput_device, cap: libinput_device_capability) -> c::c_int; + pub fn libinput_device_has_capability( + device: *mut libinput_device, + cap: libinput_device_capability, + ) -> c::c_int; + pub fn libinput_device_config_left_handed_set( + device: *mut libinput_device, + left_handed: c::c_int, + ) -> libinput_config_status; + pub fn libinput_device_config_accel_set_profile( + device: *mut libinput_device, + profile: libinput_config_accel_profile, + ) -> libinput_config_status; + pub fn libinput_device_config_accel_set_speed( + device: *mut libinput_device, + speed: f64, + ) -> libinput_config_status; pub fn libinput_event_destroy(event: *mut libinput_event); pub fn libinput_event_get_type(event: *mut libinput_event) -> libinput_event_type; @@ -67,6 +82,10 @@ extern "C" { event: *mut libinput_event_pointer, axis: libinput_pointer_axis, ) -> f64; + pub fn libinput_event_pointer_has_axis( + event: *mut libinput_event_pointer, + axis: libinput_pointer_axis, + ) -> c::c_int; } #[repr(C)] diff --git a/src/tree/container.rs b/src/tree/container.rs index 9f461ee4..6a5ec662 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -551,6 +551,7 @@ impl ContainerNode { fn compute_render_data(&self) { self.compute_render_data_scheduled.set(false); let mut rd = self.render_data.borrow_mut(); + let rd = rd.deref_mut(); let theme = &self.state.theme; let th = theme.title_height.get(); let bw = theme.border_width.get(); @@ -564,6 +565,19 @@ impl ContainerNode { rd.active_title_rects.clear(); rd.border_rects.clear(); rd.underline_rects.clear(); + let mut render_title = |title: &str, width: i32, x: i32, y: i32| { + if th == 0 || width == 0 || title.is_empty() { + return; + } + if let Some(ctx) = &ctx { + match text::render(ctx, width, th, &font, title, Color::GREY) { + Ok(t) => rd.titles.push(ContainerTitle { x, y, tex: t }), + Err(e) => { + log::error!("Could not render title {}: {}", title, ErrorFmt(e)); + } + } + } + }; if self.mono_child.get().is_some() { let content_width = self.width.get().sub(bw * (num_children - 1)).max(0); let space_per_child = content_width / num_children; @@ -585,19 +599,8 @@ impl ContainerNode { } else { rd.title_rects.push(rect); } - if let Some(ctx) = &ctx { - let title = c.title.borrow_mut(); - match text::render(ctx, width, th, &font, &title, Color::GREY) { - Ok(t) => rd.titles.push(ContainerTitle { - x: pos, - y: 0, - tex: t, - }), - Err(e) => { - log::error!("Could not render title {}: {}", title, ErrorFmt(e)); - } - } - } + let title = c.title.borrow_mut(); + render_title(&title, width, pos, 0); pos += width + bw; } rd.underline_rects @@ -623,19 +626,8 @@ impl ContainerNode { } let rect = Rect::new_sized(body.x1(), body.y1() - 1, body.width(), 1).unwrap(); rd.underline_rects.push(rect); - if let Some(ctx) = &ctx { - let title = c.title.borrow_mut(); - match text::render(ctx, body.width(), th, &font, &title, Color::GREY) { - Ok(t) => rd.titles.push(ContainerTitle { - x: body.x1(), - y: body.y1() - th - 1, - tex: t, - }), - Err(e) => { - log::error!("Could not render title {}: {}", title, ErrorFmt(e)); - } - } - } + let title = c.title.borrow_mut(); + render_title(&title, body.width(), body.x1(), body.y1() - th - 1); } } } diff --git a/src/tree/float.rs b/src/tree/float.rs index 726cc751..d7307660 100644 --- a/src/tree/float.rs +++ b/src/tree/float.rs @@ -166,7 +166,7 @@ impl FloatNode { let title = self.title.borrow_mut(); self.title_texture.set(None); let pos = self.position.get(); - if pos.width() <= 2 * bw { + if pos.width() <= 2 * bw || th == 0 || title.is_empty() { return; } let ctx = match self.state.render_ctx.get() {