210 Commits

Author SHA1 Message Date
Nova
bf89b73e8f feat: version bump 2023-07-22 18:31:09 -04:00
Nova
2e252279bb fix: states 2023-07-19 06:04:15 -07:00
Nova
9cf43ec535 fix: surface not mapping 2023-07-19 06:04:08 -07:00
Nova
f15578f7df feat: formatting 2023-07-19 06:03:28 -07:00
Nova
f63ca4a25b feat: play space 2023-07-16 10:42:35 -07:00
technobaboo
89741508e3 feat: make readme more readable 2023-07-11 11:44:38 -07:00
technobaboo
81be807749 fix(ci): add semicolons 2023-07-11 11:16:15 -07:00
technobaboo
fcdb8a7edf fix(ci): appimagetool 2023-07-11 11:11:07 -07:00
technobaboo
90ce185f29 fix(ci): xcb glx 2023-07-11 10:59:26 -07:00
technobaboo
d6353035ae fix(ci): ninja-build instead of ninja 2023-07-11 10:55:08 -07:00
technobaboo
ceb1b23264 feat: ci take 2 2023-07-11 10:53:31 -07:00
Nova
199e6f70b3 refactor: use dmabuf v4 instead of bind_display 2023-06-27 05:53:45 -04:00
Nova
641db4face refactor: disable shader injection 2023-06-26 20:49:21 -04:00
Nova
80d292b511 feat: match stereokit to log level 2023-06-26 20:43:02 -04:00
Nova
7fbcc92d02 fix: unwrap in main fn 2023-06-26 20:33:04 -04:00
Nova
de46726d01 feat: hardware accelerated wayland apps 2023-06-26 20:31:38 -04:00
Nova
6efa3a909e feat: proper dmabuf import 2023-06-26 20:09:20 -04:00
Nova
ea0f174da7 feat: shaders!! working!! 2023-06-26 19:49:10 -04:00
Nova
444146fa21 feat: it borken 2023-06-26 04:37:38 -04:00
Nova
a7930760e8 feat: glsl simula text shaders 2023-06-25 10:05:18 -04:00
Nova
668c32f583 fix: ctrl+c in tty 2023-06-21 01:47:10 -04:00
Nova
927e1c48e2 fix: mouse pointer keyboard ray direction 2023-06-14 23:00:17 -04:00
Nova
8cc20e054c feat: version bump 2023-06-11 01:37:21 -04:00
Nova
b12b171b53 feat: spatial bounds 2023-06-11 00:38:05 -04:00
Nova
0e61d51072 feat(input): custom pointers 2023-05-31 08:50:15 -04:00
Nova
e61c04960e fix(node): better send remote signal 2023-05-31 08:48:59 -04:00
Nova
5dc82be1a3 fix(pointer): proper direction 2023-05-31 08:48:24 -04:00
Nova
6861b92972 fix(main): make eye pointer not work in flatscreen 2023-05-31 08:47:16 -04:00
Nova
f68f350cd2 fix(scenegraph): recurse through aliases 2023-05-31 08:47:02 -04:00
Nova
2820415373 feat: readd dmabufs 2023-05-30 02:20:27 -04:00
Nova
f721a57604 fix: janky dmabuf hack 2023-05-27 09:48:34 -04:00
Nova
fb4149eaa7 feat: eye gaze support 2023-05-23 18:56:46 -04:00
matthewcroughan
d3746ef787 ci: print flatland revision for gnome-graphical-test in Discord message 2023-05-20 11:08:43 +01:00
matthewcroughan
9d4b4bee4d github: remove workflows
Since Hercules CI is in use now, GitHub Actions are not necessarily required
2023-05-20 11:08:43 +01:00
matthewcroughan
5390b0effb flake: add hercules-ci
This commit also adds a HCI Effect for posting to Discord the result of the gnome-graphical-test on every single commit
2023-05-20 11:08:43 +01:00
matthewcroughan
13da4c8d60 nix: add graphical-gnome-test
This VM integration test spawns Gnome, monado-service,
stardust-xr-server, flatland and weston-cliptest and tests that the
functionality works correctly. The result is a screenshot. If any
program in the test produces an exit code above 0 it will fail the test,
graphical rendering bugs should be visible in the resulting screenshot
2023-05-20 11:08:43 +01:00
matthewcroughan
1740d55f9c flake.lock: Update
Flake lock file updates:

• Updated input 'fenix':
    'github:nix-community/fenix/3a0b59a2ea946a533c62ac417596835779087f0e' (2023-04-20)
  → 'github:nix-community/fenix/5816c7bbcc385d2e65877631497df3f7d66b354a' (2023-05-11)
• Updated input 'fenix/rust-analyzer-src':
    'github:rust-lang/rust-analyzer/2400b36a2ed40f68a26473f69ac208ba10d98af9' (2023-04-19)
  → 'github:rust-lang/rust-analyzer/b7cdd93f3e1533e96d4cfa1ac8573e6210a2bedf' (2023-05-09)
• Added input 'flatland':
    'github:StardustXR/flatland/24613a496841bdf38e5f136608d5295860a75fce' (2023-05-11)
• Added input 'flatland/fenix':
    'github:nix-community/fenix/ee59e1c769657b1e27e608f8b981fa8f6b715583' (2023-03-14)
• Added input 'flatland/fenix/nixpkgs':
    follows 'flatland/nixpkgs'
• Added input 'flatland/fenix/rust-analyzer-src':
    'github:rust-lang/rust-analyzer/95497533524537b1cc7a2870ce94b0b14503be8b' (2023-03-13)
• Added input 'flatland/nixpkgs':
    'github:NixOS/nixpkgs/67f26c1cfc5d5783628231e776a81c1ade623e0b' (2023-03-13)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/da45bf6ec7bbcc5d1e14d3795c025199f28e0de0' (2023-04-30)
  → 'github:NixOS/nixpkgs/897876e4c484f1e8f92009fd11b7d988a121a4e7' (2023-05-06)
2023-05-20 11:08:43 +01:00
matthewcroughan
52d5e97de6 flake: filter nix code and README out of src
This means that changing the Nix code doesn't cause the Rust code to need to be recompiled when using nix build
2023-05-20 11:08:43 +01:00
Nova
633df045d4 feat: appimage support!! 2023-05-19 18:12:22 -04:00
Nova
415bf5bb04 feat: clean up main function 2023-05-19 18:11:52 -04:00
Nova
4e2d4a15c9 feat: flat wayland display env var 2023-05-18 06:00:53 -04:00
Nova
ef0142183d fix: better pointer compare distance algorithm 2023-05-10 23:44:36 -04:00
Nova
e5dfd9d3df fix(model): copy on create to make unique 2023-05-10 23:44:23 -04:00
Nova
6773fe2cf3 feat: instant model loading 2023-05-10 20:10:31 -04:00
Nova
5a6e7e02ca fix(wayland): stop crash 2023-05-10 19:14:57 -04:00
Nova
c5d8ec2ef1 fix: remove dbg statement 2023-05-10 19:02:09 -04:00
Nova
a31781146e fix: upgrade smithay 2023-05-10 16:51:39 -04:00
Nova
cb9368cb8e fix: model nodes 2023-05-10 16:49:56 -04:00
Nova
629c05e507 feat: model nodes 2023-05-10 08:38:21 -04:00
Matthew Croughan
9123153bf3 fix: nix flake smithay lock issues
* flake: use allowBuiltInFetchGit to prevent narHash reproducibility issues

using the builtin fetcher allows fetching git dependencies with only the ref and without storing the narHash for the fixed-output-derivation

* gitignore: add nix result symlinks
2023-05-06 17:37:46 +00:00
Nova
f3dc632ffc feat: order inputs 2023-05-02 21:58:53 -04:00
Astavie
c369100d8a fix: nix overlay
* nix flake

* workflow

* remove flake-utils

* update flake

* fix

* remove cargo hash

* fix overlay
2023-05-01 23:29:34 +00:00
Astavie
e10d40ef5e fix: nix flake
* nix flake

* workflow

* remove flake-utils

* update flake

* fix

* remove cargo hash
2023-05-01 21:56:49 +00:00
Nova King
d6ca367187 feat: FUNDING.yml 2023-05-01 17:31:03 +00:00
Nova
88ac8a8b86 better panel item startup settings order 2023-05-01 12:59:49 -04:00
Nova
70fef89e2d fix: launch env vars to launch as much stuff in wayland as possible 2023-05-01 00:05:00 -04:00
Nova
4d79a59b20 fix(objects/hand): hand enabled when controller not 2023-04-30 18:28:40 -04:00
Nova
c776c1b712 feat: new stereokit 2023-04-30 13:25:13 -04:00
Saphira Kai
d4de15e0b3 remove broken Debug derivation for XdgSurfaceData 2023-04-24 13:12:44 -03:00
Nova
9d220ec235 feat(startup): get environment 2023-04-24 09:53:20 -04:00
Nova
09c6c010e2 feat: cargo lock update 2023-04-24 08:31:28 -04:00
Nova
c9e185e9f3 feat: dependency updates 2023-04-24 08:31:07 -04:00
Nova
4737149c85 feat(wayland): popups, more compatibility, more stability
get_parent


grab


popups

fix head thingy


popup list


feat: remove set_active

feat(wayland): commit_popup

feat(wayland): cleanup


moar changess


actually fix the problem with everything oh my god


proper popup state


fix: multi thread event loop


fix: match popup surface ID


make wayland input system go over surfaces instead of toplevels


feat: massive refactor of all wayland things
2023-04-24 06:30:39 -04:00
Nova
648451b47e fix: mouse pointer 2023-04-23 09:34:43 -04:00
Nova
a9ef2d6f4b feat: custom startup script 2023-04-23 09:34:43 -04:00
Astavie
d6ffcadd76 fix: nix flake
* nix flake

* workflow

* remove flake-utils

* update flake
2023-04-20 10:35:50 +00:00
Nova
448b7489e8 feat: desktop file 2023-03-25 03:06:50 -04:00
Nova
622cf60a65 feat: upgrade stereokit-rs 2023-03-23 14:12:48 -04:00
Astavie
1ab11f1660 feat: nix support & github workflow
* nix flake

* workflow

* remove flake-utils
2023-03-14 19:35:40 +00:00
Nova
9654e6cc59 fix: unignore cargo.lock 2023-03-13 13:44:12 -07:00
Nova
44d177858f fix(input/hand): correct serialization transform matrix order 2023-03-08 01:45:03 -05:00
Nova
be41f11b83 feat(input): new system 2023-02-25 16:39:30 -05:00
Nova
dd2bffc2b1 refactor(input): make all inputs have nodes 2023-02-24 11:43:06 -05:00
Nova
d2ef508607 feat: update everything, clean dependencies 2023-02-23 08:41:40 -05:00
Nova
0cc7c7bc24 refactor(model): remove shader use 2023-02-23 07:17:36 -05:00
Nova
8d65e304cb fix(model): make default pbr shader clip 2023-02-20 18:03:02 -05:00
Nova
b0dbccbd18 fix(items): proper drop 2023-02-20 10:24:59 -05:00
Nova
a823fbfb57 fix(mouse pointer): keyboard 2023-02-18 02:06:17 -05:00
Nova
4a864e6519 fix(cargo.toml): upgrade stereokit 2023-02-17 13:10:23 -05:00
Nova
e23d847449 fix(mouse pointer): proper pointer transform 2023-02-17 13:10:08 -05:00
Nova
8ba199f053 fix: order of operations on wayland material properties 2023-02-16 14:03:13 -05:00
Nova
23925b4475 fix(item): send acceptors to new item ui 2023-02-16 14:02:43 -05:00
Nova
7ea0220f33 fix: update stereokit 2023-02-16 14:02:21 -05:00
Nova
969e4de882 feat: disabled/enabled 2023-02-16 00:30:25 -05:00
Nova
e5acb3013f fix: node aspect drawable 2023-02-09 03:58:56 -05:00
Nova
3d57bed1c0 refactor: node aspect drawable 2023-02-08 21:06:24 -05:00
Nova
45839ebf60 fix: cargo fmt 2023-02-07 18:04:20 -05:00
Nova
0bb5b53e02 fix(dev profile): optimization level 0 2023-02-07 16:15:37 -05:00
Nova
4f966b6d71 feat(model): pbr clip shader 2023-02-07 16:15:20 -05:00
awtterpip
2687a393b5 fixed bug where sound wasn't stoppable 2023-02-07 10:34:10 -06:00
awtterpip
5c605932ef gave audio interface proper name 2023-02-07 09:13:55 -06:00
piper
bccdc8221e feat: audio! 2023-02-04 20:39:08 -05:00
Nova
bddf17bbef fix(stereokit): version 2023-02-04 20:38:10 -05:00
Nova
e8511e8759 refactor(cargo.toml): profile optimizations 2023-02-02 16:32:43 -05:00
Nova
85296f538b feat(spatial): fields_distance, normal, closest_point 2023-02-01 19:21:35 -05:00
Nova
f8ff80b781 fix(items): make acceptor fields non-optional 2023-01-28 11:12:51 -05:00
Nova
932fef87f5 refactor: change logic_step to frame event 2023-01-26 09:08:40 -05:00
Nova
742780e34e refactor: remove many unwrap calls 2023-01-25 11:50:53 -05:00
Nova
41ede661f7 feat(material): auto copy on change parameter 2023-01-25 09:23:01 -05:00
Nova
8d85460803 feat: make event loop multithreaded 2023-01-25 09:17:52 -05:00
Nova
ac71581db8 fix(spatial): moving object relative to itself 2023-01-25 05:40:37 -05:00
Nova
2f894c4058 fix(spatial): parse_transform returned result 2023-01-25 05:40:19 -05:00
Nova
2b97c98a6e refactor(wayland): remove SeatData wrapper 2023-01-22 02:38:40 -05:00
Nova
98d9f491ba fix(wayland): update pointer scroll 2023-01-22 02:30:12 -05:00
Nova
16d710e106 fix(panel_item): allow surfaces with size of 0,0 2023-01-22 00:58:25 -05:00
Nova
9ad202e778 refactor(spatial): get/set parent methods 2023-01-22 00:42:04 -05:00
Nova
b3747d623c fix(spatial): reference space can be self 2023-01-22 00:24:38 -05:00
Nova
d5ff9281e6 feat: update/clean dependencies 2023-01-22 00:24:13 -05:00
Nova
18ebd8c522 feat: input multiplexing 2023-01-21 18:07:25 -05:00
Nova
411f71c217 feat: startup script 2023-01-17 18:51:46 -05:00
Nova
3027ae20a9 feat(spatial): keep track of children 2023-01-16 11:17:12 -05:00
Nova
fbce321426 refactor(main): make arrays tuples 2023-01-16 11:03:46 -05:00
Nova
74bc3a306e feat: update stereokit to have fancy tracing 2023-01-15 04:23:26 -05:00
Nova
a950ad59f1 fix(input): grab issues 2023-01-15 04:04:09 -05:00
Nova
cf840da444 feat(stereokit): log filtering 2023-01-15 04:03:21 -05:00
Nova
173fba35fa feat: even more tracing 2023-01-15 01:13:22 -05:00
Nova
97fbbec0fe feat: adaptive sleep delay 2023-01-14 23:48:49 -05:00
Nova
400f3a23bf feat: spatial tracing 2023-01-14 22:59:00 -05:00
Nova
1ad3336b6f feat: span tracing!!! 2023-01-14 22:32:41 -05:00
Nova
8e9956abe1 refactor(input): more compact registry contains 2023-01-14 20:29:33 -05:00
Nova
6ca93ea24c fix(event loop, client): better async 2023-01-14 12:38:05 -05:00
Nova
49810e8fd1 refactor(cargo.toml): remove unneeded deps and features 2023-01-14 11:17:52 -05:00
Nova
afd0946558 fix(input): reduce latency by several frames 2023-01-14 11:03:47 -05:00
Nova
fd31d0cd99 feat(tokio): profiling 2023-01-14 10:38:39 -05:00
Nova
2f380da62f refactor(wayland): remove commented out code\ 2023-01-07 10:15:56 -05:00
Nova
1c6971cd11 feat(model): use resource ID for texture 2023-01-06 09:05:30 -05:00
Nova
da4cf084d2 fix: remove stereokit patch 2023-01-05 21:49:03 -05:00
Nova
ca95ed5461 feat(model): set material parameter 2023-01-05 21:46:25 -05:00
Nova
1b06cb6952 fix(drawable/lines): properly make cyclic point 2023-01-05 08:28:29 -05:00
Nova
df89c826bb fix: remove opt level 3 for dev 2023-01-05 07:59:20 -05:00
Nova
21f7f66440 feat: update stereokit 2023-01-04 23:51:48 -05:00
Nova
3f1bad18c8 feat(wayland/surface): geometry resizing, unused 2023-01-04 21:36:55 -05:00
Nova
0c190cc833 feat(delta): mark_changed 2023-01-04 21:36:25 -05:00
Nova
5f0df8e7c1 fix(wayland): SSD all the things 2023-01-04 08:26:10 -05:00
Nova
d715f2f9ed fix(wayland): toplevel states bytemucked to u8 2023-01-04 08:25:54 -05:00
Nova
d7fa4e62b8 feat(wayland): proper surface geometry 2023-01-04 07:25:33 -05:00
Nova
568ebb0060 feat(wayland): serial counter 2023-01-04 07:25:22 -05:00
Nova
42efc67625 feat(delta): const 2023-01-04 07:23:23 -05:00
Nova
dd4b0097a1 feat(wayland): set toplevel capabilities 2023-01-03 10:08:39 -05:00
Nova
a483cdbc7d feat(wayland): recommended_state 2023-01-02 18:53:58 -05:00
Nova
84a7546442 refactor(wayland): remove xdg output manager 2023-01-02 03:49:29 -05:00
Nova
dd43f238ff refactor(wayland): comment out xdg activation protocol 2023-01-02 03:43:50 -05:00
Nova
4f057358c8 fix(wayland): drop panel item correctly 2023-01-01 14:37:11 -05:00
Nova
e20971aef7 feat(wayland): switch pointer focus dynamically 2023-01-01 14:36:46 -05:00
Nova
eb0d3c5bcf fix(wayland): set seat cursor 2023-01-01 14:34:18 -05:00
Nova
a18222e3df fix(wayland): xdg surface size when not set 2023-01-01 14:33:07 -05:00
Nova
93ca932da9 feat(wayland/xdg_shell): set surface states None 2022-12-26 11:15:37 -05:00
Nova
c512b2fef5 feat(wayland): make state fields optional 2022-12-26 08:22:09 -05:00
Nova
f53c684377 fix(wayland): panel item configure toplevel 2022-12-25 16:19:22 -05:00
Nova
3552166207 feat(wayland): configure and commit for toplevel] 2022-12-25 16:01:23 -05:00
Nova
0b6eb147c5 feat(input): allow scaling input handlers 2022-12-21 05:34:34 -05:00
Nova
1833ed50f3 feat: update stardust-xr 2022-12-17 02:29:32 -05:00
Nova
6cdbfb3bad refactor(data): identical values for mask 2022-12-17 02:28:06 -05:00
Nova
a5e0cb19c9 refactor(startup): auto acceptor on item add to 2022-12-10 10:26:26 -05:00
Nova
519ab94312 refactor(startup): generate startup token 2022-12-10 09:46:47 -05:00
Nova
f2a8c0ed13 refactor(startup): rename to STARTUP_SETTINGS 2022-12-10 09:27:37 -05:00
Nova
b3998f315d feat(startup): automatic acceptors 2022-12-10 09:18:02 -05:00
Nova
40bcd61b98 feat(startup settings): use /proc/{pid}/environ 2022-12-10 09:17:37 -05:00
Nova
7a4d557c61 fix(wayland): dmabuf formats 2022-12-10 00:30:53 -05:00
Nova
303b3f3ca2 refactor(wayland): remove manual dmabuf importing 2022-12-09 07:04:50 -05:00
Nova
ac5e949614 fix: drain all dmabufs 2022-12-08 05:40:54 -05:00
Nova
60baabb850 feat: optimization level 3 for debug 2022-12-07 14:47:25 -05:00
Nova
248e48fd8e feat(wayland): dmabuf 2022-12-07 14:30:48 -05:00
Nova
b9baee7e5f feat(resources): list of extensions to check 2022-12-05 22:44:04 -05:00
Nova
3598ffdbb1 refactor(sk_hand): use snake case for datamap keys 2022-12-03 17:18:27 -05:00
Nova
c171d9e6db feat: tracing 2022-12-02 20:46:28 -05:00
Nova
d7a607a663 switch to color_eyre instead of anyhow 2022-12-02 13:58:54 -05:00
Nova
03ccf9127d fix(input): O(n log n) instead of O(n^2) 2022-12-02 11:09:23 -05:00
Nova
6a3024657f fix(items): give aliases a proper lifetime 2022-11-30 22:34:16 -05:00
Nova
a0058fcc2e fix(alias): make output optional 2022-11-30 07:04:06 -05:00
Nova
410cc13c4f fix(lines): use sRGB colors 2022-11-28 00:32:41 -05:00
Nova
bc259dbe01 fix(lines): convert f32 to u8 colors correctly 2022-11-26 15:22:23 -05:00
Nova
3730e20248 fix(lines): accept f32 colors 2022-11-26 00:43:04 -05:00
Nova
1be413065d fix: text not working 2022-11-26 00:34:37 -05:00
Nova
2721c20c8b fix(wayland): update smithay version 2022-11-25 23:58:22 -05:00
Nova
80130f6ffd feat(fields): torus field 2022-11-24 18:57:11 -05:00
Nova
8da778eaba refactor(fields): use let else for getting field 2022-11-24 18:56:59 -05:00
Nova
3c708d1aaf feat(drawable): lines 2022-11-21 16:39:28 -05:00
Nova
1ae1bef3c1 refactor(items): move capture to item acceptor 2022-11-20 13:34:15 -05:00
Nova
7fd0c1fddb feat(items): acceptor 2022-11-19 11:25:10 -05:00
Nova
fd9957b784 fix(wayland): cursor material queue higher 2022-11-14 11:53:08 -05:00
Nova
57da02dbad refactor(stereokit): upgrade version 2022-11-14 09:05:36 -05:00
Nova
83a5b36ddc refactor(wayland): make code cleaner 2022-11-12 11:53:11 -05:00
Nova
8c36d73775 fix: upgrade rust version 2022-11-11 13:25:57 -05:00
Nova
8396b98f67 fix(wayland): pointer_motion works when inactive 2022-11-11 13:25:48 -05:00
Nova
46d989ce7f fix(wayland): remove unwraps 2022-11-11 12:52:51 -05:00
Nova
75ac570486 refactor(wayland): s/ObjectId/Weak<WlSurface>/ 2022-11-09 13:05:21 -05:00
Nova
242def9d06 feat: wayland feature 2022-11-09 11:13:07 -05:00
Nova
959f32009b fix(wayland): account for surface data map panic 2022-11-09 11:02:48 -05:00
Nova
57796c217d fix(panel item): set cursor full of snake 2022-11-08 21:16:03 -05:00
Nova
cea3390e36 refactor(items): genericize item acceptors/ui 2022-11-08 20:25:43 -05:00
Nova
a756e80064 fix: make aliased signals snake case 2022-11-08 20:17:15 -05:00
Nova
1f61d32877 refactor: use snake case for method names 2022-11-08 06:10:03 -05:00
Nova
da7e2c5e6e fix(wayland): upgrade smithay version 2022-11-06 16:49:30 -05:00
Nova
fd0940bfe9 feat(objects/input): add keyboard to mouse_pointer 2022-11-05 17:56:52 -04:00
Nova
2b4a495c07 refactor(data): simplify 2022-11-05 17:56:34 -04:00
Nova
cffb968d2e refactor: remove item alias remote_methods 2022-11-05 17:56:09 -04:00
Nova
201ab3aee8 feat(field): ray_march 2022-11-05 17:55:27 -04:00
Nova
cfa3584dda feat(field): expose ray marching to clients 2022-11-01 07:59:49 -04:00
Nova
f19ba93958 refactor(client): use new messenger 2022-10-30 00:14:24 -04:00
Nova
09a2572c3b refactor(node): return Result<&T> from get aspect 2022-10-29 07:32:51 -04:00
Nova
c6316b4e8b feat: terrible hack for moses 2022-10-26 05:19:20 -04:00
Nova
9cd900b23f fix(wayland): remove wayland crate pinning 2022-10-25 16:21:22 -04:00
Nova
a6d30cb366 refactor: use master smithay branch 2022-10-25 16:07:36 -04:00
Nova
3e94a3f62a fix(wayland): set default output size 2022-10-25 12:56:59 -04:00
Nova
060f8264ff fix(data): send "data" to receiver 2022-10-25 07:32:25 -04:00
Nova
b7b3907647 feat: pulse sender/receiver 2022-10-21 06:21:56 -04:00
Nova
1550555df1 fix: clippy 2022-10-21 06:21:49 -04:00
Nova
c42a29a034 feat: zones 2022-10-20 11:32:33 -04:00
Nova King
621bf6b82a Merge pull request #2 from philpax/fix-build
fix: remove path dependency for stereokit
2022-10-19 05:55:53 +00:00
50 changed files with 1319 additions and 2596 deletions

3
.gitignore vendored
View File

@@ -11,5 +11,4 @@
*result*
/libs/
*.AppImage
*.blend1
*.AppImage

444
Cargo.lock generated
View File

@@ -10,9 +10,9 @@ checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
[[package]]
name = "addr2line"
version = "0.20.0"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3"
checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
dependencies = [
"gimli",
]
@@ -23,15 +23,6 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
dependencies = [
"memchr",
]
[[package]]
name = "aliasable"
version = "0.1.3"
@@ -125,9 +116,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.72"
version = "1.0.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
[[package]]
name = "appendlist"
@@ -155,13 +146,13 @@ dependencies = [
[[package]]
name = "async-trait"
version = "0.1.72"
version = "0.1.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09"
checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
]
[[package]]
@@ -183,9 +174,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "axum"
version = "0.6.19"
version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a1de45611fdb535bfde7b7de4fd54f4fd2b17b1737c0a59b69bf9b92074b8c"
checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39"
dependencies = [
"async-trait",
"axum-core",
@@ -228,15 +219,15 @@ dependencies = [
[[package]]
name = "backtrace"
version = "0.3.68"
version = "0.3.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12"
checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"miniz_oxide 0.6.2",
"object",
"rustc-demangle",
]
@@ -283,9 +274,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.3.3"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded"
[[package]]
name = "bumpalo"
@@ -310,7 +301,7 @@ checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
]
[[package]]
@@ -398,9 +389,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.3.19"
version = "4.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fd304a20bff958a57f04c4e96a2e7594cc4490a0e809cbd48bb6437edaa452d"
checksum = "d9394150f5b4273a1763355bd1c2ec54cc5a2593f790587bcd6b2c947cfa9211"
dependencies = [
"clap_builder",
"clap_derive",
@@ -409,26 +400,27 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.3.19"
version = "4.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01c6a3f08f1fe5662a35cfe393aec09c4df95f60ee93b7556505260f75eee9e1"
checksum = "9a78fbdd3cc2914ddf37ba444114bc7765bbdcb55ec9cbe6fa054f0137400717"
dependencies = [
"anstream",
"anstyle",
"bitflags 1.3.2",
"clap_lex",
"strsim",
]
[[package]]
name = "clap_derive"
version = "4.3.12"
version = "4.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54a9bb5758fc5dfe728d1019941681eccaf0cf8a4189b692a0ee2f2ecf90a050"
checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f"
dependencies = [
"heck",
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
]
[[package]]
@@ -471,9 +463,9 @@ dependencies = [
[[package]]
name = "color-rs"
version = "0.8.0"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3415c18b81f66b23614db9fcccbf19d2af434e04d9a6c7ac10e49930f39d89f8"
checksum = "05d6cda18d80350d6a6d15d1f2dd6f5c88b3d61882e08801e8d68f506434b808"
dependencies = [
"angle",
"half",
@@ -495,7 +487,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d"
dependencies = [
"quote",
"syn 2.0.28",
"syn 2.0.22",
]
[[package]]
@@ -512,9 +504,9 @@ dependencies = [
[[package]]
name = "console-subscriber"
version = "0.1.10"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4cf42660ac07fcebed809cfe561dd8730bcd35b075215e6479c516bcd0d11cb"
checksum = "57ab2224a0311582eb03adba4caaf18644f7b1f10a760803a803b9b605187fc7"
dependencies = [
"console-api",
"crossbeam-channel",
@@ -570,12 +562,12 @@ dependencies = [
[[package]]
name = "dashmap"
version = "5.5.0"
version = "5.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d"
checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc"
dependencies = [
"cfg-if",
"hashbrown 0.14.0",
"hashbrown 0.12.3",
"lock_api",
"once_cell",
"parking_lot_core 0.9.8",
@@ -666,79 +658,15 @@ dependencies = [
[[package]]
name = "either"
version = "1.9.0"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
[[package]]
name = "encoding"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec"
dependencies = [
"encoding-index-japanese",
"encoding-index-korean",
"encoding-index-simpchinese",
"encoding-index-singlebyte",
"encoding-index-tradchinese",
]
[[package]]
name = "encoding-index-japanese"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding-index-korean"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding-index-simpchinese"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding-index-singlebyte"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding-index-tradchinese"
version = "1.20141219.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18"
dependencies = [
"encoding_index_tests",
]
[[package]]
name = "encoding_index_tests"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "equivalent"
version = "1.0.1"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
[[package]]
name = "errno"
@@ -773,9 +701,12 @@ dependencies = [
[[package]]
name = "fastrand"
version = "2.0.0"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
dependencies = [
"instant",
]
[[package]]
name = "flatbuffers"
@@ -794,7 +725,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
dependencies = [
"crc32fast",
"miniz_oxide",
"miniz_oxide 0.7.1",
]
[[package]]
@@ -877,16 +808,6 @@ dependencies = [
"pin-utils",
]
[[package]]
name = "gethostname"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "getrandom"
version = "0.2.10"
@@ -1017,9 +938,18 @@ dependencies = [
[[package]]
name = "hermit-abi"
version = "0.3.2"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "hermit-abi"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "http"
@@ -1161,18 +1091,19 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi 0.3.2",
"hermit-abi 0.3.1",
"libc",
"windows-sys",
]
[[package]]
name = "is-terminal"
version = "0.4.9"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
dependencies = [
"hermit-abi 0.3.2",
"hermit-abi 0.3.1",
"io-lifetimes",
"rustix",
"windows-sys",
]
@@ -1188,9 +1119,9 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.9"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "js-sys"
@@ -1247,9 +1178,9 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
version = "0.4.3"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09fc20d2ca12cb9f044c93e3bd6d32d523e6e2ec3db4f7b2939cd99026ecd3f0"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "lock_api"
@@ -1276,7 +1207,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
]
[[package]]
@@ -1285,7 +1216,7 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata 0.1.10",
"regex-automata",
]
[[package]]
@@ -1302,9 +1233,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memmap2"
version = "0.7.1"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f49388d20533534cd19360ad3d6a7dadc885944aa802ba3995040c5ec11288c6"
checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327"
dependencies = [
"libc",
]
@@ -1339,6 +1270,15 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
dependencies = [
"adler",
]
[[package]]
name = "miniz_oxide"
version = "0.7.1"
@@ -1432,20 +1372,20 @@ dependencies = [
[[package]]
name = "num-traits"
version = "0.2.16"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi 0.3.2",
"hermit-abi 0.2.6",
"libc",
]
@@ -1488,14 +1428,14 @@ dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
]
[[package]]
name = "object"
version = "0.31.1"
version = "0.30.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1"
checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385"
dependencies = [
"memchr",
]
@@ -1609,29 +1549,29 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
[[package]]
name = "pin-project"
version = "1.1.2"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842"
checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.2"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
]
[[package]]
name = "pin-project-lite"
version = "0.2.10"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57"
checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]]
name = "pin-utils"
@@ -1647,9 +1587,9 @@ checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "portable-atomic"
version = "1.4.1"
version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edc55135a600d700580e406b4de0d59cb9ad25e344a3a091a97ded2622ec4ec6"
checksum = "767eb9f07d4a5ebcb39bbf2d452058a93c011373abf6832e24194a1c3f004794"
[[package]]
name = "ppv-lite86"
@@ -1704,32 +1644,13 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.66"
version = "1.0.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb"
dependencies = [
"unicode-ident",
]
[[package]]
name = "profiling"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "332cd62e95873ea4f41f3dfd6bbbfc5b52aec892d7e8d534197c4720a0bbbab2"
dependencies = [
"profiling-procmacros",
]
[[package]]
name = "profiling-procmacros"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a10adb8d151bb1280afb8bed41ae5db26be1b056964947133c7525b0bf39c0b0"
dependencies = [
"quote",
"syn 1.0.109",
]
[[package]]
name = "prost"
version = "0.11.9"
@@ -1773,9 +1694,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.31"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0"
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
dependencies = [
"proc-macro2",
]
@@ -1841,14 +1762,11 @@ dependencies = [
[[package]]
name = "regex"
version = "1.9.1"
version = "1.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata 0.3.3",
"regex-syntax 0.7.4",
"regex-syntax 0.7.2",
]
[[package]]
@@ -1860,17 +1778,6 @@ dependencies = [
"regex-syntax 0.6.29",
]
[[package]]
name = "regex-automata"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax 0.7.4",
]
[[package]]
name = "regex-syntax"
version = "0.6.29"
@@ -1879,9 +1786,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.7.4"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2"
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
[[package]]
name = "rustc-demangle"
@@ -1906,12 +1813,13 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.38.4"
version = "0.37.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a962918ea88d644592894bc6dc55acc6c0956488adcebbfb6e273506b7fd6e5"
checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0"
dependencies = [
"bitflags 2.3.3",
"bitflags 1.3.2",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
@@ -1919,15 +1827,15 @@ dependencies = [
[[package]]
name = "rustversion"
version = "1.0.14"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
[[package]]
name = "ryu"
version = "1.0.15"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "scan_fmt"
@@ -1943,15 +1851,15 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
[[package]]
name = "scopeguard"
version = "1.2.0"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
version = "1.0.18"
version = "1.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
[[package]]
name = "send_wrapper"
@@ -1961,29 +1869,29 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73"
[[package]]
name = "serde"
version = "1.0.180"
version = "1.0.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ea67f183f058fe88a4e3ec6e2788e003840893b91bac4559cabedd00863b3ed"
checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.180"
version = "1.0.164"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24e744d7782b686ab3b73267ef05697159cc0e5abbed3f47f9933165e5219036"
checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
]
[[package]]
name = "serde_json"
version = "1.0.103"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b"
checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3"
dependencies = [
"itoa",
"ryu",
@@ -1992,13 +1900,13 @@ dependencies = [
[[package]]
name = "serde_repr"
version = "0.1.15"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e168eaaf71e8f9bd6037feb05190485708e019f4fd87d161b3c0a0d37daf85e5"
checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
]
[[package]]
@@ -2045,24 +1953,23 @@ dependencies = [
[[package]]
name = "smallvec"
version = "1.11.0"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "smithay"
version = "0.3.0"
source = "git+https://github.com/smithay/smithay.git#ae7fb22315a8cf16c33b5468e9d2faaa4390520d"
source = "git+https://github.com/smithay/smithay.git#da5c1b9d4dc21c8fe4037e216a82419cab124a77"
dependencies = [
"appendlist",
"bitflags 2.3.3",
"bitflags 2.3.2",
"calloop",
"cgmath",
"downcast-rs",
"drm",
"drm-ffi",
"drm-fourcc",
"encoding",
"gl_generator",
"indexmap 1.9.3",
"lazy_static",
@@ -2070,10 +1977,8 @@ dependencies = [
"libloading 0.8.0",
"nix 0.26.2",
"once_cell",
"profiling",
"rand",
"scan_fmt",
"scopeguard",
"tempfile",
"thiserror",
"tracing",
@@ -2081,7 +1986,6 @@ dependencies = [
"wayland-protocols-misc",
"wayland-protocols-wlr",
"wayland-server",
"x11rb",
"xkbcommon",
]
@@ -2097,16 +2001,15 @@ dependencies = [
[[package]]
name = "stardust-xr"
version = "0.13.0"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f493d5557c543404778beeba7051bc7bf537541b91cbd2b67983515675acba8"
checksum = "0efaf53544cca5e641ba51928f492a8639cf62399207f8d5c1e3f917e4fc4aa1"
dependencies = [
"chrono",
"cluFlock",
"color-rs",
"dirs",
"mint",
"nix 0.26.2",
"parking_lot 0.12.1",
"rustc-hash",
"serde",
@@ -2219,9 +2122,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.28"
version = "2.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616"
dependencies = [
"proc-macro2",
"quote",
@@ -2236,10 +2139,11 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "tempfile"
version = "3.7.0"
version = "3.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5486094ee78b2e5038a6382ed7645bc084dc2ec433426ca4c3cb61e2007b8998"
checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
dependencies = [
"autocfg",
"cfg-if",
"fastrand",
"redox_syscall 0.3.5",
@@ -2249,22 +2153,22 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.44"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.44"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
]
[[package]]
@@ -2290,12 +2194,11 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.29.1"
version = "1.28.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2"
dependencies = [
"autocfg",
"backtrace",
"bytes",
"libc",
"mio",
@@ -2327,7 +2230,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
]
[[package]]
@@ -2363,9 +2266,9 @@ checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b"
[[package]]
name = "toml_edit"
version = "0.19.14"
version = "0.19.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a"
checksum = "266f016b7f039eec8a1a80dfe6156b633d208b9fccca5e4db1d6775b0c4e34a7"
dependencies = [
"indexmap 2.0.0",
"toml_datetime",
@@ -2452,7 +2355,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
]
[[package]]
@@ -2513,9 +2416,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "unicode-ident"
version = "1.0.11"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
[[package]]
name = "utf8parse"
@@ -2583,7 +2486,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
"wasm-bindgen-shared",
]
@@ -2605,7 +2508,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.28",
"syn 2.0.22",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@@ -2633,9 +2536,9 @@ dependencies = [
[[package]]
name = "wayland-protocols"
version = "0.30.1"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b28101e5ca94f70461a6c2d610f76d85ad223d042dd76585ab23d3422dd9b4d"
checksum = "7fefbeb8a360abe67ab7c2efe1d297a1a50ee011f5460791bc18870c26bb84e2"
dependencies = [
"bitflags 1.3.2",
"wayland-backend",
@@ -2732,15 +2635,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-wsapoll"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@@ -2767,9 +2661,9 @@ dependencies = [
[[package]]
name = "windows-targets"
version = "0.48.1"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
@@ -2824,40 +2718,18 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winnow"
version = "0.5.0"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81fac9742fd1ad1bd9643b991319f72dd031016d44b77039a26977eb667141e7"
checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448"
dependencies = [
"memchr",
]
[[package]]
name = "x11rb"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdf3c79412dd91bae7a7366b8ad1565a85e35dd049affc3a6a2c549e97419617"
dependencies = [
"gethostname",
"nix 0.25.1",
"winapi",
"winapi-wsapoll",
"x11rb-protocol",
]
[[package]]
name = "x11rb-protocol"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0b1513b141123073ce54d5bb1d33f801f17508fbd61e02060b1214e96d39c56"
dependencies = [
"nix 0.25.1",
]
[[package]]
name = "xkbcommon"
version = "0.5.1"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52db25b599e92bf6e3904134618728eeb7b49a5a4f38f107f92399bb9c496b88"
checksum = "acbee136714379ab22da0280207fdb7f47e0bb940adea97731b65598b8c7a92e"
dependencies = [
"libc",
"memmap2",
@@ -2865,6 +2737,6 @@ dependencies = [
[[package]]
name = "xml-rs"
version = "0.8.16"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47430998a7b5d499ccee752b41567bc3afc57e1327dc855b1a2aa44ce29b5fa1"
checksum = "52839dc911083a8ef63efa4d039d1f58b5e409f923e44c80828f206f66e5541c"

View File

@@ -13,10 +13,8 @@ name = "stardust-xr-server"
path = "src/main.rs"
[features]
default = ["wayland", "xwayland"]
openxr_runtime = []
default = ["wayland"]
wayland = ["dep:smithay", "dep:xkbcommon"]
xwayland = ["smithay/xwayland"]
profile_tokio = ["dep:console-subscriber", "tokio/tracing"]
profile_app = ["dep:tracing-chrome"]
@@ -53,7 +51,7 @@ tokio = { version = "1.27.0", features = ["rt-multi-thread", "signal"] }
send_wrapper = "0.6.0"
prisma = "0.1.1"
xkbcommon = { version = "0.5.0", default-features = false, optional = true }
stardust-xr = "0.13.0"
stardust-xr = "0.11.4"
directories = "5.0.0"
serde = { version = "1.0.160", features = ["derive"] }
tracing = "0.1.37"
@@ -65,7 +63,7 @@ atty = "0.2.14"
[dependencies.stereokit]
default-features = false
features = ["linux-egl"]
version = "0.16.9"
version = "0.16.7"
[dependencies.smithay]
# git = "https://github.com/technobaboo/smithay.git" # Until we get stereokit to understand OES samplers and external textures

View File

@@ -1,6 +1,4 @@
use super::scenegraph::Scenegraph;
#[cfg(feature = "oxr_runtime")]
use crate::openxr;
use crate::{
core::{registry::OwnedRegistry, task},
nodes::{
@@ -110,8 +108,6 @@ impl Client {
items::create_interface(&client)?;
input::create_interface(&client)?;
startup::create_interface(&client)?;
#[cfg(feature = "openxr_runtime")]
openxr::create_interface(&client);
let pid_printable = pid
.map(|pid| pid.to_string())

View File

@@ -7,4 +7,3 @@ pub mod registry;
pub mod resource;
pub mod scenegraph;
pub mod task;
pub mod typed_datamap;

View File

@@ -1,10 +1,9 @@
use crate::core::client::Client;
use crate::nodes::Node;
use crate::{core::client::Client, nodes::Message};
use color_eyre::eyre::Result;
use once_cell::sync::OnceCell;
use stardust_xr::scenegraph;
use stardust_xr::scenegraph::ScenegraphError;
use std::os::fd::OwnedFd;
use std::sync::{Arc, Weak};
use tracing::{debug, debug_span, instrument};
@@ -51,25 +50,12 @@ impl Scenegraph {
}
impl scenegraph::Scenegraph for Scenegraph {
fn send_signal(
&self,
path: &str,
method: &str,
data: &[u8],
fds: Vec<OwnedFd>,
) -> Result<(), ScenegraphError> {
fn send_signal(&self, path: &str, method: &str, data: &[u8]) -> Result<(), ScenegraphError> {
let Some(client) = self.get_client() else {return Err(ScenegraphError::SignalNotFound)};
debug_span!("Handle signal", path, method).in_scope(|| {
self.get_node(path)
.ok_or(ScenegraphError::NodeNotFound)?
.send_local_signal(
client,
method,
Message {
data: data.to_vec(),
fds,
},
)
.send_local_signal(client, method, data)
})
}
fn execute_method(
@@ -77,22 +63,12 @@ impl scenegraph::Scenegraph for Scenegraph {
path: &str,
method: &str,
data: &[u8],
fds: Vec<OwnedFd>,
) -> Result<(Vec<u8>, Vec<OwnedFd>), ScenegraphError> {
) -> Result<Vec<u8>, ScenegraphError> {
let Some(client) = self.get_client() else {return Err(ScenegraphError::MethodNotFound)};
debug_span!("Handle method", path, method).in_scope(|| {
let message = self
.get_node(path)
self.get_node(path)
.ok_or(ScenegraphError::NodeNotFound)?
.execute_local_method(
client,
method,
Message {
data: data.to_vec(),
fds,
},
)?;
Ok((message.data, message.fds))
.execute_local_method(client, method, data)
})
}
}

View File

@@ -1,56 +0,0 @@
#![allow(unused)]
use std::ops::{Deref, DerefMut};
use color_eyre::eyre::Result;
use once_cell::sync::Lazy;
use serde::{de::DeserializeOwned, Serialize};
use stardust_xr::schemas::{
flat::Datamap,
flex::flexbuffers::{FlexbufferSerializer, Reader, ReaderError},
};
use crate::nodes::Message;
pub struct TypedDatamap<T: DeserializeOwned + Serialize>(T);
impl<T: DeserializeOwned + Serialize> TypedDatamap<T> {
pub fn new(data: T) -> Self {
TypedDatamap(data)
}
pub fn from_flex(message: Message) -> Result<Self> {
let root = Reader::get_root(message.as_ref())?;
T::deserialize(root).map(Self::new).map_err(|e| e.into())
}
pub fn to_datamap(&mut self) -> Result<Datamap> {
let mut serializer = FlexbufferSerializer::default();
self.0.serialize(&mut serializer)?;
Datamap::new(serializer.take_buffer()).map_err(|e| e.into())
}
pub fn serialize(&mut self) -> Option<Vec<u8>> {
let mut serializer = FlexbufferSerializer::default();
self.0.serialize(&mut serializer).ok()?;
// check if this is actually a map
Reader::get_root(serializer.view()).ok()?.get_map().ok()?;
Some(serializer.take_buffer())
}
}
impl<T: DeserializeOwned + Serialize> Default for TypedDatamap<T>
where
T: Default,
{
fn default() -> Self {
Self(T::default())
}
}
impl<T: DeserializeOwned + Serialize> Deref for TypedDatamap<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: DeserializeOwned + Serialize> DerefMut for TypedDatamap<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

View File

@@ -1,8 +1,6 @@
mod core;
mod nodes;
mod objects;
#[cfg(feature = "openxr_runtime")]
mod openxr;
#[cfg(feature = "wayland")]
mod wayland;
@@ -19,6 +17,7 @@ use clap::Parser;
use directories::ProjectDirs;
use once_cell::sync::OnceCell;
use stardust_xr::server;
use std::mem::ManuallyDrop;
use std::path::PathBuf;
use std::process::{Command, Stdio};
use std::sync::Arc;
@@ -33,8 +32,6 @@ use tracing::metadata::LevelFilter;
use tracing::{debug_span, error, info};
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
pub static SK_INFO: OnceCell<SystemInfo> = OnceCell::new();
#[derive(Parser)]
#[clap(author, version, about, long_about = None)]
struct CliArgs {
@@ -118,8 +115,6 @@ fn main() {
let _ = SK_MULTITHREAD.set(sk.multithreaded());
info!("Init StereoKit");
SK_INFO.set(stereokit.system_info()).unwrap();
sk.material_set_shader(
sk.material_find("default/material_pbr").unwrap(),
sk.shader_find("default/shader_pbr_clip").unwrap(),
@@ -150,7 +145,7 @@ fn main() {
}
}
let mut mouse_pointer = cli_args
let mouse_pointer = cli_args
.flatscreen
.then(MousePointer::new)
.transpose()
@@ -164,8 +159,8 @@ fn main() {
.flatten();
let mut controllers = (!cli_args.flatscreen && !cli_args.disable_controller)
.then(|| {
let left = SkController::new(&sk, Handed::Left).ok();
let right = SkController::new(&sk, Handed::Right).ok();
let left = SkController::new(Handed::Left).ok();
let right = SkController::new(Handed::Right).ok();
left.zip(right)
})
.flatten();
@@ -194,63 +189,51 @@ fn main() {
let _tokio_handle = event_loop_info.tokio_handle.enter();
#[cfg(feature = "wayland")]
let mut wayland = Some(wayland::Wayland::new().expect("Could not initialize wayland"));
let mut wayland = wayland::Wayland::new().unwrap();
info!("Stardust ready!");
let mut startup_child = if let Some(project_dirs) = project_dirs.as_ref() {
if let Some(project_dirs) = project_dirs.as_ref() {
let startup_script_path = cli_args
.startup_script
.clone()
.and_then(|p| p.canonicalize().ok())
.unwrap_or_else(|| project_dirs.config_dir().join("startup"));
let mut startup_command = Command::new(startup_script_path);
startup_command.stdin(Stdio::null());
startup_command.env(
"FLAT_WAYLAND_DISPLAY",
std::env::var_os("WAYLAND_DISPLAY").unwrap_or_default(),
);
startup_command.env(
"STARDUST_INSTANCE",
event_loop_info
.socket_path
.file_name()
.expect("Stardust socket path not found"),
);
#[cfg(feature = "wayland")]
{
startup_command.env("WAYLAND_DISPLAY", &wayland.as_ref().unwrap().socket_name);
#[cfg(feature = "xwayland")]
startup_command.env(
"DISPLAY",
format!(":{}", wayland.as_ref().unwrap().xwayland_state.display),
);
startup_command.env("GDK_BACKEND", "wayland");
startup_command.env("QT_QPA_PLATFORM", "wayland");
startup_command.env("MOZ_ENABLE_WAYLAND", "1");
startup_command.env("CLUTTER_BACKEND", "wayland");
startup_command.env("SDL_VIDEODRIVER", "wayland");
}
startup_command.spawn().ok()
} else {
None
};
let _startup = Command::new(startup_script_path)
.stdin(Stdio::null())
.env(
"FLAT_WAYLAND_DISPLAY",
std::env::var_os("WAYLAND_DISPLAY").unwrap_or_default(),
)
.env("WAYLAND_DISPLAY", &wayland.socket_name)
.env(
"STARDUST_INSTANCE",
event_loop_info
.socket_path
.file_name()
.expect("Stardust socket path not found"),
)
.env("GDK_BACKEND", "wayland")
.env("QT_QPA_PLATFORM", "wayland")
.env("MOZ_ENABLE_WAYLAND", "1")
.env("CLUTTER_BACKEND", "wayland")
.env("SDL_VIDEODRIVER", "wayland")
.spawn();
}
let mut last_frame_delta = Duration::ZERO;
let mut sleep_duration = Duration::ZERO;
debug_span!("StereoKit").in_scope(|| {
sk.run_stateful(
&mut wayland,
move |wayland, _, sk| {
sk.run(
|sk| {
let _span = debug_span!("StereoKit step");
let _span = _span.enter();
hmd::frame(sk);
#[cfg(feature = "wayland")]
wayland.as_mut().unwrap().frame_event(sk);
wayland.frame_event(sk);
destroy_queue::clear();
if let Some(mouse_pointer) = &mut mouse_pointer {
if let Some(mouse_pointer) = &mouse_pointer {
mouse_pointer.update(sk);
}
if let Some((left_hand, right_hand)) = &mut hands {
@@ -277,33 +260,26 @@ fn main() {
);
#[cfg(feature = "wayland")]
wayland.as_mut().unwrap().update(sk);
wayland.update(sk);
drawable::draw(sk);
audio::update(sk);
#[cfg(feature = "wayland")]
wayland.as_mut().unwrap().make_context_current();
wayland.make_context_current();
},
|wayland, _sk| {
|_| {
info!("Cleanly shut down StereoKit");
if let Some(mut startup_child) = startup_child.take() {
let _ = startup_child.kill();
}
#[cfg(feature = "wayland")]
wayland.take();
},
)
});
#[cfg(feature = "wayland")]
let _wayland = ManuallyDrop::new(wayland);
let _ = event_stop_tx.send(());
event_thread
.join()
.expect("Failed to cleanly shut down event loop")
.unwrap();
// #[cfg(feature = "wayland")]
// let _wayland = ManuallyDrop::new(wayland);
info!("Cleanly shut down Stardust");
}

View File

@@ -1,4 +1,4 @@
use super::{Message, Node};
use super::Node;
use crate::core::client::Client;
use crate::core::destroy_queue;
use crate::core::registry::Registry;
@@ -83,13 +83,13 @@ impl Sound {
}
}
fn play_flex(node: &Node, _calling_client: Arc<Client>, _message: Message) -> Result<()> {
fn play_flex(node: &Node, _calling_client: Arc<Client>, _data: &[u8]) -> Result<()> {
let sound = node.sound.get().unwrap();
sound.play.lock().replace(());
Ok(())
}
pub fn stop_flex(node: &Node, _calling_client: Arc<Client>, _message: Message) -> Result<()> {
pub fn stop_flex(node: &Node, _calling_client: Arc<Client>, _data: &[u8]) -> Result<()> {
let sound = node.sound.get().unwrap();
sound.stop.lock().replace(());
Ok(())
@@ -108,7 +108,7 @@ pub fn create_interface(client: &Arc<Client>) -> Result<()> {
node.add_to_scenegraph().map(|_| ())
}
pub fn create_flex(_node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
pub fn create_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
#[derive(Deserialize)]
struct CreateSoundInfo<'a> {
name: &'a str,
@@ -116,7 +116,7 @@ pub fn create_flex(_node: &Node, calling_client: Arc<Client>, message: Message)
transform: Transform,
resource: ResourceID,
}
let info: CreateSoundInfo = deserialize(message.as_ref())?;
let info: CreateSoundInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/audio/sound", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, true);

View File

@@ -1,7 +1,7 @@
use super::alias::AliasInfo;
use super::fields::Field;
use super::spatial::{parse_transform, Spatial};
use super::{Alias, Message, Node};
use super::{Alias, Node};
use crate::core::client::Client;
use crate::core::node_collections::LifeLinkedNodeMap;
use crate::core::registry::Registry;
@@ -24,7 +24,7 @@ pub fn mask_matches(mask_map_lesser: &Mask, mask_map_greater: &Mask) -> bool {
for key in mask_map_lesser.get_mask()?.iter_keys() {
let lesser_key = mask_map_lesser.get_mask()?.index(key)?;
let greater_key = mask_map_greater.get_mask()?.index(key)?;
if lesser_key.flexbuffer_type() != greater_key.flexbuffer_type() {
if lesser_key.to_string() != greater_key.to_string() {
return Err(flexbuffers::ReaderError::InvalidPackedType {}.into());
}
}
@@ -85,9 +85,9 @@ impl PulseSender {
if !mask_matches(&self.mask, &receiver.mask) {
return;
}
let Some(tx_node) = self.node.upgrade() else {return};
let Some(tx_client) = tx_node.get_client() else {return};
let Some(rx_node) = receiver.node.upgrade() else {return};
let Some(tx_node) = self.node.upgrade() else { return };
let Some(tx_client) = tx_node.get_client() else { return };
let Some(rx_node) = receiver.node.upgrade() else { return };
// Receiver itself
let rx_alias = Alias::create(
&tx_client,
@@ -142,7 +142,7 @@ impl PulseSender {
};
let Ok(data) = serialize(info) else {return};
let _ = tx_node.send_remote_signal("new_receiver", data);
let _ = tx_node.send_remote_signal("new_receiver", &data);
}
fn handle_drop_receiver(&self, receiver: &PulseReceiver) {
@@ -151,11 +151,11 @@ impl PulseSender {
self.aliases.remove(&(uid.to_string() + "-field"));
let Some(tx_node) = self.node.upgrade() else {return};
let Ok(data) = serialize(&uid) else {return};
let _ = tx_node.send_remote_signal("drop_receiver", data);
let _ = tx_node.send_remote_signal("drop_receiver", &data);
}
fn send_data_flex(node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
let info: SendDataInfo = deserialize(message.as_ref())?;
fn send_data_flex(node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let info: SendDataInfo = deserialize(data)?;
let receiver_node = calling_client.get_node("Pulse receiver", info.uid)?;
let receiver =
receiver_node.get_aspect("Pulse Receiver", "pulse receiver", |n| &n.pulse_receiver)?;
@@ -210,7 +210,7 @@ impl PulseReceiver {
pub fn send_data(&self, uid: &str, data: Vec<u8>) -> Result<()> {
if let Some(node) = self.node.upgrade() {
node.send_remote_signal("data", serialize(SendDataInfo { uid, data })?)?;
node.send_remote_signal("data", &serialize(SendDataInfo { uid, data })?)?;
}
Ok(())
}
@@ -235,7 +235,7 @@ pub fn create_interface(client: &Arc<Client>) -> Result<()> {
pub fn create_pulse_sender_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
#[derive(Deserialize)]
struct CreatePulseSenderInfo<'a> {
@@ -244,7 +244,7 @@ pub fn create_pulse_sender_flex(
transform: Transform,
mask: Vec<u8>,
}
let info: CreatePulseSenderInfo = deserialize(message.as_ref())?;
let info: CreatePulseSenderInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/data/sender", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, false);
@@ -261,7 +261,7 @@ pub fn create_pulse_sender_flex(
pub fn create_pulse_receiver_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
#[derive(Deserialize)]
struct CreatePulseReceiverInfo<'a> {
@@ -271,7 +271,7 @@ pub fn create_pulse_receiver_flex(
field_path: &'a str,
mask: Vec<u8>,
}
let info: CreatePulseReceiverInfo = deserialize(message.as_ref())?;
let info: CreatePulseReceiverInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/data/receiver", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, false);

View File

@@ -2,7 +2,7 @@ use crate::{
core::{client::Client, registry::Registry},
nodes::{
spatial::{find_spatial_parent, parse_transform, Spatial},
Message, Node,
Node,
},
};
use color_eyre::eyre::{bail, ensure, Result};
@@ -97,14 +97,10 @@ impl Lines {
draw_ctx.line_add_listv(points.make_contiguous());
}
pub fn set_points_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
pub fn set_points_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let Some(Drawable::Lines(lines)) = node.drawable.get() else {bail!("Not a drawable??")};
let mut points: Vec<LinePointRaw> = deserialize(message.as_ref())?;
let mut points: Vec<LinePointRaw> = deserialize(data)?;
for p in &mut points {
p.color[0] = p.color[0].powf(2.2);
p.color[1] = p.color[1].powf(2.2);
@@ -113,14 +109,10 @@ impl Lines {
lines.data.lock().points = points;
Ok(())
}
pub fn set_cyclic_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
pub fn set_cyclic_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let Some(Drawable::Lines(lines)) = node.drawable.get() else {bail!("Not a drawable??")};
lines.data.lock().cyclic = deserialize(message.as_ref())?;
lines.data.lock().cyclic = deserialize(data)?;
Ok(())
}
}
@@ -138,7 +130,7 @@ pub fn draw_all(draw_ctx: &impl StereoKitDraw) {
}
}
pub fn create_flex(_node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
pub fn create_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
#[derive(Deserialize)]
struct CreateTextInfo<'a> {
name: &'a str,
@@ -147,7 +139,7 @@ pub fn create_flex(_node: &Node, calling_client: Arc<Client>, message: Message)
points: Vec<LinePointRaw>,
cyclic: bool,
}
let mut info: CreateTextInfo = deserialize(message.as_ref())?;
let mut info: CreateTextInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/drawable/lines", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, true);

View File

@@ -9,7 +9,7 @@ use self::{
text::Text,
};
use super::{Message, Node};
use super::Node;
use crate::core::client::Client;
use color_eyre::eyre::Result;
use parking_lot::Mutex;
@@ -56,14 +56,14 @@ pub fn draw(sk: &impl StereoKitDraw) {
static QUEUED_SKYLIGHT: Mutex<Option<PathBuf>> = Mutex::new(None);
static QUEUED_SKYTEX: Mutex<Option<PathBuf>> = Mutex::new(None);
fn set_sky_file_flex(_node: &Node, _calling_client: Arc<Client>, message: Message) -> Result<()> {
fn set_sky_file_flex(_node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
#[derive(Deserialize)]
struct SkyFileInfo {
path: PathBuf,
skytex: Option<bool>,
skylight: Option<bool>,
}
let info: SkyFileInfo = deserialize(message.as_ref())?;
let info: SkyFileInfo = deserialize(data)?;
info.path.metadata()?;
if info.skytex.unwrap_or_default() {
QUEUED_SKYTEX.lock().replace(info.path.clone());

View File

@@ -5,7 +5,6 @@ use crate::core::registry::Registry;
use crate::core::resource::ResourceID;
use crate::nodes::drawable::Drawable;
use crate::nodes::spatial::{find_spatial_parent, parse_transform, Spatial};
use crate::nodes::Message;
use crate::SK_MULTITHREAD;
use color_eyre::eyre::{bail, ensure, eyre, Result};
use glam::Mat4;
@@ -214,11 +213,11 @@ impl ModelPart {
fn set_material_parameter_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
let Some(Drawable::ModelPart(model_part)) = node.drawable.get() else {bail!("Not a drawable??")};
let (name, value): (String, MaterialParameter) = deserialize(message.as_ref())?;
let (name, value): (String, MaterialParameter) = deserialize(data)?;
model_part
.pending_material_parameters
@@ -343,7 +342,7 @@ pub fn draw_all(sk: &impl StereoKitDraw) {
}
}
pub fn create_flex(_node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
pub fn create_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
#[derive(Deserialize)]
struct CreateModelInfo<'a> {
name: &'a str,
@@ -351,7 +350,7 @@ pub fn create_flex(_node: &Node, calling_client: Arc<Client>, message: Message)
transform: Transform,
resource: ResourceID,
}
let info: CreateModelInfo = deserialize(message.as_ref())?;
let info: CreateModelInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/drawable/model", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, true);

View File

@@ -3,7 +3,7 @@ use crate::{
nodes::{
drawable::Drawable,
spatial::{find_spatial_parent, parse_transform, Spatial},
Message, Node,
Node,
},
};
use color_eyre::eyre::{bail, ensure, eyre, Result};
@@ -151,22 +151,18 @@ impl Text {
pub fn set_character_height_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
let Some(Drawable::Text(text)) = node.drawable.get() else {bail!("Not a drawable??")};
text.data.lock().character_height = deserialize(message.as_ref())?;
text.data.lock().character_height = deserialize(data)?;
Ok(())
}
pub fn set_text_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
pub fn set_text_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let Some(Drawable::Text(text)) = node.drawable.get() else {bail!("Not a drawable??")};
text.data.lock().text = deserialize(message.as_ref())?;
text.data.lock().text = deserialize(data)?;
Ok(())
}
}
@@ -187,7 +183,7 @@ pub fn draw_all(sk: &impl StereoKitDraw) {
}
}
pub fn create_flex(_node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
pub fn create_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
#[derive(Deserialize)]
struct CreateTextInfo<'a> {
name: &'a str,
@@ -202,7 +198,7 @@ pub fn create_flex(_node: &Node, calling_client: Arc<Client>, message: Message)
bounds_align: TextAlign,
color: [f32; 4],
}
let info: CreateTextInfo = deserialize(message.as_ref())?;
let info: CreateTextInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/drawable/text", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, true);

View File

@@ -1,7 +1,6 @@
use super::{Field, FieldTrait, Node};
use crate::core::client::Client;
use crate::nodes::spatial::{find_spatial_parent, parse_transform, Spatial};
use crate::nodes::Message;
use color_eyre::eyre::{ensure, Result};
use glam::{vec3, vec3a, Vec3, Vec3A};
use mint::Vector3;
@@ -41,13 +40,9 @@ impl BoxField {
*self.size.lock() = size.into();
}
pub fn set_size_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
pub fn set_size_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let Field::Box(box_field) = node.field.get().unwrap().as_ref() else { return Ok(()) };
box_field.set_size(deserialize(message.as_ref())?);
box_field.set_size(deserialize(data)?);
Ok(())
}
@@ -69,11 +64,7 @@ impl FieldTrait for BoxField {
}
}
pub fn create_box_field_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
pub fn create_box_field_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
#[derive(Deserialize)]
struct CreateFieldInfo<'a> {
name: &'a str,
@@ -81,7 +72,7 @@ pub fn create_box_field_flex(
transform: Transform,
size: Vector3<f32>,
}
let info: CreateFieldInfo = deserialize(message.as_ref())?;
let info: CreateFieldInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/field", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, false);

View File

@@ -1,7 +1,6 @@
use super::{Field, FieldTrait, Node};
use crate::core::client::Client;
use crate::nodes::spatial::{find_spatial_parent, parse_transform, Spatial};
use crate::nodes::Message;
use color_eyre::eyre::{ensure, Result};
use glam::{swizzles::*, vec2, Vec3A};
use portable_atomic::AtomicF32;
@@ -44,13 +43,9 @@ impl CylinderField {
self.radius.store(radius.abs(), Ordering::Relaxed);
}
pub fn set_size_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
pub fn set_size_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let Field::Cylinder(cylinder_field) = node.field.get().unwrap().as_ref() else { return Ok(()) };
let (length, radius) = deserialize(message.as_ref())?;
let (length, radius) = deserialize(data)?;
cylinder_field.set_size(length, radius);
Ok(())
}
@@ -72,7 +67,7 @@ impl FieldTrait for CylinderField {
pub fn create_cylinder_field_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
#[derive(Deserialize)]
struct CreateFieldInfo<'a> {
@@ -82,7 +77,7 @@ pub fn create_cylinder_field_flex(
length: f32,
radius: f32,
}
let info: CreateFieldInfo = deserialize(message.as_ref())?;
let info: CreateFieldInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/field", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, false);

View File

@@ -10,7 +10,7 @@ use self::torus::{create_torus_field_flex, TorusField};
use super::alias::AliasInfo;
use super::spatial::Spatial;
use super::{Message, Node};
use super::Node;
use crate::core::client::Client;
use crate::nodes::spatial::find_reference_space;
use color_eyre::eyre::Result;
@@ -133,17 +133,13 @@ const MAX_RAY_MARCH: f32 = f32::MAX;
// const MIN_RAY_LENGTH: f32 = 0_f32;
const MAX_RAY_LENGTH: f32 = 1000_f32;
fn field_distance_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<Message> {
fn field_distance_flex(node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<Vec<u8>> {
#[derive(Deserialize)]
struct FieldInfoArgs<'a> {
reference_space_path: &'a str,
point: Vector3<f32>,
}
let args: FieldInfoArgs = deserialize(message.as_ref())?;
let args: FieldInfoArgs = deserialize(data)?;
let reference_space = find_reference_space(&calling_client, args.reference_space_path)?;
let distance = node
@@ -151,20 +147,16 @@ fn field_distance_flex(
.get()
.unwrap()
.distance(reference_space.as_ref(), args.point.into());
Ok(serialize(distance)?.into())
Ok(serialize(distance)?)
}
fn field_normal_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<Message> {
fn field_normal_flex(node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<Vec<u8>> {
#[derive(Deserialize)]
struct FieldInfoArgs<'a> {
reference_space_path: &'a str,
point: Vector3<f32>,
radius: Option<f32>,
}
let args: FieldInfoArgs = deserialize(message.as_ref())?;
let args: FieldInfoArgs = deserialize(data)?;
let reference_space = find_reference_space(&calling_client, args.reference_space_path)?;
let normal = node.field.get().as_ref().unwrap().normal(
@@ -172,20 +164,20 @@ fn field_normal_flex(
args.point.into(),
args.radius.unwrap_or(0.001),
);
Ok(serialize(mint::Vector3::from(normal))?.into())
Ok(serialize(mint::Vector3::from(normal))?)
}
fn field_closest_point_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<Message> {
data: &[u8],
) -> Result<Vec<u8>> {
#[derive(Deserialize)]
struct FieldInfoArgs<'a> {
reference_space_path: &'a str,
point: Vector3<f32>,
radius: Option<f32>,
}
let args: FieldInfoArgs = deserialize(message.as_ref())?;
let args: FieldInfoArgs = deserialize(data)?;
let reference_space = find_reference_space(&calling_client, args.reference_space_path)?;
let closest_point = node.field.get().as_ref().unwrap().closest_point(
@@ -193,20 +185,16 @@ fn field_closest_point_flex(
args.point.into(),
args.radius.unwrap_or(0.001),
);
Ok(serialize(mint::Vector3::from(closest_point))?.into())
Ok(serialize(mint::Vector3::from(closest_point))?)
}
fn field_ray_march_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<Message> {
fn field_ray_march_flex(node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<Vec<u8>> {
#[derive(Deserialize)]
struct FieldInfoArgs<'a> {
reference_space_path: &'a str,
ray_origin: Vector3<f32>,
ray_direction: Vector3<f32>,
}
let args: FieldInfoArgs = deserialize(message.as_ref())?;
let args: FieldInfoArgs = deserialize(data)?;
let reference_space = find_reference_space(&calling_client, args.reference_space_path)?;
let ray_march_result = node.field.get().unwrap().ray_march(Ray {
@@ -214,7 +202,7 @@ fn field_ray_march_flex(
direction: args.ray_direction.into(),
space: reference_space,
});
Ok(serialize(ray_march_result)?.into())
Ok(serialize(ray_march_result)?)
}
pub enum Field {

View File

@@ -1,7 +1,6 @@
use super::{Field, FieldTrait, Node};
use crate::core::client::Client;
use crate::nodes::spatial::{find_spatial_parent, Spatial};
use crate::nodes::Message;
use color_eyre::eyre::{ensure, Result};
use glam::{Mat4, Vec3A};
use mint::Vector3;
@@ -40,13 +39,9 @@ impl SphereField {
self.radius.store(radius, Ordering::Relaxed);
}
pub fn set_radius_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
pub fn set_radius_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let Field::Sphere(sphere_field) = node.field.get().unwrap().as_ref() else { return Ok(()) };
sphere_field.set_radius(deserialize(message.as_ref())?);
sphere_field.set_radius(deserialize(data)?);
Ok(())
}
}
@@ -69,7 +64,7 @@ impl FieldTrait for SphereField {
pub fn create_sphere_field_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
#[derive(Deserialize)]
struct CreateFieldInfo<'a> {
@@ -78,7 +73,7 @@ pub fn create_sphere_field_flex(
origin: Option<Vector3<f32>>,
radius: f32,
}
let info: CreateFieldInfo = deserialize(message.as_ref())?;
let info: CreateFieldInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/field", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = Mat4::from_translation(

View File

@@ -1,7 +1,6 @@
use super::{Field, FieldTrait, Node};
use crate::core::client::Client;
use crate::nodes::spatial::{find_spatial_parent, parse_transform, Spatial};
use crate::nodes::Message;
use color_eyre::eyre::{ensure, Result};
use glam::{swizzles::*, vec2, Vec3A};
use portable_atomic::AtomicF32;
@@ -44,13 +43,9 @@ impl TorusField {
self.radius_b.store(radius_b.abs(), Ordering::Relaxed);
}
pub fn set_size_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
pub fn set_size_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let Field::Torus(torus_field) = node.field.get().unwrap().as_ref() else { return Ok(()) };
let (radius_a, radius_b) = deserialize(message.as_ref())?;
let (radius_a, radius_b) = deserialize(data)?;
torus_field.set_size(radius_a, radius_b);
Ok(())
@@ -72,7 +67,7 @@ impl FieldTrait for TorusField {
pub fn create_torus_field_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
#[derive(Deserialize)]
struct CreateFieldInfo<'a> {
@@ -82,7 +77,7 @@ pub fn create_torus_field_flex(
radius_a: f32,
radius_b: f32,
}
let info: CreateFieldInfo = deserialize(message.as_ref())?;
let info: CreateFieldInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/field", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, false);

View File

@@ -10,7 +10,7 @@ use super::{
alias::{Alias, AliasInfo},
fields::{find_field, Field, FIELD_ALIAS_INFO},
spatial::{find_spatial_parent, parse_transform, Spatial},
Message, Node,
Node,
};
use crate::core::{client::Client, node_collections::LifeLinkedNodeMap};
use crate::core::{node_collections::LifeLinkedNodeList, registry::Registry};
@@ -109,21 +109,21 @@ impl InputMethod {
.cloned()
}
fn capture_flex(node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
fn capture_flex(node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let method = InputMethod::get(node)?;
let handler = InputHandler::find(&calling_client, deserialize(message.as_ref())?)?;
let handler = InputHandler::find(&calling_client, deserialize(data)?)?;
method.captures.add_raw(&handler);
node.send_remote_signal("capture", message)
node.send_remote_signal("capture", data)
}
fn set_datamap_flex(node: &Node, _calling_client: Arc<Client>, message: Message) -> Result<()> {
fn set_datamap_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let method = InputMethod::get(node)?;
method.datamap.lock().replace(Datamap::new(message.data)?);
method.datamap.lock().replace(Datamap::new(data.to_vec())?);
Ok(())
}
fn set_handlers_flex(node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
fn set_handlers_flex(node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let method = InputMethod::get(node)?;
let handler_paths: Vec<&str> = deserialize(message.as_ref())?;
let handler_paths: Vec<&str> = deserialize(data)?;
let handlers: Vec<Weak<InputHandler>> = handler_paths
.into_iter()
.filter_map(|p| InputHandler::find(&calling_client, p).ok())
@@ -147,9 +147,9 @@ impl InputMethod {
}
fn handle_new_handler(&self, handler: &InputHandler) {
let Some(method_node) = self.node.upgrade() else {return};
let Some(method_client) = method_node.get_client() else {return};
let Some(handler_node) = handler.node.upgrade() else {return};
let Some(method_node) = self.node.upgrade() else { return };
let Some(method_client) = method_node.get_client() else { return };
let Some(handler_node) = handler.node.upgrade() else { return };
// Receiver itself
let Ok(handler_alias) = Alias::create(
&method_client,
@@ -178,7 +178,7 @@ impl InputMethod {
}
let Ok(data) = serialize(&handler.uid) else {return};
let _ = method_node.send_remote_signal("handler_created", data);
let _ = method_node.send_remote_signal("handler_created", &data);
}
fn handle_drop_handler(&self, handler: &InputHandler) {
let uid = handler.uid.as_str();
@@ -186,7 +186,7 @@ impl InputMethod {
self.handler_aliases.remove(&(uid.to_string() + "-field"));
let Some(tx_node) = self.node.upgrade() else {return};
let Ok(data) = serialize(&uid) else {return};
let _ = tx_node.send_remote_signal("handler_destroyed", data);
let _ = tx_node.send_remote_signal("handler_destroyed", &data);
}
}
impl Drop for InputMethod {
@@ -284,7 +284,7 @@ impl InputHandler {
#[instrument(level = "debug", skip(self, distance_link))]
fn send_input(&self, order: u32, distance_link: &DistanceLink, datamap: Datamap) {
let Some(node) = self.node.upgrade() else {return};
let _ = node.send_remote_signal("input", distance_link.serialize(order, datamap));
let _ = node.send_remote_signal("input", &distance_link.serialize(order, datamap));
}
}
impl PartialEq for InputHandler {
@@ -312,7 +312,7 @@ pub fn create_interface(client: &Arc<Client>) -> Result<()> {
pub fn create_input_handler_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
#[derive(Deserialize)]
struct CreateInputHandlerInfo<'a> {
@@ -321,7 +321,7 @@ pub fn create_input_handler_flex(
transform: Transform,
field_path: &'a str,
}
let info: CreateInputHandlerInfo = deserialize(message.as_ref())?;
let info: CreateInputHandlerInfo = deserialize(data)?;
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, true);
let field = find_field(&calling_client, info.field_path)?;

View File

@@ -3,7 +3,7 @@ use crate::core::client::Client;
use crate::nodes::fields::{Field, Ray, RayMarchResult};
use crate::nodes::input::{InputMethod, InputType};
use crate::nodes::spatial::{find_spatial_parent, parse_transform, Spatial};
use crate::nodes::{Message, Node};
use crate::nodes::Node;
use glam::{vec3, Mat4};
use serde::Deserialize;
use stardust_xr::schemas::flat::{Datamap, InputDataType, Pointer as FlatPointer};
@@ -63,7 +63,7 @@ impl InputSpecialization for Pointer {
pub fn create_pointer_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> color_eyre::eyre::Result<()> {
#[derive(Deserialize)]
struct CreatePointerInfo<'a> {
@@ -72,7 +72,7 @@ pub fn create_pointer_flex(
transform: Transform,
datamap: Option<Vec<u8>>,
}
let info: CreatePointerInfo = deserialize(message.as_ref())?;
let info: CreatePointerInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/input/method/pointer", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, false);

View File

@@ -3,7 +3,7 @@ use crate::core::client::Client;
use crate::nodes::fields::Field;
use crate::nodes::input::{InputMethod, InputType};
use crate::nodes::spatial::{find_spatial_parent, parse_transform, Spatial};
use crate::nodes::{Message, Node};
use crate::nodes::Node;
use color_eyre::eyre::Result;
use glam::{vec3a, Mat4};
use serde::Deserialize;
@@ -17,9 +17,9 @@ pub struct Tip {
pub radius: f32,
}
impl Tip {
fn set_radius(node: &Node, _calling_client: Arc<Client>, message: Message) -> Result<()> {
fn set_radius(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
if let InputType::Tip(tip) = &mut *node.input_method.get().unwrap().specialization.lock() {
tip.radius = deserialize(message.as_ref())?;
tip.radius = deserialize(data)?;
}
Ok(())
}
@@ -45,7 +45,7 @@ impl InputSpecialization for Tip {
}
}
pub fn create_tip_flex(_node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
pub fn create_tip_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
#[derive(Deserialize)]
struct CreateTipInfo<'a> {
name: &'a str,
@@ -54,7 +54,7 @@ pub fn create_tip_flex(_node: &Node, calling_client: Arc<Client>, message: Messa
radius: f32,
datamap: Option<Vec<u8>>,
}
let info: CreateTipInfo = deserialize(message.as_ref())?;
let info: CreateTipInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/input/method/tip", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, false);

View File

@@ -1,4 +1,4 @@
use super::{Item, ItemType};
use super::{Item, ItemSpecialization, ItemType};
use crate::{
core::{
client::{Client, INTERNAL_CLIENT},
@@ -7,7 +7,7 @@ use crate::{
nodes::{
items::TypeInfo,
spatial::{find_spatial_parent, parse_transform, Spatial},
Message, Node,
Node,
},
};
use color_eyre::eyre::{eyre, Result};
@@ -15,7 +15,7 @@ use lazy_static::lazy_static;
use nanoid::nanoid;
use serde::Deserialize;
use stardust_xr::{
schemas::flex::{deserialize, serialize},
schemas::flex::{deserialize, flexbuffers, serialize},
values::Transform,
};
use std::sync::Arc;
@@ -46,26 +46,23 @@ impl EnvironmentItem {
node.add_local_method("get_path", EnvironmentItem::get_path_flex);
}
fn get_path_flex(
node: &Node,
_calling_client: Arc<Client>,
_message: Message,
) -> Result<Message> {
fn get_path_flex(node: &Node, _calling_client: Arc<Client>, _data: &[u8]) -> Result<Vec<u8>> {
let ItemType::Environment(environment_item) = &node.item.get().unwrap().specialization else {
return Err(eyre!("Wrong item type?"))
};
Ok(serialize(environment_item.path.as_str())?.into())
Ok(flexbuffers::singleton(environment_item.path.as_str()))
}
pub fn serialize_start_data(&self, id: &str) -> Result<Message> {
Ok(serialize((id, self.path.as_str()))?.into())
}
impl ItemSpecialization for EnvironmentItem {
fn serialize_start_data(&self, id: &str) -> Vec<u8> {
serialize((id, self.path.as_str())).unwrap()
}
}
pub(super) fn create_environment_item_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
#[derive(Deserialize)]
struct CreateEnvironmentItemInfo<'a> {
@@ -74,7 +71,7 @@ pub(super) fn create_environment_item_flex(
transform: Transform,
item_data: String,
}
let info: CreateEnvironmentItemInfo = deserialize(message.as_ref())?;
let info: CreateEnvironmentItemInfo = deserialize(data)?;
let parent_name = format!("/item/{}/item", ITEM_TYPE_INFO_ENVIRONMENT.type_name);
let space = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, false);

View File

@@ -1,25 +1,26 @@
mod environment;
pub mod panel;
use self::environment::{EnvironmentItem, ITEM_TYPE_INFO_ENVIRONMENT};
use self::panel::{PanelItemTrait, ITEM_TYPE_INFO_PANEL};
use super::fields::Field;
use super::spatial::{find_spatial_parent, parse_transform, Spatial};
use super::{Alias, Message, Node};
use super::{Alias, Node};
use crate::core::client::Client;
use crate::core::node_collections::LifeLinkedNodeMap;
use crate::core::registry::Registry;
use crate::nodes::alias::AliasInfo;
use crate::nodes::fields::find_field;
#[cfg(feature = "wayland")]
use crate::wayland::panel_item::{PanelItem, ITEM_TYPE_INFO_PANEL};
use color_eyre::eyre::{ensure, eyre, Result};
use lazy_static::lazy_static;
use nanoid::nanoid;
use parking_lot::Mutex;
use portable_atomic::Ordering;
use serde::Deserialize;
use stardust_xr::schemas::flex::{deserialize, serialize};
use stardust_xr::schemas::flex::{deserialize, flexbuffers, serialize};
use stardust_xr::values::Transform;
use std::hash::Hash;
use std::ops::Deref;
use std::sync::{Arc, Weak};
lazy_static! {
@@ -153,7 +154,7 @@ impl Item {
self.make_alias_named(client, parent, &self.uid)
}
fn release_flex(node: &Node, _calling_client: Arc<Client>, _message: Message) -> Result<()> {
fn release_flex(node: &Node, _calling_client: Arc<Client>, _data: &[u8]) -> Result<()> {
let item = node.get_aspect("Item", "item", |n| &n.item)?;
release(item, None);
@@ -170,28 +171,26 @@ impl Drop for Item {
}
}
pub trait ItemSpecialization {
fn serialize_start_data(&self, id: &str) -> Vec<u8>;
}
pub enum ItemType {
Environment(EnvironmentItem),
Panel(Arc<dyn PanelItemTrait>),
#[cfg(feature = "wayland")]
Panel(Arc<PanelItem>),
}
impl ItemType {
fn serialize_start_data(&self, id: &str) -> Result<Message> {
impl Deref for ItemType {
type Target = dyn ItemSpecialization;
fn deref(&self) -> &Self::Target {
match self {
ItemType::Environment(e) => e.serialize_start_data(id),
ItemType::Panel(p) => p.serialize_start_data(id),
ItemType::Environment(item) => item,
#[cfg(feature = "wayland")]
ItemType::Panel(item) => item.as_ref(),
}
}
}
// impl Deref for ItemType {
// type Target = dyn ItemSpecialization;
// fn deref(&self) -> &Self::Target {
// match self {
// ItemType::Environment(item) => item,
// ItemType::Panel(item) => item.as_ref(),
// }
// }
// }
pub struct ItemUI {
node: Weak<Node>,
@@ -226,44 +225,49 @@ impl ItemUI {
Ok(())
}
fn send_state(&self, state: &str, name: &str) {
let Ok(serialized_data) = serialize(name) else {return};
let _ = self
.node
.upgrade()
.unwrap()
.send_remote_signal(state, serialized_data);
.send_remote_signal(state, flexbuffers::singleton(name).as_slice());
}
fn handle_create_item(&self, item: &Item) {
let Some(node) = self.node.upgrade() else {return};
let Some(client) = node.get_client() else {return};
let Some(node) = self.node.upgrade() else { return };
let Some(client) = node.get_client() else { return };
if let Ok(alias_node) = item.make_alias(&client, &(node.get_path().to_string() + "/item")) {
self.item_aliases.add(item.uid.clone(), &alias_node);
}
let Ok(serialized_data) = item.specialization.serialize_start_data(&item.uid) else {return};
let _ = node.send_remote_signal("create_item", serialized_data);
let _ = node.send_remote_signal(
"create_item",
&item.specialization.serialize_start_data(&item.uid),
);
}
fn handle_destroy_item(&self, item: &Item) {
self.item_aliases.remove(&item.uid);
self.send_state("destroy_item", item.uid.as_str());
}
fn handle_capture_item(&self, item: &Item, acceptor: &ItemAcceptor) {
let Some(node) = self.node.upgrade() else {return};
let Some(node) = self.node.upgrade() else { return };
let Ok(message) = serialize((item.uid.as_str(), acceptor.uid.as_str())) else {return};
let _ = node.send_remote_signal("capture_item", message);
let _ = node.send_remote_signal(
"capture_item",
&serialize((item.uid.as_str(), acceptor.uid.as_str())).unwrap(),
);
}
fn handle_release_item(&self, item: &Item, acceptor: &ItemAcceptor) {
let Some(node) = self.node.upgrade() else {return};
let Some(node) = self.node.upgrade() else { return };
let Ok(message) = serialize((item.uid.as_str(), acceptor.uid.as_str())) else {return};
let _ = node.send_remote_signal("release_item", message);
let _ = node.send_remote_signal(
"release_item",
&serialize((item.uid.as_str(), acceptor.uid.as_str())).unwrap(),
);
}
fn handle_create_acceptor(&self, acceptor: &ItemAcceptor) {
let Some(node) = self.node.upgrade() else {return};
let Some(client) = node.get_client() else {return};
let Some(node) = self.node.upgrade() else { return };
let Some(client) = node.get_client() else { return };
let Ok((alias, field_alias)) = acceptor.make_aliases(
&client,
@@ -272,8 +276,7 @@ impl ItemUI {
self.acceptor_aliases.add(acceptor.uid.clone(), &alias);
self.acceptor_field_aliases
.add(acceptor.uid.clone(), &field_alias);
let Ok(message) = serialize(&acceptor.uid) else {return};
let _ = node.send_remote_signal("create_acceptor", message);
let _ = node.send_remote_signal("create_acceptor", &serialize(&acceptor.uid).unwrap());
}
fn handle_destroy_acceptor(&self, acceptor: &ItemAcceptor) {
self.send_state("destroy_acceptor", acceptor.uid.as_str());
@@ -312,13 +315,13 @@ impl ItemAcceptor {
let _ = node.item_acceptor.set(acceptor);
}
fn capture_flex(node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
fn capture_flex(node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
if !node.enabled.load(Ordering::Relaxed) {
return Ok(());
}
let acceptor = node.item_acceptor.get().unwrap();
let item_path: &str = deserialize(message.as_ref())?;
let item_path: &str = deserialize(data)?;
let item_node = calling_client.get_node("Item", item_path)?;
let item = item_node.get_aspect("Item", "item", |n| &n.item)?;
capture(item, acceptor);
@@ -350,24 +353,24 @@ impl ItemAcceptor {
Ok((acceptor_alias, acceptor_field_alias))
}
fn handle_capture(&self, item: &Arc<Item>) {
let Some(node) = self.node.upgrade() else {return};
let Some(client) = node.get_client() else {return};
let Some(node) = self.node.upgrade() else { return };
let Some(client) = node.get_client() else { return };
self.accepted_registry.add_raw(item);
if let Ok(alias_node) = item.make_alias(&client, &node.path) {
self.accepted_aliases.add(item.uid.clone(), &alias_node);
}
let Ok(serialized_data) = item.specialization.serialize_start_data(&item.uid) else {return};
let _ = node.send_remote_signal("capture", serialized_data);
let _ = node.send_remote_signal(
"capture",
&item.specialization.serialize_start_data(&item.uid),
);
}
fn handle_release(&self, item: &Item) {
let Some(node) = self.node.upgrade() else {return};
let Some(node) = self.node.upgrade() else { return };
self.accepted_registry.remove(item);
self.accepted_aliases.remove(&item.uid);
let Ok(message) = serialize(&item.uid) else {return};
let _ = node.send_remote_signal("release", message);
let _ = node.send_remote_signal("release", &serialize(&item.uid).unwrap());
}
}
impl Drop for ItemAcceptor {
@@ -402,16 +405,12 @@ fn type_info(name: &str) -> Result<&'static TypeInfo> {
}
}
pub fn register_item_ui_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
pub fn register_item_ui_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
#[derive(Deserialize)]
struct RegisterItemUIInfo<'a> {
item_type: &'a str,
}
let info: RegisterItemUIInfo = deserialize(message.as_ref())?;
let info: RegisterItemUIInfo = deserialize(data)?;
let type_info = type_info(info.item_type)?;
let ui =
Node::create(&calling_client, "/item", type_info.type_name, true).add_to_scenegraph()?;
@@ -419,11 +418,7 @@ pub fn register_item_ui_flex(
Ok(())
}
fn create_item_acceptor_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
fn create_item_acceptor_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
#[derive(Deserialize)]
struct CreateItemAcceptorInfo<'a> {
name: &'a str,
@@ -432,7 +427,7 @@ fn create_item_acceptor_flex(
field_path: &'a str,
item_type: &'a str,
}
let info: CreateItemAcceptorInfo = deserialize(message.as_ref())?;
let info: CreateItemAcceptorInfo = deserialize(data)?;
let space = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, false);
let field = find_field(&calling_client, info.field_path)?;

View File

@@ -1,507 +0,0 @@
use crate::{
core::{
client::{get_env, startup_settings, Client, INTERNAL_CLIENT},
registry::Registry,
},
nodes::{
drawable::{model::ModelPart, Drawable},
items::{self, Item, ItemType, TypeInfo},
spatial::Spatial,
Message, Node,
},
};
use color_eyre::eyre::{bail, eyre, Result};
use glam::Mat4;
use lazy_static::lazy_static;
use mint::Vector2;
use nanoid::nanoid;
use serde::{
de::{Deserializer, Error, SeqAccess, Visitor},
ser::Serializer,
Deserialize, Serialize,
};
use stardust_xr::schemas::flex::{deserialize, serialize};
use std::sync::{Arc, Weak};
use tracing::debug;
lazy_static! {
pub static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo {
type_name: "panel",
aliased_local_signals: vec![
"apply_surface_material",
"configure_toplevel",
"set_toplevel_capabilities",
"pointer_scroll",
"pointer_button",
"pointer_motion",
"keyboard_key",
"keyboard_set_keymap_names",
"keyboard_set_keymap_string",
"close",
],
aliased_local_methods: vec![],
aliased_remote_signals: vec![
"commit_toplevel",
"recommend_toplevel_state",
"set_cursor",
"new_popup",
"reposition_popup",
"drop_popup",
],
ui: Default::default(),
items: Registry::new(),
acceptors: Registry::new(),
};
}
/// An ID for a surface inside this panel item
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub enum SurfaceID {
Cursor,
Toplevel,
Popup(String),
}
impl Default for SurfaceID {
fn default() -> Self {
Self::Toplevel
}
}
impl<'de> serde::Deserialize<'de> for SurfaceID {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_seq(SurfaceIDVisitor)
}
}
struct SurfaceIDVisitor;
impl<'de> Visitor<'de> for SurfaceIDVisitor {
type Value = SurfaceID;
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.write_str("idk")
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let Some(discrim) = seq.next_element()? else {
return Err(A::Error::missing_field("discrim"));
};
// idk if you wanna check for extraneous elements
// I didn't bother
match discrim {
"Cursor" => Ok(SurfaceID::Cursor),
"Toplevel" => Ok(SurfaceID::Toplevel),
"Popup" => {
let Some(text) = seq.next_element()? else {
return Err(A::Error::missing_field("popup_text"));
};
Ok(SurfaceID::Popup(text))
}
_ => Err(A::Error::unknown_variant(
discrim,
&["Cursor", "Toplevel", "Popup"],
)),
}
}
}
impl serde::Serialize for SurfaceID {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::Cursor => ["Cursor"].serialize(serializer),
Self::Toplevel => ["Toplevel"].serialize(serializer),
Self::Popup(text) => ["Popup", text].serialize(serializer),
}
}
}
#[derive(Debug, Clone, Copy, Serialize)]
#[serde(tag = "type", content = "content")]
pub enum RecommendedState {
Maximize(bool),
Fullscreen(bool),
Minimize,
Move,
Resize(u32),
}
pub trait Backend: Send + Sync + 'static {
fn serialize_start_data(&self, id: &str) -> Result<Message>;
fn serialize_toplevel(&self) -> Result<Message>;
fn set_toplevel_capabilities(&self, capabilities: Vec<u8>);
fn configure_toplevel(
&self,
size: Option<Vector2<u32>>,
states: Vec<u32>,
bounds: Option<Vector2<u32>>,
);
fn apply_surface_material(&self, surface: SurfaceID, model_part: &Arc<ModelPart>);
fn pointer_motion(&self, surface: &SurfaceID, position: Vector2<f32>);
fn pointer_button(&self, surface: &SurfaceID, button: u32, pressed: bool);
fn pointer_scroll(
&self,
surface: &SurfaceID,
scroll_distance: Option<Vector2<f32>>,
scroll_steps: Option<Vector2<f32>>,
);
fn keyboard_set_keymap(&self, keymap: &str) -> Result<()>;
fn keyboard_key(&self, surface: &SurfaceID, key: u32, state: bool);
}
pub fn panel_item_from_node(node: &Node) -> Option<Arc<dyn PanelItemTrait>> {
let ItemType::Panel(panel_item) = &node.item.get()?.specialization else {return None};
Some(panel_item.clone())
}
pub trait PanelItemTrait: Backend + Send + Sync + 'static {
fn uid(&self) -> &str;
// fn node(&self) -> Option<Arc<Node>>;
}
pub struct PanelItem<B: Backend + ?Sized> {
pub uid: String,
node: Weak<Node>,
pub backend: Box<B>,
}
impl<B: Backend + ?Sized> PanelItem<B> {
pub fn create(backend: Box<B>, pid: Option<i32>) -> (Arc<Node>, Arc<PanelItem<B>>) {
debug!(?pid, "Create panel item");
let startup_settings = pid
.and_then(|pid| get_env(pid).ok())
.and_then(|env| startup_settings(&env));
let uid = nanoid!();
let node = Node::create(&INTERNAL_CLIENT, "/item/panel/item", &uid, true)
.add_to_scenegraph()
.unwrap();
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap();
if let Some(startup_settings) = &startup_settings {
spatial.set_local_transform(
spatial.global_transform().inverse() * startup_settings.transform,
);
}
let panel_item = Arc::new(PanelItem {
uid: uid.clone(),
node: Arc::downgrade(&node),
backend,
});
let generic_panel_item: Arc<dyn PanelItemTrait> = panel_item.clone();
let item = Item::add_to(
&node,
uid,
&ITEM_TYPE_INFO_PANEL,
ItemType::Panel(generic_panel_item),
);
// panel_item
// .seat_data
// .new_surface(&wl_surface, Arc::downgrade(&panel_item));
if let Some(startup_settings) = &startup_settings {
if let Some(acceptor) = startup_settings
.acceptors
.get(&*ITEM_TYPE_INFO_PANEL)
.and_then(|acc| acc.upgrade())
{
items::capture(&item, &acceptor);
}
}
node.add_local_signal("apply_surface_material", Self::apply_surface_material_flex);
node.add_local_signal("configure_toplevel", Self::configure_toplevel_flex);
node.add_local_signal(
"set_toplevel_capabilities",
Self::set_toplevel_capabilities_flex,
);
node.add_local_signal("pointer_scroll", Self::pointer_scroll_flex);
node.add_local_signal("pointer_button", Self::pointer_button_flex);
node.add_local_signal("pointer_motion", Self::pointer_motion_flex);
node.add_local_signal(
"keyboard_set_keymap_string",
Self::keyboard_set_keymap_string_flex,
);
// node.add_local_signal(
// "keyboard_set_keymap_names",
// Self::keyboard_set_keymap_names_flex,
// );
node.add_local_signal("keyboard_key", Self::keyboard_key_flex);
(node, panel_item)
}
pub fn node(&self) -> Option<Arc<Node>> {
self.node.upgrade()
}
fn apply_surface_material_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
#[derive(Debug, Deserialize)]
struct SurfaceMaterialInfo<'a> {
surface: SurfaceID,
model_node_path: &'a str,
}
let info: SurfaceMaterialInfo = deserialize(message.as_ref())?;
let model_node = calling_client
.scenegraph
.get_node(info.model_node_path)
.ok_or_else(|| eyre!("Model node not found"))?;
let Some(Drawable::ModelPart(model_part)) = model_node.drawable.get() else {bail!("Node is not a model")};
debug!(?info, "Apply surface material");
panel_item.apply_surface_material(info.surface, model_part);
Ok(())
}
fn pointer_motion_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
let (surface_id, position): (SurfaceID, Vector2<f32>) = deserialize(message.as_ref())?;
debug!(?surface_id, ?position, "Pointer deactivate");
panel_item.pointer_motion(&surface_id, position);
Ok(())
}
fn pointer_button_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
let (surface_id, button, state): (SurfaceID, u32, u32) = deserialize(message.as_ref())?;
debug!(?surface_id, button, state, "Pointer button");
panel_item.pointer_button(&surface_id, button, state == 0);
Ok(())
}
fn pointer_scroll_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
#[derive(Debug, Deserialize)]
struct PointerScrollInfo {
surface_id: SurfaceID,
axis_continuous: Option<Vector2<f32>>,
axis_discrete: Option<Vector2<f32>>,
}
let info: PointerScrollInfo = deserialize(message.as_ref())?;
debug!(?info, "Pointer scroll");
panel_item.pointer_scroll(&info.surface_id, info.axis_continuous, info.axis_discrete);
Ok(())
}
fn keyboard_set_keymap_string_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
let keymap_string: &str = deserialize(message.as_ref())?;
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
debug!("Keyboard set keymap");
panel_item.keyboard_set_keymap(keymap_string)
// PanelItem::keyboard_set_keymap_flex(node, &keymap)
}
// fn keyboard_set_keymap_names_flex(
// node: &Node,
// _calling_client: Arc<Client>,
// message: Message,
// ) -> Result<()> {
// #[derive(Debug, Deserialize)]
// struct Names<'a> {
// rules: &'a str,
// model: &'a str,
// layout: &'a str,
// variant: &'a str,
// options: Option<String>,
// }
// let names: Names = deserialize(message.as_ref())?;
// let context = xkb::Context::new(0);
// let keymap = Keymap::new_from_names(
// &context,
// names.rules,
// names.model,
// names.layout,
// names.variant,
// names.options,
// XKB_KEYMAP_FORMAT_TEXT_V1,
// )
// .ok_or_else(|| eyre!("Keymap is not valid"))?;
// PanelItem::keyboard_set_keymap_flex(node, &keymap)
// }
// fn keyboard_set_keymap_flex(node: &Node, keymap: &str) -> Result<()> {
// let Some(panel_item): Option<Arc<PanelItem<dyn WaylandBackend>>> = panel_item_from_node(node) else { return Ok(()) };
// debug!("Keyboard set keymap");
// panel_item.seat_data.set_keymap(
// keymap,
// match &panel_item {
// Backend::Wayland(w) => w.input_surfaces(),
// #[cfg(feature = "xwayland")]
// Backend::X11(_) => panel_item
// .toplevel_wl_surface()
// .map(|s| vec![s])
// .unwrap_or_default(),
// },
// );
// Ok(())
// }
fn keyboard_key_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
let (surface_id, key, state): (SurfaceID, u32, u32) = deserialize(message.as_ref())?;
debug!(key, state, "Set keyboard key state");
panel_item.keyboard_key(&surface_id, key, state == 0);
Ok(())
}
pub fn grab_keyboard(&self, sid: Option<SurfaceID>) {
let Some(node) = self.node.upgrade() else {return};
let Ok(message) = serialize(sid) else {return};
let _ = node.send_remote_signal("grab_keyboard", message);
}
fn configure_toplevel_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
#[derive(Debug, Deserialize)]
struct ConfigureToplevelInfo {
size: Option<Vector2<u32>>,
states: Vec<u32>,
bounds: Option<Vector2<u32>>,
}
let info: ConfigureToplevelInfo = deserialize(message.as_ref())?;
panel_item.configure_toplevel(info.size, info.states, info.bounds);
Ok(())
}
fn set_toplevel_capabilities_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
let Some(panel_item) = panel_item_from_node(node) else { return Ok(()) };
let capabilities: Vec<u8> = deserialize(message.as_ref())?;
debug!("Set toplevel capabilities");
panel_item.set_toplevel_capabilities(capabilities);
Ok(())
}
pub fn commit_toplevel(&self) {
debug!("Commit toplevel");
let Some(node) = self.node.upgrade() else {return};
let Ok(data) = self.backend.serialize_toplevel() else {return};
let _ = node.send_remote_signal("commit_toplevel", data);
}
pub fn recommend_toplevel_state(&self, state: RecommendedState) {
let Some(node) = self.node.upgrade() else {return};
let data = serialize(state).unwrap();
debug!(?state, "Recommend toplevel state");
let _ = node.send_remote_signal("recommend_toplevel_state", data);
}
}
impl<B: Backend + ?Sized> PanelItemTrait for PanelItem<B> {
fn uid(&self) -> &str {
&self.uid
}
}
impl<B: Backend + ?Sized> Backend for PanelItem<B> {
fn serialize_start_data(&self, id: &str) -> Result<Message> {
self.backend.serialize_start_data(id)
}
fn serialize_toplevel(&self) -> Result<Message> {
self.backend.serialize_toplevel()
}
fn set_toplevel_capabilities(&self, capabilities: Vec<u8>) {
self.backend.set_toplevel_capabilities(capabilities)
}
fn configure_toplevel(
&self,
size: Option<Vector2<u32>>,
states: Vec<u32>,
bounds: Option<Vector2<u32>>,
) {
self.backend.configure_toplevel(size, states, bounds)
}
fn apply_surface_material(&self, surface: SurfaceID, model_part: &Arc<ModelPart>) {
self.backend.apply_surface_material(surface, model_part)
}
fn pointer_motion(&self, surface: &SurfaceID, position: Vector2<f32>) {
self.backend.pointer_motion(surface, position)
}
fn pointer_button(&self, surface: &SurfaceID, button: u32, pressed: bool) {
self.backend.pointer_button(surface, button, pressed)
}
fn pointer_scroll(
&self,
surface: &SurfaceID,
scroll_distance: Option<Vector2<f32>>,
scroll_steps: Option<Vector2<f32>>,
) {
self.backend
.pointer_scroll(surface, scroll_distance, scroll_steps)
}
fn keyboard_set_keymap(&self, keymap: &str) -> Result<()> {
self.backend.keyboard_set_keymap(keymap)
}
fn keyboard_key(&self, surface: &SurfaceID, key: u32, state: bool) {
self.backend.keyboard_key(surface, key, state)
}
}
impl<B: Backend + ?Sized> Drop for PanelItem<B> {
fn drop(&mut self) {
// Dropped panel item, basically just a debug breakpoint place
}
}

View File

@@ -22,15 +22,12 @@ use stardust_xr::messenger::MessageSenderHandle;
use stardust_xr::scenegraph::ScenegraphError;
use stardust_xr::schemas::flex::deserialize;
use std::fmt::Debug;
use std::os::fd::OwnedFd;
use std::sync::{Arc, Weak};
use std::vec::Vec;
use tracing::{debug_span, instrument};
use crate::core::client::Client;
use crate::core::registry::Registry;
#[cfg(feature = "openxr_runtime")]
use crate::openxr;
use self::alias::Alias;
use self::audio::Sound;
@@ -43,26 +40,8 @@ use self::spatial::zone::Zone;
use self::spatial::Spatial;
use self::startup::StartupSettings;
pub struct Message {
pub data: Vec<u8>,
pub fds: Vec<OwnedFd>,
}
impl From<Vec<u8>> for Message {
fn from(data: Vec<u8>) -> Self {
Message {
data,
fds: Vec::new(),
}
}
}
impl AsRef<[u8]> for Message {
fn as_ref(&self) -> &[u8] {
&self.data
}
}
pub type Signal = fn(&Node, Arc<Client>, Message) -> Result<()>;
pub type Method = fn(&Node, Arc<Client>, Message) -> Result<Message>;
pub type Signal = fn(&Node, Arc<Client>, &[u8]) -> Result<()>;
pub type Method = fn(&Node, Arc<Client>, &[u8]) -> Result<Vec<u8>>;
pub struct Node {
pub enabled: Arc<AtomicBool>,
@@ -103,10 +82,6 @@ pub struct Node {
// Startup
pub startup_settings: OnceCell<Mutex<StartupSettings>>,
// OpenXR
#[cfg(feature = "openxr_runtime")]
pub openxr_object: OnceCell<openxr::Object>,
}
impl Node {
@@ -150,8 +125,6 @@ impl Node {
item_acceptor: OnceCell::new(),
item_ui: OnceCell::new(),
sound: OnceCell::new(),
#[cfg(feature = "openxr_runtime")]
openxr_object: OnceCell::new(),
startup_settings: OnceCell::new(),
};
node.add_local_signal("set_enabled", Node::set_enabled_flex);
@@ -171,20 +144,11 @@ impl Node {
}
}
pub fn set_enabled_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
node.enabled
.store(deserialize(message.as_ref())?, Ordering::Relaxed);
pub fn set_enabled_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
node.enabled.store(deserialize(data)?, Ordering::Relaxed);
Ok(())
}
pub fn destroy_flex(
node: &Node,
_calling_client: Arc<Client>,
_message: Message,
) -> Result<()> {
pub fn destroy_flex(node: &Node, _calling_client: Arc<Client>, _data: &[u8]) -> Result<()> {
if node.destroyable {
node.destroy();
}
@@ -216,7 +180,7 @@ impl Node {
&self,
calling_client: Arc<Client>,
method: &str,
message: Message,
data: &[u8],
) -> Result<(), ScenegraphError> {
if let Some(alias) = self.alias.get() {
if !alias.info.server_signals.iter().any(|e| e == &method) {
@@ -226,13 +190,13 @@ impl Node {
.original
.upgrade()
.ok_or(ScenegraphError::BrokenAlias)?
.send_local_signal(calling_client, method, message)
.send_local_signal(calling_client, method, data)
} else {
let signal = self
.local_signals
.get(method)
.ok_or(ScenegraphError::SignalNotFound)?;
signal(self, calling_client, message).map_err(|error| ScenegraphError::SignalError {
signal(self, calling_client, data).map_err(|error| ScenegraphError::SignalError {
error: error.to_string(),
})
}
@@ -241,8 +205,8 @@ impl Node {
&self,
calling_client: Arc<Client>,
method: &str,
message: Message,
) -> Result<Message, ScenegraphError> {
data: &[u8],
) -> Result<Vec<u8>, ScenegraphError> {
if let Some(alias) = self.alias.get() {
if !alias.info.server_methods.iter().any(|e| e == &method) {
return Err(ScenegraphError::MethodNotFound);
@@ -251,14 +215,7 @@ impl Node {
.original
.upgrade()
.ok_or(ScenegraphError::BrokenAlias)?
.execute_local_method(
calling_client,
method,
Message {
data: message.data.clone(),
fds: Vec::new(),
},
)
.execute_local_method(calling_client, method, data)
} else {
let method = self
.local_methods
@@ -266,36 +223,27 @@ impl Node {
.ok_or(ScenegraphError::MethodNotFound)?;
debug_span!("Handle method").in_scope(|| {
method(self, calling_client, message).map_err(|error| {
ScenegraphError::MethodError {
error: error.to_string(),
}
method(self, calling_client, data).map_err(|error| ScenegraphError::MethodError {
error: error.to_string(),
})
})
}
}
#[instrument(level = "debug", skip_all)]
pub fn send_remote_signal(&self, method: &str, message: impl Into<Message>) -> Result<()> {
let message = message.into();
pub fn send_remote_signal(&self, method: &str, data: &[u8]) -> Result<()> {
self.aliases
.get_valid_contents()
.iter()
.filter(|alias| alias.info.client_signals.iter().any(|e| e == &method))
.filter_map(|alias| alias.node.upgrade())
.for_each(|node| {
// Beware! file descriptors will not be sent to aliases!!!
let _ = node.send_remote_signal(
method,
Message {
data: message.data.clone(),
fds: Vec::new(),
},
);
let _ = node.send_remote_signal(method, data);
});
let path = self.path.clone();
let method = method.to_string();
let data = data.to_vec();
if let Some(handle) = self.message_sender_handle.as_ref() {
handle.signal(path.as_str(), method.as_str(), &message.data, message.fds)?;
handle.signal(path.as_str(), method.as_str(), data.as_slice())?;
}
Ok(())
}
@@ -304,7 +252,7 @@ impl Node {
// &self,
// method: &str,
// data: Vec<u8>,
// ) -> Result<impl Future<Output = Result<Message>>> {
// ) -> Result<impl Future<Output = Result<Vec<u8>>>> {
// let message_sender_handle = self
// .message_sender_handle
// .as_ref()

View File

@@ -1,5 +1,5 @@
use super::spatial::Spatial;
use super::{Message, Node};
use super::Node;
use crate::core::client::Client;
use crate::core::registry::Registry;
use color_eyre::eyre::Result;
@@ -39,11 +39,7 @@ impl Root {
}))
}
fn subscribe_frame_flex(
_node: &Node,
calling_client: Arc<Client>,
_message: Message,
) -> Result<()> {
fn subscribe_frame_flex(_node: &Node, calling_client: Arc<Client>, _data: &[u8]) -> Result<()> {
calling_client
.root
.get()
@@ -58,7 +54,7 @@ impl Root {
if let Ok(data) = serialize((delta, 0.0)) {
for root in ROOT_REGISTRY.get_valid_contents() {
if root.send_frame_event.load(Ordering::Relaxed) {
let _ = root.node.send_remote_signal("frame", data.clone());
let _ = root.node.send_remote_signal("frame", &data);
}
}
}
@@ -67,9 +63,9 @@ impl Root {
fn set_base_prefixes_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
*calling_client.base_resource_prefixes.lock() = deserialize(message.as_ref())?;
*calling_client.base_resource_prefixes.lock() = deserialize(data)?;
Ok(())
}
}

View File

@@ -1,7 +1,7 @@
pub mod zone;
use self::zone::{create_zone_flex, Zone};
use super::{Message, Node};
use super::Node;
use crate::core::client::Client;
use crate::core::registry::Registry;
use color_eyre::eyre::{ensure, eyre, Result};
@@ -232,13 +232,13 @@ impl Spatial {
pub fn get_bounding_box_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<Message> {
data: &[u8],
) -> Result<Vec<u8>> {
let this_spatial = node
.spatial
.get()
.ok_or_else(|| eyre!("Node doesn't have a spatial?"))?;
let relative_spatial_path: Option<&str> = deserialize(message.as_ref())?;
let relative_spatial_path: Option<&str> = deserialize(data)?;
let bounds = if let Some(relative_spatial_path) = relative_spatial_path {
let relative_spatial = find_reference_space(&calling_client, relative_spatial_path)?;
let center =
@@ -260,24 +260,23 @@ impl Spatial {
this_spatial.get_bounding_box()
};
Ok(serialize((
serialize((
mint::Vector3::from(bounds.center),
mint::Vector3::from(bounds.dimensions),
))?
.into())
))
.map_err(|e| e.into())
}
pub fn get_transform_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<Message> {
data: &[u8],
) -> Result<Vec<u8>> {
let this_spatial = node
.spatial
.get()
.ok_or_else(|| eyre!("Node doesn't have a spatial?"))?;
let relative_spatial =
find_reference_space(&calling_client, deserialize(message.as_ref())?)?;
let relative_spatial = find_reference_space(&calling_client, deserialize(data)?)?;
let (scale, rotation, position) = Spatial::space_to_space_matrix(
Some(this_spatial.as_ref()),
@@ -285,24 +284,20 @@ impl Spatial {
)
.to_scale_rotation_translation();
Ok(serialize((
serialize((
mint::Vector3::from(position),
mint::Quaternion::from(rotation),
mint::Vector3::from(scale),
))?
.into())
))
.map_err(|e| e.into())
}
pub fn set_transform_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
pub fn set_transform_flex(node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
#[derive(Deserialize)]
struct TransformArgs<'a> {
reference_space_path: Option<&'a str>,
transform: Transform,
}
let transform_args: TransformArgs = deserialize(message.as_ref())?;
let transform_args: TransformArgs = deserialize(data)?;
let reference_space_transform = transform_args
.reference_space_path
.map(|path| find_reference_space(&calling_client, path))
@@ -317,29 +312,25 @@ impl Spatial {
pub fn set_spatial_parent_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
let parent = find_spatial_parent(&calling_client, deserialize(message.as_ref())?)?;
let parent = find_spatial_parent(&calling_client, deserialize(data)?)?;
node.spatial.get().unwrap().set_spatial_parent(Some(parent))
}
pub fn set_spatial_parent_in_place_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
let parent = find_spatial_parent(&calling_client, deserialize(message.as_ref())?)?;
let parent = find_spatial_parent(&calling_client, deserialize(data)?)?;
node.spatial
.get()
.unwrap()
.set_spatial_parent_in_place(Some(parent))?;
Ok(())
}
pub fn set_zoneable_flex(
node: &Node,
_calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
let zoneable: bool = deserialize(message.as_ref())?;
pub fn set_zoneable_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let zoneable: bool = deserialize(data)?;
let spatial = node.spatial.get().unwrap();
if zoneable {
ZONEABLE_REGISTRY.add_raw(spatial);
@@ -353,9 +344,9 @@ impl Spatial {
pub fn field_distance_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<Message> {
let (point, fields): (Vector3<f32>, Vec<Option<&str>>) = deserialize(message.as_ref())?;
data: &[u8],
) -> Result<Vec<u8>> {
let (point, fields): (Vector3<f32>, Vec<Option<&str>>) = deserialize(data)?;
let spatial = node.spatial.get().unwrap();
let output = fields
@@ -371,14 +362,14 @@ impl Spatial {
.map(|f| f.map(|f| f.distance(spatial, point.into())))
.collect::<Vec<Option<f32>>>();
Ok(serialize(output)?.into())
Ok(serialize(output)?)
}
pub fn field_normal_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<Message> {
let (point, fields): (Vector3<f32>, Vec<Option<&str>>) = deserialize(message.as_ref())?;
data: &[u8],
) -> Result<Vec<u8>> {
let (point, fields): (Vector3<f32>, Vec<Option<&str>>) = deserialize(data)?;
let spatial = node.spatial.get().unwrap();
let output = fields
@@ -394,14 +385,14 @@ impl Spatial {
.map(|f| f.map(|f| Vector3::from(f.normal(spatial, point.into(), 0.001))))
.collect::<Vec<_>>();
Ok(serialize(output)?.into())
Ok(serialize(output)?)
}
pub fn field_closest_point_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<Message> {
let (point, fields): (Vector3<f32>, Vec<Option<&str>>) = deserialize(message.as_ref())?;
data: &[u8],
) -> Result<Vec<u8>> {
let (point, fields): (Vector3<f32>, Vec<Option<&str>>) = deserialize(data)?;
let spatial = node.spatial.get().unwrap();
let output = fields
@@ -417,7 +408,7 @@ impl Spatial {
.map(|f| f.map(|f| Vector3::from(f.closest_point(spatial, point.into(), 0.001))))
.collect::<Vec<_>>();
Ok(serialize(output)?.into())
Ok(serialize(output)?)
}
#[instrument]
@@ -499,11 +490,7 @@ pub fn create_interface(client: &Arc<Client>) -> Result<()> {
node.add_to_scenegraph().map(|_| ())
}
pub fn create_spatial_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
) -> Result<()> {
pub fn create_spatial_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
#[derive(Deserialize)]
struct CreateSpatialInfo<'a> {
name: &'a str,
@@ -511,7 +498,7 @@ pub fn create_spatial_flex(
transform: Transform,
zoneable: bool,
}
let info: CreateSpatialInfo = deserialize(message.as_ref())?;
let info: CreateSpatialInfo = deserialize(data)?;
let node = Node::create(&calling_client, "/spatial/spatial", info.name, true);
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, true);

View File

@@ -5,7 +5,7 @@ use crate::{
alias::{Alias, AliasInfo},
fields::{find_field, Field},
spatial::{find_spatial_parent, parse_transform},
Message, Node,
Node,
},
};
use color_eyre::eyre::Result;
@@ -31,19 +31,17 @@ pub fn capture(spatial: &Arc<Spatial>, zone: &Arc<Zone>) {
*spatial.old_parent.lock() = spatial.get_parent();
*spatial.zone.lock() = Arc::downgrade(zone);
zone.captured.add_raw(spatial);
let Some(node) = zone.spatial.node.upgrade() else {return};
let Ok(message) = serialize(&spatial.uid) else {return};
let _ = node.send_remote_signal("capture", message);
let node = zone.spatial.node.upgrade().unwrap();
let _ = node.send_remote_signal("capture", &serialize(&spatial.uid).unwrap());
}
}
pub fn release(spatial: &Spatial) {
let _ = spatial.set_spatial_parent_in_place(spatial.old_parent.lock().take());
let mut spatial_zone = spatial.zone.lock();
if let Some(spatial_zone) = spatial_zone.upgrade() {
let Some(node) = spatial_zone.spatial.node.upgrade() else {return};
let node = spatial_zone.spatial.node.upgrade().unwrap();
spatial_zone.captured.remove(spatial);
let Ok(message) = serialize(&spatial.uid) else {return};
let _ = node.send_remote_signal("release", message);
let _ = node.send_remote_signal("release", &serialize(&spatial.uid).unwrap());
}
*spatial_zone = Weak::new();
}
@@ -68,20 +66,20 @@ impl Zone {
let _ = node.zone.set(zone.clone());
zone
}
fn capture_flex(node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
fn capture_flex(node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let zone = node.zone.get().unwrap();
let capture_path: &str = deserialize(message.as_ref())?;
let capture_path: &str = deserialize(data)?;
let spatial = find_spatial(&calling_client, "Spatial", capture_path)?;
capture(&spatial, zone);
Ok(())
}
fn release_flex(_node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
let capture_path: &str = deserialize(message.as_ref())?;
fn release_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let capture_path: &str = deserialize(data)?;
let spatial = find_spatial(&calling_client, "Spatial", capture_path)?;
release(&spatial);
Ok(())
}
fn update(node: &Node, _calling_client: Arc<Client>, _message: Message) -> Result<()> {
fn update(node: &Node, _calling_client: Arc<Client>, _data: &[u8]) -> Result<()> {
let zone = node.zone.get().unwrap();
let Some(field) = zone.field.upgrade() else { return Err(color_eyre::eyre::eyre!("Zone's field has been destroyed")) };
let Some((zone_client, zone_node)) = zone
@@ -131,10 +129,10 @@ impl Zone {
.collect::<FxHashMap<String, Arc<Node>>>();
for entered_uid in zoneables.keys().filter(|k| !old_zoneables.contains_key(*k)) {
node.send_remote_signal("enter", serialize(entered_uid)?)?;
node.send_remote_signal("enter", &serialize(entered_uid)?)?;
}
for left_uid in old_zoneables.keys().filter(|k| !zoneables.contains_key(*k)) {
node.send_remote_signal("leave", serialize(left_uid)?)?;
node.send_remote_signal("leave", &serialize(left_uid)?)?;
}
*old_zoneables = zoneables;
@@ -150,7 +148,7 @@ impl Drop for Zone {
}
}
pub fn create_zone_flex(_node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
pub fn create_zone_flex(_node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
#[derive(Deserialize)]
struct CreateZoneInfo<'a> {
name: &'a str,
@@ -158,7 +156,7 @@ pub fn create_zone_flex(_node: &Node, calling_client: Arc<Client>, message: Mess
transform: Transform,
field_path: &'a str,
}
let info: CreateZoneInfo = deserialize(message.as_ref())?;
let info: CreateZoneInfo = deserialize(data)?;
let parent = find_spatial_parent(&calling_client, info.parent_path)?;
let transform = parse_transform(info.transform, true, true, false);
let field = find_field(&calling_client, info.field_path)?;

View File

@@ -1,11 +1,9 @@
#[cfg(feature = "xwayland")]
use crate::wayland::xwayland::DISPLAY;
use crate::{core::client::Client, wayland::WAYLAND_DISPLAY, STARDUST_INSTANCE};
use super::{
items::{ItemAcceptor, TypeInfo},
spatial::find_spatial,
Message, Node,
Node,
};
use color_eyre::eyre::Result;
use glam::Mat4;
@@ -33,12 +31,8 @@ impl StartupSettings {
.set(Mutex::new(StartupSettings::default()));
}
fn set_root_flex(node: &Node, calling_client: Arc<Client>, message: Message) -> Result<()> {
let spatial = find_spatial(
&calling_client,
"Root spatial",
deserialize(message.as_ref())?,
)?;
fn set_root_flex(node: &Node, calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let spatial = find_spatial(&calling_client, "Root spatial", deserialize(data)?)?;
node.startup_settings.get().unwrap().lock().transform = spatial.global_transform();
Ok(())
@@ -47,10 +41,9 @@ impl StartupSettings {
fn add_automatic_acceptor_flex(
node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
let acceptor_node =
calling_client.get_node("Item acceptor", deserialize(message.as_ref())?)?;
let acceptor_node = calling_client.get_node("Item acceptor", deserialize(data)?)?;
let acceptor =
acceptor_node.get_aspect("Item acceptor", "item acceptor", |n| &n.item_acceptor)?;
let mut startup_settings = node.startup_settings.get().unwrap().lock();
@@ -64,14 +57,14 @@ impl StartupSettings {
fn generate_startup_token_flex(
node: &Node,
_calling_client: Arc<Client>,
_message: Message,
) -> Result<Message> {
_data: &[u8],
) -> Result<Vec<u8>> {
let id = nanoid::nanoid!();
let data = serialize(&id)?;
STARTUP_SETTINGS
.lock()
.insert(id, node.startup_settings.get().unwrap().lock().clone());
Ok(data.into())
Ok(data)
}
}
impl Debug for StartupSettings {
@@ -103,12 +96,12 @@ pub fn create_interface(client: &Arc<Client>) -> Result<()> {
pub fn create_startup_settings_flex(
_node: &Node,
calling_client: Arc<Client>,
message: Message,
data: &[u8],
) -> Result<()> {
let node = Node::create(
&calling_client,
"/startup/settings",
deserialize(message.as_ref())?,
deserialize(data)?,
true,
)
.add_to_scenegraph()?;
@@ -135,15 +128,13 @@ macro_rules! var_env_insert {
pub fn get_connection_environment_flex(
_node: &Node,
_calling_client: Arc<Client>,
_message: Message,
) -> Result<Message> {
_data: &[u8],
) -> Result<Vec<u8>> {
let mut env: FxHashMap<String, String> = FxHashMap::default();
var_env_insert!(env, STARDUST_INSTANCE);
#[cfg(feature = "wayland")]
{
var_env_insert!(env, WAYLAND_DISPLAY);
#[cfg(feature = "xwayland")]
var_env_insert!(env, DISPLAY);
env.insert("GDK_BACKEND".to_string(), "wayland".to_string());
env.insert("QT_QPA_PLATFORM".to_string(), "wayland".to_string());
env.insert("MOZ_ENABLE_WAYLAND".to_string(), "1".to_string());
@@ -151,5 +142,5 @@ pub fn get_connection_environment_flex(
env.insert("SDL_VIDEODRIVER".to_string(), "wayland".to_string());
}
Ok(serialize(env)?.into())
Ok(serialize(env)?)
}

Binary file not shown.

Binary file not shown.

View File

@@ -1,5 +1,5 @@
use crate::{
core::{client::INTERNAL_CLIENT, typed_datamap::TypedDatamap},
core::client::INTERNAL_CLIENT,
nodes::{
data::{mask_matches, Mask, PulseSender, PULSE_RECEIVER_REGISTRY},
fields::Ray,
@@ -9,25 +9,18 @@ use crate::{
},
};
use color_eyre::eyre::Result;
use glam::{vec2, vec3, Mat4, Vec2, Vec3};
use glam::{vec3, Mat4, Vec3};
use nanoid::nanoid;
use serde::{Deserialize, Serialize};
use stardust_xr::schemas::flex::flexbuffers;
use serde::Serialize;
use stardust_xr::schemas::{flat::Datamap, flex::flexbuffers};
use std::{convert::TryFrom, sync::Arc};
use stereokit::{ray_from_mouse, ButtonState, Key, StereoKitMultiThread};
use tracing::instrument;
const SK_KEYMAP: &str = include_str!("sk.kmp");
#[derive(Default, Deserialize, Serialize)]
struct MouseDatamap {
select: f32,
grab: f32,
scroll: Vec2,
}
#[derive(Debug, Clone, Serialize)]
struct KeyboardEvent {
pub struct KeyboardEvent {
pub keyboard: String,
pub keymap: Option<String>,
pub keys_up: Option<Vec<u32>>,
@@ -38,7 +31,6 @@ pub struct MousePointer {
node: Arc<Node>,
spatial: Arc<Spatial>,
pointer: Arc<InputMethod>,
datamap: TypedDatamap<MouseDatamap>,
keyboard_sender: Arc<PulseSender>,
}
impl MousePointer {
@@ -61,12 +53,11 @@ impl MousePointer {
node,
spatial,
pointer,
datamap: Default::default(),
keyboard_sender,
})
}
#[instrument(level = "debug", name = "Update Flatscreen Pointer Ray", skip_all)]
pub fn update(&mut self, sk: &impl StereoKitMultiThread) {
pub fn update(&self, sk: &impl StereoKitMultiThread) {
let mouse = sk.input_mouse();
let ray = ray_from_mouse(mouse.pos).unwrap();
@@ -80,18 +71,30 @@ impl MousePointer {
);
{
// Set pointer input datamap
self.datamap.select = if sk.input_key(Key::MouseLeft).contains(ButtonState::ACTIVE) {
1.0f32
} else {
0.0f32
};
self.datamap.grab = if sk.input_key(Key::MouseRight).contains(ButtonState::ACTIVE) {
1.0f32
} else {
0.0f32
};
self.datamap.scroll = vec2(0.0, mouse.scroll_change / 120.0);
*self.pointer.datamap.lock() = self.datamap.to_datamap().ok();
let mut fbb = flexbuffers::Builder::default();
let mut map = fbb.start_map();
map.push(
"select",
if sk.input_key(Key::MouseLeft).contains(ButtonState::ACTIVE) {
1.0f32
} else {
0.0f32
},
);
map.push(
"grab",
if sk.input_key(Key::MouseRight).contains(ButtonState::ACTIVE) {
1.0f32
} else {
0.0f32
},
);
let mut scroll_vec = map.start_vector("scroll");
scroll_vec.push(0_f32);
scroll_vec.push(mouse.scroll_change / 120.0);
scroll_vec.end_vector();
map.end_map();
*self.pointer.datamap.lock() = Datamap::new(fbb.take_buffer()).ok();
}
self.send_keyboard_input(sk);
}

View File

@@ -1,5 +1,5 @@
use crate::{
core::{client::INTERNAL_CLIENT, typed_datamap::TypedDatamap},
core::client::INTERNAL_CLIENT,
nodes::{
input::{tip::Tip, InputMethod, InputType},
spatial::Spatial,
@@ -7,70 +7,51 @@ use crate::{
},
};
use color_eyre::eyre::Result;
use glam::{Mat4, Vec2};
use glam::Mat4;
use nanoid::nanoid;
use serde::{Deserialize, Serialize};
use stardust_xr::values::Transform;
use std::sync::Arc;
use stereokit::{
ButtonState, Color128, Handed, Model, RenderLayer, StereoKitDraw, StereoKitMultiThread,
use stardust_xr::{
schemas::{flat::Datamap, flex::flexbuffers},
values::Transform,
};
use std::sync::Arc;
use stereokit::{ButtonState, Handed, StereoKitMultiThread};
use tracing::instrument;
#[derive(Default, Deserialize, Serialize)]
struct ControllerDatamap {
select: f32,
grab: f32,
scroll: Vec2,
}
pub struct SkController {
_node: Arc<Node>,
input: Arc<InputMethod>,
model: Model,
handed: Handed,
datamap: TypedDatamap<ControllerDatamap>,
}
impl SkController {
pub fn new(sk: &impl StereoKitMultiThread, handed: Handed) -> Result<Self> {
pub fn new(handed: Handed) -> Result<Self> {
let _node = Node::create(&INTERNAL_CLIENT, "", &nanoid!(), false).add_to_scenegraph()?;
Spatial::add_to(&_node, None, Mat4::IDENTITY, false)?;
let model = sk.model_create_mem("cursor", include_bytes!("cursor.glb"), None)?;
let tip = InputType::Tip(Tip::default());
let input = InputMethod::add_to(&_node, tip, None)?;
Ok(SkController {
_node,
input,
handed,
model,
datamap: Default::default(),
})
}
#[instrument(level = "debug", name = "Update StereoKit Tip Input Method", skip_all)]
pub fn update(&mut self, sk: &impl StereoKitDraw) {
pub fn update(&mut self, sk: &impl StereoKitMultiThread) {
let controller = sk.input_controller(self.handed);
*self.input.enabled.lock() = controller.tracked.contains(ButtonState::ACTIVE);
if *self.input.enabled.lock() {
sk.model_draw(
&self.model,
Mat4::from_rotation_translation(
controller.aim.orientation,
controller.aim.position,
),
Color128::default(),
RenderLayer::all(),
);
self.input.spatial.set_local_transform_components(
None,
Transform::from_position_rotation(
controller.aim.position,
controller.aim.orientation,
controller.pose.position,
controller.pose.orientation,
),
);
}
self.datamap.select = controller.trigger;
self.datamap.grab = controller.grip;
self.datamap.scroll = controller.stick;
*self.input.datamap.lock() = self.datamap.to_datamap().ok();
let mut fbb = flexbuffers::Builder::default();
let mut map = fbb.start_map();
map.push("select", controller.trigger);
map.push("grab", controller.grip);
map.end_map();
*self.input.datamap.lock() = Datamap::new(fbb.take_buffer()).ok();
}
}

View File

@@ -1,5 +1,5 @@
use crate::{
core::{client::INTERNAL_CLIENT, typed_datamap::TypedDatamap},
core::client::INTERNAL_CLIENT,
nodes::{
input::{hand::Hand, InputMethod, InputType},
spatial::Spatial,
@@ -9,8 +9,10 @@ use crate::{
use color_eyre::eyre::Result;
use glam::Mat4;
use nanoid::nanoid;
use serde::{Deserialize, Serialize};
use stardust_xr::schemas::flat::{Hand as FlatHand, Joint};
use stardust_xr::schemas::{
flat::{Datamap, Hand as FlatHand, Joint},
flex::flexbuffers,
};
use std::sync::Arc;
use stereokit::{ButtonState, HandJoint, Handed, StereoKitMultiThread};
use tracing::instrument;
@@ -23,17 +25,10 @@ fn convert_joint(joint: HandJoint) -> Joint {
}
}
#[derive(Default, Deserialize, Serialize)]
struct HandDatamap {
pinch_strength: f32,
grab_strength: f32,
}
pub struct SkHand {
_node: Arc<Node>,
input: Arc<InputMethod>,
handed: Handed,
datamap: TypedDatamap<HandDatamap>,
}
impl SkHand {
pub fn new(handed: Handed) -> Result<Self> {
@@ -50,7 +45,6 @@ impl SkHand {
_node,
input,
handed,
datamap: Default::default(),
})
}
#[instrument(level = "debug", name = "Update Hand Input Method", skip_all)]
@@ -60,7 +54,6 @@ impl SkHand {
let controller = sk.input_controller(self.handed);
*self.input.enabled.lock() = controller.tracked.contains(ButtonState::INACTIVE)
&& sk_hand.tracked_state.contains(ButtonState::ACTIVE);
sk.input_hand_visible(self.handed, *self.input.enabled.lock());
if *self.input.enabled.lock() {
hand.base.thumb.tip = convert_joint(sk_hand.fingers[0][4]);
hand.base.thumb.distal = convert_joint(sk_hand.fingers[0][3]);
@@ -93,8 +86,11 @@ impl SkHand {
hand.base.elbow = None;
}
}
self.datamap.pinch_strength = sk_hand.pinch_activation;
self.datamap.grab_strength = sk_hand.grip_activation;
*self.input.datamap.lock() = self.datamap.to_datamap().ok();
let mut fbb = flexbuffers::Builder::default();
let mut map = fbb.start_map();
map.push("grab_strength", sk_hand.grip_activation);
map.push("pinch_strength", sk_hand.pinch_activation);
map.end_map();
*self.input.datamap.lock() = Datamap::new(fbb.take_buffer()).ok();
}
}

View File

@@ -1,76 +0,0 @@
use super::Object;
use crate::{core::client::Client, nodes::Node};
use color_eyre::eyre::{bail, Result};
use parking_lot::Mutex;
use rustc_hash::FxHashMap;
use serde::Deserialize;
use stardust_xr::schemas::flex::deserialize;
use std::sync::Arc;
#[derive(Debug)]
pub struct Action {
// _info: InstanceInfo,
_localized_name: String,
suggested_bindings: Mutex<FxHashMap<String, String>>,
}
impl Action {
pub fn create_action_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Object::ActionSet(action_set) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
bail!("Object not an instance")
};
#[derive(Debug, Deserialize)]
struct CreateActionInfo {
name: String,
localized_name: String,
}
let info: CreateActionInfo = dbg!(deserialize(data)?);
let node = Node::create(
&node.get_client().unwrap(),
node.get_path(),
&info.name,
true,
)
.add_to_scenegraph();
node.add_local_signal("suggest_binding", Self::suggest_binding_flex);
let action = Arc::new(Action {
_localized_name: info.localized_name,
suggested_bindings: Mutex::new(FxHashMap::default()),
});
action_set
.actions
.lock()
.insert(info.name, Arc::downgrade(&action));
node.openxr_object.set(Object::Action(action)).unwrap();
Ok(())
}
pub fn suggest_binding_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Object::Action(action) = node.get_aspect("OpenXR interface", "Action", |n| &n.openxr_object)? else {
bail!("Object not an action")
};
#[derive(Debug, Deserialize)]
struct SuggestBindingArgs {
interaction_profile: String,
binding: String,
}
let args: SuggestBindingArgs = dbg!(deserialize(data)?);
action
.suggested_bindings
.lock()
.insert(args.interaction_profile, args.binding);
Ok(())
}
}

View File

@@ -1,60 +0,0 @@
use super::{action::Action, Object};
use crate::{core::client::Client, nodes::Node};
use color_eyre::eyre::{bail, Result};
use parking_lot::Mutex;
use rustc_hash::FxHashMap;
use serde::Deserialize;
use stardust_xr::schemas::flex::deserialize;
use std::sync::{Arc, Weak};
#[derive(Debug)]
pub struct ActionSet {
// _info: InstanceInfo,
_localized_name: String,
_priority: u32,
pub actions: Mutex<FxHashMap<String, Weak<Action>>>,
}
impl ActionSet {
pub fn create_action_set_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Object::Instance(instance) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
bail!("Object not an instance")
};
let Some(instance) = instance.get() else { bail!("Instance not initialized") };
#[derive(Deserialize)]
struct CreateActionSetInfo {
name: String,
localized_name: String,
priority: u32,
}
let info: CreateActionSetInfo = deserialize(data)?;
let node = Node::create(
&node.get_client().unwrap(),
"/openxr/action_set",
&info.name,
true,
)
.add_to_scenegraph();
node.add_local_signal("create_action", Action::create_action_flex);
let action_set = Arc::new(ActionSet {
_localized_name: info.localized_name,
_priority: info.priority,
actions: Mutex::new(FxHashMap::default()),
});
instance
.action_sets
.lock()
.insert(info.name, Arc::downgrade(&action_set));
node.openxr_object
.set(Object::ActionSet(action_set))
.unwrap();
Ok(())
}
}

View File

@@ -1,47 +0,0 @@
use super::{action_set::ActionSet, Object};
use crate::{core::client::Client, nodes::Node};
use color_eyre::eyre::{bail, eyre, Result};
use parking_lot::Mutex;
use rustc_hash::FxHashMap;
use serde::Deserialize;
use stardust_xr::schemas::flex::deserialize;
use std::sync::{Arc, Weak};
#[derive(Debug, Deserialize)]
struct InstanceInfo {
_app_info: ApplicationInfo,
_extension_names: Vec<String>,
}
#[derive(Debug, Deserialize)]
struct ApplicationInfo {
_app_name: String,
_app_version: u32,
_engine_name: String,
_engine_version: u32,
_api_version: u64,
}
#[derive(Debug)]
pub struct Instance {
_info: InstanceInfo,
pub action_sets: Mutex<FxHashMap<String, Weak<ActionSet>>>,
}
impl Instance {
pub fn setup_instance_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Object::Instance(instance) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
bail!("Object not an instance")
};
let instance_info = Instance {
_info: deserialize(data)?,
action_sets: Mutex::new(FxHashMap::default()),
};
dbg!(&instance_info);
instance
.set(Arc::new(instance_info))
.map_err(|_| eyre!("Instance already set up"))
}
}

View File

@@ -1,34 +0,0 @@
mod action;
mod action_set;
mod instance;
mod session;
mod system;
use self::{
action::Action, action_set::ActionSet, instance::Instance, session::Session, system::System,
};
use crate::{core::client::Client, nodes::Node};
use once_cell::sync::OnceCell;
use std::sync::Arc;
#[derive(Debug)]
pub enum Object {
Instance(OnceCell<Arc<Instance>>),
System(System),
Session(Session),
ActionSet(Arc<ActionSet>),
Action(Arc<Action>),
}
pub fn create_interface(client: &Arc<Client>) {
let node = Node::create(client, "", "openxr", false);
node.add_local_signal("setup_instance", Instance::setup_instance_flex);
node.add_local_method("get_system", System::get_system_flex);
node.add_local_signal("create_action_set", ActionSet::create_action_set_flex);
node.openxr_object
.set(Object::Instance(OnceCell::new()))
.unwrap();
node.add_to_scenegraph();
}

View File

@@ -1,34 +0,0 @@
use std::sync::Arc;
use color_eyre::eyre::{bail, Result};
use stardust_xr::schemas::flex::deserialize;
use super::Object;
use crate::{core::client::Client, nodes::Node};
#[derive(Debug)]
pub struct Session {
// _info: InstanceInfo,
}
impl Session {
pub fn create_session_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Object::System(_system) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
bail!("Object not a system")
};
let node = Node::create(
&node.get_client().unwrap(),
node.get_path(),
deserialize(data)?,
true,
)
.add_to_scenegraph();
let session = Session {};
node.openxr_object.set(Object::Session(session)).unwrap();
Ok(())
}
}

View File

@@ -1,76 +0,0 @@
use super::{session::Session, Object};
use crate::{core::client::Client, nodes::Node, SK_INFO};
use color_eyre::eyre::{bail, eyre, Result};
use serde::Serialize;
use stardust_xr::schemas::flex::{deserialize, serialize};
use std::sync::Arc;
#[derive(Debug)]
pub enum System {
Handheld,
HeadMounted,
}
impl System {
pub fn from_raw(raw: u32) -> Option<Self> {
match raw {
1 => Some(System::Handheld),
2 => Some(System::HeadMounted),
_ => None,
}
}
pub fn get_system_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<Vec<u8>> {
// let Object::Instance(instance) = node.get_aspect("OpenXR interface", "Instance", |n| &n.openxr_object)? else {
// bail!("Object not an instance")
// };
let system_type: u32 = deserialize(data)?;
let system = System::from_raw(system_type).ok_or_else(|| eyre!("No system exists!"))?;
let node = Node::create(
&node.get_client().unwrap(),
node.get_path(),
&format!("system{}", system_type),
true,
)
.add_to_scenegraph();
node.add_local_method("views", System::views_flex);
node.add_local_signal("create_session", Session::create_session_flex);
node.openxr_object.set(Object::System(system)).unwrap();
Ok(serialize(system_type)?)
}
fn views_flex(_node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<Vec<u8>> {
let view_configuration_type: u64 = deserialize(data)?;
let view_count: u32 = match view_configuration_type {
1 => 1,
2 => 2,
1000037000 => 4,
1000054000 => 1,
_ => bail!("Invalid view config type"),
};
#[derive(Debug, Serialize)]
struct View {
recommended_image_rect_width: u32,
max_image_rect_width: u32,
recommended_image_rect_height: u32,
max_image_rect_height: u32,
}
let sk_info = SK_INFO.get().unwrap();
Ok(serialize(
(0..view_count)
.map(|_| View {
recommended_image_rect_width: sk_info.display_width,
max_image_rect_width: sk_info.display_width,
recommended_image_rect_height: sk_info.display_height,
max_image_rect_height: sk_info.display_height,
})
.collect::<Vec<_>>(),
)?)
}
}

View File

@@ -2,8 +2,6 @@ use crate::wayland::surface::CoreSurface;
use super::state::{ClientState, WaylandState};
use portable_atomic::{AtomicU32, Ordering};
#[cfg(feature = "xwayland")]
use smithay::xwayland::XWaylandClientData;
use smithay::{
delegate_compositor,
reexports::wayland_server::{protocol::wl_surface::WlSurface, Client},
@@ -40,15 +38,7 @@ impl CompositorHandler for WaylandState {
}
fn client_compositor_state<'a>(&self, client: &'a Client) -> &'a CompositorClientState {
if let Some(client_state) = client.get_data::<ClientState>() {
&client_state.compositor_state
} else {
#[cfg(feature = "xwayland")]
if let Some(xwayland_client_data) = client.get_data::<XWaylandClientData>() {
return &xwayland_client_data.compositor_state;
}
unimplemented!()
}
&client.get_data::<ClientState>().unwrap().compositor_state
}
}

View File

@@ -88,9 +88,9 @@ impl KdeDecorationHandler for WaylandState {
&mut self,
_surface: &WlSurface,
decoration: &OrgKdeKwinServerDecoration,
mode: WEnum<KdeMode>,
_mode: WEnum<KdeMode>,
) {
decoration.mode(mode.into_result().unwrap());
decoration.mode(KdeMode::Server);
}
}
delegate_kde_decoration!(WaylandState);

View File

@@ -1,17 +1,15 @@
mod compositor;
mod data_device;
mod decoration;
pub mod panel_item;
mod seat;
mod shaders;
mod state;
mod surface;
// mod xdg_activation;
mod xdg_shell;
#[cfg(feature = "xwayland")]
pub mod xwayland;
use self::{state::WaylandState, surface::CORE_SURFACES};
use crate::wayland::seat::SeatData;
use crate::{core::task, wayland::state::ClientState};
use color_eyre::eyre::{ensure, Result};
use global_counter::primitive::exact::CounterU32;
@@ -37,6 +35,7 @@ use tokio::{
use tracing::{debug, debug_span, info, instrument};
pub static WAYLAND_DISPLAY: OnceCell<String> = OnceCell::new();
pub static SERIAL_COUNTER: CounterU32 = CounterU32::new(0);
struct EGLRawHandles {
@@ -68,9 +67,7 @@ pub struct Wayland {
join_handle: JoinHandle<Result<()>>,
renderer: GlesRenderer,
dmabuf_rx: UnboundedReceiver<Dmabuf>,
wayland_state: Arc<Mutex<WaylandState>>,
#[cfg(feature = "xwayland")]
pub xwayland_state: xwayland::XWaylandState,
state: Arc<Mutex<WaylandState>>,
}
impl Wayland {
pub fn new() -> Result<Self> {
@@ -88,10 +85,7 @@ impl Wayland {
let (dmabuf_tx, dmabuf_rx) = mpsc::unbounded_channel();
let display = Arc::new(Mutex::new(display));
#[cfg(feature = "xwayland")]
let xwayland_state = xwayland::XWaylandState::create(&display_handle).unwrap();
let wayland_state =
WaylandState::new(display.clone(), display_handle, &renderer, dmabuf_tx);
let state = WaylandState::new(display.clone(), display_handle, &renderer, dmabuf_tx);
let (global_destroy_queue_in, global_destroy_queue) = mpsc::channel(8);
GLOBAL_DESTROY_QUEUE.set(global_destroy_queue_in).unwrap();
@@ -103,12 +97,8 @@ impl Wayland {
.expect("seriously message nova this time they screwed up big time");
info!(socket_name, "Wayland active");
let join_handle = Wayland::start_loop(
display.clone(),
socket,
wayland_state.clone(),
global_destroy_queue,
)?;
let join_handle =
Wayland::start_loop(display.clone(), socket, state.clone(), global_destroy_queue)?;
Ok(Wayland {
display,
@@ -116,9 +106,7 @@ impl Wayland {
join_handle,
renderer,
dmabuf_rx,
wayland_state,
#[cfg(feature = "xwayland")]
xwayland_state,
state,
})
}
@@ -147,13 +135,9 @@ impl Wayland {
}
acc = listen_async.accept() => { // New client connected
let (stream, _) = acc?;
let client_state = Arc::new(ClientState {
compositor_state: Default::default(),
display: Arc::downgrade(&display),
seat: SeatData::new(&dh1)
});
let client = dh2.insert_client(stream.into_std()?, client_state.clone())?;
client_state.seat.client.set(client.id()).unwrap();
let client = dh2.insert_client(stream.into_std()?, Arc::new(ClientState::default()))?;
state.lock().new_client(client.id(), &dh2);
}
e = dispatch_poll_listener.readable() => { // Dispatch
let mut guard = e?;
@@ -183,7 +167,7 @@ impl Wayland {
}
pub fn frame_event(&self, sk: &impl StereoKitDraw) {
let state = self.wayland_state.lock();
let state = self.state.lock();
for core_surface in CORE_SURFACES.get_valid_contents() {
core_surface.frame(sk, state.output.clone());

663
src/wayland/panel_item.rs Normal file
View File

@@ -0,0 +1,663 @@
use super::{
seat::{Cursor, SeatData},
surface::CoreSurface,
xdg_shell::{PopupData, ToplevelData, XdgSurfaceData},
SERIAL_COUNTER,
};
use crate::{
core::{
client::{get_env, startup_settings, Client, INTERNAL_CLIENT},
registry::Registry,
},
nodes::{
drawable::Drawable,
items::{self, Item, ItemSpecialization, ItemType, TypeInfo},
spatial::Spatial,
Node,
},
wayland::seat::{KeyboardEvent, PointerEvent},
};
use color_eyre::eyre::{bail, eyre, Result};
use glam::Mat4;
use lazy_static::lazy_static;
use mint::Vector2;
use nanoid::nanoid;
use parking_lot::Mutex;
use rustc_hash::FxHashMap;
use serde::{
de::{Deserializer, Error, SeqAccess, Visitor},
ser::Serializer,
Deserialize, Serialize,
};
use smithay::{
reexports::{
wayland_protocols::xdg::shell::server::{
xdg_popup::XdgPopup,
xdg_surface::XdgSurface,
xdg_toplevel::{XdgToplevel, EVT_CONFIGURE_BOUNDS_SINCE, EVT_WM_CAPABILITIES_SINCE},
},
wayland_server::{
backend::Credentials, protocol::wl_surface::WlSurface, Resource, Weak as WlWeak,
},
},
wayland::compositor,
};
use stardust_xr::schemas::flex::{deserialize, serialize};
use std::sync::{Arc, Weak};
use tracing::debug;
use xkbcommon::xkb::{self, ffi::XKB_KEYMAP_FORMAT_TEXT_V1, Keymap};
lazy_static! {
pub static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo {
type_name: "panel",
aliased_local_signals: vec![
"apply_surface_material",
"configure_toplevel",
"set_toplevel_capabilities",
"pointer_scroll",
"pointer_button",
"pointer_motion",
"keyboard_key",
"keyboard_set_keymap_names",
"keyboard_set_keymap_string",
"close",
],
aliased_local_methods: vec![],
aliased_remote_signals: vec![
"commit_toplevel",
"recommend_toplevel_state",
"set_cursor",
"new_popup",
"reposition_popup",
"drop_popup",
],
ui: Default::default(),
items: Registry::new(),
acceptors: Registry::new(),
};
}
/// An ID for a surface inside this panel item
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub enum SurfaceID {
Cursor,
Toplevel,
Popup(String),
}
impl Default for SurfaceID {
fn default() -> Self {
Self::Toplevel
}
}
impl<'de> serde::Deserialize<'de> for SurfaceID {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_seq(SurfaceIDVisitor)
}
}
struct SurfaceIDVisitor;
impl<'de> Visitor<'de> for SurfaceIDVisitor {
type Value = SurfaceID;
fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.write_str("idk")
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let Some(discrim) = seq.next_element()? else {
return Err(A::Error::missing_field("discrim"));
};
// idk if you wanna check for extraneous elements
// I didn't bother
match discrim {
"Cursor" => Ok(SurfaceID::Cursor),
"Toplevel" => Ok(SurfaceID::Toplevel),
"Popup" => {
let Some(text) = seq.next_element()? else {
return Err(A::Error::missing_field("popup_text"));
};
Ok(SurfaceID::Popup(text))
}
_ => Err(A::Error::unknown_variant(
discrim,
&["Cursor", "Toplevel", "Popup"],
)),
}
}
}
impl serde::Serialize for SurfaceID {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
match self {
Self::Cursor => ["Cursor"].serialize(serializer),
Self::Toplevel => ["Toplevel"].serialize(serializer),
Self::Popup(text) => ["Popup", text].serialize(serializer),
}
}
}
#[derive(Debug, Clone, Copy, Serialize)]
#[serde(tag = "type", content = "content")]
pub enum RecommendedState {
Maximize(bool),
Fullscreen(bool),
Minimize,
Move,
Resize(u32),
}
pub struct PanelItem {
pub uid: String,
node: Weak<Node>,
cursor: Mutex<Option<WlWeak<WlSurface>>>,
pub seat_data: Arc<SeatData>,
toplevel: WlWeak<XdgToplevel>,
popups: Mutex<FxHashMap<String, WlWeak<XdgPopup>>>,
pointer_grab: Mutex<Option<SurfaceID>>,
keyboard_grab: Mutex<Option<SurfaceID>>,
}
impl PanelItem {
pub fn create(
toplevel: XdgToplevel,
wl_surface: WlSurface,
client_credentials: Option<Credentials>,
seat_data: Arc<SeatData>,
) -> (Arc<Node>, Arc<PanelItem>) {
debug!(?toplevel, ?client_credentials, "Create panel item");
let startup_settings = client_credentials
.and_then(|cred| get_env(cred.pid).ok())
.and_then(|env| startup_settings(&env));
let uid = nanoid!();
let node = Arc::new(Node::create(
&INTERNAL_CLIENT,
"/item/panel/item",
&uid,
true,
));
let spatial = Spatial::add_to(&node, None, Mat4::IDENTITY, false).unwrap();
let panel_item = Arc::new(PanelItem {
uid: uid.clone(),
node: Arc::downgrade(&node),
cursor: Mutex::new(None),
seat_data,
toplevel: toplevel.downgrade(),
popups: Mutex::new(FxHashMap::default()),
pointer_grab: Mutex::new(None),
keyboard_grab: Mutex::new(None),
});
if let Some(startup_settings) = &startup_settings {
spatial.set_local_transform(
spatial.global_transform().inverse() * startup_settings.transform,
);
}
panel_item
.seat_data
.new_surface(&wl_surface, Arc::downgrade(&panel_item));
let item = Item::add_to(
&node,
uid,
&ITEM_TYPE_INFO_PANEL,
ItemType::Panel(panel_item.clone()),
);
if let Some(startup_settings) = &startup_settings {
if let Some(acceptor) = startup_settings
.acceptors
.get(&*ITEM_TYPE_INFO_PANEL)
.and_then(|acc| acc.upgrade())
{
items::capture(&item, &acceptor);
}
}
node.add_local_signal(
"apply_surface_material",
PanelItem::apply_surface_material_flex,
);
node.add_local_signal("configure_toplevel", PanelItem::configure_toplevel_flex);
node.add_local_signal(
"set_toplevel_capabilities",
PanelItem::set_toplevel_capabilities_flex,
);
node.add_local_signal("pointer_scroll", PanelItem::pointer_scroll_flex);
node.add_local_signal("pointer_button", PanelItem::pointer_button_flex);
node.add_local_signal("pointer_motion", PanelItem::pointer_motion_flex);
node.add_local_signal(
"keyboard_set_keymap_string",
PanelItem::keyboard_set_keymap_string_flex,
);
node.add_local_signal(
"keyboard_set_keymap_names",
PanelItem::keyboard_set_keymap_names_flex,
);
node.add_local_signal("keyboard_key", PanelItem::keyboard_key_flex);
(node, panel_item)
}
pub fn from_node(node: &Node) -> Option<Arc<PanelItem>> {
let ItemType::Panel(panel_item) = &node.item.get()?.specialization else {return None};
Some(panel_item.clone())
}
fn toplevel(&self) -> XdgToplevel {
self.toplevel.upgrade().unwrap()
}
fn toplevel_xdg_surface(&self) -> XdgSurface {
let toplevel = self.toplevel();
let data = ToplevelData::get(&toplevel).lock();
data.xdg_surface()
}
fn toplevel_wl_surface(&self) -> WlSurface {
XdgSurfaceData::get(&self.toplevel_xdg_surface())
.lock()
.wl_surface()
}
fn core_surface(&self) -> Option<Arc<CoreSurface>> {
compositor::with_states(&self.toplevel_wl_surface(), |data| {
data.data_map.get::<Arc<CoreSurface>>().cloned()
})
}
fn flush_clients(&self) {
if let Some(core_surface) = self.core_surface() {
core_surface.flush_clients();
}
}
fn wl_surface_from_id(&self, id: &SurfaceID) -> Option<WlSurface> {
match id {
SurfaceID::Cursor => self.cursor.lock().clone()?.upgrade().ok(),
SurfaceID::Toplevel => Some(self.toplevel_wl_surface()),
SurfaceID::Popup(popup) => {
let popups = self.popups.lock();
let popup = popups.get(popup)?.upgrade().ok()?;
let surf = PopupData::get(&popup).lock().wl_surface();
Some(surf)
}
}
}
fn wl_surface_from_id_result(&self, id: &SurfaceID) -> Result<WlSurface> {
self.wl_surface_from_id(id)
.ok_or(eyre!("Surface with ID not found"))
}
fn apply_surface_material_flex(
node: &Node,
calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
#[derive(Debug, Deserialize)]
struct SurfaceMaterialInfo<'a> {
surface: SurfaceID,
model_node_path: &'a str,
}
let info: SurfaceMaterialInfo = deserialize(data)?;
let Some(wl_surface) = panel_item.wl_surface_from_id(&info.surface) else { return Ok(()) };
let Some(core_surface) = CoreSurface::from_wl_surface(&wl_surface) else { return Ok(()) };
let model_node = calling_client
.scenegraph
.get_node(info.model_node_path)
.ok_or_else(|| eyre!("Model node not found"))?;
let Some(Drawable::ModelPart(model_node)) = model_node.drawable.get() else {bail!("Node is not a model")};
debug!(?info, "Apply surface material");
core_surface.apply_material(model_node);
Ok(())
}
fn pointer_motion_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
let (surface_id, position): (SurfaceID, Vector2<f64>) = deserialize(data)?;
let wl_surface = panel_item.wl_surface_from_id_result(&surface_id)?;
debug!(?surface_id, ?position, "Pointer deactivate");
panel_item
.seat_data
.pointer_event(&wl_surface, PointerEvent::Motion(position));
panel_item.flush_clients();
Ok(())
}
fn pointer_button_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
let (surface_id, button, state): (SurfaceID, u32, u32) = deserialize(data)?;
let wl_surface = panel_item.wl_surface_from_id_result(&surface_id)?;
debug!(?surface_id, button, state, "Pointer button");
panel_item
.seat_data
.pointer_event(&wl_surface, PointerEvent::Button { button, state });
panel_item.flush_clients();
Ok(())
}
fn pointer_scroll_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
#[derive(Debug, Deserialize)]
struct PointerScrollInfo {
surface_id: SurfaceID,
axis_continuous: Option<Vector2<f32>>,
axis_discrete: Option<Vector2<f32>>,
}
let info: PointerScrollInfo = deserialize(data)?;
let wl_surface = panel_item.wl_surface_from_id_result(&info.surface_id)?;
debug!(?info, "Pointer scroll");
panel_item.seat_data.pointer_event(
&wl_surface,
PointerEvent::Scroll {
axis_continuous: info.axis_continuous,
axis_discrete: info.axis_discrete,
},
);
panel_item.flush_clients();
Ok(())
}
fn keyboard_set_keymap_string_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let context = xkb::Context::new(0);
let keymap =
Keymap::new_from_string(&context, deserialize(data)?, XKB_KEYMAP_FORMAT_TEXT_V1, 0)
.ok_or_else(|| eyre!("Keymap is not valid"))?;
PanelItem::keyboard_set_keymap_flex(node, &keymap)
}
fn keyboard_set_keymap_names_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
#[derive(Debug, Deserialize)]
struct Names<'a> {
rules: &'a str,
model: &'a str,
layout: &'a str,
variant: &'a str,
options: Option<String>,
}
let names: Names = deserialize(data)?;
let context = xkb::Context::new(0);
let keymap = Keymap::new_from_names(
&context,
names.rules,
names.model,
names.layout,
names.variant,
names.options,
XKB_KEYMAP_FORMAT_TEXT_V1,
)
.ok_or_else(|| eyre!("Keymap is not valid"))?;
PanelItem::keyboard_set_keymap_flex(node, &keymap)
}
fn keyboard_set_keymap_flex(node: &Node, keymap: &Keymap) -> Result<()> {
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
let toplevel = panel_item.toplevel_wl_surface();
debug!(?toplevel, "Keyboard set keymap");
let mut surfaces = vec![toplevel];
surfaces.extend(panel_item.popups.lock().values().filter_map(|p| {
let popup = p.upgrade().ok()?;
let popup_data = PopupData::get(&popup).lock();
let xdg_surface = popup_data.xdg_surface();
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface).lock();
Some(xdg_surface_data.wl_surface())
}));
panel_item.seat_data.set_keymap(keymap, surfaces);
Ok(())
}
fn keyboard_key_flex(node: &Node, _calling_client: Arc<Client>, data: &[u8]) -> Result<()> {
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
let (surface_id, key, state): (SurfaceID, u32, u32) = deserialize(data)?;
let wl_surface = panel_item.wl_surface_from_id_result(&surface_id)?;
debug!(key, state, "Set keyboard key state");
panel_item
.seat_data
.keyboard_event(&wl_surface, KeyboardEvent::Key { key, state });
Ok(())
}
fn configure_toplevel_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
let Ok(xdg_toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
let xdg_surface = panel_item.toplevel_xdg_surface();
#[derive(Debug, Deserialize)]
struct ConfigureToplevelInfo {
size: Option<Vector2<u32>>,
states: Vec<u32>,
bounds: Option<Vector2<u32>>,
}
let info: ConfigureToplevelInfo = deserialize(data)?;
debug!(info = ?&info, "Configure toplevel info");
if let Some(bounds) = info.bounds {
if xdg_toplevel.version() > EVT_CONFIGURE_BOUNDS_SINCE {
xdg_toplevel.configure_bounds(bounds.x as i32, bounds.y as i32);
}
}
let zero_size = Vector2::from([0; 2]);
let size = info.size.unwrap_or(zero_size);
// if size == zero_size && (info.states.contains(1) || info.states.contains(2)) {
// xdg_toplevel.configure(
// size.x as i32,
// size.y as i32,
// info.states
// .into_iter()
// .flat_map(|state| state.to_ne_bytes())
// .collect(),
// );
// }
xdg_toplevel.configure(
size.x as i32,
size.y as i32,
info.states.into_iter().flat_map(u32::to_ne_bytes).collect(),
);
xdg_surface.configure(SERIAL_COUNTER.inc());
core_surface.flush_clients();
Ok(())
}
fn set_toplevel_capabilities_flex(
node: &Node,
_calling_client: Arc<Client>,
data: &[u8],
) -> Result<()> {
let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) };
let Some(core_surface) = panel_item.core_surface() else { return Ok(()) };
let Ok(xdg_toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) };
if xdg_toplevel.version() < EVT_WM_CAPABILITIES_SINCE {
return Ok(());
}
let xdg_surface = panel_item.toplevel_xdg_surface();
let capabilities: Vec<u8> = deserialize(data)?;
debug!("Set toplevel capabilities");
xdg_toplevel.wm_capabilities(capabilities);
xdg_surface.configure(SERIAL_COUNTER.inc());
core_surface.flush_clients();
Ok(())
}
pub fn commit_toplevel(&self) {
// let mapped_size = self.core_surface().and_then(|c| c.size());
let toplevel = self.toplevel();
let state = ToplevelData::get(&toplevel);
let state = state.lock();
// let mut queued_state = state.queued_state.take().unwrap();
// queued_state.mapped = mapped_size.is_some();
// if let Some(size) = mapped_size {
// queued_state.size = size;
// queued_state.geometry.update_to_surface_size(size);
// }
// *state = (*queued_state).clone();
// state.queued_state = Some(queued_state);
debug!(state = ?&*state, "Commit toplevel");
let Some(node) = self.node.upgrade() else { return };
let _ = node.send_remote_signal("commit_toplevel", &serialize(&*state).unwrap());
}
pub fn recommend_toplevel_state(&self, state: RecommendedState) {
let Some(node) = self.node.upgrade() else { return };
let data = serialize(state).unwrap();
debug!(?state, "Recommend toplevel state");
let _ = node.send_remote_signal("recommend_toplevel_state", &data);
}
pub fn new_popup(&self, popup: &XdgPopup, data: &PopupData) {
let uid = data.uid.clone();
self.popups.lock().insert(uid.clone(), popup.downgrade());
let Some(node) = self.node.upgrade() else { return };
let _ = node.send_remote_signal("new_popup", &serialize(&(&uid, data)).unwrap());
}
// pub fn commit_popup(&self, data: &PopupData) {
// let xdg_surf = data.xdg_surface.upgrade().unwrap();
// let surf = xdg_surf
// .data::<XdgSurfaceData>()
// .unwrap()
// .wl_surface
// .upgrade()
// .unwrap();
// let core_surface =
// compositor::with_states(&surf, |s| s.data_map.get::<Arc<CoreSurface>>().cloned())
// .unwrap();
// let mut popup_state = data.state.lock();
// popup_state.mapped = core_surface.size().is_some();
// }
pub fn reposition_popup(&self, popup_state: &PopupData) {
let Some(node) = self.node.upgrade() else { return };
let _ = node.send_remote_signal(
"reposition_popup",
&serialize(popup_state.positioner_data().unwrap()).unwrap(),
);
}
pub fn drop_popup(&self, uid: &str) {
if let Some(popup) = self
.popups
.lock()
.remove(uid)
.and_then(|popup| popup.upgrade().ok()?.data::<Arc<PopupData>>().cloned())
{
self.seat_data.drop_surface(&popup.wl_surface());
}
let Some(node) = self.node.upgrade() else { return };
let _ = node.send_remote_signal("drop_popup", &serialize(uid).unwrap());
}
pub fn grab_keyboard(&self, sid: Option<SurfaceID>) {
let Some(node) = self.node.upgrade() else { return };
let _ = node.send_remote_signal("grab_keyboard", &serialize(sid).unwrap());
}
pub fn set_cursor(&self, surface: Option<&WlSurface>, hotspot_x: i32, hotspot_y: i32) {
let Some(node) = self.node.upgrade() else { return };
debug!(?surface, hotspot_x, hotspot_y, "Set cursor size");
let mut data = serialize(()).unwrap();
let cursor_size = surface
.and_then(|c| CoreSurface::from_wl_surface(c))
.and_then(|c| c.size());
if let Some(size) = cursor_size {
data = serialize((size, (hotspot_x, hotspot_y))).unwrap();
}
let _ = node.send_remote_signal("set_cursor", &data);
*self.cursor.lock() = surface.map(|surf| surf.downgrade());
}
pub fn on_drop(&self) {
let toplevel = self.toplevel_wl_surface();
self.seat_data.drop_surface(&toplevel);
debug!("Drop panel item");
}
}
impl ItemSpecialization for PanelItem {
fn serialize_start_data(&self, id: &str) -> Vec<u8> {
let cursor = self.cursor.lock().as_ref().and_then(|c| c.upgrade().ok());
let cursor_size = cursor
.as_ref()
.and_then(|c| CoreSurface::from_wl_surface(&c))
.and_then(|c| c.size());
let cursor_hotspot = cursor
.and_then(|c| {
compositor::with_states(&c, |data| data.data_map.get::<Arc<Cursor>>().cloned())
})
.map(|cursor| cursor.hotspot);
let toplevel = self.toplevel();
let toplevel_state = ToplevelData::get(&toplevel);
let toplevel_state = toplevel_state.lock().clone();
let popups = self
.popups
.lock()
.values()
.filter_map(|v| Some(v.upgrade().ok()?.data::<Mutex<PopupData>>()?.lock().clone()))
.collect::<Vec<_>>();
let pointer_grab = self.pointer_grab.lock().clone();
let keyboard_grab = self.keyboard_grab.lock().clone();
serialize((
id,
(
cursor_size.zip(cursor_hotspot),
toplevel_state,
popups,
pointer_grab,
keyboard_grab,
),
))
.unwrap()
}
}
impl Drop for PanelItem {
fn drop(&mut self) {
// Dropped panel item, basically just a debug breakpoint place
}
}

View File

@@ -1,10 +1,9 @@
use super::{
state::{ClientState, WaylandState},
surface::CoreSurface,
GLOBAL_DESTROY_QUEUE, SERIAL_COUNTER,
panel_item::PanelItem, state::WaylandState, surface::CoreSurface, GLOBAL_DESTROY_QUEUE,
SERIAL_COUNTER,
};
use crate::core::task;
use color_eyre::eyre::{eyre, Result};
use color_eyre::eyre::Result;
use mint::Vector2;
use nanoid::nanoid;
use once_cell::sync::OnceCell;
@@ -28,12 +27,11 @@ use smithay::{
};
use std::{
collections::VecDeque,
sync::Arc,
sync::{Arc, Weak},
time::{Duration, Instant},
};
use tokio::sync::watch;
use tracing::{debug, warn};
use xkbcommon::xkb::{self, ffi::XKB_KEYMAP_FORMAT_TEXT_V1, Keymap};
use xkbcommon::xkb::{self, Keymap};
pub struct KeyboardInfo {
keymap: KeymapFile,
@@ -89,7 +87,7 @@ unsafe impl Send for KeyboardInfo {}
#[derive(Debug, Clone, Copy)]
pub enum PointerEvent {
Motion(Vector2<f32>),
Motion(Vector2<f64>),
Button {
button: u32,
state: u32,
@@ -108,30 +106,23 @@ pub enum KeyboardEvent {
const POINTER_EVENT_TIMEOUT: Duration = Duration::from_secs(1);
struct SurfaceInfo {
wl_surface: WlWeak<WlSurface>,
cursor_sender: watch::Sender<Option<CursorInfo>>,
panel_item: Weak<PanelItem>,
pointer_queue: VecDeque<PointerEvent>,
pointer_latest_event: Instant,
keyboard_queue: VecDeque<KeyboardEvent>,
keyboard_info: Option<KeyboardInfo>,
}
impl SurfaceInfo {
fn new(wl_surface: &WlSurface, cursor_sender: watch::Sender<Option<CursorInfo>>) -> Self {
fn new(wl_surface: &WlSurface, panel_item: Weak<PanelItem>) -> Self {
SurfaceInfo {
wl_surface: wl_surface.downgrade(),
cursor_sender,
panel_item,
pointer_queue: VecDeque::new(),
pointer_latest_event: Instant::now(),
keyboard_queue: VecDeque::new(),
keyboard_info: None,
}
}
fn flush(&self) {
if let Some(client) = self.wl_surface.upgrade().ok().and_then(|s| s.client()) {
if let Some(client_data) = client.get_data::<ClientState>() {
client_data.flush();
}
}
}
fn handle_pointer_events(&mut self, pointer: &WlPointer, mut locked: bool) -> bool {
let Ok(focus) = self.wl_surface.upgrade() else { return false; };
let Some(core_surface) = CoreSurface::from_wl_surface(&focus) else { return false; };
@@ -146,20 +137,18 @@ impl SurfaceInfo {
pointer.enter(
SERIAL_COUNTER.inc(),
&focus,
(pos.x as f64).clamp(0.0, focus_size.x as f64),
(pos.y as f64).clamp(0.0, focus_size.y as f64),
pos.x.clamp(0.0, focus_size.x as f64),
pos.y.clamp(0.0, focus_size.y as f64),
);
locked = true;
}
(true, PointerEvent::Motion(pos)) => {
pointer.motion(
0,
(pos.x as f64).clamp(0.0, focus_size.x as f64),
(pos.y as f64).clamp(0.0, focus_size.y as f64),
pos.x.clamp(0.0, focus_size.x as f64),
pos.y.clamp(0.0, focus_size.y as f64),
);
if pointer.version() >= wl_pointer::EVT_FRAME_SINCE {
pointer.frame();
}
pointer.frame();
}
(true, PointerEvent::Button { button, state }) => {
pointer.button(
@@ -172,9 +161,7 @@ impl SurfaceInfo {
_ => continue,
},
);
if pointer.version() >= wl_pointer::EVT_FRAME_SINCE {
pointer.frame();
}
pointer.frame();
}
(
true,
@@ -187,22 +174,15 @@ impl SurfaceInfo {
pointer.axis(0, Axis::HorizontalScroll, axis_continuous.x as f64);
pointer.axis(0, Axis::VerticalScroll, axis_continuous.y as f64);
}
if pointer.version() >= wl_pointer::EVT_AXIS_DISCRETE_SINCE {
if let Some(axis_discrete) = axis_discrete {
pointer.axis_discrete(Axis::HorizontalScroll, axis_discrete.x as i32);
pointer.axis_discrete(Axis::VerticalScroll, axis_discrete.y as i32);
}
if let Some(axis_discrete) = axis_discrete {
pointer.axis_discrete(Axis::HorizontalScroll, axis_discrete.x as i32);
pointer.axis_discrete(Axis::VerticalScroll, axis_discrete.y as i32);
}
if pointer.version() >= wl_pointer::EVT_AXIS_STOP_SINCE
&& axis_discrete.is_none()
&& axis_continuous.is_none()
{
if axis_discrete.is_none() && axis_continuous.is_none() {
pointer.axis_stop(0, Axis::HorizontalScroll);
pointer.axis_stop(0, Axis::VerticalScroll);
}
if pointer.version() >= wl_pointer::EVT_FRAME_SINCE {
pointer.frame();
}
pointer.frame();
}
(locked, event) => {
warn!(locked, ?event, "Invalid pointer event!");
@@ -213,7 +193,6 @@ impl SurfaceInfo {
pointer.leave(SERIAL_COUNTER.inc(), &focus);
locked = false;
}
self.flush();
locked
}
@@ -223,9 +202,7 @@ impl SurfaceInfo {
if !locked {
keyboard.enter(0, &focus, vec![]);
if keyboard.version() >= wl_keyboard::EVT_REPEAT_INFO_SINCE {
keyboard.repeat_info(0, 0);
}
keyboard.repeat_info(0, 0);
locked = info.keymap.send(keyboard).is_ok();
}
while let Some(event) = self.keyboard_queue.pop_front() {
@@ -247,13 +224,12 @@ impl SurfaceInfo {
}
}
}
self.flush();
locked
}
}
pub struct SeatData {
pub client: OnceCell<ClientId>,
client: ClientId,
global_id: OnceCell<GlobalId>,
surfaces: Mutex<FxHashMap<ObjectId, SurfaceInfo>>,
pointer: OnceCell<(WlPointer, Mutex<ObjectId>)>,
@@ -261,9 +237,9 @@ pub struct SeatData {
touch: OnceCell<WlTouch>,
}
impl SeatData {
pub fn new(dh: &DisplayHandle) -> Arc<Self> {
pub fn new(dh: &DisplayHandle, client: ClientId) -> Arc<Self> {
let seat_data = Arc::new(SeatData {
client: OnceCell::new(),
client,
global_id: OnceCell::new(),
surfaces: Mutex::new(FxHashMap::default()),
pointer: OnceCell::new(),
@@ -279,14 +255,6 @@ impl SeatData {
seat_data
}
pub fn set_keymap_str(&self, keymap: &str, surfaces: Vec<WlSurface>) -> Result<()> {
let context = xkb::Context::new(0);
let keymap =
Keymap::new_from_string(&context, keymap.to_string(), XKB_KEYMAP_FORMAT_TEXT_V1, 0)
.ok_or_else(|| eyre!("Keymap is not valid"))?;
self.set_keymap(&keymap, surfaces);
Ok(())
}
pub fn set_keymap(&self, keymap: &Keymap, surfaces: Vec<WlSurface>) {
let mut panels = self.surfaces.lock();
let Some((_, focus)) = self.keyboard.get() else {return};
@@ -375,13 +343,10 @@ impl SeatData {
}
}
pub fn new_surface(&self, surface: &WlSurface) -> watch::Receiver<Option<CursorInfo>> {
let (tx, rx) = watch::channel(None);
pub fn new_surface(&self, surface: &WlSurface, panel_item: Weak<PanelItem>) {
self.surfaces
.lock()
.insert(surface.id(), SurfaceInfo::new(surface, tx));
rx
.insert(surface.id(), SurfaceInfo::new(surface, panel_item));
}
pub fn drop_surface(&self, surface: &WlSurface) {
self.surfaces.lock().remove(&surface.id());
@@ -408,18 +373,6 @@ impl Drop for SeatData {
}
}
pub struct CursorInfo {
pub surface: WlWeak<WlSurface>,
pub hotspot_x: i32,
pub hotspot_y: i32,
}
impl CursorInfo {
pub fn cursor_data(&self) -> Option<(Vector2<u32>, Vector2<i32>)> {
let cursor_size = CoreSurface::from_wl_surface(&self.surface.upgrade().ok()?)?.size()?;
Some((cursor_size, [self.hotspot_x, self.hotspot_y].into()))
}
}
impl GlobalDispatch<WlSeat, Arc<SeatData>, WaylandState> for WaylandState {
fn bind(
_state: &mut WaylandState,
@@ -439,8 +392,7 @@ impl GlobalDispatch<WlSeat, Arc<SeatData>, WaylandState> for WaylandState {
}
fn can_view(client: Client, data: &Arc<SeatData>) -> bool {
let Some(seat_client) = data.client.get().cloned() else {return false};
client.id() == seat_client
client.id() == data.client
}
}
@@ -461,9 +413,7 @@ impl Dispatch<WlSeat, Arc<SeatData>, WaylandState> for WaylandState {
}
wl_seat::Request::GetKeyboard { id } => {
let keyboard = data_init.init(id, data.clone());
if keyboard.version() >= wl_keyboard::EVT_REPEAT_INFO_SINCE {
keyboard.repeat_info(0, 0);
}
keyboard.repeat_info(0, 0);
let _ = data.keyboard.set((keyboard, Mutex::new(ObjectId::null())));
}
wl_seat::Request::GetTouch { id } => {
@@ -475,9 +425,12 @@ impl Dispatch<WlSeat, Arc<SeatData>, WaylandState> for WaylandState {
}
}
pub struct Cursor {
pub hotspot: Vector2<i32>,
}
impl Dispatch<WlPointer, Arc<SeatData>, WaylandState> for WaylandState {
fn request(
_state: &mut WaylandState,
state: &mut WaylandState,
_client: &Client,
_resource: &WlPointer,
request: wl_pointer::Request,
@@ -493,8 +446,16 @@ impl Dispatch<WlPointer, Arc<SeatData>, WaylandState> for WaylandState {
hotspot_y,
} => {
if let Some(surface) = surface.as_ref() {
CoreSurface::add_to(dh.clone(), surface, || (), |_| ());
CoreSurface::add_to(&state.display, dh.clone(), surface, || (), |_| ());
compositor::with_states(surface, |data| {
data.data_map.insert_if_missing_threadsafe(|| {
Arc::new(Mutex::new(Cursor {
hotspot: Vector2::from([hotspot_x, hotspot_y]),
}))
});
let mut cursor = data.data_map.get::<Arc<Mutex<Cursor>>>().unwrap().lock();
cursor.hotspot = Vector2::from([hotspot_x, hotspot_y]);
if let Some(core_surface) = data.data_map.get::<Arc<CoreSurface>>() {
core_surface.set_material_offset(1);
}
@@ -505,12 +466,8 @@ impl Dispatch<WlPointer, Arc<SeatData>, WaylandState> for WaylandState {
let focus = focus.lock();
let surfaces = seat_data.surfaces.lock();
let Some(surface_info) = surfaces.get(&focus) else {return};
let cursor_info = surface.map(|surface| CursorInfo {
surface: surface.downgrade(),
hotspot_x,
hotspot_y,
});
let _ = surface_info.cursor_sender.send_replace(cursor_info);
let Some(panel_item) = surface_info.panel_item.upgrade() else {return};
panel_item.set_cursor(surface.as_ref(), hotspot_x, hotspot_y);
}
wl_pointer::Request::Release => (),
_ => unreachable!(),

View File

@@ -1,5 +1,6 @@
use crate::wayland::seat::SeatData;
use parking_lot::Mutex;
use rustc_hash::FxHashMap;
use smithay::{
backend::{
allocator::dmabuf::Dmabuf,
@@ -36,16 +37,9 @@ use std::sync::{Arc, Weak};
use tokio::sync::mpsc::UnboundedSender;
use tracing::{info, warn};
#[derive(Default)]
pub struct ClientState {
pub compositor_state: CompositorClientState,
pub display: Weak<Mutex<Display<WaylandState>>>,
pub seat: Arc<SeatData>,
}
impl ClientState {
pub fn flush(&self) {
let Some(display) = self.display.upgrade() else {return};
let _ = display.lock().flush_clients();
}
}
impl ClientData for ClientState {
fn initialized(&self, client_id: ClientId) {
@@ -72,6 +66,7 @@ pub struct WaylandState {
dmabuf_state: (DmabufState, DmabufGlobal, Option<DmabufFeedback>),
dmabuf_tx: UnboundedSender<Dmabuf>,
pub output: Output,
pub seats: FxHashMap<ClientId, Arc<SeatData>>,
}
impl WaylandState {
@@ -135,7 +130,7 @@ impl WaylandState {
);
let _output_global = output.create_global::<Self>(&display_handle);
let mode = Mode {
size: (2048, 2048).into(),
size: (4096, 4096).into(),
refresh: 60000,
};
output.change_current_state(
@@ -164,9 +159,15 @@ impl WaylandState {
dmabuf_state,
dmabuf_tx,
output,
seats: FxHashMap::default(),
})
})
}
pub fn new_client(&mut self, client: ClientId, dh: &DisplayHandle) {
let seat_data = SeatData::new(dh, client.clone());
self.seats.insert(client, seat_data);
}
}
impl Drop for WaylandState {
fn drop(&mut self) {

View File

@@ -15,10 +15,16 @@ use smithay::{
},
desktop::utils::send_frames_surface_tree,
output::Output,
reexports::wayland_server::{self, protocol::wl_surface::WlSurface, DisplayHandle, Resource},
reexports::wayland_server::{
self, protocol::wl_surface::WlSurface, Display, DisplayHandle, Resource,
},
wayland::compositor::{self, SurfaceData},
};
use std::{ffi::c_void, sync::Arc, time::Duration};
use std::{
ffi::c_void,
sync::{Arc, Weak},
time::Duration,
};
use stereokit::{
Material, StereoKitDraw, Tex, TextureAddress, TextureFormat, TextureSample, TextureType,
Transparency,
@@ -37,6 +43,7 @@ impl Drop for CoreSurfaceData {
}
pub struct CoreSurface {
display: Weak<Mutex<Display<WaylandState>>>,
pub dh: DisplayHandle,
pub weak_surface: wayland_server::Weak<WlSurface>,
mapped_data: Mutex<Option<CoreSurfaceData>>,
@@ -50,6 +57,7 @@ pub struct CoreSurface {
impl CoreSurface {
pub fn add_to(
display: &Arc<Mutex<Display<WaylandState>>>,
dh: DisplayHandle,
surface: &WlSurface,
on_mapped: impl Fn() + Send + Sync + 'static,
@@ -58,6 +66,7 @@ impl CoreSurface {
compositor::with_states(surface, |data| {
data.data_map.insert_if_missing_threadsafe(|| {
CORE_SURFACES.add(CoreSurface {
display: Arc::downgrade(display),
dh,
weak_surface: surface.downgrade(),
mapped_data: Mutex::new(None),
@@ -83,7 +92,7 @@ impl CoreSurface {
}
pub fn process(&self, sk: &impl StereoKitDraw, renderer: &mut GlesRenderer) {
let Some(wl_surface) = self.wl_surface() else {return};
let Some(wl_surface) = self.wl_surface() else { return };
let sk_tex = self.sk_tex.get_or_init(|| {
SendWrapper::new(sk.tex_create(TextureType::IMAGE_NO_MIPS, TextureFormat::RGBA32))
@@ -166,7 +175,7 @@ impl CoreSurface {
}
pub fn frame(&self, sk: &impl StereoKitDraw, output: Output) {
let Some(wl_surface) = self.wl_surface() else {return};
let Some(wl_surface) = self.wl_surface() else { return };
send_frames_surface_tree(
&wl_surface,
@@ -181,8 +190,8 @@ impl CoreSurface {
*self.material_offset.lock().value_mut() = material_offset;
}
pub fn apply_material(&self, model_part: &Arc<ModelPart>) {
self.pending_material_applications.add_raw(model_part)
pub fn apply_material(&self, model_node: &Arc<ModelPart>) {
self.pending_material_applications.add_raw(model_node)
}
fn apply_surface_materials(&self) {
@@ -207,6 +216,15 @@ impl CoreSurface {
pub fn size(&self) -> Option<Vector2<u32>> {
self.mapped_data.lock().as_ref().map(|d| d.size)
}
pub fn flush_clients(&self) {
self.display
.upgrade()
.unwrap()
.lock()
.flush_clients()
.unwrap();
}
}
impl Drop for CoreSurface {
fn drop(&mut self) {

View File

@@ -1,26 +1,21 @@
use crate::nodes::Node;
use super::{
seat::{CursorInfo, KeyboardEvent, PointerEvent, SeatData},
state::{ClientState, WaylandState},
panel_item::{PanelItem, RecommendedState, SurfaceID},
state::WaylandState,
surface::CoreSurface,
SERIAL_COUNTER,
};
use crate::nodes::{
drawable::model::ModelPart,
items::panel::{Backend, PanelItem, RecommendedState, SurfaceID},
Message, Node,
};
use color_eyre::eyre::{eyre, Result};
use mint::Vector2;
use nanoid::nanoid;
use parking_lot::Mutex;
use rustc_hash::FxHashMap;
use serde::{ser::SerializeSeq, Serialize, Serializer};
use smithay::reexports::{
wayland_protocols::xdg::shell::server::{
xdg_popup::{self, XdgPopup},
xdg_positioner::{self, Anchor, ConstraintAdjustment, Gravity, XdgPositioner},
xdg_surface::{self, XdgSurface},
xdg_toplevel::{self, XdgToplevel, EVT_CONFIGURE_BOUNDS_SINCE, EVT_WM_CAPABILITIES_SINCE},
xdg_toplevel::{self, XdgToplevel, EVT_WM_CAPABILITIES_SINCE},
xdg_wm_base::{self, XdgWmBase},
},
wayland_server::{
@@ -30,14 +25,11 @@ use smithay::reexports::{
Weak as WlWeak,
},
};
use stardust_xr::schemas::flex::serialize;
use std::{
fmt::Debug,
sync::{Arc, Weak},
};
use tokio::sync::watch;
use tracing::{debug, warn};
use xkbcommon::xkb::{self, ffi::XKB_KEYMAP_FORMAT_TEXT_V1, Keymap};
impl GlobalDispatch<XdgWmBase, (), WaylandState> for WaylandState {
fn bind(
@@ -213,7 +205,7 @@ impl Default for Geometry {
pub struct XdgSurfaceData {
wl_surface: WlWeak<WlSurface>,
surface_id: SurfaceID,
panel_item: Weak<PanelItem<XDGBackend>>,
panel_item: Weak<PanelItem>,
geometry: Option<Geometry>,
}
impl XdgSurfaceData {
@@ -225,13 +217,13 @@ impl XdgSurfaceData {
geometry: None,
}
}
pub fn get(xdg_surface: &XdgSurface) -> Option<&Mutex<Self>> {
xdg_surface.data::<Mutex<Self>>()
pub fn get(xdg_surface: &XdgSurface) -> &Mutex<Self> {
xdg_surface.data::<Mutex<Self>>().unwrap()
}
pub fn wl_surface(&self) -> Option<WlSurface> {
self.wl_surface.upgrade().ok()
pub fn wl_surface(&self) -> WlSurface {
self.wl_surface.upgrade().unwrap()
}
pub fn panel_item(&self) -> Option<Arc<PanelItem<XDGBackend>>> {
pub fn panel_item(&self) -> Option<Arc<PanelItem>> {
self.panel_item.upgrade()
}
}
@@ -278,24 +270,26 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
xdg_surface.configure(SERIAL_COUNTER.inc());
let client_credentials = client.get_credentials(&state.display_handle).ok();
let Some(seat_data) = client.get_data::<ClientState>().map(|s| s.seat.clone()) else {return};
let Some(wl_surface) = xdg_surface_data.lock().wl_surface() else {return};
let seat_data = state.seats.get(&client.id()).unwrap().clone();
CoreSurface::add_to(
&state.display,
state.display_handle.clone(),
&wl_surface,
&xdg_surface_data.lock().wl_surface(),
{
let toplevel = toplevel.downgrade();
move || {
let toplevel = toplevel.upgrade().unwrap();
let toplevel_data = ToplevelData::get(&toplevel);
let Some(xdg_surface) = toplevel_data.lock().xdg_surface() else {return};
let Some(xdg_surface_data) = XdgSurfaceData::get(&xdg_surface) else {return};
let xdg_surface = toplevel_data.lock().xdg_surface();
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface);
let wl_surface = xdg_surface_data.lock().wl_surface();
xdg_surface_data.lock().surface_id = SurfaceID::Toplevel;
let Some(backend) = XDGBackend::create(toplevel.clone(), seat_data.clone()) else {return};
let (node, panel_item) = PanelItem::create(
Box::new(backend),
client_credentials.map(|c| c.pid),
toplevel.clone(),
wl_surface.clone(),
client_credentials,
seat_data.clone(),
);
toplevel_data.lock().panel_item_node.replace(node);
xdg_surface_data.lock().panel_item = Arc::downgrade(&panel_item);
@@ -307,7 +301,6 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
let toplevel = toplevel.upgrade().unwrap();
let toplevel_data = ToplevelData::get(&toplevel);
let Some(panel_item) = toplevel_data.lock().panel_item() else {
let Some(xdg_surface) = toplevel_data.lock().xdg_surface() else {return};
// if the wayland toplevel isn't mapped, hammer it again with a configure until it cooperates
toplevel.configure(
0,
@@ -318,6 +311,7 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
vec![]
},
);
let xdg_surface = toplevel_data.lock().xdg_surface();
xdg_surface.configure(SERIAL_COUNTER.inc());
return
};
@@ -356,21 +350,25 @@ impl Dispatch<XdgSurface, Mutex<XdgSurfaceData>, WaylandState> for WaylandState
xdg_surface_data.lock().surface_id = SurfaceID::Popup(uid);
let panel_item = parent_data.panel_item().unwrap();
xdg_surface_data.lock().panel_item = Arc::downgrade(&panel_item);
panel_item.seat_data.new_surface(
&xdg_surface_data.lock().wl_surface(),
Arc::downgrade(&panel_item),
);
debug!(?xdg_popup, ?xdg_surface, "Create XDG popup");
let xdg_surface = xdg_surface.downgrade();
let xdg_popup = xdg_popup.downgrade();
CoreSurface::add_to(
&state.display,
state.display_handle.clone(),
&xdg_surface_data.lock().wl_surface.upgrade().unwrap(),
move || {
let xdg_popup = xdg_popup.upgrade().unwrap();
let Some(popup_data) = PopupData::get(&xdg_popup) else {return};
let popup_data = PopupData::get(&xdg_popup);
let popup_data = popup_data.lock();
// panel_item.commit_popup(popup_data);
panel_item
.backend
.new_popup(&panel_item, &xdg_popup, &*popup_data);
panel_item.new_popup(&xdg_popup, &*popup_data);
},
move |commit_count| {
if commit_count == 0 {
@@ -442,22 +440,21 @@ impl ToplevelData {
toplevel.data::<Mutex<ToplevelData>>().unwrap()
}
pub fn xdg_surface(&self) -> Option<XdgSurface> {
self.xdg_surface.upgrade().ok()
pub fn xdg_surface(&self) -> XdgSurface {
self.xdg_surface.upgrade().unwrap()
}
fn panel_item(&self) -> Option<Arc<PanelItem<XDGBackend>>> {
let xdg_surface = self.xdg_surface()?;
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface)?.lock();
fn panel_item(&self) -> Option<Arc<PanelItem>> {
let xdg_surface = self.xdg_surface();
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface).lock();
xdg_surface_data.panel_item()
}
}
impl Serialize for ToplevelData {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let Some(xdg_surface) = self.xdg_surface() else {return serializer.serialize_none()};
let Some(xdg_surface_data) = XdgSurfaceData::get(&xdg_surface) else {return serializer.serialize_none()};
let xdg_surface_data = xdg_surface_data.lock();
let xdg_surface = self.xdg_surface();
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface).lock();
let geometry = xdg_surface_data.geometry.clone();
let Some(wl_surface) = xdg_surface_data.wl_surface() else {return serde_error::<S>("Wayland surface not found")};
let wl_surface = xdg_surface_data.wl_surface();
let Some(core_surface) = CoreSurface::from_wl_surface(&wl_surface) else {return serde_error::<S>("Core surface not found")};
let Some(size) = core_surface.size() else {return serializer.serialize_none()};
let geometry = geometry.unwrap_or_else(|| Geometry {
@@ -521,7 +518,7 @@ impl Dispatch<XdgToplevel, Mutex<ToplevelData>, WaylandState> for WaylandState {
}
xdg_toplevel::Request::Move { seat, serial } => {
debug!(?xdg_toplevel, ?seat, serial, "XDG Toplevel move request");
let Some(panel_item) = data.lock().panel_item() else {return};
let Some(panel_item) = data.lock().panel_item() else { return };
panel_item.recommend_toplevel_state(RecommendedState::Move);
}
xdg_toplevel::Request::Resize {
@@ -529,7 +526,7 @@ impl Dispatch<XdgToplevel, Mutex<ToplevelData>, WaylandState> for WaylandState {
serial,
edges,
} => {
let WEnum::Value(edges) = edges else {return};
let WEnum::Value(edges) = edges else { return };
debug!(
?xdg_toplevel,
?seat,
@@ -537,7 +534,7 @@ impl Dispatch<XdgToplevel, Mutex<ToplevelData>, WaylandState> for WaylandState {
?edges,
"XDG Toplevel resize request"
);
let Some(panel_item) = data.lock().panel_item() else {return};
let Some(panel_item) = data.lock().panel_item() else { return };
panel_item.recommend_toplevel_state(RecommendedState::Resize(edges as u32));
}
xdg_toplevel::Request::SetMaxSize { width, height } => {
@@ -551,29 +548,29 @@ impl Dispatch<XdgToplevel, Mutex<ToplevelData>, WaylandState> for WaylandState {
.then_some(Vector2::from([width as u32, height as u32]));
}
xdg_toplevel::Request::SetMaximized => {
let Some(panel_item) = data.lock().panel_item() else {return};
let Some(panel_item) = data.lock().panel_item() else { return };
panel_item.recommend_toplevel_state(RecommendedState::Maximize(true));
}
xdg_toplevel::Request::UnsetMaximized => {
let Some(panel_item) = data.lock().panel_item() else {return};
let Some(panel_item) = data.lock().panel_item() else { return };
panel_item.recommend_toplevel_state(RecommendedState::Maximize(false));
}
xdg_toplevel::Request::SetFullscreen { output: _ } => {
let Some(panel_item) = data.lock().panel_item() else {return};
let Some(panel_item) = data.lock().panel_item() else { return };
panel_item.recommend_toplevel_state(RecommendedState::Fullscreen(true));
}
xdg_toplevel::Request::UnsetFullscreen => {
let Some(panel_item) = data.lock().panel_item() else {return};
let Some(panel_item) = data.lock().panel_item() else { return };
panel_item.recommend_toplevel_state(RecommendedState::Fullscreen(true));
}
xdg_toplevel::Request::SetMinimized => {
let Some(panel_item) = data.lock().panel_item() else {return};
let Some(panel_item) = data.lock().panel_item() else { return };
panel_item.recommend_toplevel_state(RecommendedState::Minimize);
}
xdg_toplevel::Request::Destroy => {
debug!(?xdg_toplevel, "Destroy XDG Toplevel");
let Some(panel_item) = data.lock().panel_item() else {return};
panel_item.backend.on_drop();
let Some(panel_item) = data.lock().panel_item() else { return };
panel_item.on_drop();
}
_ => unreachable!(),
}
@@ -603,25 +600,21 @@ impl PopupData {
xdg_surface: xdg_surface.downgrade(),
}
}
pub fn get(popup: &XdgPopup) -> Option<&Mutex<Self>> {
popup.data::<Mutex<Self>>()
pub fn get(popup: &XdgPopup) -> &Mutex<Self> {
popup.data::<Mutex<Self>>().unwrap()
}
pub fn xdg_surface(&self) -> Option<XdgSurface> {
self.xdg_surface.upgrade().ok()
pub fn xdg_surface(&self) -> XdgSurface {
self.xdg_surface.upgrade().unwrap()
}
fn panel_item(&self) -> Option<Arc<PanelItem<XDGBackend>>> {
XdgSurfaceData::get(&self.xdg_surface()?)?
.lock()
.panel_item()
fn panel_item(&self) -> Option<Arc<PanelItem>> {
XdgSurfaceData::get(&self.xdg_surface()).lock().panel_item()
}
// fn get_parent(&self) -> Option<XdgSurface> {
// self.parent.as_ref()?.upgrade().ok()
// }
pub fn wl_surface(&self) -> Option<WlSurface> {
XdgSurfaceData::get(&self.xdg_surface()?)?
.lock()
.wl_surface()
pub fn wl_surface(&self) -> WlSurface {
XdgSurfaceData::get(&self.xdg_surface()).lock().wl_surface()
}
pub fn positioner_data(&self) -> Option<PositionerData> {
@@ -676,8 +669,8 @@ impl Dispatch<XdgPopup, Mutex<PopupData>, WaylandState> for WaylandState {
debug!(?xdg_popup, ?positioner, token, "XDG popup reposition");
data.positioner = positioner;
let Some(panel_item) = data.panel_item() else {return};
panel_item.backend.reposition_popup(&panel_item, &*data)
panel_item.reposition_popup(&*data);
// xdg_popup.popup_done(); // temporary hack to avoid apps locking up before popups are implemented
}
xdg_popup::Request::Destroy => {
let data = data.lock();
@@ -699,260 +692,6 @@ impl Dispatch<XdgPopup, Mutex<PopupData>, WaylandState> for WaylandState {
) {
let data = data.lock();
let Some(panel_item) = data.panel_item() else {return};
panel_item.backend.drop_popup(&panel_item, &data.uid);
}
}
pub struct XDGBackend {
toplevel: WlWeak<XdgToplevel>,
toplevel_wl_surface: WlWeak<WlSurface>,
popups: Mutex<FxHashMap<String, WlWeak<XdgPopup>>>,
cursor: watch::Receiver<Option<CursorInfo>>,
pub seat: Arc<SeatData>,
pointer_grab: Mutex<Option<SurfaceID>>,
keyboard_grab: Mutex<Option<SurfaceID>>,
}
impl XDGBackend {
pub fn create(toplevel: XdgToplevel, seat: Arc<SeatData>) -> Option<Self> {
let toplevel_wl_surface =
XdgSurfaceData::get(&ToplevelData::get(&toplevel).lock().xdg_surface()?)?
.lock()
.wl_surface()?
.downgrade();
let cursor = seat.new_surface(&toplevel_wl_surface.upgrade().ok()?);
Some(XDGBackend {
toplevel: toplevel.downgrade(),
toplevel_wl_surface,
popups: Mutex::new(FxHashMap::default()),
cursor,
seat,
pointer_grab: Mutex::new(None),
keyboard_grab: Mutex::new(None),
})
}
fn wl_surface_from_id(&self, id: &SurfaceID) -> Option<WlSurface> {
match id {
SurfaceID::Cursor => self.cursor.borrow().as_ref()?.surface.upgrade().ok(),
SurfaceID::Toplevel => self.toplevel_wl_surface(),
SurfaceID::Popup(popup) => {
let popups = self.popups.lock();
let popup = popups.get(popup)?.upgrade().ok()?;
let wl_surface = PopupData::get(&popup)?.lock().wl_surface();
wl_surface
}
}
}
fn toplevel(&self) -> Option<XdgToplevel> {
self.toplevel.upgrade().ok()
}
fn toplevel_xdg_surface(&self) -> Option<XdgSurface> {
let toplevel = self.toplevel()?;
let data = ToplevelData::get(&toplevel).lock();
data.xdg_surface()
}
fn toplevel_wl_surface(&self) -> Option<WlSurface> {
self.toplevel_wl_surface.upgrade().ok()
}
fn input_surfaces(&self) -> Vec<WlSurface> {
let mut surfaces = self
.toplevel_wl_surface()
.map(|s| vec![s])
.unwrap_or_default();
surfaces.extend(self.popups.lock().values().filter_map(|p| {
let popup = p.upgrade().ok()?;
let popup_data = PopupData::get(&popup)?.lock();
let xdg_surface = popup_data.xdg_surface()?;
let xdg_surface_data = XdgSurfaceData::get(&xdg_surface)?.lock();
xdg_surface_data.wl_surface()
}));
surfaces
}
pub fn new_popup(
&self,
panel_item: &PanelItem<XDGBackend>,
popup: &XdgPopup,
data: &PopupData,
) {
let uid = data.uid.clone();
self.popups.lock().insert(uid.clone(), popup.downgrade());
let Some(node) = panel_item.node() else {return};
let Ok(message) = serialize(&(&uid, data)) else {return};
let _ = node.send_remote_signal("new_popup", message);
}
pub fn reposition_popup(&self, panel_item: &PanelItem<XDGBackend>, popup_state: &PopupData) {
let Some(node) = panel_item.node() else {return};
let _ = node.send_remote_signal(
"reposition_popup",
serialize(popup_state.positioner_data().unwrap()).unwrap(),
);
}
pub fn drop_popup(&self, panel_item: &PanelItem<XDGBackend>, uid: &str) {
'seat_drop: {
let Some(popup) = self
.popups
.lock()
.remove(uid) else {break 'seat_drop};
let Some(popup) = popup.upgrade().ok() else {break 'seat_drop};
let Some(popup) = popup.data::<Arc<PopupData>>().cloned() else {break 'seat_drop};
let Some(wl_surface) = popup.wl_surface() else {break 'seat_drop};
self.seat.drop_surface(&wl_surface);
}
let Some(node) = panel_item.node() else {return};
let Ok(message) = serialize(uid) else {return};
let _ = node.send_remote_signal("drop_popup", message);
}
fn popups_data(&self) -> Vec<PopupData> {
self.popups
.lock()
.values()
.filter_map(|v| Some(v.upgrade().ok()?.data::<Mutex<PopupData>>()?.lock().clone()))
.collect::<Vec<_>>()
}
pub fn on_drop(&self) {
let Some(toplevel) = self.toplevel_wl_surface() else {return};
self.seat.drop_surface(&toplevel);
debug!("Dropped panel item gracefully");
}
fn flush_client(&self) {
let Some(client) = self.toplevel_wl_surface().and_then(|s| s.client()) else {return};
if let Some(client_state) = client.get_data::<ClientState>() {
client_state.flush();
}
}
}
impl Backend for XDGBackend {
fn serialize_start_data(&self, id: &str) -> Result<Message> {
let toplevel_state = self
.toplevel()
.map(|t| ToplevelData::get(&t).lock().clone());
let pointer_grab = self.pointer_grab.lock().clone();
let keyboard_grab = self.keyboard_grab.lock().clone();
Ok(serialize((
id,
(
self.cursor.borrow().as_ref().and_then(|c| c.cursor_data()),
toplevel_state,
self.popups_data(),
pointer_grab,
keyboard_grab,
),
))?
.into())
}
fn serialize_toplevel(&self) -> Result<Message> {
let toplevel = self
.toplevel()
.ok_or_else(|| eyre!("Toplevel does not exist"))?;
let state = ToplevelData::get(&toplevel);
let data = serialize(&state.lock().clone())?;
Ok(data.into())
}
fn set_toplevel_capabilities(&self, capabilities: Vec<u8>) {
let Ok(xdg_toplevel) = self.toplevel.upgrade() else {return};
let Some(xdg_surface) = self.toplevel_xdg_surface() else {return};
if xdg_toplevel.version() < EVT_WM_CAPABILITIES_SINCE {
return;
}
xdg_toplevel.wm_capabilities(capabilities);
xdg_surface.configure(SERIAL_COUNTER.inc());
self.flush_client();
}
fn configure_toplevel(
&self,
size: Option<Vector2<u32>>,
states: Vec<u32>,
bounds: Option<Vector2<u32>>,
) {
let Ok(xdg_toplevel) = self.toplevel.upgrade() else {return};
let Some(xdg_surface) = self.toplevel_xdg_surface() else {return};
debug!(?size, ?states, ?bounds, "Configure toplevel info");
if let Some(bounds) = bounds {
if xdg_toplevel.version() > EVT_CONFIGURE_BOUNDS_SINCE {
xdg_toplevel.configure_bounds(bounds.x as i32, bounds.y as i32);
}
}
let size = size.unwrap_or(Vector2::from([0; 2]));
xdg_toplevel.configure(
size.x as i32,
size.y as i32,
states
.into_iter()
.flat_map(|state| state.to_ne_bytes())
.collect(),
);
xdg_surface.configure(SERIAL_COUNTER.inc());
self.flush_client();
}
fn apply_surface_material(&self, surface: SurfaceID, model_part: &Arc<ModelPart>) {
let Some(wl_surface) = self.wl_surface_from_id(&surface) else {return};
let Some(core_surface) = CoreSurface::from_wl_surface(&wl_surface) else {return};
core_surface.apply_material(model_part);
}
fn pointer_motion(&self, surface: &SurfaceID, position: Vector2<f32>) {
let Some(surface) = self.wl_surface_from_id(surface) else {return};
self.seat
.pointer_event(&surface, PointerEvent::Motion(position));
}
fn pointer_button(&self, surface: &SurfaceID, button: u32, pressed: bool) {
let Some(surface) = self.wl_surface_from_id(surface) else {return};
self.seat.pointer_event(
&surface,
PointerEvent::Button {
button,
state: if pressed { 1 } else { 0 },
},
)
}
fn pointer_scroll(
&self,
surface: &SurfaceID,
scroll_distance: Option<Vector2<f32>>,
scroll_steps: Option<Vector2<f32>>,
) {
let Some(surface) = self.wl_surface_from_id(surface) else {return};
self.seat.pointer_event(
&surface,
PointerEvent::Scroll {
axis_continuous: scroll_distance,
axis_discrete: scroll_steps,
},
)
}
fn keyboard_set_keymap(&self, keymap: &str) -> Result<()> {
let context = xkb::Context::new(0);
let keymap =
Keymap::new_from_string(&context, keymap.to_string(), XKB_KEYMAP_FORMAT_TEXT_V1, 0)
.ok_or_else(|| eyre!("Keymap is not valid"))?;
self.seat.set_keymap(&keymap, self.input_surfaces());
Ok(())
}
fn keyboard_key(&self, surface: &SurfaceID, key: u32, state: bool) {
let Some(surface) = self.wl_surface_from_id(surface) else {return};
self.seat.keyboard_event(
&surface,
KeyboardEvent::Key {
key,
state: if state { 1 } else { 0 },
},
)
panel_item.drop_popup(&data.uid);
}
}

View File

@@ -1,398 +0,0 @@
use super::{
seat::{KeyboardEvent, PointerEvent, SeatData},
state::ClientState,
xdg_shell::PopupData,
};
use crate::{
nodes::{
drawable::model::ModelPart,
items::panel::{Backend, PanelItem, RecommendedState, SurfaceID},
Message,
},
wayland::surface::CoreSurface,
};
use color_eyre::eyre::Result;
use mint::Vector2;
use once_cell::sync::OnceCell;
use parking_lot::Mutex;
use smithay::{
reexports::{
calloop::{EventLoop, LoopSignal},
wayland_protocols::xdg::shell::server::xdg_toplevel,
wayland_server::{protocol::wl_surface::WlSurface, DisplayHandle, Resource, WEnum},
x11rb::protocol::xproto::Window,
},
utils::{Logical, Rectangle},
wayland::compositor,
xwayland::{
xwm::{Reorder, ResizeEdge, XwmId},
X11Surface, X11Wm, XWayland, XWaylandEvent, XwmHandler,
},
};
use stardust_xr::schemas::flex::serialize;
use std::{ffi::OsStr, iter::empty, sync::Arc, time::Duration};
use tokio::sync::oneshot;
use tracing::debug;
pub static DISPLAY: OnceCell<String> = OnceCell::new();
pub struct XWaylandState {
pub display: u32,
event_loop_signal: LoopSignal,
}
impl XWaylandState {
pub fn create(dh: &DisplayHandle) -> Result<Self> {
let dh = dh.clone();
let (tx, rx) = oneshot::channel();
tokio::task::spawn_blocking(move || {
let mut event_loop: EventLoop<XWaylandHandler> = EventLoop::try_new()?;
let (xwayland, connection) = XWayland::new(&dh);
let handle = event_loop.handle();
event_loop
.handle()
.insert_source(connection, {
let dh = dh.clone();
move |event, _, handler| match event {
XWaylandEvent::Ready {
connection,
client,
client_fd: _,
display: _,
} => {
handler.seat = client.get_data::<ClientState>().map(|s| s.seat.clone());
handler.wm =
X11Wm::start_wm(handle.clone(), dh.clone(), connection, client)
.ok();
}
XWaylandEvent::Exited => (),
}
})
.map_err(|e| e.error)?;
let display = xwayland.start(
event_loop.handle(),
None,
empty::<(&OsStr, &OsStr)>(),
true,
|_| (),
)?;
let _ = tx.send(XWaylandState {
display,
event_loop_signal: event_loop.get_signal(),
});
let mut handler = XWaylandHandler {
wayland_display_handle: dh,
wm: None,
seat: None,
};
event_loop.run(Duration::from_millis(100), &mut handler, |_| ())
});
let state = rx.blocking_recv()?;
let _ = DISPLAY.set(format!(":{}", state.display));
Ok(state)
}
}
impl Drop for XWaylandState {
fn drop(&mut self) {
self.event_loop_signal.stop();
}
}
struct XWaylandHandler {
wayland_display_handle: DisplayHandle,
wm: Option<X11Wm>,
seat: Option<Arc<SeatData>>,
}
impl XWaylandHandler {
fn panel_item(&self, window: &X11Surface) -> Option<Arc<PanelItem<X11Backend>>> {
compositor::with_states(&window.wl_surface()?, |s| {
s.data_map.get::<Arc<PanelItem<X11Backend>>>().cloned()
})
}
}
impl XwmHandler for XWaylandHandler {
fn xwm_state(&mut self, _xwm: XwmId) -> &mut X11Wm {
self.wm.as_mut().unwrap()
}
fn new_window(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "New X window");
}
fn new_override_redirect_window(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "New X override redirect window");
}
fn map_window_request(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "X map window request");
window.set_mapped(true).unwrap();
}
fn map_window_notify(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "X map window notify");
let dh = self.wayland_display_handle.clone();
let seat = self.seat.clone().unwrap();
CoreSurface::add_to(
self.wayland_display_handle.clone(),
&window.wl_surface().unwrap(),
{
let window = window.clone();
move || {
let Some(wl_surface) = window.wl_surface() else {return};
let seat = seat.clone();
window.user_data().insert_if_missing_threadsafe(|| {
let (_node, panel_item) = PanelItem::create(
Box::new(X11Backend {
toplevel_parent: None,
toplevel: window.clone(),
seat,
_pointer_grab: Mutex::new(None),
_keyboard_grab: Mutex::new(None),
}),
wl_surface
.client()
.and_then(|c| c.get_credentials(&dh).ok())
.map(|c| c.pid),
);
panel_item
});
}
},
move |_| {
let Some(panel_item) = window.user_data().get::<Arc<PanelItem<X11Backend>>>() else {return};
panel_item.commit_toplevel();
},
);
}
fn mapped_override_redirect_window(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "X map override redirect window");
}
fn unmapped_window(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "Unmap X window");
}
fn destroyed_window(&mut self, _xwm: XwmId, window: X11Surface) {
debug!(?window, "Destroy X window");
}
fn configure_request(
&mut self,
_xwm: XwmId,
window: X11Surface,
x: Option<i32>,
y: Option<i32>,
w: Option<u32>,
h: Option<u32>,
reorder: Option<Reorder>,
) {
debug!(?window, x, y, w, h, ?reorder, "Configure X window");
}
fn configure_notify(
&mut self,
_xwm: XwmId,
window: X11Surface,
geometry: Rectangle<i32, Logical>,
above: Option<Window>,
) {
debug!(?window, ?geometry, above, "Configure X window");
}
fn move_request(&mut self, _xwm: XwmId, window: X11Surface, button: u32) {
let Some(panel_item) = self.panel_item(&window) else {return};
debug!(?window, button, "X window requests move");
panel_item.recommend_toplevel_state(RecommendedState::Move);
}
fn resize_request(
&mut self,
_xwm: XwmId,
window: X11Surface,
button: u32,
resize_edge: ResizeEdge,
) {
let Some(panel_item) = self.panel_item(&window) else {return};
debug!(?window, button, ?resize_edge, "X window requests resize");
panel_item.recommend_toplevel_state(RecommendedState::Resize(
WEnum::Value(match resize_edge {
ResizeEdge::Top => xdg_toplevel::ResizeEdge::Top,
ResizeEdge::Bottom => xdg_toplevel::ResizeEdge::Bottom,
ResizeEdge::Left => xdg_toplevel::ResizeEdge::Left,
ResizeEdge::TopLeft => xdg_toplevel::ResizeEdge::TopLeft,
ResizeEdge::BottomLeft => xdg_toplevel::ResizeEdge::BottomLeft,
ResizeEdge::Right => xdg_toplevel::ResizeEdge::Right,
ResizeEdge::TopRight => xdg_toplevel::ResizeEdge::TopRight,
ResizeEdge::BottomRight => xdg_toplevel::ResizeEdge::BottomRight,
})
.into(),
));
}
fn maximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
let Some(panel_item) = self.panel_item(&window) else {return};
panel_item.recommend_toplevel_state(RecommendedState::Maximize(true));
}
fn unmaximize_request(&mut self, _xwm: XwmId, window: X11Surface) {
let Some(panel_item) = self.panel_item(&window) else {return};
panel_item.recommend_toplevel_state(RecommendedState::Maximize(false));
}
fn fullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) {
let Some(panel_item) = self.panel_item(&window) else {return};
panel_item.recommend_toplevel_state(RecommendedState::Fullscreen(true));
}
fn unfullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) {
let Some(panel_item) = self.panel_item(&window) else {return};
panel_item.recommend_toplevel_state(RecommendedState::Fullscreen(true));
}
fn minimize_request(&mut self, _xwm: XwmId, window: X11Surface) {
let Some(panel_item) = self.panel_item(&window) else {return};
panel_item.recommend_toplevel_state(RecommendedState::Minimize);
}
}
pub struct X11Backend {
pub toplevel_parent: Option<X11Surface>,
pub toplevel: X11Surface,
pub seat: Arc<SeatData>,
_pointer_grab: Mutex<Option<SurfaceID>>,
_keyboard_grab: Mutex<Option<SurfaceID>>,
}
impl X11Backend {
fn wl_surface_from_id(&self, id: &SurfaceID) -> Option<WlSurface> {
match id {
SurfaceID::Cursor => None,
SurfaceID::Toplevel => self.toplevel.wl_surface(),
SurfaceID::Popup(_) => None,
}
}
// fn flush_client(&self) {
// let Some(client) = self.toplevel.wl_surface().and_then(|s| s.client()) else {return};
// if let Some(client_state) = client.get_data::<ClientState>() {
// client_state.flush();
// }
// }
}
impl Backend for X11Backend {
fn serialize_start_data(&self, id: &str) -> Result<Message> {
let size = (
self.toplevel.geometry().size.w as u32,
self.toplevel.geometry().size.h as u32,
);
let toplevel_state = (
None::<String>,
self.toplevel.title(),
None::<String>,
(
self.toplevel.geometry().size.w as u32,
self.toplevel.geometry().size.h as u32,
),
self.toplevel.min_size().map(|s| (s.w as u32, s.h as u32)),
self.toplevel.max_size().map(|s| (s.w as u32, s.w as u32)),
((0_i32, 0_i32), size),
vec![0_u32; 0],
);
let info = (
None::<(Vector2<u32>, Vector2<i32>)>,
toplevel_state,
Vec::<PopupData>::new(),
None::<SurfaceID>,
None::<SurfaceID>,
);
Ok(serialize((id, info))?.into())
}
fn serialize_toplevel(&self) -> Result<Message> {
let toplevel_state = (
None::<String>,
self.toplevel.title(),
None::<String>,
(
self.toplevel.geometry().size.w,
self.toplevel.geometry().size.h,
),
self.toplevel.min_size().map(|s| (s.w, s.h)),
self.toplevel.max_size().map(|s| (s.w, s.w)),
);
let data = serialize(&toplevel_state)?;
Ok(data.into())
}
fn set_toplevel_capabilities(&self, _capabilities: Vec<u8>) {}
fn configure_toplevel(
&self,
size: Option<Vector2<u32>>,
states: Vec<u32>,
_bounds: Option<Vector2<u32>>,
) {
let _ = self.toplevel.configure(
size.map(|s| Rectangle::from_loc_and_size((0, 0), (s.x as i32, s.y as i32))),
);
let _ = self.toplevel.set_maximized(states.contains(&1));
}
fn apply_surface_material(&self, surface: SurfaceID, model_part: &Arc<ModelPart>) {
let Some(wl_surface) = self.wl_surface_from_id(&surface) else {return};
let Some(core_surface) = CoreSurface::from_wl_surface(&wl_surface) else {return};
core_surface.apply_material(model_part);
}
fn pointer_motion(&self, surface: &SurfaceID, position: Vector2<f32>) {
let Some(surface) = self.wl_surface_from_id(surface) else {return};
self.seat
.pointer_event(&surface, PointerEvent::Motion(position));
}
fn pointer_button(&self, surface: &SurfaceID, button: u32, pressed: bool) {
let Some(surface) = self.wl_surface_from_id(surface) else {return};
self.seat.pointer_event(
&surface,
PointerEvent::Button {
button,
state: if pressed { 1 } else { 0 },
},
)
}
fn pointer_scroll(
&self,
surface: &SurfaceID,
scroll_distance: Option<Vector2<f32>>,
scroll_steps: Option<Vector2<f32>>,
) {
let Some(surface) = self.wl_surface_from_id(surface) else {return};
self.seat.pointer_event(
&surface,
PointerEvent::Scroll {
axis_continuous: scroll_distance,
axis_discrete: scroll_steps,
},
)
}
fn keyboard_set_keymap(&self, keymap: &str) -> Result<()> {
self.seat.set_keymap_str(
&keymap,
if let Some(toplevel) = self.toplevel.wl_surface() {
vec![toplevel]
} else {
vec![]
},
)
}
fn keyboard_key(&self, surface: &SurfaceID, key: u32, state: bool) {
let Some(surface) = self.wl_surface_from_id(surface) else {return};
self.seat.keyboard_event(
&surface,
KeyboardEvent::Key {
key,
state: if state { 1 } else { 0 },
},
)
}
}