Set keyboard LEDs (capslock, numlock, scrollock)

It doesn't seem there's currently a way to iterate over input devices,
so this adds a `Vec` of libinput keyboard devices. When run with the
kms backend.

Not the most elegant solution, but it doesn't seem practical to add a
type generic to `Devices` given how backends are handled, and `Device`
can't be made into a trait object. Another trait could be added, but
this is fine, and technically should perform better (but if it actually
had to iterate over many keyboards, something has gone very wrong).
This commit is contained in:
Ian Douglas Scott 2024-03-05 21:31:33 -08:00 committed by Victoria Brekenfeld
parent a8846ed2b8
commit a204197e6d
2 changed files with 37 additions and 7 deletions

View file

@ -33,7 +33,7 @@ use smithay::{
},
desktop::{layer_map_for_output, space::SpaceElement, WindowSurfaceType},
input::{
keyboard::{FilterResult, KeysymHandle, XkbConfig},
keyboard::{FilterResult, KeysymHandle, LedState, XkbConfig},
pointer::{
AxisFrame, ButtonEvent, CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent,
GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent,
@ -76,7 +76,11 @@ pub struct SupressedKeys(RefCell<Vec<(Keycode, Option<RegistrationToken>)>>);
#[derive(Default, Debug)]
pub struct ModifiersShortcutQueue(RefCell<Option<KeyPattern>>);
#[derive(Default)]
pub struct Devices(RefCell<HashMap<String, Vec<DeviceCapability>>>);
pub struct Devices {
capabilities: RefCell<HashMap<String, Vec<DeviceCapability>>>,
// Used for updating keyboard leds on kms backend
keyboards: RefCell<Vec<InputDevice>>,
}
impl Default for SeatId {
fn default() -> SeatId {
@ -138,9 +142,9 @@ impl ModifiersShortcutQueue {
}
impl Devices {
fn add_device<D: Device>(&self, device: &D) -> Vec<DeviceCapability> {
fn add_device<D: Device + 'static>(&self, device: &D) -> Vec<DeviceCapability> {
let id = device.id();
let mut map = self.0.borrow_mut();
let mut map = self.capabilities.borrow_mut();
let caps = [
DeviceCapability::Keyboard,
DeviceCapability::Pointer,
@ -156,22 +160,41 @@ impl Devices {
.filter(|c| map.values().flatten().all(|has| *c != *has))
.collect::<Vec<_>>();
map.insert(id, caps);
if device.has_capability(DeviceCapability::Keyboard) {
if let Some(device) = <dyn Any>::downcast_ref::<InputDevice>(device) {
self.keyboards.borrow_mut().push(device.clone());
}
}
new_caps
}
pub fn has_device<D: Device>(&self, device: &D) -> bool {
self.0.borrow().contains_key(&device.id())
self.capabilities.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();
let mut keyboards = self.keyboards.borrow_mut();
if let Some(idx) = keyboards.iter().position(|x| x.id() == id) {
keyboards.remove(idx);
}
let mut map = self.capabilities.borrow_mut();
map.remove(&id)
.unwrap_or(Vec::new())
.into_iter()
.filter(|c| map.values().flatten().all(|has| *c != *has))
.collect()
}
pub fn update_led_state(&self, led_state: LedState) {
for keyboard in self.keyboards.borrow_mut().iter_mut() {
keyboard.led_update(led_state.into());
}
}
}
pub fn add_seat(

View file

@ -1,12 +1,13 @@
// SPDX-License-Identifier: GPL-3.0-only
use crate::{
input::Devices,
shell::focus::target::{KeyboardFocusTarget, PointerFocusTarget},
state::State,
};
use smithay::{
delegate_seat,
input::{pointer::CursorImageStatus, SeatHandler, SeatState},
input::{keyboard::LedState, pointer::CursorImageStatus, SeatHandler, SeatState},
reexports::wayland_server::Resource,
wayland::{
seat::WaylandFocus, selection::data_device::set_data_device_focus,
@ -49,6 +50,12 @@ impl SeatHandler for State {
set_primary_focus(dh, seat, Some(client))
}
}
fn led_state_changed(&mut self, seat: &smithay::input::Seat<Self>, led_state: LedState) {
let userdata = seat.user_data();
let devices = userdata.get::<Devices>().unwrap();
devices.update_led_state(led_state);
}
}
delegate_seat!(State);