fix: always auto-detect the background color, support setting the window theme (#3207)

Co-authored-by: Alexsander Falcucci <alex.falcucci@gmail.com>
This commit is contained in:
fredizzimo 2025-11-21 07:41:24 +02:00 committed by GitHub
parent ef3333ddf9
commit 701526fbff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 670 additions and 102 deletions

488
Cargo.lock generated
View file

@ -82,6 +82,15 @@ dependencies = [
"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]]
name = "android-properties"
version = "0.2.2"
@ -183,6 +192,29 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
[[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]]
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]]
name = "async-trait"
version = "0.1.89"
@ -262,6 +294,15 @@ 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.3",
]
[[package]]
name = "bumpalo"
version = "3.19.0"
@ -694,6 +735,33 @@ version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[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]]
name = "equivalent"
version = "1.0.2"
@ -716,6 +784,33 @@ version = "3.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59"
[[package]]
name = "event-listener"
version = "5.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
dependencies = [
"concurrent-queue",
"parking",
"pin-project-lite",
]
[[package]]
name = "event-listener-strategy"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
dependencies = [
"event-listener",
"pin-project-lite",
]
[[package]]
name = "fastrand"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]]
name = "fdeflate"
version = "0.3.7"
@ -878,6 +973,19 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
[[package]]
name = "futures-lite"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
dependencies = [
"fastrand",
"futures-core",
"futures-io",
"parking",
"pin-project-lite",
]
[[package]]
name = "futures-macro"
version = "0.3.31"
@ -1078,9 +1186,9 @@ dependencies = [
[[package]]
name = "hashbrown"
version = "0.16.0"
version = "0.16.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
dependencies = [
"allocator-api2",
"equivalent",
@ -1099,6 +1207,12 @@ version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "hex"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "iana-time-zone"
version = "0.1.64"
@ -1138,9 +1252,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "2.12.0"
version = "2.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f"
checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
dependencies = [
"equivalent",
"hashbrown",
@ -1360,6 +1474,15 @@ dependencies = [
"libc",
]
[[package]]
name = "memoffset"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
dependencies = [
"autocfg",
]
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@ -1398,6 +1521,31 @@ dependencies = [
"pxfm",
]
[[package]]
name = "mundy"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d1507867e7cc8ae71ec01ef4a7a4b9f4b1a827324b414a0232b04e19324ec92d"
dependencies = [
"android-build",
"cfg-if",
"dispatch",
"futures-channel",
"futures-lite",
"jni",
"ndk-context",
"objc2 0.6.3",
"objc2-app-kit 0.3.2",
"objc2-foundation 0.3.2",
"pin-project-lite",
"tokio",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"windows",
"zbus",
]
[[package]]
name = "ndk"
version = "0.9.0"
@ -1452,6 +1600,7 @@ dependencies = [
"itertools 0.14.0",
"log",
"lru",
"mundy",
"neovide-derive",
"notify-debouncer-full",
"num",
@ -1501,6 +1650,19 @@ dependencies = [
"syn",
]
[[package]]
name = "nix"
version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
dependencies = [
"bitflags 2.10.0",
"cfg-if",
"cfg_aliases",
"libc",
"memoffset",
]
[[package]]
name = "nom"
version = "7.1.3"
@ -1696,11 +1858,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff"
dependencies = [
"bitflags 2.10.0",
"block2",
"block2 0.5.1",
"libc",
"objc2 0.5.2",
"objc2-core-data",
"objc2-core-image",
"objc2-core-data 0.2.2",
"objc2-core-image 0.2.2",
"objc2-foundation 0.2.2",
"objc2-quartz-core 0.2.2",
]
@ -1712,8 +1874,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c"
dependencies = [
"bitflags 2.10.0",
"block2 0.6.2",
"libc",
"objc2 0.6.3",
"objc2-cloud-kit 0.3.2",
"objc2-core-data 0.3.2",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-core-image 0.3.2",
"objc2-core-text",
"objc2-core-video",
"objc2-foundation 0.3.2",
"objc2-quartz-core 0.3.2",
]
@ -1725,19 +1895,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009"
dependencies = [
"bitflags 2.10.0",
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-core-location",
"objc2-foundation 0.2.2",
]
[[package]]
name = "objc2-cloud-kit"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73ad74d880bb43877038da939b7427bba67e9dd42004a18b809ba7d87cee241c"
dependencies = [
"bitflags 2.10.0",
"objc2 0.6.3",
"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",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
]
@ -1749,11 +1930,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef"
dependencies = [
"bitflags 2.10.0",
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
]
[[package]]
name = "objc2-core-data"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b402a653efbb5e82ce4df10683b6b28027616a2715e90009947d50b8dd298fa"
dependencies = [
"bitflags 2.10.0",
"objc2 0.6.3",
"objc2-foundation 0.3.2",
]
[[package]]
name = "objc2-core-foundation"
version = "0.3.2"
@ -1772,7 +1964,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
dependencies = [
"bitflags 2.10.0",
"dispatch2",
"objc2 0.6.3",
"objc2-core-foundation",
"objc2-io-surface",
]
[[package]]
@ -1781,24 +1976,46 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80"
dependencies = [
"block2",
"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.3",
"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",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-contacts",
"objc2-foundation 0.2.2",
]
[[package]]
name = "objc2-core-text"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d"
dependencies = [
"bitflags 2.10.0",
"objc2 0.6.3",
"objc2-core-foundation",
"objc2-core-graphics",
]
[[package]]
name = "objc2-core-video"
version = "0.3.2"
@ -1806,8 +2023,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6"
dependencies = [
"bitflags 2.10.0",
"objc2 0.6.3",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-io-surface",
]
[[package]]
@ -1823,7 +2042,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8"
dependencies = [
"bitflags 2.10.0",
"block2",
"block2 0.5.1",
"dispatch",
"libc",
"objc2 0.5.2",
@ -1834,6 +2053,19 @@ name = "objc2-foundation"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
dependencies = [
"bitflags 2.10.0",
"block2 0.6.2",
"libc",
"objc2 0.6.3",
"objc2-core-foundation",
]
[[package]]
name = "objc2-io-surface"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d"
dependencies = [
"bitflags 2.10.0",
"objc2 0.6.3",
@ -1846,7 +2078,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398"
dependencies = [
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-app-kit 0.2.2",
"objc2-foundation 0.2.2",
@ -1859,7 +2091,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6"
dependencies = [
"bitflags 2.10.0",
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
]
@ -1882,7 +2114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a"
dependencies = [
"bitflags 2.10.0",
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
"objc2-metal 0.2.2",
@ -1918,11 +2150,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f"
dependencies = [
"bitflags 2.10.0",
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-cloud-kit",
"objc2-core-data",
"objc2-core-image",
"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",
@ -1938,7 +2170,7 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe"
dependencies = [
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-foundation 0.2.2",
]
@ -1950,7 +2182,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3"
dependencies = [
"bitflags 2.10.0",
"block2",
"block2 0.5.1",
"objc2 0.5.2",
"objc2-core-location",
"objc2-foundation 0.2.2",
@ -1992,6 +2224,16 @@ dependencies = [
"libredox",
]
[[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]]
name = "owned_ttf_parser"
version = "0.25.1"
@ -2001,6 +2243,12 @@ dependencies = [
"ttf-parser",
]
[[package]]
name = "parking"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
[[package]]
name = "parking_lot"
version = "0.12.5"
@ -2506,6 +2754,17 @@ dependencies = [
"serde_core",
]
[[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]]
name = "serde_spanned"
version = "1.0.3"
@ -2708,6 +2967,12 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strict-num"
version = "0.1.1"
@ -2774,6 +3039,19 @@ dependencies = [
"xattr",
]
[[package]]
name = "tempfile"
version = "3.23.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
dependencies = [
"fastrand",
"getrandom 0.3.4",
"once_cell",
"rustix 1.1.2",
"windows-sys 0.61.2",
]
[[package]]
name = "thiserror"
version = "1.0.69"
@ -2884,6 +3162,7 @@ dependencies = [
"signal-hook-registry",
"socket2",
"tokio-macros",
"tracing",
"windows-sys 0.61.2",
]
@ -2991,14 +3270,29 @@ checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
dependencies = [
"log",
"pin-project-lite",
"tracing-attributes",
"tracing-core",
]
[[package]]
name = "tracing-attributes"
version = "0.1.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
dependencies = [
"once_cell",
]
[[package]]
name = "tracy-client-sys"
@ -3022,6 +3316,17 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41713888c5ccfd99979fcd1afd47b71652e331b3d4a0e19d30769e80fec76cce"
[[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]]
name = "unicode-ident"
version = "1.0.22"
@ -3040,6 +3345,17 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
dependencies = [
"js-sys",
"serde",
"wasm-bindgen",
]
[[package]]
name = "uzers"
version = "0.12.1"
@ -3294,6 +3610,22 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.11"
@ -3303,6 +3635,12 @@ dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows"
version = "0.62.2"
@ -3665,7 +4003,7 @@ dependencies = [
"android-activity",
"atomic-waker",
"bitflags 2.10.0",
"block2",
"block2 0.5.1",
"bytemuck",
"calloop 0.13.0",
"cfg_aliases",
@ -3836,6 +4174,62 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5"
[[package]]
name = "zbus"
version = "5.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b622b18155f7a93d1cd2dc8c01d2d6a44e08fb9ebb7b3f9e6ed101488bad6c91"
dependencies = [
"async-broadcast",
"async-recursion",
"async-trait",
"enumflags2",
"event-listener",
"futures-core",
"futures-lite",
"hex",
"nix",
"ordered-stream",
"serde",
"serde_repr",
"tokio",
"tracing",
"uds_windows",
"uuid",
"windows-sys 0.61.2",
"winnow",
"zbus_macros",
"zbus_names",
"zvariant",
]
[[package]]
name = "zbus_macros"
version = "5.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cdb94821ca8a87ca9c298b5d1cbd80e2a8b67115d99f6e4551ac49e42b6a314"
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]]
name = "zeno"
version = "0.3.3"
@ -3844,20 +4238,60 @@ checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524"
[[package]]
name = "zerocopy"
version = "0.8.27"
version = "0.8.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
checksum = "43fa6694ed34d6e57407afbccdeecfa268c470a7d2a5b0cf49ce9fcc345afb90"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.27"
version = "0.8.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
checksum = "c640b22cd9817fae95be82f0d2f90b11f7605f6c319d16705c459b27ac2cbc26"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "zvariant"
version = "5.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2be61892e4f2b1772727be11630a62664a1826b62efa43a6fe7449521cb8744c"
dependencies = [
"endi",
"enumflags2",
"serde",
"winnow",
"zvariant_derive",
"zvariant_utils",
]
[[package]]
name = "zvariant_derive"
version = "5.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da58575a1b2b20766513b1ec59d8e2e68db2745379f961f86650655e862d2006"
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

@ -64,6 +64,10 @@ indoc = "2.0.5"
itertools = "0.14.0"
log = "0.4.22"
lru = "0.16.0"
mundy = { version = "0.2.0", default-features = false, features = [
"tokio",
"color-scheme",
] }
neovide-derive = { path = "neovide-derive", version = "0.1.4" }
notify-debouncer-full = "0.6.0"
num = "0.4.3"

View file

@ -139,6 +139,16 @@ M.private.dropfile = function(filename, tabs)
}, {})
end
M.private.can_set_background = function()
local info = vim.api.nvim_get_option_info2("background", {})
-- Don't change the background if someone else has set it
if info.was_set and info.last_set_chan ~= args.neovide_channel_id then
return false
else
return true
end
end
M.disable_redraw = function()
-- Wrap inside pcall to avoid errors if Neovide disconnects
pcall(rpcnotify, "neovide.set_redraw", false)

View file

@ -10,6 +10,7 @@ mod ui_commands;
use std::{io::Error, ops::Add, sync::Arc, time::Duration};
use anyhow::{bail, Context, Result};
use futures::StreamExt;
use itertools::Itertools;
use log::info;
use nvim_rs::{error::CallError, Neovim, UiAttachOptions, Value};
@ -111,6 +112,7 @@ async fn launch(
handler: NeovimHandler,
grid_size: Option<GridSize<u32>>,
settings: Arc<Settings>,
colorscheme_stream: &mut mundy::PreferencesStream,
) -> Result<NeovimSession> {
let neovim_instance = neovim_instance(settings.as_ref()).await?;
#[allow(unused_mut)]
@ -148,6 +150,18 @@ async fn launch(
start_ui_command_handler(session.neovim.clone(), settings.clone());
settings.read_initial_values(&session.neovim).await?;
let colorscheme = timeout(Duration::from_millis(200), colorscheme_stream.next()).await;
let background = match colorscheme {
Ok(Some(preferences)) => match preferences.color_scheme {
mundy::ColorScheme::Dark => "dark",
mundy::ColorScheme::Light => "light",
mundy::ColorScheme::NoPreference => "dark",
},
Ok(None) => "dark",
Err(..) => "dark",
};
set_background_if_allowed(background, &session.neovim).await;
let mut options = UiAttachOptions::new();
options.set_linegrid_external(true);
options.set_multigrid_external(!cmdline_settings.no_multi_grid);
@ -208,6 +222,36 @@ async fn run(session: NeovimSession, proxy: EventLoopProxy<UserEvent>) {
proxy.send_event(UserEvent::NeovimExited).ok();
}
async fn set_background_if_allowed(background: &str, neovim: &Neovim<NeovimWriter>) {
// Unfortunately neovim does not set the last_set_chan for options when they are set through
// exec_lua. The last_set_sid is also generic, so we are forced to do two calls.
if let Ok(can_set) = neovim
.exec_lua(
"return neovide.private.can_set_background()",
vec![background.into()],
)
.await
{
if can_set.as_bool().unwrap() {
let _ = neovim.set_option("background", background.into()).await;
}
}
}
async fn update_colorscheme(mut stream: mundy::PreferencesStream, neovim: Neovim<NeovimWriter>) {
while let Some(preferences) = stream.next().await {
if let Some(background) = match preferences.color_scheme {
mundy::ColorScheme::Dark => Some("dark"),
mundy::ColorScheme::Light => Some("light"),
// At least KDE Plasma sends this after sending the actual color scheme
// So do nothing
mundy::ColorScheme::NoPreference => None,
} {
set_background_if_allowed(background, &neovim).await;
}
}
}
impl NeovimRuntime {
pub fn new() -> Result<Self, Error> {
let runtime = Builder::new_multi_thread().enable_all().build()?;
@ -221,11 +265,19 @@ impl NeovimRuntime {
grid_size: Option<GridSize<u32>>,
running_tracker: RunningTracker,
settings: Arc<Settings>,
mut colorscheme_stream: mundy::PreferencesStream,
) -> Result<()> {
let handler = start_editor(event_loop_proxy.clone(), running_tracker, settings.clone());
let session = self
.runtime
.block_on(launch(handler, grid_size, settings))?;
let session = self.runtime.block_on(launch(
handler,
grid_size,
settings,
&mut colorscheme_stream,
))?;
self.runtime.spawn(update_colorscheme(
colorscheme_stream,
session.neovim.clone(),
));
self.runtime.spawn(run(session, event_loop_proxy));
Ok(())
}

View file

@ -3,7 +3,7 @@ use std::sync::{Arc, OnceLock};
use anyhow::{Context, Result};
use indoc::indoc;
use log::trace;
use nvim_rs::{call_args, error::CallError, rpc::model::IntoVal, Neovim, Value};
use nvim_rs::{call_args, error::CallError, rpc::model::IntoVal, Neovim};
use strum::AsRefStr;
use tokio::sync::mpsc::unbounded_channel;
@ -124,7 +124,6 @@ pub enum ParallelCommand {
FocusLost,
FocusGained,
DisplayAvailableFonts(Vec<String>),
SetBackground(String),
ShowError { lines: Vec<String> },
}
@ -218,10 +217,6 @@ impl ParallelCommand {
.await
.map(|_| ()) // We don't care about the result
.context("FileDrop failed"),
ParallelCommand::SetBackground(background) => nvim
.set_option_value("background", Value::from(background), nvim_dict! {})
.await
.context("SetBackground failed"),
ParallelCommand::DisplayAvailableFonts(fonts) => display_available_fonts(nvim, fonts)
.await
.context("DisplayAvailableFonts failed"),

View file

@ -8,15 +8,10 @@ mod window;
use std::{collections::HashMap, sync::Arc, thread};
use log::{error, trace, warn};
use tokio::sync::mpsc::unbounded_channel;
use winit::event_loop::EventLoopProxy;
#[cfg(target_os = "macos")]
use winit::window::Theme;
#[cfg(target_os = "macos")]
use skia_safe::Color4f;
use tokio::sync::mpsc::unbounded_channel;
use winit::event_loop::EventLoopProxy;
use winit::window::Theme;
use crate::{
bridge::{GridLineCell, GuiOption, NeovimHandler, RedrawEvent, WindowAnchor},
@ -28,9 +23,6 @@ use crate::{
window::{UserEvent, WindowCommand, WindowSettings},
};
#[cfg(target_os = "macos")]
use crate::{cmd_line::CmdLineSettings, frame::Frame};
pub use cursor::{Cursor, CursorMode, CursorShape};
pub use draw_command_batcher::DrawCommandBatcher;
pub use style::{Colors, Style, UnderlineStyle};
@ -193,15 +185,10 @@ impl Editor {
}
RedrawEvent::DefaultColorsSet { colors } => {
tracy_zone!("EditorDefaultColorsSet");
// Set the dark/light theme of window, so the titlebar text gets correct color.
#[cfg(target_os = "macos")]
if self.settings.get::<CmdLineSettings>().frame == Frame::Transparent {
let _ = self.event_loop_proxy.send_event(
WindowCommand::ThemeChanged(window_theme_for_background(colors.background))
.into(),
);
}
let _ = self.event_loop_proxy.send_event(
WindowCommand::ThemeChanged(window_theme_for_background(colors.background))
.into(),
);
self.draw_command_batcher
.queue(DrawCommand::DefaultStyleChanged(Style::new(colors)));
@ -788,13 +775,11 @@ pub fn start_editor(
/// Based on formula in https://graphicdesign.stackexchange.com/questions/62368/automatically-select-a-foreground-color-based-on-a-background-color
/// Check if the color is light or dark
#[cfg(target_os = "macos")]
fn is_light_color(color: &Color4f) -> bool {
0.2126 * color.r + 0.7152 * color.g + 0.0722 * color.b > 0.5
}
/// Get the proper dark/light theme for a background_color.
#[cfg(target_os = "macos")]
fn window_theme_for_background(background_color: Option<Color4f>) -> Option<Theme> {
background_color?;

View file

@ -79,6 +79,9 @@ use crate::settings::{load_last_window_settings, Config, PersistentWindowSetting
pub use profiling::startup_profiler;
#[cfg(target_os = "macos")]
use crate::frame::Frame;
const DEFAULT_BACKTRACES_FILE: &str = "neovide_backtraces.log";
const BACKTRACES_FILE_ENV_VAR: &str = "NEOVIDE_BACKTRACES";
const REQUEST_MESSAGE: &str = "This is a bug and we would love for it to be reported to https://github.com/neovide/neovide/issues";
@ -105,6 +108,8 @@ fn main() -> ExitCode {
let event_loop = create_event_loop();
clipboard::init(&event_loop);
let colorscheme_stream = mundy::Preferences::stream(mundy::Interest::ColorScheme);
let running_tracker = RunningTracker::new();
let settings = Arc::new(Settings::new());
@ -112,6 +117,7 @@ fn main() -> ExitCode {
event_loop.create_proxy(),
running_tracker.clone(),
settings.clone(),
colorscheme_stream,
) {
Err(err) => handle_startup_errors(err, event_loop, settings.clone()),
Ok((window_size, initial_config, runtime)) => {
@ -144,6 +150,7 @@ fn setup(
proxy: EventLoopProxy<UserEvent>,
running_tracker: RunningTracker,
settings: Arc<Settings>,
colorscheme_stream: mundy::PreferencesStream,
) -> Result<(WindowSize, Config, NeovimRuntime)> {
// --------------
// | Architecture |
@ -252,6 +259,15 @@ fn setup(
trace!("Neovide version: {}", crate_version!());
// Set BgColor by default when using a transparent frame, so the titlebar text gets correct
// color.
#[cfg(target_os = "macos")]
if settings.get::<CmdLineSettings>().frame == Frame::Transparent {
let mut window_settings = settings.get::<WindowSettings>();
window_settings.theme = window::ThemeSettings::BgColor;
settings.set(&window_settings);
}
let window_settings = load_last_window_settings().ok();
let window_size = determine_window_size(window_settings.as_ref(), &settings);
let grid_size = match window_size {
@ -266,7 +282,13 @@ fn setup(
};
let mut runtime = NeovimRuntime::new()?;
runtime.launch(proxy, grid_size, running_tracker, settings)?;
runtime.launch(
proxy,
grid_size,
running_tracker,
settings,
colorscheme_stream,
)?;
Ok((window_size, config, runtime))
}

View file

@ -1,7 +1,6 @@
use log::error;
use rmpv::Value;
use crate::settings::*;
use crate::{error_msg, settings::*};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OptionAsMeta {
@ -20,12 +19,12 @@ impl ParseFromValue for OptionAsMeta {
"both" => OptionAsMeta::Both,
"none" => OptionAsMeta::None,
value => {
error!("Setting OptionAsMeta expected one of `only_left`, `only_right`, `both`, or `none`, but received {value:?}");
error_msg!("Setting OptionAsMeta expected one of `only_left`, `only_right`, `both`, or `none`, but received {value:?}");
return;
}
};
} else {
error!("Setting OptionAsMeta expected string, but received {value:?}");
error_msg!("Setting OptionAsMeta expected string, but received {value:?}");
}
}
}

View file

@ -53,7 +53,7 @@ use crate::{
utils::expand_tilde,
};
pub use error_window::show_error_window;
pub use settings::{WindowSettings, WindowSettingsChanged};
pub use settings::{ThemeSettings, WindowSettings, WindowSettingsChanged};
pub use update_loop::ShouldRender;
pub use update_loop::UpdateLoop;
pub use window_wrapper::WinitWindowWrapper;
@ -80,7 +80,6 @@ pub enum WindowCommand {
ListAvailableFonts,
FocusWindow,
Minimize,
#[allow(dead_code)] // Theme change is only used on macOS right now
ThemeChanged(Option<Theme>),
#[cfg(windows)]
RegisterRightClick,
@ -142,13 +141,14 @@ pub fn create_window(
maximized: bool,
title: &str,
settings: &Settings,
theme: Option<Theme>,
) -> WindowConfig {
let cmd_line_settings = settings.get::<CmdLineSettings>();
let icon = load_icon(cmd_line_settings.icon.as_ref());
let window_settings = load_last_window_settings().ok();
let persistent_window_settings = load_last_window_settings().ok();
let previous_position = match window_settings {
let previous_position = match persistent_window_settings {
Some(PersistentWindowSettings::Windowed { position, .. }) => Some(position),
_ => None,
};
@ -160,7 +160,8 @@ pub fn create_window(
.with_cursor(Cursor::Icon(mouse_cursor_icon.parse()))
.with_maximized(maximized)
.with_transparent(true)
.with_visible(false);
.with_visible(false)
.with_theme(theme);
#[cfg(target_family = "unix")]
let window_attributes = window_attributes.with_window_icon(Some(icon));

View file

@ -1,3 +1,5 @@
use rmpv::Value;
use crate::error_msg;
use crate::settings::*;
@ -27,7 +29,7 @@ pub struct WindowSettings {
pub remember_window_size: bool,
pub scale_factor: f32,
pub show_border: bool,
pub theme: String,
pub theme: ThemeSettings,
pub touch_deadzone: f32,
pub touch_drag_timeout: f32,
pub window_blurred: bool,
@ -75,7 +77,7 @@ impl Default for WindowSettings {
remember_window_size: true,
scale_factor: 1.0,
show_border: false,
theme: "".to_string(),
theme: ThemeSettings::Auto,
touch_deadzone: 6.0,
touch_drag_timeout: 0.17,
window_blurred: false,
@ -99,3 +101,41 @@ impl Default for WindowSettings {
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ThemeSettings {
Auto,
Dark,
Light,
BgColor,
}
impl ParseFromValue for ThemeSettings {
fn parse_from_value(&mut self, value: Value) {
if value.is_str() {
*self = match value.as_str().unwrap() {
"auto" => ThemeSettings::Auto,
"dark" => ThemeSettings::Dark,
"light" => ThemeSettings::Light,
"bg_color" => ThemeSettings::BgColor,
value => {
error_msg!("Setting Theme expected one of `auto`, `dark`, `light`, `bg_color`, but received {value:?}");
return;
}
};
} else {
error_msg!("Setting Theme expected string, but received {value:?}");
}
}
}
impl From<ThemeSettings> for Value {
fn from(value: ThemeSettings) -> Self {
match value {
ThemeSettings::Auto => Value::from("auto"),
ThemeSettings::Dark => Value::from("dark"),
ThemeSettings::Light => Value::from("light"),
ThemeSettings::BgColor => Value::from("bg_color"),
}
}
}

View file

@ -30,7 +30,7 @@ use crate::{
MIN_GRID_SIZE,
},
units::{GridRect, GridSize, PixelPos, PixelSize},
window::{create_window, PhysicalSize, ShouldRender, WindowSize},
window::{create_window, PhysicalSize, ShouldRender, ThemeSettings, WindowSize},
CmdLineSettings,
};
#[cfg(windows)]
@ -63,10 +63,6 @@ pub struct WindowPadding {
pub bottom: u32,
}
pub fn set_background(background: &str) {
send_ui(ParallelCommand::SetBackground(background.to_string()));
}
#[derive(PartialEq, PartialOrd)]
enum UIState {
Initing, // Running init.vim/lua
@ -94,6 +90,7 @@ pub struct WinitWindowWrapper {
is_minimized: bool,
ime_enabled: bool,
ime_area: (dpi::PhysicalPosition<u32>, dpi::PhysicalSize<u32>),
inferred_theme: Option<Theme>,
pub vsync: Option<VSync>,
#[cfg(target_os = "macos")]
pub macos_feature: Option<MacosWindowFeature>,
@ -133,6 +130,7 @@ impl WinitWindowWrapper {
vsync: None,
ime_enabled: false,
ime_area: Default::default(),
inferred_theme: None,
#[cfg(target_os = "macos")]
macos_feature: None,
settings,
@ -213,7 +211,10 @@ impl WinitWindowWrapper {
self.is_minimized = true;
}
WindowCommand::ThemeChanged(new_theme) => {
self.handle_theme_changed(new_theme);
if self.inferred_theme != new_theme {
self.inferred_theme = new_theme;
self.handle_theme_changed();
}
}
#[cfg(windows)]
WindowCommand::RegisterRightClick => register_right_click(),
@ -257,6 +258,9 @@ impl WinitWindowWrapper {
WindowSettingsChanged::Opacity(..) | WindowSettingsChanged::NormalOpacity(..) => {
self.renderer.prepare_lines(true);
}
WindowSettingsChanged::Theme(..) => {
self.handle_theme_changed();
}
#[cfg(target_os = "windows")]
WindowSettingsChanged::TitleBackgroundColor(color) => {
self.handle_title_background_color(&color);
@ -311,9 +315,19 @@ impl WinitWindowWrapper {
}
}
pub fn handle_theme_changed(&mut self, new_theme: Option<Theme>) {
fn get_theme(&self) -> Option<Theme> {
let WindowSettings { theme, .. } = self.settings.get::<WindowSettings>();
match theme {
ThemeSettings::Auto => None,
ThemeSettings::Light => Some(Theme::Light),
ThemeSettings::Dark => Some(Theme::Dark),
ThemeSettings::BgColor => self.inferred_theme,
}
}
pub fn handle_theme_changed(&mut self) {
if let Some(skia_renderer) = &self.skia_renderer {
skia_renderer.window().set_theme(new_theme);
skia_renderer.window().set_theme(self.get_theme());
}
}
@ -383,17 +397,6 @@ impl WinitWindowWrapper {
self.handle_focus_lost();
}
}
WindowEvent::ThemeChanged(theme) => {
tracy_zone!("ThemeChanged");
let settings = self.settings.get::<WindowSettings>();
if settings.theme.as_str() == "auto" {
let background = match theme {
Theme::Light => "light",
Theme::Dark => "dark",
};
set_background(background);
}
}
WindowEvent::Moved(_) => {
tracy_zone!("Moved");
vsync.update(skia_renderer.window());
@ -486,12 +489,13 @@ impl WinitWindowWrapper {
let maximized = matches!(self.initial_window_size, WindowSize::Maximized);
let window_config = create_window(event_loop, maximized, &self.title, &self.settings);
let theme = self.get_theme();
let window_config =
create_window(event_loop, maximized, &self.title, &self.settings, theme);
let window = &window_config.window;
let WindowSettings {
input_ime,
theme,
opacity,
normal_opacity,
window_blurred,
@ -603,17 +607,6 @@ impl WinitWindowWrapper {
window.set_fullscreen(Some(Fullscreen::Borderless(handle)));
}
match theme.as_str() {
"light" => set_background("light"),
"dark" => set_background("dark"),
"auto" => match window.theme() {
Some(Theme::Light) => set_background("light"),
Some(Theme::Dark) => set_background("dark"),
None => {}
},
_ => {}
}
#[cfg(target_os = "windows")]
{
if let Some(winit_color) = Self::parse_winit_color(&title_background_color) {

View file

@ -536,6 +536,32 @@ Set the [`background`](https://neovim.io/doc/user/options.html#'background') opt
starts. Possible values: _light_, _dark_, _auto_. On systems that support it, _auto_ will mirror the
system theme, and will update `background` when the system theme changes.
**Unreleased yet.**
**NOTE:** The meaning of the setting has changed in 0.16.0. The default value of the Neovim
[`background`](https://neovim.io/doc/user/options.html#'background') option is now always
automatically set, and updates according to the system theme, as long as the user has not set it to
something else.
Sets the theme of the Neovide window on systems that supports it.
- `auto` - Use the system theme
- `light` - Set the window theme to light
- `dark` - Set the window theme to dark
- `bg_color` - Determine window theme from the Neovide normal/background color
`bg`, which would mirror the Neovim background option is not supported yet, due to technical
challenges. If you need that now it's best to set both `neovide_theme` and `background` to the same.
The default is `auto`, except when using `--frame transparent` on macOS to preserve the old visual
look with that configuration.
Supported platforms:
- Windows
- MacOS
- Linux Wayland with client-side decorations (Most notably Gnome)
#### Layer grouping
VimScript:

View file

@ -168,6 +168,13 @@ vim.g.neovide_scroll_animation_far_lines = 0
vim.g.neovide_scroll_animation_length = 0.00
```
## The default Neovim background is dark on a light Gnome theme
Gnome does not support a genuine light theme. See [this Gnome
issue](https://gitlab.gnome.org/GNOME/gnome-control-center/-/issues/1948). You can work around it by
setting it manually with `gsettings set org.gnome.desktop.interface color-scheme prefer-light`.
But do note that it resets when you change the Gnome theme.
## macOS Login Shells
Traditionally, Unix shells use two main configuration files that are executed