1
0
Fork 0
forked from wry/wry

input: add click method and middle button emulation

This commit is contained in:
Stipe Kotarac 2025-05-12 17:52:36 +02:00 committed by Julian Orth
parent 0524e01a3c
commit b20153550e
24 changed files with 598 additions and 21 deletions

View file

@ -229,6 +229,14 @@ pub trait InputDevice {
None
}
fn set_natural_scrolling_enabled(&self, enabled: bool);
fn click_method(&self) -> Option<InputDeviceClickMethod> {
None
}
fn set_click_method(&self, method: InputDeviceClickMethod);
fn middle_button_emulation_enabled(&self) -> Option<bool> {
None
}
fn set_middle_button_emulation_enabled(&self, enabled: bool);
fn tablet_info(&self) -> Option<Box<TabletInit>> {
None
}
@ -269,6 +277,13 @@ pub enum InputDeviceAccelProfile {
Adaptive,
}
#[derive(Debug, Copy, Clone)]
pub enum InputDeviceClickMethod {
None,
ButtonAreas,
Clickfinger,
}
pub enum BackendEvent {
NewDrmDevice(Rc<dyn BackendDrmDevice>),
NewConnector(Rc<dyn Connector>),

View file

@ -8,7 +8,8 @@ use {
async_engine::SpawnedFuture,
backend::{
Backend, InputDevice, InputDeviceAccelProfile, InputDeviceCapability,
InputDeviceGroupId, InputDeviceId, InputEvent, KeyState, TransformMatrix,
InputDeviceClickMethod, InputDeviceGroupId, InputDeviceId, InputEvent, KeyState,
TransformMatrix,
},
backends::metal::video::{
MetalDrmDeviceData, MetalLeaseData, MetalRenderContext, PendingDrmDevice,
@ -26,9 +27,10 @@ use {
libinput::{
LibInput, LibInputAdapter, LibInputError,
consts::{
AccelProfile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, LIBINPUT_DEVICE_CAP_TABLET_PAD,
LIBINPUT_DEVICE_CAP_TABLET_TOOL,
AccelProfile, ConfigClickMethod, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS,
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER, LIBINPUT_CONFIG_CLICK_METHOD_NONE,
LIBINPUT_DEVICE_CAP_TABLET_PAD, LIBINPUT_DEVICE_CAP_TABLET_TOOL,
},
device::{LibInputDevice, RegisteredDevice},
},
@ -400,6 +402,8 @@ struct InputDeviceProperties {
drag_lock_enabled: Cell<Option<bool>>,
natural_scrolling_enabled: Cell<Option<bool>>,
calibration_matrix: Cell<Option<[[f32; 3]; 2]>>,
click_method: Cell<Option<ConfigClickMethod>>,
middle_button_emulation_enabled: Cell<Option<bool>>,
}
#[derive(Clone)]
@ -463,6 +467,12 @@ impl MetalInputDevice {
if let Some(lh) = self.desired.calibration_matrix.get() {
self.set_calibration_matrix(lh);
}
if let Some(method) = self.desired.click_method.get() {
self.set_click_method_(method);
}
if let Some(enabled) = self.desired.middle_button_emulation_enabled.get() {
self.set_middle_button_emulation_enabled(enabled);
}
self.fetch_effective();
}
@ -497,6 +507,14 @@ impl MetalInputDevice {
.calibration_matrix
.set(Some(device.get_calibration_matrix()));
}
if device.has_click_methods() {
self.effective.click_method.set(Some(device.click_method()));
}
if device.middle_button_emulation_available() {
self.effective
.middle_button_emulation_enabled
.set(Some(device.middle_button_emulation_enabled()));
}
}
fn pre_pause(&self) {
@ -528,6 +546,18 @@ impl MetalInputDevice {
}
}
}
fn set_click_method_(&self, method: ConfigClickMethod) {
self.desired.click_method.set(Some(method));
if let Some(dev) = self.inputdev.get() {
if dev.device().has_click_methods() {
dev.device().set_click_method(method);
self.effective
.click_method
.set(Some(dev.device().click_method()));
}
}
}
}
impl InputDevice for MetalInputDevice {
@ -705,6 +735,44 @@ impl InputDevice for MetalInputDevice {
}
}
fn click_method(&self) -> Option<InputDeviceClickMethod> {
let p = self.effective.click_method.get()?;
let p = match p {
LIBINPUT_CONFIG_CLICK_METHOD_NONE => InputDeviceClickMethod::None,
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS => InputDeviceClickMethod::ButtonAreas,
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER => InputDeviceClickMethod::Clickfinger,
_ => return None,
};
Some(p)
}
fn set_click_method(&self, method: InputDeviceClickMethod) {
let method = match method {
InputDeviceClickMethod::None => LIBINPUT_CONFIG_CLICK_METHOD_NONE,
InputDeviceClickMethod::ButtonAreas => LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS,
InputDeviceClickMethod::Clickfinger => LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER,
};
self.set_click_method_(method);
}
fn middle_button_emulation_enabled(&self) -> Option<bool> {
self.effective.middle_button_emulation_enabled.get()
}
fn set_middle_button_emulation_enabled(&self, enabled: bool) {
self.desired
.middle_button_emulation_enabled
.set(Some(enabled));
if let Some(dev) = self.inputdev.get() {
if dev.device().middle_button_emulation_available() {
dev.device().set_middle_button_emulation_enabled(enabled);
self.effective
.middle_button_emulation_enabled
.set(Some(dev.device().middle_button_emulation_enabled()));
}
}
}
fn tablet_info(&self) -> Option<Box<TabletInit>> {
let dev = self.inputdev.get()?;
let dev = dev.device();

View file

@ -6,7 +6,8 @@ use {
AXIS_120, AxisSource, Backend, BackendColorSpace, BackendDrmDevice, BackendEvent,
BackendTransferFunction, Connector, ConnectorEvent, ConnectorId, ConnectorKernelId,
DrmDeviceId, DrmEvent, InputDevice, InputDeviceAccelProfile, InputDeviceCapability,
InputDeviceId, InputEvent, KeyState, Mode, MonitorInfo, ScrollAxis, TransformMatrix,
InputDeviceClickMethod, InputDeviceId, InputEvent, KeyState, Mode, MonitorInfo,
ScrollAxis, TransformMatrix,
},
cmm::cmm_primaries::Primaries,
fixed::Fixed,
@ -1219,6 +1220,14 @@ impl InputDevice for XSeatKeyboard {
fn set_natural_scrolling_enabled(&self, enabled: bool) {
let _ = enabled;
}
fn set_click_method(&self, method: InputDeviceClickMethod) {
let _ = method;
}
fn set_middle_button_emulation_enabled(&self, enabled: bool) {
let _ = enabled;
}
}
impl InputDevice for XSeatMouse {
@ -1288,4 +1297,12 @@ impl InputDevice for XSeatMouse {
fn set_natural_scrolling_enabled(&self, enabled: bool) {
let _ = enabled;
}
fn set_click_method(&self, method: InputDeviceClickMethod) {
let _ = method;
}
fn set_middle_button_emulation_enabled(&self, enabled: bool) {
let _ = enabled;
}
}

View file

@ -1,10 +1,12 @@
use {
crate::{
backend::{InputDeviceAccelProfile, InputDeviceCapability},
backend::{InputDeviceAccelProfile, InputDeviceCapability, InputDeviceClickMethod},
cli::GlobalArgs,
clientmem::ClientMem,
libinput::consts::{
LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE, LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT,
ConfigClickMethod, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS,
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER, LIBINPUT_CONFIG_CLICK_METHOD_NONE,
},
tools::tool_client::{Handle, ToolClient, with_tool_client},
utils::{errorfmt::ErrorFmt, string_ext::StringExt},
@ -133,6 +135,10 @@ pub enum DeviceCommand {
RemoveMapping,
/// Set the calibration matrix.
SetCalibrationMatrix(SetCalibrationMatrixArgs),
/// Set the click method.
SetClickMethod(SetClickMethodArgs),
/// Set whether the device uses middle button emulation.
SetMiddleButtonEmulation(SetMiddleButtonEmulationArgs),
}
#[derive(ValueEnum, Debug, Clone)]
@ -212,6 +218,26 @@ pub struct SetCalibrationMatrixArgs {
pub m12: f32,
}
#[derive(ValueEnum, Debug, Clone)]
pub enum ClickMethod {
None,
ButtonAreas,
Clickfinger,
}
#[derive(Args, Debug, Clone)]
pub struct SetClickMethodArgs {
/// The method.
pub method: ClickMethod,
}
#[derive(Args, Debug, Clone)]
pub struct SetMiddleButtonEmulationArgs {
/// Whether middle button emulation is enabled.
#[arg(action = clap::ArgAction::Set)]
pub middle_button_emulation: bool,
}
#[derive(Args, Debug, Clone)]
pub struct MapToOutputArgs {
/// The output to map to.
@ -286,6 +312,8 @@ struct InputDevice {
pub transform_matrix: Option<[[f64; 2]; 2]>,
pub output: Option<String>,
pub calibration_matrix: Option<[[f32; 3]; 2]>,
pub click_method: Option<InputDeviceClickMethod>,
pub middle_button_emulation_enabled: Option<bool>,
}
#[derive(Clone, Debug, Default)]
@ -626,6 +654,34 @@ impl Input {
m12: a.m12,
});
}
DeviceCommand::SetClickMethod(a) => {
let method = match a.method {
ClickMethod::None => LIBINPUT_CONFIG_CLICK_METHOD_NONE.0,
ClickMethod::ButtonAreas => LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS.0,
ClickMethod::Clickfinger => LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER.0,
};
self.handle_error(input, |e| {
eprintln!("Could not set the click method: {}", e);
});
tc.send(jay_input::SetClickMethod {
self_id: input,
id: args.device,
method,
});
}
DeviceCommand::SetMiddleButtonEmulation(a) => {
self.handle_error(input, |e| {
eprintln!(
"Could not modify the middle-button-emulation setting: {}",
e
);
});
tc.send(jay_input::SetMiddleButtonEmulation {
self_id: input,
id: args.device,
enabled: a.middle_button_emulation as _,
});
}
}
tc.round_trip().await;
}
@ -762,6 +818,17 @@ impl Input {
if let Some(v) = &device.calibration_matrix {
println!("{prefix} calibration matrix: {:?}", v);
}
if let Some(v) = &device.click_method {
let name = match v {
InputDeviceClickMethod::None => "none",
InputDeviceClickMethod::ButtonAreas => "button-areas",
InputDeviceClickMethod::Clickfinger => "clickfinger",
};
println!("{prefix} click method: {}", name);
}
if let Some(v) = &device.middle_button_emulation_enabled {
println!("{prefix} middle button emulation: {}", v);
}
}
async fn get(self: &Rc<Self>, input: JayInputId) -> Data {
@ -827,6 +894,8 @@ impl Input {
transform_matrix: uapi::pod_read(msg.transform_matrix).ok(),
output: None,
calibration_matrix: None,
click_method: None,
middle_button_emulation_enabled: None,
});
});
jay_input::InputDeviceOutput::handle(tc, input, data.clone(), |data, msg| {
@ -842,6 +911,29 @@ impl Input {
Some([[msg.m00, msg.m01, msg.m02], [msg.m10, msg.m11, msg.m12]]);
}
});
jay_input::ClickMethod::handle(tc, input, data.clone(), |data, msg| {
let click_method = match ConfigClickMethod(msg.click_method) {
LIBINPUT_CONFIG_CLICK_METHOD_NONE => Some(InputDeviceClickMethod::None),
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS => {
Some(InputDeviceClickMethod::ButtonAreas)
}
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER => {
Some(InputDeviceClickMethod::Clickfinger)
}
_ => None,
};
let mut data = data.borrow_mut();
if let Some(last) = data.input_device.last_mut() {
last.click_method = click_method;
}
});
jay_input::MiddleButtonEmulation::handle(tc, input, data.clone(), |data, msg| {
let mut data = data.borrow_mut();
if let Some(last) = data.input_device.last_mut() {
last.middle_button_emulation_enabled =
Some(msg.middle_button_emulation_enabled != 0);
}
});
tc.round_trip().await;
let x = data.borrow_mut().clone();
x

View file

@ -3,7 +3,7 @@ use {
async_engine::SpawnedFuture,
backend::{
self, BackendColorSpace, BackendTransferFunction, ConnectorId, DrmDeviceId,
InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId,
InputDeviceAccelProfile, InputDeviceCapability, InputDeviceClickMethod, InputDeviceId,
},
client::{Client, ClientId},
cmm::cmm_transfer_function::TransferFunction,
@ -56,6 +56,9 @@ use {
CAP_GESTURE, CAP_KEYBOARD, CAP_POINTER, CAP_SWITCH, CAP_TABLET_PAD,
CAP_TABLET_TOOL, CAP_TOUCH, Capability,
},
clickmethod::{
CLICK_METHOD_BUTTON_AREAS, CLICK_METHOD_CLICKFINGER, CLICK_METHOD_NONE, ClickMethod,
},
},
keyboard::{Keymap, mods::Modifiers, syms::KeySym},
logging::LogLevel,
@ -828,6 +831,32 @@ impl ConfigProxyHandler {
Ok(())
}
fn handle_set_click_method(
&self,
device: InputDevice,
click_method: ClickMethod,
) -> Result<(), CphError> {
let dev = self.get_device_handler_data(device)?;
let method = match click_method {
CLICK_METHOD_NONE => InputDeviceClickMethod::None,
CLICK_METHOD_BUTTON_AREAS => InputDeviceClickMethod::ButtonAreas,
CLICK_METHOD_CLICKFINGER => InputDeviceClickMethod::Clickfinger,
_ => return Err(CphError::UnknownClickMethod(click_method)),
};
dev.device.set_click_method(method);
Ok(())
}
fn handle_set_middle_button_emulation_enabled(
&self,
device: InputDevice,
enabled: bool,
) -> Result<(), CphError> {
let dev = self.get_device_handler_data(device)?;
dev.device.set_middle_button_emulation_enabled(enabled);
Ok(())
}
fn handle_set_ei_socket_enabled(&self, enabled: bool) {
self.state.enable_ei_acceptor.set(enabled);
self.state.update_ei_acceptor();
@ -2916,6 +2945,12 @@ impl ConfigProxyHandler {
ClientMessage::SetPointerRevertKey { seat, key } => self
.handle_set_pointer_revert_key(seat, key)
.wrn("set_pointer_revert_key")?,
ClientMessage::SetClickMethod { device, method } => self
.handle_set_click_method(device, method)
.wrn("set_click_method")?,
ClientMessage::SetMiddleButtonEmulationEnabled { device, enabled } => self
.handle_set_middle_button_emulation_enabled(device, enabled)
.wrn("set_middle_button_emulation_enabled")?,
}
Ok(())
}
@ -2945,6 +2980,8 @@ enum CphError {
UnknownAccelProfile(AccelProfile),
#[error("Queried unknown capability: {}", (.0).0)]
UnknownCapability(Capability),
#[error("Tried to set an unknown click method: {}", (.0).0)]
UnknownClickMethod(ClickMethod),
#[error("The sized {} is outside the valid range [{}, {}] for component {}", .0, .1.min(), .1.max(), .1.name())]
InvalidSize(i32, ThemeSized),
#[error("The ol' forker is not available")]

View file

@ -79,7 +79,7 @@ impl Global for JayCompositorGlobal {
}
fn version(&self) -> u32 {
18
19
}
fn required_caps(&self) -> ClientCaps {

View file

@ -1,14 +1,15 @@
use {
crate::{
backend::{self, InputDeviceAccelProfile, InputDeviceId},
backend::{self, InputDeviceAccelProfile, InputDeviceClickMethod, InputDeviceId},
client::{Client, ClientError},
clientmem::{ClientMem, ClientMemError},
ifs::wl_seat::WlSeatGlobal,
kbvm::{KbvmError, KbvmMap},
leaks::Tracker,
libinput::consts::{
AccelProfile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT,
AccelProfile, ConfigClickMethod, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT, LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS,
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER, LIBINPUT_CONFIG_CLICK_METHOD_NONE,
},
object::{Object, Version},
state::{DeviceHandlerData, InputDeviceData},
@ -28,6 +29,8 @@ pub struct JayInput {
}
const CALIBRATION_MATRIX_SINCE: Version = Version(4);
const CLICK_METHOD_SINCE: Version = Version(19);
const MIDDLE_BUTTON_EMULATION_SINCE: Version = Version(19);
impl JayInput {
pub fn new(id: JayInputId, client: &Rc<Client>, version: Version) -> Self {
@ -155,6 +158,30 @@ impl JayInput {
});
}
}
if self.version >= CLICK_METHOD_SINCE {
if let Some(click_method) = dev.click_method() {
self.client.event(ClickMethod {
self_id: self.id,
click_method: match click_method {
InputDeviceClickMethod::None => LIBINPUT_CONFIG_CLICK_METHOD_NONE.0,
InputDeviceClickMethod::Clickfinger => {
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER.0
}
InputDeviceClickMethod::ButtonAreas => {
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS.0
}
},
});
}
}
if self.version >= MIDDLE_BUTTON_EMULATION_SINCE {
if let Some(middle_button_emulation) = dev.middle_button_emulation_enabled() {
self.client.event(MiddleButtonEmulation {
self_id: self.id,
middle_button_emulation_enabled: middle_button_emulation as _,
});
}
}
}
fn device(&self, id: u32) -> Result<Rc<DeviceHandlerData>, JayInputError> {
@ -461,6 +488,33 @@ impl JayInputRequestHandler for JayInput {
Ok(())
})
}
fn set_click_method(&self, req: SetClickMethod, _slf: &Rc<Self>) -> Result<(), Self::Error> {
self.or_error(|| {
let dev = self.device(req.id)?;
let method = match ConfigClickMethod(req.method) {
LIBINPUT_CONFIG_CLICK_METHOD_NONE => InputDeviceClickMethod::None,
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS => InputDeviceClickMethod::ButtonAreas,
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER => InputDeviceClickMethod::Clickfinger,
_ => return Err(JayInputError::UnknownClickMethod(req.method)),
};
dev.device.set_click_method(method);
Ok(())
})
}
fn set_middle_button_emulation(
&self,
req: SetMiddleButtonEmulation,
_slf: &Rc<Self>,
) -> Result<(), Self::Error> {
self.or_error(|| {
let dev = self.device(req.id)?;
dev.device
.set_middle_button_emulation_enabled(req.enabled != 0);
Ok(())
})
}
}
object_base! {
@ -482,6 +536,8 @@ pub enum JayInputError {
DeviceDoesNotExist(u32),
#[error("There is no acceleration profile with id {0}")]
UnknownAccelerationProfile(i32),
#[error("There is no click method with id {0}")]
UnknownClickMethod(i32),
#[error("Repeat rate must not be negative")]
NegativeRepeatRate,
#[error("Repeat delay must not be negative")]

View file

@ -5,8 +5,8 @@ use {
backend::{
AxisSource, Backend, BackendColorSpace, BackendEvent, BackendTransferFunction,
Connector, ConnectorEvent, ConnectorId, ConnectorKernelId, DrmDeviceId, InputDevice,
InputDeviceAccelProfile, InputDeviceCapability, InputDeviceId, InputEvent, KeyState,
Mode, MonitorInfo, ScrollAxis, TransformMatrix,
InputDeviceAccelProfile, InputDeviceCapability, InputDeviceClickMethod, InputDeviceId,
InputEvent, KeyState, Mode, MonitorInfo, ScrollAxis, TransformMatrix,
},
cmm::cmm_primaries::Primaries,
compositor::TestFuture,
@ -543,6 +543,14 @@ trait TestInputDevice: InputDevice {
fn set_natural_scrolling_enabled(&self, enabled: bool) {
let _ = enabled;
}
fn set_click_method(&self, method: InputDeviceClickMethod) {
let _ = method;
}
fn set_middle_button_emulation_enabled(&self, enabled: bool) {
let _ = enabled;
}
}
impl<T: TestInputDevice> InputDevice for T {
@ -609,4 +617,12 @@ impl<T: TestInputDevice> InputDevice for T {
fn set_natural_scrolling_enabled(&self, enabled: bool) {
<Self as TestInputDevice>::set_natural_scrolling_enabled(self, enabled)
}
fn set_click_method(&self, method: InputDeviceClickMethod) {
<Self as TestInputDevice>::set_click_method(self, method)
}
fn set_middle_button_emulation_enabled(&self, enabled: bool) {
<Self as TestInputDevice>::set_middle_button_emulation_enabled(self, enabled)
}
}

View file

@ -188,3 +188,18 @@ cenum! {
LIBINPUT_CONFIG_DRAG_LOCK_DISABLED = 0,
LIBINPUT_CONFIG_DRAG_LOCK_ENABLED = 1,
}
cenum! {
ConfigClickMethod, LIBINPUT_CONFIG_CLICK_METHOD;
LIBINPUT_CONFIG_CLICK_METHOD_NONE = 0,
LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS = 1 << 0,
LIBINPUT_CONFIG_CLICK_METHOD_CLICKFINGER = 1 << 1,
}
cenum! {
ConfigMiddleEmulationState, LIBINPUT_CONFIG_MIDDLE_EMULATION_STATE;
LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED = 0,
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED = 1,
}

View file

@ -2,9 +2,11 @@ use {
crate::libinput::{
LibInput,
consts::{
AccelProfile, ConfigDragLockState, ConfigDragState, ConfigTapState, DeviceCapability,
AccelProfile, ConfigClickMethod, ConfigDragLockState, ConfigDragState,
ConfigMiddleEmulationState, ConfigTapState, DeviceCapability,
LIBINPUT_CONFIG_DRAG_DISABLED, LIBINPUT_CONFIG_DRAG_ENABLED,
LIBINPUT_CONFIG_DRAG_LOCK_DISABLED, LIBINPUT_CONFIG_DRAG_LOCK_ENABLED,
LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED, LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED,
LIBINPUT_CONFIG_TAP_DISABLED, LIBINPUT_CONFIG_TAP_ENABLED,
},
sys::{
@ -13,9 +15,14 @@ use {
libinput_device_config_accel_set_profile, libinput_device_config_accel_set_speed,
libinput_device_config_calibration_get_matrix,
libinput_device_config_calibration_has_matrix,
libinput_device_config_calibration_set_matrix, libinput_device_config_left_handed_get,
libinput_device_config_calibration_set_matrix, libinput_device_config_click_get_method,
libinput_device_config_click_get_methods, libinput_device_config_click_set_method,
libinput_device_config_left_handed_get,
libinput_device_config_left_handed_is_available,
libinput_device_config_left_handed_set,
libinput_device_config_middle_emulation_get_enabled,
libinput_device_config_middle_emulation_is_available,
libinput_device_config_middle_emulation_set_enabled,
libinput_device_config_scroll_get_natural_scroll_enabled,
libinput_device_config_scroll_has_natural_scroll,
libinput_device_config_scroll_set_natural_scroll_enabled,
@ -209,6 +216,46 @@ impl<'a> LibInputDevice<'a> {
unsafe { libinput_device_config_scroll_has_natural_scroll(self.dev) != 0 }
}
pub fn has_click_methods(&self) -> bool {
unsafe { libinput_device_config_click_get_methods(self.dev) != 0 }
}
pub fn click_method(&self) -> ConfigClickMethod {
unsafe { ConfigClickMethod(libinput_device_config_click_get_method(self.dev)) }
}
pub fn set_click_method(&self, method: ConfigClickMethod) {
unsafe {
libinput_device_config_click_set_method(self.dev, method.raw() as _);
}
}
pub fn set_middle_button_emulation_enabled(&self, enabled: bool) {
let enabled = match enabled {
true => LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED,
false => LIBINPUT_CONFIG_MIDDLE_EMULATION_DISABLED,
};
unsafe {
libinput_device_config_middle_emulation_set_enabled(self.dev, enabled.raw() as _);
}
}
pub fn middle_button_emulation_enabled(&self) -> bool {
let enabled = unsafe {
ConfigMiddleEmulationState(libinput_device_config_middle_emulation_get_enabled(
self.dev,
))
};
match enabled {
LIBINPUT_CONFIG_MIDDLE_EMULATION_ENABLED => true,
_ => false,
}
}
pub fn middle_button_emulation_available(&self) -> bool {
unsafe { libinput_device_config_middle_emulation_is_available(self.dev) != 0 }
}
pub fn device_group(&self) -> LibInputDeviceGroup<'_> {
LibInputDeviceGroup {
group: unsafe { libinput_device_get_device_group(self.dev) },

View file

@ -114,6 +114,26 @@ unsafe extern "C" {
device: *mut libinput_device,
) -> c::c_int;
pub fn libinput_device_config_click_get_methods(device: *mut libinput_device) -> u32;
pub fn libinput_device_config_click_get_method(
device: *mut libinput_device,
) -> libinput_config_click_method;
pub fn libinput_device_config_click_set_method(
device: *mut libinput_device,
method: libinput_config_click_method,
) -> libinput_config_status;
pub fn libinput_device_config_middle_emulation_set_enabled(
device: *mut libinput_device,
enable: libinput_config_middle_emulation_state,
) -> libinput_config_status;
pub fn libinput_device_config_middle_emulation_get_enabled(
device: *mut libinput_device,
) -> libinput_config_middle_emulation_state;
pub fn libinput_device_config_middle_emulation_is_available(
device: *mut libinput_device,
) -> c::c_int;
pub fn libinput_event_destroy(event: *mut libinput_event);
pub fn libinput_event_get_type(event: *mut libinput_event) -> libinput_event_type;
pub fn libinput_event_get_device(event: *mut libinput_event) -> *mut libinput_device;

View file

@ -335,7 +335,7 @@ impl ToolClient {
self_id: s.registry,
name: s.jay_compositor.0,
interface: JayCompositor.name(),
version: s.jay_compositor.1.min(18),
version: s.jay_compositor.1.min(19),
id: id.into(),
});
self.jay_compositor.set(Some(id));