session and seat management daemon
0

Configure Feed

Select the types of activity you want to include in your feed.

chore(deps): disable bevy_ecs default features to drop reflect and async_executor

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

authored by

parzivale
Claude Sonnet 4.6
and committed by
Tangled
(Jul 8, 2026, 4:02 PM +0300) ccafbf8f 326a19d8

+485 -290
+322 -1
Cargo.lock
··· 68 68 checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" 69 69 70 70 [[package]] 71 + name = "arrayvec" 72 + version = "0.7.8" 73 + source = "registry+https://github.com/rust-lang/crates.io-index" 74 + checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" 75 + 76 + [[package]] 71 77 name = "async-broadcast" 72 78 version = "0.7.2" 73 79 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 186 192 version = "4.7.1" 187 193 source = "registry+https://github.com/rust-lang/crates.io-index" 188 194 checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" 195 + dependencies = [ 196 + "portable-atomic", 197 + ] 189 198 190 199 [[package]] 191 200 name = "async-trait" ··· 203 212 version = "1.1.2" 204 213 source = "registry+https://github.com/rust-lang/crates.io-index" 205 214 checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 215 + dependencies = [ 216 + "portable-atomic", 217 + ] 206 218 207 219 [[package]] 208 220 name = "autocfg" ··· 211 223 checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" 212 224 213 225 [[package]] 226 + name = "bevy_ecs" 227 + version = "0.19.0" 228 + source = "registry+https://github.com/rust-lang/crates.io-index" 229 + checksum = "4654b9b3535fa7813d2878a50e1b5ad80a361dc1c913b96ded57667f65d70a01" 230 + dependencies = [ 231 + "arrayvec", 232 + "bevy_ecs_macros", 233 + "bevy_platform", 234 + "bevy_ptr", 235 + "bevy_tasks", 236 + "bevy_utils", 237 + "bitflags 2.13.0", 238 + "bumpalo", 239 + "concurrent-queue", 240 + "derive_more", 241 + "fixedbitset", 242 + "indexmap", 243 + "log", 244 + "nonmax", 245 + "slotmap", 246 + "smallvec", 247 + "thiserror", 248 + "variadics_please", 249 + ] 250 + 251 + [[package]] 252 + name = "bevy_ecs_macro_logic" 253 + version = "0.19.0" 254 + source = "registry+https://github.com/rust-lang/crates.io-index" 255 + checksum = "ee0b98a74141ce8dce4654c60020ebbaefab32646f42af6bbae55f282ae65ff7" 256 + dependencies = [ 257 + "bevy_macro_utils", 258 + "proc-macro2", 259 + "quote", 260 + "syn", 261 + ] 262 + 263 + [[package]] 264 + name = "bevy_ecs_macros" 265 + version = "0.19.0" 266 + source = "registry+https://github.com/rust-lang/crates.io-index" 267 + checksum = "4dc958a194d226d618404e0fea99a3c8b4146207a00a3ba07fa712bf71607240" 268 + dependencies = [ 269 + "bevy_ecs_macro_logic", 270 + "bevy_macro_utils", 271 + "proc-macro2", 272 + "quote", 273 + "syn", 274 + ] 275 + 276 + [[package]] 277 + name = "bevy_macro_utils" 278 + version = "0.19.0" 279 + source = "registry+https://github.com/rust-lang/crates.io-index" 280 + checksum = "746a19912c6dc1bbe79188778573e8a253d5832c696b2fcb95578c17b29ff7ba" 281 + dependencies = [ 282 + "proc-macro2", 283 + "quote", 284 + "syn", 285 + "toml_edit", 286 + ] 287 + 288 + [[package]] 289 + name = "bevy_platform" 290 + version = "0.19.0" 291 + source = "registry+https://github.com/rust-lang/crates.io-index" 292 + checksum = "3120670bb2308980f723477c9d82476fcda31f08be9b256c3f0acdee82a65094" 293 + dependencies = [ 294 + "foldhash", 295 + "futures-channel", 296 + "hashbrown 0.16.1", 297 + "portable-atomic", 298 + "portable-atomic-util", 299 + "serde", 300 + "spin", 301 + "windows-sys", 302 + ] 303 + 304 + [[package]] 305 + name = "bevy_ptr" 306 + version = "0.19.0" 307 + source = "registry+https://github.com/rust-lang/crates.io-index" 308 + checksum = "b511e89f7078fd21fdea77061a0ca3e737297c7011bb10c073e0aecb17c9fea6" 309 + 310 + [[package]] 311 + name = "bevy_tasks" 312 + version = "0.19.0" 313 + source = "registry+https://github.com/rust-lang/crates.io-index" 314 + checksum = "fa34e6b9b804851ec08a41c0346c859d82e2fa98c906d74b965ee61bbbb688e4" 315 + dependencies = [ 316 + "async-task", 317 + "atomic-waker", 318 + "bevy_platform", 319 + "crossbeam-queue", 320 + "derive_more", 321 + "futures-lite", 322 + "heapless", 323 + "web-task", 324 + ] 325 + 326 + [[package]] 327 + name = "bevy_utils" 328 + version = "0.19.0" 329 + source = "registry+https://github.com/rust-lang/crates.io-index" 330 + checksum = "3aceea6c7ffdd568f866d5ca4dfe50c33440c54f7bc230c13a9ba7ab0c91aed1" 331 + dependencies = [ 332 + "bevy_platform", 333 + "disqualified", 334 + "indexmap", 335 + ] 336 + 337 + [[package]] 214 338 name = "bitflags" 215 339 version = "1.3.2" 216 340 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 240 364 version = "3.20.3" 241 365 source = "registry+https://github.com/rust-lang/crates.io-index" 242 366 checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" 367 + 368 + [[package]] 369 + name = "byteorder" 370 + version = "1.5.0" 371 + source = "registry+https://github.com/rust-lang/crates.io-index" 372 + checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 243 373 244 374 [[package]] 245 375 name = "calloop" ··· 339 469 checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" 340 470 dependencies = [ 341 471 "crossbeam-utils", 472 + "portable-atomic", 473 + ] 474 + 475 + [[package]] 476 + name = "convert_case" 477 + version = "0.10.0" 478 + source = "registry+https://github.com/rust-lang/crates.io-index" 479 + checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" 480 + dependencies = [ 481 + "unicode-segmentation", 482 + ] 483 + 484 + [[package]] 485 + name = "crossbeam-queue" 486 + version = "0.3.13" 487 + source = "registry+https://github.com/rust-lang/crates.io-index" 488 + checksum = "803d13fb3b09d88be9f4dbc29062c66b19bf7170867ceb746d2a8689bf6c7a26" 489 + dependencies = [ 490 + "crossbeam-utils", 342 491 ] 343 492 344 493 [[package]] ··· 367 516 version = "0.1.0" 368 517 dependencies = [ 369 518 "anyhow", 519 + "bevy_ecs", 370 520 "calloop", 371 521 "clap", 372 522 "env_logger", ··· 410 560 ] 411 561 412 562 [[package]] 563 + name = "derive_more" 564 + version = "2.1.1" 565 + source = "registry+https://github.com/rust-lang/crates.io-index" 566 + checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" 567 + dependencies = [ 568 + "derive_more-impl", 569 + ] 570 + 571 + [[package]] 572 + name = "derive_more-impl" 573 + version = "2.1.1" 574 + source = "registry+https://github.com/rust-lang/crates.io-index" 575 + checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" 576 + dependencies = [ 577 + "convert_case", 578 + "proc-macro2", 579 + "quote", 580 + "rustc_version", 581 + "syn", 582 + "unicode-xid", 583 + ] 584 + 585 + [[package]] 586 + name = "disqualified" 587 + version = "1.0.0" 588 + source = "registry+https://github.com/rust-lang/crates.io-index" 589 + checksum = "c9c272297e804878a2a4b707cfcfc6d2328b5bb936944613b4fdf2b9269afdfd" 590 + 591 + [[package]] 413 592 name = "endi" 414 593 version = "1.1.1" 415 594 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 503 682 checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" 504 683 505 684 [[package]] 685 + name = "fixedbitset" 686 + version = "0.5.7" 687 + source = "registry+https://github.com/rust-lang/crates.io-index" 688 + checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" 689 + 690 + [[package]] 691 + name = "foldhash" 692 + version = "0.2.0" 693 + source = "registry+https://github.com/rust-lang/crates.io-index" 694 + checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" 695 + 696 + [[package]] 697 + name = "futures-channel" 698 + version = "0.3.32" 699 + source = "registry+https://github.com/rust-lang/crates.io-index" 700 + checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" 701 + dependencies = [ 702 + "futures-core", 703 + ] 704 + 705 + [[package]] 506 706 name = "futures-core" 507 707 version = "0.3.32" 508 708 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 557 757 ] 558 758 559 759 [[package]] 760 + name = "hash32" 761 + version = "0.3.1" 762 + source = "registry+https://github.com/rust-lang/crates.io-index" 763 + checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" 764 + dependencies = [ 765 + "byteorder", 766 + ] 767 + 768 + [[package]] 769 + name = "hashbrown" 770 + version = "0.16.1" 771 + source = "registry+https://github.com/rust-lang/crates.io-index" 772 + checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" 773 + dependencies = [ 774 + "equivalent", 775 + ] 776 + 777 + [[package]] 560 778 name = "hashbrown" 561 779 version = "0.17.1" 562 780 source = "registry+https://github.com/rust-lang/crates.io-index" 563 781 checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" 564 782 565 783 [[package]] 784 + name = "heapless" 785 + version = "0.9.3" 786 + source = "registry+https://github.com/rust-lang/crates.io-index" 787 + checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4" 788 + dependencies = [ 789 + "hash32", 790 + "portable-atomic", 791 + "stable_deref_trait", 792 + ] 793 + 794 + [[package]] 566 795 name = "heck" 567 796 version = "0.5.0" 568 797 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 619 848 checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" 620 849 dependencies = [ 621 850 "equivalent", 622 - "hashbrown", 851 + "hashbrown 0.17.1", 623 852 ] 624 853 625 854 [[package]] ··· 714 943 "cfg_aliases", 715 944 "libc", 716 945 ] 946 + 947 + [[package]] 948 + name = "nonmax" 949 + version = "0.5.5" 950 + source = "registry+https://github.com/rust-lang/crates.io-index" 951 + checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" 717 952 718 953 [[package]] 719 954 name = "once_cell" ··· 896 1131 checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" 897 1132 898 1133 [[package]] 1134 + name = "rustc_version" 1135 + version = "0.4.1" 1136 + source = "registry+https://github.com/rust-lang/crates.io-index" 1137 + checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" 1138 + dependencies = [ 1139 + "semver", 1140 + ] 1141 + 1142 + [[package]] 899 1143 name = "rustix" 900 1144 version = "1.1.4" 901 1145 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 913 1157 version = "1.0.22" 914 1158 source = "registry+https://github.com/rust-lang/crates.io-index" 915 1159 checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" 1160 + 1161 + [[package]] 1162 + name = "semver" 1163 + version = "1.0.28" 1164 + source = "registry+https://github.com/rust-lang/crates.io-index" 1165 + checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" 916 1166 917 1167 [[package]] 918 1168 name = "serde" ··· 983 1233 version = "0.4.12" 984 1234 source = "registry+https://github.com/rust-lang/crates.io-index" 985 1235 checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" 1236 + 1237 + [[package]] 1238 + name = "slotmap" 1239 + version = "1.1.1" 1240 + source = "registry+https://github.com/rust-lang/crates.io-index" 1241 + checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" 1242 + dependencies = [ 1243 + "version_check", 1244 + ] 1245 + 1246 + [[package]] 1247 + name = "smallvec" 1248 + version = "1.15.2" 1249 + source = "registry+https://github.com/rust-lang/crates.io-index" 1250 + checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" 1251 + 1252 + [[package]] 1253 + name = "spin" 1254 + version = "0.10.0" 1255 + source = "registry+https://github.com/rust-lang/crates.io-index" 1256 + checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" 1257 + dependencies = [ 1258 + "portable-atomic", 1259 + ] 1260 + 1261 + [[package]] 1262 + name = "stable_deref_trait" 1263 + version = "1.2.1" 1264 + source = "registry+https://github.com/rust-lang/crates.io-index" 1265 + checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" 986 1266 987 1267 [[package]] 988 1268 name = "strsim" ··· 1114 1394 checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" 1115 1395 1116 1396 [[package]] 1397 + name = "unicode-segmentation" 1398 + version = "1.13.3" 1399 + source = "registry+https://github.com/rust-lang/crates.io-index" 1400 + checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" 1401 + 1402 + [[package]] 1403 + name = "unicode-xid" 1404 + version = "0.2.6" 1405 + source = "registry+https://github.com/rust-lang/crates.io-index" 1406 + checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" 1407 + 1408 + [[package]] 1117 1409 name = "users" 1118 1410 version = "0.11.0" 1119 1411 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1141 1433 ] 1142 1434 1143 1435 [[package]] 1436 + name = "variadics_please" 1437 + version = "1.1.0" 1438 + source = "registry+https://github.com/rust-lang/crates.io-index" 1439 + checksum = "41b6d82be61465f97d42bd1d15bf20f3b0a3a0905018f38f9d6f6962055b0b5c" 1440 + dependencies = [ 1441 + "proc-macro2", 1442 + "quote", 1443 + "syn", 1444 + ] 1445 + 1446 + [[package]] 1447 + name = "version_check" 1448 + version = "0.9.5" 1449 + source = "registry+https://github.com/rust-lang/crates.io-index" 1450 + checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 1451 + 1452 + [[package]] 1144 1453 name = "wasm-bindgen" 1145 1454 version = "0.2.126" 1146 1455 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1183 1492 checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" 1184 1493 dependencies = [ 1185 1494 "unicode-ident", 1495 + ] 1496 + 1497 + [[package]] 1498 + name = "web-task" 1499 + version = "1.1.3" 1500 + source = "registry+https://github.com/rust-lang/crates.io-index" 1501 + checksum = "1cdc136a53ccd64a1211f107ccc34404769fbcc0f165f1afa065f5d88ab93538" 1502 + dependencies = [ 1503 + "async-task", 1504 + "cfg-if", 1505 + "js-sys", 1506 + "wasm-bindgen", 1186 1507 ] 1187 1508 1188 1509 [[package]]
+1
daemon/Cargo.toml
··· 22 22 rustix = { version = "1.1.4", features = ["fs", "net", "process", "system"] } 23 23 users = "0.11.0" 24 24 zbus = { version = "5.16.0", optional = true } 25 + bevy_ecs = { version = "0.19.0", default-features = false } 25 26 26 27 [build-dependencies] 27 28 hyprwire-scanner = "0.4.3"
+9 -9
daemon/src/device.rs
··· 71 71 ); 72 72 } 73 73 74 - if let Some(devices) = world.get_mut::<ecs::Devices>(client_entity) { 74 + if let Some(mut devices) = world.get_mut::<ecs::Devices>(client_entity) { 75 75 devices.0.remove(idx); 76 76 } 77 - world.remove_entity(device_entity); 77 + world.despawn(device_entity); 78 78 79 79 Ok(()) 80 80 } ··· 151 151 .ok_or_else(|| anyhow::anyhow!("device has no fd"))?; 152 152 drm_set_master(&fd.0) 153 153 .map_err(|err| anyhow::anyhow!("Could not make device fd drm master: {err}"))?; 154 - world.insert(entity, ecs::DeviceActive(true)); 154 + world.entity_mut(entity).insert(ecs::DeviceActive(true)); 155 155 } 156 156 DeviceKind::Evdev | DeviceKind::Hidraw => { 157 157 return Err(anyhow::anyhow!("device type cannot be activated")); 158 158 } 159 159 DeviceKind::Wscons => { 160 - world.insert(entity, ecs::DeviceActive(true)); 160 + world.entity_mut(entity).insert(ecs::DeviceActive(true)); 161 161 } 162 162 } 163 163 ··· 204 204 DeviceKind::Wscons => {} 205 205 } 206 206 207 - world.insert(entity, ecs::DeviceActive(false)); 207 + world.entity_mut(entity).insert(ecs::DeviceActive(false)); 208 208 Ok(()) 209 209 } 210 210 ··· 215 215 } 216 216 217 217 pub fn add_object(world: &mut ecs::World, entity: ecs::Entity, object: device::Device) { 218 - if let Some(ref_count) = world.get_mut::<ecs::DeviceRefCount>(entity) { 218 + if let Some(mut ref_count) = world.get_mut::<ecs::DeviceRefCount>(entity) { 219 219 ref_count.0 += 1; 220 220 } 221 - if let Some(objects) = world.get_mut::<ecs::DeviceObjects>(entity) { 221 + if let Some(mut objects) = world.get_mut::<ecs::DeviceObjects>(entity) { 222 222 objects.0.push(object); 223 223 } 224 224 } ··· 269 269 } 270 270 271 271 pub fn remove_object(world: &mut ecs::World, entity: ecs::Entity, object: &device::Device) { 272 - if let Some(objects) = world.get_mut::<ecs::DeviceObjects>(entity) { 272 + if let Some(mut objects) = world.get_mut::<ecs::DeviceObjects>(entity) { 273 273 objects.0.retain(|candidate| candidate != object); 274 274 } 275 275 } ··· 283 283 } 284 284 285 285 pub fn decrement_ref(world: &mut ecs::World, entity: ecs::Entity) -> usize { 286 - let Some(ref_count) = world.get_mut::<ecs::DeviceRefCount>(entity) else { 286 + let Some(mut ref_count) = world.get_mut::<ecs::DeviceRefCount>(entity) else { 287 287 return 0; 288 288 }; 289 289 ref_count.0 = ref_count.0.saturating_sub(1);
+33 -50
daemon/src/ecs/components.rs
··· 1 1 use crate::{device, seat, seat_v1, session, session_core_session, session_core_v1}; 2 + use bevy_ecs::prelude::*; 2 3 use std::os::fd; 3 4 use std::{path, time}; 4 5 5 - pub trait Component: Sized { 6 - fn storage(world: &mut super::World) -> &mut Vec<Option<Self>>; 7 - fn storage_ref(world: &super::World) -> &Vec<Option<Self>>; 8 - } 9 - 10 - macro_rules! component { 11 - ($name:ident, $field:ident) => { 12 - impl Component for $name { 13 - fn storage(world: &mut super::World) -> &mut Vec<Option<Self>> { 14 - &mut world.$field 15 - } 16 - fn storage_ref(world: &super::World) -> &Vec<Option<Self>> { 17 - &world.$field 18 - } 19 - } 20 - }; 21 - } 22 - 6 + #[derive(Component)] 23 7 pub struct Uid(pub u32); 24 - component!(Uid, uid_components); 25 8 9 + #[derive(Component)] 26 10 pub struct Username(pub String); 27 - component!(Username, username_components); 28 11 12 + #[derive(Component)] 29 13 pub struct Vt(pub u32); 30 - component!(Vt, vt_components); 31 14 15 + #[derive(Component)] 32 16 pub struct SeatName(pub String); 33 - component!(SeatName, seat_name_components); 34 17 35 - pub struct SeatEntity(pub super::Entity); 36 - component!(SeatEntity, seat_entity_components); 18 + #[derive(Component)] 19 + pub struct SeatEntity(pub Entity); 37 20 21 + #[derive(Component)] 38 22 pub struct Timestamp(pub time::SystemTime); 39 - component!(Timestamp, timestamp_components); 40 23 24 + #[derive(Component)] 41 25 pub struct LeaderId(pub i32); 42 - component!(LeaderId, leader_id_components); 43 26 27 + #[derive(Component)] 44 28 pub struct IsLocal(pub bool); 45 - component!(IsLocal, is_local_components); 46 29 30 + #[derive(Component)] 47 31 pub struct RemoteHost(pub String); 48 - component!(RemoteHost, remote_host_components); 49 32 33 + #[derive(Component)] 50 34 pub struct SessionObjects(pub Vec<session_core_session::SessionCoreSession>); 51 - component!(SessionObjects, session_objects_components); 52 35 36 + #[derive(Component)] 53 37 pub struct ActiveState(pub session_core_v1::ActiveState); 54 - component!(ActiveState, active_state_components); 55 38 39 + #[derive(Component)] 56 40 pub struct Session(pub session::SessionId); 57 - component!(Session, session_components); 58 41 42 + #[derive(Component)] 59 43 pub struct SeatObject(pub seat_v1::seat::Seat); 60 - component!(SeatObject, seat_object_components); 61 44 62 - pub struct Devices(pub Vec<super::Entity>); 63 - component!(Devices, devices_components); 45 + #[derive(Component)] 46 + pub struct Devices(pub Vec<Entity>); 64 47 48 + #[derive(Component)] 65 49 pub struct DeviceObjects(pub Vec<seat_v1::device::Device>); 66 - component!(DeviceObjects, device_objects_components); 67 50 51 + #[derive(Component)] 68 52 pub struct DevicePath(pub path::PathBuf); 69 - component!(DevicePath, device_path_components); 70 53 54 + #[derive(Component)] 71 55 pub struct DeviceRefCount(pub usize); 72 - component!(DeviceRefCount, device_ref_count_components); 73 56 57 + #[derive(Component)] 74 58 pub struct DeviceKind(pub device::DeviceKind); 75 - component!(DeviceKind, device_kind_components); 76 59 60 + #[derive(Component)] 77 61 pub struct DeviceId(pub u32); 78 - component!(DeviceId, device_id_components); 79 62 63 + #[derive(Component)] 80 64 pub struct DeviceActive(pub bool); 81 - component!(DeviceActive, device_active_components); 82 65 66 + #[derive(Component)] 83 67 pub struct DeviceFd(pub fd::OwnedFd); 84 - component!(DeviceFd, device_fd_components); 85 68 69 + #[derive(Component)] 86 70 pub struct SeatState(pub seat::SeatState); 87 - component!(SeatState, seat_state_components); 88 71 89 72 #[derive(Clone, Copy, PartialEq, Eq)] 90 73 pub enum SeatKind { ··· 92 75 NonVtBound, 93 76 } 94 77 78 + #[derive(Component)] 95 79 pub struct SeatMode(pub SeatKind); 96 - component!(SeatMode, seat_mode_components); 97 80 81 + #[derive(Component)] 98 82 pub struct CurrentVt(pub u32); 99 - component!(CurrentVt, current_vt_components); 100 83 101 - pub struct SeatClients(pub Vec<super::Entity>); 102 - component!(SeatClients, seat_clients_components); 84 + #[derive(Component)] 85 + pub struct SeatClients(pub Vec<Entity>); 103 86 104 - pub struct ActiveClient(pub super::Entity); 105 - component!(ActiveClient, active_client_components); 87 + #[derive(Component)] 88 + pub struct ActiveClient(pub Entity); 106 89 107 - pub struct NextClient(pub super::Entity); 108 - component!(NextClient, next_client_components); 90 + #[derive(Component)] 91 + pub struct NextClient(pub Entity);
+74 -187
daemon/src/ecs/mod.rs
··· 2 2 3 3 use crate::session; 4 4 use crate::{device, seat, seat_v1, session_core_session, session_core_v1}; 5 + pub use bevy_ecs::entity::Entity; 6 + pub use bevy_ecs::world::World; 5 7 pub use components::*; 6 8 use std::os::fd; 7 9 use std::path; 8 10 use std::time; 9 11 10 - #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] 11 - pub struct Entity(usize); 12 - 13 - #[derive(Default)] 14 - pub struct World { 15 - next_entity: usize, 16 - free_entities: Vec<Entity>, 17 - uid_components: Vec<Option<Uid>>, 18 - username_components: Vec<Option<Username>>, 19 - vt_components: Vec<Option<Vt>>, 20 - seat_name_components: Vec<Option<SeatName>>, 21 - seat_entity_components: Vec<Option<SeatEntity>>, 22 - timestamp_components: Vec<Option<Timestamp>>, 23 - leader_id_components: Vec<Option<LeaderId>>, 24 - is_local_components: Vec<Option<IsLocal>>, 25 - remote_host_components: Vec<Option<RemoteHost>>, 26 - session_objects_components: Vec<Option<SessionObjects>>, 27 - active_state_components: Vec<Option<ActiveState>>, 28 - session_components: Vec<Option<Session>>, 29 - seat_object_components: Vec<Option<SeatObject>>, 30 - devices_components: Vec<Option<Devices>>, 31 - device_objects_components: Vec<Option<DeviceObjects>>, 32 - device_path_components: Vec<Option<DevicePath>>, 33 - device_ref_count_components: Vec<Option<DeviceRefCount>>, 34 - device_kind_components: Vec<Option<DeviceKind>>, 35 - device_id_components: Vec<Option<DeviceId>>, 36 - device_active_components: Vec<Option<DeviceActive>>, 37 - device_fd_components: Vec<Option<DeviceFd>>, 38 - seat_state_components: Vec<Option<SeatState>>, 39 - seat_mode_components: Vec<Option<SeatMode>>, 40 - current_vt_components: Vec<Option<CurrentVt>>, 41 - seat_clients_components: Vec<Option<SeatClients>>, 42 - active_client_components: Vec<Option<ActiveClient>>, 43 - next_client_components: Vec<Option<NextClient>>, 44 - } 45 - 46 - impl World { 47 - pub fn new() -> Self { 48 - Self::default() 12 + #[allow(clippy::too_many_arguments)] 13 + pub fn insert_session( 14 + world: &mut World, 15 + session_id: session::SessionId, 16 + uid: u32, 17 + username: String, 18 + vt: u32, 19 + seat: Option<String>, 20 + seat_entity: Option<Entity>, 21 + timestamp: time::SystemTime, 22 + leader_id: i32, 23 + is_local: bool, 24 + remote_host: String, 25 + objects: Vec<session_core_session::SessionCoreSession>, 26 + active_state: session_core_v1::ActiveState, 27 + ) -> Entity { 28 + let mut cmd = world.spawn(( 29 + Session(session_id), 30 + Uid(uid), 31 + Username(username), 32 + Vt(vt), 33 + Timestamp(timestamp), 34 + LeaderId(leader_id), 35 + IsLocal(is_local), 36 + RemoteHost(remote_host), 37 + SessionObjects(objects), 38 + ActiveState(active_state), 39 + )); 40 + if let Some(name) = seat { 41 + cmd.insert(SeatName(name)); 49 42 } 50 - 51 - fn entity(&mut self) -> Entity { 52 - if let Some(entity) = self.free_entities.pop() { 53 - return entity; 54 - } 55 - 56 - let entity = Entity(self.next_entity); 57 - self.next_entity += 1; 58 - entity 43 + if let Some(entity) = seat_entity { 44 + cmd.insert(SeatEntity(entity)); 59 45 } 46 + cmd.id() 47 + } 60 48 61 - #[allow(clippy::too_many_arguments)] 62 - pub fn insert_session( 63 - &mut self, 64 - session_id: session::SessionId, 65 - uid: u32, 66 - username: String, 67 - vt: u32, 68 - seat: Option<String>, 69 - seat_entity: Option<Entity>, 70 - timestamp: time::SystemTime, 71 - leader_id: i32, 72 - is_local: bool, 73 - remote_host: String, 74 - objects: Vec<session_core_session::SessionCoreSession>, 75 - active_state: session_core_v1::ActiveState, 76 - ) -> Entity { 77 - let entity = self.entity(); 78 - self.insert(entity, Session(session_id)); 79 - self.insert(entity, Uid(uid)); 80 - self.insert(entity, Username(username)); 81 - self.insert(entity, Vt(vt)); 82 - if let Some(seat) = seat { 83 - self.insert(entity, SeatName(seat)); 84 - } 85 - if let Some(seat_entity) = seat_entity { 86 - self.insert(entity, SeatEntity(seat_entity)); 87 - } 88 - self.insert(entity, Timestamp(timestamp)); 89 - self.insert(entity, LeaderId(leader_id)); 90 - self.insert(entity, IsLocal(is_local)); 91 - self.insert(entity, RemoteHost(remote_host)); 92 - self.insert(entity, SessionObjects(objects)); 93 - self.insert(entity, ActiveState(active_state)); 94 - entity 95 - } 49 + pub fn insert_client(world: &mut World, object: seat_v1::seat::Seat) -> Entity { 50 + world 51 + .spawn(( 52 + SeatObject(object), 53 + Devices(Vec::new()), 54 + SeatState(seat::SeatState::New), 55 + )) 56 + .id() 57 + } 96 58 97 - pub fn insert_client(&mut self, object: seat_v1::seat::Seat) -> Entity { 98 - let entity = self.entity(); 99 - self.insert(entity, SeatObject(object)); 100 - self.insert(entity, Devices(Vec::new())); 101 - self.insert(entity, SeatState(seat::SeatState::New)); 102 - entity 103 - } 104 - 105 - pub fn insert_seat(&mut self, name: String, mode: SeatKind, current_vt: u32) -> Entity { 106 - let entity = self.entity(); 107 - self.insert(entity, SeatName(name)); 108 - self.insert(entity, SeatMode(mode)); 109 - self.insert(entity, CurrentVt(current_vt)); 110 - self.insert(entity, SeatClients(Vec::new())); 111 - entity 112 - } 113 - 114 - pub fn insert_device( 115 - &mut self, 116 - object: seat_v1::device::Device, 117 - path: path::PathBuf, 118 - kind: device::DeviceKind, 119 - id: u32, 120 - active: bool, 121 - fd: fd::OwnedFd, 122 - ) -> Entity { 123 - let entity = self.entity(); 124 - self.insert(entity, DeviceObjects(vec![object])); 125 - self.insert(entity, DevicePath(path)); 126 - self.insert(entity, DeviceRefCount(1)); 127 - self.insert(entity, DeviceKind(kind)); 128 - self.insert(entity, DeviceId(id)); 129 - self.insert(entity, DeviceActive(active)); 130 - self.insert(entity, DeviceFd(fd)); 131 - entity 132 - } 133 - 134 - pub fn insert<C>(&mut self, entity: Entity, component: C) 135 - where 136 - C: Component, 137 - { 138 - let storage = C::storage(self); 139 - if storage.len() <= entity.0 { 140 - storage.reserve(entity.0 + 1 - storage.len()); 141 - storage.resize_with(entity.0 + 1, || None); 142 - } 143 - storage[entity.0] = Some(component); 144 - } 145 - 146 - pub fn get<C>(&self, entity: Entity) -> Option<&C> 147 - where 148 - C: Component, 149 - { 150 - C::storage_ref(self).get(entity.0)?.as_ref() 151 - } 152 - 153 - pub fn get_mut<C>(&mut self, entity: Entity) -> Option<&mut C> 154 - where 155 - C: Component, 156 - { 157 - C::storage(self).get_mut(entity.0)?.as_mut() 158 - } 159 - 160 - pub fn remove<C>(&mut self, entity: Entity) -> Option<C> 161 - where 162 - C: Component, 163 - { 164 - C::storage(self).get_mut(entity.0)?.take() 165 - } 166 - 167 - pub fn remove_entity(&mut self, entity: Entity) { 168 - clear_component(&mut self.uid_components, entity); 169 - clear_component(&mut self.username_components, entity); 170 - clear_component(&mut self.vt_components, entity); 171 - clear_component(&mut self.seat_name_components, entity); 172 - clear_component(&mut self.seat_entity_components, entity); 173 - clear_component(&mut self.timestamp_components, entity); 174 - clear_component(&mut self.leader_id_components, entity); 175 - clear_component(&mut self.is_local_components, entity); 176 - clear_component(&mut self.remote_host_components, entity); 177 - clear_component(&mut self.session_objects_components, entity); 178 - clear_component(&mut self.active_state_components, entity); 179 - clear_component(&mut self.session_components, entity); 180 - clear_component(&mut self.seat_object_components, entity); 181 - clear_component(&mut self.devices_components, entity); 182 - clear_component(&mut self.device_objects_components, entity); 183 - clear_component(&mut self.device_path_components, entity); 184 - clear_component(&mut self.device_ref_count_components, entity); 185 - clear_component(&mut self.device_kind_components, entity); 186 - clear_component(&mut self.device_id_components, entity); 187 - clear_component(&mut self.device_active_components, entity); 188 - clear_component(&mut self.device_fd_components, entity); 189 - clear_component(&mut self.seat_state_components, entity); 190 - clear_component(&mut self.seat_mode_components, entity); 191 - clear_component(&mut self.current_vt_components, entity); 192 - clear_component(&mut self.seat_clients_components, entity); 193 - clear_component(&mut self.active_client_components, entity); 194 - clear_component(&mut self.next_client_components, entity); 195 - self.free_entities.push(entity); 196 - } 59 + pub fn insert_seat(world: &mut World, name: String, mode: SeatKind, current_vt: u32) -> Entity { 60 + world 61 + .spawn(( 62 + SeatName(name), 63 + SeatMode(mode), 64 + CurrentVt(current_vt), 65 + SeatClients(Vec::new()), 66 + )) 67 + .id() 197 68 } 198 69 199 - fn clear_component<C>(storage: &mut [Option<C>], entity: Entity) { 200 - if let Some(component) = storage.get_mut(entity.0) { 201 - *component = None; 202 - } 70 + pub fn insert_device( 71 + world: &mut World, 72 + object: seat_v1::device::Device, 73 + path: path::PathBuf, 74 + kind: device::DeviceKind, 75 + id: u32, 76 + active: bool, 77 + fd: fd::OwnedFd, 78 + ) -> Entity { 79 + world 80 + .spawn(( 81 + DeviceObjects(vec![object]), 82 + DevicePath(path), 83 + DeviceRefCount(1), 84 + DeviceKind(kind), 85 + DeviceId(id), 86 + DeviceActive(active), 87 + DeviceFd(fd), 88 + )) 89 + .id() 203 90 }
+6 -4
daemon/src/main.rs
··· 110 110 .is_some_and(|session| session.0 == session_id) 111 111 })?; 112 112 let entity = self.session_entities.remove(idx); 113 - self.world.remove_entity(entity); 113 + self.world.despawn(entity); 114 114 #[cfg(feature = "consolekit")] 115 115 self.consolekit.remove_session(session_id); 116 116 Some(entity) ··· 226 226 active_state = session_core_v1::ActiveState::Active; 227 227 } 228 228 229 - let session_entity = self.world.insert_session( 229 + let session_entity = ecs::insert_session( 230 + &mut self.world, 230 231 session_id, 231 232 uid, 232 233 username, ··· 268 269 .map_or("", |username| username.0.as_str()); 269 270 log::info!(session_id = session_id.as_raw(), uid, username; "session destroyed"); 270 271 271 - if let Some(active_state) = self.world.get_mut::<ecs::ActiveState>(entity) { 272 + if let Some(mut active_state) = self.world.get_mut::<ecs::ActiveState>(entity) { 272 273 active_state.0 = session_core_v1::ActiveState::Closing; 273 274 } 274 275 #[cfg(feature = "consolekit")] ··· 623 624 world: ecs::World::new(), 624 625 }; 625 626 626 - let seat_entity = sessiond.world.insert_seat( 627 + let seat_entity = ecs::insert_seat( 628 + &mut sessiond.world, 627 629 "seat0".to_string(), 628 630 if vtbound { 629 631 ecs::SeatKind::VtBound
+36 -35
daemon/src/seat.rs
··· 125 125 vt_open(session_id.as_raw())?; 126 126 } 127 127 128 - world.insert(client_entity, ecs::SeatName(seat_name.clone())); 129 - world.insert(client_entity, ecs::SeatEntity(seat_entity)); 130 - world.insert(client_entity, ecs::Session(session_id)); 131 - world.insert(client_entity, ecs::SeatState(SeatState::Enabled)); 132 - if let Some(clients) = world.get_mut::<ecs::SeatClients>(seat_entity) { 128 + world.entity_mut(client_entity).insert(( 129 + ecs::SeatName(seat_name.clone()), 130 + ecs::SeatEntity(seat_entity), 131 + ecs::Session(session_id), 132 + ecs::SeatState(SeatState::Enabled), 133 + )); 134 + if let Some(mut clients) = world.get_mut::<ecs::SeatClients>(seat_entity) { 133 135 clients.0.push(client_entity); 134 136 } 135 - world.insert(seat_entity, ecs::ActiveClient(client_entity)); 137 + world.entity_mut(seat_entity).insert(ecs::ActiveClient(client_entity)); 136 138 137 139 if let Some(object) = world.get::<ecs::SeatObject>(client_entity) { 138 140 object.0.send_enabled(); ··· 192 194 if let Some(object) = world.get::<ecs::SeatObject>(client_entity) { 193 195 object.0.send_enabled(); 194 196 } 195 - world.insert(client_entity, ecs::SeatState(SeatState::Enabled)); 196 - world.insert(seat_entity, ecs::ActiveClient(client_entity)); 197 + world.entity_mut(client_entity).insert(ecs::SeatState(SeatState::Enabled)); 198 + world.entity_mut(seat_entity).insert(ecs::ActiveClient(client_entity)); 197 199 log::info!("Opened client {} on {}", session_id.as_raw(), seat_name); 198 200 199 201 Ok(()) ··· 232 234 } 233 235 Ok(device::DeviceKind::Evdev | device::DeviceKind::Hidraw) => { 234 236 device::send_revoked(world, device_entity); 235 - world.remove_entity(device_entity); 237 + world.despawn(device_entity); 236 238 } 237 239 Err(err) => { 238 240 log::error!("Could not determine device kind: {err}"); ··· 240 242 } 241 243 } 242 244 } 243 - if let Some(devices) = world.get_mut::<ecs::Devices>(client_entity) { 245 + if let Some(mut devices) = world.get_mut::<ecs::Devices>(client_entity) { 244 246 devices.0 = retained_devices; 245 247 } 246 248 } 247 249 248 - world.insert(client_entity, ecs::SeatState(SeatState::PendingDisabled)); 250 + world.entity_mut(client_entity).insert(ecs::SeatState(SeatState::PendingDisabled)); 249 251 if let Some(object) = world.get::<ecs::SeatObject>(client_entity) { 250 252 object.0.send_disabled(); 251 253 } ··· 266 268 267 269 let session_id = client_session_id(world, client_entity)?; 268 270 let seat_name = seat_name(world, seat_entity)?; 269 - world.insert(client_entity, ecs::SeatState(SeatState::Disabled)); 271 + world.entity_mut(client_entity).insert(ecs::SeatState(SeatState::Disabled)); 270 272 log::info!("Disabled client {} on {}", session_id.as_raw(), seat_name); 271 273 272 274 if !is_active_client(world, seat_entity, client_entity) { 273 275 return Ok(()); 274 276 } 275 277 276 - let _ = world.remove::<ecs::ActiveClient>(seat_entity); 278 + world.entity_mut(seat_entity).remove::<ecs::ActiveClient>(); 277 279 let _ = activate(world, seat_entity); 278 280 279 281 Ok(()) ··· 340 342 session.as_raw(), 341 343 seat_name 342 344 ); 343 - world.insert(seat_entity, ecs::NextClient(target)); 345 + world.entity_mut(seat_entity).insert(ecs::NextClient(target)); 344 346 disable_client(world, seat_entity, client_entity)?; 345 347 346 348 Ok(()) ··· 355 357 .get::<ecs::NextClient>(seat_entity) 356 358 .is_some_and(|next_client| next_client.0 == client_entity) 357 359 { 358 - let _ = world.remove::<ecs::NextClient>(seat_entity); 360 + world.entity_mut(seat_entity).remove::<ecs::NextClient>(); 359 361 } 360 362 361 363 let session_id = world ··· 366 368 .map_or(SeatState::Closed, |state| state.0); 367 369 let seat_name = seat_name(world, seat_entity)?; 368 370 369 - if let Some(clients) = world.get_mut::<ecs::SeatClients>(seat_entity) { 371 + if let Some(mut clients) = world.get_mut::<ecs::SeatClients>(seat_entity) { 370 372 clients.0.retain(|client| *client != client_entity); 371 373 } 372 374 ··· 376 378 let path = device::path_display(world, device_entity); 377 379 log::error!("Could not deactivate {path}: {err}"); 378 380 } 379 - world.remove_entity(device_entity); 381 + world.despawn(device_entity); 380 382 } 381 383 } 382 - if let Some(devices) = world.get_mut::<ecs::Devices>(client_entity) { 384 + if let Some(mut devices) = world.get_mut::<ecs::Devices>(client_entity) { 383 385 devices.0.clear(); 384 386 } 385 387 386 388 let was_current = is_active_client(world, seat_entity, client_entity); 387 389 if was_current { 388 - let _ = world.remove::<ecs::ActiveClient>(seat_entity); 390 + world.entity_mut(seat_entity).remove::<ecs::ActiveClient>(); 389 391 let _ = activate(world, seat_entity); 390 392 } 391 393 ··· 406 408 } 407 409 } 408 410 409 - world.insert(client_entity, ecs::SeatState(SeatState::Closed)); 410 - let _ = world.remove::<ecs::SeatName>(client_entity); 411 - let _ = world.remove::<ecs::SeatEntity>(client_entity); 412 - let _ = world.remove::<ecs::Session>(client_entity); 413 - world.remove_entity(client_entity); 411 + world.despawn(client_entity); 414 412 415 413 log::info!( 416 414 "Removed client {} from {}", ··· 529 527 } 530 528 }; 531 529 532 - let device_entity = world.insert_device( 530 + let device_entity = ecs::insert_device( 531 + world, 533 532 device, 534 533 sanitized_path, 535 534 kind, ··· 553 552 "could not activate device", 554 553 ); 555 554 } 556 - world.remove_entity(device_entity); 555 + world.despawn(device_entity); 557 556 return; 558 557 } 559 558 560 559 if let Err(err) = device::send_opened(world, device_entity) { 561 560 log::error!("Could not send opened device event: {err}"); 562 561 } 563 - if let Some(devices) = world.get_mut::<ecs::Devices>(client_entity) { 562 + if let Some(mut devices) = world.get_mut::<ecs::Devices>(client_entity) { 564 563 devices.0.push(device_entity); 565 564 } 566 565 } ··· 572 571 } 573 572 574 573 match current_vt() { 575 - Ok(vt) => world.insert(seat_entity, ecs::CurrentVt(vt)), 574 + Ok(vt) => { world.entity_mut(seat_entity).insert(ecs::CurrentVt(vt)); } 576 575 Err(err) => log::error!("Could not query active VT: {err}"), 577 576 } 578 577 } ··· 674 673 } 675 674 676 675 let seat_name = seat_name(world, seat_entity)?; 677 - let next_client = if let Some(next_client) = world.remove::<ecs::NextClient>(seat_entity) { 676 + let next_client = if let Some(next_client) = world.entity_mut(seat_entity).take::<ecs::NextClient>() { 678 677 log::debug!("Activating next queued client on {seat_name}"); 679 678 Some(next_client.0) 680 679 } else { ··· 737 736 } 738 737 739 738 terminal::Terminal::open(cur_vt)?.ack_release()?; 740 - world.insert(seat_entity, ecs::CurrentVt(0)); 739 + world.entity_mut(seat_entity).insert(ecs::CurrentVt(0)); 741 740 742 741 Ok(Some(released_vt)) 743 742 } ··· 746 745 let acquired_vt = current_vt()?; 747 746 log::debug!("Activating VT"); 748 747 terminal::Terminal::open(acquired_vt)?.ack_acquire()?; 749 - world.insert(seat_entity, ecs::CurrentVt(acquired_vt)); 748 + world.entity_mut(seat_entity).insert(ecs::CurrentVt(acquired_vt)); 750 749 751 750 if world.get::<ecs::ActiveClient>(seat_entity).is_none() { 752 751 activate(world, seat_entity)?; ··· 899 898 return; 900 899 }; 901 900 902 - let client_entity = self.world.insert_client(seat.clone()); 901 + let client_entity = ecs::insert_client(&mut self.world, seat.clone()); 903 902 if let Err(err) = add_client(&mut self.world, seat_entity, client_entity) { 904 903 log::error!("Could not add client to seat: {err}"); 905 904 seat.send_disabled(); 906 - self.world.remove_entity(client_entity); 905 + self.world.despawn(client_entity); 907 906 return; 908 907 } 909 908 ··· 930 929 .is_none_or(|seat| seat.0 != seat_entity) 931 930 { 932 931 log::info!(session_id = session_id.as_raw(), seat = seat_name.as_str(); "session seat changed"); 933 - self.world.insert(entity, ecs::SeatName(seat_name.clone())); 934 - self.world.insert(entity, ecs::SeatEntity(seat_entity)); 932 + self.world.entity_mut(entity).insert(( 933 + ecs::SeatName(seat_name.clone()), 934 + ecs::SeatEntity(seat_entity), 935 + )); 935 936 } 936 937 if let Some(objects) = self.world.get::<ecs::SessionObjects>(entity) { 937 938 for object in &objects.0 {
+4 -4
daemon/src/session.rs
··· 87 87 }; 88 88 89 89 if matches!(event, session_core_session::Event::Destroy) { 90 - if let Some(objects) = self.world.get_mut::<crate::ecs::SessionObjects>(entity) { 90 + if let Some(mut objects) = self.world.get_mut::<crate::ecs::SessionObjects>(entity) { 91 91 objects.0.retain(|session_object| session_object != object); 92 92 } 93 93 return; ··· 206 206 } 207 207 object.send_done(); 208 208 209 - if let Some(objects) = world.get_mut::<ecs::SessionObjects>(entity) { 209 + if let Some(mut objects) = world.get_mut::<ecs::SessionObjects>(entity) { 210 210 objects.0.push(object); 211 211 } 212 212 } ··· 219 219 ) { 220 220 let vt = world.get::<ecs::Vt>(entity).map_or(0, |vt| vt.0); 221 221 log::info!(session_id = session_id.as_raw(), vt; "session state changed"); 222 - if let Some(active_state) = world.get_mut::<ecs::ActiveState>(entity) { 222 + if let Some(mut active_state) = world.get_mut::<ecs::ActiveState>(entity) { 223 223 active_state.0 = state; 224 224 } 225 225 if let Some(objects) = world.get::<ecs::SessionObjects>(entity) { ··· 246 246 ) { 247 247 let vt = world.get::<ecs::Vt>(entity).map_or(0, |vt| vt.0); 248 248 log::info!(session_id = session_id.as_raw(), vt; "session state changed"); 249 - if let Some(active_state) = world.get_mut::<ecs::ActiveState>(entity) { 249 + if let Some(mut active_state) = world.get_mut::<ecs::ActiveState>(entity) { 250 250 active_state.0 = state; 251 251 } 252 252 if let Some(objects) = world.get::<ecs::SessionObjects>(entity) {