diff --git a/Cargo.lock b/Cargo.lock index b309db1d..805e6066 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -157,12 +157,6 @@ dependencies = [ "equator", ] -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - [[package]] name = "android-activity" version = "0.6.1" @@ -787,13 +781,6 @@ dependencies = [ "cfg_aliases", ] -[[package]] -name = "build_helpers" -version = "0.14.0" -dependencies = [ - "cfg_aliases", -] - [[package]] name = "built" version = "0.8.0" @@ -1301,7 +1288,7 @@ dependencies = [ [[package]] name = "cosmic-client-toolkit" version = "0.2.0" -source = "git+https://github.com/pop-os/cosmic-protocols?rev=32283d7#32283d76a8d0342da74c4cc022a533c52dcf378f" +source = "git+https://github.com/pop-os/cosmic-protocols?rev=160b086#160b086abe03cd34a8a375d7fbe47b24308d1f38" dependencies = [ "bitflags 2.11.0", "cosmic-protocols", @@ -1314,7 +1301,7 @@ dependencies = [ [[package]] name = "cosmic-protocols" version = "0.2.0" -source = "git+https://github.com/pop-os/cosmic-protocols?rev=32283d7#32283d76a8d0342da74c4cc022a533c52dcf378f" +source = "git+https://github.com/pop-os/cosmic-protocols?rev=160b086#160b086abe03cd34a8a375d7fbe47b24308d1f38" dependencies = [ "bitflags 2.11.0", "wayland-backend", @@ -1327,9 +1314,8 @@ dependencies = [ [[package]] name = "cosmic-text" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be17b688510d934ce13f48a2beba700e11583e281e0fda99c22bb256a14eda73" +version = "0.18.2" +source = "git+https://github.com/pop-os/cosmic-text.git#4d74f795cc771fdcc7ea0f9cacba63fcf036fad6" dependencies = [ "bitflags 2.11.0", "fontdb", @@ -1453,7 +1439,7 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "cryoglyph" version = "0.1.0" -source = "git+https://github.com/iced-rs/cryoglyph.git?rev=e429a025df36ab8145708acb309080ae3deec17a#e429a025df36ab8145708acb309080ae3deec17a" +source = "git+https://github.com/pop-os/glyphon.git?tag=cosmic-0.14#c49de15bce4d8254ac136d1be9911960cc85ce12" dependencies = [ "cosmic-text", "etagere", @@ -1575,7 +1561,7 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.2", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -1803,7 +1789,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -2306,7 +2292,7 @@ dependencies = [ "gobject-sys", "libc", "system-deps", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -2418,17 +2404,34 @@ dependencies = [ ] [[package]] -name = "gpu-allocator" -version = "0.28.0" +name = "gpu-alloc" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51255ea7cfaadb6c5f1528d43e92a82acb2b96c43365989a28b2d44ee38f8795" +checksum = "fbcd2dba93594b227a1f57ee09b8b9da8892c34d55aa332e034a228d0fe6a171" +dependencies = [ + "bitflags 2.11.0", + "gpu-alloc-types", +] + +[[package]] +name = "gpu-alloc-types" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98ff03b468aa837d70984d55f5d3f846f6ec31fe34bbb97c4f85219caeee1ca4" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "gpu-allocator" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd" dependencies = [ - "ash", - "hashbrown 0.16.1", "log", "presser", - "thiserror 2.0.18", - "windows 0.57.0", + "thiserror 1.0.69", + "windows 0.58.0", ] [[package]] @@ -2696,8 +2699,6 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ - "allocator-api2", - "equivalent", "foldhash 0.2.0", ] @@ -2964,7 +2965,6 @@ dependencies = [ name = "iced" version = "0.14.0" dependencies = [ - "build_helpers", "criterion", "dnd", "iced_accessibility", @@ -3016,7 +3016,6 @@ version = "0.14.0" dependencies = [ "approx", "bitflags 2.11.0", - "build_helpers", "bytes", "cosmic-client-toolkit", "dnd", @@ -3032,7 +3031,6 @@ dependencies = [ "serde", "smol_str", "thiserror 2.0.18", - "unicode-segmentation", "web-time", "window_clipboard", ] @@ -3123,7 +3121,6 @@ dependencies = [ name = "iced_runtime" version = "0.14.0" dependencies = [ - "build_helpers", "bytes", "cosmic-client-toolkit", "dnd", @@ -3191,7 +3188,6 @@ version = "0.14.0" dependencies = [ "as-raw-xcb-connection", "bitflags 2.11.0", - "build_helpers", "bytemuck", "cosmic-client-toolkit", "cryoglyph", @@ -3206,7 +3202,6 @@ dependencies = [ "resvg", "rustc-hash 2.1.2", "rustix 0.38.44", - "smithay-client-toolkit 0.20.0", "thiserror 2.0.18", "tiny-xlib", "wayland-backend", @@ -3221,7 +3216,6 @@ dependencies = [ name = "iced_widget" version = "0.14.2" dependencies = [ - "build_helpers", "cosmic-client-toolkit", "dnd", "iced_accessibility", @@ -3243,7 +3237,6 @@ dependencies = [ name = "iced_winit" version = "0.14.0" dependencies = [ - "build_helpers", "cosmic-client-toolkit", "cursor-icon", "dnd", @@ -3485,7 +3478,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -3543,7 +3536,7 @@ dependencies = [ "portable-atomic", "portable-atomic-util", "serde_core", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -4052,9 +4045,9 @@ dependencies = [ [[package]] name = "metal" -version = "0.33.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7047791b5bc903b8cd963014b355f71dc9864a9a0b727057676c1dcae5cbc15" +checksum = "00c15a6f673ff72ddcc22394663290f870fb224c1bfce55734a75c414150e605" dependencies = [ "bitflags 2.11.0", "block", @@ -4200,9 +4193,9 @@ checksum = "13d2233c9842d08cfe13f9eac96e207ca6a2ea10b80259ebe8ad0268be27d2af" [[package]] name = "naga" -version = "28.0.0" +version = "27.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618f667225063219ddfc61251087db8a9aec3c3f0950c916b614e403486f1135" +checksum = "066cf25f0e8b11ee0df221219010f213ad429855f57c494f995590c861a9a7d8" dependencies = [ "arrayvec", "bit-set", @@ -4307,7 +4300,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -5713,7 +5706,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -5726,7 +5719,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -6341,7 +6334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -6635,7 +6628,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix 1.1.4", - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -7174,7 +7167,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e" dependencies = [ "memoffset", "tempfile", - "windows-sys 0.61.2", + "windows-sys 0.60.2", ] [[package]] @@ -7830,13 +7823,12 @@ checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" [[package]] name = "wgpu" -version = "28.0.0" +version = "27.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9cb534d5ffd109c7d1135f34cdae29e60eab94855a625dcfe1705f8bc7ad79f" +checksum = "bfe68bac7cde125de7a731c3400723cadaaf1703795ad3f4805f187459cd7a77" dependencies = [ "arrayvec", "bitflags 2.11.0", - "bytemuck", "cfg-if", "cfg_aliases", "document-features", @@ -7860,9 +7852,9 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "28.0.1" +version = "27.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d23f4642f53f666adcfd2d3218ab174d1e6681101aef18696b90cbe64d1c10f9" +checksum = "27a75de515543b1897b26119f93731b385a19aea165a1ec5f0e3acecc229cae7" dependencies = [ "arrayvec", "bit-set", @@ -7893,45 +7885,45 @@ dependencies = [ [[package]] name = "wgpu-core-deps-apple" -version = "28.0.0" +version = "27.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87b7b696b918f337c486bf93142454080a32a37832ba8a31e4f48221890047da" +checksum = "0772ae958e9be0c729561d5e3fd9a19679bcdfb945b8b1a1969d9bfe8056d233" dependencies = [ "wgpu-hal", ] [[package]] name = "wgpu-core-deps-emscripten" -version = "28.0.0" +version = "27.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b251c331f84feac147de3c4aa3aa45112622a95dd7ee1b74384fa0458dbd79" +checksum = "b06ac3444a95b0813ecfd81ddb2774b66220b264b3e2031152a4a29fda4da6b5" dependencies = [ "wgpu-hal", ] [[package]] name = "wgpu-core-deps-wasm" -version = "28.0.0" +version = "27.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12a2cf578ce8d7d50d0e63ddc2345c7dcb599f6eb90b888813406ea78b9b7010" +checksum = "9b1027dcf3b027a877e44819df7ceb0e2e98578830f8cd34cd6c3c7c2a7a50b7" dependencies = [ "wgpu-hal", ] [[package]] name = "wgpu-core-deps-windows-linux-android" -version = "28.0.0" +version = "27.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ca976e72b2c9964eb243e281f6ce7f14a514e409920920dcda12ae40febaae" +checksum = "71197027d61a71748e4120f05a9242b2ad142e3c01f8c1b47707945a879a03c3" dependencies = [ "wgpu-hal", ] [[package]] name = "wgpu-hal" -version = "28.0.1" +version = "27.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d6cb474beb218824dcc9e1ce679d973f719262789bfb27407da560cac20eeb" +checksum = "5b21cb61c57ee198bc4aff71aeadff4cbb80b927beb912506af9c780d64313ce" dependencies = [ "android_system_properties", "arrayvec", @@ -7945,6 +7937,7 @@ dependencies = [ "core-graphics-types 0.2.0", "glow", "glutin_wgl_sys", + "gpu-alloc", "gpu-allocator", "gpu-descriptor", "hashbrown 0.16.1", @@ -7971,20 +7964,21 @@ dependencies = [ "wasm-bindgen", "web-sys", "wgpu-types", - "windows 0.62.2", - "windows-core 0.62.2", + "windows 0.58.0", + "windows-core 0.58.0", ] [[package]] name = "wgpu-types" -version = "28.0.0" +version = "27.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e18308757e594ed2cd27dddbb16a139c42a683819d32a2e0b1b0167552f5840c" +checksum = "afdcf84c395990db737f2dd91628706cb31e86d72e53482320d368e52b5da5eb" dependencies = [ "bitflags 2.11.0", "bytemuck", "js-sys", "log", + "thiserror 2.0.18", "web-sys", ] @@ -8010,7 +8004,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.52.0", ] [[package]] @@ -8044,6 +8038,16 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" +dependencies = [ + "windows-core 0.58.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows" version = "0.61.3" @@ -8099,6 +8103,19 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" +dependencies = [ + "windows-implement 0.58.0", + "windows-interface 0.58.0", + "windows-result 0.2.0", + "windows-strings 0.1.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows-core" version = "0.61.2" @@ -8158,6 +8175,17 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-implement" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-implement" version = "0.60.2" @@ -8180,6 +8208,17 @@ dependencies = [ "syn", ] +[[package]] +name = "windows-interface" +version = "0.58.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-interface" version = "0.59.3" @@ -8243,6 +8282,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-result" version = "0.3.4" @@ -8261,6 +8309,16 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-strings" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" +dependencies = [ + "windows-result 0.2.0", + "windows-targets 0.52.6", +] + [[package]] name = "windows-strings" version = "0.4.2" diff --git a/Cargo.toml b/Cargo.toml index a1498ba6..49b4b5d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -118,17 +118,13 @@ winit = [ "iced_accessibility?/accesskit_winit", "iced_program/winit", ] -wayland = [ - "iced_renderer/wayland", - "iced_winit/wayland", - "iced_runtime/wayland", - "iced_widget/wayland", - "iced_core/wayland", -] - +wayland = ["iced_renderer/wayland", "iced_winit/wayland"] +cctk = ["iced_winit/cctk", "iced_widget/cctk", "iced_core/cctk", "wayland"] +# Enables the sctk shell. [dependencies] + + iced_devtools.workspace = true -iced_devtools.optional = true iced_debug.workspace = true iced_program.workspace = true @@ -138,9 +134,10 @@ iced_renderer.workspace = true iced_runtime.workspace = true iced_widget.workspace = true iced_winit.workspace = true -iced_winit.optional = true +iced_devtools.optional = true iced_tester.workspace = true iced_tester.optional = true +iced_winit.optional = true iced_highlighter.workspace = true iced_highlighter.optional = true iced_accessibility.workspace = true @@ -193,7 +190,6 @@ members = [ "winit", "examples/*", "accessibility", - "build_helpers", ] exclude = ["examples/integration"] @@ -206,7 +202,7 @@ repository = "https://github.com/iced-rs/iced" homepage = "https://iced.rs" categories = ["gui"] keywords = ["gui", "ui", "graphics", "interface", "widgets"] -rust-version = "1.92" +rust-version = "1.89" [workspace.dependencies] iced = { version = "0.14.0", path = "." } @@ -242,9 +238,10 @@ async-std = "1.0" bitflags = "2.5" bytemuck = { version = "1.0", features = ["derive"] } bytes = "1.6" -cosmic-text = { path = "../../cosmic-text" } -cryoglyph = { package = "cryoglyph", path = "../../glyphon" } +cosmic-text = { git = "https://github.com/pop-os/cosmic-text.git" } +# cosmic-text = "0.10" dark-light = "1.0" +cryoglyph = { package = "cryoglyph", git = "https://github.com/pop-os/glyphon.git", tag = "cosmic-0.14" } resvg = "0.45" web-sys = "0.3.69" guillotiere = "0.6" @@ -278,11 +275,8 @@ tiny-skia = { version = "0.11", default-features = false, features = [ "std", "simd", ] } -cctk = { path = "../../cosmic-protocols/client-toolkit", package = "cosmic-client-toolkit" } -# Yoda: default-features=false drops softbuffer's x11 / x11-dlopen (pulled -# tiny-xlib + as-raw-xcb-connection). The wayland + wayland-dlopen features -# are re-activated via iced_tiny_skia's own `wayland` feature propagation. -softbuffer = { path = "../../softbuffer", default-features = false } +cctk = { git = "https://github.com/pop-os/cosmic-protocols", package = "cosmic-client-toolkit", rev = "160b086" } +softbuffer = { git = "https://github.com/pop-os/softbuffer", tag = "cosmic-4.0" } syntect = "5.2" tokio = "1.0" tracing = "0.1" @@ -294,7 +288,7 @@ url = "2.5" wasm-bindgen-futures = "0.4" wasmtimer = "0.4.2" web-time = "1.1" -wgpu = { version = "28.0", default-features = false, features = [ +wgpu = { version = "27.0", default-features = false, features = [ "std", "wgsl", ] } @@ -308,40 +302,13 @@ wayland-client = { version = "0.31.5" } winapi = "0.3" # window_clipboard = "0.4.1" -# Yoda: window_clipboard pinned to our public fork that has x11 gated behind -# an opt-in feature. default-features=false + features=["wayland"] drops -# clipboard_x11 + x11rb from the build. Branch yoda-x11-optional on -# https://forge.aditua.com/leyoda/window_clipboard. -window_clipboard = { path = "../../window_clipboard", default-features = false, features = ["wayland"] } -dnd = { path = "../../window_clipboard/dnd" } -mime = { path = "../../window_clipboard/mime" } -# Yoda: default-features = false drops winit's x11 default, which otherwise -# pulls winit-x11, x11-dl, tiny-xlib, as-raw-xcb-connection. Our Wayland-only -# fork doesn't need any of that — the wayland + wayland-dlopen features are -# re-enabled via iced_winit's own feature propagation from libcosmic-yoda. -winit = { path = "../../winit/winit", default-features = false } -winit-core = { path = "../../winit/winit-core" } +window_clipboard = { git = "https://github.com/pop-os/window_clipboard.git", tag = "sctk-0.20" } +dnd = { git = "https://github.com/pop-os/window_clipboard.git", tag = "sctk-0.20" } +mime = { git = "https://github.com/pop-os/window_clipboard.git", tag = "sctk-0.20" } +winit = { git = "https://github.com/pop-os/winit.git", tag = "cosmic-0.14" } +winit-core = { git = "https://github.com/pop-os/winit.git", tag = "cosmic-0.14" } cursor-icon = "1.1.0" -[patch.'https://github.com/pop-os/softbuffer'] -softbuffer = { path = "../../softbuffer" } - -[patch.'https://github.com/pop-os/smithay-clipboard'] -smithay-clipboard = { path = "../../smithay-clipboard" } - -[patch.'https://github.com/pop-os/winit.git'] -dpi = { path = "../../winit/dpi" } -winit = { path = "../../winit/winit" } -winit-android = { path = "../../winit/winit-android" } -winit-appkit = { path = "../../winit/winit-appkit" } -winit-common = { path = "../../winit/winit-common" } -winit-core = { path = "../../winit/winit-core" } -winit-orbital = { path = "../../winit/winit-orbital" } -winit-uikit = { path = "../../winit/winit-uikit" } -winit-wayland = { path = "../../winit/winit-wayland" } -winit-web = { path = "../../winit/winit-web" } -winit-win32 = { path = "../../winit/winit-win32" } -winit-x11 = { path = "../../winit/winit-x11" } [workspace.lints.rust] rust_2018_idioms = { level = "deny", priority = -1 } @@ -367,6 +334,3 @@ useless_conversion = "deny" [workspace.lints.rustdoc] broken_intra_doc_links = "forbid" - -[build-dependencies] -build_helpers = { path = "./build_helpers" } diff --git a/build.rs b/build.rs deleted file mode 100644 index db00a773..00000000 --- a/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - build_helpers::cfg_aliases_setup(); -} diff --git a/build_helpers/Cargo.toml b/build_helpers/Cargo.toml deleted file mode 100644 index ff319f69..00000000 --- a/build_helpers/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "build_helpers" -version.workspace = true -authors.workspace = true -edition.workspace = true -license.workspace = true -repository.workspace = true -homepage.workspace = true -categories.workspace = true -keywords.workspace = true -rust-version.workspace = true - -[dependencies] -cfg_aliases = { version = "0.2.1" } - -[lints] -workspace = true diff --git a/build_helpers/src/lib.rs b/build_helpers/src/lib.rs deleted file mode 100644 index 364b6ed8..00000000 --- a/build_helpers/src/lib.rs +++ /dev/null @@ -1,24 +0,0 @@ -use cfg_aliases::cfg_aliases; - -pub fn cfg_aliases_setup() { - // The script doesn't depend on our code - println!("cargo:rerun-if-changed=build.rs"); - - // Setup cfg aliases - cfg_aliases! { - // Systems. - android_platform: { target_os = "android" }, - wasm_platform: { all(target_family = "wasm", not(target_os = "emscripten")) }, - macos_platform: { target_os = "macos" }, - ios_platform: { target_os = "ios" }, - windows_platform: { target_os = "windows" }, - apple: { any(target_os = "ios", target_os = "macos") }, - free_unix: { all(unix, not(apple), not(android_platform), not(target_os = "emscripten")) }, - redox: { target_os = "redox" }, - - // Native displays. - wayland_platform: { all(feature = "wayland", free_unix, not(wasm), not(redox)) }, - xdg_portal: { all(feature = "xdg-portal", free_unix, not(wasm), not(redox)) }, - orbital_platform: { redox }, - } -} diff --git a/core/Cargo.toml b/core/Cargo.toml index f3136a87..e64a5c37 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -19,7 +19,6 @@ crisp = [] basic-shaping = [] advanced-shaping = [] a11y = ["iced_accessibility"] -wayland = ["cctk"] [dependencies] palette = "0.7" @@ -32,7 +31,6 @@ num-traits.workspace = true rustc-hash.workspace = true smol_str.workspace = true thiserror.workspace = true -unicode-segmentation.workspace = true web-time.workspace = true serde.workspace = true @@ -44,6 +42,8 @@ window_clipboard.workspace = true dnd.workspace = true mime.workspace = true +cctk.workspace = true +cctk.optional = true # /TODO(POP) [dependencies.iced_accessibility] version = "0.1.0" @@ -55,10 +55,3 @@ raw-window-handle.workspace = true [dev-dependencies] approx = "0.5" - -[target.'cfg(all(unix, not(any(target_os = "redox", target_family = "wasm", target_os = "android", target_vendor = "apple"))))'.dependencies] -cctk.workspace = true -cctk.optional = true - -[build-dependencies] -build_helpers = { path = "../build_helpers" } diff --git a/core/build.rs b/core/build.rs deleted file mode 100644 index db00a773..00000000 --- a/core/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - build_helpers::cfg_aliases_setup(); -} diff --git a/core/src/element.rs b/core/src/element.rs index dbe449c5..f97ed6bc 100644 --- a/core/src/element.rs +++ b/core/src/element.rs @@ -1,4 +1,4 @@ -use crate::event::Event; +use crate::event::{self, Event}; use crate::id::Id; use crate::layout; use crate::mouse; diff --git a/core/src/event.rs b/core/src/event.rs index b4a28a29..1aaf4ff4 100644 --- a/core/src/event.rs +++ b/core/src/event.rs @@ -7,8 +7,7 @@ use crate::keyboard; use crate::mouse; use crate::touch; use crate::window; - -#[cfg(wayland_platform)] +#[cfg(all(feature = "cctk", target_os = "linux"))] /// A platform specific event for wayland pub mod wayland; /// A user interface event. @@ -50,7 +49,7 @@ pub enum Event { /// A platform specific event #[derive(Debug, Clone, PartialEq)] pub enum PlatformSpecific { - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] /// A Wayland specific event Wayland(wayland::Event), } diff --git a/core/src/event/wayland/mod.rs b/core/src/event/wayland/mod.rs index 5050ce66..03e74407 100644 --- a/core/src/event/wayland/mod.rs +++ b/core/src/event/wayland/mod.rs @@ -46,6 +46,4 @@ pub enum Event { Subsurface(SubsurfaceEvent), /// Keyboard inhibit shortcuts ShortcutsInhibited(bool), - /// Blur Support Enabled - BlurEnabled, } diff --git a/core/src/overlay/group.rs b/core/src/overlay/group.rs index 1a4ce672..ec0906e7 100644 --- a/core/src/overlay/group.rs +++ b/core/src/overlay/group.rs @@ -3,7 +3,7 @@ use crate::mouse; use crate::overlay; use crate::renderer; use crate::widget; -use crate::{Clipboard, Event, Layout, Overlay, Shell, Size}; +use crate::{Clipboard, Event, Layout, Overlay, Point, Rectangle, Shell, Size}; /// An [`Overlay`] container that displays multiple overlay [`overlay::Element`] /// children. diff --git a/core/src/text/editor.rs b/core/src/text/editor.rs index ff89af01..e0b87756 100644 --- a/core/src/text/editor.rs +++ b/core/src/text/editor.rs @@ -78,8 +78,6 @@ pub enum Action { SelectLine, /// Select the entire buffer. SelectAll, - /// Clear the selection - ClearSelection, /// Perform an [`Edit`]. Edit(Edit), /// Click the [`Editor`] at the given [`Point`]. diff --git a/core/src/widget/operation/search_id.rs b/core/src/widget/operation/search_id.rs index e03fac8a..1286abaf 100644 --- a/core/src/widget/operation/search_id.rs +++ b/core/src/widget/operation/search_id.rs @@ -4,7 +4,7 @@ use super::Operation; use crate::{ Rectangle, id::Id, - widget::operation::Outcome, + widget::operation::{Outcome, focusable::Count}, }; /// Produces an [`Operation`] that searches for the Id diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index 2598b74e..1e40bf9e 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -22,18 +22,16 @@ //! ``` use crate::alignment; use crate::layout; -use crate::mouse::{self, click}; +use crate::mouse; use crate::renderer; -use crate::text; use crate::text::paragraph::{self, Paragraph}; +use crate::text::{self, Fragment}; use crate::widget::tree::{self, Tree}; use crate::{ - Clipboard, Color, Element, Event, Layout, Length, Pixels, Point, Rectangle, - Shell, Size, Theme, Widget, keyboard, touch, + Color, Element, Layout, Length, Pixels, Rectangle, Size, Theme, Widget, }; -use unicode_segmentation::UnicodeSegmentation; - +use std::borrow::Cow; pub use text::{Alignment, Ellipsize, LineHeight, Shaping, Wrapping}; /// A bunch of text. @@ -67,7 +65,6 @@ where fragment: text::Fragment<'a>, format: Format, class: Theme::Class<'a>, - selectable: bool, } impl<'a, Theme, Renderer> Text<'a, Theme, Renderer> @@ -82,7 +79,6 @@ where fragment: fragment.into_fragment(), format: Format::default(), class: Theme::default(), - selectable: false, } } @@ -193,17 +189,7 @@ where { let color = color.map(Into::into); - self.style(move |_theme| Style { - color, - ..Style::default() - }) - } - - /// Makes the [`Text`] selectable. When enabled, the user can click and - /// drag to select text, and copy it with Ctrl+C / Cmd+C. - pub fn selectable(mut self) -> Self { - self.selectable = true; - self + self.style(move |_theme| Style { color }) } /// Sets the style class of the [`Text`]. @@ -216,114 +202,7 @@ where } /// The internal state of a [`Text`] widget. -pub struct State { - /// The cached paragraph layout. - pub paragraph: paragraph::Plain

, - /// Lazily allocated when text is selectable and first interacted with. - selection: Option>, - focused: bool, - keyboard_focused: bool, - context_menu_position: Option, -} - -impl Default for State

{ - fn default() -> Self { - Self { - paragraph: paragraph::Plain::default(), - selection: None, - focused: false, - keyboard_focused: false, - context_menu_position: None, - } - } -} - -impl std::fmt::Debug for State

{ - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_struct("State") - .field("selection", &self.selection) - .field("focused", &self.focused) - .finish_non_exhaustive() - } -} - -impl State

{ - /// Returns `true` if the widget currently has focus. - pub fn is_focused(&self) -> bool { - self.focused - } - - /// Returns `true` if focus was gained via keyboard navigation (Tab). - pub fn is_keyboard_focused(&self) -> bool { - self.keyboard_focused - } - - /// Clears focus, selection, and all interaction state. - pub fn clear_focus(&mut self) { - self.focused = false; - self.keyboard_focused = false; - self.context_menu_position = None; - if let Some(sel) = &mut self.selection { - sel.clear(); - } - } - - /// Returns the context menu position, if a context menu should be shown. - pub fn context_menu_position(&self) -> Option { - self.context_menu_position - } - - /// Sets or clears the context menu position. - pub fn set_context_menu_position(&mut self, pos: Option) { - self.context_menu_position = pos; - } -} - -impl std::ops::Deref for State

{ - type Target = paragraph::Plain

; - - fn deref(&self) -> ¶graph::Plain

{ - &self.paragraph - } -} - -impl std::ops::DerefMut for State

{ - fn deref_mut(&mut self) -> &mut paragraph::Plain

{ - &mut self.paragraph - } -} - -#[derive(Debug, Clone, Default)] -struct SelectionState { - anchor: usize, - end: usize, - dragging: bool, - modifiers: keyboard::Modifiers, - last_click: Option, -} - -impl SelectionState { - fn clear(&mut self) { - self.anchor = 0; - self.end = 0; - self.dragging = false; - } -} - -impl crate::widget::operation::Focusable for State

{ - fn is_focused(&self) -> bool { - self.focused - } - - fn focus(&mut self) { - self.focused = true; - self.keyboard_focused = true; - } - - fn unfocus(&mut self) { - self.clear_focus(); - } -} +pub type State

= paragraph::Plain

; impl Widget for Text<'_, Theme, Renderer> @@ -336,7 +215,7 @@ where } fn state(&self) -> tree::State { - tree::State::new(State::::default()) + tree::State::new(paragraph::Plain::::default()) } fn size(&self) -> Size { @@ -352,10 +231,8 @@ where renderer: &Renderer, limits: &layout::Limits, ) -> layout::Node { - let state = tree.state.downcast_mut::>(); - layout( - &mut state.paragraph, + tree.state.downcast_mut::>(), renderer, limits, &self.fragment, @@ -375,351 +252,25 @@ where ) { let state = tree.state.downcast_ref::>(); let style = theme.style(&self.class); - let bounds = layout.bounds(); - let paragraph = state.paragraph.raw(); - if let Some(sel) = &state.selection { - let left = sel.anchor.min(sel.end); - let right = sel.anchor.max(sel.end); - let content: &str = self.fragment.as_ref(); - if left != right { - let lo_byte = grapheme_to_byte(content, left); - let hi_byte = grapheme_to_byte(content, right); - - let anchor = bounds.anchor( - paragraph.min_bounds(), - paragraph.align_x(), - paragraph.align_y(), - ); - - let rects = paragraph.highlight( - 0, - (lo_byte, text::Affinity::After), - (hi_byte, text::Affinity::Before), - ); - - for r in rects { - renderer.fill_quad( - renderer::Quad { - bounds: Rectangle { - x: anchor.x + r.x, - y: anchor.y + r.y, - width: r.width, - height: r.height, - }, - ..renderer::Quad::default() - }, - style.selected_fill, - ); - } - } - } - - draw(renderer, defaults, bounds, paragraph, style, viewport); - } - - fn update( - &mut self, - tree: &mut Tree, - event: &Event, - layout: Layout<'_>, - cursor: mouse::Cursor, - _renderer: &Renderer, - clipboard: &mut dyn Clipboard, - shell: &mut Shell<'_, Message>, - _viewport: &Rectangle, - ) { - if !self.selectable { - return; - } - - let state = tree.state.downcast_mut::>(); - let bounds = layout.bounds(); - let content: &str = self.fragment.as_ref(); - let grapheme_count = content.graphemes(true).count(); - let paragraph = state.paragraph.raw(); - - // Any click outside this widget clears selection and focus. - if matches!( - event, - Event::Mouse(mouse::Event::ButtonPressed(_)) - | Event::Touch(touch::Event::FingerPressed { .. }) - ) { - if cursor.position_over(bounds).is_none() { - let was_visible = state.focused - || state.keyboard_focused - || state - .selection - .as_ref() - .is_some_and(|sel| sel.anchor != sel.end); - - state.focused = false; - state.keyboard_focused = false; - if let Some(sel) = &mut state.selection { - sel.clear(); - } - - if was_visible { - shell.request_redraw(); - } - } - } - - match event { - Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) - | Event::Touch(touch::Event::FingerPressed { .. }) => { - if state.context_menu_position.take().is_some() { - shell.capture_event(); - return; - } - - if let Some(pos) = cursor.position_over(bounds) { - let sel = state.selection.get_or_insert_with(|| { - Box::new(SelectionState::default()) - }); - - let anchor = bounds.anchor( - paragraph.min_bounds(), - paragraph.align_x(), - paragraph.align_y(), - ); - let relative = - Point::new(pos.x - anchor.x, pos.y - anchor.y); - - let grapheme_pos = - hit_to_grapheme(paragraph, relative, content); - - let new_click = click::Click::new( - pos, - mouse::Button::Left, - sel.last_click.take(), - ); - - match new_click.kind() { - click::Kind::Single => { - if sel.modifiers.shift() { - sel.end = grapheme_pos; - } else { - sel.anchor = grapheme_pos; - sel.end = grapheme_pos; - } - sel.dragging = true; - } - click::Kind::Double => { - sel.anchor = - previous_start_of_word(content, grapheme_pos); - sel.end = next_end_of_word(content, grapheme_pos); - sel.dragging = true; - } - click::Kind::Triple => { - sel.anchor = 0; - sel.end = grapheme_count; - sel.dragging = true; - } - } - - sel.last_click = Some(new_click); - state.focused = true; - state.keyboard_focused = false; - shell.capture_event(); - shell.request_redraw(); - } - } - - Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Right)) => { - if let Some(pos) = cursor.position_over(bounds) { - state.context_menu_position = Some(pos); - state.focused = true; - state.keyboard_focused = false; - shell.capture_event(); - shell.request_redraw(); - } - } - - Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) - | Event::Touch(touch::Event::FingerLifted { .. }) => { - if let Some(sel) = &mut state.selection { - sel.dragging = false; - } - } - - Event::Mouse(mouse::Event::CursorMoved { position }) - | Event::Touch(touch::Event::FingerMoved { position, .. }) => { - if let Some(sel) = &mut state.selection { - if sel.dragging { - let anchor = bounds.anchor( - paragraph.min_bounds(), - paragraph.align_x(), - paragraph.align_y(), - ); - let relative = Point::new( - position.x - anchor.x, - position.y - anchor.y, - ); - - let end = hit_to_grapheme(paragraph, relative, content); - - // Only the drag reaching a new grapheme changes what - // is drawn; plain motion inside one does not. - if end != sel.end { - sel.end = end; - shell.request_redraw(); - } - - shell.capture_event(); - } - } - } - - Event::Keyboard(keyboard::Event::KeyPressed { - key, - modifiers, - physical_key, - text: _, - .. - }) => { - if !state.focused { - return; - } - let sel = state - .selection - .get_or_insert_with(|| Box::new(SelectionState::default())); - - if modifiers.command() { - match key.to_latin(*physical_key) { - Some('c') => { - let left = sel.anchor.min(sel.end); - let right = sel.anchor.max(sel.end); - if left != right { - let selected: String = content - .graphemes(true) - .skip(left) - .take(right - left) - .collect(); - clipboard.write( - crate::clipboard::Kind::Standard, - selected, - ); - } - shell.capture_event(); - return; - } - Some('a') => { - sel.anchor = 0; - sel.end = grapheme_count; - shell.capture_event(); - shell.request_redraw(); - return; - } - _ => {} - } - } - - match key { - keyboard::Key::Named(keyboard::key::Named::ArrowLeft) => { - let by_word = is_jump_modifier(*modifiers); - if modifiers.shift() { - sel.end = if by_word { - previous_start_of_word(content, sel.end) - } else { - sel.end.saturating_sub(1) - }; - } else { - let left = sel.anchor.min(sel.end); - let pos = if by_word { - previous_start_of_word(content, left) - } else { - left.saturating_sub(1) - }; - sel.anchor = pos; - sel.end = pos; - } - shell.capture_event(); - shell.request_redraw(); - } - keyboard::Key::Named(keyboard::key::Named::ArrowRight) => { - let by_word = is_jump_modifier(*modifiers); - if modifiers.shift() { - sel.end = if by_word { - next_end_of_word(content, sel.end) - } else { - (sel.end + 1).min(grapheme_count) - }; - } else { - let right = sel.anchor.max(sel.end); - let pos = if by_word { - next_end_of_word(content, right) - } else { - (right + 1).min(grapheme_count) - }; - sel.anchor = pos; - sel.end = pos; - } - shell.capture_event(); - shell.request_redraw(); - } - keyboard::Key::Named(keyboard::key::Named::Home) => { - if modifiers.shift() { - sel.end = 0; - } else { - sel.anchor = 0; - sel.end = 0; - } - shell.capture_event(); - shell.request_redraw(); - } - keyboard::Key::Named(keyboard::key::Named::End) => { - if modifiers.shift() { - sel.end = grapheme_count; - } else { - sel.anchor = grapheme_count; - sel.end = grapheme_count; - } - shell.capture_event(); - shell.request_redraw(); - } - _ => {} - } - } - - Event::Keyboard(keyboard::Event::ModifiersChanged(modifiers)) => { - if let Some(sel) = &mut state.selection { - sel.modifiers = *modifiers; - } - } - - _ => {} - } - } - - fn mouse_interaction( - &self, - _tree: &Tree, - layout: Layout<'_>, - cursor: mouse::Cursor, - _viewport: &Rectangle, - _renderer: &Renderer, - ) -> mouse::Interaction { - if self.selectable && cursor.is_over(layout.bounds()) { - mouse::Interaction::Text - } else { - mouse::Interaction::None - } + draw( + renderer, + defaults, + layout.bounds(), + state.raw(), + style, + viewport, + ); } fn operate( &mut self, - tree: &mut Tree, + _tree: &mut Tree, layout: Layout<'_>, _renderer: &Renderer, operation: &mut dyn super::Operation, ) { operation.text(None, layout.bounds(), &self.fragment); - - if self.selectable { - let state = tree.state.downcast_mut::>(); - operation.focusable(None, layout.bounds(), state); - } } #[cfg(feature = "a11y")] @@ -920,23 +471,12 @@ where } /// The appearance of some text. -#[derive(Debug, Clone, Copy, PartialEq)] +#[derive(Debug, Clone, Copy, PartialEq, Default)] pub struct Style { /// The [`Color`] of the text. /// /// The default, `None`, means using the inherited color. pub color: Option, - /// The fill [`Color`] of the selection highlight. - pub selected_fill: Color, -} - -impl Default for Style { - fn default() -> Self { - Self { - color: None, - selected_fill: DEFAULT_SELECTION_COLOR, - } - } } /// The theme catalog of a [`Text`]. @@ -970,14 +510,13 @@ impl Catalog for Theme { /// The default text styling; color is inherited. pub fn default(_theme: &Theme) -> Style { - Style::default() + Style { color: None } } /// Text with the default base color. pub fn base(theme: &Theme) -> Style { Style { color: Some(theme.palette().text), - ..Style::default() } } @@ -985,7 +524,6 @@ pub fn base(theme: &Theme) -> Style { pub fn primary(theme: &Theme) -> Style { Style { color: Some(theme.palette().primary), - ..Style::default() } } @@ -993,7 +531,6 @@ pub fn primary(theme: &Theme) -> Style { pub fn secondary(theme: &Theme) -> Style { Style { color: Some(theme.extended_palette().secondary.base.color), - ..Style::default() } } @@ -1001,7 +538,6 @@ pub fn secondary(theme: &Theme) -> Style { pub fn success(theme: &Theme) -> Style { Style { color: Some(theme.palette().success), - ..Style::default() } } @@ -1009,7 +545,6 @@ pub fn success(theme: &Theme) -> Style { pub fn warning(theme: &Theme) -> Style { Style { color: Some(theme.palette().warning), - ..Style::default() } } @@ -1017,177 +552,5 @@ pub fn warning(theme: &Theme) -> Style { pub fn danger(theme: &Theme) -> Style { Style { color: Some(theme.palette().danger), - ..Style::default() - } -} - -use crate::widget::tree::Tree as WidgetTree; - -/// Implement this on a **widget** to enable context menu support for -/// text selection (Copy, Select All, and optionally Cut / Paste) in libcosmic -pub trait HasSelectableText { - /// Returns the currently selected text, if any. - fn selected_text(&self, tree: &WidgetTree) -> Option; - - /// Selects all text. - fn select_all(&self, tree: &mut WidgetTree); - - /// Returns `true` if the widget is editable (enables Cut / Paste). - fn is_editable(&self) -> bool { - false - } - - /// Returns `true` if the widget is currently focused. - fn is_focused(&self, tree: &WidgetTree) -> bool; - - /// Returns the position where the context menu should appear - fn context_menu_position(&self, tree: &WidgetTree) -> Option; - - /// Sets or clears the context menu position. - fn set_context_menu_position( - &self, - tree: &mut WidgetTree, - pos: Option, - ); - - /// Copies the selection to the clipboard. - fn copy_to_clipboard( - &self, - tree: &WidgetTree, - clipboard: &mut dyn Clipboard, - ) { - if let Some(text) = self.selected_text(tree) { - clipboard.write(crate::clipboard::Kind::Standard, text); - } - } - - /// Deletes the selected text and returns the new full content. - /// Only called when [`is_editable`](Self::is_editable) is `true`. - fn delete_selection(&self, _tree: &mut WidgetTree) -> Option { - None - } - - /// Inserts `text` at the cursor (replacing any selection) and returns - /// the new full content. - /// Only called when [`is_editable`](Self::is_editable) is `true`. - fn paste_text( - &self, - _tree: &mut WidgetTree, - _text: &str, - ) -> Option { - None - } -} - -impl HasSelectableText - for Text<'_, Theme, Renderer> -{ - fn selected_text(&self, tree: &WidgetTree) -> Option { - let state = tree.state.downcast_ref::>(); - let sel = state.selection.as_ref()?; - let left = sel.anchor.min(sel.end); - let right = sel.anchor.max(sel.end); - if left == right { - return None; - } - let content = state.paragraph.content(); - let lo = grapheme_to_byte(content, left); - let hi = grapheme_to_byte(content, right); - content.get(lo..hi).map(|s| s.to_owned()) - } - - fn select_all(&self, tree: &mut WidgetTree) { - let state = tree.state.downcast_mut::>(); - let count = state.paragraph.content().graphemes(true).count(); - let sel = state - .selection - .get_or_insert_with(|| Box::new(SelectionState::default())); - sel.anchor = 0; - sel.end = count; - } - - fn is_focused(&self, tree: &WidgetTree) -> bool { - let state = tree.state.downcast_ref::>(); - state.is_focused() - } - - fn context_menu_position(&self, tree: &WidgetTree) -> Option { - let state = tree.state.downcast_ref::>(); - state.context_menu_position() - } - - fn set_context_menu_position( - &self, - tree: &mut WidgetTree, - pos: Option, - ) { - let state = tree.state.downcast_mut::>(); - state.set_context_menu_position(pos); - } -} - -const DEFAULT_SELECTION_COLOR: Color = Color { - r: 0.0, - g: 0.47, - b: 0.84, - a: 0.3, -}; - -fn grapheme_to_byte(content: &str, grapheme_index: usize) -> usize { - content - .graphemes(true) - .take(grapheme_index) - .map(|g| g.len()) - .sum() -} - -fn hit_to_grapheme( - paragraph: &P, - point: Point, - content: &str, -) -> usize { - match paragraph.hit_test(point) { - Some(hit) => { - let byte_offset = hit.cursor().min(content.len()); - content[..byte_offset].graphemes(true).count() - } - None => content.graphemes(true).count(), - } -} - -fn previous_start_of_word(content: &str, grapheme_index: usize) -> usize { - let graphemes: Vec<&str> = content.graphemes(true).collect(); - let clamped = grapheme_index.min(graphemes.len()); - let before: String = graphemes[..clamped].concat(); - - UnicodeSegmentation::split_word_bound_indices(&*before) - .filter(|(_, word)| !word.trim_start().is_empty()) - .next_back() - .map_or(0, |(i, prev_word)| { - clamped - - prev_word.graphemes(true).count() - - before[i + prev_word.len()..].graphemes(true).count() - }) -} - -fn next_end_of_word(content: &str, grapheme_index: usize) -> usize { - let graphemes: Vec<&str> = content.graphemes(true).collect(); - let clamped = grapheme_index.min(graphemes.len()); - let after: String = graphemes[clamped..].concat(); - - UnicodeSegmentation::split_word_bound_indices(&*after) - .find(|(_, word)| !word.trim_start().is_empty()) - .map_or(graphemes.len(), |(i, next_word)| { - clamped - + next_word.graphemes(true).count() - + after[..i].graphemes(true).count() - }) -} - -fn is_jump_modifier(modifiers: keyboard::Modifiers) -> bool { - if cfg!(target_os = "macos") { - modifiers.alt() - } else { - modifiers.control() } } diff --git a/examples/counter/src/main.rs b/examples/counter/src/main.rs index cfae782a..5027afd7 100644 --- a/examples/counter/src/main.rs +++ b/examples/counter/src/main.rs @@ -1,5 +1,5 @@ -use iced::widget::{button, column, text, Column}; use iced::Center; +use iced::widget::{Column, button, column, text}; pub fn main() -> iced::Result { iced::run(Counter::update, Counter::view) @@ -42,7 +42,7 @@ impl Counter { #[cfg(test)] mod tests { use super::*; - use iced_test::{simulator, Error}; + use iced_test::{Error, simulator}; #[test] fn it_counts() -> Result<(), Error> { diff --git a/examples/custom_shader/src/scene/pipeline.rs b/examples/custom_shader/src/scene/pipeline.rs index 30262a5d..80b0d533 100644 --- a/examples/custom_shader/src/scene/pipeline.rs +++ b/examples/custom_shader/src/scene/pipeline.rs @@ -140,7 +140,7 @@ impl Pipeline { address_mode_w: wgpu::AddressMode::ClampToEdge, mag_filter: wgpu::FilterMode::Linear, min_filter: wgpu::FilterMode::Linear, - mipmap_filter: wgpu::MipmapFilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Linear, ..Default::default() }); @@ -223,7 +223,7 @@ impl Pipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("cubes pipeline layout"), bind_group_layouts: &[&uniform_bind_group_layout], - immediate_size: 0, + push_constant_ranges: &[], }); let shader = @@ -280,7 +280,7 @@ impl Pipeline { compilation_options: wgpu::PipelineCompilationOptions::default(), }), - multiview_mask: None, + multiview: None, cache: None, }); @@ -388,7 +388,6 @@ impl Pipeline { ), timestamp_writes: None, occlusion_query_set: None, - multiview_mask: None, }); pass.set_viewport( @@ -479,7 +478,7 @@ impl DepthPipeline { device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("cubes.depth_pipeline.layout"), bind_group_layouts: &[&bind_group_layout], - immediate_size: 0, + push_constant_ranges: &[], }); let shader = @@ -521,7 +520,7 @@ impl DepthPipeline { compilation_options: wgpu::PipelineCompilationOptions::default(), }), - multiview_mask: None, + multiview: None, cache: None, }); @@ -587,7 +586,6 @@ impl DepthPipeline { ), timestamp_writes: None, occlusion_query_set: None, - multiview_mask: None, }); pass.set_viewport( diff --git a/examples/integration/src/scene.rs b/examples/integration/src/scene.rs index 1b248036..4e4757fa 100644 --- a/examples/integration/src/scene.rs +++ b/examples/integration/src/scene.rs @@ -43,7 +43,6 @@ impl Scene { depth_stencil_attachment: None, timestamp_writes: None, occlusion_query_set: None, - multiview_mask: None, }) } @@ -65,8 +64,8 @@ fn build_pipeline( let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: None, + push_constant_ranges: &[], bind_group_layouts: &[], - immediate_size: 0, }); device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { @@ -102,7 +101,7 @@ fn build_pipeline( mask: !0, alpha_to_coverage_enabled: false, }, - multiview_mask: None, + multiview: None, cache: None, }) } diff --git a/examples/sctk_drag/src/dnd_destination.rs b/examples/sctk_drag/src/dnd_destination.rs index d1b3374b..1081d8bb 100644 --- a/examples/sctk_drag/src/dnd_destination.rs +++ b/examples/sctk_drag/src/dnd_destination.rs @@ -3,20 +3,20 @@ use std::{ sync::atomic::{AtomicU64, Ordering}, }; +use iced::{Element, id::Id}; use iced::{ + Event, Length, Rectangle, clipboard::{ dnd::{self, DndAction, DndDestinationRectangle, DndEvent, OfferEvent}, mime::AllowedMimeTypes, }, event, id::Internal, - mouse, overlay, Event, Length, Rectangle, + mouse, overlay, }; -use iced::{id::Id, Element}; use iced_core::{ - self, layout, - widget::{tree, Tree}, - Clipboard, Layout, Shell, Widget, + self, Clipboard, Layout, Shell, Widget, layout, + widget::{Tree, tree}, }; pub fn dnd_destination<'a, Message: 'static>( diff --git a/examples/sctk_drag/src/dnd_source.rs b/examples/sctk_drag/src/dnd_source.rs index e93b925e..1d8b85c4 100644 --- a/examples/sctk_drag/src/dnd_source.rs +++ b/examples/sctk_drag/src/dnd_source.rs @@ -1,16 +1,16 @@ use std::any::Any; +use iced::Element; use iced::id::Id; use iced::widget::container; -use iced::Element; use iced::{ + Event, Length, Point, Rectangle, clipboard::dnd::{DndAction, DndEvent, SourceEvent}, - event, mouse, overlay, Event, Length, Point, Rectangle, + event, mouse, overlay, }; use iced_core::{ - layout, renderer, - widget::{tree, Tree}, - Clipboard, Shell, + Clipboard, Shell, layout, renderer, + widget::{Tree, tree}, }; use iced_core::{Layout, Widget}; @@ -37,11 +37,11 @@ pub struct DndSource<'a, Message, AppMessage, D> { } impl< - 'a, - Message: 'static, - AppMessage: 'static, - D: iced::clipboard::mime::AsMimeTypes + std::marker::Send + 'static, - > DndSource<'a, Message, AppMessage, D> + 'a, + Message: 'static, + AppMessage: 'static, + D: iced::clipboard::mime::AsMimeTypes + std::marker::Send + 'static, +> DndSource<'a, Message, AppMessage, D> { pub fn new(child: impl Into>) -> Self { Self { @@ -119,11 +119,11 @@ impl< } impl< - 'a, - Message: 'static, - AppMessage: 'static, - D: iced::clipboard::mime::AsMimeTypes + std::marker::Send + 'static, - > Widget + 'a, + Message: 'static, + AppMessage: 'static, + D: iced::clipboard::mime::AsMimeTypes + std::marker::Send + 'static, +> Widget for DndSource<'a, Message, AppMessage, D> { fn children(&self) -> Vec { @@ -357,11 +357,11 @@ impl< } impl< - 'a, - Message: 'static, - AppMessage: 'static, - D: iced::clipboard::mime::AsMimeTypes + std::marker::Send + 'static, - > From> for Element<'a, Message> + 'a, + Message: 'static, + AppMessage: 'static, + D: iced::clipboard::mime::AsMimeTypes + std::marker::Send + 'static, +> From> for Element<'a, Message> { fn from(e: DndSource<'a, Message, AppMessage, D>) -> Element<'a, Message> { Element::new(e) diff --git a/examples/sctk_subsurface/src/main.rs b/examples/sctk_subsurface/src/main.rs index a204572c..c00f7225 100644 --- a/examples/sctk_subsurface/src/main.rs +++ b/examples/sctk_subsurface/src/main.rs @@ -7,6 +7,7 @@ use cctk::sctk::reexports::{ use iced::platform_specific::shell::commands::subsurface::get_subsurface; use iced::{ + Element, Length, Subscription, Task, event::wayland::Event as WaylandEvent, platform_specific::{ runtime::wayland::subsurface::SctkSubsurfaceSettings, @@ -14,7 +15,6 @@ use iced::{ }, widget::{button, column, text, text_input}, window::{self, Id, Settings}, - Element, Length, Subscription, Task, }; use std::sync::{Arc, Mutex}; diff --git a/examples/todos/src/main.rs b/examples/todos/src/main.rs index 9fe39035..2e3722b1 100644 --- a/examples/todos/src/main.rs +++ b/examples/todos/src/main.rs @@ -477,7 +477,6 @@ fn delete_icon() -> Text<'static> { fn subtle(theme: &Theme) -> text::Style { text::Style { color: Some(theme.extended_palette().background.strongest.color), - ..text::Style::default() } } diff --git a/graphics/src/image.rs b/graphics/src/image.rs index d9b23216..e5fe9281 100644 --- a/graphics/src/image.rs +++ b/graphics/src/image.rs @@ -2,6 +2,8 @@ #[cfg(feature = "image")] use crate::core::Bytes; +use crate::core::Color; +use crate::core::Radians; use crate::core::Rectangle; use crate::core::image; use crate::core::svg; diff --git a/graphics/src/layer.rs b/graphics/src/layer.rs index 210b8309..31cfe68a 100644 --- a/graphics/src/layer.rs +++ b/graphics/src/layer.rs @@ -83,20 +83,13 @@ impl Stack { /// Pushes a new clipping region in the [`Stack`]; creating a new layer in the /// process. pub fn push_clip(&mut self, bounds: Rectangle) { - let bounds = bounds * self.transformation(); - let bounds = bounds - .intersection(&self.layers[self.current].bounds()) - .unwrap_or(Rectangle { - width: 0.0, - height: 0.0, - ..bounds - }); - self.previous.push(self.current); self.current = self.active_count; self.active_count += 1; + let bounds = bounds * self.transformation(); + if self.current == self.layers.len() { self.layers.push(T::with_bounds(bounds)); } else { diff --git a/graphics/src/text.rs b/graphics/src/text.rs index 910cbbde..230a362d 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -161,14 +161,6 @@ impl FontSystem { &mut self.raw } - /// Returns a reference to the underlying [`fontdb::Database`]. - /// - /// Unlike going through [`raw`](Self::raw) and `db_mut`, this does not - /// clear `cosmic-text`'s internal font-match cache. - pub fn db(&self) -> &cosmic_text::fontdb::Database { - self.raw.db() - } - /// Loads a font from its bytes. pub fn load_font(&mut self, bytes: Cow<'static, [u8]>) { if let Cow::Borrowed(bytes) = bytes { diff --git a/graphics/src/text/editor.rs b/graphics/src/text/editor.rs index 1586479e..b284c76b 100644 --- a/graphics/src/text/editor.rs +++ b/graphics/src/text/editor.rs @@ -336,10 +336,6 @@ impl editor::Editor for Editor { } } - Action::ClearSelection => { - editor.set_selection(cosmic_text::Selection::None); - } - // Editing events Action::Edit(edit) => { let topmost_line_before_edit = editor diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 1cb23e23..ea4741d1 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -17,7 +17,7 @@ workspace = true debug = [] selector = ["dep:iced_selector"] a11y = ["iced_accessibility", "iced_core/a11y"] -wayland = ["iced_core/wayland", "dep:cctk"] +cctk = ["iced_core/cctk", "dep:cctk"] [dependencies] bytes.workspace = true @@ -33,14 +33,9 @@ sipper.optional = true iced_selector.workspace = true iced_selector.optional = true iced_futures.features = ["thread-pool"] +cctk.workspace = true +cctk.optional = true iced_accessibility.workspace = true iced_accessibility.optional = true window_clipboard.workspace = true dnd.workspace = true - -[target.'cfg(all(unix, not(any(target_os = "redox", target_family = "wasm", target_os = "android", target_vendor = "apple"))))'.dependencies] -cctk.workspace = true -cctk.optional = true - -[build-dependencies] -build_helpers = { path = "../build_helpers" } diff --git a/runtime/build.rs b/runtime/build.rs deleted file mode 100644 index db00a773..00000000 --- a/runtime/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - build_helpers::cfg_aliases_setup(); -} diff --git a/runtime/src/dnd.rs b/runtime/src/dnd.rs index 2e526eb6..e6f2b267 100644 --- a/runtime/src/dnd.rs +++ b/runtime/src/dnd.rs @@ -1,10 +1,12 @@ //! Access the clipboard. +use std::any::Any; use dnd::{DndDestinationRectangle, DndSurface}; -use window_clipboard::mime::AllowedMimeTypes; +use iced_core::clipboard::DndSource; +use window_clipboard::mime::{AllowedMimeTypes, AsMimeTypes}; -use crate::{Action, Task, oneshot, task}; +use crate::{oneshot, task, Action, Task}; /// An action to be performed on the system. pub enum DndAction { diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 68034bfc..22da3d66 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -28,6 +28,7 @@ pub use task::Task; pub use user_interface::UserInterface; pub use window::Window; +use crate::core::Color; use crate::futures::futures::channel::oneshot; use std::borrow::Cow; diff --git a/runtime/src/platform_specific/mod.rs b/runtime/src/platform_specific/mod.rs index 9cc66ddd..4ef5ad9f 100644 --- a/runtime/src/platform_specific/mod.rs +++ b/runtime/src/platform_specific/mod.rs @@ -2,23 +2,23 @@ use std::fmt; -#[cfg(wayland_platform)] +#[cfg(all(feature = "cctk", target_os = "linux"))] /// Platform specific actions defined for wayland pub mod wayland; /// Platform specific actions defined for wayland pub enum Action { /// Wayland Specific Actions - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] Wayland(wayland::Action), } impl fmt::Debug for Action { fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] Action::Wayland(action) => action.fmt(_f), - #[cfg(not(wayland_platform))] + #[cfg(not(all(feature = "cctk", target_os = "linux")))] _ => Ok(()), } } diff --git a/runtime/src/platform_specific/wayland/activation.rs b/runtime/src/platform_specific/wayland/activation.rs index 3f48f01c..64d4dc4d 100644 --- a/runtime/src/platform_specific/wayland/activation.rs +++ b/runtime/src/platform_specific/wayland/activation.rs @@ -36,7 +36,7 @@ impl fmt::Debug for Action { f, "Action::ActivationAction::Activate {{ window: {:?}, token: {:?} }}", window, token, - ), + ) } } } diff --git a/runtime/src/platform_specific/wayland/layer_surface.rs b/runtime/src/platform_specific/wayland/layer_surface.rs index 6e5f3e9e..4745ef67 100644 --- a/runtime/src/platform_specific/wayland/layer_surface.rs +++ b/runtime/src/platform_specific/wayland/layer_surface.rs @@ -6,8 +6,8 @@ use cctk::sctk::{ }; use iced_core::layout::Limits; -use iced_core::Rectangle; use iced_core::window::Id; +use iced_core::Rectangle; /// output for layer surface #[derive(Debug, Clone)] @@ -150,13 +150,6 @@ pub enum Action { /// layer of the layer surface layer: Layer, }, - /// padding of the surface geometry - Padding { - /// id of the layer surface - id: Id, - /// padding of the surface geometry - padding: IcedMargin, - }, } impl fmt::Debug for Action { @@ -169,51 +162,35 @@ impl fmt::Debug for Action { ), Action::Size { id, width, height } => write!( f, - "Action::LayerSurfaceAction::Size {{ id: {:#?}, width: {:?}, height: {:?} }}", - id, width, height + "Action::LayerSurfaceAction::Size {{ id: {:#?}, width: {:?}, height: {:?} }}", id, width, height ), Action::Destroy(id) => write!( f, - "Action::LayerSurfaceAction::Destroy {{ id: {:#?} }}", - id + "Action::LayerSurfaceAction::Destroy {{ id: {:#?} }}", id ), Action::Anchor { id, anchor } => write!( f, - "Action::LayerSurfaceAction::Anchor {{ id: {:#?}, anchor: {:?} }}", - id, anchor + "Action::LayerSurfaceAction::Anchor {{ id: {:#?}, anchor: {:?} }}", id, anchor ), Action::ExclusiveZone { id, exclusive_zone } => write!( f, - "Action::LayerSurfaceAction::ExclusiveZone {{ id: {:#?}, exclusive_zone: {exclusive_zone} }}", - id + "Action::LayerSurfaceAction::ExclusiveZone {{ id: {:#?}, exclusive_zone: {exclusive_zone} }}", id ), Action::Margin { id, margin } => write!( f, - "Action::LayerSurfaceAction::Margin {{ id: {:#?}, margin: {:?} }}", - id, margin + "Action::LayerSurfaceAction::Margin {{ id: {:#?}, margin: {:?} }}", id, margin ), - Action::KeyboardInteractivity { - id, - keyboard_interactivity, - } => write!( + Action::KeyboardInteractivity { id, keyboard_interactivity } => write!( f, - "Action::LayerSurfaceAction::KeyboardInteractivity {{ id: {:#?}, keyboard_interactivity: {:?} }}", - id, keyboard_interactivity + "Action::LayerSurfaceAction::KeyboardInteractivity {{ id: {:#?}, keyboard_interactivity: {:?} }}", id, keyboard_interactivity ), Action::InputZone { id, zone } => write!( f, - "Action::LayerSurfaceAction::InputZone {{ id: {:#?}, zone: {:?} }}", - id, zone + "Action::LayerSurfaceAction::InputZone {{ id: {:#?}, zone: {:?} }}", id, zone ), Action::Layer { id, layer } => write!( f, - "Action::LayerSurfaceAction::Layer {{ id: {:#?}, layer: {:?} }}", - id, layer - ), - Action::Padding { id, padding } => write!( - f, - "Action::LayerSurfaceAction::Padding {{ id: {:#?}, padding: {:?} }}", - id, padding + "Action::LayerSurfaceAction::Layer {{ id: {:#?}, layer: {:?} }}", id, layer ), } } diff --git a/runtime/src/platform_specific/wayland/popup.rs b/runtime/src/platform_specific/wayland/popup.rs index 27279ab6..e0475eb8 100644 --- a/runtime/src/platform_specific/wayland/popup.rs +++ b/runtime/src/platform_specific/wayland/popup.rs @@ -124,34 +124,26 @@ pub enum Action { /// height height: u32, }, - /// set the size of the popup - Reposition { - /// id of the popup - id: Id, - /// positioner of the popup - positioner: SctkPositioner, - }, } impl fmt::Debug for Action { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Action::Popup { popup, .. } => { - write!(f, "Action::PopupAction::Popup {{ popup: {:?} }}", popup) - } - Action::Destroy { id } => { - write!(f, "Action::PopupAction::Destroy {{ id: {:?} }}", id) - } + Action::Popup { popup, .. } => write!( + f, + "Action::PopupAction::Popup {{ popup: {:?} }}", + popup + ), + Action::Destroy { id } => write!( + f, + "Action::PopupAction::Destroy {{ id: {:?} }}", + id + ), Action::Size { id, width, height } => write!( f, "Action::PopupAction::Size {{ id: {:?}, width: {:?}, height: {:?} }}", id, width, height ), - Action::Reposition { id, positioner } => write!( - f, - "Action::Reposition {{ id: {:?}, positioner: {:?} }}", - id, positioner - ), } } } diff --git a/runtime/src/window.rs b/runtime/src/window.rs index ae6445ec..4d2f5650 100644 --- a/runtime/src/window.rs +++ b/runtime/src/window.rs @@ -222,7 +222,7 @@ pub fn frames() -> Subscription<(Id, Instant)> { _ => None, }) } -#[cfg(wayland_platform)] +#[cfg(all(feature = "cctk", target_os = "linux"))] /// Subscribes to the frames of the window of the running application. /// /// The resulting [`Subscription`] will produce items at a rate equal to the diff --git a/src/lib.rs b/src/lib.rs index 28870ee2..8d408969 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -606,7 +606,7 @@ pub mod font { pub mod event { //! Handle events of a user interface. pub use crate::core::event::PlatformSpecific; - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] pub use crate::core::event::wayland; pub use crate::core::event::{Event, Status}; pub use iced_futures::event::{listen, listen_raw, listen_with}; @@ -683,8 +683,6 @@ pub use event::Event; pub use executor::Executor; pub use font::Font; pub use renderer::Renderer; -#[cfg(feature = "canvas")] -pub use renderer::graphics::geometry; pub use task::Task; pub use window::Window; diff --git a/tester/src/lib.rs b/tester/src/lib.rs index f41fbb68..334f17bc 100644 --- a/tester/src/lib.rs +++ b/tester/src/lib.rs @@ -775,7 +775,6 @@ impl Tester

{ } _ => None, }, - ..text::Style::default() }) .into() }, @@ -946,7 +945,6 @@ where text(label).size(14).style(|theme: &core::Theme| { text::Style { color: Some(theme.extended_palette().background.weak.text), - ..text::Style::default() } }), space::horizontal(), diff --git a/tiny_skia/src/engine.rs b/tiny_skia/src/engine.rs index 9f0b54f2..61323f04 100644 --- a/tiny_skia/src/engine.rs +++ b/tiny_skia/src/engine.rs @@ -263,10 +263,6 @@ impl Engine { } else { // Draw corners that have too small border radii as having no border radius, // but mask them with the rounded rectangle with the correct border radius. - if path_bounds.width < 1.0 || path_bounds.height < 1.0 { - return; - } - let mut temp_pixmap = tiny_skia::Pixmap::new( path_bounds.width as u32, path_bounds.height as u32, diff --git a/tiny_skia/src/vector.rs b/tiny_skia/src/vector.rs index 2c3b219c..59cd1993 100644 --- a/tiny_skia/src/vector.rs +++ b/tiny_skia/src/vector.rs @@ -1,6 +1,5 @@ use crate::core::svg::{Data, Handle}; use crate::core::{Color, Rectangle, Size}; -use crate::graphics::text; use resvg::usvg; use rustc_hash::{FxHashMap, FxHashSet}; @@ -75,7 +74,6 @@ struct Cache { rasters: FxHashMap, raster_hits: FxHashSet, fontdb: Option>, - fontdb_version: Option, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -89,15 +87,12 @@ impl Cache { fn load(&mut self, handle: &Handle) -> Option<&usvg::Tree> { let id = handle.id(); - // Reuse the font database already loaded by the `cosmic-text` font - // system. We clone it once and refresh only when a font is - // loaded (i.e. when the font system's version changes). - let font_system = text::font_system().read().expect("Read font system"); - let version = font_system.version(); + // TODO: Reuse `cosmic-text` font database + if self.fontdb.is_none() { + let mut fontdb = usvg::fontdb::Database::new(); + fontdb.load_system_fonts(); - if self.fontdb_version != Some(version) { - self.fontdb = Some(Arc::new(font_system.db().clone())); - self.fontdb_version = Some(version); + self.fontdb = Some(Arc::new(fontdb)); } let options = usvg::Options { diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index c278fb17..48fca1b8 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -25,12 +25,6 @@ svg = ["iced_graphics/svg", "resvg/text"] web-colors = ["iced_graphics/web-colors"] webgl = ["wgpu/webgl"] strict-assertions = [] -# Yoda: opt-in X11 backend. Pulls tiny-xlib/as-raw-xcb-connection/x11rb -# (which otherwise were unconditional direct deps on unix). Wayland-only -# builds just leave this off — window/x11.rs and the DRI3 device-id -# fallback in window/compositor.rs are cfg-gated on it. -x11 = ["dep:as-raw-xcb-connection", "dep:tiny-xlib", "dep:x11rb"] -wayland = ["cctk"] [dependencies] iced_debug.workspace = true @@ -63,14 +57,11 @@ wayland-protocols.workspace = true wayland-backend = { version = "0.3.3", features = ["client_system"] } wayland-client = { version = "0.31.2" } wayland-sys = { version = "0.31.1", features = ["dlopen"] } -as-raw-xcb-connection = { version = "1.0.1", optional = true } -tiny-xlib = { version = "0.2.3", optional = true } -x11rb = { version = "0.13.1", optional = true, features = [ +as-raw-xcb-connection = "1.0.1" +tiny-xlib = "0.2.3" +x11rb = { version = "0.13.1", features = [ "allow-unsafe-code", "dl-libxcb", "dri3", "randr", ] } - -[build-dependencies] -build_helpers = { path = "../build_helpers" } diff --git a/wgpu/build.rs b/wgpu/build.rs deleted file mode 100644 index db00a773..00000000 --- a/wgpu/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - build_helpers::cfg_aliases_setup(); -} diff --git a/wgpu/src/buffer.rs b/wgpu/src/buffer.rs index e251e979..172922da 100644 --- a/wgpu/src/buffer.rs +++ b/wgpu/src/buffer.rs @@ -63,6 +63,7 @@ impl Buffer { /// Returns the size of the written bytes. pub fn write( &mut self, + device: &wgpu::Device, encoder: &mut wgpu::CommandEncoder, belt: &mut wgpu::util::StagingBelt, offset: usize, @@ -78,6 +79,7 @@ impl Buffer { &self.raw, (offset + bytes_written) as u64, MAX_WRITE_SIZE_U64, + device, ) .copy_from_slice( &bytes[bytes_written..bytes_written + MAX_WRITE_SIZE], @@ -98,6 +100,7 @@ impl Buffer { &self.raw, (offset + bytes_written) as u64, bytes_left, + device, ) .copy_from_slice(&bytes[bytes_written..]); diff --git a/wgpu/src/color.rs b/wgpu/src/color.rs index 642d4ea7..52fe8463 100644 --- a/wgpu/src/color.rs +++ b/wgpu/src/color.rs @@ -99,7 +99,7 @@ pub fn convert( device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("iced_wgpu.offscreen.blit.pipeline_layout"), bind_group_layouts: &[&constant_layout, &texture_layout], - immediate_size: 0, + push_constant_ranges: &[], }); let shader = device.create_shader_module(wgpu::ShaderModuleDescriptor { @@ -149,7 +149,7 @@ pub fn convert( }, depth_stencil: None, multisample: wgpu::MultisampleState::default(), - multiview_mask: None, + multiview: None, cache: None, }); @@ -194,7 +194,6 @@ pub fn convert( depth_stencil_attachment: None, timestamp_writes: None, occlusion_query_set: None, - multiview_mask: None, }); pass.set_pipeline(&pipeline); diff --git a/wgpu/src/image/atlas.rs b/wgpu/src/image/atlas.rs index d23e7452..09258329 100644 --- a/wgpu/src/image/atlas.rs +++ b/wgpu/src/image/atlas.rs @@ -132,7 +132,7 @@ impl Atlas { match &entry { Entry::Contiguous(allocation) => { self.upload_allocation( - pixels, width, 0, allocation, encoder, belt, + pixels, width, 0, allocation, device, encoder, belt, ); } Entry::Fragmented { fragments, .. } => { @@ -145,6 +145,7 @@ impl Atlas { width, offset, &fragment.allocation, + device, encoder, belt, ); @@ -311,6 +312,7 @@ impl Atlas { image_width: u32, offset: usize, allocation: &Allocation, + device: &wgpu::Device, encoder: &mut wgpu::CommandEncoder, belt: &mut wgpu::util::StagingBelt, ) { @@ -332,6 +334,7 @@ impl Atlas { let buffer_slice = belt.allocate( wgpu::BufferSize::new(total_bytes as u64).unwrap(), wgpu::BufferSize::new(8 * 4).unwrap(), + device, ); const PIXEL: usize = 4; diff --git a/wgpu/src/image/cache.rs b/wgpu/src/image/cache.rs index 88a48640..097a383f 100644 --- a/wgpu/src/image/cache.rs +++ b/wgpu/src/image/cache.rs @@ -38,10 +38,7 @@ impl Cache { raster: Raster { cache: crate::image::raster::Cache::default(), pending: HashMap::new(), - belt: wgpu::util::StagingBelt::new( - device.clone(), - 2 * 1024 * 1024, - ), + belt: wgpu::util::StagingBelt::new(2 * 1024 * 1024), }, #[cfg(feature = "svg")] vector: crate::image::vector::Cache::default(), @@ -454,10 +451,7 @@ mod worker { backend, texture_layout, shell: shell.clone(), - belt: wgpu::util::StagingBelt::new( - device.clone(), - 4 * 1024 * 1024, - ), + belt: wgpu::util::StagingBelt::new(4 * 1024 * 1024), jobs: jobs_receiver, output: work_sender, quit: quit_receiver, diff --git a/wgpu/src/image/mod.rs b/wgpu/src/image/mod.rs index d0665ee4..ba98f443 100644 --- a/wgpu/src/image/mod.rs +++ b/wgpu/src/image/mod.rs @@ -45,7 +45,7 @@ impl Pipeline { address_mode_w: wgpu::AddressMode::ClampToEdge, min_filter: wgpu::FilterMode::Nearest, mag_filter: wgpu::FilterMode::Nearest, - mipmap_filter: wgpu::MipmapFilterMode::Nearest, + mipmap_filter: wgpu::FilterMode::Nearest, ..Default::default() }); @@ -55,7 +55,7 @@ impl Pipeline { address_mode_w: wgpu::AddressMode::ClampToEdge, min_filter: wgpu::FilterMode::Linear, mag_filter: wgpu::FilterMode::Linear, - mipmap_filter: wgpu::MipmapFilterMode::Linear, + mipmap_filter: wgpu::FilterMode::Linear, ..Default::default() }); @@ -106,8 +106,8 @@ impl Pipeline { let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("iced_wgpu::image pipeline layout"), + push_constant_ranges: &[], bind_group_layouts: &[&constant_layout, &texture_layout], - immediate_size: 0, }); let shader = @@ -191,7 +191,7 @@ impl Pipeline { mask: !0, alpha_to_coverage_enabled: false, }, - multiview_mask: None, + multiview: None, cache: None, }); @@ -528,6 +528,7 @@ impl Layer { &self.uniforms, 0, (bytes.len() as u64).try_into().expect("Sized uniforms"), + device, ) .copy_from_slice(bytes); @@ -538,11 +539,11 @@ impl Layer { let mut offset = 0; if !nearest.is_empty() { - offset += self.instances.write(encoder, belt, 0, nearest); + offset += self.instances.write(device, encoder, belt, 0, nearest); } if !linear.is_empty() { - let _ = self.instances.write(encoder, belt, offset, linear); + let _ = self.instances.write(device, encoder, belt, offset, linear); } } diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 03a72042..4eb52cc8 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -126,7 +126,6 @@ impl Renderer { // It would be great if the `StagingBelt` API exposed methods // for introspection to detect when a resize may be worth it. staging_belt: wgpu::util::StagingBelt::new( - engine.device.clone(), buffer::MAX_WRITE_SIZE as u64, ), @@ -455,7 +454,6 @@ impl Renderer { depth_stencil_attachment: None, timestamp_writes: None, occlusion_query_set: None, - multiview_mask: None, }, )); @@ -530,7 +528,6 @@ impl Renderer { depth_stencil_attachment: None, timestamp_writes: None, occlusion_query_set: None, - multiview_mask: None, }, )); } @@ -624,7 +621,6 @@ impl Renderer { depth_stencil_attachment: None, timestamp_writes: None, occlusion_query_set: None, - multiview_mask: None, }, )); } diff --git a/wgpu/src/quad.rs b/wgpu/src/quad.rs index 4cab2598..31bf69cf 100644 --- a/wgpu/src/quad.rs +++ b/wgpu/src/quad.rs @@ -209,7 +209,7 @@ impl Layer { transformation: Transformation, scale: f32, ) { - self.update(encoder, belt, transformation, scale); + self.update(device, encoder, belt, transformation, scale); if !quads.solids.is_empty() { self.solid.prepare(device, encoder, belt, &quads.solids); @@ -223,6 +223,7 @@ impl Layer { pub fn update( &mut self, + device: &wgpu::Device, encoder: &mut wgpu::CommandEncoder, belt: &mut wgpu::util::StagingBelt, transformation: Transformation, @@ -236,6 +237,7 @@ impl Layer { &self.constants_buffer, 0, (bytes.len() as u64).try_into().expect("Sized uniforms"), + device, ) .copy_from_slice(bytes); } diff --git a/wgpu/src/quad/gradient.rs b/wgpu/src/quad/gradient.rs index 55e62e79..6a5eed8d 100644 --- a/wgpu/src/quad/gradient.rs +++ b/wgpu/src/quad/gradient.rs @@ -51,7 +51,7 @@ impl Layer { instances: &[Gradient], ) { let _ = self.instances.resize(device, instances.len()); - let _ = self.instances.write(encoder, belt, 0, instances); + let _ = self.instances.write(device, encoder, belt, 0, instances); self.instance_count = instances.len(); } @@ -75,8 +75,8 @@ impl Pipeline { let layout = device.create_pipeline_layout( &wgpu::PipelineLayoutDescriptor { label: Some("iced_wgpu.quad.gradient.pipeline"), + push_constant_ranges: &[], bind_group_layouts: &[constants_layout], - immediate_size: 0, }, ); @@ -155,7 +155,7 @@ impl Pipeline { mask: !0, alpha_to_coverage_enabled: false, }, - multiview_mask: None, + multiview: None, cache: None, }, ); diff --git a/wgpu/src/quad/solid.rs b/wgpu/src/quad/solid.rs index 49e4cf01..7e48358e 100644 --- a/wgpu/src/quad/solid.rs +++ b/wgpu/src/quad/solid.rs @@ -45,7 +45,7 @@ impl Layer { instances: &[Solid], ) { let _ = self.instances.resize(device, instances.len()); - let _ = self.instances.write(encoder, belt, 0, instances); + let _ = self.instances.write(device, encoder, belt, 0, instances); self.instance_count = instances.len(); } @@ -65,8 +65,8 @@ impl Pipeline { let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("iced_wgpu.quad.solid.pipeline"), + push_constant_ranges: &[], bind_group_layouts: &[constants_layout], - immediate_size: 0, }); let shader = @@ -139,7 +139,7 @@ impl Pipeline { mask: !0, alpha_to_coverage_enabled: false, }, - multiview_mask: None, + multiview: None, cache: None, }); diff --git a/wgpu/src/text.rs b/wgpu/src/text.rs index b6d9e679..16efa092 100644 --- a/wgpu/src/text.rs +++ b/wgpu/src/text.rs @@ -619,7 +619,7 @@ fn prepare( )?; Some(cryoglyph::TextArea { - text: buffer.layout_runs(), + buffer, left: position.x, top: position.y, scale: transformation.scale_factor() diff --git a/wgpu/src/triangle.rs b/wgpu/src/triangle.rs index 5607d03a..fa5ecb9c 100644 --- a/wgpu/src/triangle.rs +++ b/wgpu/src/triangle.rs @@ -313,7 +313,6 @@ fn render<'a>( depth_stencil_attachment: None, timestamp_writes: None, occlusion_query_set: None, - multiview_mask: None, }) }; @@ -426,13 +425,18 @@ impl Layer { let indices = mesh.indices(); - index_offset += - self.index_buffer - .write(encoder, belt, index_offset, indices); + index_offset += self.index_buffer.write( + device, + encoder, + belt, + index_offset, + indices, + ); match mesh { Mesh::Solid { buffers, .. } => { solid_vertex_offset += self.solid.vertices.write( + device, encoder, belt, solid_vertex_offset, @@ -440,14 +444,16 @@ impl Layer { ); solid_uniform_offset += self.solid.uniforms.write( + device, encoder, belt, solid_uniform_offset, &[uniforms], - ) + ); } Mesh::Gradient { buffers, .. } => { gradient_vertex_offset += self.gradient.vertices.write( + device, encoder, belt, gradient_vertex_offset, @@ -455,6 +461,7 @@ impl Layer { ); gradient_uniform_offset += self.gradient.uniforms.write( + device, encoder, belt, gradient_uniform_offset, @@ -724,7 +731,7 @@ mod solid { &wgpu::PipelineLayoutDescriptor { label: Some("iced_wgpu.triangle.solid.pipeline_layout"), bind_group_layouts: &[&constants_layout], - immediate_size: 0, + push_constant_ranges: &[], }, ); @@ -777,7 +784,7 @@ mod solid { primitive: triangle::primitive_state(), depth_stencil: None, multisample: triangle::multisample_state(antialiasing), - multiview_mask: None, + multiview: None, cache: None, }, ); @@ -879,7 +886,7 @@ mod gradient { &wgpu::PipelineLayoutDescriptor { label: Some("iced_wgpu.triangle.gradient.pipeline_layout"), bind_group_layouts: &[&constants_layout], - immediate_size: 0, + push_constant_ranges: &[], }, ); @@ -942,7 +949,7 @@ mod gradient { primitive: triangle::primitive_state(), depth_stencil: None, multisample: triangle::multisample_state(antialiasing), - multiview_mask: None, + multiview: None, cache: None, }, ); diff --git a/wgpu/src/triangle/msaa.rs b/wgpu/src/triangle/msaa.rs index 46118361..8ca49461 100644 --- a/wgpu/src/triangle/msaa.rs +++ b/wgpu/src/triangle/msaa.rs @@ -69,8 +69,8 @@ impl Pipeline { let layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { label: Some("iced_wgpu::triangle::msaa pipeline layout"), + push_constant_ranges: &[], bind_group_layouts: &[&constant_layout, &texture_layout], - immediate_size: 0, }); let shader = @@ -116,7 +116,7 @@ impl Pipeline { mask: !0, alpha_to_coverage_enabled: false, }, - multiview_mask: None, + multiview: None, cache: None, }); @@ -177,7 +177,6 @@ impl Pipeline { depth_stencil_attachment: None, timestamp_writes: None, occlusion_query_set: None, - multiview_mask: None, }) } } @@ -321,6 +320,7 @@ impl State { 0, NonZeroU64::new(std::mem::size_of::() as u64) .expect("non-empty ratio"), + device, ) .copy_from_slice(bytemuck::bytes_of(&ratio)); @@ -351,7 +351,6 @@ impl State { depth_stencil_attachment: None, timestamp_writes: None, occlusion_query_set: None, - multiview_mask: None, }); render_pass.set_pipeline(&pipeline.raw); diff --git a/wgpu/src/window.rs b/wgpu/src/window.rs index 61be2187..b9ec54bd 100644 --- a/wgpu/src/window.rs +++ b/wgpu/src/window.rs @@ -1,8 +1,13 @@ //! Display rendering results on windows. pub mod compositor; -#[cfg(wayland_platform)] +#[cfg(all( + unix, + feature = "cctk", + not(target_os = "macos"), + not(target_os = "redox") +))] mod wayland; -#[cfg(all(unix, feature = "x11", not(target_os = "macos"), not(target_os = "redox")))] +#[cfg(all(unix, not(target_os = "macos"), not(target_os = "redox")))] mod x11; pub use compositor::Compositor; diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index fef87b39..833a642e 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -9,10 +9,16 @@ use crate::graphics::{self, Shell, Viewport}; use crate::settings::{self, Settings}; use crate::{Engine, Renderer}; -#[cfg(wayland_platform)] +#[cfg(all( + unix, + feature = "cctk", + not(target_os = "macos"), + not(target_os = "redox") +))] use super::wayland::get_wayland_device_ids; -#[cfg(all(unix, feature = "x11", not(target_os = "macos"), not(target_os = "redox")))] +#[cfg(all(unix, not(target_os = "macos"), not(target_os = "redox")))] use super::x11::get_x11_device_ids; +use std::future::Future; /// A window graphics backend for iced powered by `wgpu`. pub struct Compositor { @@ -59,12 +65,15 @@ impl Compositor { compatible_window: Option, shell: Shell, ) -> Result { - #[cfg(wayland_platform)] + #[cfg(all( + unix, + feature = "cctk", + not(target_os = "macos"), + not(target_os = "redox") + ))] let ids = compatible_window.as_ref().and_then(|window| { - let w = get_wayland_device_ids(window); - #[cfg(feature = "x11")] - let w = w.or_else(|| get_x11_device_ids(window)); - w + get_wayland_device_ids(window) + .or_else(|| get_x11_device_ids(window)) }); // HACK: @@ -73,7 +82,12 @@ impl Compositor { // 3. and the user didn't set an adapter name, // 4. and the user didn't request the high power pref // => don't load the nvidia icd, as it might power on the gpu in hybrid setups causing severe delays - #[cfg(wayland_platform)] + #[cfg(all( + unix, + feature = "cctk", + not(target_os = "macos"), + not(target_os = "redox") + ))] if !matches!(ids, Some((0x10de, _))) && std::env::var_os("__NV_PRIME_RENDER_OFFLOAD") .is_none_or(|var| var == "0") @@ -112,7 +126,6 @@ impl Compositor { // if log::max_level() >= log::LevelFilter::Info { // let available_adapters: Vec<_> = instance // .enumerate_adapters(settings.backends) - // .await // .iter() // .map(wgpu::Adapter::get_info) // .collect(); @@ -133,11 +146,15 @@ impl Compositor { let mut adapter = None; #[cfg_attr(not(unix), allow(dead_code))] if std::env::var_os("WGPU_ADAPTER_NAME").is_none() { - #[cfg(wayland_platform)] + #[cfg(all( + unix, + feature = "cctk", + not(target_os = "macos"), + not(target_os = "redox") + ))] if let Some((vendor_id, device_id)) = ids { adapter = instance .enumerate_adapters(settings.backends) - .await .into_iter() .filter(|adapter| { let info = adapter.get_info(); @@ -155,7 +172,6 @@ impl Compositor { } else if let Ok(name) = std::env::var("WGPU_ADAPTER_NAME") { adapter = instance .enumerate_adapters(settings.backends) - .await .into_iter() .filter(|adapter| { let info = adapter.get_info(); @@ -168,8 +184,6 @@ impl Compositor { true } }); - } else { - adapter = instance.request_adapter(&adapter_options).await.ok(); } let adapter = match adapter { @@ -272,14 +286,6 @@ impl Compositor { ..limits }); - // Request SHADER_F16 only if the adapter supports it (e.g., not available in WebGL2) - let required_features = - if adapter.features().contains(wgpu::Features::SHADER_F16) { - wgpu::Features::SHADER_F16 - } else { - wgpu::Features::empty() - }; - let mut errors = Vec::new(); for required_limits in limits { @@ -288,7 +294,7 @@ impl Compositor { label: Some( "iced_wgpu::window::compositor device descriptor", ), - required_features, + required_features: wgpu::Features::empty(), required_limits: required_limits.clone(), memory_hints: wgpu::MemoryHints::MemoryUsage, trace: wgpu::Trace::Off, @@ -346,14 +352,6 @@ pub fn present( ) -> Result<(), compositor::SurfaceError> { match surface.get_current_texture() { Ok(frame) => { - if frame.texture.width() != viewport.physical_width() - || frame.texture.height() != viewport.physical_height() - { - return Err(compositor::SurfaceError::Outdated); - } - - let suboptimal = frame.suboptimal; - let view = &frame .texture .create_view(&wgpu::TextureViewDescriptor::default()); @@ -369,10 +367,6 @@ pub fn present( on_pre_present(); frame.present(); - if suboptimal { - return Err(compositor::SurfaceError::Outdated); - } - Ok(()) } Err(error) => match error { diff --git a/wgpu/src/window/x11.rs b/wgpu/src/window/x11.rs index a1508134..58da401a 100644 --- a/wgpu/src/window/x11.rs +++ b/wgpu/src/window/x11.rs @@ -1,5 +1,3 @@ -#![allow(unexpected_cfgs)] - use std::{ fs, io::{BufRead, BufReader}, @@ -146,9 +144,7 @@ pub fn get_x11_device_ids(window: &W) -> Option<(u16, u16)> { { let stat = stat(Path::new("/dev/dri").join(device)).ok()?; - // Hack (u64 as u64) for E2K CPU architecture - #[allow(clippy::unnecessary_cast)] - let dev = stat.st_rdev as u64; + let dev = stat.st_rdev; return super::ids_from_dev(dev); } } @@ -169,9 +165,7 @@ pub fn get_x11_device_ids(window: &W) -> Option<(u16, u16)> { let dri3 = conn.dri3_open(root, x11rb::NONE).ok()?.reply().ok()?; let device_fd = dri3.device_fd; let stat = fstat(device_fd).ok()?; - // Hack (u64 as u64) for E2K CPU architecture - #[allow(clippy::unnecessary_cast)] - let dev = stat.st_rdev as u64; + let dev = stat.st_rdev; super::ids_from_dev(dev) } } diff --git a/widget/Cargo.toml b/widget/Cargo.toml index 0726ae40..ab34819b 100644 --- a/widget/Cargo.toml +++ b/widget/Cargo.toml @@ -29,13 +29,15 @@ highlighter = ["dep:iced_highlighter"] advanced = [] crisp = [] a11y = ["iced_accessibility"] -wayland = ["iced_runtime/wayland", "dep:cctk"] +cctk = ["iced_runtime/cctk", "dep:cctk"] [dependencies] iced_renderer.workspace = true iced_runtime.workspace = true iced_accessibility.workspace = true iced_accessibility.optional = true +cctk.workspace = true +cctk.optional = true num-traits.workspace = true log.workspace = true rustc-hash.workspace = true @@ -55,10 +57,3 @@ pulldown-cmark.optional = true iced_highlighter.workspace = true iced_highlighter.optional = true - -[target.'cfg(all(unix, not(any(target_os = "redox", target_family = "wasm", target_os = "android", target_vendor = "apple"))))'.dependencies] -cctk.workspace = true -cctk.optional = true - -[build-dependencies] -build_helpers = { path = "../build_helpers" } diff --git a/widget/build.rs b/widget/build.rs deleted file mode 100644 index db00a773..00000000 --- a/widget/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - build_helpers::cfg_aliases_setup(); -} diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs index 6ac48b0e..873a4541 100644 --- a/widget/src/checkbox.rs +++ b/widget/src/checkbox.rs @@ -505,7 +505,6 @@ where state.raw(), crate::text::Style { color: style.text_color, - ..crate::text::Style::default() }, viewport, ); diff --git a/widget/src/container.rs b/widget/src/container.rs index a264007a..c9a300c9 100644 --- a/widget/src/container.rs +++ b/widget/src/container.rs @@ -35,7 +35,7 @@ use crate::core::{ color, }; -use iced_runtime::{Task, task}; +use iced_runtime::{Action, Task, task}; /// A widget that aligns its contents inside of its boundaries. /// @@ -601,7 +601,7 @@ pub fn visible_bounds(id: Id) -> Task> { operate: &mut dyn FnMut(&mut dyn Operation>), ) { self.depth += 1; - operate(self); + self.traverse(operate); self.depth -= 1; } diff --git a/widget/src/keyed/column.rs b/widget/src/keyed/column.rs index bb98d606..baaee5c9 100644 --- a/widget/src/keyed/column.rs +++ b/widget/src/keyed/column.rs @@ -1,6 +1,7 @@ //! Keyed columns distribute content vertically while keeping continuity. //! Distribute content vertically. +use crate::core::event; use crate::core::layout; use crate::core::mouse; use crate::core::overlay; @@ -292,12 +293,9 @@ where .zip(&mut tree.children) .zip(layout.children()) .for_each(|((child, state), c_layout)| { - child.as_widget_mut().operate( - state, - c_layout.with_virtual_offset(layout.virtual_offset()), - renderer, - operation, - ); + child + .as_widget_mut() + .operate(state, c_layout.with_virtual_offset(layout.virtual_offset()), renderer, operation); }); }); } @@ -320,13 +318,7 @@ where .zip(layout.children()) { child.as_widget_mut().update( - tree, - event, - c_layout.with_virtual_offset(layout.virtual_offset()), - cursor, - renderer, - clipboard, - shell, + tree, event, c_layout.with_virtual_offset(layout.virtual_offset()), cursor, renderer, clipboard, shell, viewport, ); } @@ -345,13 +337,9 @@ where .zip(&tree.children) .zip(layout.children()) .map(|((child, tree), c_layout)| { - child.as_widget().mouse_interaction( - tree, - c_layout.with_virtual_offset(layout.virtual_offset()), - cursor, - viewport, - renderer, - ) + child + .as_widget() + .mouse_interaction(tree, c_layout.with_virtual_offset(layout.virtual_offset()), cursor, viewport, renderer) }) .max() .unwrap_or_default() diff --git a/widget/src/lib.rs b/widget/src/lib.rs index 526f3576..d9bdf1f3 100644 --- a/widget/src/lib.rs +++ b/widget/src/lib.rs @@ -9,8 +9,6 @@ pub use iced_renderer::graphics; pub use core::widget::Id; -pub(crate) const DRAG_DEADBAND_DISTANCE: f32 = 10.0; - mod action; mod mouse_area; mod pin; diff --git a/widget/src/list.rs b/widget/src/list.rs index 9f33244e..de9fe9b8 100644 --- a/widget/src/list.rs +++ b/widget/src/list.rs @@ -1,5 +1,5 @@ #![allow(missing_docs)] -use crate::core::event::Event; +use crate::core::event::{self, Event}; use crate::core::layout; use crate::core::mouse; use crate::core::overlay; @@ -363,25 +363,24 @@ where let state = tree.state.downcast_mut::(); let offset = layout.position() - Point::ORIGIN; - for (element, (index, layout, tree)) in self - .visible_elements + self.visible_elements .iter_mut() .zip(&mut state.visible_layouts) - { - element.as_widget_mut().update( - tree, - event, - Layout::with_offset( - offset + Vector::new(0.0, self.spacing * *index as f32), - layout, - ), - cursor, - renderer, - clipboard, - shell, - viewport, - ); - } + .map(|(element, (index, layout, tree))| { + element.as_widget_mut().update( + tree, + event, + Layout::with_offset( + offset + Vector::new(0.0, self.spacing * *index as f32), + layout, + ), + cursor, + renderer, + clipboard, + shell, + viewport, + ) + }); if let Event::Window(window::Event::RedrawRequested(_)) = event { match &mut state.task { diff --git a/widget/src/mouse_area.rs b/widget/src/mouse_area.rs index 4d808348..3d355c52 100644 --- a/widget/src/mouse_area.rs +++ b/widget/src/mouse_area.rs @@ -2,6 +2,7 @@ use iced_renderer::core::mouse::Click; +use crate::core::event; use crate::core::layout; use crate::core::mouse; use crate::core::overlay; diff --git a/widget/src/pane_grid.rs b/widget/src/pane_grid.rs index 9358c0ad..d43c69bd 100644 --- a/widget/src/pane_grid.rs +++ b/widget/src/pane_grid.rs @@ -92,8 +92,7 @@ use crate::core::{ }; use log::trace; -use crate::DRAG_DEADBAND_DISTANCE; - +const DRAG_DEADBAND_DISTANCE: f32 = 10.0; const THICKNESS_RATIO: f32 = 25.0; /// A collection of panes distributed using either vertical or horizontal splits diff --git a/widget/src/pane_grid/content.rs b/widget/src/pane_grid/content.rs index 4c41e3a6..a76010e7 100644 --- a/widget/src/pane_grid/content.rs +++ b/widget/src/pane_grid/content.rs @@ -6,7 +6,7 @@ use crate::core::renderer; use crate::core::widget::{self, Tree}; use crate::core::{ self, Clipboard, Element, Event, Layout, Point, Rectangle, Shell, Size, - Vector, + Vector, event, }; use crate::pane_grid::{Draggable, TitleBar}; diff --git a/widget/src/pin.rs b/widget/src/pin.rs index cef75944..8eb5906e 100644 --- a/widget/src/pin.rs +++ b/widget/src/pin.rs @@ -60,7 +60,6 @@ where width: Length, height: Length, position: Point, - overflow: bool, } impl<'a, Message, Theme, Renderer> Pin<'a, Message, Theme, Renderer> @@ -76,7 +75,6 @@ where width: Length::Fill, height: Length::Fill, position: Point::ORIGIN, - overflow: false, } } @@ -109,12 +107,6 @@ where self.position.y = y.into().0; self } - - /// Sets whether the [`Pin`] can overflow its boundaries. - pub fn overflow(mut self, overflow: bool) -> Self { - self.overflow = overflow; - self - } } impl Widget @@ -153,12 +145,8 @@ where ) -> layout::Node { let limits = limits.width(self.width).height(self.height); - let available = - if self.overflow { - limits.max() - } else { - limits.max() - Size::new(self.position.x, self.position.y) - }; + let available = + limits.max() - Size::new(self.position.x, self.position.y); let node = self .content diff --git a/widget/src/radio.rs b/widget/src/radio.rs index bdca259c..1aa97355 100644 --- a/widget/src/radio.rs +++ b/widget/src/radio.rs @@ -459,7 +459,6 @@ where state.raw(), crate::text::Style { color: style.text_color, - ..crate::text::Style::default() }, viewport, ); diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index cbe3d55a..e005a7b8 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -27,6 +27,7 @@ use iced_runtime::core::widget::Id; #[cfg(feature = "a11y")] use std::borrow::Cow; +use crate::core::event; use crate::core::keyboard; use crate::core::layout; use crate::core::mouse; @@ -932,7 +933,7 @@ where let had_input_method = shell.input_method().is_enabled(); - let c_event = match event.clone() { + let mut c_event = match event.clone() { Event::Dnd(dnd::DndEvent::Offer( id, dnd::OfferEvent::Enter { @@ -960,16 +961,6 @@ where y: y + translation.y as f64, }, )), - Event::Touch(touch::Event::FingerLifted { - id, - position, - }) if matches!( - state.interaction, - Interaction::TouchScrolling(_) - ) => - { - Event::Touch(touch::Event::FingerLost { id, position }) - } e => e, }; self.content.as_widget_mut().update( @@ -997,14 +988,6 @@ where } }; - if matches!( - event, - Event::Mouse(mouse::Event::CursorMoved { .. }) - | Event::Touch(touch::Event::FingerPressed { .. }) - ) { - state.suppress_touch_hover = false; - } - if matches!( event, Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) @@ -1013,18 +996,10 @@ where | touch::Event::FingerLost { .. } ) ) { - if matches!(state.interaction, Interaction::TouchScrolling(_)) { - state.suppress_touch_hover = true; - } state.interaction = Interaction::None; - state.touch_press_start = None; return; } - if let Event::Touch(touch::Event::FingerPressed { .. }) = event { - state.touch_press_start = cursor_over_scrollable; - } - if shell.is_event_captured() { return; } @@ -1118,31 +1093,14 @@ where Interaction::TouchScrolling(position); } touch::Event::FingerMoved { .. } => { - let Some(cursor_position) = cursor.position() + let Interaction::TouchScrolling( + scroll_box_touched_at, + ) = state.interaction else { return; }; - if !matches!( - state.interaction, - Interaction::TouchScrolling(_) - ) { - let Some(start) = state.touch_press_start - else { - return; - }; - if start.distance(cursor_position) - < crate::DRAG_DEADBAND_DISTANCE - { - return; - } - state.interaction = - Interaction::TouchScrolling(start); - } - - let Interaction::TouchScrolling( - scroll_box_touched_at, - ) = state.interaction + let Some(cursor_position) = cursor.position() else { return; }; @@ -1364,14 +1322,6 @@ where state.translation(self.direction, bounds, content_bounds); let cursor = match cursor_over_scrollable { - _ if state.suppress_touch_hover - || matches!( - state.interaction, - Interaction::TouchScrolling(_) - ) => - { - mouse::Cursor::Unavailable - } Some(cursor_position) if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) => { @@ -1547,14 +1497,6 @@ where state.translation(self.direction, bounds, content_bounds); let cursor = match cursor_over_scrollable { - _ if state.suppress_touch_hover - || matches!( - state.interaction, - Interaction::TouchScrolling(_) - ) => - { - cursor.levitate() + translation - } Some(cursor_position) if !(mouse_over_x_scrollbar || mouse_over_y_scrollbar) => { @@ -2080,8 +2022,6 @@ struct State { last_notified: Option, last_scrolled: Option, is_scrollbar_visible: bool, - touch_press_start: Option, - suppress_touch_hover: bool, } #[derive(Debug, Clone, Copy)] @@ -2107,8 +2047,6 @@ impl Default for State { last_notified: None, last_scrolled: None, is_scrollbar_visible: true, - touch_press_start: None, - suppress_touch_hover: false, } } } diff --git a/widget/src/slider.rs b/widget/src/slider.rs index 70cfc9e4..ff32f417 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -110,8 +110,6 @@ where height: f32, class: Theme::Class<'a>, status: Option, - handle_width: f32, - handle_height: f32, } impl<'a, T, Message, Theme> Slider<'a, T, Message, Theme> @@ -121,13 +119,7 @@ where Theme: Catalog, { /// The default height of a [`Slider`]. - pub const DEFAULT_HEIGHT: f32 = 26.0; - - /// The default max height of a [`Handle`]. - pub const DEFAULT_MAX_HANDLE_HEIGHT: f32 = 26.0; - - /// The default max width of a [`Handle`]. - pub const DEFAULT_MAX_HANDLE_WIDTH: f32 = 26.0; + pub const DEFAULT_HEIGHT: f32 = 16.0; /// Creates a new [`Slider`]. /// @@ -173,8 +165,6 @@ where height: Self::DEFAULT_HEIGHT, class: Theme::default(), status: None, - handle_width: Self::DEFAULT_MAX_HANDLE_WIDTH, - handle_height: Self::DEFAULT_MAX_HANDLE_HEIGHT, } } @@ -217,24 +207,6 @@ where self } - /// Sets the max width of the [`Handle`]. - /// - /// Theme can be used to change the size and shape of handle - /// but width of handle defined in theme will not exceed this width - pub fn handle_width(mut self, width: impl Into) -> Self { - self.handle_width = width.into().0; - self - } - - /// Sets the max height of the [`Handle`]. - /// - /// Theme can be used to change the size and shape of handle - /// but height of handle defined in theme will not exceed this height - pub fn handle_height(mut self, height: impl Into) -> Self { - self.handle_height = height.into().0; - self - } - /// Sets the step size of the [`Slider`]. pub fn step(mut self, step: impl Into) -> Self { self.step = step.into(); @@ -351,15 +323,8 @@ where let mut update = || { let current_value = self.value; - self.handle_width = self.handle_width.min(layout.bounds().width); - self.handle_height = self.handle_height.min(layout.bounds().height); - let locate = |cursor_position: Point| -> Option { - let bounds = Rectangle { - x: layout.bounds().x + self.handle_width / 2.0, - width: layout.bounds().width - self.handle_width, - ..layout.bounds() - }; + let bounds = layout.bounds(); if cursor_position.x <= bounds.x { Some(*self.range.start()) @@ -544,29 +509,53 @@ where _cursor: mouse::Cursor, _viewport: &Rectangle, ) { - let bounds = Rectangle { - x: layout.bounds().x + self.handle_width / 2.0, - width: layout.bounds().width - self.handle_width, - ..layout.bounds() - }; + let bounds = layout.bounds(); let style = theme.style(&self.class, self.status.unwrap_or(Status::Active)); - let (mut handle_width, mut handle_height, handle_border_radius) = + let border_width = style + .handle + .border_width + .min(bounds.height / 2.0) + .min(bounds.width / 2.0); + + let (handle_width, handle_height, handle_border_radius) = match style.handle.shape { HandleShape::Circle { radius } => { + let radius = (radius) + .max(2.0 * border_width) + .min(bounds.height / 2.0) + .min(bounds.width / 2.0 + 2.0 * border_width); (radius * 2.0, radius * 2.0, Radius::from(radius)) } HandleShape::Rectangle { height, width, border_radius, - } => (f32::from(width), f32::from(height), border_radius), - }; + } => { + let width = (f32::from(width)).max(2.0 * border_width); + let height = (f32::from(height)).max(2.0 * border_width); + let mut border_radius: [f32; 4] = border_radius.into(); + for r in &mut border_radius { + *r = (*r) + .min(height / 2.0) + .min(width / 2.0) + .max(*r * (width + border_width * 2.0) / width); + } - handle_width = handle_width.min(self.handle_width); - handle_height = handle_height.min(self.handle_height); + ( + width, + height, + Radius { + top_left: border_radius[0], + top_right: border_radius[1], + bottom_right: border_radius[2], + bottom_left: border_radius[3], + }, + ) + } + }; let value = self.value.into() as f32; let (range_start, range_end) = { @@ -578,7 +567,8 @@ where let offset = if range_start >= range_end { 0.0 } else { - bounds.width * (value - range_start) / (range_end - range_start) + (bounds.width - handle_width) * (value - range_start) + / (range_end - range_start) }; let rail_y = bounds.y + bounds.height / 2.0; @@ -600,8 +590,7 @@ where x: bounds.x + offset, y: rail_y + 6.0, width: BREAKPOINT_WIDTH, - height: 8.0_f32 - .min(bounds.y + bounds.height - (rail_y + 6.0)), + height: 8.0, }, border: Border { radius: 0.0.into(), @@ -618,9 +607,9 @@ where renderer::Quad { bounds: Rectangle { x: bounds.x, - y: rail_y - (style.rail.width).min(bounds.height) / 2.0, - width: offset, - height: (style.rail.width).min(bounds.height), + y: rail_y - style.rail.width / 2.0, + width: offset + handle_width / 2.0, + height: style.rail.width, }, border: style.rail.border, ..renderer::Quad::default() @@ -633,10 +622,10 @@ where renderer.fill_quad( renderer::Quad { bounds: Rectangle { - x: bounds.x + offset, - y: rail_y - (style.rail.width).min(bounds.height) / 2.0, - width: bounds.width - offset, - height: (style.rail.width).min(bounds.height), + x: bounds.x + offset + handle_width / 2.0, + y: rail_y - style.rail.width / 2.0, + width: bounds.width - offset - handle_width / 2.0, + height: style.rail.width, }, border: style.rail.border, ..renderer::Quad::default() @@ -648,7 +637,7 @@ where renderer.fill_quad( renderer::Quad { bounds: Rectangle { - x: bounds.x + offset - handle_width / 2.0, + x: bounds.x + offset, y: rail_y - (handle_height / 2.0), width: handle_width, height: handle_height, diff --git a/widget/src/stack.rs b/widget/src/stack.rs index cd30a886..e85bf2af 100644 --- a/widget/src/stack.rs +++ b/widget/src/stack.rs @@ -1,5 +1,6 @@ //! Display content on top of other content. +use crate::core::event; use crate::core::layout; use crate::core::mouse; use crate::core::overlay; diff --git a/widget/src/text/rich.rs b/widget/src/text/rich.rs index ef44e2bf..cd368e83 100644 --- a/widget/src/text/rich.rs +++ b/widget/src/text/rich.rs @@ -179,10 +179,7 @@ where { let color = color.map(Into::into); - self.style(move |_theme| Style { - color, - ..Style::default() - }) + self.style(move |_theme| Style { color }) } /// Sets the default style class of the [`Rich`] text. diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs index 34a8825f..b93c96f3 100644 --- a/widget/src/text_editor.rs +++ b/widget/src/text_editor.rs @@ -544,8 +544,6 @@ pub struct State { highlighter: RefCell, highlighter_settings: Highlighter::Settings, highlighter_format_address: usize, - context_menu_position: Option, - pending_edit: Option, } #[derive(Debug, Clone)] @@ -581,14 +579,6 @@ impl State { pub fn is_focused(&self) -> bool { self.focus.is_some() } - - /// Clears focus, selection, and all interaction state. - pub fn clear_focus(&mut self) { - self.focus = None; - self.drag_click = None; - self.context_menu_position = None; - self.pending_edit = Some(Action::ClearSelection); - } } impl operation::Focusable @@ -603,7 +593,7 @@ impl operation::Focusable } fn unfocus(&mut self) { - self.clear_focus(); + self.focus = None; } } @@ -631,8 +621,6 @@ where )), highlighter_settings: self.highlighter_settings.clone(), highlighter_format_address: self.highlighter_format as usize, - context_menu_position: None, - pending_edit: None, }) } @@ -711,58 +699,6 @@ where shell: &mut Shell<'_, Message>, _viewport: &Rectangle, ) { - // Handle context menu and focus-loss on clicks outside. - { - let state = tree.state.downcast_mut::>(); - let text_bounds = layout.bounds(); - - if matches!( - event, - Event::Mouse(mouse::Event::ButtonPressed(_)) - | Event::Touch( - crate::core::touch::Event::FingerPressed { .. } - ) - ) && cursor.position_over(text_bounds).is_none() - { - state.clear_focus(); - } - - match event { - Event::Mouse(mouse::Event::ButtonPressed( - mouse::Button::Right, - )) => { - if let Some(pos) = cursor.position_over(text_bounds) { - if state.focus.is_none() { - state.focus = Some(Focus::now()); - } - state.context_menu_position = Some(pos); - shell.capture_event(); - return; - } - } - Event::Mouse(mouse::Event::ButtonPressed( - mouse::Button::Left, - )) => { - if state.context_menu_position.take().is_some() { - shell.capture_event(); - return; - } - } - _ => {} - } - } - - // Process pending edits from context menu - // publishes via on_edit so the app calls content.perform(). - { - let state = tree.state.downcast_mut::>(); - if let Some(action) = state.pending_edit.take() { - if let Some(on_edit) = self.on_edit.as_ref() { - shell.publish((on_edit)(action)); - } - } - } - let Some(on_edit) = self.on_edit.as_ref() else { return; }; @@ -1287,23 +1223,6 @@ impl Binding { return Some(binding); } - let alt_clipboard = match key.as_ref() { - keyboard::Key::Named(key::Named::Insert) if modifiers.shift() => { - Some(Self::Paste) - } - keyboard::Key::Named(key::Named::Insert) if modifiers.command() => { - Some(Self::Copy) - } - keyboard::Key::Named(key::Named::Delete) if modifiers.shift() => { - Some(Self::Cut) - } - _ => None, - }; - - if let Some(binding) = alt_clipboard { - return Some(binding); - } - #[cfg(target_os = "macos")] let modified_key = convert_macos_shortcut(&key, modifiers).unwrap_or(modified_key); @@ -1626,63 +1545,3 @@ pub(crate) fn convert_macos_shortcut( Some(keyboard::Key::Named(key)) } - -use crate::core::widget::text::HasSelectableText; - -impl HasSelectableText - for TextEditor<'_, Highlighter, Message, Theme, Renderer> -where - Highlighter: text::Highlighter, - Theme: Catalog, - Renderer: text::Renderer, -{ - fn selected_text(&self, _tree: &widget::Tree) -> Option { - self.content.selection() - } - - fn select_all(&self, tree: &mut widget::Tree) { - let state = tree.state.downcast_mut::>(); - state.pending_edit = Some(Action::SelectAll); - } - - fn is_editable(&self) -> bool { - self.on_edit.is_some() - } - - fn is_focused(&self, tree: &widget::Tree) -> bool { - tree.state.downcast_ref::>().is_focused() - } - - fn context_menu_position(&self, tree: &widget::Tree) -> Option { - tree.state - .downcast_ref::>() - .context_menu_position - } - - fn set_context_menu_position( - &self, - tree: &mut widget::Tree, - pos: Option, - ) { - tree.state - .downcast_mut::>() - .context_menu_position = pos; - } - - fn delete_selection(&self, tree: &mut widget::Tree) -> Option { - let state = tree.state.downcast_mut::>(); - state.pending_edit = Some(Action::Edit(Edit::Delete)); - Some(String::new()) - } - - fn paste_text( - &self, - tree: &mut widget::Tree, - text: &str, - ) -> Option { - let state = tree.state.downcast_mut::>(); - state.pending_edit = - Some(Action::Edit(Edit::Paste(Arc::new(text.to_owned())))); - Some(String::new()) - } -} diff --git a/widget/src/themer.rs b/widget/src/themer.rs index 76448ae1..306c8580 100644 --- a/widget/src/themer.rs +++ b/widget/src/themer.rs @@ -1,5 +1,6 @@ use crate::container; +use crate::core::event; use crate::core::layout; use crate::core::mouse; use crate::core::overlay; diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs index b4e66887..d398a79b 100644 --- a/widget/src/toggler.rs +++ b/widget/src/toggler.rs @@ -37,6 +37,7 @@ use std::borrow::Cow; use iced_runtime::core::border::Radius; use crate::core::alignment; +use crate::core::border; use crate::core::layout; use crate::core::mouse; use crate::core::renderer; @@ -482,7 +483,6 @@ where state.raw(), crate::text::Style { color: style.text_color, - ..crate::text::Style::default() }, viewport, ); @@ -509,7 +509,7 @@ where let space = style.handle_margin; - let _toggler_background_bounds = Rectangle { + let toggler_background_bounds = Rectangle { x: bounds.x, y: bounds.y, width: bounds.width, @@ -529,7 +529,7 @@ where style.background, ); - let _padding = (style.padding_ratio * bounds.height).round(); + let padding = (style.padding_ratio * bounds.height).round(); let toggler_foreground_bounds = Rectangle { x: bounds.x + if self.is_toggled { diff --git a/winit/Cargo.toml b/winit/Cargo.toml index 741528b5..41e4a582 100644 --- a/winit/Cargo.toml +++ b/winit/Cargo.toml @@ -14,18 +14,7 @@ keywords.workspace = true workspace = true [features] -wayland = [ - "winit/wayland", - "wayland-csd-adwaita", - "wayland-protocols", - "raw-window-handle", - "iced_runtime/wayland", - "wayland-backend", - "xkbcommon", - "xkbcommon-dl", - "xkeysym", - "dep:cctk", -] +wayland = ["winit/wayland", "wayland-csd-adwaita"] default = ["x11", "wayland-dlopen"] debug = ["iced_debug/enable"] sysinfo = ["dep:sysinfo"] @@ -37,6 +26,17 @@ program = [] wayland-dlopen = ["winit/wayland-dlopen"] wayland-csd-adwaita = ["winit/wayland-csd-adwaita"] a11y = ["iced_accessibility", "iced_runtime/a11y"] +cctk = [ + "wayland", + "wayland-protocols", + "raw-window-handle", + "iced_runtime/cctk", + "wayland-backend", + "xkbcommon", + "xkbcommon-dl", + "xkeysym", + "dep:cctk", +] # Prevents multiple separate process instances. single-instance = [] @@ -64,8 +64,7 @@ iced_debug.workspace = true iced_program.workspace = true -[target.'cfg(all(unix, not(any(target_os = "redox", target_family = "wasm", target_os = "android", target_vendor = "apple"))))'.dependencies] - +[target.'cfg(target_os = "linux")'.dependencies] mundy.workspace = true mundy.optional = true @@ -90,6 +89,3 @@ winapi.workspace = true web-sys.workspace = true web-sys.features = ["Document", "Window", "HtmlCanvasElement"] wasm-bindgen-futures.workspace = true - -[build-dependencies] -build_helpers = { path = "../build_helpers" } diff --git a/winit/build.rs b/winit/build.rs deleted file mode 100644 index db00a773..00000000 --- a/winit/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - build_helpers::cfg_aliases_setup(); -} diff --git a/winit/src/application/drag_resize.rs b/winit/src/application/drag_resize.rs index 29fa10da..6d575b52 100644 --- a/winit/src/application/drag_resize.rs +++ b/winit/src/application/drag_resize.rs @@ -49,10 +49,7 @@ pub fn event_func( position, .. } => { - let resizable = !window.is_decorated() - && !window.is_maximized() - && window.fullscreen().is_none(); - if resizable { + if !window.is_decorated() { let location = cursor_resize_direction( window.surface_size(), *position, diff --git a/winit/src/clipboard.rs b/winit/src/clipboard.rs index 2c9e4a32..d302ac36 100644 --- a/winit/src/clipboard.rs +++ b/winit/src/clipboard.rs @@ -92,7 +92,7 @@ impl Clipboard { }) .unwrap_or(State::Unavailable); - #[cfg(wayland_platform)] + #[cfg(target_os = "linux")] if let State::Connected { clipboard, .. } = &state { clipboard.init_dnd(Box::new(sender)); } diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs index 8ce3ed66..cc5676b5 100644 --- a/winit/src/conversion.rs +++ b/winit/src/conversion.rs @@ -23,33 +23,6 @@ use winit::event::Force; use winit::icon::IconProvider; use winit::keyboard::SmolStr; -/// Returns the activation token provided by the compositor, if any. -/// -/// The token is single-use, so it is only ever handed out to the first window. -#[cfg(target_os = "linux")] -fn take_activation_token() -> Option { - use std::sync::Mutex; - use std::sync::OnceLock; - use winit::platform::startup_notify::reset_activation_token_env; - - static TOKEN: OnceLock>> = - OnceLock::new(); - - TOKEN - .get_or_init(|| { - let token = std::env::var("XDG_ACTIVATION_TOKEN") - .ok() - .map(winit::window::ActivationToken::from_raw); - - reset_activation_token_env(); - - Mutex::new(token) - }) - .lock() - .ok() - .and_then(|mut token| token.take()) -} - /// Converts some [`window::Settings`] into some `WindowAttributes` from `winit`. pub fn window_attributes( settings: window::Settings, @@ -209,19 +182,12 @@ pub fn window_attributes( { use winit::platform::wayland::WindowAttributesWayland; - let mut wayland_attributes = WindowAttributesWayland::default() - .with_name( + attributes = attributes.with_platform_attributes(Box::new( + WindowAttributesWayland::default().with_name( &settings.platform_specific.application_id, &settings.platform_specific.application_id, - ); - - if let Some(token) = take_activation_token() { - wayland_attributes = - wayland_attributes.with_activation_token(token); - } - - attributes = attributes - .with_platform_attributes(Box::new(wayland_attributes)); + ), + )); } } @@ -421,19 +387,19 @@ pub fn window_event( self::modifiers(new_modifiers.state()), ))) } - WindowEvent::Ime(event) => match event { - Ime::Enabled => Some(input_method::Event::Opened), - Ime::Preedit(content, size) => Some(input_method::Event::Preedit( + WindowEvent::Ime(event) => Some(Event::InputMethod(match event { + Ime::Enabled => input_method::Event::Opened, + Ime::Preedit(content, size) => input_method::Event::Preedit( content, size.map(|(start, end)| start..end), - )), - Ime::Commit(content) => Some(input_method::Event::Commit(content)), - Ime::Disabled => Some(input_method::Event::Closed), - // Upstream iced depends on the winit version which doesn't support - // this kind of ime event. - Ime::DeleteSurrounding { .. } => None, - } - .map(Event::InputMethod), + ), + Ime::Commit(content) => input_method::Event::Commit(content), + Ime::Disabled => input_method::Event::Closed, + Ime::DeleteSurrounding { + before_bytes, + after_bytes, + } => todo!(), + })), WindowEvent::Focused(focused) => Some(Event::Window(if focused { window::Event::Focused } else { @@ -458,7 +424,7 @@ pub fn window_event( WindowEvent::ScaleFactorChanged { scale_factor, .. } => { Some(Event::Window(window::Event::Rescaled(scale_factor as f32))) } - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] WindowEvent::SuggestedBounds(bounds) => { let size = bounds.map(|bounds| { let size = bounds.to_logical(scale_factor); @@ -471,7 +437,7 @@ pub fn window_event( ), ))) } - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] WindowEvent::WindowStateChanged => { use cctk::sctk::reexports::csd_frame::WindowState; use winit::platform::wayland::WindowExtWayland; @@ -1525,7 +1491,7 @@ pub fn winit_key_code( }) } -#[cfg(wayland_platform)] +#[cfg(all(feature = "cctk", target_os = "linux"))] fn winit_native_key_code( keycode: keyboard::key::NativeCode, ) -> winit::keyboard::NativeKeyCode { @@ -1549,7 +1515,7 @@ fn winit_native_key_code( } /// Reconstruct the raw keycode -#[cfg(wayland_platform)] +#[cfg(all(feature = "cctk", target_os = "linux"))] pub fn physical_to_scancode(physical: keyboard::key::Physical) -> Option { let Some(physical_key) = (match physical { keyboard::key::Physical::Code(code) => { diff --git a/winit/src/lib.rs b/winit/src/lib.rs index 38457840..735d73aa 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -40,6 +40,12 @@ pub mod clipboard; pub mod conversion; pub mod platform_specific; +#[cfg(feature = "program")] +pub mod program; + +#[cfg(feature = "system")] +pub mod system; + mod error; mod proxy; mod window; @@ -47,6 +53,7 @@ mod window; pub use clipboard::Clipboard; pub use error::Error; pub use proxy::Proxy; +use winit::dpi::LogicalSize; use winit::dpi::PhysicalPosition; use winit::dpi::PhysicalSize; @@ -91,10 +98,10 @@ where let event_loop = EventLoop::new().expect("Create event loop"); - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] let is_wayland = winit::platform::wayland::EventLoopExtWayland::is_wayland(&event_loop); - #[cfg(not(wayland_platform))] + #[cfg(not(all(feature = "cctk", target_os = "linux")))] let is_wayland = false; // TODO this is new.. @@ -185,15 +192,11 @@ where receiver: mpsc::UnboundedReceiver, error: Option, system_theme: Option>, - #[cfg(feature = "a11y")] control_sender: mpsc::UnboundedSender, - + #[cfg(feature = "a11y")] - adapters: std::collections::HashMap< - window::Id, - (u64, iced_accessibility::accesskit_winit::Adapter), - >, - + adapters: std::collections::HashMap, + #[cfg(target_arch = "wasm32")] is_booted: std::rc::Rc>, #[cfg(target_arch = "wasm32")] @@ -212,7 +215,6 @@ where id: settings.id, sender: event_sender, receiver: control_receiver, - #[cfg(feature = "a11y")] control_sender: control_sender.clone(), error: None, system_theme: Some(system_theme_sender), @@ -261,7 +263,7 @@ where | winit::event::WindowEvent::Moved(_) ); - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] { if matches!(event, WindowEvent::RedrawRequested) { for id in @@ -499,15 +501,9 @@ where } }; } - let window: Arc< - dyn winit::window::Window + 'static, - > = Arc::from(window); + let window: Arc = Arc::from(window); #[cfg(feature = "a11y")] - self.init_adapter( - event_loop, - id, - window.clone(), - ); + self.init_adapter(event_loop, id, window.clone()); self.process_event( event_loop, @@ -576,10 +572,11 @@ where .expect("Send event"); } Control::Winit(id, e) => { - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] { if matches!(e, WindowEvent::RedrawRequested) - { + { + for id in crate::subsurface_widget::subsurface_ids(id) { _ = self.sender .unbounded_send(Event::Winit( @@ -600,7 +597,7 @@ where } } } - + self.sender .start_send(Event::Winit(id, e)) .expect("Send event"); @@ -613,7 +610,7 @@ where #[cfg(feature = "a11y")] Control::InitAdapter(id, window) => { self.init_adapter(event_loop, id, window); - + self.process_event( event_loop, Some(Event::A11yAdapter(id)), @@ -621,8 +618,8 @@ where } #[cfg(feature = "a11y")] Control::Cleanup(id) => { - _ = self.adapters.remove(&id); - } + _ = self.adapters.remove(&id); + }, }, _ => { break; @@ -636,35 +633,34 @@ where } } - #[cfg(feature = "a11y")] - fn init_adapter( - &mut self, - event_loop: &(dyn winit::event_loop::ActiveEventLoop + 'static), - id: core::window::Id, - window: Arc, - ) { + #[cfg(feature = "a11y")] + fn init_adapter(&mut self, event_loop: &(dyn winit::event_loop::ActiveEventLoop + 'static), id: core::window::Id, window: Arc) { use crate::a11y::*; use iced_accessibility::accesskit::{ - ActivationHandler, Node, NodeId, Role, Tree, TreeUpdate, + ActivationHandler, Node, NodeId, Role, + Tree, TreeUpdate, }; use iced_accessibility::accesskit_winit::Adapter; - - let node_id = iced_runtime::core::id::window_node_id(); - - let activation_handler = WinitActivationHandler { - proxy: self.control_sender.clone(), - title: String::new(), - }; - + + let node_id = + iced_runtime::core::id::window_node_id(); + + let activation_handler = + WinitActivationHandler { + proxy: self.control_sender.clone(), + title: String::new(), + }; + let action_handler = WinitActionHandler { id, proxy: self.control_sender.clone(), }; - - let deactivation_handler = WinitDeactivationHandler { - proxy: self.control_sender.clone(), - }; - + + let deactivation_handler = + WinitDeactivationHandler { + proxy: self.control_sender.clone(), + }; + _ = self.adapters.insert( id, ( @@ -678,6 +674,8 @@ where ), ), ); + + } } @@ -772,7 +770,7 @@ async fn run_instance

( let mut platform_specific_handler = crate::platform_specific::PlatformSpecific::default(); - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] if is_wayland { platform_specific_handler = platform_specific_handler.with_wayland( control_sender.clone(), @@ -840,30 +838,6 @@ async fn run_instance

( log::info!("System theme: {system_theme:?}"); - macro_rules! run_action { - ($action:expr) => { - run_action( - $action, - &program, - &mut runtime, - &mut compositor, - &mut events, - &mut messages, - &mut clipboard, - &mut control_sender, - &mut user_interfaces, - &mut window_manager, - &mut ui_caches, - &mut is_window_opening, - &mut system_theme, - &mut platform_specific_handler, - &mut dnd_surface, - &mut dnd_surface_id, - is_daemon, - ) - }; - } - 'next_event: loop { // Empty the queue if possible let event = if let Ok(event) = event_receiver.try_recv() { @@ -883,36 +857,35 @@ async fn run_instance

( exit_on_close_request, make_visible, on_open, - resize_border, + resize_border } => { - #[cfg(wayland_platform)] + + #[cfg(all(feature = "cctk", target_os = "linux"))] platform_specific_handler.send_wayland( platform_specific::Action::TrackWindow(window.clone(), id), ); - if compositor.is_none() { - match create_compositor::

( - window.clone(), - CreateCompositor { - proxy: &proxy, - runtime: &mut runtime, - display_handle: &display_handle, - graphics_settings: &graphics_settings, - default_fonts: &default_fonts, - }, - ) - .await - { - Ok(comp) => { - compositor = Some(comp); - } - Err(error) => { - control_sender - .start_send(Control::Crash( - Error::GraphicsCreationFailed(error), - )) - .expect("Send control message"); - continue; - } + match create_compositor::

( + window.clone(), + CreateCompositor { + proxy: &proxy, + runtime: &mut runtime, + display_handle: &display_handle, + graphics_settings: &graphics_settings, + default_fonts: &default_fonts, + }, + ) + .await + { + Ok(comp) => { + compositor = Some(comp); + } + Err(error) => { + control_sender + .start_send(Control::Crash( + Error::GraphicsCreationFailed(error), + )) + .expect("Send control message"); + continue; } } @@ -940,7 +913,7 @@ async fn run_instance

( compositor, exit_on_close_request, system_theme, - resize_border, + resize_border ); window.raw.set_theme(conversion::window_theme( @@ -1026,7 +999,22 @@ async fn run_instance

( } } Event::UserEvent(action) => { - let exited = run_action!(action); + let exited = run_action( + action, + &program, + &mut runtime, + &mut compositor, + &mut events, + &mut messages, + &mut clipboard, + &mut control_sender, + &mut user_interfaces, + &mut window_manager, + &mut ui_caches, + &mut is_window_opening, + &mut system_theme, + &mut platform_specific_handler, + ); if exited { runtime.track(None.into_iter()); } @@ -1037,7 +1025,7 @@ async fn run_instance

( continue; }; - let Some((id, mut window)) = + let Some((id, mut window)) = window_manager.get_mut_alias(window_id) else { continue; @@ -1052,12 +1040,12 @@ async fn run_instance

( )) .expect("Send redraw event"); continue; - } + } // XX must force update to corner radius before the surface is committed. - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] if (window.surface_version != window.state.surface_version() - || window.logical_size() != window.state.logical_size()) - && !crate::subsurface_widget::is_subsurface(window_id) + || window.logical_size() != window.state.logical_size() + ) && !crate::subsurface_widget::is_subsurface(window_id) { platform_specific_handler.send_wayland( platform_specific::Action::ResizeWindow(id), @@ -1168,7 +1156,22 @@ async fn run_instance

( continue; } - _ = run_action!(action); + _ = run_action( + action, + &program, + &mut runtime, + &mut compositor, + &mut events, + &mut messages, + &mut clipboard, + &mut control_sender, + &mut user_interfaces, + &mut window_manager, + &mut ui_caches, + &mut is_window_opening, + &mut system_theme, + &mut platform_specific_handler, + ); } for (window_id, window) in window_manager.iter_mut() { @@ -1323,7 +1326,9 @@ async fn run_instance

( continue; }; // Initiates a drag resize window state when found. - if let Some(func) = window.drag_resize_window_func.as_mut() { + if let Some(func) = + window.drag_resize_window_func.as_mut() + { if func(window.raw.as_ref(), &event) { continue; } @@ -1349,9 +1354,22 @@ async fn run_instance

( if matches!(event, winit::event::WindowEvent::CloseRequested) && window.exit_on_close_request { - _ = run_action!(Action::Window( - runtime::window::Action::Close(id) - )); + _ = run_action( + Action::Window(runtime::window::Action::Close(id)), + &program, + &mut runtime, + &mut compositor, + &mut events, + &mut messages, + &mut clipboard, + &mut control_sender, + &mut user_interfaces, + &mut window_manager, + &mut ui_caches, + &mut is_window_opening, + &mut system_theme, + &mut platform_specific_handler, + ); } else { window.state.update(&program, window.raw.as_ref(), &event); @@ -1393,7 +1411,8 @@ async fn run_instance

( true } }); - #[cfg(wayland_platform)] + let no_window_events = window_events.is_empty(); + #[cfg(all(feature = "cctk", target_os = "linux"))] window_events.push(core::Event::PlatformSpecific( core::event::PlatformSpecific::Wayland( core::event::wayland::Event::RequestResize, @@ -1410,7 +1429,8 @@ async fn run_instance

( &mut clipboard, &mut messages, ); - let mut needs_redraw = !messages.is_empty(); + let mut needs_redraw = + !no_window_events || !messages.is_empty(); if let Some(requested_size) = clipboard.requested_logical_size.lock().unwrap().take() { @@ -1466,17 +1486,8 @@ async fn run_instance

( mouse_interaction, .. } => { - let mouse_changed = - window.mouse_interaction != mouse_interaction; - window.update_mouse(mouse_interaction); - if mouse_changed { - window.request_redraw( - core::window::RedrawRequest::NextFrame, - ); - } - #[cfg(not(feature = "unconditional-rendering"))] window.request_redraw(_redraw_request); } @@ -1536,7 +1547,22 @@ async fn run_instance

( )); for action in actions { - let exited = run_action!(action); + let exited = run_action( + action, + &program, + &mut runtime, + &mut compositor, + &mut events, + &mut messages, + &mut clipboard, + &mut control_sender, + &mut user_interfaces, + &mut window_manager, + &mut ui_caches, + &mut is_window_opening, + &mut system_theme, + &mut platform_specific_handler, + ); if exited { runtime.track(None.into_iter()); } @@ -1746,6 +1772,7 @@ async fn run_instance

( }; // search windows for widget with operation + if result.is_none() { log::warn!( "start_dnd: widget {:?} not found; drag will fail", @@ -2079,11 +2106,6 @@ fn run_action<'a, P, C>( is_window_opening: &mut bool, system_theme: &mut theme::Mode, platform_specific: &mut crate::platform_specific::PlatformSpecific, - dnd_surface: &mut Option< - Arc>, - >, - dnd_surface_id: &mut Option, - is_daemon: bool, ) -> bool where P: Program, @@ -2126,7 +2148,7 @@ where on_open: channel, }) .expect("Send control action"); - + *is_window_opening = true; } window::Action::Close(id) => { @@ -2137,7 +2159,7 @@ where _ = control_sender.start_send(Control::Cleanup(id)).ok(); } let proxy = clipboard.proxy(); - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] platform_specific .send_wayland(platform_specific::Action::RemoveWindow(id)); if let Some(window) = window_manager.remove(id) { @@ -2168,7 +2190,7 @@ where )); } - if window_manager.is_empty() && !is_daemon { + if window_manager.is_empty() { *compositor = None; } } @@ -2598,10 +2620,6 @@ where } iced_runtime::dnd::DndAction::EndDnd => { clipboard.end_dnd(); - *dnd_surface = None; - if let Some(id) = dnd_surface_id.take() { - platform_specific.retain_subsurfaces(|other| other != id); - } } iced_runtime::dnd::DndAction::PeekDnd(m, channel) => { let data = clipboard.peek_dnd(m); diff --git a/winit/src/platform_specific/mod.rs b/winit/src/platform_specific/mod.rs index e1bfd9b9..9b74ee9c 100644 --- a/winit/src/platform_specific/mod.rs +++ b/winit/src/platform_specific/mod.rs @@ -1,20 +1,24 @@ //! Wayland specific shell //! -use std::collections::HashMap; +use std::{borrow::Cow, collections::HashMap, sync::Arc}; -use iced_graphics::compositor; +#[cfg(all(feature = "cctk", target_os = "linux"))] +use cctk::sctk::reexports::client::Connection; +use iced_graphics::{Compositor, compositor}; use iced_runtime::{ core::{Vector, window}, - user_interface, + platform_specific, user_interface, }; use winit::raw_window_handle::HasWindowHandle; -#[cfg(wayland_platform)] +#[cfg(all(feature = "cctk", target_os = "linux"))] pub mod wayland; -#[cfg(wayland_platform)] +#[cfg(all(feature = "cctk", target_os = "linux"))] pub use wayland::*; +#[cfg(all(feature = "cctk", target_os = "linux"))] +use wayland_backend::client::Backend; use crate::{CreateCompositor, Program, WindowManager}; @@ -31,7 +35,7 @@ pub type UserInterfaces<'a, P> = HashMap< #[derive(Debug)] pub enum Event { - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] Wayland(sctk_event::SctkEvent), } @@ -57,7 +61,7 @@ impl SurfaceIdWrapper { #[derive(Debug, Default)] pub struct PlatformSpecific { - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] wayland: WaylandSpecific, } @@ -67,7 +71,7 @@ impl PlatformSpecific { action: iced_runtime::platform_specific::Action, ) { match action { - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] iced_runtime::platform_specific::Action::Wayland(a) => { self.send_wayland(wayland::Action::Action(a)); } @@ -78,14 +82,14 @@ impl PlatformSpecific { &mut self, keep: F, ) { - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] { self.wayland.retain_subsurfaces(keep); } } pub(crate) fn clear_subsurface_list(&mut self) { - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] { self.wayland.clear_subsurface_list(); } @@ -96,7 +100,7 @@ impl PlatformSpecific { id: window::Id, window: &dyn HasWindowHandle, ) { - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] { use cctk::sctk::reexports::client::{ Proxy, protocol::wl_surface::WlSurface, @@ -147,14 +151,11 @@ impl PlatformSpecific { pub(crate) fn create_surface( &mut self, ) -> Option> { - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] { - self.wayland.create_surface() - } - #[cfg(not(wayland_platform))] - { - None + return self.wayland.create_surface(); } + None } pub(crate) fn update_surface_shm( @@ -166,7 +167,7 @@ impl PlatformSpecific { data: &[u8], offset: Vector, ) { - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] { return self.wayland.update_surface_shm( surface, width, height, scale, data, offset, @@ -194,7 +195,7 @@ pub(crate) async fn handle_event<'a, 'b, P>( P: Program, { match e { - #[cfg(wayland_platform)] + #[cfg(all(feature = "cctk", target_os = "linux"))] Event::Wayland(e) => { platform_specific .wayland diff --git a/winit/src/platform_specific/wayland/commands/activation.rs b/winit/src/platform_specific/wayland/commands/activation.rs index 442ee08c..fa051031 100644 --- a/winit/src/platform_specific/wayland/commands/activation.rs +++ b/winit/src/platform_specific/wayland/commands/activation.rs @@ -1,8 +1,8 @@ use crate::core::window::Id as SurfaceId; use iced_runtime::{ - self, Action, Task, + self, platform_specific::{self, wayland}, - task, + task, Action, Task, }; pub fn request_token( diff --git a/winit/src/platform_specific/wayland/commands/blur.rs b/winit/src/platform_specific/wayland/commands/blur.rs deleted file mode 100644 index e9a73646..00000000 --- a/winit/src/platform_specific/wayland/commands/blur.rs +++ /dev/null @@ -1,17 +0,0 @@ -use iced_futures::core::window; -use iced_runtime::{ - self, Action, Task, - platform_specific::{self, wayland}, - task, -}; - -pub fn blur( - id: window::Id, - blur: Option>, -) -> Task<()> { - task::oneshot(|_| { - Action::PlatformSpecific(platform_specific::Action::Wayland( - wayland::Action::BlurSurface(id, blur), - )) - }) -} diff --git a/winit/src/platform_specific/wayland/commands/corner_radius.rs b/winit/src/platform_specific/wayland/commands/corner_radius.rs index 4cc122dd..c5ba6016 100644 --- a/winit/src/platform_specific/wayland/commands/corner_radius.rs +++ b/winit/src/platform_specific/wayland/commands/corner_radius.rs @@ -1,11 +1,11 @@ use iced_futures::core::window; use iced_runtime::{ - self, Action, Task, + self, platform_specific::{ self, wayland::{self, CornerRadius}, }, - task, + task, Action, Task, }; pub fn corner_radius( diff --git a/winit/src/platform_specific/wayland/commands/keyboard_shortcuts_inhibit.rs b/winit/src/platform_specific/wayland/commands/keyboard_shortcuts_inhibit.rs index afc2e27b..783b62c6 100644 --- a/winit/src/platform_specific/wayland/commands/keyboard_shortcuts_inhibit.rs +++ b/winit/src/platform_specific/wayland/commands/keyboard_shortcuts_inhibit.rs @@ -1,7 +1,7 @@ use iced_runtime::{ - self, Action, Task, + self, platform_specific::{self, wayland}, - task, + task, Action, Task, }; pub fn inhibit_shortcuts(inhibit: bool) -> Task<()> { diff --git a/winit/src/platform_specific/wayland/commands/layer_surface.rs b/winit/src/platform_specific/wayland/commands/layer_surface.rs index cdb4e93d..839db95c 100644 --- a/winit/src/platform_specific/wayland/commands/layer_surface.rs +++ b/winit/src/platform_specific/wayland/commands/layer_surface.rs @@ -2,7 +2,7 @@ use crate::core::window::Id as SurfaceId; use iced_runtime::{ - self, Action, Task, + self, platform_specific::{ self, wayland::{ @@ -10,7 +10,7 @@ use iced_runtime::{ layer_surface::{IcedMargin, SctkLayerSurfaceSettings}, }, }, - task, + task, Action, Task, }; pub use cctk::sctk::shell::wlr_layer::{Anchor, KeyboardInteractivity, Layer}; @@ -114,14 +114,3 @@ pub fn set_layer(id: SurfaceId, layer: Layer) -> Task { )), )) } - -pub fn set_padding( - id: SurfaceId, - padding: IcedMargin, -) -> Task { - task::effect(Action::PlatformSpecific( - platform_specific::Action::Wayland(wayland::Action::LayerSurface( - wayland::layer_surface::Action::Padding { id, padding }, - )), - )) -} diff --git a/winit/src/platform_specific/wayland/commands/mod.rs b/winit/src/platform_specific/wayland/commands/mod.rs index cd6832c7..191dc3a5 100644 --- a/winit/src/platform_specific/wayland/commands/mod.rs +++ b/winit/src/platform_specific/wayland/commands/mod.rs @@ -1,7 +1,6 @@ //! Interact with the wayland objects of your application. pub mod activation; -pub mod blur; pub mod corner_radius; pub mod keyboard_shortcuts_inhibit; pub mod layer_surface; diff --git a/winit/src/platform_specific/wayland/commands/overlap_notify.rs b/winit/src/platform_specific/wayland/commands/overlap_notify.rs index 417cfb24..860838c3 100644 --- a/winit/src/platform_specific/wayland/commands/overlap_notify.rs +++ b/winit/src/platform_specific/wayland/commands/overlap_notify.rs @@ -1,8 +1,7 @@ use iced_futures::core::window::Id; use iced_runtime::{ - Action, Task, platform_specific::{self, wayland}, - task, + task, Action, Task, }; /// Request subscription for overlap notification events on the surface diff --git a/winit/src/platform_specific/wayland/commands/popup.rs b/winit/src/platform_specific/wayland/commands/popup.rs index c702f4f1..f70d97f4 100644 --- a/winit/src/platform_specific/wayland/commands/popup.rs +++ b/winit/src/platform_specific/wayland/commands/popup.rs @@ -1,15 +1,12 @@ //! Interact with the popups of your application. use crate::core::window::Id as SurfaceId; use iced_runtime::{ - self, Action, Task, + self, platform_specific::{ self, - wayland::{ - self, - popup::{SctkPopupSettings, SctkPositioner}, - }, + wayland::{self, popup::SctkPopupSettings}, }, - task, + task, Action, Task, }; /// @@ -35,18 +32,6 @@ pub fn set_size( )) } -/// -pub fn reposition( - id: SurfaceId, - positioner: SctkPositioner, -) -> Task { - task::effect(Action::PlatformSpecific( - platform_specific::Action::Wayland(wayland::Action::Popup( - wayland::popup::Action::Reposition { id, positioner }, - )), - )) -} - /// pub fn destroy_popup(id: SurfaceId) -> Task { task::effect(Action::PlatformSpecific( diff --git a/winit/src/platform_specific/wayland/commands/session_lock.rs b/winit/src/platform_specific/wayland/commands/session_lock.rs index a530c12e..7f8748f7 100644 --- a/winit/src/platform_specific/wayland/commands/session_lock.rs +++ b/winit/src/platform_specific/wayland/commands/session_lock.rs @@ -1,9 +1,9 @@ use crate::core::window::Id as SurfaceId; use cctk::sctk::reexports::client::protocol::wl_output::WlOutput; use iced_runtime::{ - self, Action, Task, + self, platform_specific::{self, wayland}, - task, + task, Action, Task, }; pub fn lock() -> Task { diff --git a/winit/src/platform_specific/wayland/commands/subsurface.rs b/winit/src/platform_specific/wayland/commands/subsurface.rs index 20c3cdb7..a76e3b4e 100644 --- a/winit/src/platform_specific/wayland/commands/subsurface.rs +++ b/winit/src/platform_specific/wayland/commands/subsurface.rs @@ -1,12 +1,12 @@ use crate::core::window::Id as SurfaceId; pub use cctk::sctk::shell::wlr_layer::{Anchor, KeyboardInteractivity, Layer}; use iced_runtime::{ - self, Action, Task, + self, platform_specific::{ self, wayland::{self, subsurface::SctkSubsurfaceSettings}, }, - task, + task, Action, Task, }; pub fn get_subsurface( diff --git a/winit/src/platform_specific/wayland/event_loop/mod.rs b/winit/src/platform_specific/wayland/event_loop/mod.rs index b4589840..976595a7 100644 --- a/winit/src/platform_specific/wayland/event_loop/mod.rs +++ b/winit/src/platform_specific/wayland/event_loop/mod.rs @@ -33,7 +33,7 @@ use cctk::{ reexports::{ calloop::{self, EventLoop}, client::{ - Connection, Proxy, globals::registry_queue_init, + ConnectError, Connection, Proxy, globals::registry_queue_init, }, }, registry::RegistryState, @@ -46,6 +46,8 @@ use cctk::{ }; use raw_window_handle::HasDisplayHandle; use state::{FrameStatus, SctkWindow, send_event}; +#[cfg(feature = "a11y")] +use std::sync::{Arc, Mutex}; use std::{ collections::{HashMap, HashSet}, fmt::Debug, @@ -69,8 +71,8 @@ pub struct SctkEventLoop { pub(crate) state: SctkState, } -#[derive(Debug)] pub enum Error { + Connect(ConnectError), Calloop(calloop::Error), Global(GlobalError), NoDisplayHandle, @@ -127,7 +129,7 @@ impl SctkEventLoop { crate::platform_specific::Action::ResizeWindow(id) => { if let Some((_, v)) = state.windows.iter() .find(|w| w.id == id) - .map(|w| state.corner_radii.get(&id)) + .map(|w| w.corner_radius.as_ref()) .unwrap_or_default() { _ = state.handle_action(iced_runtime::platform_specific::wayland::Action::RoundedCorners(id, *v)); } @@ -136,7 +138,7 @@ impl SctkEventLoop { window, id, ) => { - state.windows.push(SctkWindow { window, id }); + state.windows.push(SctkWindow { window, id, corner_radius: Default::default() }); if let Some(v) = state.pending_corner_radius.remove(&id) { _ = state.handle_action(iced_runtime::platform_specific::wayland::Action::RoundedCorners(id, Some(v))); } @@ -348,7 +350,7 @@ impl SctkEventLoop { ), corner_radius_manager: registry_state.bind_one::( &qh, - 1..=2, + 1..=1, (), ).ok(), toplevel_manager: ToplevelManagerState::try_new( @@ -375,7 +377,6 @@ impl SctkEventLoop { seats: Vec::new(), windows: Vec::new(), blur_surfaces: HashMap::new(), - corner_radii: HashMap::new(), layer_surfaces: Vec::new(), popups: Vec::new(), lock_surfaces: Vec::new(), @@ -401,7 +402,6 @@ impl SctkEventLoop { preedit: None, pending_delete: None, pending_commit: None, - pending_blur: HashMap::new(), }, _features: Default::default(), }; @@ -488,23 +488,6 @@ impl SctkEventLoop { let had_events = !state.state.sctk_events.is_empty(); let mut wake_up = had_events; - for e in state.state.sctk_events.drain(..) { - if let SctkEvent::Winit(id, e) = e { - _ = state - .state - .events_sender - .unbounded_send(Control::Winit(id, e)); - } else { - _ = - state - .state - .events_sender - .unbounded_send(Control::PlatformSpecific( - crate::platform_specific::Event::Wayland(e), - )); - } - } - for s in state .state @@ -549,6 +532,22 @@ impl SctkEventLoop { ); } + for e in state.state.sctk_events.drain(..) { + if let SctkEvent::Winit(id, e) = e { + _ = state + .state + .events_sender + .unbounded_send(Control::Winit(id, e)); + } else { + _ = + state + .state + .events_sender + .unbounded_send(Control::PlatformSpecific( + crate::platform_specific::Event::Wayland(e), + )); + } + } if wake_up { state.state.proxy.wake_up(); } diff --git a/winit/src/platform_specific/wayland/event_loop/proxy.rs b/winit/src/platform_specific/wayland/event_loop/proxy.rs index 58229dc1..bdbc44a4 100644 --- a/winit/src/platform_specific/wayland/event_loop/proxy.rs +++ b/winit/src/platform_specific/wayland/event_loop/proxy.rs @@ -1,8 +1,8 @@ use cctk::sctk::reexports::calloop; use iced_futures::futures::{ - Sink, channel::mpsc, task::{Context, Poll}, + Sink, }; use std::pin::Pin; diff --git a/winit/src/platform_specific/wayland/event_loop/state.rs b/winit/src/platform_specific/wayland/event_loop/state.rs index f4a8c5d7..f99e48ba 100644 --- a/winit/src/platform_specific/wayland/event_loop/state.rs +++ b/winit/src/platform_specific/wayland/event_loop/state.rs @@ -4,7 +4,6 @@ use crate::{ activation::IcedRequestData, ext_background_effect, overlap::{OverlapNotificationV1, OverlapNotifyV1}, - shell::corner_radius::CornerRadiusWrapper, text_input::{Preedit, TextInputManager}, }, platform_specific::{ @@ -31,6 +30,7 @@ use std::{ convert::Infallible, fmt::Debug, sync::{Arc, Mutex, atomic::AtomicU32}, + thread::panicking, time::Duration, }; use wayland_backend::client::ObjectId; @@ -41,13 +41,17 @@ use winit::{ use cctk::{ cosmic_protocols::{ - corner_radius::v1::client::cosmic_corner_radius_manager_v1::CosmicCornerRadiusManagerV1, + corner_radius::v1::client::{ + cosmic_corner_radius_manager_v1::CosmicCornerRadiusManagerV1, + cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1, + }, overlap_notify::v1::client::zcosmic_overlap_notification_v1::ZcosmicOverlapNotificationV1, }, sctk::{ activation::{ActivationState, RequestData}, compositor::CompositorState, error::GlobalError, + globals::GlobalData, output::OutputState, reexports::{ calloop::{LoopHandle, timer::TimeoutAction}, @@ -63,12 +67,11 @@ use cctk::{ wl_touch::WlTouch, }, }, - protocols_wlr::layer_shell::v1::client::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1, }, registry::RegistryState, seat::{ SeatState, - keyboard::{KeyEvent, Modifiers}, + keyboard::KeyEvent, pointer::{CursorIcon, PointerData, ThemedPointer}, touch::TouchData, }, @@ -94,6 +97,7 @@ use cctk::{ }; use iced_runtime::{ core::{self, Point, touch}, + keyboard::Modifiers, platform_specific::{ self, wayland::{ @@ -105,10 +109,7 @@ use iced_runtime::{ }, }; use wayland_protocols::{ - ext::background_effect::v1::client::{ - ext_background_effect_manager_v1, - ext_background_effect_surface_v1::ExtBackgroundEffectSurfaceV1, - }, + ext::background_effect::v1::client::ext_background_effect_surface_v1::ExtBackgroundEffectSurfaceV1, wp::{ fractional_scale::v1::client::wp_fractional_scale_v1::WpFractionalScaleV1, keyboard_shortcuts_inhibit::zv1::client::{ @@ -342,12 +343,22 @@ pub struct SctkPopupData { pub(crate) grab: bool, } +#[derive(Debug)] +pub struct MyCosmicCornerRadiusToplevelV1(CosmicCornerRadiusToplevelV1); + +impl Drop for MyCosmicCornerRadiusToplevelV1 { + fn drop(&mut self) { + self.0.destroy(); + } +} + #[derive(Debug, Clone)] -pub struct SctkCornerRadius(Arc); +pub struct SctkCornerRadius(Arc); pub struct SctkWindow { pub(crate) window: Arc, pub(crate) id: core::window::Id, + pub(crate) corner_radius: Option<(SctkCornerRadius, Option)>, } impl SctkWindow { @@ -434,8 +445,7 @@ pub struct SctkState { pub(crate) popups: Vec, pub(crate) subsurfaces: Vec, pub(crate) lock_surfaces: Vec, - pub(crate) blur_surfaces: HashMap, - pub(crate) corner_radii: HashMap)>, + pub(crate) blur_surfaces: HashMap>, pub(crate) touch_points: HashMap, /// Window updates, which are coming from SCTK or the compositor, which require @@ -489,7 +499,6 @@ pub struct SctkState { pub(crate) corner_radius_manager: Option, pub(crate) pending_corner_radius: HashMap, - pub(crate) pending_blur: HashMap>, pub(crate) text_input_manager: Option, pub(crate) text_input: Option>, @@ -501,10 +510,6 @@ pub struct SctkState { /// An error that occurred while running an application. #[derive(Debug, thiserror::Error)] pub enum PopupCreationError { - /// The requested ID already exists. - #[error("The requested ID already exists")] - AlreadyExists, - /// Positioner creation failed #[error("Positioner creation failed")] PositionerCreationFailed(GlobalError), @@ -525,10 +530,6 @@ pub enum PopupCreationError { /// An error that occurred while running an application. #[derive(Debug, thiserror::Error)] pub enum LayerSurfaceCreationError { - /// The requested ID already exists. - #[error("The requested ID already exists")] - AlreadyExists, - /// Layer shell is not supported by the compositor #[error("Layer shell is not supported by the compositor")] LayerShellNotSupported, @@ -545,10 +546,6 @@ pub enum LayerSurfaceCreationError { /// An error that occurred while running an application. #[derive(Debug, thiserror::Error)] pub enum SubsurfaceCreationError { - /// The requested ID already exists. - #[error("The requested ID already exists")] - AlreadyExists, - /// Subsurface creation failed #[error("Subsurface creation failed")] CreationFailed(GlobalError), @@ -687,18 +684,6 @@ impl SctkState { ), PopupCreationError, > { - if self.layer_surfaces.iter().any(|s| s.id == settings.id) - || self.windows.iter().any(|w| w.id == settings.id) - || self.popups.iter().any(|p| p.data.id == settings.id) - || self.subsurfaces.iter().any(|s| s.id == settings.id) - { - log::warn!( - "Popup surface with id {:?} already exists", - settings.id - ); - return Err(PopupCreationError::AlreadyExists); - } - let (parent, toplevel) = if let Some(parent) = self.layer_surfaces.iter().find(|l| l.id == settings.parent) { @@ -840,7 +825,6 @@ impl SctkState { ) } }; - let toplevel = toplevel.clone(); popup.xdg_surface().set_window_geometry( 0, @@ -873,15 +857,7 @@ impl SctkState { } _ = wl_surface.frame(&self.queue_handle, wl_surface.clone()); - - if let Some(old) = self.blur_surfaces.remove(&settings.id) { - old.destroy(); - } - _ = self.corner_radii.remove(&settings.id); - - if let Some(blur) = self.pending_blur.remove(&settings.id) { - self.apply_blur(settings.id, Some(blur), &wl_surface); - } + wl_surface.commit(); let wp_viewport = self.viewporter_state.as_ref().map(|state| { let viewport = @@ -914,13 +890,6 @@ impl SctkState { close_with_children: settings.close_with_children, }); - if let Some(corners) = self.pending_corner_radius.remove(&settings.id) { - self.handle_action(Action::RoundedCorners( - settings.id, - Some(corners), - )); - } - wl_surface.commit(); Ok(( settings.id, parent.wl_surface().clone(), @@ -955,15 +924,6 @@ impl SctkState { IcedOutput::Output(output) => Some(output), }; - if self.layer_surfaces.iter().any(|s| s.id == id) - || self.windows.iter().any(|w| w.id == id) - || self.popups.iter().any(|p| p.data.id == id) - || self.subsurfaces.iter().any(|s| s.id == id) - { - log::warn!("Layer surface with id {id:?} already exists"); - return Err(LayerSurfaceCreationError::AlreadyExists); - } - let layer_shell = self .layer_shell .as_ref() @@ -1016,15 +976,7 @@ impl SctkState { layer_surface.set_input_region(Some(®ion)); region.destroy(); } - - if let Some(old) = self.blur_surfaces.remove(&id) { - old.destroy(); - } - _ = self.corner_radii.remove(&id); - - if let Some(blur) = self.pending_blur.remove(&id) { - self.apply_blur(id, Some(blur), &wl_surface); - } + layer_surface.commit(); let wp_viewport = self.viewporter_state.as_ref().map(|state| { state.get_viewport(layer_surface.wl_surface(), &self.queue_handle) @@ -1058,10 +1010,6 @@ impl SctkState { wp_fractional_scale, common: common.clone(), }); - if let Some(corners) = self.pending_corner_radius.remove(&id) { - _ = self.handle_action(Action::RoundedCorners(id, Some(corners))); - } - layer_surface.commit(); Ok((id, CommonSurface::Layer(layer_surface), common)) } pub fn get_lock_surface( @@ -1069,14 +1017,6 @@ impl SctkState { id: core::window::Id, output: &WlOutput, ) -> Option<(CommonSurface, Arc>)> { - if self.layer_surfaces.iter().any(|s| s.id == id) - || self.windows.iter().any(|w| w.id == id) - || self.popups.iter().any(|p| p.data.id == id) - || self.subsurfaces.iter().any(|s| s.id == id) - { - log::warn!("Lock surface with id {id:?} already exists"); - return None; - } if let Some(lock) = self.session_lock.as_ref() { let wl_surface = self.compositor_state.create_surface(&self.queue_handle); @@ -1150,19 +1090,14 @@ impl SctkState { } }, platform_specific::wayland::layer_surface::Action::Destroy(id) => { - if let Some(p) = self - .popups - .iter().find_map(|p| - self.layer_surfaces.iter().find_map(|l| if l.id == id && l.surface.wl_surface() == p.data.parent.wl_surface() {Some(p.data.id)} else {None})) { - _ = self.handle_action(Action::Popup(platform_specific::wayland::popup::Action::Destroy { id: p })); - } if let Some(i) = self.layer_surfaces.iter().position(|l| l.id == id) { let l = self.layer_surfaces.remove(i); if let Some(blurred) = self.blur_surfaces.remove(&l.id) { - blurred.destroy(); + for s in blurred { + s.destroy(); + } } - _ = self.corner_radii.remove(&id); let (removed, remaining): (Vec<_>, Vec<_>) = self .subsurfaces @@ -1185,7 +1120,6 @@ impl SctkState { if let Some(destroyed) = self.id_map.remove(&l.surface.wl_surface().id()) { _ = self.destroyed.insert(destroyed); } - send_event(&self.events_sender, &self.proxy, SctkEvent::LayerSurfaceEvent { variant: LayerSurfaceEventVariant::Done, id: l.surface.wl_surface().clone(), @@ -1260,14 +1194,6 @@ impl SctkState { } }, - platform_specific::wayland::layer_surface::Action::Padding { id, padding } => { - // corner radius padding - if let Some((protocol_object, _)) = self.corner_radii.get_mut(&id) { - if let CornerRadiusWrapper::Wlr(protocol_object) = protocol_object.0.as_ref() { - protocol_object.set_padding(padding.top, padding.right, padding.bottom, padding.left); - } - } - }, }, Action::Popup(action) => match action { platform_specific::wayland::popup::Action::Popup { popup: settings } => { @@ -1279,11 +1205,11 @@ impl SctkState { || self.layer_surfaces.iter().any(|l| l.id == settings.parent && p.data.parent.wl_surface() == l.surface.wl_surface())) ) { let existing = &mut self.popups[existing]; - let size = if let Some(size) = settings.positioner.size { - size + let size = if settings.positioner.size.is_none() { + log::info!("No configured popup size"); + (1, 1) } else { - let guard = existing.common.lock().unwrap(); - (guard.size.width, guard.size.height) + settings.positioner.size.unwrap() }; let Ok(positioner) = XdgPositioner::new(&self.xdg_shell_state) .map_err(PopupCreationError::PositionerCreationFailed) else { @@ -1372,6 +1298,7 @@ impl SctkState { } }); } + // log::error!("Invalid popup Id {:?}", popup.id); } else { self.pending_popup = None; match self.get_popup(settings) { @@ -1403,7 +1330,7 @@ impl SctkState { }, }; let mut to_destroy = vec![sctk_popup]; - + // TODO optionally destroy parents if they request to be destroyed with children while let Some(popup_to_destroy_last) = to_destroy.last().and_then(|popup| self .popups .iter() @@ -1426,10 +1353,10 @@ impl SctkState { } if let Some(blurred) = self.blur_surfaces.remove(&id) { - blurred.destroy(); + for s in blurred { + s.destroy(); + } } - _ = self.corner_radii.remove(&id); - let (removed, remaining): (Vec<_>, Vec<_>) = self .subsurfaces @@ -1466,48 +1393,6 @@ impl SctkState { SctkEvent::PopupEvent { variant: crate::sctk_event::PopupEventVariant::Size(width, height), toplevel_id: sctk_popup.data.parent.wl_surface().clone(), parent_id: sctk_popup.data.parent.wl_surface().clone(), id: surface }); } }, - platform_specific::wayland::popup::Action::Reposition { id, positioner } => { - if let Some(sctk_popup) = self - .popups - .iter_mut() - .find(|s| s.data.id == id) - { - sctk_popup.data.positioner.set_anchor(positioner.anchor); - sctk_popup.data.positioner.set_anchor_rect( - positioner.anchor_rect.x, - positioner.anchor_rect.y, - positioner.anchor_rect.width, - positioner.anchor_rect.height, - ); - if let Ok(constraint_adjustment) = - positioner.constraint_adjustment.try_into() - { - sctk_popup.data.positioner.set_constraint_adjustment(constraint_adjustment); - } - sctk_popup.data.positioner.set_gravity(positioner.gravity); - sctk_popup.data.positioner.set_offset( - positioner.offset.0, - positioner.offset.1, - ); - if positioner.reactive { - sctk_popup.data.positioner.set_reactive(); - } - let guard =sctk_popup.common.lock().unwrap(); - let w = guard.size.width; - let h = guard.size.height; - drop(guard); - let size = positioner.size.unwrap_or((w, h)); - sctk_popup.popup - .xdg_surface() - .set_window_geometry(0, 0, w as i32, h as i32); - sctk_popup.update_viewport(w, h); - // update positioner - sctk_popup.data.positioner.set_size(w as i32, h as i32); - sctk_popup.popup.reposition(&sctk_popup.data.positioner, TOKEN_CTR.fetch_add(1, std::sync::atomic::Ordering::Relaxed)); let surface = sctk_popup.popup.wl_surface().clone(); - _ = send_event(&self.events_sender, &self.proxy, - SctkEvent::PopupEvent { variant: crate::sctk_event::PopupEventVariant::Size(size.0, size.1), toplevel_id: sctk_popup.data.parent.wl_surface().clone(), parent_id: sctk_popup.data.parent.wl_surface().clone(), id: surface }); - } - }, }, Action::Activation(activation_event) => match activation_event { platform_specific::wayland::activation::Action::RequestToken { app_id, window, channel } => { @@ -1584,7 +1469,7 @@ impl SctkState { // TODO how to handle this when there's no lock? if let Some((surface, _)) = self.get_lock_surface(id, &output) { let wl_surface = surface.wl_surface(); - + receive_frame(&mut self.frame_status, &wl_surface); } } @@ -1596,10 +1481,10 @@ impl SctkState { { let surface = self.lock_surfaces.remove(i); if let Some(blurred) = self.blur_surfaces.remove(&surface.id) { - blurred.destroy(); + for s in blurred { + s.destroy(); + } } - _ = self.corner_radii.remove(&id); - let (removed, remaining): (Vec<_>, Vec<_>) = self .subsurfaces .drain(..) @@ -1639,7 +1524,7 @@ impl SctkState { }; let notification = overlap_notify_state.notify.notify_on_overlap(wlr, &self.queue_handle, OverlapNotificationV1 { surface: layer_surface.surface.wl_surface().clone() }); _ = self.overlap_notifications.insert(my_id, notification); - } else if !enabled { + } else { _ = self.overlap_notifications.remove(&my_id); } } else { @@ -1681,10 +1566,10 @@ impl SctkState { } for (destroyed, parent, id) in destroyed { if let Some(blurred) = self.blur_surfaces.remove(&id) { - blurred.destroy(); + for s in blurred { + s.destroy(); + } } - _ = self.corner_radii.remove(&id); - if let Some((wl_surface, f)) = self.seats.iter_mut().find(|f| { f.kbd_focus.as_ref().is_some_and(|f| *f == destroyed) }).and_then(|f| Some((parent, &mut f.kbd_focus))) { @@ -1712,25 +1597,8 @@ impl SctkState { } Action::RoundedCorners(id, v) => { if let Some(manager) = self.corner_radius_manager.as_ref() { - enum Surface { - Xdg(XdgSurface, Option), - Wlr(ZwlrLayerSurfaceV1), - } - let s = if let Some(w) = self.windows.iter_mut().find(|w| w.id == id) { - Some((Surface::Xdg(w.xdg_surface(&self.connection), Some(w.xdg_toplevel(&self.connection))), w.window.surface_size().cast::().to_logical(w.window.scale_factor()))) - } else if let Some(p) = self.popups.iter_mut().find(|w| w.data.id == id) { - let guard = p.common.lock().unwrap(); - Some((Surface::Xdg(p.popup.xdg_surface().clone(), None), guard.size.cast::())) - } else if let Some(l) = self.layer_surfaces.iter_mut().find(|l| l.id == id) { - let guard = l.common.lock().unwrap(); - match l.surface.kind() { - SurfaceKind::Wlr(l) => Some((Surface::Wlr(l.clone()), guard.size.cast::())), - _ => None - } - } else { - None - }; - if let Some((s, geo_size)) = s { + if let Some(w) = self.windows.iter_mut().find(|w| w.id == id) { + let geo_size: LogicalSize = w.window.surface_size().cast::().to_logical(w.window.scale_factor()); let half_min_dim = (geo_size.width as u32).min(geo_size.height as u32) / 2; if let Some(radii) = v { @@ -1740,73 +1608,37 @@ impl SctkState { bottom_right: radii.bottom_right.min(half_min_dim), bottom_left: radii.bottom_left.min(half_min_dim), }; - if let Some((protocol_object, corner_radii)) = self.corner_radii.get_mut(&id) { + if let Some((protocol_object, corner_radii)) = w.corner_radius.as_mut() { if *corner_radii != Some(adjusted_radii) { - match protocol_object.0.as_ref() { - CornerRadiusWrapper::Xdg(protocol_object) => protocol_object.set_radius( - adjusted_radii.top_left, - adjusted_radii.top_right, - adjusted_radii.bottom_right, - adjusted_radii.bottom_left, - ), - CornerRadiusWrapper::Wlr(protocol_object) => protocol_object.set_radius( - adjusted_radii.top_left, - adjusted_radii.top_right, - adjusted_radii.bottom_right, - adjusted_radii.bottom_left, - ) - }; + protocol_object.0.0.set_radius( + adjusted_radii.top_left, + adjusted_radii.top_right, + adjusted_radii.bottom_right, + adjusted_radii.bottom_left, + ); *corner_radii = Some(adjusted_radii.clone()); } } else { + let toplevel = w.xdg_toplevel(&self.connection); - let protocol_object = match s { - Surface::Xdg(s, w) => { - if manager.version() == 1 { - if let Some(w) = w { - CornerRadiusWrapper::Xdg(manager.get_corner_radius(&w, &self.queue_handle, ())) - } else { - log::error!("Corner radius is not supported for popups on xdg shell v1"); - return Ok(()); - } - } else { - CornerRadiusWrapper::Xdg(manager.get_corner_radius_surface(&s, &self.queue_handle, ()))} - } - Surface::Wlr(l) => { - if manager.version() == 1 { - return Ok(()); - } - CornerRadiusWrapper::Wlr(manager.get_corner_radius_layer(&l, &self.queue_handle, ()))} - }; - match &protocol_object { - CornerRadiusWrapper::Xdg(protocol_object) => protocol_object.set_radius( - adjusted_radii.top_left, - adjusted_radii.top_right, - adjusted_radii.bottom_right, - adjusted_radii.bottom_left, - ), - CornerRadiusWrapper::Wlr(protocol_object) => protocol_object.set_radius( - adjusted_radii.top_left, - adjusted_radii.top_right, - adjusted_radii.bottom_right, - adjusted_radii.bottom_left, - ) - }; - _ = self.corner_radii.insert(id, (SctkCornerRadius(Arc::new(protocol_object)), Some(adjusted_radii.clone()))); + let protocol_object = manager.get_corner_radius(&toplevel, &self.queue_handle, ()); + + protocol_object.set_radius( + adjusted_radii.top_left, + adjusted_radii.top_right, + adjusted_radii.bottom_right, + adjusted_radii.bottom_left, + ); + w.corner_radius = Some((SctkCornerRadius(Arc::new(MyCosmicCornerRadiusToplevelV1( protocol_object))), Some(adjusted_radii.clone()))); } } else { - if let Some(old) = self.corner_radii.get_mut(&id) { - match old.0.0.as_ref() { - CornerRadiusWrapper::Xdg(protocol_object) => protocol_object.unset_radius(), - CornerRadiusWrapper::Wlr(protocol_object) => { - protocol_object.unset_radius() - } - }; + if let Some(old) = w.corner_radius.as_mut() { + old.0.0.as_ref().0.unset_radius(); old.1 = None; } } } else { - if let Some(v) = v { + if let Some(v) = v{ _ = self.pending_corner_radius.insert(id, v); } else { _ = self.pending_corner_radius.remove(&id); @@ -1821,7 +1653,7 @@ impl SctkState { bg_effect_mgr.enqueue(id, rectangles.clone()); return Ok(()); } - + let s = if let Some(s) = self.popups.iter().find(|s| s.data.id == id) { s.popup.wl_surface() } else if let Some(s) = self.layer_surfaces.iter().find(|s| s.id == id) { @@ -1831,79 +1663,84 @@ impl SctkState { } else if let Some(subsurface) = self.subsurfaces.iter().find(|s| s.id == id) { &subsurface.instance.wl_surface } else { - log::info!("Failed to find surface for blur action"); - if let Some(rectangles) = rectangles { - _ = self.pending_blur.insert(id, rectangles.clone()); - } + log::error!("Failed to find surface for blur action"); return Ok(()); - }.clone(); - self.apply_blur(id, rectangles, &s) + }; + let existing_blur = self.blur_surfaces.entry(id); + match (existing_blur, rectangles) { + (Entry::Occupied(occupied_entry), None) => { + let blur_surfaces = occupied_entry.remove(); + for region in blur_surfaces { + region.destroy(); + } + }, + (Entry::Occupied(mut occupied_entry), Some(rectangles)) => { + let blur_surfaces = occupied_entry.get_mut(); + let regions = rectangles.into_iter().map(|rect| { + let region = self + .compositor_state + .wl_compositor() + .create_region(&self.queue_handle, ()); + region.add( + rect.x.round() as i32, + rect.y.round() as i32, + rect.width.round() as i32, + rect.height.round() as i32, + ); + region + }).collect::>(); + if regions.len() > blur_surfaces.len() { + // add extra blur surfaces if needed + for _ in blur_surfaces.len()..regions.len() { + let Some(extra_region) = self.ext_background_effect_manager.as_mut().map(|mgr| mgr.blur(s, &self.queue_handle)) else { + log::error!("Failed to create blur effect for surface"); + return Ok(()); + }; + blur_surfaces.push(extra_region); + } + } else if regions.len() < blur_surfaces.len() { + for surface in blur_surfaces.iter().skip(regions.len()) { + surface.destroy(); + } + } + + // update existing blur surfaces + for (blur_surface, region) in blur_surfaces.iter().zip(regions.into_iter()) { + blur_surface.set_blur_region(Some(®ion)); + } + }, + (Entry::Vacant(..), None) => { + // nothing to remove + }, + (Entry::Vacant(vacant_entry), Some(rectangles)) => { + if self.ext_background_effect_manager.is_none() { + log::error!("Blur effect is not supported."); + return Ok(()); + } + let blur_surfaces = rectangles.into_iter().map(|rect| { + let region = self + .compositor_state + .wl_compositor() + .create_region(&self.queue_handle, ()); + region.add( + rect.x.round() as i32, + rect.y.round() as i32, + rect.width.round() as i32, + rect.height.round() as i32, + ); + let blur_manager = self.ext_background_effect_manager.as_mut().unwrap(); + let blur_surface = blur_manager.blur(s, &self.queue_handle); + blur_surface.set_blur_region(Some(®ion)); + blur_surface + }).collect::>(); + _ = vacant_entry.insert(blur_surfaces); + }, + } }, }; Ok(()) } - fn apply_blur( - &mut self, - id: core::window::Id, - rectangles: Option>, - s: &WlSurface, - ) { - let existing_blur = self.blur_surfaces.entry(id); - - match (existing_blur, rectangles) { - (Entry::Occupied(occupied_entry), None) => { - let blur_surface = occupied_entry.remove(); - blur_surface.destroy(); - } - (Entry::Occupied(mut occupied_entry), Some(rectangles)) => { - let blur_surface = occupied_entry.get_mut(); - let region = self - .compositor_state - .wl_compositor() - .create_region(&self.queue_handle, ()); - for rect in rectangles.into_iter() { - region.add( - rect.x.round() as i32, - rect.y.round() as i32, - rect.width.round() as i32, - rect.height.round() as i32, - ); - } - - // update existing blur surfaces - blur_surface.set_blur_region(Some(®ion)); - } - (Entry::Vacant(..), None) => { - // nothing to remove - } - (Entry::Vacant(vacant_entry), Some(rectangles)) => { - if self.ext_background_effect_manager.is_none() { - log::error!("Blur effect is not supported."); - return; - } - let region = self - .compositor_state - .wl_compositor() - .create_region(&self.queue_handle, ()); - for rect in rectangles { - region.add( - rect.x.round() as i32, - rect.y.round() as i32, - rect.width.round() as i32, - rect.height.round() as i32, - ); - } - - let blur_manager = - self.ext_background_effect_manager.as_mut().unwrap(); - let blur_surface = blur_manager.blur(s, &self.queue_handle); - blur_surface.set_blur_region(Some(®ion)); - _ = vacant_entry.insert(blur_surface); - } - } - } - pub fn get_subsurface( &mut self, settings: SctkSubsurfaceSettings, @@ -1917,17 +1754,9 @@ impl SctkState { ), SubsurfaceCreationError, > { - let Some(subsurface_state) = self.subsurface_state.clone() else { + let Some(subsurface_state) = self.subsurface_state.as_ref() else { return Err(SubsurfaceCreationError::Unsupported); }; - if self.layer_surfaces.iter().any(|s| s.id == settings.id) - || self.windows.iter().any(|w| w.id == settings.id) - || self.popups.iter().any(|p| p.data.id == settings.id) - || self.subsurfaces.iter().any(|s| s.id == settings.id) - { - log::warn!("Subsurface with id {:?} already exists", settings.id); - return Err(SubsurfaceCreationError::AlreadyExists); - } let size = settings.size.unwrap_or(Size::new(1., 1.)); let half_w = size.width / 2.; @@ -2033,14 +1862,7 @@ impl SctkState { region.destroy(); } - if let Some(old) = self.blur_surfaces.remove(&settings.id) { - old.destroy(); - } - _ = self.corner_radii.remove(&settings.id); - - if let Some(blur) = self.pending_blur.remove(&settings.id) { - _ = self.apply_blur(settings.id, Some(blur), &wl_surface); - } + wl_surface.commit(); let wp_viewport = subsurface_state.wp_viewporter.get_viewport( &wl_surface, @@ -2116,11 +1938,7 @@ impl SctkState { // XXX subsurfaces need to be sorted by z in descending order self.subsurfaces .sort_by(|a, b| b.instance.z.cmp(&a.instance.z)); - if let Some(corners) = self.pending_corner_radius.remove(&id) { - self.handle_action(Action::RoundedCorners(id, Some(corners))); - } - wl_surface.commit(); Ok(( id, parent.wl_surface().clone(), diff --git a/winit/src/platform_specific/wayland/handlers/ext_background_effect.rs b/winit/src/platform_specific/wayland/handlers/ext_background_effect.rs index 2d0df67a..03a80da9 100644 --- a/winit/src/platform_specific/wayland/handlers/ext_background_effect.rs +++ b/winit/src/platform_specific/wayland/handlers/ext_background_effect.rs @@ -1,7 +1,6 @@ use std::collections::HashMap; use cctk::sctk; -use iced_futures::futures::SinkExt; use iced_runtime::core::Rectangle; use iced_runtime::platform_specific::wayland::Action; use sctk::globals::GlobalData; @@ -12,7 +11,7 @@ use wayland_protocols::ext::background_effect::v1::client::ext_background_effect use wayland_protocols::ext::background_effect::v1::client::ext_background_effect_surface_v1::ExtBackgroundEffectSurfaceV1; use crate::event_loop::state::SctkState; -use crate::{platform_specific, window}; +use crate::window; #[derive(Debug, Clone)] pub struct ExtBackgroundEffectManager { @@ -71,15 +70,8 @@ impl Dispatch state.ext_background_effect_manager.as_mut() { bg_effect_mgr.capabilities = capability; - if capability.contains(Capability::Blur) { - queued_actions = bg_effect_mgr - .queued_blur_actions - .drain() - .collect(); - state - .sctk_events - .push(crate::sctk_event::SctkEvent::Blur); - } + queued_actions = + bg_effect_mgr.queued_blur_actions.drain().collect(); } for (id, rects) in queued_actions { _ = state.handle_action(Action::BlurSurface(id, rects)); diff --git a/winit/src/platform_specific/wayland/handlers/seat/keyboard.rs b/winit/src/platform_specific/wayland/handlers/seat/keyboard.rs index f83e1180..5ff7fb4b 100644 --- a/winit/src/platform_specific/wayland/handlers/seat/keyboard.rs +++ b/winit/src/platform_specific/wayland/handlers/seat/keyboard.rs @@ -4,46 +4,10 @@ use crate::platform_specific::wayland::{ }; use cctk::sctk::{ delegate_keyboard, - seat::keyboard::{KeyboardHandler, Keysym, Modifiers}, + seat::keyboard::{KeyboardHandler, Keysym}, }; use cctk::sctk::{reexports::client::Proxy, seat::keyboard::RawModifiers}; -fn modifiers_from_keysyms( - keysyms: &[Keysym], - previous: Modifiers, -) -> Modifiers { - let mut modifiers = Modifiers { - caps_lock: previous.caps_lock, - num_lock: previous.num_lock, - ..Modifiers::default() - }; - - for keysym in keysyms { - match keysym.raw() { - xkeysym::key::Shift_L | xkeysym::key::Shift_R => { - modifiers.shift = true - } - xkeysym::key::Control_L | xkeysym::key::Control_R => { - modifiers.ctrl = true - } - xkeysym::key::Alt_L | xkeysym::key::Alt_R => modifiers.alt = true, - xkeysym::key::Super_L - | xkeysym::key::Super_R - | xkeysym::key::Hyper_L - | xkeysym::key::Hyper_R - | xkeysym::key::Meta_L - | xkeysym::key::Meta_R => modifiers.logo = true, - xkeysym::key::Caps_Lock | xkeysym::key::Shift_Lock => { - modifiers.caps_lock = true - } - xkeysym::key::Num_Lock => modifiers.num_lock = true, - _ => {} - } - } - - modifiers -} - impl KeyboardHandler for SctkState { fn enter( &mut self, @@ -53,9 +17,9 @@ impl KeyboardHandler for SctkState { surface: &cctk::sctk::reexports::client::protocol::wl_surface::WlSurface, _serial: u32, _raw: &[u32], - keysyms: &[Keysym], + _keysyms: &[Keysym], ) { - let (i, mut is_active, seat, modifiers) = { + let (i, mut is_active, seat) = { let (i, is_active, my_seat) = match self.seats.iter_mut().enumerate().find_map(|(i, s)| { if s.kbd.as_ref() == Some(keyboard) { @@ -77,11 +41,9 @@ impl KeyboardHandler for SctkState { surface }; _ = my_seat.kbd_focus.replace(surface.clone()); - let modifiers = modifiers_from_keysyms(keysyms, my_seat._modifiers); - my_seat._modifiers = modifiers; let seat = my_seat.seat.clone(); - (i, is_active, seat, modifiers) + (i, is_active, seat) }; if !is_active && self.seats[0].kbd_focus.is_none() { @@ -111,12 +73,6 @@ impl KeyboardHandler for SctkState { seat_id: seat.clone(), surface: surface.clone(), }); - self.sctk_events.push(SctkEvent::KeyboardEvent { - variant: KeyboardEventVariant::Modifiers(modifiers), - kbd_id: keyboard.clone(), - seat_id: seat.clone(), - surface: surface.clone(), - }); } } } @@ -170,7 +126,6 @@ impl KeyboardHandler for SctkState { if self.windows.iter().any(|w| w.window.id() == id) { continue; } - let modifiers = s._modifiers; self.sctk_events.push(SctkEvent::Winit( id, winit::event::WindowEvent::Focused(true), @@ -182,12 +137,6 @@ impl KeyboardHandler for SctkState { kbd_id: s.kbd.clone().unwrap(), seat_id: s.seat.clone(), surface: surface.clone(), - }); - self.sctk_events.push(SctkEvent::KeyboardEvent { - variant: KeyboardEventVariant::Modifiers(modifiers), - kbd_id: s.kbd.clone().unwrap(), - seat_id: s.seat.clone(), - surface: surface.clone(), }) } } @@ -299,7 +248,6 @@ impl KeyboardHandler for SctkState { }; let seat_id = my_seat.seat.clone(); let kbd_id = keyboard.clone(); - my_seat._modifiers = modifiers; if is_active { if let Some(surface) = my_seat.kbd_focus.clone() { diff --git a/winit/src/platform_specific/wayland/handlers/seat/pointer.rs b/winit/src/platform_specific/wayland/handlers/seat/pointer.rs index b40912ec..8c962a4d 100644 --- a/winit/src/platform_specific/wayland/handlers/seat/pointer.rs +++ b/winit/src/platform_specific/wayland/handlers/seat/pointer.rs @@ -1,5 +1,8 @@ -use crate::platform_specific::wayland::{ - event_loop::state::SctkState, sctk_event::SctkEvent, +use crate::{ + event_loop::state::FrameStatus, + platform_specific::wayland::{ + event_loop::state::SctkState, sctk_event::SctkEvent, + }, }; use cctk::sctk::{ delegate_pointer, @@ -47,6 +50,14 @@ impl PointerHandler for SctkState { continue; } + let entry = self + .frame_status + .entry(e.surface.id()) + .or_insert(FrameStatus::RequestedRedraw); + if matches!(entry, FrameStatus::Received) { + *entry = FrameStatus::Ready; + } + self.sctk_events.push(SctkEvent::PointerEvent { variant: PointerEvent { surface: e.surface.clone(), diff --git a/winit/src/platform_specific/wayland/handlers/seat/seat.rs b/winit/src/platform_specific/wayland/handlers/seat/seat.rs index ee6b0e6e..2901ce8e 100644 --- a/winit/src/platform_specific/wayland/handlers/seat/seat.rs +++ b/winit/src/platform_specific/wayland/handlers/seat/seat.rs @@ -4,9 +4,10 @@ use crate::platform_specific::wayland::{ }; use cctk::sctk::{ delegate_seat, - reexports::client::{Proxy, protocol::wl_keyboard::WlKeyboard}, - seat::{SeatHandler, keyboard::Modifiers, pointer::ThemeSpec}, + reexports::client::{protocol::wl_keyboard::WlKeyboard, Proxy}, + seat::{pointer::ThemeSpec, SeatHandler}, }; +use iced_runtime::keyboard::Modifiers; use std::sync::Arc; impl SeatHandler for SctkState { diff --git a/winit/src/platform_specific/wayland/handlers/seat/touch.rs b/winit/src/platform_specific/wayland/handlers/seat/touch.rs index a0b1cce0..f726fd93 100644 --- a/winit/src/platform_specific/wayland/handlers/seat/touch.rs +++ b/winit/src/platform_specific/wayland/handlers/seat/touch.rs @@ -9,12 +9,12 @@ use crate::{ use cctk::sctk::{ delegate_touch, reexports::client::{ - Connection, Proxy, QueueHandle, protocol::{wl_surface::WlSurface, wl_touch::WlTouch}, + Connection, Proxy, QueueHandle, }, seat::touch::TouchHandler, }; -use iced_runtime::core::{Point, touch}; +use iced_runtime::core::{touch, Point}; impl TouchHandler for SctkState { fn down( diff --git a/winit/src/platform_specific/wayland/handlers/session_lock.rs b/winit/src/platform_specific/wayland/handlers/session_lock.rs index 98eb5586..d0eee5ef 100644 --- a/winit/src/platform_specific/wayland/handlers/session_lock.rs +++ b/winit/src/platform_specific/wayland/handlers/session_lock.rs @@ -1,9 +1,6 @@ use crate::{ event_loop::state::CommonSurface, - platform_specific::wayland::{ - event_loop::state::receive_frame, handlers::SctkState, - sctk_event::SctkEvent, - }, + platform_specific::wayland::{handlers::SctkState, sctk_event::SctkEvent}, }; use cctk::sctk::{ delegate_session_lock, @@ -70,10 +67,6 @@ impl SessionLockHandler for SctkState { configure, first, }); - - let wl_surface = session_lock_surface.wl_surface().clone(); - receive_frame(&mut self.frame_status, &wl_surface); - self.request_redraw(&wl_surface); } } diff --git a/winit/src/platform_specific/wayland/handlers/shell/corner_radius.rs b/winit/src/platform_specific/wayland/handlers/shell/corner_radius.rs index c4bdda88..bd7d2409 100644 --- a/winit/src/platform_specific/wayland/handlers/shell/corner_radius.rs +++ b/winit/src/platform_specific/wayland/handlers/shell/corner_radius.rs @@ -1,29 +1,17 @@ -use cctk::{ - cosmic_protocols::corner_radius::v1::client::{ - cosmic_corner_radius_layer_v1::CosmicCornerRadiusLayerV1, +use cctk::{sctk, cosmic_protocols::{ + corner_radius::v1::client::{ cosmic_corner_radius_manager_v1::CosmicCornerRadiusManagerV1, cosmic_corner_radius_toplevel_v1::CosmicCornerRadiusToplevelV1, }, - sctk, + overlap_notify::v1::client::zcosmic_overlap_notification_v1::ZcosmicOverlapNotificationV1, +}}; +use sctk::reexports::{ + client::{Connection, Dispatch, Proxy}, + }; -use sctk::reexports::client::{Connection, Dispatch, Proxy}; use crate::event_loop::state::SctkState; - -#[derive(Debug)] -pub enum CornerRadiusWrapper { - Xdg(CosmicCornerRadiusToplevelV1), - Wlr(CosmicCornerRadiusLayerV1), -} - -impl Drop for CornerRadiusWrapper { - fn drop(&mut self) { - match self { - Self::Xdg(c) => c.destroy(), - Self::Wlr(c) => c.destroy(), - }; - } -} +use crate::platform_specific::wayland::SctkEvent; impl Dispatch for SctkState { fn event( @@ -33,11 +21,15 @@ impl Dispatch for SctkState { _data: &(), _conn: &Connection, _qhandle: &sctk::reexports::client::QueueHandle, - ) { - } + ) {} } -impl Dispatch for SctkState { +impl + Dispatch< + CosmicCornerRadiusToplevelV1, + (), + > for SctkState +{ fn event( state: &mut Self, _proxy: &CosmicCornerRadiusToplevelV1, @@ -47,22 +39,7 @@ impl Dispatch for SctkState { _qhandle: &sctk::reexports::client::QueueHandle, ) { match event { - _ => unimplemented!(), - } - } -} - -impl Dispatch for SctkState { - fn event( - state: &mut Self, - _proxy: &CosmicCornerRadiusLayerV1, - event: ::Event, - _data: &(), - _conn: &Connection, - _qhandle: &sctk::reexports::client::QueueHandle, - ) { - match event { - _ => unimplemented!(), + _ => unimplemented!() } } } diff --git a/winit/src/platform_specific/wayland/handlers/shell/layer.rs b/winit/src/platform_specific/wayland/handlers/shell/layer.rs index 5e6bad57..65e5724b 100644 --- a/winit/src/platform_specific/wayland/handlers/shell/layer.rs +++ b/winit/src/platform_specific/wayland/handlers/shell/layer.rs @@ -1,13 +1,13 @@ use crate::platform_specific::wayland::{ - event_loop::state::{SctkState, receive_frame}, + event_loop::state::{receive_frame, SctkState}, sctk_event::{LayerSurfaceEventVariant, SctkEvent}, }; use cctk::sctk::{ delegate_layer, reexports::client::Proxy, shell::{ - WaylandSurface, wlr_layer::{Anchor, KeyboardInteractivity, LayerShellHandler}, + WaylandSurface, }, }; use std::fmt::Debug; @@ -27,15 +27,6 @@ impl LayerShellHandler for SctkState { None => return, }; - if let Some(id) = self.id_map.remove(&layer.surface.wl_surface().id()) { - if let Some(blurred) = self.blur_surfaces.remove(&id) { - blurred.destroy(); - } - _ = self.corner_radii.remove(&id); - - _ = self.destroyed.insert(id); - } - self.sctk_events.push(SctkEvent::LayerSurfaceEvent { variant: LayerSurfaceEventVariant::Done, id: layer.surface.wl_surface().clone(), diff --git a/winit/src/platform_specific/wayland/handlers/shell/mod.rs b/winit/src/platform_specific/wayland/handlers/shell/mod.rs index c4117eb7..af8b5961 100644 --- a/winit/src/platform_specific/wayland/handlers/shell/mod.rs +++ b/winit/src/platform_specific/wayland/handlers/shell/mod.rs @@ -1,4 +1,4 @@ -pub mod corner_radius; pub mod layer; pub mod xdg_popup; pub mod xdg_window; +pub mod corner_radius; diff --git a/winit/src/platform_specific/wayland/handlers/shell/xdg_popup.rs b/winit/src/platform_specific/wayland/handlers/shell/xdg_popup.rs index 432f5bde..55bf2b87 100644 --- a/winit/src/platform_specific/wayland/handlers/shell/xdg_popup.rs +++ b/winit/src/platform_specific/wayland/handlers/shell/xdg_popup.rs @@ -84,11 +84,6 @@ impl PopupHandler for SctkState { for popup in to_destroy.into_iter().rev() { if let Some(id) = self.id_map.remove(&popup.popup.wl_surface().id()) { - if let Some(blurred) = self.blur_surfaces.remove(&id) { - blurred.destroy(); - } - _ = self.corner_radii.remove(&id); - _ = self.destroyed.insert(id); } diff --git a/winit/src/platform_specific/wayland/handlers/wp_viewporter.rs b/winit/src/platform_specific/wayland/handlers/wp_viewporter.rs index 7bbd66d1..5cfe28d7 100644 --- a/winit/src/platform_specific/wayland/handlers/wp_viewporter.rs +++ b/winit/src/platform_specific/wayland/handlers/wp_viewporter.rs @@ -1,10 +1,10 @@ //! Handling of the wp-viewporter. -use cctk::sctk::reexports::client::Dispatch; use cctk::sctk::reexports::client::globals::{BindError, GlobalList}; use cctk::sctk::reexports::client::protocol::wl_surface::WlSurface; +use cctk::sctk::reexports::client::Dispatch; use cctk::sctk::reexports::client::{ - Connection, Proxy, QueueHandle, delegate_dispatch, + delegate_dispatch, Connection, Proxy, QueueHandle, }; use cctk::sctk::reexports::protocols::wp::viewporter::client::wp_viewport::WpViewport; use cctk::sctk::reexports::protocols::wp::viewporter::client::wp_viewporter::WpViewporter; diff --git a/winit/src/platform_specific/wayland/mod.rs b/winit/src/platform_specific/wayland/mod.rs index e98316ce..9b3a7ec0 100644 --- a/winit/src/platform_specific/wayland/mod.rs +++ b/winit/src/platform_specific/wayland/mod.rs @@ -21,7 +21,6 @@ use iced_runtime::core::{Vector, window}; use raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle}; use raw_window_handle::{HasRawDisplayHandle, RawWindowHandle}; use sctk_event::SctkEvent; -use std::sync::OnceLock; use std::{collections::HashMap, sync::Arc}; use subsurface_widget::{SubsurfaceInstance, SubsurfaceState}; use wayland_backend::client::ObjectId; @@ -129,6 +128,7 @@ impl PlatformSpecific { }; self.wayland.display_handle = Some(display); self.wayland.proxy = Some(raw); + // TODO remove this self.wayland.sender = crate::platform_specific::event_loop::SctkEventLoop::new( self.wayland.winit_event_sender.clone().unwrap(), diff --git a/winit/src/platform_specific/wayland/sctk_event.rs b/winit/src/platform_specific/wayland/sctk_event.rs index 2ac54bed..8845b0c9 100755 --- a/winit/src/platform_specific/wayland/sctk_event.rs +++ b/winit/src/platform_specific/wayland/sctk_event.rs @@ -68,8 +68,10 @@ use cctk::{ xdg::{popup::PopupConfigure, window::WindowConfigure}, }, }, + wayland_client::protocol::wl_subsurface::WlSubsurface, }; use std::{ + any::Any, collections::HashMap, num::NonZeroU32, sync::{Arc, Mutex}, @@ -96,7 +98,9 @@ use super::{ #[derive(Debug, Clone)] pub enum SctkEvent { - Blur, + // + // Input events + // SeatEvent { variant: SeatEventVariant, id: WlSeat, @@ -118,6 +122,11 @@ pub enum SctkEvent { seat_id: WlSeat, surface: WlSurface, }, + // TODO data device & touch + + // + // Surface Events + // WindowEvent { variant: WindowEventVariant, id: WlSurface, @@ -158,6 +167,10 @@ pub enum SctkEvent { }, SubsurfaceEvent(SubsurfaceEventVariant), + + // + // output events + // NewOutput { id: WlOutput, info: Option, @@ -167,7 +180,9 @@ pub enum SctkEvent { info: OutputInfo, }, RemovedOutput(WlOutput), - + // + // compositor events + // ScaleFactorChanged { factor: f64, id: WlOutput, @@ -1723,12 +1738,6 @@ impl SctkEvent { ), ), )), - SctkEvent::Blur => events.push(( - None, - iced_runtime::core::Event::PlatformSpecific( - PlatformSpecific::Wayland(wayland::Event::BlurEnabled), - ), - )), } } } diff --git a/winit/src/platform_specific/wayland/subsurface_widget.rs b/winit/src/platform_specific/wayland/subsurface_widget.rs index c3173fa9..dbecc52d 100644 --- a/winit/src/platform_specific/wayland/subsurface_widget.rs +++ b/winit/src/platform_specific/wayland/subsurface_widget.rs @@ -409,10 +409,7 @@ impl SubsurfaceState { .unwrap(); canvas[0..width as usize * height as usize * 4].copy_from_slice(data); surface.damage_buffer(0, 0, width as i32, height as i32); - if let Err(err) = buffer.attach_to(&surface) { - log::warn!("failed to attach shm buffer to subsurface: {err}"); - return; - } + buffer.attach_to(&surface); surface.offset(offset.x as i32, offset.y as i32); wp_viewport.set_destination( (width as f64 / scale) as i32, diff --git a/winit/src/window.rs b/winit/src/window.rs index e56483f4..87d35a5a 100644 --- a/winit/src/window.rs +++ b/winit/src/window.rs @@ -335,9 +335,19 @@ where } if self.ime_state != Some((cursor, purpose)) { + // Specify only the bottom-left position of the cursor on Linux + // because fcitx5 doesn't work well with cursor areas of + // the top-left position and height. + // The candidate window hides the composing text (a.k.a. preedit). + let (cursor_y, cursor_height) = + if cfg!(not(any(target_os = "windows", target_os = "macos"))) { + (cursor.y + cursor.height, 0.0) + } else { + (cursor.y, cursor.height) + }; self.raw.set_ime_cursor_area( - LogicalPosition::new(cursor.x, cursor.y).into(), - LogicalSize::new(cursor.width, cursor.height).into(), + LogicalPosition::new(cursor.x, cursor_y).into(), + LogicalSize::new(cursor.width, cursor_height).into(), ); self.raw.set_ime_purpose(conversion::ime_purpose(purpose)); diff --git a/winit/src/window/state.rs b/winit/src/window/state.rs index 1e16fc51..98fdf9ee 100644 --- a/winit/src/window/state.rs +++ b/winit/src/window/state.rs @@ -97,7 +97,6 @@ where self.ready = ready; } - #[cfg(feature = "a11y")] pub(crate) fn set_a11y_ready(&mut self, ready: bool) { self.a11y_ready = ready; }