diff --git a/Cargo.lock b/Cargo.lock index 341bfac..29db205 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,6 +67,12 @@ version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" +[[package]] +name = "arrayvec" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" + [[package]] name = "async-broadcast" version = "0.7.2" @@ -186,6 +192,9 @@ name = "async-task" version = "4.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" +dependencies = [ + "portable-atomic", +] [[package]] name = "async-trait" @@ -203,6 +212,9 @@ name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +dependencies = [ + "portable-atomic", +] [[package]] name = "autocfg" @@ -210,6 +222,118 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "bevy_ecs" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4654b9b3535fa7813d2878a50e1b5ad80a361dc1c913b96ded57667f65d70a01" +dependencies = [ + "arrayvec", + "bevy_ecs_macros", + "bevy_platform", + "bevy_ptr", + "bevy_tasks", + "bevy_utils", + "bitflags 2.13.0", + "bumpalo", + "concurrent-queue", + "derive_more", + "fixedbitset", + "indexmap", + "log", + "nonmax", + "slotmap", + "smallvec", + "thiserror", + "variadics_please", +] + +[[package]] +name = "bevy_ecs_macro_logic" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee0b98a74141ce8dce4654c60020ebbaefab32646f42af6bbae55f282ae65ff7" +dependencies = [ + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_ecs_macros" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dc958a194d226d618404e0fea99a3c8b4146207a00a3ba07fa712bf71607240" +dependencies = [ + "bevy_ecs_macro_logic", + "bevy_macro_utils", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "bevy_macro_utils" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "746a19912c6dc1bbe79188778573e8a253d5832c696b2fcb95578c17b29ff7ba" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "toml_edit", +] + +[[package]] +name = "bevy_platform" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3120670bb2308980f723477c9d82476fcda31f08be9b256c3f0acdee82a65094" +dependencies = [ + "foldhash", + "futures-channel", + "hashbrown 0.16.1", + "portable-atomic", + "portable-atomic-util", + "serde", + "spin", + "windows-sys", +] + +[[package]] +name = "bevy_ptr" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b511e89f7078fd21fdea77061a0ca3e737297c7011bb10c073e0aecb17c9fea6" + +[[package]] +name = "bevy_tasks" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa34e6b9b804851ec08a41c0346c859d82e2fa98c906d74b965ee61bbbb688e4" +dependencies = [ + "async-task", + "atomic-waker", + "bevy_platform", + "crossbeam-queue", + "derive_more", + "futures-lite", + "heapless", + "web-task", +] + +[[package]] +name = "bevy_utils" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aceea6c7ffdd568f866d5ca4dfe50c33440c54f7bc230c13a9ba7ab0c91aed1" +dependencies = [ + "bevy_platform", + "disqualified", + "indexmap", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -241,6 +365,12 @@ version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "calloop" version = "0.14.4" @@ -337,6 +467,25 @@ name = "concurrent-queue" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", + "portable-atomic", +] + +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" dependencies = [ "crossbeam-utils", ] @@ -367,6 +516,7 @@ name = "daemon" version = "0.1.0" dependencies = [ "anyhow", + "bevy_ecs", "calloop", "clap", "env_logger", @@ -409,6 +559,35 @@ dependencies = [ "thiserror", ] +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn", + "unicode-xid", +] + +[[package]] +name = "disqualified" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9c272297e804878a2a4b707cfcfc6d2328b5bb936944613b4fdf2b9269afdfd" + [[package]] name = "endi" version = "1.1.1" @@ -502,6 +681,27 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", +] + [[package]] name = "futures-core" version = "0.3.32" @@ -556,12 +756,41 @@ dependencies = [ "r-efi", ] +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "equivalent", +] + [[package]] name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +[[package]] +name = "heapless" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4" +dependencies = [ + "hash32", + "portable-atomic", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.5.0" @@ -619,7 +848,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.17.1", ] [[package]] @@ -715,6 +944,12 @@ dependencies = [ "libc", ] +[[package]] +name = "nonmax" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" + [[package]] name = "once_cell" version = "1.21.4" @@ -895,6 +1130,15 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "1.1.4" @@ -914,6 +1158,12 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" + [[package]] name = "serde" version = "1.0.228" @@ -984,6 +1234,36 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "strsim" version = "0.11.1" @@ -1113,6 +1393,18 @@ version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "unicode-segmentation" +version = "1.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + [[package]] name = "users" version = "0.11.0" @@ -1140,6 +1432,23 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "variadics_please" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41b6d82be61465f97d42bd1d15bf20f3b0a3a0905018f38f9d6f6962055b0b5c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wasm-bindgen" version = "0.2.126" @@ -1185,6 +1494,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "web-task" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cdc136a53ccd64a1211f107ccc34404769fbcc0f165f1afa065f5d88ab93538" +dependencies = [ + "async-task", + "cfg-if", + "js-sys", + "wasm-bindgen", +] + [[package]] name = "windows-link" version = "0.2.1" diff --git a/daemon/Cargo.toml b/daemon/Cargo.toml index 894b3ee..e9fb10c 100644 --- a/daemon/Cargo.toml +++ b/daemon/Cargo.toml @@ -22,6 +22,7 @@ calloop = { version = "0.14.4", features = ["signals"] } rustix = { version = "1.1.4", features = ["fs", "net", "process", "system"] } users = "0.11.0" zbus = { version = "5.16.0", optional = true } +bevy_ecs = { version = "0.19.0", default-features = false } [build-dependencies] hyprwire-scanner = "0.4.3" diff --git a/daemon/src/device.rs b/daemon/src/device.rs index c1f2bf3..683addb 100644 --- a/daemon/src/device.rs +++ b/daemon/src/device.rs @@ -71,10 +71,10 @@ pub fn close_device( ); } - if let Some(devices) = world.get_mut::(client_entity) { + if let Some(mut devices) = world.get_mut::(client_entity) { devices.0.remove(idx); } - world.remove_entity(device_entity); + world.despawn(device_entity); Ok(()) } @@ -151,13 +151,13 @@ pub fn activate(world: &mut ecs::World, entity: ecs::Entity) -> anyhow::Result<( .ok_or_else(|| anyhow::anyhow!("device has no fd"))?; drm_set_master(&fd.0) .map_err(|err| anyhow::anyhow!("Could not make device fd drm master: {err}"))?; - world.insert(entity, ecs::DeviceActive(true)); + world.entity_mut(entity).insert(ecs::DeviceActive(true)); } DeviceKind::Evdev | DeviceKind::Hidraw => { return Err(anyhow::anyhow!("device type cannot be activated")); } DeviceKind::Wscons => { - world.insert(entity, ecs::DeviceActive(true)); + world.entity_mut(entity).insert(ecs::DeviceActive(true)); } } @@ -204,7 +204,7 @@ pub fn deactivate(world: &mut ecs::World, entity: ecs::Entity) -> anyhow::Result DeviceKind::Wscons => {} } - world.insert(entity, ecs::DeviceActive(false)); + world.entity_mut(entity).insert(ecs::DeviceActive(false)); Ok(()) } @@ -215,10 +215,10 @@ pub fn matches_path(world: &ecs::World, entity: ecs::Entity, path: &path::Path) } pub fn add_object(world: &mut ecs::World, entity: ecs::Entity, object: device::Device) { - if let Some(ref_count) = world.get_mut::(entity) { + if let Some(mut ref_count) = world.get_mut::(entity) { ref_count.0 += 1; } - if let Some(objects) = world.get_mut::(entity) { + if let Some(mut objects) = world.get_mut::(entity) { objects.0.push(object); } } @@ -269,7 +269,7 @@ pub fn contains_object(world: &ecs::World, entity: ecs::Entity, object: &device: } pub fn remove_object(world: &mut ecs::World, entity: ecs::Entity, object: &device::Device) { - if let Some(objects) = world.get_mut::(entity) { + if let Some(mut objects) = world.get_mut::(entity) { objects.0.retain(|candidate| candidate != object); } } @@ -283,7 +283,7 @@ pub fn send_revoked(world: &ecs::World, entity: ecs::Entity) { } pub fn decrement_ref(world: &mut ecs::World, entity: ecs::Entity) -> usize { - let Some(ref_count) = world.get_mut::(entity) else { + let Some(mut ref_count) = world.get_mut::(entity) else { return 0; }; ref_count.0 = ref_count.0.saturating_sub(1); diff --git a/daemon/src/ecs/components.rs b/daemon/src/ecs/components.rs index b0ca68c..cb46214 100644 --- a/daemon/src/ecs/components.rs +++ b/daemon/src/ecs/components.rs @@ -1,90 +1,73 @@ use crate::{device, seat, seat_v1, session, session_core_session, session_core_v1}; +use bevy_ecs::prelude::*; use std::os::fd; use std::{path, time}; -pub trait Component: Sized { - fn storage(world: &mut super::World) -> &mut Vec>; - fn storage_ref(world: &super::World) -> &Vec>; -} - -macro_rules! component { - ($name:ident, $field:ident) => { - impl Component for $name { - fn storage(world: &mut super::World) -> &mut Vec> { - &mut world.$field - } - fn storage_ref(world: &super::World) -> &Vec> { - &world.$field - } - } - }; -} - +#[derive(Component)] pub struct Uid(pub u32); -component!(Uid, uid_components); +#[derive(Component)] pub struct Username(pub String); -component!(Username, username_components); +#[derive(Component)] pub struct Vt(pub u32); -component!(Vt, vt_components); +#[derive(Component)] pub struct SeatName(pub String); -component!(SeatName, seat_name_components); -pub struct SeatEntity(pub super::Entity); -component!(SeatEntity, seat_entity_components); +#[derive(Component)] +pub struct SeatEntity(pub Entity); +#[derive(Component)] pub struct Timestamp(pub time::SystemTime); -component!(Timestamp, timestamp_components); +#[derive(Component)] pub struct LeaderId(pub i32); -component!(LeaderId, leader_id_components); +#[derive(Component)] pub struct IsLocal(pub bool); -component!(IsLocal, is_local_components); +#[derive(Component)] pub struct RemoteHost(pub String); -component!(RemoteHost, remote_host_components); +#[derive(Component)] pub struct SessionObjects(pub Vec); -component!(SessionObjects, session_objects_components); +#[derive(Component)] pub struct ActiveState(pub session_core_v1::ActiveState); -component!(ActiveState, active_state_components); +#[derive(Component)] pub struct Session(pub session::SessionId); -component!(Session, session_components); +#[derive(Component)] pub struct SeatObject(pub seat_v1::seat::Seat); -component!(SeatObject, seat_object_components); -pub struct Devices(pub Vec); -component!(Devices, devices_components); +#[derive(Component)] +pub struct Devices(pub Vec); +#[derive(Component)] pub struct DeviceObjects(pub Vec); -component!(DeviceObjects, device_objects_components); +#[derive(Component)] pub struct DevicePath(pub path::PathBuf); -component!(DevicePath, device_path_components); +#[derive(Component)] pub struct DeviceRefCount(pub usize); -component!(DeviceRefCount, device_ref_count_components); +#[derive(Component)] pub struct DeviceKind(pub device::DeviceKind); -component!(DeviceKind, device_kind_components); +#[derive(Component)] pub struct DeviceId(pub u32); -component!(DeviceId, device_id_components); +#[derive(Component)] pub struct DeviceActive(pub bool); -component!(DeviceActive, device_active_components); +#[derive(Component)] pub struct DeviceFd(pub fd::OwnedFd); -component!(DeviceFd, device_fd_components); +#[derive(Component)] pub struct SeatState(pub seat::SeatState); -component!(SeatState, seat_state_components); #[derive(Clone, Copy, PartialEq, Eq)] pub enum SeatKind { @@ -92,17 +75,17 @@ pub enum SeatKind { NonVtBound, } +#[derive(Component)] pub struct SeatMode(pub SeatKind); -component!(SeatMode, seat_mode_components); +#[derive(Component)] pub struct CurrentVt(pub u32); -component!(CurrentVt, current_vt_components); -pub struct SeatClients(pub Vec); -component!(SeatClients, seat_clients_components); +#[derive(Component)] +pub struct SeatClients(pub Vec); -pub struct ActiveClient(pub super::Entity); -component!(ActiveClient, active_client_components); +#[derive(Component)] +pub struct ActiveClient(pub Entity); -pub struct NextClient(pub super::Entity); -component!(NextClient, next_client_components); +#[derive(Component)] +pub struct NextClient(pub Entity); diff --git a/daemon/src/ecs/mod.rs b/daemon/src/ecs/mod.rs index e9c3b9e..466dc94 100644 --- a/daemon/src/ecs/mod.rs +++ b/daemon/src/ecs/mod.rs @@ -2,202 +2,89 @@ mod components; use crate::session; use crate::{device, seat, seat_v1, session_core_session, session_core_v1}; +pub use bevy_ecs::entity::Entity; +pub use bevy_ecs::world::World; pub use components::*; use std::os::fd; use std::path; use std::time; -#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] -pub struct Entity(usize); - -#[derive(Default)] -pub struct World { - next_entity: usize, - free_entities: Vec, - uid_components: Vec>, - username_components: Vec>, - vt_components: Vec>, - seat_name_components: Vec>, - seat_entity_components: Vec>, - timestamp_components: Vec>, - leader_id_components: Vec>, - is_local_components: Vec>, - remote_host_components: Vec>, - session_objects_components: Vec>, - active_state_components: Vec>, - session_components: Vec>, - seat_object_components: Vec>, - devices_components: Vec>, - device_objects_components: Vec>, - device_path_components: Vec>, - device_ref_count_components: Vec>, - device_kind_components: Vec>, - device_id_components: Vec>, - device_active_components: Vec>, - device_fd_components: Vec>, - seat_state_components: Vec>, - seat_mode_components: Vec>, - current_vt_components: Vec>, - seat_clients_components: Vec>, - active_client_components: Vec>, - next_client_components: Vec>, -} - -impl World { - pub fn new() -> Self { - Self::default() - } - - fn entity(&mut self) -> Entity { - if let Some(entity) = self.free_entities.pop() { - return entity; - } - - let entity = Entity(self.next_entity); - self.next_entity += 1; - entity - } - - #[allow(clippy::too_many_arguments)] - pub fn insert_session( - &mut self, - session_id: session::SessionId, - uid: u32, - username: String, - vt: u32, - seat: Option, - seat_entity: Option, - timestamp: time::SystemTime, - leader_id: i32, - is_local: bool, - remote_host: String, - objects: Vec, - active_state: session_core_v1::ActiveState, - ) -> Entity { - let entity = self.entity(); - self.insert(entity, Session(session_id)); - self.insert(entity, Uid(uid)); - self.insert(entity, Username(username)); - self.insert(entity, Vt(vt)); - if let Some(seat) = seat { - self.insert(entity, SeatName(seat)); - } - if let Some(seat_entity) = seat_entity { - self.insert(entity, SeatEntity(seat_entity)); - } - self.insert(entity, Timestamp(timestamp)); - self.insert(entity, LeaderId(leader_id)); - self.insert(entity, IsLocal(is_local)); - self.insert(entity, RemoteHost(remote_host)); - self.insert(entity, SessionObjects(objects)); - self.insert(entity, ActiveState(active_state)); - entity - } - - pub fn insert_client(&mut self, object: seat_v1::seat::Seat) -> Entity { - let entity = self.entity(); - self.insert(entity, SeatObject(object)); - self.insert(entity, Devices(Vec::new())); - self.insert(entity, SeatState(seat::SeatState::New)); - entity - } - - pub fn insert_seat(&mut self, name: String, mode: SeatKind, current_vt: u32) -> Entity { - let entity = self.entity(); - self.insert(entity, SeatName(name)); - self.insert(entity, SeatMode(mode)); - self.insert(entity, CurrentVt(current_vt)); - self.insert(entity, SeatClients(Vec::new())); - entity +#[allow(clippy::too_many_arguments)] +pub fn insert_session( + world: &mut World, + session_id: session::SessionId, + uid: u32, + username: String, + vt: u32, + seat: Option, + seat_entity: Option, + timestamp: time::SystemTime, + leader_id: i32, + is_local: bool, + remote_host: String, + objects: Vec, + active_state: session_core_v1::ActiveState, +) -> Entity { + let mut cmd = world.spawn(( + Session(session_id), + Uid(uid), + Username(username), + Vt(vt), + Timestamp(timestamp), + LeaderId(leader_id), + IsLocal(is_local), + RemoteHost(remote_host), + SessionObjects(objects), + ActiveState(active_state), + )); + if let Some(name) = seat { + cmd.insert(SeatName(name)); } - - pub fn insert_device( - &mut self, - object: seat_v1::device::Device, - path: path::PathBuf, - kind: device::DeviceKind, - id: u32, - active: bool, - fd: fd::OwnedFd, - ) -> Entity { - let entity = self.entity(); - self.insert(entity, DeviceObjects(vec![object])); - self.insert(entity, DevicePath(path)); - self.insert(entity, DeviceRefCount(1)); - self.insert(entity, DeviceKind(kind)); - self.insert(entity, DeviceId(id)); - self.insert(entity, DeviceActive(active)); - self.insert(entity, DeviceFd(fd)); - entity - } - - pub fn insert(&mut self, entity: Entity, component: C) - where - C: Component, - { - let storage = C::storage(self); - if storage.len() <= entity.0 { - storage.reserve(entity.0 + 1 - storage.len()); - storage.resize_with(entity.0 + 1, || None); - } - storage[entity.0] = Some(component); - } - - pub fn get(&self, entity: Entity) -> Option<&C> - where - C: Component, - { - C::storage_ref(self).get(entity.0)?.as_ref() - } - - pub fn get_mut(&mut self, entity: Entity) -> Option<&mut C> - where - C: Component, - { - C::storage(self).get_mut(entity.0)?.as_mut() + if let Some(entity) = seat_entity { + cmd.insert(SeatEntity(entity)); } + cmd.id() +} - pub fn remove(&mut self, entity: Entity) -> Option - where - C: Component, - { - C::storage(self).get_mut(entity.0)?.take() - } +pub fn insert_client(world: &mut World, object: seat_v1::seat::Seat) -> Entity { + world + .spawn(( + SeatObject(object), + Devices(Vec::new()), + SeatState(seat::SeatState::New), + )) + .id() +} - pub fn remove_entity(&mut self, entity: Entity) { - clear_component(&mut self.uid_components, entity); - clear_component(&mut self.username_components, entity); - clear_component(&mut self.vt_components, entity); - clear_component(&mut self.seat_name_components, entity); - clear_component(&mut self.seat_entity_components, entity); - clear_component(&mut self.timestamp_components, entity); - clear_component(&mut self.leader_id_components, entity); - clear_component(&mut self.is_local_components, entity); - clear_component(&mut self.remote_host_components, entity); - clear_component(&mut self.session_objects_components, entity); - clear_component(&mut self.active_state_components, entity); - clear_component(&mut self.session_components, entity); - clear_component(&mut self.seat_object_components, entity); - clear_component(&mut self.devices_components, entity); - clear_component(&mut self.device_objects_components, entity); - clear_component(&mut self.device_path_components, entity); - clear_component(&mut self.device_ref_count_components, entity); - clear_component(&mut self.device_kind_components, entity); - clear_component(&mut self.device_id_components, entity); - clear_component(&mut self.device_active_components, entity); - clear_component(&mut self.device_fd_components, entity); - clear_component(&mut self.seat_state_components, entity); - clear_component(&mut self.seat_mode_components, entity); - clear_component(&mut self.current_vt_components, entity); - clear_component(&mut self.seat_clients_components, entity); - clear_component(&mut self.active_client_components, entity); - clear_component(&mut self.next_client_components, entity); - self.free_entities.push(entity); - } +pub fn insert_seat(world: &mut World, name: String, mode: SeatKind, current_vt: u32) -> Entity { + world + .spawn(( + SeatName(name), + SeatMode(mode), + CurrentVt(current_vt), + SeatClients(Vec::new()), + )) + .id() } -fn clear_component(storage: &mut [Option], entity: Entity) { - if let Some(component) = storage.get_mut(entity.0) { - *component = None; - } +pub fn insert_device( + world: &mut World, + object: seat_v1::device::Device, + path: path::PathBuf, + kind: device::DeviceKind, + id: u32, + active: bool, + fd: fd::OwnedFd, +) -> Entity { + world + .spawn(( + DeviceObjects(vec![object]), + DevicePath(path), + DeviceRefCount(1), + DeviceKind(kind), + DeviceId(id), + DeviceActive(active), + DeviceFd(fd), + )) + .id() } diff --git a/daemon/src/main.rs b/daemon/src/main.rs index bca0c1f..a6b620d 100644 --- a/daemon/src/main.rs +++ b/daemon/src/main.rs @@ -110,7 +110,7 @@ impl Sessiond { .is_some_and(|session| session.0 == session_id) })?; let entity = self.session_entities.remove(idx); - self.world.remove_entity(entity); + self.world.despawn(entity); #[cfg(feature = "consolekit")] self.consolekit.remove_session(session_id); Some(entity) @@ -226,7 +226,8 @@ impl hyprwire::Dispatch for Sessiond { active_state = session_core_v1::ActiveState::Active; } - let session_entity = self.world.insert_session( + let session_entity = ecs::insert_session( + &mut self.world, session_id, uid, username, @@ -268,7 +269,7 @@ impl hyprwire::Dispatch for Sessiond { .map_or("", |username| username.0.as_str()); log::info!(session_id = session_id.as_raw(), uid, username; "session destroyed"); - if let Some(active_state) = self.world.get_mut::(entity) { + if let Some(mut active_state) = self.world.get_mut::(entity) { active_state.0 = session_core_v1::ActiveState::Closing; } #[cfg(feature = "consolekit")] @@ -623,7 +624,8 @@ fn main() -> anyhow::Result<()> { world: ecs::World::new(), }; - let seat_entity = sessiond.world.insert_seat( + let seat_entity = ecs::insert_seat( + &mut sessiond.world, "seat0".to_string(), if vtbound { ecs::SeatKind::VtBound diff --git a/daemon/src/seat.rs b/daemon/src/seat.rs index 1c6ba98..e3537ca 100644 --- a/daemon/src/seat.rs +++ b/daemon/src/seat.rs @@ -125,14 +125,16 @@ pub fn add_client( vt_open(session_id.as_raw())?; } - world.insert(client_entity, ecs::SeatName(seat_name.clone())); - world.insert(client_entity, ecs::SeatEntity(seat_entity)); - world.insert(client_entity, ecs::Session(session_id)); - world.insert(client_entity, ecs::SeatState(SeatState::Enabled)); - if let Some(clients) = world.get_mut::(seat_entity) { + world.entity_mut(client_entity).insert(( + ecs::SeatName(seat_name.clone()), + ecs::SeatEntity(seat_entity), + ecs::Session(session_id), + ecs::SeatState(SeatState::Enabled), + )); + if let Some(mut clients) = world.get_mut::(seat_entity) { clients.0.push(client_entity); } - world.insert(seat_entity, ecs::ActiveClient(client_entity)); + world.entity_mut(seat_entity).insert(ecs::ActiveClient(client_entity)); if let Some(object) = world.get::(client_entity) { object.0.send_enabled(); @@ -192,8 +194,8 @@ pub fn open_client( if let Some(object) = world.get::(client_entity) { object.0.send_enabled(); } - world.insert(client_entity, ecs::SeatState(SeatState::Enabled)); - world.insert(seat_entity, ecs::ActiveClient(client_entity)); + world.entity_mut(client_entity).insert(ecs::SeatState(SeatState::Enabled)); + world.entity_mut(seat_entity).insert(ecs::ActiveClient(client_entity)); log::info!("Opened client {} on {}", session_id.as_raw(), seat_name); Ok(()) @@ -232,7 +234,7 @@ pub fn disable_client( } Ok(device::DeviceKind::Evdev | device::DeviceKind::Hidraw) => { device::send_revoked(world, device_entity); - world.remove_entity(device_entity); + world.despawn(device_entity); } Err(err) => { log::error!("Could not determine device kind: {err}"); @@ -240,12 +242,12 @@ pub fn disable_client( } } } - if let Some(devices) = world.get_mut::(client_entity) { + if let Some(mut devices) = world.get_mut::(client_entity) { devices.0 = retained_devices; } } - world.insert(client_entity, ecs::SeatState(SeatState::PendingDisabled)); + world.entity_mut(client_entity).insert(ecs::SeatState(SeatState::PendingDisabled)); if let Some(object) = world.get::(client_entity) { object.0.send_disabled(); } @@ -266,14 +268,14 @@ pub fn ack_disable_client( let session_id = client_session_id(world, client_entity)?; let seat_name = seat_name(world, seat_entity)?; - world.insert(client_entity, ecs::SeatState(SeatState::Disabled)); + world.entity_mut(client_entity).insert(ecs::SeatState(SeatState::Disabled)); log::info!("Disabled client {} on {}", session_id.as_raw(), seat_name); if !is_active_client(world, seat_entity, client_entity) { return Ok(()); } - let _ = world.remove::(seat_entity); + world.entity_mut(seat_entity).remove::(); let _ = activate(world, seat_entity); Ok(()) @@ -340,7 +342,7 @@ pub fn set_next_session( session.as_raw(), seat_name ); - world.insert(seat_entity, ecs::NextClient(target)); + world.entity_mut(seat_entity).insert(ecs::NextClient(target)); disable_client(world, seat_entity, client_entity)?; Ok(()) @@ -355,7 +357,7 @@ pub fn remove_client( .get::(seat_entity) .is_some_and(|next_client| next_client.0 == client_entity) { - let _ = world.remove::(seat_entity); + world.entity_mut(seat_entity).remove::(); } let session_id = world @@ -366,7 +368,7 @@ pub fn remove_client( .map_or(SeatState::Closed, |state| state.0); let seat_name = seat_name(world, seat_entity)?; - if let Some(clients) = world.get_mut::(seat_entity) { + if let Some(mut clients) = world.get_mut::(seat_entity) { clients.0.retain(|client| *client != client_entity); } @@ -376,16 +378,16 @@ pub fn remove_client( let path = device::path_display(world, device_entity); log::error!("Could not deactivate {path}: {err}"); } - world.remove_entity(device_entity); + world.despawn(device_entity); } } - if let Some(devices) = world.get_mut::(client_entity) { + if let Some(mut devices) = world.get_mut::(client_entity) { devices.0.clear(); } let was_current = is_active_client(world, seat_entity, client_entity); if was_current { - let _ = world.remove::(seat_entity); + world.entity_mut(seat_entity).remove::(); let _ = activate(world, seat_entity); } @@ -406,11 +408,7 @@ pub fn remove_client( } } - world.insert(client_entity, ecs::SeatState(SeatState::Closed)); - let _ = world.remove::(client_entity); - let _ = world.remove::(client_entity); - let _ = world.remove::(client_entity); - world.remove_entity(client_entity); + world.despawn(client_entity); log::info!( "Removed client {} from {}", @@ -529,7 +527,8 @@ pub fn open_device( } }; - let device_entity = world.insert_device( + let device_entity = ecs::insert_device( + world, device, sanitized_path, kind, @@ -553,14 +552,14 @@ pub fn open_device( "could not activate device", ); } - world.remove_entity(device_entity); + world.despawn(device_entity); return; } if let Err(err) = device::send_opened(world, device_entity) { log::error!("Could not send opened device event: {err}"); } - if let Some(devices) = world.get_mut::(client_entity) { + if let Some(mut devices) = world.get_mut::(client_entity) { devices.0.push(device_entity); } } @@ -572,7 +571,7 @@ pub fn refresh_current_vts(world: &mut ecs::World, seat_entities: &[ecs::Entity] } match current_vt() { - Ok(vt) => world.insert(seat_entity, ecs::CurrentVt(vt)), + Ok(vt) => { world.entity_mut(seat_entity).insert(ecs::CurrentVt(vt)); } Err(err) => log::error!("Could not query active VT: {err}"), } } @@ -674,7 +673,7 @@ fn activate(world: &mut ecs::World, seat_entity: ecs::Entity) -> anyhow::Result< } let seat_name = seat_name(world, seat_entity)?; - let next_client = if let Some(next_client) = world.remove::(seat_entity) { + let next_client = if let Some(next_client) = world.entity_mut(seat_entity).take::() { log::debug!("Activating next queued client on {seat_name}"); Some(next_client.0) } else { @@ -737,7 +736,7 @@ fn release_vt(world: &mut ecs::World, seat_entity: ecs::Entity) -> anyhow::Resul } terminal::Terminal::open(cur_vt)?.ack_release()?; - world.insert(seat_entity, ecs::CurrentVt(0)); + world.entity_mut(seat_entity).insert(ecs::CurrentVt(0)); Ok(Some(released_vt)) } @@ -746,7 +745,7 @@ fn activate_vt(world: &mut ecs::World, seat_entity: ecs::Entity) -> anyhow::Resu let acquired_vt = current_vt()?; log::debug!("Activating VT"); terminal::Terminal::open(acquired_vt)?.ack_acquire()?; - world.insert(seat_entity, ecs::CurrentVt(acquired_vt)); + world.entity_mut(seat_entity).insert(ecs::CurrentVt(acquired_vt)); if world.get::(seat_entity).is_none() { activate(world, seat_entity)?; @@ -899,11 +898,11 @@ impl hyprwire::Dispatch for crate::Sessiond { return; }; - let client_entity = self.world.insert_client(seat.clone()); + let client_entity = ecs::insert_client(&mut self.world, seat.clone()); if let Err(err) = add_client(&mut self.world, seat_entity, client_entity) { log::error!("Could not add client to seat: {err}"); seat.send_disabled(); - self.world.remove_entity(client_entity); + self.world.despawn(client_entity); return; } @@ -930,8 +929,10 @@ impl hyprwire::Dispatch for crate::Sessiond { .is_none_or(|seat| seat.0 != seat_entity) { log::info!(session_id = session_id.as_raw(), seat = seat_name.as_str(); "session seat changed"); - self.world.insert(entity, ecs::SeatName(seat_name.clone())); - self.world.insert(entity, ecs::SeatEntity(seat_entity)); + self.world.entity_mut(entity).insert(( + ecs::SeatName(seat_name.clone()), + ecs::SeatEntity(seat_entity), + )); } if let Some(objects) = self.world.get::(entity) { for object in &objects.0 { diff --git a/daemon/src/session.rs b/daemon/src/session.rs index cc1b865..ee34432 100644 --- a/daemon/src/session.rs +++ b/daemon/src/session.rs @@ -87,7 +87,7 @@ impl hyprwire::Dispatch for crate::Ses }; if matches!(event, session_core_session::Event::Destroy) { - if let Some(objects) = self.world.get_mut::(entity) { + if let Some(mut objects) = self.world.get_mut::(entity) { objects.0.retain(|session_object| session_object != object); } return; @@ -206,7 +206,7 @@ pub fn add_session_object( } object.send_done(); - if let Some(objects) = world.get_mut::(entity) { + if let Some(mut objects) = world.get_mut::(entity) { objects.0.push(object); } } @@ -219,7 +219,7 @@ pub fn set_session_state( ) { let vt = world.get::(entity).map_or(0, |vt| vt.0); log::info!(session_id = session_id.as_raw(), vt; "session state changed"); - if let Some(active_state) = world.get_mut::(entity) { + if let Some(mut active_state) = world.get_mut::(entity) { active_state.0 = state; } if let Some(objects) = world.get::(entity) { @@ -246,7 +246,7 @@ pub fn set_state( ) { let vt = world.get::(entity).map_or(0, |vt| vt.0); log::info!(session_id = session_id.as_raw(), vt; "session state changed"); - if let Some(active_state) = world.get_mut::(entity) { + if let Some(mut active_state) = world.get_mut::(entity) { active_state.0 = state; } if let Some(objects) = world.get::(entity) {