From 8697545238e629ca040617bcba4c8b383c8bf4c7 Mon Sep 17 00:00:00 2001 From: 443eb9#C <443eb9@gmail.com> Date: Mon, 10 Aug 2026 17:45:17 +0800 Subject: [PATCH 1/8] upgrade winit to 0.31 --- Cargo.lock | 795 +++++++++++++++---------------- Cargo.toml | 2 +- examples/integration/src/main.rs | 24 +- winit/Cargo.toml | 4 - winit/src/conversion.rs | 369 +++++++------- winit/src/lib.rs | 315 ++++++++---- winit/src/proxy.rs | 22 +- winit/src/window.rs | 40 +- winit/src/window/state.rs | 27 +- 9 files changed, 883 insertions(+), 715 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae17e10089..11b417eded 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,19 +24,6 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" -[[package]] -name = "ahash" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" -dependencies = [ - "cfg-if", - "getrandom 0.3.4", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" version = "1.1.4" @@ -161,11 +148,11 @@ dependencies = [ "clipboard-win", "image", "log", - "objc2 0.6.4", - "objc2-app-kit 0.3.2", + "objc2", + "objc2-app-kit", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.2", + "objc2-foundation", "parking_lot", "percent-encoding", "windows-sys 0.60.2", @@ -311,7 +298,7 @@ dependencies = [ "futures-lite", "parking", "polling", - "rustix 1.1.4", + "rustix", "slab", "windows-sys 0.61.2", ] @@ -353,7 +340,7 @@ dependencies = [ "cfg-if", "event-listener", "futures-lite", - "rustix 1.1.4", + "rustix", ] [[package]] @@ -379,7 +366,7 @@ dependencies = [ "cfg-if", "futures-core", "futures-io", - "rustix 1.1.4", + "rustix", "signal-hook-registry", "slab", "windows-sys 0.61.2", @@ -585,22 +572,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.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "objc2 0.6.4", + "objc2", ] [[package]] @@ -622,6 +600,16 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e79769241dcd44edf79a732545e8b5cec84c247ac060f5252cd51885d093a8fc" +[[package]] +name = "borsh" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a88b7ea17d208c4193f2c1e6de3c35fe71f98c96982d5ced308bdcc749ff6e1f" +dependencies = [ + "bytes", + "cfg_aliases", +] + [[package]] name = "built" version = "0.8.1" @@ -680,26 +668,25 @@ checksum = "2e93abca9e28e0a1b9877922aacb20576e05d4679ffa78c3d6dc22a26a216659" [[package]] name = "calloop" -version = "0.13.0" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" dependencies = [ "bitflags 2.13.0", - "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", ] @@ -742,9 +729,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" [[package]] name = "chacha20" @@ -959,30 +946,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 0.9.4", - "core-graphics-types", - "foreign-types 0.5.0", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "libc", -] - [[package]] name = "core_maths" version = "0.1.1" @@ -1280,9 +1243,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ "bitflags 2.13.0", - "block2 0.6.2", + "block2", "libc", - "objc2 0.6.4", + "objc2", ] [[package]] @@ -1330,8 +1293,8 @@ dependencies = [ [[package]] name = "dpi" -version = "0.1.1" -source = "git+https://github.com/iced-rs/winit.git?rev=05b8ff17a06562f0a10bb46e6eaacbe2a95cb5ed#05b8ff17a06562f0a10bb46e6eaacbe2a95cb5ed" +version = "0.1.2" +source = "git+https://github.com/rust-windowing/winit.git?rev=f5e20bd7da25934f39abe8dc44a0597110ef6357#f5e20bd7da25934f39abe8dc44a0597110ef6357" [[package]] name = "dtor" @@ -1636,28 +1599,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared 0.1.1", -] - -[[package]] -name = "foreign-types" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" -dependencies = [ - "foreign-types-macros", - "foreign-types-shared 0.3.1", -] - -[[package]] -name = "foreign-types-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" -dependencies = [ - "proc-macro2", - "quote", - "syn", + "foreign-types-shared", ] [[package]] @@ -1666,12 +1608,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -[[package]] -name = "foreign-types-shared" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" - [[package]] name = "form_urlencoded" version = "1.2.2" @@ -1830,7 +1766,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ - "rustix 1.1.4", + "rustix", "windows-link", ] @@ -2450,7 +2386,7 @@ dependencies = [ "resvg", "rustc-hash 2.1.3", "softbuffer", - "tiny-skia", + "tiny-skia 0.11.4", ] [[package]] @@ -2499,7 +2435,6 @@ dependencies = [ "iced_runtime", "log", "mundy", - "objc2 0.5.2", "rustc-hash 2.1.3", "sysinfo", "thiserror 2.0.18", @@ -2892,6 +2827,16 @@ dependencies = [ "mutate_once", ] +[[package]] +name = "keyboard-types" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fbe853b403ae61a04233030ae8a79d94975281ed9770a1f9e246732b534b28d" +dependencies = [ + "bitflags 2.13.0", + "serde", +] + [[package]] name = "khronos-egl" version = "6.0.0" @@ -3021,12 +2966,6 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" -[[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.12.1" @@ -3185,7 +3124,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" dependencies = [ - "rustix 1.1.4", + "rustix", ] [[package]] @@ -3290,9 +3229,9 @@ dependencies = [ "futures-lite", "jni", "ndk-context", - "objc2 0.6.4", - "objc2-app-kit 0.3.2", - "objc2-foundation 0.3.2", + "objc2", + "objc2-app-kit", + "objc2-foundation", "pin-project-lite", "wasm-bindgen", "wasm-bindgen-futures", @@ -3507,22 +3446,6 @@ dependencies = [ "syn", ] -[[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.4" @@ -3532,22 +3455,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.13.0", - "block2 0.5.1", - "libc", - "objc2 0.5.2", - "objc2-core-data 0.2.2", - "objc2-core-image 0.2.2", - "objc2-foundation 0.2.2", - "objc2-quartz-core 0.2.2", -] - [[package]] name = "objc2-app-kit" version = "0.3.2" @@ -3555,31 +3462,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.13.0", - "block2 0.6.2", + "block2", "libc", - "objc2 0.6.4", - "objc2-cloud-kit 0.3.2", - "objc2-core-data 0.3.2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", "objc2-core-foundation", "objc2-core-graphics", - "objc2-core-image 0.3.2", + "objc2-core-image", "objc2-core-text", "objc2-core-video", - "objc2-foundation 0.3.2", - "objc2-quartz-core 0.3.2", -] - -[[package]] -name = "objc2-cloud-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" -dependencies = [ - "bitflags 2.13.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-core-location", - "objc2-foundation 0.2.2", + "objc2-foundation", + "objc2-quartz-core", ] [[package]] @@ -3589,31 +3483,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c" dependencies = [ "bitflags 2.13.0", - "objc2 0.6.4", - "objc2-foundation 0.3.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.13.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", + "objc2", + "objc2-foundation", ] [[package]] @@ -3623,8 +3494,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa" dependencies = [ "bitflags 2.13.0", - "objc2 0.6.4", - "objc2-foundation 0.3.2", + "objc2", + "objc2-foundation", ] [[package]] @@ -3634,8 +3505,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.13.0", + "block2", "dispatch2", - "objc2 0.6.4", + "objc2", ] [[package]] @@ -3646,43 +3518,20 @@ checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ "bitflags 2.13.0", "dispatch2", - "objc2 0.6.4", + "libc", + "objc2", "objc2-core-foundation", "objc2-io-surface", ] -[[package]] -name = "objc2-core-image" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal 0.2.2", -] - [[package]] name = "objc2-core-image" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5d563b38d2b97209f8e861173de434bd0214cf020e3423a52624cd1d989f006" dependencies = [ - "objc2 0.6.4", - "objc2-foundation 0.3.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", + "objc2", + "objc2-foundation", ] [[package]] @@ -3692,7 +3541,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" dependencies = [ "bitflags 2.13.0", - "objc2 0.6.4", + "objc2", "objc2-core-foundation", "objc2-core-graphics", ] @@ -3704,7 +3553,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" dependencies = [ "bitflags 2.13.0", - "objc2 0.6.4", + "objc2", "objc2-core-foundation", "objc2-core-graphics", "objc2-io-surface", @@ -3716,19 +3565,6 @@ 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.13.0", - "block2 0.5.1", - "dispatch", - "libc", - "objc2 0.5.2", -] - [[package]] name = "objc2-foundation" version = "0.3.2" @@ -3736,9 +3572,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.13.0", - "block2 0.6.2", + "block2", "libc", - "objc2 0.6.4", + "objc2", "objc2-core-foundation", ] @@ -3749,34 +3585,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ "bitflags 2.13.0", - "objc2 0.6.4", + "objc2", "objc2-core-foundation", ] -[[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.13.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - [[package]] name = "objc2-metal" version = "0.3.2" @@ -3784,22 +3596,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" dependencies = [ "bitflags 2.13.0", - "block2 0.6.2", - "objc2 0.6.4", - "objc2-foundation 0.3.2", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" -dependencies = [ - "bitflags 2.13.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal 0.2.2", + "block2", + "objc2", + "objc2-foundation", ] [[package]] @@ -3809,65 +3608,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ "bitflags 2.13.0", - "objc2 0.6.4", + "objc2", "objc2-core-foundation", - "objc2-foundation 0.3.2", - "objc2-metal 0.3.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", + "objc2-metal", ] [[package]] name = "objc2-ui-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" -dependencies = [ - "bitflags 2.13.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-cloud-kit 0.2.2", - "objc2-core-data 0.2.2", - "objc2-core-image 0.2.2", - "objc2-core-location", - "objc2-foundation 0.2.2", - "objc2-link-presentation", - "objc2-quartz-core 0.2.2", - "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" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ "bitflags 2.13.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-core-location", - "objc2-foundation 0.2.2", + "objc2", + "objc2-core-foundation", + "objc2-foundation", ] [[package]] @@ -3900,7 +3656,7 @@ checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ "bitflags 2.13.0", "cfg-if", - "foreign-types 0.3.2", + "foreign-types", "libc", "openssl-macros", "openssl-sys", @@ -3943,11 +3699,10 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orbclient" -version = "0.3.55" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5df339f526ea9a60e371768d50efc2f2508c7203290731565d1f7a6f71d21747" +checksum = "bb08138df30517916447489a70848de31244c40c7b520bcf5ebdc9db6299da59" dependencies = [ - "libc", "libredox", ] @@ -4301,7 +4056,7 @@ dependencies = [ "concurrent-queue", "hermit-abi", "pin-project-lite", - "rustix 1.1.4", + "rustix", "windows-sys 0.61.2", ] @@ -4646,10 +4401,10 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" dependencies = [ - "objc2 0.6.4", + "objc2", "objc2-core-foundation", - "objc2-foundation 0.3.2", - "objc2-quartz-core 0.3.2", + "objc2-foundation", + "objc2-quartz-core", ] [[package]] @@ -4694,12 +4449,13 @@ dependencies = [ ] [[package]] -name = "redox_syscall" -version = "0.4.1" +name = "redox_event" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "c5018d583d6d2f5499352aea8d177e9067d1eb03ab17c78169d5ba7a30001b15" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.13.0", + "libredox", ] [[package]] @@ -4821,7 +4577,7 @@ dependencies = [ "pico-args", "rgb", "svgtypes", - "tiny-skia", + "tiny-skia 0.11.4", "usvg", "zune-jpeg 0.4.21", ] @@ -4833,14 +4589,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a15ad77d9e70a92437d8f74c35d99b4e4691128df018833e99f90bcd36152672" dependencies = [ "ashpd", - "block2 0.6.2", + "block2", "dispatch2", "js-sys", "log", - "objc2 0.6.4", - "objc2-app-kit 0.3.2", + "objc2", + "objc2-app-kit", "objc2-core-foundation", - "objc2-foundation 0.3.2", + "objc2-foundation", "pollster", "raw-window-handle", "urlencoding", @@ -4900,19 +4656,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.13.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - [[package]] name = "rustix" version = "1.1.4" @@ -4922,7 +4665,7 @@ dependencies = [ "bitflags 2.13.0", "errno", "libc", - "linux-raw-sys 0.12.1", + "linux-raw-sys", "windows-sys 0.61.2", ] @@ -5045,15 +4788,15 @@ dependencies = [ [[package]] name = "sctk-adwaita" -version = "0.10.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" +checksum = "1f8ea028b7cb32e2f577b0a55a7b54cb206376bdb1221bd5c81dcf20b68db1fb" dependencies = [ "ab_glyph", "log", "memmap2", "smithay-client-toolkit", - "tiny-skia", + "tiny-skia 0.12.0", ] [[package]] @@ -5322,24 +5065,24 @@ checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "smithay-client-toolkit" -version = "0.19.2" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +checksum = "74dc9ee14b0fdcb535f9556141bacac070c994a977d2240ee455d7438a617f00" dependencies = [ "bitflags 2.13.0", "calloop", "calloop-wayland-source", "cursor-icon", - "libc", "log", "memmap2", - "rustix 0.38.44", - "thiserror 1.0.69", - "wayland-backend", + "rustix", + "thiserror 2.0.18", "wayland-client", "wayland-csd-frame", "wayland-cursor", "wayland-protocols", + "wayland-protocols-experimental", + "wayland-protocols-misc", "wayland-protocols-wlr", "wayland-scanner", "xkeysym", @@ -5376,6 +5119,10 @@ name = "smol_str" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4aaa7368fcf4852a4c2dd92df0cace6a71f2091ca0a23391ce7f3a31833f1523" +dependencies = [ + "borsh", + "serde_core", +] [[package]] name = "socket2" @@ -5399,14 +5146,14 @@ dependencies = [ "js-sys", "memmap2", "ndk", - "objc2 0.6.4", + "objc2", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.2", - "objc2-quartz-core 0.3.2", + "objc2-foundation", + "objc2-quartz-core", "raw-window-handle", "redox_syscall 0.5.18", - "rustix 1.1.4", + "rustix", "tiny-xlib", "tracing", "wasm-bindgen", @@ -5661,7 +5408,7 @@ dependencies = [ "fastrand", "getrandom 0.4.3", "once_cell", - "rustix 1.1.4", + "rustix", "windows-sys 0.61.2", ] @@ -5795,7 +5542,21 @@ dependencies = [ "cfg-if", "log", "png 0.17.16", - "tiny-skia-path", + "tiny-skia-path 0.11.4", +] + +[[package]] +name = "tiny-skia" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47ffee5eaaf5527f630fb0e356b90ebdec84d5d18d937c5e440350f88c5a91ea" +dependencies = [ + "arrayref", + "arrayvec", + "bytemuck", + "cfg-if", + "log", + "tiny-skia-path 0.12.0", ] [[package]] @@ -5809,6 +5570,17 @@ dependencies = [ "strict-num", ] +[[package]] +name = "tiny-skia-path" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edca365c3faccca67d06593c5980fa6c57687de727a03131735bb85f01fdeeb9" +dependencies = [ + "arrayref", + "bytemuck", + "strict-num", +] + [[package]] name = "tiny-xlib" version = "0.2.5" @@ -6299,7 +6071,7 @@ dependencies = [ "siphasher", "strict-num", "svgtypes", - "tiny-skia-path", + "tiny-skia-path 0.11.4", "unicode-bidi", "unicode-script", "unicode-vo", @@ -6534,7 +6306,7 @@ checksum = "2857dd20b54e916ec7253b3d6b4d5c4d7d4ca2c33c2e11c6c76a99bd8744755d" dependencies = [ "cc", "downcast-rs", - "rustix 1.1.4", + "rustix", "scoped-tls", "smallvec", "wayland-sys", @@ -6547,7 +6319,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" dependencies = [ "bitflags 2.13.0", - "rustix 1.1.4", + "rustix", "wayland-backend", "wayland-scanner", ] @@ -6569,7 +6341,7 @@ version = "0.31.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" dependencies = [ - "rustix 1.1.4", + "rustix", "wayland-client", "xcursor", ] @@ -6586,6 +6358,32 @@ dependencies = [ "wayland-scanner", ] +[[package]] +name = "wayland-protocols-experimental" +version = "20251230.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c6c3e7178e553d093d46999032bc79aafea9dedd71dd702c8ace7bbc25cf13" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-misc" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8" +dependencies = [ + "bitflags 2.13.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + [[package]] name = "wayland-protocols-plasma" version = "0.3.12" @@ -6665,8 +6463,8 @@ dependencies = [ "jni", "log", "ndk-context", - "objc2 0.6.4", - "objc2-foundation 0.3.2", + "objc2", + "objc2-foundation", "url", "web-sys", ] @@ -6807,7 +6605,7 @@ dependencies = [ "ash", "bit-set 0.9.1", "bitflags 2.13.0", - "block2 0.6.2", + "block2", "bytemuck", "cfg-if", "cfg_aliases", @@ -6823,11 +6621,11 @@ dependencies = [ "log", "naga", "ndk-sys", - "objc2 0.6.4", + "objc2", "objc2-core-foundation", - "objc2-foundation 0.3.2", - "objc2-metal 0.3.2", - "objc2-quartz-core 0.3.2", + "objc2-foundation", + "objc2-metal", + "objc2-quartz-core", "once_cell", "ordered-float", "parking_lot", @@ -7079,15 +6877,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.60.2" @@ -7246,50 +7035,219 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winit" -version = "0.30.8" -source = "git+https://github.com/iced-rs/winit.git?rev=05b8ff17a06562f0a10bb46e6eaacbe2a95cb5ed#05b8ff17a06562f0a10bb46e6eaacbe2a95cb5ed" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git?rev=f5e20bd7da25934f39abe8dc44a0597110ef6357#f5e20bd7da25934f39abe8dc44a0597110ef6357" dependencies = [ - "ahash", - "android-activity", - "atomic-waker", "bitflags 2.13.0", - "block2 0.5.1", - "bytemuck", - "calloop", "cfg_aliases", - "concurrent-queue", - "core-foundation 0.9.4", - "core-graphics", "cursor-icon", "dpi", - "js-sys", "libc", - "memmap2", + "raw-window-handle", + "rustix", + "smol_str 0.3.6", + "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.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git?rev=f5e20bd7da25934f39abe8dc44a0597110ef6357#f5e20bd7da25934f39abe8dc44a0597110ef6357" +dependencies = [ + "android-activity", + "bitflags 2.13.0", + "dpi", "ndk", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", - "objc2-ui-kit", + "raw-window-handle", + "smol_str 0.3.6", + "tracing", + "winit-core", +] + +[[package]] +name = "winit-appkit" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git?rev=f5e20bd7da25934f39abe8dc44a0597110ef6357#f5e20bd7da25934f39abe8dc44a0597110ef6357" +dependencies = [ + "bitflags 2.13.0", + "block2", + "dispatch2", + "dpi", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-core-video", + "objc2-foundation", + "raw-window-handle", + "smol_str 0.3.6", + "tracing", + "winit-common", + "winit-core", +] + +[[package]] +name = "winit-common" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git?rev=f5e20bd7da25934f39abe8dc44a0597110ef6357#f5e20bd7da25934f39abe8dc44a0597110ef6357" +dependencies = [ + "block2", + "memmap2", + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "smol_str 0.3.6", + "tracing", + "winit-core", + "x11-dl", + "xkbcommon-dl", +] + +[[package]] +name = "winit-core" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git?rev=f5e20bd7da25934f39abe8dc44a0597110ef6357#f5e20bd7da25934f39abe8dc44a0597110ef6357" +dependencies = [ + "bitflags 2.13.0", + "cursor-icon", + "dpi", + "keyboard-types", + "raw-window-handle", + "smol_str 0.3.6", + "url", + "web-time", +] + +[[package]] +name = "winit-orbital" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git?rev=f5e20bd7da25934f39abe8dc44a0597110ef6357#f5e20bd7da25934f39abe8dc44a0597110ef6357" +dependencies = [ + "bitflags 2.13.0", + "dpi", + "libredox", "orbclient", + "raw-window-handle", + "redox_event", + "smol_str 0.3.6", + "tracing", + "winit-core", +] + +[[package]] +name = "winit-uikit" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git?rev=f5e20bd7da25934f39abe8dc44a0597110ef6357#f5e20bd7da25934f39abe8dc44a0597110ef6357" +dependencies = [ + "bitflags 2.13.0", + "block2", + "dispatch2", + "dpi", + "objc2", + "objc2-core-foundation", + "objc2-foundation", + "objc2-ui-kit", + "raw-window-handle", + "smol_str 0.3.6", + "tracing", + "winit-common", + "winit-core", +] + +[[package]] +name = "winit-wayland" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git?rev=f5e20bd7da25934f39abe8dc44a0597110ef6357#f5e20bd7da25934f39abe8dc44a0597110ef6357" +dependencies = [ + "bitflags 2.13.0", + "calloop", + "cursor-icon", + "dpi", + "foldhash 0.2.0", + "libc", + "memmap2", "percent-encoding", - "pin-project", "raw-window-handle", - "redox_syscall 0.4.1", - "rustix 0.38.44", + "rustix", "sctk-adwaita", "smithay-client-toolkit", - "smol_str 0.2.2", + "smol_str 0.3.6", "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.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git?rev=f5e20bd7da25934f39abe8dc44a0597110ef6357#f5e20bd7da25934f39abe8dc44a0597110ef6357" +dependencies = [ + "atomic-waker", + "bitflags 2.13.0", + "concurrent-queue", + "cursor-icon", + "dpi", + "js-sys", + "pin-project", + "raw-window-handle", + "smol_str 0.3.6", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", "web-time", - "windows-sys 0.52.0", + "winit-core", +] + +[[package]] +name = "winit-win32" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git?rev=f5e20bd7da25934f39abe8dc44a0597110ef6357#f5e20bd7da25934f39abe8dc44a0597110ef6357" +dependencies = [ + "bitflags 2.13.0", + "cursor-icon", + "dpi", + "raw-window-handle", + "smol_str 0.3.6", + "tracing", + "unicode-segmentation", + "url", + "windows-sys 0.61.2", + "winit-core", +] + +[[package]] +name = "winit-x11" +version = "0.31.0-beta.2" +source = "git+https://github.com/rust-windowing/winit.git?rev=f5e20bd7da25934f39abe8dc44a0597110ef6357#f5e20bd7da25934f39abe8dc44a0597110ef6357" +dependencies = [ + "bitflags 2.13.0", + "bytemuck", + "calloop", + "cursor-icon", + "dpi", + "libc", + "percent-encoding", + "raw-window-handle", + "rustix", + "smol_str 0.3.6", + "tracing", + "winit-common", + "winit-core", "x11-dl", "x11rb", "xkbcommon-dl", @@ -7319,7 +7277,7 @@ dependencies = [ "libc", "log", "os_pipe", - "rustix 1.1.4", + "rustix", "thiserror 2.0.18", "tree_magic_mini", "wayland-backend", @@ -7356,8 +7314,9 @@ dependencies = [ "libc", "libloading", "once_cell", - "rustix 1.1.4", + "rustix", "x11rb-protocol", + "xcursor", ] [[package]] @@ -7475,7 +7434,7 @@ dependencies = [ "hex", "libc", "ordered-stream", - "rustix 1.1.4", + "rustix", "serde", "serde_repr", "tracing", diff --git a/Cargo.toml b/Cargo.toml index 23d4d09013..74a7077caf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -244,7 +244,7 @@ wasmtimer = "0.4.2" web-sys = "=0.3.85" web-time = "1.1" wgpu = { version = "29", default-features = false, features = ["std", "wgsl"] } -winit = { git = "https://github.com/iced-rs/winit.git", rev = "05b8ff17a06562f0a10bb46e6eaacbe2a95cb5ed", default-features = false, features = ["rwh_06"] } +winit = { git = "https://github.com/rust-windowing/winit.git", rev = "f5e20bd7da25934f39abe8dc44a0597110ef6357", default-features = false } [workspace.lints.rust] rust_2018_idioms = { level = "deny", priority = -1 } diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs index 43602e6970..186607abc0 100644 --- a/examples/integration/src/main.rs +++ b/examples/integration/src/main.rs @@ -35,7 +35,7 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { enum Runner { Loading, Ready { - window: Arc, + window: Arc, queue: wgpu::Queue, device: wgpu::Device, surface: wgpu::Surface<'static>, @@ -53,15 +53,15 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { } impl winit::application::ApplicationHandler for Runner { - fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { + fn resumed(&mut self, event_loop: &dyn winit::event_loop::ActiveEventLoop) { if let Self::Loading = self { - let window = Arc::new( + let window: Arc = Arc::from( event_loop .create_window(winit::window::WindowAttributes::default()) .expect("Create window"), ); - let physical_size = window.inner_size(); + let physical_size = window.surface_size(); let viewport = Viewport::with_physical_size( Size::new(physical_size.width, physical_size.height), renderer::Scale { @@ -174,9 +174,11 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { } } + fn can_create_surfaces(&mut self, _event_loop: &dyn winit::event_loop::ActiveEventLoop) {} + fn window_event( &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, + event_loop: &dyn winit::event_loop::ActiveEventLoop, _window_id: winit::window::WindowId, event: WindowEvent, ) { @@ -207,7 +209,7 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { match event { WindowEvent::RedrawRequested => { if *resized { - let size = window.inner_size(); + let size = window.surface_size(); *viewport = Viewport::with_physical_size( Size::new(size.width, size.height), @@ -285,7 +287,7 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { if let Some(icon) = iced_winit::conversion::mouse_interaction(mouse_interaction) { - window.set_cursor(icon); + window.set_cursor(winit::cursor::Cursor::Icon(icon)); window.set_cursor_visible(true); } else { window.set_cursor_visible(false); @@ -312,7 +314,7 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { } } } - WindowEvent::CursorMoved { position, .. } => { + WindowEvent::PointerMoved { position, .. } => { *cursor = mouse::Cursor::Available(conversion::cursor_position( position, viewport.scale_factor(), @@ -321,7 +323,7 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { WindowEvent::ModifiersChanged(new_modifiers) => { *modifiers = new_modifiers.state(); } - WindowEvent::Resized(_) => { + WindowEvent::SurfaceResized(_) => { *resized = true; } WindowEvent::CloseRequested => { @@ -365,6 +367,6 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { } } - let mut runner = Runner::Loading; - event_loop.run_app(&mut runner) + let runner = Runner::Loading; + event_loop.run_app(runner) } diff --git a/winit/Cargo.toml b/winit/Cargo.toml index 8a6de0687f..dbfe110335 100644 --- a/winit/Cargo.toml +++ b/winit/Cargo.toml @@ -48,7 +48,3 @@ wasm-bindgen-futures.workspace = true [target.'cfg(target_os = "linux")'.dependencies] mundy.workspace = true mundy.optional = true - -# Delete once we update to `winit 0.31` -[target.'cfg(target_os = "macos")'.dependencies] -objc2 = { version = "0.5", features = ["relax-sign-encoding"] } diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs index 259f145848..d0ab26e2e7 100644 --- a/winit/src/conversion.rs +++ b/winit/src/conversion.rs @@ -2,6 +2,7 @@ //! //! [`winit`]: https://github.com/rust-windowing/winit //! [`iced_runtime`]: https://github.com/iced-rs/iced/tree/master/runtime + use crate::core::input_method; use crate::core::keyboard; use crate::core::mouse; @@ -36,7 +37,7 @@ pub fn window_attributes( attributes = attributes .with_title(title) - .with_inner_size(winit::dpi::LogicalSize { + .with_surface_size(winit::dpi::LogicalSize { width: settings.size.width * scale_factor, height: settings.size.height * scale_factor, }) @@ -44,7 +45,7 @@ pub fn window_attributes( .with_fullscreen( settings .fullscreen - .then_some(winit::window::Fullscreen::Borderless(None)), + .then_some(winit::monitor::Fullscreen::Borderless(None)), ) .with_resizable(settings.resizable) .with_enabled_buttons(buttons) @@ -60,14 +61,14 @@ pub fn window_attributes( } if let Some(min_size) = settings.min_size { - attributes = attributes.with_min_inner_size(winit::dpi::LogicalSize { + attributes = attributes.with_min_surface_size(winit::dpi::LogicalSize { width: min_size.width, height: min_size.height, }); } if let Some(max_size) = settings.max_size { - attributes = attributes.with_max_inner_size(winit::dpi::LogicalSize { + attributes = attributes.with_max_surface_size(winit::dpi::LogicalSize { width: max_size.width, height: max_size.height, }); @@ -80,65 +81,71 @@ pub fn window_attributes( target_os = "openbsd" ))] { - use ::winit::platform::wayland::WindowAttributesExtWayland; + use ::winit::platform::wayland::WindowAttributesWayland; if let Some(id) = _id { - attributes = attributes.with_name(id.clone(), id); + attributes = attributes.with_platform_attributes(Box::new( + WindowAttributesWayland::default().with_name(id.clone(), id), + )); } } #[cfg(target_os = "windows")] { use window::settings::platform; - use winit::platform::windows::{CornerPreference, WindowAttributesExtWindows}; - - attributes = attributes.with_drag_and_drop(settings.platform_specific.drag_and_drop); - - attributes = attributes.with_skip_taskbar(settings.platform_specific.skip_taskbar); - - attributes = - attributes.with_undecorated_shadow(settings.platform_specific.undecorated_shadow); - - attributes = - attributes.with_corner_preference(match settings.platform_specific.corner_preference { - platform::CornerPreference::Default => CornerPreference::Default, - platform::CornerPreference::DoNotRound => CornerPreference::DoNotRound, - platform::CornerPreference::Round => CornerPreference::Round, - platform::CornerPreference::RoundSmall => CornerPreference::RoundSmall, - }); + use winit::platform::windows::{CornerPreference, WindowAttributesWindows}; + + attributes = attributes.with_platform_attributes(Box::new( + WindowAttributesWindows::default() + .with_drag_and_drop(settings.platform_specific.drag_and_drop) + .with_skip_taskbar(settings.platform_specific.skip_taskbar) + .with_undecorated_shadow(settings.platform_specific.undecorated_shadow) + .with_corner_preference(match settings.platform_specific.corner_preference { + platform::CornerPreference::Default => CornerPreference::Default, + platform::CornerPreference::DoNotRound => CornerPreference::DoNotRound, + platform::CornerPreference::Round => CornerPreference::Round, + platform::CornerPreference::RoundSmall => CornerPreference::RoundSmall, + }), + )); } #[cfg(target_os = "macos")] { - use winit::platform::macos::WindowAttributesExtMacOS; - - attributes = attributes - .with_title_hidden(settings.platform_specific.title_hidden) - .with_titlebar_transparent(settings.platform_specific.titlebar_transparent) - .with_fullsize_content_view(settings.platform_specific.fullsize_content_view); + use winit::platform::macos::WindowAttributesMacOS; + + attributes = attributes.with_platform_attributes(Box::new( + WindowAttributesMacOS::default() + .with_title_hidden(settings.platform_specific.title_hidden) + .with_titlebar_transparent(settings.platform_specific.titlebar_transparent) + .with_fullsize_content_view(settings.platform_specific.fullsize_content_view), + )); } #[cfg(target_os = "linux")] { #[cfg(feature = "x11")] { - use winit::platform::x11::WindowAttributesExtX11; - - attributes = attributes - .with_override_redirect(settings.platform_specific.override_redirect) - .with_name( - &settings.platform_specific.application_id, - &settings.platform_specific.application_id, - ); + use winit::platform::x11::WindowAttributesX11; + + attributes = attributes.with_platform_attributes(Box::new( + WindowAttributesX11::default() + .with_override_redirect(settings.platform_specific.override_redirect) + .with_name( + &settings.platform_specific.application_id, + &settings.platform_specific.application_id, + ), + )); } #[cfg(feature = "wayland")] { - use winit::platform::wayland::WindowAttributesExtWayland; + use winit::platform::wayland::WindowAttributesWayland; - attributes = attributes.with_name( - &settings.platform_specific.application_id, - &settings.platform_specific.application_id, - ); + attributes = attributes.with_platform_attributes(Box::new( + WindowAttributesWayland::default().with_name( + &settings.platform_specific.application_id, + &settings.platform_specific.application_id, + ), + )); } } @@ -155,7 +162,7 @@ pub fn window_event( use winit::event::WindowEvent; match event { - WindowEvent::Resized(new_size) => { + WindowEvent::SurfaceResized(new_size) => { let logical_size = new_size.to_logical(f64::from(scale_factor)); Some(Event::Window(window::Event::Resized(Size { @@ -164,23 +171,73 @@ pub fn window_event( }))) } WindowEvent::CloseRequested => Some(Event::Window(window::Event::CloseRequested)), - WindowEvent::CursorMoved { position, .. } => { - let position = position.to_logical::(f64::from(scale_factor)); + WindowEvent::PointerMoved { + position, source, .. + } => match source { + winit::event::PointerSource::Touch { finger_id, .. } => { + let position = position.to_logical::(f64::from(scale_factor)); + + Some(Event::Touch(touch::Event::FingerMoved { + id: touch::Finger(finger_id.into_raw() as u64), + position: Point::new(position.x as f32, position.y as f32), + })) + } + _ => { + let position = position.to_logical::(f64::from(scale_factor)); - Some(Event::Mouse(mouse::Event::CursorMoved { - position: Point::new(position.x as f32, position.y as f32), - })) - } - WindowEvent::CursorEntered { .. } => Some(Event::Mouse(mouse::Event::CursorEntered)), - WindowEvent::CursorLeft { .. } => Some(Event::Mouse(mouse::Event::CursorLeft)), - WindowEvent::MouseInput { button, state, .. } => { - let button = mouse_button(button); - - Some(Event::Mouse(match state { - winit::event::ElementState::Pressed => mouse::Event::ButtonPressed(button), - winit::event::ElementState::Released => mouse::Event::ButtonReleased(button), - })) - } + Some(Event::Mouse(mouse::Event::CursorMoved { + position: Point::new(position.x as f32, position.y as f32), + })) + } + }, + WindowEvent::PointerEntered { kind, .. } => match kind { + winit::event::PointerKind::Touch(_) => None, + _ => Some(Event::Mouse(mouse::Event::CursorEntered)), + }, + WindowEvent::PointerLeft { position, kind, .. } => match kind { + winit::event::PointerKind::Touch(finger_id) => { + let id = touch::Finger(finger_id.into_raw() as u64); + + position.map(|position| { + let position = position.to_logical::(f64::from(scale_factor)); + + Event::Touch(touch::Event::FingerLost { + id, + position: Point::new(position.x as f32, position.y as f32), + }) + }) + } + _ => Some(Event::Mouse(mouse::Event::CursorLeft)), + }, + WindowEvent::PointerButton { + button, + state, + position, + .. + } => match button { + winit::event::ButtonSource::Mouse(button) => { + let button = mouse_button(button); + + Some(Event::Mouse(match state { + winit::event::ElementState::Pressed => mouse::Event::ButtonPressed(button), + winit::event::ElementState::Released => mouse::Event::ButtonReleased(button), + })) + } + winit::event::ButtonSource::Touch { finger_id, .. } => { + let id = touch::Finger(finger_id.into_raw() as u64); + let position = position.to_logical::(f64::from(scale_factor)); + let position = Point::new(position.x as f32, position.y as f32); + Some(Event::Touch(match state { + winit::event::ElementState::Pressed => { + touch::Event::FingerPressed { id, position } + } + winit::event::ElementState::Released => { + touch::Event::FingerLifted { id, position } + } + })) + } + _ => None, + }, WindowEvent::MouseWheel { delta, .. } => match delta { winit::event::MouseScrollDelta::LineDelta(delta_x, delta_y) => { Some(Event::Mouse(mouse::Event::WheelScrolled { @@ -198,40 +255,18 @@ pub fn window_event( }, })) } + _ => None, }, // Ignore keyboard presses/releases during window focus/unfocus WindowEvent::KeyboardInput { is_synthetic, .. } if is_synthetic => None, WindowEvent::KeyboardInput { event, .. } => Some(Event::Keyboard({ - let key = { - #[cfg(not(target_arch = "wasm32"))] - { - use winit::platform::modifier_supplement::KeyEventExtModifierSupplement; - event.key_without_modifiers() - } - - #[cfg(target_arch = "wasm32")] - { - // TODO: Fix inconsistent API on Wasm - event.logical_key.clone() - } - }; - - let text = { - #[cfg(not(target_arch = "wasm32"))] - { - use crate::core::SmolStr; - use winit::platform::modifier_supplement::KeyEventExtModifierSupplement; - - event.text_with_all_modifiers().map(SmolStr::new) - } + let key = event.key_without_modifiers.clone(); - #[cfg(target_arch = "wasm32")] - { - // TODO: Fix inconsistent API on Wasm - event.text - } - } - .filter(|text| !text.as_str().chars().any(is_private_use)); + let text = event + .text_with_all_modifiers + .clone() + .map(|text| crate::core::SmolStr::new(text.as_str())) + .filter(|text| !text.as_str().chars().any(is_private_use)); let winit::event::KeyEvent { state, @@ -283,20 +318,14 @@ pub fn window_event( } Ime::Commit(content) => input_method::Event::Commit(content), Ime::Disabled => input_method::Event::Closed, + Ime::DeleteSurrounding { .. } => return None, + _ => return None, })), WindowEvent::Focused(focused) => Some(Event::Window(if focused { window::Event::Focused } else { window::Event::Unfocused })), - WindowEvent::HoveredFile(path) => { - Some(Event::Window(window::Event::FileHovered(path.clone()))) - } - WindowEvent::DroppedFile(path) => { - Some(Event::Window(window::Event::FileDropped(path.clone()))) - } - WindowEvent::HoveredFileCancelled => Some(Event::Window(window::Event::FilesHoveredLeft)), - WindowEvent::Touch(touch) => Some(Event::Touch(touch_event(touch, scale_factor))), WindowEvent::Moved(position) => { let winit::dpi::LogicalPosition { x, y } = position.to_logical(f64::from(scale_factor)); @@ -338,10 +367,15 @@ pub fn position( } window::Position::SpecificWith(to_position) => { if let Some(monitor) = monitor { - let start = monitor.position(); + let start = monitor + .position() + .unwrap_or(winit::dpi::PhysicalPosition::new(0, 0)); - let resolution: winit::dpi::LogicalSize = - monitor.size().to_logical(monitor.scale_factor()); + let resolution: winit::dpi::LogicalSize = monitor + .current_video_mode() + .map(|mode| mode.size()) + .unwrap_or(winit::dpi::PhysicalSize::new(1, 1)) + .to_logical(monitor.scale_factor()); let position = to_position(size, Size::new(resolution.width, resolution.height)); @@ -363,10 +397,15 @@ pub fn position( } window::Position::Centered => { if let Some(monitor) = monitor { - let start = monitor.position(); + let start = monitor + .position() + .unwrap_or(winit::dpi::PhysicalPosition::new(0, 0)); - let resolution: winit::dpi::LogicalSize = - monitor.size().to_logical(monitor.scale_factor()); + let resolution: winit::dpi::LogicalSize = monitor + .current_video_mode() + .map(|mode| mode.size()) + .unwrap_or(winit::dpi::PhysicalSize::new(1, 1)) + .to_logical(monitor.scale_factor()); let centered: winit::dpi::PhysicalPosition = winit::dpi::LogicalPosition { x: (resolution.width - f64::from(size.width)) / 2.0, @@ -393,10 +432,10 @@ pub fn position( pub fn fullscreen( monitor: Option, mode: window::Mode, -) -> Option { +) -> Option { match mode { window::Mode::Windowed | window::Mode::Hidden => None, - window::Mode::Fullscreen => Some(winit::window::Fullscreen::Borderless(monitor)), + window::Mode::Fullscreen => Some(winit::monitor::Fullscreen::Borderless(monitor)), } } @@ -411,7 +450,7 @@ pub fn visible(mode: window::Mode) -> bool { /// Converts a [`winit`] fullscreen mode into a [`window::Mode`]. /// /// [`winit`]: https://github.com/rust-windowing/winit -pub fn mode(mode: Option) -> window::Mode { +pub fn mode(mode: Option) -> window::Mode { match mode { None => window::Mode::Windowed, Some(_) => window::Mode::Fullscreen, @@ -442,38 +481,38 @@ pub fn window_theme(mode: theme::Mode) -> Option { /// Converts a [`mouse::Interaction`] into a [`winit`] cursor icon. /// /// [`winit`]: https://github.com/rust-windowing/winit -pub fn mouse_interaction(interaction: mouse::Interaction) -> Option { +pub fn mouse_interaction(interaction: mouse::Interaction) -> Option { use mouse::Interaction; let icon = match interaction { Interaction::Hidden => { return None; } - Interaction::None | Interaction::Idle => winit::window::CursorIcon::Default, - Interaction::ContextMenu => winit::window::CursorIcon::ContextMenu, - Interaction::Help => winit::window::CursorIcon::Help, - Interaction::Pointer => winit::window::CursorIcon::Pointer, - Interaction::Progress => winit::window::CursorIcon::Progress, - Interaction::Wait => winit::window::CursorIcon::Wait, - Interaction::Cell => winit::window::CursorIcon::Cell, - Interaction::Crosshair => winit::window::CursorIcon::Crosshair, - Interaction::Text => winit::window::CursorIcon::Text, - Interaction::Alias => winit::window::CursorIcon::Alias, - Interaction::Copy => winit::window::CursorIcon::Copy, - Interaction::Move => winit::window::CursorIcon::Move, - Interaction::NoDrop => winit::window::CursorIcon::NoDrop, - Interaction::NotAllowed => winit::window::CursorIcon::NotAllowed, - Interaction::Grab => winit::window::CursorIcon::Grab, - Interaction::Grabbing => winit::window::CursorIcon::Grabbing, - Interaction::ResizingHorizontally => winit::window::CursorIcon::EwResize, - Interaction::ResizingVertically => winit::window::CursorIcon::NsResize, - Interaction::ResizingDiagonallyUp => winit::window::CursorIcon::NeswResize, - Interaction::ResizingDiagonallyDown => winit::window::CursorIcon::NwseResize, - Interaction::ResizingColumn => winit::window::CursorIcon::ColResize, - Interaction::ResizingRow => winit::window::CursorIcon::RowResize, - Interaction::AllScroll => winit::window::CursorIcon::AllScroll, - Interaction::ZoomIn => winit::window::CursorIcon::ZoomIn, - Interaction::ZoomOut => winit::window::CursorIcon::ZoomOut, + Interaction::None | Interaction::Idle => winit::cursor::CursorIcon::Default, + Interaction::ContextMenu => winit::cursor::CursorIcon::ContextMenu, + Interaction::Help => winit::cursor::CursorIcon::Help, + Interaction::Pointer => winit::cursor::CursorIcon::Pointer, + Interaction::Progress => winit::cursor::CursorIcon::Progress, + Interaction::Wait => winit::cursor::CursorIcon::Wait, + Interaction::Cell => winit::cursor::CursorIcon::Cell, + Interaction::Crosshair => winit::cursor::CursorIcon::Crosshair, + Interaction::Text => winit::cursor::CursorIcon::Text, + Interaction::Alias => winit::cursor::CursorIcon::Alias, + Interaction::Copy => winit::cursor::CursorIcon::Copy, + Interaction::Move => winit::cursor::CursorIcon::Move, + Interaction::NoDrop => winit::cursor::CursorIcon::NoDrop, + Interaction::NotAllowed => winit::cursor::CursorIcon::NotAllowed, + Interaction::Grab => winit::cursor::CursorIcon::Grab, + Interaction::Grabbing => winit::cursor::CursorIcon::Grabbing, + Interaction::ResizingHorizontally => winit::cursor::CursorIcon::EwResize, + Interaction::ResizingVertically => winit::cursor::CursorIcon::NsResize, + Interaction::ResizingDiagonallyUp => winit::cursor::CursorIcon::NeswResize, + Interaction::ResizingDiagonallyDown => winit::cursor::CursorIcon::NwseResize, + Interaction::ResizingColumn => winit::cursor::CursorIcon::ColResize, + Interaction::ResizingRow => winit::cursor::CursorIcon::RowResize, + Interaction::AllScroll => winit::cursor::CursorIcon::AllScroll, + Interaction::ZoomIn => winit::cursor::CursorIcon::ZoomIn, + Interaction::ZoomOut => winit::cursor::CursorIcon::ZoomOut, }; Some(icon) @@ -490,7 +529,33 @@ pub fn mouse_button(mouse_button: winit::event::MouseButton) -> mouse::Button { winit::event::MouseButton::Middle => mouse::Button::Middle, winit::event::MouseButton::Back => mouse::Button::Back, winit::event::MouseButton::Forward => mouse::Button::Forward, - winit::event::MouseButton::Other(other) => mouse::Button::Other(other), + winit::event::MouseButton::Button6 => mouse::Button::Other(6), + winit::event::MouseButton::Button7 => mouse::Button::Other(7), + winit::event::MouseButton::Button8 => mouse::Button::Other(8), + winit::event::MouseButton::Button9 => mouse::Button::Other(9), + winit::event::MouseButton::Button10 => mouse::Button::Other(10), + winit::event::MouseButton::Button11 => mouse::Button::Other(11), + winit::event::MouseButton::Button12 => mouse::Button::Other(12), + winit::event::MouseButton::Button13 => mouse::Button::Other(13), + winit::event::MouseButton::Button14 => mouse::Button::Other(14), + winit::event::MouseButton::Button15 => mouse::Button::Other(15), + winit::event::MouseButton::Button16 => mouse::Button::Other(16), + winit::event::MouseButton::Button17 => mouse::Button::Other(17), + winit::event::MouseButton::Button18 => mouse::Button::Other(18), + winit::event::MouseButton::Button19 => mouse::Button::Other(19), + winit::event::MouseButton::Button20 => mouse::Button::Other(20), + winit::event::MouseButton::Button21 => mouse::Button::Other(21), + winit::event::MouseButton::Button22 => mouse::Button::Other(22), + winit::event::MouseButton::Button23 => mouse::Button::Other(23), + winit::event::MouseButton::Button24 => mouse::Button::Other(24), + winit::event::MouseButton::Button25 => mouse::Button::Other(25), + winit::event::MouseButton::Button26 => mouse::Button::Other(26), + winit::event::MouseButton::Button27 => mouse::Button::Other(27), + winit::event::MouseButton::Button28 => mouse::Button::Other(28), + winit::event::MouseButton::Button29 => mouse::Button::Other(29), + winit::event::MouseButton::Button30 => mouse::Button::Other(30), + winit::event::MouseButton::Button31 => mouse::Button::Other(31), + winit::event::MouseButton::Button32 => mouse::Button::Other(32), } } @@ -505,7 +570,7 @@ pub fn modifiers(modifiers: winit::keyboard::ModifiersState) -> keyboard::Modifi result.set(keyboard::Modifiers::SHIFT, modifiers.shift_key()); result.set(keyboard::Modifiers::CTRL, modifiers.control_key()); result.set(keyboard::Modifiers::ALT, modifiers.alt_key()); - result.set(keyboard::Modifiers::LOGO, modifiers.super_key()); + result.set(keyboard::Modifiers::LOGO, modifiers.meta_key()); result } @@ -517,36 +582,20 @@ pub fn cursor_position(position: winit::dpi::PhysicalPosition, scale_factor Point::new(logical_position.x, logical_position.y) } -/// Converts a `Touch` from [`winit`] to an [`iced`] touch event. -/// -/// [`winit`]: https://github.com/rust-windowing/winit -/// [`iced`]: https://github.com/iced-rs/iced/tree/0.12 -pub fn touch_event(touch: winit::event::Touch, scale_factor: f32) -> touch::Event { - let id = touch::Finger(touch.id); - let position = { - let location = touch.location.to_logical::(f64::from(scale_factor)); - - Point::new(location.x as f32, location.y as f32) - }; - - match touch.phase { - winit::event::TouchPhase::Started => touch::Event::FingerPressed { id, position }, - winit::event::TouchPhase::Moved => touch::Event::FingerMoved { id, position }, - winit::event::TouchPhase::Ended => touch::Event::FingerLifted { id, position }, - winit::event::TouchPhase::Cancelled => touch::Event::FingerLost { id, position }, - } -} - /// Converts a `Key` from [`winit`] to an [`iced`] key. /// /// [`winit`]: https://github.com/rust-windowing/winit /// [`iced`]: https://github.com/iced-rs/iced/tree/0.12 +#[allow(deprecated)] pub fn key(key: winit::keyboard::Key) -> keyboard::Key { use keyboard::key::Named; use winit::keyboard::NamedKey; match key { - winit::keyboard::Key::Character(c) => keyboard::Key::Character(c), + winit::keyboard::Key::Character(c) if c == " " => keyboard::Key::Named(Named::Space), + winit::keyboard::Key::Character(c) => { + keyboard::Key::Character(crate::core::SmolStr::new(c.as_str())) + } winit::keyboard::Key::Named(named_key) => keyboard::Key::Named(match named_key { NamedKey::Alt => Named::Alt, NamedKey::AltGraph => Named::AltGraph, @@ -564,7 +613,6 @@ pub fn key(key: winit::keyboard::Key) -> keyboard::Key { NamedKey::Super => Named::Super, NamedKey::Enter => Named::Enter, NamedKey::Tab => Named::Tab, - NamedKey::Space => Named::Space, NamedKey::ArrowDown => Named::ArrowDown, NamedKey::ArrowLeft => Named::ArrowLeft, NamedKey::ArrowRight => Named::ArrowRight, @@ -881,6 +929,7 @@ pub fn physical_key(physical_key: winit::keyboard::PhysicalKey) -> keyboard::key /// /// [`winit`]: https://github.com/rust-windowing/winit /// [`iced`]: https://github.com/iced-rs/iced/tree/0.12 +#[allow(deprecated)] pub fn key_code(key_code: winit::keyboard::KeyCode) -> Option { use winit::keyboard::KeyCode; @@ -943,8 +992,8 @@ pub fn key_code(key_code: winit::keyboard::KeyCode) -> Option keyboard::key::Code::ControlLeft, KeyCode::ControlRight => keyboard::key::Code::ControlRight, KeyCode::Enter => keyboard::key::Code::Enter, - KeyCode::SuperLeft => keyboard::key::Code::SuperLeft, - KeyCode::SuperRight => keyboard::key::Code::SuperRight, + KeyCode::MetaLeft => keyboard::key::Code::SuperLeft, + KeyCode::MetaRight => keyboard::key::Code::SuperRight, KeyCode::ShiftLeft => keyboard::key::Code::ShiftLeft, KeyCode::ShiftRight => keyboard::key::Code::ShiftRight, KeyCode::Space => keyboard::key::Code::Space, @@ -1027,7 +1076,6 @@ pub fn key_code(key_code: winit::keyboard::KeyCode) -> Option keyboard::key::Code::AudioVolumeMute, KeyCode::AudioVolumeUp => keyboard::key::Code::AudioVolumeUp, KeyCode::WakeUp => keyboard::key::Code::WakeUp, - KeyCode::Meta => keyboard::key::Code::Meta, KeyCode::Hyper => keyboard::key::Code::Hyper, KeyCode::Turbo => keyboard::key::Code::Turbo, KeyCode::Abort => keyboard::key::Code::Abort, @@ -1098,6 +1146,7 @@ pub fn native_key_code( NativeKeyCode::MacOS(code) => keyboard::key::NativeCode::MacOS(code), NativeKeyCode::Windows(code) => keyboard::key::NativeCode::Windows(code), NativeKeyCode::Xkb(code) => keyboard::key::NativeCode::Xkb(code), + _ => keyboard::key::NativeCode::Unidentified, } } @@ -1128,10 +1177,12 @@ pub fn resize_direction(resize_direction: window::Direction) -> winit::window::R /// Converts some [`window::Icon`] into its `winit` counterpart. /// /// Returns `None` if there is an error during the conversion. -pub fn icon(icon: window::Icon) -> Option { +pub fn icon(icon: window::Icon) -> Option { let (pixels, size) = icon.into_raw(); - winit::window::Icon::from_rgba(pixels, size.width, size.height).ok() + winit::icon::RgbaIcon::new(pixels, size.width, size.height) + .map(Into::into) + .ok() } /// Converts some [`input_method::Purpose`] into its `winit` counterpart. diff --git a/winit/src/lib.rs b/winit/src/lib.rs index f7d2ca1b81..688a599ce1 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -78,15 +78,13 @@ where let settings = program.settings(); let window_settings = program.window(); - let event_loop = EventLoop::with_user_event() - .build() - .expect("Create event loop"); + let event_loop = EventLoop::new().expect("Create event loop"); let backend_settings = backend::Settings::from(&settings); let renderer_settings = renderer::Settings::from(&settings); let display_handle = event_loop.owned_display_handle(); - let (proxy, worker) = Proxy::new(event_loop.create_proxy()); + let (proxy, worker, outbox) = Proxy::new(event_loop.create_proxy()); #[cfg(feature = "debug")] { @@ -151,8 +149,10 @@ where id: Option, sender: mpsc::UnboundedSender>>, receiver: mpsc::UnboundedReceiver, + outbox: mpsc::UnboundedReceiver>, error: Option, system_theme: Option>, + drag: Option, #[cfg(target_arch = "wasm32")] canvas: Option, @@ -164,8 +164,10 @@ where id: settings.id, sender: event_sender, receiver: control_receiver, + outbox, error: None, system_theme: Some(system_theme_sender), + drag: None, #[cfg(target_arch = "wasm32")] canvas: None, @@ -173,11 +175,11 @@ where boot_span.finish(); - impl winit::application::ApplicationHandler> for Runner + impl winit::application::ApplicationHandler for Runner where F: Future, { - fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { + fn resumed(&mut self, event_loop: &dyn winit::event_loop::ActiveEventLoop) { if let Some(sender) = self.system_theme.take() { let _ = sender.send( event_loop @@ -188,33 +190,45 @@ where } } + fn can_create_surfaces(&mut self, _event_loop: &dyn winit::event_loop::ActiveEventLoop) {} + fn new_events( &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, + event_loop: &dyn winit::event_loop::ActiveEventLoop, cause: winit::event::StartCause, ) { self.process_event( event_loop, - Event::EventLoopAwakened(winit::event::Event::NewEvents(cause)), + Event::EventLoopAwakened(EventLoopEvent::NewEvents(cause)), ); } fn window_event( &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, + event_loop: &dyn winit::event_loop::ActiveEventLoop, window_id: winit::window::WindowId, event: winit::event::WindowEvent, ) { #[cfg(target_os = "windows")] let is_move_or_resize = matches!( event, - winit::event::WindowEvent::Resized(_) | winit::event::WindowEvent::Moved(_) + winit::event::WindowEvent::SurfaceResized(_) | winit::event::WindowEvent::Moved(_) ); - self.process_event( - event_loop, - Event::EventLoopAwakened(winit::event::Event::WindowEvent { window_id, event }), - ); + match event { + event @ (winit::event::WindowEvent::DragEntered { .. } + | winit::event::WindowEvent::DragDropped { .. } + | winit::event::WindowEvent::DragLeft { .. } + | winit::event::WindowEvent::DataTransferReceived { .. }) => { + self.handle_drag_event(event_loop, window_id, event); + } + event => { + self.process_event( + event_loop, + Event::EventLoopAwakened(EventLoopEvent::WindowEvent { window_id, event }), + ); + } + } // TODO: Remove when unnecessary // On Windows, we emulate an `AboutToWait` event after every `Resized` event @@ -225,36 +239,25 @@ where if is_move_or_resize { self.process_event( event_loop, - Event::EventLoopAwakened(winit::event::Event::AboutToWait), + Event::EventLoopAwakened(EventLoopEvent::AboutToWait), ); } } } - fn user_event( - &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, - action: Action, - ) { - self.process_event( - event_loop, - Event::EventLoopAwakened(winit::event::Event::UserEvent(action)), - ); - } - - fn received_url(&mut self, event_loop: &winit::event_loop::ActiveEventLoop, url: String) { - self.process_event( - event_loop, - Event::EventLoopAwakened(winit::event::Event::PlatformSpecific( - winit::event::PlatformSpecific::MacOS(winit::event::MacOS::ReceivedUrl(url)), - )), - ); + fn proxy_wake_up(&mut self, event_loop: &dyn winit::event_loop::ActiveEventLoop) { + while let Ok(action) = self.outbox.try_recv() { + self.process_event( + event_loop, + Event::EventLoopAwakened(EventLoopEvent::UserEvent(action)), + ); + } } - fn about_to_wait(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { + fn about_to_wait(&mut self, event_loop: &dyn winit::event_loop::ActiveEventLoop) { self.process_event( event_loop, - Event::EventLoopAwakened(winit::event::Event::AboutToWait), + Event::EventLoopAwakened(EventLoopEvent::AboutToWait), ); } } @@ -265,7 +268,7 @@ where { fn process_event( &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, + event_loop: &dyn winit::event_loop::ActiveEventLoop, event: Event>, ) { if event_loop.exiting() { @@ -321,8 +324,13 @@ where #[cfg(target_arch = "wasm32")] let window_attributes = { - use winit::platform::web::WindowAttributesExtWebSys; - window_attributes.with_canvas(self.canvas.take()) + use winit::platform::web::WindowAttributesWeb; + let attributes = winit::window::WindowAttributes::default() + .with_platform_attributes(Box::new( + WindowAttributesWeb::default() + .with_canvas(self.canvas.take()), + )); + attributes }; log::info!( @@ -349,7 +357,7 @@ where #[cfg(target_arch = "wasm32")] { - use winit::platform::web::WindowExtWebSys; + use winit::platform::web::WindowExtWeb; let canvas = window.canvas().expect("Get window canvas"); @@ -386,7 +394,7 @@ where event_loop, Event::WindowCreated { id, - window: Arc::new(window), + window: Arc::from(window), exit_on_close_request, make_visible: visible, on_open, @@ -421,20 +429,116 @@ where }; } } + + fn handle_drag_event( + &mut self, + event_loop: &dyn winit::event_loop::ActiveEventLoop, + window_id: winit::window::WindowId, + event: winit::event::WindowEvent, + ) { + use winit::data_transfer::TypeHint; + use winit::event_loop::DndAction; + + let mut emit_file_event = |event: window::Event| { + self.sender + .start_send(Event::EventLoopAwakened(EventLoopEvent::FileEvent { + window_id, + event: crate::core::Event::Window(event), + })) + .expect("Send event"); + }; + + match event { + winit::event::WindowEvent::DragEntered { id, .. } => { + let _ = event_loop.set_valid_dnd_actions(id, &[DndAction::Copy]); + + self.drag = Some(DragSession { + window_id, + id, + path: None, + dropped: false, + }); + + let _ = event_loop.fetch_data_transfer(id, &TypeHint::UriList); + } + winit::event::WindowEvent::DataTransferReceived { id, value, .. } => { + let Some(drag) = &mut self.drag else { + return; + }; + + if drag.id != id || drag.path.is_some() || drag.window_id != window_id { + return; + } + + let paths = match value.try_as_file_paths() { + Ok(paths) => paths, + Err(error) if error.kind() == std::io::ErrorKind::WouldBlock => { + let _ = event_loop.fetch_data_transfer(id, &TypeHint::UriList); + + return; + } + Err(_) => return, + }; + + let Some(path) = paths.into_iter().next() else { + return; + }; + + if drag.dropped { + self.drag = None; + + emit_file_event(window::Event::FileDropped(path)); + } else { + drag.path = Some(path.clone()); + + emit_file_event(window::Event::FileHovered(path)); + } + } + winit::event::WindowEvent::DragDropped { id, .. } => { + let Some(drag) = &mut self.drag else { + return; + }; + + if drag.id != id || drag.window_id != window_id { + return; + } + + if let Some(path) = drag.path.take() { + self.drag = None; + + emit_file_event(window::Event::FileDropped(path)); + } else { + drag.dropped = true; + + let _ = event_loop.fetch_data_transfer(id, &TypeHint::UriList); + } + } + winit::event::WindowEvent::DragLeft { id, .. } => { + if self + .drag + .take_if(|drag| drag.id == id && drag.window_id == window_id) + .is_some() + { + emit_file_event(window::Event::FilesHoveredLeft); + } + } + _ => {} + } + } } #[cfg(not(target_arch = "wasm32"))] { let mut runner = runner; - let _ = event_loop.run_app(&mut runner); + let error = runner.error.take(); + let _ = event_loop.run_app(runner); - runner.error.map(Err).unwrap_or(Ok(())) + error.map(Err).unwrap_or(Ok(())) } #[cfg(target_arch = "wasm32")] { - use winit::platform::web::EventLoopExtWebSys; - let _ = event_loop.spawn_app(runner); + let _ = event_loop.run_app(runner).expect("Run application"); Ok(()) } @@ -444,15 +548,38 @@ where enum Event { WindowCreated { id: window::Id, - window: Arc, + window: Arc, exit_on_close_request: bool, make_visible: bool, on_open: oneshot::Sender, }, - EventLoopAwakened(winit::event::Event), + EventLoopAwakened(EventLoopEvent), Exit, } +#[derive(Debug)] +enum EventLoopEvent { + NewEvents(winit::event::StartCause), + UserEvent(Message), + WindowEvent { + window_id: winit::window::WindowId, + event: winit::event::WindowEvent, + }, + FileEvent { + window_id: winit::window::WindowId, + event: crate::core::Event, + }, + AboutToWait, +} + +#[derive(Debug)] +struct DragSession { + window_id: winit::window::WindowId, + id: winit::data_transfer::DataTransferId, + path: Option, + dropped: bool, +} + #[derive(Debug)] enum Control { ChangeFlow(winit::event_loop::ControlFlow), @@ -686,12 +813,12 @@ async fn run_instance

( } Event::EventLoopAwakened(event) => { match event { - event::Event::NewEvents(event::StartCause::Init) => { + EventLoopEvent::NewEvents(event::StartCause::Init) => { for (_id, window) in window_manager.iter_mut() { window.raw.request_redraw(); } } - event::Event::NewEvents(event::StartCause::ResumeTimeReached { .. }) => { + EventLoopEvent::NewEvents(event::StartCause::ResumeTimeReached { .. }) => { let now = Instant::now(); for (_id, window) in window_manager.iter_mut() { @@ -711,16 +838,7 @@ async fn run_instance

( control_sender.start_send(Control::ChangeFlow(ControlFlow::Wait)); } } - event::Event::PlatformSpecific(event::PlatformSpecific::MacOS( - event::MacOS::ReceivedUrl(url), - )) => { - runtime.broadcast(subscription::Event::PlatformSpecific( - subscription::PlatformSpecific::MacOS( - subscription::MacOS::ReceivedUrl(url), - ), - )); - } - event::Event::UserEvent(action) => { + EventLoopEvent::UserEvent(action) => { run_action( action, &program, @@ -740,7 +858,7 @@ async fn run_instance

( ); actions += 1; } - event::Event::WindowEvent { + EventLoopEvent::WindowEvent { window_id: id, event: event::WindowEvent::RedrawRequested, .. @@ -991,7 +1109,7 @@ async fn run_instance

( }, } } - event::Event::WindowEvent { + EventLoopEvent::WindowEvent { event: window_event, window_id, } => { @@ -1012,7 +1130,7 @@ async fn run_instance

( }; match window_event { - winit::event::WindowEvent::Resized(_) + winit::event::WindowEvent::SurfaceResized(_) | winit::event::WindowEvent::Occluded(false) => { window.raw.request_redraw(); } @@ -1050,7 +1168,7 @@ async fn run_instance

( &mut renderer_settings, ); } else { - window.state.update(&program, &window.raw, &window_event); + window.state.update(&program, &*window.raw, &window_event); if let Some(event) = conversion::window_event( window_event, @@ -1061,7 +1179,12 @@ async fn run_instance

( } } } - event::Event::AboutToWait => { + EventLoopEvent::FileEvent { window_id, event } => { + if let Some((id, _)) = window_manager.get_mut_alias(window_id) { + events.push((id, event)); + } + } + EventLoopEvent::AboutToWait => { if actions > 0 { proxy.free_slots(actions); actions = 0; @@ -1379,46 +1502,52 @@ fn run_action<'a, P, C>( } window::Action::Resize(id, size) => { if let Some(window) = window_manager.get_mut(id) { - let _ = window.raw.request_inner_size( + let _ = window.raw.request_surface_size( winit::dpi::LogicalSize { width: size.width, height: size.height, } - .to_physical::(f64::from(window.state.scale_factor())), + .to_physical::(f64::from(window.state.scale_factor())) + .into(), ); } } window::Action::SetMinSize(id, size) => { if let Some(window) = window_manager.get_mut(id) { - window.raw.set_min_inner_size(size.map(|size| { + window.raw.set_min_surface_size(size.map(|size| { winit::dpi::LogicalSize { width: size.width, height: size.height, } .to_physical::(f64::from(window.state.scale_factor())) + .into() })); } } window::Action::SetMaxSize(id, size) => { if let Some(window) = window_manager.get_mut(id) { - window.raw.set_max_inner_size(size.map(|size| { + window.raw.set_max_surface_size(size.map(|size| { winit::dpi::LogicalSize { width: size.width, height: size.height, } .to_physical::(f64::from(window.state.scale_factor())) + .into() })); } } window::Action::SetResizeIncrements(id, increments) => { if let Some(window) = window_manager.get_mut(id) { - window.raw.set_resize_increments(increments.map(|size| { - winit::dpi::LogicalSize { - width: size.width, - height: size.height, - } - .to_physical::(f64::from(window.state.scale_factor())) - })); + window + .raw + .set_surface_resize_increments(increments.map(|size| { + winit::dpi::LogicalSize { + width: size.width, + height: size.height, + } + .to_physical::(f64::from(window.state.scale_factor())) + .into() + })); } } window::Action::SetResizable(id, resizable) => { @@ -1476,10 +1605,13 @@ fn run_action<'a, P, C>( } window::Action::Move(id, position) => { if let Some(window) = window_manager.get_mut(id) { - window.raw.set_outer_position(winit::dpi::LogicalPosition { - x: position.x, - y: position.y, - }); + window.raw.set_outer_position( + winit::dpi::LogicalPosition { + x: position.x, + y: position.y, + } + .into(), + ); } } window::Action::SetMode(id, mode) => { @@ -1537,15 +1669,18 @@ fn run_action<'a, P, C>( if let Some(window) = window_manager.get_mut(id) && let mouse::Cursor::Available(point) = window.state.cursor() { - window.raw.show_window_menu(winit::dpi::LogicalPosition { - x: point.x, - y: point.y, - }); + window.raw.show_window_menu( + winit::dpi::LogicalPosition { + x: point.x, + y: point.y, + } + .into(), + ); } } window::Action::GetRawId(id, channel) => { if let Some(window) = window_manager.get_mut(id) { - let _ = channel.send(window.raw.id().into()); + let _ = channel.send(window.raw.id().into_raw() as u64); } } window::Action::Run(id, f) => { @@ -1582,11 +1717,13 @@ fn run_action<'a, P, C>( } window::Action::GetMonitorSize(id, channel) => { if let Some(window) = window_manager.get(id) { - let size = window.raw.current_monitor().map(|monitor| { + let size = window.raw.current_monitor().and_then(|monitor| { let scale = window.state.scale_factor(); - let size = monitor.size().to_logical(f64::from(scale)); + let size = monitor + .current_video_mode() + .map(|mode| mode.size().to_logical(f64::from(scale))); - Size::new(size.width, size.height) + size.map(|size| Size::new(size.width, size.height)) }); let _ = channel.send(size); @@ -1647,7 +1784,7 @@ fn run_action<'a, P, C>( for (_id, window) in window_manager.iter_mut() { window.state.update( program, - &window.raw, + &*window.raw, &winit::event::WindowEvent::ThemeChanged(theme), ); } @@ -1815,7 +1952,7 @@ where for (id, window) in window_manager.iter_mut() { let old_size = window.state.logical_size(); - window.state.synchronize(program, id, &window.raw); + window.state.synchronize(program, id, &*window.raw); let new_size = window.state.logical_size(); @@ -1870,7 +2007,7 @@ pub fn user_force_quit( .. }, .. - } if c == "q" && _modifiers.super_key() => true, + } if c == "q" && _modifiers.meta_key() => true, _ => false, } } diff --git a/winit/src/proxy.rs b/winit/src/proxy.rs index 1aa3100aae..63cc7133cd 100644 --- a/winit/src/proxy.rs +++ b/winit/src/proxy.rs @@ -12,9 +12,10 @@ use std::pin::Pin; /// An event loop proxy with backpressure that implements `Sink`. #[derive(Debug)] pub struct Proxy { - raw: winit::event_loop::EventLoopProxy>, + raw: winit::event_loop::EventLoopProxy, sender: mpsc::Sender>, notifier: mpsc::Sender, + outbox: mpsc::UnboundedSender>, } impl Clone for Proxy { @@ -23,6 +24,7 @@ impl Clone for Proxy { raw: self.raw.clone(), sender: self.sender.clone(), notifier: self.notifier.clone(), + outbox: self.outbox.clone(), } } } @@ -32,10 +34,16 @@ impl Proxy { /// Creates a new [`Proxy`] from an `EventLoopProxy`. pub fn new( - raw: winit::event_loop::EventLoopProxy>, - ) -> (Self, impl Future) { + raw: winit::event_loop::EventLoopProxy, + ) -> ( + Self, + impl Future, + mpsc::UnboundedReceiver>, + ) { let (notifier, mut processed) = mpsc::channel(Self::MAX_SIZE); let (sender, mut receiver) = mpsc::channel(Self::MAX_SIZE); + let (outbox, outbox_receiver) = mpsc::unbounded(); + let worker_outbox = outbox.clone(); let proxy = raw.clone(); let worker = async move { @@ -45,7 +53,8 @@ impl Proxy { if count < Self::MAX_SIZE { select! { message = receiver.select_next_some() => { - let _ = proxy.send_event(message); + let _ = worker_outbox.unbounded_send(message); + proxy.wake_up(); count += 1; } amount = processed.select_next_some() => { @@ -69,8 +78,10 @@ impl Proxy { raw, sender, notifier, + outbox, }, worker, + outbox_receiver, ) } @@ -92,7 +103,8 @@ impl Proxy { /// Note: This skips the backpressure mechanism with an unbounded /// channel. Use sparingly! pub fn send_action(&self, action: Action) { - let _ = self.raw.send_event(action); + let _ = self.outbox.unbounded_send(action); + self.raw.wake_up(); } /// Frees an amount of slots for additional messages to be queued in diff --git a/winit/src/window.rs b/winit/src/window.rs index 5f9ef0e611..54a29c2684 100644 --- a/winit/src/window.rs +++ b/winit/src/window.rs @@ -51,7 +51,7 @@ where pub fn insert( &mut self, id: Id, - window: Arc, + window: Arc, program: &program::Instance

, compositor: &mut C, proxy: Proxy, @@ -59,7 +59,7 @@ where exit_on_close_request: bool, system_theme: theme::Mode, ) -> &mut Window { - let state = State::new(program, id, &window, system_theme); + let state = State::new(program, id, &*window, system_theme); let surface_size = state.physical_size(); let surface_version = state.surface_version(); let surface = @@ -175,7 +175,7 @@ where C: Compositor, P::Theme: theme::Base, { - pub raw: Arc, + pub raw: Arc, pub waker: shell::Waker, pub state: State

, pub exit_on_close_request: bool, @@ -255,7 +255,7 @@ where pub fn update_mouse(&mut self, interaction: mouse::Interaction) { if interaction != self.mouse_interaction { if let Some(icon) = conversion::mouse_interaction(interaction) { - self.raw.set_cursor(icon); + self.raw.set_cursor(winit::cursor::Cursor::Icon(icon)); if self.mouse_interaction == mouse::Interaction::Hidden { self.raw.set_cursor_visible(true); @@ -280,25 +280,31 @@ where } fn enable_ime(&mut self, cursor: Rectangle, purpose: input_method::Purpose) { - if self.ime_state.is_none() { - self.raw.set_ime_allowed(true); - } + #[allow(deprecated)] + { + if self.ime_state.is_none() { + self.raw.set_ime_allowed(true); + } - if self.ime_state != Some((cursor, purpose)) { - self.raw.set_ime_cursor_area( - LogicalPosition::new(cursor.x, cursor.y), - LogicalSize::new(cursor.width, cursor.height), - ); - self.raw.set_ime_purpose(conversion::ime_purpose(purpose)); + if self.ime_state != Some((cursor, purpose)) { + self.raw.set_ime_cursor_area( + LogicalPosition::new(cursor.x, cursor.y).into(), + LogicalSize::new(cursor.width, cursor.height).into(), + ); + self.raw.set_ime_purpose(conversion::ime_purpose(purpose)); - self.ime_state = Some((cursor, purpose)); + self.ime_state = Some((cursor, purpose)); + } } } fn disable_ime(&mut self) { - if self.ime_state.is_some() { - self.raw.set_ime_allowed(false); - self.ime_state = None; + #[allow(deprecated)] + { + if self.ime_state.is_some() { + self.raw.set_ime_allowed(false); + self.ime_state = None; + } } self.preedit = None; diff --git a/winit/src/window/state.rs b/winit/src/window/state.rs index 40590c2687..a7175139f9 100644 --- a/winit/src/window/state.rs +++ b/winit/src/window/state.rs @@ -5,7 +5,7 @@ use crate::core::{mouse, theme, window}; use crate::graphics::Viewport; use crate::program::{self, Program}; -use winit::event::{Touch, WindowEvent}; +use winit::event::{PointerKind, WindowEvent}; use winit::window::Window; use std::fmt::{Debug, Formatter}; @@ -48,7 +48,7 @@ where pub fn new( program: &program::Instance

, window_id: window::Id, - window: &Window, + window: &dyn Window, system_theme: theme::Mode, ) -> Self { let title = program.title(window_id); @@ -59,7 +59,7 @@ where let style = program.style(theme.as_ref().unwrap_or(&default_theme)); let viewport = { - let physical_size = window.inner_size(); + let physical_size = window.surface_size(); Viewport::with_physical_size( Size::new(physical_size.width, physical_size.height), @@ -136,9 +136,14 @@ where self.style.text_color } - pub fn update(&mut self, program: &program::Instance

, window: &Window, event: &WindowEvent) { + pub fn update( + &mut self, + program: &program::Instance

, + window: &dyn Window, + event: &WindowEvent, + ) { match event { - WindowEvent::Resized(new_size) => { + WindowEvent::SurfaceResized(new_size) => { let size = Size::new(new_size.width, new_size.height); self.viewport = Viewport::with_physical_size( @@ -165,13 +170,13 @@ where ); self.surface_version += 1; } - WindowEvent::CursorMoved { position, .. } - | WindowEvent::Touch(Touch { - location: position, .. - }) => { + WindowEvent::PointerMoved { position, .. } => { self.cursor_position = Some(*position); } - WindowEvent::CursorLeft { .. } => { + WindowEvent::PointerLeft { + kind: PointerKind::Mouse | PointerKind::TabletTool(_) | PointerKind::Unknown, + .. + } => { self.cursor_position = None; } WindowEvent::ModifiersChanged(new_modifiers) => { @@ -194,7 +199,7 @@ where &mut self, program: &program::Instance

, window_id: window::Id, - window: &Window, + window: &dyn Window, ) { // Update window title let new_title = program.title(window_id); From 31f4a2a3e8277ca875a6b7b3f6fc10f7dafa119c Mon Sep 17 00:00:00 2001 From: 443eb9#C <443eb9@gmail.com> Date: Mon, 10 Aug 2026 18:02:06 +0800 Subject: [PATCH 2/8] don't send the first path only. previous iced sends all paths --- winit/src/lib.rs | 59 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/winit/src/lib.rs b/winit/src/lib.rs index 688a599ce1..1fd1ada2df 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -439,15 +439,6 @@ where use winit::data_transfer::TypeHint; use winit::event_loop::DndAction; - let mut emit_file_event = |event: window::Event| { - self.sender - .start_send(Event::EventLoopAwakened(EventLoopEvent::FileEvent { - window_id, - event: crate::core::Event::Window(event), - })) - .expect("Send event"); - }; - match event { winit::event::WindowEvent::DragEntered { id, .. } => { let _ = event_loop.set_valid_dnd_actions(id, &[DndAction::Copy]); @@ -480,18 +471,32 @@ where Err(_) => return, }; - let Some(path) = paths.into_iter().next() else { - return; - }; - if drag.dropped { self.drag = None; - emit_file_event(window::Event::FileDropped(path)); + for path in paths { + let _ = self.sender.start_send(Event::EventLoopAwakened( + EventLoopEvent::FileEvent { + window_id, + event: crate::core::Event::Window(window::Event::FileDropped( + path, + )), + }, + )); + } } else { - drag.path = Some(path.clone()); - - emit_file_event(window::Event::FileHovered(path)); + drag.path = Some(paths.clone()); + + for path in paths { + let _ = self.sender.start_send(Event::EventLoopAwakened( + EventLoopEvent::FileEvent { + window_id, + event: crate::core::Event::Window(window::Event::FileHovered( + path, + )), + }, + )); + } } } winit::event::WindowEvent::DragDropped { id, .. } => { @@ -506,7 +511,16 @@ where if let Some(path) = drag.path.take() { self.drag = None; - emit_file_event(window::Event::FileDropped(path)); + for path in path { + let _ = self.sender.start_send(Event::EventLoopAwakened( + EventLoopEvent::FileEvent { + window_id, + event: crate::core::Event::Window(window::Event::FileDropped( + path, + )), + }, + )); + } } else { drag.dropped = true; @@ -519,7 +533,12 @@ where .take_if(|drag| drag.id == id && drag.window_id == window_id) .is_some() { - emit_file_event(window::Event::FilesHoveredLeft); + let _ = self.sender.start_send(Event::EventLoopAwakened( + EventLoopEvent::FileEvent { + window_id, + event: crate::core::Event::Window(window::Event::FilesHoveredLeft), + }, + )); } } _ => {} @@ -576,7 +595,7 @@ enum EventLoopEvent { struct DragSession { window_id: winit::window::WindowId, id: winit::data_transfer::DataTransferId, - path: Option, + path: Option>, dropped: bool, } From 77d5f619f2023598d9d12022532e4564b457ae70 Mon Sep 17 00:00:00 2001 From: 443eb9#C <443eb9@gmail.com> Date: Tue, 11 Aug 2026 18:52:47 +0800 Subject: [PATCH 3/8] add pointer types --- core/src/event.rs | 4 ++ core/src/lib.rs | 1 + core/src/pointer.rs | 15 ++++ core/src/pointer/button.rs | 138 +++++++++++++++++++++++++++++++++++++ core/src/pointer/event.rs | 77 +++++++++++++++++++++ core/src/pointer/force.rs | 15 ++++ core/src/pointer/id.rs | 15 ++++ core/src/pointer/source.rs | 56 +++++++++++++++ core/src/pointer/tablet.rs | 72 +++++++++++++++++++ 9 files changed, 393 insertions(+) create mode 100644 core/src/pointer.rs create mode 100644 core/src/pointer/button.rs create mode 100644 core/src/pointer/event.rs create mode 100644 core/src/pointer/force.rs create mode 100644 core/src/pointer/id.rs create mode 100644 core/src/pointer/source.rs create mode 100644 core/src/pointer/tablet.rs diff --git a/core/src/event.rs b/core/src/event.rs index f5325a57de..0cde9238bc 100644 --- a/core/src/event.rs +++ b/core/src/event.rs @@ -3,6 +3,7 @@ use crate::clipboard; use crate::input_method; use crate::keyboard; use crate::mouse; +use crate::pointer; use crate::touch; use crate::window; @@ -20,6 +21,9 @@ pub enum Event { /// A mouse event Mouse(mouse::Event), + /// A pointer event + Pointer(pointer::Event), + /// A window event Window(window::Event), diff --git a/core/src/lib.rs b/core/src/lib.rs index a6b67b8de2..019b69e6eb 100644 --- a/core/src/lib.rs +++ b/core/src/lib.rs @@ -26,6 +26,7 @@ pub mod length; pub mod mouse; pub mod overlay; pub mod padding; +pub mod pointer; pub mod renderer; pub mod shell; pub mod svg; diff --git a/core/src/pointer.rs b/core/src/pointer.rs new file mode 100644 index 0000000000..58226ee90c --- /dev/null +++ b/core/src/pointer.rs @@ -0,0 +1,15 @@ +//! Handle pointer events. + +mod button; +mod event; +mod force; +mod id; +mod source; +mod tablet; + +pub use button::{ButtonSource, MouseButton, TabletToolButton}; +pub use event::{Event, ScrollDelta}; +pub use force::Force; +pub use id::FingerId; +pub use source::{PointerKind, PointerSource}; +pub use tablet::{TabletToolAngle, TabletToolData, TabletToolKind, TabletToolTilt}; diff --git a/core/src/pointer/button.rs b/core/src/pointer/button.rs new file mode 100644 index 0000000000..18841b14c0 --- /dev/null +++ b/core/src/pointer/button.rs @@ -0,0 +1,138 @@ +use super::{FingerId, Force, TabletToolData, TabletToolKind}; + +/// The source and button of a pointer button event. +#[derive(Debug, Clone, PartialEq)] +pub enum ButtonSource { + /// A mouse button. + Mouse(MouseButton), + + /// A touch contact. + Touch { + /// The identifier of the finger. + finger_id: FingerId, + + /// The force of the touch, if reported by the device. + force: Option, + }, + + /// A tablet tool button. + TabletTool { + /// The kind of tablet tool. + kind: TabletToolKind, + + /// The button that changed state. + button: TabletToolButton, + + /// Data describing how the tool is held and used. + data: TabletToolData, + }, + + /// A button from an unknown pointer source. + Unknown(u16), +} + +/// A button of a mouse. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(u8)] +#[allow(missing_docs)] +pub enum MouseButton { + Left = 0, + Right = 1, + Middle = 2, + Back = 3, + Forward = 4, + Button6 = 5, + Button7 = 6, + Button8 = 7, + Button9 = 8, + Button10 = 9, + Button11 = 10, + Button12 = 11, + Button13 = 12, + Button14 = 13, + Button15 = 14, + Button16 = 15, + Button17 = 16, + Button18 = 17, + Button19 = 18, + Button20 = 19, + Button21 = 20, + Button22 = 21, + Button23 = 22, + Button24 = 23, + Button25 = 24, + Button26 = 25, + Button27 = 26, + Button28 = 27, + Button29 = 28, + Button30 = 29, + Button31 = 30, + Button32 = 31, +} + +impl MouseButton { + /// Constructs a mouse button from a value in the range `0..=31`. + pub fn try_from_u8(button: u8) -> Option { + Some(match button { + 0 => Self::Left, + 1 => Self::Right, + 2 => Self::Middle, + 3 => Self::Back, + 4 => Self::Forward, + 5 => Self::Button6, + 6 => Self::Button7, + 7 => Self::Button8, + 8 => Self::Button9, + 9 => Self::Button10, + 10 => Self::Button11, + 11 => Self::Button12, + 12 => Self::Button13, + 13 => Self::Button14, + 14 => Self::Button15, + 15 => Self::Button16, + 16 => Self::Button17, + 17 => Self::Button18, + 18 => Self::Button19, + 19 => Self::Button20, + 20 => Self::Button21, + 21 => Self::Button22, + 22 => Self::Button23, + 23 => Self::Button24, + 24 => Self::Button25, + 25 => Self::Button26, + 26 => Self::Button27, + 27 => Self::Button28, + 28 => Self::Button29, + 29 => Self::Button30, + 30 => Self::Button31, + 31 => Self::Button32, + _ => return None, + }) + } +} + +/// A button of a tablet tool. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum TabletToolButton { + /// Contact between the tool and tablet surface. + Contact, + + /// The tool's barrel button. + Barrel, + + /// Another tablet tool button. + Other(u16), +} + +impl From for Option { + fn from(button: TabletToolButton) -> Self { + Some(match button { + TabletToolButton::Contact => MouseButton::Left, + TabletToolButton::Barrel => MouseButton::Right, + TabletToolButton::Other(1) => MouseButton::Middle, + TabletToolButton::Other(3) => MouseButton::Back, + TabletToolButton::Other(4) => MouseButton::Forward, + TabletToolButton::Other(_) => return None, + }) + } +} diff --git a/core/src/pointer/event.rs b/core/src/pointer/event.rs new file mode 100644 index 0000000000..8e6ed116d6 --- /dev/null +++ b/core/src/pointer/event.rs @@ -0,0 +1,77 @@ +use crate::Point; + +use super::{ButtonSource, PointerKind, PointerSource}; + +/// A pointer event. +#[derive(Debug, Clone, PartialEq)] +pub enum Event { + /// A pointer entered the window. + PointerEntered { + /// The position of the pointer when it entered the window. + position: Point, + + /// The kind of pointer that entered the window. + kind: PointerKind, + }, + + /// A pointer left the window. + PointerLeft { + /// The kind of pointer that left the window. + kind: PointerKind, + }, + + /// A pointer moved within the window. + PointerMoved { + /// The new position of the pointer. + position: Point, + + /// The source of the pointer movement. + source: PointerSource, + }, + + /// A pointer button was pressed. + PointerPressed { + /// The position of the pointer when the button was pressed. + position: Point, + + /// The source and button that were pressed. + button: ButtonSource, + }, + + /// A pointer button was released. + PointerReleased { + /// The position of the pointer when the button was released. + position: Point, + + /// The source and button that were released. + button: ButtonSource, + }, + + /// A mouse wheel or touchpad was scrolled. + MouseWheel { + /// The scroll movement. + delta: ScrollDelta, + }, +} + +/// A scroll movement. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ScrollDelta { + /// A line-based scroll movement. + Lines { + /// The number of horizontal lines scrolled. + x: f32, + + /// The number of vertical lines scrolled. + y: f32, + }, + + /// A pixel-based scroll movement. + Pixels { + /// The number of horizontal pixels scrolled. + x: f32, + + /// The number of vertical pixels scrolled. + y: f32, + }, +} diff --git a/core/src/pointer/force.rs b/core/src/pointer/force.rs new file mode 100644 index 0000000000..75989882ae --- /dev/null +++ b/core/src/pointer/force.rs @@ -0,0 +1,15 @@ +/// The force of a touch or tablet interaction. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum Force { + /// A force calibrated by the platform. + Calibrated { + /// The applied force, where `1.0` represents an average touch. + force: f64, + + /// The maximum force supported by the device. + max_possible_force: f64, + }, + + /// A force normalized to the range from `0.0` to `1.0`. + Normalized(f64), +} diff --git a/core/src/pointer/id.rs b/core/src/pointer/id.rs new file mode 100644 index 0000000000..143343b32c --- /dev/null +++ b/core/src/pointer/id.rs @@ -0,0 +1,15 @@ +/// An identifier for a finger in a touch interaction. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct FingerId(usize); + +impl FingerId { + /// Converts the identifier into its underlying integer. + pub const fn into_raw(self) -> usize { + self.0 + } + + /// Constructs an identifier from its underlying integer. + pub const fn from_raw(id: usize) -> Self { + Self(id) + } +} diff --git a/core/src/pointer/source.rs b/core/src/pointer/source.rs new file mode 100644 index 0000000000..cd8b044e7b --- /dev/null +++ b/core/src/pointer/source.rs @@ -0,0 +1,56 @@ +use super::{FingerId, Force, TabletToolData, TabletToolKind}; + +/// The kind of device that produced a pointer event. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum PointerKind { + /// A mouse. + Mouse, + + /// A finger touching a screen. + Touch(FingerId), + + /// A tablet tool. + TabletTool(TabletToolKind), + + /// An unknown pointer device. + Unknown, +} + +/// The device and associated data that produced a pointer event. +#[derive(Debug, Clone, PartialEq)] +pub enum PointerSource { + /// A mouse. + Mouse, + + /// A finger touching a screen. + Touch { + /// The identifier of the finger. + finger_id: FingerId, + + /// The force of the touch, if reported by the device. + force: Option, + }, + + /// A tablet tool. + TabletTool { + /// The kind of tablet tool. + kind: TabletToolKind, + + /// Data describing how the tool is held and used. + data: TabletToolData, + }, + + /// An unknown pointer device. + Unknown, +} + +impl From for PointerKind { + fn from(source: PointerSource) -> Self { + match source { + PointerSource::Mouse => Self::Mouse, + PointerSource::Touch { finger_id, .. } => Self::Touch(finger_id), + PointerSource::TabletTool { kind, .. } => Self::TabletTool(kind), + PointerSource::Unknown => Self::Unknown, + } + } +} diff --git a/core/src/pointer/tablet.rs b/core/src/pointer/tablet.rs new file mode 100644 index 0000000000..321c9709f9 --- /dev/null +++ b/core/src/pointer/tablet.rs @@ -0,0 +1,72 @@ +use super::Force; + +/// The kind of tool used with a tablet. +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] +pub enum TabletToolKind { + /// A pen. + #[default] + Pen, + + /// An eraser. + Eraser, + + /// A brush. + Brush, + + /// A pencil. + Pencil, + + /// An airbrush. + Airbrush, + + /// A finger-like tool. + Finger, + + /// A mouse-like tool. + Mouse, + + /// A lens cursor. + Lens, +} + +/// Data describing how a tablet tool is held and used. +#[derive(Debug, Default, Clone, PartialEq)] +pub struct TabletToolData { + /// The force applied to the tool against the surface. + pub force: Option, + /// The normalized tangential, or barrel, pressure in the range `-1.0..=1.0`. + pub tangential_force: Option, + /// The clockwise rotation of the tool in degrees, in the range `0..=359`. + pub twist: Option, + /// The plane angle of the tool in degrees. + pub tilt: Option, + /// The angular position of the tool in radians. + pub angle: Option, +} + +/// The plane angle of a tablet tool in degrees. +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct TabletToolTilt { + /// The angle between the surface Y-Z plane and the tool's surface Y plane. + pub x: i8, + /// The angle between the surface X-Z plane and the tool's surface X plane. + pub y: i8, +} + +/// The angular position of a tablet tool in radians. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct TabletToolAngle { + /// The angle between the tool and the surface X-Y plane. + pub altitude: f64, + /// The clockwise rotation between the tool's major axis and the surface X-Y plane. + pub azimuth: f64, +} + +impl Default for TabletToolAngle { + fn default() -> Self { + Self { + altitude: std::f64::consts::FRAC_2_PI, + azimuth: 0.0, + } + } +} From d3d4cfcc465a5215623dd4309b452f3fb5305db8 Mon Sep 17 00:00:00 2001 From: 443eb9#C <443eb9@gmail.com> Date: Tue, 11 Aug 2026 19:01:17 +0800 Subject: [PATCH 4/8] add conversions of new pointer event --- winit/src/conversion.rs | 305 +++++++++++++++++++++++++--------------- 1 file changed, 193 insertions(+), 112 deletions(-) diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs index d0ab26e2e7..149280d455 100644 --- a/winit/src/conversion.rs +++ b/winit/src/conversion.rs @@ -6,8 +6,8 @@ use crate::core::input_method; use crate::core::keyboard; use crate::core::mouse; +use crate::core::pointer; use crate::core::theme; -use crate::core::touch; use crate::core::window; use crate::core::{Event, Point, Size}; @@ -173,90 +173,60 @@ pub fn window_event( WindowEvent::CloseRequested => Some(Event::Window(window::Event::CloseRequested)), WindowEvent::PointerMoved { position, source, .. - } => match source { - winit::event::PointerSource::Touch { finger_id, .. } => { - let position = position.to_logical::(f64::from(scale_factor)); - - Some(Event::Touch(touch::Event::FingerMoved { - id: touch::Finger(finger_id.into_raw() as u64), - position: Point::new(position.x as f32, position.y as f32), - })) - } - _ => { - let position = position.to_logical::(f64::from(scale_factor)); + } => { + let position = position.to_logical::(f64::from(scale_factor)); - Some(Event::Mouse(mouse::Event::CursorMoved { - position: Point::new(position.x as f32, position.y as f32), - })) - } - }, - WindowEvent::PointerEntered { kind, .. } => match kind { - winit::event::PointerKind::Touch(_) => None, - _ => Some(Event::Mouse(mouse::Event::CursorEntered)), - }, - WindowEvent::PointerLeft { position, kind, .. } => match kind { - winit::event::PointerKind::Touch(finger_id) => { - let id = touch::Finger(finger_id.into_raw() as u64); - - position.map(|position| { - let position = position.to_logical::(f64::from(scale_factor)); - - Event::Touch(touch::Event::FingerLost { - id, - position: Point::new(position.x as f32, position.y as f32), - }) - }) - } - _ => Some(Event::Mouse(mouse::Event::CursorLeft)), - }, + Some(Event::Pointer(pointer::Event::PointerMoved { + position: Point::new(position.x as f32, position.y as f32), + source: pointer_source(source)?, + })) + } + WindowEvent::PointerEntered { position, kind, .. } => { + let position = position.to_logical::(f64::from(scale_factor)); + + Some(Event::Pointer(pointer::Event::PointerEntered { + position: Point::new(position.x as f32, position.y as f32), + kind: pointer_kind(kind)?, + })) + } + WindowEvent::PointerLeft { kind, .. } => { + Some(Event::Pointer(pointer::Event::PointerLeft { + kind: pointer_kind(kind)?, + })) + } WindowEvent::PointerButton { button, state, position, .. - } => match button { - winit::event::ButtonSource::Mouse(button) => { - let button = mouse_button(button); - - Some(Event::Mouse(match state { - winit::event::ElementState::Pressed => mouse::Event::ButtonPressed(button), - winit::event::ElementState::Released => mouse::Event::ButtonReleased(button), - })) - } - winit::event::ButtonSource::Touch { finger_id, .. } => { - let id = touch::Finger(finger_id.into_raw() as u64); - let position = position.to_logical::(f64::from(scale_factor)); - let position = Point::new(position.x as f32, position.y as f32); - Some(Event::Touch(match state { - winit::event::ElementState::Pressed => { - touch::Event::FingerPressed { id, position } - } - winit::event::ElementState::Released => { - touch::Event::FingerLifted { id, position } - } - })) - } - _ => None, - }, - WindowEvent::MouseWheel { delta, .. } => match delta { - winit::event::MouseScrollDelta::LineDelta(delta_x, delta_y) => { - Some(Event::Mouse(mouse::Event::WheelScrolled { - delta: mouse::ScrollDelta::Lines { - x: delta_x, - y: delta_y, - }, - })) - } - winit::event::MouseScrollDelta::PixelDelta(position) => { - Some(Event::Mouse(mouse::Event::WheelScrolled { - delta: mouse::ScrollDelta::Pixels { + } => { + let position = position.to_logical::(f64::from(scale_factor)); + let position = Point::new(position.x as f32, position.y as f32); + let button = button_source(button)?; + + Some(Event::Pointer(match state { + winit::event::ElementState::Pressed => { + pointer::Event::PointerPressed { position, button } + } + winit::event::ElementState::Released => { + pointer::Event::PointerReleased { position, button } + } + })) + } + WindowEvent::MouseWheel { delta, .. } => Some(Event::Pointer(pointer::Event::MouseWheel { + delta: match delta { + winit::event::MouseScrollDelta::LineDelta(x, y) => { + pointer::ScrollDelta::Lines { x, y } + } + winit::event::MouseScrollDelta::PixelDelta(position) => { + pointer::ScrollDelta::Pixels { x: position.x as f32, y: position.y as f32, - }, - })) - } - _ => None, - }, + } + } + _ => return None, + }, + })), // Ignore keyboard presses/releases during window focus/unfocus WindowEvent::KeyboardInput { is_synthetic, .. } if is_synthetic => None, WindowEvent::KeyboardInput { event, .. } => Some(Event::Keyboard({ @@ -518,44 +488,155 @@ pub fn mouse_interaction(interaction: mouse::Interaction) -> Option mouse::Button { +pub fn mouse_button(mouse_button: winit::event::MouseButton) -> pointer::MouseButton { match mouse_button { - winit::event::MouseButton::Left => mouse::Button::Left, - winit::event::MouseButton::Right => mouse::Button::Right, - winit::event::MouseButton::Middle => mouse::Button::Middle, - winit::event::MouseButton::Back => mouse::Button::Back, - winit::event::MouseButton::Forward => mouse::Button::Forward, - winit::event::MouseButton::Button6 => mouse::Button::Other(6), - winit::event::MouseButton::Button7 => mouse::Button::Other(7), - winit::event::MouseButton::Button8 => mouse::Button::Other(8), - winit::event::MouseButton::Button9 => mouse::Button::Other(9), - winit::event::MouseButton::Button10 => mouse::Button::Other(10), - winit::event::MouseButton::Button11 => mouse::Button::Other(11), - winit::event::MouseButton::Button12 => mouse::Button::Other(12), - winit::event::MouseButton::Button13 => mouse::Button::Other(13), - winit::event::MouseButton::Button14 => mouse::Button::Other(14), - winit::event::MouseButton::Button15 => mouse::Button::Other(15), - winit::event::MouseButton::Button16 => mouse::Button::Other(16), - winit::event::MouseButton::Button17 => mouse::Button::Other(17), - winit::event::MouseButton::Button18 => mouse::Button::Other(18), - winit::event::MouseButton::Button19 => mouse::Button::Other(19), - winit::event::MouseButton::Button20 => mouse::Button::Other(20), - winit::event::MouseButton::Button21 => mouse::Button::Other(21), - winit::event::MouseButton::Button22 => mouse::Button::Other(22), - winit::event::MouseButton::Button23 => mouse::Button::Other(23), - winit::event::MouseButton::Button24 => mouse::Button::Other(24), - winit::event::MouseButton::Button25 => mouse::Button::Other(25), - winit::event::MouseButton::Button26 => mouse::Button::Other(26), - winit::event::MouseButton::Button27 => mouse::Button::Other(27), - winit::event::MouseButton::Button28 => mouse::Button::Other(28), - winit::event::MouseButton::Button29 => mouse::Button::Other(29), - winit::event::MouseButton::Button30 => mouse::Button::Other(30), - winit::event::MouseButton::Button31 => mouse::Button::Other(31), - winit::event::MouseButton::Button32 => mouse::Button::Other(32), + winit::event::MouseButton::Left => pointer::MouseButton::Left, + winit::event::MouseButton::Right => pointer::MouseButton::Right, + winit::event::MouseButton::Middle => pointer::MouseButton::Middle, + winit::event::MouseButton::Back => pointer::MouseButton::Back, + winit::event::MouseButton::Forward => pointer::MouseButton::Forward, + winit::event::MouseButton::Button6 => pointer::MouseButton::Button6, + winit::event::MouseButton::Button7 => pointer::MouseButton::Button7, + winit::event::MouseButton::Button8 => pointer::MouseButton::Button8, + winit::event::MouseButton::Button9 => pointer::MouseButton::Button9, + winit::event::MouseButton::Button10 => pointer::MouseButton::Button10, + winit::event::MouseButton::Button11 => pointer::MouseButton::Button11, + winit::event::MouseButton::Button12 => pointer::MouseButton::Button12, + winit::event::MouseButton::Button13 => pointer::MouseButton::Button13, + winit::event::MouseButton::Button14 => pointer::MouseButton::Button14, + winit::event::MouseButton::Button15 => pointer::MouseButton::Button15, + winit::event::MouseButton::Button16 => pointer::MouseButton::Button16, + winit::event::MouseButton::Button17 => pointer::MouseButton::Button17, + winit::event::MouseButton::Button18 => pointer::MouseButton::Button18, + winit::event::MouseButton::Button19 => pointer::MouseButton::Button19, + winit::event::MouseButton::Button20 => pointer::MouseButton::Button20, + winit::event::MouseButton::Button21 => pointer::MouseButton::Button21, + winit::event::MouseButton::Button22 => pointer::MouseButton::Button22, + winit::event::MouseButton::Button23 => pointer::MouseButton::Button23, + winit::event::MouseButton::Button24 => pointer::MouseButton::Button24, + winit::event::MouseButton::Button25 => pointer::MouseButton::Button25, + winit::event::MouseButton::Button26 => pointer::MouseButton::Button26, + winit::event::MouseButton::Button27 => pointer::MouseButton::Button27, + winit::event::MouseButton::Button28 => pointer::MouseButton::Button28, + winit::event::MouseButton::Button29 => pointer::MouseButton::Button29, + winit::event::MouseButton::Button30 => pointer::MouseButton::Button30, + winit::event::MouseButton::Button31 => pointer::MouseButton::Button31, + winit::event::MouseButton::Button32 => pointer::MouseButton::Button32, + } +} + +fn pointer_kind(kind: winit::event::PointerKind) -> Option { + Some(match kind { + winit::event::PointerKind::Mouse => pointer::PointerKind::Mouse, + winit::event::PointerKind::Touch(finger_id) => { + pointer::PointerKind::Touch(pointer::FingerId::from_raw(finger_id.into_raw())) + } + winit::event::PointerKind::TabletTool(kind) => { + pointer::PointerKind::TabletTool(tablet_tool_kind(kind)?) + } + winit::event::PointerKind::Unknown => pointer::PointerKind::Unknown, + _ => return None, + }) +} + +fn pointer_source(source: winit::event::PointerSource) -> Option { + Some(match source { + winit::event::PointerSource::Mouse => pointer::PointerSource::Mouse, + winit::event::PointerSource::Touch { finger_id, force } => pointer::PointerSource::Touch { + finger_id: pointer::FingerId::from_raw(finger_id.into_raw()), + force: force.map(pointer_force), + }, + winit::event::PointerSource::TabletTool { kind, data } => { + pointer::PointerSource::TabletTool { + kind: tablet_tool_kind(kind)?, + data: tablet_tool_data(data), + } + } + winit::event::PointerSource::Unknown => pointer::PointerSource::Unknown, + _ => return None, + }) +} + +fn button_source(source: winit::event::ButtonSource) -> Option { + Some(match source { + winit::event::ButtonSource::Mouse(button) => { + pointer::ButtonSource::Mouse(mouse_button(button)) + } + winit::event::ButtonSource::Touch { finger_id, force } => pointer::ButtonSource::Touch { + finger_id: pointer::FingerId::from_raw(finger_id.into_raw()), + force: force.map(pointer_force), + }, + winit::event::ButtonSource::TabletTool { kind, button, data } => { + pointer::ButtonSource::TabletTool { + kind: tablet_tool_kind(kind)?, + button: tablet_tool_button(button), + data: tablet_tool_data(data), + } + } + winit::event::ButtonSource::Unknown(button) => pointer::ButtonSource::Unknown(button), + _ => return None, + }) +} + +fn pointer_force(force: winit::event::Force) -> pointer::Force { + match force { + winit::event::Force::Calibrated { + force, + max_possible_force, + } => pointer::Force::Calibrated { + force, + max_possible_force, + }, + winit::event::Force::Normalized(force) => pointer::Force::Normalized(force), + } +} + +fn tablet_tool_kind(kind: winit::event::TabletToolKind) -> Option { + Some(match kind { + winit::event::TabletToolKind::Pen => pointer::TabletToolKind::Pen, + winit::event::TabletToolKind::Eraser => pointer::TabletToolKind::Eraser, + winit::event::TabletToolKind::Brush => pointer::TabletToolKind::Brush, + winit::event::TabletToolKind::Pencil => pointer::TabletToolKind::Pencil, + winit::event::TabletToolKind::Airbrush => pointer::TabletToolKind::Airbrush, + winit::event::TabletToolKind::Finger => pointer::TabletToolKind::Finger, + winit::event::TabletToolKind::Mouse => pointer::TabletToolKind::Mouse, + winit::event::TabletToolKind::Lens => pointer::TabletToolKind::Lens, + _ => return None, + }) +} + +fn tablet_tool_data(data: winit::event::TabletToolData) -> pointer::TabletToolData { + pointer::TabletToolData { + force: data.force.map(pointer_force), + tangential_force: data.tangential_force, + twist: data.twist, + tilt: data.tilt.map(tablet_tool_tilt), + angle: data.angle.map(tablet_tool_angle), + } +} + +fn tablet_tool_tilt(tilt: winit::event::TabletToolTilt) -> pointer::TabletToolTilt { + pointer::TabletToolTilt { + x: tilt.x, + y: tilt.y, + } +} + +fn tablet_tool_angle(angle: winit::event::TabletToolAngle) -> pointer::TabletToolAngle { + pointer::TabletToolAngle { + altitude: angle.altitude, + azimuth: angle.azimuth, + } +} + +fn tablet_tool_button(button: winit::event::TabletToolButton) -> pointer::TabletToolButton { + match button { + winit::event::TabletToolButton::Contact => pointer::TabletToolButton::Contact, + winit::event::TabletToolButton::Barrel => pointer::TabletToolButton::Barrel, + winit::event::TabletToolButton::Other(button) => pointer::TabletToolButton::Other(button), } } From fd36ac33f9eb4a932ef95ac2ed8e4280b36fe299 Mon Sep 17 00:00:00 2001 From: 443eb9#C <443eb9@gmail.com> Date: Tue, 11 Aug 2026 19:15:34 +0800 Subject: [PATCH 5/8] added helpers for pointer event --- core/src/pointer/event.rs | 66 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/core/src/pointer/event.rs b/core/src/pointer/event.rs index 8e6ed116d6..c5552d1e97 100644 --- a/core/src/pointer/event.rs +++ b/core/src/pointer/event.rs @@ -1,6 +1,6 @@ use crate::Point; -use super::{ButtonSource, PointerKind, PointerSource}; +use super::{ButtonSource, MouseButton, PointerKind, PointerSource, TabletToolButton}; /// A pointer event. #[derive(Debug, Clone, PartialEq)] @@ -54,6 +54,70 @@ pub enum Event { }, } +impl Event { + /// Returns whether the event is a mouse left click, finger press, or tablet contact. + pub fn is_primary_click(&self) -> bool { + matches!( + self, + Self::PointerPressed { + button: ButtonSource::Mouse(MouseButton::Left) + | ButtonSource::Touch { .. } + | ButtonSource::TabletTool { + button: TabletToolButton::Contact, + .. + }, + .. + } + ) + } + + /// Returns whether the event is a mouse left release, finger lift, or tablet contact release. + pub fn is_primary_release(&self) -> bool { + matches!( + self, + Self::PointerReleased { + button: ButtonSource::Mouse(MouseButton::Left) + | ButtonSource::Touch { .. } + | ButtonSource::TabletTool { + button: TabletToolButton::Contact, + .. + }, + .. + } + ) + } + + /// Returns whether the event is a mouse right click or tablet barrel press. + pub fn is_secondary_click(&self) -> bool { + matches!( + self, + Self::PointerPressed { + button: ButtonSource::Mouse(MouseButton::Right) + | ButtonSource::TabletTool { + button: TabletToolButton::Barrel, + .. + }, + .. + } + ) + } + + /// Returns whether the event is a mouse right release or tablet barrel lift. + pub fn is_secondary_release(&self) -> bool { + matches!( + self, + Self::PointerReleased { + button: ButtonSource::Mouse(MouseButton::Right) + | ButtonSource::TabletTool { + button: TabletToolButton::Barrel, + .. + }, + .. + } + ) + } +} + /// A scroll movement. #[derive(Debug, Clone, Copy, PartialEq)] pub enum ScrollDelta { From 62084a46e26e3eea721a8f20cb6248a52d5c8be1 Mon Sep 17 00:00:00 2001 From: 443eb9#C <443eb9@gmail.com> Date: Tue, 11 Aug 2026 19:52:12 +0800 Subject: [PATCH 6/8] better pointer module structure --- core/src/mouse.rs | 11 +- core/src/mouse/event.rs | 22 +-- core/src/pointer.rs | 74 +++++++-- core/src/pointer/button.rs | 124 ++------------- core/src/pointer/event.rs | 66 +++----- core/src/pointer/id.rs | 15 -- core/src/pointer/mouse.rs | 34 ++++ core/src/{ => pointer}/mouse/button.rs | 0 core/src/{ => pointer}/mouse/click.rs | 3 +- core/src/{ => pointer}/mouse/cursor.rs | 0 core/src/{ => pointer}/mouse/interaction.rs | 0 core/src/pointer/source.rs | 56 ------- core/src/pointer/tablet.rs | 51 +++++- core/src/pointer/{force.rs => touch.rs} | 6 + core/src/touch.rs | 7 +- winit/src/conversion.rs | 163 ++++++++++---------- 16 files changed, 265 insertions(+), 367 deletions(-) delete mode 100644 core/src/pointer/id.rs create mode 100644 core/src/pointer/mouse.rs rename core/src/{ => pointer}/mouse/button.rs (100%) rename core/src/{ => pointer}/mouse/click.rs (98%) rename core/src/{ => pointer}/mouse/cursor.rs (100%) rename core/src/{ => pointer}/mouse/interaction.rs (100%) delete mode 100644 core/src/pointer/source.rs rename core/src/pointer/{force.rs => touch.rs} (71%) diff --git a/core/src/mouse.rs b/core/src/mouse.rs index d13a60fbc1..c014e862c6 100644 --- a/core/src/mouse.rs +++ b/core/src/mouse.rs @@ -1,13 +1,6 @@ //! Handle mouse events. -pub mod click; -mod button; -mod cursor; mod event; -mod interaction; -pub use button::Button; -pub use click::Click; -pub use cursor::Cursor; -pub use event::{Event, ScrollDelta}; -pub use interaction::Interaction; +pub use crate::pointer::mouse::{Button, Click, Cursor, Interaction, ScrollDelta, click}; +pub use event::Event; diff --git a/core/src/mouse/event.rs b/core/src/mouse/event.rs index 7f5585ada0..cdaa717066 100644 --- a/core/src/mouse/event.rs +++ b/core/src/mouse/event.rs @@ -1,6 +1,6 @@ use crate::Point; -use super::Button; +use super::{Button, ScrollDelta}; /// A mouse event. /// @@ -34,23 +34,3 @@ pub enum Event { delta: ScrollDelta, }, } - -/// A scroll movement. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum ScrollDelta { - /// A line-based scroll movement - Lines { - /// The number of horizontal lines scrolled - x: f32, - - /// The number of vertical lines scrolled - y: f32, - }, - /// A pixel-based scroll movement - Pixels { - /// The number of horizontal pixels scrolled - x: f32, - /// The number of vertical pixels scrolled - y: f32, - }, -} diff --git a/core/src/pointer.rs b/core/src/pointer.rs index 58226ee90c..1bf0aada9b 100644 --- a/core/src/pointer.rs +++ b/core/src/pointer.rs @@ -1,15 +1,65 @@ //! Handle pointer events. -mod button; +pub mod button; +pub mod mouse; +pub mod tablet; +pub mod touch; + mod event; -mod force; -mod id; -mod source; -mod tablet; - -pub use button::{ButtonSource, MouseButton, TabletToolButton}; -pub use event::{Event, ScrollDelta}; -pub use force::Force; -pub use id::FingerId; -pub use source::{PointerKind, PointerSource}; -pub use tablet::{TabletToolAngle, TabletToolData, TabletToolKind, TabletToolTilt}; + +pub use event::Event; + +/// The kind of device that produced a pointer event. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Kind { + /// A mouse. + Mouse, + + /// A finger touching a screen. + Touch(touch::Finger), + + /// A tablet tool. + TabletTool(tablet::Kind), + + /// An unknown pointer device. + Unknown, +} + +/// The device and associated data that produced a pointer event. +#[derive(Debug, Clone, PartialEq)] +pub enum Source { + /// A mouse. + Mouse, + + /// A finger touching a screen. + Touch { + /// The identifier of the finger. + finger_id: touch::Finger, + + /// The force of the touch, if reported by the device. + force: Option, + }, + + /// A tablet tool. + TabletTool { + /// The kind of tablet tool. + kind: tablet::Kind, + + /// Data describing how the tool is held and used. + data: tablet::Data, + }, + + /// An unknown pointer device. + Unknown, +} + +impl From for crate::pointer::Kind { + fn from(source: Source) -> Self { + match source { + Source::Mouse => Self::Mouse, + Source::Touch { finger_id, .. } => Self::Touch(finger_id), + Source::TabletTool { kind, .. } => Self::TabletTool(kind), + Source::Unknown => Self::Unknown, + } + } +} diff --git a/core/src/pointer/button.rs b/core/src/pointer/button.rs index 18841b14c0..0c2bf657a0 100644 --- a/core/src/pointer/button.rs +++ b/core/src/pointer/button.rs @@ -1,138 +1,34 @@ -use super::{FingerId, Force, TabletToolData, TabletToolKind}; +//! Handle pointer buttons. + +use crate::pointer::{mouse, tablet, touch}; /// The source and button of a pointer button event. #[derive(Debug, Clone, PartialEq)] -pub enum ButtonSource { +pub enum Source { /// A mouse button. - Mouse(MouseButton), + Mouse(mouse::Button), /// A touch contact. Touch { /// The identifier of the finger. - finger_id: FingerId, + finger_id: touch::Finger, /// The force of the touch, if reported by the device. - force: Option, + force: Option, }, /// A tablet tool button. TabletTool { /// The kind of tablet tool. - kind: TabletToolKind, + kind: tablet::Kind, /// The button that changed state. - button: TabletToolButton, + button: tablet::Button, /// Data describing how the tool is held and used. - data: TabletToolData, + data: tablet::Data, }, /// A button from an unknown pointer source. Unknown(u16), } - -/// A button of a mouse. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[repr(u8)] -#[allow(missing_docs)] -pub enum MouseButton { - Left = 0, - Right = 1, - Middle = 2, - Back = 3, - Forward = 4, - Button6 = 5, - Button7 = 6, - Button8 = 7, - Button9 = 8, - Button10 = 9, - Button11 = 10, - Button12 = 11, - Button13 = 12, - Button14 = 13, - Button15 = 14, - Button16 = 15, - Button17 = 16, - Button18 = 17, - Button19 = 18, - Button20 = 19, - Button21 = 20, - Button22 = 21, - Button23 = 22, - Button24 = 23, - Button25 = 24, - Button26 = 25, - Button27 = 26, - Button28 = 27, - Button29 = 28, - Button30 = 29, - Button31 = 30, - Button32 = 31, -} - -impl MouseButton { - /// Constructs a mouse button from a value in the range `0..=31`. - pub fn try_from_u8(button: u8) -> Option { - Some(match button { - 0 => Self::Left, - 1 => Self::Right, - 2 => Self::Middle, - 3 => Self::Back, - 4 => Self::Forward, - 5 => Self::Button6, - 6 => Self::Button7, - 7 => Self::Button8, - 8 => Self::Button9, - 9 => Self::Button10, - 10 => Self::Button11, - 11 => Self::Button12, - 12 => Self::Button13, - 13 => Self::Button14, - 14 => Self::Button15, - 15 => Self::Button16, - 16 => Self::Button17, - 17 => Self::Button18, - 18 => Self::Button19, - 19 => Self::Button20, - 20 => Self::Button21, - 21 => Self::Button22, - 22 => Self::Button23, - 23 => Self::Button24, - 24 => Self::Button25, - 25 => Self::Button26, - 26 => Self::Button27, - 27 => Self::Button28, - 28 => Self::Button29, - 29 => Self::Button30, - 30 => Self::Button31, - 31 => Self::Button32, - _ => return None, - }) - } -} - -/// A button of a tablet tool. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum TabletToolButton { - /// Contact between the tool and tablet surface. - Contact, - - /// The tool's barrel button. - Barrel, - - /// Another tablet tool button. - Other(u16), -} - -impl From for Option { - fn from(button: TabletToolButton) -> Self { - Some(match button { - TabletToolButton::Contact => MouseButton::Left, - TabletToolButton::Barrel => MouseButton::Right, - TabletToolButton::Other(1) => MouseButton::Middle, - TabletToolButton::Other(3) => MouseButton::Back, - TabletToolButton::Other(4) => MouseButton::Forward, - TabletToolButton::Other(_) => return None, - }) - } -} diff --git a/core/src/pointer/event.rs b/core/src/pointer/event.rs index c5552d1e97..4c8ac64d21 100644 --- a/core/src/pointer/event.rs +++ b/core/src/pointer/event.rs @@ -1,6 +1,6 @@ use crate::Point; - -use super::{ButtonSource, MouseButton, PointerKind, PointerSource, TabletToolButton}; +use crate::pointer; +use crate::pointer::{button, mouse, tablet}; /// A pointer event. #[derive(Debug, Clone, PartialEq)] @@ -11,13 +11,13 @@ pub enum Event { position: Point, /// The kind of pointer that entered the window. - kind: PointerKind, + kind: pointer::Kind, }, /// A pointer left the window. PointerLeft { /// The kind of pointer that left the window. - kind: PointerKind, + kind: pointer::Kind, }, /// A pointer moved within the window. @@ -26,7 +26,7 @@ pub enum Event { position: Point, /// The source of the pointer movement. - source: PointerSource, + source: pointer::Source, }, /// A pointer button was pressed. @@ -35,7 +35,7 @@ pub enum Event { position: Point, /// The source and button that were pressed. - button: ButtonSource, + button: button::Source, }, /// A pointer button was released. @@ -44,13 +44,13 @@ pub enum Event { position: Point, /// The source and button that were released. - button: ButtonSource, + button: button::Source, }, /// A mouse wheel or touchpad was scrolled. MouseWheel { /// The scroll movement. - delta: ScrollDelta, + delta: mouse::ScrollDelta, }, } @@ -60,10 +60,10 @@ impl Event { matches!( self, Self::PointerPressed { - button: ButtonSource::Mouse(MouseButton::Left) - | ButtonSource::Touch { .. } - | ButtonSource::TabletTool { - button: TabletToolButton::Contact, + button: button::Source::Mouse(mouse::Button::Left) + | button::Source::Touch { .. } + | button::Source::TabletTool { + button: tablet::Button::Contact, .. }, .. @@ -76,10 +76,10 @@ impl Event { matches!( self, Self::PointerReleased { - button: ButtonSource::Mouse(MouseButton::Left) - | ButtonSource::Touch { .. } - | ButtonSource::TabletTool { - button: TabletToolButton::Contact, + button: button::Source::Mouse(mouse::Button::Left) + | button::Source::Touch { .. } + | button::Source::TabletTool { + button: tablet::Button::Contact, .. }, .. @@ -92,9 +92,9 @@ impl Event { matches!( self, Self::PointerPressed { - button: ButtonSource::Mouse(MouseButton::Right) - | ButtonSource::TabletTool { - button: TabletToolButton::Barrel, + button: button::Source::Mouse(mouse::Button::Right) + | button::Source::TabletTool { + button: tablet::Button::Barrel, .. }, .. @@ -107,9 +107,9 @@ impl Event { matches!( self, Self::PointerReleased { - button: ButtonSource::Mouse(MouseButton::Right) - | ButtonSource::TabletTool { - button: TabletToolButton::Barrel, + button: button::Source::Mouse(mouse::Button::Right) + | button::Source::TabletTool { + button: tablet::Button::Barrel, .. }, .. @@ -117,25 +117,3 @@ impl Event { ) } } - -/// A scroll movement. -#[derive(Debug, Clone, Copy, PartialEq)] -pub enum ScrollDelta { - /// A line-based scroll movement. - Lines { - /// The number of horizontal lines scrolled. - x: f32, - - /// The number of vertical lines scrolled. - y: f32, - }, - - /// A pixel-based scroll movement. - Pixels { - /// The number of horizontal pixels scrolled. - x: f32, - - /// The number of vertical pixels scrolled. - y: f32, - }, -} diff --git a/core/src/pointer/id.rs b/core/src/pointer/id.rs deleted file mode 100644 index 143343b32c..0000000000 --- a/core/src/pointer/id.rs +++ /dev/null @@ -1,15 +0,0 @@ -/// An identifier for a finger in a touch interaction. -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct FingerId(usize); - -impl FingerId { - /// Converts the identifier into its underlying integer. - pub const fn into_raw(self) -> usize { - self.0 - } - - /// Constructs an identifier from its underlying integer. - pub const fn from_raw(id: usize) -> Self { - Self(id) - } -} diff --git a/core/src/pointer/mouse.rs b/core/src/pointer/mouse.rs new file mode 100644 index 0000000000..1e059db15f --- /dev/null +++ b/core/src/pointer/mouse.rs @@ -0,0 +1,34 @@ +//! Handle mouse input. + +pub mod click; + +mod button; +mod cursor; +mod interaction; + +pub use button::Button; +pub use click::Click; +pub use cursor::Cursor; +pub use interaction::Interaction; + +/// A scroll movement. +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ScrollDelta { + /// A line-based scroll movement. + Lines { + /// The number of horizontal lines scrolled. + x: f32, + + /// The number of vertical lines scrolled. + y: f32, + }, + + /// A pixel-based scroll movement. + Pixels { + /// The number of horizontal pixels scrolled. + x: f32, + + /// The number of vertical pixels scrolled. + y: f32, + }, +} diff --git a/core/src/mouse/button.rs b/core/src/pointer/mouse/button.rs similarity index 100% rename from core/src/mouse/button.rs rename to core/src/pointer/mouse/button.rs diff --git a/core/src/mouse/click.rs b/core/src/pointer/mouse/click.rs similarity index 98% rename from core/src/mouse/click.rs rename to core/src/pointer/mouse/click.rs index 8a1c461c41..ed0437ad0e 100644 --- a/core/src/mouse/click.rs +++ b/core/src/pointer/mouse/click.rs @@ -1,10 +1,11 @@ //! Track mouse clicks. -use crate::mouse::Button; use crate::time::Instant; use crate::{Point, Transformation}; use std::ops::Mul; +use super::Button; + /// A mouse click. #[derive(Debug, Clone, Copy)] pub struct Click { diff --git a/core/src/mouse/cursor.rs b/core/src/pointer/mouse/cursor.rs similarity index 100% rename from core/src/mouse/cursor.rs rename to core/src/pointer/mouse/cursor.rs diff --git a/core/src/mouse/interaction.rs b/core/src/pointer/mouse/interaction.rs similarity index 100% rename from core/src/mouse/interaction.rs rename to core/src/pointer/mouse/interaction.rs diff --git a/core/src/pointer/source.rs b/core/src/pointer/source.rs deleted file mode 100644 index cd8b044e7b..0000000000 --- a/core/src/pointer/source.rs +++ /dev/null @@ -1,56 +0,0 @@ -use super::{FingerId, Force, TabletToolData, TabletToolKind}; - -/// The kind of device that produced a pointer event. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum PointerKind { - /// A mouse. - Mouse, - - /// A finger touching a screen. - Touch(FingerId), - - /// A tablet tool. - TabletTool(TabletToolKind), - - /// An unknown pointer device. - Unknown, -} - -/// The device and associated data that produced a pointer event. -#[derive(Debug, Clone, PartialEq)] -pub enum PointerSource { - /// A mouse. - Mouse, - - /// A finger touching a screen. - Touch { - /// The identifier of the finger. - finger_id: FingerId, - - /// The force of the touch, if reported by the device. - force: Option, - }, - - /// A tablet tool. - TabletTool { - /// The kind of tablet tool. - kind: TabletToolKind, - - /// Data describing how the tool is held and used. - data: TabletToolData, - }, - - /// An unknown pointer device. - Unknown, -} - -impl From for PointerKind { - fn from(source: PointerSource) -> Self { - match source { - PointerSource::Mouse => Self::Mouse, - PointerSource::Touch { finger_id, .. } => Self::Touch(finger_id), - PointerSource::TabletTool { kind, .. } => Self::TabletTool(kind), - PointerSource::Unknown => Self::Unknown, - } - } -} diff --git a/core/src/pointer/tablet.rs b/core/src/pointer/tablet.rs index 321c9709f9..2b1e81c25c 100644 --- a/core/src/pointer/tablet.rs +++ b/core/src/pointer/tablet.rs @@ -1,8 +1,11 @@ -use super::Force; +//! Handle tablet tool input. + +use crate::pointer::mouse; +use crate::pointer::touch::Force; /// The kind of tool used with a tablet. #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] -pub enum TabletToolKind { +pub enum Kind { /// A pen. #[default] Pen, @@ -31,38 +34,44 @@ pub enum TabletToolKind { /// Data describing how a tablet tool is held and used. #[derive(Debug, Default, Clone, PartialEq)] -pub struct TabletToolData { +pub struct Data { /// The force applied to the tool against the surface. pub force: Option, + /// The normalized tangential, or barrel, pressure in the range `-1.0..=1.0`. pub tangential_force: Option, + /// The clockwise rotation of the tool in degrees, in the range `0..=359`. pub twist: Option, + /// The plane angle of the tool in degrees. - pub tilt: Option, + pub tilt: Option, + /// The angular position of the tool in radians. - pub angle: Option, + pub angle: Option, } /// The plane angle of a tablet tool in degrees. #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct TabletToolTilt { +pub struct Tilt { /// The angle between the surface Y-Z plane and the tool's surface Y plane. pub x: i8, + /// The angle between the surface X-Z plane and the tool's surface X plane. pub y: i8, } /// The angular position of a tablet tool in radians. #[derive(Debug, Clone, Copy, PartialEq)] -pub struct TabletToolAngle { +pub struct Angle { /// The angle between the tool and the surface X-Y plane. pub altitude: f64, + /// The clockwise rotation between the tool's major axis and the surface X-Y plane. pub azimuth: f64, } -impl Default for TabletToolAngle { +impl Default for Angle { fn default() -> Self { Self { altitude: std::f64::consts::FRAC_2_PI, @@ -70,3 +79,29 @@ impl Default for TabletToolAngle { } } } + +/// A button of a tablet tool. +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum Button { + /// Contact between the tool and tablet surface. + Contact, + + /// The tool's barrel button. + Barrel, + + /// Another tablet tool button. + Other(u16), +} + +impl From