diff --git a/wayvr/src/subsystem/hid/provider/dummy.rs b/wayvr/src/subsystem/hid/provider/dummy.rs index 1c521bf2..578f5f6a 100644 --- a/wayvr/src/subsystem/hid/provider/dummy.rs +++ b/wayvr/src/subsystem/hid/provider/dummy.rs @@ -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) {} } \ No newline at end of file diff --git a/wayvr/src/subsystem/hid/provider/mod.rs b/wayvr/src/subsystem/hid/provider/mod.rs index 2a610a6c..ab2581b2 100644 --- a/wayvr/src/subsystem/hid/provider/mod.rs +++ b/wayvr/src/subsystem/hid/provider/mod.rs @@ -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); } \ No newline at end of file diff --git a/wayvr/src/subsystem/hid/provider/uinput.rs b/wayvr/src/subsystem/hid/provider/uinput.rs index 1da78a28..15e9168e 100644 --- a/wayvr/src/subsystem/hid/provider/uinput.rs +++ b/wayvr/src/subsystem/hid/provider/uinput.rs @@ -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() { diff --git a/wayvr/src/subsystem/hid/provider/wl_virtual.rs b/wayvr/src/subsystem/hid/provider/wl_virtual.rs index 6a51b5e0..2cc68070 100644 --- a/wayvr/src/subsystem/hid/provider/wl_virtual.rs +++ b/wayvr/src/subsystem/hid/provider/wl_virtual.rs @@ -28,7 +28,7 @@ pub struct WlVirtualProvider { virtual_pointer: ZwlrVirtualPointerV1, desktop_extent: Vec2, desktop_origin: Vec2, - _file: std::fs::File, + keymap_file: Option, 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 { - let mut state = KbState; + let state = KbState; let connection = wayland_client::Connection::connect_to_env()?; - let (globals, mut queue) = registry_queue_init::(&connection)?; + let (globals, queue) = registry_queue_init::(&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 { diff --git a/wayvr/src/subsystem/input.rs b/wayvr/src/subsystem/input.rs index 5195ac21..9c60c179 100644 --- a/wayvr/src/subsystem/input.rs +++ b/wayvr/src/subsystem/input.rs @@ -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!(