Add keymap support to HID providers and refactor related functionality

This commit is contained in:
SparkyTD 2026-06-08 13:25:18 +02:00
parent 0625570285
commit 595e3eb43a
5 changed files with 79 additions and 48 deletions

View File

@ -1,5 +1,5 @@
use glam::Vec2;
use crate::subsystem::hid::{VirtualKey, WheelDelta};
use crate::subsystem::hid::{VirtualKey, WheelDelta, XkbKeymap};
use crate::subsystem::hid::provider::HidProvider;
pub struct DummyProvider;
@ -8,9 +8,12 @@ impl HidProvider for DummyProvider {
fn mouse_move(&mut self, _pos: Vec2) {}
fn send_button(&mut self, _button: u16, _down: bool) {}
fn wheel(&mut self, _delta: WheelDelta) {}
fn set_modifiers(&mut self, _modifiers: u8) {}
fn send_key(&self, _key: VirtualKey, _down: bool) {}
fn set_desktop_extent(&mut self, _extent: Vec2) {}
fn set_desktop_origin(&mut self, _origin: Vec2) {}
fn set_modifiers(&mut self, _modifiers: u8) {}
fn send_key(&self, _key: VirtualKey, _down: bool) {}
fn set_keymap(&mut self, _keymap: &XkbKeymap) {}
fn commit(&mut self) {}
}

View File

@ -1,17 +1,23 @@
use glam::Vec2;
use crate::subsystem::hid::{VirtualKey, WheelDelta};
use crate::subsystem::hid::{VirtualKey, WheelDelta, XkbKeymap};
pub mod uinput;
pub mod wl_virtual;
pub mod dummy;
pub trait HidProvider: Sync + Send {
// Pointer Functions
fn mouse_move(&mut self, pos: Vec2);
fn send_button(&mut self, button: u16, down: bool);
fn wheel(&mut self, delta: WheelDelta);
fn set_modifiers(&mut self, mods: u8);
fn send_key(&self, key: VirtualKey, down: bool);
fn set_desktop_extent(&mut self, extent: Vec2);
fn set_desktop_origin(&mut self, origin: Vec2);
// Keyboard Functions
fn set_modifiers(&mut self, mods: u8);
fn send_key(&self, key: VirtualKey, down: bool);
fn set_keymap(&mut self, keymap: &XkbKeymap);
// Common Functions
fn commit(&mut self);
}

View File

@ -6,7 +6,7 @@ use strum::IntoEnumIterator;
use input_linux::{AbsoluteAxis, AbsoluteInfo, AbsoluteInfoSetup, EventKind, InputId, Key, RelativeAxis, UInputHandle};
use wlx_common::overlays::ToastTopic;
use crate::overlays::toast::Toast;
use crate::subsystem::hid::{get_time, new_event, MouseAction, MouseButtonAction, VirtualKey, WheelDelta, EV_ABS, EV_KEY, EV_REL, EV_SYN, MODS_TO_KEYS, MOUSE_EXTENT, MOUSE_LEFT, MOUSE_MIDDLE};
use crate::subsystem::hid::{get_time, new_event, MouseAction, MouseButtonAction, VirtualKey, WheelDelta, XkbKeymap, EV_ABS, EV_KEY, EV_REL, EV_SYN, MODS_TO_KEYS, MOUSE_EXTENT, MOUSE_LEFT, MOUSE_MIDDLE};
use crate::subsystem::hid::provider::HidProvider;
pub struct UInputProvider {
@ -171,6 +171,12 @@ impl HidProvider for UInputProvider {
self.current_action.pos = None;
}
}
fn set_desktop_extent(&mut self, extent: Vec2) {
self.desktop_extent = extent;
}
fn set_desktop_origin(&mut self, origin: Vec2) {
self.desktop_origin = origin;
}
fn set_modifiers(&mut self, modifiers: u8) {
let changed = self.cur_modifiers ^ modifiers;
for i in 0..8 {
@ -183,6 +189,7 @@ impl HidProvider for UInputProvider {
}
self.cur_modifiers = modifiers;
}
fn send_key(&self, key: VirtualKey, down: bool) {
#[cfg(debug_assertions)]
log::trace!("send_key: {key:?} {down}");
@ -196,13 +203,8 @@ impl HidProvider for UInputProvider {
log::error!("send_key: {res}");
}
}
fn set_desktop_extent(&mut self, extent: Vec2) {
self.desktop_extent = extent;
}
fn set_desktop_origin(&mut self, origin: Vec2) {
self.desktop_origin = origin;
}
fn set_keymap(&mut self, _keymap: &XkbKeymap) {}
fn commit(&mut self) {
if let Some(pos) = self.current_action.pos.take() {

View File

@ -28,7 +28,7 @@ pub struct WlVirtualProvider {
virtual_pointer: ZwlrVirtualPointerV1,
desktop_extent: Vec2,
desktop_origin: Vec2,
_file: std::fs::File,
keymap_file: Option<std::fs::File>,
virtual_keyboard: ZwpVirtualKeyboardV1,
keyboard_mods_state: u8,
@ -101,6 +101,14 @@ impl HidProvider for WlVirtualProvider {
self.virtual_pointer.frame();
}
fn set_desktop_extent(&mut self, extent: Vec2) {
self.desktop_extent = extent;
}
fn set_desktop_origin(&mut self, origin: Vec2) {
self.desktop_origin = origin;
}
fn set_modifiers(&mut self, mods: u8) {
const LOCKED: u8 = CAPS_LOCK | NUM_LOCK;
@ -109,7 +117,8 @@ impl HidProvider for WlVirtualProvider {
if changed & bit != 0 {
let down = mods & bit != 0;
if let Some(kc) = Self::modifier_keycode(bit) {
self.virtual_keyboard.key(Self::now_ms(), kc - 8, down as u32);
self.virtual_keyboard
.key(Self::now_ms(), kc - 8, down as u32);
}
}
}
@ -138,12 +147,25 @@ impl HidProvider for WlVirtualProvider {
self._connection.flush().unwrap();
}
fn set_desktop_extent(&mut self, extent: Vec2) {
self.desktop_extent = extent;
}
fn set_keymap(&mut self, keymap: &XkbKeymap) {
#[cfg(debug_assertions)]
log::trace!("Keyboard keymap: {:?}", keymap.inner.layouts().next().unwrap_or("Unknown"));
fn set_desktop_origin(&mut self, origin: Vec2) {
self.desktop_origin = origin;
let mut bytes = keymap
.inner
.get_as_string(KEYMAP_FORMAT_TEXT_V1)
.into_bytes();
bytes.push(0);
let fd = memfd_create("virtual-keyboard-keymap", MemfdFlags::CLOEXEC)
.expect("Failed to create memfd");
let mut file = std::fs::File::from(fd);
file.write_all(&bytes).expect("failed to write the keymap");
self.virtual_keyboard
.keymap(KeymapFormat::XkbV1 as u32, file.as_fd(), bytes.len() as u32);
self.queue.roundtrip(&mut self.state).unwrap();
self.keymap_file.replace(file);
}
fn commit(&mut self) {
@ -153,10 +175,10 @@ impl HidProvider for WlVirtualProvider {
impl WlVirtualProvider {
pub fn try_new() -> anyhow::Result<Self> {
let mut state = KbState;
let state = KbState;
let connection = wayland_client::Connection::connect_to_env()?;
let (globals, mut queue) = registry_queue_init::<KbState>(&connection)?;
let (globals, queue) = registry_queue_init::<KbState>(&connection)?;
let qh = queue.handle();
let seat: WlSeat = globals
.bind(&qh, 4..=9, ())
@ -174,31 +196,8 @@ impl WlVirtualProvider {
let virtual_keyboard = keyboard_manager.create_virtual_keyboard(&seat, &qh, ());
let xkb_context = Context::new(CONTEXT_NO_FLAGS);
let xkb_keymap = Keymap::new_from_names(
&xkb_context,
"",
"",
"us",
"",
None,
KEYMAP_COMPILE_NO_FLAGS,
)
.expect("Failed to compile XKB keymap");
let mut bytes = xkb_keymap.get_as_string(KEYMAP_FORMAT_TEXT_V1).into_bytes();
bytes.push(0);
let fd = memfd_create("virtual-keyboard-keymap", MemfdFlags::CLOEXEC)
.expect("Failed to create memfd");
let mut file = std::fs::File::from(fd);
file.write_all(&bytes).expect("failed to write the keymap");
virtual_keyboard.keymap(KeymapFormat::XkbV1 as u32, file.as_fd(), bytes.len() as u32);
queue.roundtrip(&mut state)?;
Ok(Self {
_file: file,
let mut result = Self {
keymap_file: None,
_connection: connection,
queue,
state,
@ -207,7 +206,27 @@ impl WlVirtualProvider {
desktop_extent: Vec2::ZERO,
desktop_origin: Vec2::ZERO,
keyboard_mods_state: 0,
})
};
result.set_keymap(&XkbKeymap {
inner: Self::default_keymap(),
});
Ok(result)
}
fn default_keymap() -> Keymap {
let xkb_context = Context::new(CONTEXT_NO_FLAGS);
Keymap::new_from_names(
&xkb_context,
"",
"",
"us",
"",
None,
KEYMAP_COMPILE_NO_FLAGS,
)
.expect("Failed to compile XKB keymap")
}
fn modifier_keycode(bit: u8) -> Option<u32> {

View File

@ -56,6 +56,7 @@ impl HidWrapper {
.inspect_err(|e| log::error!("Could not set WayVR keymap: {e:?}"));
} else {
self.keymap = Some(keymap.clone());
self.inner.set_keymap(&keymap);
}
log::info!(