diff --git a/Cargo.lock b/Cargo.lock index 6345518..8059e47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2653,7 +2653,7 @@ checksum = "2f2b15926089e5526bb2dd738a2eb0e59034356e06eb71e1cd912358c0e62c4d" [[package]] name = "stardust-xr" version = "0.45.0" -source = "git+https://github.com/StardustXR/core.git?branch=dev#41f9e416cc54e7a8b4b815a43384e57478ac502c" +source = "git+https://github.com/StardustXR/core.git?branch=dev#6ea2a27df24e5fcf31fe2f7726989f0a1aecbd6c" dependencies = [ "cluFlock", "color-eyre", @@ -2674,7 +2674,7 @@ dependencies = [ [[package]] name = "stardust-xr-schemas" version = "1.5.3" -source = "git+https://github.com/StardustXR/core.git?branch=dev#41f9e416cc54e7a8b4b815a43384e57478ac502c" +source = "git+https://github.com/StardustXR/core.git?branch=dev#6ea2a27df24e5fcf31fe2f7726989f0a1aecbd6c" dependencies = [ "flatbuffers", "flexbuffers", diff --git a/codegen/src/lib.rs b/codegen/src/lib.rs index 4af4df8..757780c 100644 --- a/codegen/src/lib.rs +++ b/codegen/src/lib.rs @@ -25,10 +25,6 @@ pub fn codegen_field_protocol(_input: proc_macro::TokenStream) -> proc_macro::To codegen_protocol(FIELD_PROTOCOL) } #[proc_macro] -pub fn codegen_data_protocol(_input: proc_macro::TokenStream) -> proc_macro::TokenStream { - codegen_protocol(DATA_PROTOCOL) -} -#[proc_macro] pub fn codegen_audio_protocol(_input: proc_macro::TokenStream) -> proc_macro::TokenStream { codegen_protocol(AUDIO_PROTOCOL) } @@ -578,6 +574,7 @@ fn argument_type_option_name(argument_type: &ArgumentType) -> String { ArgumentType::Union(u) => u.clone(), ArgumentType::Struct(s) => s.clone(), ArgumentType::Node { _type, .. } => _type.clone(), + ArgumentType::Fd => "File Descriptor".to_string(), } } fn generate_argument_type( @@ -674,6 +671,9 @@ fn generate_argument_type( quote!(std::sync::Arc) } } + ArgumentType::Fd => { + quote!(&std::os::fd::OwnedFd) + } }; if optional { diff --git a/src/core/client.rs b/src/core/client.rs index 82897d0..f5956bb 100644 --- a/src/core/client.rs +++ b/src/core/client.rs @@ -6,7 +6,7 @@ use super::{ use crate::{ core::{registry::OwnedRegistry, task}, nodes::{ - audio, data, drawable, fields, input, items, + audio, drawable, fields, input, items, root::{ClientState, Root}, spatial, Node, }, @@ -112,7 +112,6 @@ impl Client { fields::create_interface(&client)?; drawable::create_interface(&client)?; audio::create_interface(&client)?; - data::create_interface(&client)?; input::create_interface(&client)?; items::camera::create_interface(&client)?; items::panel::create_interface(&client)?; diff --git a/src/nodes/data.rs b/src/nodes/data.rs deleted file mode 100644 index 2b50ac1..0000000 --- a/src/nodes/data.rs +++ /dev/null @@ -1,271 +0,0 @@ -use super::alias::AliasList; -use super::fields::Field; -use super::spatial::{parse_transform, Spatial}; -use super::{Alias, Aspect, Node}; -use crate::core::client::Client; -use crate::core::registry::Registry; -use crate::nodes::fields::FIELD_ALIAS_INFO; -use crate::nodes::spatial::Transform; -use crate::nodes::spatial::SPATIAL_ASPECT_ALIAS_INFO; -use color_eyre::eyre::{bail, ensure, eyre, Result}; -use lazy_static::lazy_static; -use parking_lot::Mutex; -use slotmap::{DefaultKey, Key, KeyData, SlotMap}; -use stardust_xr::schemas::flex::flexbuffers; -use stardust_xr::values::Datamap; -use std::sync::{Arc, Weak}; - -lazy_static! { - pub static ref KEYMAPS: Mutex> = Mutex::new(SlotMap::default()); -} - -// TODO: probably just use d-bus for this stuff (custom protocol for exporting spatials as refs) because the mask stuff is just too confusing - -static PULSE_SENDER_REGISTRY: Registry = Registry::new(); -pub static PULSE_RECEIVER_REGISTRY: Registry = Registry::new(); - -pub fn get_mask(datamap: &Datamap) -> Result> { - flexbuffers::Reader::get_root(datamap.raw().as_slice()) - .map_err(|_| eyre!("Mask is not a valid flexbuffer"))? - .get_map() - .map_err(|_| eyre!("Mask is not a valid map")) -} -pub fn mask_matches(mask_map_lesser: &Datamap, mask_map_greater: &Datamap) -> bool { - (|| -> Result<_> { - for key in get_mask(mask_map_lesser)?.iter_keys() { - let lesser_key = get_mask(mask_map_lesser)?.index(key)?; - let greater_key = get_mask(mask_map_greater)?.index(key)?; - // otherwise zero-length vectors don't count the same as a single type vector - if lesser_key.flexbuffer_type().is_heterogenous_vector() - && lesser_key.as_vector().is_empty() - && greater_key.flexbuffer_type().is_vector() - { - continue; - } - if !lesser_key.flexbuffer_type().is_null() - && lesser_key.flexbuffer_type() != greater_key.flexbuffer_type() - { - return Err(flexbuffers::ReaderError::InvalidPackedType {}.into()); - } - } - Ok(()) - })() - .is_ok() -} - -stardust_xr_server_codegen::codegen_data_protocol!(); - -pub struct PulseSender { - node: Weak, - pub mask: Datamap, - aliases: AliasList, - field_aliases: AliasList, -} -impl PulseSender { - pub fn add_to(node: &Arc, mask: Datamap) -> Result> { - let sender = PulseSender { - node: Arc::downgrade(node), - mask, - aliases: AliasList::default(), - field_aliases: AliasList::default(), - }; - - let sender = PULSE_SENDER_REGISTRY.add(sender); - node.add_aspect_raw(sender.clone()); - for receiver in PULSE_RECEIVER_REGISTRY.get_valid_contents() { - sender.handle_new_receiver(&receiver); - } - Ok(sender.clone()) - } - fn handle_new_receiver(&self, receiver: &PulseReceiver) { - if !mask_matches(&self.mask, &receiver.mask) { - return; - } - let Some(tx_node) = self.node.upgrade() else { - return; - }; - let Some(tx_client) = tx_node.get_client() else { - return; - }; - let Some(rx_node) = receiver.node.upgrade() else { - return; - }; - // Receiver itself - let Ok(rx_alias) = Alias::create( - &rx_node, - &tx_client, - PULSE_RECEIVER_ASPECT_ALIAS_INFO.clone(), - Some(&self.aliases), - ) else { - return; - }; - - // Receiver's field - let Ok(rx_field_alias) = Alias::create( - &rx_node - .get_aspect::() - .unwrap() - .field - .spatial - .node() - .unwrap(), - &tx_client, - FIELD_ALIAS_INFO.clone(), - Some(&self.aliases), - ) else { - return; - }; - - let _ = pulse_sender_client::new_receiver(&tx_node, &rx_alias, &rx_field_alias); - } - - fn handle_drop_receiver(&self, receiver: &PulseReceiver) { - let Some(node) = receiver.node.upgrade() else { - return; - }; - self.aliases.remove_aspect(receiver); - self.field_aliases.remove_aspect(receiver.field.as_ref()); - let Some(tx_node) = self.node.upgrade() else { - return; - }; - let _ = pulse_sender_client::drop_receiver(&tx_node, node.get_id()); - } -} -impl Aspect for PulseSender { - impl_aspect_for_pulse_sender_aspect! {} -} -impl PulseSenderAspect for PulseSender {} -impl Drop for PulseSender { - fn drop(&mut self) { - PULSE_SENDER_REGISTRY.remove(self); - } -} - -pub struct PulseReceiver { - pub node: Weak, - pub field: Arc, - pub mask: Datamap, -} -impl PulseReceiver { - pub fn add_to( - node: &Arc, - field: Arc, - mask: Datamap, - ) -> Result> { - let receiver = PulseReceiver { - node: Arc::downgrade(node), - field, - mask, - }; - let receiver = PULSE_RECEIVER_REGISTRY.add(receiver); - - node.add_aspect_raw(receiver.clone()); - for sender in PULSE_SENDER_REGISTRY.get_valid_contents() { - sender.handle_new_receiver(&receiver); - } - Ok(receiver) - } -} -impl Aspect for PulseReceiver { - impl_aspect_for_pulse_receiver_aspect! {} -} -impl PulseReceiverAspect for PulseReceiver { - fn send_data( - node: Arc, - _calling_client: Arc, - sender: Arc, - data: Datamap, - ) -> Result<()> { - let this_receiver = node.get_aspect::().unwrap(); - - ensure!( - mask_matches(&this_receiver.mask, &data), - "Message ({data:?}) does not contain the same keys as the receiver's mask ({:?})", - this_receiver.mask - ); - pulse_receiver_client::data(&node, &sender, &data)?; - Ok(()) - } -} -impl Drop for PulseReceiver { - fn drop(&mut self) { - PULSE_RECEIVER_REGISTRY.remove(self); - for sender in PULSE_SENDER_REGISTRY.get_valid_contents() { - sender.handle_drop_receiver(self); - } - } -} - -impl InterfaceAspect for Interface { - fn create_pulse_sender( - _node: Arc, - calling_client: Arc, - id: u64, - parent: Arc, - transform: Transform, - mask: Datamap, - ) -> Result<()> { - get_mask(&mask)?; - let node = Node::from_id(&calling_client, id, true); - let parent = parent.get_aspect::()?; - let transform = transform.to_mat4(true, true, false); - - let node = node.add_to_scenegraph()?; - Spatial::add_to(&node, Some(parent.clone()), transform, false); - PulseSender::add_to(&node, mask)?; - Ok(()) - } - - fn create_pulse_receiver( - _node: Arc, - calling_client: Arc, - id: u64, - parent: Arc, - transform: Transform, - field: Arc, - mask: Datamap, - ) -> Result<()> { - get_mask(&mask)?; - let node = Node::from_id(&calling_client, id, true); - let parent = parent.get_aspect::()?; - let transform = parse_transform(transform, true, true, false); - let field = field.get_aspect::()?; - - let node = node.add_to_scenegraph()?; - Spatial::add_to(&node, Some(parent.clone()), transform, false); - PulseReceiver::add_to(&node, field, mask)?; - Ok(()) - } - - async fn register_keymap( - _node: Arc, - _calling_client: Arc, - keymap: String, - ) -> Result { - let mut keymaps = KEYMAPS.lock(); - if let Some(found_keymap_id) = keymaps - .iter() - .filter(|(_k, v)| *v == &keymap) - .map(|(k, _v)| k) - .last() - { - return Ok(found_keymap_id.data().as_ffi()); - } - - let key = keymaps.insert(keymap); - Ok(key.data().as_ffi()) - } - - async fn get_keymap( - _node: Arc, - _calling_client: Arc, - keymap_id: u64, - ) -> Result { - let keymaps = KEYMAPS.lock(); - let Some(keymap) = keymaps.get(KeyData::from_ffi(keymap_id).into()) else { - bail!("Could not find keymap. Try registering it") - }; - - Ok(keymap.clone()) - } -} diff --git a/src/nodes/items/panel.rs b/src/nodes/items/panel.rs index 50b0205..f238b7a 100644 --- a/src/nodes/items/panel.rs +++ b/src/nodes/items/panel.rs @@ -15,10 +15,12 @@ use crate::{ Node, }, }; -use color_eyre::eyre::Result; +use color_eyre::eyre::{bail, Result}; use glam::Mat4; use lazy_static::lazy_static; use mint::Vector2; +use parking_lot::Mutex; +use slotmap::{DefaultKey, Key, KeyData, SlotMap}; use std::sync::{Arc, Weak}; use tracing::{debug, info}; @@ -33,6 +35,7 @@ impl Default for Geometry { } lazy_static! { + pub static ref KEYMAPS: Mutex> = Mutex::new(SlotMap::default()); pub static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo { type_name: "panel", alias_info: PANEL_ITEM_ASPECT_ALIAS_INFO.clone(), @@ -72,7 +75,7 @@ pub trait Backend: Send + Sync + 'static { scroll_steps: Option>, ); - fn keyboard_keys(&self, surface: &SurfaceId, keymap_id: u64, keys: Vec); + fn keyboard_key(&self, surface: &SurfaceId, keymap_id: u64, key: u32, pressed: bool); fn touch_down(&self, surface: &SurfaceId, id: u32, position: Vector2); fn touch_move(&self, id: u32, position: Vector2); @@ -349,19 +352,20 @@ impl PanelItemAspect for PanelItem { } #[doc = "Send a series of key presses and releases (positive keycode for pressed, negative for released)."] - fn keyboard_keys( + fn keyboard_key( node: Arc, _calling_client: Arc, surface: SurfaceId, keymap_id: u64, - keys: Vec, + key: u32, + pressed: bool, ) -> Result<()> { let Some(panel_item) = panel_item_from_node(&node) else { return Ok(()); }; panel_item .backend() - .keyboard_keys(&surface, keymap_id, keys); + .keyboard_key(&surface, keymap_id, key, pressed); Ok(()) } @@ -479,4 +483,36 @@ impl InterfaceAspect for Interface { field, ) } + + async fn register_keymap( + _node: Arc, + _calling_client: Arc, + keymap: String, + ) -> Result { + let mut keymaps = KEYMAPS.lock(); + if let Some(found_keymap_id) = keymaps + .iter() + .filter(|(_k, v)| *v == &keymap) + .map(|(k, _v)| k) + .last() + { + return Ok(found_keymap_id.data().as_ffi()); + } + + let key = keymaps.insert(keymap); + Ok(key.data().as_ffi()) + } + + async fn get_keymap( + _node: Arc, + _calling_client: Arc, + keymap_id: u64, + ) -> Result { + let keymaps = KEYMAPS.lock(); + let Some(keymap) = keymaps.get(KeyData::from_ffi(keymap_id).into()) else { + bail!("Could not find keymap. Try registering it") + }; + + Ok(keymap.clone()) + } } diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index 44824de..482f580 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -1,6 +1,5 @@ pub mod alias; pub mod audio; -pub mod data; pub mod drawable; pub mod fields; pub mod input; diff --git a/src/objects/input/mouse_pointer.rs b/src/objects/input/mouse_pointer.rs index d0ce96e..ba0ad5a 100644 --- a/src/objects/input/mouse_pointer.rs +++ b/src/objects/input/mouse_pointer.rs @@ -2,9 +2,9 @@ use super::{get_sorted_handlers, CaptureManager, DistanceCalculator}; use crate::{ core::client::INTERNAL_CLIENT, nodes::{ - data::KEYMAPS, fields::{Field, FieldTrait, Ray, EXPORTED_FIELDS}, input::{InputDataType, InputMethod, Pointer}, + items::panel::KEYMAPS, spatial::Spatial, Node, OwnedNode, }, @@ -186,7 +186,6 @@ impl MousePointer { } while let Some(Ok(Some((handler, field_ref_id)))) = join_set.join_next().await { 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; diff --git a/src/wayland/seat.rs b/src/wayland/seat.rs index ddc5baf..43aff00 100644 --- a/src/wayland/seat.rs +++ b/src/wayland/seat.rs @@ -1,10 +1,7 @@ use super::{state::WaylandState, surface::CoreSurface, utils::WlSurfaceExt}; use crate::{ core::task, - nodes::{ - data::KEYMAPS, - items::panel::{Backend, Geometry, PanelItem}, - }, + nodes::items::panel::{Backend, Geometry, PanelItem, KEYMAPS}, }; use mint::Vector2; use parking_lot::Mutex; @@ -203,7 +200,7 @@ impl SeatWrapper { pointer.frame(&mut state); } - pub fn keyboard_keys(&self, surface: WlSurface, keymap_id: u64, keys: Vec) { + pub fn keyboard_key(&self, surface: WlSurface, keymap_id: u64, key: u32, pressed: bool) { let Some(state) = self.wayland_state.upgrade() else { return; }; @@ -226,20 +223,18 @@ impl SeatWrapper { { return; } - for key in keys { - keyboard.input( - &mut state.lock(), - key.unsigned_abs(), - if key > 0 { - KeyState::Pressed - } else { - KeyState::Released - }, - SERIAL_COUNTER.next_serial(), - 0, - |_, _, _| FilterResult::Forward::<()>, - ); - } + keyboard.input( + &mut state.lock(), + key, + if pressed { + KeyState::Pressed + } else { + KeyState::Released + }, + SERIAL_COUNTER.next_serial(), + 0, + |_, _, _| FilterResult::Forward::<()>, + ); } pub fn touch_down(&self, surface: WlSurface, id: u32, position: Vector2) { diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs index 8d2b83b..e5d8e57 100644 --- a/src/wayland/xdg_shell.rs +++ b/src/wayland/xdg_shell.rs @@ -515,11 +515,11 @@ impl Backend for XdgBackend { self.seat.pointer_scroll(scroll_distance, scroll_steps) } - fn keyboard_keys(&self, surface: &SurfaceId, keymap_id: u64, keys: Vec) { + fn keyboard_key(&self, surface: &SurfaceId, keymap_id: u64, key: u32, pressed: bool) { let Some(surface) = self.wl_surface_from_id(surface) else { return; }; - self.seat.keyboard_keys(surface, keymap_id, keys) + self.seat.keyboard_key(surface, keymap_id, key, pressed) } fn touch_down(&self, surface: &SurfaceId, id: u32, position: Vector2) {