refactor: use new xkb input code

This commit is contained in:
Nova
2024-12-09 11:34:49 -05:00
parent d27ec84496
commit 3c66109c45
4 changed files with 138 additions and 81 deletions

10
Cargo.lock generated
View File

@@ -1519,7 +1519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"windows-targets 0.48.5", "windows-targets 0.52.6",
] ]
[[package]] [[package]]
@@ -1880,7 +1880,7 @@ version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56"
dependencies = [ dependencies = [
"proc-macro-crate 1.3.1", "proc-macro-crate 3.2.0",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.87", "syn 2.0.87",
@@ -2653,7 +2653,7 @@ checksum = "2f2b15926089e5526bb2dd738a2eb0e59034356e06eb71e1cd912358c0e62c4d"
[[package]] [[package]]
name = "stardust-xr" name = "stardust-xr"
version = "0.45.0" version = "0.45.0"
source = "git+https://github.com/StardustXR/core.git?branch=dev#b68343a67f93e95ac5bec138c8ee0e082189a489" source = "git+https://github.com/StardustXR/core.git?branch=dev#41f9e416cc54e7a8b4b815a43384e57478ac502c"
dependencies = [ dependencies = [
"cluFlock", "cluFlock",
"color-eyre", "color-eyre",
@@ -2674,7 +2674,7 @@ dependencies = [
[[package]] [[package]]
name = "stardust-xr-schemas" name = "stardust-xr-schemas"
version = "1.5.3" version = "1.5.3"
source = "git+https://github.com/StardustXR/core.git?branch=dev#b68343a67f93e95ac5bec138c8ee0e082189a489" source = "git+https://github.com/StardustXR/core.git?branch=dev#41f9e416cc54e7a8b4b815a43384e57478ac502c"
dependencies = [ dependencies = [
"flatbuffers", "flatbuffers",
"flexbuffers", "flexbuffers",
@@ -3395,7 +3395,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]

View File

@@ -17,6 +17,7 @@ use directories::ProjectDirs;
use objects::ServerObjects; use objects::ServerObjects;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
use session::{launch_start, save_session}; use session::{launch_start, save_session};
use stardust_xr::schemas::dbus::object_registry::ObjectRegistry;
use stardust_xr::server; use stardust_xr::server;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::Arc; use std::sync::Arc;
@@ -139,13 +140,25 @@ async fn main() {
.await .await
.expect("Couldn't add the object manager"); .expect("Couldn't add the object manager");
let object_registry = ObjectRegistry::new(&dbus_connection).await.expect(
"Couldn't make the object registry to find all objects with given interfaces in d-bus",
);
let sk_ready_notifier = Arc::new(Notify::new()); let sk_ready_notifier = Arc::new(Notify::new());
let stereokit_loop = tokio::task::spawn_blocking({ let stereokit_loop = tokio::task::spawn_blocking({
let sk_ready_notifier = sk_ready_notifier.clone(); let sk_ready_notifier = sk_ready_notifier.clone();
let project_dirs = project_dirs.clone(); let project_dirs = project_dirs.clone();
let cli_args = cli_args.clone(); let cli_args = cli_args.clone();
let dbus_connection = dbus_connection.clone(); let dbus_connection = dbus_connection.clone();
move || stereokit_loop(sk_ready_notifier, project_dirs, cli_args, dbus_connection) move || {
stereokit_loop(
sk_ready_notifier,
project_dirs,
cli_args,
dbus_connection,
object_registry,
)
}
}); });
sk_ready_notifier.notified().await; sk_ready_notifier.notified().await;
let mut startup_children = project_dirs let mut startup_children = project_dirs
@@ -173,6 +186,7 @@ fn stereokit_loop(
project_dirs: Option<ProjectDirs>, project_dirs: Option<ProjectDirs>,
args: CliArgs, args: CliArgs,
dbus_connection: Connection, dbus_connection: Connection,
object_registry: ObjectRegistry,
) { ) {
let sk = SkSettings::default() let sk = SkSettings::default()
.app_name("Stardust XR") .app_name("Stardust XR")
@@ -258,7 +272,7 @@ fn stereokit_loop(
wayland.frame_event(); wayland.frame_event();
destroy_queue::clear(); destroy_queue::clear();
objects.update(&sk, token); objects.update(&sk, token, &dbus_connection, &object_registry);
input::process_input(); input::process_input();
nodes::root::Root::send_frame_events(Time::get_step_unscaled()); nodes::root::Root::send_frame_events(Time::get_step_unscaled());
adaptive_sleep( adaptive_sleep(

View File

@@ -1,10 +1,11 @@
use super::{get_sorted_handlers, CaptureManager, DistanceCalculator};
use crate::{ use crate::{
core::client::INTERNAL_CLIENT, core::client::INTERNAL_CLIENT,
nodes::{ nodes::{
data::{ data::{
mask_matches, pulse_receiver_client, PulseSender, KEYMAPS, PULSE_RECEIVER_REGISTRY, mask_matches, pulse_receiver_client, PulseSender, KEYMAPS, PULSE_RECEIVER_REGISTRY,
}, },
fields::{FieldTrait, Ray}, fields::{Field, FieldTrait, Ray, EXPORTED_FIELDS},
input::{InputDataType, InputHandler, InputMethod, Pointer, INPUT_HANDLER_REGISTRY}, input::{InputDataType, InputHandler, InputMethod, Pointer, INPUT_HANDLER_REGISTRY},
spatial::Spatial, spatial::Spatial,
Node, OwnedNode, Node, OwnedNode,
@@ -15,12 +16,16 @@ use glam::{vec3, Mat4, Vec3};
use mint::Vector2; use mint::Vector2;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use slotmap::{DefaultKey, Key as SlotKey}; use slotmap::{DefaultKey, Key as SlotKey};
use stardust_xr::values::Datamap; use stardust_xr::{
schemas::dbus::{interfaces::FieldRefProxy, object_registry::ObjectRegistry},
values::Datamap,
};
use std::sync::Arc; use std::sync::Arc;
use stereokit_rust::system::{Input, Key}; use stereokit_rust::system::{Input, Key};
use tokio::task::JoinSet;
use tokio::time::{timeout, Duration};
use xkbcommon_rs::{xkb_keymap::CompileFlags, Context, Keymap, KeymapFormat}; use xkbcommon_rs::{xkb_keymap::CompileFlags, Context, Keymap, KeymapFormat};
use zbus::{names::OwnedInterfaceName, Connection};
use super::{get_sorted_handlers, CaptureManager, DistanceCalculator};
#[derive(Debug, Deserialize, Serialize)] #[derive(Debug, Deserialize, Serialize)]
struct MouseEvent { struct MouseEvent {
@@ -46,12 +51,14 @@ impl Default for MouseEvent {
} }
} }
#[derive(Debug, Clone, Deserialize, Serialize, Default)] #[zbus::proxy(
pub struct KeyboardEvent { interface = "org.stardustxr.XKBv1",
pub keyboard: (), default_service = "org.stardustxr.XKBv1"
pub xkbv1: (), )]
pub keymap_id: u64, trait KeyboardHandler {
pub keys: Vec<i32>, async fn keymap(&self, keymap_id: u64) -> zbus::Result<()>;
async fn key_state(&self, key: u32, pressed: bool) -> zbus::Result<()>;
async fn reset(&self) -> zbus::Result<()>;
} }
#[allow(unused)] #[allow(unused)]
@@ -62,8 +69,6 @@ pub struct MousePointer {
pointer: Arc<InputMethod>, pointer: Arc<InputMethod>,
capture_manager: CaptureManager, capture_manager: CaptureManager,
mouse_datamap: MouseEvent, mouse_datamap: MouseEvent,
keyboard_datamap: KeyboardEvent,
keyboard_sender: Arc<PulseSender>,
} }
impl MousePointer { impl MousePointer {
pub fn new() -> Result<Self> { pub fn new() -> Result<Self> {
@@ -83,29 +88,16 @@ impl MousePointer {
.unwrap(), .unwrap(),
); );
let keyboard_sender = PulseSender::add_to(
&node.0,
Datamap::from_typed(KeyboardEvent::default()).unwrap(),
)
.unwrap();
Ok(MousePointer { Ok(MousePointer {
node, node,
spatial, spatial,
pointer, pointer,
capture_manager: CaptureManager::default(), capture_manager: CaptureManager::default(),
mouse_datamap: Default::default(), mouse_datamap: Default::default(),
keyboard_datamap: KeyboardEvent {
keyboard: (),
xkbv1: (),
keymap_id: keymap.data().as_ffi(),
keys: vec![],
},
keymap, keymap,
keyboard_sender,
}) })
} }
pub fn update(&mut self) { pub fn update(&mut self, dbus_connection: &Connection, object_registry: &ObjectRegistry) {
let mouse = Input::get_mouse(); let mouse = Input::get_mouse();
let ray = mouse.get_ray(); let ray = mouse.get_ray();
@@ -131,7 +123,7 @@ impl MousePointer {
*self.pointer.datamap.lock() = Datamap::from_typed(&self.mouse_datamap).unwrap(); *self.pointer.datamap.lock() = Datamap::from_typed(&self.mouse_datamap).unwrap();
} }
self.target_pointer_input(); self.target_pointer_input();
self.send_keyboard_input(); self.send_keyboard_input(dbus_connection, object_registry);
} }
fn target_pointer_input(&mut self) { fn target_pointer_input(&mut self) {
let distance_calculator: DistanceCalculator = |space, data, field| { let distance_calculator: DistanceCalculator = |space, data, field| {
@@ -158,56 +150,98 @@ impl MousePointer {
self.pointer.set_handler_order(sorted_handlers.iter()); self.pointer.set_handler_order(sorted_handlers.iter());
} }
fn send_keyboard_input(&mut self) { pub fn send_keyboard_input(
let rx = PULSE_RECEIVER_REGISTRY &mut self,
.get_valid_contents() dbus_connection: &Connection,
.into_iter() object_registry: &ObjectRegistry,
.filter(|rx| mask_matches(&rx.mask, &self.keyboard_sender.mask)) ) {
.map(|rx| { let keyboard_handlers = object_registry.get_objects("org.stardustxr.XKBv1");
let result = rx.field.ray_march(Ray {
origin: vec3(0.0, 0.0, 0.0), // Spawn async task to handle keyboard input
direction: vec3(0.0, 0.0, -1.0), tokio::spawn({
space: self.spatial.clone(), let keyboard_handlers = keyboard_handlers.clone();
}); let spatial = self.spatial.clone();
(rx, result) let keymap_id = self.keymap.data().as_ffi();
}) let dbus_connection = dbus_connection.clone();
.filter(|(_rx, result)| {
result.deepest_point_distance > 0.0 && result.min_distance < 0.05 async move {
}) let mut closest_handler = None;
.reduce(|(rx_a, result_a), (rx_b, result_b)| { let mut closest_distance = f32::MAX;
if result_a.deepest_point_distance < result_b.deepest_point_distance {
(rx_a, result_a) let mut join_set = JoinSet::new();
} else { for handler in &keyboard_handlers {
(rx_b, result_b) let handler = handler.clone();
let dbus_connection = dbus_connection.clone();
join_set.spawn(async move {
timeout(Duration::from_millis(1), async {
let field_ref = handler
.to_typed_proxy::<FieldRefProxy>(&dbus_connection)
.await
.ok()?;
let uid = field_ref.uid().await.ok()?;
Some((handler, uid))
})
.await
.ok()
.flatten()
});
} }
}) while let Some(Ok(Some((handler, field_ref_id)))) = join_set.join_next().await {
.map(|(rx, _)| rx); let exported_fields = EXPORTED_FIELDS.lock();
dbg!(&*exported_fields);
let Some(field_ref_node) = exported_fields.get(&field_ref_id) else {
println!("didn't find a thing :(");
continue;
};
// println!("still sendin stuff :)");
let Ok(field_ref) = field_ref_node.get_aspect::<Field>() else {
continue;
};
drop(exported_fields);
if let Some(rx) = rx { let result = field_ref.ray_march(Ray {
let keys = (8_u32..254) origin: vec3(0.0, 0.0, 0.0),
.map(|i| unsafe { std::mem::transmute(i) }) direction: vec3(0.0, 0.0, -1.0),
.filter_map(|k| Some((map_key(k)?, Input::key(k)))) space: spatial.clone(),
.filter_map(|(i, k)| { });
if k.is_just_active() {
Some(i as i32) if result.deepest_point_distance > 0.0
} else if k.is_just_inactive() { && result.min_distance < 0.05
Some(-(i as i32)) && result.deepest_point_distance < closest_distance
} else { {
None closest_distance = result.deepest_point_distance;
closest_handler = Some(handler);
} }
}) }
.collect();
self.keyboard_datamap.keys = keys; let Some(handler) = closest_handler else {
if !self.keyboard_datamap.keys.is_empty() { return;
pulse_receiver_client::data( };
&rx.node.upgrade().unwrap(), let Ok(keyboard_handler) = handler
&self.node.0, .to_typed_proxy::<KeyboardHandlerProxy>(&dbus_connection)
&Datamap::from_typed(&self.keyboard_datamap).unwrap(), .await
) else {
.unwrap(); return;
};
// Register keymap first
let _ = keyboard_handler.keymap(keymap_id).await;
// Send key states
for i in 8_u32..254 {
let key = unsafe { std::mem::transmute::<u32, stereokit_rust::system::Key>(i) };
let Some(mapped_key) = map_key(key) else {
continue;
};
let input_state = Input::key(key);
if input_state.is_just_active() {
let _ = keyboard_handler.key_state(mapped_key, true).await;
} else if input_state.is_just_inactive() {
let _ = keyboard_handler.key_state(mapped_key, false).await;
}
}
} }
} });
} }
} }

View File

@@ -14,6 +14,7 @@ use input::{
sk_hand::SkHand, sk_hand::SkHand,
}; };
use play_space::PlaySpaceBounds; use play_space::PlaySpaceBounds;
use stardust_xr::schemas::dbus::object_registry::ObjectRegistry;
use std::{marker::PhantomData, sync::Arc}; use std::{marker::PhantomData, sync::Arc};
use stereokit_rust::{ use stereokit_rust::{
material::Material, material::Material,
@@ -116,7 +117,13 @@ impl ServerObjects {
} }
} }
pub fn update(&mut self, sk: &Sk, token: &MainThreadToken) { pub fn update(
&mut self,
sk: &Sk,
token: &MainThreadToken,
dbus_connection: &Connection,
object_registry: &ObjectRegistry,
) {
let hmd_pose = Input::get_head(); let hmd_pose = Input::get_head();
self.hmd self.hmd
.0 .0
@@ -177,7 +184,9 @@ impl ServerObjects {
eye_pointer.update(); eye_pointer.update();
} }
} }
Inputs::MousePointer(mouse_pointer) => mouse_pointer.update(), Inputs::MousePointer(mouse_pointer) => {
mouse_pointer.update(dbus_connection, object_registry)
}
// Inputs::Controllers((left, right)) => { // Inputs::Controllers((left, right)) => {
// left.update(token); // left.update(token);
// right.update(token); // right.update(token);