Use winit to obtain current theme::Mode

This commit is contained in:
Héctor Ramón Jiménez 2025-09-08 05:16:20 +02:00
parent 5c7ae8a3d6
commit 0111f514a1
No known key found for this signature in database
GPG key ID: 7CC46565708259A7
25 changed files with 208 additions and 602 deletions

477
Cargo.lock generated
View file

@ -91,15 +91,6 @@ dependencies = [
"thiserror 1.0.69", "thiserror 1.0.69",
] ]
[[package]]
name = "android-build"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cac4c64175d504608cf239756339c07f6384a476f97f20a7043f92920b0b8fd"
dependencies = [
"windows-sys 0.52.0",
]
[[package]] [[package]]
name = "android-properties" name = "android-properties"
version = "0.2.2" version = "0.2.2"
@ -199,18 +190,6 @@ dependencies = [
"libloading", "libloading",
] ]
[[package]]
name = "async-broadcast"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
dependencies = [
"event-listener",
"event-listener-strategy",
"futures-core",
"pin-project-lite",
]
[[package]] [[package]]
name = "async-channel" name = "async-channel"
version = "2.5.0" version = "2.5.0"
@ -306,17 +285,6 @@ dependencies = [
"rustix 1.0.8", "rustix 1.0.8",
] ]
[[package]]
name = "async-recursion"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "async-signal" name = "async-signal"
version = "0.2.12" version = "0.2.12"
@ -341,17 +309,6 @@ version = "4.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
[[package]]
name = "async-trait"
version = "0.1.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "async-tungstenite" name = "async-tungstenite"
version = "0.25.1" version = "0.25.1"
@ -545,15 +502,6 @@ dependencies = [
"objc2 0.5.2", "objc2 0.5.2",
] ]
[[package]]
name = "block2"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2"
dependencies = [
"objc2 0.6.2",
]
[[package]] [[package]]
name = "blocking" name = "blocking"
version = "1.6.2" version = "1.6.2"
@ -831,7 +779,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7f4aaa047ba3c3630b080bb9860894732ff23e2aee290a418909aa6d5df38f" checksum = "9b7f4aaa047ba3c3630b080bb9860894732ff23e2aee290a418909aa6d5df38f"
dependencies = [ dependencies = [
"objc2 0.5.2", "objc2 0.5.2",
"objc2-app-kit 0.2.2", "objc2-app-kit",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
] ]
@ -1241,16 +1189,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b"
[[package]]
name = "dispatch2"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
]
[[package]] [[package]]
name = "displaydoc" name = "displaydoc"
version = "0.2.5" version = "0.2.5"
@ -1362,33 +1300,6 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "endi"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf"
[[package]]
name = "enumflags2"
version = "0.7.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef"
dependencies = [
"enumflags2_derive",
"serde",
]
[[package]]
name = "enumflags2_derive"
version = "0.7.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "equator" name = "equator"
version = "0.4.2" version = "0.4.2"
@ -2182,12 +2093,6 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]] [[package]]
name = "hexf-parse" name = "hexf-parse"
version = "0.2.1" version = "0.2.1"
@ -2432,7 +2337,6 @@ dependencies = [
"glam", "glam",
"lilt", "lilt",
"log", "log",
"mundy",
"num-traits", "num-traits",
"rustc-hash 2.1.1", "rustc-hash 2.1.1",
"serde", "serde",
@ -3258,15 +3162,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "memoffset"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "metal" name = "metal"
version = "0.32.0" version = "0.32.0"
@ -3376,31 +3271,6 @@ dependencies = [
"voronator", "voronator",
] ]
[[package]]
name = "mundy"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5f507e52285e981a349f7224e0ac7eaf014e1a9cce399471547c8dfbc018b79"
dependencies = [
"android-build",
"async-io",
"cfg-if",
"dispatch",
"futures-channel",
"futures-lite",
"jni",
"ndk-context",
"objc2 0.6.2",
"objc2-app-kit 0.3.1",
"objc2-foundation 0.3.1",
"pin-project-lite",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"windows 0.61.3",
"zbus",
]
[[package]] [[package]]
name = "mutate_once" name = "mutate_once"
version = "0.1.2" version = "0.1.2"
@ -3486,19 +3356,6 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
[[package]]
name = "nix"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
dependencies = [
"bitflags 2.9.4",
"cfg-if",
"cfg_aliases",
"libc",
"memoffset",
]
[[package]] [[package]]
name = "nom" name = "nom"
version = "7.1.3" version = "7.1.3"
@ -3674,32 +3531,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff"
dependencies = [ dependencies = [
"bitflags 2.9.4", "bitflags 2.9.4",
"block2 0.5.1", "block2",
"libc", "libc",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-core-data 0.2.2", "objc2-core-data",
"objc2-core-image 0.2.2", "objc2-core-image",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
"objc2-quartz-core 0.2.2", "objc2-quartz-core",
]
[[package]]
name = "objc2-app-kit"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc"
dependencies = [
"bitflags 2.9.4",
"block2 0.6.1",
"libc",
"objc2 0.6.2",
"objc2-cloud-kit 0.3.1",
"objc2-core-data 0.3.1",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-core-image 0.3.1",
"objc2-foundation 0.3.1",
"objc2-quartz-core 0.3.1",
] ]
[[package]] [[package]]
@ -3709,30 +3547,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009"
dependencies = [ dependencies = [
"bitflags 2.9.4", "bitflags 2.9.4",
"block2 0.5.1", "block2",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-core-location", "objc2-core-location",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
] ]
[[package]]
name = "objc2-cloud-kit"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17614fdcd9b411e6ff1117dfb1d0150f908ba83a7df81b1f118005fe0a8ea15d"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
"objc2-foundation 0.3.1",
]
[[package]] [[package]]
name = "objc2-contacts" name = "objc2-contacts"
version = "0.2.2" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889"
dependencies = [ dependencies = [
"block2 0.5.1", "block2",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
] ]
@ -3744,75 +3571,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
dependencies = [ dependencies = [
"bitflags 2.9.4", "bitflags 2.9.4",
"block2 0.5.1", "block2",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
] ]
[[package]]
name = "objc2-core-data"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291fbbf7d29287518e8686417cf7239c74700fd4b607623140a7d4a3c834329d"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
"objc2-foundation 0.3.1",
]
[[package]]
name = "objc2-core-foundation"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
dependencies = [
"bitflags 2.9.4",
"dispatch2",
"objc2 0.6.2",
]
[[package]]
name = "objc2-core-graphics"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4"
dependencies = [
"bitflags 2.9.4",
"dispatch2",
"objc2 0.6.2",
"objc2-core-foundation",
"objc2-io-surface",
]
[[package]] [[package]]
name = "objc2-core-image" name = "objc2-core-image"
version = "0.2.2" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
dependencies = [ dependencies = [
"block2 0.5.1", "block2",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
"objc2-metal", "objc2-metal",
] ]
[[package]]
name = "objc2-core-image"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79b3dc0cc4386b6ccf21c157591b34a7f44c8e75b064f85502901ab2188c007e"
dependencies = [
"objc2 0.6.2",
"objc2-foundation 0.3.1",
]
[[package]] [[package]]
name = "objc2-core-location" name = "objc2-core-location"
version = "0.2.2" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781"
dependencies = [ dependencies = [
"block2 0.5.1", "block2",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-contacts", "objc2-contacts",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
@ -3831,7 +3613,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
dependencies = [ dependencies = [
"bitflags 2.9.4", "bitflags 2.9.4",
"block2 0.5.1", "block2",
"dispatch", "dispatch",
"libc", "libc",
"objc2 0.5.2", "objc2 0.5.2",
@ -3844,21 +3626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c"
dependencies = [ dependencies = [
"bitflags 2.9.4", "bitflags 2.9.4",
"block2 0.6.1",
"libc",
"objc2 0.6.2", "objc2 0.6.2",
"objc2-core-foundation",
]
[[package]]
name = "objc2-io-surface"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
"objc2-core-foundation",
] ]
[[package]] [[package]]
@ -3867,9 +3635,9 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
dependencies = [ dependencies = [
"block2 0.5.1", "block2",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-app-kit 0.2.2", "objc2-app-kit",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
] ]
@ -3880,7 +3648,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
dependencies = [ dependencies = [
"bitflags 2.9.4", "bitflags 2.9.4",
"block2 0.5.1", "block2",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
] ]
@ -3892,23 +3660,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
dependencies = [ dependencies = [
"bitflags 2.9.4", "bitflags 2.9.4",
"block2 0.5.1", "block2",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
"objc2-metal", "objc2-metal",
] ]
[[package]]
name = "objc2-quartz-core"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ffb6a0cd5f182dc964334388560b12a57f7b74b3e2dec5e2722aa2dfb2ccd5"
dependencies = [
"bitflags 2.9.4",
"objc2 0.6.2",
"objc2-foundation 0.3.1",
]
[[package]] [[package]]
name = "objc2-symbols" name = "objc2-symbols"
version = "0.2.2" version = "0.2.2"
@ -3926,15 +3683,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f"
dependencies = [ dependencies = [
"bitflags 2.9.4", "bitflags 2.9.4",
"block2 0.5.1", "block2",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-cloud-kit 0.2.2", "objc2-cloud-kit",
"objc2-core-data 0.2.2", "objc2-core-data",
"objc2-core-image 0.2.2", "objc2-core-image",
"objc2-core-location", "objc2-core-location",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
"objc2-link-presentation", "objc2-link-presentation",
"objc2-quartz-core 0.2.2", "objc2-quartz-core",
"objc2-symbols", "objc2-symbols",
"objc2-uniform-type-identifiers", "objc2-uniform-type-identifiers",
"objc2-user-notifications", "objc2-user-notifications",
@ -3946,7 +3703,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe"
dependencies = [ dependencies = [
"block2 0.5.1", "block2",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
] ]
@ -3958,7 +3715,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3"
dependencies = [ dependencies = [
"bitflags 2.9.4", "bitflags 2.9.4",
"block2 0.5.1", "block2",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-core-location", "objc2-core-location",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
@ -4095,16 +3852,6 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "ordered-stream"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50"
dependencies = [
"futures-core",
"pin-project-lite",
]
[[package]] [[package]]
name = "ouroboros" name = "ouroboros"
version = "0.18.5" version = "0.18.5"
@ -5215,17 +4962,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_repr"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "serde_spanned" name = "serde_spanned"
version = "0.6.9" version = "0.6.9"
@ -5479,7 +5215,7 @@ dependencies = [
"memmap2", "memmap2",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
"objc2-quartz-core 0.2.2", "objc2-quartz-core",
"raw-window-handle 0.6.2", "raw-window-handle 0.6.2",
"redox_syscall 0.5.17", "redox_syscall 0.5.17",
"rustix 0.38.44", "rustix 0.38.44",
@ -6266,17 +6002,6 @@ version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
[[package]]
name = "uds_windows"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9"
dependencies = [
"memoffset",
"tempfile",
"winapi",
]
[[package]] [[package]]
name = "unicase" name = "unicase"
version = "2.8.1" version = "2.8.1"
@ -7055,28 +6780,6 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "windows"
version = "0.61.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
dependencies = [
"windows-collections",
"windows-core 0.61.2",
"windows-future",
"windows-link 0.1.3",
"windows-numerics",
]
[[package]]
name = "windows-collections"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
dependencies = [
"windows-core 0.61.2",
]
[[package]] [[package]]
name = "windows-core" name = "windows-core"
version = "0.57.0" version = "0.57.0"
@ -7115,17 +6818,6 @@ dependencies = [
"windows-strings 0.4.2", "windows-strings 0.4.2",
] ]
[[package]]
name = "windows-future"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
dependencies = [
"windows-core 0.61.2",
"windows-link 0.1.3",
"windows-threading",
]
[[package]] [[package]]
name = "windows-implement" name = "windows-implement"
version = "0.57.0" version = "0.57.0"
@ -7204,16 +6896,6 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
[[package]]
name = "windows-numerics"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
dependencies = [
"windows-core 0.61.2",
"windows-link 0.1.3",
]
[[package]] [[package]]
name = "windows-registry" name = "windows-registry"
version = "0.5.3" version = "0.5.3"
@ -7388,15 +7070,6 @@ dependencies = [
"windows_x86_64_msvc 0.53.0", "windows_x86_64_msvc 0.53.0",
] ]
[[package]]
name = "windows-threading"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
dependencies = [
"windows-link 0.1.3",
]
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.42.2" version = "0.42.2"
@ -7586,7 +7259,7 @@ dependencies = [
"android-activity", "android-activity",
"atomic-waker", "atomic-waker",
"bitflags 2.9.4", "bitflags 2.9.4",
"block2 0.5.1", "block2",
"bytemuck", "bytemuck",
"calloop", "calloop",
"cfg_aliases", "cfg_aliases",
@ -7600,7 +7273,7 @@ dependencies = [
"memmap2", "memmap2",
"ndk", "ndk",
"objc2 0.5.2", "objc2 0.5.2",
"objc2-app-kit 0.2.2", "objc2-app-kit",
"objc2-foundation 0.2.2", "objc2-foundation 0.2.2",
"objc2-ui-kit", "objc2-ui-kit",
"orbclient", "orbclient",
@ -7763,66 +7436,6 @@ dependencies = [
"synstructure", "synstructure",
] ]
[[package]]
name = "zbus"
version = "5.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67a073be99ace1adc48af593701c8015cd9817df372e14a1a6b0ee8f8bf043be"
dependencies = [
"async-broadcast",
"async-executor",
"async-io",
"async-lock",
"async-process",
"async-recursion",
"async-task",
"async-trait",
"blocking",
"enumflags2",
"event-listener",
"futures-core",
"futures-lite",
"hex",
"nix",
"ordered-stream",
"serde",
"serde_repr",
"tracing",
"uds_windows",
"windows-sys 0.60.2",
"winnow",
"zbus_macros",
"zbus_names",
"zvariant",
]
[[package]]
name = "zbus_macros"
version = "5.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e80cd713a45a49859dcb648053f63265f4f2851b6420d47a958e5697c68b131"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"zbus_names",
"zvariant",
"zvariant_utils",
]
[[package]]
name = "zbus_names"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97"
dependencies = [
"serde",
"static_assertions",
"winnow",
"zvariant",
]
[[package]] [[package]]
name = "zeno" name = "zeno"
version = "0.3.3" version = "0.3.3"
@ -7932,43 +7545,3 @@ checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713"
dependencies = [ dependencies = [
"zune-core", "zune-core",
] ]
[[package]]
name = "zvariant"
version = "5.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "999dd3be73c52b1fccd109a4a81e4fcd20fab1d3599c8121b38d04e1419498db"
dependencies = [
"endi",
"enumflags2",
"serde",
"winnow",
"zvariant_derive",
"zvariant_utils",
]
[[package]]
name = "zvariant_derive"
version = "5.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6643fd0b26a46d226bd90d3f07c1b5321fe9bb7f04673cb37ac6d6883885b68e"
dependencies = [
"proc-macro-crate",
"proc-macro2",
"quote",
"syn",
"zvariant_utils",
]
[[package]]
name = "zvariant_utils"
version = "3.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6949d142f89f6916deca2232cf26a8afacf2b9fdc35ce766105e104478be599"
dependencies = [
"proc-macro2",
"quote",
"serde",
"syn",
"winnow",
]

View file

@ -22,7 +22,7 @@ all-features = true
maintenance = { status = "actively-developed" } maintenance = { status = "actively-developed" }
[features] [features]
default = ["wgpu", "tiny-skia", "crisp", "web-colors", "auto-detect-theme", "thread-pool"] default = ["wgpu", "tiny-skia", "crisp", "web-colors", "thread-pool"]
# Enables the `wgpu` GPU-accelerated renderer backend # Enables the `wgpu` GPU-accelerated renderer backend
wgpu = ["iced_renderer/wgpu", "iced_widget/wgpu"] wgpu = ["iced_renderer/wgpu", "iced_widget/wgpu"]
# Enables the `tiny-skia` software renderer backend # Enables the `tiny-skia` software renderer backend
@ -67,8 +67,6 @@ highlighter = ["iced_highlighter", "iced_widget/highlighter"]
advanced = ["iced_core/advanced", "iced_widget/advanced"] advanced = ["iced_core/advanced", "iced_widget/advanced"]
# Embeds Fira Sans into the final application; useful for testing and Wasm builds # Embeds Fira Sans into the final application; useful for testing and Wasm builds
fira-sans = ["iced_renderer/fira-sans"] fira-sans = ["iced_renderer/fira-sans"]
# Auto-detects light/dark mode for the built-in theme
auto-detect-theme = ["iced_core/auto-detect-theme"]
# Enables basic text shaping by default # Enables basic text shaping by default
basic-shaping = ["iced_core/basic-shaping"] basic-shaping = ["iced_core/basic-shaping"]
# Enables advanced text shaping by default # Enables advanced text shaping by default
@ -218,9 +216,6 @@ wgpu = "26.0"
window_clipboard = "0.4.1" window_clipboard = "0.4.1"
winit = { git = "https://github.com/iced-rs/winit.git", rev = "11414b6aa45699f038114e61b4ddf5102b2d3b4b" } winit = { git = "https://github.com/iced-rs/winit.git", rev = "11414b6aa45699f038114e61b4ddf5102b2d3b4b" }
mundy.version = "0.2"
mundy.default-features = false
[workspace.lints.rust] [workspace.lints.rust]
rust_2018_idioms = { level = "deny", priority = -1 } rust_2018_idioms = { level = "deny", priority = -1 }
missing_debug_implementations = "deny" missing_debug_implementations = "deny"

View file

@ -14,7 +14,6 @@ keywords.workspace = true
workspace = true workspace = true
[features] [features]
auto-detect-theme = ["dep:mundy"]
advanced = [] advanced = []
crisp = [] crisp = []
basic-shaping = [] basic-shaping = []
@ -32,10 +31,6 @@ smol_str.workspace = true
thiserror.workspace = true thiserror.workspace = true
web-time.workspace = true web-time.workspace = true
mundy.workspace = true
mundy.optional = true
mundy.features = ["async-io", "color-scheme"]
serde.workspace = true serde.workspace = true
serde.optional = true serde.optional = true
serde.features = ["derive"] serde.features = ["derive"]

View file

@ -166,36 +166,6 @@ impl Theme {
} }
} }
impl Default for Theme {
fn default() -> Self {
#[cfg(feature = "auto-detect-theme")]
{
use crate::time::Duration;
use std::sync::LazyLock;
static DEFAULT: LazyLock<Theme> = LazyLock::new(|| {
let color_scheme = mundy::Preferences::once_blocking(
mundy::Interest::ColorScheme,
Duration::from_millis(100),
)
.map(|preferences| preferences.color_scheme)
.unwrap_or_default();
match color_scheme {
mundy::ColorScheme::Dark => Theme::Dark,
mundy::ColorScheme::Light
| mundy::ColorScheme::NoPreference => Theme::Light,
}
});
DEFAULT.clone()
}
#[cfg(not(feature = "auto-detect-theme"))]
Theme::Light
}
}
impl fmt::Display for Theme { impl fmt::Display for Theme {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
@ -261,6 +231,18 @@ impl fmt::Display for Custom {
} }
} }
/// A theme mode, denoting the tone or brightness of a theme.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Mode {
/// No specific tone.
#[default]
None,
/// A mode referring to themes with light tones.
Light,
/// A mode referring to themes with dark tones.
Dark,
}
/// The base style of a theme. /// The base style of a theme.
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub struct Style { pub struct Style {
@ -273,6 +255,9 @@ pub struct Style {
/// The default blank style of a theme. /// The default blank style of a theme.
pub trait Base { pub trait Base {
/// Returns the default theme for the preferred [`Mode`].
fn default(preference: Mode) -> Self;
/// Returns the default base [`Style`] of a theme. /// Returns the default base [`Style`] of a theme.
fn base(&self) -> Style; fn base(&self) -> Style;
@ -285,6 +270,13 @@ pub trait Base {
} }
impl Base for Theme { impl Base for Theme {
fn default(preference: Mode) -> Self {
match preference {
Mode::None | Mode::Light => Self::Light,
Mode::Dark => Self::Dark,
}
}
fn base(&self) -> Style { fn base(&self) -> Style {
default(self) default(self)
} }

View file

@ -12,7 +12,7 @@ mod time_machine;
use crate::core::border; use crate::core::border;
use crate::core::keyboard; use crate::core::keyboard;
use crate::core::theme::{self, Base, Theme}; use crate::core::theme::{self, Theme};
use crate::core::time::seconds; use crate::core::time::seconds;
use crate::core::window; use crate::core::window;
use crate::core::{Alignment::Center, Color, Element, Length::Fill}; use crate::core::{Alignment::Center, Color, Element, Length::Fill};
@ -90,7 +90,11 @@ where
state.subscription(&self.program) state.subscription(&self.program)
} }
fn theme(&self, state: &Self::State, window: window::Id) -> Self::Theme { fn theme(
&self,
state: &Self::State,
window: window::Id,
) -> Option<Self::Theme> {
state.theme(&self.program, window) state.theme(&self.program, window)
} }
@ -307,14 +311,12 @@ where
} }
}; };
let theme = program.theme(state, window); fn derive_theme<T: theme::Base>(theme: &T) -> Theme {
let derive_theme = move || {
theme theme
.palette() .palette()
.map(|palette| Theme::custom("iced devtools", palette)) .map(|palette| Theme::custom("iced devtools", palette))
.unwrap_or_default() .unwrap_or(Theme::Dark)
}; }
let mode = match &self.mode { let mode = match &self.mode {
Mode::None => None, Mode::None => None,
@ -340,7 +342,7 @@ where
} }
} }
.map(|mode| { .map(|mode| {
themer(derive_theme(), Element::from(mode).map(Event::Message)) themer(derive_theme, Element::from(mode).map(Event::Message))
}); });
let notification = self let notification = self
@ -359,7 +361,7 @@ where
.push_maybe(mode.map(opaque)) .push_maybe(mode.map(opaque))
.push_maybe(notification.map(|notification| { .push_maybe(notification.map(|notification| {
themer( themer(
derive_theme(), derive_theme,
bottom_right(opaque( bottom_right(opaque(
container(notification) container(notification)
.padding(10) .padding(10)
@ -389,7 +391,7 @@ where
Subscription::batch([subscription, hotkeys, commands]) Subscription::batch([subscription, hotkeys, commands])
} }
fn theme(&self, program: &P, window: window::Id) -> P::Theme { fn theme(&self, program: &P, window: window::Id) -> Option<P::Theme> {
program.theme(self.state(), window) program.theme(self.state(), window)
} }

View file

@ -10,7 +10,7 @@ use iced::{Element, Fill, Point, Rectangle, Renderer, Subscription, Theme};
pub fn main() -> iced::Result { pub fn main() -> iced::Result {
iced::application(Arc::new, Arc::update, Arc::view) iced::application(Arc::new, Arc::update, Arc::view)
.subscription(Arc::subscription) .subscription(Arc::subscription)
.theme(|_| Theme::Dark) .theme(Theme::Dark)
.run() .run()
} }

View file

@ -4,7 +4,7 @@ use iced::{Element, Theme};
pub fn main() -> iced::Result { pub fn main() -> iced::Result {
iced::application(Example::default, Example::update, Example::view) iced::application(Example::default, Example::update, Example::view)
.theme(|_| Theme::CatppuccinMocha) .theme(Theme::CatppuccinMocha)
.run() .run()
} }

View file

@ -11,7 +11,7 @@ use iced::{
pub fn main() -> iced::Result { pub fn main() -> iced::Result {
iced::application(Image::default, Image::update, Image::view) iced::application(Image::default, Image::update, Image::view)
.subscription(Image::subscription) .subscription(Image::subscription)
.theme(|_| Theme::TokyoNight) .theme(Theme::TokyoNight)
.run() .run()
} }

View file

@ -16,7 +16,7 @@ pub fn main() -> iced::Result {
iced::application(GameOfLife::default, GameOfLife::update, GameOfLife::view) iced::application(GameOfLife::default, GameOfLife::update, GameOfLife::view)
.subscription(GameOfLife::subscription) .subscription(GameOfLife::subscription)
.theme(|_| Theme::Dark) .theme(Theme::Dark)
.centered() .centered()
.run() .run()
} }

View file

@ -19,11 +19,11 @@ pub fn main() -> iced::Result {
.run() .run()
} }
#[derive(Default, Debug)] #[derive(Debug, Default)]
struct Layout { struct Layout {
example: Example, example: Example,
explain: bool, explain: bool,
theme: Theme, theme: Option<Theme>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -51,7 +51,7 @@ impl Layout {
self.explain = explain; self.explain = explain;
} }
Message::ThemeSelected(theme) => { Message::ThemeSelected(theme) => {
self.theme = theme; self.theme = Some(theme);
} }
} }
} }
@ -74,7 +74,8 @@ impl Layout {
horizontal_space(), horizontal_space(),
checkbox("Explain", self.explain) checkbox("Explain", self.explain)
.on_toggle(Message::ExplainToggled), .on_toggle(Message::ExplainToggled),
pick_list(Theme::ALL, Some(&self.theme), Message::ThemeSelected), pick_list(Theme::ALL, self.theme.as_ref(), Message::ThemeSelected)
.placeholder("Theme"),
] ]
.spacing(20) .spacing(20)
.align_y(Center); .align_y(Center);
@ -116,7 +117,7 @@ impl Layout {
.into() .into()
} }
fn theme(&self) -> Theme { fn theme(&self) -> Option<Theme> {
self.theme.clone() self.theme.clone()
} }
} }

View file

@ -138,12 +138,8 @@ impl Example {
} }
} }
fn theme(&self, window: window::Id) -> Theme { fn theme(&self, window: window::Id) -> Option<Theme> {
if let Some(window) = self.windows.get(&window) { Some(self.windows.get(&window)?.theme.clone())
window.theme.clone()
} else {
Theme::default()
}
} }
fn scale_factor(&self, window: window::Id) -> f32 { fn scale_factor(&self, window: window::Id) -> f32 {

View file

@ -20,7 +20,7 @@ struct QRGenerator {
data: String, data: String,
qr_code: Option<qr_code::Data>, qr_code: Option<qr_code::Data>,
total_size: Option<f32>, total_size: Option<f32>,
theme: Theme, theme: Option<Theme>,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -58,7 +58,7 @@ impl QRGenerator {
self.total_size = Some(total_size); self.total_size = Some(total_size);
} }
Message::ThemeChanged(theme) => { Message::ThemeChanged(theme) => {
self.theme = theme; self.theme = Some(theme);
} }
} }
} }
@ -78,7 +78,8 @@ impl QRGenerator {
let choose_theme = row![ let choose_theme = row![
text("Theme:"), text("Theme:"),
pick_list(Theme::ALL, Some(&self.theme), Message::ThemeChanged,) pick_list(Theme::ALL, self.theme.as_ref(), Message::ThemeChanged)
.placeholder("Theme")
] ]
.spacing(10) .spacing(10)
.align_y(Center); .align_y(Center);
@ -107,7 +108,7 @@ impl QRGenerator {
center(content).padding(20).into() center(content).padding(20).into()
} }
fn theme(&self) -> Theme { fn theme(&self) -> Option<Theme> {
self.theme.clone() self.theme.clone()
} }
} }

View file

@ -15,7 +15,7 @@ pub fn main() -> iced::Result {
#[derive(Default)] #[derive(Default)]
struct Styling { struct Styling {
theme: Theme, theme: Option<Theme>,
input_value: String, input_value: String,
slider_value: f32, slider_value: f32,
checkbox_value: bool, checkbox_value: bool,
@ -38,7 +38,7 @@ impl Styling {
fn update(&mut self, message: Message) { fn update(&mut self, message: Message) {
match message { match message {
Message::ThemeChanged(theme) => { Message::ThemeChanged(theme) => {
self.theme = theme; self.theme = Some(theme);
} }
Message::InputChanged(value) => self.input_value = value, Message::InputChanged(value) => self.input_value = value,
Message::ButtonPressed => {} Message::ButtonPressed => {}
@ -46,20 +46,20 @@ impl Styling {
Message::CheckboxToggled(value) => self.checkbox_value = value, Message::CheckboxToggled(value) => self.checkbox_value = value,
Message::TogglerToggled(value) => self.toggler_value = value, Message::TogglerToggled(value) => self.toggler_value = value,
Message::PreviousTheme | Message::NextTheme => { Message::PreviousTheme | Message::NextTheme => {
if let Some(current) = Theme::ALL if let Some(current) = Theme::ALL.iter().position(|candidate| {
.iter() self.theme.as_ref() == Some(candidate)
.position(|candidate| &self.theme == candidate) }) {
{ self.theme =
self.theme = if matches!(message, Message::NextTheme) { Some(if matches!(message, Message::NextTheme) {
Theme::ALL[(current + 1) % Theme::ALL.len()].clone() Theme::ALL[(current + 1) % Theme::ALL.len()].clone()
} else if current == 0 { } else if current == 0 {
Theme::ALL Theme::ALL
.last() .last()
.expect("Theme::ALL must not be empty") .expect("Theme::ALL must not be empty")
.clone() .clone()
} else { } else {
Theme::ALL[current - 1].clone() Theme::ALL[current - 1].clone()
}; });
} }
} }
} }
@ -68,8 +68,9 @@ impl Styling {
fn view(&self) -> Element<'_, Message> { fn view(&self) -> Element<'_, Message> {
let choose_theme = column![ let choose_theme = column![
text("Theme:"), text("Theme:"),
pick_list(Theme::ALL, Some(&self.theme), Message::ThemeChanged) pick_list(Theme::ALL, self.theme.as_ref(), Message::ThemeChanged)
.width(Fill), .width(Fill)
.placeholder("System"),
] ]
.spacing(10); .spacing(10);
@ -190,7 +191,7 @@ impl Styling {
}) })
} }
fn theme(&self) -> Theme { fn theme(&self) -> Option<Theme> {
self.theme.clone() self.theme.clone()
} }
} }
@ -210,9 +211,7 @@ mod tests {
.cloned() .cloned()
.map(|theme| { .map(|theme| {
let mut styling = Styling::default(); let mut styling = Styling::default();
styling.update(Message::ThemeChanged(theme)); styling.update(Message::ThemeChanged(theme.clone()));
let theme = styling.theme();
let mut ui = simulator(styling.view()); let mut ui = simulator(styling.view());
let snapshot = ui.snapshot(&theme)?; let snapshot = ui.snapshot(&theme)?;

View file

@ -8,7 +8,7 @@ use iced::{Center, Element, Fill, Font, Right, Theme};
pub fn main() -> iced::Result { pub fn main() -> iced::Result {
iced::application(Table::new, Table::update, Table::view) iced::application(Table::new, Table::update, Table::view)
.theme(|_| Theme::CatppuccinMocha) .theme(Theme::CatppuccinMocha)
.run() .run()
} }

View file

@ -1,11 +1,10 @@
use iced::border;
use iced::widget::{Button, Column, Container, Slider}; use iced::widget::{Button, Column, Container, Slider};
use iced::widget::{ use iced::widget::{
button, center_x, center_y, checkbox, column, horizontal_space, image, button, center_x, center_y, checkbox, column, horizontal_space, image,
radio, rich_text, row, scrollable, slider, span, text, text_input, toggler, radio, rich_text, row, scrollable, slider, span, text, text_input, toggler,
vertical_space, vertical_space,
}; };
use iced::{Center, Color, Element, Fill, Font, Pixels, Theme}; use iced::{Center, Color, Element, Fill, Font, Pixels, color};
pub fn main() -> iced::Result { pub fn main() -> iced::Result {
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
@ -201,7 +200,7 @@ impl Tour {
Self::container("Welcome!") Self::container("Welcome!")
.push( .push(
"This is a simple tour meant to showcase a bunch of \ "This is a simple tour meant to showcase a bunch of \
widgets that can be easily implemented on top of Iced.", widgets that come bundled in Iced.",
) )
.push( .push(
"Iced is a cross-platform GUI library for Rust focused on \ "Iced is a cross-platform GUI library for Rust focused on \
@ -216,28 +215,19 @@ impl Tour {
built on top of wgpu, a graphics library supporting Vulkan, \ built on top of wgpu, a graphics library supporting Vulkan, \
Metal, DX11, and DX12.", Metal, DX11, and DX12.",
) )
.push({ .push(
let theme = Theme::default();
let palette = theme.extended_palette();
rich_text![ rich_text![
"Additionally, this tour can also run on WebAssembly ", "Additionally, this tour can also run on WebAssembly ",
"by leveraging ", "by leveraging ",
span("trunk") span("trunk")
.color(palette.primary.base.color) .color(color!(0x0000FF))
.background(palette.background.weakest.color) .underline(true)
.border(
border::rounded(2)
.width(1)
.color(palette.background.weak.color)
)
.padding([0, 2])
.font(Font::MONOSPACE) .font(Font::MONOSPACE)
.link(Message::OpenTrunk), .link(Message::OpenTrunk),
"." "."
] ]
.on_link_click(std::convert::identity) .on_link_click(std::convert::identity),
}) )
.push( .push(
"You will need to interact with the UI in order to reach \ "You will need to interact with the UI in order to reach \
the end!", the end!",

View file

@ -11,7 +11,7 @@ pub fn main() -> iced::Result {
VectorialText::update, VectorialText::update,
VectorialText::view, VectorialText::view,
) )
.theme(|_| Theme::Dark) .theme(Theme::Dark)
.run() .run()
} }

View file

@ -12,7 +12,7 @@ use iced::{
pub fn main() -> iced::Result { pub fn main() -> iced::Result {
iced::application(Example::default, Example::update, Example::view) iced::application(Example::default, Example::update, Example::view)
.subscription(Example::subscription) .subscription(Example::subscription)
.theme(|_| Theme::Dark) .theme(Theme::Dark)
.run() .run()
} }

View file

@ -25,7 +25,7 @@ pub trait Program: Sized {
type Message: Message + 'static; type Message: Message + 'static;
/// The theme of the program. /// The theme of the program.
type Theme: Default + theme::Base; type Theme: theme::Base;
/// The renderer of the program. /// The renderer of the program.
type Renderer: Renderer; type Renderer: Renderer;
@ -86,8 +86,12 @@ pub trait Program: Sized {
Subscription::none() Subscription::none()
} }
fn theme(&self, _state: &Self::State, _window: window::Id) -> Self::Theme { fn theme(
<Self::Theme as Default>::default() &self,
_state: &Self::State,
_window: window::Id,
) -> Option<Self::Theme> {
None
} }
fn style(&self, _state: &Self::State, theme: &Self::Theme) -> theme::Style { fn style(&self, _state: &Self::State, theme: &Self::Theme) -> theme::Style {
@ -152,7 +156,7 @@ pub fn with_title<P: Program>(
&self, &self,
state: &Self::State, state: &Self::State,
window: window::Id, window: window::Id,
) -> Self::Theme { ) -> Option<Self::Theme> {
self.program.theme(state, window) self.program.theme(state, window)
} }
@ -238,7 +242,7 @@ pub fn with_subscription<P: Program>(
&self, &self,
state: &Self::State, state: &Self::State,
window: window::Id, window: window::Id,
) -> Self::Theme { ) -> Option<Self::Theme> {
self.program.theme(state, window) self.program.theme(state, window)
} }
@ -264,7 +268,7 @@ pub fn with_subscription<P: Program>(
/// Decorates a [`Program`] with the given theme function. /// Decorates a [`Program`] with the given theme function.
pub fn with_theme<P: Program>( pub fn with_theme<P: Program>(
program: P, program: P,
f: impl Fn(&P::State, window::Id) -> P::Theme, f: impl Fn(&P::State, window::Id) -> Option<P::Theme>,
) -> impl Program<State = P::State, Message = P::Message, Theme = P::Theme> { ) -> impl Program<State = P::State, Message = P::Message, Theme = P::Theme> {
struct WithTheme<P, F> { struct WithTheme<P, F> {
program: P, program: P,
@ -273,7 +277,7 @@ pub fn with_theme<P: Program>(
impl<P: Program, F> Program for WithTheme<P, F> impl<P: Program, F> Program for WithTheme<P, F>
where where
F: Fn(&P::State, window::Id) -> P::Theme, F: Fn(&P::State, window::Id) -> Option<P::Theme>,
{ {
type State = P::State; type State = P::State;
type Message = P::Message; type Message = P::Message;
@ -285,7 +289,7 @@ pub fn with_theme<P: Program>(
&self, &self,
state: &Self::State, state: &Self::State,
window: window::Id, window: window::Id,
) -> Self::Theme { ) -> Option<Self::Theme> {
(self.theme)(state, window) (self.theme)(state, window)
} }
@ -407,7 +411,7 @@ pub fn with_style<P: Program>(
&self, &self,
state: &Self::State, state: &Self::State,
window: window::Id, window: window::Id,
) -> Self::Theme { ) -> Option<Self::Theme> {
self.program.theme(state, window) self.program.theme(state, window)
} }
@ -478,7 +482,7 @@ pub fn with_scale_factor<P: Program>(
&self, &self,
state: &Self::State, state: &Self::State,
window: window::Id, window: window::Id,
) -> Self::Theme { ) -> Option<Self::Theme> {
self.program.theme(state, window) self.program.theme(state, window)
} }
@ -561,7 +565,7 @@ pub fn with_executor<P: Program, E: Executor>(
&self, &self,
state: &Self::State, state: &Self::State,
window: window::Id, window: window::Id,
) -> Self::Theme { ) -> Option<Self::Theme> {
self.program.theme(state, window) self.program.theme(state, window)
} }
@ -628,7 +632,7 @@ impl<P: Program> Instance<P> {
} }
/// Returns the current theme of the [`Instance`]. /// Returns the current theme of the [`Instance`].
pub fn theme(&self, window: window::Id) -> P::Theme { pub fn theme(&self, window: window::Id) -> Option<P::Theme> {
self.program.theme(&self.state, window) self.program.theme(&self.state, window)
} }

View file

@ -7,7 +7,7 @@
//! //!
//! pub fn main() -> iced::Result { //! pub fn main() -> iced::Result {
//! iced::application(u64::default, update, view) //! iced::application(u64::default, update, view)
//! .theme(|_| Theme::Dark) //! .theme(Theme::Dark)
//! .centered() //! .centered()
//! .run() //! .run()
//! } //! }
@ -35,7 +35,7 @@ use crate::shell;
use crate::theme; use crate::theme;
use crate::window; use crate::window;
use crate::{ use crate::{
Element, Executor, Font, Result, Settings, Size, Subscription, Task, Element, Executor, Font, Result, Settings, Size, Subscription, Task, Theme,
}; };
use iced_debug as debug; use iced_debug as debug;
@ -82,7 +82,7 @@ pub fn application<State, Message, Theme, Renderer>(
where where
State: 'static, State: 'static,
Message: program::Message + 'static, Message: program::Message + 'static,
Theme: Default + theme::Base, Theme: theme::Base,
Renderer: program::Renderer, Renderer: program::Renderer,
{ {
use std::marker::PhantomData; use std::marker::PhantomData;
@ -101,7 +101,7 @@ where
for Instance<State, Message, Theme, Renderer, Boot, Update, View> for Instance<State, Message, Theme, Renderer, Boot, Update, View>
where where
Message: program::Message + 'static, Message: program::Message + 'static,
Theme: Default + theme::Base, Theme: theme::Base,
Renderer: program::Renderer, Renderer: program::Renderer,
Boot: self::Boot<State, Message>, Boot: self::Boot<State, Message>,
Update: self::Update<State, Message>, Update: self::Update<State, Message>,
@ -355,13 +355,13 @@ impl<P: Program> Application<P> {
/// Sets the theme logic of the [`Application`]. /// Sets the theme logic of the [`Application`].
pub fn theme( pub fn theme(
self, self,
f: impl Fn(&P::State) -> P::Theme, f: impl ThemeFn<P::State, P::Theme>,
) -> Application< ) -> Application<
impl Program<State = P::State, Message = P::Message, Theme = P::Theme>, impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
> { > {
Application { Application {
raw: program::with_theme(self.raw, move |state, _window| { raw: program::with_theme(self.raw, move |state, _window| {
debug::hot(|| f(state)) debug::hot(|| f.theme(state))
}), }),
settings: self.settings, settings: self.settings,
window: self.window, window: self.window,
@ -529,3 +529,25 @@ where
self(state).into() self(state).into()
} }
} }
/// TODO
pub trait ThemeFn<State, Theme> {
/// TODO
fn theme(&self, state: &State) -> Option<Theme>;
}
impl<State> ThemeFn<State, Theme> for Theme {
fn theme(&self, _state: &State) -> Option<Theme> {
Some(self.clone())
}
}
impl<F, T, State, Theme> ThemeFn<State, Theme> for F
where
F: Fn(&State) -> T,
T: Into<Option<Theme>>,
{
fn theme(&self, state: &State) -> Option<Theme> {
(self)(state).into()
}
}

View file

@ -30,7 +30,7 @@ pub fn timed<State, Message, Theme, Renderer>(
where where
State: 'static, State: 'static,
Message: program::Message + 'static, Message: program::Message + 'static,
Theme: Default + theme::Base + 'static, Theme: theme::Base + 'static,
Renderer: program::Renderer + 'static, Renderer: program::Renderer + 'static,
{ {
use std::marker::PhantomData; use std::marker::PhantomData;
@ -69,7 +69,7 @@ where
> >
where where
Message: program::Message + 'static, Message: program::Message + 'static,
Theme: Default + theme::Base + 'static, Theme: theme::Base + 'static,
Renderer: program::Renderer + 'static, Renderer: program::Renderer + 'static,
Boot: self::Boot<State, Message>, Boot: self::Boot<State, Message>,
Update: self::Update<State, Message>, Update: self::Update<State, Message>,

View file

@ -4,7 +4,9 @@ use crate::program::{self, Program};
use crate::shell; use crate::shell;
use crate::theme; use crate::theme;
use crate::window; use crate::window;
use crate::{Element, Executor, Font, Result, Settings, Subscription, Task}; use crate::{
Element, Executor, Font, Result, Settings, Subscription, Task, Theme,
};
use iced_debug as debug; use iced_debug as debug;
@ -28,7 +30,7 @@ pub fn daemon<State, Message, Theme, Renderer>(
where where
State: 'static, State: 'static,
Message: program::Message + 'static, Message: program::Message + 'static,
Theme: Default + theme::Base, Theme: theme::Base,
Renderer: program::Renderer, Renderer: program::Renderer,
{ {
use std::marker::PhantomData; use std::marker::PhantomData;
@ -47,7 +49,7 @@ where
for Instance<State, Message, Theme, Renderer, Boot, Update, View> for Instance<State, Message, Theme, Renderer, Boot, Update, View>
where where
Message: program::Message + 'static, Message: program::Message + 'static,
Theme: Default + theme::Base, Theme: theme::Base,
Renderer: program::Renderer, Renderer: program::Renderer,
Boot: application::Boot<State, Message>, Boot: application::Boot<State, Message>,
Update: application::Update<State, Message>, Update: application::Update<State, Message>,
@ -202,13 +204,13 @@ impl<P: Program> Daemon<P> {
/// Sets the theme logic of the [`Daemon`]. /// Sets the theme logic of the [`Daemon`].
pub fn theme( pub fn theme(
self, self,
f: impl Fn(&P::State, window::Id) -> P::Theme, f: impl ThemeFn<P::State, P::Theme>,
) -> Daemon< ) -> Daemon<
impl Program<State = P::State, Message = P::Message, Theme = P::Theme>, impl Program<State = P::State, Message = P::Message, Theme = P::Theme>,
> { > {
Daemon { Daemon {
raw: program::with_theme(self.raw, move |state, window| { raw: program::with_theme(self.raw, move |state, window| {
debug::hot(|| f(state, window)) debug::hot(|| f.theme(state, window))
}), }),
settings: self.settings, settings: self.settings,
} }
@ -314,3 +316,25 @@ where
self(state, window).into() self(state, window).into()
} }
} }
/// TODO
pub trait ThemeFn<State, Theme> {
/// TODO
fn theme(&self, state: &State, window: window::Id) -> Option<Theme>;
}
impl<State> ThemeFn<State, Theme> for Theme {
fn theme(&self, _state: &State, _window: window::Id) -> Option<Theme> {
Some(self.clone())
}
}
impl<F, T, State, Theme> ThemeFn<State, Theme> for F
where
F: Fn(&State, window::Id) -> T,
T: Into<Option<Theme>>,
{
fn theme(&self, state: &State, window: window::Id) -> Option<Theme> {
(self)(state, window).into()
}
}

View file

@ -698,7 +698,7 @@ pub fn run<State, Message, Theme, Renderer>(
where where
State: Default + 'static, State: Default + 'static,
Message: program::Message + 'static, Message: program::Message + 'static,
Theme: Default + theme::Base + 'static, Theme: theme::Base + 'static,
Renderer: program::Renderer + 'static, Renderer: program::Renderer + 'static,
{ {
application(State::default, update, view).run() application(State::default, update, view).run()

View file

@ -2063,7 +2063,7 @@ where
/// A widget that applies any `Theme` to its contents. /// A widget that applies any `Theme` to its contents.
pub fn themer<'a, Message, OldTheme, NewTheme, Renderer>( pub fn themer<'a, Message, OldTheme, NewTheme, Renderer>(
new_theme: NewTheme, to_theme: impl Fn(&OldTheme) -> NewTheme,
content: impl Into<Element<'a, Message, NewTheme, Renderer>>, content: impl Into<Element<'a, Message, NewTheme, Renderer>>,
) -> Themer< ) -> Themer<
'a, 'a,
@ -2077,7 +2077,7 @@ where
Renderer: core::Renderer, Renderer: core::Renderer,
NewTheme: Clone, NewTheme: Clone,
{ {
Themer::new(move |_| new_theme.clone(), content) Themer::new(to_theme, content)
} }
/// Creates a [`PaneGrid`] with the given [`pane_grid::State`] and view function. /// Creates a [`PaneGrid`] with the given [`pane_grid::State`] and view function.

View file

@ -595,14 +595,7 @@ async fn run_instance<P>(
} }
} }
debug::theme_changed(|| { let is_first = window_manager.is_empty();
if window_manager.is_empty() {
theme::Base::palette(&program.theme(id))
} else {
None
}
});
let window = window_manager.insert( let window = window_manager.insert(
id, id,
window, window,
@ -613,6 +606,14 @@ async fn run_instance<P>(
exit_on_close_request, exit_on_close_request,
); );
debug::theme_changed(|| {
if is_first {
theme::Base::palette(window.state.theme())
} else {
None
}
});
let logical_size = window.state.logical_size(); let logical_size = window.state.logical_size();
let _ = user_interfaces.insert( let _ = user_interfaces.insert(

View file

@ -21,6 +21,7 @@ where
cursor_position: Option<winit::dpi::PhysicalPosition<f64>>, cursor_position: Option<winit::dpi::PhysicalPosition<f64>>,
modifiers: winit::keyboard::ModifiersState, modifiers: winit::keyboard::ModifiersState,
theme: P::Theme, theme: P::Theme,
theme_mode: theme::Mode,
style: theme::Style, style: theme::Style,
} }
@ -52,7 +53,14 @@ where
) -> Self { ) -> Self {
let title = program.title(window_id); let title = program.title(window_id);
let scale_factor = program.scale_factor(window_id); let scale_factor = program.scale_factor(window_id);
let theme = program.theme(window_id); let theme_mode = match window.theme() {
None => theme::Mode::None,
Some(winit::window::Theme::Light) => theme::Mode::Light,
Some(winit::window::Theme::Dark) => theme::Mode::Dark,
};
let theme = program
.theme(window_id)
.unwrap_or_else(|| <P::Theme as theme::Base>::default(theme_mode));
let style = program.style(&theme); let style = program.style(&theme);
let viewport = { let viewport = {
@ -72,6 +80,7 @@ where
cursor_position: None, cursor_position: None,
modifiers: winit::keyboard::ModifiersState::default(), modifiers: winit::keyboard::ModifiersState::default(),
theme, theme,
theme_mode,
style, style,
} }
} }
@ -216,7 +225,9 @@ where
} }
// Update theme and appearance // Update theme and appearance
self.theme = program.theme(window_id); self.theme = program.theme(window_id).unwrap_or_else(|| {
<P::Theme as theme::Base>::default(self.theme_mode)
});
self.style = program.style(&self.theme); self.style = program.style(&self.theme);
} }
} }