From 57039a3ccb16521e5bb461ad201957cd06072ccc Mon Sep 17 00:00:00 2001 From: Nova Date: Mon, 24 Apr 2023 06:18:21 -0400 Subject: [PATCH] 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 --- Cargo.lock | 523 +++++++++++++++++++-------------- Cargo.toml | 17 +- src/main.rs | 3 +- src/nodes/drawable/model.rs | 2 +- src/nodes/items/environment.rs | 2 + src/nodes/items/mod.rs | 3 +- src/nodes/mod.rs | 5 + src/wayland/compositor.rs | 29 +- src/wayland/mod.rs | 33 +-- src/wayland/panel_item.rs | 444 ++++++++++++++++------------ src/wayland/seat.rs | 248 ++++++---------- src/wayland/state.rs | 37 +-- src/wayland/surface.rs | 45 +-- src/wayland/xdg_shell.rs | 473 +++++++++++++++++++++-------- 14 files changed, 1091 insertions(+), 773 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7de2247..94e77ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -70,6 +70,55 @@ dependencies = [ "num-traits", ] +[[package]] +name = "anstream" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e579a7752471abc2a8268df8b20005e3eadd975f585398f17efcfd8d4927371" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is-terminal", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d" + +[[package]] +name = "anstyle-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +dependencies = [ + "windows-sys 0.48.0", +] + +[[package]] +name = "anstyle-wincon" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcd8291a340dd8ac70e18878bc4501dd7b4ff970cfa21c207d36ece51ea88fd" +dependencies = [ + "anstyle", + "windows-sys 0.48.0", +] + [[package]] name = "anyhow" version = "1.0.70" @@ -102,9 +151,9 @@ dependencies = [ [[package]] name = "async-stream" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" dependencies = [ "async-stream-impl", "futures-core", @@ -113,24 +162,24 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote 1.0.26", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] name = "async-trait" -version = "0.1.67" +version = "0.1.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ea188f25f0255d8f92797797c97ebf5631fa88178beb1a46fdf5622c9a00e4" +checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" dependencies = [ "proc-macro2", "quote 1.0.26", - "syn 2.0.8", + "syn 2.0.15", ] [[package]] @@ -141,13 +190,13 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.6.12" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f8ccfd9221ee7d1f3d4b33e1f8319b3a81ed8f61f2ea40b37b859794b4491" +checksum = "3b32c5ea3aabaf4deb5f5ced2d688ec0844c881c9e6c696a8b769a05fc691e62" dependencies = [ "async-trait", "axum-core", - "bitflags 1.3.2", + "bitflags", "bytes", "futures-util", "http", @@ -169,9 +218,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2f958c80c248b34b9a877a643811be8dbca03ca5ba827f2b63baf3a81e5fc4e" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", "bytes", @@ -211,7 +260,7 @@ version = "0.64.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cexpr", "clang-sys", "lazy_static", @@ -233,19 +282,13 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "bitflags" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1" - [[package]] name = "bitflags_serde_shim" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e678d043c18557c001a9f81be1c04e09339f9c990b8d5e20801e7ca4a1c6f244" dependencies = [ - "bitflags 1.3.2", + "bitflags", "serde", ] @@ -328,9 +371,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ed9a53e5d4d9c573ae844bfac6872b159cb1d1585a83b29e7a64b7eef7332a" +checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" dependencies = [ "glob", "libc", @@ -339,40 +382,45 @@ dependencies = [ [[package]] name = "clap" -version = "4.1.11" +version = "4.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42dfd32784433290c51d92c438bb72ea5063797fc3cc9a21a8c4346bebbb2098" +checksum = "956ac1f6381d8d82ab4684768f89c0ea3afe66925ceadb4eeb3fc452ffc55d62" dependencies = [ - "bitflags 2.0.2", + "clap_builder", "clap_derive", - "clap_lex", - "is-terminal", "once_cell", +] + +[[package]] +name = "clap_builder" +version = "4.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84080e799e54cff944f4b4a4b0e71630b0e0443b25b985175c7dddc1a859b749" +dependencies = [ + "anstream", + "anstyle", + "bitflags", + "clap_lex", "strsim", - "termcolor", ] [[package]] name = "clap_derive" -version = "4.1.9" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fddf67631444a3a3e3e5ac51c36a5e01335302de677bd78759eaa90ab1f46644" +checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4" dependencies = [ "heck 0.4.1", - "proc-macro-error", "proc-macro2", "quote 1.0.26", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] name = "clap_lex" -version = "0.3.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646" -dependencies = [ - "os_str_bytes", -] +checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1" [[package]] name = "cluFlock" @@ -386,9 +434,9 @@ dependencies = [ [[package]] name = "cmake" -version = "0.1.49" +version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db34956e100b30725f2eb215f90d4871051239535632f84fea3bc92722c66b7c" +checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" dependencies = [ "cc", ] @@ -443,6 +491,12 @@ dependencies = [ "tracing-error", ] +[[package]] +name = "colorchoice" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" + [[package]] name = "console-api" version = "0.4.0" @@ -481,9 +535,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "crc32fast" @@ -496,9 +550,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ "cfg-if", "crossbeam-utils", @@ -515,9 +569,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c00419335c41018365ddf7e4d5f1c12ee3659ddcf3e01974650ba1de73d038" +checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" dependencies = [ "cc", "cxxbridge-flags", @@ -527,9 +581,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb8307ad413a98fff033c8545ecf133e3257747b3bae935e7602aab8aa92d4ca" +checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" dependencies = [ "cc", "codespan-reporting", @@ -537,24 +591,24 @@ dependencies = [ "proc-macro2", "quote 1.0.26", "scratch", - "syn 2.0.8", + "syn 2.0.15", ] [[package]] name = "cxxbridge-flags" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc52e2eb08915cb12596d29d55f0b5384f00d697a646dbd269b6ecb0fbd9d31" +checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" [[package]] name = "cxxbridge-macro" -version = "1.0.93" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "631569015d0d8d54e6c241733f944042623ab6df7bc3be7466874b05fcdb1c5f" +checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" dependencies = [ "proc-macro2", "quote 1.0.26", - "syn 2.0.8", + "syn 2.0.15", ] [[package]] @@ -653,27 +707,16 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74be3be809c18e089de43bdc504652bb2bc473fca8756131f8689db8cf079ba9" dependencies = [ - "dirs-sys 0.4.0", + "dirs-sys", ] [[package]] name = "dirs" -version = "4.0.0" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +checksum = "dece029acd3353e3a58ac2e3eb3c8d6c35827a892edc6cc4138ef9c33df46ecd" dependencies = [ - "dirs-sys 0.3.7", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", + "dirs-sys", ] [[package]] @@ -716,13 +759,13 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "errno" -version = "0.2.8" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" dependencies = [ "errno-dragonfly", "libc", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -760,7 +803,7 @@ version = "23.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77f5399c2c9c50ae9418e522842ad362f61ee48b346ac106807bd355a8a7c619" dependencies = [ - "bitflags 1.3.2", + "bitflags", "rustc_version", ] @@ -780,7 +823,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15d14128f06405808ce75bfebe11e9b0f9da18719ede6d7bdb1702d6bfe0f7e8" dependencies = [ - "bitflags 1.3.2", + "bitflags", "byteorder", "num_enum 0.5.11", "serde", @@ -795,9 +838,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "futures" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -809,9 +852,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -819,33 +862,33 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-io" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-sink" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-util" -version = "0.3.27" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-core", "futures-sink", @@ -856,9 +899,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" dependencies = [ "cfg-if", "libc", @@ -918,9 +961,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.16" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" +checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21" dependencies = [ "bytes", "fnv", @@ -1032,9 +1075,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.25" +version = "0.14.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" dependencies = [ "bytes", "futures-channel", @@ -1068,9 +1111,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.54" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c17cc76786e99f8d2f055c11159e7f0091c42474dcc3189fbab96072e873e6d" +checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1104,9 +1147,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "indexmap" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown", @@ -1123,25 +1166,25 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" dependencies = [ "hermit-abi 0.3.1", "libc", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "is-terminal" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8687c819457e979cc940d09cb16e42a1bf70aa6b60a549de6d3a62a0ee90c69e" +checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", "rustix", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -1188,9 +1231,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.140" +version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" [[package]] name = "libloading" @@ -1213,9 +1256,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.1.4" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" +checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" [[package]] name = "lock_api" @@ -1348,7 +1391,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" dependencies = [ "autocfg", - "bitflags 1.3.2", + "bitflags", "cfg-if", "libc", "memoffset 0.6.5", @@ -1360,7 +1403,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cfg-if", "libc", "memoffset 0.7.1", @@ -1467,7 +1510,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote 1.0.26", - "syn 2.0.8", + "syn 2.0.15", ] [[package]] @@ -1485,12 +1528,6 @@ version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" -[[package]] -name = "os_str_bytes" -version = "6.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" - [[package]] name = "ouroboros" version = "0.15.6" @@ -1556,7 +1593,7 @@ dependencies = [ "cfg-if", "instant", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", "winapi", ] @@ -1569,7 +1606,7 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", "windows-sys 0.45.0", ] @@ -1626,9 +1663,9 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "portable-atomic" -version = "1.0.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c00c8683a03bd4fe7db7dd64ab4abee6b42166bc81231da983486ce96be51a" +checksum = "f602a0d1e09a48e4f8e8b4d4042e32807c3676da31f2ecabeac9f96226ec6c45" [[package]] name = "ppv-lite86" @@ -1683,18 +1720,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.53" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] [[package]] name = "prost" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" dependencies = [ "bytes", "prost-derive", @@ -1702,9 +1739,9 @@ dependencies = [ [[package]] name = "prost-derive" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" dependencies = [ "anyhow", "itertools", @@ -1715,9 +1752,9 @@ dependencies = [ [[package]] name = "prost-types" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88" +checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13" dependencies = [ "prost", ] @@ -1782,7 +1819,16 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags 1.3.2", + "bitflags", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags", ] [[package]] @@ -1792,15 +1838,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", - "redox_syscall", + "redox_syscall 0.2.16", "thiserror", ] [[package]] name = "regex" -version = "1.7.2" +version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cce168fea28d3e05f158bda4576cf0c844d5045bc2cc3620fa0292ed5bb5814c" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ "regex-syntax", ] @@ -1822,9 +1868,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "rustc-demangle" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc-hash" @@ -1843,16 +1889,16 @@ dependencies = [ [[package]] name = "rustix" -version = "0.36.11" +version = "0.37.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4165c9963ab29e422d6c26fbc1d37f15bace6b2810221f9d925023480fcf0e" +checksum = "85597d61f83914ddeba6a47b3b8ffe7365107221c2e557ed94426489fefb5f77" dependencies = [ - "bitflags 1.3.2", + "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -1905,29 +1951,29 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.158" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.158" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ "proc-macro2", "quote 1.0.26", - "syn 2.0.8", + "syn 2.0.15", ] [[package]] name = "serde_json" -version = "1.0.94" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "itoa", "ryu", @@ -1942,7 +1988,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab" dependencies = [ "proc-macro2", "quote 1.0.26", - "syn 2.0.8", + "syn 2.0.15", ] [[package]] @@ -1978,12 +2024,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "slog" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06" - [[package]] name = "slotmap" version = "1.0.6" @@ -2002,10 +2042,10 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "smithay" version = "0.3.0" -source = "git+https://github.com/technobaboo/smithay.git#1224a0ac9851cc0b2059c964139c3227ca45dff9" +source = "git+https://github.com/smithay/smithay.git#dd36639310f8529f366f5750cf10a86b8bf12eea" dependencies = [ "appendlist", - "bitflags 1.3.2", + "bitflags", "calloop", "cgmath", "downcast-rs", @@ -2019,9 +2059,9 @@ dependencies = [ "once_cell", "rand", "scan_fmt", - "slog", "tempfile", "thiserror", + "tracing", "wayland-protocols", "wayland-protocols-misc", "wayland-protocols-wlr", @@ -2041,9 +2081,9 @@ dependencies = [ [[package]] name = "stardust-xr" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "798fb96a582da0fe0c791cfc10005a5eff3fbe3024e73b139456e63eda1380f4" +checksum = "fc2cd4aadc48fe9f84ce997b91ab14a0553c03b9105a8429e46d213e95e04a13" dependencies = [ "chrono", "cluFlock", @@ -2096,14 +2136,12 @@ dependencies = [ "rustc-hash", "send_wrapper", "serde", - "slog", "smithay", "stardust-xr", "stereokit", "tokio", "tracing", "tracing-chrome", - "tracing-slog", "tracing-subscriber", "xkbcommon", ] @@ -2120,7 +2158,7 @@ version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e1a6491c921ee4bb53bc41f08345d621769ea6802cd020cd308975a790487cb" dependencies = [ - "bitflags 1.3.2", + "bitflags", "bitflags_serde_shim", "color-eyre", "derive_builder", @@ -2179,9 +2217,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.8" +version = "2.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" dependencies = [ "proc-macro2", "quote 1.0.26", @@ -2205,15 +2243,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", + "redox_syscall 0.3.5", "rustix", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] @@ -2242,7 +2280,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote 1.0.26", - "syn 2.0.8", + "syn 2.0.15", ] [[package]] @@ -2268,14 +2306,13 @@ dependencies = [ [[package]] name = "tokio" -version = "1.26.0" +version = "1.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64" +checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" dependencies = [ "autocfg", "bytes", "libc", - "memchr", "mio", "num_cpus", "parking_lot 0.12.1", @@ -2299,13 +2336,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.8.2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" dependencies = [ "proc-macro2", "quote 1.0.26", - "syn 1.0.109", + "syn 2.0.15", ] [[package]] @@ -2489,22 +2526,11 @@ dependencies = [ "tracing-core", ] -[[package]] -name = "tracing-slog" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ffd12d2d54fb99df994fde4e3320959e32208420bfe375a664c5d8cd894a23b" -dependencies = [ - "once_cell", - "slog", - "tracing-core", -] - [[package]] name = "tracing-subscriber" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" dependencies = [ "matchers", "nu-ansi-term", @@ -2560,6 +2586,12 @@ dependencies = [ "parking_lot 0.11.2", ] +[[package]] +name = "utf8parse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" + [[package]] name = "valuable" version = "0.1.0" @@ -2675,7 +2707,7 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fefbeb8a360abe67ab7c2efe1d297a1a50ee011f5460791bc18870c26bb84e2" dependencies = [ - "bitflags 1.3.2", + "bitflags", "wayland-backend", "wayland-scanner", "wayland-server", @@ -2687,7 +2719,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897d4e99645e1ed9245e9e6b5efa78828d2b23b661016d63d55251243d812f8b" dependencies = [ - "bitflags 1.3.2", + "bitflags", "wayland-backend", "wayland-protocols", "wayland-scanner", @@ -2700,7 +2732,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fce991093320e4a6a525876e6b629ab24da25f9baef0c2e0080ad173ec89588a" dependencies = [ - "bitflags 1.3.2", + "bitflags", "wayland-backend", "wayland-protocols", "wayland-scanner", @@ -2724,7 +2756,7 @@ version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9062def387c1b1d80e366d8243c2b3bd6d9e4f343032a3e5da8d4aa03866cf89" dependencies = [ - "bitflags 1.3.2", + "bitflags", "downcast-rs", "io-lifetimes", "nix 0.26.2", @@ -2787,26 +2819,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.46.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows-targets 0.48.0", ] [[package]] @@ -2815,7 +2832,16 @@ version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" dependencies = [ - "windows-targets", + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", ] [[package]] @@ -2824,13 +2850,28 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", ] [[package]] @@ -2839,36 +2880,72 @@ version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + [[package]] name = "windows_i686_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + [[package]] name = "windows_i686_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -2876,10 +2953,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] -name = "winnow" -version = "0.4.0" +name = "windows_x86_64_msvc" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deac0939bd6e4f24ab5919fbf751c97a8cfc8543bb083a305ed5c0c10bb241d1" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "winnow" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 6d4af91..85a2589 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ homepage = "https://stardustxr.org" [dependencies] color-eyre = { version = "0.6.2", default-features = false } -clap = { version = "4.1.6", features = ["derive"] } +clap = { version = "4.2.4", features = ["derive"] } dashmap = "5.4.0" glam = {version = "0.23.0", features = ["mint"]} lazy_static = "1.4.0" @@ -18,19 +18,17 @@ mint = "0.5.9" nanoid = "0.4.0" once_cell = "1.17.1" parking_lot = "0.12.1" -portable-atomic = {version = "1.0.1", features = ["float", "std"]} +portable-atomic = {version = "1.2.0", features = ["float", "std"]} rustc-hash = "1.1.0" -tokio = { version = "1.25.0", features = ["rt-multi-thread", "signal"] } +tokio = { version = "1.27.0", features = ["rt-multi-thread", "signal"] } send_wrapper = "0.6.0" prisma = "0.1.1" -slog = "2.7.0" xkbcommon = { version = "0.5.0", default-features = false, optional = true } -stardust-xr = "0.11.0" +stardust-xr = "0.11.1" directories = "5.0.0" -serde = { version = "1.0.152", features = ["derive"] } +serde = { version = "1.0.160", features = ["derive"] } tracing = "0.1.37" -tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } -tracing-slog = "0.2.0" +tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } global_counter = "0.2.2" rand = "0.8.5" @@ -40,7 +38,8 @@ features = ["linux-egl", "color_named", "prisma"] version = "0.15.3" [dependencies.smithay] -git = "https://github.com/technobaboo/smithay.git" # Until we get stereokit to understand OES samplers and external textures +# git = "https://github.com/technobaboo/smithay.git" # Until we get stereokit to understand OES samplers and external textures +git = "https://github.com/smithay/smithay.git" # Until we get stereokit to understand OES samplers and external textures default-features = false features = ["desktop", "renderer_gl", "wayland_frontend"] version = "*" diff --git a/src/main.rs b/src/main.rs index cb8e505..835731f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -74,6 +74,7 @@ fn main() -> Result<()> { let log_layer = fmt::Layer::new() .with_thread_names(true) .with_ansi(true) + .with_line_number(true) .with_filter(EnvFilter::from_default_env()); registry.with(log_layer).init(); @@ -250,8 +251,8 @@ fn main() -> Result<()> { Ok(()) } -// #[tokio::main] #[tokio::main] +// #[tokio::main(flavor = "current_thread")] async fn event_loop( info_sender: oneshot::Sender, stop_rx: oneshot::Receiver<()>, diff --git a/src/nodes/drawable/model.rs b/src/nodes/drawable/model.rs index 6b0199c..b44eeff 100644 --- a/src/nodes/drawable/model.rs +++ b/src/nodes/drawable/model.rs @@ -107,7 +107,7 @@ impl MaterialParameter { let Some(texture_path) = resource.get_file( &client.base_resource_prefixes.lock().clone(), &[OsStr::new("png"), OsStr::new("jpg")], - ) else { return; }; + ) else {return}; if let Some(tex) = Texture::from_file(sk, texture_path, true, 0) { material.set_parameter(sk, parameter_name, &tex); } diff --git a/src/nodes/items/environment.rs b/src/nodes/items/environment.rs index 3282670..c2e17a0 100644 --- a/src/nodes/items/environment.rs +++ b/src/nodes/items/environment.rs @@ -12,6 +12,7 @@ use crate::{ }; use color_eyre::eyre::{eyre, Result}; use lazy_static::lazy_static; +use nanoid::nanoid; use serde::Deserialize; use stardust_xr::{ schemas::flex::{deserialize, flexbuffers, serialize}, @@ -38,6 +39,7 @@ impl EnvironmentItem { pub fn add_to(node: &Arc, path: String) { Item::add_to( node, + nanoid!(), &ITEM_TYPE_INFO_ENVIRONMENT, ItemType::Environment(EnvironmentItem { path }), ); diff --git a/src/nodes/items/mod.rs b/src/nodes/items/mod.rs index 12af9a7..252ce4a 100644 --- a/src/nodes/items/mod.rs +++ b/src/nodes/items/mod.rs @@ -88,12 +88,13 @@ pub struct Item { impl Item { pub fn add_to( node: &Arc, + uid: String, type_info: &'static TypeInfo, specialization: ItemType, ) -> Arc { let item = Item { node: Arc::downgrade(node), - uid: node.uid.clone(), + uid, type_info, captured_acceptor: Default::default(), specialization, diff --git a/src/nodes/mod.rs b/src/nodes/mod.rs index 2a8bfd9..7b901af 100644 --- a/src/nodes/mod.rs +++ b/src/nodes/mod.rs @@ -272,3 +272,8 @@ impl Debug for Node { .finish() } } +impl Drop for Node { + fn drop(&mut self) { + // Debug breakpoint + } +} diff --git a/src/wayland/compositor.rs b/src/wayland/compositor.rs index 2bbb16c..ac189c8 100644 --- a/src/wayland/compositor.rs +++ b/src/wayland/compositor.rs @@ -1,4 +1,7 @@ -use super::{panel_item::PanelItem, state::WaylandState, surface::CoreSurface}; +use crate::wayland::surface::CoreSurface; + +use super::state::WaylandState; +use portable_atomic::{AtomicU32, Ordering}; use smithay::{ delegate_compositor, reexports::wayland_server::protocol::wl_surface::WlSurface, @@ -14,12 +17,24 @@ impl CompositorHandler for WaylandState { fn commit(&mut self, surface: &WlSurface) { debug!(?surface, "Surface commit"); - CoreSurface::add_to(&self.display, self.display_handle.clone(), surface); - if let Some(panel_item) = compositor::with_states(surface, |data| { - data.data_map.get::>().cloned() - }) { - panel_item.commit_toplevel(); - }; + let mut count = 0; + let core_surface = compositor::with_states(surface, |data| { + let count_new = data + .data_map + .insert_if_missing_threadsafe(|| AtomicU32::new(0)); + if !count_new { + count = data + .data_map + .get::() + .unwrap() + .fetch_add(1, Ordering::Relaxed); + } + + data.data_map.get::>().cloned() + }); + if let Some(core_surface) = core_surface { + core_surface.commit(count); + } } } diff --git a/src/wayland/mod.rs b/src/wayland/mod.rs index 3df4da7..5060be5 100644 --- a/src/wayland/mod.rs +++ b/src/wayland/mod.rs @@ -16,11 +16,9 @@ use global_counter::primitive::exact::CounterU32; use once_cell::sync::OnceCell; use parking_lot::Mutex; use sk::lifecycle::StereoKitDraw; -use slog::Drain; -use smithay::{ - backend::{egl::EGLContext, renderer::gles2::Gles2Renderer}, - reexports::wayland_server::{backend::GlobalId, Display, ListeningSocket}, -}; +use smithay::backend::egl::EGLContext; +use smithay::backend::renderer::gles::GlesRenderer; +use smithay::reexports::wayland_server::{backend::GlobalId, Display, ListeningSocket}; use std::os::unix::prelude::AsRawFd; use std::{ ffi::c_void, @@ -59,36 +57,28 @@ fn get_sk_egl() -> Result { static GLOBAL_DESTROY_QUEUE: OnceCell> = OnceCell::new(); pub struct Wayland { - log: slog::Logger, - display: Arc>>, pub socket_name: String, join_handle: JoinHandle>, - renderer: Gles2Renderer, + renderer: GlesRenderer, state: Arc>, } impl Wayland { pub fn new() -> Result { - let log = ::slog::Logger::root(::tracing_slog::TracingSlogDrain.fuse(), slog::o!()); - let egl_raw_handles = get_sk_egl()?; let renderer = unsafe { - Gles2Renderer::new( - EGLContext::from_raw( - egl_raw_handles.display, - egl_raw_handles.config, - egl_raw_handles.context, - log.clone(), - )?, - log.clone(), - )? + GlesRenderer::new(EGLContext::from_raw( + egl_raw_handles.display, + egl_raw_handles.config, + egl_raw_handles.context, + )?)? }; let display: Display = Display::new()?; let display_handle = display.handle(); let display = Arc::new(Mutex::new(display)); - let state = WaylandState::new(log.clone(), display.clone(), display_handle, &renderer); + let state = WaylandState::new(display.clone(), display_handle, &renderer); let (global_destroy_queue_in, global_destroy_queue) = mpsc::channel(8); GLOBAL_DESTROY_QUEUE.set(global_destroy_queue_in).unwrap(); @@ -101,7 +91,6 @@ impl Wayland { Wayland::start_loop(display.clone(), socket, state.clone(), global_destroy_queue)?; Ok(Wayland { - log, display, socket_name, join_handle, @@ -157,7 +146,7 @@ impl Wayland { #[instrument(level = "debug", name = "Wayland frame", skip(self, sk))] pub fn update(&mut self, sk: &StereoKitDraw) { for core_surface in CORE_SURFACES.get_valid_contents() { - core_surface.process(sk, &mut self.renderer, &self.log); + core_surface.process(sk, &mut self.renderer); } self.display.lock().flush_clients().unwrap(); diff --git a/src/wayland/panel_item.rs b/src/wayland/panel_item.rs index 567c37d..1edd383 100644 --- a/src/wayland/panel_item.rs +++ b/src/wayland/panel_item.rs @@ -1,7 +1,7 @@ use super::{ seat::{Cursor, SeatData}, surface::CoreSurface, - xdg_shell::{XdgSurfaceData, XdgToplevelData}, + xdg_shell::{PopupData, ToplevelData, XdgSurfaceData}, SERIAL_COUNTER, }; use crate::{ @@ -23,11 +23,18 @@ use lazy_static::lazy_static; use mint::Vector2; use nanoid::nanoid; use parking_lot::Mutex; -use serde::{Deserialize, Serialize}; +use rustc_hash::FxHashMap; +use serde::{ + de::{Deserializer, Error, SeqAccess, Visitor}, + ser::Serializer, + Deserialize, Serialize, +}; use smithay::{ reexports::{ - wayland_protocols::xdg::shell::server::xdg_toplevel::{ - XdgToplevel, EVT_CONFIGURE_BOUNDS_SINCE, EVT_WM_CAPABILITIES_SINCE, + 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, @@ -44,55 +51,92 @@ lazy_static! { pub static ref ITEM_TYPE_INFO_PANEL: TypeInfo = TypeInfo { type_name: "panel", aliased_local_signals: vec![ - "apply_cursor_material", - "apply_toplevel_material", + "apply_surface_material", "configure_toplevel", "set_toplevel_capabilities", - "pointer_set_active", "pointer_scroll", "pointer_button", "pointer_motion", - "keyboard_set_active", "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"], + 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(), }; } -#[derive(Debug, Clone, Serialize)] -pub struct ToplevelState { - #[serde(skip_serializing)] - pub mapped: bool, - #[serde(skip_serializing)] - pub parent: Option>, - pub title: Option, - pub app_id: Option, - pub size: Vector2, - pub max_size: Option>, - pub min_size: Option>, - pub states: Vec, - #[serde(skip_serializing)] - pub queued_state: Option>, +/// 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 ToplevelState { +impl Default for SurfaceID { fn default() -> Self { - Self { - mapped: false, - parent: None, - title: None, - app_id: None, - size: Vector2::from([0; 2]), - max_size: None, - min_size: None, - states: Vec::new(), - queued_state: None, + Self::Toplevel + } +} + +impl<'de> serde::Deserialize<'de> for SurfaceID { + fn deserialize>(deserializer: D) -> Result { + 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>(self, mut seq: A) -> Result { + 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(&self, serializer: S) -> Result { + match self { + Self::Cursor => ["Cursor"].serialize(serializer), + Self::Toplevel => ["Toplevel"].serialize(serializer), + Self::Popup(text) => ["Popup", text].serialize(serializer), } } } @@ -108,11 +152,15 @@ pub enum RecommendedState { } pub struct PanelItem { + pub uid: String, node: Weak, client_credentials: Option, + cursor: Mutex>>, + pub seat_data: Arc, toplevel: WlWeak, - pub cursor: Mutex>>, - seat_data: Arc, + popups: Mutex>>, + pointer_grab: Mutex>, + keyboard_grab: Mutex>, } impl PanelItem { pub fn create( @@ -122,51 +170,49 @@ impl PanelItem { seat_data: Arc, ) -> (Arc, Arc) { debug!(?toplevel, ?client_credentials, "Create panel item"); + let uid = nanoid!(); let node = Arc::new(Node::create( &INTERNAL_CLIENT, "/item/panel/item", - &nanoid!(), + &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), client_credentials, - toplevel: toplevel.downgrade(), cursor: Mutex::new(None), seat_data, + toplevel: toplevel.downgrade(), + popups: Mutex::new(FxHashMap::default()), + pointer_grab: Mutex::new(None), + keyboard_grab: Mutex::new(None), }); panel_item .seat_data - .new_panel_item(&panel_item, &toplevel, &wl_surface); + .new_surface(&wl_surface, Arc::downgrade(&panel_item)); let item = Item::add_to( &node, + uid, &ITEM_TYPE_INFO_PANEL, ItemType::Panel(panel_item.clone()), ); node.add_local_signal( - "apply_toplevel_material", - PanelItem::apply_toplevel_material_flex, + "apply_surface_material", + PanelItem::apply_surface_material_flex, ); node.add_local_signal("configure_toplevel", PanelItem::configure_toplevel_flex); - if toplevel.version() >= EVT_WM_CAPABILITIES_SINCE { - node.add_local_signal( - "set_toplevel_capabilities", - PanelItem::set_toplevel_capabilities_flex, - ); - } node.add_local_signal( - "apply_cursor_material", - PanelItem::apply_cursor_material_flex, + "set_toplevel_capabilities", + PanelItem::set_toplevel_capabilities_flex, ); - node.add_local_signal("pointer_set_active", PanelItem::pointer_set_active_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_active", PanelItem::keyboard_set_active_flex); node.add_local_signal( "keyboard_set_keymap_string", PanelItem::keyboard_set_keymap_string_flex, @@ -195,38 +241,26 @@ impl PanelItem { (node, panel_item) } - pub fn from_node(node: &Node) -> Option<&PanelItem> { - node.item.get().and_then(|item| match &item.specialization { - ItemType::Panel(panel_item) => Some(&**panel_item), - _ => None, - }) + pub fn from_node(node: &Node) -> Option> { + let ItemType::Panel(panel_item) = &node.item.get()?.specialization else {return None}; + Some(panel_item.clone()) } - fn toplevel_surface_data(&self) -> Option { - Some( - self.toplevel - .upgrade() - .ok()? - .data::()? - .xdg_surface_data - .clone(), - ) + fn toplevel(&self) -> XdgToplevel { + self.toplevel.upgrade().unwrap() } - fn toplevel_state(&self) -> Option>> { - Some( - self.toplevel - .upgrade() - .ok()? - .data::()? - .state - .clone(), - ) + fn toplevel_xdg_surface(&self) -> XdgSurface { + let toplevel = self.toplevel(); + let data = ToplevelData::get(&toplevel).lock(); + data.xdg_surface() } - pub fn toplevel_wl_surface(&self) -> Option { - self.toplevel_surface_data()?.wl_surface.upgrade().ok() + fn toplevel_wl_surface(&self) -> WlSurface { + XdgSurfaceData::get(&self.toplevel_xdg_surface()) + .lock() + .wl_surface() } fn core_surface(&self) -> Option> { - compositor::with_states(&self.toplevel_wl_surface()?, |data| { + compositor::with_states(&self.toplevel_wl_surface(), |data| { data.data_map.get::>().cloned() }) } @@ -235,55 +269,49 @@ impl PanelItem { core_surface.flush_clients(); } } - - fn apply_toplevel_material_flex( - node: &Node, - calling_client: Arc, - data: &[u8], - ) -> Result<()> { - #[derive(Debug, Deserialize)] - struct SurfaceMaterialInfo<'a> { - model_path: &'a str, - idx: u32, - } - let info: SurfaceMaterialInfo = deserialize(data)?; - let model_node = calling_client - .scenegraph - .get_node(info.model_path) - .ok_or_else(|| eyre!("Model node not found"))?; - let Some(Drawable::Model(model)) = model_node.drawable.get() else {bail!("Node is not a model")}; - debug!(?info, "Apply toplevel material"); - - if let ItemType::Panel(panel_item) = &node.item.get().unwrap().specialization { - if let Some(core_surface) = panel_item.core_surface() { - core_surface.apply_material(model.clone(), info.idx); + fn wl_surface_from_id(&self, id: &SurfaceID) -> Option { + 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) } } - - Ok(()) + } + fn wl_surface_from_id_result(&self, id: &SurfaceID) -> Result { + self.wl_surface_from_id(id) + .ok_or(eyre!("Surface with ID not found")) } - fn apply_cursor_material_flex( + fn apply_surface_material_flex( node: &Node, calling_client: Arc, data: &[u8], ) -> Result<()> { let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; - let Some(cursor) = panel_item.cursor.lock().as_ref().and_then(|c| c.upgrade().ok()) else { return Ok(())}; - let Some(core_surface) = CoreSurface::from_wl_surface(&cursor) else { return Ok(()) }; #[derive(Debug, Deserialize)] struct SurfaceMaterialInfo<'a> { + surface: SurfaceID, model_path: &'a str, idx: u32, } + let info: SurfaceMaterialInfo = deserialize(data)?; - debug!(?cursor, ?info, "Apply cursor material"); + + 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_path) .ok_or_else(|| eyre!("Model node not found"))?; let Some(Drawable::Model(model)) = model_node.drawable.get() else {bail!("Node is not a model")}; + debug!(?info, "Apply surface material"); + core_surface.apply_material(model.clone(), info.idx); Ok(()) @@ -291,69 +319,57 @@ impl PanelItem { fn pointer_motion_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; - let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) }; - debug!(?toplevel, "Pointer deactivate"); + + let (surface_id, position): (SurfaceID, Vector2) = 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(&toplevel, PointerEvent::Motion(deserialize(data)?)); + .pointer_event(&wl_surface, PointerEvent::Motion(position)); panel_item.flush_clients(); Ok(()) } fn pointer_button_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; - let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) }; - let (button, state): (u32, u32) = deserialize(data)?; - debug!(button, state, "Pointer button"); + 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(&toplevel, PointerEvent::Button { button, state }); + .pointer_event(&wl_surface, PointerEvent::Button { button, state }); panel_item.flush_clients(); Ok(()) } fn pointer_scroll_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; - let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) }; #[derive(Debug, Deserialize)] - struct PointerScrollArgs { + struct PointerScrollInfo { + surface_id: SurfaceID, axis_continuous: Option>, axis_discrete: Option>, } - let args: PointerScrollArgs = deserialize(data)?; + let info: PointerScrollInfo = deserialize(data)?; + let wl_surface = panel_item.wl_surface_from_id_result(&info.surface_id)?; - debug!(?args, "Pointer scroll"); + debug!(?info, "Pointer scroll"); panel_item.seat_data.pointer_event( - &toplevel, + &wl_surface, PointerEvent::Scroll { - axis_continuous: args.axis_continuous, - axis_discrete: args.axis_discrete, + axis_continuous: info.axis_continuous, + axis_discrete: info.axis_discrete, }, ); panel_item.flush_clients(); Ok(()) } - fn pointer_set_active_flex( - node: &Node, - _calling_client: Arc, - data: &[u8], - ) -> Result<()> { - let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; - let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) }; - let active: bool = deserialize(data)?; - debug!(?toplevel, active, "Pointer set active"); - - panel_item.seat_data.set_pointer_active(&toplevel, active); - panel_item.flush_clients(); - - Ok(()) - } fn keyboard_set_keymap_string_flex( node: &Node, @@ -397,38 +413,32 @@ impl PanelItem { } fn keyboard_set_keymap_flex(node: &Node, keymap: &Keymap) -> Result<()> { let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; - let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) }; + let toplevel = panel_item.toplevel_wl_surface(); debug!(?toplevel, "Keyboard set keymap"); - panel_item.seat_data.set_keymap(&toplevel, 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()) + })); - Ok(()) - } - - fn keyboard_set_active_flex( - node: &Node, - _calling_client: Arc, - data: &[u8], - ) -> Result<()> { - let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; - let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) }; - let active: bool = deserialize(data)?; - debug!(?toplevel, active, "Keyboard set active"); - - panel_item.seat_data.set_keyboard_active(&toplevel, active); + panel_item.seat_data.set_keymap(keymap, surfaces); Ok(()) } fn keyboard_key_flex(node: &Node, _calling_client: Arc, data: &[u8]) -> Result<()> { let Some(panel_item) = PanelItem::from_node(node) else { return Ok(()) }; - let Ok(toplevel) = panel_item.toplevel.upgrade() else { return Ok(()) }; - let (key, state): (u32, u32) = deserialize(data)?; + 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(&toplevel, KeyboardEvent::Key { key, state }); + .keyboard_event(&wl_surface, KeyboardEvent::Key { key, state }); Ok(()) } @@ -441,7 +451,7 @@ impl PanelItem { 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 Some(xdg_surface) = panel_item.toplevel_surface_data().and_then(|d| d.xdg_surface.upgrade().ok()) else { return Ok(()) }; + let xdg_surface = panel_item.toplevel_xdg_surface(); #[derive(Debug, Deserialize)] struct ConfigureToplevelInfo { @@ -452,9 +462,6 @@ impl PanelItem { let info: ConfigureToplevelInfo = deserialize(data)?; debug!(info = ?&info, "Configure toplevel info"); - if let Some(xdg_state) = panel_item.toplevel_state() { - xdg_state.lock().queued_state.as_mut().unwrap().states = info.states.clone(); - } 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); @@ -483,7 +490,10 @@ impl PanelItem { 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 Some(xdg_surface) = panel_item.toplevel_surface_data().and_then(|d| d.xdg_surface.upgrade().ok()) else { return Ok(()) }; + if xdg_toplevel.version() < EVT_WM_CAPABILITIES_SINCE { + return Ok(()); + } + let xdg_surface = panel_item.toplevel_xdg_surface(); let capabilities: Vec = deserialize(data)?; debug!("Set toplevel capabilities"); @@ -495,23 +505,22 @@ impl PanelItem { } pub fn commit_toplevel(&self) { - let mapped_size = self.core_surface().and_then(|c| c.size()); - let Some(state) = self.toplevel_state() else { return }; - let mut 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; - } - *state = (*queued_state).clone(); - state.queued_state = Some(queued_state); + // 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.mapped.then_some(&*state), "Commit toplevel"); + debug!(state = ?&*state, "Commit toplevel"); let Some(node) = self.node.upgrade() else { return }; - let _ = node.send_remote_signal( - "commit_toplevel", - &serialize(&state.mapped.then_some(&*state)).unwrap(), - ); + let _ = node.send_remote_signal("commit_toplevel", &serialize(&*state).unwrap()); } pub fn recommend_toplevel_state(&self, state: RecommendedState) { @@ -522,6 +531,56 @@ impl PanelItem { 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::() + // .unwrap() + // .wl_surface + // .upgrade() + // .unwrap(); + + // let core_surface = + // compositor::with_states(&surf, |s| s.data_map.get::>().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::>().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) { + 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"); @@ -540,8 +599,8 @@ impl PanelItem { } pub fn on_drop(&self) { - let Ok(toplevel) = self.toplevel.upgrade() else { return; }; - self.seat_data.drop_panel_item(&toplevel); + let toplevel = self.toplevel_wl_surface(); + self.seat_data.drop_surface(&toplevel); debug!("Drop panel item"); } @@ -559,12 +618,35 @@ impl ItemSpecialization for PanelItem { }) .map(|cursor| cursor.hotspot); - let toplevel_state = self.toplevel_state(); - let toplevel_state = toplevel_state.as_ref().map(|state| state.lock()); - let toplevel_state = toplevel_state - .as_ref() - .and_then(|state| state.mapped.then_some(&**state)); + let toplevel = self.toplevel(); + let toplevel_state = ToplevelData::get(&toplevel); + let toplevel_state = toplevel_state.lock().clone(); - serialize((id, (toplevel_state, cursor_size.zip(cursor_hotspot)))).unwrap() + let popups = self + .popups + .lock() + .values() + .filter_map(|v| Some(v.upgrade().ok()?.data::>()?.lock().clone())) + .collect::>(); + + 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 } } diff --git a/src/wayland/seat.rs b/src/wayland/seat.rs index ab0a7d0..983630b 100644 --- a/src/wayland/seat.rs +++ b/src/wayland/seat.rs @@ -1,9 +1,8 @@ -use crate::core::task; - use super::{ panel_item::PanelItem, state::WaylandState, surface::CoreSurface, GLOBAL_DESTROY_QUEUE, SERIAL_COUNTER, }; +use crate::core::task; use color_eyre::eyre::Result; use mint::Vector2; use nanoid::nanoid; @@ -13,20 +12,16 @@ use rand::{seq::IteratorRandom, thread_rng}; use rustc_hash::{FxHashMap, FxHashSet}; use smithay::{ input::keyboard::{KeymapFile, ModifiersState}, - reexports::{ - wayland_protocols::xdg::shell::server::xdg_toplevel::XdgToplevel, - wayland_server::{ - backend::{ClientId, GlobalId, ObjectId}, - protocol::{ - wl_keyboard::{self, KeyState, WlKeyboard}, - wl_pointer::{self, Axis, ButtonState, WlPointer}, - wl_seat::{self, Capability, WlSeat, EVT_NAME_SINCE}, - wl_surface::WlSurface, - wl_touch::{self, WlTouch}, - }, - Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, - Weak as WlWeak, + reexports::wayland_server::{ + backend::{ClientId, GlobalId, ObjectId}, + protocol::{ + wl_keyboard::{self, KeyState, WlKeyboard}, + wl_pointer::{self, Axis, ButtonState, WlPointer}, + wl_seat::{self, Capability, WlSeat, EVT_NAME_SINCE}, + wl_surface::WlSurface, + wl_touch::{self, WlTouch}, }, + Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, Weak as WlWeak, }, wayland::compositor, }; @@ -48,7 +43,7 @@ impl KeyboardInfo { pub fn new(keymap: &Keymap) -> Self { KeyboardInfo { state: xkb::State::new(keymap), - keymap: KeymapFile::new(keymap, None), + keymap: KeymapFile::new(keymap), mods: ModifiersState::default(), keys: FxHashSet::default(), } @@ -109,51 +104,34 @@ pub enum KeyboardEvent { } const POINTER_EVENT_TIMEOUT: Duration = Duration::from_secs(1); -struct PanelInfo { +struct SurfaceInfo { + wl_surface: WlWeak, panel_item: Weak, - toplevel: WlWeak, - focus: WlWeak, - pointer_queue: Option>, + pointer_queue: VecDeque, pointer_latest_event: Instant, - keyboard_queue: Option>, + keyboard_queue: VecDeque, keyboard_info: Option, } -impl PanelInfo { - fn new(panel_item: &Arc, toplevel: &XdgToplevel, focus: &WlSurface) -> Self { - PanelInfo { - toplevel: toplevel.downgrade(), - panel_item: Arc::downgrade(panel_item), - focus: focus.downgrade(), - pointer_queue: None, +impl SurfaceInfo { + fn new(wl_surface: &WlSurface, panel_item: Weak) -> Self { + SurfaceInfo { + wl_surface: wl_surface.downgrade(), + panel_item, + pointer_queue: VecDeque::new(), pointer_latest_event: Instant::now(), - keyboard_queue: None, + keyboard_queue: VecDeque::new(), keyboard_info: None, } } - pub fn set_pointer_active(&mut self, seat_data: &SeatData, active: bool) { - if active && self.pointer_queue.is_none() { - self.pointer_queue.replace(Default::default()); - } - - if !active && self.pointer_queue.is_some() { - self.pointer_queue.take(); - let Ok(focus) = self.focus.upgrade() else {return}; - let Some((pointer, pointer_focus)) = seat_data.pointer.get() else {return}; - if &*pointer_focus.lock() == &Some(self.toplevel.id()) { - pointer.leave(SERIAL_COUNTER.inc(), &focus); - } - } - } fn handle_pointer_events(&mut self, pointer: &WlPointer, mut locked: bool) -> bool { - let Ok(focus) = self.focus.upgrade() else { return false; }; - let Some(pointer_queue) = self.pointer_queue.as_mut() else { return false; }; + let Ok(focus) = self.wl_surface.upgrade() else { return false; }; let Some(core_surface) = CoreSurface::from_wl_surface(&focus) else { return false; }; let Some(focus_size) = core_surface.size() else { return false; }; - if !pointer_queue.is_empty() { + if !self.pointer_queue.is_empty() { self.pointer_latest_event = Instant::now(); } - while let Some(event) = pointer_queue.pop_front() { + while let Some(event) = self.pointer_queue.pop_front() { match (locked, event) { (false, PointerEvent::Motion(pos)) => { pointer.enter( @@ -218,22 +196,8 @@ impl PanelInfo { locked } - pub fn set_keyboard_active(&mut self, seat_data: &SeatData, active: bool) { - if active && self.keyboard_queue.is_none() { - self.keyboard_queue.replace(Default::default()); - } - if !active && self.keyboard_queue.is_some() { - self.keyboard_queue.take(); - let Ok(focus) = self.focus.upgrade() else {return}; - let Some((keyboard, keyboard_focus)) = seat_data.keyboard.get() else {return}; - if &*keyboard_focus.lock() == &Some(self.toplevel.id()) { - keyboard.leave(SERIAL_COUNTER.inc(), &focus); - } - } - } fn handle_keyboard_events(&mut self, keyboard: &WlKeyboard, mut locked: bool) -> bool { - let Ok(focus) = self.focus.upgrade() else { return false; }; - let Some(keyboard_queue) = self.keyboard_queue.as_mut() else { return false; }; + let Ok(focus) = self.wl_surface.upgrade() else { return false; }; let Some(info) = self.keyboard_info.as_mut() else { return true; }; if !locked { @@ -241,7 +205,7 @@ impl PanelInfo { keyboard.repeat_info(0, 0); locked = info.keymap.send(keyboard).is_ok(); } - while let Some(event) = keyboard_queue.pop_front() { + while let Some(event) = self.keyboard_queue.pop_front() { debug!(locked, ?event, "Process keyboard event"); match (locked, event) { (true, KeyboardEvent::Keymap) => { @@ -267,9 +231,9 @@ impl PanelInfo { pub struct SeatData { client: ClientId, global_id: OnceCell, - panels: Mutex>, - pointer: OnceCell<(WlPointer, Mutex>)>, - keyboard: OnceCell<(WlKeyboard, Mutex>)>, + surfaces: Mutex>, + pointer: OnceCell<(WlPointer, Mutex)>, + keyboard: OnceCell<(WlKeyboard, Mutex)>, touch: OnceCell, } impl SeatData { @@ -277,7 +241,7 @@ impl SeatData { let seat_data = Arc::new(SeatData { client, global_id: OnceCell::new(), - panels: Mutex::new(FxHashMap::default()), + surfaces: Mutex::new(FxHashMap::default()), pointer: OnceCell::new(), keyboard: OnceCell::new(), touch: OnceCell::new(), @@ -291,144 +255,111 @@ impl SeatData { seat_data } - // pub fn set_focus(&self, toplevel: &WlSurface, focus: &WlSurface) { - // if let Some(panel_info) = self.panels.lock().get_mut(&toplevel.id()) { - // panel_info.focus = focus.downgrade(); - // match panel_info.pointer_queue.back() { - // None => (), - // Some(&PointerEvent::Leave) => (), - // _ => panel_info.pointer_queue.push_back(PointerEvent::Leave), - // }; - // match panel_info.keyboard_queue.back() { - // None => (), - // Some(&KeyboardEvent::Leave) => (), - // _ => panel_info.keyboard_queue.push_back(KeyboardEvent::Leave), - // }; - // } - // } - pub fn set_pointer_active(&self, toplevel: &XdgToplevel, active: bool) { - let mut panels = self.panels.lock(); - let Some(panel_info) = panels.get_mut(&toplevel.id()) else {return}; - panel_info.set_pointer_active(self, active); - } - pub fn set_keyboard_active(&self, toplevel: &XdgToplevel, active: bool) { - let mut panels = self.panels.lock(); - let Some(panel_info) = panels.get_mut(&toplevel.id()) else {return}; - panel_info.set_keyboard_active(self, active); - } - pub fn set_keymap(&self, toplevel: &XdgToplevel, keymap: &Keymap) { - let mut panels = self.panels.lock(); - let Some(panel_info) = panels.get_mut(&toplevel.id()) else {return}; - panel_info.keyboard_info.replace(KeyboardInfo::new(keymap)); - - let Some(keyboard_queue) = panel_info.keyboard_queue.as_mut() else {return}; + pub fn set_keymap(&self, keymap: &Keymap, surfaces: Vec) { + let mut panels = self.surfaces.lock(); let Some((_, focus)) = self.keyboard.get() else {return}; - let Some(id) = &*focus.lock() else {return}; - if id == &toplevel.id() { - keyboard_queue.push_back(KeyboardEvent::Keymap); + for surface in surfaces { + let Some(surface_info) = panels.get_mut(&surface.id()) else {continue}; + surface_info + .keyboard_info + .replace(KeyboardInfo::new(keymap)); + + if *focus.lock() == surface.id() { + surface_info.keyboard_queue.push_back(KeyboardEvent::Keymap); + } } } - pub fn pointer_event(&self, toplevel: &XdgToplevel, event: PointerEvent) { - let mut panels = self.panels.lock(); - let Some(panel_info) = panels.get_mut(&toplevel.id()) else {return}; - let Some(pointer_queue) = panel_info.pointer_queue.as_mut() else {return}; - pointer_queue.push_back(event); - drop(panels); + pub fn pointer_event(&self, surface: &WlSurface, event: PointerEvent) { + let mut surfaces = self.surfaces.lock(); + let Some(surface_info) = surfaces.get_mut(&surface.id()) else {return}; + surface_info.pointer_queue.push_back(event); + drop(surfaces); self.handle_pointer_events(); } - pub fn keyboard_event(&self, toplevel: &XdgToplevel, event: KeyboardEvent) { - let mut panels = self.panels.lock(); - let Some(panel_info) = panels.get_mut(&toplevel.id()) else {return}; - let Some(keyboard_queue) = panel_info.keyboard_queue.as_mut() else {return}; - keyboard_queue.push_back(event); - drop(panels); + pub fn keyboard_event(&self, surface: &WlSurface, event: KeyboardEvent) { + let mut surfaces = self.surfaces.lock(); + let Some(surface_info) = surfaces.get_mut(&surface.id()) else {return}; + surface_info.keyboard_queue.push_back(event); + drop(surfaces); self.handle_keyboard_events(); } fn handle_pointer_events(&self) { - let mut panels = self.panels.lock(); + let mut surfaces = self.surfaces.lock(); let Some((pointer, pointer_focus)) = self.pointer.get() else {return}; let mut pointer_focus = pointer_focus.lock(); loop { - let locked = pointer_focus.is_some(); + let locked = !pointer_focus.is_null(); // Pick a pointer to focus on if there is none - if pointer_focus.is_none() { - *pointer_focus = panels + if pointer_focus.is_null() { + *pointer_focus = surfaces .iter() - .filter(|(_k, v)| v.pointer_queue.is_some()) - .filter(|(_k, v)| !v.pointer_queue.as_ref().unwrap().is_empty()) + .filter(|(_k, v)| !v.pointer_queue.is_empty()) .map(|(k, _v)| k) .choose(&mut thread_rng()) - .cloned(); + .cloned() + .unwrap_or(ObjectId::null()); } - if pointer_focus.is_none() { + if pointer_focus.is_null() { // If there's still none, guess we're done with pointer events for the time being break; } - let Some(panel_info) = panels.get_mut(pointer_focus.as_ref().unwrap()) else {break}; - if panel_info.handle_pointer_events(pointer, locked) { + let Some(surface_info) = surfaces.get_mut(&pointer_focus) else {break}; + if surface_info.handle_pointer_events(pointer, locked) { // We haven't gotten to a point where we can switch the focus break; } else { - pointer_focus.take(); + *pointer_focus = ObjectId::null(); } } } fn handle_keyboard_events(&self) { - let mut panels = self.panels.lock(); + let mut surfaces = self.surfaces.lock(); let Some((keyboard, keyboard_focus)) = self.keyboard.get() else {return}; let mut keyboard_focus = keyboard_focus.lock(); loop { - let locked = keyboard_focus.is_some(); + let locked = !keyboard_focus.is_null(); // Pick a keyboard to focus on if there is none - if keyboard_focus.is_none() { - *keyboard_focus = panels + if keyboard_focus.is_null() { + *keyboard_focus = surfaces .iter() .filter(|(_k, v)| v.keyboard_info.is_some()) - .filter(|(_k, v)| v.keyboard_queue.is_some()) - .filter(|(_k, v)| !v.keyboard_queue.as_ref().unwrap().is_empty()) + .filter(|(_k, v)| !v.keyboard_queue.is_empty()) .map(|(k, _v)| k) .choose(&mut thread_rng()) - .cloned(); + .cloned() + .unwrap_or(ObjectId::null()); } - if keyboard_focus.is_none() { - // If there's still none, guess we're done with keyboard events for the time being - break; - } - let Some(panel_info) = panels.get_mut(keyboard_focus.as_ref().unwrap()) else {break}; - if panel_info.handle_keyboard_events(keyboard, locked) { + // If there's still none, guess we're done with keyboard events for the time being + let Some(surface_info) = surfaces.get_mut(&keyboard_focus) else {break}; + if surface_info.handle_keyboard_events(keyboard, locked) { // We haven't gotten to a point where we can switch the focus break; } else { - keyboard_focus.take(); + *keyboard_focus = ObjectId::null(); } } } - pub fn new_panel_item( - &self, - panel_item: &Arc, - toplevel: &XdgToplevel, - focus: &WlSurface, - ) { - self.panels + pub fn new_surface(&self, surface: &WlSurface, panel_item: Weak) { + self.surfaces .lock() - .insert(toplevel.id(), PanelInfo::new(panel_item, toplevel, focus)); + .insert(surface.id(), SurfaceInfo::new(surface, panel_item)); } - pub fn drop_panel_item(&self, toplevel: &XdgToplevel) { - self.panels.lock().remove(&toplevel.id()); + pub fn drop_surface(&self, surface: &WlSurface) { + self.surfaces.lock().remove(&surface.id()); if let Some((_, pointer_focus)) = self.pointer.get() { let mut pointer_focus = pointer_focus.lock(); - if *pointer_focus == Some(toplevel.id()) { - pointer_focus.take(); + if *pointer_focus == surface.id() { + *pointer_focus = ObjectId::null(); } } if let Some((_, keyboard_focus)) = self.keyboard.get() { let mut keyboard_focus = keyboard_focus.lock(); - if *keyboard_focus == Some(toplevel.id()) { - keyboard_focus.take(); + if *keyboard_focus == surface.id() { + *keyboard_focus = ObjectId::null(); } } } @@ -478,12 +409,12 @@ impl Dispatch, WaylandState> for WaylandState { match request { wl_seat::Request::GetPointer { id } => { let pointer = data_init.init(id, data.clone()); - let _ = data.pointer.set((pointer, Mutex::new(None))); + let _ = data.pointer.set((pointer, Mutex::new(ObjectId::null()))); } wl_seat::Request::GetKeyboard { id } => { let keyboard = data_init.init(id, data.clone()); keyboard.repeat_info(0, 0); - let _ = data.keyboard.set((keyboard, Mutex::new(None))); + let _ = data.keyboard.set((keyboard, Mutex::new(ObjectId::null()))); } wl_seat::Request::GetTouch { id } => { let _ = data.touch.set(data_init.init(id, data.clone())); @@ -515,7 +446,7 @@ impl Dispatch, WaylandState> for WaylandState { hotspot_y, } => { if let Some(surface) = surface.as_ref() { - CoreSurface::add_to(&state.display, 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 { @@ -533,10 +464,9 @@ impl Dispatch, WaylandState> for WaylandState { let Some((_, focus)) = seat_data.pointer.get() else {return}; let focus = focus.lock(); - let Some(id) = &*focus else {return}; - let panels = seat_data.panels.lock(); - let Some(panel_info) = panels.get(&id) else {return}; - let Some(panel_item) = panel_info.panel_item.upgrade() else {return}; + let surfaces = seat_data.surfaces.lock(); + let Some(surface_info) = surfaces.get(&focus) else {return}; + 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 => (), diff --git a/src/wayland/state.rs b/src/wayland/state.rs index dad1a40..8b80cbe 100644 --- a/src/wayland/state.rs +++ b/src/wayland/state.rs @@ -1,11 +1,10 @@ use crate::wayland::seat::SeatData; use parking_lot::Mutex; use rustc_hash::FxHashMap; -use slog::Logger; use smithay::{ backend::{ allocator::dmabuf::Dmabuf, - renderer::{gles2::Gles2Renderer, ImportDma}, + renderer::{gles::GlesRenderer, ImportDma}, }, delegate_dmabuf, delegate_output, delegate_shm, output::{Mode, Output, Scale, Subpixel}, @@ -49,7 +48,6 @@ impl ClientData for ClientState { pub struct WaylandState { pub weak_ref: Weak>, - pub log: Logger, pub display: Arc>>, pub display_handle: DisplayHandle, @@ -66,24 +64,19 @@ pub struct WaylandState { impl WaylandState { pub fn new( - log: Logger, display: Arc>>, display_handle: DisplayHandle, - renderer: &Gles2Renderer, + renderer: &GlesRenderer, ) -> Arc> { - let compositor_state = CompositorState::new::(&display_handle, log.clone()); - // let xdg_activation_state = XdgActivationState::new::(&display_handle, log.clone()); - let kde_decoration_state = KdeDecorationState::new::( - &display_handle, - DecorationMode::Server, - log.clone(), - ); - let shm_state = ShmState::new::(&display_handle, vec![], log.clone()); + let compositor_state = CompositorState::new::(&display_handle); + // let xdg_activation_state = XdgActivationState::new::(&display_handle); + let kde_decoration_state = + KdeDecorationState::new::(&display_handle, DecorationMode::Server); + let shm_state = ShmState::new::(&display_handle, vec![]); let mut dmabuf_state = DmabufState::new(); - let dmabuf_global = dmabuf_state.create_global::( + let dmabuf_global = dmabuf_state.create_global::( &display_handle, - renderer.dmabuf_formats().cloned().collect::>(), - log.clone(), + renderer.dmabuf_formats().collect::>(), ); let output = Output::new( "1x".to_owned(), @@ -93,18 +86,19 @@ impl WaylandState { make: "Virtual XR Display".to_owned(), model: "Your Headset Name Here".to_owned(), }, - log.clone(), ); let _output_global = output.create_global::(&display_handle); + let mode = Mode { + size: (4096, 4096).into(), + refresh: 60000, + }; output.change_current_state( - Some(Mode { - size: (4096, 4096).into(), - refresh: 60000, - }), + Some(mode), Some(Transform::Normal), Some(Scale::Integer(2)), None, ); + output.set_preferred(mode); display_handle.create_global::(3, ()); display_handle.create_global::(5, ()); display_handle.create_global::(1, ()); @@ -114,7 +108,6 @@ impl WaylandState { Arc::new_cyclic(|weak| { Mutex::new(WaylandState { weak_ref: weak.clone(), - log, display, display_handle, diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index 6bc4891..2e07d88 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -7,10 +7,9 @@ use mint::Vector2; use once_cell::sync::OnceCell; use parking_lot::Mutex; use send_wrapper::SendWrapper; -use slog::Logger; use smithay::{ backend::renderer::{ - gles2::{Gles2Renderer, Gles2Texture}, + gles::{GlesRenderer, GlesTexture}, utils::{import_surface_tree, on_commit_buffer_handler, RendererSurfaceStateUserData}, Renderer, Texture, }, @@ -35,22 +34,8 @@ use stereokit::{ pub static CORE_SURFACES: Registry = Registry::new(); -#[derive(Debug, Clone, Copy)] -pub struct SurfaceGeometry { - pub origin: Vector2, - pub size: Vector2, -} -impl Default for SurfaceGeometry { - fn default() -> Self { - Self { - origin: [0; 2].into(), - size: [0; 2].into(), - } - } -} - pub struct CoreSurfaceData { - wl_tex: Option>, + wl_tex: Option>, pub size: Vector2, } impl Drop for CoreSurfaceData { @@ -67,7 +52,7 @@ pub struct CoreSurface { sk_tex: OnceCell>, sk_mat: OnceCell>>, material_offset: Mutex>, - // geometry: Mutex>>, + on_commit: Box, pub pending_material_applications: Mutex, u32)>>, } @@ -76,11 +61,9 @@ impl CoreSurface { display: &Arc>>, dh: DisplayHandle, surface: &WlSurface, + on_commit: impl Fn(u32) + Send + Sync + 'static, ) { compositor::with_states(surface, |data| { - // let mut geometry: Delta> = - // Delta::new(data.data_map.get::().cloned()); - // geometry.mark_changed(); data.data_map.insert_if_missing_threadsafe(|| { CORE_SURFACES.add(CoreSurface { display: Arc::downgrade(display), @@ -90,20 +73,24 @@ impl CoreSurface { sk_tex: OnceCell::new(), sk_mat: OnceCell::new(), material_offset: Mutex::new(Delta::new(0)), - // geometry: Mutex::new(geometry), + on_commit: Box::new(on_commit) as Box, pending_material_applications: Mutex::new(Vec::new()), }) }); }); } + pub fn commit(&self, count: u32) { + (self.on_commit)(count); + } + pub fn from_wl_surface(surf: &WlSurface) -> Option> { compositor::with_states(surf, |data| { data.data_map.get::>().cloned() }) } - pub fn process(&self, sk: &StereoKitDraw, renderer: &mut Gles2Renderer, log: &Logger) { + pub fn process(&self, sk: &StereoKitDraw, renderer: &mut GlesRenderer) { let Some(wl_surface) = self.wl_surface() else { return }; let sk_tex = self.sk_tex.get_or_init(|| { @@ -122,14 +109,14 @@ impl CoreSurface { // Let smithay handle buffer management (has to be done here as RendererSurfaceStates is not thread safe) on_commit_buffer_handler(&wl_surface); // Import all surface buffers into textures - if import_surface_tree(renderer, &wl_surface, log).is_err() { + if import_surface_tree(renderer, &wl_surface).is_err() { return; } let mapped = compositor::with_states(&wl_surface, |data| { data.data_map .get::() - .map(|surface_states| surface_states.borrow().wl_buffer().is_some()) + .map(|surface_states| surface_states.borrow().buffer().is_some()) .unwrap_or(false) }); @@ -147,7 +134,7 @@ impl CoreSurface { .unwrap() .borrow(); let smithay_tex = renderer_surface_state - .texture::(renderer.id()) + .texture::(renderer.id()) .unwrap() .clone(); @@ -156,7 +143,7 @@ impl CoreSurface { unsafe { sk_tex.set_native( smithay_tex.tex_id() as usize, - smithay::backend::renderer::gles2::ffi::RGBA8.into(), + smithay::backend::renderer::gles::ffi::RGBA8.into(), TextureType::ImageNoMips, smithay_tex.width(), smithay_tex.height(), @@ -195,10 +182,6 @@ impl CoreSurface { *self.material_offset.lock().value_mut() = material_offset; } - // pub fn set_geometry(&self, geometry: SurfaceGeometry) { - // *self.geometry.lock().value_mut() = Some(geometry); - // } - pub fn apply_material(&self, model: Arc, material_idx: u32) { self.pending_material_applications .lock() diff --git a/src/wayland/xdg_shell.rs b/src/wayland/xdg_shell.rs index a354acc..76731cd 100644 --- a/src/wayland/xdg_shell.rs +++ b/src/wayland/xdg_shell.rs @@ -1,29 +1,34 @@ +use crate::nodes::Node; + use super::{ - panel_item::{PanelItem, RecommendedState, ToplevelState}, + panel_item::{PanelItem, RecommendedState, SurfaceID}, state::WaylandState, - surface::SurfaceGeometry, + surface::CoreSurface, SERIAL_COUNTER, }; use mint::Vector2; +use nanoid::nanoid; use parking_lot::Mutex; -use serde::Serialize; -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_WM_CAPABILITIES_SINCE}, - xdg_wm_base::{self, XdgWmBase}, - }, - wayland_server::{ - protocol::wl_surface::WlSurface, Client, DataInit, Dispatch, DisplayHandle, - GlobalDispatch, New, Resource, WEnum, Weak, - }, +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_WM_CAPABILITIES_SINCE}, + xdg_wm_base::{self, XdgWmBase}, + }, + wayland_server::{ + backend::{ClientId, ObjectId}, + protocol::wl_surface::WlSurface, + Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, Resource, WEnum, + Weak as WlWeak, }, - wayland::compositor, }; -use std::sync::Arc; +use std::{ + fmt::Debug, + sync::{Arc, Weak}, +}; use tracing::{debug, warn}; impl GlobalDispatch for WaylandState { @@ -38,11 +43,6 @@ impl GlobalDispatch for WaylandState { data_init.init(resource, ()); } } -#[derive(Debug)] -pub struct WaylandSurface { - wl_surface: Weak, - geometry: Arc>>, -} impl Dispatch for WaylandState { fn request( @@ -56,18 +56,11 @@ impl Dispatch for WaylandState { ) { match request { xdg_wm_base::Request::CreatePositioner { id } => { - let positioner = - data_init.init(id, Arc::new(Mutex::new(PositionerData::default()))); + let positioner = data_init.init(id, Mutex::new(PositionerData::default())); debug!(?positioner, "Create XDG positioner"); } xdg_wm_base::Request::GetXdgSurface { id, surface } => { - let xdg_surface = data_init.init( - id, - WaylandSurface { - wl_surface: surface.downgrade(), - geometry: Arc::new(Mutex::new(None)), - }, - ); + let xdg_surface = data_init.init(id, Mutex::new(XdgSurfaceData::new(&surface))); debug!(?xdg_surface, "Create XDG surface"); } xdg_wm_base::Request::Pong { serial } => { @@ -81,7 +74,7 @@ impl Dispatch for WaylandState { } } -#[derive(Debug, Serialize)] +#[derive(Debug, Serialize, Clone, Copy)] pub struct PositionerData { size: Vector2, anchor_rect_pos: Vector2, @@ -107,13 +100,13 @@ impl Default for PositionerData { } } -impl Dispatch>, WaylandState> for WaylandState { +impl Dispatch, WaylandState> for WaylandState { fn request( _state: &mut WaylandState, _client: &Client, positioner: &XdgPositioner, request: xdg_positioner::Request, - data: &Arc>, + data: &Mutex, _dhandle: &DisplayHandle, _data_init: &mut DataInit<'_, WaylandState>, ) { @@ -195,39 +188,69 @@ impl Dispatch>, WaylandState> for Wayla } } -#[derive(Debug, Clone)] -pub struct XdgSurfaceData { - pub wl_surface: Weak, - pub xdg_surface: Weak, - pub geometry: Arc>>, +#[derive(Debug, Serialize, Clone, Copy)] +pub struct Geometry { + pub origin: Vector2, + pub size: Vector2, } -impl Dispatch for WaylandState { +impl Default for Geometry { + fn default() -> Self { + Self { + origin: Vector2::from([0; 2]), + size: Vector2::from([0; 2]), + } + } +} + +#[derive(Debug)] +pub struct XdgSurfaceData { + wl_surface: WlWeak, + surface_id: SurfaceID, + panel_item: Weak, + geometry: Option, +} +impl XdgSurfaceData { + pub fn new(wl_surface: &WlSurface) -> Self { + XdgSurfaceData { + wl_surface: wl_surface.downgrade(), + surface_id: SurfaceID::Toplevel, + panel_item: Weak::new(), + geometry: None, + } + } + pub fn get(xdg_surface: &XdgSurface) -> &Mutex { + xdg_surface.data::>().unwrap() + } + pub fn wl_surface(&self) -> WlSurface { + self.wl_surface.upgrade().unwrap() + } + pub fn panel_item(&self) -> Option> { + self.panel_item.upgrade() + } +} +// impl Clone for XdgSurfaceData { +// fn clone(&self) -> Self { +// Self { +// wl_surface: self.wl_surface.clone(), +// geometry: self.geometry.clone(), +// surface_type: Mutex::new(self.surface_type.lock().clone()), +// } +// } +// } +impl Dispatch, WaylandState> for WaylandState { fn request( state: &mut WaylandState, client: &Client, xdg_surface: &XdgSurface, request: xdg_surface::Request, - data: &WaylandSurface, + xdg_surface_data: &Mutex, _dhandle: &DisplayHandle, data_init: &mut DataInit<'_, WaylandState>, ) { match request { xdg_surface::Request::GetToplevel { id } => { - let toplevel_state = Arc::new(Mutex::new(ToplevelState { - queued_state: Some(Box::new(ToplevelState::default())), - ..Default::default() - })); - let toplevel = data_init.init( - id, - XdgToplevelData { - state: toplevel_state, - xdg_surface_data: XdgSurfaceData { - wl_surface: data.wl_surface.clone(), - xdg_surface: xdg_surface.downgrade(), - geometry: data.geometry.clone(), - }, - }, - ); + let toplevel_state = Mutex::new(ToplevelData::new(xdg_surface)); + let toplevel = data_init.init(id, toplevel_state); debug!(?toplevel, ?xdg_surface, "Create XDG toplevel"); if toplevel.version() >= EVT_WM_CAPABILITIES_SINCE { @@ -236,25 +259,99 @@ impl Dispatch for WaylandState { toplevel.configure(0, 0, vec![]); xdg_surface.configure(SERIAL_COUNTER.inc()); - let (node, item) = PanelItem::create( - toplevel, - data.wl_surface.upgrade().unwrap(), - client.get_credentials(&state.display_handle).ok(), - state.seats.get(&client.id()).unwrap().clone(), + let client_credentials = client.get_credentials(&state.display_handle).ok(); + let seat_data = state.seats.get(&client.id()).unwrap().clone(); + let toplevel_weak = toplevel.downgrade(); + CoreSurface::add_to( + &state.display, + state.display_handle.clone(), + &xdg_surface_data.lock().wl_surface(), + move |c| match c { + 0 => { + let toplevel = toplevel_weak.upgrade().unwrap(); + let toplevel_data = ToplevelData::get(&toplevel); + 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 (node, panel_item) = PanelItem::create( + 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); + } + _ => { + let toplevel = toplevel_weak.upgrade().unwrap(); + let toplevel_data = ToplevelData::get(&toplevel); + let panel_item = toplevel_data.lock().panel_item().unwrap(); + panel_item.commit_toplevel(); + } + }, ); - compositor::with_states(&data.wl_surface.upgrade().unwrap(), |surface_data| { - surface_data.data_map.insert_if_missing_threadsafe(|| node); - surface_data.data_map.insert_if_missing_threadsafe(|| item); - }); } xdg_surface::Request::GetPopup { id, - parent: _, - positioner: _, + parent, + positioner, } => { - let popup = data_init.init(id, ()); - debug!(?popup, ?xdg_surface, "Create XDG popup"); - popup.popup_done(); // temporary hack to avoid apps locking up before popups are implemented + let parent_clone = parent.clone().unwrap(); + let parent_data = parent_clone.data::>().unwrap().lock(); + // let positioner_data = positioner + // .data::>() + // .unwrap() + // .lock() + // .clone(); + // let parent = match &*parent_data { + // XdgSurfaceType::Toplevel(_) => SurfaceID::Toplevel, + // XdgSurfaceType::Popup(p) => { + // SurfaceID::Popup(p.upgrade().unwrap().uid.clone()) + // } + // XdgSurfaceType::Unknown => return, + // }; + let uid = nanoid!(); + let popup_data = Mutex::new(PopupData::new( + uid.clone(), + xdg_surface, + parent_data.surface_id.clone(), + positioner, + )); + let xdg_popup = data_init.init(id, popup_data); + 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 |commit_count| match commit_count { + 0 => xdg_surface + .upgrade() + .unwrap() + .configure(SERIAL_COUNTER.inc()), + c => { + let xdg_popup = xdg_popup.upgrade().unwrap(); + let popup_data = PopupData::get(&xdg_popup); + let popup_data = popup_data.lock(); + // panel_item.commit_popup(popup_data); + if c == 1 { + panel_item.new_popup(&xdg_popup, &*popup_data); + } + } + }, + ); } xdg_surface::Request::SetWindowGeometry { x, @@ -266,18 +363,11 @@ impl Dispatch for WaylandState { ?xdg_surface, x, y, width, height, "Set XDG surface geometry" ); - let geometry = SurfaceGeometry { - origin: [x as u32, y as u32].into(), + let geometry = Geometry { + origin: [x, y].into(), size: [width as u32, height as u32].into(), }; - *data.geometry.lock() = Some(geometry); - let Ok(wl_surface) = data.wl_surface.upgrade() else { return; }; - compositor::with_states(&wl_surface, |data| { - // if let Some(core_surface) = data.data_map.get::>() { - // core_surface.set_geometry(geometry); - // } - data.data_map.insert_if_missing_threadsafe(|| geometry); - }); + xdg_surface_data.lock().geometry.replace(geometry); } xdg_surface::Request::AckConfigure { serial } => { debug!(?xdg_surface, serial, "Acknowledge XDG surface configure"); @@ -290,47 +380,104 @@ impl Dispatch for WaylandState { } } -#[derive(Debug)] -pub struct XdgToplevelData { - pub state: Arc>, - pub xdg_surface_data: XdgSurfaceData, +fn serde_error(msg: &str) -> Result { + Err(serde::ser::Error::custom(msg)) } -impl XdgToplevelData { + +#[derive(Debug, Clone)] +pub struct ToplevelData { + panel_item_node: Option>, + xdg_surface: WlWeak, + parent: Option>, + title: Option, + app_id: Option, + max_size: Option>, + min_size: Option>, + states: Vec, +} +impl ToplevelData { + fn new(xdg_surface: &XdgSurface) -> Self { + ToplevelData { + panel_item_node: None, + xdg_surface: xdg_surface.downgrade(), + parent: None, + title: None, + app_id: None, + max_size: None, + min_size: None, + states: Vec::new(), + } + } + + pub fn get(toplevel: &XdgToplevel) -> &Mutex { + toplevel.data::>().unwrap() + } + + pub fn xdg_surface(&self) -> XdgSurface { + self.xdg_surface.upgrade().unwrap() + } fn panel_item(&self) -> Option> { - let wl_surface = self.xdg_surface_data.wl_surface.upgrade().ok()?; - compositor::with_states(&wl_surface, |data| { - data.data_map.get::>().cloned() - }) + let xdg_surface = self.xdg_surface(); + let xdg_surface_data = XdgSurfaceData::get(&xdg_surface).lock(); + xdg_surface_data.panel_item() } } -impl Dispatch for WaylandState { +impl Serialize for ToplevelData { + fn serialize(&self, serializer: S) -> Result { + let xdg_surface = self.xdg_surface(); + let xdg_surface_data = XdgSurfaceData::get(&xdg_surface).lock(); + let geometry = xdg_surface_data.geometry.clone(); + let wl_surface = xdg_surface_data.wl_surface(); + let Some(core_surface) = CoreSurface::from_wl_surface(&wl_surface) else {return serde_error::("Core surface not found")}; + let Some(size) = core_surface.size() else {return serializer.serialize_none()}; + let geometry = geometry.unwrap_or_else(|| Geometry { + origin: [0; 2].into(), + size, + }); + + let mut seq = serializer.serialize_seq(None)?; + // Parent UID + seq.serialize_element(&self.parent.as_ref().and_then(|p| { + Some( + ToplevelData::get(&p.upgrade().ok()?) + .lock() + .panel_item()? + .uid + .clone(), + ) + }))?; + seq.serialize_element(&self.title)?; + seq.serialize_element(&self.app_id)?; + seq.serialize_element(&size)?; + seq.serialize_element(&self.min_size)?; + seq.serialize_element(&self.max_size)?; + seq.serialize_element(&geometry)?; + seq.serialize_element(&self.states)?; + seq.end() + } +} +impl Dispatch, WaylandState> for WaylandState { fn request( _state: &mut WaylandState, _client: &Client, xdg_toplevel: &XdgToplevel, request: xdg_toplevel::Request, - data: &XdgToplevelData, + data: &Mutex, _dhandle: &DisplayHandle, _data_init: &mut DataInit<'_, WaylandState>, ) { match request { xdg_toplevel::Request::SetParent { parent } => { debug!(?xdg_toplevel, ?parent, "Set XDG Toplevel parent"); - let mut state = data.state.lock(); - let queued_state = state.queued_state.as_mut().unwrap(); - queued_state.parent = parent.map(|toplevel| toplevel.downgrade()); + data.lock().parent = parent.map(|toplevel| toplevel.downgrade()); } xdg_toplevel::Request::SetTitle { title } => { debug!(?xdg_toplevel, ?title, "Set XDG Toplevel title"); - let mut state = data.state.lock(); - let queued_state = state.queued_state.as_mut().unwrap(); - queued_state.title = (!title.is_empty()).then_some(title); + data.lock().title = (!title.is_empty()).then_some(title); } xdg_toplevel::Request::SetAppId { app_id } => { debug!(?xdg_toplevel, ?app_id, "Set XDG Toplevel app ID"); - let mut state = data.state.lock(); - let queued_state = state.queued_state.as_mut().unwrap(); - queued_state.app_id = (!app_id.is_empty()).then_some(app_id); + data.lock().app_id = (!app_id.is_empty()).then_some(app_id); } xdg_toplevel::Request::ShowWindowMenu { seat, serial, x, y } => { debug!( @@ -344,7 +491,7 @@ impl Dispatch for WaylandState { } xdg_toplevel::Request::Move { seat, serial } => { debug!(?xdg_toplevel, ?seat, serial, "XDG Toplevel move request"); - let Some(panel_item) = data.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 { @@ -360,46 +507,42 @@ impl Dispatch for WaylandState { ?edges, "XDG Toplevel resize request" ); - let Some(panel_item) = data.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 } => { debug!(?xdg_toplevel, width, height, "Set XDG Toplevel max size"); - let mut state = data.state.lock(); - let queued_state = state.queued_state.as_mut().unwrap(); - queued_state.max_size = (width > 1 || height > 1) + data.lock().max_size = (width > 1 || height > 1) .then_some(Vector2::from([width as u32, height as u32])); } xdg_toplevel::Request::SetMinSize { width, height } => { debug!(?xdg_toplevel, width, height, "Set XDG Toplevel min size"); - let mut state = data.state.lock(); - let queued_state = state.queued_state.as_mut().unwrap(); - queued_state.min_size = (width > 1 || height > 1) + data.lock().min_size = (width > 1 || height > 1) .then_some(Vector2::from([width as u32, height as u32])); } xdg_toplevel::Request::SetMaximized => { - let Some(panel_item) = data.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.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.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.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.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.panel_item() else { return }; + let Some(panel_item) = data.lock().panel_item() else { return }; panel_item.on_drop(); } _ => unreachable!(), @@ -407,29 +550,121 @@ impl Dispatch for WaylandState { } } -impl Dispatch for WaylandState { +#[derive(Clone)] +pub struct PopupData { + pub uid: String, + grabbed: bool, + parent_id: SurfaceID, + positioner: XdgPositioner, + xdg_surface: WlWeak, +} +impl PopupData { + fn new( + uid: impl ToString, + xdg_surface: &XdgSurface, + parent_id: SurfaceID, + positioner: XdgPositioner, + ) -> Self { + PopupData { + uid: uid.to_string(), + grabbed: false, + parent_id, + positioner, + xdg_surface: xdg_surface.downgrade(), + } + } + pub fn get(popup: &XdgPopup) -> &Mutex { + popup.data::>().unwrap() + } + pub fn xdg_surface(&self) -> XdgSurface { + self.xdg_surface.upgrade().unwrap() + } + + fn panel_item(&self) -> Option> { + XdgSurfaceData::get(&self.xdg_surface()).lock().panel_item() + } + // fn get_parent(&self) -> Option { + // self.parent.as_ref()?.upgrade().ok() + // } + pub fn wl_surface(&self) -> WlSurface { + XdgSurfaceData::get(&self.xdg_surface()).lock().wl_surface() + } + + pub fn positioner_data(&self) -> Option { + Some( + self.positioner + .data::>()? + .lock() + .clone(), + ) + } +} + +impl Serialize for PopupData { + fn serialize(&self, serializer: S) -> Result { + let Some(positioner_data) = self.positioner_data() else {return serde_error::("Positioner not found")}; + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&self.uid)?; + seq.serialize_element(&self.parent_id)?; + seq.serialize_element(&positioner_data)?; + seq.end() + } +} +impl Debug for PopupData { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("XdgPopupData") + .field("uid", &self.uid) + .field("positioner", &self.positioner) + .field("xdg_surface", &self.xdg_surface) + .finish() + } +} +impl Dispatch, WaylandState> for WaylandState { fn request( _state: &mut WaylandState, _client: &Client, xdg_popup: &XdgPopup, request: xdg_popup::Request, - _data: &(), + data: &Mutex, _dhandle: &DisplayHandle, _data_init: &mut DataInit<'_, WaylandState>, ) { match request { xdg_popup::Request::Grab { seat, serial } => { + let mut data = data.lock(); + data.grabbed = true; debug!(?xdg_popup, ?seat, serial, "XDG popup grab"); - xdg_popup.popup_done(); // temporary hack to avoid apps locking up before popups are implemented + let Some(panel_item) = data.panel_item() else {return}; + panel_item.grab_keyboard(Some(SurfaceID::Popup(data.uid.clone()))); } xdg_popup::Request::Reposition { positioner, token } => { + let mut data = data.lock(); debug!(?xdg_popup, ?positioner, token, "XDG popup reposition"); - xdg_popup.popup_done(); // temporary hack to avoid apps locking up before popups are implemented + data.positioner = positioner; + let Some(panel_item) = data.panel_item() else {return}; + 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(); debug!(?xdg_popup, "Destroy XDG popup"); + if data.grabbed { + let Some(panel_item) = data.panel_item() else {return}; + panel_item.grab_keyboard(None); + } } _ => unreachable!(), } } + + fn destroyed( + _state: &mut WaylandState, + _client: ClientId, + _resource: ObjectId, + data: &Mutex, + ) { + let data = data.lock(); + let Some(panel_item) = data.panel_item() else {return}; + panel_item.drop_popup(&data.uid); + } }