diff --git a/default-config/src/lib.rs b/default-config/src/lib.rs index d7541e0a..ab8b2f6c 100644 --- a/default-config/src/lib.rs +++ b/default-config/src/lib.rs @@ -12,6 +12,7 @@ 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; @@ -93,12 +94,14 @@ fn configure_seat(s: Seat) { fn do_grab(s: Seat, grab: bool) { for device in s.input_devices() { - log::info!( - "{}rabbing keyboard {:?}", - if grab { "G" } else { "Ung" }, - device.0 - ); - grab_input_device(device, grab); + if device.has_capability(CAP_KEYBOARD) { + log::info!( + "{}rabbing keyboard {:?}", + if grab { "G" } else { "Ung" }, + device.0 + ); + grab_input_device(device, grab); + } } if grab { s.unbind(SYM_y); diff --git a/jay-config/src/_private/client.rs b/jay-config/src/_private/client.rs index dc32b97d..1ac011a0 100644 --- a/jay-config/src/_private/client.rs +++ b/jay-config/src/_private/client.rs @@ -4,13 +4,14 @@ use crate::_private::ipc::{ClientMessage, InitMessage, Response, ServerMessage}; use crate::_private::{bincode_ops, logging, Config, ConfigEntry, ConfigEntryGen, VERSION}; use crate::keyboard::keymap::Keymap; use crate::theme::Color; -use crate::{Axis, Command, Direction, InputDevice, LogLevel, ModifiedKeySym, Seat}; +use crate::{Axis, Command, Direction, LogLevel, ModifiedKeySym, Seat}; use std::cell::{Cell, RefCell}; use std::collections::hash_map::Entry; 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(), @@ -317,6 +318,17 @@ impl Client { self.send(&ClientMessage::SetSeat { device, seat }) } + pub fn has_capability(&self, device: InputDevice, cap: Capability) -> bool { + let res = self.with_response(|| self.send(&ClientMessage::HasCapability { device, cap })); + match res { + Response::HasCapability { has } => has, + _ => { + log::error!("Server did not send a response to a has_capability request"); + false + } + } + } + pub fn seat_set_keymap(&self, seat: Seat, keymap: Keymap) { self.send(&ClientMessage::SeatSetKeymap { seat, keymap }) } diff --git a/jay-config/src/_private/ipc.rs b/jay-config/src/_private/ipc.rs index c2e8af0b..d35cc804 100644 --- a/jay-config/src/_private/ipc.rs +++ b/jay-config/src/_private/ipc.rs @@ -2,8 +2,9 @@ use crate::keyboard::keymap::Keymap; use crate::keyboard::mods::Modifiers; use crate::keyboard::syms::KeySym; use crate::theme::Color; -use crate::{Axis, Direction, InputDevice, LogLevel, Seat}; +use crate::{Axis, Direction, LogLevel, Seat}; use bincode::{BorrowDecode, Decode, Encode}; +use crate::input::{Capability, InputDevice}; #[derive(Encode, BorrowDecode, Debug)] pub enum ServerMessage { @@ -136,6 +137,10 @@ pub enum ClientMessage<'a> { ToggleFloating { seat: Seat, }, + HasCapability { + device: InputDevice, + cap: Capability, + }, } #[derive(Encode, Decode, Debug)] @@ -150,6 +155,7 @@ pub enum Response { GetInputDevices { devices: Vec }, GetTitleHeight { height: i32 }, GetBorderWidth { width: i32 }, + HasCapability { has: bool }, } #[derive(Encode, Decode, Debug)] diff --git a/jay-config/src/embedded.rs b/jay-config/src/embedded.rs index 54a81f54..5d5e6dc2 100644 --- a/jay-config/src/embedded.rs +++ b/jay-config/src/embedded.rs @@ -1,4 +1,4 @@ -use crate::InputDevice; +use crate::input::InputDevice; pub fn grab_input_device(kb: InputDevice, grab: bool) { get!().grab(kb, grab); diff --git a/jay-config/src/input.rs b/jay-config/src/input.rs new file mode 100644 index 00000000..1f15bcd7 --- /dev/null +++ b/jay-config/src/input.rs @@ -0,0 +1,26 @@ +use bincode::{Decode, Encode}; +use crate::Seat; + +#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] +pub struct InputDevice(pub u64); + +impl InputDevice { + pub fn set_seat(self, seat: Seat) { + get!().set_seat(self, seat) + } + + pub fn has_capability(self, cap: Capability) -> bool { + get!(false).has_capability(self, cap) + } +} + +#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] +pub struct Capability(pub u32); + +pub const CAP_KEYBOARD: Capability = Capability(0); +pub const CAP_POINTER: Capability = Capability(1); +pub const CAP_TOUCH: Capability = Capability(2); +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); diff --git a/jay-config/src/lib.rs b/jay-config/src/lib.rs index e11ac0a7..76e26a40 100644 --- a/jay-config/src/lib.rs +++ b/jay-config/src/lib.rs @@ -2,6 +2,7 @@ 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; @@ -10,6 +11,7 @@ pub mod _private; pub mod embedded; pub mod keyboard; pub mod theme; +pub mod input; #[derive(Encode, Decode, Copy, Clone, Debug)] pub enum LogLevel { @@ -39,15 +41,6 @@ impl Seat { } } -#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] -pub struct InputDevice(pub u64); - -impl InputDevice { - pub fn set_seat(self, seat: Seat) { - get!().set_seat(self, seat) - } -} - #[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)] pub enum Axis { Horizontal, diff --git a/jay-config/src/macros.rs b/jay-config/src/macros.rs index 6f4707de..3f49fd30 100644 --- a/jay-config/src/macros.rs +++ b/jay-config/src/macros.rs @@ -17,11 +17,14 @@ macro_rules! config { macro_rules! get { () => {{ + get!(()) + }}; + ($def:expr) => {{ #[allow(unused_unsafe)] let client = unsafe { let client = crate::_private::client::CLIENT.with(|client| client.get()); if client.is_null() { - return; + return $def; } &*client }; diff --git a/src/backend.rs b/src/backend.rs index 0a41b935..b5508047 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -23,6 +23,18 @@ pub trait InputDevice { fn event(&self) -> Option; fn on_change(&self, cb: Rc); fn grab(&self, grab: bool); + fn has_capability(&self, cap: InputDeviceCapability) -> bool; +} + +#[derive(Debug, Copy, Clone)] +pub enum InputDeviceCapability { + Keyboard, + Pointer, + Touch, + TabletTool, + TabletPad, + Gesture, + Switch, } pub enum BackendEvent { diff --git a/src/backends/metal.rs b/src/backends/metal.rs index 51429605..b9354de7 100644 --- a/src/backends/metal.rs +++ b/src/backends/metal.rs @@ -3,7 +3,7 @@ mod monitor; mod video; use crate::async_engine::{AsyncError, AsyncFd}; -use crate::backend::{Backend, InputDevice, InputDeviceId, InputEvent}; +use crate::backend::{Backend, InputDevice, InputDeviceCapability, InputDeviceId, InputEvent}; use crate::backends::metal::video::{MetalDrmDevice, PendingDrmDevice}; use crate::dbus::DbusError; use crate::drm::drm::DrmError; @@ -25,6 +25,7 @@ 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 { @@ -180,7 +181,7 @@ struct MetalInputDevice { id: InputDeviceId, _devnum: c::dev_t, fd: CloneCell>>, - inputdev: Cell>, + inputdev: CloneCell>>, devnode: CString, _sysname: CString, removed: Cell, @@ -242,6 +243,22 @@ impl InputDevice for MetalInputDevice { fn grab(&self, _grab: bool) { // nothing } + + fn has_capability(&self, cap: InputDeviceCapability) -> bool { + let li = match cap { + InputDeviceCapability::Keyboard => LIBINPUT_DEVICE_CAP_KEYBOARD, + InputDeviceCapability::Pointer => LIBINPUT_DEVICE_CAP_POINTER, + InputDeviceCapability::Touch => LIBINPUT_DEVICE_CAP_TOUCH, + InputDeviceCapability::TabletTool => LIBINPUT_DEVICE_CAP_TABLET_TOOL, + InputDeviceCapability::TabletPad => LIBINPUT_DEVICE_CAP_TABLET_PAD, + InputDeviceCapability::Gesture => LIBINPUT_DEVICE_CAP_GESTURE, + InputDeviceCapability::Switch => LIBINPUT_DEVICE_CAP_SWITCH, + }; + match self.inputdev.get() { + Some(dev) => dev.device().has_cap(li), + _ => false, + } + } } impl MetalInputDevice { diff --git a/src/backends/metal/monitor.rs b/src/backends/metal/monitor.rs index 3e412cb9..86a0c5b9 100644 --- a/src/backends/metal/monitor.rs +++ b/src/backends/metal/monitor.rs @@ -95,7 +95,7 @@ impl MetalBackend { self.state.fdcloser.close(old); } let inputdev = match self.libinput.open(dev.devnode.as_c_str()) { - Ok(d) => d, + Ok(d) => Rc::new(d), Err(_) => return, }; inputdev.device().set_slot(dev.slot); @@ -314,7 +314,7 @@ impl MetalBackend { } dev.fd.set(Some(res.fd.clone())); let inputdev = match slf.libinput.open(dev.devnode.as_c_str()) { - Ok(d) => d, + Ok(d) => Rc::new(d), Err(_) => return, }; inputdev.device().set_slot(slot); diff --git a/src/backends/x.rs b/src/backends/x.rs index 58cca93d..6a08ce3a 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -1,8 +1,5 @@ use crate::async_engine::{Phase, SpawnedFuture}; -use crate::backend::{ - Backend, BackendEvent, InputDevice, InputDeviceId, InputEvent, KeyState, Output, OutputId, - ScrollAxis, -}; +use crate::backend::{Backend, BackendEvent, InputDevice, 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}; @@ -638,9 +635,12 @@ impl XBackendData { return; } - let image = &output.images[output.next_image.fetch_add(1) % output.images.len()]; let serial = output.serial.fetch_add(1); + let image = &output.images[output.next_image.fetch_add(1) % output.images.len()]; + image.idle.set(false); + image.last_serial.set(serial); + if let Some(node) = self.state.root.outputs.get(&output.id) { let fb = image.fb.get(); fb.render(&*node, &self.state, Some(node.position.get())); @@ -667,8 +667,6 @@ impl XBackendData { log::error!("Could not present image: {:?}", e); return; } - image.idle.set(false); - image.last_serial.set(serial); } async fn handle_input_event(self: &Rc, event: &Event) -> Result<(), XBackendError> { @@ -958,6 +956,13 @@ impl InputDevice for XSeatKeyboard { fn grab(&self, grab: bool) { self.0.backend.grab_requests.push((self.0.clone(), grab)); } + + fn has_capability(&self, cap: InputDeviceCapability) -> bool { + match cap { + InputDeviceCapability::Keyboard => true, + _ => false, + } + } } impl InputDevice for XSeatMouse { @@ -980,4 +985,11 @@ impl InputDevice for XSeatMouse { fn grab(&self, _grab: bool) { log::error!("Cannot grab xorg mouse"); } + + fn has_capability(&self, cap: InputDeviceCapability) -> bool { + match cap { + InputDeviceCapability::Pointer => true, + _ => false, + } + } } diff --git a/src/config.rs b/src/config.rs index 27a79778..cb8e2ae3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -9,12 +9,13 @@ 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::keyboard::ModifiedKeySym; -use jay_config::{InputDevice, 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 7476cdbd..967ef05e 100644 --- a/src/config/handler.rs +++ b/src/config/handler.rs @@ -1,5 +1,5 @@ use crate::backend; -use crate::backend::InputDeviceId; +use crate::backend::{InputDeviceCapability, InputDeviceId}; use crate::ifs::wl_seat::{SeatId, WlSeatGlobal}; use crate::state::{DeviceHandlerData, State}; use crate::tree::walker::NodeVisitorBase; @@ -16,12 +16,13 @@ use jay_config::_private::ipc::{ClientMessage, Response, ServerMessage}; use jay_config::keyboard::keymap::Keymap; use jay_config::keyboard::mods::Modifiers; use jay_config::keyboard::syms::KeySym; -use jay_config::{Axis, Direction, InputDevice, LogLevel, Seat}; +use jay_config::{Axis, Direction, LogLevel, Seat}; use libloading::Library; 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>, @@ -47,6 +48,12 @@ impl ConfigProxyHandler { self.bufs.push(buf); } + pub fn respond(&self, msg: Response) { + self.send(&ServerMessage::Response { + response: msg, + }) + } + fn id(&self) -> u64 { self.next_id.fetch_add(1) } @@ -83,10 +90,8 @@ impl ConfigProxyHandler { let global_name = self.state.globals.name(); let seat = WlSeatGlobal::new(global_name, name, &self.state); self.state.globals.add_global(&self.state, &seat); - self.send(&ServerMessage::Response { - response: Response::CreateSeat { - seat: Seat(seat.id().raw() as _), - }, + self.respond(Response::CreateSeat { + seat: Seat(seat.id().raw() as _), }); } @@ -99,9 +104,7 @@ impl ConfigProxyHandler { } _ => (Keymap::INVALID, Err(ParseKeymapError::ParsingFailed)), }; - self.send(&ServerMessage::Response { - response: Response::ParseKeymap { keymap }, - }); + self.respond(Response::ParseKeymap { keymap }); res } @@ -131,9 +134,7 @@ impl ConfigProxyHandler { fn handle_get_repeat_rate(&self, seat: Seat) -> Result<(), SeatGetRepeatRateError> { let seat = self.get_seat(seat)?; let (rate, delay) = seat.get_rate(); - self.send(&ServerMessage::Response { - response: Response::GetRepeatRate { rate, delay }, - }); + self.respond(Response::GetRepeatRate { rate, delay }); Ok(()) } @@ -184,7 +185,7 @@ impl ConfigProxyHandler { let kbs = self.state.input_device_handlers.borrow_mut(); match kbs.get(&(InputDeviceId::from_raw(kb.0 as _))) { None => Err(CphError::KeyboardDoesNotExist(kb)), - Some(kb) => Ok(kb.device.clone()), + Some(kb) => Ok(kb.data.device.clone()), } } @@ -206,12 +207,31 @@ impl ConfigProxyHandler { Ok(()) } + fn handle_has_capability(&self, device: InputDevice, cap: Capability) -> Result<(), HasCapabilityError> { + let dev = self.get_device_handler_data(device)?; + let has_cap = 'has_cap: { + let cap = match cap { + CAP_KEYBOARD => InputDeviceCapability::Keyboard, + CAP_POINTER => InputDeviceCapability::Pointer, + CAP_TOUCH => InputDeviceCapability::Touch, + CAP_TABLET_TOOL => InputDeviceCapability::TabletTool, + CAP_TABLET_PAD => InputDeviceCapability::TabletPad, + CAP_GESTURE => InputDeviceCapability::Gesture, + CAP_SWITCH => InputDeviceCapability::Switch, + _ => break 'has_cap false, + }; + dev.device.has_capability(cap) + }; + self.respond(Response::HasCapability { + has: has_cap, + }); + Ok(()) + } + fn handle_get_mono(&self, seat: Seat) -> Result<(), GetMonoError> { let seat = self.get_seat(seat)?; - self.send(&ServerMessage::Response { - response: Response::GetMono { - mono: seat.get_mono().unwrap_or(false), - }, + self.respond(Response::GetMono { + mono: seat.get_mono().unwrap_or(false), }); Ok(()) } @@ -224,13 +244,11 @@ impl ConfigProxyHandler { fn handle_get_split(&self, seat: Seat) -> Result<(), GetSplitError> { let seat = self.get_seat(seat)?; - self.send(&ServerMessage::Response { - response: Response::GetSplit { - axis: seat - .get_split() - .unwrap_or(ContainerSplit::Horizontal) - .into(), - }, + self.respond(Response::GetSplit { + axis: seat + .get_split() + .unwrap_or(ContainerSplit::Horizontal) + .into(), }); Ok(()) } @@ -284,9 +302,7 @@ impl ConfigProxyHandler { } } } - self.send(&ServerMessage::Response { - response: Response::GetInputDevices { devices: res }, - }); + self.respond(Response::GetInputDevices { devices: res }); } fn handle_get_seats(&self) { @@ -297,9 +313,7 @@ impl ConfigProxyHandler { .map(|seat| Seat::from_raw(seat.id().raw() as _)) .collect() }; - self.send(&ServerMessage::Response { - response: Response::GetSeats { seats }, - }); + self.respond(Response::GetSeats { seats }); } fn handle_run( @@ -323,18 +337,14 @@ impl ConfigProxyHandler { } fn handle_get_title_height(&self) { - self.send(&ServerMessage::Response { - response: Response::GetTitleHeight { - height: self.state.theme.title_height.get(), - }, + self.respond(Response::GetTitleHeight { + height: self.state.theme.title_height.get(), }); } fn handle_get_border_width(&self) { - self.send(&ServerMessage::Response { - response: Response::GetBorderWidth { - width: self.state.theme.border_width.get(), - }, + self.respond(Response::GetBorderWidth { + width: self.state.theme.border_width.get(), }); } @@ -500,6 +510,7 @@ 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)?, } Ok(()) } @@ -547,6 +558,8 @@ enum CphError { SetTitleHeightError(#[from] SetTitleHeightError), #[error("Could not process a `set_border_width` request")] SetBorderWidthError(#[from] SetBorderWidthError), + #[error("Could not process a `has_capability` request")] + HasCapabilityError(#[from] HasCapabilityError), #[error("Device {0:?} does not exist")] DeviceDoesNotExist(InputDevice), #[error("Device {0:?} does not exist")] @@ -572,6 +585,13 @@ enum SetSeatError { } efrom!(SetSeatError, CphError); +#[derive(Debug, Error)] +enum HasCapabilityError { + #[error(transparent)] + CphError(#[from] Box), +} +efrom!(HasCapabilityError, CphError); + #[derive(Debug, Error)] enum AddShortcutError { #[error(transparent)] diff --git a/src/libinput/device.rs b/src/libinput/device.rs index 9113251f..1e6ee8ee 100644 --- a/src/libinput/device.rs +++ b/src/libinput/device.rs @@ -1,10 +1,8 @@ -use crate::libinput::sys::{ - libinput_device, libinput_device_get_user_data, libinput_device_set_user_data, - libinput_device_unref, libinput_path_remove_device, -}; +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::LibInput; use std::marker::PhantomData; use std::rc::Rc; +use crate::libinput::consts::{DeviceCapability}; pub struct LibInputDevice<'a> { pub(super) dev: *mut libinput_device, @@ -39,6 +37,11 @@ impl<'a> LibInputDevice<'a> { Some(res - 1) } } + + pub fn has_cap(&self, cap: DeviceCapability) -> bool { + let res = unsafe { libinput_device_has_capability(self.dev, cap.raw() as _) }; + res != 0 + } } impl RegisteredDevice { diff --git a/src/libinput/sys.rs b/src/libinput/sys.rs index 1f98e4ad..bd33d409 100644 --- a/src/libinput/sys.rs +++ b/src/libinput/sys.rs @@ -24,6 +24,11 @@ extern "C" { interface: *const libinput_interface, user_data: *mut c::c_void, ) -> *mut libinput; + pub fn libinput_unref(libinput: *mut libinput) -> *mut libinput; + pub fn libinput_get_fd(libinput: *mut libinput) -> c::c_int; + pub fn libinput_dispatch(libinput: *mut libinput) -> c::c_int; + pub fn libinput_get_event(libinput: *mut libinput) -> *mut libinput_event; + pub fn libinput_device_set_user_data(device: *mut libinput_device, user_data: *mut c::c_void); pub fn libinput_device_get_user_data(device: *mut libinput_device) -> *mut c::c_void; pub fn libinput_device_ref(device: *mut libinput_device) -> *mut libinput_device; @@ -33,12 +38,7 @@ extern "C" { path: *const c::c_char, ) -> *mut libinput_device; pub fn libinput_path_remove_device(device: *mut libinput_device); - pub fn libinput_unref(libinput: *mut libinput) -> *mut libinput; - pub fn libinput_get_fd(libinput: *mut libinput) -> c::c_int; - - pub fn libinput_dispatch(libinput: *mut libinput) -> c::c_int; - - pub fn libinput_get_event(libinput: *mut libinput) -> *mut libinput_event; + pub fn libinput_device_has_capability(device: *mut libinput_device, cap: libinput_device_capability) -> 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; diff --git a/src/state.rs b/src/state.rs index 86e464d6..d31f464e 100644 --- a/src/state.rs +++ b/src/state.rs @@ -73,12 +73,12 @@ pub struct State { pub struct InputDeviceData { pub handler: SpawnedFuture<()>, pub id: InputDeviceId, - pub device: Rc, pub data: Rc, } pub struct DeviceHandlerData { pub seat: CloneCell>>, + pub device: Rc, } impl State { diff --git a/src/tasks/input_device.rs b/src/tasks/input_device.rs index 81753c29..1bbf767c 100644 --- a/src/tasks/input_device.rs +++ b/src/tasks/input_device.rs @@ -6,6 +6,7 @@ use std::rc::Rc; pub fn handle(state: &Rc, dev: Rc) { let data = Rc::new(DeviceHandlerData { seat: Default::default(), + device: dev.clone(), }); let oh = DeviceHandler { state: state.clone(), @@ -18,7 +19,6 @@ pub fn handle(state: &Rc, dev: Rc) { InputDeviceData { handler, id: dev.id(), - device: dev.clone(), data, }, );