diff --git a/Cargo.lock b/Cargo.lock index 98a7c904..82210add 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -308,7 +308,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 1.0.8", + "rustix", "slab", "windows-sys 0.60.2", ] @@ -350,7 +350,7 @@ dependencies = [ "cfg-if", "event-listener", "futures-lite", - "rustix 1.0.8", + "rustix", ] [[package]] @@ -376,7 +376,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 1.0.8", + "rustix", "signal-hook-registry", "slab", "windows-sys 0.60.2", @@ -521,22 +521,13 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" -dependencies = [ - "objc2 0.5.2", -] - [[package]] name = "block2" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2" dependencies = [ - "objc2 0.6.2", + "objc2", ] [[package]] @@ -552,6 +543,15 @@ dependencies = [ "piper", ] +[[package]] +name = "borsh" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" +dependencies = [ + "cfg_aliases", +] + [[package]] name = "built" version = "0.7.7" @@ -613,26 +613,25 @@ dependencies = [ [[package]] name = "calloop" -version = "0.13.0" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e" dependencies = [ "bitflags 2.9.3", - "log", "polling", - "rustix 0.38.44", + "rustix", "slab", - "thiserror 1.0.69", + "tracing", ] [[package]] name = "calloop-wayland-source" -version = "0.3.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +checksum = "138efcf0940a02ebf0cc8d1eff41a1682a46b431630f4c52450d6265876021fa" dependencies = [ "calloop", - "rustix 0.38.44", + "rustix", "wayland-backend", "wayland-client", ] @@ -998,19 +997,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "core-graphics" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types 0.5.0", - "libc", -] - [[package]] name = "core-graphics-types" version = "0.1.3" @@ -1119,7 +1105,7 @@ dependencies = [ "document-features", "mio", "parking_lot", - "rustix 1.0.8", + "rustix", "signal-hook", "signal-hook-mio", "winapi", @@ -1262,12 +1248,6 @@ dependencies = [ "windows-sys 0.60.2", ] -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - [[package]] name = "dispatch2" version = "0.3.0" @@ -1275,9 +1255,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" dependencies = [ "bitflags 2.9.3", - "block2 0.6.1", + "block2", "libc", - "objc2 0.6.2", + "objc2", ] [[package]] @@ -1337,8 +1317,7 @@ dependencies = [ [[package]] name = "dpi" version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +source = "git+https://github.com/rust-windowing/winit.git?rev=66283a79bddd034c45fb0e72c84fa5cd4e5f82fb#66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" dependencies = [ "serde", ] @@ -1671,10 +1650,10 @@ dependencies = [ "hashbrown", "icu_locid", "memmap2", - "objc2 0.6.2", + "objc2", "objc2-core-foundation", "objc2-core-text", - "objc2-foundation 0.3.1", + "objc2-foundation", "peniko", "read-fonts 0.29.3", "roxmltree", @@ -1872,7 +1851,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55" dependencies = [ - "rustix 1.0.8", + "rustix", "windows-targets 0.52.6", ] @@ -2275,7 +2254,7 @@ dependencies = [ "graphite-desktop-wrapper", "libc", "objc2-io-surface", - "objc2-metal 0.3.1", + "objc2-metal", "open", "rand 0.9.2", "rfd", @@ -3059,6 +3038,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "keyboard-types" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53cea01d04c8251f945a9f16c5364da6cdb8bce69a61382663302c62f4186d13" +dependencies = [ + "bitflags 2.9.3", + "serde", +] + [[package]] name = "khronos-egl" version = "6.0.0" @@ -3166,15 +3155,9 @@ checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" dependencies = [ "bitflags 2.9.3", "libc", - "redox_syscall 0.5.17", + "redox_syscall", ] -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - [[package]] name = "linux-raw-sys" version = "0.9.4" @@ -3642,22 +3625,6 @@ dependencies = [ "malloc_buf", ] -[[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" - -[[package]] -name = "objc2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" -dependencies = [ - "objc-sys", - "objc2-encode", -] - [[package]] name = "objc2" version = "0.6.2" @@ -3667,22 +3634,6 @@ dependencies = [ "objc2-encode", ] -[[package]] -name = "objc2-app-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" -dependencies = [ - "bitflags 2.9.3", - "block2 0.5.1", - "libc", - "objc2 0.5.2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation 0.2.2", - "objc2-quartz-core", -] - [[package]] name = "objc2-app-kit" version = "0.3.1" @@ -3690,45 +3641,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" dependencies = [ "bitflags 2.9.3", - "block2 0.6.1", - "objc2 0.6.2", - "objc2-foundation 0.3.1", -] - -[[package]] -name = "objc2-cloud-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" -dependencies = [ - "bitflags 2.9.3", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-core-location", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-contacts" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-core-data" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" -dependencies = [ - "bitflags 2.9.3", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", + "block2", + "objc2", + "objc2-core-foundation", + "objc2-foundation", ] [[package]] @@ -3738,32 +3654,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" dependencies = [ "bitflags 2.9.3", + "block2", "dispatch2", - "objc2 0.6.2", + "objc2", ] [[package]] -name = "objc2-core-image" -version = "0.2.2" +name = "objc2-core-graphics" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal 0.2.2", -] - -[[package]] -name = "objc2-core-location" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-contacts", - "objc2-foundation 0.2.2", + "bitflags 2.9.3", + "libc", + "objc2-core-foundation", ] [[package]] @@ -3776,25 +3680,23 @@ dependencies = [ "objc2-core-foundation", ] +[[package]] +name = "objc2-core-video" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1989c3e76c7e978cab0ba9e6f4961cd00ed14ca21121444cc26877403bfb6303" +dependencies = [ + "bitflags 2.9.3", + "objc2-core-foundation", + "objc2-core-graphics", +] + [[package]] name = "objc2-encode" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" -[[package]] -name = "objc2-foundation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" -dependencies = [ - "bitflags 2.9.3", - "block2 0.5.1", - "dispatch", - "libc", - "objc2 0.5.2", -] - [[package]] name = "objc2-foundation" version = "0.3.1" @@ -3802,7 +3704,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ "bitflags 2.9.3", - "objc2 0.6.2", + "block2", + "objc2", "objc2-core-foundation", ] @@ -3814,33 +3717,9 @@ checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" dependencies = [ "bitflags 2.9.3", "libc", - "objc2 0.6.2", + "objc2", "objc2-core-foundation", - "objc2-foundation 0.3.1", -] - -[[package]] -name = "objc2-link-presentation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-metal" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" -dependencies = [ - "bitflags 2.9.3", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", + "objc2-foundation", ] [[package]] @@ -3850,79 +3729,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f246c183239540aab1782457b35ab2040d4259175bd1d0c58e46ada7b47a874" dependencies = [ "bitflags 2.9.3", - "block2 0.6.1", + "block2", "dispatch2", - "objc2 0.6.2", + "objc2", "objc2-core-foundation", - "objc2-foundation 0.3.1", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" -dependencies = [ - "bitflags 2.9.3", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal 0.2.2", -] - -[[package]] -name = "objc2-symbols" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" -dependencies = [ - "objc2 0.5.2", - "objc2-foundation 0.2.2", + "objc2-foundation", ] [[package]] name = "objc2-ui-kit" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +checksum = "25b1312ad7bc8a0e92adae17aa10f90aae1fb618832f9b993b022b591027daed" dependencies = [ "bitflags 2.9.3", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-cloud-kit", - "objc2-core-data", - "objc2-core-image", - "objc2-core-location", - "objc2-foundation 0.2.2", - "objc2-link-presentation", - "objc2-quartz-core", - "objc2-symbols", - "objc2-uniform-type-identifiers", - "objc2-user-notifications", -] - -[[package]] -name = "objc2-uniform-type-identifiers" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-user-notifications" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" -dependencies = [ - "bitflags 2.9.3", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-core-location", - "objc2-foundation 0.2.2", + "objc2", + "objc2-core-foundation", + "objc2-foundation", ] [[package]] @@ -4083,7 +3906,7 @@ checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.17", + "redox_syscall", "smallvec", "windows-targets 0.52.6", ] @@ -4320,7 +4143,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.0.8", + "rustix", "windows-sys 0.60.2", ] @@ -4730,15 +4553,6 @@ dependencies = [ "font-types", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.5.17" @@ -4873,14 +4687,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef2bee61e6cffa4635c72d7d81a84294e28f0930db0ddcb0f66d10244674ebed" dependencies = [ "ashpd", - "block2 0.6.1", + "block2", "dispatch2", "js-sys", "log", - "objc2 0.6.2", - "objc2-app-kit 0.3.1", + "objc2", + "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.1", + "objc2-foundation", "pollster", "raw-window-handle", "urlencoding", @@ -4993,19 +4807,6 @@ dependencies = [ "spirv", ] -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.9.3", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - [[package]] name = "rustix" version = "1.0.8" @@ -5015,7 +4816,7 @@ dependencies = [ "bitflags 2.9.3", "errno", "libc", - "linux-raw-sys 0.9.4", + "linux-raw-sys", "windows-sys 0.60.2", ] @@ -5144,9 +4945,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +checksum = "1dd3accc0f3f4bbaf2c9e1957a030dc582028130c67660d44c0a0345a22ca69b" dependencies = [ "ab_glyph", "log", @@ -5421,9 +5222,9 @@ dependencies = [ [[package]] name = "smithay-client-toolkit" -version = "0.19.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" dependencies = [ "bitflags 2.9.3", "calloop", @@ -5432,13 +5233,15 @@ dependencies = [ "libc", "log", "memmap2", - "rustix 0.38.44", - "thiserror 1.0.69", + "rustix", + "thiserror 2.0.16", "wayland-backend", "wayland-client", "wayland-csd-frame", "wayland-cursor", "wayland-protocols", + "wayland-protocols-experimental", + "wayland-protocols-misc", "wayland-protocols-wlr", "wayland-scanner", "xkeysym", @@ -5446,10 +5249,11 @@ dependencies = [ [[package]] name = "smol_str" -version = "0.2.2" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +checksum = "9676b89cd56310a87b93dec47b11af744f34d5fc9f367b829474eec0a891350d" dependencies = [ + "borsh", "serde", ] @@ -5776,7 +5580,7 @@ dependencies = [ "fastrand", "getrandom 0.3.3", "once_cell", - "rustix 1.0.8", + "rustix", "windows-sys 0.60.2", ] @@ -6104,6 +5908,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -6610,7 +6415,7 @@ checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35" dependencies = [ "cc", "downcast-rs", - "rustix 1.0.8", + "rustix", "scoped-tls", "smallvec", "wayland-sys", @@ -6623,7 +6428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d" dependencies = [ "bitflags 2.9.3", - "rustix 1.0.8", + "rustix", "wayland-backend", "wayland-scanner", ] @@ -6645,7 +6450,7 @@ version = "0.31.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29" dependencies = [ - "rustix 1.0.8", + "rustix", "wayland-client", "xcursor", ] @@ -6662,6 +6467,32 @@ dependencies = [ "wayland-scanner", ] +[[package]] +name = "wayland-protocols-experimental" +version = "20250721.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" +dependencies = [ + "bitflags 2.9.3", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfe33d551eb8bffd03ff067a8b44bb963919157841a99957151299a6307d19c" +dependencies = [ + "bitflags 2.9.3", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + [[package]] name = "wayland-protocols-plasma" version = "0.3.9" @@ -7303,51 +7134,215 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winit" version = "0.30.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732" +source = "git+https://github.com/rust-windowing/winit.git?rev=66283a79bddd034c45fb0e72c84fa5cd4e5f82fb#66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" dependencies = [ - "ahash", - "android-activity", - "atomic-waker", "bitflags 2.9.3", - "block2 0.5.1", - "bytemuck", - "calloop", "cfg_aliases", - "concurrent-queue", - "core-foundation", - "core-graphics", "cursor-icon", "dpi", - "js-sys", + "libc", + "raw-window-handle", + "rustix", + "serde", + "smol_str", + "tracing", + "winit-android", + "winit-appkit", + "winit-common", + "winit-core", + "winit-orbital", + "winit-uikit", + "winit-wayland", + "winit-web", + "winit-win32", + "winit-x11", +] + +[[package]] +name = "winit-android" +version = "0.30.12" +source = "git+https://github.com/rust-windowing/winit.git?rev=66283a79bddd034c45fb0e72c84fa5cd4e5f82fb#66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" +dependencies = [ + "android-activity", + "bitflags 2.9.3", + "dpi", + "ndk", + "raw-window-handle", + "smol_str", + "tracing", + "winit-core", +] + +[[package]] +name = "winit-appkit" +version = "0.30.12" +source = "git+https://github.com/rust-windowing/winit.git?rev=66283a79bddd034c45fb0e72c84fa5cd4e5f82fb#66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" +dependencies = [ + "bitflags 2.9.3", + "block2", + "dispatch2", + "dpi", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-video", + "objc2-foundation", + "raw-window-handle", + "smol_str", + "tracing", + "winit-common", + "winit-core", +] + +[[package]] +name = "winit-common" +version = "0.30.12" +source = "git+https://github.com/rust-windowing/winit.git?rev=66283a79bddd034c45fb0e72c84fa5cd4e5f82fb#66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" +dependencies = [ + "memmap2", + "objc2", + "objc2-core-foundation", + "smol_str", + "tracing", + "winit-core", + "x11-dl", + "xkbcommon-dl", +] + +[[package]] +name = "winit-core" +version = "0.30.12" +source = "git+https://github.com/rust-windowing/winit.git?rev=66283a79bddd034c45fb0e72c84fa5cd4e5f82fb#66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" +dependencies = [ + "bitflags 2.9.3", + "cursor-icon", + "dpi", + "keyboard-types", + "raw-window-handle", + "serde", + "smol_str", + "web-time", +] + +[[package]] +name = "winit-orbital" +version = "0.30.12" +source = "git+https://github.com/rust-windowing/winit.git?rev=66283a79bddd034c45fb0e72c84fa5cd4e5f82fb#66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" +dependencies = [ + "bitflags 2.9.3", + "dpi", + "orbclient", + "raw-window-handle", + "redox_syscall", + "smol_str", + "tracing", + "winit-core", +] + +[[package]] +name = "winit-uikit" +version = "0.30.12" +source = "git+https://github.com/rust-windowing/winit.git?rev=66283a79bddd034c45fb0e72c84fa5cd4e5f82fb#66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" +dependencies = [ + "bitflags 2.9.3", + "block2", + "dispatch2", + "dpi", + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-ui-kit", + "raw-window-handle", + "serde", + "smol_str", + "tracing", + "winit-common", + "winit-core", +] + +[[package]] +name = "winit-wayland" +version = "0.30.12" +source = "git+https://github.com/rust-windowing/winit.git?rev=66283a79bddd034c45fb0e72c84fa5cd4e5f82fb#66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" +dependencies = [ + "ahash", + "bitflags 2.9.3", + "calloop", + "cursor-icon", + "dpi", "libc", "memmap2", - "ndk", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", - "objc2-ui-kit", - "orbclient", - "percent-encoding", - "pin-project", "raw-window-handle", - "redox_syscall 0.4.1", - "rustix 0.38.44", + "rustix", "sctk-adwaita", - "serde", "smithay-client-toolkit", "smol_str", "tracing", - "unicode-segmentation", - "wasm-bindgen", - "wasm-bindgen-futures", "wayland-backend", "wayland-client", "wayland-protocols", "wayland-protocols-plasma", + "winit-common", + "winit-core", +] + +[[package]] +name = "winit-web" +version = "0.30.12" +source = "git+https://github.com/rust-windowing/winit.git?rev=66283a79bddd034c45fb0e72c84fa5cd4e5f82fb#66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" +dependencies = [ + "atomic-waker", + "bitflags 2.9.3", + "concurrent-queue", + "cursor-icon", + "dpi", + "js-sys", + "pin-project", + "raw-window-handle", + "smol_str", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", "web-time", - "windows-sys 0.52.0", + "winit-core", +] + +[[package]] +name = "winit-win32" +version = "0.30.12" +source = "git+https://github.com/rust-windowing/winit.git?rev=66283a79bddd034c45fb0e72c84fa5cd4e5f82fb#66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" +dependencies = [ + "bitflags 2.9.3", + "cursor-icon", + "dpi", + "raw-window-handle", + "smol_str", + "tracing", + "unicode-segmentation", + "windows-sys 0.59.0", + "winit-core", +] + +[[package]] +name = "winit-x11" +version = "0.30.12" +source = "git+https://github.com/rust-windowing/winit.git?rev=66283a79bddd034c45fb0e72c84fa5cd4e5f82fb#66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" +dependencies = [ + "bitflags 2.9.3", + "bytemuck", + "calloop", + "cursor-icon", + "dpi", + "libc", + "percent-encoding", + "raw-window-handle", + "rustix", + "smol_str", + "tracing", + "winit-common", + "winit-core", "x11-dl", "x11rb", "xkbcommon-dl", @@ -7402,8 +7397,9 @@ dependencies = [ "libc", "libloading", "once_cell", - "rustix 1.0.8", + "rustix", "x11rb-protocol", + "xcursor", ] [[package]] @@ -7419,7 +7415,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af3a19837351dc82ba89f8a125e22a3c475f05aba604acc023d62b2739ae2909" dependencies = [ "libc", - "rustix 1.0.8", + "rustix", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 5ea89efb..f48ba53b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -132,7 +132,7 @@ web-sys = { version = "=0.3.77", features = [ "HtmlImageElement", "ImageBitmapRenderingContext", ] } -winit = { version = "0.30", features = ["wayland", "rwh_06"] } +winit = { git = "https://github.com/rust-windowing/winit.git", rev = "66283a79bddd034c45fb0e72c84fa5cd4e5f82fb" } url = "2.5" tokio = { version = "1.29", features = ["fs", "macros", "io-std", "rt"] } vello = { git = "https://github.com/linebender/vello.git", rev = "87cc5bee6d3a34d15017dbbb58634ddc7f33ff9b" } # TODO switch back to stable when a release is made diff --git a/desktop/Cargo.toml b/desktop/Cargo.toml index 43fb5fc9..8f64bb69 100644 --- a/desktop/Cargo.toml +++ b/desktop/Cargo.toml @@ -26,7 +26,7 @@ graphite-desktop-wrapper = { path = "wrapper" } graphite-desktop-embedded-resources = { path = "embedded-resources", optional = true } wgpu = { workspace = true } -winit = { workspace = true, features = ["serde"] } +winit = { workspace = true, features = [ "serde" ] } thiserror = { workspace = true } futures = { workspace = true } cef = { workspace = true } @@ -34,7 +34,7 @@ cef-dll-sys = { workspace = true } tracing-subscriber = { workspace = true } tracing = { workspace = true } dirs = { workspace = true } -ron = { workspace = true} +ron = { workspace = true } bytemuck = { workspace = true } glam = { workspace = true } vello = { workspace = true } diff --git a/desktop/src/app.rs b/desktop/src/app.rs index c8e16ae1..10b52d48 100644 --- a/desktop/src/app.rs +++ b/desktop/src/app.rs @@ -1,39 +1,37 @@ -use crate::CustomEvent; -use crate::cef::WindowSize; -use crate::consts::{APP_NAME, CEF_MESSAGE_LOOP_MAX_ITERATIONS}; -use crate::persist::PersistentData; -use crate::render::GraphicsState; -use graphite_desktop_wrapper::messages::{DesktopFrontendMessage, DesktopWrapperMessage, Platform}; -use graphite_desktop_wrapper::{DesktopWrapper, NodeGraphExecutionResult, WgpuContext, serialize_frontend_messages}; - use rfd::AsyncFileDialog; use std::sync::Arc; +use std::sync::mpsc::Receiver; use std::sync::mpsc::Sender; use std::sync::mpsc::SyncSender; use std::thread; use std::time::Duration; use std::time::Instant; use winit::application::ApplicationHandler; -use winit::dpi::PhysicalSize; use winit::event::WindowEvent; use winit::event_loop::ActiveEventLoop; use winit::event_loop::ControlFlow; -use winit::event_loop::EventLoopProxy; use winit::window::Window; use winit::window::WindowId; use crate::cef; +use crate::consts::CEF_MESSAGE_LOOP_MAX_ITERATIONS; +use crate::event::{AppEvent, AppEventScheduler}; use crate::native_window; +use crate::persist::PersistentData; +use crate::render::GraphicsState; +use graphite_desktop_wrapper::messages::{DesktopFrontendMessage, DesktopWrapperMessage, Platform}; +use graphite_desktop_wrapper::{DesktopWrapper, NodeGraphExecutionResult, WgpuContext, serialize_frontend_messages}; -pub(crate) struct WinitApp { +pub(crate) struct App { cef_context: Box, - window: Option>, + window: Option>, native_window: native_window::NativeWindowHandle, cef_schedule: Option, - window_size_sender: Sender, + cef_window_size_sender: Sender, graphics_state: Option, wgpu_context: WgpuContext, - event_loop_proxy: EventLoopProxy, + app_event_receiver: Receiver, + app_event_scheduler: AppEventScheduler, desktop_wrapper: DesktopWrapper, last_ui_update: Instant, avg_frame_time: f32, @@ -43,14 +41,20 @@ pub(crate) struct WinitApp { persistent_data: PersistentData, } -impl WinitApp { - pub(crate) fn new(cef_context: Box, window_size_sender: Sender, wgpu_context: WgpuContext, event_loop_proxy: EventLoopProxy) -> Self { - let rendering_loop_proxy = event_loop_proxy.clone(); +impl App { + pub(crate) fn new( + cef_context: Box, + window_size_sender: Sender, + wgpu_context: WgpuContext, + app_event_receiver: Receiver, + app_event_scheduler: AppEventScheduler, + ) -> Self { + let rendering_app_event_scheduler = app_event_scheduler.clone(); let (start_render_sender, start_render_receiver) = std::sync::mpsc::sync_channel(1); std::thread::spawn(move || { loop { let result = futures::executor::block_on(DesktopWrapper::execute_node_graph()); - let _ = rendering_loop_proxy.send_event(CustomEvent::NodeGraphExecutionResult(result)); + rendering_app_event_scheduler.schedule(AppEvent::NodeGraphExecutionResult(result)); let _ = start_render_receiver.recv(); } }); @@ -63,9 +67,10 @@ impl WinitApp { window: None, cef_schedule: Some(Instant::now()), graphics_state: None, - window_size_sender, + cef_window_size_sender: window_size_sender, wgpu_context, - event_loop_proxy, + app_event_receiver, + app_event_scheduler, desktop_wrapper: DesktopWrapper::new(), last_ui_update: Instant::now(), avg_frame_time: 0., @@ -87,7 +92,7 @@ impl WinitApp { self.send_or_queue_web_message(bytes); } DesktopFrontendMessage::OpenFileDialog { title, filters, context } => { - let event_loop_proxy = self.event_loop_proxy.clone(); + let app_event_scheduler = self.app_event_scheduler.clone(); let _ = thread::spawn(move || { let mut dialog = AsyncFileDialog::new().set_title(title); for filter in filters { @@ -100,7 +105,7 @@ impl WinitApp { && let Ok(content) = std::fs::read(&path) { let message = DesktopWrapperMessage::OpenFileDialogResult { path, content, context }; - let _ = event_loop_proxy.send_event(CustomEvent::DesktopWrapperMessage(message)); + app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(message)); } }); } @@ -111,7 +116,7 @@ impl WinitApp { filters, context, } => { - let event_loop_proxy = self.event_loop_proxy.clone(); + let app_event_scheduler = self.app_event_scheduler.clone(); let _ = thread::spawn(move || { let mut dialog = AsyncFileDialog::new().set_title(title).set_file_name(default_filename); if let Some(folder) = default_folder { @@ -125,7 +130,7 @@ impl WinitApp { if let Some(path) = futures::executor::block_on(show_dialog) { let message = DesktopWrapperMessage::SaveFileDialogResult { path, context }; - let _ = event_loop_proxy.send_event(CustomEvent::DesktopWrapperMessage(message)); + app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(message)); } }); } @@ -145,7 +150,7 @@ impl WinitApp { if let Some(graphics_state) = &mut self.graphics_state && let Some(window) = &self.window { - let window_size = window.inner_size(); + let window_size = window.surface_size(); let viewport_offset_x = x / window_size.width as f32; let viewport_offset_y = y / window_size.height as f32; @@ -173,7 +178,7 @@ impl WinitApp { } } DesktopFrontendMessage::CloseWindow => { - let _ = self.event_loop_proxy.send_event(CustomEvent::CloseWindow); + self.app_event_scheduler.schedule(AppEvent::CloseWindow); } DesktopFrontendMessage::PersistenceWriteDocument { id, document } => { self.persistent_data.write_document(id, document); @@ -252,43 +257,67 @@ impl WinitApp { self.web_communication_startup_buffer.push(message); } } -} -impl ApplicationHandler for WinitApp { - fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { - // Set a timeout in case we miss any cef schedule requests - let timeout = Instant::now() + Duration::from_millis(10); - let wait_until = timeout.min(self.cef_schedule.unwrap_or(timeout)); - if let Some(schedule) = self.cef_schedule - && schedule < Instant::now() - { - self.cef_schedule = None; - // Poll cef message loop multiple times to avoid message loop starvation - for _ in 0..CEF_MESSAGE_LOOP_MAX_ITERATIONS { - self.cef_context.work(); + fn user_event(&mut self, event_loop: &dyn ActiveEventLoop, event: AppEvent) { + match event { + AppEvent::WebCommunicationInitialized => { + self.web_communication_initialized = true; + for message in self.web_communication_startup_buffer.drain(..) { + self.cef_context.send_web_message(message); + } + } + AppEvent::DesktopWrapperMessage(message) => self.dispatch_desktop_wrapper_message(message), + AppEvent::NodeGraphExecutionResult(result) => match result { + NodeGraphExecutionResult::HasRun(texture) => { + self.dispatch_desktop_wrapper_message(DesktopWrapperMessage::PollNodeGraphEvaluation); + if let Some(texture) = texture + && let Some(graphics_state) = self.graphics_state.as_mut() + && let Some(window) = self.window.as_ref() + { + graphics_state.bind_viewport_texture(texture); + window.request_redraw(); + } + } + NodeGraphExecutionResult::NotRun => {} + }, + AppEvent::UiUpdate(texture) => { + if let Some(graphics_state) = self.graphics_state.as_mut() { + graphics_state.resize(texture.width(), texture.height()); + graphics_state.bind_ui_texture(texture); + let elapsed = self.last_ui_update.elapsed().as_secs_f32(); + self.last_ui_update = Instant::now(); + if elapsed < 0.5 { + self.avg_frame_time = (self.avg_frame_time * 3. + elapsed) / 4.; + } + } + if let Some(window) = &self.window { + window.request_redraw(); + } + } + AppEvent::ScheduleBrowserWork(instant) => { + if instant <= Instant::now() { + self.cef_context.work(); + } else { + self.cef_schedule = Some(instant); + } + } + AppEvent::CloseWindow => { + // TODO: Implement graceful shutdown + + tracing::info!("Exiting main event loop"); + event_loop.exit(); } } - if let Some(window) = &self.window.as_ref() { - window.request_redraw(); - } - - event_loop.set_control_flow(ControlFlow::WaitUntil(wait_until)); } +} +impl ApplicationHandler for App { + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { + let window_attributes = self.native_window.build(event_loop); - fn resumed(&mut self, event_loop: &ActiveEventLoop) { - let mut window = Window::default_attributes() - .with_title(APP_NAME) - .with_min_inner_size(winit::dpi::LogicalSize::new(400, 300)) - .with_inner_size(winit::dpi::LogicalSize::new(1200, 800)) - .with_resizable(true); + let window: Arc = Arc::from(event_loop.create_window(window_attributes).unwrap()); - window = self.native_window.build(window, event_loop); + self.native_window.setup(window.as_ref()); - let window = event_loop.create_window(window).unwrap(); - - self.native_window.setup(&window); - - let window = Arc::new(window); let graphics_state = GraphicsState::new(window.clone(), self.wgpu_context.clone()); self.window = Some(window); @@ -307,67 +336,21 @@ impl ApplicationHandler for WinitApp { self.dispatch_desktop_wrapper_message(DesktopWrapperMessage::UpdatePlatform(platform)); } - fn user_event(&mut self, event_loop: &ActiveEventLoop, event: CustomEvent) { - match event { - CustomEvent::WebCommunicationInitialized => { - self.web_communication_initialized = true; - for message in self.web_communication_startup_buffer.drain(..) { - self.cef_context.send_web_message(message); - } - } - CustomEvent::DesktopWrapperMessage(message) => self.dispatch_desktop_wrapper_message(message), - CustomEvent::NodeGraphExecutionResult(result) => match result { - NodeGraphExecutionResult::HasRun(texture) => { - self.dispatch_desktop_wrapper_message(DesktopWrapperMessage::PollNodeGraphEvaluation); - if let Some(texture) = texture - && let Some(graphics_state) = self.graphics_state.as_mut() - && let Some(window) = self.window.as_ref() - { - graphics_state.bind_viewport_texture(texture); - window.request_redraw(); - } - } - NodeGraphExecutionResult::NotRun => {} - }, - CustomEvent::UiUpdate(texture) => { - if let Some(graphics_state) = self.graphics_state.as_mut() { - graphics_state.resize(texture.width(), texture.height()); - graphics_state.bind_ui_texture(texture); - let elapsed = self.last_ui_update.elapsed().as_secs_f32(); - self.last_ui_update = Instant::now(); - if elapsed < 0.5 { - self.avg_frame_time = (self.avg_frame_time * 3. + elapsed) / 4.; - } - } - if let Some(window) = &self.window { - window.request_redraw(); - } - } - CustomEvent::ScheduleBrowserWork(instant) => { - if instant <= Instant::now() { - self.cef_context.work(); - } else { - self.cef_schedule = Some(instant); - } - } - CustomEvent::CloseWindow => { - // TODO: Implement graceful shutdown - - tracing::info!("Exiting main event loop"); - event_loop.exit(); - } + fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) { + while let Ok(event) = self.app_event_receiver.try_recv() { + self.user_event(event_loop, event); } } - fn window_event(&mut self, event_loop: &ActiveEventLoop, _window_id: WindowId, event: WindowEvent) { + fn window_event(&mut self, event_loop: &dyn ActiveEventLoop, _window_id: WindowId, event: WindowEvent) { self.cef_context.handle_window_event(&event); match event { WindowEvent::CloseRequested => { - let _ = self.event_loop_proxy.send_event(CustomEvent::CloseWindow); + self.app_event_scheduler.schedule(AppEvent::CloseWindow); } - WindowEvent::Resized(PhysicalSize { width, height }) => { - let _ = self.window_size_sender.send(WindowSize::new(width as usize, height as usize)); + WindowEvent::SurfaceResized(size) => { + let _ = self.cef_window_size_sender.send(size.into()); self.cef_context.notify_of_resize(); } WindowEvent::RedrawRequested => { @@ -387,18 +370,19 @@ impl ApplicationHandler for WinitApp { let _ = self.start_render_sender.try_send(()); } } - // Currently not supported on wayland see https://github.com/rust-windowing/winit/issues/1881 - WindowEvent::DroppedFile(path) => { - match std::fs::read(&path) { - Ok(content) => { - let message = DesktopWrapperMessage::OpenFile { path, content }; - let _ = self.event_loop_proxy.send_event(CustomEvent::DesktopWrapperMessage(message)); - } - Err(e) => { - tracing::error!("Failed to read dropped file {}: {}", path.display(), e); - return; - } - }; + WindowEvent::DragDropped { paths, .. } => { + for path in paths { + match std::fs::read(&path) { + Ok(content) => { + let message = DesktopWrapperMessage::OpenFile { path, content }; + self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(message)); + } + Err(e) => { + tracing::error!("Failed to read dropped file {}: {}", path.display(), e); + return; + } + }; + } } _ => {} } @@ -406,4 +390,24 @@ impl ApplicationHandler for WinitApp { // Notify cef of possible input events self.cef_context.work(); } + + fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) { + // Set a timeout in case we miss any cef schedule requests + let timeout = Instant::now() + Duration::from_millis(10); + let wait_until = timeout.min(self.cef_schedule.unwrap_or(timeout)); + if let Some(schedule) = self.cef_schedule + && schedule < Instant::now() + { + self.cef_schedule = None; + // Poll cef message loop multiple times to avoid message loop starvation + for _ in 0..CEF_MESSAGE_LOOP_MAX_ITERATIONS { + self.cef_context.work(); + } + } + if let Some(window) = &self.window.as_ref() { + window.request_redraw(); + } + + event_loop.set_control_flow(ControlFlow::WaitUntil(wait_until)); + } } diff --git a/desktop/src/cef.rs b/desktop/src/cef.rs index 06e03169..8839c00f 100644 --- a/desktop/src/cef.rs +++ b/desktop/src/cef.rs @@ -10,10 +10,9 @@ //! - **Windows**: D3D11 shared textures via either Vulkan or D3D12 interop (`accelerated_paint_d3d11` feature) //! - **macOS**: IOSurface via Metal/Vulkan interop (`accelerated_paint_iosurface` feature) //! -//! //! The system gracefully falls back to CPU textures when hardware acceleration is unavailable. -use crate::CustomEvent; +use crate::event::{AppEvent, AppEventScheduler}; use crate::render::FrameBufferRef; use graphite_desktop_wrapper::{WgpuContext, deserialize_editor_message}; use std::fs::File; @@ -38,7 +37,6 @@ mod texture_import; use texture_import::SharedTextureHandle; pub(crate) use context::{CefContext, CefContextBuilder, InitError}; -use winit::event_loop::EventLoopProxy; pub(crate) trait CefEventHandler: Clone + Send + Sync + 'static { fn window_size(&self) -> WindowSize; @@ -58,12 +56,16 @@ pub(crate) struct WindowSize { pub(crate) width: usize, pub(crate) height: usize, } - impl WindowSize { pub(crate) fn new(width: usize, height: usize) -> Self { Self { width, height } } } +impl From> for WindowSize { + fn from(size: winit::dpi::PhysicalSize) -> Self { + Self::new(size.width as usize, size.height as usize) + } +} #[derive(Clone)] pub(crate) struct Resource { @@ -88,29 +90,17 @@ impl Read for ResourceReader { #[derive(Clone)] pub(crate) struct CefHandler { - window_size_receiver: Arc>, - event_loop_proxy: EventLoopProxy, wgpu_context: WgpuContext, + app_event_scheduler: AppEventScheduler, + window_size_receiver: Arc>, } -struct WindowSizeReceiver { - receiver: Receiver, - window_size: WindowSize, -} -impl WindowSizeReceiver { - fn new(window_size_receiver: Receiver) -> Self { - Self { - window_size: WindowSize { width: 1, height: 1 }, - receiver: window_size_receiver, - } - } -} impl CefHandler { - pub(crate) fn new(window_size_receiver: Receiver, event_loop_proxy: EventLoopProxy, wgpu_context: WgpuContext) -> Self { + pub(crate) fn new(wgpu_context: WgpuContext, app_event_scheduler: AppEventScheduler, window_size_receiver: Receiver) -> Self { Self { - window_size_receiver: Arc::new(Mutex::new(WindowSizeReceiver::new(window_size_receiver))), - event_loop_proxy, wgpu_context, + app_event_scheduler, + window_size_receiver: Arc::new(Mutex::new(WindowSizeReceiver::new(window_size_receiver))), } } } @@ -164,14 +154,14 @@ impl CefEventHandler for CefHandler { }, ); - let _ = self.event_loop_proxy.send_event(CustomEvent::UiUpdate(texture)); + self.app_event_scheduler.schedule(AppEvent::UiUpdate(texture)); } #[cfg(feature = "accelerated_paint")] fn draw_gpu(&self, shared_texture: SharedTextureHandle) { match shared_texture.import_texture(&self.wgpu_context.device) { Ok(texture) => { - let _ = self.event_loop_proxy.send_event(CustomEvent::UiUpdate(texture)); + self.app_event_scheduler.schedule(AppEvent::UiUpdate(texture)); } Err(e) => { tracing::error!("Failed to import shared texture: {}", e); @@ -235,11 +225,11 @@ impl CefEventHandler for CefHandler { } fn schedule_cef_message_loop_work(&self, scheduled_time: std::time::Instant) { - let _ = self.event_loop_proxy.send_event(CustomEvent::ScheduleBrowserWork(scheduled_time)); + self.app_event_scheduler.schedule(AppEvent::ScheduleBrowserWork(scheduled_time)); } fn initialized_web_communication(&self) { - let _ = self.event_loop_proxy.send_event(CustomEvent::WebCommunicationInitialized); + self.app_event_scheduler.schedule(AppEvent::WebCommunicationInitialized); } fn receive_web_message(&self, message: &[u8]) { @@ -247,6 +237,19 @@ impl CefEventHandler for CefHandler { tracing::error!("Failed to deserialize web message"); return; }; - let _ = self.event_loop_proxy.send_event(CustomEvent::DesktopWrapperMessage(desktop_wrapper_message)); + self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(desktop_wrapper_message)); + } +} + +struct WindowSizeReceiver { + window_size: WindowSize, + receiver: Receiver, +} +impl WindowSizeReceiver { + fn new(window_size_receiver: Receiver) -> Self { + Self { + window_size: WindowSize { width: 1, height: 1 }, + receiver: window_size_receiver, + } } } diff --git a/desktop/src/cef/input.rs b/desktop/src/cef/input.rs index 6f20eb7d..44d86a10 100644 --- a/desktop/src/cef/input.rs +++ b/desktop/src/cef/input.rs @@ -2,7 +2,7 @@ use cef::sys::{cef_event_flags_t, cef_key_event_type_t, cef_mouse_button_type_t} use cef::{Browser, ImplBrowser, ImplBrowserHost, KeyEvent, KeyEventType, MouseEvent}; use std::time::Instant; use winit::dpi::PhysicalPosition; -use winit::event::{ElementState, MouseButton, MouseScrollDelta, WindowEvent}; +use winit::event::{ButtonSource, ElementState, MouseButton, MouseScrollDelta, WindowEvent}; mod keymap; use keymap::{ToNativeKeycode, ToVKBits}; @@ -11,7 +11,7 @@ use super::consts::{MULTICLICK_ALLOWED_TRAVEL, MULTICLICK_TIMEOUT, SCROLL_LINE_H pub(crate) fn handle_window_event(browser: &Browser, input_state: &mut InputState, event: &WindowEvent) { match event { - WindowEvent::CursorMoved { position, .. } => { + WindowEvent::PointerMoved { position, .. } => { input_state.cursor_move(position); let Some(host) = browser.host() else { @@ -19,13 +19,20 @@ pub(crate) fn handle_window_event(browser: &Browser, input_state: &mut InputStat }; host.send_mouse_move_event(Some(&input_state.into()), 0); } - WindowEvent::MouseInput { state, button, .. } => { - let cef_click_count = input_state.mouse_input(button, state).into(); + WindowEvent::PointerButton { state, button, .. } => { + let mouse_button = match button { + ButtonSource::Mouse(mouse_button) => mouse_button, + _ => { + return; // TODO: Handle touch input + } + }; + + let cef_click_count = input_state.mouse_input(mouse_button, state).into(); let cef_mouse_up = match state { ElementState::Pressed => 0, ElementState::Released => 1, }; - let cef_button = match button { + let cef_button = match mouse_button { MouseButton::Left => cef::MouseButtonType::from(cef_mouse_button_type_t::MBT_LEFT), MouseButton::Right => cef::MouseButtonType::from(cef_mouse_button_type_t::MBT_RIGHT), MouseButton::Middle => cef::MouseButtonType::from(cef_mouse_button_type_t::MBT_MIDDLE), @@ -59,7 +66,6 @@ pub(crate) fn handle_window_event(browser: &Browser, input_state: &mut InputStat winit::keyboard::Key::Named(named_key) => ( Some(named_key), match named_key { - winit::keyboard::NamedKey::Space => Some(' '), winit::keyboard::NamedKey::Enter => Some('\u{000d}'), _ => None, }, @@ -312,7 +318,7 @@ impl CefModifiers { if input_state.modifiers.alt_key() { inner |= cef_event_flags_t::EVENTFLAG_ALT_DOWN as u32; } - if input_state.modifiers.super_key() { + if input_state.modifiers.meta_key() { inner |= cef_event_flags_t::EVENTFLAG_COMMAND_DOWN as u32; } diff --git a/desktop/src/cef/input/keymap.rs b/desktop/src/cef/input/keymap.rs index 0861af41..44cd56f4 100644 --- a/desktop/src/cef/input/keymap.rs +++ b/desktop/src/cef/input/keymap.rs @@ -47,10 +47,8 @@ impl ToVKBits for winit::keyboard::NamedKey { (0x91, ScrollLock), (0x10, Shift), (0x5B, Meta), - (0x5C, Super), (0x0D, Enter), (0x09, Tab), - (0x20, Space), (0x28, ArrowDown), (0x25, ArrowLeft), (0x27, ArrowRight), @@ -253,6 +251,7 @@ impl ToVKBits for char { (0xDE, '"'), (0xBF, '/'), (0xBF, '?'), + (0x20, ' '), ) } } diff --git a/desktop/src/event.rs b/desktop/src/event.rs new file mode 100644 index 00000000..3fa856d5 --- /dev/null +++ b/desktop/src/event.rs @@ -0,0 +1,34 @@ +use graphite_desktop_wrapper::NodeGraphExecutionResult; +use graphite_desktop_wrapper::messages::DesktopWrapperMessage; + +pub(crate) enum AppEvent { + UiUpdate(wgpu::Texture), + ScheduleBrowserWork(std::time::Instant), + WebCommunicationInitialized, + DesktopWrapperMessage(DesktopWrapperMessage), + NodeGraphExecutionResult(NodeGraphExecutionResult), + CloseWindow, +} + +#[derive(Clone)] +pub(crate) struct AppEventScheduler { + pub(crate) proxy: winit::event_loop::EventLoopProxy, + pub(crate) sender: std::sync::mpsc::Sender, +} + +impl AppEventScheduler { + pub(crate) fn schedule(&self, event: AppEvent) { + let _ = self.sender.send(event); + self.proxy.wake_up(); + } +} + +pub(crate) trait CreateAppEventSchedulerEventLoopExt { + fn create_app_event_scheduler(&self, sender: std::sync::mpsc::Sender) -> AppEventScheduler; +} + +impl CreateAppEventSchedulerEventLoopExt for winit::event_loop::EventLoop { + fn create_app_event_scheduler(&self, sender: std::sync::mpsc::Sender) -> AppEventScheduler { + AppEventScheduler { proxy: self.create_proxy(), sender } + } +} diff --git a/desktop/src/main.rs b/desktop/src/main.rs index d6aa4414..16190d0f 100644 --- a/desktop/src/main.rs +++ b/desktop/src/main.rs @@ -1,35 +1,22 @@ use std::process::exit; -use std::time::Instant; - -use cef::CefHandler; use tracing_subscriber::EnvFilter; use winit::event_loop::EventLoop; +use graphite_desktop_wrapper::WgpuContext; + pub(crate) mod consts; +mod app; mod cef; - +mod dirs; +mod event; mod native_window; - +mod persist; mod render; -mod app; -use app::WinitApp; - -mod dirs; -mod persist; - -use graphite_desktop_wrapper::messages::DesktopWrapperMessage; -use graphite_desktop_wrapper::{NodeGraphExecutionResult, WgpuContext}; - -pub(crate) enum CustomEvent { - UiUpdate(wgpu::Texture), - ScheduleBrowserWork(Instant), - WebCommunicationInitialized, - DesktopWrapperMessage(DesktopWrapperMessage), - NodeGraphExecutionResult(NodeGraphExecutionResult), - CloseWindow, -} +use app::App; +use cef::CefHandler; +use event::CreateAppEventSchedulerEventLoopExt; fn main() { tracing_subscriber::fmt().with_env_filter(EnvFilter::from_default_env()).init(); @@ -46,13 +33,18 @@ fn main() { let wgpu_context = futures::executor::block_on(WgpuContext::new()).unwrap(); - let event_loop = EventLoop::::with_user_event().build().unwrap(); + let event_loop = EventLoop::new().unwrap(); + let (app_event_sender, app_event_receiver) = std::sync::mpsc::channel(); + let app_event_scheduler = event_loop.create_app_event_scheduler(app_event_sender); let (window_size_sender, window_size_receiver) = std::sync::mpsc::channel(); - let cef_handler = cef::CefHandler::new(window_size_receiver, event_loop.create_proxy(), wgpu_context.clone()); + let cef_handler = cef::CefHandler::new(wgpu_context.clone(), app_event_scheduler.clone(), window_size_receiver); let cef_context = match cef_context_builder.initialize(cef_handler) { - Ok(c) => c, + Ok(c) => { + tracing::info!("CEF initialized successfully"); + c + } Err(cef::InitError::AlreadyRunning) => { tracing::error!("Another instance is already running, Exiting."); exit(0); @@ -71,9 +63,7 @@ fn main() { } }; - tracing::info!("CEF initialized successfully"); + let mut app = App::new(Box::new(cef_context), window_size_sender, wgpu_context, app_event_receiver, app_event_scheduler); - let mut winit_app = WinitApp::new(Box::new(cef_context), window_size_sender, wgpu_context, event_loop.create_proxy()); - - event_loop.run_app(&mut winit_app).unwrap(); + event_loop.run_app(&mut app).unwrap(); } diff --git a/desktop/src/native_window.rs b/desktop/src/native_window.rs index 1b3d7445..21404b69 100644 --- a/desktop/src/native_window.rs +++ b/desktop/src/native_window.rs @@ -1,6 +1,8 @@ use winit::event_loop::ActiveEventLoop; use winit::window::{Window, WindowAttributes}; +use crate::consts::APP_NAME; + #[cfg(target_os = "windows")] mod windows; @@ -17,25 +19,31 @@ impl Default for NativeWindowHandle { } impl NativeWindowHandle { #[allow(unused_variables)] - pub(super) fn build(&mut self, window: WindowAttributes, event_loop: &ActiveEventLoop) -> WindowAttributes { + pub(super) fn build(&mut self, event_loop: &dyn ActiveEventLoop) -> WindowAttributes { + let mut window = WindowAttributes::default() + .with_title(APP_NAME) + .with_min_surface_size(winit::dpi::LogicalSize::new(400, 300)) + .with_surface_size(winit::dpi::LogicalSize::new(1200, 800)) + .with_resizable(true); + #[cfg(target_os = "linux")] { use crate::consts::{APP_ID, APP_NAME}; use winit::platform::wayland::ActiveEventLoopExtWayland; - if event_loop.is_wayland() { - winit::platform::wayland::WindowAttributesExtWayland::with_name(window, APP_ID, "") + use winit::platform::wayland::WindowAttributesWayland; + use winit::platform::x11::WindowAttributesX11; + window = if event_loop.is_wayland() { + let wayland_window = WindowAttributesWayland::default().with_name(APP_ID, ""); + window.with_platform_attributes(Box::new(wayland_window)) } else { - winit::platform::x11::WindowAttributesExtX11::with_name(window, APP_ID, APP_NAME) + let x11_window = WindowAttributesX11::default().with_name(APP_ID, APP_NAME); + window.with_platform_attributes(Box::new(x11_window)) } } - #[cfg(not(target_os = "linux"))] - { - window - } + window } - #[allow(unused_variables)] - pub(crate) fn setup(&mut self, window: &Window) { + pub(crate) fn setup(&mut self, window: &dyn Window) { #[cfg(target_os = "windows")] { *self = NativeWindowHandle::Windows(windows::WindowsNativeWindowHandle::new(window)); diff --git a/desktop/src/native_window/windows.rs b/desktop/src/native_window/windows.rs index 58a569ef..18a18679 100644 --- a/desktop/src/native_window/windows.rs +++ b/desktop/src/native_window/windows.rs @@ -23,7 +23,7 @@ pub(super) struct WindowsNativeWindowHandle { inner: WindowsNativeWindowHandleInner, } impl WindowsNativeWindowHandle { - pub(super) fn new(window: &Window) -> Self { + pub(super) fn new(window: &dyn Window) -> Self { let inner = WindowsNativeWindowHandleInner::new(window); WindowsNativeWindowHandle { inner } } @@ -41,7 +41,7 @@ struct WindowsNativeWindowHandleInner { prev_window_message_handler: isize, } impl WindowsNativeWindowHandleInner { - fn new(window: &Window) -> WindowsNativeWindowHandleInner { + fn new(window: &dyn Window) -> WindowsNativeWindowHandleInner { // Extract Win32 HWND from winit. let hwnd = match window.window_handle().expect("No window handle").as_raw() { RawWindowHandle::Win32(h) => HWND(h.hwnd.get() as *mut std::ffi::c_void), diff --git a/desktop/src/render/graphics_state.rs b/desktop/src/render/graphics_state.rs index fdec45a6..1d1d1aef 100644 --- a/desktop/src/render/graphics_state.rs +++ b/desktop/src/render/graphics_state.rs @@ -24,8 +24,8 @@ pub(crate) struct GraphicsState { } impl GraphicsState { - pub(crate) fn new(window: Arc, context: WgpuContext) -> Self { - let size = window.inner_size(); + pub(crate) fn new(window: Arc, context: WgpuContext) -> Self { + let size = window.surface_size(); let surface = context.instance.create_surface(window).unwrap(); @@ -232,7 +232,7 @@ impl GraphicsState { self.bind_overlays_texture(texture); } - pub(crate) fn render(&mut self, window: &Window) -> Result<(), wgpu::SurfaceError> { + pub(crate) fn render(&mut self, window: &dyn Window) -> Result<(), wgpu::SurfaceError> { if let Some(scene) = self.overlays_scene.take() { self.render_overlays(scene); } diff --git a/node-graph/graph-craft/src/wasm_application_io.rs b/node-graph/graph-craft/src/wasm_application_io.rs index 999b00fe..abca58d8 100644 --- a/node-graph/graph-craft/src/wasm_application_io.rs +++ b/node-graph/graph-craft/src/wasm_application_io.rs @@ -26,7 +26,7 @@ struct WindowWrapper { #[cfg(target_family = "wasm")] window: SurfaceHandle, #[cfg(not(target_family = "wasm"))] - window: SurfaceHandle>, + window: SurfaceHandle>, } #[cfg(target_family = "wasm")] @@ -187,7 +187,7 @@ impl ApplicationIo for WasmApplicationIo { #[cfg(target_family = "wasm")] type Surface = HtmlCanvasElement; #[cfg(not(target_family = "wasm"))] - type Surface = Arc; + type Surface = Arc; #[cfg(feature = "wgpu")] type Executor = WgpuExecutor; #[cfg(not(feature = "wgpu"))] diff --git a/node-graph/wgpu-executor/src/lib.rs b/node-graph/wgpu-executor/src/lib.rs index 15a9da7f..4a1e7f3e 100644 --- a/node-graph/wgpu-executor/src/lib.rs +++ b/node-graph/wgpu-executor/src/lib.rs @@ -53,7 +53,7 @@ pub struct TargetTexture { #[cfg(target_family = "wasm")] pub type Window = web_sys::HtmlCanvasElement; #[cfg(not(target_family = "wasm"))] -pub type Window = Arc; +pub type Window = Arc; unsafe impl StaticType for Surface { type Static = Surface;