diff --git a/Cargo.lock b/Cargo.lock index b5d874b8..b309db1d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -787,6 +787,13 @@ dependencies = [ "cfg_aliases", ] +[[package]] +name = "build_helpers" +version = "0.14.0" +dependencies = [ + "cfg_aliases", +] + [[package]] name = "built" version = "0.8.0" @@ -1076,6 +1083,7 @@ dependencies = [ [[package]] name = "clipboard_macos" version = "0.1.0" +source = "git+https://github.com/pop-os/window_clipboard.git?tag=sctk-0.20#f68595ee0e62fbd6589f4709b5aaa5c3c7ea5f6c" dependencies = [ "objc", "objc-foundation", @@ -1085,12 +1093,22 @@ dependencies = [ [[package]] name = "clipboard_wayland" version = "0.2.2" +source = "git+https://github.com/pop-os/window_clipboard.git?tag=sctk-0.20#f68595ee0e62fbd6589f4709b5aaa5c3c7ea5f6c" dependencies = [ "dnd", "mime 0.1.0", "smithay-clipboard", ] +[[package]] +name = "clipboard_x11" +version = "0.4.2" +source = "git+https://github.com/pop-os/window_clipboard.git?tag=sctk-0.20#f68595ee0e62fbd6589f4709b5aaa5c3c7ea5f6c" +dependencies = [ + "thiserror 1.0.69", + "x11rb", +] + [[package]] name = "clock" version = "0.1.0" @@ -1283,6 +1301,7 @@ dependencies = [ [[package]] name = "cosmic-client-toolkit" version = "0.2.0" +source = "git+https://github.com/pop-os/cosmic-protocols?rev=32283d7#32283d76a8d0342da74c4cc022a533c52dcf378f" dependencies = [ "bitflags 2.11.0", "cosmic-protocols", @@ -1295,6 +1314,7 @@ dependencies = [ [[package]] name = "cosmic-protocols" version = "0.2.0" +source = "git+https://github.com/pop-os/cosmic-protocols?rev=32283d7#32283d76a8d0342da74c4cc022a533c52dcf378f" dependencies = [ "bitflags 2.11.0", "wayland-backend", @@ -1308,6 +1328,8 @@ dependencies = [ [[package]] name = "cosmic-text" version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be17b688510d934ce13f48a2beba700e11583e281e0fda99c22bb256a14eda73" dependencies = [ "bitflags 2.11.0", "fontdb", @@ -1325,7 +1347,6 @@ dependencies = [ "unicode-linebreak", "unicode-script", "unicode-segmentation", - "unicode-width", ] [[package]] @@ -1432,6 +1453,7 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] name = "cryoglyph" version = "0.1.0" +source = "git+https://github.com/iced-rs/cryoglyph.git?rev=e429a025df36ab8145708acb309080ae3deec17a#e429a025df36ab8145708acb309080ae3deec17a" dependencies = [ "cosmic-text", "etagere", @@ -1608,6 +1630,7 @@ dependencies = [ [[package]] name = "dnd" version = "0.1.0" +source = "git+https://github.com/pop-os/window_clipboard.git?tag=sctk-0.20#f68595ee0e62fbd6589f4709b5aaa5c3c7ea5f6c" dependencies = [ "bitflags 2.11.0", "mime 0.1.0", @@ -1642,6 +1665,30 @@ dependencies = [ [[package]] name = "dpi" version = "0.1.2" +source = "git+https://github.com/pop-os/winit.git?tag=cosmic-0.14#261cda54017f98a12dc55569c864430fe6770366" + +[[package]] +name = "drm" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0f8a69e60d75ae7dab4ef26a59ca99f2a89d4c142089b537775ae0c198bdcde" +dependencies = [ + "bitflags 2.11.0", + "bytemuck", + "drm-ffi", + "drm-fourcc", + "rustix 0.38.44", +] + +[[package]] +name = "drm-ffi" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41334f8405792483e32ad05fbb9c5680ff4e84491883d2947a4757dc54cb2ac6" +dependencies = [ + "drm-sys", + "rustix 0.38.44", +] [[package]] name = "drm-fourcc" @@ -1649,6 +1696,16 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" +[[package]] +name = "drm-sys" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d09ff881f92f118b11105ba5e34ff8f4adf27b30dae8f12e28c193af1c83176" +dependencies = [ + "libc", + "linux-raw-sys 0.6.5", +] + [[package]] name = "editor" version = "0.1.0" @@ -2371,7 +2428,7 @@ dependencies = [ "log", "presser", "thiserror 2.0.18", - "windows 0.62.2", + "windows 0.57.0", ] [[package]] @@ -2907,6 +2964,7 @@ dependencies = [ name = "iced" version = "0.14.0" dependencies = [ + "build_helpers", "criterion", "dnd", "iced_accessibility", @@ -2958,6 +3016,7 @@ version = "0.14.0" dependencies = [ "approx", "bitflags 2.11.0", + "build_helpers", "bytes", "cosmic-client-toolkit", "dnd", @@ -3064,6 +3123,7 @@ dependencies = [ name = "iced_runtime" version = "0.14.0" dependencies = [ + "build_helpers", "bytes", "cosmic-client-toolkit", "dnd", @@ -3131,6 +3191,7 @@ version = "0.14.0" dependencies = [ "as-raw-xcb-connection", "bitflags 2.11.0", + "build_helpers", "bytemuck", "cosmic-client-toolkit", "cryoglyph", @@ -3145,6 +3206,7 @@ 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", @@ -3159,6 +3221,7 @@ dependencies = [ name = "iced_widget" version = "0.14.2" dependencies = [ + "build_helpers", "cosmic-client-toolkit", "dnd", "iced_accessibility", @@ -3180,6 +3243,7 @@ dependencies = [ name = "iced_winit" version = "0.14.0" dependencies = [ + "build_helpers", "cosmic-client-toolkit", "cursor-icon", "dnd", @@ -3736,14 +3800,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.18" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" dependencies = [ "bitflags 2.11.0", "libc", "plain", - "redox_syscall 0.9.0", + "redox_syscall 0.7.4", ] [[package]] @@ -3773,6 +3837,12 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "linux-raw-sys" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7" + [[package]] name = "linux-raw-sys" version = "0.12.1" @@ -3998,6 +4068,7 @@ dependencies = [ [[package]] name = "mime" version = "0.1.0" +source = "git+https://github.com/pop-os/window_clipboard.git?tag=sctk-0.20#f68595ee0e62fbd6589f4709b5aaa5c3c7ea5f6c" dependencies = [ "smithay-clipboard", ] @@ -5423,16 +5494,6 @@ dependencies = [ "font-types", ] -[[package]] -name = "redox_event" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5018d583d6d2f5499352aea8d177e9067d1eb03ab17c78169d5ba7a30001b15" -dependencies = [ - "bitflags 2.11.0", - "libredox", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -5444,9 +5505,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.9.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5102a6aaa05aa011a238e178e6bca86d2cb56fc9f586d37cb80f5bca6e07759" +checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a" dependencies = [ "bitflags 2.11.0", ] @@ -6228,6 +6289,7 @@ dependencies = [ [[package]] name = "smithay-clipboard" version = "0.8.0" +source = "git+https://github.com/pop-os/smithay-clipboard?tag=sctk-0.20#859b02c88f45c554049a67c6ddeec1692ce0e20b" dependencies = [ "libc", "raw-window-handle", @@ -6285,12 +6347,14 @@ dependencies = [ [[package]] name = "softbuffer" version = "0.4.1" +source = "git+https://github.com/pop-os/softbuffer?tag=cosmic-4.0#a3f77e251e7422803f693df6e3fc313c010c4dcb" dependencies = [ "as-raw-xcb-connection", "bytemuck", "cfg_aliases", "cocoa", "core-graphics", + "drm", "fastrand", "foreign-types 0.5.0", "js-sys", @@ -7958,10 +8022,12 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "window_clipboard" version = "0.4.1" +source = "git+https://github.com/pop-os/window_clipboard.git?tag=sctk-0.20#f68595ee0e62fbd6589f4709b5aaa5c3c7ea5f6c" dependencies = [ "clipboard-win", "clipboard_macos", "clipboard_wayland", + "clipboard_x11", "dnd", "mime 0.1.0", "raw-window-handle", @@ -8465,6 +8531,7 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winit" version = "0.31.0-beta.2" +source = "git+https://github.com/pop-os/winit.git?tag=cosmic-0.14#261cda54017f98a12dc55569c864430fe6770366" dependencies = [ "bitflags 2.11.0", "cfg_aliases", @@ -8490,6 +8557,7 @@ dependencies = [ [[package]] name = "winit-android" version = "0.31.0-beta.2" +source = "git+https://github.com/pop-os/winit.git?tag=cosmic-0.14#261cda54017f98a12dc55569c864430fe6770366" dependencies = [ "android-activity", "bitflags 2.11.0", @@ -8504,6 +8572,7 @@ dependencies = [ [[package]] name = "winit-appkit" version = "0.31.0-beta.2" +source = "git+https://github.com/pop-os/winit.git?tag=cosmic-0.14#261cda54017f98a12dc55569c864430fe6770366" dependencies = [ "bitflags 2.11.0", "block2 0.6.2", @@ -8525,6 +8594,7 @@ dependencies = [ [[package]] name = "winit-common" version = "0.31.0-beta.2" +source = "git+https://github.com/pop-os/winit.git?tag=cosmic-0.14#261cda54017f98a12dc55569c864430fe6770366" dependencies = [ "memmap2 0.9.10", "objc2 0.6.4", @@ -8539,6 +8609,7 @@ dependencies = [ [[package]] name = "winit-core" version = "0.31.0-beta.2" +source = "git+https://github.com/pop-os/winit.git?tag=cosmic-0.14#261cda54017f98a12dc55569c864430fe6770366" dependencies = [ "bitflags 2.11.0", "cursor-icon", @@ -8552,13 +8623,14 @@ dependencies = [ [[package]] name = "winit-orbital" version = "0.31.0-beta.2" +source = "git+https://github.com/pop-os/winit.git?tag=cosmic-0.14#261cda54017f98a12dc55569c864430fe6770366" dependencies = [ "bitflags 2.11.0", "dpi", "libredox", "orbclient", "raw-window-handle", - "redox_event", + "redox_syscall 0.7.4", "smol_str", "tracing", "winit-core", @@ -8567,6 +8639,7 @@ dependencies = [ [[package]] name = "winit-uikit" version = "0.31.0-beta.2" +source = "git+https://github.com/pop-os/winit.git?tag=cosmic-0.14#261cda54017f98a12dc55569c864430fe6770366" dependencies = [ "bitflags 2.11.0", "block2 0.6.2", @@ -8586,6 +8659,7 @@ dependencies = [ [[package]] name = "winit-wayland" version = "0.31.0-beta.2" +source = "git+https://github.com/pop-os/winit.git?tag=cosmic-0.14#261cda54017f98a12dc55569c864430fe6770366" dependencies = [ "ahash", "bitflags 2.11.0", @@ -8611,6 +8685,7 @@ dependencies = [ [[package]] name = "winit-web" version = "0.31.0-beta.2" +source = "git+https://github.com/pop-os/winit.git?tag=cosmic-0.14#261cda54017f98a12dc55569c864430fe6770366" dependencies = [ "atomic-waker", "bitflags 2.11.0", @@ -8632,6 +8707,7 @@ dependencies = [ [[package]] name = "winit-win32" version = "0.31.0-beta.2" +source = "git+https://github.com/pop-os/winit.git?tag=cosmic-0.14#261cda54017f98a12dc55569c864430fe6770366" dependencies = [ "bitflags 2.11.0", "cursor-icon", @@ -8647,6 +8723,7 @@ dependencies = [ [[package]] name = "winit-x11" version = "0.31.0-beta.2" +source = "git+https://github.com/pop-os/winit.git?tag=cosmic-0.14#261cda54017f98a12dc55569c864430fe6770366" dependencies = [ "bitflags 2.11.0", "bytemuck", @@ -9191,7 +9268,3 @@ dependencies = [ "syn", "winnow 0.7.15", ] - -[[patch.unused]] -name = "cosmic-freedesktop-icons" -version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index c49fcf92..a1498ba6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -118,13 +118,17 @@ winit = [ "iced_accessibility?/accesskit_winit", "iced_program/winit", ] -wayland = ["iced_renderer/wayland", "iced_winit/wayland"] -cctk = ["iced_winit/cctk", "iced_widget/cctk", "iced_core/cctk", "wayland"] -# Enables the sctk shell. +wayland = [ + "iced_renderer/wayland", + "iced_winit/wayland", + "iced_runtime/wayland", + "iced_widget/wayland", + "iced_core/wayland", +] + [dependencies] - - iced_devtools.workspace = true +iced_devtools.optional = true iced_debug.workspace = true iced_program.workspace = true @@ -134,10 +138,9 @@ iced_renderer.workspace = true iced_runtime.workspace = true iced_widget.workspace = true iced_winit.workspace = true -iced_devtools.optional = true +iced_winit.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 @@ -190,6 +193,7 @@ members = [ "winit", "examples/*", "accessibility", + "build_helpers", ] exclude = ["examples/integration"] @@ -363,3 +367,6 @@ 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 new file mode 100644 index 00000000..db00a773 --- /dev/null +++ b/build.rs @@ -0,0 +1,3 @@ +fn main() { + build_helpers::cfg_aliases_setup(); +} diff --git a/build_helpers/Cargo.toml b/build_helpers/Cargo.toml new file mode 100644 index 00000000..ff319f69 --- /dev/null +++ b/build_helpers/Cargo.toml @@ -0,0 +1,17 @@ +[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 new file mode 100644 index 00000000..364b6ed8 --- /dev/null +++ b/build_helpers/src/lib.rs @@ -0,0 +1,24 @@ +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 0a376b7c..f3136a87 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -19,6 +19,7 @@ crisp = [] basic-shaping = [] advanced-shaping = [] a11y = ["iced_accessibility"] +wayland = ["cctk"] [dependencies] palette = "0.7" @@ -43,8 +44,6 @@ 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" @@ -56,3 +55,10 @@ 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 new file mode 100644 index 00000000..db00a773 --- /dev/null +++ b/core/build.rs @@ -0,0 +1,3 @@ +fn main() { + build_helpers::cfg_aliases_setup(); +} diff --git a/core/src/event.rs b/core/src/event.rs index 1aaf4ff4..b4a28a29 100644 --- a/core/src/event.rs +++ b/core/src/event.rs @@ -7,7 +7,8 @@ use crate::keyboard; use crate::mouse; use crate::touch; use crate::window; -#[cfg(all(feature = "cctk", target_os = "linux"))] + +#[cfg(wayland_platform)] /// A platform specific event for wayland pub mod wayland; /// A user interface event. @@ -49,7 +50,7 @@ pub enum Event { /// A platform specific event #[derive(Debug, Clone, PartialEq)] pub enum PlatformSpecific { - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] /// A Wayland specific event Wayland(wayland::Event), } diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index 2ba0ada4..2598b74e 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -446,11 +446,22 @@ where | 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(); + } } } @@ -511,6 +522,7 @@ where state.focused = true; state.keyboard_focused = false; shell.capture_event(); + shell.request_redraw(); } } @@ -520,6 +532,7 @@ where state.focused = true; state.keyboard_focused = false; shell.capture_event(); + shell.request_redraw(); } } @@ -544,7 +557,15 @@ where position.y - anchor.y, ); - sel.end = hit_to_grapheme(paragraph, relative, content); + 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(); } } @@ -587,6 +608,7 @@ where sel.anchor = 0; sel.end = grapheme_count; shell.capture_event(); + shell.request_redraw(); return; } _ => {} @@ -613,6 +635,7 @@ where sel.end = pos; } shell.capture_event(); + shell.request_redraw(); } keyboard::Key::Named(keyboard::key::Named::ArrowRight) => { let by_word = is_jump_modifier(*modifiers); @@ -633,6 +656,7 @@ where sel.end = pos; } shell.capture_event(); + shell.request_redraw(); } keyboard::Key::Named(keyboard::key::Named::Home) => { if modifiers.shift() { @@ -642,6 +666,7 @@ where sel.end = 0; } shell.capture_event(); + shell.request_redraw(); } keyboard::Key::Named(keyboard::key::Named::End) => { if modifiers.shift() { @@ -651,6 +676,7 @@ where sel.end = grapheme_count; } shell.capture_event(); + shell.request_redraw(); } _ => {} } diff --git a/graphics/src/layer.rs b/graphics/src/layer.rs index 31cfe68a..210b8309 100644 --- a/graphics/src/layer.rs +++ b/graphics/src/layer.rs @@ -83,13 +83,20 @@ 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/runtime/Cargo.toml b/runtime/Cargo.toml index ea4741d1..1cb23e23 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"] -cctk = ["iced_core/cctk", "dep:cctk"] +wayland = ["iced_core/wayland", "dep:cctk"] [dependencies] bytes.workspace = true @@ -33,9 +33,14 @@ 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 new file mode 100644 index 00000000..db00a773 --- /dev/null +++ b/runtime/build.rs @@ -0,0 +1,3 @@ +fn main() { + build_helpers::cfg_aliases_setup(); +} diff --git a/runtime/src/platform_specific/mod.rs b/runtime/src/platform_specific/mod.rs index 4ef5ad9f..9cc66ddd 100644 --- a/runtime/src/platform_specific/mod.rs +++ b/runtime/src/platform_specific/mod.rs @@ -2,23 +2,23 @@ use std::fmt; -#[cfg(all(feature = "cctk", target_os = "linux"))] +#[cfg(wayland_platform)] /// Platform specific actions defined for wayland pub mod wayland; /// Platform specific actions defined for wayland pub enum Action { /// Wayland Specific Actions - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] Wayland(wayland::Action), } impl fmt::Debug for Action { fn fmt(&self, _f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] Action::Wayland(action) => action.fmt(_f), - #[cfg(not(all(feature = "cctk", target_os = "linux")))] + #[cfg(not(wayland_platform))] _ => Ok(()), } } diff --git a/runtime/src/window.rs b/runtime/src/window.rs index 4d2f5650..ae6445ec 100644 --- a/runtime/src/window.rs +++ b/runtime/src/window.rs @@ -222,7 +222,7 @@ pub fn frames() -> Subscription<(Id, Instant)> { _ => None, }) } -#[cfg(all(feature = "cctk", target_os = "linux"))] +#[cfg(wayland_platform)] /// 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 6e57128b..28870ee2 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(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] pub use crate::core::event::wayland; pub use crate::core::event::{Event, Status}; pub use iced_futures::event::{listen, listen_raw, listen_with}; diff --git a/tiny_skia/src/engine.rs b/tiny_skia/src/engine.rs index 61323f04..9f0b54f2 100644 --- a/tiny_skia/src/engine.rs +++ b/tiny_skia/src/engine.rs @@ -263,6 +263,10 @@ 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/wgpu/Cargo.toml b/wgpu/Cargo.toml index ffbcd293..c278fb17 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -30,6 +30,7 @@ strict-assertions = [] # 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 @@ -70,3 +71,6 @@ x11rb = { version = "0.13.1", optional = true, features = [ "dri3", "randr", ] } + +[build-dependencies] +build_helpers = { path = "../build_helpers" } diff --git a/wgpu/build.rs b/wgpu/build.rs new file mode 100644 index 00000000..db00a773 --- /dev/null +++ b/wgpu/build.rs @@ -0,0 +1,3 @@ +fn main() { + build_helpers::cfg_aliases_setup(); +} diff --git a/wgpu/src/window.rs b/wgpu/src/window.rs index f71b7d3f..61be2187 100644 --- a/wgpu/src/window.rs +++ b/wgpu/src/window.rs @@ -1,11 +1,6 @@ //! Display rendering results on windows. pub mod compositor; -#[cfg(all( - unix, - feature = "cctk", - not(target_os = "macos"), - not(target_os = "redox") -))] +#[cfg(wayland_platform)] mod wayland; #[cfg(all(unix, feature = "x11", not(target_os = "macos"), not(target_os = "redox")))] mod x11; diff --git a/wgpu/src/window/compositor.rs b/wgpu/src/window/compositor.rs index d6186ab5..fef87b39 100644 --- a/wgpu/src/window/compositor.rs +++ b/wgpu/src/window/compositor.rs @@ -9,16 +9,10 @@ use crate::graphics::{self, Shell, Viewport}; use crate::settings::{self, Settings}; use crate::{Engine, Renderer}; -#[cfg(all( - unix, - feature = "cctk", - not(target_os = "macos"), - not(target_os = "redox") -))] +#[cfg(wayland_platform)] use super::wayland::get_wayland_device_ids; #[cfg(all(unix, feature = "x11", 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 { @@ -65,12 +59,7 @@ impl Compositor { compatible_window: Option, shell: Shell, ) -> Result { - #[cfg(all( - unix, - feature = "cctk", - not(target_os = "macos"), - not(target_os = "redox") - ))] + #[cfg(wayland_platform)] let ids = compatible_window.as_ref().and_then(|window| { let w = get_wayland_device_ids(window); #[cfg(feature = "x11")] @@ -78,23 +67,13 @@ impl Compositor { w }); - #[cfg(all( - unix, - not(feature = "cctk"), - not(target_os = "macos"), - not(target_os = "redox") - ))] - let ids = compatible_window - .as_ref() - .and_then(|window| get_x11_device_ids(window)); - // HACK: // 1. If we specifically didn't select an nvidia gpu // 2. and the user didn't specifically request an nvidia gpu // 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(all(unix, not(target_os = "macos"), not(target_os = "redox")))] + #[cfg(wayland_platform)] if !matches!(ids, Some((0x10de, _))) && std::env::var_os("__NV_PRIME_RENDER_OFFLOAD") .is_none_or(|var| var == "0") @@ -154,11 +133,7 @@ impl Compositor { let mut adapter = None; #[cfg_attr(not(unix), allow(dead_code))] if std::env::var_os("WGPU_ADAPTER_NAME").is_none() { - #[cfg(all( - unix, - not(target_os = "macos"), - not(target_os = "redox") - ))] + #[cfg(wayland_platform)] if let Some((vendor_id, device_id)) = ids { adapter = instance .enumerate_adapters(settings.backends) diff --git a/wgpu/src/window/x11.rs b/wgpu/src/window/x11.rs index 58da401a..a1508134 100644 --- a/wgpu/src/window/x11.rs +++ b/wgpu/src/window/x11.rs @@ -1,3 +1,5 @@ +#![allow(unexpected_cfgs)] + use std::{ fs, io::{BufRead, BufReader}, @@ -144,7 +146,9 @@ pub fn get_x11_device_ids(window: &W) -> Option<(u16, u16)> { { let stat = stat(Path::new("/dev/dri").join(device)).ok()?; - let dev = stat.st_rdev; + // Hack (u64 as u64) for E2K CPU architecture + #[allow(clippy::unnecessary_cast)] + let dev = stat.st_rdev as u64; return super::ids_from_dev(dev); } } @@ -165,7 +169,9 @@ 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()?; - let dev = stat.st_rdev; + // Hack (u64 as u64) for E2K CPU architecture + #[allow(clippy::unnecessary_cast)] + let dev = stat.st_rdev as u64; super::ids_from_dev(dev) } } diff --git a/widget/Cargo.toml b/widget/Cargo.toml index ab34819b..0726ae40 100644 --- a/widget/Cargo.toml +++ b/widget/Cargo.toml @@ -29,15 +29,13 @@ highlighter = ["dep:iced_highlighter"] advanced = [] crisp = [] a11y = ["iced_accessibility"] -cctk = ["iced_runtime/cctk", "dep:cctk"] +wayland = ["iced_runtime/wayland", "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 @@ -57,3 +55,10 @@ 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 new file mode 100644 index 00000000..db00a773 --- /dev/null +++ b/widget/build.rs @@ -0,0 +1,3 @@ +fn main() { + build_helpers::cfg_aliases_setup(); +} diff --git a/widget/src/pin.rs b/widget/src/pin.rs index 8eb5906e..cef75944 100644 --- a/widget/src/pin.rs +++ b/widget/src/pin.rs @@ -60,6 +60,7 @@ where width: Length, height: Length, position: Point, + overflow: bool, } impl<'a, Message, Theme, Renderer> Pin<'a, Message, Theme, Renderer> @@ -75,6 +76,7 @@ where width: Length::Fill, height: Length::Fill, position: Point::ORIGIN, + overflow: false, } } @@ -107,6 +109,12 @@ 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 @@ -145,8 +153,12 @@ where ) -> layout::Node { let limits = limits.width(self.width).height(self.height); - let available = - limits.max() - Size::new(self.position.x, self.position.y); + let available = + if self.overflow { + limits.max() + } else { + limits.max() - Size::new(self.position.x, self.position.y) + }; let node = self .content diff --git a/widget/src/slider.rs b/widget/src/slider.rs index ff32f417..70cfc9e4 100644 --- a/widget/src/slider.rs +++ b/widget/src/slider.rs @@ -110,6 +110,8 @@ 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> @@ -119,7 +121,13 @@ where Theme: Catalog, { /// The default height of a [`Slider`]. - pub const DEFAULT_HEIGHT: f32 = 16.0; + 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; /// Creates a new [`Slider`]. /// @@ -165,6 +173,8 @@ where height: Self::DEFAULT_HEIGHT, class: Theme::default(), status: None, + handle_width: Self::DEFAULT_MAX_HANDLE_WIDTH, + handle_height: Self::DEFAULT_MAX_HANDLE_HEIGHT, } } @@ -207,6 +217,24 @@ 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(); @@ -323,8 +351,15 @@ 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 = layout.bounds(); + let bounds = Rectangle { + x: layout.bounds().x + self.handle_width / 2.0, + width: layout.bounds().width - self.handle_width, + ..layout.bounds() + }; if cursor_position.x <= bounds.x { Some(*self.range.start()) @@ -509,54 +544,30 @@ where _cursor: mouse::Cursor, _viewport: &Rectangle, ) { - let bounds = layout.bounds(); + let bounds = Rectangle { + x: layout.bounds().x + self.handle_width / 2.0, + width: layout.bounds().width - self.handle_width, + ..layout.bounds() + }; let style = theme.style(&self.class, self.status.unwrap_or(Status::Active)); - 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) = + let (mut handle_width, mut 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, - } => { - 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); - } - - ( - width, - height, - Radius { - top_left: border_radius[0], - top_right: border_radius[1], - bottom_right: border_radius[2], - bottom_left: border_radius[3], - }, - ) - } + } => (f32::from(width), f32::from(height), border_radius), }; + handle_width = handle_width.min(self.handle_width); + handle_height = handle_height.min(self.handle_height); + let value = self.value.into() as f32; let (range_start, range_end) = { let (start, end) = self.range.clone().into_inner(); @@ -567,8 +578,7 @@ where let offset = if range_start >= range_end { 0.0 } else { - (bounds.width - handle_width) * (value - range_start) - / (range_end - range_start) + bounds.width * (value - range_start) / (range_end - range_start) }; let rail_y = bounds.y + bounds.height / 2.0; @@ -590,7 +600,8 @@ where x: bounds.x + offset, y: rail_y + 6.0, width: BREAKPOINT_WIDTH, - height: 8.0, + height: 8.0_f32 + .min(bounds.y + bounds.height - (rail_y + 6.0)), }, border: Border { radius: 0.0.into(), @@ -607,9 +618,9 @@ where renderer::Quad { bounds: Rectangle { x: bounds.x, - y: rail_y - style.rail.width / 2.0, - width: offset + handle_width / 2.0, - height: style.rail.width, + y: rail_y - (style.rail.width).min(bounds.height) / 2.0, + width: offset, + height: (style.rail.width).min(bounds.height), }, border: style.rail.border, ..renderer::Quad::default() @@ -622,10 +633,10 @@ where renderer.fill_quad( renderer::Quad { bounds: Rectangle { - 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, + 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), }, border: style.rail.border, ..renderer::Quad::default() @@ -637,7 +648,7 @@ where renderer.fill_quad( renderer::Quad { bounds: Rectangle { - x: bounds.x + offset, + x: bounds.x + offset - handle_width / 2.0, y: rail_y - (handle_height / 2.0), width: handle_width, height: handle_height, diff --git a/winit/Cargo.toml b/winit/Cargo.toml index 41e4a582..741528b5 100644 --- a/winit/Cargo.toml +++ b/winit/Cargo.toml @@ -14,7 +14,18 @@ keywords.workspace = true workspace = true [features] -wayland = ["winit/wayland", "wayland-csd-adwaita"] +wayland = [ + "winit/wayland", + "wayland-csd-adwaita", + "wayland-protocols", + "raw-window-handle", + "iced_runtime/wayland", + "wayland-backend", + "xkbcommon", + "xkbcommon-dl", + "xkeysym", + "dep:cctk", +] default = ["x11", "wayland-dlopen"] debug = ["iced_debug/enable"] sysinfo = ["dep:sysinfo"] @@ -26,17 +37,6 @@ 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,7 +64,8 @@ iced_debug.workspace = true iced_program.workspace = true -[target.'cfg(target_os = "linux")'.dependencies] +[target.'cfg(all(unix, not(any(target_os = "redox", target_family = "wasm", target_os = "android", target_vendor = "apple"))))'.dependencies] + mundy.workspace = true mundy.optional = true @@ -89,3 +90,6 @@ 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 new file mode 100644 index 00000000..db00a773 --- /dev/null +++ b/winit/build.rs @@ -0,0 +1,3 @@ +fn main() { + build_helpers::cfg_aliases_setup(); +} diff --git a/winit/src/application/drag_resize.rs b/winit/src/application/drag_resize.rs index 6d575b52..29fa10da 100644 --- a/winit/src/application/drag_resize.rs +++ b/winit/src/application/drag_resize.rs @@ -49,7 +49,10 @@ pub fn event_func( position, .. } => { - if !window.is_decorated() { + let resizable = !window.is_decorated() + && !window.is_maximized() + && window.fullscreen().is_none(); + if resizable { let location = cursor_resize_direction( window.surface_size(), *position, diff --git a/winit/src/clipboard.rs b/winit/src/clipboard.rs index d302ac36..2c9e4a32 100644 --- a/winit/src/clipboard.rs +++ b/winit/src/clipboard.rs @@ -92,7 +92,7 @@ impl Clipboard { }) .unwrap_or(State::Unavailable); - #[cfg(target_os = "linux")] + #[cfg(wayland_platform)] 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 97cc97a6..8ce3ed66 100644 --- a/winit/src/conversion.rs +++ b/winit/src/conversion.rs @@ -23,6 +23,33 @@ 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, @@ -182,12 +209,19 @@ pub fn window_attributes( { use winit::platform::wayland::WindowAttributesWayland; - attributes = attributes.with_platform_attributes(Box::new( - WindowAttributesWayland::default().with_name( + let mut wayland_attributes = 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)); } } @@ -424,7 +458,7 @@ pub fn window_event( WindowEvent::ScaleFactorChanged { scale_factor, .. } => { Some(Event::Window(window::Event::Rescaled(scale_factor as f32))) } - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] WindowEvent::SuggestedBounds(bounds) => { let size = bounds.map(|bounds| { let size = bounds.to_logical(scale_factor); @@ -437,7 +471,7 @@ pub fn window_event( ), ))) } - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] WindowEvent::WindowStateChanged => { use cctk::sctk::reexports::csd_frame::WindowState; use winit::platform::wayland::WindowExtWayland; @@ -1491,7 +1525,7 @@ pub fn winit_key_code( }) } -#[cfg(all(feature = "cctk", target_os = "linux"))] +#[cfg(wayland_platform)] fn winit_native_key_code( keycode: keyboard::key::NativeCode, ) -> winit::keyboard::NativeKeyCode { @@ -1515,7 +1549,7 @@ fn winit_native_key_code( } /// Reconstruct the raw keycode -#[cfg(all(feature = "cctk", target_os = "linux"))] +#[cfg(wayland_platform)] 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 918f6c2a..38457840 100644 --- a/winit/src/lib.rs +++ b/winit/src/lib.rs @@ -47,7 +47,6 @@ 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; @@ -92,10 +91,10 @@ where let event_loop = EventLoop::new().expect("Create event loop"); - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] let is_wayland = winit::platform::wayland::EventLoopExtWayland::is_wayland(&event_loop); - #[cfg(not(all(feature = "cctk", target_os = "linux")))] + #[cfg(not(wayland_platform))] let is_wayland = false; // TODO this is new.. @@ -262,7 +261,7 @@ where | winit::event::WindowEvent::Moved(_) ); - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] { if matches!(event, WindowEvent::RedrawRequested) { for id in @@ -577,10 +576,7 @@ where .expect("Send event"); } Control::Winit(id, e) => { - #[cfg(all( - feature = "cctk", - target_os = "linux" - ))] + #[cfg(wayland_platform)] { if matches!(e, WindowEvent::RedrawRequested) { @@ -776,7 +772,7 @@ async fn run_instance

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

( &mut is_window_opening, &mut system_theme, &mut platform_specific_handler, + &mut dnd_surface, + &mut dnd_surface_id, is_daemon, ) }; @@ -887,7 +885,7 @@ async fn run_instance

( on_open, resize_border, } => { - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] platform_specific_handler.send_wayland( platform_specific::Action::TrackWindow(window.clone(), id), ); @@ -1056,7 +1054,7 @@ async fn run_instance

( continue; } // XX must force update to corner radius before the surface is committed. - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] if (window.surface_version != window.state.surface_version() || window.logical_size() != window.state.logical_size()) && !crate::subsurface_widget::is_subsurface(window_id) @@ -1395,8 +1393,7 @@ async fn run_instance

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

( &mut clipboard, &mut messages, ); - let mut needs_redraw = - !no_window_events || !messages.is_empty(); + let mut needs_redraw = !messages.is_empty(); if let Some(requested_size) = clipboard.requested_logical_size.lock().unwrap().take() { @@ -1470,8 +1466,17 @@ 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); } @@ -2074,6 +2079,10 @@ 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 @@ -2128,7 +2137,7 @@ where _ = control_sender.start_send(Control::Cleanup(id)).ok(); } let proxy = clipboard.proxy(); - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] platform_specific .send_wayland(platform_specific::Action::RemoveWindow(id)); if let Some(window) = window_manager.remove(id) { @@ -2589,6 +2598,10 @@ 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 5e84d16a..e66cf5f1 100644 --- a/winit/src/platform_specific/mod.rs +++ b/winit/src/platform_specific/mod.rs @@ -1,24 +1,20 @@ //! Wayland specific shell //! -use std::{borrow::Cow, collections::HashMap, sync::Arc}; +use std::collections::HashMap; -#[cfg(all(feature = "cctk", target_os = "linux"))] -use cctk::sctk::reexports::client::Connection; -use iced_graphics::{Compositor, compositor}; +use iced_graphics::compositor; use iced_runtime::{ core::{Vector, window}, - platform_specific, user_interface, + user_interface, }; use winit::raw_window_handle::HasWindowHandle; -#[cfg(all(feature = "cctk", target_os = "linux"))] +#[cfg(wayland_platform)] pub mod wayland; -#[cfg(all(feature = "cctk", target_os = "linux"))] +#[cfg(wayland_platform)] pub use wayland::*; -#[cfg(all(feature = "cctk", target_os = "linux"))] -use wayland_backend::client::Backend; use crate::{CreateCompositor, Program, WindowManager}; @@ -35,7 +31,7 @@ pub type UserInterfaces<'a, P> = HashMap< #[derive(Debug)] pub enum Event { - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] Wayland(sctk_event::SctkEvent), } @@ -61,7 +57,7 @@ impl SurfaceIdWrapper { #[derive(Debug, Default)] pub struct PlatformSpecific { - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] wayland: WaylandSpecific, } @@ -71,7 +67,7 @@ impl PlatformSpecific { action: iced_runtime::platform_specific::Action, ) { match action { - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] iced_runtime::platform_specific::Action::Wayland(a) => { self.send_wayland(wayland::Action::Action(a)); } @@ -82,14 +78,14 @@ impl PlatformSpecific { &mut self, keep: F, ) { - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] { self.wayland.retain_subsurfaces(keep); } } pub(crate) fn clear_subsurface_list(&mut self) { - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] { self.wayland.clear_subsurface_list(); } @@ -100,7 +96,7 @@ impl PlatformSpecific { id: window::Id, window: &dyn HasWindowHandle, ) { - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] { use cctk::sctk::reexports::client::{ Proxy, protocol::wl_surface::WlSurface, @@ -151,7 +147,7 @@ impl PlatformSpecific { pub(crate) fn create_surface( &mut self, ) -> Option> { - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] { self.wayland.create_surface() } @@ -170,7 +166,7 @@ impl PlatformSpecific { data: &[u8], offset: Vector, ) { - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] { return self.wayland.update_surface_shm( surface, width, height, scale, data, offset, @@ -198,7 +194,7 @@ pub(crate) async fn handle_event<'a, 'b, P>( P: Program, { match e { - #[cfg(all(feature = "cctk", target_os = "linux"))] + #[cfg(wayland_platform)] Event::Wayland(e) => { platform_specific .wayland diff --git a/winit/src/platform_specific/wayland/event_loop/state.rs b/winit/src/platform_specific/wayland/event_loop/state.rs index b817e4d5..f4a8c5d7 100644 --- a/winit/src/platform_specific/wayland/event_loop/state.rs +++ b/winit/src/platform_specific/wayland/event_loop/state.rs @@ -874,6 +874,11 @@ 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); } @@ -1011,6 +1016,12 @@ 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); } @@ -1268,11 +1279,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 settings.positioner.size.is_none() { - log::info!("No configured popup size"); - (1, 1) + let size = if let Some(size) = settings.positioner.size { + size } else { - settings.positioner.size.unwrap() + let guard = existing.common.lock().unwrap(); + (guard.size.width, guard.size.height) }; let Ok(positioner) = XdgPositioner::new(&self.xdg_shell_state) .map_err(PopupCreationError::PositionerCreationFailed) else { @@ -1392,7 +1403,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() @@ -1839,6 +1850,7 @@ impl SctkState { 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(); @@ -2021,6 +2033,11 @@ 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); } diff --git a/winit/src/platform_specific/wayland/handlers/seat/pointer.rs b/winit/src/platform_specific/wayland/handlers/seat/pointer.rs index 8c962a4d..b40912ec 100644 --- a/winit/src/platform_specific/wayland/handlers/seat/pointer.rs +++ b/winit/src/platform_specific/wayland/handlers/seat/pointer.rs @@ -1,8 +1,5 @@ -use crate::{ - event_loop::state::FrameStatus, - platform_specific::wayland::{ - event_loop::state::SctkState, sctk_event::SctkEvent, - }, +use crate::platform_specific::wayland::{ + event_loop::state::SctkState, sctk_event::SctkEvent, }; use cctk::sctk::{ delegate_pointer, @@ -50,14 +47,6 @@ 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/shell/layer.rs b/winit/src/platform_specific/wayland/handlers/shell/layer.rs index 22fd6560..5e6bad57 100644 --- a/winit/src/platform_specific/wayland/handlers/shell/layer.rs +++ b/winit/src/platform_specific/wayland/handlers/shell/layer.rs @@ -27,6 +27,15 @@ 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/xdg_popup.rs b/winit/src/platform_specific/wayland/handlers/shell/xdg_popup.rs index 55bf2b87..432f5bde 100644 --- a/winit/src/platform_specific/wayland/handlers/shell/xdg_popup.rs +++ b/winit/src/platform_specific/wayland/handlers/shell/xdg_popup.rs @@ -84,6 +84,11 @@ 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); }