diff --git a/Cargo.lock b/Cargo.lock index 0a50459..f03af8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -878,15 +878,6 @@ version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" -[[package]] -name = "glam" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12f597d56c1bd55a811a1be189459e8fad2bbc272616375602443bdfb37fa774" -dependencies = [ - "mint", -] - [[package]] name = "glam" version = "0.24.0" @@ -1636,7 +1627,7 @@ dependencies = [ "directories", "dirs", "ez-pixmap", - "glam 0.24.0", + "glam", "image", "lazy_static", "linicon", @@ -2065,9 +2056,7 @@ dependencies = [ [[package]] name = "stardust-xr" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ce36e7f3285a6b1391a298c01bbbb92c9f3d77967a78d1beaac21c0043d23b" +version = "0.11.4" dependencies = [ "chrono", "cluFlock", @@ -2085,9 +2074,7 @@ dependencies = [ [[package]] name = "stardust-xr-fusion" -version = "0.39.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75214564f52e031f3873963b855cbd9a8253502ef18912480e8e84ad98a30c8" +version = "0.40.2" dependencies = [ "color-eyre", "color-rs", @@ -2103,17 +2090,16 @@ dependencies = [ "thiserror", "tokio", "tracing", - "xkbcommon", ] [[package]] name = "stardust-xr-molecules" -version = "0.24.0" +version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "185291b7cf2368a9ef0deed9e5ebf2c49954e862d2747aeee96cc08a57796c1c" +checksum = "724a92e67765300651d165950b70ec4800d4ad6450f473882f6024d5a559ea9d" dependencies = [ "color-rs", - "glam 0.24.0", + "glam", "lazy_static", "map-range", "mint", @@ -2127,16 +2113,16 @@ dependencies = [ [[package]] name = "stardust-xr-schemas" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bebfbddbcba7db7ce8180bb373c9ad5a7d58ff60ee213ca07562820d7e8aab0" +version = "1.5.0" dependencies = [ "flatbuffers", "flexbuffers", - "glam 0.22.0", + "glam", + "manifest-dir-macros", "mint", "ouroboros", "serde", + "serde_repr", "thiserror", ] diff --git a/Cargo.toml b/Cargo.toml index 401041d..dfe4147 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,8 +20,8 @@ nix = "0.26.1" regex = "1.7.1" resvg = "0.29.0" rustc-hash = "1.1.0" -stardust-xr-fusion = "0.39.2" -stardust-xr-molecules = "0.24.0" +stardust-xr-fusion = "0.40.2" +stardust-xr-molecules = "0.24.3" tokio = { version = "1.24.1", features = ["full"] } tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } tween = "2.0.0" @@ -29,4 +29,7 @@ ustr = "0.9.0" walkdir = "2.3.2" [dev-dependencies] -tempdir = "0.3.7" \ No newline at end of file +tempdir = "0.3.7" + +[patch.crates-io.stardust-xr-fusion] +path = "../../core/fusion" \ No newline at end of file diff --git a/assets/hexagon.blend b/assets/hexagon.blend index 17e162a..20cd188 100644 Binary files a/assets/hexagon.blend and b/assets/hexagon.blend differ diff --git a/examples/hexagon_launcher.rs b/examples/hexagon_launcher.rs index 437aa7f..9b230c8 100644 --- a/examples/hexagon_launcher.rs +++ b/examples/hexagon_launcher.rs @@ -3,23 +3,26 @@ use glam::Quat; use manifest_dir_macros::directory_relative_path; use mint::Vector3; use protostar::{ - protostar::ProtoStar, - xdg::{get_desktop_files, parse_desktop_file, DesktopFile}, + application::Application, + xdg::{get_desktop_files, parse_desktop_file, DesktopFile, Icon, IconType}, }; use stardust_xr_fusion::{ client::{Client, FrameInfo, RootHandler}, core::values::Transform, - drawable::{MaterialParameter, Model, ResourceID}, + drawable::{Alignment, Bounds, MaterialParameter, Model, ResourceID, Text, TextFit, TextStyle}, fields::BoxField, node::NodeError, + node::NodeType, spatial::Spatial, }; use stardust_xr_molecules::{touch_plane::TouchPlane, GrabData, Grabbable}; use std::f32::consts::PI; use tween::TweenTime; +use tween::{QuartInOut, Tweener}; const APP_SIZE: f32 = 0.06; const PADDING: f32 = 0.005; +const ACTIVATION_DISTANCE: f32 = 0.5; #[derive(Clone)] struct Hex { @@ -110,7 +113,7 @@ impl AppHexGrid { break; }; apps.push( - App::new( + App::create_from_desktop_file( button.grabbable.content_parent(), hex.get_coords(), desktop_files.pop().unwrap(), @@ -132,16 +135,20 @@ impl RootHandler for AppHexGrid { let color = [0.0, 1.0, 0.0, 1.0]; self.button .model - .set_material_parameter(1, "color", MaterialParameter::Color(color)) + .model_part("Hex") + .unwrap() + .set_material_parameter("color", MaterialParameter::Color(color)) .unwrap(); for app in &mut self.apps { - app.protostar.toggle(); + app.toggle(); } } else if self.button.touch_plane.touch_stopped() { let color = [0.0, 0.0, 1.0, 1.0]; self.button .model - .set_material_parameter(1, "color", MaterialParameter::Color(color)) + .model_part("Hex") + .unwrap() + .set_material_parameter("color", MaterialParameter::Color(color)) .unwrap(); } for app in &mut self.apps { @@ -149,31 +156,6 @@ impl RootHandler for AppHexGrid { } } } -struct App { - _desktop_file: DesktopFile, - protostar: ProtoStar, -} - -impl App { - fn new( - parent: &Spatial, - position: impl Into>, - desktop_file: DesktopFile, - ) -> Option { - let position = position.into(); - let protostar = - ProtoStar::create_from_desktop_file(parent, position, desktop_file.clone()).ok()?; - Some(App { - _desktop_file: desktop_file, - protostar, - }) - } -} -impl RootHandler for App { - fn frame(&mut self, info: FrameInfo) { - self.protostar.frame(info); - } -} struct Button { touch_plane: TouchPlane, @@ -210,7 +192,9 @@ impl Button { ), &ResourceID::new_namespaced("protostar", "hexagon/hexagon"), )?; - model.set_material_parameter(1, "color", MaterialParameter::Color([0.0, 0.0, 1.0, 1.0]))?; + model + .model_part("Hex")? + .set_material_parameter("color", MaterialParameter::Color([0.0, 0.0, 1.0, 1.0]))?; Ok(Button { touch_plane, grabbable, @@ -230,3 +214,230 @@ impl RootHandler for Button { self.touch_plane.update(); } } + +fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result { + return match &icon.icon_type { + IconType::Png => { + let t = Transform::from_rotation_scale( + Quat::from_rotation_x(PI / 2.0) * Quat::from_rotation_y(PI), + [APP_SIZE * 0.5; 3], + ); + + let model = Model::create( + parent, + t, + &ResourceID::new_namespaced("protostar", "hexagon/hexagon"), + )?; + model + .model_part("Hex")? + .set_material_parameter("color", MaterialParameter::Color([0.0, 1.0, 1.0, 1.0]))?; + model.model_part("Icon")?.set_material_parameter( + "diffuse", + MaterialParameter::Texture(ResourceID::Direct(icon.path.clone())), + )?; + Ok(model) + } + IconType::Gltf => Ok(Model::create( + parent, + Transform::from_scale([0.05; 3]), + &ResourceID::new_direct(icon.path.clone())?, + )?), + _ => panic!("Invalid Icon Type"), + }; +} + +pub struct App { + application: Application, + parent: Spatial, + position: Vector3, + grabbable: Grabbable, + _field: BoxField, + icon: Model, + label: Option, + grabbable_shrink: Option>, + grabbable_grow: Option>, + grabbable_move: Option>, + currently_shown: bool, +} +impl App { + pub fn create_from_desktop_file( + parent: &Spatial, + position: impl Into>, + desktop_file: DesktopFile, + ) -> Result { + let position = position.into(); + let field = BoxField::create(parent, Transform::default(), [APP_SIZE; 3])?; + let application = Application::create(&parent.client()?, desktop_file)?; + let icon = application.icon(128, false); + let grabbable = Grabbable::create( + parent, + Transform::from_position(position), + &field, + GrabData { + max_distance: 0.01, + frame_cancel_threshold: 50, + ..Default::default() + }, + )?; + grabbable.content_parent().set_spatial_parent(parent)?; + field.set_spatial_parent(grabbable.content_parent())?; + let icon = icon + .map(|i| model_from_icon(grabbable.content_parent(), &i)) + .unwrap_or_else(|| { + Ok(Model::create( + grabbable.content_parent(), + Transform::from_rotation_scale( + Quat::from_rotation_x(PI / 2.0) * Quat::from_rotation_y(PI), + [APP_SIZE * 0.5; 3], + ), + &ResourceID::new_namespaced("protostar", "hexagon/hexagon"), + )?) + })?; + + let label_style = TextStyle { + character_height: APP_SIZE * 2.0, + bounds: Some(Bounds { + bounds: [1.0; 2].into(), + fit: TextFit::Wrap, + bounds_align: Alignment::XCenter | Alignment::YCenter, + }), + text_align: Alignment::Center.into(), + ..Default::default() + }; + let label = application.name().and_then(|name| { + Text::create( + &icon, + Transform::from_position_rotation( + [0.0, 0.1, -(APP_SIZE * 4.0)], + Quat::from_rotation_x(PI * 0.5), + ), + name, + label_style, + ) + .ok() + }); + Ok(App { + parent: parent.alias(), + position, + grabbable, + _field: field, + label, + application, + icon, + grabbable_shrink: None, + grabbable_grow: None, + grabbable_move: None, + currently_shown: true, + }) + } + pub fn content_parent(&self) -> &Spatial { + self.grabbable.content_parent() + } + pub fn toggle(&mut self) { + self.grabbable.set_enabled(!self.currently_shown).unwrap(); + if self.currently_shown { + self.grabbable_move = Some(Tweener::quart_in_out(1.0, 0.0001, 0.25)); //TODO make the scale a parameter + } else { + self.icon.set_enabled(true).unwrap(); + self.label.as_ref().map(|l| l.set_enabled(true).unwrap()); + self.grabbable_move = Some(Tweener::quart_in_out(0.0001, 1.0, 0.25)); + } + self.currently_shown = !self.currently_shown; + } +} +impl RootHandler for App { + fn frame(&mut self, info: FrameInfo) { + let _ = self.grabbable.update(&info); + + if let Some(grabbable_move) = &mut self.grabbable_move { + if !grabbable_move.is_finished() { + let scale = grabbable_move.move_by(info.delta); + self.grabbable + .content_parent() + .set_position( + Some(&self.parent), + [ + self.position.x * scale, + self.position.y * scale, + self.position.z * scale, + ], + ) + .unwrap(); + } else { + if grabbable_move.final_value() == 0.0001 { + self.icon.set_enabled(false).unwrap(); + self.label.as_ref().map(|l| l.set_enabled(false).unwrap()); + } + self.grabbable_move = None; + } + } + if let Some(grabbable_shrink) = &mut self.grabbable_shrink { + if !grabbable_shrink.is_finished() { + let scale = grabbable_shrink.move_by(info.delta); + self.grabbable + .content_parent() + .set_scale(Some(&self.parent), Vector3::from([scale; 3])) + .unwrap(); + } else { + self.grabbable + .content_parent() + .set_spatial_parent(&self.parent) + .unwrap(); + if self.currently_shown { + self.grabbable_grow = Some(Tweener::quart_in_out(0.0001, 1.0, 0.25)); + self.grabbable.cancel_angular_velocity(); + self.grabbable.cancel_linear_velocity(); + } + self.grabbable_shrink = None; + self.grabbable + .content_parent() + .set_position(Some(&self.parent), self.position) + .unwrap(); + self.grabbable + .content_parent() + .set_rotation(Some(&self.parent), Quat::default()) + .unwrap(); + self.icon + .set_rotation( + None, + Quat::from_rotation_x(PI / 2.0) * Quat::from_rotation_y(PI), + ) + .unwrap(); + } + } else if let Some(grabbable_grow) = &mut self.grabbable_grow { + if !grabbable_grow.is_finished() { + let scale = grabbable_grow.move_by(info.delta); + self.grabbable + .content_parent() + .set_scale(Some(&self.parent), Vector3::from([scale; 3])) + .unwrap(); + } else { + self.grabbable + .content_parent() + .set_spatial_parent(&self.parent) + .unwrap(); + self.grabbable_grow = None; + } + } else if self.grabbable.valid() && self.grabbable.grab_action().actor_stopped() { + self.grabbable_shrink = Some(Tweener::quart_in_out(APP_SIZE * 0.5, 0.0001, 0.25)); + let Ok(distance_future) = self.grabbable + .content_parent() + .get_position_rotation_scale(&self.parent) + else {return}; + + let application = self.application.clone(); + let space = self.content_parent().alias(); + + //TODO: split the executable string for the args + tokio::task::spawn(async move { + let distance_vector = distance_future.await.ok().unwrap().0; + let distance = ((distance_vector.x.powi(2) + distance_vector.y.powi(2)).sqrt() + + distance_vector.z.powi(2)) + .sqrt(); + if dbg!(distance) > ACTIVATION_DISTANCE { + let _ = application.launch(&space); + } + }); + } + } +} diff --git a/mono_crash.0.0.json b/mono_crash.0.0.json new file mode 100644 index 0000000..1387e70 --- /dev/null +++ b/mono_crash.0.0.json @@ -0,0 +1,1665 @@ +{ + "protocol_version" : "0.0.6", + "configuration" : { + "version" : "(6.13.0) (explicit/88268f9e785)", + "tlc" : "__thread", + "sigsgev" : "altstack", + "notifications" : "epoll", + "architecture" : "amd64", + "disabled_features" : "com", + "smallconfig" : "disabled", + "bigarrays" : "disabled", + "softdebug" : "enabled", + "interpreter" : "enabled", + "llvm_support" : "disabled", + "suspend" : "preemptive" + }, + "memory" : { + "minor_gc_time" : "0", + "major_gc_time" : "9842", + "minor_gc_count" : "0", + "major_gc_count" : "1", + "major_gc_time_concurrent" : "0" + }, + "threads" : [ + { + "is_managed" : false, + "offset_free_hash" : "0x0", + "offset_rich_hash" : "0x0", + "crashed" : false, + "native_thread_id" : "0x7f48c6dff6c0", + "thread_info_addr" : "0x7f4828000b70", + "thread_name" : "Finalizer", + "ctx" : { + "IP" : "0x7f48ce074f0e", + "SP" : "0x7f48c6dfec80", + "BP" : "(nil)" + }, + "unmanaged_frames" : [ + { + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603559", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7514514", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce074f0e", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce0803e0", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c763abe1", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c76040f0", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603fb2", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c767d428", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c767d0bb", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce07844b", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce0fbe40", + "native_offset" : "0x00000" + } + + ] + }, + { + "is_managed" : true, + "offset_free_hash" : "0x9bfc75db6", + "offset_rich_hash" : "0x9bfc75f80", + "crashed" : false, + "native_thread_id" : "0x7f4772dfc6c0", + "thread_info_addr" : "0x7f4728000b70", + "thread_name" : "Timer-Scheduler", + "ctx" : { + "IP" : "0x7f48ce074f0e", + "SP" : "0x7f4772dfaf20", + "BP" : "(nil)" + }, + "managed_frames" : [ + { + "is_managed" : "false", + "native_address" : "unregistered" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x00000", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00000" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x60020a2", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00044" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x600208e", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00014" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x600208d", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00000" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x6002088", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00019" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x600208b", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00000" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x600214a", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x0003c" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x6001f6d", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00014" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x6001f15", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00071" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x6001f13", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00000" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x6001f12", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x0002b" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x6001f6f", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00008" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x00000", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00065" + } + + ], + "unmanaged_frames" : [ + { + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603559", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7514514", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce074f0e", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce077ab5", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c764e6eb", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c760d387", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c760d1fd", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c760d419", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c75ff08d", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c75aef0d", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x00000", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00000" + } + + ] +}, +{ + "is_managed" : false, + "offset_free_hash" : "0x0", + "offset_rich_hash" : "0x0", + "crashed" : false, + "native_thread_id" : "0x7f47713fe6c0", + "thread_info_addr" : "0x7f4720000b70", + "thread_name" : "Thread Pool I/O", + "ctx" : { + "IP" : "0x7f48ce074f0e", + "SP" : "0x7f47713fdb50", + "BP" : "(nil)" + }, + "unmanaged_frames" : [ + { + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603559", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7514514", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce074f0e", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce077ab5", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c764e6eb", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c76578fa", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7565721", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c76040f0", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603fb2", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c767d428", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c767d0bb", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce07844b", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce0fbe40", + "native_offset" : "0x00000" + } + + ] +}, +{ + "is_managed" : false, + "offset_free_hash" : "0x0", + "offset_rich_hash" : "0x0", + "crashed" : false, + "native_thread_id" : "0x7f4770ffc6c0", + "thread_info_addr" : "0x7f4708000b70", + "thread_name" : "Thread Pool Wor", + "ctx" : { + "IP" : "0x7f48ce074f0e", + "SP" : "0x7f4770ffbc50", + "BP" : "(nil)" + }, + "unmanaged_frames" : [ + { + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603559", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7514514", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce074f0e", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce0801cb", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7565e4a", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c76040f0", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603fb2", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c767d428", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c767d0bb", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce07844b", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce0fbe40", + "native_offset" : "0x00000" + } + + ] +}, +{ + "is_managed" : false, + "offset_free_hash" : "0x0", + "offset_rich_hash" : "0x0", + "crashed" : false, + "native_thread_id" : "0x7f4770bfa6c0", + "thread_info_addr" : "0x7f4700000b70", + "thread_name" : "Thread Pool Wor", + "ctx" : { + "IP" : "0x7f48ce074f0e", + "SP" : "0x7f4770bf9c50", + "BP" : "(nil)" + }, + "unmanaged_frames" : [ + { + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603559", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7514514", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce074f0e", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce0801cb", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7565e4a", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c76040f0", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c7603fb2", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c767d428", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48c767d0bb", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce07844b", + "native_offset" : "0x00000" + } +, + { + "is_managed" : "false", + "native_address" : "0x7f48ce0fbe40", + "native_offset" : "0x00000" + } + + ] +}, +{ + "is_managed" : true, + "offset_free_hash" : "0x709fb4f11", + "offset_rich_hash" : "0x709fb5098", + "crashed" : false, + "native_thread_id" : "0x7f47737fe6c0", + "thread_info_addr" : "0x7f4750000b70", + "thread_name" : "LeapC Worker", + "ctx" : { + "IP" : "0x7f48ce074f0e", + "SP" : "0x7f47737fcf10", + "BP" : "(nil)" + }, + "managed_frames" : [ + { + "is_managed" : "false", + "native_address" : "unregistered" + } +, + { + "is_managed" : "true", + "guid" : "E5EF776C-70F2-43B0-927D-7EF9AD9EEE08", + "token" : "0x00000", + "native_offset" : "0x0", + "filename" : "LeapMotion.LeapCSharp.dll", + "sizeofimage" : "0x1e000", + "timestamp" : "0xf5879ec7", + "il_offset" : "0x0000c" + } +, + { + "is_managed" : "true", + "guid" : "E5EF776C-70F2-43B0-927D-7EF9AD9EEE08", + "token" : "0x6000020", + "native_offset" : "0x0", + "filename" : "LeapMotion.LeapCSharp.dll", + "sizeofimage" : "0x1e000", + "timestamp" : "0xf5879ec7", + "il_offset" : "0x0005e" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x6001f6d", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00014" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x6001f15", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00071" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x6001f13", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00000" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x6001f12", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x0002b" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x6001f6f", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00008" + } +, + { + "is_managed" : "true", + "guid" : "7FB66C41-B6E6-41FB-91B7-FD5E48B4C50D", + "token" : "0x00000", + "native_offset" : "0x0", + "filename" : "mscorlib.dll", + "sizeofimage" : "0x470000", + "timestamp" : "0xa9ddd34c", + "il_offset" : "0x00065" + } + + ], +"unmanaged_frames" : [ +{ + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603559", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7514514", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce074f0e", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce077d85", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c6290ebf", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c62ca9d8", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c62cbcfe", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c62a6b98", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c62a77b1", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "true", + "guid" : "E5EF776C-70F2-43B0-927D-7EF9AD9EEE08", + "token" : "0x00000", + "native_offset" : "0x0", + "filename" : "LeapMotion.LeapCSharp.dll", + "sizeofimage" : "0x1e000", + "timestamp" : "0xf5879ec7", + "il_offset" : "0x00000" + } + +] +}, +{ +"is_managed" : false, +"offset_free_hash" : "0x0", +"offset_rich_hash" : "0x0", +"crashed" : true, +"native_thread_id" : "0x7f48d03ad740", +"thread_info_addr" : "0x15d8f00", +"thread_name" : "ultraleap-hand-", +"ctx" : { + "IP" : "0x7f48cfb0d407", + "SP" : "0x7ffd9dd9ba10", + "BP" : "0x15bfdc0" +}, +"unmanaged_frames" : [ +{ + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603d2b", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c75151c9", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c74bdd12", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c744302d", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48cfb0d407", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48cfa86adb", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48cfa86b2b", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48cf062396", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48cf0676e5", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48cf0533f9", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce014850", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce01490a", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x201029", + "native_offset" : "0x00000" + } + +] +}, +{ +"is_managed" : false, +"offset_free_hash" : "0x0", +"offset_rich_hash" : "0x0", +"crashed" : false, +"native_thread_id" : "0x7f477041e6c0", +"thread_info_addr" : "0x7f46f8000b70", +"thread_name" : "Thread Pool Wor", +"ctx" : { + "IP" : "0x7f48ce074f0e", + "SP" : "0x7f477041dc50", + "BP" : "(nil)" +}, +"unmanaged_frames" : [ +{ + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603559", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7514514", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce074f0e", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce0801cb", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7565e4a", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c76040f0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603fb2", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c767d428", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c767d0bb", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce07844b", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce0fbe40", + "native_offset" : "0x00000" + } + +] +}, +{ +"is_managed" : false, +"offset_free_hash" : "0x0", +"offset_rich_hash" : "0x0", +"crashed" : false, +"native_thread_id" : "0x7f482019c6c0", +"thread_info_addr" : "0x7f475c000b70", +"thread_name" : "Loading.Preload", +"ctx" : { + "IP" : "0x7f48ce0f42ed", + "SP" : "0x7f482019bda8", + "BP" : "0x7f48d02a0448" +}, +"unmanaged_frames" : [ +{ + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603559", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7514514", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce0f42ed", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48cfa4f1ce", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48cee327b9", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48cee326f6", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48cef00f29", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce07844b", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce0fbe40", + "native_offset" : "0x00000" + } + +] +}, +{ +"is_managed" : false, +"offset_free_hash" : "0x0", +"offset_rich_hash" : "0x0", +"crashed" : false, +"native_thread_id" : "0x7f47715ff6c0", +"thread_info_addr" : "0x7f472c000b70", +"thread_name" : "Thread Pool I/O", +"ctx" : { + "IP" : "0x7f48ce0eec0f", + "SP" : "0x7f47715fec30", + "BP" : "0x7f48c76cc80c" +}, +"unmanaged_frames" : [ +{ + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603559", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7514514", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce0eec0f", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c76080ef", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7607b99", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c76040f0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603fb2", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c767d428", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c767d0bb", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce07844b", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce0fbe40", + "native_offset" : "0x00000" + } + +] +}, +{ +"is_managed" : false, +"offset_free_hash" : "0x0", +"offset_rich_hash" : "0x0", +"crashed" : false, +"native_thread_id" : "0x7f47711fd6c0", +"thread_info_addr" : "0x7f4724000b70", +"thread_name" : "Thread Pool Wor", +"ctx" : { + "IP" : "0x7f48ce074f0e", + "SP" : "0x7f47711fcc50", + "BP" : "(nil)" +}, +"unmanaged_frames" : [ +{ + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603559", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7514514", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce074f0e", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce0801cb", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7565e4a", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c76040f0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603fb2", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c767d428", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c767d0bb", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce07844b", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce0fbe40", + "native_offset" : "0x00000" + } + +] +}, +{ +"is_managed" : false, +"offset_free_hash" : "0x0", +"offset_rich_hash" : "0x0", +"crashed" : false, +"native_thread_id" : "0x7f4770dfb6c0", +"thread_info_addr" : "0x7f470c000b70", +"thread_name" : "Thread Pool Wor", +"ctx" : { + "IP" : "0x7f48ce074f0e", + "SP" : "0x7f4770dfac50", + "BP" : "(nil)" +}, +"unmanaged_frames" : [ +{ + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603559", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7514514", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce074f0e", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce0801cb", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7565e4a", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c76040f0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603fb2", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c767d428", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c767d0bb", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce07844b", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce0fbe40", + "native_offset" : "0x00000" + } + +] +}, +{ +"is_managed" : false, +"offset_free_hash" : "0x0", +"offset_rich_hash" : "0x0", +"crashed" : false, +"native_thread_id" : "0x7f47709f96c0", +"thread_info_addr" : "0x7f4704000b70", +"thread_name" : "Thread Pool Wor", +"ctx" : { + "IP" : "0x7f48ce074f0e", + "SP" : "0x7f47709f8c50", + "BP" : "(nil)" +}, +"unmanaged_frames" : [ +{ + "is_managed" : "false", + "native_address" : "0x7f48c74b98ad", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603471", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603797", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603559", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7514514", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce02aab0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce074f0e", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce0801cb", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7565e4a", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c76040f0", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c7603fb2", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c767d428", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48c767d0bb", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce07844b", + "native_offset" : "0x00000" + } +, +{ + "is_managed" : "false", + "native_address" : "0x7f48ce0fbe40", + "native_offset" : "0x00000" + } + +] +} +] +} \ No newline at end of file diff --git a/res/protostar/hexagon/hexagon.bin b/res/protostar/hexagon/hexagon.bin index e900474..f56fec4 100644 Binary files a/res/protostar/hexagon/hexagon.bin and b/res/protostar/hexagon/hexagon.bin differ diff --git a/res/protostar/hexagon/hexagon.gltf b/res/protostar/hexagon/hexagon.gltf index 2199495..f0480e3 100644 --- a/res/protostar/hexagon/hexagon.gltf +++ b/res/protostar/hexagon/hexagon.gltf @@ -1,276 +1,286 @@ { - "asset" : { - "generator" : "Khronos glTF Blender I/O v3.4.50", - "version" : "2.0" - }, - "extensionsUsed" : [ - "KHR_materials_unlit" - ], - "scene" : 0, - "scenes" : [ - { - "name" : "Scene", - "nodes" : [ - 0 - ] - } - ], - "nodes" : [ - { - "mesh" : 0, - "name" : "Hex" - } - ], - "materials" : [ - { - "alphaCutoff" : 0.5, - "alphaMode" : "MASK", - "extensions" : { - "KHR_materials_unlit" : {} - }, - "name" : "Icon", - "pbrMetallicRoughness" : { - "baseColorTexture" : { - "index" : 0, - "texCoord" : 0 - }, - "metallicFactor" : 0, - "roughnessFactor" : 0.9 - } - }, - { - "alphaMode" : "BLEND", - "extensions" : { - "KHR_materials_unlit" : {} - }, - "name" : "Hex", - "pbrMetallicRoughness" : { - "baseColorFactor" : [ - 1, - 0, - 0, - 1 - ], - "baseColorTexture" : { - "index" : 1, - "texCoord" : 0 - }, - "metallicFactor" : 0, - "roughnessFactor" : 0.9 - } - } - ], - "meshes" : [ - { - "name" : "Circle", - "primitives" : [ - { - "attributes" : { - "COLOR_0" : 0, - "POSITION" : 1, - "TEXCOORD_0" : 2, - "NORMAL" : 3 - }, - "indices" : 4, - "material" : 0 - }, - { - "attributes" : { - "COLOR_0" : 5, - "POSITION" : 6, - "TEXCOORD_0" : 7, - "NORMAL" : 8 - }, - "indices" : 9, - "material" : 1 - } - ] - } - ], - "textures" : [ - { - "sampler" : 0, - "source" : 0 - }, - { - "sampler" : 1, - "source" : 1 - } - ], - "images" : [ - { - "mimeType" : "image/png", - "name" : "icon_test", - "uri" : "icon_test.png" - }, - { - "mimeType" : "image/png", - "name" : "hex_atlas", - "uri" : "hex_atlas.png" - } - ], - "accessors" : [ - { - "bufferView" : 0, - "componentType" : 5123, - "count" : 4, - "normalized" : true, - "type" : "VEC4" - }, - { - "bufferView" : 1, - "componentType" : 5126, - "count" : 4, - "max" : [ - 0.5853440165519714, - 0.05000000074505806, - 0.5853440165519714 - ], - "min" : [ - -0.5853440165519714, - 0.05000000074505806, - -0.5853440165519714 - ], - "type" : "VEC3" - }, - { - "bufferView" : 2, - "componentType" : 5126, - "count" : 4, - "type" : "VEC2" - }, - { - "bufferView" : 3, - "componentType" : 5126, - "count" : 4, - "type" : "VEC3" - }, - { - "bufferView" : 4, - "componentType" : 5123, - "count" : 6, - "type" : "SCALAR" - }, - { - "bufferView" : 5, - "componentType" : 5123, - "count" : 54, - "normalized" : true, - "type" : "VEC4" - }, - { - "bufferView" : 6, - "componentType" : 5126, - "count" : 54, - "max" : [ - 1.0441828966140747, - 0.05000000074505806, - 0.9042890667915344 - ], - "min" : [ - -1.0441828966140747, - 0, - -0.9042890667915344 - ], - "type" : "VEC3" - }, - { - "bufferView" : 7, - "componentType" : 5126, - "count" : 54, - "type" : "VEC2" - }, - { - "bufferView" : 8, - "componentType" : 5126, - "count" : 54, - "type" : "VEC3" - }, - { - "bufferView" : 9, - "componentType" : 5123, - "count" : 84, - "type" : "SCALAR" - } - ], - "bufferViews" : [ - { - "buffer" : 0, - "byteLength" : 32, - "byteOffset" : 0, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 48, - "byteOffset" : 32, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 32, - "byteOffset" : 80, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 48, - "byteOffset" : 112, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 12, - "byteOffset" : 160, - "target" : 34963 - }, - { - "buffer" : 0, - "byteLength" : 432, - "byteOffset" : 172, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 648, - "byteOffset" : 604, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 432, - "byteOffset" : 1252, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 648, - "byteOffset" : 1684, - "target" : 34962 - }, - { - "buffer" : 0, - "byteLength" : 168, - "byteOffset" : 2332, - "target" : 34963 - } - ], - "samplers" : [ - { - "magFilter" : 9729, - "minFilter" : 9987, - "wrapS" : 33071, - "wrapT" : 33071 - }, - { - "magFilter" : 9729, - "minFilter" : 9987 - } - ], - "buffers" : [ - { - "byteLength" : 2500, - "uri" : "hexagon.bin" - } - ] + "asset":{ + "generator":"Khronos glTF Blender I/O v3.5.30", + "version":"2.0" + }, + "extensionsUsed":[ + "KHR_materials_unlit" + ], + "scene":0, + "scenes":[ + { + "name":"Scene", + "nodes":[ + 0, + 1 + ] + } + ], + "nodes":[ + { + "mesh":0, + "name":"Icon" + }, + { + "mesh":1, + "name":"Hex" + } + ], + "materials":[ + { + "alphaCutoff":0.5, + "alphaMode":"MASK", + "extensions":{ + "KHR_materials_unlit":{} + }, + "name":"Icon", + "pbrMetallicRoughness":{ + "baseColorTexture":{ + "index":0, + "texCoord":0 + }, + "metallicFactor":0, + "roughnessFactor":0.9 + } + }, + { + "alphaMode":"BLEND", + "extensions":{ + "KHR_materials_unlit":{} + }, + "name":"Hex", + "pbrMetallicRoughness":{ + "baseColorFactor":[ + 1, + 0, + 0, + 1 + ], + "baseColorTexture":{ + "index":1, + "texCoord":0 + }, + "metallicFactor":0, + "roughnessFactor":0.9 + } + } + ], + "meshes":[ + { + "name":"Circle", + "primitives":[ + { + "attributes":{ + "COLOR_0":0, + "POSITION":1, + "TEXCOORD_0":2, + "NORMAL":3 + }, + "indices":4, + "material":0 + } + ] + }, + { + "name":"Circle.001", + "primitives":[ + { + "attributes":{ + "COLOR_0":5, + "POSITION":6, + "TEXCOORD_0":7, + "NORMAL":8 + }, + "indices":9, + "material":1 + } + ] + } + ], + "textures":[ + { + "sampler":0, + "source":0 + }, + { + "sampler":1, + "source":1 + } + ], + "images":[ + { + "mimeType":"image/png", + "name":"icon_test", + "uri":"icon_test.png" + }, + { + "mimeType":"image/png", + "name":"hex_atlas", + "uri":"hex_atlas.png" + } + ], + "accessors":[ + { + "bufferView":0, + "componentType":5123, + "count":4, + "normalized":true, + "type":"VEC4" + }, + { + "bufferView":1, + "componentType":5126, + "count":4, + "max":[ + 0.5853440165519714, + 0.05000000074505806, + 0.5853440165519714 + ], + "min":[ + -0.5853440165519714, + 0.05000000074505806, + -0.5853440165519714 + ], + "type":"VEC3" + }, + { + "bufferView":2, + "componentType":5126, + "count":4, + "type":"VEC2" + }, + { + "bufferView":3, + "componentType":5126, + "count":4, + "type":"VEC3" + }, + { + "bufferView":4, + "componentType":5123, + "count":6, + "type":"SCALAR" + }, + { + "bufferView":5, + "componentType":5123, + "count":54, + "normalized":true, + "type":"VEC4" + }, + { + "bufferView":6, + "componentType":5126, + "count":54, + "max":[ + 1.0441828966140747, + 0.05000000074505806, + 0.9042890667915344 + ], + "min":[ + -1.0441828966140747, + 0, + -0.9042890667915344 + ], + "type":"VEC3" + }, + { + "bufferView":7, + "componentType":5126, + "count":54, + "type":"VEC2" + }, + { + "bufferView":8, + "componentType":5126, + "count":54, + "type":"VEC3" + }, + { + "bufferView":9, + "componentType":5123, + "count":84, + "type":"SCALAR" + } + ], + "bufferViews":[ + { + "buffer":0, + "byteLength":32, + "byteOffset":0, + "target":34962 + }, + { + "buffer":0, + "byteLength":48, + "byteOffset":32, + "target":34962 + }, + { + "buffer":0, + "byteLength":32, + "byteOffset":80, + "target":34962 + }, + { + "buffer":0, + "byteLength":48, + "byteOffset":112, + "target":34962 + }, + { + "buffer":0, + "byteLength":12, + "byteOffset":160, + "target":34963 + }, + { + "buffer":0, + "byteLength":432, + "byteOffset":172, + "target":34962 + }, + { + "buffer":0, + "byteLength":648, + "byteOffset":604, + "target":34962 + }, + { + "buffer":0, + "byteLength":432, + "byteOffset":1252, + "target":34962 + }, + { + "buffer":0, + "byteLength":648, + "byteOffset":1684, + "target":34962 + }, + { + "buffer":0, + "byteLength":168, + "byteOffset":2332, + "target":34963 + } + ], + "samplers":[ + { + "magFilter":9729, + "minFilter":9987, + "wrapS":33071, + "wrapT":33071 + }, + { + "magFilter":9729, + "minFilter":9987 + } + ], + "buffers":[ + { + "byteLength":2500, + "uri":"hexagon.bin" + } + ] } diff --git a/src/application.rs b/src/application.rs new file mode 100644 index 0000000..466bddc --- /dev/null +++ b/src/application.rs @@ -0,0 +1,100 @@ +use crate::xdg::{DesktopFile, Icon, IconType}; +use nix::unistd::setsid; +use regex::Regex; +use stardust_xr_fusion::{ + client::Client, + node::{NodeError, NodeType}, + spatial::Spatial, + startup_settings::StartupSettings, +}; +use std::{ + os::unix::process::CommandExt, + process::{Command, Stdio}, + sync::Arc, +}; + +#[derive(Debug, Clone)] +pub struct Application { + desktop_file: DesktopFile, + startup_settings: Arc, +} +impl Application { + pub fn create(client: &Arc, desktop_file: DesktopFile) -> Result { + if desktop_file.no_display { + return Err(NodeError::DoesNotExist); + } + + let startup_settings = Arc::new(StartupSettings::create(client)?); + Ok(Application { + desktop_file, + startup_settings, + }) + } + + pub fn name(&self) -> Option<&str> { + self.desktop_file.name.as_deref() + } + pub fn categories(&self) -> &[String] { + self.desktop_file.categories.as_slice() + } + + pub fn icon(&self, preferred_px_size: u16, prefer_3d: bool) -> Option { + let raw_icons = self.desktop_file.get_raw_icons(preferred_px_size); + let mut icon = raw_icons.iter().max_by_key(|i| i.size).cloned(); + if prefer_3d { + icon = raw_icons + .into_iter() + .find(|i| match i.icon_type { + IconType::Gltf => true, + _ => false, + }) + .or(icon); + } + + icon.and_then(|i| i.cached_process(preferred_px_size).ok()) + } + + pub fn launch(&self, launch_space: &Spatial) -> Result<(), NodeError> { + self.startup_settings.set_root(launch_space)?; + let future_startup_token = self.startup_settings.generate_startup_token()?; + let future_connection_env = self + .startup_settings + .node() + .client()? + .get_connection_environment()?; + + let executable = self + .desktop_file + .command + .clone() + .ok_or(NodeError::DoesNotExist)?; + tokio::task::spawn(async move { + let Ok(startup_token) = future_startup_token.await else {return}; + let Ok(connection_env) = future_connection_env.await else {return}; + + for (k, v) in connection_env.into_iter() { + std::env::set_var(k, v); + } + + std::env::set_var("STARDUST_STARTUP_TOKEN", startup_token); + let re = Regex::new(r"%[fFuUdDnNickvm]").unwrap(); + let exec = re.replace_all(&executable, ""); + unsafe { + Command::new("sh") + .arg("-c") + .arg(exec.to_string()) + .stdin(Stdio::null()) + .stdout(Stdio::null()) + .stderr(Stdio::null()) + .pre_exec(|| { + _ = setsid(); + Ok(()) + }) + .spawn() + .expect("Failed to start child process"); + } + }); + + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index bda7f63..c9c8dfe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,3 @@ +pub mod application; pub mod protostar; pub mod xdg; diff --git a/src/main.rs b/src/main.rs index a41c780..dd84573 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,5 @@ use clap::Parser; -use color_eyre::{ - eyre::{bail, Result}, - Report, -}; +use color_eyre::{eyre::Result, Report}; use manifest_dir_macros::directory_relative_path; use protostar::{protostar::ProtoStar, xdg::parse_desktop_file}; use stardust_xr_fusion::client::Client; @@ -11,21 +8,8 @@ use std::path::PathBuf; #[derive(Debug, Parser)] #[clap(author, version, about, long_about = None)] struct Args { - #[clap(short, long, default_value_t = 0.1)] - size: f32, - #[clap( - short, - long, - conflicts_with = "command", - required_unless_present = "command", - conflicts_with = "icon", - required_unless_present = "icon" - )] - desktop_file: Option, - #[clap(short, long, conflicts_with = "desktop_file", requires = "command")] - icon: Option, - #[clap(short, long, conflicts_with = "desktop_file", requires = "icon")] - command: Option, + // #[clap(short, long)] + desktop_file: PathBuf, } #[tokio::main(flavor = "current_thread")] @@ -35,17 +19,11 @@ async fn main() -> Result<()> { let (client, event_loop) = Client::connect_with_async_loop().await?; client.set_base_prefixes(&[directory_relative_path!("res")]); - let protostar = if let Some(desktop_file) = args.desktop_file { - ProtoStar::create_from_desktop_file( - client.get_root(), - [0.0, 0.0, 0.0], - parse_desktop_file(desktop_file).map_err(|e| Report::msg(e))?, - )? - } else if let Some(command) = args.command { - ProtoStar::new_raw(client.get_root(), [0.0, 0.0, 0.0], None, None, command)? - } else { - bail!("No command or desktop file, nothing to launch."); - }; + let protostar = ProtoStar::create_from_desktop_file( + client.get_root(), + [0.0, 0.0, 0.0], + parse_desktop_file(args.desktop_file).map_err(|e| Report::msg(e))?, + )?; let _root = client.wrap_root(protostar); diff --git a/src/protostar.rs b/src/protostar.rs index b86cbae..1fa8406 100644 --- a/src/protostar.rs +++ b/src/protostar.rs @@ -1,9 +1,10 @@ -use crate::xdg::{DesktopFile, Icon, IconType}; -use color_eyre::eyre::{eyre, Result}; +use crate::{ + application::Application, + xdg::{DesktopFile, Icon, IconType}, +}; +use color_eyre::eyre::Result; use glam::Quat; use mint::Vector3; -use nix::unistd::setsid; -use regex::Regex; use stardust_xr_fusion::{ client::{FrameInfo, RootHandler}, core::values::Transform, @@ -11,12 +12,9 @@ use stardust_xr_fusion::{ fields::BoxField, node::NodeType, spatial::Spatial, - startup_settings::StartupSettings, }; use stardust_xr_molecules::{GrabData, Grabbable}; use std::f32::consts::PI; -use std::os::unix::process::CommandExt; -use std::process::{Command, Stdio}; use tween::{QuartInOut, Tweener}; const MODEL_SCALE: f32 = 0.03; @@ -35,13 +33,10 @@ fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result { t, &ResourceID::new_namespaced("protostar", "hexagon/hexagon"), )?; - model.set_material_parameter( - 1, - "color", - MaterialParameter::Color([0.0, 1.0, 1.0, 1.0]), - )?; - model.set_material_parameter( - 0, + model + .model_part("Hex")? + .set_material_parameter("color", MaterialParameter::Color([0.0, 1.0, 1.0, 1.0]))?; + model.model_part("Icon")?.set_material_parameter( "diffuse", MaterialParameter::Texture(ResourceID::Direct(icon.path.clone())), )?; @@ -57,16 +52,16 @@ fn model_from_icon(parent: &Spatial, icon: &Icon) -> Result { } pub struct ProtoStar { + application: Application, parent: Spatial, position: Vector3, grabbable: Grabbable, - field: BoxField, + _field: BoxField, icon: Model, label: Option, grabbable_shrink: Option>, grabbable_grow: Option>, grabbable_move: Option>, - execute_command: String, currently_shown: bool, } impl ProtoStar { @@ -74,45 +69,11 @@ impl ProtoStar { parent: &Spatial, position: impl Into>, desktop_file: DesktopFile, - ) -> Result { - // dbg!(&desktop_file); - let raw_icons = desktop_file.get_raw_icons(); - let mut icon = raw_icons - .clone() - .into_iter() - .find(|i| match i.icon_type { - IconType::Gltf => true, - _ => false, - }) - .or(raw_icons.into_iter().max_by_key(|i| i.size)); - - match icon { - Some(i) => { - icon = match i.cached_process(128) { - Ok(i) => Some(i), - _ => None, - } - } - None => {} - } - - Self::new_raw( - parent, - position, - desktop_file.name.as_deref(), - icon, - desktop_file.command.ok_or_else(|| eyre!("No command"))?, - ) - } - pub fn new_raw( - parent: &Spatial, - position: impl Into>, - name: Option<&str>, - icon: Option, - execute_command: String, ) -> Result { let position = position.into(); let field = BoxField::create(parent, Transform::default(), [MODEL_SCALE * 2.0; 3])?; + let application = Application::create(&parent.client()?, desktop_file)?; + let icon = application.icon(128, false); let grabbable = Grabbable::create( parent, Transform::from_position(position), @@ -147,7 +108,7 @@ impl ProtoStar { text_align: Alignment::Center.into(), ..Default::default() }; - let label = name.and_then(|name| { + let label = application.name().and_then(|name| { Text::create( &icon, Transform::from_position_rotation( @@ -163,14 +124,14 @@ impl ProtoStar { parent: parent.alias(), position, grabbable, - field, + _field: field, label, + application, icon, grabbable_shrink: None, grabbable_grow: None, - execute_command, - currently_shown: true, grabbable_move: None, + currently_shown: true, }) } pub fn content_parent(&self) -> &Spatial { @@ -261,20 +222,15 @@ impl RootHandler for ProtoStar { .unwrap(); self.grabbable_grow = None; } - } else if self.grabbable.grab_action().actor_stopped() { - let startup_settings = StartupSettings::create(&self.field.client().unwrap()).unwrap(); - startup_settings - .set_root(self.grabbable.content_parent()) - .unwrap(); + } else if self.grabbable.valid() && self.grabbable.grab_action().actor_stopped() { self.grabbable_shrink = Some(Tweener::quart_in_out(MODEL_SCALE, 0.0001, 0.25)); - let distance_future = self - .grabbable + let Ok(distance_future) = self.grabbable .content_parent() .get_position_rotation_scale(&self.parent) - .unwrap(); + else {return}; - let executable = self.execute_command.clone(); - let client = self.content_parent().client().unwrap(); + let application = self.application.clone(); + let space = self.content_parent().alias(); //TODO: split the executable string for the args tokio::task::spawn(async move { @@ -283,30 +239,7 @@ impl RootHandler for ProtoStar { + distance_vector.z.powi(2)) .sqrt(); if dbg!(distance) > ACTIVATION_DISTANCE { - let future = startup_settings.generate_startup_token().unwrap(); - - let env = client.get_connection_environment().unwrap().await.unwrap(); - for (k, v) in env.into_iter() { - std::env::set_var(k, v); - } - - std::env::set_var("STARDUST_STARTUP_TOKEN", future.await.unwrap()); - let re = Regex::new(r"%[fFuUdDnNickvm]").unwrap(); - let exec = re.replace_all(&executable, ""); - unsafe { - Command::new("sh") - .arg("-c") - .arg(exec.to_string()) - .stdin(Stdio::null()) - .stdout(Stdio::null()) - .stderr(Stdio::null()) - .pre_exec(|| { - _ = setsid(); - Ok(()) - }) - .spawn() - .expect("Failed to start child process"); - } + let _ = application.launch(&space); } }); } diff --git a/src/xdg.rs b/src/xdg.rs index 9390232..e024843 100644 --- a/src/xdg.rs +++ b/src/xdg.rs @@ -183,19 +183,19 @@ pub struct DesktopFile { pub no_display: bool, } impl DesktopFile { - pub fn get_raw_icons(&self) -> Vec { + pub fn get_raw_icons(&self, preferred_px_size: u16) -> Vec { // Get the name of the icon from the DesktopFile struct let Some(icon_name) = self.icon.as_ref() else { return Vec::new(); }; let test_icon_path = self.path.join(Path::new(icon_name)); if test_icon_path.exists() { - if let Some(icon) = Icon::from_path(test_icon_path, 128) { + if let Some(icon) = Icon::from_path(test_icon_path, preferred_px_size) { return vec![icon]; } } let cache_icon_path = get_image_cache_dir().join(icon_name).canonicalize(); if cache_icon_path.is_ok() { - if let Some(icon) = Icon::from_path(cache_icon_path.unwrap(), 128) { + if let Some(icon) = Icon::from_path(cache_icon_path.unwrap(), preferred_px_size) { return vec![icon]; } } @@ -272,7 +272,7 @@ fn test_get_icon_path() { }; // Call the get_icon_path() function with a size argument and store the result - let icon_paths = desktop_file.get_raw_icons(); + let icon_paths = desktop_file.get_raw_icons(128); dbg!(&icon_paths); // Assert that the get_icon_path() function returns the expected result